diff -Nru swftools-0.9.2+ds1/avi2swf/avi2swf.1 swftools-0.9.1/avi2swf/avi2swf.1 --- swftools-0.9.2+ds1/avi2swf/avi2swf.1 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/avi2swf/avi2swf.1 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,59 @@ +.TH avi2swf "1" "February 2006" "avi2swf" "swftools" +.SH NAME +avi2swf - Converts an avi video file to SWF. + +.SH Synopsis +.B avi2swf file.avi [-o output.swf] + +.SH DESCRIPTION +Converts an AVI video file to SWF. +.PP +From Version 6 on, SWF supports h.263 video rendering. This tool generates, +among some other formats (see below), SWF movies which contain such h.263 video +from AVI files. + +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR + Print help and exit +.TP +\fB\-o\fR, \fB\-\-output\fR filename + Specify output filename +.TP +\fB\-A\fR, \fB\-\-adjust\fR seconds + Audio adjust: Shift sound -seconds to the future or +seconds into the past. +.TP +\fB\-n\fR, \fB\-\-num\fR frames + Number of frames to encode +.TP +\fB\-m\fR, \fB\-\-mp3-bitrate\fR \fIkbps\fR + Set the mp3 bitrate to encode audio with +.TP +\fB\-r\fR, \fB\-\-mp3-samplerate\fR \fIhz\fR + Set the mp3 samplerate to encode audio with (default: 11025) +.TP +\fB\-s\fR, \fB\-\-scale\fR \fIval\fR + Scale down to factor \fIval\fR. (in %, e.g. 100 = original size) +.TP +\fB\-S\fR, \fB\-\-skipframes\fR \fInum\fR + Skip \fInum\fR frames before starting the conversion. +.TP +\fB\-p\fR, \fB\-\-flip\fR + Turn movie upside down +.TP +\fB\-q\fR, \fB\-\-quality\fR \fIval\fR + Set the quality to \fIval\fR. (0-100, 0=worst, 100=best, default:80) +.TP +\fB\-k\fR, \fB\-\-keyframe\fR + Set the number of intermediate frames between keyframes. +.TP +\fB\-x\fR, \fB\-\-extragood\fR + Enable some \fIvery\fR expensive compression strategies. You may + want to let this run overnight. +.TP +\fB\-T\fR, \fB\-\-flashversion\fR \fIn\fR + Set output flash version to \fIn\fR. Notice: H.263 compression will only be + used for n >= 6. +.TP +\fB\-V\fR, \fB\-\-version\fR + Print program version and exit diff -Nru swftools-0.9.2+ds1/avi2swf/avi2swf.cc swftools-0.9.1/avi2swf/avi2swf.cc --- swftools-0.9.2+ds1/avi2swf/avi2swf.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/avi2swf/avi2swf.cc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,347 @@ +/* avi2swf.cc + Convert avi movie files into swf. + + Part of the swftools package. + + Copyright (c) 2001,2002,2003 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 "../config.h" + +#include "../lib/args.h" +#include "v2swf.h" +#ifdef WIN32 +#include "videoreader_vfw.hh" +#else +#include "videoreader_avifile.hh" +#endif + +static char * filename = 0; +static char * outputfilename = "output.swf"; +int verbose = 0; + +static int quality = 80; +static double scale = 1.0; +static int flip = 0; +static int expensive = 0; +static int flashversion = 6; +static int keyframe_interval = -1; +static int skip = 0; +static float audio_adjust = 0; +static int mp3_bitrate = 32; +static int samplerate = 11025; +static int numframes = 0; +static char* skipframes = 0; + +static struct options_t options[] = { +{"h", "help"}, +{"o", "output"}, +{"A", "adjust"}, +{"n", "num"}, +{"m", "mp3-bitrate"}, +{"r", "mp3-samplerate"}, +{"s", "scale"}, +{"S", "skipframes"}, +{"p", "flip"}, +{"q", "quality"}, +{"k", "keyframe"}, +{"x", "extragood"}, +{"T", "flashversion"}, +{"V", "version"}, +{0,0} +}; + +int args_callback_option(char*name,char*val) +{ + if(!strcmp(name, "V")) { + printf("avi2swf-ng - part of %s %s\n", PACKAGE, VERSION); + exit(0); + } + else if(!strcmp(name, "o")) { + outputfilename = val; + return 1; + } + else if(!strcmp(name, "n")) { + numframes = atoi(val); + return 1; + } + else if(!strcmp(name, "d")) { + scale = atof(val); + return 1; + } + else if(!strcmp(name, "q")) { + quality = atoi(val); + if(quality<0) + quality = 0; + if(quality>100) + quality = 100; + return 1; + } + else if(!strcmp(name, "p")) { + flip = 1; + return 0; + } + else if(!strcmp(name, "k")) { + keyframe_interval = atoi(val); + return 1; + } + else if(!strcmp(name, "A")) { + audio_adjust = atof(val); + return 1; + } + else if(!strcmp(name, "v")) { + verbose = 1; + return 0; + } + else if(!strcmp(name, "T")) { + flashversion = atoi(val); + return 1; + } + else if(!strcmp(name, "x")) { + expensive = 1; + return 0; + } + else if(!strcmp(name, "m")) { + mp3_bitrate = atoi(val); + return 1; + } + else if(!strcmp(name, "r")) { + samplerate = atoi(val); + if(samplerate >= 11000 && samplerate <= 12000) + samplerate = 11025; + else if(samplerate >= 22000 && samplerate <= 23000) + samplerate = 22050; + else if(samplerate >= 44000 && samplerate <= 45000) + samplerate = 44100; + else { + fprintf(stderr, "Invalid samplerate: %d\n", samplerate); + fprintf(stderr, "Allowed values: 11025, 22050, 44100\n", samplerate); + exit(1); + } + return 1; + } + else if(!strcmp(name, "S")) { + skip = atoi(val); + return 1; + } + else if(!strcmp(name, "C")) { + skipframes = strdup(val); + return 1; + } + else if(!strcmp(name, "s")) { + scale = atoi(val)/100.0; + if(scale>1.0 || scale<=0) { + fprintf(stderr, "Scale must be in the range 1-100!\n"); + exit(1); + } + return 1; + } + fprintf(stderr, "Unknown option: -%s\n", name); + exit(1); +} +int args_callback_longoption(char*name,char*val) +{ + return args_long2shortoption(options, name, val); +} +void args_callback_usage(char *name) +{ + printf("\n"); + printf("Usage: %s file.avi [-o output.swf]\n", name); + printf("\n"); + printf("-h , --help Print help and exit\n"); + printf("-o , --output filename Specify output filename\n"); + printf("-A , --adjust seconds Audio adjust: Shift sound -seconds to the future or +seconds into the past.\n"); + printf("-n , --num frames Number of frames to encode\n"); + printf("-m , --mp3-bitrate Set the mp3 bitrate to encode audio with\n"); + printf("-r , --mp3-samplerate Set the mp3 samplerate to encode audio with (default: 11025)\n"); + printf("-s , --scale Scale down to factor . (in %, e.g. 100 = original size)\n"); + printf("-S , --skipframes Skip frames before starting the conversion.\n"); + printf("-p , --flip Turn movie upside down\n"); + printf("-q , --quality Set the quality to . (0-100, 0=worst, 100=best, default:80)\n"); + printf("-k , --keyframe Set the number of intermediate frames between keyframes.\n"); + printf("-x , --extragood Enable some *very* expensive compression strategies.\n"); + printf("-T , --flashversion Set output flash version to .\n"); + printf("-V , --version Print program version and exit\n"); + printf("\n"); +} +int args_callback_command(char*name,char*val) +{ + if(filename) { + fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n", + filename, name); + } + filename = name; + return 0; +} + +static char toabuf[128]; +static char*ftoa(double a) +{ + sprintf(toabuf, "%f", a); + return toabuf; +} +static char*itoa(int a) +{ + sprintf(toabuf, "%d", a); + return toabuf; +} + +#ifdef DO_SIGNALS +pthread_t main_thread; +static void sigterm(int sig) +{ + if(pthread_equal (pthread_self(), main_thread)) + { + if(frameno>0 && !shutdown_avi2swf) { + if(verbose) + printf("Thread [%08x] got sigterm %d\n", pthread_self(), sig); + shutdown_avi2swf++; + } else { + exit(1); + } + } +} +#endif + +int main (int argc,char ** argv) +{ + videoreader_t video; + v2swf_t v2swf; + int ret; + FILE*fi; + +#ifdef DO_SIGNALS + signal(SIGTERM, sigterm); + signal(SIGINT , sigterm); + signal(SIGQUIT, sigterm); + main_thread = pthread_self(); +#endif + + processargs(argc, argv); + if(!filename) { + fprintf(stderr, "You must supply a filename"); + exit(0); + } + if(keyframe_interval<0) { + if(flashversion>=6) + keyframe_interval=20; + else + keyframe_interval=5; + } + + fi = fopen(outputfilename, "wb"); + if(!fi) { + fflush(stdout); fflush(stderr); + fprintf(stderr, "Couldn't open %s\n", outputfilename); + exit(1); + } + +#ifdef WIN32 + ret = videoreader_vfw_open(&video, filename); +#else + ret = videoreader_avifile_open(&video, filename); +#endif + + if(ret<0) { + fprintf(stderr, "Error opening %s\n", filename); + exit(1); + } + + if(verbose) { + printf("| video framerate: %f\n", video.fps); + printf("| video size: %dx%d\n", video.width, video.height); + printf("| audio rate: %d\n", video.samplerate); + printf("| audio channels: %d\n", video.channels); + } + + ret = v2swf_init(&v2swf, &video); + if(verbose) + v2swf_setparameter(&v2swf, "verbose", "1"); + if(numframes) + v2swf_setparameter(&v2swf, "numframes", itoa(numframes)); + v2swf_setparameter(&v2swf, "quality", itoa(quality)); + v2swf_setparameter(&v2swf, "blockdiff", "0"); + v2swf_setparameter(&v2swf, "blockdiff_mode", "exact"); + v2swf_setparameter(&v2swf, "mp3_bitrate", itoa(mp3_bitrate)); + v2swf_setparameter(&v2swf, "samplerate", itoa(samplerate)); + //v2swf_setparameter(&v2swf, "fixheader", "1"); + //v2swf_setparameter(&v2swf, "framerate", "15"); + v2swf_setparameter(&v2swf, "scale", ftoa(scale)); + v2swf_setparameter(&v2swf, "prescale", "1"); + v2swf_setparameter(&v2swf, "flash_version", itoa(flashversion)); + v2swf_setparameter(&v2swf, "keyframe_interval", itoa(keyframe_interval)); + if(skipframes) + v2swf_setparameter(&v2swf, "skipframes", skipframes); + if(expensive) + v2swf_setparameter(&v2swf, "motioncompensation", "1"); + if(flip) + video.setparameter(&video, "flip", "1"); + if(verbose) + video.setparameter(&video, "verbose", "1"); + + if(!verbose) + printf("\n"); + + if(audio_adjust>0) { + int num = ((int)(audio_adjust*video.samplerate))*video.channels*2; + void*buf = malloc(num); + video.getsamples(&video, buf, num); + free(buf); + } else if(audio_adjust<0) { + int num = (int)(-audio_adjust*video.fps); + void*buf = malloc(video.width*video.height*4); + int t; + for(t=0;t + Set the mp3 bitrate to encode audio with +-r , --mp3-samplerate + Set the mp3 samplerate to encode audio with (default: 11025) +-s , --scale + Scale down to factor . (in %, e.g. 100 = original size) +-S , --skipframes + Skip frames before starting the conversion. +-p , --flip + Turn movie upside down +-q , --quality + Set the quality to . (0-100, 0=worst, 100=best, default:80) +-k , --keyframe + Set the number of intermediate frames between keyframes. +-x , --extragood + Enable some *very* expensive compression strategies. + Enable some \fIvery\fR expensive compression strategies. You may + want to let this run overnight. +-T , --flashversion + Set output flash version to . + Set output flash version to . Notice: H.263 compression will only be + used for n >= 6. +-V , --version + Print program version and exit diff -Nru swftools-0.9.2+ds1/avi2swf/Makefile.in swftools-0.9.1/avi2swf/Makefile.in --- swftools-0.9.2+ds1/avi2swf/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/avi2swf/Makefile.in 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,41 @@ +top_builddir = .. +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +include ../Makefile.common + +VIDEO_LIBS=@VIDEO_LIBS@ +VIDEO_CFLAGS=@VIDEO_CFLAGS@ + +all: avi2swf$(E) + +videoreader_avifile.$(O): videoreader_avifile.cc videoreader_avifile.hh + $(CC) $(VIDEO_CFLAGS) $< -o $@ + +videoreader_vfw.$(O): videoreader_vfw.cc videoreader_vfw.hh + $(CC) $(VIDEO_CFLAGS) $< -o $@ + +avi2swf.$(O): avi2swf.cc videoreader_vfw.hh videoreader_avifile.hh + $(CC) $< -o $@ + +v2swf.$(O): v2swf.c ../lib/q.h + $(C) $< -o $@ + +avi2swf$(E): avi2swf.$(O) v2swf.$(O) videoreader_avifile.$(O) videoreader_vfw.$(O) ../lib/libbase$(A) + $(LL) avi2swf.$(O) v2swf.$(O) videoreader_avifile.$(O) videoreader_vfw.$(O) -o avi2swf$(E) ../lib/librfxswf$(A) ../lib/libbase$(A) $(LIBS) $(VIDEO_LIBS) + $(STRIP) avi2swf$(E) + +install: + $(mkinstalldirs) $(bindir) + $(mkinstalldirs) $(man1dir) + @file=avi2swf;$(INSTALL_BIN);$(INSTALL_MAN1) + +uninstall: + @file=avi2swf;$(UNINSTALL_BIN);$(UNINSTALL_MAN1) + +clean: + rm -f *.o *.obj *.lo *.a *.lib *.la avi2swf avi2swf.exe gmon.out + +doc: + perl ../parsedoc.pl avi2swf.doc + +.PHONY: all doc clean install uninstall diff -Nru swftools-0.9.2+ds1/avi2swf/v2swf.c swftools-0.9.1/avi2swf/v2swf.c --- swftools-0.9.2+ds1/avi2swf/v2swf.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/avi2swf/v2swf.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,1080 @@ +/* v2swf.c + part of swftools + + Copyright (C) 2003 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 "v2swf.h" +#include "../lib/rfxswf.h" +#include "../lib/q.h" + +typedef struct _v2swf_internal_t +{ + TAG*tag; + + int filesize; + int headersize; + int frames; + + int myframes; + + writer_t out; + writer_t out2; + + ringbuffer_t r; + videoreader_t* video; + double video_fps; + + int width; + int height; + + int video_eof; + int audio_eof; + + unsigned char* vrbuffer; + unsigned char* buffer; + unsigned char* lastbitmap; + + int id; + int lastid; + + int quality; + int blockdiff; + int keyframe_interval; + int diffmode; + + float framerate; + float fpsratio; + float fpspos; + + int bitrate; + int samplerate; + + int finished; + int keyframe; + int showframe; + + int skipframes; + + float samplepos; + float framesamplepos; + int samplewritepos; + double soundframepos; + int soundstreamhead; + int seek; + + int numframes; + + double audio_fix; + int fixheader; + int prescale; + + int scale; + + int add_cut; + + int domotion; + + int head_done; + + int version; + + VIDEOSTREAM stream; + +} v2swf_internal_t; + +static int verbose = 0; +static int filelog = 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--; + } + if(filelog) + { + FILE*fi = fopen("debug.log", "ab+"); + fprintf(fi, "(v2swf) %s\n", buf); + fflush(fi); + fclose(fi); + } + + printf("(v2swf) %s\n", buf); + fflush(stdout); +} + +extern int swf_mp3_in_samplerate; +extern int swf_mp3_out_samplerate; +extern int swf_mp3_channels; +extern int swf_mp3_bitrate; + + +static void writeShape(v2swf_internal_t*i, int id, int gfxid, int width, int height) +{ + RGBA rgb; + MATRIX m; + SHAPE*shape; + SRECT r; + int lines = 0; + int ls,fs; + swf_ResetTag(i->tag, ST_DEFINESHAPE); + swf_ShapeNew(&shape); + rgb.b = rgb.g = rgb.r = 0xff; + if(lines) + ls = swf_ShapeAddLineStyle(shape,20,&rgb); + swf_GetMatrix(NULL,&m); + m.sx = 20*65536; + m.sy = 20*65536; + + fs = swf_ShapeAddBitmapFillStyle(shape,&m,gfxid,0); + swf_SetU16(i->tag,id); // ID + r.xmin = 0; + r.ymin = 0; + r.xmax = width*20; + r.ymax = height*20; + swf_SetRect(i->tag,&r); + + swf_SetShapeStyles(i->tag,shape); + swf_ShapeCountBits(shape,NULL,NULL); + swf_SetShapeBits(i->tag,shape); + + swf_ShapeSetAll(i->tag,shape,0,0,lines?ls:0,fs,0); + + swf_ShapeSetLine(i->tag,shape,width*20,0); + swf_ShapeSetLine(i->tag,shape,0,height*20); + swf_ShapeSetLine(i->tag,shape,-width*20,0); + swf_ShapeSetLine(i->tag,shape,0,-height*20); + swf_ShapeSetEnd(i->tag); + i->filesize += swf_WriteTag2(&i->out, i->tag); + swf_ShapeFree(shape); +} + +/* returns 0 on partial read */ +static int getSamples(videoreader_t*video, S16*data, int len, double speedup) +{ + double pos = 0; + double ratio = (double) video->samplerate * speedup / swf_mp3_in_samplerate; + int rlen = (int)(len * ratio); + int t; + S16 tmp[576*32]; + int r = /*resampled len */ rlen * + /* s16_le */ 2 * + video->channels; + int l = 0; + memset(tmp, 0, sizeof(tmp)); + if(r>0) + l = videoreader_getsamples(video, tmp, r); + if(l <= 0) { + return 0; + } + msg("%d samples read", l); + + /* convert to 1 channel */ + for(t=0;tchannels;s++) + a += tmp[t*video->channels+s]; + tmp[t] = a/video->channels; + } + + /* down/up-sample to the desired input samplerate (swf_mp3_in_samplerate) */ + for(t=0;taudio_fix; + int num = 0; + int pos = 0; + S16 block1[576*4 * 2]; + + msg("writeAudioForOneFrame()"); + + if(i->audio_eof || i->video->channels<=0 || i->video->samplerate<=0) { + i->audio_eof = 1; + return; /* no sound in video */ + } + + blocksize = (i->samplerate > 22050) ? 1152 : 576; + blockspersecond = ((double)i->samplerate)/blocksize; + + /* notice: for framerates greater than about 35, audio starts getting choppy. */ + framespersecond = i->framerate; + + framesperblock = framespersecond / blockspersecond; + samplesperframe = (blocksize * blockspersecond) / framespersecond; /* 11khz-samples per frame */ + samplesperblock = samplesperframe * framesperblock; + + msg("samplesperblock: %f", samplesperblock); + + if(!i->soundstreamhead) { + swf_mp3_out_samplerate = i->samplerate; + /* The pre-processing of sound samples in getSamples(..) above + re-samples the sound to swf_mp3_in_samplerate. It is best to + simply make it the original samplerate: */ + swf_mp3_in_samplerate = i->video->samplerate; + + /* first run - initialize */ + swf_mp3_channels = 1;//i->video->channels; + swf_mp3_bitrate = i->bitrate; + swf_ResetTag(i->tag, ST_SOUNDSTREAMHEAD); + /* samplesperframe overrides the movie framerate: */ + msg("swf_SetSoundStreamHead(): %08x %d", i->tag, samplesperframe); + swf_SetSoundStreamHead(i->tag, samplesperframe); + msg("swf_SetSoundStreamHead() done"); + i->filesize += swf_WriteTag2(&i->out, i->tag); + i->soundstreamhead = 1; + } + + /* for framerates greater than 19.14, every now and then a frame + hasn't a soundstreamblock. Determine whether this is the case. + */ + msg("SOUND: frame:%d soundframepos:%f samplewritepos:%d samplepos:%f\n", i->frames, i->soundframepos, i->samplewritepos, i->samplepos); + if(i->frames < i->soundframepos) { + msg("SOUND: block skipped\n"); + i->samplepos += samplesperframe; + return; + } + + seek = i->seek; + + //while(i->samplewritepos + num * blocksize < i->samplepos + blocksize) { + do { + i->samplewritepos += blocksize; + i->soundframepos += framesperblock; + num++; + } + while(i->samplewritepos < i->samplepos); + + msg("SOUND: number of blocks: %d", num); + + /* write num frames, max 1 block */ + for(pos=0;posvideo, block1, blocksize * (double)swf_mp3_in_samplerate/swf_mp3_out_samplerate, speedup)) { + i->audio_eof = 1; i->video->samplerate = i->video->channels = 0; //end of soundtrack + /* fall through, this probably was a partial read. (We did, after all, + come to this point, so i->audio_eof must have been false so far) */ + } + if(!pos) { + swf_ResetTag(i->tag, ST_SOUNDSTREAMBLOCK); + swf_SetSoundStreamBlock(i->tag, block1, seek, num); + } else { + swf_SetSoundStreamBlock(i->tag, block1, seek, 0); + } + } + i->filesize += swf_WriteTag2(&i->out, i->tag); + + i->seek = blocksize - (i->samplewritepos - i->samplepos); + i->samplepos += samplesperframe; +} + +static void writeShowFrame(v2swf_internal_t* i) +{ + do { + writeAudioForOneFrame(i); + + swf_ResetTag(i->tag, ST_SHOWFRAME); + i->filesize += swf_WriteTag2(&i->out, i->tag); + + i->fpspos -= 1.0; + i->frames ++; + } + while(i->fpspos >= 1.0); + i->showframe = 0; +} + +static void writeShowTags(v2swf_internal_t* i, int shapeid, int bmid, int width, int height) +{ + writeShape(i, shapeid, bmid, width, height); + + swf_ResetTag(i->tag, ST_PLACEOBJECT2); + if(!i->prescale) { + MATRIX m; + swf_GetMatrix(0, &m); + m.sx = m.sy = i->scale; + swf_ObjectPlace(i->tag,shapeid,shapeid,&m,0,0); + } else { + swf_ObjectPlace(i->tag,shapeid,shapeid,0,0,0); + } + i->filesize += swf_WriteTag2(&i->out, i->tag); + + i->showframe = 1; +} + +static int wwrite(writer_t*w, void*data, int len) +{ + v2swf_internal_t* i = (v2swf_internal_t*)w->internal; + ringbuffer_put(&i->r, data, len); + return len; +} + +static void wfinish(writer_t*w) +{ + v2swf_internal_t* i = (v2swf_internal_t*)w->internal; +} + +static void writehead(v2swf_internal_t*i) +{ + char header[]="FWS\6\0\0\0\4"; + SWF swf; + int ret; + int id; + + header[3] = i->version; + if(i->version >= 6) { //MX + header[0] = 'C'; + + i->out2.write = wwrite; + i->out2.finish = wfinish; + i->out2.internal = i; + i->out2.type = 77; + i->out2.bitpos = 0; + i->out2.mybyte = 0; + i->out2.pos = 0; + writer_init_zlibdeflate(&i->out, &i->out2); + } else { + i->out.write = wwrite; + i->out.finish = wfinish; + i->out.internal = i; + i->out.type = 77; + i->out.bitpos = 0; + i->out.mybyte = 0; + i->out.pos = 0; + i->out2 = i->out; + } + + if(i->prescale) { + i->width = (int)(i->video->width*(i->scale/65536.0)); + i->height = (int)(i->video->height*(i->scale/65536.0)); + } else { + i->width = i->video->width; + i->height = i->video->height; + } + if(!i->width) + i->width = 1; + if(!i->height) + i->height = 1; + i->buffer = (unsigned char*)malloc(i->width*i->height*4); + i->vrbuffer = (unsigned char*)malloc(i->video->width*i->video->height*4); + + memset(&swf, 0, sizeof(SWF)); + swf.fileVersion=i->version; + swf.fileSize = 0; + swf.frameCount = 65535; + swf.movieSize.xmax=i->width*20; + swf.movieSize.ymax=i->height*20; + swf.compressed = 8; /* 8 = compression done by caller (us) */ + swf.frameRate = (int)(i->framerate*0x100);//25*0x100; + + /* write the first 8 bytes to out */ + i->out2.write(&i->out2, header, 8); + + i->filesize += swf_WriteHeader2(&i->out, &swf); + i->headersize = i->filesize; + + i->tag = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR); + swf_SetU8(i->tag, 0); //black + swf_SetU8(i->tag, 0); + swf_SetU8(i->tag, 0); + i->filesize += swf_WriteTag2(&i->out, i->tag); +} + +static void finish(v2swf_internal_t*i) +{ + msg("finish(): i->finished=%d\n", i->finished); + if(!i->finished) { + msg("write endtag\n", i->finished); + + if(i->add_cut) { + swf_ResetTag(i->tag, ST_SHOWFRAME); + i->filesize += swf_WriteTag2(&i->out, i->tag); + + swf_ResetTag(i->tag, ST_REMOVEOBJECT2); + swf_SetU16(i->tag, 1); //depth + i->filesize += swf_WriteTag2(&i->out, i->tag); + + swf_ResetTag(i->tag, ST_DOACTION); + swf_SetU16(i->tag, 0x0007); + i->filesize += swf_WriteTag2(&i->out, i->tag); + } + + swf_ResetTag(i->tag, ST_END); + i->filesize += swf_WriteTag2(&i->out, i->tag); + + i->out.finish(&i->out); + + if(i->version>=6) { + swf_VideoStreamClear(&i->stream); + } + if(i->buffer) { + free(i->buffer);i->buffer = 0; + } + if(i->vrbuffer) { + free(i->vrbuffer);i->vrbuffer = 0; + } + if(i->lastbitmap) { + free(i->lastbitmap);i->lastbitmap = 0; + } + + /* FIXME: we shouldn't be doing this. the caller should */ + msg("call videoreader_close(%08x)\n", i->video); + videoreader_close(i->video); + + i->finished = 1; + } + msg("finishing done\n"); +} +static void cleanup(v2swf_internal_t*i) +{ + int t; + for(t=i->lastid;tid;t++) { + if(!(t&1)) { + swf_ResetTag(i->tag, ST_REMOVEOBJECT2); + swf_SetU16(i->tag, t); + i->filesize += swf_WriteTag2(&i->out, i->tag); + } + swf_ResetTag(i->tag, ST_FREECHARACTER); + swf_SetU16(i->tag, t); + i->filesize += swf_WriteTag2(&i->out, i->tag); + } + i->lastid = i->id; +} + +#define DIFFMODE_MAX 1 +#define DIFFMODE_MEAN 2 +#define DIFFMODE_EXACT 3 +#define DIFFMODE_QMEAN 4 + +static int blockdiff_max(U8*d1,U8*d2,int yadd, int maxdiff, int xl, int yl) +{ + int x,y; + for(y=0;ymaxdiff) + return 1; + + d1+=4; d2+=4; + } + d1 += yadd; d2 += yadd; + } + return 0; +} + +static int blockdiff_mean(U8*d1,U8*d2,int yadd, int maxdiff, int xl, int yl) +{ + int mean = 0; + int x,y; + for(y=0;y maxdiff) + return 1; + return 0; +} + +static int blockdiff_qmean(U8*d1,U8*d2,int yadd, int maxdiff, int xl, int yl) +{ + int mean = 0; + int x,y; + for(y=0;y maxdiff*maxdiff) + return 1; + return 0; +} + +static int blockdiff_exact(U8*d1,U8*d2,int yadd, int xl, int yl) +{ + int x,y; + for(y=0;yhead_done) { + writehead(i); + if(i->version>=6) { + swf_ResetTag(i->tag, ST_DEFINEVIDEOSTREAM); + swf_SetU16(i->tag, 99); + swf_SetVideoStreamDefine(i->tag, &i->stream, 65535, i->width, i->height); + i->filesize += swf_WriteTag2(&i->out, i->tag); + if(i->domotion) { + i->stream.do_motion = 1; + } + } + i->head_done = 1; + } +} + +static void scaleimage(v2swf_internal_t*i) +{ + int x,y; + int xv,yv; + int xm = (i->video->width*65536)/i->width; + int ym = (i->video->height*65536)/i->height; + msg("scaling from %dx%d to %dx%d\n", + i->video->width, i->video->height, + i->width, i->height + ); + + memset(i->buffer, 255, i->width*i->height*4); + for(y=0,yv=0;yheight;y++,yv+=ym) { + int*src = &((int*)i->vrbuffer)[(yv>>16)*i->video->width]; + int*dest = &((int*)i->buffer)[y*i->width]; + for(x=0,xv=0;xwidth;x++,xv+=xm) { + dest[x] = src[xv>>16]; + } + } + //memcpy(i->buffer, i->vrbuffer, i->width*i->height*4); +} + +static int writeAudioOnly(v2swf_internal_t*i) +{ + if(i->showframe) { + i->fpspos += i->fpsratio; + /* skip frames */ + if(i->fpspos<1.0) { + return 0; + } + writeShowFrame(i); + } + i->showframe = 1; + return 1; +} + +static int getframe(v2swf_internal_t*i) +{ + if(!i->skipframes) + return videoreader_getimage(i->video, i->vrbuffer); + else { + int t; + for(t=0;tskipframes;t++) { + int ret = videoreader_getimage(i->video, i->vrbuffer); + if(!ret) + return 0; + } + return 1; + } +} + +static int encodeoneframe(v2swf_internal_t*i) +{ + videoreader_t*video = i->video; + int ret; + + checkInit(i); + + if(i->video_eof && i->audio_eof) { + if(!i->finished) + finish(i); + return 0; + } + + if(!i->audio_eof && i->video_eof) { + return writeAudioOnly(i); + } + + if(!getframe(i) || (i->numframes && i->frames==i->numframes)) + { + i->video_eof = 1; + msg("videoreader returned eof\n"); + if(i->audio_eof || (i->numframes && i->frames==i->numframes)) { + finish(i); + return 0; + } else { + return writeAudioOnly(i); + } + } + + msg("encoding image for frame %d\n", i->frames); + if(i->showframe) { + i->fpspos += i->fpsratio; + /* skip frames */ + if(i->fpspos<1.0) { + return 0; + } + writeShowFrame(i); + } + + scaleimage(i); + + msg("version is %d\n", i->version); + + if(i->version <= 4) { + + int bmid = i->id++; + int shapeid = i->id++; + int width2 = i->width * 4; + + if(i->id>=4) { + swf_ResetTag(i->tag, ST_REMOVEOBJECT2); + swf_SetU16(i->tag, i->id-3); + i->filesize += swf_WriteTag2(&i->out, i->tag); + swf_ResetTag(i->tag, ST_FREECHARACTER); + swf_SetU16(i->tag, i->id-4); + i->filesize += swf_WriteTag2(&i->out, i->tag); + } + + swf_ResetTag(i->tag, ST_DEFINEBITSJPEG2); + swf_SetU16(i->tag, bmid); + swf_SetJPEGBits2(i->tag, i->width, i->height, (RGBA*)i->buffer, i->quality); + i->filesize += swf_WriteTag2(&i->out, i->tag); + + writeShowTags(i, shapeid, bmid, i->width, i->height); + + } else if(i->version == 5) { + int width2 = i->width * 4; + int width8 = (i->width+7)/8; + int height8 = (i->height+7)/8; + + /* the idea is here to only update those jpeg 8x8 blocks + which actually have changed. This means that we have to keep + the bitmap from the last frame for the comparison. */ + + (i->keyframe)--; + if(!i->lastbitmap || !i->keyframe) { + int t, bmid,shapeid; + cleanup(i); + + if(!i->lastbitmap) { + msg("Creating bitmap buffer for %dx%d (%dx%d), (%dx%d)\n", i->width, i->height, width2, i->height, width8, height8); + i->lastbitmap = (U8*)malloc(width2*i->height); + } + memcpy(i->lastbitmap, i->buffer, width2*i->height); + + i->keyframe = i->keyframe_interval; + + bmid = i->id++; + shapeid = i->id++; + width2 = i->width * 4; + swf_ResetTag(i->tag, ST_DEFINEBITSJPEG2); + swf_SetU16(i->tag, bmid); + swf_SetJPEGBits2(i->tag, i->width, i->height, (RGBA*)i->buffer, i->quality); + i->filesize += swf_WriteTag2(&i->out, i->tag); + + writeShowTags(i, shapeid, bmid, i->width, i->height); + return 1; + } else { + /* The following looks so ugly because it's somewhat optimized. + What it does is walk through all the 8x8 blocks, find those + which have changed too much and set all others to (R,G,B,A)=(0,0,0,0). + It also set's alpha to 255 in those who haven't changed, and + copies them to lastbitmap. + */ + + int x8, y8; + //int maxdiff = ((100 - i->quality)*256)/100; + int maxdiff = i->blockdiff*3; + for(y8=0;y8 i->width) + xl = i->width - x8*8; + if(y8*8+yl > i->height) + yl = i->height - y8*8; + d1 = &i->buffer[width2*y8*8+x8*8*4]; + d1b = d1; + d2 = &i->lastbitmap[width2*y8*8+x8*8*4]; + d2b = d2; + yadd = width2 - (xl*4); + + if(i->diffmode == DIFFMODE_MAX) { + if(blockdiff_max(d1, d2, yadd, maxdiff, xl, yl)) + goto differ; + } else if(i->diffmode == DIFFMODE_MEAN) { + if(blockdiff_mean(d1, d2, yadd, maxdiff, xl, yl)) + goto differ; + } else if(i->diffmode == DIFFMODE_EXACT) { + if(blockdiff_exact(d1, d2, yadd, xl, yl)) + goto differ; + } else if(i->diffmode == DIFFMODE_QMEAN) { + if(blockdiff_qmean(d1, d2, yadd, maxdiff, xl, yl)) + goto differ; + } + + for(y=0;yid++; + int shapeid = i->id++; + + swf_ResetTag(i->tag, ST_DEFINEBITSJPEG3); + swf_SetU16(i->tag, bmid); + swf_SetJPEGBits3(i->tag, i->width, i->height, (RGBA*)i->buffer, i->quality); + i->filesize += swf_WriteTag2(&i->out, i->tag); + + writeShowTags(i, shapeid, bmid, i->width, i->height); + } + } else { + int quant = 1+(30-(30*i->quality)/100); + SWFPLACEOBJECT obj; + + swf_GetPlaceObject(0, &obj); + if(!i->prescale) { + obj.matrix.sx = obj.matrix.sy = i->scale; + } + + if(i->stream.frame==0) { + obj.depth = 1; + obj.id = 99; + } else { + obj.move = 1; + obj.depth = 1; + obj.ratio = i->stream.frame; + } + + swf_ResetTag(i->tag, ST_VIDEOFRAME); + swf_SetU16(i->tag, 99); + if(!(--i->keyframe)) { + msg("setting video I-frame, ratio=%d\n", i->stream.frame); + swf_SetVideoStreamIFrame(i->tag, &i->stream, (RGBA*)i->buffer, quant); + i->keyframe = i->keyframe_interval; + } else { + msg("setting video P-frame, ratio=%d\n", i->stream.frame); + swf_SetVideoStreamPFrame(i->tag, &i->stream, (RGBA*)i->buffer, quant); + } + i->filesize += swf_WriteTag2(&i->out, i->tag); + + swf_ResetTag(i->tag, ST_PLACEOBJECT2); + swf_SetPlaceObject(i->tag,&obj); + i->filesize += swf_WriteTag2(&i->out, i->tag); + i->showframe = 1; + } + return 1; +} + +static void init_fps(v2swf_internal_t*i) +{ + int oldframerate = i->framerate; + i->framerate = i->video->fps / i->skipframes; + i->video_fps = ((int)(i->framerate*256))/256.0; + if(oldframerate) + msg("setting new framerate to %f\n", i->framerate); +} + +int v2swf_init(v2swf_t*v2swf, videoreader_t * video) +{ + int ret = 0; + int t=0; + v2swf_internal_t* i; + msg("v2swf_init()\n"); + memset(v2swf, 0, sizeof(v2swf_t)); + i = (v2swf_internal_t*)malloc(sizeof(v2swf_internal_t)); + memset(i, 0, sizeof(v2swf_internal_t)); + v2swf->internal = i; + + ringbuffer_init(&i->r); + + i->skipframes = 1; + i->framerate = 0; + i->video = video; + init_fps(i); + + msg("video: %dx%d, fps %f\n", video->width, video->height, video->fps); + + i->blockdiff = 64; + i->keyframe_interval = 8; + i->quality = 20; + i->scale = 65536; + i->add_cut = 1; + i->samplerate = 11025; + i->prescale = 0; + i->numframes= 0; + i->skipframes = 0; + i->head_done = 0; + i->diffmode = DIFFMODE_QMEAN; + i->audio_fix = 1.0; + i->fixheader = 0; + i->fpsratio = 1.00000000000; + i->fpspos = 0.0; + i->bitrate = 32; + i->version = 6; + i->buffer = 0; + i->lastbitmap = 0; + i->filesize = 8; + i->frames = 0; + i->id = 1; + i->lastid = 1; + i->keyframe = 1; + i->showframe = 0; + + memset(&i->out, 0, sizeof(writer_t)); + memset(&i->out2, 0, sizeof(writer_t)); + + return 0; +} +int v2swf_read(v2swf_t*v2swf, void*buffer, int len) +{ + v2swf_internal_t* i; + int l; + msg("v2swf_read(%d)\n", len); + i = (v2swf_internal_t*)v2swf->internal; + + while(!i->finished && i->r.available < len) { + if(!encodeoneframe(i)) { + break; + } + } + msg("v2swf_read() done: %d bytes available in ringbuffer\n", i->r.available); + l = ringbuffer_read(&i->r, buffer, len); + + return l; +} +void v2swf_close(v2swf_t*v2swf) +{ + v2swf_internal_t* i = (v2swf_internal_t*)v2swf->internal; + msg("close(): i->finished=%d\n", i->finished); + + /* needed only if aborting: */ + finish(i); + + msg("freeing memory\n"); + free(v2swf->internal); + memset(v2swf, 0, sizeof(v2swf_t)); + msg("close() done\n"); +} + +static int mp3_bitrates[] = +{ 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}; + +void v2swf_setparameter(v2swf_t*v2swf, char*name, char*value) +{ + v2swf_internal_t* i; + + msg("set parameters %s to %s\n", name, value); + + if(!strcmp(name, "verbose")) { + verbose = 1; + msg("set parameters %s to %s\n", name, value); + return; + } + + if(!v2swf || !v2swf->internal) { + printf("error- couldn't set parameter %s: not initialized yet\n", name);fflush(stdout); + return; + } + i = (v2swf_internal_t*)v2swf->internal; + + if(!strcmp(name, "flash_version")) { + i->version = atoi(value); + } else if(!strcmp(name, "audiosync")) { + i->audio_fix = (int)(atof(value)); + } else if(!strcmp(name, "addcut")) { + i->add_cut = atoi(value); + } else if(!strcmp(name, "scale")) { + i->scale = (int)(atof(value)*65536); + } else if(!strcmp(name, "scale65536")) { + i->scale = atoi(value); + } else if(!strcmp(name, "quality")) { + i->quality = atoi(value); + } else if(!strcmp(name, "skipframes")) { + i->skipframes = atoi(value); + init_fps(i); + } else if(!strcmp(name, "numframes")) { + i->numframes = atoi(value); + } else if(!strcmp(name, "motioncompensation")) { + i->domotion = atoi(value); + } else if(!strcmp(name, "prescale")) { + i->prescale = atoi(value); + } else if(!strcmp(name, "blockdiff")) { + i->blockdiff = atoi(value); + } else if(!strcmp(name, "fixheader")) { + i->fixheader = atoi(value); + } else if(!strcmp(name, "samplerate")) { + i->samplerate = atoi(value); + } else if(!strcmp(name, "framerate")) { + i->framerate = atof(value); + i->fpsratio = i->framerate / i->video_fps; + } + else if(!strcmp(name, "mp3_bitrate")) { + int t=0,o; + i->bitrate = o = atoi(value); + if(i->bitrate>160) + i->bitrate = 160; + while(mp3_bitrates[t]) { + if(i->bitrate <= mp3_bitrates[t]) { + i->bitrate = mp3_bitrates[t]; + break; + } + t++; + } + msg("bitrate %d requested, setting to %d", o, i->bitrate); + } + else if(!strcmp(name, "blockdiff_mode")) { + if(!strcmp(value, "max")) i->diffmode = DIFFMODE_MAX; + else if(!strcmp(value, "mean")) i->diffmode = DIFFMODE_MEAN; + else if(!strcmp(value, "qmean")) i->diffmode = DIFFMODE_QMEAN; + else if(!strcmp(value, "exact")) i->diffmode = DIFFMODE_EXACT; + else { + printf("diffmode %s not recognized\n", value); + printf("valid diffmodes are: %s\n", "max, mean, qmean, exact"); + } + } + else if(!strcmp(name, "keyframe_interval") + || !strcmp(name, "keyframe")) { + int k = atoi(value);if(k<=0) k=1; + i->keyframe_interval = k; + } + else { + printf("Setting encoder.%s not recognized!\n", name);fflush(stdout); + return; + } +} +void v2swf_backpatch(v2swf_t*v2swf, char*filename) +{ + FILE* fi; + unsigned char f; + v2swf_internal_t* i = (v2swf_internal_t*)v2swf->internal; + msg("v2swf_backpatch %s\n", filename); + if(!i) { + printf("call backpatch before close\n");fflush(stdout); + } + fi = fopen(filename, "rb+"); + if(!fi) { + printf("can't open %s\n", filename); + exit(1); + } + fseek(fi, 4, SEEK_SET); + f = i->filesize ;fwrite(&f,1,1,fi); + f = i->filesize >> 8 ;fwrite(&f,1,1,fi); + f = i->filesize >> 16;fwrite(&f,1,1,fi); + f = i->filesize >> 24;fwrite(&f,1,1,fi); + if(i->version<6) { + /* no compression- we can backpatch the frames too */ + fseek(fi, i->headersize-2, SEEK_SET); + f = i->frames ;fwrite(&f,1,1,fi); + f = i->frames >> 8 ;fwrite(&f,1,1,fi); + } + fclose(fi); + if(i->fixheader) { + SWF tmp; + int fi; + msg("v2swf_backpatch %s - fix header\n", filename); + memset(&tmp, 0, sizeof(tmp)); + fi = open(filename, O_RDONLY|O_BINARY); + if(fi>=0) { + if(swf_ReadSWF(fi, &tmp)>=0) { + close(fi); + fi = open(filename, O_WRONLY|O_BINARY|O_TRUNC|O_CREAT, 0666); + if(fi>=0) { + swf_WriteSWF(fi, &tmp); + close(fi); + msg("v2swf_backpatch %s - fix header: success\n", filename); + } + } + } + } +} + +void v2swf_setvideoparameter(videoreader_t*v, char*name, char*value) +{ + msg("v2swf_setvideoparameter()"); + videoreader_setparameter(v, name, value); +} diff -Nru swftools-0.9.2+ds1/avi2swf/v2swf.h swftools-0.9.1/avi2swf/v2swf.h --- swftools-0.9.2+ds1/avi2swf/v2swf.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/avi2swf/v2swf.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,46 @@ +/* v2swf.h + header file for v2swf.h - part of SWFTools + + Copyright (C) 2003 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 __video_h__ +#define __video_h__ + +#ifdef __cplusplus +extern "C" { +#else +typedef unsigned char bool; +#endif + +#include "videoreader.h" + +typedef struct _v2swf_t +{ + void*internal; +} v2swf_t; + +int v2swf_init(v2swf_t*v2swf, videoreader_t * video); +int v2swf_read(v2swf_t*v2swf, void*buffer, int len); +void v2swf_setparameter(v2swf_t*v2swf, char*name, char*value); +void v2swf_close(v2swf_t*v2swf); +void v2swf_backpatch(v2swf_t*v2swf, char*filename); + +#ifdef __cplusplus +} +#endif + +#endif diff -Nru swftools-0.9.2+ds1/avi2swf/videoreader_avifile.cc swftools-0.9.1/avi2swf/videoreader_avifile.cc --- swftools-0.9.2+ds1/avi2swf/videoreader_avifile.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/avi2swf/videoreader_avifile.cc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,354 @@ +/* videoreader_avifile.cc + Read avi files using the avifile library. + + Part of the swftools package. + + Copyright (c) 2001,2002,2003 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 "../config.h" +#include "videoreader.h" + +#ifdef HAVE_AVIFILE + +#undef HAVE_CONFIG_H + +#ifdef HAVE_VERSION_H + #include +#endif +#ifdef HAVE_AVIFILE_VERSION_H + #include +#endif + +#if (AVIFILE_MAJOR_VERSION == 0) && (AVIFILE_MINOR_VERSION>=6) + #include + #include + #include + #include + #include + #define VERSION6 +#else + #include + #include + #include + #define Width width + #define Height height + #define Data data + #define Bpp bpp +#endif + +#ifdef HAVE_SIGNAL_H +#ifdef HAVE_PTHREAD_H +#include +#include +#define DO_SIGNALS +#endif +#endif + +#include "../lib/q.h" + +static int verbose = 0; + +typedef struct _videoreader_avifile_internal +{ + IAviReadFile* player; + IAviReadStream* astream; + IAviReadStream* vstream; + int do_audio; + int do_video; + int video_eof; + int audio_eof; + int flip; + int frame; + int soundbits; + ringbuffer_t audio_buffer; +} videoreader_avifile_internal; + +static int readSamples(videoreader_avifile_internal*i, void*buffer, int buffer_size, int numsamples) +{ + int ret; + while(i->audio_buffer.available < buffer_size) { + unsigned int samples_read = 0, bytes_read = 0; + ret = i->astream->ReadFrames(buffer, buffer_size, numsamples, samples_read, bytes_read); + if(ret!=0) { + if(verbose) { + printf("ReadFrames() returns %d\n", ret);fflush(stdout); + } + } + if(samples_read<=0) { + int l = i->audio_buffer.available; + ringbuffer_read(&i->audio_buffer, buffer, l); + return l; + } + ringbuffer_put(&i->audio_buffer, buffer, bytes_read); + } + ringbuffer_read(&i->audio_buffer, buffer, buffer_size); + return buffer_size; +} +static int videoreader_avifile_getsamples(videoreader_t* v, void*buffer, int num) +{ + videoreader_avifile_internal*i = (videoreader_avifile_internal*)v->internal; + if(verbose) { + printf("videoreader_getsamples(%d)\n", num);fflush(stdout); + } + if(i->audio_eof) + return 0; + if(i->soundbits == 8) { + int num_read = readSamples(i, buffer, num/2, num/(v->channels*2))*2; + unsigned char*b = (unsigned char*)buffer; + int t; + for(t=num_read-2;t>=0;t-=2) { + unsigned char x = b[t/2]; + b[t] = 0; + b[t+1] = x-128; + } + if(!num_read) { + if(verbose) { + printf("end of audio\n");fflush(stdout); + } + i->audio_eof=1; + } + return num_read; + } + if(i->soundbits == 16) { + int num_read = readSamples(i, buffer, num, num/(v->channels*2)); + if(!num_read) { + if(verbose) { + printf("end of audio\n");fflush(stdout); + } + i->audio_eof=1; + } + return num_read; + } + return 0; +} +static int videoreader_avifile_getimage(videoreader_t* v, void*buffer) +{ + videoreader_avifile_internal*i = (videoreader_avifile_internal*)v->internal; + if(verbose) { + printf("videoreader_getimage()\n");fflush(stdout); + } + + if(i->video_eof) + return 0; + + if(i->vstream->ReadFrame() < 0) { + if(verbose) printf("vstream->ReadFrame() returned value < 0, shutting down...\n"); + i->video_eof = 1; + return 0; + } + CImage*img2 = 0; + CImage*img = i->vstream->GetFrame(); + if(!img) { + if(verbose) printf("vstream->GetFrame() returned NULL, shutting down...\n"); + i->video_eof = 1; + return 0; + } + /* we convert the image to YUV first, because we can convert to RGB from YUV only */ + img->ToYUV(); + img->ToRGB(); + if(img->Bpp() != 3) { + if(verbose) printf("Warning: converthing from bpp %d to bpp 3, this fails on older avifile versions...\n", img->Bpp()); + BitmapInfo tmp(v->width, v->height, 24); + img2 = new CImage(img, &tmp); + img = img2; + } + + v->frame++; + i->frame++; + unsigned char*data = img->Data(); + int bpp = img->Bpp(); + if(bpp == 3) { + int x,y; + for(y=0;yheight;y++) { + unsigned char*from,*to; + to = &((unsigned char*)buffer)[y*v->width*4]; + if(i->flip) + from = img->At(v->height-y-1); + else + from = img->At(y); + for(x=0;xwidth;x++) { + to[x*4+0] = 0; + to[x*4+1] = from[x*3+2]; + to[x*4+2] = from[x*3+1]; + to[x*4+3] = from[x*3+0]; + } + } + if(img2) delete img2; + return v->width*v->height*4; + } else { + if(img2) delete img2; + if(verbose) printf("Can't handle bpp %d, shutting down...\n", bpp); + i->video_eof = 1; + return 0; + } +} +static void videoreader_avifile_close(videoreader_t* v) +{ + videoreader_avifile_internal*i = (videoreader_avifile_internal*)v->internal; + if(verbose) { + printf("videoreader_close()\n");fflush(stdout); + } + if(i->do_audio) { + ringbuffer_clear(&i->audio_buffer); + } +} +static void videoreader_avifile_setparameter(videoreader_t*v, char*name, char*value) +{ + videoreader_avifile_internal*i = (videoreader_avifile_internal*)v->internal; + if(!strcmp(name, "verbose")) { + verbose = atoi(value); + } + if(!strcmp(name, "flip")) { + i->flip = atoi(value); + } + if(verbose) { + printf("videoreader_setparameter(%s, %s)\n", name, value);fflush(stdout); + } +} + +int videoreader_avifile_open(videoreader_t* v, char* filename) +{ + if(!filename) { + /* codec query */ + return 0; + } + videoreader_avifile_internal* i; + i = (videoreader_avifile_internal*)malloc(sizeof(videoreader_avifile_internal)); + memset(i, 0, sizeof(videoreader_avifile_internal)); + memset(v, 0, sizeof(videoreader_t)); + v->getsamples = videoreader_avifile_getsamples; + v->close = videoreader_avifile_close; + v->getimage = videoreader_avifile_getimage; + v->getsamples = videoreader_avifile_getsamples; + v->setparameter = videoreader_avifile_setparameter; + v->internal = i; + v->frame = 0; + + i->do_video = 1; + i->do_audio = 1; + + i->player = CreateIAviReadFile(filename); + if(verbose) { + printf("%d streams (%d video, %d audio)\n", + i->player->StreamCount(), + i->player->VideoStreamCount(), + i->player->AudioStreamCount()); + } + i->astream = i->player->GetStream(0, AviStream::Audio); + i->vstream = i->player->GetStream(0, AviStream::Video); + if(!i->vstream) { + printf("Couldn't open video stream\n"); + i->do_video = 0; + } + if(!i->astream) { + printf("Couldn't open video stream\n"); + i->do_audio = 0; + } +#ifdef NO_MP3 + if(i->do_audio) { + printf(stderr, "MP3 support has been disabled at compile time, not converting soundtrack"); + i->do_audio = 0; + } +#endif + + if(!i->do_video && !i->do_audio) { + printf("File has neither audio nor video streams.(?)\n"); + return -1; + } + +#ifndef VERSION6 + MainAVIHeader head; + int dwMicroSecPerFrame = 0; + player->GetFileHeader(&head); + printf("fps: %d\n", 1000000/head.dwMicroSecPerFrame); + printf("frames: %d\n", head.dwTotalFrames); + printf("streams: %d\n", head.dwStreams); + printf("width: %d\n", abs(head.dwWidth)); + printf("height: %d\n", abs(head.dwHeight)); + printf("sound: %u samples (%f seconds)\n", i->astream->GetEndPos(), i->astream->GetEndTime()); + v->width = abs(head.dwWidth); + v->height = abs(head.dwHeight); + dwMicroSecPerFrame = head.dwMicroSecPerFrame; + samplesperframe = astream->GetEndPos()/astream->GetEndTime()*head.dwMicroSecPerFrame/1000000; + v->samplerate = (int)(astream->GetEndPos()/astream->GetEndTime()); + v->fps = 1000000.0/dwMicroSecPerFrame; + i->soundbits = 16; +#else + if(i->do_video) + { + StreamInfo*videoinfo; + videoinfo = i->vstream->GetStreamInfo(); + v->width = abs(videoinfo->GetVideoWidth()); + v->height = abs(videoinfo->GetVideoHeight()); + v->fps = (double)(videoinfo->GetFps()); + } + if(i->do_audio) + { + WAVEFORMATEX wave; + StreamInfo*audioinfo; + + i->astream->GetAudioFormatInfo(&wave,0); + audioinfo = i->astream->GetStreamInfo(); + + v->channels = wave.nChannels; + v->samplerate = wave.nSamplesPerSec; + i->soundbits = wave.wBitsPerSample; + + if(v->channels==0 || v->samplerate==0 || i->soundbits==0 || wave.wFormatTag!=1) { + v->samplerate = audioinfo->GetAudioSamplesPerSec(); + v->channels = audioinfo->GetAudioChannels(); + i->soundbits = audioinfo->GetAudioBitsPerSample(); + } + + if(verbose) { + printf("formatinfo: format %d, %d channels, %d bits/sample, rate %d, blockalign %d\n", wave.wFormatTag, wave.nChannels, wave.wBitsPerSample, wave.nSamplesPerSec, wave.nBlockAlign); + printf("audioinfo: %d channels, %d bits/sample, rate %d\n", audioinfo->GetAudioChannels(), audioinfo->GetAudioBitsPerSample(), audioinfo->GetAudioSamplesPerSec()); + } + if(i->soundbits != 8 && i->soundbits != 16) { + printf("Can't handle %d bit audio, disabling sound\n", wave.wBitsPerSample); + i->do_audio = 0; + i->soundbits = 0; + v->channels = 0; + v->samplerate = 0; + } + } +#endif + i->vstream -> StartStreaming(); + if(i->do_audio) { + i->astream -> StartStreaming(); + ringbuffer_init(&i->audio_buffer); +#ifdef VERSION6 + WAVEFORMATEX wave; + i->astream -> GetOutputFormat(&wave, sizeof(wave)); + printf("formatinfo: format %d, %d channels, %d bits/sample, rate %d, blockalign %d\n", wave.wFormatTag, wave.nChannels, wave.wBitsPerSample, wave.nSamplesPerSec, wave.nBlockAlign); +#endif + } + + return 0; +} + +#else //HAVE_AVIFILE + +int videoreader_avifile_open(videoreader_t* v, char* filename) +{ + return -1; +} + +#endif //HAVE_AVIFILE diff -Nru swftools-0.9.2+ds1/avi2swf/videoreader_avifile.hh swftools-0.9.1/avi2swf/videoreader_avifile.hh --- swftools-0.9.2+ds1/avi2swf/videoreader_avifile.hh 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/avi2swf/videoreader_avifile.hh 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,29 @@ +/* videoreader_avifile.hh + Read avi files using the avifile library. + + Part of the swftools package. + + Copyright (c) 2001,2002,2003 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 __videoreader_avifile_h__ +#define __videoreader_avifile_h__ + +#include "videoreader.h" + +int videoreader_avifile_open(videoreader_t* v, char* filename); + +#endif diff -Nru swftools-0.9.2+ds1/avi2swf/videoreader_dummy.cc swftools-0.9.1/avi2swf/videoreader_dummy.cc --- swftools-0.9.2+ds1/avi2swf/videoreader_dummy.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/avi2swf/videoreader_dummy.cc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,105 @@ +/* videoreader_dummy.cc + Simple example for a videoreader. + + Part of the swftools package. + + 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 +#include +#include "videoreader.h" + +typedef struct _my_internal +{ + int pos; + int len; //frames +} my_internal; + +typedef struct _RGBA +{ unsigned char a; + unsigned char r; + unsigned char g; + unsigned char b; +} RGBA; + +int my_getsamples(videoreader_t* v, void*buffer, int num) +{ + /* generate audio data */ + my_internal*i = (my_internal*)v->internal; + // printf("request for %d samples\n", num); + + return 0; // no audio +} + +int my_getimage(videoreader_t* v, void*buffer) +{ + /* generate video frame */ + my_internal*i = (my_internal*)v->internal; + RGBA*buf = (RGBA*)buffer; + + if(i->pos>=i->len) + return 0; /* end of video */ + + i->pos++; // next frame + + int x,y; + /* generate a simple color gradient */ + for(y=0;yheight;y++) + for(x=0;xwidth;x++) { + int r,g,b; + r = x; + g = y; + b = x+y; + buf[y*v->width + x].r = r; + buf[y*v->width + x].g = g; + buf[y*v->width + x].b = b; + buf[y*v->width + x].a = 255; + } + return v->width*v->height*4; +} +void my_close(videoreader_t* v) +{ + my_internal*i = (my_internal*)v->internal; + free(v->internal);v->internal = 0; +} +void my_setparameter(videoreader_t*v, char*name, char*value) +{ +} +int videoreader_dummy_open(videoreader_t* v, char* filename) +{ + my_internal* i; + i = (my_internal*)malloc(sizeof(my_internal)); + memset(i, 0, sizeof(my_internal)); + v->internal = i; + v->getsamples = my_getsamples; + v->close = my_close; + v->getimage = my_getimage; + v->getsamples = my_getsamples; + v->setparameter = my_setparameter; + + i->len = 2000; //number of frames + + v->width = 320; // video + v->height = 200; + v->fps = 15; + + v->channels = 0; // no audio + v->samplerate = 0; + + return 0; +} diff -Nru swftools-0.9.2+ds1/avi2swf/videoreader.h swftools-0.9.1/avi2swf/videoreader.h --- swftools-0.9.2+ds1/avi2swf/videoreader.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/avi2swf/videoreader.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,34 @@ +#ifndef __videoreader_t__ +#define __videoreader_t__ + +#define videoreader_getsamples(v, buffer, num) ((v)->getsamples((v),(buffer),(num))) +#define videoreader_getimage(v, buffer) ((v)->getimage((v),(buffer))) +#define videoreader_eof(v) ((v)->eof(v)) +#define videoreader_setparameter(v,name,value) ((v)->setparameter((v),(name),(value))) +#define videoreader_close(v) ((v)->close(v)) + +typedef struct _videoreader_t +{ + void*internal; + + /* video */ + int width; + int height; + double fps; + + /* audio */ + int channels; + int samplerate; + + /* progress */ + int frame; + + void (*setparameter) (struct _videoreader_t*, char*name, char*value); + int (*getsamples) (struct _videoreader_t*, void*buffer, int num); + int (*getimage) (struct _videoreader_t*, void*buffer); // buffer must hold width*height*4 bytes + void (*close) (struct _videoreader_t*); + +} videoreader_t; + + +#endif diff -Nru swftools-0.9.2+ds1/avi2swf/videoreader_vfw.cc swftools-0.9.1/avi2swf/videoreader_vfw.cc --- swftools-0.9.2+ds1/avi2swf/videoreader_vfw.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/avi2swf/videoreader_vfw.cc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,401 @@ +/* videoreader_vfw.cc + Read avi files using Video For Windows (vfw). + + Part of the swftools package. + + 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 "videoreader.h" +#ifdef WIN32 +#include +#include +#include +#include + +typedef struct _videoreader_vfw_internal { + //video: + PAVISTREAM vs; + //audio: + PAVISTREAM as; + + PGETFRAME getframe; + IAVIFile* avifile; + BITMAPINFOHEADER bitmap; + WAVEFORMATEX waveformat; + + int audio_eof; + int video_eof; + + int video_pos; + int video_end; + + int audio_pos; + int audio_end; + + float fps; + int width,height; + + int samplerate; + int channels; + + int flip; +} videoreader_vfw_internal_t; + +static int avifile_initialized = 0; +static int verbose; + +#define _TRACE_ {printf("vfw: %s: %d (%s)\n",__FILE__,__LINE__,__func__);fflush(stdout);} + +static int bitmap_to_rgba(BITMAPINFOHEADER*bi, void*buffer, const int dest_width, const int dest_height, int flip) +{ + UCHAR*data = (UCHAR*)(bi+1); // actual bitmap data starts after the header + + if(bi->biPlanes!=1 || bi->biCompression!=0 || bi->biBitCount%4!=0) { + /* unsupported format */ + fprintf(stderr, "bitmap_to_rgba: unsupported format: biPlanes=%d, biCompression=%d biBitCount=%d\n", + bi->biPlanes, bi->biCompression, bi->biBitCount); + return 0; + } + + ULONG*dest = (ULONG*)buffer; + + int width = abs(bi->biWidth); + int height = abs(bi->biHeight); + if(dest_width != width || dest_height != height) { + /* TODO: size conversion */ + fprintf(stderr, "size mismatch: %dx%d != %dx%d\n", width, height, dest_width, dest_height); + return 0; + } + + /* convert the various image types to RGBA- + TODO: is there some way to let the Windows API do this? */ + int bytesperpixel = ((bi->biWidth*bi->biBitCount)+7)&~7; + int linex = ((bytesperpixel/8)+3)&~3; + memset(dest, 255, dest_width*dest_height*4);//pre-fill alpha channel + + const int starty = flip? 0 : dest_height-1; + const int endy = flip? dest_height : -1; + const int yinc = flip? 1 : -1; + + if(verbose) { + printf("vfw: Convering scanlines %d to %d from bpp %d, %d stepping, flip=%d\n", starty, endy, bi->biBitCount, yinc, flip); + } + + if(bi->biBitCount==1) { + UCHAR*img = data; + int y; + for(y=starty;y!=endy;y+=yinc) { + UCHAR*line = &img[linex*y]; + int x; + for(x=0;x>(x&7))&1); + } + } + } else if(bi->biBitCount==4) { + UCHAR*img = &data[bi->biClrUsed*4]; + UCHAR*pal = data; + int y; + for(y=starty;y!=endy;y+=yinc) { + UCHAR*line = &img[linex*y]; + int x; + for(x=0;x>4)<<2|0]<<8|pal[(line[0]>>4)<<2|1]<<16|pal[(line[0]>>4)<<2|2]<<24; + *dest++ = 255|pal[(line[0]&0x0f)<<2|0]<<8|pal[(line[0]&0x0f)<<2|1]<<16|pal[(line[0]&0x0f)<<2|2]<<24; + line++; + } + } + } else if(bi->biBitCount==8) { + UCHAR*img = &data[bi->biClrUsed*4]; + UCHAR*pal = data; + int y; + for(y=starty;y!=endy;y+=yinc) { + UCHAR*line = &img[linex*y]; + int x; + for(x=0;xbiBitCount==16) { + UCHAR*img = data; + int y; + for(y=starty;y!=endy;y+=yinc) { + UCHAR*line = &img[linex*y]; + int x; + for(x=0;x>5&0x1f)<<(16+3)|(c>>10&0x1f)<<(8+3); + line+=2; + } + } + } else if(bi->biBitCount==24) { + UCHAR*img = data; + int y; + for(y=starty;y!=endy;y+=yinc) { + UCHAR*line = &img[linex*y]; + int x; + for(x=0;xbiBitCount==32) { + UCHAR*img = data; + int y; + for(y=starty;y!=endy;y+=yinc) { + UCHAR*line = &img[linex*y]; + int x; + for(x=0;xbiBitCount); + return 0; + } + return 1; +} + +static int videoreader_vfw_getimage(videoreader_t* vr, void*buffer) +{ + videoreader_vfw_internal_t* i = (videoreader_vfw_internal_t*)vr->internal; + + if (i->video_pos >= i->video_end) + i->video_eof = 1; + + if(i->video_eof) + return 0; + + LPBITMAPINFOHEADER bi; + bi = (LPBITMAPINFOHEADER)AVIStreamGetFrame(i->getframe, i->video_pos); + + i->video_pos++; + vr->frame++; + + if(!bi) { + fprintf(stderr, "AVIStreamGetFrame failed\n"); + return 0; + } + + if(!bitmap_to_rgba(bi, buffer, i->width, i->height, i->flip)) { + fprintf(stderr, "couldn't convert bitmap to RGBA.\n"); + return 0; + } + return i->width*i->height*4; +} + +static int readAudioBlock(videoreader_vfw_internal_t* i, void*buf, int len) +{ + LONG bytes; + LONG samples; + AVIStreamRead(i->as, i->audio_pos, len/(2*i->waveformat.nChannels), buf, len, &bytes, &samples); + i->audio_pos += samples; + return bytes; +} + +static int videoreader_vfw_getsamples(videoreader_t* vr, void*buf, int num) +{ + videoreader_vfw_internal_t* i = (videoreader_vfw_internal_t*)vr->internal; + + if(i->audio_eof) + return 0; + + switch(i->waveformat.wBitsPerSample) { + case 1: { + int len = readAudioBlock(i, buf, num); + int t = len-1; + do { + ((SHORT*)buf)[t] = ((((BYTE*)buf)[t>>3])>>(t&7))<<15; + } while(--t>=0); + if(!len) i->audio_eof = 1; + return len*8; + } + case 8: { + int len = readAudioBlock(i, buf, num); + int t = len-1; + do { + ((SHORT*)buf)[t] = (((BYTE*)buf)[t]<<8)^0x8000; + } while(--t>=0); + if(!len) i->audio_eof = 1; + return len*2; + } + case 16: { + int len = readAudioBlock(i, buf, num); + if(!len) i->audio_eof = 1; + return len; + } + default: { + return 0; + } + } +} + +static void videoreader_vfw_close(videoreader_t* vr) +{ + videoreader_vfw_internal_t* i = (videoreader_vfw_internal_t*)vr->internal; + + AVIStreamGetFrameClose(i->getframe); + if(i->vs) { + AVIStreamRelease(i->vs); i->vs = 0; + } + if(i->as) { + AVIStreamRelease(i->as); i->vs = 0; + } + AVIFileRelease(i->avifile); i->avifile = 0; + + AVIFileExit(); avifile_initialized=0; + + free(vr->internal); vr->internal = 0; +} + +static void videoreader_vfw_setparameter(videoreader_t*vr, char*name, char*value) +{ + videoreader_vfw_internal_t* i = (videoreader_vfw_internal_t*)vr->internal; + if(!strcmp(name, "flip")) { + i->flip = atoi(value); + } else if(!strcmp(name, "verbose")) { + verbose = atoi(value); + } +} + +int videoreader_vfw_open(videoreader_t* vr, char* filename) +{ + memset(vr, 0, sizeof(videoreader_t)); + if(!filename) { + /* codec query */ + return 1; + } + + videoreader_vfw_internal_t* i = (videoreader_vfw_internal_t*)malloc(sizeof(videoreader_vfw_internal_t)); + memset(i, 0, sizeof(videoreader_vfw_internal_t)); + + vr->internal = i; + vr->getimage = videoreader_vfw_getimage; + vr->getsamples = videoreader_vfw_getsamples; + vr->close = videoreader_vfw_close; + vr->setparameter = videoreader_vfw_setparameter; + + if(!avifile_initialized) { + AVIFileInit(); + } + if(AVIFileOpen(&i->avifile, filename, OF_SHARE_DENY_WRITE, 0)) { + fprintf(stderr, "Couldn't open %s\n", filename); + return -1; + } + AVIFILEINFO info; + AVIFileInfo(i->avifile, &info, sizeof(info)); + + /* calculate framerate */ + i->fps = (double)info.dwRate/(double)info.dwScale; + + if(verbose) { + printf("vfw: file %s has %f fps, and %d streams\n", i->fps, info.dwStreams); + } + + unsigned int t=0; + while(tavifile, &stream, streamtypeANY, t) != AVIERR_OK || !stream) + break; //video_end of (working) streams + + AVISTREAMINFO streaminfo; + AVIStreamInfo(stream, &streaminfo, sizeof(streaminfo)); + + if (streaminfo.fccType == streamtypeVIDEO) { + /* video stream */ + + BITMAPINFOHEADER bitmap; + LONG size = sizeof(bitmap); + AVIStreamReadFormat(stream, 0, &bitmap, &size); + + if(1) { + i->bitmap = bitmap; + i->vs = stream; + i->width = abs(bitmap.biWidth); + i->height = abs(bitmap.biHeight); + } else { + fprintf(stderr, "Ignoring video stream: %dx%d compression=%d planes=%d\n", + abs(bitmap.biWidth), abs(bitmap.biHeight), + bitmap.biCompression,bitmap.biPlanes); + } + } + else if (streaminfo.fccType == streamtypeAUDIO) { + /* audio stream */ + + WAVEFORMATEX waveformat; + LONG size = sizeof(waveformat); + AVIStreamReadFormat(stream, 0, &waveformat, &size); + + if(waveformat.wBitsPerSample == 16 || + waveformat.wBitsPerSample == 8 || + waveformat.wBitsPerSample == 1 + ) { + i->waveformat = waveformat; + i->as = stream; + i->channels = waveformat.nChannels; + i->samplerate = waveformat.nSamplesPerSec; + } else { + fprintf(stderr, "Ignoring audio stream: bitspersample=%d\n", waveformat.wBitsPerSample); + } + } + t++; + } + + if(i->vs) { + if(verbose) { + printf("vfw: video stream: %dx%d, %.2f\n", i->width, i->height, i->fps); + } + vr->width = i->width; + vr->height = i->height; + vr->fps = i->fps; + } else { + fprintf(stderr, "AVIReader: Warning: No video stream\n"); + } + if(i->as) { + if(verbose) { + printf("vfw: audio stream: %d channels, %d samples/sec", i->channels, i->samplerate); + } + vr->channels = i->channels; + vr->samplerate = i->samplerate; + } else { + fprintf(stderr, "AVIReader: Warning: No audio stream\n"); + } + + i->getframe = AVIStreamGetFrameOpen(i->vs, 0); + if(!i->getframe) { + fprintf(stderr, "Couldn't initialize AVIStream for %s- codec missing?\n", filename); + return -1; + } + + i->video_pos = AVIStreamStart(i->vs); + i->video_end = AVIStreamEnd(i->vs); + i->audio_pos = 0; + i->audio_end = 0x7fffffff; + + return 0; +} + +#else //WIN32 + +int videoreader_vfw_open(videoreader_t* vr, char* filename) +{ + return -1; +} + +#endif //WIN32 + diff -Nru swftools-0.9.2+ds1/avi2swf/videoreader_vfw.hh swftools-0.9.1/avi2swf/videoreader_vfw.hh --- swftools-0.9.2+ds1/avi2swf/videoreader_vfw.hh 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/avi2swf/videoreader_vfw.hh 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,29 @@ +/* videoreader_vfw.hh + Read avi files using video for windows (vfw). + + Part of the swftools package. + + 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 */ + +#ifndef __videoreader_vfw_h__ +#define __videoreader_vfw_h__ + +#include "videoreader.h" + +int videoreader_vfw_open(videoreader_t* v, char* filename); + +#endif diff -Nru swftools-0.9.2+ds1/ChangeLog swftools-0.9.1/ChangeLog --- swftools-0.9.2+ds1/ChangeLog 2011-12-12 21:29:27.000000000 +0000 +++ swftools-0.9.1/ChangeLog 2012-06-20 15:37:18.000000000 +0000 @@ -295,3 +295,12 @@ * librfxswf: support for fontalignzones * gpdf2swf: completely reworked pdf2swf GUI (Ricardo Pedroso) * as3compile: many bugfixes, support for swc libraries + +0.9.2: + * as3compile: code cleanup + * lib/filters/remove_invisible_characters: new filter for pdf2swf + * lib/filters/rescale_images: new filter + * lib/gfximage: new fft based image rescaling + * lib/gfxpoly/moments: Added functions for polygon moments. + * pdf2swf: refactoring, bugfixes, started Poppler integration + * src/ttftool: new tool, for debugging Flash 9 TTF fonts diff -Nru swftools-0.9.2+ds1/debian/bzr-builder.manifest swftools-0.9.1/debian/bzr-builder.manifest --- swftools-0.9.2+ds1/debian/bzr-builder.manifest 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/debian/bzr-builder.manifest 2012-06-20 15:37:24.000000000 +0000 @@ -0,0 +1,4 @@ +# bzr-builder format 0.3 deb-version {debupstream}-0~4935 +lp:~guilhem-fr/swftools/trunk revid:git-v1:4126f6f9c3d4a3214249326a08662942a3b2615b +merge fix-xpdf lp:~guilhem-fr/swftools/fix-FTBFS-xpdf revid:guilhem+ubuntu@lettron.fr-20120321182130-mylc6r78b0765pqc +nest packaging lp:~guilhem-fr/swftools/debian debian revid:guilhem+ubuntu@lettron.fr-20120402150052-hxiauzrhg9udv59r diff -Nru swftools-0.9.2+ds1/debian/changelog swftools-0.9.1/debian/changelog --- swftools-0.9.2+ds1/debian/changelog 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/changelog 2012-06-20 15:37:24.000000000 +0000 @@ -1,107 +1,23 @@ -swftools (0.9.2+ds1-2) unstable; urgency=low +swftools (0.9.1-0~4935~quantal1) quantal; urgency=low - * Removed numbering from patch names and sorted alphabetically. - * Build with LAME support. - * Updated copyright file. - - -- Christian Welzel Sat, 21 Apr 2012 12:42:54 +0100 - -swftools (0.9.2+ds1-1) unstable; urgency=low - - * New maintainer (Closes: 583982). - * New upstream release. - * Bump Standards Version to 3.9.3. - * Switch to source format 3.0 (quilt), remove dpatch, rename patch files. - * Raise dh compat level to 7. - * debian/rules completely rewritten. - * Add build-depends on autotools-dev, flex, libjpeg8-dev. - * Refresh patches. - * Remove 02_faq.patch (file FAQ removed from upstream source). - * README.source rewritten. - * Add build depends on libpoppler-dev and autoconf. - * Removed conflict and replace with libming =< 1:0.3.0-11.1 as all versions - in debian are later than this one. - * Updated watch file. - - -- Christian Welzel Sun, 1 Apr 2012 12:42:54 +0100 - -swftools (0.9.0-0ubuntu2) lucid; urgency=low - - * Initial release for Lucid - - patches/05_xpdf-pl4.patch: added pl4 patch to embdded copy of xpdf - * Fixed spelling error description - * Updated standards version - * Added README.source - * Added misc:Depends - * Manually purged more files left behind after a make clean - * Added debian/format - * Took over as maintainer as this will now reside in partner - - -- Brian Thomason Tue, 06 Apr 2010 17:10:53 -0400 - -swftools (0.9.0-0ubuntu1) karmic; urgency=low - - * New upstream release (LP: #369931) - - patches/01_manpages: edited to match updated version of src/pdf2swf.1 and - src/wav2swf.1 - - patches/02_faq: edited to match updated version of FAQ - - patches/04_makefile: edited to delete the patch on lib/Makefile.in and - src/Makefile.in (applied upstream) - - deleted patch 99_configure_for_python2.5_and_2.6 (applied upstream) - - debian/swftools.doc: deleted installation of TODO and - pdf2swf/HOWTO_pdf2swf as they don't exist anymore - - -- Fabrice Coutadeur Thu, 30 Apr 2009 05:22:19 +0200 - -swftools (0.8.1-2.1ubuntu1) jaunty; urgency=low - - * debian/rules: - - Added include of /usr/share/python/python.mk - - Changed site-package by $(call py_sitename_sh, $@) (LP: #?????) - * debian/python-rfxswf.install: changed site-packages to *-packages to take - into account dist-packages directory - * debian/patches/99_configure_for_python2.5_and_2.6.dpatch: patch configure - file to take python 2.5 and 2.6 into account - - -- Fabrice Coutadeur Tue, 31 Mar 2009 04:42:00 +0000 - -swftools (0.8.1-2.1) unstable; urgency=low - - * Non-maintainer upload. - * Add versioned Replaces and Conflicts on libming-util. (Closes: #480378). - * Remove optional build-depends on libart-dev. - * Fix libgif4-dev dependency. (Should be libgif-dev). - * Fix up python package building. (Closes: #509629). - + Thanks a million to Thomas Viehmann. - - -- Barry deFreese Tue, 23 Dec 2008 13:58:42 -0500 - -swftools (0.8.1-2) unstable; urgency=low - - * Fixed the python-rfxswf dependencies. (Closes: #427834). - * Changed the python-rfxswf to comply with the policy. - * Move Homepage from package description to source stanza. - * Replace libungif4-dev build-dep with libgif-dev. - * Improve watch file regexp. - * Add debian/pyversions file. - * Fixed the minus signs in the manpages. - * Format copyright file for UTF-8. - * Bump Standards Version to 3.8.0. - - -- Simo Kauppi Thu, 10 Dec 2008 20:10:01 +0200 - -swftools (0.8.1-1) unstable; urgency=low - - * New upstream release - * Fixed the debian/copyright to include the exceptions in MD5.c and - pdf2swf/fonts/* - * Disabled the failing check for gcc 2.95 compiler + * Auto build. - -- Simo Kauppi Sun, 4 Mar 2007 10:02:33 +0200 + -- Guilhem Lettron Wed, 20 Jun 2012 15:37:24 +0000 -swftools (0.8.0-1) unstable; urgency=low +swftools (0.9.1-0) precise; urgency=low - * Initial release. (Closes: #187275: ITP: swftools -- collection of - SWF (Flash) manipulation and generation - Debian Bug report logs) + * update upstream + * fix FTBFS + * remove protected pdf code - -- Simo Kauppi Wed, 31 Jan 2007 17:46:16 +0200 + -- Guilhem Lettron Thu, 22 Mar 2012 14:49:46 +0100 + +swftools (0.9.1-0maverick2) maverick; urgency=low + + * pdf2swf: bugfixes, speedups + * pdf2swf: improved font quality (FlashType) + * librfxswf: support for fontalignzones + * gpdf2swf: completely reworked pdf2swf GUI (Ricardo Pedroso) + * as3compile: many bugfixes, support for swc libraries + + -- PIERSON Yves Thu, 26 Aug 2010 13:02:10 +0200 diff -Nru swftools-0.9.2+ds1/debian/control swftools-0.9.1/debian/control --- swftools-0.9.2+ds1/debian/control 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/control 2012-06-20 15:37:24.000000000 +0000 @@ -1,48 +1,28 @@ Source: swftools -Section: utils +Section: devel Priority: extra -Maintainer: Christian Welzel -Build-Depends: - automake, - autotools-dev, - debhelper (>= 7.0.50~), - flex, - libfontconfig1-dev, - libfreetype6-dev, - libgif-dev, - libjpeg8-dev, - libmp3lame-dev, - libt1-dev, - zlib1g-dev -Standards-Version: 3.9.3 +Maintainer: PIERSON Yves +Build-Depends: debhelper (>= 7), autotools-dev, libjpeg62-dev, libfreetype6-dev +Standards-Version: 3.8.3 Homepage: http://www.swftools.org/ Package: swftools Architecture: any -Depends: gsfonts, ${misc:Depends}, ${shlibs:Depends} -Suggests: gs-common -Description: Collection of utilities for SWF file manipulation/creation - SWF Tools is a collection of SWF (Flash) manipulation and creation utilities. - . - This package includes: as3compile, font2swf, gif2swf, jpeg2swf, png2swf, - swfcombine, swfextract, swfdump, swfrender, swfstrings, swfbbox, swfc and - wav2swf. - . - * as3compile is a standalone ActionScript 3.0 compiler. Mostly compatible - with Flex. - * font2swf converts font files (TTF, Type1) into SWF. - * gif2swf converts GIFs into SWF. It is also able to handle animated gifs. - * jpeg2swf takes one or more JPEG pictures and generates an SWF slideshow. - * png2swf takes one or more PNG pictures and generates an SWF slideshow. - * swfcombine is a tool for inserting SWFs into Wrapper SWFs. (Templates) - E.g. for including the pdf2swf SWFs into some sort of Browsing-SWF. - * swfextract allows one to extract Movieclips, Sounds, Images etc. from SWF - files. - * swfdump prints out various information about SWFs. - * swfrender converts a swf to an image. - * swfstrings scans SWFs for text data. - * swfbbox allows one to readjust SWF bounding boxes. - * swfc is a tool for creating SWF files from simple script files. - * wav2swf converts WAV files into SWF. - . - This package does not include pdf2swf and avi2swf. +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: SWFTools is a collection of utilities for working with Adobe Flash files (SWF files). + The tool collection includes programs for reading SWF files, combining them, and creating them from other content (like images, sound files, videos or sourcecode). SWFTools is released under the GPL. + The current collection is comprised of the programs detailed below: + * PDF2SWF A PDF to SWF Converter. Generates one frame per page. Enables you to have fully formatted text, including tables, formulas, graphics etc. inside your Flash Movie. It's based on the xpdf PDF parser from Derek B. Noonburg. + * SWFCombine A multi-function tool for inserting SWFs into Wrapper SWFs, contatenating SWFs, stacking SWFs or for basic parameter manipulation (e.g. changing size). + * SWFStrings Scans SWFs for text data. + * SWFDump Prints out various informations about SWFs, like contained images/fonts/sounds, disassembly of contained code as well as cross-reference and bounding box data. + * JPEG2SWF Takes one or more JPEG pictures and generates a SWF slideshow from them. Supports motion estimation compression (h.263) for better compression of video sequences. + * PNG2SWF Like JPEG2SWF, only for PNGs. + * GIF2SWF Converts GIFs to SWF. Also able to handle animated gifs. + * WAV2SWF Converts WAV audio files to SWFs, using the L.A.M.E. MP3 encoder library. + * AVI2SWF Converts AVI animation files to SWF. It supports Flash MX H.263 compression. Some examples can be found at examples.html. (Notice: this tool is not included anymore in the latest version, as ffmpeg or mencoder do a better job nowadays) + * Font2SWF Converts font files (TTF, Type1) to SWF. + * SWFBBox Allows to read out, optimize and readjust SWF bounding boxes. + * SWFC A tool for creating SWF files from simple script files. Includes support for both ActionScript 2.0 as well as ActionScript 3.0. + * SWFExtract Allows to extract Movieclips, Sounds, Images etc. from SWF files. + * AS3Compile A standalone ActionScript 3.0 compiler. Mostly compatible with Flex. \ No newline at end of file diff -Nru swftools-0.9.2+ds1/debian/copyright swftools-0.9.1/debian/copyright --- swftools-0.9.2+ds1/debian/copyright 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/copyright 2012-06-20 15:37:24.000000000 +0000 @@ -1,44 +1,40 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: swftools -Upstream-Contact: http://www.swftools.org/ -Source: http://www.swftools.org/download.html - -Files: debian/* -Copyright: 2007-2008, Simo Kauppi - 2008, Barry deFreese - 2009, Fabrice Coutadeur - 2010, Brian Thomason - 2012, Christian Welzel -License: GPL-2+ - -Files: * -Copyright: 2000-2007, Matthias Kramm - 2000-2003, Rainer Böhme - 2005, Daichi Shinozaki - 1996-2007, Glyph & Cog, LLC - 1998-2001, Raph Levien - 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. - 2002, Opaque Industries - http://www.opaque.net - 1995, 1996, 1997, and 1998 WIDE Project. - 2003, Poul-Henning Kamp - 2004, Mederra Oy - 2005, Joel Yliluoma - 1997, URW Software - 1999, (URW)++ Design & Development -License: GPL-2+ - -License: GPL-2+ - 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., - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -X-Comment: On Debian GNU/Linux systems, the complete text of the GNU General - Public License can be found in the /usr/share/common-licenses/GPL-2 file. +This work was packaged for Debian by: + + PIERSON Yves on Wed, 25 Aug 2010 16:28:55 +0200 + +It was downloaded from http://www.swftools.org/download.html + +Upstream Author(s): + + Matthias Kramm + Rainer Böhme + De Clarke + +Copyright: + + Copyright (C) 2010 Matthias Kramm + Copyright (C) 2010 Rainer Böhme + Copyright (C) 2010 De Clarke + +License: + + 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 + +The Debian packaging is: + + Copyright (C) 2010 PIERSON Yves + +and is licensed under the GPL version 3, +see `/usr/share/common-licenses/GPL-3'. diff -Nru swftools-0.9.2+ds1/debian/patches/add-missing-m4.patch swftools-0.9.1/debian/patches/add-missing-m4.patch --- swftools-0.9.2+ds1/debian/patches/add-missing-m4.patch 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/patches/add-missing-m4.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,236 +0,0 @@ -Description: Add missing m4 macros for autoconf - The upstream source tarball misses some m4 macros to rebuild configure. - These macros are taken from upstream git repository. -Author: Christian Welzel -Last-Update: 2012-02-05 - ---- /dev/null -+++ swftools/m4/fftw.m4 -@@ -0,0 +1,52 @@ -+AC_DEFUN([RFX_CHECK_FFTW], -+[ -+ OLDCPPFLAGS="${CPPFLAGS}" -+ OLDLIBS="${LIBS}" -+ -+ AC_CHECK_LIB(fftw3f, fftwf_plan_dft_r2c_2d, [HAVE_LIBFFTW3=1],) -+ AC_CHECK_HEADERS(fftw3.h,[HAVE_FFTW3_H=1]) -+ -+ if test "x${HAVE_LIBFFTW3}" != "x";then -+ if test "x${HAVE_FFTW3_H}" != "x";then -+ HAVE_FFTW3=1 -+ fi -+ fi -+ -+ if test "x${HAVE_FFTW3}" = "x1"; then -+ LIBS="$LIBS -lfftw3f" -+ AC_MSG_CHECKING([whether we can compile the fftw3 test program]) -+ -+ cat > conftest.c << EOF -+ #include -+ -+ int main() -+ { -+ char*data = fftw_malloc(sizeof(fftwf_complex)*600*800); -+ fftwf_plan plan = fftwf_plan_dft_2d(600, 800, (fftwf_complex*)data, (fftwf_complex*)data, FFTW_FORWARD, FFTW_ESTIMATE); -+ plan = fftwf_plan_dft_r2c_2d(600, 800, (float*)data, (fftwf_complex*)data, FFTW_ESTIMATE); -+ plan = fftwf_plan_dft_c2r_2d(600, 800, (fftwf_complex*)data, (float*)data, FFTW_ESTIMATE); -+ fftwf_execute(plan); -+ fftwf_destroy_plan(plan); -+ } -+EOF -+ -+ ac_link='$CC $CPPFLAGS $CFLAGS conftest.c $LDFLAGS $LIBS -o conftest${ac_exeext}' -+ if { (eval echo fftw3.m4:71: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then -+ AC_MSG_RESULT(yes) -+ AC_DEFINE([HAVE_FFTW3], [1], [Define if fftw3 is available]) -+ else -+ echo "configure: failed program was:" >&5 -+ cat conftest.c >&5 -+ HAVE_FFTW3=0 -+ AC_MSG_RESULT(no) -+ fi -+ rm -f conftest* -+ fi -+ -+ # if the above didn't work out, reset all changes to the compiler variables. -+ if test "x${HAVE_FFTW3}" "!=" "x1"; then -+ CPPFLAGS=$OLDCPPFLAGS -+ LIBS=$OLDLIBS -+ fi -+]) -+ ---- /dev/null -+++ swftools/m4/lowercase.m4 -@@ -0,0 +1,17 @@ -+AC_DEFUN([RFX_CHECK_LOWERCASE_UPPERCASE], -+[ -+AC_MSG_CHECKING([whether the filesystem normalizes file names]) -+ -+echo test1 > __abcdefghijklmnopqrstuvwxyz.txt -+echo test2 > __ABCDEFGHIJKLMNOPQRSTUVWXYZ.txt -+if test `cat __abcdefghijklmnopqrstuvwxyz.txt` = "test2";then -+ AC_MSG_RESULT(yes) -+ AC_DEFINE([LOWERCASE_UPPERCASE], [1], [Define if the file system is case invariant]) -+else -+ AC_MSG_RESULT(no) -+fi -+ -+rm -f __abcdefghijklmnopqrstuvwxyz.txt -+rm -f __ABCDEFGHIJKLMNOPQRSTUVWXYZ.txt -+]) -+ ---- /dev/null -+++ swftools/m4/opengl.m4 -@@ -0,0 +1,55 @@ -+AC_DEFUN([RFX_CHECK_OPENGL], -+[ -+OLDCPPFLAGS="${CPPFLAGS}" -+OLDLIBS="${LIBS}" -+ -+AC_CHECK_LIB(GL, glBegin) -+AC_CHECK_LIB(GLU, gluBeginSurface) -+AC_CHECK_LIB(glut, glutInit) -+AC_CHECK_HEADERS(GL/gl.h GL/glut.h) -+ -+cat > conftest.c << EOF -+#include -+#include -+#include -+ -+int main(int argc, char*argv[]) -+{ -+ glutInit(&argc, argv); -+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); -+ glutInitWindowSize(320,200); -+ glutInitWindowPosition(0,0); -+ glutCreateWindow("main"); -+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); -+ glShadeModel(GL_SMOOTH); -+ glEnable (GL_LINE_SMOOTH); -+ glEnable (GL_POLYGON_SMOOTH); -+ glEnable (GL_BLEND); -+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -+ glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE); -+ glHint (GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE); -+} -+EOF -+ -+AC_MSG_CHECKING([whether we can compile the opengl test program]) -+ -+ac_link='$CC $CPPFLAGS $CFLAGS conftest.c $LDFLAGS $LIBS -o conftest${ac_exeext}' -+if { (eval echo opengl.m4:71: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then -+ AC_MSG_RESULT(yes) -+ HAVE_OPENGL=1 -+ AC_DEFINE([HAVE_OPENGL], [1], [Defined if opengl is available]) -+else -+ echo "configure: failed program was:" >&5 -+ cat conftest.c >&5 -+ HAVE_OPENGL= -+ AC_MSG_RESULT(no) -+fi -+rm -f conftest* -+ -+# if the above didn't work out, reset all changes to the compiler variables. -+if test "x${HAVE_OPENGL}" "!=" "x1"; then -+ CPPFLAGS=$OLDCPPFLAGS -+ LIBS=$OLDLIBS -+fi -+]) -+ ---- /dev/null -+++ swftools/m4/ruby.m4 -@@ -0,0 +1,94 @@ -+AC_DEFUN([RFX_CHECK_RUBY], -+[ -+AC_PATH_PROG([RUBY], [ruby],,) -+ -+RUBY_CPPFLAGS="" -+RUBY_LDFLAGS="" -+RUBY_LIBS="" -+ -+rubylib=ruby18 -+ -+AC_MSG_CHECKING([for ruby's include directory]) -+if test "x$RUBY" '!=' "x";then -+ rubyinc=`$RUBY -e 'require "rbconfig";puts Config::expand(Config::CONFIG.send("\x5b\x5d", "archdir"))' 2>/dev/null` -+ if test -d $rubyinc;then -+ AC_MSG_RESULT($rubyinc) -+ -+ # If we got a sensible archdir, we also ask ruby to supply us with CPPFLAGS -+ # and LDFLAGS. -+ AC_MSG_CHECKING([for ruby's cpp flags]) -+ rubycpp=`$RUBY -e 'require "rbconfig";puts Config::expand(Config::CONFIG.send("\x5b\x5d", "CPPFLAGS"))' 2>/dev/null` -+ AC_MSG_RESULT($rubycpp) -+ -+ AC_MSG_CHECKING([for ruby's ld flags]) -+ rubyld=`$RUBY -e 'require "rbconfig";puts Config::expand(Config::CONFIG.send("\x5b\x5d", "LIBRUBYARG_SHARED"))' 2>/dev/null` -+ rubyld2=`$RUBY -e 'require "rbconfig";v=Config::expand(Config::CONFIG.send("\x5b\x5d", "LIBRUBY_LDSHARED"));puts v.gsub(/^g?cc/,"")' 2>/dev/null` -+ AC_MSG_RESULT("$rubyld $rubyld2") -+ -+ AC_MSG_CHECKING([for ruby library name]) -+ rubylib=`$RUBY -e 'require "rbconfig";puts Config::expand(Config::CONFIG.send("\x5b\x5d", "RUBY_SO_NAME"))' 2>/dev/null` -+ AC_MSG_RESULT($rubylib) -+ -+ RUBY_CPPFLAGS="$rubycpp -I$rubyinc $RUBY_CPPFLAGS" -+ RUBY_LDFLAGS="$rubyld $rubyld2 $RUBY_LDFLAGS" -+ RUBY_INSTALLDIR="$rubyinc" -+ else -+ AC_MSG_RESULT('unknown') -+ fi -+else -+ AC_MSG_RESULT('unknown') -+fi -+ -+#OLDLDFLAGS="$LDFLAGS" -+#LDFLAGS="$LDFLAGS $RUBY_LDFLAGS" -+#AC_CHECK_LIB($rubylib, rb_define_method, HAVE_RUBY_LIB=1,) -+#LDFLAGS="$OLDLDFLAGS" -+ -+OLDCPPFLAGS="$CPPFLAGS" -+CPPFLAGS="$CPPFLAGS $RUBY_CPPFLAGS" -+AC_CHECK_HEADERS([ruby.h],[HAVE_RUBY_H=1]) -+CPPFLAGS="$OLDCPPFLAGS" -+ -+AC_MSG_CHECKING([whether we should compile the ruby module]) -+if test "x${HAVE_RUBY_H}" '!=' "x";then -+ #RUBY_LIBS="$RUBY_LIBS -l$rubylib" -+ -+ cat > conftest.c << EOF -+#include -+static VALUE foobar; -+VALUE foobar_set_foo(VALUE module, VALUE _key, VALUE _value) -+{ -+ return Qnil; -+} -+int Init_foobar() -+{ -+ foobar = rb_define_module("foobar"); -+ rb_define_module_function(foobar, "set_foo", foobar_set_foo, 2); -+ return 0; -+} -+int main() {return 0;} -+EOF -+ ac_link='$CC $SHARED $CPPFLAGS $RUBY_CPPFLAGS $CFLAGS conftest.c $LDFLAGS $RUBY_LDFLAGS $LIBS $RUBY_LIBS -o conftest${SLEXT}' -+ if { (eval echo ruby.m4: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${SLEXT}; then -+ RUBY_OK=yes -+ else -+ echo "configure: failed program was:" >&5 -+ cat conftest.c >&5 -+ fi -+ rm -f conftest* -+fi -+ -+if test "x${RUBY_OK}" '=' "xyes"; then -+ AC_MSG_RESULT([yes]) -+ AC_SUBST(RUBY_LIBS) -+ AC_SUBST(RUBY_CPPFLAGS) -+ AC_SUBST(RUBY_LDFLAGS) -+ AC_SUBST(RUBY_INSTALLDIR) -+else -+ AC_MSG_RESULT([no]) -+ RUBY_CPPFLAGS="" -+ RUBY_LDFLAGS="" -+ RUBY_LIBS="" -+ RUBY_INSTALLDIR="" -+fi -+]) diff -Nru swftools-0.9.2+ds1/debian/patches/add-swfrender-manpage.patch swftools-0.9.1/debian/patches/add-swfrender-manpage.patch --- swftools-0.9.2+ds1/debian/patches/add-swfrender-manpage.patch 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/patches/add-swfrender-manpage.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -Description: Add manpage for swfrender -Author: Christian Welzel -Last-Update: 2012-02-15 - ---- /dev/null -+++ swftools/src/swfrender.1 -@@ -0,0 +1,29 @@ -+.TH swfrender "1" "April 2009" "swfrender" "swftools" -+.SH NAME -+swfrender - creates bitmaps from swf. -+ -+.SH Synopsis -+.B swfrender file.swf [-o output.png] -+ -+.SH DESCRIPTION -+Swfrender creates bitmaps from swf files created with pdf2swf, jpeg2swf or png2swf. -+.PP -+ -+.SH OPTIONS -+.TP -+\fB\-h\fR, \fB\-\-help\fR -+ Print short help message and exit -+.TP -+\fB\-l\fR, \fB\-\-legacy\fR -+ Use old rendering framework -+.TP -+.TP -+\fB\-o\fR, \fB\-\-output\fR \fIfilename\fR -+ Write output to file \fIfilename\fR. (If not given, the output will go -+ to a file called "output.swf") -+.TP -+\fB\-V\fR, \fB\-\-version\fR -+ Print version info and exit -+.SH AUTHOR -+ -+Matthias Kramm diff -Nru swftools-0.9.2+ds1/debian/patches/configure.patch swftools-0.9.1/debian/patches/configure.patch --- swftools-0.9.2+ds1/debian/patches/configure.patch 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/patches/configure.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -## 03_configure.patch by Simo Kauppi -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: This patch patches the configure script, which was generated -## DP: by running the latest aclocal and autoconf. -## DP: The only difference to the upstream is the avifile-config, -## DP: which gives rpath (see bug #347536). - ---- swftools_2011-12-15.orig/configure -+++ swftools_2011-12-15/configure -@@ -6779,7 +6779,7 @@ - EOF - - if test "x$AVIFILE_CONFIG" '!=' "x";then -- AVIFILE_LIBS=`$AVIFILE_CONFIG --libs` -+ AVIFILE_LIBS=`$AVIFILE_CONFIG --libs |sed 's/-Wl,-rpath,\/usr\/lib\ //g'` - AVIFILE_CFLAGS=`$AVIFILE_CONFIG --cflags` - avifile_link='$CXX $CPPFLAGS $CXXFLAGS $AVIFILE_CFLAGS conftest.cpp $AVIFILE_LIBS -o conftest${ac_exeext}' - if { (eval echo avi2swf.m4:71: \"$avifile_link\") 1>&5; (eval $avifile_link) 2>&5; } && test -s conftest${ac_exeext} && ./conftest${ac_exeext}; then diff -Nru swftools-0.9.2+ds1/debian/patches/makefile.patch swftools-0.9.1/debian/patches/makefile.patch --- swftools-0.9.2+ds1/debian/patches/makefile.patch 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/patches/makefile.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -## 04-makefile.patch by Simo Kauppi -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: This patch adds the LDFLAGS to linker in Makefile.common.in to pass -## DP: the -WL,-z defs parameters. -## DP: This patch also removes the libart from the lib/Makefile.in and -## DP: src/Makefile.in, because we use the Debian libart instead of the -## DP: one included in the upstream tar ball. - ---- swftools.orig/Makefile.common.in -+++ swftools/Makefile.common.in -@@ -11,8 +11,8 @@ - DEP=@CC@ -MM $(DEFS) $(INCLUDES) @CPPFLAGS@ - C=@CC@ -c $(DEFS) $(INCLUDES) @CPPFLAGS@ @CFLAGS@ - CC=@CXX@ -c $(DEFS) $(INCLUDES) @CPPFLAGS@ @CXXFLAGS@ --L=@CC@ $(DEFS) --LL=@CXX@ $(DEFS) -+L=@CC@ $(DEFS) $(LDFLAGS) -+LL=@CXX@ $(DEFS) $(LDFLAGS) - AR=@AR@ - LIBTOOL=@LIBTOOL@ - SC=$(LIBTOOL) @CC@ -c $(DEFS) $(INCLUDES) @CPPFLAGS@ @CFLAGS@ ---- swftools.orig/swfs/Makefile.in -+++ swftools/swfs/Makefile.in -@@ -41,9 +41,9 @@ - $(INSTALL_DATA) ./PreLoaderTemplate.swf $(pkgdatadir)/swfs/PreLoaderTemplate.swf - $(INSTALL_DATA) ./tessel_loader.swf $(pkgdatadir)/swfs/tessel_loader.swf - $(INSTALL_DATA) ./swft_loader.swf $(pkgdatadir)/swfs/swft_loader.swf -- rm -f $(pkgdatadir)/swfs/default_viewer.swf -o -L $(pkgdatadir)/swfs/default_viewer.swf -+ rm -f $(pkgdatadir)/swfs/default_viewer.swf - $(LN_S) $(pkgdatadir)/swfs/simple_viewer.swf $(pkgdatadir)/swfs/default_viewer.swf -- rm -f $(pkgdatadir)/swfs/default_loader.swf -o -L $(pkgdatadir)/swfs/default_loader.swf -+ rm -f $(pkgdatadir)/swfs/default_loader.swf - $(LN_S) $(pkgdatadir)/swfs/tessel_loader.swf $(pkgdatadir)/swfs/default_loader.swf - - uninstall: diff -Nru swftools-0.9.2+ds1/debian/patches/manpages.patch swftools-0.9.1/debian/patches/manpages.patch --- swftools-0.9.2+ds1/debian/patches/manpages.patch 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/patches/manpages.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,245 +0,0 @@ -## 01-manpages.patch by Simo Kauppi -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: This patch fixes the jpg2swf.1 and swfstrings.1 manpages, which -## DP: have the letter 'ö' in the author's name. -## DP: Fixes also the minus signs in swfextract.1, swfdump.1, swfbbox.1, -## DP: font2swf.1, pdf2swf.1, wav2swf.1 and swfcombine.1 manpages. - ---- swftools.orig/src/font2swf.1 -+++ swftools/src/font2swf.1 -@@ -20,7 +20,7 @@ - Print short help message and exit - .TP - \fB\-v\fR, \fB\-\-verbose\fR -- Be verbose. Use more than one -v for greater effect. -+ Be verbose. Use more than one \-v for greater effect. - .TP - \fB\-o\fR, \fB\-\-output\fR \fIfilename\fR - Write output to file \fIfilename\fR. (If not given, the output will go ---- swftools.orig/src/jpeg2swf.1 -+++ swftools/src/jpeg2swf.1 -@@ -8,7 +8,7 @@ - .SH DESCRIPTION - This tool converts jpeg image files into an SWF animation. It takes any - number of input pictures, and converts them to SWF one\-by\-one, where every --converted picture is a seperate frame in the target SWF. -+converted picture is a separate frame in the target SWF. - - .SH OPTIONS - .TP -@@ -57,6 +57,6 @@ - Make importable as asset with \fIassetname\fR - .SH AUTHORS - --Rainer Böhme -+Rainer B\[:o]hme - .TP - Matthias Kramm ---- swftools.orig/src/pdf2swf.1 -+++ swftools/src/pdf2swf.1 -@@ -1,9 +1,9 @@ - .TH pdf2swf "1" "June 2008" "pdf2swf" "swftools" - .SH NAME --pdf2swf - Converts Acrobat PDF files into Flash SWF Animation files. -+pdf2swf \- Converts Acrobat PDF files into Flash SWF Animation files. - - .SH Synopsis --.B pdf2swf [-options] file.pdf -o file.swf -+.B pdf2swf [\-options] file.pdf \-o file.swf - - .SH DESCRIPTION - Converts a PDF file to a SWF file. -@@ -17,7 +17,7 @@ - Print version info and exit - .TP - \fB\-o\fR, \fB\-\-output\fR file.swf -- will go into a seperate file. -+ will go into a separate file. - .TP - \fB\-p\fR, \fB\-\-pages\fR range - 3-5,10-12 -@@ -26,7 +26,7 @@ - Use password for deciphering the pdf. - .TP - \fB\-v\fR, \fB\-\-verbose\fR -- Be verbose. Use more than one -v for greater effect. -+ Be verbose. Use more than one /-v for greater effect. - .TP - \fB\-z\fR, \fB\-\-zlib\fR - The resulting SWF will not be playable in browsers with Flash Plugins 5 and below! -@@ -38,7 +38,7 @@ - Set quality of embedded jpeg pictures to quality. 0 is worst (small), 100 is best (big). (default:85) - .TP - \fB\-s\fR, \fB\-\-set\fR param=value -- Set a SWF encoder specific parameter. See pdf2swf -s help for more information. -+ Set a SWF encoder specific parameter. See pdf2swf \-s help for more information. - .TP - \fB\-w\fR, \fB\-\-samewindow\fR - When clicked on, the page they point to will be opened in the window the SWF is displayed. -@@ -68,7 +68,7 @@ - filename is an arbitrary swf animation. - .TP - \fB\-q\fR, \fB\-\-quiet\fR -- Suppress normal messages. Use -qq to suppress warnings, also. -+ Suppress normal messages. Use \-qq to suppress warnings, also. - .TP - \fB\-S\fR, \fB\-\-shapes\fR - Don't use SWF Fonts, but store everything as shape. ---- swftools.orig/src/swfbbox.1 -+++ swftools/src/swfbbox.1 -@@ -35,7 +35,7 @@ - Clip bounding boxes to movie size - .TP - \fB\-o\fR, \fB\-\-output\fR \fIfilename\fR -- Set output filename to \fIfilename\fR (for -O) -+ Set output filename to \fIfilename\fR (for \-O) - .TP - \fB\-v\fR, \fB\-\-verbose\fR - Be more verbose ---- swftools.orig/src/swfcombine.1 -+++ swftools/src/swfcombine.1 -@@ -29,7 +29,7 @@ - .TP - \fB\-t\fR, \fB\-\-stack\fR - Don't assume the first file is a master file. Instead, store each -- file in a seperate frame. -+ file in a separate frame. - .TP - \fB\-T\fR, \fB\-\-stack1\fR - place each slave in the first frame (no master movie) -@@ -47,7 +47,7 @@ - Clip the slave objects by the corresponding master objects - .TP - \fB\-v\fR, \fB\-\-verbose\fR -- Be verbose. Use more than one -v for greater effect -+ Be verbose. Use more than one \-v for greater effect - .TP - \fB\-F\fR, \fB\-\-flashversion\fR - Set the flash version of the output file. -@@ -72,10 +72,10 @@ - Force the output to have the framerate \fIfps\fR. (Otherwise, the framerate of the master file will be used) - .TP - \fB\-X\fR, \fB\-\-width\fR \fIwidth\fR -- Force movie bbox width to \fIwidth\fR (default: use master width (not with -t)) -+ Force movie bbox width to \fIwidth\fR (default: use master width (not with \-t)) - .TP - \fB\-Y\fR, \fB\-\-height\fR \fIheight\fR -- Force movie bbox height to \fIheight\fR (default: use master height (not with -t)) -+ Force movie bbox height to \fIheight\fR (default: use master height (not with \-t)) - .TP - \fB\-N\fR, \fB\-\-local-with-networking\fR - Make output file "local-with-networking" -@@ -109,7 +109,7 @@ - The slave name may also be the object id, preceded by '#', in which case - the object to be replaced is referenced by id and not by instance name. - .SH Combining (stacking) one or more .swf files without a master --The flash files will be inserted in seperate frames. They will still be -+The flash files will be inserted in separate frames. They will still be - packed into Movieclips, therefore the outputfile will have exactly as many - frames as there were inputfiles. Also, the files don't need to have names. - If you want to access the Movieclips, their names are frameXX, where XX is ---- swftools.orig/src/swfdump.1 -+++ swftools/src/swfdump.1 -@@ -18,7 +18,7 @@ - Print short help message and exit - .TP - \fB\-D\fR, \fB\-\-full\fR -- Show everything. Same as -atp -+ Show everything. Same as \-atp - .TP - \fB\-V\fR, \fB\-\-version\fR - Print version info and exit -@@ -51,16 +51,16 @@ - Print tag's bounding boxes - .TP - \fB\-X\fR, \fB\-\-width\fR -- Print out the horizontal dimension of the movie, in a string of the form "-X width" -+ Print out the horizontal dimension of the movie, in a string of the form "\-X width" - .TP - \fB\-Y\fR, \fB\-\-height\fR -- Print out the vertical dimension of the movie, in a string of the form "-Y height" -+ Print out the vertical dimension of the movie, in a string of the form "\-Y height" - .TP - \fB\-r\fR, \fB\-\-rate\fR -- Print out the frame rate of the movie, in a string of the form "-r rate". -+ Print out the frame rate of the movie, in a string of the form "\-r rate". - .TP - \fB\-f\fR, \fB\-\-frames\fR -- Print out the number of frames in the movie, in a string of the form "-f frames" -+ Print out the number of frames in the movie, in a string of the form "\-f frames" - .TP - \fB\-d\fR, \fB\-\-hex\fR - Print hex output of tag data, too. ---- swftools.orig/src/swfextract.1 -+++ swftools/src/swfextract.1 -@@ -5,7 +5,7 @@ - .B swfextract - [\fIoptions\fR] [\fIfile.swf\fR] - .SH DESCRIPTION --swfextracts allows to extract swf movieclips and objects out of swf files. -+swfextracts allows one to extract swf movieclips and objects out of swf files. - .PP - SWF files are animation files which can be displayed in Web Browsers using - the Flash Plugin. -@@ -27,7 +27,7 @@ - \fIids\fR is a range of JPEG IDs to extract. E.g. 1-2,3,14- - .TP - \fB\-p\fR, \fB\-\-pngs\fR \fIids\fR --\fIids\fR is a range of PNG IDs to extract. E.g. -10,20-30 -+\fIids\fR is a range of PNG IDs to extract. E.g. \-10,20\-30 - .TP - \fB\-f\fR, \fB\-\-frame\fR \fIframes\fR - \fIframes\fR is a range of frames to extract. E.g. 1-10,20-30,40- -@@ -40,7 +40,7 @@ - .TP - \fB\-P\fR, \fB\-\-placeobject\fR - Copy original placeobject tag for the given object into the --output file (Use with -i). This means that the object is -+output file (Use with \-i). This means that the object is - at the same position in the generated movie as in the - original movie. - .TP ---- swftools.orig/src/swfstrings.1 -+++ swftools/src/swfstrings.1 -@@ -30,6 +30,6 @@ - Print version information and exit - .SH AUTHORS - --Rainer Böhme -+Rainer B\[:o]hme - .TP - Matthias Kramm ---- swftools.orig/src/wav2swf.1 -+++ swftools/src/wav2swf.1 -@@ -47,7 +47,7 @@ - Set mp3 bitrate to \fIbps\fR (default: 32) - .TP - \fB\-v\fR, \fB\-\-verbose\fR -- Be more verbose. (Use more than one -v for greater effect) -+ Be more verbose. (Use more than one /-v for greater effect) - .SH AUTHOR - - Matthias Kramm ---- swftools.orig/src/gif2swf.1 -+++ swftools/src/gif2swf.1 -@@ -9,7 +9,7 @@ - .SH DESCRIPTION - This tools converts gif image files into an SWF animation. It takes any - number of input pictures, and converts them to SWF one\-by\-one, where every --converted picture is a seperate frame in the target SWF. -+converted picture is a separate frame in the target SWF. - - .SH OPTIONS - .TP ---- swftools.orig/src/png2swf.1 -+++ swftools/src/png2swf.1 -@@ -9,7 +9,7 @@ - .SH DESCRIPTION - This tools converts png image files into an SWF animation. It takes any - number of input pictures, and converts them to SWF one\-by\-one, where every --converted picture is a seperate frame in the target SWF. -+converted picture is a separate frame in the target SWF. - .PP - The way the - images are encoded in SWF is very similar to PNG (in that a zlib\-based, lossless diff -Nru swftools-0.9.2+ds1/debian/patches/remove-avi2swf.patch swftools-0.9.1/debian/patches/remove-avi2swf.patch --- swftools-0.9.2+ds1/debian/patches/remove-avi2swf.patch 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/patches/remove-avi2swf.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -Description: Do not generate avi2swf. -Author: Christian Welzel -Last-Update: 2012-03-25 - ---- swftools.orig/configure.in -+++ swftools/configure.in -@@ -476,13 +476,13 @@ - echo "* The following headers/libraries are missing: " ${MISSINGLIBS} - fi - --avi2swf="avi2swf/Makefile" --if test "x${AVIFILE}" '!=' "xtrue" -a "x${AVIFIL32}" '!=' "xtrue"; then -- #don't whine, avi2swf is outdated anyway -- #echo "* Disabling avi2swf tool..." -- echo all install uninstall clean: > avi2swf/Makefile -- avi2swf= --fi -+#avi2swf="avi2swf/Makefile" -+#if test "x${AVIFILE}" '!=' "xtrue" -a "x${AVIFIL32}" '!=' "xtrue"; then -+# #don't whine, avi2swf is outdated anyway -+# #echo "* Disabling avi2swf tool..." -+# echo all install uninstall clean: > avi2swf/Makefile -+# avi2swf= -+#fi - - pdf2swf_makefile="lib/pdf/Makefile" - PDF2SWF='pdf2swf$(E)' ---- swftools.orig/Makefile.in -+++ swftools/Makefile.in -@@ -14,8 +14,6 @@ - # cd lib/python;$(MAKE) $@ - @echo making $@ in lib/ruby... - cd src;$(MAKE) $@ -- @echo making $@ in avi2swf... -- cd avi2swf;$(MAKE) $@ - @echo making $@ in swfs... - cd swfs;$(MAKE) $@ - @$(MAKE) $@-local diff -Nru swftools-0.9.2+ds1/debian/patches/remove-fontconfig.patch swftools-0.9.1/debian/patches/remove-fontconfig.patch --- swftools-0.9.2+ds1/debian/patches/remove-fontconfig.patch 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/patches/remove-fontconfig.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -Description: Remove check for fontconfig from configure. - Should remove the depends on libfontconfig. This is not needed as long - as no pdf2swf is build. -Author: Christian Welzel -Last-Update: 2012-04-12 - ---- swftools.orig/configure.in -+++ swftools/configure.in -@@ -285,7 +285,7 @@ - - RFX_CHECK_FREETYPE - --RFX_CHECK_FONTCONFIG -+# RFX_CHECK_FONTCONFIG - - RFX_CHECK_FFTW - diff -Nru swftools-0.9.2+ds1/debian/patches/remove-pdf2swf.patch swftools-0.9.1/debian/patches/remove-pdf2swf.patch --- swftools-0.9.2+ds1/debian/patches/remove-pdf2swf.patch 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/patches/remove-pdf2swf.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -Description: Disable build of libgfxpdf and pdf2swf - Build of python module is also disabled because all these parts - depend on lib/pdf which cannot be build without embedded xpdf copy. -Author: Christian Welzel -Last-Update: 2012-02-18 - ---- swftools.orig/lib/Makefile.in -+++ swftools/lib/Makefile.in -@@ -3,7 +3,7 @@ - top_srcdir = @top_srcdir@ - include ../Makefile.common - --all: librfxswf$(A) libgfxpdf$(A) libbase$(A) libgfx$(A) libgfxswf$(A) libocr$(A) -+all: librfxswf$(A) libbase$(A) libgfx$(A) libgfxswf$(A) libocr$(A) - - lame_objects = lame/psymodel.$(O) lame/fft.$(O) lame/newmdct.$(O) lame/quantize.$(O) lame/takehiro.$(O) lame/reservoir.$(O) lame/quantize_pvt.$(O) lame/vbrquantize.$(O) lame/encoder.$(O) lame/id3tag.$(O) lame/version.$(O) lame/tables.$(O) lame/util.$(O) lame/bitstream.$(O) lame/set_get.$(O) lame/VbrTag.$(O) lame/lame.$(O) - lame_in_source = @lame_in_source@ -@@ -188,8 +188,8 @@ - $(AR) r librfxswf$(A) $(rfxswf_objects) rfxswf.$(O) drawer.$(O) $(lame_in_source) $(h263_objects) $(as12compiler_in_source) $(as3compiler_objects) - $(RANLIB) librfxswf$(A) - --libgfxpdf$(A): pdf/VectorGraphicOutputDev.cc pdf/VectorGraphicOutputDev.h pdf/pdf.cc pdf/pdf.h -- cd pdf;$(MAKE) libgfxpdf -+#libgfxpdf$(A): pdf/VectorGraphicOutputDev.cc pdf/VectorGraphicOutputDev.h pdf/pdf.cc pdf/pdf.h -+# cd pdf;$(MAKE) libgfxpdf - - tests: png.test.c - $(L) png.test.c -o png.test $(LIBS) -@@ -203,5 +203,4 @@ - cd lame && $(MAKE) clean && cd .. || true - cd action && $(MAKE) clean && cd .. - cd python && $(MAKE) clean && cd .. -- cd pdf && $(MAKE) clean && cd .. - ---- swftools.orig/src/Makefile.in -+++ swftools/src/Makefile.in -@@ -3,7 +3,7 @@ - top_srcdir = @top_srcdir@ - include ../Makefile.common - --install_programs = wav2swf$(E) @PNG2SWF@ swfcombine$(E) swfstrings$(E) swfextract$(E) swfdump$(E) swfc$(E) @JPEG2SWF@ @GIF2SWF@ swfbbox$(E) font2swf$(E) swfrender$(E) as3compile$(E) @PDF2SWF@ @PDF2PDF@ -+install_programs = wav2swf$(E) @PNG2SWF@ swfcombine$(E) swfstrings$(E) swfextract$(E) swfdump$(E) swfc$(E) @JPEG2SWF@ @GIF2SWF@ swfbbox$(E) font2swf$(E) swfrender$(E) as3compile$(E) @PDF2PDF@ - programs = $(install_programs) swfbytes$(E) ttftool$(E) - - all: $(programs) -@@ -12,8 +12,6 @@ - $(C) wav2swf.c -o $@ - png2swf.$(O): png2swf.c - $(C) png2swf.c -o $@ --pdf2swf.$(O): pdf2swf.c -- $(C) pdf2swf.c -o $@ - pdf2pdf.$(O): pdf2pdf.c - $(C) pdf2pdf.c -o $@ - gfx2gfx.$(O): gfx2gfx.c -@@ -120,9 +118,6 @@ - PDF2SWF_OBJ=../lib/libgfxswf$(A) ../lib/librfxswf$(A) ../lib/libgfxpdf$(A) ../lib/libgfx$(A) ../lib/libbase$(A) - OCR_OBJ=../lib/libocr$(A) - --pdf2swf$(E): pdf2swf.$(O) $(PDF2SWF_OBJ) -- $(LL) pdf2swf.$(O) -o $@ $(PDF2SWF_OBJ) $(LIBS) $(CXXLIBS) -- $(STRIP) $@ - pdf2pdf$(E): pdf2pdf.$(O) $(PDF2SWF_OBJ) - $(LL) pdf2pdf.$(O) -o $@ $(PDF2SWF_OBJ) $(LIBS) $(CXXLIBS) - $(STRIP) $@ -@@ -143,9 +138,9 @@ - - clean: - rm -f *.o *.obj *.lo *.la *~ gmon.out -- rm -f as3compile gif2swf swfbbox swfbytes swfbytes swfdump pdf2swf wav2swf png2swf swfcombine swfextract swfstrings png2swf jpeg2swf swfc font2swf pdf2pdf gfx2gfx swfrender ttftool -- @rm -f as3compile.exe gif2swf.exe swfbytes.exe swfbytes.exe pdf2swf.exe swfbbox.exe swfdump.exe wav2swf.exe png2swf.exe swfcombine.exe swfextract.exe swfstrings.exe png2swf.exe jpeg2swf.exe swfc.exe font2swf.exe pdf2pdf.exe gfx2gfx.exe swfrender.exe ttftool.exe -- @rm -f as3compile$(E) gif2swf$(E) pdf2swf$(E) swfbytes$(E) swfbytes$(E) swfbbox$(E) swfdump$(E) wav2swf$(E) png2swf$(E) swfcombine$(E) swfextract$(E) swfstrings$(E) png2swf$(E) jpeg2swf$(E) swfc$(E) font2swf$(E) pdf2pdf$(E) gfx2gfx$(E) swfrender$(E) ttftool$(E) -+ rm -f as3compile gif2swf swfbbox swfbytes swfbytes swfdump wav2swf png2swf swfcombine swfextract swfstrings png2swf jpeg2swf swfc font2swf pdf2pdf gfx2gfx swfrender ttftool -+ @rm -f as3compile.exe gif2swf.exe swfbytes.exe swfbytes.exe swfbbox.exe swfdump.exe wav2swf.exe png2swf.exe swfcombine.exe swfextract.exe swfstrings.exe png2swf.exe jpeg2swf.exe swfc.exe font2swf.exe pdf2pdf.exe gfx2gfx.exe swfrender.exe ttftool.exe -+ @rm -f as3compile$(E) gif2swf$(E) swfbytes$(E) swfbytes$(E) swfbbox$(E) swfdump$(E) wav2swf$(E) png2swf$(E) swfcombine$(E) swfextract$(E) swfstrings$(E) png2swf$(E) jpeg2swf$(E) swfc$(E) font2swf$(E) pdf2pdf$(E) gfx2gfx$(E) swfrender$(E) ttftool$(E) - - doc: - perl ../parsedoc.pl wav2swf.doc ---- swftools.orig/Makefile.in -+++ swftools/Makefile.in -@@ -8,12 +8,10 @@ - cd m4;$(MAKE) $@ - @echo making $@ in lib... - cd lib;$(MAKE) $@ -- @echo making $@ in lib/pdf... -- cd lib/pdf;$(MAKE) $@ - @echo making $@ in lib... - cd lib;$(MAKE) $@ -- @echo making $@ in lib/python... -- cd lib/python;$(MAKE) $@ -+# @echo making $@ in lib/python... -+# cd lib/python;$(MAKE) $@ - @echo making $@ in lib/ruby... - cd src;$(MAKE) $@ - @echo making $@ in avi2swf... ---- swftools.orig/lib/python/Makefile.in -+++ swftools/lib/python/Makefile.in -@@ -37,7 +37,8 @@ - $(AR) cru SWF$(A) $(SWF_OBJS) $(SWF_DEPS) - $(RANLIB) SWF$(A) - --GFX_DEPS=../libgfxpdf$(A) ../libgfxswf$(A) ../librfxswf$(A) ../libgfx$(A) ../libocr$(A) ../libbase$(A) -+#GFX_DEPS=../libgfxpdf$(A) ../libgfxswf$(A) ../librfxswf$(A) ../libgfx$(A) ../libocr$(A) ../libbase$(A) -+GFX_DEPS=../libgfxswf$(A) ../librfxswf$(A) ../libgfx$(A) ../libocr$(A) ../libbase$(A) - gfx.$(SLEXT): gfx.$(O) $(GFX_DEPS) Makefile - $(L) -g $(SHARED) gfx.$(O) -o gfx.$(SLEXT) $(GFX_DEPS) $(PYTHON_LIB) $(LIBS) $(CXXLIBS) - gfx$(A): gfx.$(O) $(GFX_DEPS) Makefile diff -Nru swftools-0.9.2+ds1/debian/patches/series swftools-0.9.1/debian/patches/series --- swftools-0.9.2+ds1/debian/patches/series 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -add-missing-m4.patch -add-swfrender-manpage.patch -remove-pdf2swf.patch -remove-avi2swf.patch -manpages.patch -makefile.patch -spelling.patch -remove-fontconfig.patch diff -Nru swftools-0.9.2+ds1/debian/patches/spelling.patch swftools-0.9.1/debian/patches/spelling.patch --- swftools-0.9.2+ds1/debian/patches/spelling.patch 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/patches/spelling.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -Description: Fixes spelling errors not contained in man pages - See also 01_manpages.patch. -Author: Christian Welzel -Last-Update: 2012-02-05 - ---- swftools.orig/src/swfcombine.c -+++ swftools/src/swfcombine.c -@@ -309,7 +309,7 @@ - printf("OR: %s [-rXYomlcv] --dummy [-xys] [file]\n", name); - printf("\n"); - printf("-o , --output explicitly specify output file. (otherwise, output.swf will be used)\n"); -- printf("-t , --stack place each slave in a seperate frame (no master movie)\n"); -+ printf("-t , --stack place each slave in a separate frame (no master movie)\n"); - printf("-T , --stack1 place each slave in the first frame (no master movie)\n"); - printf("-m , --merge Don't store the slaves in Sprites/MovieClips\n"); - printf("-a , --cat concatenate all slave files (no master movie)\n"); diff -Nru swftools-0.9.2+ds1/debian/README.source swftools-0.9.1/debian/README.source --- swftools-0.9.2+ds1/debian/README.source 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/README.source 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -swftools (0.9.1+201202040819+ds1-1) - - * repack upstream tarball to remove - - embedded copy of xpdf - - avi2swf subproject as its dead upstream. Upstream recommends to use mencoder - or ffmpeg. - - -- Christian Welzel Sun, 29 Jan 2012 12:42:54 +0100 diff -Nru swftools-0.9.2+ds1/debian/rules swftools-0.9.1/debian/rules --- swftools-0.9.2+ds1/debian/rules 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/rules 2012-06-20 15:37:24.000000000 +0000 @@ -1,86 +1,83 @@ #!/usr/bin/make -f +# Sample debian/rules that uses debhelper. +# This file is public domain software, originally written by Joey Hess. +# +# This version is for packages that are architecture dependent. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 -SRC_VERSION = $(shell dpkg-parsechangelog | sed -ne 's/^Version: \(\([0-9]\+\):\)\?\(.*\)-.*/\3/p') -ORIG_VERSION = $(shell echo $(SRC_VERSION) | sed -ne 's/+ds1//p') -ORIGTAR = swftools_$(ORIG_VERSION).orig.tar.gz -ORIGDIR = swftools_$(ORIG_VERSION).orig -DEBTAR = swftools_$(SRC_VERSION).orig.tar.gz - -# These are used for cross-compiling and for saving the configure script -# from having to guess our platform (since we know it already) -DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) -DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) - -# --enable-warnings sets CFLAGS to -# "-Wall -Wno-unused -Wno-format -Wno-redundant-decls" -# --enable-debug sets CFLAGS to "-O2 -g" -# in the configure script -#ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) -# CFLAGS = -g -# CFGFLAGS = --enable-warnings -#else -# CFGFLAGS = --enable-warnings --enable-debug -#endif +build: build-stamp +build-stamp: + dh_testdir + + # Add here commands to compile the package. + #$(MAKE) + ./configure + make -%: - dh $@ + touch build-stamp clean: dh_testdir dh_testroot - [ ! -f Makefile ] || $(MAKE) distclean - rm -f core - rm -f python*-stamp - rm -f aclocal.m4 config.h config.log lib/action/Makefile swfs/Makefile lib/pdf/Makefile lib/swf/Makefile - rm -f _pypath.py _pypath.txt - rm -rf lib/python/usr -# [ ! -f configure.dist ] || mv configure.dist configure - dh_autotools-dev_restoreconfig + rm -f build-stamp + + # Add here commands to clean up after the build process. + #$(MAKE) clean + #$(MAKE) distclean + dh_clean -override_dh_auto_configure: - dh_autotools-dev_updateconfig -# mv configure configure.dist - aclocal -I m4 - autoconf - LDFLAGS="-Wl,-z,defs" ./configure --enable-debug --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info --disable-poppler $(CFGFLAGS) - -#override_dh_auto_build: -# # Add libart stuff into the Makefile.common -# cp Makefile.common Makefile.common.bak -# echo "C += $(LIBART_CFLAGS)" >>Makefile.common -# echo "CC += $(LIBART_CFLAGS)" >>Makefile.common -# echo "LIBS += $(LIBART_LIBS)" >>Makefile.common -# $(MAKE) -# $(MAKE) -C lib - -# mv Makefile.common.bak Makefile.common - -# $(MAKE) -C src -# $(MAKE) -C swfs - -# cp Makefile.common Makefile.common.bak -# $(foreach pp, $(python_versions), $(call build_python,$(pp),$(pp)/$(call py_sitename, $(pp)))) -# mv Makefile.common.bak Makefile.common - -override_dh_auto_install: - dh_auto_install -- prefix=$(CURDIR)/debian/tmp/usr - mkdir -p debian/tmp/usr/lib - mkdir -p debian/tmp/usr/include/rfxswf - /usr/bin/install -m 644 lib/librfxswf.a debian/tmp/usr/lib/ - /usr/bin/install -m 644 config.h lib/rfxswf.h lib/bitio.h lib/drawer.h lib/mem.h lib/types.h debian/tmp/usr/include/rfxswf/ - sed -i s/"\(#include \"\.\)\.\(\/config\.h\"\)"/"\1\2"/ debian/tmp/usr/include/rfxswf/rfxswf.h -# cp -r lib/python/usr debian/tmp/ - -get-orig-source: - uscan --no-conf --force-download --rename --download-current-version --destdir=. - mkdir -p _unpack - tar -xzf $(ORIGTAR) -C _unpack - find _unpack -maxdepth 1 -name "swftools*" -type d -exec mv \{} _unpack/swftools_$(ORIG_VERSION).orig \; - rm -rf _unpack/$(ORIGDIR)/lib/pdf/xpdf - rm -rf _unpack/$(ORIGDIR)/avi2swf - tar -czf $(DEBTAR) -C _unpack $(ORIGDIR) - rm -rf _unpack +install: build + dh_testdir + dh_testroot + dh_prep + dh_installdirs + + # Add here commands to install the package into debian/ + #$(MAKE) prefix=`pwd`/debian/`dh_listpackages`/usr install + make prefix=../debian/swftools/usr install + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installcatalogs +# dh_installpam +# dh_installmime +# dh_installinit +# dh_installcron +# dh_installinfo +# dh_installwm +# dh_installudev +# dh_lintian +# dh_bugfiles +# dh_undocumented + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff -Nru swftools-0.9.2+ds1/debian/source/format swftools-0.9.1/debian/source/format --- swftools-0.9.2+ds1/debian/source/format 2012-06-20 15:49:27.000000000 +0000 +++ swftools-0.9.1/debian/source/format 2012-06-20 15:49:28.000000000 +0000 @@ -1 +1 @@ -3.0 (quilt) +3.0 (native) diff -Nru swftools-0.9.2+ds1/debian/swftools.docs swftools-0.9.1/debian/swftools.docs --- swftools-0.9.2+ds1/debian/swftools.docs 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/swftools.docs 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -AUTHORS diff -Nru swftools-0.9.2+ds1/debian/swftools.examples swftools-0.9.1/debian/swftools.examples --- swftools-0.9.2+ds1/debian/swftools.examples 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/swftools.examples 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -doc/fileformat.sc diff -Nru swftools-0.9.2+ds1/debian/swftools.install swftools-0.9.1/debian/swftools.install --- swftools-0.9.2+ds1/debian/swftools.install 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/swftools.install 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/bin -usr/share diff -Nru swftools-0.9.2+ds1/debian/swftools.links swftools-0.9.1/debian/swftools.links --- swftools-0.9.2+ds1/debian/swftools.links 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/swftools.links 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -usr/share/swftools/swfs/tessel_loader.swf usr/share/swftools/swfs/default_loader.swf -usr/share/swftools/swfs/simple_viewer.swf usr/share/swftools/swfs/default_viewer.swf -usr/share/fonts/type1/gsfonts usr/share/swftools/fonts diff -Nru swftools-0.9.2+ds1/debian/watch swftools-0.9.1/debian/watch --- swftools-0.9.2+ds1/debian/watch 2012-04-21 18:18:34.000000000 +0000 +++ swftools-0.9.1/debian/watch 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -version=3 - -# http://www.swftools.org/swftools-2012-02-04-0819.tar.gz -opts=\ -dversionmangle=s/\+ds1[~]*//,\ -uversionmangle=s/(\d+)-(\d+)-(\d+)-(\d+)/0.9.1+$1$2$3$4/,\ -downloadurlmangle=s/.*0.9.1\+(\d{4})(\d{2})(\d{2})(\d{4}).*/http:\/\/www.swftools.org\/swftools-$1-$2-$3-$4.tar.gz/\ - http://www.swftools.org/download.html (?:.*/)?swftools-([\d.-]+)\.tar\.gz Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/doc/Arial.swf and /tmp/M5qDI_SGQH/swftools-0.9.1/doc/Arial.swf differ Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/doc/beach.jpg and /tmp/M5qDI_SGQH/swftools-0.9.1/doc/beach.jpg differ diff -Nru swftools-0.9.2+ds1/doc/Bugs/BadPins.sc swftools-0.9.1/doc/Bugs/BadPins.sc --- swftools-0.9.2+ds1/doc/Bugs/BadPins.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/Bugs/BadPins.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,49 @@ +# (The only difference between those two files is the change alpha to 0 at +# frame 100.) + +.swf bbox=autocrop version=4 fps=25 name="GoodPins.swf" +.box box1 width=100 height=100 color=red line=5 # a simple red box +.frame 0 + .put box1 x=100 y=100 alpha=0 +.frame 60 + .change box1 alpha=100% # box bright +.frame 80 + .change box1 # box hold +.frame 120 + .jump box1 alpha=100% # make the box appear suddenly and leap around a bit +.frame 125 + .jump box1 x+=20 y+=20 +.frame 130 + .jump box1 x-=20 +.frame 135 + .jump box1 x-=20 y-=20 +.frame 140 + .jump box1 x=100 y=100 # put box bck where it belongs +.frame 160 + .change box1 alpha=0 # box fade +.end + + +.swf bbox=autocrop version=4 fps=25 name="BadPins.swf" +.box box1 width=100 height=100 color=red line=5 # a simple red box +.frame 0 + .put box1 x=100 y=100 alpha=0 +.frame 60 + .change box1 alpha=100% # box bright +.frame 80 + .change box1 # box hold +.frame 100 + .change box1 alpha=0 # box fade +.frame 120 + .jump box1 alpha=100% # make the box appear suddenly and leap around a bit +.frame 125 + .jump box1 x+=20 y+=20 # why doesn't this work? +.frame 130 + .jump box1 x-=20 +.frame 135 + .jump box1 x-=20 y-=20 +.frame 140 + .jump box1 x=100 y=100 # put box bck where it belongs +.frame 160 + .change box1 alpha=0 # box fade +.end diff -Nru swftools-0.9.2+ds1/doc/caiviar.css swftools-0.9.1/doc/caiviar.css --- swftools-0.9.2+ds1/doc/caiviar.css 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/caiviar.css 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,343 @@ +BODY { + color: black; + font-family: Verdana, Arial, Helvetica; + font-size: 1.0em; +} + +.dochead { + margin-top: 1.5em; + font-size: 1.7em; + font-weight: bold; + color: #000000; +} + +.chaphead { +/* margin: 1.2em 14% 0.5em 3%; */ + font-size: 2.3em; + font-weight: bold; + color: #0000ff; +} + +.chapnum { + font-size: 0.8em; + font-weight: bold; + color: #0000ff; +} + +.secthead { +/* margin: 1.0em 14% 0.2em 4%;*/ +/* My suggested new color and size, to take the new subsections (level 3) into account. + color: #2545ee; + font-size: 1.1em;*/ + color: #2020ff; + font-size: 1.4em; + font-weight: bold; + font-family: Verdana, Arial, Helvetica; + /*text-decoration: underline;*/ +} + +.subsecthead { +/* margin: 1.0em 14% 0.2em 4%;*/ + color: #6c6cff; + font-size: 1.2em; + font-weight: bold; + font-family: Verdana, Arial, Helvetica; +/* text-decoration: underline; */ +} + +.subsubsecthead { +/* margin: 1.0em 14% 0.2em 4%;*/ + color: #303030; + font-size: 1.0em; + font-weight: bold; + font-family: Verdana, Arial, Helvetica; +/* text-decoration: underline; */ +} + +a.highlight:link { color: #00ff00; text-decoration: none; } +a.highlight:visited { color: #00ff00; text-decoration: none; } +a.highlight:hover { color: #00ff00; text-decoration: underline; } +a.highlight:active { color: #00ff00; text-decoration: underline; } + +a.menulink:link { color: #a0a0d0; text-decoration: none; } +a.menulink:visited { color: #a0a0d0; text-decoration: none; } +a.menulink:hover { color: #00ff00; text-decoration: underline; } +a.menulink:active { color: #00ff00; text-decoration: underline; } + +a.oldlink:link { color: #9090c0; text-decoration: none; } +a.oldlink:visited { color: #9090c0; text-decoration: none; } +a.oldlink:hover { color: #00ff00; text-decoration: underline; } +a.oldlink:active { color: #00ff00; text-decoration: underline; } + +a.altlink:link { color: #7a5ada; text-decoration: none; } +a.altlink:visited { color: #5a3aba; text-decoration: none; } +a.altlink:hover { color: #7a5ada; text-decoration: underline; } +a.altlink:active { color: #7a5ada; text-decoration: underline; } + + +.menu { + font-size: 0.75em; + font-weight: bold; + font-family: Verdana, Arial, Helvetica; + color: #cccccc; + padding-left: 1.0em; + padding-right: 1.0em; + padding-top: 0.5em; + padding-bottom: 0.75em; +} + +.altmenu { + font-size: 0.65em; + font-weight: bold; + font-family: Verdana, Arial, Helvetica; + color: #000000; + padding-left: 1.0em; + padding-right: 1.0em; +} + +.alttext { + font-size: 0.65em; + font-family: Verdana, Arial, Helvetica; + color: #000000; +/* padding-left: 1.0em; + padding-right: 1.0em;*/ +} + +.infotab { + padding: 0.5em; + margin-top: 1.0em; + margin-left: 1.0em; + margin-bottom: 1.0em; +} + +.infohead { + font-size: 0.7em; + font-family: Verdana, Arial, Helvetica; + padding-top: 0.2em; + padding-bottom: 0.2em; + padding-left: 1.0em; + margin-left: 1.0em; + color: #ffffff; + font-weight: bold; +} + +.infosub { + margin-top: 0.25em; + margin-bottom: 0.15em; + margin-left: 0em; + margin-right: 0.5em; + padding: 0em; + font-weight: bold; +} + +.infolist { + margin-top: 0.05em; + margin-bottom: 0.05em; + margin-left: 1.0em; + margin-right: 0.5em; + padding: 0em; + padding-top: 0.3em; +} + +.infogfx { + padding: 0em; +} + +.infotext { + font-size: 0.7em; + font-family: Verdana, Arial, Helvetica; + color: #320f61; + margin-left: 1.5em; + margin-right: 1.5em; +} +/* +.chaphead { + margin: 1.2em 14% 0.5em 3%; + font-size: 1.6em; + font-weight: bold; +} +*/ +.copyright { + padding-left: 1.0em; + padding-right: 1.0em; + margin: 0em 0% 0.2em 0%; + font-size: 0.7em; + font-family: Verdana, Arial, Helvetica; + text-align: right; + color: #808080; +} + +.copyright:link { + text-decoration: underline; + color: #808080; +} + +.copyright:visited { + text-decoration: underline; + color: #808080; +} + +.copyright:hover { + text-decoration: underline; + color: #0000ff; + +} + +.subhead { + font-family: Verdana, Arial, Helvetica; + font-size: 1.2em; + font-weight: bold; + /*margin: 0.5em 0% 0.5em 0%;*/ +} + +.content { + /*padding: 3em;*/ + padding-top: 0em; + padding-left: 1.0em; + padding-right: 1.0em; + font-family: Verdana, Arial, Helvetica; + font-size: 0.8em; +} + +.ntable { + padding: 0em; + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +.itable { + padding: 0em; + margin-top: 0.0em; + margin-bottom: 0.0em; +} + +.ncontent { + /*content with no padding, for an ugly Netscape 4.7 compatibility hack*/ + padding: 0em; + margin-top: 0.5em; + margin-bottom: 0.5em; + font-family: Verdana, Arial, Helvetica; + font-size: 0.8em; +} + +PRE { + padding: 0.5em; + font-family: Lucida Console, Courier; + color: #000000; + font-size: 0.75em; +} + +.input { + color: #0000ff; +} + +.comment { + color: #ff0000; +} + +.code { + font-family: Lucida Console, Courier; + color: #0000ff; + font-size: 0.9em; +} + +.path { + font-family: Lucida Console, Courier; + /*color: #008060; */ + font-size: 0.9em; + font-weight: bold; +} + +.emphasis { + font-style: italic; +} + +.brite { + color: #ff0000; +} + +P.note { + padding: 0.5em; +} + +P.impo { + padding: 0.5em; +} + +P.warn { + padding: 0.5em; +} + +.contentbox { + margin-left: 5%; + margin-right: 5%; + margin-top: 2%; + margin-bottom: 2%; + padding: 0.8em; +} + +.logobg { + background: #45347b; +} + +.top { + background: black; + font-family: Verdana, Arial, Helvetica; + font-size: 0.8em; + color: #c0c0c0; + padding: 0em; + margin: 0em; +} + +.topnews { + background: #5f4e4e; + color: white; +} + +.tophead { + color: #a7f3fe; + font-weight: bold; + margin: 0em; +} + +.tableinfo { + padding-left: 1.0em; + padding-right: 1.0em; + font-size: 0.7em; + background: #dddddd; + font-weight: bold; + font-family: Verdana, Arial, Helvetica; +} + +.toptext { + color: #ffffff; + margin-bottom: 7px; +} +.toptext a:hover { + color: #00ff00; +} + +.toptext a:link { + font-style: normal; + color: #00dd00; +} + +.bartext { + color: #6c6cff; + font-family: Verdana, Arial, Helvetica; + font-size: 0.8em; + padding: 0em; +} +.docs-index { + margin: 0em; + margin-left: 20px; + font-family: Verdana, Arial, Helvetica; + line-height: 1.25em; + border: 3px white solid; +} +/*this works fine in IE, but not in any other browser!, yet it's perfectly valid */ +.docs-index .emphasis { + font-style: normal; + font-weight: bold; +} + diff -Nru swftools-0.9.2+ds1/doc/codebeautifier.pl swftools-0.9.1/doc/codebeautifier.pl --- swftools-0.9.2+ds1/doc/codebeautifier.pl 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/codebeautifier.pl 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,60 @@ +$nr = 1; +while() +{ + if(/\[CALLPERL\s+(.*)\s+left\]/ ... /\[CALLPERL end\]/) { + $lang = $1 if($1); + $code .= $_ if(!/CALLPERL/); + $name = $1 if(/.flash.*name=([^&][^ ]*)/); + $name = $1 if(/.flash.*name="([^&]*)"/); + chomp $name; + } + elsif(/\[CALLPERL .*right\]/ ... /\[CALLPERL end\]/) { + $highlight .= $_ if(!/CALLPERL/); + } + elsif ($code ne "" && ($lang eq "swfc" || $lang eq "sc")) { + $code =~ s/"/"/g; + +# print stderr "Warning: ttf->swf\n" if($code =~ s/Arial.ttf/Arial.swf/g); + + open(fi, ">tmp.sc");print fi $code;close(fi); + print stderr "[$lang] swfc tmp.sc ($name)\n"; + system("../src/swfc tmp.sc >&2"); + ($embed = `swfdump -e $name`) =~ /WIDTH="([^"]*)"/; + system("cp $name data"); + $width = $1; + print ""; + print $embed; + print ""; + $code=""; + print; + unlink "tmp.sc"; + } + elsif ($code ne "" && ($lang eq "python" or $lang eq "shell")) { + $code =~ s/"/"/g; + if($lang eq "python") { + open(fi, ">$nr.py");print fi $code;close(fi); + $nr = $nr + 1; + } + print ""; + print $embed; + print ""; + $code=""; + print; + } + elsif ($code ne "") { + $code=""; + } + elsif ($highlight ne "") { + $highlight =~ s/^\n\s*//g; + $highlight =~ s/\s*\n$//g; + print "
\n";
+	# todo: apply syntax highlighting.
+	print $highlight."\n";
+	print "
\n"; + $highlight=""; + print; + } + else { + print; + } +} Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/doc/Courier.swf and /tmp/M5qDI_SGQH/swftools-0.9.1/doc/Courier.swf differ diff -Nru swftools-0.9.2+ds1/doc/examples/boxes.sc swftools-0.9.1/doc/examples/boxes.sc --- swftools-0.9.2+ds1/doc/examples/boxes.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/boxes.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,24 @@ +# boxes.sc +# +# Do things with rectangles. + +.flash bbox=autocrop version=6 fps=50 name="boxes.swf" compress + + .box box1 width=100 height=100 color=red fill #filled red box + .box box2 width=100 height=100 color=white #white hollow frame + .box box3 width=100 height=100 color=green line=10 fill=blue #filled blue box, with thick green border + +.frame 0 + .put box1 x=30 scalex=30 + .put box2 x=30 scalex=30 + .put box3 x=30 scalex=30 +.frame 100 + .change box1 x+=300 scalex=100 + .change box2 y+=300 scalex=100 + .change box3 x+=300 y-=300 scalex=100 +.frame 150 + .del box1 + .del box2 + .del box3 +.end + diff -Nru swftools-0.9.2+ds1/doc/examples/clip.sc swftools-0.9.1/doc/examples/clip.sc --- swftools-0.9.2+ds1/doc/examples/clip.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/clip.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,29 @@ +# clipping.sc +# +# Test clipping + +.flash name="clip.swf" fps=25 + .sprite s1 # this just constructs a colorful object "s1" + .box b1 40 40 color=red fill=violet line=10 + .box b2 40 40 color=blue fill=green line=10 + .box b3 40 40 color=yellow fill=cyan line=10 + .box b4 40 40 color=white fill=black line=10 + .put b1 0 0 + .put b2 60 0 + .put b3 60 60 + .put b4 0 60 + .end + + # the line and fill colors of the circle don't actually do anything- + # as it's used for clipping only it's shape matters + .circle c1 80 color=blue fill=green + + .startclip c1 x=-160 y=-160 #c1 clips... + .put s1 # ...the sprite s1 + .end + +.frame 200 + .change c1 x=160 y=160 # movement doesn't change the clipping property + .change s1 rotate=5 + +.end diff -Nru swftools-0.9.2+ds1/doc/examples/cxform.sc swftools-0.9.1/doc/examples/cxform.sc --- swftools-0.9.2+ds1/doc/examples/cxform.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/cxform.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,24 @@ +# cxform.sc +# +# Try color transforms + +.flash name="cxform.swf" version=5 fps=50 + + .png s1 "lena.png" + + .put s1 x=50 y=50 scalex=110 scaley=110 + .frame 50 + .change s1 x=0 y=0 scalex=210 scaley=210 red=-1+255 green=-1+255 blue=-1+255 #invert + .frame 100 + .change s1 x=100 y=50 scalex=110 scaley=110 red=0 green=+0 blue=+0 #remove red + .frame 150 + .change s1 x=0 y=0 scalex=210 scaley=210 red=+0 green=2 blue=-1+255 #amplify green, invert blue + .frame 200 + .change s1 x=50 y=100 scalex=110 scaley=110 red=2-128 green=-2+255 blue=+0.7+40 #alien glow + .frame 250 + .change s1 x=0 y=0 scalex=210 scaley=210 red=8-1024 green=8-1024 blue=8-1024 #palette reduce + .frame 300 + .change s1 x=0 y=0 scalex=210 scaley=210 red=+0 green=+0 blue=+0 #back to normal + .frame 350 + .change s1 x=105 y=105 scalex=0 scaley=0 luminance=0 #fadeout +.end diff -Nru swftools-0.9.2+ds1/doc/examples/fonts.sc swftools-0.9.1/doc/examples/fonts.sc --- swftools-0.9.2+ds1/doc/examples/fonts.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/fonts.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,12 @@ +# fonts.sc +# +# fonts&text + +.flash name="fonts.swf" + .font courier "Courier.swf" + .font helvetica "Helvetica.swf" + .text abc text="abcdefghijklmnopqrstuvwxyz" font=courier size=100% color=blue + .text abc2 text="abcdefghijklmnopqrstuvwxyz" font=helvetica size=100% color=red + .put abc + .put abc2 y=200 +.end diff -Nru swftools-0.9.2+ds1/doc/examples/ghosts2.sc swftools-0.9.1/doc/examples/ghosts2.sc --- swftools-0.9.2+ds1/doc/examples/ghosts2.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/ghosts2.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,93 @@ +# Shearing + +.flash bbox=autocrop name="ghosts2.swf" fps=25 + +.font helvetica "Helvetica.swf" + +.text text text="swfc" font=helvetica size=100% color=yellow + +.sprite fader + .frame 0 + .put text + .frame 50 + .change text alpha=0 +.end + +.frame 0 + .put t1=fader x=200 y=200 +.frame 10 + .put t2=fader x=200 y=200 rotate=10 +.frame 20 + .put t3=fader x=200 y=200 rotate=20 +.frame 30 + .put t4=fader x=200 y=200 rotate=30 +.frame 40 + .put t5=fader x=200 y=200 rotate=40 +.frame 50 + .put t6=fader x=200 y=200 rotate=50 +.frame 60 + .put t7=fader x=200 y=200 rotate=60 +.frame 70 + .put t8=fader x=200 y=200 rotate=70 +.frame 80 + .put t9=fader x=200 y=200 rotate=80 +.frame 90 + .put t10=fader x=200 y=200 rotate=90 +.frame 100 + .put t11=fader x=200 y=200 rotate=100 +.frame 110 + .put t12=fader x=200 y=200 rotate=110 +.frame 120 + .put t13=fader x=200 y=200 rotate=120 +.frame 130 + .put t14=fader x=200 y=200 rotate=130 +.frame 140 + .put t15=fader x=200 y=200 rotate=140 +.frame 150 + .put t16=fader x=200 y=200 rotate=150 +.frame 160 + .put t17=fader x=200 y=200 rotate=160 +.frame 170 + .put t18=fader x=200 y=200 rotate=170 +.frame 180 + .put t19=fader x=200 y=200 rotate=180 +.frame 190 + .put t20=fader x=200 y=200 rotate=190 +.frame 200 + .put t21=fader x=200 y=200 rotate=200 +.frame 210 + .put t22=fader x=200 y=200 rotate=210 +.frame 220 + .put t23=fader x=200 y=200 rotate=220 +.frame 230 + .put t24=fader x=200 y=200 rotate=230 +.frame 240 + .put t25=fader x=200 y=200 rotate=240 +.frame 250 + .put t26=fader x=200 y=200 rotate=250 +.frame 260 + .put t27=fader x=200 y=200 rotate=260 +.frame 270 + .put t28=fader x=200 y=200 rotate=270 +.frame 280 + .put t29=fader x=200 y=200 rotate=280 +.frame 290 + .put t30=fader x=200 y=200 rotate=290 +.frame 300 + .put t31=fader x=200 y=200 rotate=300 +.frame 310 + .put t32=fader x=200 y=200 rotate=310 +.frame 320 + .put t33=fader x=200 y=200 rotate=320 +.frame 330 + .put t334=fader x=200 y=200 rotate=330 +.frame 340 + .put t35=fader x=200 y=200 rotate=340 +.frame 350 + .put t36=fader x=200 y=200 rotate=350 +.frame 360 + .put t37=text x=200 y=200 +.frame 400 + .change t37 alpha=0 + +.end diff -Nru swftools-0.9.2+ds1/doc/examples/ghosts.sc swftools-0.9.1/doc/examples/ghosts.sc --- swftools-0.9.2+ds1/doc/examples/ghosts.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/ghosts.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,74 @@ +# Shearing + +.flash bbox=autocrop name="ghosts.swf" fps=25 + +.font helvetica "Helvetica.swf" +.text text text="swfc" font=helvetica size=100% color=yellow + +.frame 0 + .put t0=text x=150 y=150 alpha=100% + .put t0a=text x=150 y=150 alpha=95% + .put t0b=text x=150 y=150 alpha=90% + .put t1=text x=150 y=150 alpha=85% + .put t1a=text x=150 y=150 alpha=80% + .put t1b=text x=150 y=150 alpha=75% + .put t2=text x=150 y=150 alpha=70% + .put t2a=text x=150 y=150 alpha=65% + .put t2b=text x=150 y=150 alpha=60% + .put t3=text x=150 y=150 alpha=55% + .put t3a=text x=150 y=150 alpha=50% + .put t3b=text x=150 y=150 alpha=45% +.frame 2 + .change t0a +.frame 4 + .change t0b +.frame 5 + .change t1 +.frame 7 + .change t1a +.frame 9 + .change t1b +.frame 10 + .change t2 +.frame 12 + .change t2a +.frame 14 + .change t2b +.frame 15 + .change t3 +.frame 20 + .change t3a +.frame 25 + .change t3b +.frame 100 + .change t0 rotate+=360 +.frame 102 + .change t0a rotate+=360 alpha=0 +.frame 104 + .change t0b rotate+=360 alpha=0 +.frame 105 + .change t1 rotate+=360 alpha=0 +.frame 107 + .change t1a rotate+=360 alpha=0 +.frame 109 + .change t1b rotate+=360 alpha=0 +.frame 110 + .change t2 rotate+=360 alpha=0 +.frame 112 + .change t2a rotate+=360 alpha=0 +.frame 114 + .change t2b rotate+=360 alpha=0 +.frame 115 + .change t3 rotate+=360 alpha=0 +.frame 117 + .change t3a rotate+=360 alpha=0 +.frame 119 + .change t3b rotate+=360 alpha=0 +.frame 122 + .change t0 .change t1 .change t2 .change t3 + .change t0a .change t0b .change t1a .change t1b + .change t2a .change t2b .change t3a .change t3b +.frame 150 + .change t0 alpha=0 +.end + diff -Nru swftools-0.9.2+ds1/doc/examples/HoppingMonkey.sc swftools-0.9.1/doc/examples/HoppingMonkey.sc --- swftools-0.9.2+ds1/doc/examples/HoppingMonkey.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/HoppingMonkey.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,26 @@ +# monkey.sc +# + +.flash bbox=autocrop version=4 fps=50 name="HoppingMonkey.swf" + + .swf island "island.swf" + .swf monkey "monkey4.swf" + .put island + .point leftfoot 45 177 + .point rightfoot 138 177 + .frame 0 .put monkey 160 160 + .frame 20 .change monkey 160 160 + .frame 30 .change monkey 160 122 + .frame 35 .change monkey 160 112 + .frame 40 .change monkey 160 122 + .frame 50 .change monkey 160 160 + + .frame 70 .change monkey 205 337 pin=leftfoot rotate=0 + .frame 90 .change monkey rotate=30 + .frame 100 .change monkey rotate=30 + .frame 120 .change monkey rotate=0 + .frame 122 .change monkey 298 337 pin=rightfoot rotate=0 + .frame 140 .change monkey rotate=-30 + .frame 150 .change monkey rotate=-30 + .frame 170 .change monkey rotate=0 +.end diff -Nru swftools-0.9.2+ds1/doc/examples/MoveTutorial.sc swftools-0.9.1/doc/examples/MoveTutorial.sc --- swftools-0.9.2+ds1/doc/examples/MoveTutorial.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/MoveTutorial.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,167 @@ +# Moves.sc +# tutorial on types of Moves for the user. + +.flash bbox=autocrop version=4 fps=25 name="MoveTutorial.swf" + +# SPRITES + +.sprite reticle + .box box width=5 height=5 color=yellow + .put b1=box 0 0 + .put b2=box 5 0 + .put b3=box 0 5 + .put b4=box 5 5 +.end +# +# CHARACTERS +# +.swf axes axesClip.swf +.circle pin 8 color=blue fill=blue +# +.font helv "HelveticaBold.swf" +# +.text mesg1 text="(1) This tutorial demonstrates object motions." font=helv color=yellow size=25% +.text mesg2 text="(2) Every object can be animated in coordinate space." font=helv color=red size=25% +.text mesg3 text="(3) Let's examine each type of motion." font=helv color=magenta size=25% +# +.text mesg4 text="(4) It can translate in x..." font=helv color=green size=25% +.text mesg5 text="(5) ... it can translate in y ..." font=helv color=cyan size=25% +.text mesg6 text="(6) or both." font=helv color=yellow size=25% +.text mesg7 text="(7) It can rotate." font=helv color=magenta size=25% +# +.text mesg8 text="(8) It can scale in x ..." font=helv color=blue size=25% +.text mesg9 text="(9) ... it can scale in y ..." font=helv color=red size=25% +.text mesg10 text="(10)... or both." font=helv color=cyan size=25% +.text mesg11 text="(11) It can shear positively ..." font=helv color=green size=25% +.text mesg12 text="(12) ... or negatively." font=helv color=yellow size=25% +.text mesg13 text="(13) By combining these motions ..." font=helv color=blue size=25% +# +.text mesg14 text="(14) ... you can produce various illusions ..." font=helv color=red size=25% +.text mesg15 text="(15) ... of depth and velocity." font=helv color=magenta size=25% +# .text mesg13 text="(16) and it will rotate in place." font=helv color=red size=25% +# .text mesg13 text="(17) and it will rotate in place." font=helv color=red size=25% +# .text mesg13 text="(18) and it will rotate in place." font=helv color=red size=25% +# .text mesg13 text="(19) and it will rotate in place." font=helv color=red size=25% + +.text annot1 text="Increasing X" font=helv color=yellow size=12% +.text annot2 text="Increasing Y" font=helv color=yellow size=12% + +# MACROS + +# MAIN + +.box box1 width=100 height=100 color=red line=5 # a simple red box + +.frame 0 + .macro tfader 0,10 mesg1 + .put box1 x=100 y=100 pin=center +.frame n+=30 + .change box1 # release that box +.frame n+=30 # *** slide 1 + .change box1 pin=center x=120 y=120 scale=75% +.frame n+=30 + .change box1 pin=center x=150 y=150 rotate+=90 scale=100% + .macro tfader 0,10 mesg2 +.frame n+=30 + .change box1 shear=+1.5 pin=center +.frame n+=30 + .macro tfader 0,10 mesg3 + .change box1 x=100 y=100 shear=0 pin=(0,0) +.frame n+=60 + .macro tfader 0,10 mesg4 + .put axes x=20 y=20 scale=120% + .put annot1 x=30 y=50 + .put annot2 x=30 y=70 + .change box1 x=100 y=100 shear=0 pin=(0,0) rotate=0 +.frame n+=20 + .change box1 x+=50 +.frame n+=20 + .change box1 x-=50 +.frame n+=20 + .macro tfader 0,10 mesg5 +.frame n+=20 + .change box1 y+=50 +.frame n+=20 + .change box1 y-=50 +.frame n+=20 + .macro tfader 0,10 mesg6 +.frame n+=30 + .change box1 x+=100 y+=100 + .change annot1 x=80 + .change annot2 y=120 +# .change box1 x=100 +.frame n+=30 + .change box1 x-=50 y-=50 + .macro tfader 0,10 mesg7 # it can rotate + .change annot1 alpha=0 + .change annot2 alpha=0 + .change axes alpha=0 +.frame n+=2 + .del annot1 + .del annot2 + .del axes +.frame n+=30 + .change box1 rotate=180 +.frame n+=30 + .change box1 rotate=0 + .macro tfader 0,10 mesg8 # it can scale in x +.frame n+=30 + .change box1 scalex=50% +.frame n+=30 + .change box1 scalex=100% + .macro tfader 0,10 mesg9 # or in y +.frame n+=30 + .change box1 scaley=50% +.frame n+=30 + .change box1 scaley=100% + .macro tfader 0,10 mesg10 # or both +.frame n+=30 + .change box1 scale=50% +.frame n+=30 + .change box1 scale=100% + .macro tfader 0,10 mesg11 # positive shear +.frame n+=30 + .change box1 shear=+.5 +.frame n+=30 + .change box1 shear=0 + .macro tfader 0,10 mesg12 # negative shear +.frame n+=30 + .change box1 shear=-.5 +.frame n+=30 + .change box1 shear=0 + .macro tfader 0,10 mesg13 # by combining +.frame n+=90 + .change box1 pin=center x=200 y+=50 rotate=360 scale=25% +.frame n+=30 + .macro tfader 0,10 mesg14 # we produce the illusion + .change box1 pin=center x=100 y=100 rotate=0 scale=100 +.frame n+=2 + .jump box1 shear=1.0 x+=4 +.frame n+=18 + .change box1 x+=80 shear=0 +.frame n+=20 + .change box1 x+=80 +.frame n+=5 + .change box1 shear=-.5 +.frame n+=5 + .change box1 shear=0 +.frame n+=2 + .change box1 y+=5 +.frame n+=2 + .change box1 y-=5 +.frame n+=2 + .change box1 y+=5 +.frame n+=2 + .change box1 y-=5 +.frame n+=60 + .change box1 x-=150 y-=10 rotate=180 scalex=-100% +.frame n+=60 + .change box1 pin=center rotate=0 scalex=100% +.frame n+=60 + .macro tfader 0,10 mesg15 # of depth and velocity +.frame n+=60 + .change box1 alpha=0 + +.end + + diff -Nru swftools-0.9.2+ds1/doc/examples/multiMove.sc swftools-0.9.1/doc/examples/multiMove.sc --- swftools-0.9.2+ds1/doc/examples/multiMove.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/multiMove.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,75 @@ +# shear.sc +# +# test shear + +.flash bbox=autocrop version=6 fps=50 name="multiMove.swf" +# +.font helv "HelveticaBold.swf" +# +.text mesg1 text="I am just translating now" font=helv color=red size=50% +.text mesg2 text="I am just shearing now" font=helv color=red size=50% +.text mesg3 text="I am translating AND shearing now" font=helv color=yellow size=50% +# +.text mesg4 text="I am just rotating now" font=helv color=blue size=50% +.text mesg5 text="I am translating and rotating now" font=helv color=green size=50% +# +.text mesg6 text="I am just rotating now" font=helv color=blue size=50% +.text mesg7 text="I am shearing and rotating now" font=helv color=yellow size=50% +# +.text mesg8 text="I am now translating AND rotating AND shearing!" font=helv color=yellow size=50% +.text mesg9 text="And now we are done." font=helv color=red size=50% + +.box box1 width=100 height=100 color=red line=5 # a simple red box + +.frame 0 + .put box1 x=100 y=100 pin=center + .put mesg1 x=0 y=10 +.frame 50 + .change box1 x+=100 pin=center +.frame 100 + .change box1 x-=100 pin=center + .del mesg1 + .put mesg2 x=0 y=10 +.frame 150 + .change box1 shear=1.0 pin=center +.frame 200 + .change box1 shear=0.0 pin=center + .del mesg2 + .put mesg3 x=0 y=10 +.frame 250 + .change box1 x+=100 shear=1.0 pin=center +.frame 300 + .change box1 x-=100 shear=0.0 pin=center + .del mesg3 + .put mesg4 x=0 y=10 +.frame 350 + .change box1 rotate+=180 pin=center +.frame 400 + .change box1 rotate-=180 pin=center + .del mesg4 + .put mesg5 x=0 y=10 +.frame 450 + .change box1 rotate+=180 x+=100 pin=center +.frame 500 + .change box1 rotate-=180 x-=100 pin=center + .del mesg5 + .put mesg7 x=0 y=10 +.frame 550 + .change box1 rotate+=180 shear=1.0 pin=center +.frame 600 + .change box1 rotate-=180 shear=0.0 pin=center + .del mesg7 + .put mesg8 x=0 y=10 +.frame 650 + .change box1 rotate+=180 x+=100 shear=1.0 pin=center +.frame 700 + .change box1 rotate-=180 x-=100 shear=0.0 pin=center + .del mesg8 + .put mesg9 x=0 y=10 +.frame 750 + .change mesg9 alpha=0 + .change box1 alpha=0 scale=0 + + +.end + diff -Nru swftools-0.9.2+ds1/doc/examples/Pins.sc swftools-0.9.1/doc/examples/Pins.sc --- swftools-0.9.2+ds1/doc/examples/Pins.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/Pins.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,376 @@ +# Pins.sc +# tutorial on Pins for the user. + +.flash bbox=autocrop version=4 fps=25 name="Pins.swf" + +.sprite reticle + .box box width=5 height=5 color=yellow + .put b1=box 0 0 + .put b2=box 5 0 + .put b3=box 0 5 + .put b4=box 5 5 +.end +# +.circle pin 8 color=blue fill=blue +# +.font helv "HelveticaBold.swf" +# +.text mesg1 text="(1) This tutorial explains \"pins\" . . ." font=helv color=yellow size=100% +.text mesg2 text="(2) Every object such as this simple box ..." font=helv color=red size=100% +.text mesg3 text="(3) ... is \"pinned\" to a screen x,y." font=helv color=yellow size=100% +# +.text mesg4 text="(4) The yellow reticle is at 100,100..." font=helv color=yellow size=100% +.text mesg5 text="(5) The box's \"pin\" is at (relative to the box) 0,0." font=helv color=green size=100% +.text mesg6 text="(6) When we .put the box at 100,100, its pin lands..." font=helv color=blue size=100% +.text mesg7 text="(7) ... on 100,100." font=helv color=yellow size=100% +# +.text mesg8 text="(8) Relative 0,0 is the default pin." font=helv color=yellow size=100% +.text mesg9 text="(9) If we rotate the box..." font=helv color=red size=100% +.text mesg10 text="(10)... it rotates around its default pin" font=helv color=red size=100% +.text mesg11 text="(11) If we specify a special pin called \"center\"" font=helv color=red size=100% +.text mesg12 text="(12) the box center will be at 100,100..." font=helv color=red size=100% +.text mesg13 text="(13) and it will rotate in place." font=helv color=red size=100% +# +.text mesg14 text="(14) Interesting things will happen..." font=helv color=red size=100% +.text mesg15 text="(15) ... if a .change command moves the pin!" font=helv color=red size=100% +# .text mesg13 text="(16) and it will rotate in place." font=helv color=red size=100% +# .text mesg13 text="(17) and it will rotate in place." font=helv color=red size=100% +# .text mesg13 text="(18) and it will rotate in place." font=helv color=red size=100% +# .text mesg13 text="(19) and it will rotate in place." font=helv color=red size=100% + +# +# oh no, we have to make zillions of these sprites... sigh... +.sprite m1 + .frame 0 + .put mesg1 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg1 alpha=100% # mesg 1 bright + .frame 40 + .change mesg1 # mesg 1 hold + .frame 60 + .change mesg1 alpha=0 # mesg 1 fade + .frame 65 + .del mesg1 # mesg 1 gone +.end +# +.sprite m2 + .frame 0 + .put mesg2 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg2 alpha=100% # mesg 1 bright + .frame 40 + .change mesg2 # mesg 1 hold + .frame 60 + .change mesg2 alpha=0 # mesg 1 fade + .frame 65 + .del mesg2 # mesg 1 gone +.end +# +.sprite m3 + .frame 0 + .put mesg3 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg3 alpha=100% # mesg 1 bright + .frame 40 + .change mesg3 # mesg 1 hold + .frame 60 + .change mesg3 alpha=0 # mesg 1 fade + .frame 65 + .del mesg3 # mesg 1 gone +.end +# +.sprite m4 + .frame 0 + .put mesg4 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg4 alpha=100% # mesg 1 bright + .frame 40 + .change mesg4 # mesg 1 hold + .frame 60 + .change mesg4 alpha=0 # mesg 1 fade + .frame 65 + .del mesg4 # mesg 1 gone +.end +# +.sprite m5 + .frame 0 + .put mesg5 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg5 alpha=100% # mesg 1 bright + .frame 40 + .change mesg5 # mesg 1 hold + .frame 60 + .change mesg5 alpha=0 # mesg 1 fade + .frame 65 + .del mesg5 # mesg 1 gone +.end +# +.sprite m6 + .frame 0 + .put mesg6 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg6 alpha=100% # mesg 1 bright + .frame 40 + .change mesg6 # mesg 1 hold + .frame 60 + .change mesg6 alpha=0 # mesg 1 fade + .frame 65 + .del mesg6 # mesg 1 gone +.end +# +.sprite m7 + .frame 0 + .put mesg7 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg7 alpha=100% # mesg 1 bright + .frame 40 + .change mesg7 # mesg 1 hold + .frame 60 + .change mesg7 alpha=0 # mesg 1 fade + .frame 65 + .del mesg7 # mesg 1 gone +.end +# +.sprite m8 + .frame 0 + .put mesg8 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg8 alpha=100% # mesg 1 bright + .frame 40 + .change mesg8 # mesg 1 hold + .frame 60 + .change mesg8 alpha=0 # mesg 1 fade + .frame 65 + .del mesg8 # mesg 1 gone +.end +# +.sprite m9 + .frame 0 + .put mesg9 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg9 alpha=100% # mesg 1 bright + .frame 40 + .change mesg9 # mesg 1 hold + .frame 60 + .change mesg9 alpha=0 # mesg 1 fade +.end +# +.sprite m10 + .frame 0 + .put mesg10 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg10 alpha=100% # mesg 1 bright + .frame 40 + .change mesg10 # mesg 1 hold + .frame 60 + .change mesg10 alpha=0 # mesg 1 fade +.end +# +.sprite m11 + .frame 0 + .put mesg11 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg11 alpha=100% # mesg 1 bright + .frame 40 + .change mesg11 # mesg 1 hold + .frame 60 + .change mesg11 alpha=0 # mesg 1 fade +.end +# +.sprite m12 + .frame 0 + .put mesg12 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg12 alpha=100% # mesg 1 bright + .frame 40 + .change mesg12 # mesg 1 hold + .frame 60 + .change mesg12 alpha=0 # mesg 1 fade +.end +# +.sprite m13 + .frame 0 + .put mesg13 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg13 alpha=100% # mesg 1 bright + .frame 40 + .change mesg13 # mesg 1 hold + .frame 60 + .change mesg13 alpha=0 # mesg 1 fade +.end +# +.sprite m14 + .frame 0 + .put mesg14 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg14 alpha=100% # mesg 1 bright + .frame 40 + .change mesg14 # mesg 1 hold + .frame 60 + .change mesg14 alpha=0 # mesg 1 fade +.end +# +.sprite m15 + .frame 0 + .put mesg15 x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change mesg15 alpha=100% # mesg 1 bright + .frame 40 + .change mesg15 # mesg 1 hold + .frame 60 + .change mesg15 alpha=0 # mesg 1 fade +.end +# +.box box1 width=100 height=100 color=red line=5 # a simple red box + +.frame 0 + .put m1 0 0 # at rel frame 20 is the bright spot, or "next" frame + .put box1 x=100 y=100 alpha=0 +.frame 20 # *** slide 1 +.frame 60 + .change box1 alpha=100% # box bright + .put m2 0 0 +.frame 61 + .del m1 +.frame 80 + .change box1 # box hold +.frame 120 + .put m3 0 0 + .jump box1 alpha=100% # make the box appear suddenly and leap around a bit +.frame 121 .del m2 +.frame 125 + .jump box1 x+=20 y+=20 # why doesn't this work? +.frame 130 + .jump box1 x-=20 +.frame 135 + .jump box1 x-=20 y-=20 +.frame 140 + .jump box1 x=100 y=100 # put box bck where it belongs +.frame 145 + .jump box1 x-=20 y-=15 +.frame 150 + .jump box1 x+=20 y+=40 +.frame 155 + .jump box1 x=100 y=100 +.frame 160 + .put pin 100 100 alpha=0 pin=center # pin placed (dark, bottom layer) + .put reticle 100 100 alpha=0 pin=center # place reticle (dark, top layer) +.frame 180 + .put m4 0 0 + .change box1 alpha=0 # box fade + .change reticle alpha=100% # reticle bright +.frame 181 + .del m3 +.frame 200 + .change reticle # hold reticle +.frame 220 + .change reticle alpha=0 # reticle dark + .change pin # hold that pin + .change box1 # hold that box +.frame 240 + .put m5 0 0 +.frame 241 + .del m4 +.frame 260 + .change box1 alpha=100% # box bright +.frame 280 + .change pin alpha=100% # pin bright +.frame 300 + .put m6 0 0 + .jump pin blue=0 red=+100% # blink the pin! +.frame 301 + .del m5 +.frame 305 + .jump pin blue=100% red=0 +.frame 310 + .jump pin blue=0 red=+100% +.frame 315 + .jump pin blue=100% red=0 +.frame 320 + .jump pin blue=0 red=+100% +.frame 325 + .jump pin blue=100% red=0 +.frame 330 + .jump pin blue=0 red=+100% +.frame 335 + .jump pin blue=100% red=0 +.frame 340 + .change reticle # hold that reticle! + .jump pin blue=0 red=+100% +.frame 345 + .jump pin blue=100% red=0 +.frame 360 + .put m7 0 0 + .change reticle alpha=100% +.frame 361 + .del m6 +.frame 420 + .put m8 0 0 +.frame 421 + .del m7 +.frame 460 + .change box1 +.frame 480 + .put m9 +.frame 481 + .del m8 +.frame 500 + .change box1 rotate+=90 +.frame 540 + .put m10 +.frame 541 + .change box1 rotate-=90 + .del m9 + .change pin +.frame 600 + .put m11 + .change box1 +.frame 601 + .del m10 +.frame 620 + .change box1 x=100 y=100 pin=center +.frame 625 + .jump pin blue=100% red=0 +.frame 640 + .jump pin blue=0 red=+100% +.frame 655 + .jump pin blue=100% red=0 +.frame 660 + .put m12 + .jump pin blue=0 red=+100% +.frame 661 + .del m11 +.frame 665 + .jump pin blue=100% red=0 +.frame 670 + .jump pin blue=0 red=+100% +.frame 675 + .jump pin blue=100% red=0 +.frame 700 + .change box1 +.frame 720 + .put m13 + .change box1 rotate+=90 pin=center +.frame 721 + .del m12 +.frame 760 + .change box1 rotate-=90 +.frame 780 + .put m14 + .change box1 pin=(0,0) x=100 y=100 +.frame 781 + .del m13 +.frame 840 + .put m15 + .change box1 pin=center rotate+=90 +.frame 841 + .del m14 +.frame 901 + .del m15 + .change box1 pin=(0,0) rotate-=90 +.frame 960 + .change box1 alpha=0 + +.end + + diff -Nru swftools-0.9.2+ds1/doc/examples/PinsTutorial.sc swftools-0.9.1/doc/examples/PinsTutorial.sc --- swftools-0.9.2+ds1/doc/examples/PinsTutorial.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/PinsTutorial.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,201 @@ +# Pins.sc +# tutorial on Pins for the user. + +.flash bbox=autocrop version=4 fps=25 name="PinsTutorial.swf" + +# SPRITES + +.sprite reticle + .box box width=5 height=5 color=yellow + .put b1=box 0 0 + .put b2=box 5 0 + .put b3=box 0 5 + .put b4=box 5 5 +.end +# +# CHARACTERS +# +.circle pin 8 color=blue fill=blue +# +.font helv "HelveticaBold.swf" +# +.text mesg1 text="(1) This tutorial explains \"pins\" . . ." font=helv color=yellow size=25% +.text mesg2 text="(2) Every object such as this simple box ..." font=helv color=magenta size=25% +.text mesg3 text="(3) ... is \"pinned\" to a screen x,y." font=helv color=cyan size=25% +# +.text mesg4 text="(4) The yellow reticle is at 100,100..." font=helv color=red size=25% +.text mesg5 text="(5) The box's \"pin\" is at (relative to the box) 0,0." font=helv color=green size=25% +.text mesg6 text="(6) When we .put the box at 100,100, its pin lands..." font=helv color=blue size=25% +.text mesg7 text="(7) ... on 100,100." font=helv color=magenta size=25% +# +.text mesg8 text="(8) Relative 0,0 is the default pin." font=helv color=yellow size=25% +.text mesg9 text="(9) If we rotate the box..." font=helv color=red size=25% +.text mesg10 text="(10)... it rotates around its default pin" font=helv color=blue size=25% +.text mesg11 text="(11) If we specify a special pin called \"center\"" font=helv color=green size=25% +.text mesg12 text="(12) the box center will be at 100,100..." font=helv color=yellow size=25% +.text mesg13 text="(13) and it will rotate in place." font=helv color=cyan size=25% +# +.text mesg14 text="(14) Interesting things will happen if we rotate..." font=helv color=magenta size=25% +.text mesg15 text="(15) ... while a .change command moves the pin!" font=helv color=green size=25% +.text mesg16 text="(16) The pin is also relevant when scaling." font=helv color=blue size=25% +.text mesg17 text="(17) Scaling takes place relative to the fixed pin." font=helv color=red size=25% +.text mesg18 text="(18) It's important to know where your pin is!" font=helv color=white size=25% +# .text mesg19 text="(19) and it will rotate in place." font=helv color=red size=25% + +# MACROS + +# MAIN + +.box box1 width=100 height=100 color=red line=5 # a simple red box + +.frame 0 + .macro tfader 0,10 mesg1 + .put box1 x=100 y=100 alpha=0 +.frame n+=20 # *** slide 1 + .change box1 # hold that box +.frame n+=40 + .change box1 alpha=100% # box bright + .macro tfader 0,10 mesg2 +.frame n+=40 + .change box1 # box hold +.frame n+=5 + .jump box1 x=120 y=120 # why doesn't this work? +.frame n+=5 + .jump box1 x=60 y=120 # why doesn't this work? +.frame n+=20 + .macro tfader 0,10 mesg3 + .jump box1 # make the box appear suddenly and leap around a bit +.frame n+=5 + .jump box1 x=100 y=100 # why doesn't this work? +.frame n+=5 + .jump box1 x-=20 +.frame n+=5 + .jump box1 x-=20 y-=20 +.frame n+=5 + .jump box1 x=100 y=100 # put box bck where it belongs +.frame n+=5 + .jump box1 x-=20 y-=15 +.frame n+=5 + .jump box1 x+=20 y+=40 +.frame n+=5 + .jump box1 x=100 y=100 +.frame n+=5 + .put pin 100 100 alpha=0 pin=center # pin placed (dark, bottom layer) + .put reticle 100 100 alpha=0 pin=center # place reticle (dark, top layer) +.frame n+=20 + .macro tfader 0,10 mesg4 + .change box1 alpha=0 # box fade + .change reticle alpha=100% # reticle bright +.frame n+=20 + .change reticle # hold reticle +.frame n+=20 + .change reticle alpha=0 # reticle dark + .change pin # hold that pin + .change box1 # hold that box +.frame n+=20 + .macro tfader 0,10 mesg5 +.frame n+=20 + .change box1 alpha=100% # box bright +.frame n+=20 + .change pin alpha=100% # pin bright +.frame n+=20 + .macro tfader 0,10 mesg6 + .jump pin blue=0 red=+100% # blink the pin! +.frame n+=5 + .jump pin blue=100% red=0 +.frame n+=5 + .jump pin blue=0 red=+100% +.frame n+=5 + .jump pin blue=100% red=0 +.frame n+=5 + .jump pin blue=0 red=+100% +.frame n+=5 + .jump pin blue=100% red=0 +.frame n+=5 + .jump pin blue=0 red=+100% +.frame n+=5 + .jump pin blue=100% red=0 +.frame n+=5 + .change reticle # hold that reticle! + .jump pin blue=0 red=+100% +.frame n+=5 + .jump pin blue=100% red=0 +.frame n+=15 + .macro tfader 0,10 mesg7 + .change reticle alpha=100% +.frame n+=60 + .macro tfader 0,10 mesg8 +.frame n+=20 + .change box1 +.frame n+=20 + .macro tfader 0,10 mesg9 +.frame n+=20 + .change box1 rotate+=90 +.frame n+=40 + .macro tfader 0,10 mesg10 +.frame n+=1 + .change box1 rotate-=90 + .change pin +.frame n+=59 + .macro tfader 0,10 mesg11 + .change box1 +.frame n+=20 + .change box1 x=100 y=100 pin=center +.frame n+=5 + .jump pin blue=100% red=0 +.frame n+=15 + .jump pin blue=0 red=+100% +.frame n+=15 + .jump pin blue=100% red=0 +.frame n+=5 + .macro tfader 0,10 mesg12 + .jump pin blue=0 red=+100% +.frame n+=5 + .jump pin blue=100% red=0 +.frame n+=5 + .jump pin blue=0 red=+100% +.frame n+=5 + .jump pin blue=100% red=0 +.frame n+=5 + .change box1 +.frame n+=20 + .macro tfader 0,10 mesg13 + .change box1 rotate+=90 pin=center +.frame n+=40 + .change box1 rotate-=90 +.frame n+=20 + .macro tfader 0,10 mesg14 + .change box1 pin=(0,0) x=100 y=100 +.frame n+=60 + .macro tfader 0,10 mesg15 + .change box1 pin=center rotate+=90 +.frame n+=60 + .change box1 pin=(0,0) rotate-=90 + .macro tfader 0,10 mesg16 +.frame n+=40 + .change box1 scale=50% +.frame n+=40 + .change box1 scale=100% +.frame n+=15 + .change box1 pin=center +.frame n+=5 + .macro tfader 0,10 mesg17 +.frame n+=40 + .change box1 scale=50% +.frame n+=40 + .change box1 scale=100% alpha=0 +.frame n+=5 + .macro tfader 0,10 mesg18 + .jump pin blue=0 red=+100% +.frame n+=5 + .jump pin blue=100% red=0 +.frame n+=5 + .jump pin blue=0 red=+100% +.frame n+=5 + .jump pin blue=100% red=0 +.frame n+=20 + .change pin alpha=0 + +.end + + diff -Nru swftools-0.9.2+ds1/doc/examples/player.sc swftools-0.9.1/doc/examples/player.sc --- swftools-0.9.2+ds1/doc/examples/player.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/player.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,122 @@ +.flash version=6 fps=50 name="player.swf" bbox=800x600 + + .swf filetoplay "cxform.swf" + .put filetoplay + + .action: + filetoplay.Stop(); + Stop(); + .end + + .gradient gblue: + 0% #4040ff + 25% #8080ff + 50% #c0c0ff + 75% #8080ff + 100% #4040ff + .end + + .gradient ggreen: + 0% #40ff40 + 25% #80ff80 + 50% #c0ffc0 + 75% #80ff80 + 100% #40ff40 + .end + + .gradient gcyan: + 0% #40ffff + 25% #80ffff + 50% #c0ffff + 75% #80ffff + 100% #40ffff + .end + + .outline arrowoutline: + moveTo -30,-10 + lineTo -30,10 + lineTo 0,10 + lineTo 0,20 + lineTo 30,0 + lineTo 0,-20 + lineTo 0,-10 + lineTo -30,-10 + .end + .outline stopoutline: + moveTo -20,-20 + lineTo -20, 20 + lineTo 20, 20 + lineTo 20,-20 + lineTo -20,-20 + .end + .outline pauseoutline: + moveTo -20,-20 + lineTo -20, 20 + lineTo -4, 20 + lineTo -4,-20 + lineTo -20,-20 + + moveTo 20,-20 + lineTo 20, 20 + lineTo 4, 20 + lineTo 4,-20 + lineTo 20,-20 + .end + + .filled arrow_blue outline=arrowoutline fill=gblue line=3 color=blue + .filled arrow_green outline=arrowoutline fill=ggreen line=3 color=green + .filled arrow_cyan outline=arrowoutline fill=gcyan line=3 color=cyan + + .filled stop_blue outline=stopoutline fill=gblue line=3 color=blue + .filled stop_green outline=stopoutline fill=ggreen line=3 color=green + .filled stop_cyan outline=stopoutline fill=gcyan line=3 color=cyan + + .filled pause_blue outline=pauseoutline fill=gblue line=3 color=blue + .filled pause_green outline=pauseoutline fill=ggreen line=3 color=green + .filled pause_cyan outline=pauseoutline fill=gcyan line=3 color=cyan + + .button leftbutton + .show arrow_blue as=area,idle scalex=-100% alpha=50% + .show arrow_green as=hover scalex=-100% + .show arrow_cyan as=pressed scalex=-100% + .on_release inside: + filetoplay.gotoAndStop(1); + .end + .end + + .button stopbutton + .show stop_blue as=area,idle alpha=50% + .show stop_green as=hover alpha=50% + .show stop_cyan as=pressed alpha=50% + .on_release inside: + filetoplay.Stop(); + .end + .end + + .button pausebutton + .show pause_blue as=area,idle alpha=50% + .show pause_green as=hover alpha=50% + .show pause_cyan as=pressed alpha=50% + .on_release inside: + filetoplay.Stop(); + .end + .end + + .button rightbutton + .show arrow_blue as=area,idle alpha=50% + .show arrow_green as=hover alpha=50% + .show arrow_cyan as=pressed alpha=50% + .on_release inside: + filetoplay.Play(); + .end + .end + + .sprite overlay: + .put leftbutton x=35 y=25 + .put stopbutton x=105 y=25 + .put pausebutton x=175 y=25 + .put rightbutton x=245 y=25 + .end + + +.end diff -Nru swftools-0.9.2+ds1/doc/examples/points.sc swftools-0.9.1/doc/examples/points.sc --- swftools-0.9.2+ds1/doc/examples/points.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/points.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,32 @@ +# points.sc +# +# Test points, pivots, pins + +.swf version=5 fps=20 name="points.swf" + +.box box 90 90 color=white fill=red line=5 +.point center 45 45 +.point corner1 0 0 +.point corner2 90 0 +.point corner3 90 90 +.point corner4 0 90 + +.put b1a=box x=90 y=90 pin=center +.put b1b=box x=90 y=90 pin=center alpha=50% +# OR: .put b1=box x=90 y=90 pin=(45,45) rotate=0 + +.put b2=box x=90 y=90 pin=corner1 alpha=75% blue=+128 red=0.2 +.put b3=box x=90 y=90 pin=corner2 alpha=75% blue=+128 red=0.2 +.put b4=box x=90 y=90 pin=corner3 alpha=75% blue=+128 red=0.2 +.put b5=box x=90 y=90 pin=corner4 alpha=75% blue=+128 red=0.2 + +.frame 100 +.change b1a rotate-=720 +.change b1b rotate+=720 +.change b2 rotate+=360 +.change b3 rotate-=360 +.change b4 rotate+=360 +.change b5 rotate-=360 + +.end + diff -Nru swftools-0.9.2+ds1/doc/examples/StrobeShear.sc swftools-0.9.1/doc/examples/StrobeShear.sc --- swftools-0.9.2+ds1/doc/examples/StrobeShear.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/StrobeShear.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,45 @@ +# shear.sc +# +# Shearing + +.swf bbox=300x200:-30 name="StrobeShear.swf" fps=25 + .font helvetica "Helvetica.swf" + .text text text="Shear" font=helvetica size=100% color=yellow +.frame 0 + .put t0=text y=150 alpha=0% shear=0 + .put t1=text y=150 alpha=0% shear=1 + .put t2=text y=150 alpha=0% shear=2 + .put t3=text y=150 alpha=0% shear=3 + .put t4=text y=150 alpha=0% shear=4 + .put t5=text y=150 alpha=0% shear=5 + .put t6=text y=150 alpha=0% shear=6 + .put t7=text y=150 alpha=0% shear=7 + .put t8=text y=150 alpha=0% shear=8 + .put t9=text y=150 alpha=0% shear=9 +.frame 50 + .change t0 alpha=40% shear=0 + .change t1 alpha=40% shear=0 + .change t2 alpha=40% shear=0 + .change t3 alpha=40% shear=0 + .change t4 alpha=40% shear=0 + .change t5 alpha=40% shear=0 + .change t6 alpha=40% shear=0 + .change t7 alpha=40% shear=0 + .change t8 alpha=40% shear=0 + .change t9 alpha=40% shear=0 +.frame 100 + .change t0 .change t1 .change t2 .change t3 .change t4 + .change t5 .change t6 .change t7 .change t8 .change t9 +.frame 150 + .change t0 alpha=0% shear=-9 + .change t1 alpha=0% shear=-8 + .change t2 alpha=0% shear=-7 + .change t3 alpha=0% shear=-6 + .change t4 alpha=0% shear=-5 + .change t5 alpha=0% shear=-4 + .change t6 alpha=0% shear=-3 + .change t7 alpha=0% shear=-2 + .change t8 alpha=0% shear=-1 + .change t9 alpha=0% shear=-0 +.end + diff -Nru swftools-0.9.2+ds1/doc/examples/textselect.sc swftools-0.9.1/doc/examples/textselect.sc --- swftools-0.9.2+ds1/doc/examples/textselect.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/textselect.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,63 @@ +.flash version=6 + + .font Arial "../doc/Arial.swf" + .edittext et width=600 height=50 color=black font=Arial size=40pt border text=test variable=text_selection + + .frame 1 + + .swf TextBox document.swf + .put TextBox + .put et x=10 y=10 + + .frame 2 + + .action: + str = TextBox.getTextSnapShot(); + str.setSelectColor(0xffff00); + firstChar = -1; + + TextBox.onMouseDown = function() { + firstChar = str.hitTestTextNearPos(_xmouse, _ymouse, 0); + str.setSelected(0, str.getCount(), false); + _root.text_selection = str.getSelectedText(true); + }; + + TextBox.onMouseUp = function() { + if (firstChar >= 0) { + lastChar = str.hitTestTextNearPos(_xmouse, _ymouse, 0); + if (firstChar != lastChar) { + if (firstChar < lastChar) { + str.setSelected(firstChar, lastChar+1, true); + _root.text_selection = str.getSelectedText(true); + } else { + str.setSelected(lastChar, firstChar+1, true); + } + } + _root.text_selection = str.getSelectedText(true); + firstChar = -1; + lastChar = -1; + } + }; + + TextBox.onMouseMove = function() { + if(firstChar != -1) { + str.setSelected(0, str.getCount(), false); //unselect everything + + lastChar = str.hitTestTextNearPos(_xmouse, _ymouse, 0); + if (firstChar < lastChar) { + str.setSelected(firstChar, lastChar+1, true); + } else if(lastChar >= 0) { + str.setSelected(lastChar, firstChar+1, true); + } + _root.text_selection = str.getSelectedText(true); + } + }; + .end + + .frame 3 + .action: + Stop(); + .end + +.end + diff -Nru swftools-0.9.2+ds1/doc/examples/tfader.sc swftools-0.9.1/doc/examples/tfader.sc --- swftools-0.9.2+ds1/doc/examples/tfader.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/tfader.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,13 @@ +.macro fader TXT + .frame 0 + .put TXT x=0 y=10 alpha=0 # mesg 1 placed + .frame 20 + .change TXT alpha=100% # mesg 1 bright + .frame 40 + .change TXT # mesg 1 hold + .frame 60 + .change TXT alpha=0 # mesg 1 fade + .frame 65 + .del TXT # mesg 1 gone +.end + diff -Nru swftools-0.9.2+ds1/doc/examples/transparency.sc swftools-0.9.1/doc/examples/transparency.sc --- swftools-0.9.2+ds1/doc/examples/transparency.sc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/examples/transparency.sc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,22 @@ +# transparency.sc +# +# Test transparency + +.flash bbox=200x200 version=5 fps=25 name="transparency.swf" + +.box box1 90 90 color=yellow fill=blue line=5 +.box box2 90 90 color=white fill=red line=5 + +.put b1=box1 75 75 rotate=0 +.put b2=box1 75 75 rotate=90 +.put b3=box1 75 75 rotate=180 +.put b4=box1 75 75 rotate=270 +.put box2 30 30 alpha=100% +.frame 300 +.change b1 rotate+=360 +.change b2 rotate+=360 +.change b3 rotate+=360 +.change b4 rotate+=360 +.change box2 alpha=0% +.end + diff -Nru swftools-0.9.2+ds1/doc/guide.xsl swftools-0.9.1/doc/guide.xsl --- swftools-0.9.2+ds1/doc/guide.xsl 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/guide.xsl 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,428 @@ + +]> + + + + + + + + + + + + + + + <xsl:value-of select="title"/> + + + + +

+ + + + + +

+ +
+ + + + +
+
+ + + +
+ + + + + + +
__prevlink____currentchapter____nextlink__
+
+ + + +
+ + + + + chapterlink + +   + + + + + +<!-- snip:chapter !!!""!!! --> + + + + +

+ + . + + +

+ + + + + + +<!-- snip:/chapter --> + +
+ + + + + + + + + + + + +

+ .  +   +

+
+ + + + +
+ + + + + + +

+ ..  +   +

+
+ + + + + +
+ + + + + + + +

+ ...  +   +

+
+ + + + + + +
+ + + +
+ + + + {@short} + + + + {@short} + + +
+
+ + +
+
+ + + + + + +
+

+ Note: + +

+
+
+ + + + + + +
+

+ Important: + +

+
+
+ + + + + + +
+

+ Warning: + +

+
+
+ + + // + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ +

+
+ + + + + + +
+
+	    
+	  
+
+
+
+ + + + + + + + + + +
+ + +
+
+ + + + + + + doc_chap_pre + + + + + + + + +[CALLPERL left] + +[CALLPERL end] + + + + +
+

+ + + Code listing .: + + + Code listing . + + +

+
+ +[CALLPERL right] + +[CALLPERL end] +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + +

+
+ +

+ + + +

+
+
+
+ + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + +
    + +
+
+ + +
    + +
+
+ + +
  • + +
  • +
    + + +
    Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/doc/line.gif and /tmp/M5qDI_SGQH/swftools-0.9.1/doc/line.gif differ diff -Nru swftools-0.9.2+ds1/doc/Makefile swftools-0.9.1/doc/Makefile --- swftools-0.9.2+ds1/doc/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/Makefile 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,13 @@ +all: + rm -f swfc.*.html + rm -f data/* || true + xsltproc guide.xsl swfc.xml > tmp.html + perl codebeautifier.pl < tmp.html > swfc.html + perl seperate.pl swfc.html + cp swfc.1.html swfc.html + rm tmp.html + cp beach.jpg Arial.swf Courier.swf Times.swf scenery.jpg data + cp swfc.html swfc.*.html caiviar.css data + +upload: + ./syncswfc Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/doc/photo.swf and /tmp/M5qDI_SGQH/swftools-0.9.1/doc/photo.swf differ diff -Nru swftools-0.9.2+ds1/doc/pygfx.svg swftools-0.9.1/doc/pygfx.svg --- swftools-0.9.2+ds1/doc/pygfx.svg 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/pygfx.svg 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,396 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + Flash + Bitmap + OCR + OpenGL + eBooks (LRF) + pygfx + PDF + Flash + Bitmap + + + + + Hidden polygon removal + + Rescaling + + Rendering / Optimizing + ... + Filters + + + + + + + Input Formats + Output Formats + + Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/doc/scenery.jpg and /tmp/M5qDI_SGQH/swftools-0.9.1/doc/scenery.jpg differ diff -Nru swftools-0.9.2+ds1/doc/seperate.pl swftools-0.9.1/doc/seperate.pl --- swftools-0.9.2+ds1/doc/seperate.pl 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/seperate.pl 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,89 @@ +#!/usr/bin/perl + +$filename = $ARGV[0]; + +$filename =~ /^(.*)\.([^.]*)$/; +$basename = $1; +$extension = $2; + +print "Processing $filename...\n"; + +$head = ""; + +open(fi, "<$filename"); + +while() { + last if(/snip:chapter/); + $head .= $_; +} + +# chapters +my $nr=1; +my @chapters; +my @names; +/!!!"(.*)"!!!/;$name = $1; +while() { + my $chapter = ""; + # one chapter + while(1) { + if(/snip:\/chapter/) { + while() { + last if(!/^\s*$/); + } + last; + } + $chapter .= $_; + $_ = ; + } + $names[$nr] = $name; + $chapters[$nr++] = $chapter; + + /!!!"(.*)"!!!/;$name = $1; + if(!/snip:chapter/) { + last; + } +} + +while($_) { + $tail .= $_; + $_ = ; +} + +close(fi); + +my $num = $nr; +$nr=1; +for($nr=1;$nr<$num;$nr++) { + $h2 = $head; + $t2 = $tail; + my $filename = "$basename.$nr.$extension"; + print "Creating $filename...\n"; + for($n=1;$n<$num;$n++) { + if($nr == $n) { + $h2 =~ s/chapterlink$n/>$names[$n]<<\/a>/; + } else { + $h2 =~ s/chapterlink$n/$names[$n]<\/a>/; + } + } + + if($nr > 1) { + $prev = $names[$nr-1]; + $aprev = $basename.".".($nr-1).".".$extension; + $t2 =~ s/__prevlink__/Previous: $prev<\/a>/; + } else { + $t2 =~ s/__prevlink__/ /; + } + if($nr < $num-1) { + $next= $names[$nr+1]; + $anext = $basename.".".($nr+1).".".$extension; + + $t2 =~ s/__nextlink__/Next: $next<\/a>/; + } else { + $t2 =~ s/__nextlink__/ /; + } + $t2 =~ s/__currentchapter__/$names[$nr]/; + + open(fi, ">$filename"); + print fi "$h2\n$chapters[$nr]\n$t2"; + close(fi); +} diff -Nru swftools-0.9.2+ds1/doc/swfc.xml swftools-0.9.1/doc/swfc.xml --- swftools-0.9.2+ds1/doc/swfc.xml 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/doc/swfc.xml 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,981 @@ + + + +SWFC Manual + + +swfc is a tool for generating flash files. You can write small simple scripts +and then have them compiled to SWF Flash Animations. + + + + + + + +
    Calling swfc + +

    + + swfc is command line based. You call it via + + $ swfc file.sc + + The filename of what is generated depends on the filename of the script (file.sc), + the filename given inside the script, and the optional -o passed to swfc. + +

    + +
    + +
    A simple swfc example + +

    + Let's create a simple SWF file, shall we? + The following script creates a red box with a yellow border. On the right side you + see the script used, on the left side the swf file that is generated. +

    + + +.flash filename="box.swf" + .box b1 100 100 color=yellow fill=red + .put b1 pin=center scale=0% + .frame 100 + .change b1 pin=center scale=100% + .frame 200 + .change b1 pin=center scale=0% +.end + + +

    + The .box command creates the box. Every object that is created must also be explicitly + put into the scene using .put to become visible. +

    +

    + Change, on the other hand, modifies an already existing object. + It works gradually: In the example above, the change happens over 100 frames. + If you want to change an object suddently from one frame to the next, you + would use the .jump command. +

    + +
    + +
    Color transforms + +

    +You can define a number of parameters in the .put, .change and .jump +tags. Among those are the color transform parameters red, green, +blue and alpha. +Furthermore, for convenience, there's also luminance, which sets red, green and +blue in one go. +

    +

    +Each one of these consists of two parts: The multiplicator and the shift. +The syntax is + ±<multiplicator>±<shift> . +So, for example, to make an object 50% brighter, you would use +luminance=+128. Notice that all color components inside the transformed object in the range 128-255 +will be mapped to 255 with this. To map 0 to 128, 255 to 255, but 128 to 192, you would +use luminance=0.5+128. +

    +

    +You can also specify negative values for both <mutliplicator> and <shift>. +This makes it e.g. possible to invert an object: luminance=-1+255. +

    +

    +The following example demonstrates a few of the possible transforms: +

    + + + +.flash filename="cxform.swf" version=5 fps=25 + + .jpeg s1 "photo.jpeg" quality=80% + + .put s1 x=50 y=50 scalex=110 scaley=110 + .frame 50 + .change s1 x=0 y=0 scalex=210 scaley=210 red=-1+255 green=-1+255 blue=-1+255 #invert + .frame 100 + .change s1 x=100 y=50 scalex=110 scaley=110 red=0 green=+0 blue=+0 #remove red + .frame 150 + .change s1 x=0 y=0 scalex=210 scaley=210 red=+0 green=2 blue=-1+255 #amplify green, invert blue + .frame 200 + .change s1 x=50 y=100 scalex=110 scaley=110 red=2-128 green=-2+255 blue=+0.7+40 #alien glow + .frame 250 + .change s1 x=0 y=0 scalex=210 scaley=210 red=8-1024 green=8-1024 blue=8-1024 #palette reduce + .frame 300 + .change s1 x=0 y=0 scalex=210 scaley=210 red=+0 green=+0 blue=+0 #back to normal + .frame 350 + .change s1 x=105 y=105 scalex=0 scaley=0 luminance=0 #fadeout +.end + + +A very useful fact is also that you can color transform the alpha component. +So to fade any object into the background, you would simply transform it's +alpha color: E.g. alpha=64 would make the object 75% transparent. +This is used in an example further below. +
    + + +
    + + + +
    + +swfc has font support. That means you can also insert texts into +your animations. +The easiest way to load a font is to do something like + + .font Arial filename="Arial.ttf" + +. +You now have a font named Arial to play with. +For example, for the obligatory hello world program: + + +.flash filename="helloworld.swf" + + .font Arial filename="Arial.ttf" + .text helloworld font=Arial text="Hello World!" + .put helloworld +.end + + + +The text argument expects UTF-8 strings. So if you want to +pass any special characters (umlauts, digraphs etc.), they have to +be UTF-8 encoded. + + +Besides TrueType fonts, swfc also supports native SWF fonts. +If you have a SWF with a font you would like to use, do a + + swfextract file.swf + +Then write down the font ID of the font, and do a + + swfextract -f <fontid> file.swf -o myfont.swf + +. +

    +This will give you a file named myfont.swf which you can +also use in the filename parameter of .font. +

    + +

    +Furthermore, you can convert TTF and Type1 +fonts into SWF using font2swf: + + font2swf Arial.ttf -o Arial.swf + +The nice advantage of this is that you can play +Arial.swf in the flash player and see what the +font looks like. +(Also, loading a font in SWF format is slighly +faster than from a TTF file, as with TTFs spline +conversion has to take place). +

    + +
    +
    +

    +So much for the basics. Now let's go to the more advanced +functionality around fonts. +

    + +

    +Apart from being able to define text in your swfc files, +you can also define text outlines. +Those are not real characters but rather abstract vector +objects which you can use in other commands. +

    + + +.flash filename="fontoutline.swf" + .font Arial "Arial.swf" + .textshape helloworld font=Arial size=200% text="Hello World" + .filled filled_helloworld outline=helloworld fill=blue line=3 color=green + .put filled_helloworld +.end + + +Here, .textshape helloworld defines an outline named "helloworld", +which is then used to construct a filled outline named filled_helloworld. + +To make this a little more interesting, let's fill with a gradient instead +of a plain color: + + +.flash filename="fontgradient.swf" + .font Arial "Arial.swf" + .textshape helloworld font=Arial text="SHADE" + + .gradient whitefade: + 0% black + 50% #505050 + 100% yellow + .end + + .filled filled_helloworld outline=helloworld fill=whitefade line=1 color=#2c2c2c + .put filled_helloworld scale=200% +.end + + +While at it, you can also fill with an image: + + +.flash filename="fontimage.swf" + .font courier "Courier.swf" + .jpeg beach "beach.jpg" + .textshape text font=courier text="HOLIDAY" + + .filled filled_text outline=text fill=beach line=1 color=#2c2c2c + .put filled_text scale=200% +.end + + +But let's get back to normal .text characters. +The following demonstrates that you can treat objects defined +with .text like normal shapes, i.e., scale them, move them, and use +them for clipping: + + +.flash filename="text5.swf" +.font courier "Courier.swf" +.text hithere text="HELLO" font=courier size=200% +.jpeg scenery "scenery.jpg" + +.frame 1 + .startclip hithere pin=center x=100 y=75 scale=50% #text clips... + .put scenery scale=50% + .end +.frame 100 + .change hithere rotate+=360 pin=center scale=100% + +.end + + +

    +The last two examples look similar, but their underlying structure +is different: The first is a shape object filled with +image data (that is, a texture), while the second uses a normal +text object to clip an rectangular image. (More about clipping in +the next section) +

    + +

    +Also, .text takes a color attribute (that's actually +the poor man's version of the more advanced filling options +that .textshape in conjunction with .filled offers), +which is used here together with the alpha parameter of .change: +

    + + +.flash filename="text6.swf" +.font times "Times.swf" +.text hello text="HELLO" font=times size=200% color=blue +.text world text="WORLD" font=times size=200% color=red + +.frame 1 + .put hello pin=center x=50 y=50 + .put world pin=center x=50 y=50 alpha=25% +.frame 200 + .change hello rotate+=360 pin=center alpha=25% + .change world rotate-=360 pin=center alpha=100% +.end + + +
    + +
    + +Another example for clipping against text: + + +.flash filename="textclip.swf" bbox=400x120 background=black version=6 +.font times "Times.swf" +.textshape helloworld text="HELLO WORLD" font=times size=300% +.filled helloworld1 outline=helloworld fill=blue line=0 +.filled helloworld2 outline=helloworld fill=green line=0 + +.frame 1 +.put h3=helloworld1 y=100 +.startclip h1=helloworld1 y=100 + .put h2=helloworld2 y=100 +.end + +.frame 1000 +.change h1 x=-1000 +.change h2 x=-500 +.change h3 x=-1000 +.end + + +
    + +
    + +A special type of text in SWF is the edittext, which +can be modified by the viewer. It's content can also be queried +and set from ActionScript (see below). +You can generate this type of text with the .edittext command: + + +.flash filename="edittext.swf" bbox=410x210 + .font Arial "Arial.swf" + .edittext myedittext font=Arial size=50% + width=400 height=200 + color=blue border multiline wordwrap + text="Edit me!\nClick with your mouse on this text to edit it." + .put myedittext x=3 y=3 +.end + + +
    +
    + + + +
    + +In the previous chapter, we learned how to create a text outline +using .textshape. The other way to create outlines is to +use the .outline command: + + +.flash filename="house.swf" + + .outline house_outline: + M 36.99 29.93 L 15.52 51.39 L 20.44 51.39 L 20.44 81.91 + L 39.73 81.91 L 39.73 62.33 L 48.36 62.33 + L 48.36 81.91 L 53.84 81.91 L 53.84 51.39 + L 58.45 51.39 L 36.99 29.93 + M 28.79 53.70 L 34.55 53.70 L 34.55 60.60 L 28.79 60.60 + L 28.79 53.70 + .end + .filled house outline=house_outline fill=grey color=grey + .put house +.end + + +The syntax of the paths inside the .outline command is the same as in svg. +That means you can use the svg editor of your choice (e.g.: inkscape) +to create these outlines. You then need to extract them out of the .xml/.svg file. +They are inside the "d" attribute of the "path" tag: + + +... + <path + style="fill:#0000ff;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;" + d="M 369.90625 299.31250 L 155.21875 513.96875 L 204.40625 513.96875 L 204.40625 819.15625 L 397.31250 819.15625 L 397.31250 623.37500 L 483.68750 623.37500 L 483.68750 819.15625 L 538.40625 819.15625 L 538.40625 513.96875 L 584.56250 513.96875 L 369.90625 299.31250 z M 287.90625 537.00000 L 345.50000 537.00000 L 345.50000 606.09375 L 287.90625 606.09375 L 287.90625 537.00000 z " + id="rect908" /> +... + + +
    + +
    + +Outlines can be filled with gradients, bitmaps etc., just like +seen previously with .textshape: + + +.flash filename="gradients.swf" + + .outline star: + M 521,640 C 502,678 370,546 328,554 C 270,566 152,731 93,722 + C 51,716 147,549 127,512 C 98,460 -107,400 -117,341 + C -124,299 63,339 93,308 C 133,265 127,50 180,23 + C 218,3 238,195 276,213 C 330,238 532,166 575,208 + C 605,238 429,316 424,358 C 416,417 547,587 521,640 + .end + + .gradient rainbow: + 0% blue + 25% green + 50% yellow + 75% orange + 100% red + .end + + .gradient fire radial: + 0% white + 50% yellow + 100% red + .end + + .gradient horizon: + 0% cyan + 49% blue + 50% green + 100% peru + .end + + .gradient transparent: + 0% #ff000000 + 100% #ff0000ff + .end + + .box scenery fill=horizon width=200 height=200 + .box bar fill=transparent width=240 height=20 + .filled star1 outline=star fill=rainbow line=1 + .filled star2 outline=star fill=fire line=1 + + .put scenery rotate=90% + .put star1 scale=10% x=-70 + .put star2 scale=10% x=-180 y=110 + .put bar x=-180 y=10 rotate=45 +.end + + + + +
    + +
    + +

    +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 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 FOR FOR_IN IF WHILE DO_WHILE MAYBEELSE BREAK RETURN CONTINUE TRY +%type INNERFUNCTION +%type USE_NAMESPACE DEFAULT_NAMESPACE +%type FOR_INIT +%type IMPORT +%type MAYBETYPE +%type GETSET +%type PARAM +%type PARAM_LIST +%type MAYBE_PARAM_LIST +%type MAYBE_MODIFIERS +%type MODIFIER_LIST +%type MODIFIER +%type CONSTANT MAYBECONSTANT +%type IMPLEMENTS_LIST +%type EXTENDS CLASS_SPEC +%type EXTENDS_LIST +%type CLASS PACKAGEANDCLASS +%type CLASS_SPEC_LIST +%type XMLEXPR1 XMLEXPR2 XML2 XMLNODE XMLATTRIBUTE XMLATTRIBUTES MAYBE_XMLATTRIBUTES XMLTEXT XML_ID_OR_EXPR XML +%type TYPE +//%type VARIABLE +%type MEMBER +%type NEW +//%type T_IDENTIFIER +%type FUNCTIONCALL +%type MAYBE_EXPRESSION_LIST EXPRESSION_LIST EXPRESSION_LIST_AND_COMMA MAYBE_PARAM_VALUES +%type MAYBE_DICT_EXPRPAIR_LIST DICT_EXPRPAIR_LIST WITH_HEAD +%type DICTLH + +// precedence: from low to high + +%left prec_none +%left prec_var_read + +%left below_semicolon +%left ';' +%left ',' +%nonassoc below_assignment // for ?:, contrary to spec +%right '=' "*=" "/=" "%=" "+=" "-=" "<<=" ">>=" ">>>=" "&=" "^=" "|=" +%right '?' ':' +%left "||" +%left "&&" +%left '|' +%left '^' +%nonassoc '&' +%nonassoc "==" "!=" "===" "!==" +%nonassoc "is" "as" "in" +%left below_lt +%nonassoc "<=" '<' ">=" '>' "instanceof" // TODO: support "a < b < c" syntax? +%left "<<" ">>" ">>>" +%left below_minus +%left '-' '+' +%left '/' '*' '%' +%left plusplus_prefix minusminus_prefix '~' '!' "void" "delete" "typeof" //FIXME: *unary* + - should be here, too +%left "--" "++" +%nonassoc below_curly + +%left '(' +%left new2 +%left '[' ']' "new" '{' "{ (dictionary)" '.' ".." "::" '@' + +%left below_identifier +%left T_IDENTIFIER "arguments" +%left above_identifier +%left below_else +%nonassoc "else" + +// needed for "return" precedence: +%nonassoc T_STRING T_REGEXP +%nonassoc T_INT T_UINT T_FLOAT KW_NAN +%nonassoc "false" "true" "null" "undefined" "super" "function" +%left above_function + + +%{ + +#define PASS1 }} if(as3_pass == 1) {{ +#define PASS1END }} if(as3_pass == 2) {{ +#define PASS2 }} if(as3_pass == 2) {{ +#define PASS12 }} if(as3_pass == 1 || as3_pass == 2) {{ +#define PASS12END }} if(as3_pass == 2) {{ +#define PASS_ALWAYS }} {{ + +%} + +%% + +/* ------------ code blocks / statements ---------------- */ + +PROGRAM: MAYBE_PROGRAM_CODE_LIST + +MAYBE_PROGRAM_CODE_LIST: | PROGRAM_CODE_LIST +PROGRAM_CODE_LIST: PROGRAM_CODE + | PROGRAM_CODE_LIST PROGRAM_CODE + +PROGRAM_CODE: PACKAGE_DECLARATION + | INTERFACE_DECLARATION + | CLASS_DECLARATION + | FUNCTION_DECLARATION + | SLOT_DECLARATION + | PACKAGE_INITCODE +/* | CONDITIONAL_COMPILATION '{' MAYBE_PROGRAM_CODE_LIST '}' {PASS_ALWAYS as3_pass=$1;}*/ + | ';' + +MAYBE_INPACKAGE_CODE_LIST: | INPACKAGE_CODE_LIST +INPACKAGE_CODE_LIST: INPACKAGE_CODE + | INPACKAGE_CODE_LIST INPACKAGE_CODE + +INPACKAGE_CODE: INTERFACE_DECLARATION + | CLASS_DECLARATION + | FUNCTION_DECLARATION + | SLOT_DECLARATION + | PACKAGE_INITCODE +/* | CONDITIONAL_COMPILATION '{' MAYBE_INPACKAGE_CODE_LIST '}' {PASS_ALWAYS as3_pass=$1;}*/ + | '[' EMBED_START E ']' {PASS_ALWAYS as3_pass=$2;PASS1 as3_warning("embed command ignored");} + | ';' + +MAYBECODE: CODE {$$=$1;} +MAYBECODE: {$$=code_new();} + +CODE: CODE CODEPIECE { + $$=code_append($1,$2); +} +CODE: CODEPIECE {$$=$1;} + +// code which may appear outside of methods +CODE_STATEMENT: DEFAULT_NAMESPACE +CODE_STATEMENT: IMPORT +CODE_STATEMENT: FOR +CODE_STATEMENT: FOR_IN +CODE_STATEMENT: WHILE +CODE_STATEMENT: DO_WHILE +CODE_STATEMENT: SWITCH +CODE_STATEMENT: IF +CODE_STATEMENT: WITH +CODE_STATEMENT: TRY +CODE_STATEMENT: VOIDEXPRESSION +CODE_STATEMENT: USE_NAMESPACE +CODE_STATEMENT: NAMESPACE_DECLARATION +CODE_STATEMENT: '{' CODE '}' {$$=$2;} +CODE_STATEMENT: '{' '}' {$$=0;} + +// code which may appear in methods (includes the above) +CODEPIECE: ';' {$$=0;} +CODEPIECE: CODE_STATEMENT +CODEPIECE: VARIABLE_DECLARATION +CODEPIECE: BREAK +CODEPIECE: CONTINUE +CODEPIECE: RETURN +CODEPIECE: THROW + +/* +CODEPIECE: CONDITIONAL_COMPILATION '{' CODE '}' { + PASS_ALWAYS + if(as3_pass) { + $$ = $3; + } else { + $$ = 0; + } + as3_pass=$1; +}*/ + +//CODEBLOCK : '{' CODE '}' {$$=$2;} +//CODEBLOCK : '{' '}' {$$=0;} +CODEBLOCK : CODEPIECE ';' {$$=$1;} +CODEBLOCK : CODEPIECE %prec below_semicolon {$$=$1;} + +/* ------------ package init code ------------------- */ + +PACKAGE_INITCODE: CODE_STATEMENT { + if($1) { + if(!global->init) + global->init = abc_initscript(global->file); + code_t**cc = &global->init->method->body->code; + *cc = code_append(*cc, $1); + } +} + +/* ------------ embed code ------------- */ + +EMBED_START: %prec above_function { + PASS_ALWAYS + $$ = as3_pass; + as3_pass=0; +} + +/* ------------ conditional compilation ------------- */ + +/*CONDITIONAL_COMPILATION: T_IDENTIFIER "::" T_IDENTIFIER { + PASS12 + $$=as3_pass; + char*key = concat3($1,"::",$3); + if(!definitions || !dict_contains(definitions, key)) { + as3_pass=0; + } + free(key); +}*/ + +/* ------------ variables --------------------------- */ + +%code { + char is_subtype_of(classinfo_t*type, classinfo_t*supertype) + { + return 1; // FIXME + } + char do_init_variable(char*name) + { + if(!state->method->no_variable_scoping) + return 0; + if(!state->new_vars) + return 1; + return 1; + } +}; + +MAYBEEXPRESSION : '=' E {$$=$2;} + | {$$=mkdummynode();} + +VARIABLE_DECLARATION : "var" VARIABLE_LIST {$$=$2;} +VARIABLE_DECLARATION : "const" VARIABLE_LIST {$$=$2;} + +VARIABLE_LIST: ONE_VARIABLE {$$ = $1;} +VARIABLE_LIST: VARIABLE_LIST ',' ONE_VARIABLE {$$ = code_append($1, $3);} + +ONE_VARIABLE: T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION +{ +PASS12 + if(variable_exists($1)) + syntaxerror("Variable %s already defined", $1); +PASS1 + new_variable(state->method, $1, $2, 1, 0); +PASS2 + + char slot = 0; + int index = 0; + variable_t*v = 0; + if(state->method->uses_slots) { + v = find_slot(state->method, $1); + if(v && !v->init) { + // this variable is stored in a slot + v->init = 1; + v->type = $2; + slot = 1; + } + } + if(!v) { + v = new_variable2(state->method, $1, $2, 1, 0); + } + + $$ = slot?abc_getscopeobject(0, 1):0; + + typedcode_t val = node_read($3); + if(!is_subtype_of(val.t, $2)) { + syntaxerror("Can't convert %s to %s", val.t->name, $2->name); + } + if($2) { + if(val.c->prev || val.c->opcode != OPCODE_PUSHUNDEFINED) { + $$ = code_append($$, val.c); + $$ = converttype($$, val.t, $2); + } else { + code_free(val.c); + $$ = defaultvalue($$, $2); + } + } else { + if(val.c->prev || val.c->opcode != OPCODE_PUSHUNDEFINED) { + $$ = code_append($$, val.c); + $$ = abc_coerce_a($$); + } else { + // don't do anything + code_free(val.c); + code_free($$); + $$ = 0; + break; + } + } + if(slot) { + $$ = abc_setslot($$, v->index); + } else { + $$ = abc_setlocal($$, v->index); + v->init = do_init_variable($1); + } +} + +/* ------------ control flow ------------------------- */ + +IF_CODEBLOCK: {PASS12 new_state();} CODEBLOCK { + $$ = var_block($2, state->vars); + PASS12 old_state(); +} +MAYBEELSE: %prec below_else {$$ = code_new();} +MAYBEELSE: "else" IF_CODEBLOCK {$$=$2;} +//MAYBEELSE: ';' "else" CODEBLOCK {$$=$3;} + +IF : "if" '(' EXPRESSION ')' IF_CODEBLOCK MAYBEELSE { + $$ = code_new(); + $$ = code_append($$, $3.c); + code_t*myjmp,*myif = $$ = abc_iffalse($$, 0); + + $$ = code_append($$, $5); + if($6) { + myjmp = $$ = abc_jump($$, 0); + } + myif->branch = $$ = abc_nop($$); + if($6) { + $$ = code_append($$, $6); + myjmp->branch = $$ = abc_nop($$); + } +} + +FOR_INIT : {$$=code_new();} +FOR_INIT : VARIABLE_DECLARATION +FOR_INIT : VOIDEXPRESSION + +// TODO: why doesn't an %prec above_identifier resolve the r-r conflict here? +// (I don't see any easy way to revolve this conflict otherwise, as we +// can't touch VAR_READ without upsetting the precedence about "return") +FOR_IN_INIT : "var" T_IDENTIFIER MAYBETYPE { + PASS1 $$=$2;new_variable(state->method, $2,$3,1,0); + PASS2 $$=$2;new_variable(state->method, $2,$3,1,0); +} +FOR_IN_INIT : T_IDENTIFIER { + PASS12 + $$=$1; +} + +FOR_START : T_FOR '(' {PASS12 new_state();$$.name=$1;$$.each=0;} +FOR_START : T_FOR "each" '(' {PASS12 new_state();$$.name=$1;$$.each=1;} + +FOR : FOR_START FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' IF_CODEBLOCK { + if($1.each) syntaxerror("invalid syntax: ; not allowed in for each statement"); + $$ = code_new(); + $$ = code_append($$, $2); + code_t*loopstart = $$ = abc_label($$); + $$ = code_append($$, $4.c); + code_t*myif = $$ = abc_iffalse($$, 0); + $$ = code_append($$, $8); + code_t*cont = $$ = abc_nop($$); + $$ = code_append($$, $6); + $$ = abc_jump($$, loopstart); + code_t*out = $$ = abc_nop($$); + breakjumpsto($$, $1.name, out); + continuejumpsto($$, $1.name, cont); + myif->branch = out; + + $$ = var_block($$, state->vars); + PASS12 old_state(); +} + +FOR_IN : FOR_START FOR_IN_INIT "in" EXPRESSION ')' IF_CODEBLOCK { + node_t*n = resolve_identifier($2); + typedcode_t w = node_write(n); + + int it = alloc_local(); + int array = alloc_local(); + + $$ = code_new(); + $$ = code_append($$, $4.c); + $$ = abc_coerce_a($$); + $$ = abc_setlocal($$, array); + $$ = abc_pushbyte($$, 0); + $$ = abc_setlocal($$, it); + + code_t*loopstart = $$ = abc_label($$); + + $$ = abc_hasnext2($$, array, it); + code_t*myif = $$ = abc_iffalse($$, 0); + $$ = abc_getlocal($$, array); + $$ = abc_getlocal($$, it); + if(!$1.each) + $$ = abc_nextname($$); + else + $$ = abc_nextvalue($$); + + $$ = converttype($$, 0, w.t); + $$ = code_append($$, w.c); + + $$ = code_append($$, $6); + $$ = abc_jump($$, loopstart); + + code_t*out = $$ = abc_nop($$); + breakjumpsto($$, $1.name, out); + continuejumpsto($$, $1.name, loopstart); + + myif->branch = out; + + $$ = abc_kill($$, it); + $$ = abc_kill($$, array); + + $$ = var_block($$, state->vars); + PASS12 old_state(); +} + +WHILE : T_WHILE '(' EXPRESSION ')' IF_CODEBLOCK { + + $$ = code_new(); + + code_t*myjmp = $$ = abc_jump($$, 0); + code_t*loopstart = $$ = abc_label($$); + $$ = code_append($$, $5); + code_t*cont = $$ = abc_nop($$); + myjmp->branch = cont; + $$ = code_append($$, $3.c); + $$ = abc_iftrue($$, loopstart); + code_t*out = $$ = abc_nop($$); + breakjumpsto($$, $1, out); + continuejumpsto($$, $1, cont); +} + +DO_WHILE : T_DO IF_CODEBLOCK "while" '(' EXPRESSION ')' { + $$ = code_new(); + code_t*loopstart = $$ = abc_label($$); + $$ = code_append($$, $2); + code_t*cont = $$ = abc_nop($$); + $$ = code_append($$, $5.c); + $$ = abc_iftrue($$, loopstart); + code_t*out = $$ = abc_nop($$); + breakjumpsto($$, $1, out); + continuejumpsto($$, $1, cont); +} + +BREAK : "break" %prec prec_none { + $$ = abc___break__(0, ""); +} +BREAK : "break" T_IDENTIFIER { + $$ = abc___break__(0, $2); +} +CONTINUE : "continue" %prec prec_none { + $$ = abc___continue__(0, ""); +} +CONTINUE : "continue" T_IDENTIFIER { + $$ = abc___continue__(0, $2); +} + +MAYBE_CASE_LIST : {$$=0;} +MAYBE_CASE_LIST : CASE_LIST {$$=$1;} +MAYBE_CASE_LIST : DEFAULT {$$=$1;} +MAYBE_CASE_LIST : CASE_LIST DEFAULT {$$=code_append($1,$2);} +CASE_LIST: CASE {$$=$1;} +CASE_LIST: CASE_LIST CASE {$$=code_append($$,$2);} + +CASE: "case" E ':' MAYBECODE { + $$ = abc_getlocal(0, state->switch_var); + $$ = code_append($$, node_read($2).c); + code_t*j = $$ = abc_ifne($$, 0); + $$ = code_append($$, $4); + if($$->opcode != OPCODE___BREAK__) { + $$ = abc___fallthrough__($$, ""); + } + code_t*e = $$ = abc_nop($$); + j->branch = e; +} +DEFAULT: "default" ':' MAYBECODE { + $$ = $3; +} +SWITCH : T_SWITCH '(' {PASS12 new_state();state->switch_var=alloc_local();} E ')' '{' MAYBE_CASE_LIST '}' { + $$ = node_read($4).c; + $$ = abc_setlocal($$, state->switch_var); + $$ = code_append($$, $7); + + code_t*out = $$ = abc_kill($$, state->switch_var); + breakjumpsto($$, $1, out); + + code_t*c = $$,*lastblock=0; + while(c) { + if(c->opcode == OPCODE_IFNE) { + if(!c->next) syntaxerror("internal error in fallthrough handling"); + lastblock=c->next; + } else if(c->opcode == OPCODE___FALLTHROUGH__) { + if(lastblock) { + c->opcode = OPCODE_JUMP; + c->branch = lastblock; + } else { + /* fall through end of switch */ + c->opcode = OPCODE_NOP; + } + } + c=c->prev; + } + + $$ = var_block($$, state->vars); + PASS12 old_state(); +} + +/* ------------ try / catch /finally ---------------- */ + +CATCH: "catch" '(' T_IDENTIFIER MAYBETYPE ')' {PASS12 new_state(); + state->exception_name=$3; + PASS1 new_variable(state->method, $3, $4, 0, 0); + PASS2 new_variable(state->method, $3, $4, 0, 0); + } + '{' MAYBECODE '}' { + namespace_t name_ns = {ACCESS_PACKAGE, ""}; + multiname_t name = {QNAME, &name_ns, 0, $3}; + + NEW(abc_exception_t, e) + e->exc_type = sig2mname($4); + e->var_name = multiname_clone(&name); + $$ = e; + + code_t*c = 0; + int i = find_variable_safe(state, $3)->index; + e->target = c = abc_nop(0); + c = abc_setlocal(c, i); + c = code_append(c, code_dup(state->method->scope_code)); + c = code_append(c, $8); + c = abc_kill(c, i); + + c = var_block(c, state->vars); + PASS12 old_state(); +} +FINALLY: "finally" '{' {PASS12 new_state();state->exception_name=0;} MAYBECODE '}' { + $4 = var_block($4, state->vars); + if(!$4) { + $$=0; + } else { + NEW(abc_exception_t, e) + e->exc_type = 0; //all exceptions + e->var_name = 0; //no name + e->target = 0; + e->to = abc_nop(0); + e->to = code_append(e->to, $4); + $$ = e; + } + PASS12 old_state(); +} + +CATCH_LIST: CATCH {$$.l=list_new();$$.finally=0;list_append($$.l,$1);} +CATCH_LIST: CATCH_LIST CATCH {$$=$1;list_append($$.l,$2);} +CATCH_FINALLY_LIST: CATCH_LIST {$$=$1;} +CATCH_FINALLY_LIST: CATCH_LIST FINALLY { + $$ = $1; + $$.finally = 0; + if($2) { + list_append($$.l,$2); + $$.finally = $2->to;$2->to=0; + } +} +CATCH_FINALLY_LIST: FINALLY { + $$.l=list_new(); + $$.finally = 0; + if($1) { + list_append($$.l,$1); + $$.finally = $1->to;$1->to=0; + } +} + +TRY : "try" '{' {PASS12 new_state(); + state->method->has_exceptions=1; + state->method->late_binding=1;//for invariant scope_code + } MAYBECODE '}' CATCH_FINALLY_LIST { + code_t*out = abc_nop(0); + + code_t*start = abc_nop(0); + $$ = code_append(start, $4); + if(!is_break_or_jump($4)) { + $$ = abc_jump($$, out); + } + code_t*end = $$ = abc_nop($$); + + int tmp; + if($6.finally) + tmp = alloc_local(); + + abc_exception_list_t*l = $6.l; + int count=0; + while(l) { + abc_exception_t*e = l->abc_exception; + if(e->var_name) { + $$ = code_append($$, e->target); + $$ = abc_jump($$, out); + } else { + as3_assert((ptroff_t)$6.finally); + // finally block + e->target = $$ = abc_nop($$); + $$ = code_append($$, code_dup(state->method->scope_code)); + $$ = abc___rethrow__($$); + } + + e->from = start; + e->to = end; + + l = l->next; + } + $$ = code_append($$, out); + + $$ = insert_finally($$, $6.finally, tmp); + + list_concat(state->method->exceptions, $6.l); + + $$ = var_block($$, state->vars); + PASS12 old_state(); +} + +/* ------------ throw ------------------------------- */ + +THROW : "throw" EXPRESSION { + $$=$2.c; + $$=abc_throw($$); +} + +THROW : "throw" { + if(!state->exception_name) + syntaxerror("re-throw only possible within a catch block"); + variable_t*v = find_variable(state, state->exception_name); + $$=code_new(); + $$=abc_getlocal($$, v->index); + $$=abc_throw($$); +} + +/* ------------ with -------------------------------- */ + +WITH_HEAD : "with" '(' EXPRESSION ')' { + new_state(); + if(state->method->has_exceptions) { + int v = alloc_local(); + state->method->scope_code = abc_getlocal(state->method->scope_code, v); + state->method->scope_code = abc_pushwith(state->method->scope_code); + $$.number = v; + } + $$.cc = $3.c; +} +WITH : WITH_HEAD CODEBLOCK { + /* remove getlocal;pushwith from scope code again */ + state->method->scope_code = code_cutlast(code_cutlast(state->method->scope_code)); + + $$ = $1.cc; + if(state->method->has_exceptions) { + $$ = abc_dup($$); + $$ = abc_setlocal($$, $1.number); + } + $$ = abc_pushwith($$); + $$ = code_append($$, $2); + $$ = abc_popscope($$); + old_state(); +} + +/* ------------ packages and imports ---------------- */ + +X_IDENTIFIER: T_IDENTIFIER + | "package" {PASS12 $$="package";} + | "namespace" {PASS12 $$="namespace";} + | "NaN" {PASS12 $$="NaN";} + +PACKAGE: PACKAGE '.' X_IDENTIFIER {PASS12 $$ = concat3($1,".",$3);free($1);$1=0;} +PACKAGE: X_IDENTIFIER {PASS12 $$=strdup($1);} + +PACKAGE_DECLARATION : "package" PACKAGE '{' {PASS12 startpackage($2);free($2);$2=0;} + MAYBE_INPACKAGE_CODE_LIST '}' {PASS12 endpackage();$$=0;} +PACKAGE_DECLARATION : "package" '{' {PASS12 startpackage("");} + MAYBE_INPACKAGE_CODE_LIST '}' {PASS12 endpackage();$$=0;} + +%code { + static void state_has_imports() + { + state->wildcard_imports = list_clone(state->wildcard_imports); + state->imports = dict_clone(state->imports); + state->has_own_imports = 1; + } + static void import_toplevel(const char*package) + { + char* s = strdup(package); + while(1) { + dict_put(state->import_toplevel_packages, s, 0); + char*x = strrchr(s, '.'); + if(!x) + break; + *x = 0; + } + free(s); + } +}; + +IMPORT : "import" T_IDENTIFIER { + PASS12 + slotinfo_t*s = registry_find(state->package, $2); + if(!s && as3_pass==1) {as3_schedule_class(state->package, $2);} + state_has_imports(); + dict_put(state->imports, state->package, $2); + $$=0; +} +IMPORT : "import" PACKAGEANDCLASS { + PASS12 + slotinfo_t*s = registry_find($2->package, $2->name); + if(!s && as3_pass==1) { + as3_schedule_class($2->package, $2->name); + } + /*if(s && s->kind == INFOTYPE_VAR && TYPE_IS_NAMESPACE(s->type)) { + trie_put(active_namespaces, (unsigned char*)$2->name, 0); + }*/ + state_has_imports(); + dict_put(state->imports, $2->name, $2); + import_toplevel($2->package); + $$=0; +} +IMPORT : "import" PACKAGE '.' '*' { + PASS12 + if(strncmp("flash.", $2, 6) && as3_pass==1) { + as3_schedule_package($2); + } + + NEW(import_t,i); + i->package = $2; + state_has_imports(); + list_append(state->wildcard_imports, i); + import_toplevel(i->package); + $$=0; +} + +/* ------------ classes and interfaces (header) -------------- */ + +MAYBE_MODIFIERS : %prec above_function {PASS12 $$.flags=0;$$.ns=0;} +MAYBE_MODIFIERS : MODIFIER_LIST {PASS12 $$=$1;} +MODIFIER_LIST : MODIFIER {PASS12 $$=$1;} +MODIFIER_LIST : MODIFIER_LIST MODIFIER { + PASS12 + $$.flags=$1.flags|$2.flags; + if($1.ns && $2.ns) syntaxerror("only one namespace allowed in one declaration"); + $$.ns=$1.ns?$1.ns:$2.ns; + +} +MODIFIER : KW_PUBLIC {PASS12 $$.flags=FLAG_PUBLIC;$$.ns=0;} + | KW_PRIVATE {PASS12 $$.flags=FLAG_PRIVATE;$$.ns=0;} + | KW_PROTECTED {PASS12 $$.flags=FLAG_PROTECTED;$$.ns=0;} + | KW_STATIC {PASS12 $$.flags=FLAG_STATIC;$$.ns=0;} + | KW_DYNAMIC {PASS12 $$.flags=FLAG_DYNAMIC;$$.ns=0;} + | KW_FINAL {PASS12 $$.flags=FLAG_FINAL;$$.ns=0;} + | KW_OVERRIDE {PASS12 $$.flags=FLAG_OVERRIDE;$$.ns=0;} + | KW_NATIVE {PASS12 $$.flags=FLAG_NATIVE;$$.ns=0;} + | KW_INTERNAL {PASS12 $$.flags=FLAG_PACKAGEINTERNAL;$$.ns=0;} +/* + | T_IDENTIFIER {PASS12 $$.flags=FLAG_NAMESPACE; + $$.ns=$1; + } +*/ + +EXTENDS : {PASS12 $$=0;} +EXTENDS : KW_EXTENDS CLASS_SPEC {PASS12 $$=$2;} + +EXTENDS_LIST : {PASS12 $$=list_new();} +EXTENDS_LIST : KW_EXTENDS CLASS_SPEC_LIST {PASS12 $$=$2;} + +IMPLEMENTS_LIST : {PASS12 $$=list_new();} +IMPLEMENTS_LIST : KW_IMPLEMENTS CLASS_SPEC_LIST {PASS12 $$=$2;} + +CLASS_DECLARATION : MAYBE_MODIFIERS "class" T_IDENTIFIER + EXTENDS IMPLEMENTS_LIST + '{' {PASS12 startclass(&$1,$3,$4,$5);} + MAYBE_CLASS_BODY + '}' {PASS12 endclass();$$=0;} + +INTERFACE_DECLARATION : MAYBE_MODIFIERS "interface" T_IDENTIFIER + EXTENDS_LIST + '{' {PASS12 $1.flags|=FLAG_INTERFACE; + startclass(&$1,$3,0,$4);} + MAYBE_INTERFACE_BODY + '}' {PASS12 endclass();$$=0;} + +/* ------------ classes and interfaces (body) -------------- */ + +MAYBE_CLASS_BODY : +MAYBE_CLASS_BODY : CLASS_BODY +CLASS_BODY : CLASS_BODY_ITEM +CLASS_BODY : CLASS_BODY CLASS_BODY_ITEM +CLASS_BODY_ITEM : ';' +/*CLASS_BODY_ITEM : CONDITIONAL_COMPILATION '{' MAYBE_CLASS_BODY '}' {PASS_ALWAYS as3_pass=$1;}*/ +CLASS_BODY_ITEM : SLOT_DECLARATION +CLASS_BODY_ITEM : FUNCTION_DECLARATION +CLASS_BODY_ITEM : '[' EMBED_START E ']' {PASS_ALWAYS as3_pass=$2;PASS1 as3_warning("embed command ignored");} + +CLASS_BODY_ITEM : CODE_STATEMENT { + code_t*c = state->cls->static_init->header; + c = code_append(c, $1); + state->cls->static_init->header = c; +} + +MAYBE_INTERFACE_BODY : +MAYBE_INTERFACE_BODY : INTERFACE_BODY +INTERFACE_BODY : IDECLARATION +INTERFACE_BODY : INTERFACE_BODY IDECLARATION +IDECLARATION : ';' +IDECLARATION : "var" T_IDENTIFIER { + syntaxerror("variable declarations not allowed in interfaces"); +} +IDECLARATION : MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE { + PASS12 + $1.flags |= FLAG_PUBLIC; + if($1.flags&(FLAG_PRIVATE|FLAG_PACKAGEINTERNAL|FLAG_PROTECTED)) { + syntaxerror("invalid method modifiers: interface methods always need to be public"); + } + startfunction(&$1,$3,$4,&$6,$8); + endfunction(&$1,$3,$4,&$6,$8, 0); + list_deep_free($6.list); +} + +/* ------------ classes and interfaces (body, slots ) ------- */ + +%code { + static int slotstate_varconst = 0; + static modifiers_t*slotstate_flags = 0; + static void setslotstate(modifiers_t* flags, int varconst) + { + slotstate_varconst = varconst; + slotstate_flags = flags; + if(state->cls) { + if(flags) { + if(flags->flags&FLAG_STATIC) { + state->method = state->cls->static_init; + } else { + state->method = state->cls->init; + } + } else { + // reset to "default" state (all in class code is static by default) */ + state->method = state->cls->static_init; + } + } else { + as3_assert(state->method); + } + } + static trait_t* add_abc_slot(modifiers_t* modifiers, const char*name, multiname_t*m, code_t***c) + { + int flags = modifiers->flags; + namespace_t ns = modifiers2access(modifiers); + + /* slot name */ + multiname_t mname = {QNAME, &ns, 0, name}; + + trait_list_t**traits; + code_t**code=0; + if(!state->cls) { + // global variable + if(!global->init) global->init = abc_initscript(global->file); + ns.name = state->package; + traits = &global->init->traits; + code = &global->init->method->body->code; + } else if(flags&FLAG_STATIC) { + // static variable + traits = &state->cls->abc->static_traits; + code = &state->cls->static_init->header; + } else { + // instance variable + traits = &state->cls->abc->traits; + code = &state->cls->init->header; + + if(ns.access == ACCESS_PROTECTED) { + ns.name = concat3(state->cls->info->package,":",state->cls->info->name); + } + } + if(c) + *c = code; + if(m) + *m = *multiname_clone(&mname); + + return trait_new_member(traits, 0, multiname_clone(&mname), 0); + } +}; + +VARCONST: "var" | "const" + +SLOT_DECLARATION: MAYBE_MODIFIERS VARCONST {PASS12 setslotstate(&$1,$2);} SLOT_LIST {PASS12 $$=$4;setslotstate(0, 0);} + +SLOT_LIST: ONE_SLOT {PASS12 $$=0;} +SLOT_LIST: SLOT_LIST ',' ONE_SLOT {PASS12 $$=0;} + +ONE_SLOT: T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION +{ +PASS12 + int flags = slotstate_flags->flags; + namespace_t ns = modifiers2access(slotstate_flags); + + if(as3_pass == 1) { + + varinfo_t* info = 0; + if(state->cls) { + memberinfo_t*i = registry_findmember(state->cls->info, ns.name, $1, 1, slotstate_flags->flags&FLAG_STATIC); + if(i) { + check_override(i, flags); + } + info = varinfo_register_onclass(state->cls->info, ns.access, ns.name, $1, slotstate_flags->flags&FLAG_STATIC); + } else { + slotinfo_t*i = registry_find(state->package, $1); + if(i) { + syntaxerror("package %s already contains '%s'", state->package, $1); + } + if(ns.name && ns.name[0]) { + syntaxerror("namespaces not allowed on package-level variables"); + } + info = varinfo_register_global(ns.access, state->package, $1); + } + + info->type = $2; + info->flags = flags; + + dict_put(global->token2info, (void*)(ptroff_t)as3_tokencount, info); + } + + if(as3_pass == 2) { + varinfo_t*info = dict_lookup(global->token2info, (void*)(ptroff_t)as3_tokencount); + + multiname_t mname; + code_t**code; + trait_t*t = add_abc_slot(slotstate_flags, $1, &mname, &code); + + if($2) { + MULTINAME(m, $2); + t->type_name = multiname_clone(&m); + } + info->slot = t->slot_id; + + /* workaround for "VerifyError: Error #1053: Illegal override of ::test2 in C1" + FIXME: is there a way to use slots and still don't have conflicting overrides? + */ + info->slot = t->slot_id = 0; + + constant_t cval = $3->type->eval($3); + if(cval.type!=CONSTANT_UNKNOWN) { + /* compile time constant */ + t->value = malloc(sizeof(constant_t)); + memcpy(t->value, &cval, sizeof(constant_t)); + info->value = constant_clone(t->value); + } else { + typedcode_t v = node_read($3); + /* initalization code (if needed) */ + code_t*c = 0; + if(v.c && !is_pushundefined(v.c)) { + c = abc_getlocal_0(c); + c = code_append(c, v.c); + c = converttype(c, v.t, $2); + if(!t->slot_id) { + c = abc_initproperty2(c, &mname); + } else { + c = abc_setslot(c, t->slot_id); + } + } + *code = code_append(*code, c); + } + + if(slotstate_varconst==KW_CONST) { + t->kind= TRAIT_CONST; + info->flags |= FLAG_CONST; + } + } + + $$=0; +} + +/* ------------ constants -------------------------------------- */ + +MAYBECONSTANT: {$$=0;} +MAYBECONSTANT: '=' E { + $$ = malloc(sizeof(constant_t)); + *$$ = node_eval($2); + if($$->type == CONSTANT_UNKNOWN) { + syntaxerror("can't evaluate default parameter value (needs to be a compile-time constant)"); + } +} + +CONSTANT : T_INT {$$ = constant_new_int($1);} +CONSTANT : T_UINT { + $$ = constant_new_uint($1); +} +CONSTANT : T_FLOAT {$$ = constant_new_float($1);} +CONSTANT : T_STRING {$$ = constant_new_string2($1.str,$1.len);free((char*)$1.str);} +CONSTANT : "true" {$$ = constant_new_true($1);} +CONSTANT : "false" {$$ = constant_new_false($1);} +CONSTANT : "null" {$$ = constant_new_null($1);} +CONSTANT : "undefined" {$$ = constant_new_undefined($1);} +CONSTANT : KW_NAN {$$ = constant_new_float(__builtin_nan(""));} + +/* ---------------------------xml ------------------------------ */ + +%code { + static int xml_level = 0; +}; + +XML: XMLNODE { + multiname_t m = {QNAME, &stdns, 0, "XML"}; + typedcode_t v; + v.c = 0; + v.c = abc_getlex2(v.c, &m); + v.c = code_append(v.c, node_read($1).c); + v.c = abc_construct(v.c, 1); + v.t = TYPE_XML; + $$ = mkcodenode(v); +} + +OPEN : '<' {PASS_ALWAYS if(!xml_level++) tokenizer_begin_xml();} +CLOSE : '>' {PASS_ALWAYS tokenizer_begin_xmltext();} +CLOSE2 : {PASS_ALWAYS if(!--xml_level) tokenizer_end_xml(); else tokenizer_begin_xmltext();} + +XMLEXPR1 : '{' E {PASS_ALWAYS tokenizer_begin_xmltext();} '}' { + $$ = $2; +} +XMLEXPR2 : '{' E {PASS_ALWAYS tokenizer_begin_xml();} '}' { + $$ = $2; +} +XMLTEXT : {$$=mkstringnode("");} +XMLTEXT : XMLTEXT XMLEXPR1 { + $$ = mkaddnode($1,$2); +} +XMLTEXT : XMLTEXT T_STRING { + char* str = string_cstr(&$2); + $$ = mkaddnode($1,mkstringnode(str)); + free(str); +} +XMLTEXT : XMLTEXT '>' { + $$ = mkaddnode($1, mkstringnode(">")); +} +XML2 : XMLNODE XMLTEXT { + $$ = mkaddnode($1,$2); +} +XML2 : XML2 XMLNODE XMLTEXT { + $$ = mkaddnode($1, mkaddnode($2,$3)); +} +XML_ID_OR_EXPR: T_IDENTIFIER { + $$ = mkstringnode($1); +} +XML_ID_OR_EXPR: XMLEXPR2 { + $$ = $1; +} + +MAYBE_XMLATTRIBUTES: { + $$ = mkstringnode(""); +} +MAYBE_XMLATTRIBUTES: XMLATTRIBUTES { + $$ = mkaddnode(mkstringnode(" "),$1); +} + +XMLNODE : OPEN XML_ID_OR_EXPR MAYBE_XMLATTRIBUTES '/' CLOSE2 '>' { + //$$ = allocprintf("<%s%s/>", $2, $3, $5, $8); + $$ = mkaddnode(mkaddnode(mkaddnode(mkstringnode("<"),$2),$3),mkstringnode("/>")); +} +XMLNODE : OPEN XML_ID_OR_EXPR MAYBE_XMLATTRIBUTES CLOSE XMLTEXT '<' '/' XML_ID_OR_EXPR CLOSE2 '>' { + //$$ = allocprintf("<%s%s>%s", $2, $3, $5, $8); + $$ = mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode( + mkstringnode("<"),$2),$3),mkstringnode(">")),$5),mkstringnode("")); +} +XMLNODE : OPEN XML_ID_OR_EXPR MAYBE_XMLATTRIBUTES CLOSE XMLTEXT XML2 '<' '/' XML_ID_OR_EXPR CLOSE2 '>' { + //$$ = allocprintf("<%s%s>%s%s", $2, $3, $5, $6, $9); + $$ = mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode( + mkstringnode("<"),$2),$3),mkstringnode(">")),$5),$6),mkstringnode("")); +} + +XMLATTRIBUTES: XMLATTRIBUTE { + $$ = $1; +} +XMLATTRIBUTES: XMLATTRIBUTES XMLATTRIBUTE { + $$ = mkaddnode($1, mkaddnode(mkstringnode(" "),$2)); +} +XMLATTRIBUTE: XMLEXPR2 { + $$ = $1; +} +XMLATTRIBUTE: XMLEXPR2 '=' T_STRING { + char* str = string_cstr(&$3); + $$ = mkaddnode($1, mkstringnode(concat2("=",str))); + free(str); +} +XMLATTRIBUTE: XMLEXPR2 '=' XMLEXPR2 { + $$ = mkaddnode($1, mkaddnode(mkstringnode("=\""), mkaddnode($3, mkstringnode("\"")))); +} +XMLATTRIBUTE: T_IDENTIFIER '=' XMLEXPR2 { + $$ = mkaddnode(mkaddnode(mkstringnode(concat2($1,"=\"")), $3), mkstringnode("\"")); +} +XMLATTRIBUTE: T_IDENTIFIER '=' T_STRING { + char* str = string_cstr(&$3); + $$=mkstringnode(allocprintf("%s=%s", $1,str)); + free(str); + free($1);free((char*)$3.str); +} + +/* ------------ classes and interfaces (body, functions) ------- */ + +// non-vararg version +MAYBE_PARAM_LIST: { + PASS12 + memset(&$$,0,sizeof($$)); +} +MAYBE_PARAM_LIST: PARAM_LIST { + PASS12 + $$=$1; +} + +// vararg version +MAYBE_PARAM_LIST: "..." PARAM { + PASS12 + memset(&$$,0,sizeof($$)); + $$.varargs=1; + list_append($$.list, $2); +} +MAYBE_PARAM_LIST: PARAM_LIST ',' "..." PARAM { + PASS12 + $$ =$1; + $$.varargs=1; + list_append($$.list, $4); +} + +// non empty +PARAM_LIST: PARAM_LIST ',' PARAM { + PASS12 + $$ = $1; + list_append($$.list, $3); +} +PARAM_LIST: PARAM { + PASS12 + memset(&$$,0,sizeof($$)); + list_append($$.list, $1); +} + +PARAM: T_IDENTIFIER ':' TYPE MAYBECONSTANT { + PASS12 + $$ = rfx_calloc(sizeof(param_t)); + $$->name=$1; + $$->type = $3; + PASS2 + $$->value = $4; +} +PARAM: T_IDENTIFIER MAYBECONSTANT { + PASS12 + $$ = rfx_calloc(sizeof(param_t)); + $$->name=$1; + $$->type = TYPE_ANY; + PASS2 + $$->value = $2; +} +GETSET : "get" + | "set" + | {PASS12 $$=0;} + +FUNCTION_DECLARATION: MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LIST ')' + MAYBETYPE '{' {PASS12 startfunction(&$1,$3,$4,&$6,$8);} MAYBECODE '}' +{ + PASS1 + endfunction(&$1,$3,$4,&$6,0,0); + PASS2 + if(!state->method->info) syntaxerror("internal error"); + + code_t*c = method_header(state->method); + c = wrap_function(c, 0, $11); + + endfunction(&$1,$3,$4,&$6,$8,c); + PASS12 + list_deep_free($6.list); + $$=0; +} + +MAYBE_IDENTIFIER: T_IDENTIFIER +MAYBE_IDENTIFIER: {PASS12 $$=0;} +INNERFUNCTION: "function" MAYBE_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE + '{' {PASS12 innerfunction($2,&$4,$6);} MAYBECODE '}' +{ + PASS1 + endfunction(0,0,$2,&$4,0,0); + PASS2 + methodinfo_t*f = state->method->info; + if(!f || !f->kind) syntaxerror("internal error"); + + code_t*c = method_header(state->method); + c = wrap_function(c, 0, $9); + + int index = state->method->var_index; + endfunction(0,0,$2,&$4,$6,c); + + $$.c = abc_getlocal(0, index); + $$.t = TYPE_FUNCTION(f); + + PASS12 list_deep_free($4.list); +} + + +/* ------------- package + class ids --------------- */ + +CLASS: X_IDENTIFIER { + PASS1 NEW(unresolvedinfo_t,c); + memset(c, 0, sizeof(*c)); + c->kind = INFOTYPE_UNRESOLVED; + c->name = $1; + c->package = get_package_from_name($1); + if(!c->package) { + c->nsset = get_current_imports(); + /* make the compiler look for this class in the current directory, + just in case: */ + as3_schedule_class_noerror(state->package, $1); + } + $$ = (classinfo_t*)c; + PASS2 + slotinfo_t*s = find_class($1); + if(!s) syntaxerror("Could not find class/method %s (current package: %s)\n", $1, state->package); + $$ = (classinfo_t*)s; + registry_use(s); +} + +PACKAGEANDCLASS : PACKAGE '.' X_IDENTIFIER { + PASS1 NEW(unresolvedinfo_t,c); + memset(c, 0, sizeof(*c)); + c->kind = INFOTYPE_UNRESOLVED; + c->package = $1; + c->name = $3; + $$ = (classinfo_t*)c; + PASS2 + slotinfo_t*s = registry_find($1, $3); + if(!s) syntaxerror("Couldn't find class/method %s.%s\n", $1, $3); + free($1);$1=0; + $$ = (classinfo_t*)s; + registry_use(s); +} + +CLASS_SPEC: PACKAGEANDCLASS + | CLASS + +CLASS_SPEC_LIST : CLASS_SPEC {PASS12 $$=list_new();list_append($$, $1);} +CLASS_SPEC_LIST : CLASS_SPEC_LIST ',' CLASS_SPEC {PASS12 $$=$1;list_append($$,$3);} + +TYPE : CLASS_SPEC {PASS12 $$=$1;} + | '*' {PASS12 $$=TYPE_ANY;} + | "void" {PASS12 $$=TYPE_VOID;} + /* + | "String" {$$=registry_getstringclass();} + | "int" {$$=registry_getintclass();} + | "uint" {$$=registry_getuintclass();} + | "Boolean" {$$=registry_getbooleanclass();} + | "Number" {$$=registry_getnumberclass();} + */ + +MAYBETYPE: ':' TYPE {PASS12 $$=$2;} +MAYBETYPE: {PASS12 $$=0;} + +/* ----------function calls, delete, constructor calls ------ */ + +MAYBE_PARAM_VALUES : %prec prec_none {$$.cc=0;$$.number=0;} +MAYBE_PARAM_VALUES : '(' MAYBE_EXPRESSION_LIST ')' {$$=$2;} + +MAYBE_EXPRESSION_LIST : {$$.cc=0;$$.number=0;} +MAYBE_EXPRESSION_LIST : EXPRESSION_LIST +MAYBE_EXPRESSION_LIST : EXPRESSION_LIST_AND_COMMA + +EXPRESSION_LIST : NONCOMMAEXPRESSION {$$.number=1; + $$.cc = $1.c; + } + +EXPRESSION_LIST_AND_COMMA: EXPRESSION_LIST ',' {$$ = $1;} +EXPRESSION_LIST : EXPRESSION_LIST_AND_COMMA NONCOMMAEXPRESSION { + $$.number= $1.number+1; + $$.cc = code_append($1.cc, $2.c); + } + +XX : %prec new2 +NEW : "new" E XX MAYBE_PARAM_VALUES { + typedcode_t v = node_read($2); + $$.c = v.c; + if($$.c->opcode == OPCODE_COERCE_A) $$.c = code_cutlast($$.c); + + code_t*paramcode = $4.cc; + if($$.c->opcode == OPCODE_GETPROPERTY) { + multiname_t*name = $$.c->data[0];$$.c->data[0]=0; + $$.c = code_cutlast($$.c); + $$.c = code_append($$.c, paramcode); + $$.c = abc_constructprop2($$.c, name, $4.number); + multiname_destroy(name); + } else if(is_getlocal($$.c)) { + $$.c = code_append($$.c, paramcode); + $$.c = abc_construct($$.c, $4.number); + } else if(TYPE_IS_CLASS(v.t) && v.t->data) { + code_free($$.c); + classinfo_t*c = v.t->data; + MULTINAME(m, c); + $$.c = abc_findpropstrict2(0, &m); + $$.c = code_append($$.c, paramcode); + $$.c = abc_constructprop2($$.c, &m, $4.number); + /*} else if($$.c->opcode == OPCODE_GETSLOT) { + int slot = (int)(ptroff_t)$$.c->data[0]; + trait_t*t = traits_find_slotid(state->cls->abc->traits,slot);//FIXME + multiname_t*name = t->name; + $$.c = code_cutlast($$.c); + $$.c = code_append($$.c, paramcode); + $$.c = abc_constructprop2($$.c, name, $4.number);*/ + } else { + $$.c = code_append($$.c, paramcode); + $$.c = abc_construct($$.c, $4.number); + } + + $$.t = TYPE_ANY; + if(TYPE_IS_CLASS(v.t) && v.t->data) { + $$.t = v.t->data; + } else { + $$.c = abc_coerce_a($$.c); + $$.t = TYPE_ANY; + } +} + +/* TODO: use abc_call (for calling local variables), + abc_callstatic (for calling own methods) + call (for closures) +*/ +FUNCTIONCALL : E '(' MAYBE_EXPRESSION_LIST ')' { + + typedcode_t v = node_read($1); + $$.c = v.c; + if($$.c->opcode == OPCODE_COERCE_A) { + $$.c = code_cutlast($$.c); + } + code_t*paramcode = $3.cc; + + $$.t = TYPE_ANY; + if($$.c->opcode == OPCODE_GETPROPERTY) { + multiname_t*name = $$.c->data[0];$$.c->data[0]=0; + $$.c = code_cutlast($$.c); + $$.c = code_append($$.c, paramcode); + $$.c = abc_callproperty2($$.c, name, $3.number); + multiname_destroy(name); +/* } else if($$.c->opcode == OPCODE_GETSLOT && $$.c->prev->opcode != OPCODE_GETSCOPEOBJECT) { + int slot = (int)(ptroff_t)$$.c->data[0]; + trait_t*t = traits_find_slotid(state->cls->abc->traits,slot); + if(t->kind!=TRAIT_METHOD) { + //ok: flash allows to assign closures to members. + } + multiname_t*name = t->name; + $$.c = code_cutlast($$.c); + $$.c = code_append($$.c, paramcode); + //$$.c = abc_callmethod($$.c, t->method, len); //#1051 illegal early access binding + $$.c = abc_callproperty2($$.c, name, $3.number);*/ + } else if($$.c->opcode == OPCODE_GETSUPER) { + multiname_t*name = $$.c->data[0];$$.c->data[0]=0; + $$.c = code_cutlast($$.c); + $$.c = code_append($$.c, paramcode); + $$.c = abc_callsuper2($$.c, name, $3.number); + multiname_destroy(name); + } else { + $$.c = abc_getglobalscope($$.c); + $$.c = code_append($$.c, paramcode); + $$.c = abc_call($$.c, $3.number); + } + + if(TYPE_IS_FUNCTION(v.t) && v.t->data) { + $$.t = ((methodinfo_t*)(v.t->data))->return_type; + } else if(TYPE_IS_CLASS(v.t) && v.t->data) { + // calling a class is like a typecast + $$.t = (classinfo_t*)v.t->data; + } else { + $$.t = TYPE_ANY; + $$.c = abc_coerce_a($$.c); + } +} + +FUNCTIONCALL : "super" '(' MAYBE_EXPRESSION_LIST ')' { + if(!state->cls) syntaxerror("super() not allowed outside of a class"); + if(!state->method) syntaxerror("super() not allowed outside of a function"); + if(!state->method->is_constructor) syntaxerror("super() not allowed outside of a constructor"); + + $$.c = code_new(); + $$.c = abc_getlocal_0($$.c); + + $$.c = code_append($$.c, $3.cc); + /* + this is dependent on the control path, check this somewhere else + if(state->method->has_super) + syntaxerror("constructor may call super() only once"); + */ + state->method->has_super = 1; + + $$.c = abc_constructsuper($$.c, $3.number); + $$.c = abc_pushundefined($$.c); + $$.t = TYPE_ANY; +} + +DELETE: "delete" E { + typedcode_t v = node_read($2); + $$.c = v.c; + if($$.c->opcode == OPCODE_COERCE_A) { + $$.c = code_cutlast($$.c); + } + multiname_t*name = 0; + if($$.c->opcode == OPCODE_GETPROPERTY) { + $$.c->opcode = OPCODE_DELETEPROPERTY; + } else if($$.c->opcode == OPCODE_GETSLOT) { + int slot = (int)(ptroff_t)$$.c->data[0]; + multiname_t*name = traits_find_slotid(state->cls->abc->traits,slot)->name; + $$.c = code_cutlast($$.c); + $$.c = abc_deleteproperty2($$.c, name); + } else { + $$.c = abc_getlocal_0($$.c); + MULTINAME_LATE(m, v.t?v.t->access:ACCESS_PACKAGE, ""); + $$.c = abc_deleteproperty2($$.c, &m); + } + $$.t = TYPE_BOOLEAN; +} + +RETURN: "return" %prec prec_none { + $$ = abc_returnvoid(0); +} +RETURN: "return" EXPRESSION { + $$ = $2.c; + $$ = abc_returnvalue($$); +} + +// ----------------------- expression types ------------------------------------- + +NONCOMMAEXPRESSION : E %prec below_lt { + $$ = node_read($1); +} +EXPRESSION : COMMA_EXPRESSION { + $$ = node_read($1); +} +COMMA_EXPRESSION : E %prec below_lt { + $$ = mkmultinode(&node_comma, $1); +} +COMMA_EXPRESSION : COMMA_EXPRESSION ',' E %prec below_lt { + $$ = multinode_extend($1, $3); +} +VOIDEXPRESSION : E %prec below_minus { + $$ = node_exec($1); +} +VOIDEXPRESSION : VOIDEXPRESSION ',' E %prec below_lt { + $$ = $1; + $$ = code_append($$, node_exec($3)); +} + +MAYBE_DICT_EXPRPAIR_LIST : {$$.cc=0;$$.number=0;} +MAYBE_DICT_EXPRPAIR_LIST : DICT_EXPRPAIR_LIST {$$=$1;} + +DICTLH: T_IDENTIFIER {$$=abc_pushstring(0,$1);} +DICTLH: T_STRING {$$=abc_pushstring2(0,&$1);} +DICTLH: T_INT {syntaxerror("dictionary keys must be strings");} +DICTLH: T_UINT {syntaxerror("dictionary keys must be strings");} +DICTLH: T_FLOAT {syntaxerror("dictionary keys must be strings");} + +DICT_EXPRPAIR_LIST : DICTLH ':' NONCOMMAEXPRESSION { + $$.cc = 0; + $$.cc = code_append($$.cc, $1); + $$.cc = code_append($$.cc, $3.c); + $$.number = 2; +} +DICT_EXPRPAIR_LIST : DICT_EXPRPAIR_LIST ',' DICTLH ':' NONCOMMAEXPRESSION { + $$.cc = $1.cc; + $$.number = $1.number+2; + $$.cc = code_append($$.cc, $3); + $$.cc = code_append($$.cc, $5.c); +} + +// ----------------------- expression evaluation ------------------------------------- + +E : INNERFUNCTION %prec prec_none {$$ = mkcodenode($1);} +E : MEMBER %prec '.' {$$ = mkcodenode($1);} +E : NEW {$$ = mkcodenode($1);} +E : DELETE {$$ = mkcodenode($1);} +E : FUNCTIONCALL {$$ = mkcodenode($1);} +E : VAR_READ %prec T_IDENTIFIER {$$ = $1;} + +E : CONSTANT { + $$ = mkconstnode($1); +} + +E : XML { + $$ = $1; +} + +/* regexp */ +E : T_REGEXP { + typedcode_t v; + v.c = 0; + multiname_t m = {QNAME, &stdns, 0, "RegExp"}; + if(!$1.options) { + v.c = abc_getlex2(v.c, &m); + v.c = abc_pushstring(v.c, $1.pattern); + v.c = abc_construct(v.c, 1); + } else { + v.c = abc_getlex2(v.c, &m); + v.c = abc_pushstring(v.c, $1.pattern); + v.c = abc_pushstring(v.c, $1.options); + v.c = abc_construct(v.c, 2); + } + v.t = TYPE_REGEXP; + $$ = mkcodenode(v); +} + +E : KW_ARGUMENTS { + PASS1 + state->method->need_arguments = 1; + PASS2 + typedcode_t v; + v.c = abc_getlocal(0, state->method->need_arguments); + v.t = TYPE_ARRAY; + $$ = mkcodenode(v); +} + +/* array */ +E : '[' MAYBE_EXPRESSION_LIST ']' { + typedcode_t v; + v.c = code_new(); + v.c = code_append(v.c, $2.cc); + v.c = abc_newarray(v.c, $2.number); + v.t = registry_getarrayclass(); + $$ = mkcodenode(v); +} + +/* dictionary */ +E : "{ (dictionary)" MAYBE_DICT_EXPRPAIR_LIST '}' { + typedcode_t v; + v.c = code_new(); + v.c = code_append(v.c, $2.cc); + v.c = abc_newobject(v.c, $2.number/2); + v.t = registry_getobjectclass(); + $$ = mkcodenode(v); +} + +E : E '<' E {$$ = mknode2(&node_lt,$1,$3);} +E : E '>' E {$$ = mknode2(&node_gt,$1,$3);} +E : E "<=" E {$$ = mknode2(&node_le,$1,$3);} +E : E ">=" E {$$ = mknode2(&node_ge,$1,$3);} +E : E "==" E {$$ = mknode2(&node_eqeq,$1,$3);} +E : E "===" E {$$ = mknode2(&node_eqeqeq,$1,$3);} +E : E "!==" E {$$ = mknode2(&node_noteqeq,$1,$3);} +E : E "!=" E {$$ = mknode2(&node_noteq,$1,$3);} +E : E "||" E {$$ = mknode2(&node_oror,$1,$3);} +E : E "&&" E {$$ = mknode2(&node_andand,$1,$3);} +E : '!' E {$$ = mknode1(&node_not, $2);} +E : '~' E {$$ = mknode1(&node_bitnot, $2);} +E : E '&' E {$$ = mknode2(&node_bitand, $1, $3);} +E : E '^' E {$$ = mknode2(&node_bitxor, $1, $3);} +E : E '|' E {$$ = mknode2(&node_bitor, $1, $3);} +E : E ">>" E {$$ = mknode2(&node_shr, $1, $3);} +E : E ">>>" E {$$ = mknode2(&node_ushr, $1, $3);} +E : E "<<" E {$$ = mknode2(&node_shl, $1, $3);} +E : E '/' E {$$ = mknode2(&node_div, $1, $3);} +E : E '%' E {$$ = mknode2(&node_mod, $1, $3);} +E : E '+' E {$$ = mknode2(&node_plus, $1, $3);} +E : E '-' E {$$ = mknode2(&node_minus, $1, $3);} +E : E '*' E {$$ = mknode2(&node_multiply, $1, $3);} +E : E "in" E {$$ = mknode2(&node_in, $1, $3);} +E : E "as" E {$$ = mknode2(&node_as, $1, $3);} +E : E "instanceof" E {$$ = mknode2(&node_instanceof, $1, $3);} +E : E "is" E {$$ = mknode2(&node_is, $1, $3);} +E : "typeof" E {$$ = mknode1(&node_typeof, $2);} +E : "void" E {$$ = mknode1(&node_void, $2);} +E : "void" { $$ = mkconstnode(constant_new_undefined());} +E : '(' COMMA_EXPRESSION ')' { $$=$2;} +E : '-' E {$$ = mknode1(&node_neg, $2);} +E : E '[' E ']' {$$ = mknode2(&node_arraylookup, $1,$3);} +E : E "*=" E {$$ = mknode2(&node_muleq, $1, $3);} +E : E "%=" E {$$ = mknode2(&node_modeq, $1, $3);} +E : E "<<=" E {$$ = mknode2(&node_shleq, $1, $3);} +E : E ">>=" E {$$ = mknode2(&node_shreq, $1, $3);} +E : E ">>>=" E {$$ = mknode2(&node_ushreq, $1, $3);} +E : E "/=" E { $$ = mknode2(&node_diveq, $1, $3);} +E : E "|=" E { $$ = mknode2(&node_bitoreq, $1, $3);} +E : E "^=" E { $$ = mknode2(&node_bitxoreq, $1, $3);} +E : E "&=" E { $$ = mknode2(&node_bitandeq, $1, $3);} +E : E "+=" E { $$ = mknode2(&node_pluseq, $1, $3);} +E : E "-=" E { $$ = mknode2(&node_minuseq, $1, $3);} +E : E '=' E { $$ = mknode2(&node_assign, $1, $3);} +E : E '?' E ':' E %prec below_assignment { $$ = mknode3(&node_tenary, $1, $3, $5);} + +E : E "++" { $$ = mknode1(&node_rplusplus, $1);} +E : E "--" { $$ = mknode1(&node_rminusminus, $1);} +E : "++" %prec plusplus_prefix E {$$ = mknode1(&node_lplusplus, $2); } +E : "--" %prec minusminus_prefix E {$$ = mknode1(&node_lminusminus, $2); } + +E : "super" '.' T_IDENTIFIER + { if(!state->cls->info) + syntaxerror("super keyword not allowed outside a class"); + classinfo_t*t = state->cls->info->superclass; + if(!t) t = TYPE_OBJECT; + memberinfo_t*f = findmember_nsset(t, $3, 1, 0); + MEMBER_MULTINAME(m, f, $3); + typedcode_t v; + v.c = 0; + v.c = abc_getlocal_0(v.c); + v.c = abc_getsuper2(v.c, &m); + v.t = slotinfo_gettype((slotinfo_t*)f); + $$ = mkcodenode(v); + } + +E : '@' T_IDENTIFIER { + typedcode_t v; + multiname_t m = {MULTINAMEA, 0, &nopackage_namespace_set, $2}; + v.c = abc_getlex2(0, &m); + v.t = TYPE_STRING; + $$ = mkcodenode(v); +} + +E : E '.' '(' {PASS12 new_state();state->xmlfilter=1;} E ')' { + PASS1 old_state(); + PASS2 + typedcode_t v = node_read($1); + typedcode_t w = node_read($5); + code_t*c = 0; + int index = alloc_local(); + int result = alloc_local(); + int tmp = alloc_local(); + int xml = alloc_local(); + + c = code_append(c, v.c); + c = abc_checkfilter(c); + c = abc_coerce_a(c); //hasnext2 converts to * + c = abc_setlocal(c, xml); + multiname_t m = {QNAME, &stdns, 0, "XMLList"}; + c = abc_getlex2(c, &m); + c = abc_construct(c, 0); + c = abc_setlocal(c, result); + c = abc_pushbyte(c, 0); + c = abc_setlocal(c, index); + code_t*jmp = c = abc_jump(c, 0); + code_t*loop = c = abc_label(c); + c = abc_getlocal(c, xml); + c = abc_getlocal(c, index); + c = abc_nextvalue(c); + c = abc_dup(c); + c = abc_setlocal(c, tmp); + c = abc_pushwith(c); + c = code_append(c, w.c); + c = abc_popscope(c); + code_t*b = c = abc_iffalse(c, 0); + c = abc_getlocal(c, result); + c = abc_getlocal(c, index); + c = abc_getlocal(c, tmp); + multiname_t m2 = {MULTINAMEL, 0, &nopackage_namespace_set, 0}; + c = abc_setproperty2(c, &m2); + c = b->branch = jmp->branch = abc_nop(c); + c = abc_kill(c, tmp); + c = abc_hasnext2(c, xml, index); + c = abc_iftrue(c, loop); + c = abc_getlocal(c, result); + c = abc_kill(c, xml); + c = abc_kill(c, result); + c = abc_kill(c, index); + + c = var_block(c, state->vars); + old_state(); + typedcode_t r; + r.c = c; + r.t = TYPE_XMLLIST; + $$ = mkcodenode(r); +} + +//ID_OR_NS : T_IDENTIFIER {$$=$1;} +ID_OR_NS : '*' {$$="*";} + +SUBNODE: X_IDENTIFIER + | '*' {$$="*";} + +%code { + node_t* resolve_identifier(const char*name); + node_t* get_descendants(node_t*e,const char*ns,const char*subnode,char multi, char attr) + { + typedcode_t v = node_read(e); + typedcode_t w; + + multiname_t m = {0,0,0,subnode}; + namespace_t zero = {ZERONAMESPACE,"*"}; + if(!strcmp(ns,"*")) { + m.ns = &zero; + m.type = attr?QNAMEA:QNAME; + } else { + typedcode_t w = node_read(resolve_identifier(ns)); + if(!TYPE_IS_NAMESPACE(w.t)) { + as3_softwarning("%s might not be a namespace", ns); + } + v.c = code_append(v.c, w.c); + v.c = converttype(v.c, w.t, TYPE_NAMESPACE); + m.type = attr?RTQNAMEA:RTQNAME; + } + + if(!multi) { + v.c = abc_getproperty2(v.c, &m); + } else { + v.c = abc_getdescendants2(v.c, &m); + } + + if(TYPE_IS_XML(v.t)) { + v.t = TYPE_XMLLIST; + } else { + v.c = abc_coerce_a(v.c); + v.t = TYPE_ANY; + } + return mkcodenode(v); + } +}; + +/* happens in preprocessor code */ +E : E "::" E { +} + +E : E '.' ID_OR_NS "::" SUBNODE { + $$ = get_descendants($1, $3, $5, 0, 0); +} +E : E ".." SUBNODE { + typedcode_t v = node_read($1); + multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3}; + v.c = abc_getdescendants2(v.c, &m); + v.t = TYPE_XMLLIST; + $$ = mkcodenode(v); +} +E : E ".." ID_OR_NS "::" SUBNODE { + $$ = get_descendants($1, $3, $5, 1, 0); +} +E : E '.' '[' E ']' { + typedcode_t v = node_read($1); + typedcode_t w = node_read($4); + multiname_t m = {MULTINAMEL, 0, &nopackage_namespace_set, 0}; + v.c = code_append(v.c, w.c); + v.c = converttype(w.c, w.t, TYPE_STRING); + v.c = abc_getproperty2(v.c, &m); + v.t = TYPE_XMLLIST; + $$ = mkcodenode(v); +} + +E : E '.' '@' SUBNODE { + typedcode_t v = node_read($1); + multiname_t m = {MULTINAMEA, 0, &nopackage_namespace_set, $4}; + v.c = abc_getproperty2(v.c, &m); + v.t = TYPE_STRING; + $$ = mkcodenode(v); +} + +E : E '.' '@' ID_OR_NS "::" SUBNODE { + $$ = get_descendants($1, $4, $6, 0, 1); +} + +E : E ".." '@' SUBNODE { + typedcode_t v = node_read($1); + multiname_t m = {MULTINAMEA, 0, &nopackage_namespace_set, $4}; + v.c = abc_getdescendants2(v.c, &m); + v.t = TYPE_STRING; + $$ = mkcodenode(v); +} +E : E ".." '@' ID_OR_NS "::" SUBNODE { + $$ = get_descendants($1, $4, $6, 1, 1); +} + +E : E '.' '@' '[' E ']' { + typedcode_t v = node_read($1); + typedcode_t w = node_read($5); + multiname_t m = {MULTINAMELA, 0, &nopackage_namespace_set, 0}; + v.c = code_append(v.c, w.c); + v.c = converttype(w.c, w.t, TYPE_STRING); + v.c = abc_getproperty2(v.c, &m); + v.t = TYPE_STRING; + $$ = mkcodenode(v); +} +E : E ".." '@' '[' E ']' { + typedcode_t v = node_read($1); + typedcode_t w = node_read($5); + multiname_t m = {MULTINAMELA, 0, &nopackage_namespace_set, 0}; + v.c = code_append(v.c, w.c); + v.c = converttype(w.c, w.t, TYPE_STRING); + v.c = abc_getdescendants2(v.c, &m); + v.t = TYPE_STRING; + $$ = mkcodenode(v); +} + +MEMBER : E '.' SUBNODE { + typedcode_t v1 = node_read($1); + $$.c = v1.c; + classinfo_t*t = v1.t; + char is_static = 0; + if(TYPE_IS_CLASS(t) && t->data) { + t = t->data; + is_static = 1; + } + if(TYPE_IS_XML(t) && !findmember_nsset(t, $3, 1, is_static)) { + multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3}; + $$.c = abc_getproperty2($$.c, &m); + $$.c = abc_coerce_a($$.c); + $$.t = TYPE_XMLLIST; + } else if(t) { + if(t->subtype==INFOTYPE_UNRESOLVED) { + syntaxerror("syntaxerror: trying to resolve property '%s' on incomplete object '%s'", $3, t->name); + } + memberinfo_t*f = findmember_nsset(t, $3, 1, is_static); + char noslot = 0; + if(f && !is_static != !(f->flags&FLAG_STATIC)) + noslot=1; + if(f && f->slot && !noslot) { + $$.c = abc_getslot($$.c, f->slot); + } else { + if(!f) { + if(!TYPE_IS_XMLLIST(t)) { + as3_softwarning("Access of undefined property '%s' in %s", $3, t->name); + } + } + MEMBER_MULTINAME(m, f, $3); + $$.c = abc_getproperty2($$.c, &m); + } + /* determine type */ + $$.t = slotinfo_gettype((slotinfo_t*)f); + if(!$$.t) + $$.c = abc_coerce_a($$.c); + + } else if(v1.c && v1.c->opcode == OPCODE___PUSHPACKAGE__) { + string_t*package = v1.c->data[0]; + char*package2 = concat3(package->str, ".", $3); + + slotinfo_t*a = registry_find(package->str, $3); + if(a) { + $$ = push_class(a); + } else if(dict_contains(state->import_toplevel_packages, package2) || + registry_ispackage(package2)) { + $$.c = v1.c; + $$.c->data[0] = string_new4(package2); + $$.t = 0; + } else { + syntaxerror("couldn't resolve %s", package2); + } + } else { + /* when resolving a property on an unknown type, we do know the + name of the property (and don't seem to need the package), but + we need to make avm2 try out all access modes */ + as3_softwarning("Resolving %s on unknown type", $3); + multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3}; + $$.c = abc_getproperty2($$.c, &m); + $$.c = abc_coerce_a($$.c); + $$.t = TYPE_ANY; + } +} + +%code { + node_t* var_read(variable_t*v) + { + typedcode_t o; + o.c = abc_getlocal(0, v->index); + o.t = v->type; + return mkcodenode(o); + } + + node_t* resolve_identifier(const char*name) + { + typedcode_t o; + o.t = 0; + o.c = 0; + + slotinfo_t*a = 0; + memberinfo_t*f = 0; + + variable_t*v; + /* look at variables */ + if((v = find_variable(state, name))) { + // name is a local variable + return var_read(v); + } + if((v = find_slot(state->method, name))) { + o.c = abc_getscopeobject(o.c, 1); + o.c = abc_getslot(o.c, v->index); + o.t = v->type; + return mkcodenode(o); + } + + int i_am_static = state->method->is_static; + + if(!state->method->inner && !state->xmlfilter && state->cls) + { + /* look at current class' members */ + if((f = findmember_nsset(state->cls->info, name, 1, i_am_static))) + { + // name is a member or attribute in this class + int var_is_static = (f->flags&FLAG_STATIC); + + if(f->kind == INFOTYPE_VAR && (f->flags&FLAG_CONST)) { + /* if the variable is a constant (and we know what is evaluates to), we + can just use the value itself */ + varinfo_t*v = (varinfo_t*)f; + if(v->value) { + return mkconstnode(v->value); + } + } + + if(var_is_static >= i_am_static) { + if(f->kind == INFOTYPE_METHOD) { + o.t = TYPE_FUNCTION(f); + } else { + o.t = f->type; + } + + if(var_is_static && !i_am_static) { + /* access to a static member from a non-static location. + do this via findpropstrict: + there doesn't seem to be any non-lookup way to access + static properties of a class */ + state->method->late_binding = 1; + o.t = f->type; + namespace_t ns = {f->access, f->package}; + multiname_t m = {QNAME, &ns, 0, name}; + o.c = abc_findpropstrict2(o.c, &m); + o.c = abc_getproperty2(o.c, &m); + return mkcodenode(o); + } else if(f->slot>0) { + o.c = abc_getlocal_0(o.c); + o.c = abc_getslot(o.c, f->slot); + return mkcodenode(o); + } else { + MEMBER_MULTINAME(m, f, name); + o.c = abc_getlocal_0(o.c); + o.c = abc_getproperty2(o.c, &m); + return mkcodenode(o); + } + } + } + /* special case: it's allowed to access non-static constants + from a static context */ + if(i_am_static && (f=findmember_nsset(state->cls->info, name, 1, 0))) { + if(f->kind == INFOTYPE_VAR && (f->flags&FLAG_CONST)) { + varinfo_t*v = (varinfo_t*)f; + if(v->value) { + return mkconstnode(v->value); + } + } + } + } + + /* look at actual classes, in the current package and imported */ + if(!state->xmlfilter && (a = find_class(name))) { + registry_use(a); + if(state->cls && state->cls->info == (classinfo_t*)a && i_am_static) { + o.c = abc_getlocal_0(0); + o.t = TYPE_CLASS((classinfo_t*)a); + } else { + o = push_class(a); + } + return mkcodenode(o); + } + + /* look through package prefixes */ + if(!state->xmlfilter && + (dict_contains(state->import_toplevel_packages, name) || + registry_ispackage(name))) { + o.c = abc___pushpackage__(o.c, (char*)name); + o.t = 0; + return mkcodenode(o); //? + } + + /* unknown object, let the avm2 resolve it */ + if(1) { + if(!state->method->inner && !state->xmlfilter) { + /* we really should make inner functions aware of the class context */ + as3_warning("Couldn't resolve '%s', doing late binding", name); + } + state->method->late_binding = 1; + + multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, name}; + + o.t = 0; + o.c = abc_findpropstrict2(o.c, &m); + o.c = abc_getproperty2(o.c, &m); + return mkcodenode(o); + } + } +}; + +/*NOTHING : %prec below_identifier*/ +VAR_READ : T_IDENTIFIER { + PASS1 + char*name = $1; + /* Queue unresolved identifiers for checking against the parent + function's variables. + We consider everything which is not a local variable "unresolved". + This encompasses class names, members of the surrounding class + etc. which is *correct* because local variables of the parent function + would shadow those. + */ + + if(!find_variable(state, name)) { + unknown_variable(name); + /* let the compiler know that it might want to check the current directory/package + for this identifier- maybe there's a file $1.as defining $1. */ + as3_schedule_class_noerror(state->package, name); + } + + $$ = 0; + PASS2 + char*name = $1; + $$ = resolve_identifier(name); +} + +// ----------------- namespaces ------------------------------------------------- + +%code { + void add_active_url(const char*url) + { + NEW(namespace_t,n); + n->name = url; + list_append(state->active_namespace_urls, n); + } +}; + +NAMESPACE_ID : "namespace" T_IDENTIFIER { + PASS12 + NEW(namespace_decl_t,n); + n->name = $2; + n->url = $2; + $$=n; +} +NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_IDENTIFIER { + PASS12 + NEW(namespace_decl_t,n); + n->name = $2; + n->url = $4; + $$=n; +} +NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_STRING { + PASS12 + NEW(namespace_decl_t,n); + n->name = $2; + n->url = $4.str; + $$=n; +} +NAMESPACE_DECLARATION : MAYBE_MODIFIERS NAMESPACE_ID { + PASS12 + dict_put(state->namespaces, (unsigned char*)$2->name, (void*)$2->url); + + namespace_t access = modifiers2access(&$1); + varinfo_t* var = varinfo_register_global(access.access, state->package, $2->name); + var->type = TYPE_NAMESPACE; + namespace_t ns; + ns.access = ACCESS_NAMESPACE; + ns.name = $2->url; + var->value = constant_new_namespace(&ns); + + if(as3_pass==2) { + MULTINAME(m, TYPE_NAMESPACE); + trait_t*t = add_abc_slot(&$1, $2->name, 0, 0); + t->value = var->value; + t->type_name = multiname_clone(&m); + } + + $$=0; +} + +DEFAULT_NAMESPACE : "default xml" "namespace" '=' E +{ + $$ = 0; + $$ = code_append($$, node_read($4).c); + $$ = abc_dxnslate($$); +} + +USE_NAMESPACE : "use" "namespace" CLASS_SPEC { + PASS12 + + varinfo_t*s = (varinfo_t*)$3; + if(s->kind == INFOTYPE_UNRESOLVED) { + s = (varinfo_t*)registry_resolve((slotinfo_t*)s); + if(!s) + syntaxerror("Couldn't resolve namespace %s", $3->name); + } + + if(!s || s->kind != INFOTYPE_VAR) + syntaxerror("%s.%s is not a public namespace (%d)", $3->package, $3->name, s?s->kind:-1); + if(!s->value || !NS_TYPE(s->value->type)) + syntaxerror("%s.%s is not a namespace", $3->package, $3->name); + + const char*url = s->value->ns->name; + dict_put(state->namespaces, (unsigned char*)$3->name, (void*)url); + add_active_url(url); + $$=0; +} + diff -Nru swftools-0.9.2+ds1/lib/as3/skeleton.m4 swftools-0.9.1/lib/as3/skeleton.m4 --- swftools-0.9.2+ds1/lib/as3/skeleton.m4 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/as3/skeleton.m4 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,1750 @@ + -*- C -*- + +# Yacc compatible skeleton for Bison + +# Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, +# 2007, 2008 Free Software Foundation, Inc. + +# 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 3 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, see . + +# Check the value of %define api.push_pull. +b4_percent_define_default([[api.push_pull]], [[pull]]) +b4_percent_define_check_values([[[[api.push_pull]], + [[pull]], [[push]], [[both]]]]) +b4_define_flag_if([pull]) m4_define([b4_pull_flag], [[1]]) +b4_define_flag_if([push]) m4_define([b4_push_flag], [[1]]) +m4_case(b4_percent_define_get([[api.push_pull]]), + [pull], [m4_define([b4_push_flag], [[0]])], + [push], [m4_define([b4_pull_flag], [[0]])]) + +# Handle BISON_USE_PUSH_FOR_PULL for the test suite. So that push parsing +# tests function as written, don't let BISON_USE_PUSH_FOR_PULL modify Bison's +# behavior at all when push parsing is already requested. +b4_define_flag_if([use_push_for_pull]) +b4_use_push_for_pull_if([ + b4_push_if([m4_define([b4_use_push_for_pull_flag], [[0]])], + [m4_define([b4_push_flag], [[1]])])]) + +m4_include(b4_pkgdatadir/[c.m4]) + +m4_define([b4_case], +[ + case $1: + if(as3_pass==2) { +$2 + } + break; +]) + +## ---------------- ## +## Default values. ## +## ---------------- ## + +# Stack parameters. +m4_define_default([b4_stack_depth_max], [10000]) +m4_define_default([b4_stack_depth_init], [200]) + + +## ------------------------ ## +## Pure/impure interfaces. ## +## ------------------------ ## + +b4_percent_define_default([[api.pure]], [[false]]) +b4_define_flag_if([pure]) +m4_define([b4_pure_flag], + [b4_percent_define_flag_if([[api.pure]], [[1]], [[0]])]) + +# b4_yacc_pure_if(IF-TRUE, IF-FALSE) +# ---------------------------------- +# Expand IF-TRUE, if %pure-parser and %parse-param, IF-FALSE otherwise. +m4_define([b4_yacc_pure_if], +[b4_pure_if([m4_ifset([b4_parse_param], + [$1], [$2])], + [$2])]) + + +# b4_yyerror_args +# --------------- +# Arguments passed to yyerror: user args plus yylloc. +m4_define([b4_yyerror_args], +[b4_yacc_pure_if([b4_locations_if([&yylloc, ])])dnl +m4_ifset([b4_parse_param], [b4_c_args(b4_parse_param), ])]) + + +# b4_lex_param +# ------------ +# Accumulate in b4_lex_param all the yylex arguments. +# b4_lex_param arrives quoted twice, but we want to keep only one level. +m4_define([b4_lex_param], +m4_dquote(b4_pure_if([[[[YYSTYPE *]], [[&yylval]]][]dnl +b4_locations_if([, [[YYLTYPE *], [&yylloc]]])m4_ifdef([b4_lex_param], [, ])])dnl +m4_ifdef([b4_lex_param], b4_lex_param))) + + +## ------------ ## +## Data Types. ## +## ------------ ## + +# b4_int_type(MIN, MAX) +# --------------------- +# Return the smallest int type able to handle numbers ranging from +# MIN to MAX (included). Overwrite the version from c.m4, which +# uses only C89 types, so that the user can override the shorter +# types, and so that pre-C89 compilers are handled correctly. +m4_define([b4_int_type], +[m4_if(b4_ints_in($@, [0], [255]), [1], [yytype_uint8], + b4_ints_in($@, [-128], [127]), [1], [yytype_int8], + + b4_ints_in($@, [0], [65535]), [1], [yytype_uint16], + b4_ints_in($@, [-32768], [32767]), [1], [yytype_int16], + + m4_eval([0 <= $1]), [1], [unsigned int], + + [int])]) + + +## ----------------- ## +## Semantic Values. ## +## ----------------- ## + + +# b4_lhs_value([TYPE]) +# -------------------- +# Expansion of $$. +m4_define([b4_lhs_value], +[(yyval[]m4_ifval([$1], [.$1]))]) + + +# b4_rhs_value(RULE-LENGTH, NUM, [TYPE]) +# -------------------------------------- +# Expansion of $NUM, where the current rule has RULE-LENGTH +# symbols on RHS. +m4_define([b4_rhs_value], +[(yyvsp@{($2) - ($1)@}m4_ifval([$3], [.$3]))]) + + + +## ----------- ## +## Locations. ## +## ----------- ## + +# b4_lhs_location() +# ----------------- +# Expansion of @$. +m4_define([b4_lhs_location], +[(yyloc)]) + + +# b4_rhs_location(RULE-LENGTH, NUM) +# --------------------------------- +# Expansion of @NUM, where the current rule has RULE-LENGTH symbols +# on RHS. +m4_define([b4_rhs_location], +[(yylsp@{($2) - ($1)@})]) + + + +## --------------------------------------------------------- ## +## Defining symbol actions, e.g., printers and destructors. ## +## --------------------------------------------------------- ## + +# We do want M4 expansion after # for CPP macros. +m4_changecom() +m4_divert_push(0)dnl +@output(b4_parser_file_name@) +b4_copyright([Skeleton implementation for Bison's Yacc-like parsers in C],dnl ' + [1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006])[ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +]b4_identification +b4_percent_code_get([[top]])[]dnl +m4_if(b4_prefix, [yy], [], +[[/* Substitute the variable and function names. */ +]b4_pull_if([[#define yyparse ]b4_prefix[parse +]])b4_push_if([[#define yypush_parse ]b4_prefix[push_parse +]b4_pull_if([[#define yypull_parse ]b4_prefix[pull_parse +]])[#define yypstate_new ]b4_prefix[pstate_new +#define yypstate_delete ]b4_prefix[pstate_delete +#define yypstate ]b4_prefix[pstate +]])[#define yylex ]b4_prefix[lex +#define yyerror ]b4_prefix[error +#define yylval ]b4_prefix[lval +#define yychar ]b4_prefix[char +#define yydebug ]b4_prefix[debug +#define yynerrs ]b4_prefix[nerrs +]b4_locations_if([[#define yylloc ]b4_prefix[lloc]])])[ + +/* Copy the first part of user declarations. */ +]b4_user_pre_prologue[ + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG ]b4_debug_flag[ +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE ]b4_error_verbose_flag[ +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE ]b4_token_table[ +#endif + +]b4_percent_code_get([[requires]])[]dnl + +b4_token_enums_defines(b4_tokens)[ + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +]m4_ifdef([b4_stype], +[[typedef union ]b4_union_name[ +{ +]b4_user_stype[ +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1]], +[m4_if(b4_tag_seen_flag, 0, +[[typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1]])])[ +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif]b4_locations_if([[ + +#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif]])b4_push_if([[ + +#ifndef YYPUSH_DECLS +# define YYPUSH_DECLS +struct yypstate; +typedef struct yypstate yypstate; +enum { YYPUSH_MORE = 4 }; + +]b4_pull_if([b4_c_function_decl([[yyparse]], [[int]], b4_parse_param) +])b4_c_function_decl([[yypush_parse]], [[int]], + [[[yypstate *yyps]], [[yyps]]]b4_pure_if([, + [[[int yypushed_char]], [[yypushed_char]]], + [[[YYSTYPE const *yypushed_val]], [[yypushed_val]]]b4_locations_if([, + [[[YYLTYPE const *yypushed_loc]], [[yypushed_loc]]]])])m4_ifset([b4_parse_param], [, + b4_parse_param])) +b4_pull_if([b4_c_function_decl([[yypull_parse]], [[int]], + [[[yypstate *yyps]], [[yyps]]]m4_ifset([b4_parse_param], [, + b4_parse_param]))]) +b4_c_function_decl([[yypstate_new]], [[yypstate *]], [[[void]], []]) +b4_c_function_decl([[yypstate_delete]], [[void]], + [[[yypstate *yyps]], [[yyps]]])[ +#endif]]) + +b4_percent_code_get([[provides]])[]dnl + +[/* Copy the second part of user declarations. */ +]b4_user_post_prologue +b4_percent_code_get[]dnl + +[#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif ]b4_c_modern[ +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && ]b4_c_modern[ +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +]b4_c_function_def([YYID], [static int], [[int yyi], [yyi]])[ +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +]b4_push_if([], +[[/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && ]b4_c_modern[ +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +]])dnl +[# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && ]b4_c_modern[ +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && ]b4_c_modern[ +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (]b4_locations_if([[defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ + && ]])[defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc;]b4_locations_if([ + YYLTYPE yyls_alloc;])[ +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +]b4_locations_if( +[# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAXIMUM)], +[# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM)])[ + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL ]b4_final_state_number[ +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST ]b4_last[ + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS ]b4_tokens_number[ +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS ]b4_nterms_number[ +/* YYNRULES -- Number of rules. */ +#define YYNRULES ]b4_rules_number[ +/* YYNRULES -- Number of states. */ +#define YYNSTATES ]b4_states_number[ + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK ]b4_undef_token_number[ +#define YYMAXUTOK ]b4_user_token_number_max[ + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const ]b4_int_type_for([b4_translate])[ yytranslate[] = +{ + ]b4_translate[ +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const ]b4_int_type_for([b4_prhs])[ yyprhs[] = +{ + ]b4_prhs[ +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const ]b4_int_type_for([b4_rhs])[ yyrhs[] = +{ + ]b4_rhs[ +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const ]b4_int_type_for([b4_rline])[ yyrline[] = +{ + ]b4_rline[ +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + ]b4_tname[ +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const ]b4_int_type_for([b4_toknum])[ yytoknum[] = +{ + ]b4_toknum[ +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const ]b4_int_type_for([b4_r1])[ yyr1[] = +{ + ]b4_r1[ +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const ]b4_int_type_for([b4_r2])[ yyr2[] = +{ + ]b4_r2[ +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const ]b4_int_type_for([b4_defact])[ yydefact[] = +{ + ]b4_defact[ +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const ]b4_int_type_for([b4_defgoto])[ yydefgoto[] = +{ + ]b4_defgoto[ +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF ]b4_pact_ninf[ +static const ]b4_int_type_for([b4_pact])[ yypact[] = +{ + ]b4_pact[ +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const ]b4_int_type_for([b4_pgoto])[ yypgoto[] = +{ + ]b4_pgoto[ +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF ]b4_table_ninf[ +static const ]b4_int_type_for([b4_table])[ yytable[] = +{ + ]b4_table[ +}; + +static const ]b4_int_type_for([b4_check])[ yycheck[] = +{ + ]b4_check[ +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const ]b4_int_type_for([b4_stos])[ yystos[] = +{ + ]b4_stos[ +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (]b4_yyerror_args[YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (]b4_pure_if([&yylval[]b4_locations_if([, &yylloc]), ])[YYLEX_PARAM) +#else +# define YYLEX ]b4_c_function_call([yylex], [int], b4_lex_param)[ +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value]b4_locations_if([, Location])[]b4_user_args[); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + +]b4_yy_symbol_print_generate([b4_c_function_def])[ + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +]b4_c_function_def([yy_stack_print], [static void], + [[yytype_int16 *yybottom], [yybottom]], + [[yytype_int16 *yytop], [yytop]])[ +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +]b4_c_function_def([yy_reduce_print], [static void], + [[YYSTYPE *yyvsp], [yyvsp]], + b4_locations_if([[[YYLTYPE *yylsp], [yylsp]], + ])[[int yyrule], [yyrule]]m4_ifset([b4_parse_param], [, + b4_parse_param]))[ +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &]b4_rhs_value(yynrhs, yyi + 1)[ + ]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl + b4_user_args[); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, ]b4_locations_if([yylsp, ])[Rule]b4_user_args[); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH ]b4_stack_depth_init[ +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH ]b4_stack_depth_max[ +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +]b4_c_function_def([yystrlen], [static YYSIZE_T], + [[const char *yystr], [yystr]])[ +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +]b4_c_function_def([yystpcpy], [static char *], + [[char *yydest], [yydest]], [[const char *yysrc], [yysrc]])[ +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +]b4_yydestruct_generate([b4_c_function_def])[ + +]b4_push_if([], +[[/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +]b4_c_function_decl([yyparse], [int], + [[void *YYPARSE_PARAM], [YYPARSE_PARAM]])[ +#else /* ! YYPARSE_PARAM */ +]b4_c_function_decl([yyparse], [int], b4_parse_param)[ +#endif /* ! YYPARSE_PARAM */]]) + +m4_divert_push([KILL])# ======================== M4 code. +# b4_declare_scanner_communication_variables +# ------------------------------------------ +# Declare the variables that are global, or local to YYPARSE if +# pure-parser. +m4_define([b4_declare_scanner_communication_variables], +[[/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +]b4_locations_if([[ +/* Location data for the lookahead symbol. */ +YYLTYPE yylloc; +]])b4_pure_if([], [[ +/* Number of syntax errors so far. */ +int yynerrs; +]])]) + +# b4_declare_parser_state_variables +# --------------------------------- +# Declare all the variables that are needed to maintain the parser state +# between calls to yypush_parse. +m4_define([b4_declare_parser_state_variables], +[b4_pure_if([[ /* Number of syntax errors so far. */ + int yynerrs; +]])[ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values.]b4_locations_if([[ + `yyls': related to locations.]])[ + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; +]b4_locations_if([[ + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls; + YYLTYPE *yylsp; + + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[2]; +]])[ + YYSIZE_T yystacksize; +]]) + +m4_divert_pop([KILL])dnl# ====================== End of M4 code. + +b4_pure_if([], [b4_declare_scanner_communication_variables]) + +b4_push_if( +[[struct yypstate + { + ]b4_declare_parser_state_variables[ + /* Used to determine if this is the first time this instance has + been used. */ + int yynew; + };]b4_pure_if([], [[ + +static char yypstate_allocated = 0;]])b4_pull_if([ + +b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[ +{ + return yypull_parse (0]m4_ifset([b4_parse_param], + [[, ]b4_c_args(b4_parse_param)])[); +} + +]b4_c_function_def([[yypull_parse]], [[int]], + [[[yypstate *yyps]], [[yyps]]]m4_ifset([b4_parse_param], [, + b4_parse_param]))[ +{ + int yystatus; + yypstate *yyps_local;]b4_pure_if([[ + int yychar; + YYSTYPE yylval;]b4_locations_if([[ + YYLTYPE yylloc;]])])[ + if (yyps == 0) + { + yyps_local = yypstate_new (); + if (!yyps_local) + {]b4_pure_if([[ + yyerror (]b4_yyerror_args[YY_("memory exhausted"));]], [[ + if (!yypstate_allocated) + yyerror (]b4_yyerror_args[YY_("memory exhausted"));]])[ + return 2; + } + } + else + yyps_local = yyps; + do { + yychar = YYLEX; + yystatus = + yypush_parse (yyps_local]b4_pure_if([[, yychar, &yylval]b4_locations_if([[, &yylloc]])])m4_ifset([b4_parse_param], [, b4_c_args(b4_parse_param)])[); + } while (yystatus == YYPUSH_MORE); + if (yyps == 0) + yypstate_delete (yyps_local); + return yystatus; +}]])[ + +/* Initialize the parser data structure. */ +]b4_c_function_def([[yypstate_new]], [[yypstate *]])[ +{ + yypstate *yyps;]b4_pure_if([], [[ + if (yypstate_allocated) + return 0;]])[ + yyps = (yypstate *) malloc (sizeof *yyps); + if (!yyps) + return 0; + yyps->yynew = 1;]b4_pure_if([], [[ + yypstate_allocated = 1;]])[ + return yyps; +} + +]b4_c_function_def([[yypstate_delete]], [[void]], + [[[yypstate *yyps]], [[yyps]]])[ +{ +#ifndef yyoverflow + /* If the stack was reallocated but the parse did not complete, then the + stack still needs to be freed. */ + if (!yyps->yynew && yyps->yyss != yyps->yyssa) + YYSTACK_FREE (yyps->yyss); +#endif + free (yyps);]b4_pure_if([], [[ + yypstate_allocated = 0;]])[ +} + +]b4_pure_if([[#define ]b4_prefix[nerrs yyps->]b4_prefix[nerrs +]])[#define yystate yyps->yystate +#define yyerrstatus yyps->yyerrstatus +#define yyssa yyps->yyssa +#define yyss yyps->yyss +#define yyssp yyps->yyssp +#define yyvsa yyps->yyvsa +#define yyvs yyps->yyvs +#define yyvsp yyps->yyvsp +]b4_locations_if([[#define yylsa yyps->yylsa +#define yyls yyps->yyls +#define yylsp yyps->yylsp +#define yyerror_range yyps->yyerror_range +]])[#define yystacksize yyps->yystacksize +]])[ +/*-------------------------. +| yyparse or yypush_parse. | +`-------------------------*/ +]b4_push_if([ +b4_c_function_def([[yypush_parse]], [[int]], + [[[yypstate *yyps]], [[yyps]]]b4_pure_if([, + [[[int yypushed_char]], [[yypushed_char]]], + [[[YYSTYPE const *yypushed_val]], [[yypushed_val]]]b4_locations_if([, + [[[YYLTYPE const *yypushed_loc]], [[yypushed_loc]]]])])m4_ifset([b4_parse_param], [, + b4_parse_param]))], [ +#ifdef YYPARSE_PARAM +b4_c_function_def([yyparse], [int], [[void *YYPARSE_PARAM], [YYPARSE_PARAM]]) +#else /* ! YYPARSE_PARAM */ +b4_c_function_def([yyparse], [int], b4_parse_param) +#endif])[ +{ +]b4_pure_if([b4_declare_scanner_communication_variables]) +b4_push_if([b4_pure_if([], [[ int yypushed_char = yychar; + YYSTYPE yypushed_val = yylval; + ]b4_locations_if([[YYLTYPE yypushed_loc = yylloc; +]])])], + [b4_declare_parser_state_variables])[ + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval;]b4_locations_if([[ + YYLTYPE yyloc;]])[ + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)]b4_locations_if([, yylsp -= (N)])[) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0;]b4_push_if([[ + + if (!yyps->yynew) + { + yyn = yypact[yystate]; + goto yyread_pushed_token; + }]])[ + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa;]b4_locations_if([[ + yyls = yylsa;]])[ + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs;]b4_locations_if([[ + yylsp = yyls; + +#if YYLTYPE_IS_TRIVIAL + /* Initialize the default location before parsing starts. */ + yylloc.first_line = yylloc.last_line = ]b4_location_initial_line[; + yylloc.first_column = yylloc.last_column = ]b4_location_initial_column[; +#endif]]) +m4_ifdef([b4_initial_action],[ +m4_pushdef([b4_at_dollar], [m4_define([b4_at_dollar_used])yylloc])dnl +m4_pushdef([b4_dollar_dollar], [m4_define([b4_dollar_dollar_used])yylval])dnl +/* User initialization code. */ +b4_user_initial_action +m4_popdef([b4_dollar_dollar])dnl +m4_popdef([b4_at_dollar])])dnl +m4_ifdef([b4_dollar_dollar_used],[[ yyvsp[0] = yylval; +]])dnl +m4_ifdef([b4_at_dollar_used], [[ yylsp[0] = yylloc; +]])[ + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss;]b4_locations_if([ + YYLTYPE *yyls1 = yyls;])[ + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp),]b4_locations_if([ + &yyls1, yysize * sizeof (*yylsp),])[ + &yystacksize); +]b4_locations_if([ + yyls = yyls1;])[ + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs);]b4_locations_if([ + YYSTACK_RELOCATE (yyls_alloc, yyls);])[ +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1;]b4_locations_if([ + yylsp = yyls + yysize - 1;])[ + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + {]b4_push_if([[ + if (!yyps->yynew) + {]b4_use_push_for_pull_if([], [[ + YYDPRINTF ((stderr, "Return for a new token:\n"));]])[ + yyresult = YYPUSH_MORE; + goto yypushreturn; + } + yyps->yynew = 0;]b4_pure_if([], [[ + /* Restoring the pushed token is only necessary for the first + yypush_parse invocation since subsequent invocations don't overwrite + it before jumping to yyread_pushed_token. */ + yychar = yypushed_char; + yylval = yypushed_val;]b4_locations_if([[ + yylloc = yypushed_loc;]])])[ +yyread_pushed_token:]])[ + YYDPRINTF ((stderr, "Reading a token: "));]b4_push_if([b4_pure_if([[ + yychar = yypushed_char; + if (yypushed_val) + yylval = *yypushed_val;]b4_locations_if([[ + if (yypushed_loc) + yylloc = *yypushed_loc;]])])], [[ + yychar = YYLEX;]])[ + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; +]b4_locations_if([ *++yylsp = yylloc;])[ + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + +]b4_locations_if( +[[ /* Default location. */ + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);]])[ + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + ]b4_user_actions[ + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval;]b4_locations_if([ + *++yylsp = yyloc;])[ + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (]b4_yyerror_args[YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (]b4_yyerror_args[yymsg); + } + else + { + yyerror (]b4_yyerror_args[YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + +]b4_locations_if([[ yyerror_range[0] = yylloc;]])[ + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + +]b4_locations_if([[ yyerror_range[0] = yylsp[1-yylen]; +]])[ /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + +]b4_locations_if([[ yyerror_range[0] = *yylsp;]])[ + yydestruct ("Error: popping", + yystos[yystate], yyvsp]b4_locations_if([, yylsp])[]b4_user_args[); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + *++yyvsp = yylval; +]b4_locations_if([[ + yyerror_range[1] = yylloc; + /* Using YYLLOC is tempting, but would change the location of + the lookahead. YYLOC is available though. */ + YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); + *++yylsp = yyloc;]])[ + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (]b4_yyerror_args[YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp]b4_locations_if([, yylsp])[]b4_user_args[); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +]b4_push_if([[ yyps->yynew = 1; + +yypushreturn: +]])[#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + +]b4_epilogue +b4_defines_if( +[@output(b4_spec_defines_file@) +b4_copyright([Skeleton interface for Bison's Yacc-like parsers in C],dnl ' + [1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006]) + +b4_percent_code_get([[requires]])[]dnl + +b4_token_enums_defines(b4_tokens) + +[#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +]m4_ifdef([b4_stype], +[[typedef union ]b4_union_name[ +{ +]b4_user_stype[ +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1]], +[m4_if(b4_tag_seen_flag, 0, +[[typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1]])])[ +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + +]b4_pure_if([], [[extern YYSTYPE ]b4_prefix[lval;]]) + +b4_locations_if( +[#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + +]b4_pure_if([], [[extern YYLTYPE ]b4_prefix[lloc;]]) +)dnl b4_locations_if +b4_push_if([[ +#ifndef YYPUSH_DECLS +# define YYPUSH_DECLS +struct ]b4_prefix[pstate; +typedef struct ]b4_prefix[pstate ]b4_prefix[pstate; +enum { YYPUSH_MORE = 4 }; +]b4_pull_if([b4_c_function_decl([b4_prefix[parse]], [[int]], b4_parse_param) +])b4_c_function_decl([b4_prefix[push_parse]], [[int]], + [[b4_prefix[pstate *yyps]], [[yyps]]]b4_pure_if([, + [[[int yypushed_char]], [[yypushed_char]]], + [[[YYSTYPE const *yypushed_val]], [[yypushed_val]]]b4_locations_if([, + [[[YYLTYPE const *yypushed_loc]], [[yypushed_loc]]]])])m4_ifset([b4_parse_param], [, + b4_parse_param])) +b4_pull_if([b4_c_function_decl([b4_prefix[pull_parse]], [[int]], + [[b4_prefix[pstate *yyps]], [[yyps]]]m4_ifset([b4_parse_param], [, + b4_parse_param]))]) +b4_c_function_decl([b4_prefix[pstate_new]], [b4_prefix[pstate *]], + [[[void]], []]) +b4_c_function_decl([b4_prefix[pstate_delete]], [[void]], + [[b4_prefix[pstate *yyps]], [[yyps]]])[ +#endif +]]) +b4_percent_code_get([[provides]])[]dnl +])dnl b4_defines_if +m4_divert_pop(0) diff -Nru swftools-0.9.2+ds1/lib/as3/test swftools-0.9.1/lib/as3/test --- swftools-0.9.2+ds1/lib/as3/test 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/as3/test 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,320 @@ +#!/usr/bin/python +# +# test.py +# +# Run compiler unit tests +# +# 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 */ + +import sys +import os +import time +import subprocess +import marshal +import select +from optparse import OptionParser + +CMD_ARGS=[] +CMD = "./parser" +#CMD="as3compile" +CMD_ARGS=["-o","abc.swf"] + +def check(s): + row = None + ok = 0 + for line in s.split("\n"): + if line.startswith("[") and line.endswith("]"): + continue + if not line.strip(): + continue + if not line.startswith("ok"): + return 0 + if line.startswith("ok "): + if "/" not in line: + return 0 + i = line.index('/') + try: + nr,l = int(line[3:i]),int(line[i+1:]) + except ValueError: + return 0 + if nr<1 or nr>l: + return 0 + if not row: + row = [0]*l + elif l != len(row): + return 0 + if row[nr-1]: + return 0 + row[nr-1] = 1 + elif line == "ok": + ok = 1 + if ok: + return not row + if row: + return 0 not in row + return 0 + +def runcmd(cmd,args,wait): + #fo = os.tmpfile() + fi,fo = os.pipe() + fo = os.fdopen(fo, "wb") + p = subprocess.Popen([cmd] + args, executable=cmd, stdout=fo, stderr=fo) + ret = -1 + output = "" + for i in range(wait*10): + if fi in select.select([fi],[],[], 0.01)[0]: + output += os.read(fi, 8192) + if "[exit]" in output: + break + if "== by" in output: + ret = -33 + break + ret = p.poll() + if ret is not None: + if cmd == "valgrind": + # valgrind never returns true + ret = 0 + break + time.sleep(0.1) + else: + os.kill(p.pid, 9) + os.system("killall -9 %s >/dev/null 2>/dev/null" % cmd) + ret = -1 + fo.close() + + if fi in select.select([fi],[],[], 0.01)[0]: + output += os.read(fi, 8192) + + os.close(fi) + return ret,output + +class Cache: + def __init__(self, filename): + self.filename = filename + self.filename_milestone = filename+"_milestone" + try: + self.filename2status = marshal.load(open(self.filename, "rb")) + except IOError: + self.filename2status = {} + try: + self.milestone = marshal.load(open(self.filename_milestone, "rb")) + except IOError: + self.milestone = {} + + def parse_args(self): + parser = OptionParser() + parser.add_option("-d", "--diff", dest="diff", help="Only run tests that failed the last time",action="store_true") + parser.add_option("-a", "--all", dest="all", help="Run all tests (also tests expected to fail)",action="store_true") + parser.add_option("-t", "--tag", dest="tag", help="Mark the current pass/fail statistic as milestone",action="store_true") + parser.add_option("-m", "--valgrind", dest="valgrind", help="Run compiler through valgrind",action="store_true") + (options, args) = parser.parse_args() + + if args and args[0]=="add": + self.all = 1 + self.tag = 1 + self.milestone[args[1]] = "ok" + self.filename2status = self.milestone + self.save() + sys.exit(0) + + self.__dict__.update(options.__dict__) + self.runtime = 1 + if self.tag: + self.all = 1 + self.runtime = 3 # allow more time if we're tagging this state + + if self.valgrind: + global CMD,CMD_ARGS + CMD_ARGS = [CMD] + CMD_ARGS + CMD = "valgrind" + self.runtime = 20 # allow even more time for valgrind + + self.checknum=-1 + self.checkfile=None + if len(args): + try: + self.checknum = int(args[0]) + except ValueError: + self.checkfile = args[0] + + @staticmethod + def load(filename): + return Cache(filename) + + def save(self): + fi = open(self.filename, "wb") + marshal.dump(self.filename2status, fi) + fi.close() + if self.tag: + assert(self.all) + fi = open(self.filename_milestone, "wb") + marshal.dump(self.filename2status, fi) + fi.close() + + def highlight(self, nr, filename): + if self.checkfile and filename==self.checkfile: + return 1 + return self.checknum==nr + + def skip_file(self, nr, filename): + if self.checknum>=0 and nr!=self.checknum: + return 1 + if self.checkfile and filename!=self.checkfile: + return 1 + if not self.all and self.milestone.get(filename,"new")!="ok": + return 1 + if self.diff and self.filename2status(filename,"new")=="ok": + return 1 + return 0 + + def file_status(self, filename, status): + self.filename2status[filename] = status + +class TestBase: + def __init__(self, cache, nr, file, run): + self.cache = cache + self.nr = nr + self.dorun = run + self.file = file + self.flash_output = None + self.flash_error = None + self.compile_output = None + self.compile_error = None + + def compile(self): + try: os.unlink("abc.swf"); + except: pass + ret,output = runcmd(CMD,CMD_ARGS+[self.file],wait=cache.runtime) + self.compile_error = 0 + self.compile_output = output + self.exit_status = 0 + if ret: + self.compile_output += "\nExit status %d" % (-ret) + self.exit_status = -ret + self.compile_error = 1 + return 0 + if not os.path.isfile("abc.swf"): + self.compile_error = 1 + return 0 + return 1 + + def run(self): + ret,output = runcmd("flashplayer",[os.path.join(os.getcwd(),"abc.swf")],wait=cache.runtime) + os.system("killall flashplayer") + self.flash_output = output + + if not check(self.flash_output): + self.flash_error = 1 + return 0 + return 1 + + def doprint(self): + print self.r(str(self.nr),3)," ", + if self.compile_error: + if self.dorun: + if self.exit_status == 11: + print "crash"," - ", + else: + print "err "," - ", + else: + print "err "," ", + else: + print "ok ", + if self.dorun: + if not self.flash_error: + print "ok ", + else: + print "err", + else: + print " ", + print " ", + print self.file + + def doprintlong(self): + print self.nr, self.file + print "================================" + print "compile:", (self.compile_error and "error" or "ok") + print self.compile_output + if not self.dorun: + return + print "================================" + print "run:", (self.flash_error and "error" or "ok") + print self.flash_output + print "================================" + + def r(self,s,l): + if(len(s)>=l): + return s + return (" "*(l-len(s))) + s + def l(self,s,l): + if(len(s)>=l): + return s + return s + (" "*(l-len(s))) + +class Test(TestBase): + def __init__(self, cache, nr, file): + TestBase.__init__(self, cache, nr, file, run=1) + if self.compile() and self.run(): + cache.file_status(file, "ok") + else: + cache.file_status(file, "error") + +class ErrTest(TestBase): + def __init__(self, cache, nr, file): + TestBase.__init__(self, cache, nr, file, run=0) + if self.compile(): + cache.file_status(file, "error") + self.compile_error = True + else: + cache.file_status(file, "ok") + self.compile_error = False + +class Suite: + def __init__(self, cache, dir): + self.dir = dir + self.cache = cache + self.errtest = "err" in dir + def run(self, nr): + print "-"*40,"tests \""+self.dir+"\"","-"*40 + for file in sorted(os.listdir(self.dir)): + if not file.endswith(".as"): + continue + nr = nr + 1 + file = os.path.join(self.dir, file) + + if cache.skip_file(nr, file): + continue + + if self.errtest: + test = ErrTest(cache, nr, file) + else: + test = Test(cache, nr, file) + + if not cache.highlight(nr, file): + test.doprint() + else: + test.doprintlong() + return nr + +cache = Cache.load(".tests.cache") +cache.parse_args() + +nr = 0 +nr = Suite(cache, "err").run(nr) +nr = Suite(cache, "ok").run(nr) + +cache.save() diff -Nru swftools-0.9.2+ds1/lib/as3/tokenizer.lex swftools-0.9.1/lib/as3/tokenizer.lex --- swftools-0.9.2+ds1/lib/as3/tokenizer.lex 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/as3/tokenizer.lex 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,829 @@ +/* tokenizer.lex + + 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 +#include "../utf8.h" +#include "common.h" +#include "tokenizer.h" +#include "files.h" + +unsigned int as3_tokencount = 0; + +static void dbg(const char*format, ...) +{ + char buf[1024]; + int l; + va_list arglist; + if(as3_verbosity<3) + 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("(tokenizer) "); + printf("%s\n", buf); + fflush(stdout); +} + +#ifndef YY_CURRENT_BUFFER +#define YY_CURRENT_BUFFER yy_current_buffer +#endif + +static void*as3_buffer=0; +static int as3_buffer_pos=0; +static int as3_buffer_len=0; +void as3_file_input(FILE*fi) +{ + as3_in = fi; + as3_buffer = 0; +} +void as3_buffer_input(void*buffer, int len) +{ + if(!buffer) + syntaxerror("trying to parse zero bytearray"); + as3_buffer = buffer; + as3_buffer_len = len; + as3_buffer_pos = 0; + as3_in = 0; +} + +//#undef BEGIN +//#define BEGIN(x) {(yy_start) = 1 + 2 *x;dbg("entering state %d", x);} + +#define YY_INPUT(buf,result,max_size) { \ + if(!as3_buffer) { \ + errno=0; \ + while((result = fread(buf, 1, max_size, as3_in))==0 && ferror(as3_in)) \ + { if(errno != EINTR) {YY_FATAL_ERROR("input in flex scanner failed"); break;} \ + errno=0; clearerr(as3_in); \ + } \ + } else { \ + int to_read = max_size; \ + if(to_read + as3_buffer_pos > as3_buffer_len) \ + to_read = as3_buffer_len - as3_buffer_pos; \ + memcpy(buf, as3_buffer+as3_buffer_pos, to_read); \ + as3_buffer_pos += to_read; \ + result=to_read; \ + } \ +} + +void handleInclude(char*text, int len, char quotes) +{ + char*filename = 0; + if(quotes) { + char*p1 = strchr(text, '"'); + char*p2 = strrchr(text, '"'); + if(!p1 || !p2 || p1==p2) { + syntaxerror("Invalid include in line %d\n", current_line); + } + *p2 = 0; + filename = strdup(p1+1); + } else { + int i1=0,i2=len; + // find start + while(!strchr(" \n\r\t\xa0", text[i1])) i1++; + // strip + while(strchr(" \n\r\t\xa0", text[i1])) i1++; + while(strchr(" \n\r\t\xa0", text[i2-1])) i2--; + if(i2!=len) text[i2]=0; + filename = strdup(&text[i1]); + } + + char*fullfilename = find_file(filename, 1); + enter_file2(filename, fullfilename, YY_CURRENT_BUFFER); + yyin = fopen(fullfilename, "rb"); + if (!yyin) { + syntaxerror("Couldn't open include file \"%s\"\n", fullfilename); + } + + yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) ); + //BEGIN(DEFAULT); keep context +} + +static int do_unescape(const char*s, const char*end, char*n) +{ + char*o = n; + int len=0; + while(s256) + syntaxerror("octal number out of range (0-255): %d", num); + if(o) o[len] = num;len++; + continue; + } + case 'x': case 'u': { + int max=2; + char bracket = 0; + char unicode = 0; + if(*s == 'u') { + max = 6; + unicode = 1; + } + s++; + if(s==end) syntaxerror("invalid \\u or \\x at end of string"); + if(*s == '{') { + s++; + if(s==end) syntaxerror("invalid \\u{ at end of string"); + bracket=1; + } + unsigned int num=0; + int nr = 0; + while(strchr("0123456789abcdefABCDEF", *s) && (bracket || nr < max) && s='0' && *s<='9') num |= *s - '0'; + if(*s>='a' && *s<='f') num |= *s - 'a' + 10; + if(*s>='A' && *s<='F') num |= *s - 'A' + 10; + nr++; + s++; + } + if(bracket) { + if(*s=='}' && s256) + syntaxerror("byte out of range (0-255): %d", num); + if(o) o[len] = num;len++; + } + break; + } + default: { + if(o) { + o[len+0] = '\\'; + o[len+1] = *s; + } + s++; + len+=2; + break; + } + } + } + if(o) o[len]=0; + return len; +} + +static string_t string_unescape(const char*in, int l) +{ + const char*s = in; + const char*end = &in[l]; + + int len = do_unescape(s, end, 0); + char*n = (char*)malloc(len+1); + do_unescape(s, end, n); + string_t out = string_new(n, len); + return out; +} + +static void handleCData(char*s, int len) +{ + a3_lval.str.str = s+9; // + a3_lval.str.str = strdup_n(a3_lval.str.str, a3_lval.str.len); +} + +static void handleRaw(char*s, int len) +{ + a3_lval.str.len = len; + a3_lval.str.str = strdup_n(s, a3_lval.str.len); +} + +static void handleString(char*s, int len) +{ + if(s[0]=='"') { + if(s[len-1]!='"') syntaxerror("String doesn't end with '\"'"); + s++;len-=2; + } + else if(s[0]=='\'') { + if(s[len-1]!='\'') syntaxerror("String doesn't end with '\"'"); + s++;len-=2; + } + else syntaxerror("String incorrectly terminated"); + + a3_lval.str = string_unescape(s, len); +} + + +char start_of_expression; + +static inline int m(int type) +{ + a3_lval.token = type; + return type; +} + +static char numberbuf[64]; +static char*nrbuf() +{ + if(yyleng>sizeof(numberbuf)-1) + syntaxerror("decimal number overflow"); + char*s = numberbuf; + memcpy(s, yytext, yyleng); + s[yyleng]=0; + return s; +} + +static inline int setint(int v) +{ + a3_lval.number_int = v; + return T_INT; +} +static inline int setfloat(double v) +{ + a3_lval.number_float = v; + return T_FLOAT; +} + +static inline int handlefloat() +{ + char*s = nrbuf(); + a3_lval.number_float = atof(s); + return T_FLOAT; +} + +static inline int handleint() +{ + char*s = nrbuf(); + char l = (yytext[0]=='-'); + + //char*max = l?"1073741824":"2147483647"; + char*max = l?"2147483648":"2147483647"; + + if(yyleng-l>10) { + as3_softwarning("integer overflow: %s (converted to Number)", s); + return handlefloat(); + } + if(yyleng-l==10) { + int t; + for(t=0;tmax[t]) { + as3_softwarning("integer overflow: %s (converted to Number)", s); + return handlefloat(); + } + else if(yytext[l+t]='0' && c<='9') + d+=(c&15)*base; + else if((c>='a' && c<='f') || (c>='A' && c<='F')) + d+=((c&0x0f)+9)*base; + } + return setfloat(d); +} +static inline int handlehex() +{ + char l = (yytext[0]=='-')+2; + int len = yyleng; + + if(len-l>8) { + char*s = nrbuf(); + syntaxerror("integer overflow %s", s); + } + + int t; + unsigned int v = 0; + for(t=l;t='0' && c<='9') + v|=(c&15); + else if((c>='a' && c<='f') || (c>='A' && c<='F')) + v|=(c&0x0f)+9; + } + if(l && v>=0x80000000) { + char*s = nrbuf(); + as3_softwarning("integer overflow: %s (converted to Number)", s); + return setfloat(v); + } + if(!l && v>0x7fffffff) { + char*s = nrbuf(); + as3_softwarning("integer overflow: %s (converted to Number)", s); + return setfloat(v); + } + + if(l==3) { + return setint(-(int)v); + } else { + return setint(v); + } +} + +void handleLabel(char*text, int len) +{ + int t; + for(t=len-1;t>=0;--t) { + if(text[t]!=' ' && + text[t]!=':') + break; + } + char*s = malloc(t+1); + memcpy(s, yytext, t); + s[t]=0; + a3_lval.id = s; +} + +static int handleregexp() +{ + char*s = malloc(yyleng); + int len=yyleng-1; + memcpy(s, yytext+1, len); + s[len] = 0; + int t; + for(t=len;t>=0;--t) { + if(s[t]=='/') { + s[t] = 0; + break; + } + } + a3_lval.regexp.pattern = s; + if(t==len) { + a3_lval.regexp.options = 0; + } else { + a3_lval.regexp.options = s+t+1; + } + return T_REGEXP; +} + +void initialize_scanner(); +#define YY_USER_INIT initialize_scanner(); + +/* count the number of lines+columns consumed by this token */ +static inline void l() { + int t; + for(t=0;t]|(-/[^-])|(--/[^>]))*--> + +//{XMLCOMMENT} + +%} + +%s REGEXPOK +%s BEGINNING +%s DEFAULT +%x XMLTEXT +%x XML + +X1 parsing identifiers with a non unicode lexer is a knightmare we have to skip all possible +X2 combinations of byte order markers or utf8 space chars and i dont quite like the fact that +X3 lex doesnt support proper comments in this section either... +X4 {NAME_HEAD}{NAME_TAIL} + +NAME_NOC2EF [a-zA-Z_\x80-\xc1\xc3-\xee\xf0-\xff] +NAME_EF [\xef][a-zA-Z0-9_\\\x80-\xba\xbc-\xff] +NAME_C2 [\xc2][a-zA-Z0-9_\\\x80-\x9f\xa1-\xff] +NAME_EFBB [\xef][\xbb][a-zA-Z0-9_\\\x80-\xbe\xc0-\xff] +NAME_TAIL [a-zA-Z_0-9\\\x80-\xff]* +NAME_HEAD (({NAME_NOC2EF})|({NAME_EF})|({NAME_C2})|({NAME_EFBB})) +NAME {NAME_HEAD}{NAME_TAIL} + +_ [^a-zA-Z0-9_\\\x80-\xff] + +HEXINT 0x[a-zA-Z0-9]+ +HEXFLOAT 0x[a-zA-Z0-9]*\.[a-zA-Z0-9]* +INT [0-9]+ +FLOAT ([0-9]+(\.[0-9]*)?|\.[0-9]+)(e[0-9]+)? + +HEXWITHSIGN [+-]?({HEXINT}) +HEXFLOATWITHSIGN [+-]?({HEXFLOAT}) +INTWITHSIGN [+-]?({INT}) +FLOATWITHSIGN [+-]?({FLOAT}) + +CDATA ])*\]*\]\]\> +XMLCOMMENT +XML <[^>]+{S}> +XMLID [A-Za-z0-9_\x80-\xff]+([:][A-Za-z0-9_\x80-\xff]+)? +XMLSTRING ["][^"]*["] + +STRING ["](\\[\x00-\xff]|[^\\"\n])*["]|['](\\[\x00-\xff]|[^\\'\n])*['] +S ([ \n\r\t\xa0]|[\xc2][\xa0]) +MULTILINE_COMMENT [/][*]+([*][^/]|[^/*]|[^*][/]|[\x00-\x1f])*[*]+[/] +SINGLELINE_COMMENT \/\/[^\n\r]*[\n\r] +REGEXP [/]([^/\n]|\\[/])*[/][a-zA-Z]* +%% + + +{SINGLELINE_COMMENT} {l(); /* single line comment */} +{MULTILINE_COMMENT} {l(); /* multi line comment */} +[/][*] {syntaxerror("syntax error: unterminated comment", yytext);} + +^include{S}+{STRING}{S}*/\n {l();handleInclude(yytext, yyleng, 1);} +^include{S}+[^" \t\xa0\r\n][\x20-\xff]*{S}*/\n {l();handleInclude(yytext, yyleng, 0);} +{STRING} {l(); BEGIN(DEFAULT);handleString(yytext, yyleng);return T_STRING;} +{CDATA} {l(); BEGIN(DEFAULT);handleCData(yytext, yyleng);return T_STRING;} + +{ +{XMLCOMMENT} {l(); BEGIN(DEFAULT);handleRaw(yytext, yyleng);return T_STRING;} +} + +{ +{XMLSTRING} {l(); handleRaw(yytext, yyleng);return T_STRING;} +[{] {c(); BEGIN(REGEXPOK);return m('{');} +[<] {c(); return m('<');} +[/] {c(); return m('/');} +[>] {c(); return m('>');} +[=] {c(); return m('=');} +{XMLID} {c(); handleRaw(yytext, yyleng);return T_IDENTIFIER;} +{S} {l(); handleRaw(yytext, yyleng);return T_STRING;} +<> {syntaxerror("unexpected end of file");} +} + +{ +[^<>{]+ {l(); handleRaw(yytext, yyleng);return T_STRING;} +[{] {c(); BEGIN(REGEXPOK);return m('{');} +[<] {c(); BEGIN(XML);return m('<');} +[>] {c(); return m('>');} +{XMLCOMMENT} {l(); handleRaw(yytext, yyleng);return T_STRING;} +{CDATA} {l(); handleRaw(yytext, yyleng);return T_STRING;} +<> {syntaxerror("unexpected end of file");} +} + +{ +{REGEXP} {c(); BEGIN(DEFAULT);return handleregexp();} +{HEXWITHSIGN}/{_} {c(); BEGIN(DEFAULT);return handlehex();} +{HEXFLOATWITHSIGN}/{_} {c(); BEGIN(DEFAULT);return handlehexfloat();} +{INTWITHSIGN}/{_} {c(); BEGIN(DEFAULT);return handleint();} +{FLOATWITHSIGN}/{_} {c(); BEGIN(DEFAULT);return handlefloat();} +} + +[\{] {c(); BEGIN(REGEXPOK);return m(T_DICTSTART);} +[\{] {c(); BEGIN(DEFAULT); return m('{');} + +\xef\xbb\xbf {/* utf 8 bom (0xfeff) */} +{S} {l();} + +{HEXINT}/{_} {c(); BEGIN(DEFAULT);return handlehex();} +{HEXFLOAT}/{_} {c(); BEGIN(DEFAULT);return handlehexfloat();} +{INT}/{_} {c(); BEGIN(DEFAULT);return handleint();} +{FLOAT}/{_} {c(); BEGIN(DEFAULT);return handlefloat();} +NaN {c(); BEGIN(DEFAULT);return m(KW_NAN);} + +3rr0r {/* for debugging: generates a tokenizer-level error */ + syntaxerror("3rr0r");} + +{NAME}{S}*:{S}*for/{_} {l();BEGIN(DEFAULT);handleLabel(yytext, yyleng-3);return T_FOR;} +{NAME}{S}*:{S}*do/{_} {l();BEGIN(DEFAULT);handleLabel(yytext, yyleng-2);return T_DO;} +{NAME}{S}*:{S}*while/{_} {l();BEGIN(DEFAULT);handleLabel(yytext, yyleng-5);return T_WHILE;} +{NAME}{S}*:{S}*switch/{_} {l();BEGIN(DEFAULT);handleLabel(yytext, yyleng-6);return T_SWITCH;} +default{S}xml {l();BEGIN(DEFAULT);return m(KW_DEFAULT_XML);} +for {c();BEGIN(DEFAULT);a3_lval.id="";return T_FOR;} +do {c();BEGIN(DEFAULT);a3_lval.id="";return T_DO;} +while {c();BEGIN(DEFAULT);a3_lval.id="";return T_WHILE;} +switch {c();BEGIN(DEFAULT);a3_lval.id="";return T_SWITCH;} + +[&][&] {c();BEGIN(REGEXPOK);return m(T_ANDAND);} +[|][|] {c();BEGIN(REGEXPOK);return m(T_OROR);} +[!][=] {c();BEGIN(REGEXPOK);return m(T_NE);} +[!][=][=] {c();BEGIN(REGEXPOK);return m(T_NEE);} +[=][=][=] {c();BEGIN(REGEXPOK);return m(T_EQEQEQ);} +[=][=] {c();BEGIN(REGEXPOK);return m(T_EQEQ);} +[>][=] {c();BEGIN(REGEXPOK);return m(T_GE);} +[<][=] {c();BEGIN(REGEXPOK);return m(T_LE);} +[-][-] {c();BEGIN(DEFAULT);return m(T_MINUSMINUS);} +[+][+] {c();BEGIN(DEFAULT);return m(T_PLUSPLUS);} +[+][=] {c();BEGIN(REGEXPOK);return m(T_PLUSBY);} +[\^][=] {c();BEGIN(REGEXPOK);return m(T_XORBY);} +[-][=] {c();BEGIN(REGEXPOK);return m(T_MINUSBY);} +[/][=] {c();BEGIN(REGEXPOK);return m(T_DIVBY);} +[%][=] {c();BEGIN(REGEXPOK);return m(T_MODBY);} +[*][=] {c();BEGIN(REGEXPOK);return m(T_MULBY);} +[|][=] {c();BEGIN(REGEXPOK);return m(T_ORBY);} +[&][=] {c();BEGIN(REGEXPOK);return m(T_ANDBY);} +[>][>][=] {c();BEGIN(REGEXPOK);return m(T_SHRBY);} +[<][<][=] {c();BEGIN(REGEXPOK);return m(T_SHLBY);} +[>][>][>][=] {c();BEGIN(REGEXPOK);return m(T_USHRBY);} +[<][<] {c();BEGIN(REGEXPOK);return m(T_SHL);} +[>][>][>] {c();BEGIN(REGEXPOK);return m(T_USHR);} +[>][>] {c();BEGIN(REGEXPOK);return m(T_SHR);} +\.\.\. {c();BEGIN(REGEXPOK);return m(T_DOTDOTDOT);} +\.\. {c();BEGIN(REGEXPOK);return m(T_DOTDOT);} +\. {c();BEGIN(REGEXPOK);return m('.');} +:: {c();BEGIN(REGEXPOK);return m(T_COLONCOLON);} +: {c();BEGIN(REGEXPOK);return m(':');} +instanceof {c();BEGIN(REGEXPOK);return m(KW_INSTANCEOF);} +implements {c();BEGIN(REGEXPOK);return m(KW_IMPLEMENTS);} +interface {c();BEGIN(DEFAULT);return m(KW_INTERFACE);} +protected {c();BEGIN(DEFAULT);return m(KW_PROTECTED);} +namespace {c();BEGIN(DEFAULT);return m(KW_NAMESPACE);} +undefined {c();BEGIN(DEFAULT);return m(KW_UNDEFINED);} +arguments {c();BEGIN(DEFAULT);return m(KW_ARGUMENTS);} +continue {c();BEGIN(DEFAULT);return m(KW_CONTINUE);} +override {c();BEGIN(DEFAULT);return m(KW_OVERRIDE);} +internal {c();BEGIN(DEFAULT);return m(KW_INTERNAL);} +function {c();BEGIN(DEFAULT);return m(KW_FUNCTION);} +finally {c();BEGIN(DEFAULT);return m(KW_FINALLY);} +default {c();BEGIN(DEFAULT);return m(KW_DEFAULT);} +package {c();BEGIN(DEFAULT);return m(KW_PACKAGE);} +private {c();BEGIN(DEFAULT);return m(KW_PRIVATE);} +dynamic {c();BEGIN(DEFAULT);return m(KW_DYNAMIC);} +extends {c();BEGIN(DEFAULT);return m(KW_EXTENDS);} +delete {c();BEGIN(REGEXPOK);return m(KW_DELETE);} +return {c();BEGIN(REGEXPOK);return m(KW_RETURN);} +public {c();BEGIN(DEFAULT);return m(KW_PUBLIC);} +native {c();BEGIN(DEFAULT);return m(KW_NATIVE);} +static {c();BEGIN(DEFAULT);return m(KW_STATIC);} +import {c();BEGIN(REGEXPOK);return m(KW_IMPORT);} +typeof {c();BEGIN(REGEXPOK);return m(KW_TYPEOF);} +throw {c();BEGIN(REGEXPOK);return m(KW_THROW);} +class {c();BEGIN(DEFAULT);return m(KW_CLASS);} +const {c();BEGIN(DEFAULT);return m(KW_CONST);} +catch {c();BEGIN(DEFAULT);return m(KW_CATCH);} +final {c();BEGIN(DEFAULT);return m(KW_FINAL);} +false {c();BEGIN(DEFAULT);return m(KW_FALSE);} +break {c();BEGIN(DEFAULT);return m(KW_BREAK);} +super {c();BEGIN(DEFAULT);return m(KW_SUPER);} +each {c();BEGIN(DEFAULT);return m(KW_EACH);} +void {c();BEGIN(DEFAULT);return m(KW_VOID);} +true {c();BEGIN(DEFAULT);return m(KW_TRUE);} +null {c();BEGIN(DEFAULT);return m(KW_NULL);} +else {c();BEGIN(DEFAULT);return m(KW_ELSE);} +case {c();BEGIN(REGEXPOK);return m(KW_CASE);} +with {c();BEGIN(REGEXPOK);return m(KW_WITH);} +use {c();BEGIN(REGEXPOK);return m(KW_USE);} +new {c();BEGIN(REGEXPOK);return m(KW_NEW);} +get {c();BEGIN(DEFAULT);return m(KW_GET);} +set {c();BEGIN(DEFAULT);return m(KW_SET);} +var {c();BEGIN(DEFAULT);return m(KW_VAR);} +try {c();BEGIN(DEFAULT);return m(KW_TRY);} +is {c();BEGIN(REGEXPOK);return m(KW_IS) ;} +in {c();BEGIN(REGEXPOK);return m(KW_IN) ;} +if {c();BEGIN(DEFAULT);return m(KW_IF) ;} +as {c();BEGIN(REGEXPOK);return m(KW_AS);} +$?{NAME} {c();BEGIN(DEFAULT);return handleIdentifier();} + +[\]\}*] {c();BEGIN(DEFAULT);return m(yytext[0]);} +[+-\/^~@$!%&\(=\[|?:;,<>] {c();BEGIN(REGEXPOK);return m(yytext[0]);} +[\)\]] {c();BEGIN(DEFAULT);return m(yytext[0]);} + +{ +. {tokenerror();} +} +<> {l(); + void*b = leave_file(); + if (!b) { + yyterminate(); + yy_delete_buffer(YY_CURRENT_BUFFER); + return m(T_EOF); + } else { + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(b); + } + } + +%% + +int yywrap() +{ + return 1; +} + +static int tokenerror() +{ + char c1=yytext[0]; + char buf[128]; + buf[0] = yytext[0]; + int t; + for(t=1;t<128;t++) { + char c = buf[t]=input(); + if(c=='\n' || c==EOF) { + buf[t] = 0; + break; + } + } + if(c1>='0' && c1<='9') + syntaxerror("syntax error: %s (identifiers must not start with a digit)"); + else + syntaxerror("syntax error [state=%d]: %s", (yy_start-1)/2, buf); + printf("\n"); + exit(1); + yyterminate(); +} + + +static char mbuf[256]; +char*token2string(enum yytokentype nr, YYSTYPE v) +{ + if(nr==T_STRING) { + char*s = malloc(v.str.len+10); + strcpy(s, ""); + memcpy(s+8, v.str.str, v.str.len); + sprintf(s+8+v.str.len, " (%d bytes)", v.str.len); + return s; + } + else if(nr==T_REGEXP) { + char*s = malloc(strlen(v.regexp.pattern)+10); + sprintf(s, "%s", v.regexp.pattern); + return s; + } + else if(nr==T_IDENTIFIER) { + char*s = malloc(strlen(v.id)+10); + sprintf(s, "%s", v.id); + return s; + } + else if(nr==T_INT) return ""; + else if(nr==T_UINT) return ""; + else if(nr==T_FLOAT) return ""; + else if(nr==T_EOF) return "***END***"; + else if(nr==T_GE) return ">="; + else if(nr==T_LE) return "<="; + else if(nr==T_MINUSMINUS) return "--"; + else if(nr==T_PLUSPLUS) return "++"; + else if(nr==KW_IMPLEMENTS) return "implements"; + else if(nr==KW_INTERFACE) return "interface"; + else if(nr==KW_NAMESPACE) return "namespace"; + else if(nr==KW_PROTECTED) return "protected"; + else if(nr==KW_OVERRIDE) return "override"; + else if(nr==KW_INTERNAL) return "internal"; + else if(nr==KW_FUNCTION) return "function"; + else if(nr==KW_PACKAGE) return "package"; + else if(nr==KW_PRIVATE) return "private"; + else if(nr==KW_BOOLEAN) return "Boolean"; + else if(nr==KW_DYNAMIC) return "dynamic"; + else if(nr==KW_EXTENDS) return "extends"; + else if(nr==KW_PUBLIC) return "public"; + else if(nr==KW_NATIVE) return "native"; + else if(nr==KW_STATIC) return "static"; + else if(nr==KW_IMPORT) return "import"; + else if(nr==KW_NUMBER) return "number"; + else if(nr==KW_CLASS) return "class"; + else if(nr==KW_CONST) return "const"; + else if(nr==KW_FINAL) return "final"; + else if(nr==KW_FALSE) return "False"; + else if(nr==KW_TRUE) return "True"; + else if(nr==KW_UINT) return "uint"; + else if(nr==KW_NULL) return "null"; + else if(nr==KW_ELSE) return "else"; + else if(nr==KW_USE) return "use"; + else if(nr==KW_INT) return "int"; + else if(nr==KW_NEW) return "new"; + else if(nr==KW_GET) return "get"; + else if(nr==KW_SET) return "set"; + else if(nr==KW_VAR) return "var"; + else if(nr==KW_IS) return "is"; + else if(nr==KW_AS) return "as"; + else { + sprintf(mbuf, "%d", nr); + return mbuf; + } +} + +void tokenizer_begin_xml() +{ + dbg("begin reading xml"); + BEGIN(XML); +} +void tokenizer_begin_xmltext() +{ + dbg("begin reading xml text"); + BEGIN(XMLTEXT); +} +void tokenizer_end_xmltext() +{ + dbg("end reading xml text"); + BEGIN(XML); +} +void tokenizer_end_xml() +{ + dbg("end reading xml"); + BEGIN(DEFAULT); +} + +void initialize_scanner() +{ + BEGIN(BEGINNING); +} + + diff -Nru swftools-0.9.2+ds1/lib/bladeenc/AUTHORS swftools-0.9.1/lib/bladeenc/AUTHORS --- swftools-0.9.2+ds1/lib/bladeenc/AUTHORS 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/AUTHORS 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,83 @@ +BladeEnc was started by Tord Jansson as a project to make a decent, free +encoder for high-bitrate MP3 encoding, heavily based on the ISO source code +for a reference encoder. Since then it has developed into a free software +project (Open Source) with many contributors: + +=============================================================================== +Project initiator and maintainer: +=============================================================================== +Tord Jansson + +=============================================================================== +Major contributors: +=============================================================================== +Andre' Piotrowski Numerous improvements to the MP3 encoding routines. +Jeff Squyres Maintains MPI port (now discontinued), various contributions. +Petteri Kamppuri Maintains MacOS port. + + + +=============================================================================== +Contributors: +=============================================================================== +Mikael Kjellström +Kevin Doherty +Milan Hodoscek +Wesley Hosking +Jon Watte +Dmitri Kalintsev +William Thompson +Olaf Pueschel +Marc Schefer +Lennart Börjeson +John DuBois +Jeremy Prior +Frans E. van Dorsselaer +Roger Fujii +Robert Schlabbach +Marco Amrein +Vitor Sessak +Serg 'Ice' Tsyganenko +Rich West +Ben Slusky +Simon Burge +Brad +Matt Craven +Paul Cantrell +Petter Reinholdtsen +Paul Martin +Troy Engel +Chris DeLise +Sadruddin Rejeb +Mauro Manfrin +Rob Ekl +Jeffrey Hawk +Stephen from Minnesota + +=============================================================================== +People who helped port BladeEnc to different architectures before it went +Open Source: +=============================================================================== +Trevor Phillips, Zac Livingston, Jon Coyle, Alexey Marinichev +Mikael Kjellström, Steve Burns, Markus Ridinger, Giao Nguyen, Joel Fredrikson +Marca Registrada, Rob Braun. + + +=============================================================================== +The ISO reference sourcecode credits the following people as its developers +and contributors: +=============================================================================== +Bill Aspromonte, Shaun Astarabadi, R. Bittner, Karlheinz Brandenburg +W. Joseph Carter, Jack Chang, Mike Coleman, Johnathan Devine, Ernst Eberlein +Dan Ellis, Peter Farrett, Jean-Georges Fritsch, Vlad Fruchter, Hendrik Fuchs +Bernhard Grill, Amit Gulati, Munsi Haque, Chuck Hsiao, Toshiyuki Ishino +Masahiro Iwadare, Earl Jennings, James Johnston, Leon v.d. Kerkhof, Don Lee +Mike Li, Yu-Tang Lin, Soren Neilsen, Simao F. Campos Neto,Mark Paley +Davis Pan, Tan Ah Peng, Kevin Peterson, Juan Pineda, Ernst F. Schroeder +Peter Siebert, Jens Spille, Sam Stewart, Al Tabayoyon, Kathy Wang +Franz-Otto Witte, Douglas Wong. + + + +IF YOU BELIEVE THAT I HAVE MISSED SOME CONTRIBUTOR IN THIS LIST, PLEASE E-MAIL +ME (tord.jansson@swipnet.se) AND I'LL CORRECT ANY MISSTAKE! diff -Nru swftools-0.9.2+ds1/lib/bladeenc/codec.c swftools-0.9.1/lib/bladeenc/codec.c --- swftools-0.9.2+ds1/lib/bladeenc/codec.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/codec.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,432 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ CHANGES ------------ + + 2000-11-22 Andre Piotrowski + + - big fix: module - original dist10 error - l3_sb_sample has to be of type 'L3SBS' not 'SBS'. + - bug fix: codecInit() - don't reset fInit-huffman_read_flag - read_huffcodetab() is a memory eater! + + 2000-12-11 ap + + - reformatted + - speed up: use single buffer +*/ + +#include +#include + +#include "common.h" +#include "l3psy.h" +#include "mdct.h" +#include "reservoir.h" +#include "formatbitstream2.h" +#include "l3bitstream.h" +#include "loop.h" +#include "encoder.h" +#include "codec.h" + + + + + +extern int fInit_fft; + + + + + +/************************************************************************/ + +#define SAMPLES_PER_FRAME 1152 + +static L3SBS l3_sb_sample; + +static layer info; + + + +#if ORG_BUFFERS +static short buffer[2][1152]; +/* static float snr32[32]; */ +static short sam[2][2048]; +#else +static FLOAT buffer[2][2048]; +static int buffer_idx; +#endif + + + +static int whole_SpF; + +static double frac_SpF, slot_lag; + +static int stereo, error_protection; + +static III_side_info_t l3_side; +static CodecInitOut sOut; + +static frame_params fr_ps; + + + +char *pEncodedOutput; +int outputBit; + +volatile double avg_slots_per_frame; + + + + + +/*____ codecInit() ____________________________________________________________*/ + +CodecInitOut *codecInit (CodecInitIn *psIn) +{ + int j; + + /* Read psIn */ + + switch (psIn->frequency) + { + case 48000: info.sampling_frequency = 1; break; + case 44100: info.sampling_frequency = 0; break; + case 32000: info.sampling_frequency = 2; break; + default : return FALSE; + } + + switch (psIn->mode) + { + case 0: info.mode = MPG_MD_STEREO ; info.mode_ext = 0; break; + case 2: info.mode = MPG_MD_DUAL_CHANNEL; info.mode_ext = 0; break; + case 3: info.mode = MPG_MD_MONO ; info.mode_ext = 0; break; + default: return FALSE; + } + + j = 0; + while (j < 15 && bitratex[1][j] != psIn->bitrate) + j++; + info.bitrate_index = j; + + info.version = 1; /* Default: MPEG-1 */ + info.emphasis = psIn->emphasis; + info.extension = psIn->fPrivate; + info.copyright = psIn->fCopyright; + info.original = psIn->fOriginal; + info.error_protection = psIn->fCRC; + + +/*_______ Static-fix _______________*/ + + + fInit_mdct_sub = 0; + fInit_mdct = 0; + + fInit_fft = 0; + + fInit_iteration_loop = 0; +/* DON'T DO THAT ALL THE TIME + fInit_huffman_read_flag = 0; +*/ + + fixStatic_loop(); + + l3_side.main_data_begin = 0; + fixStatic_reservoir(); + + +/*___________________________________*/ + + psycho_anal_init (psIn->frequency); + initWindowFilterSubband (); + initFormatBitstream (); + +/* clear buffers */ + memset ((char *) l3_sb_sample, 0, sizeof(l3_sb_sample)); + memset((char *) buffer, 0, sizeof(buffer)); +/* memset((char *) snr32, 0, sizeof(snr32));*/ +#if ORG_BUFFERS + memset((char *) sam, 0, sizeof(sam)); +#endif + + + + fr_ps.header = &info; + fr_ps.tab_num = -1; /* no table loaded */ + fr_ps.alloc = NULL; + fr_ps.actual_mode = info.mode; + fr_ps.stereo = (info.mode == MPG_MD_MONO) ? 1 : 2; + fr_ps.sblimit = SBLIMIT; + fr_ps.jsbound = SBLIMIT; + + + stereo = fr_ps.stereo; + error_protection = info.error_protection; + + avg_slots_per_frame = + ((double) SAMPLES_PER_FRAME / s_freq[1][info.sampling_frequency]) * + ((double) bitratex[1][info.bitrate_index] / 8.0); + whole_SpF = (int) avg_slots_per_frame; + frac_SpF = avg_slots_per_frame - (double) whole_SpF; + slot_lag = -frac_SpF; + +/* if (frac_SpF == 0) + info.padding = 0; +*/ + genNoisePowTab(); + +/*________________________*/ + + + if( stereo != 2 ) + sOut.nSamples = SAMPLES_PER_FRAME; + else + sOut.nSamples = SAMPLES_PER_FRAME*2; + + sOut.bufferSize = 2048; + + return &sOut; /* How many samples we want in each chunk... */ +} + + + + + +/*____ codecEncodeChunk() _____________________________________________________*/ + +unsigned int codecEncodeChunk +( + int nSamples, + short *pSamples, + char *pDest +) +{ + static double xr[2][2][576]; + static double xr_dec[2][2][576]; + static double pe[2][2]; + static int l3_enc[2][2][576]; + static III_psy_ratio ratio; + static III_scalefac_t scalefac; + int gr, ch; + int mean_bits, sideinfo_len; + int bitsPerFrame; + int j; + +/* + static int fFirst = TRUE; + + if (fFirst) + { + memset ((char *) &xr , 0, sizeof(xr)); + memset ((char *) &xr_dec , 0, sizeof(xr_dec)); + memset ((char *) &pe , 0, sizeof(pe)); + memset ((char *) &l3_enc , 0, sizeof(l3_enc)); + memset ((char *) &ratio , 0, sizeof(ratio)); + memset ((char *) &l3_side , 0, sizeof(l3_side)); + memset ((char *) &scalefac, 0, sizeof(scalefac)); + + fFirst = FALSE; + } +*/ + + +/* rebuffer audio */ + +#if ORG_BUFFERS + rebuffer_audio (buffer, pSamples, nSamples, stereo); +#else + rebuffer_audio (pSamples, buffer, &buffer_idx, nSamples, stereo); +#endif + + +/* psychoacoustic model */ + + for (gr = 0; gr < 2; gr++) + for (ch = 0; ch < stereo; ch++) + psycho_anal + ( +#if ORG_BUFFERS + &buffer[ch][gr*576], + &sam[ch][0], +#else + buffer[ch], + (buffer_idx+gr*576) & 2047, +#endif + ch, + 3, + /*snr32,*/ + &ratio.l[gr][ch][0], + &ratio.s[gr][ch][0], + &pe[gr][ch], + &l3_side.gr[gr].ch[ch].tt + ); + + +/* polyphase filtering */ + + for (gr = 0; gr < 2; gr++) + { + int gr_plus_1 = gr_idx[gr+1]; + + for (ch = 0; ch < stereo; ch++) + { + for (j = 0; j < 18; j++) + { + windowFilterSubband + ( +#if ORG_BUFFERS + &buffer[ch][gr*18*32+32*j], + ch, +#else + buffer[ch], + (buffer_idx+768-480+gr*18*32+32*j) & 2047, +#endif + l3_sb_sample[ch][gr_plus_1][j] + ); + } + } + } + + +/* apply mdct to the polyphase outputs */ + + mdct_sub (&l3_sb_sample, xr, stereo, &l3_side, 2); + + + pEncodedOutput = pDest; + outputBit = 8; + pEncodedOutput[0] = 0; + + + if (frac_SpF != 0) + { + if (slot_lag > (frac_SpF-1.0)) + { + slot_lag -= frac_SpF; + info.padding = 0; + } + else + { + info.padding = 1; + slot_lag += (1-frac_SpF); + } + } + + bitsPerFrame = 8 * whole_SpF + (info.padding * 8); + + +/* determine the mean bitrate for main data */ + + sideinfo_len = 32; + + if (stereo == 1) + sideinfo_len += 136; + else + sideinfo_len += 256; + + if (info.error_protection) + sideinfo_len += 16; + + mean_bits = (bitsPerFrame - sideinfo_len) / 2; + + +/* bit and noise allocation */ + + iteration_loop + ( + pe, + xr, + &ratio, + &l3_side, + l3_enc, + mean_bits, + stereo, + xr_dec, + &scalefac, + &fr_ps, + 0, + bitsPerFrame + ); + + +/* write the frame to the bitstream */ + + III_format_bitstream + ( + bitsPerFrame, + &fr_ps, + l3_enc, + &l3_side, + &scalefac, + xr, + NULL, + 0 + ); + + + return pEncodedOutput - pDest; +} + + + + + +/*____ codecExit() ____________________________________________________________*/ + +unsigned int codecExit (char *pDest) +{ + pEncodedOutput = pDest; + outputBit = 8; + pEncodedOutput[0] = 0; + + psycho_anal_exit (); + exitFormatBitstream (); + III_FlushBitstream (); + + return pEncodedOutput - pDest; +} + + + + + +/*____ codecFlush() _________________________________________________________*/ + +unsigned int codecFlush (char *pDest) +{ + pEncodedOutput = pDest; + outputBit = 8; + pEncodedOutput[0] = 0; + + flushFrame (); + + whole_SpF = (int) avg_slots_per_frame; + frac_SpF = avg_slots_per_frame - (double) whole_SpF; + slot_lag = -frac_SpF; + + l3_side.main_data_begin = 0; + fixStatic_reservoir (); + + return pEncodedOutput - pDest; +} + + + diff -Nru swftools-0.9.2+ds1/lib/bladeenc/codec.h swftools-0.9.1/lib/bladeenc/codec.h --- swftools-0.9.2+ds1/lib/bladeenc/codec.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/codec.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,65 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression. + + This file doesn't contain any of the ISO reference code and + is copyright Tord Jansson (tord.jansson@swipnet.se). + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ CHANGES ------------ + + 2000-12-10 Andre Piotrowski + + - reformatted +*/ + +#ifndef __CODEC__ +#define __CODEC__ + + + + + +typedef struct + { + int frequency; /* 48000, 44100 and 32000 allowed. */ + int mode; /* 0 = Stereo, 2 = Dual Channel, 3 = Mono */ + int bitrate; + int emphasis; /* 0 = None, 1 = 50/15 microsec, 3 = CCITT J.17 */ + int fPrivate; + int fCRC; + int fCopyright; + int fOriginal; + } CodecInitIn; + + +typedef struct + { + int nSamples; + int bufferSize; + } CodecInitOut; + + + +extern CodecInitOut *codecInit (CodecInitIn *psInitData); + +extern unsigned int codecEncodeChunk (int nSamples, short *pSamples, char *pOutput); + +extern unsigned int codecExit (char *pOutput); + +extern unsigned int codecFlush (char *pOutput); + + + + + +#endif /* __CODEC__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/common.c swftools-0.9.1/lib/bladeenc/common.c --- swftools-0.9.2+ds1/lib/bladeenc/common.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/common.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,105 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-11-22 Andre Piotrowski + + - bug fix: mem_alloc() - no lomger a need to allocate block*2 bytes +*/ + +/*********************************************************************** +* +* Global Include Files +* +***********************************************************************/ + +#include /* 1995-07-11 shn */ +#include +#include + +#include "common.h" + + + + + +/*********************************************************************** +* +* Global Variable Definitions +* +***********************************************************************/ + +/* 1: MPEG-1, 0: MPEG-2 LSF, 1995-07-11 shn */ +double s_freq[2][4] = +{ + {22.05, 24, 16, 0}, + {44.1 , 48, 32, 0} +}; + +/* 1: MPEG-1, 0: MPEG-2 LSF, 1995-07-11 shn */ +int bitratex[2][15] = +{ + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, + { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320} +}; + + + + + +/******************************************************************************* +* +* Allocate number of bytes of memory equal to "block". +* +*******************************************************************************/ + +void *mem_alloc (unsigned int block, char *item) +{ + void *ptr; + + ptr = (void *) malloc (block); + + memset (ptr, 0, block); + + return ptr; +} + + + + + +/**************************************************************************** +* +* Free memory pointed to by "*ptr_addr". +* +*****************************************************************************/ + +void mem_free (void **ptr_addr) +{ + if (*ptr_addr != NULL) + { + free (*ptr_addr); + *ptr_addr = NULL; + } +} + + + diff -Nru swftools-0.9.2+ds1/lib/bladeenc/common.h swftools-0.9.1/lib/bladeenc/common.h --- swftools-0.9.2+ds1/lib/bladeenc/common.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/common.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,267 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-02-07 Andre Piotrowski + + - reformatted +*/ + +#ifndef __COMMON__ +#define __COMMON__ + + + + + +/*********************************************************************** +* +* Global Include Files +* +***********************************************************************/ + +#include +#include +#include + +#include "tables.h" + + + + + +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#define MAX(A, B) ((A) > (B) ? (A) : (B)) + + + + + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + + + + + +/*********************************************************************** +* +* Global Definitions +* +***********************************************************************/ + +/* General Definitions */ + +#define FLOAT float +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#define NULL_CHAR '\0' + +#define MAX_U_32_NUM 0xFFFFFFFF + +#ifndef PI +#define PI 3.14159265358979 +#endif +#define PI4 PI/4 +#define PI64 PI/64 + +#define LN_TO_LOG10 0.2302585093 + +#define VOL_REF_NUM 0 +#define MPEG_AUDIO_ID 1 +#define MPEG_PHASE2_LSF 0 /* 1995-07-11 SHN */ + +#if 0 +#define MONO 1 +#define STEREO 2 +#endif + +#define BITS_IN_A_BYTE 8 +#define WORD 16 +#define MAX_NAME_SIZE 81 +#define SBLIMIT 32 +#define SSLIMIT 18 +#define FFT_SIZE 1024 +#define HAN_SIZE 512 +#define SCALE_BLOCK 12 +#define SCALE_RANGE 64 +#define SCALE 32768 +#define CRC16_POLYNOMIAL 0x8005 + + +/* MPEG Header Definitions - Mode Values */ + +#define MPG_MD_STEREO 0 +#define MPG_MD_DUAL_CHANNEL 2 +#define MPG_MD_MONO 3 + + +/* Mode Extention */ + +#define MPG_MD_LR_LR 0 +#define MPG_MD_LR_I 1 +#define MPG_MD_MS_LR 2 +#define MPG_MD_MS_I 3 + + +/* "bit_stream.h" Definitions */ + +#define MINIMUM 4 /* Minimum size of the buffer in bytes */ +#define MAX_LENGTH 32 /* Maximum length of word written or + read from bit stream */ + +#define READ_MODE 0 +#define WRITE_MODE 1 +#define ALIGNING 8 + + + +#define BUFFER_SIZE 4096 + + + + + +/*********************************************************************** +* +* Global Type Definitions +* +***********************************************************************/ + + +/* Structure for Reading Layer II Allocation Tables from File */ + +typedef struct + { + unsigned int steps; + unsigned int bits; + unsigned int group; + unsigned int quant; + } sb_alloc, *alloc_ptr; + +typedef sb_alloc al_table[SBLIMIT][16]; + + +/* Header Information Structure */ + +typedef struct + { + int version; + int error_protection; + int bitrate_index; + int sampling_frequency; + int padding; + int extension; + int mode; + int mode_ext; + int copyright; + int original; + int emphasis; +/* int freq; */ + } layer, *the_layer; + + +/* Parent Structure Interpreting some Frame Parameters in Header */ + +typedef struct + { + layer *header; /* raw header information */ + int actual_mode; /* when writing IS, may forget if 0 chs */ + al_table *alloc; /* bit allocation table read in */ + int tab_num; /* number of table as loaded */ + int stereo; /* 1 for mono, 2 for stereo */ + int jsbound; /* first band of joint stereo coding */ + int sblimit; /* total number of sub bands */ + } frame_params; + + + +enum byte_order { order_unknown, order_bigEndian, order_littleEndian }; +extern enum byte_order NativeByteOrder; + + +/* "bit_stream.h" Type Definitions */ + +typedef struct bit_stream_struc + { + FILE *pt; /* pointer to bit stream device */ + unsigned char *buf; /* bit stream buffer */ + int buf_size; /* size of buffer (in number of bytes) */ + int totbit; /* bit counter of bit stream */ + int buf_byte_idx; /* pointer to top byte in buffer */ + int buf_bit_idx; /* pointer to top bit of top byte in buffer */ + int mode; /* bit stream open in read or write mode */ + int eob; /* end of buffer index */ + int eobs; /* end of bit stream flag */ + char format; /* format of file in rd mode (BINARY/ASCII) */ + } Bit_stream_struc; + + + + + +#include "l3side.h" + +/*********************************************************************** +* +* Global Variable External Declarations +* +***********************************************************************/ + +/* +extern char *mode_names[4]; +extern char *layer_names[3]; +extern char *version_names[2]; +*/ +extern double s_freq[2][4]; +extern int bitratex[2][15]; + + + + + +/*********************************************************************** +* +* Global Function Prototype Declarations +* +***********************************************************************/ + +/* The following functions are in the file "common.c" */ + +extern void *mem_alloc (unsigned int block, char *item); +extern void mem_free (void **ptr_addr); + + + + + +#endif /* __COMMON__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/COPYING swftools-0.9.1/lib/bladeenc/COPYING --- swftools-0.9.2+ds1/lib/bladeenc/COPYING 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/COPYING 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,503 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + diff -Nru swftools-0.9.2+ds1/lib/bladeenc/encode.c swftools-0.9.1/lib/bladeenc/encode.c --- swftools-0.9.2+ds1/lib/bladeenc/encode.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/encode.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,1106 @@ +/* + (c) Copyright 1998-2001 - Tord Jansson + ======================================= + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-11-06 Andre Piotrowski + + - speed up: complete new, much faster functions 'create_ana_filter()', 'windowFilterSubband()' + - 'WIND_SB_CHANGE_LEVEL' 3 requires a new 'enwindow[]' (see 'tables.c') + + 2000-11-22 ap + + - bug fix: initWindowFilterSubband() -- Dividing the enwindow-entries is allowed to be done once only! + + 2000-12-11 ap + + - speed up: WIND_SB_CHANGE_LEVEL 4 + + 2001-01-12 ap + + - bug fix: fixed some typo relevant in case of ORG_BUFFERS == 1 +*/ + +#include "common.h" +#include "encoder.h" + + + + + +/* ======================================================================================== */ +/* rebuffer_audio */ +/* ======================================================================================== */ + +#if ORG_BUFFERS + +void rebuffer_audio +( + short buffer[2][1152], + short *insamp, + unsigned int samples_read, + int stereo +) +{ + unsigned int j; + + if (stereo == 2) + { + for (j = 0; j < samples_read/2; j++) + { + buffer[0][j] = insamp[2*j]; + buffer[1][j] = insamp[2*j+1]; + } + } + else + { + for (j = 0; j < samples_read; j++) + { + buffer[0][j] = insamp[j]; + buffer[1][j] = 0; + } + } + + for( ; j < 1152; j++) + { + buffer[0][j] = 0; + buffer[1][j] = 0; + } + + return; +} + +#else + +#define FLUSH 1152 +#define DELAY 768 + +void rebuffer_audio +( + const short *insamp, + FLOAT buffer[2][2048], + int *buffer_idx, + unsigned int samples_read, + int stereo +) +{ + int idx, med, fin; + + /* flush the last two read granules */ + *buffer_idx = (*buffer_idx + FLUSH) & 2047; + idx = (*buffer_idx + DELAY) & 2047; + fin = (idx + FLUSH) & 2047; + + if (stereo == 2) + { + med = (idx + samples_read/2) & 2047; + if (idx >= med) + { + while (idx < 2048) + { + buffer[0][idx] = *insamp++; + buffer[1][idx] = *insamp++; + idx++; + } + idx = 0; + } + while (idx < med) + { + buffer[0][idx] = *insamp++; + buffer[1][idx] = *insamp++; + idx++; + } + } + else + { + med = (idx + samples_read) & 2047; + if (idx >= med) + { + while (idx < 2048) + { + buffer[0][idx] = *insamp++; + buffer[1][idx] = 0; + idx++; + } + idx = 0; + } + while (idx < med) + { + buffer[0][idx] = *insamp++; + buffer[1][idx] = 0; + idx++; + } + } + + if (idx != fin) + { + if (idx > fin) + { + while (idx < 2048) + { + buffer[0][idx] = 0; + buffer[1][idx] = 0; + idx++; + } + idx = 0; + } + while (idx < fin) + { + buffer[0][idx] = 0; + buffer[1][idx] = 0; + idx++; + } + } +} + +#endif + + + + + +#if ORG_BUFFERS +#define WIND_SB_CHANGE_LEVEL 3 +#else +#define WIND_SB_CHANGE_LEVEL 4 +#endif + + + +#if WIND_SB_CHANGE_LEVEL==4 + + typedef double filter_matrix[SBLIMIT/4][32]; + + static filter_matrix m; + + /* ======================================================================================== */ + /* create_ana_filter */ + /* ======================================================================================== */ + /* + Calculates the analysis filterbank coefficients and rounds to the 9th decimal place + accuracy of the filterbank tables in the ISO document. + The coefficients are stored in #new_filter# + + + Originally was computed + + filter[i][j] := cos (PI64 * ((2*i+1) * (16-j))) + + for i = 0..SBLIMIT-1 and j = 0..63 . + + + But for j = 0..15 is 16-j = -(16-(32-j)) which implies + + (1) filter[i][j] = filter[i][32-j] . + + (We know that filter[i][16] = cos(0) = 1 , but that is not so interesting.) + + Furthermore, for j = 33..48 we get + + filter[i][96-j] + = cos (PI64 * (2*i+1) * (j-80)) + = cos (PI * (2*i+1) + PI64 * (2*i+1) * (16-j)) + (2) = cos (PI * (2*i+1)) * cos (PI64 * (2*i+1) * (16-j)) // sin (PI * (2*i+1)) = 0 + = -cos (PI64 * (2*i+1) * (16-j)) + = -filter[i][j] , + + especially is filter[i][48] = 0 . + + + On the other hand there is + + filter[31-i][j] + = cos (PI64 * (2*(31-i)+1) * (16-j)) + = cos (PI64 * (64-(2*i+1)) * (16-j)) + = cos (PI * (16-j) - PI64 * (2*i+1) * (16-j)) + = cos (PI * (16-j)) * cos (PI64 * (2*i+1) * (16-j)) // sin (PI * (16-j)) = 0 + = (-1)^^j * cos (PI64 * (2*i+1) * (16-j)) + = (-1)^^j * filter[i][j] . + + + There is a third somewhat more complication "symmetry": + + filter[15-i][j] + = cos (PI64 * (2*(15-i)+1) * (16-j)) + = cos (PI64 * (32-(2*i+1)) * (16-j)) + = cos (PI/2 * (16-j) - PI64 * (2*i+1) * (16-j)) + = cos (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (16-j)) + sin (PI/2 * (16-j)) * sin (PI64 * (2*i+1) * (16-j)) + = cos (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (16-j)) + sin (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (-1)^^i * (16-(j+32))) + + = (-1)^^( j /2 ) * filter[i][j ] for even j + = (-1)^^((j+1)/2 + i) * filter[i][j+32] for odd j with j < 32 + = (-1)^^((j-1)/2 + i) * filter[i][j-32] for odd j with j >= 32 + + + For these reasons we create a filter of the eighth size only and set + + new_filter[i][j] := filter[i][j] for i = 0..SBLIMIT/4-1 and j = 0..16 + new_filter[i][j] := filter[i][j+16] for i = 0..SBLIMIT/4-1 and j = 17..31 + */ + + static void create_ana_filter (double new_filter[SBLIMIT/4][32]) + { + register int i, j; + double t; + + for (i = 0; i < SBLIMIT/4; i++) + { + for (j = 0; j <= 16; j++) + { + t = 1e9 * cos (PI64 * (double) ((2*i+1) * (16-j))); + if (t >= 0) + modf (t + 0.5, &t); + else + modf (t - 0.5, &t); + new_filter[i][j] = t * 1e-9; + } + for (j = 17; j < 32; j++) + { + t = 1e9 * cos (PI64 * (double) ((2*i+1) * j)); /* (16-(j+16)) */ + if (t >= 0) + modf (t + 0.5, &t); + else + modf (t - 0.5, &t); + new_filter[i][j] = t * 1e-9; + } + } + } + + /* ======================================================================================== */ + /* windowFilterSubband */ + /* ======================================================================================== */ + /* + Calculates the analysis filter bank coefficients + + The windowed samples #z# is filtered by the digital filter matrix #m# to produce the + subband samples #s#. This done by first selectively picking out values from the windowed + samples, and then multiplying them by the filter matrix, producing 32 subband samples. + */ + + void windowFilterSubband + ( + const FLOAT *buffer, + int buffer_idx, + double s[SBLIMIT] + ) + { + int i, k; + + double t, u, v, w; + + double z[32]; + double *p; + double *pEnw; + + pEnw = enwindow; + + for (k = 0; k <= 16; k++) + { + t = buffer[(buffer_idx+511) & 2047] * *pEnw++; + t += buffer[(buffer_idx+447) & 2047] * *pEnw++; + t += buffer[(buffer_idx+383) & 2047] * *pEnw++; + t += buffer[(buffer_idx+319) & 2047] * *pEnw++; + t += buffer[(buffer_idx+255) & 2047] * *pEnw++; + t += buffer[(buffer_idx+191) & 2047] * *pEnw++; + t += buffer[(buffer_idx+127) & 2047] * *pEnw++; + t += buffer[(buffer_idx+ 63) & 2047] * *pEnw++; + z[k] = t; + + buffer_idx--; + } + + for (k = 15; k >= 0; k--) + { + t = buffer[(buffer_idx+511) & 2047] * *pEnw++; + t += buffer[(buffer_idx+447) & 2047] * *pEnw++; + t += buffer[(buffer_idx+383) & 2047] * *pEnw++; + t += buffer[(buffer_idx+319) & 2047] * *pEnw++; + t += buffer[(buffer_idx+255) & 2047] * *pEnw++; + t += buffer[(buffer_idx+191) & 2047] * *pEnw++; + t += buffer[(buffer_idx+127) & 2047] * *pEnw++; + t += buffer[(buffer_idx+ 63) & 2047] * *pEnw++; + z[k] += t; + + buffer_idx--; + } + + for (k = 17; k < 32; k++) + { + t = buffer[(buffer_idx+511) & 2047] * *pEnw++; + t += buffer[(buffer_idx+447) & 2047] * *pEnw++; + t += buffer[(buffer_idx+383) & 2047] * *pEnw++; + t += buffer[(buffer_idx+319) & 2047] * *pEnw++; + t += buffer[(buffer_idx+255) & 2047] * *pEnw++; + t += buffer[(buffer_idx+191) & 2047] * *pEnw++; + t += buffer[(buffer_idx+127) & 2047] * *pEnw++; + t += buffer[(buffer_idx+ 63) & 2047] * *pEnw++; + z[k] = t; + + buffer_idx--; + } + + /* normally y[48] was computed like the other entries, */ + /* but this entry is not needed because m[i][48] = 0. */ + buffer_idx--; /* But we have to increase the pointers. */ + pEnw += 8; + + for (k = 31; k > 16; k--) + { + t = buffer[(buffer_idx+511) & 2047] * *pEnw++; + t += buffer[(buffer_idx+447) & 2047] * *pEnw++; + t += buffer[(buffer_idx+383) & 2047] * *pEnw++; + t += buffer[(buffer_idx+319) & 2047] * *pEnw++; + t += buffer[(buffer_idx+255) & 2047] * *pEnw++; + t += buffer[(buffer_idx+191) & 2047] * *pEnw++; + t += buffer[(buffer_idx+127) & 2047] * *pEnw++; + t += buffer[(buffer_idx+ 63) & 2047] * *pEnw++; + z[k] -= t; + + buffer_idx--; + } + + for (i = 0; i < SBLIMIT/4; i++) + { + p = m[i]; + + t = u = v = w = 0.0; + for (k = 0; k < 16; k += 4) + { + t += p[k ] * z[k ]; + v += p[k+ 2] * z[k+2]; + u += p[k+ 1] * z[k+1] + p[k+ 3] * z[k+3]; + w -= p[k+17] * z[k+1] - p[k+19] * z[k+3]; + } + for ( ; k < 32; k += 4) + { + t += p[k ] * z[k ]; + v += p[k+ 2] * z[k+2]; + u += p[k+ 1] * z[k+1] + p[k+ 3] * z[k+3]; + w += p[k-15] * z[k+1] - p[k-13] * z[k+3]; + } + + s[ i] = (t + v) + u; + s[SBLIMIT-1-i] = (t + v) - u; + if (i & 1) + { + s[SBLIMIT/2-1-i] = (t - v) - w; + s[SBLIMIT/2 +i] = (t - v) + w; + } + else + { + s[SBLIMIT/2-1-i] = (t - v) + w; + s[SBLIMIT/2 +i] = (t - v) - w; + } + } + } + +#elif WIND_SB_CHANGE_LEVEL==3 + + #define imax (SBLIMIT/4) + typedef double filter_matrix[imax][32]; + + static int half[2]; + static int off[2]; + static double x[2][512]; + static filter_matrix m; + + /* ======================================================================================== */ + /* create_ana_filter */ + /* ======================================================================================== */ + /* + Calculates the analysis filterbank coefficients and rounds to the 9th decimal place + accuracy of the filterbank tables in the ISO document. + The coefficients are stored in #new_filter# + + + Originally was computed + + filter[i][j] := cos (PI64 * ((2*i+1) * (16-j))) + + for i = 0..SBLIMIT-1 and j = 0..63 . + + + But for j = 0..15 is 16-j = -(16-(32-j)) which implies + + (1) filter[i][j] = filter[i][32-j] . + + (We know that filter[i][16] = cos(0) = 1 , but that is not so interesting.) + + Furthermore, for j = 33..48 we get + + filter[i][96-j] + = cos (PI64 * (2*i+1) * (j-80)) + = cos (PI * (2*i+1) + PI64 * (2*i+1) * (16-j)) + (2) = cos (PI * (2*i+1)) * cos (PI64 * (2*i+1) * (16-j)) // sin (PI * (2*i+1)) = 0 + = -cos (PI64 * (2*i+1) * (16-j)) + = -filter[i][j] , + + especially is filter[i][48] = 0 . + + + On the other hand there is + + filter[31-i][j] + = cos (PI64 * (2*(31-i)+1) * (16-j)) + = cos (PI64 * (64-(2*i+1)) * (16-j)) + = cos (PI * (16-j) - PI64 * (2*i+1) * (16-j)) + = cos (PI * (16-j)) * cos (PI64 * (2*i+1) * (16-j)) // sin (PI * (16-j)) = 0 + = (-1)^^j * cos (PI64 * (2*i+1) * (16-j)) + = (-1)^^j * filter[i][j] . + + + There is a third somewhat more complication "symmetry": + + filter[15-i][j] + = cos (PI64 * (2*(15-i)+1) * (16-j)) + = cos (PI64 * (32-(2*i+1)) * (16-j)) + = cos (PI/2 * (16-j) - PI64 * (2*i+1) * (16-j)) + = cos (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (16-j)) + sin (PI/2 * (16-j)) * sin (PI64 * (2*i+1) * (16-j)) + = cos (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (16-j)) + sin (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (-1)^^i * (16-(j+32))) + + = (-1)^^( j /2 ) * filter[i][j ] for even j + = (-1)^^((j+1)/2 + i) * filter[i][j+32] for odd j with j < 32 + = (-1)^^((j-1)/2 + i) * filter[i][j-32] for odd j with j >= 32 + + + For these reasons we create a filter of the eighth size only and set + + new_filter[i][j] := filter[i][j] for i = 0..SBLIMIT/4-1 and j = 0..16 + new_filter[i][j] := filter[i][j+16] for i = 0..SBLIMIT/4-1 and j = 17..31 + */ + + static void create_ana_filter (double new_filter[imax][32]) + { + register int i, j; + double t; + + for (i = 0; i < imax; i++) + { + for (j = 0; j <= 16; j++) + { + t = 1e9 * cos (PI64 * (double) ((2*i+1) * (16-j))); + if (t >= 0) + modf (t + 0.5, &t); + else + modf (t - 0.5, &t); + new_filter[i][j] = t * 1e-9; + } + for (j = 17; j < 32; j++) + { + t = 1e9 * cos (PI64 * (double) ((2*i+1) * j)); /* (16-(j+16)) */ + if (t >= 0) + modf (t + 0.5, &t); + else + modf (t - 0.5, &t); + new_filter[i][j] = t * 1e-9; + } + } + } + + /* ======================================================================================== */ + /* windowFilterSubband */ + /* ======================================================================================== */ + /* + Calculates the analysis filter bank coefficients + + The windowed samples #z# is filtered by the digital filter matrix #m# to produce the + subband samples #s#. This done by first selectively picking out values from the windowed + samples, and then multiplying them by the filter matrix, producing 32 subband samples. + */ + + void windowFilterSubband + ( + short *pBuffer, + int ch, + double s[SBLIMIT] + ) + { + int i, k; + int a; + + double t, u, v, w; + + double z[32]; + double *pm; + double *px; + double *pEnw; + + + px = x[ch] + half[ch]; + a = off[ch]; + + /* replace 32 oldest samples with 32 new samples */ + + for (i = 0; i < 32; i++) + px[a + (31-i)*8] = (double) pBuffer[i]/*/SCALE*/; + + + pEnw = enwindow; + + for (k = 0; k <= 16; k++) + { + t = px[(a+0) & 7] * *pEnw++; + t += px[(a+1) & 7] * *pEnw++; + t += px[(a+2) & 7] * *pEnw++; + t += px[(a+3) & 7] * *pEnw++; + t += px[(a+4) & 7] * *pEnw++; + t += px[(a+5) & 7] * *pEnw++; + t += px[(a+6) & 7] * *pEnw++; + t += px[(a+7) & 7] * *pEnw++; + z[k] = t; + + px += 8; + } + + for (k = 15; k > 0; k--) + { + t = px[(a+0) & 7] * *pEnw++; + t += px[(a+1) & 7] * *pEnw++; + t += px[(a+2) & 7] * *pEnw++; + t += px[(a+3) & 7] * *pEnw++; + t += px[(a+4) & 7] * *pEnw++; + t += px[(a+5) & 7] * *pEnw++; + t += px[(a+6) & 7] * *pEnw++; + t += px[(a+7) & 7] * *pEnw++; + z[k] += t; + + px += 8; + } + + half[ch] ^= 256; /* toggling 0 or 256 */ + if (half[ch]) + { + off[ch] = (a + 7) & 7; + } + else + { + px = x[ch]; + a = (a + 1) & 7; + } + + /* k = 0; */ + { + t = px[(a+0) & 7] * *pEnw++; + t += px[(a+1) & 7] * *pEnw++; + t += px[(a+2) & 7] * *pEnw++; + t += px[(a+3) & 7] * *pEnw++; + t += px[(a+4) & 7] * *pEnw++; + t += px[(a+5) & 7] * *pEnw++; + t += px[(a+6) & 7] * *pEnw++; + t += px[(a+7) & 7] * *pEnw++; + z[k] += t; + + px += 8; + } + + for (k = 17; k < 32; k++) + { + t = px[(a+0) & 7] * *pEnw++; + t += px[(a+1) & 7] * *pEnw++; + t += px[(a+2) & 7] * *pEnw++; + t += px[(a+3) & 7] * *pEnw++; + t += px[(a+4) & 7] * *pEnw++; + t += px[(a+5) & 7] * *pEnw++; + t += px[(a+6) & 7] * *pEnw++; + t += px[(a+7) & 7] * *pEnw++; + z[k] = t; + + px += 8; + } + + /* normally y[48] was computed like the other entries, */ + /* but this entry is not needed because m[i][48] = 0. */ + px += 8; /* But we have to increase the pointers. */ + pEnw += 8; + + for (k = 31; k > 16; k--) + { + t = px[(a+0) & 7] * *pEnw++; + t += px[(a+1) & 7] * *pEnw++; + t += px[(a+2) & 7] * *pEnw++; + t += px[(a+3) & 7] * *pEnw++; + t += px[(a+4) & 7] * *pEnw++; + t += px[(a+5) & 7] * *pEnw++; + t += px[(a+6) & 7] * *pEnw++; + t += px[(a+7) & 7] * *pEnw++; + z[k] -= t; + + px += 8; + } + + for (i = 0; i < imax; i++) + { + pm = m[i]; + + t = u = v = w = 0.0; + for (k = 0; k < 16; k += 4) + { + t += pm[k ] * z[k ]; + v += pm[k+ 2] * z[k+2]; + u += pm[k+ 1] * z[k+1] + pm[k+ 3] * z[k+3]; + w -= pm[k+17] * z[k+1] - pm[k+19] * z[k+3]; + } + for ( ; k < 32; k += 4) + { + t += pm[k ] * z[k ]; + v += pm[k+ 2] * z[k+2]; + u += pm[k+ 1] * z[k+1] + pm[k+ 3] * z[k+3]; + w += pm[k-15] * z[k+1] - pm[k-13] * z[k+3]; + } + + s[ i] = (t + v) + u; + s[SBLIMIT-1-i] = (t + v) - u; + if (i & 1) + { + s[SBLIMIT/2-1-i] = (t - v) - w; + s[SBLIMIT/2 +i] = (t - v) + w; + } + else + { + s[SBLIMIT/2-1-i] = (t - v) + w; + s[SBLIMIT/2 +i] = (t - v) - w; + } + } + } + +#elif WIND_SB_CHANGE_LEVEL==2 + + typedef double filter_matrix[SBLIMIT/2][32]; + + static int off[2]; + static int half[2]; + static double x[2][512]; + static filter_matrix m; + + /* ======================================================================================== */ + /* create_ana_filter */ + /* ======================================================================================== */ + /* + Calculates the analysis filterbank coefficients and rounds to the 9th decimal place + accuracy of the filterbank tables in the ISO document. + The coefficients are stored in #new_filter# + + + Originally was computed + + filter[i][j] := cos (PI64 * ((2*i+1) * (16-j))) + + for i = 0..SBLIMIT-1 and j = 0..63 . + + + But for j = 0..15 is 16-j = -(16-(32-j)) which implies + + (1) filter[i][j] = filter[i][32-j] . + + (We know that filter[i][16] = cos(0) = 1 , but that is not so interesting.) + + Furthermore, for j = 33..48 we get + + filter[i][96-j] + = cos (PI64 * (2*i+1) * (j-80)) + = cos (PI * (2*i+1) + PI64 * (2*i+1) * (16-j)) + (2) = cos (PI * (2*i+1)) * cos (PI64 * (2*i+1) * (16-j)) // sin (PI * (2*i+1)) = 0 + = -cos (PI64 * (2*i+1) * (16-j)) + = -filter[i][j] , + + especially is filter[i][48] = 0 . + + + On the other hand there is + + filter[31-i][j] + = cos (PI64 * (2*(31-i)+1) * (16-j)) + = cos (PI64 * (64-(2*i+1)) * (16-j)) + = cos (PI * (16-j) - PI64 * (2*i+1) * (16-j)) + = cos (PI * (16-j)) * cos (PI64 * (2*i+1) * (16-j)) // sin (PI * (16-j)) = 0 + = (-1)^^j * cos (PI64 * (2*i+1) * (16-j)) + = (-1)^^j * filter[i][j] . + + + For these reasons we create a filter of the quarter size only and set + + new_filter[i][j] := filter[i][j] for i = 0..SBLIMIT/2-1 and j = 0..16 + new_filter[i][j] := filter[i][j+16] for i = 0..SBLIMIT/2-1 and j = 17..31 + */ + + static void create_ana_filter (double new_filter[SBLIMIT/2][32]) + { + register int i, j; + double t; + + for (i = 0; i < SBLIMIT/2; i++) + { + for (j = 0; j < =16; j++) + { + t = 1e9 * cos (PI64 * (double) ((2*i+1) * (16-j))); + if (t >= 0) + modf (t + 0.5, &t); + else + modf (t - 0.5, &t); + new_filter[i][j] = t * 1e-9; + } + for (j = 17; j < 32; j++) + { + t = 1e9 * cos (PI64 * (double) ((2*i+1) * j)); /* (16-(j+16)) */ + if (t >= 0) + modf (t + 0.5, &t); + else + modf (t - 0.5, &t); + new_filter[i][j] = t * 1e-9; + } + } + } + + /* ======================================================================================== */ + /* windowFilterSubband */ + /* ======================================================================================== */ + /* + Calculates the analysis filter bank coefficients + + The windowed samples #z# is filtered by the digital filter matrix #m# to produce the + subband samples #s#. This done by first selectively picking out values from the windowed + samples, and then multiplying them by the filter matrix, producing 32 subband samples. + */ + + void windowFilterSubband + ( + short *pBuffer, + int ch, + double s[SBLIMIT] + ) + { + int i, k; + int a; + + double t, u; + + double z[32]; /* y[64]; */ + double *pm; + double *px; + double *pEnw; + + + px = x[ch] + half[ch]; + a = off[ch]; + + /* replace 32 oldest samples with 32 new samples */ + + for (i = 0; i < 32; i++) + px[a + (31-i)*8] = (double) pBuffer[i] /*/SCALE*/; + + + /* + for k = 0..15 we compute + + z[k] := y[k] + y[32-k] + + and we set + + z[16| := y[16] . + */ + + pEnw = enwindow; + + for (k = 0; k <= 16; k++) /* for (j = 0; j < =16; j++) */ + { + t = px[(a+0) & 7] * pEnw[64*0]; + t += px[(a+1) & 7] * pEnw[64*1]; + t += px[(a+2) & 7] * pEnw[64*2]; + t += px[(a+3) & 7] * pEnw[64*3]; + t += px[(a+4) & 7] * pEnw[64*4]; + t += px[(a+5) & 7] * pEnw[64*5]; + t += px[(a+6) & 7] * pEnw[64*6]; + t += px[(a+7) & 7] * pEnw[64*7]; + z[k] = t; /* y[j] = t; */ + + px += 8; + pEnw++; + } + + for (k = 15; k > 0; k--) /* for (j = 17; j < 32; j++) */ + { + t = px[(a+0) & 7] * pEnw[64*0]; + t += px[(a+1) & 7] * pEnw[64*1]; + t += px[(a+2) & 7] * pEnw[64*2]; + t += px[(a+3) & 7] * pEnw[64*3]; + t += px[(a+4) & 7] * pEnw[64*4]; + t += px[(a+5) & 7] * pEnw[64*5]; + t += px[(a+6) & 7] * pEnw[64*6]; + t += px[(a+7) & 7] * pEnw[64*7]; + z[k] += t; /* y[j] = t; */ + + px += 8; + pEnw++; + } + + half[ch] ^= 256; /* toggling 0 or 256 */ + if (half[ch]) + { + off[ch] = (a + 7) & 7; /*offset is modulo (HAN_SIZE-1)*/ + } + else + { + px = x[ch]; + a = (a + 1) & 7; + } + + /* k = 0; not needed, actual value of k is 0 */ /* j = 32; */ + { + t = px[(a+0) & 7] * pEnw[64*0]; + t += px[(a+1) & 7] * pEnw[64*1]; + t += px[(a+2) & 7] * pEnw[64*2]; + t += px[(a+3) & 7] * pEnw[64*3]; + t += px[(a+4) & 7] * pEnw[64*4]; + t += px[(a+5) & 7] * pEnw[64*5]; + t += px[(a+6) & 7] * pEnw[64*6]; + t += px[(a+7) & 7] * pEnw[64*7]; + z[k] += t; /* y[j] = t; */ + + px += 8; + pEnw++; + } + + /* + for k = 17..31 we compute + + z[k] := y[k+16] - y[80-k] + */ + + for (k = 17; k < 32; k++) /* for (j = 33; j < 47; j++) */ + { + t = px[(a+0) & 7] * pEnw[64*0]; + t += px[(a+1) & 7] * pEnw[64*1]; + t += px[(a+2) & 7] * pEnw[64*2]; + t += px[(a+3) & 7] * pEnw[64*3]; + t += px[(a+4) & 7] * pEnw[64*4]; + t += px[(a+5) & 7] * pEnw[64*5]; + t += px[(a+6) & 7] * pEnw[64*6]; + t += px[(a+7) & 7] * pEnw[64*7]; + z[k] = t; /* y[j] = t; */ + + px += 8; + pEnw++; + } + + /* normally y[48] was computed like the other entries, */ + /* but this entry is not needed because m[i][48] = 0. */ + px += 8; /* But we have to increase the pointers. */ + pEnw++; + + for (k = 31; k > 16; k--) /* for (j = 49; j < 64; j++) */ + { + t = px[(a+0) & 7] * pEnw[64*0]; + t += px[(a+1) & 7] * pEnw[64*1]; + t += px[(a+2) & 7] * pEnw[64*2]; + t += px[(a+3) & 7] * pEnw[64*3]; + t += px[(a+4) & 7] * pEnw[64*4]; + t += px[(a+5) & 7] * pEnw[64*5]; + t += px[(a+6) & 7] * pEnw[64*6]; + t += px[(a+7) & 7] * pEnw[64*7]; + z[k] -= t; /* y[j] = t; */ + + px += 8; + pEnw++; + } + + pm = m[0]; /* pm = m[0]; */ + for (i = 0; i < SBLIMIT/2; i++) /* for (i = 0; i < SBLIMIT; i++) */ + { + + t = u = 0.0; /* t = 0.0; */ + for (k = 0; k < 32; ) /* for (j = 0; j < 64; j++) */ + { + t += *pm++ * z[k++]; /* t += *pm++ * y[j]; */ + u += *pm++ * z[k++]; + } + + s[ i] = t + u; /* s[i] = t; */ + s[SBLIMIT-1-i] = t - u; + } + } + +#elif WIND_SB_CHANGE_LEVEL==1 + + typedef double filter_matrix[SBLIMIT][64]; + + static int off[2]; + static int half[2]; + static double x[2][512]; + static filter_matrix m; + + /* ======================================================================================== */ + /* create_ana_filter */ + /* ======================================================================================== */ + /* + Calculates the analysis filterbank coefficients and rounds to the 9th decimal place + accuracy of the filterbank tables in the ISO document. + The coefficients are stored in #filter# + */ + + static void create_ana_filter (filter_matrix filter) + { + register int i, j; + double t; + + for (i = 0; i < SBLIMIT; i++) + { + for (j = 0; j < 64; j++) + { + t = 1e9 * cos (PI64 * (double) ((2*i+1) * (16-j))); + if (t >= 0) + modf (t + 0.5, &t); + else + modf (t - 0.5, &t); + filter[i][j] = t * 1e-9; + } + } + } + + /* ======================================================================================== */ + /* windowFilterSubband */ + /* ======================================================================================== */ + /* + Calculates the analysis filter bank coefficients + + The windowed samples #y# is filtered by the digital filter matrix #m# to produce the + subband samples #s#. This done by first selectively picking out values from the windowed + samples, and then multiplying them by the filter matrix, producing 32 subband samples. + */ + + void windowFilterSubband + ( + short *pBuffer, + int ch, + double s[SBLIMIT] + ) + { + int i, j; + int a; + + double t; + + double y[64]; + double *pm; + double *px; + double *pEnw; + + + px = x[ch] + half[ch]; + a = off[ch]; + + /* replace 32 oldest samples with 32 new samples */ + + for (i = 0; i < 32; i++) + px[a + (31-i)*8] = (double) pBuffer[i] /*/SCALE*/; + + + pEnw = enwindow; + + for (j = 0; j < 32; j++) + { + t = px[(a+0) & 7] * pEnw[64*0]; + t += px[(a+1) & 7] * pEnw[64*1]; + t += px[(a+2) & 7] * pEnw[64*2]; + t += px[(a+3) & 7] * pEnw[64*3]; + t += px[(a+4) & 7] * pEnw[64*4]; + t += px[(a+5) & 7] * pEnw[64*5]; + t += px[(a+6) & 7] * pEnw[64*6]; + t += px[(a+7) & 7] * pEnw[64*7]; + y[j] = t; + + px += 8; + pEnw++; + } + + half[ch] ^= 256; /* toggling 0 or 256 */ + if (half[ch]) + { + off[ch] = (a + 7) & 7; /*offset is modulo (HAN_SIZE-1)*/ + } + else + { + px = x[ch]; + a = (a + 1) & 7; + } + + for (j = 32; j < 64; j++) + { + t = px[(a+0) & 7] * pEnw[64*0]; + t += px[(a+1) & 7] * pEnw[64*1]; + t += px[(a+2) & 7] * pEnw[64*2]; + t += px[(a+3) & 7] * pEnw[64*3]; + t += px[(a+4) & 7] * pEnw[64*4]; + t += px[(a+5) & 7] * pEnw[64*5]; + t += px[(a+6) & 7] * pEnw[64*6]; + t += px[(a+7) & 7] * pEnw[64*7]; + y[j] = t; + + px += 8; + pEnw++; + } + + pm = m[0]; + for (i = 0; i < SBLIMIT; i++) + { + t = 0.0; + for (j = 0; j < 64; j++) + t += *pm++ * y[j]; + + s[i] = t; + } + } + +#endif + + + + + +/* ======================================================================================== */ +/* initWindowFilterSubband */ +/* ======================================================================================== */ + +void initWindowFilterSubband (void) +{ + static int initialized = 0; + + int i; + + if (!initialized) + { + create_ana_filter (m); + + for (i = 0; i < 512; i++) + enwindow[i] /= SCALE; + + initialized = 1; + } + +#if ORG_BUFFERS + half[0] = half[1] = 0; + off[0] = off[1] = 0; + memset (x, 0, sizeof(x)); +#endif +} + + + + + diff -Nru swftools-0.9.2+ds1/lib/bladeenc/encoder.h swftools-0.9.1/lib/bladeenc/encoder.h --- swftools-0.9.2+ds1/lib/bladeenc/encoder.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/encoder.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,108 @@ +/* + (c) Copyright 1998-2001 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-11 Andre Piotrowski + + - reformatted, redesigned +*/ + +#ifndef __ENCODER__ +#define __ENCODER__ + + + + + +#define ORG_BUFFERS 0 /* 1 = use original buffer concept */ + + + + + +/*********************************************************************** +* +* Encoder Definitions +* +***********************************************************************/ + +/* Psychoacoustic Model 2 Definitions */ + +#define BLKSIZE 1024 +#define HBLKSIZE 513 +#define CBANDS 63 + + + + + +/*********************************************************************** +* +* Encoder Function Prototype Declarations +* +***********************************************************************/ + + +void initWindowFilterSubband (void); + + + + +#if ORG_BUFFERS + + void rebuffer_audio + ( + short buffer[2][1152], + short *insamp, + unsigned int samples_read, + int stereo + ); + void windowFilterSubband + ( + short *pBuffer, + int ch, + double s[SBLIMIT] + ); + +#else + + void rebuffer_audio + ( + const short *insamp, + FLOAT buffer[2][2048], + int *buffer_idx, + unsigned int samples_read, + int stereo + ); + void windowFilterSubband + ( + const FLOAT *buffer, + int buffer_idx, + double s[SBLIMIT] + ); + +#endif + + + + + +#endif /* __ENCODER__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/formatbitstream2.c swftools-0.9.1/lib/bladeenc/formatbitstream2.c --- swftools-0.9.2+ds1/lib/bladeenc/formatbitstream2.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/formatbitstream2.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,502 @@ +/* + (c) Copyright 1998-2001 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression. + + This file doesn't contain any of the ISO reference code and + is copyright Tord Jansson (tord.jansson@swipnet.se). + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-05 Andre Piotrowski + + - reformatted, slightly optimized + + 2001-01-12 ap + + - use some explicit type casting to avoid compiler warnings +*/ + +#include +#include + +#if defined(_MSC) +#include +#endif + +#include "common.h" +#include "formatbitstream2.h" + + + + + +extern char *pEncodedOutput; +extern int outputBit; + + + + + +/*____ Structure Definitions _________________________________________________*/ + +typedef struct HeaderDef + { + int size; + int frameSize; + char data[128]; + struct HeaderDef *pNext; + } Header; + + + + + +/*____ Function Prototypes ___________________________________________________*/ + +static int writeMainDataBits (BF_FrameData *psFrame, BitHolder *psBH); +static void putbits (unsigned int val, int n); +static int generateHeader (BF_FrameData *psFrame); + + + + + +/*____ Static Data ___________________________________________________________*/ + +static int BitsRemaining = 0; +static Header *pHeaderChain = NULL; +static Header *pFreeHeaderChain = NULL; + + + + + +/*____ initFormatBitstream() ________________________________________________*/ + +void initFormatBitstream (void) +{ + BitsRemaining = 0; + pHeaderChain = NULL; + pFreeHeaderChain = NULL; +} + + + + + +/*____ exitFormatBitstream() _________________________________________________*/ + +void exitFormatBitstream (void) +{ + Header *psFree; + + /* Fill out the last frame with 0xFF */ + + flushFrame (); + + /* Dealocate Headers */ + + while (pHeaderChain != NULL) + { + psFree = pHeaderChain; + pHeaderChain = psFree->pNext; + free (psFree); + } + + while (pFreeHeaderChain != NULL) + { + psFree = pFreeHeaderChain; + pFreeHeaderChain = psFree->pNext; + free (psFree); + } +} + + + + + +/*____ flushFrame() _________________________________________________________*/ + +void flushFrame (void) +{ + /* Fill out the last frame with 0xFF */ + + while (BitsRemaining > 32) + { + putbits (0xFFFFFFFF, 32); + BitsRemaining -= 32; + } + + if (BitsRemaining > 0) + putbits (0xFFFFFFFF, BitsRemaining); + + BitsRemaining = 0; +} + + + + + +/*____ initBitHolder() ______________________________________________________*/ + +BitHolder *initBitHolder +( + BitHolder *wp, + int elements +) +{ + wp->element = (BitHolderElement *) malloc (sizeof(BitHolderElement) * elements); + wp->max_elements = elements; + wp->nrEntries = 0; + + return wp; +} + + + + + +/*____ exitBitHolder() ______________________________________________________*/ + +void exitBitHolder (BitHolder * wp) +{ + mem_free ((void **)&wp->element); +/* + if (wp->element != NULL) + { + free (wp->element); + wp->element = NULL; + } +*/ +} + + + + + +/*____ addBits() ____________________________________________________________*/ + +void addBits +( + BitHolder *wp, + unsigned int value, + int length +) +{ + if (length != 0) + { + if (wp->nrEntries == wp->max_elements) + { + printf ("ERROR: BitHolder overflow!\n"); + exit (-1); + } + + value &= 0xFFFFFFFF >> (32-length); + + wp->element[wp->nrEntries].value = value; + wp->element[wp->nrEntries].length = length; + wp->nrEntries++; + } +} + + + + + +/*____ writeFrame() _________________________________________________________*/ + +void writeFrame +( + BF_FrameData *psFrame, + BF_FrameResults *results +) +{ + int bits; + int gr, ch; + + int sizeRemainHeaders, sizeRemainFrames; + Header *psHeader; + + + /* Generate and save header, return size of SideInfo.*/ + + results->SILength = generateHeader (psFrame); + + + /* Put the bits and compute size of mainData */ + + bits = 0; + for (gr = 0; gr < psFrame->nGranules; gr++) + { + for (ch = 0; ch < psFrame->nChannels; ch++) + { + bits += writeMainDataBits (psFrame, &psFrame->scaleFactors[gr][ch]); + bits += writeMainDataBits (psFrame, &psFrame-> codedData[gr][ch]); + bits += writeMainDataBits (psFrame, &psFrame->userSpectrum[gr][ch]); + } + } + bits += writeMainDataBits (psFrame, &psFrame->userFrameData); + + results->mainDataLength = bits; + + + /* calculate nextBackPointer */ + + sizeRemainHeaders = 0; + sizeRemainFrames = 0; + + for (psHeader = pHeaderChain; psHeader != NULL; psHeader = psHeader->pNext) + { + sizeRemainHeaders += psHeader->size; + sizeRemainFrames += psHeader->frameSize; + } + + + results->nextBackPtr = (BitsRemaining / 8) + sizeRemainFrames - sizeRemainHeaders; /* BitsRemaining must be dividable by 8 */ +} + + + + + +/*============================================================================= + >>> Static Functions <<< +=============================================================================*/ + + + + + +/*____ writeBitHolder() _____________________________________________________*/ + +static void writeBitHolder (BitHolder *part) +{ + BitHolderElement *ep; + int i; + + ep = part->element; + for (i = 0; i < part->nrEntries; i++, ep++) + putbits (ep->value, ep->length); +} + + + + + +/*____ calcCRC() ____________________________________________________________*/ + +static int calcCRC +( + char *pData, + int size +) +{ + int i; + int crc = 0xffff; + int masking; + int carry; + int data; + + for (i = 2; i < size; i++) + { + if (i != 4 && i != 5) + { + masking = 1 << 8; + data = pData[i]; + while (masking >>= 1) + { + carry = crc & 0x8000; + crc <<= 1; + /* + if ( (carry == 0) != ((data & masking) == 0) ) + */ + if (!carry ^ !(data & masking)) + crc ^= 0x8005; + } + } + } + + crc &= 0xffff; + return crc; +} + + + + + +/*____ generateHeader() ____________________________________________________*/ + +static int generateHeader (BF_FrameData *psFrame) +{ + int gr, ch; + int crc; + Header *psHeader; + Header **wpLink; + char *pOldEncodedOutput; + + + /* Get a Free Header structure */ + + if( pFreeHeaderChain == NULL ) + psHeader = (Header *) malloc( sizeof( Header ) ); + else + { + psHeader = pFreeHeaderChain; + pFreeHeaderChain = psHeader->pNext; + } + psHeader->pNext = NULL; + for( wpLink = &pHeaderChain ; * wpLink != NULL ; wpLink = &((*wpLink)->pNext) ) + {} /* avoid compiler warning */ + *wpLink = psHeader; + + + /* Generate the Header */ + + pOldEncodedOutput = pEncodedOutput; + pEncodedOutput = psHeader->data; + pEncodedOutput[0] = 0; /* Need to be cleared since we OR in data... */ + + + writeBitHolder (&psFrame->header); + writeBitHolder (&psFrame->frameSI); + + for (ch = 0; ch < psFrame->nChannels; ch++) + writeBitHolder (&psFrame->channelSI[ch]); + + for (gr = 0; gr < psFrame->nGranules; gr++) + for (ch = 0; ch < psFrame->nChannels; ch++) + writeBitHolder (&psFrame->spectrumSI[gr][ch]); + + + /* Checksum generation (if CRC enabled).*/ + + if (!(psHeader->data[1] & 0x1)) + { + crc = calcCRC (psHeader->data, pEncodedOutput - psHeader->data); + psHeader->data[4] = (char) (crc >> 8); + psHeader->data[5] = (char) crc; + } + + + psHeader->size = pEncodedOutput - psHeader->data; + psHeader->frameSize = psFrame->frameLength / 8; + + pEncodedOutput = pOldEncodedOutput; + + + return psHeader->size * 8; +} + + + + + +/*____ writeHeader() _______________________________________________________*/ + +static int writeHeader (void) +{ + Header *psHeader; + + psHeader = pHeaderChain; + memcpy (pEncodedOutput, psHeader->data, psHeader->size); + pEncodedOutput += psHeader->size; + *pEncodedOutput = 0; + + pHeaderChain = psHeader->pNext; + psHeader->pNext = pFreeHeaderChain; + pFreeHeaderChain = psHeader; + + return (psHeader->frameSize - psHeader->size) * 8; +} + + + + + +/*____ writeMainDataBits() __________________________________________________*/ + +static int writeMainDataBits +( + BF_FrameData *psFrame, /* avoid compiler warning */ + BitHolder *psBH +) +{ + BitHolderElement *psElem = psBH->element; + int i, bits = 0; + unsigned int val; + int nBits; + + for (i = 0; i < psBH->nrEntries; i++, psElem++) + { + val = psElem->value; + nBits = psElem->length; + + if (BitsRemaining == 0) + BitsRemaining = writeHeader (); + + if (nBits > BitsRemaining) + { + nBits -= BitsRemaining; + putbits (val >> nBits, BitsRemaining); + BitsRemaining = writeHeader (); + } + + putbits (val, nBits); + BitsRemaining -= nBits; + + bits += psElem->length; + } + + return bits; +} + + + + + +/*____ putbits() _____________________________________________________________*/ + + +/*write n bits into the bit stream */ + +static void putbits +( + unsigned int val, + int n +) +{ + + if (n == 0) + return; + + while (n >= outputBit) + { + n -= outputBit; + + *pEncodedOutput |= val >> n; + + outputBit = 8; + pEncodedOutput++; + *pEncodedOutput = 0; + } + + if (n > 0) /* n < outputBit */ + { + outputBit -= n; + + *pEncodedOutput |= val << outputBit; + } +} + + + diff -Nru swftools-0.9.2+ds1/lib/bladeenc/formatbitstream2.h swftools-0.9.1/lib/bladeenc/formatbitstream2.h --- swftools-0.9.2+ds1/lib/bladeenc/formatbitstream2.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/formatbitstream2.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,101 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-15 Andre Piotrowski + + - reformatted +*/ + +#ifndef __FORMATBITSTREAM2__ +#define __FORMATBITSTREAM2__ + + + + + +#define MAX_CHANNELS 2 +#define MAX_GRANULES 2 + + + + + + +/*____ Structure Definitions ________________________________________________*/ + +typedef struct + { + unsigned int value; + int length; + } BitHolderElement; + + +typedef struct + { + int max_elements; + int nrEntries; + BitHolderElement *element; + } BitHolder; + + +typedef struct BF_FrameData + { + int frameLength; + int nGranules; + int nChannels; + BitHolder header; + BitHolder frameSI; + BitHolder channelSI[MAX_CHANNELS]; + BitHolder spectrumSI[MAX_GRANULES][MAX_CHANNELS]; + BitHolder scaleFactors[MAX_GRANULES][MAX_CHANNELS]; + BitHolder codedData[MAX_GRANULES][MAX_CHANNELS]; + BitHolder userSpectrum[MAX_GRANULES][MAX_CHANNELS]; + BitHolder userFrameData; + } BF_FrameData; + + +typedef struct BF_FrameResults + { + int SILength; + int mainDataLength; + int nextBackPtr; + } BF_FrameResults; + + + + + +/*____ Function Prototypes __________________________________________________*/ + +BitHolder *initBitHolder (BitHolder *wp, int elements); +void exitBitHolder (BitHolder *wp); +void addBits (BitHolder *wp, unsigned int value, int length); +void writeFrame (BF_FrameData *psFrame, BF_FrameResults *results); +void initFormatBitstream (void); +void exitFormatBitstream (void); +void flushFrame (void); + + + + + +#endif /* __FORMATBITSTREAM2__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/huffman.h swftools-0.9.1/lib/bladeenc/huffman.h --- swftools-0.9.2+ds1/lib/bladeenc/huffman.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/huffman.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,50 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-04 Andre Piotrowski + + - reformatted, slimmed +*/ + +#ifndef __HUFFMAN__ +#define __HUFFMAN__ + + +struct huffcodetab { + unsigned int xlen; /* max. x-index */ + unsigned int ylen; /* max. y-index */ + unsigned int linbits; /* number of linbits */ + unsigned int linmax; /* max number to be stored in linbits */ + int ref; /* a positive value indicates a reference */ + unsigned int *table; /* pointer to array[xlen][ylen] */ + unsigned char *hlen; /* pointer to array[xlen][ylen] */ +}; + + +extern struct huffcodetab ht[34]; +/* global memory block */ +/* array of all huffcodtable headers */ +/* 0..31 Huffman code table 0..31 */ +/* 32,33 count1-tables */ + + +#endif /* __HUFFMAN__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/l3bitstream.c swftools-0.9.1/lib/bladeenc/l3bitstream.c --- swftools-0.9.2+ds1/lib/bladeenc/l3bitstream.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/l3bitstream.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,665 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-04 Andre Piotrowski + + - redesigned, reformatted, slightly optimized +*/ + +#include +#include + +#include "system.h" +#include "common.h" + +#include "l3psy.h" +#include "loop.h" +#include "formatbitstream2.h" +#include "huffman.h" + +#include "l3bitstream.h" /* the public interface */ +#include "l3bitstream-pvt.h" + + + + + +static int stereo = 1; +static frame_params *fr_ps = NULL; + +static int PartHoldersInitialized = 0; + + + +static BitHolder *headerPH; +static BitHolder *frameSIPH; +static BitHolder *channelSIPH[MAX_CHANNELS]; +static BitHolder *spectrumSIPH[MAX_GRANULES][MAX_CHANNELS]; +static BitHolder *scaleFactorsPH[MAX_GRANULES][MAX_CHANNELS]; +static BitHolder *codedDataPH[MAX_GRANULES][MAX_CHANNELS]; +static BitHolder *userSpectrumPH[MAX_GRANULES][MAX_CHANNELS]; +static BitHolder *userFrameDataPH; + + + +static BF_FrameData sFrameData; +static BF_FrameResults sFrameResults; + + + + + +/* + III_format_bitstream() + + This is called after a frame of audio has been quantized and coded. + It will write the encoded audio to the bitstream. Note that + from a layer3 encoder's perspective the bit stream is primarily + a series of main_data() blocks, with header and side information + inserted at the proper locations to maintain framing. (See Figure A.7 + in the IS). +*/ + +void III_format_bitstream +( + int bitsPerFrame, + frame_params *in_fr_ps, + int l3_enc[2][2][576], + III_side_info_t *l3_side, + III_scalefac_t *scalefac, + double (*xr)[2][576], + char *ancillary, + int ancillary_bits +) +{ + int gr, ch, i, mode_gr; + + fr_ps = in_fr_ps; + stereo = fr_ps->stereo; + mode_gr = 2; + + if (!PartHoldersInitialized) + { + headerPH = initBitHolder (&sFrameData.header, 16*2); + frameSIPH = initBitHolder (&sFrameData.frameSI, 4*2); + + for (ch = 0; ch < MAX_CHANNELS; ch++) + channelSIPH[ch] = initBitHolder (&sFrameData.channelSI[ch], 8*2); + + for (gr = 0; gr < MAX_GRANULES; gr++) + { + for (ch = 0; ch < MAX_CHANNELS; ch++) + { + spectrumSIPH[gr][ch] = initBitHolder (&sFrameData. spectrumSI[gr][ch], 32*2); + scaleFactorsPH[gr][ch] = initBitHolder (&sFrameData.scaleFactors[gr][ch], 64*2); + codedDataPH[gr][ch] = initBitHolder (&sFrameData. codedData[gr][ch], 576*2); + userSpectrumPH[gr][ch] = initBitHolder (&sFrameData.userSpectrum[gr][ch], 4*2); + } + } + userFrameDataPH = initBitHolder (&sFrameData.userFrameData, 8*2); + + PartHoldersInitialized = 1; + } + +#if 1 + for (gr = 0; gr < mode_gr; gr++) + { + for (ch = 0; ch < stereo; ch++) + { + int *pi = &l3_enc[gr][ch][0]; + double *pr = &xr[gr][ch][0]; + + for (i = 0; i < 576; i++, pr++, pi++) + if (*pr < 0 && *pi > 0) + *pi *= -1; + } + } +#endif + + encodeSideInfo (l3_side); + encodeMainData (l3_enc, l3_side, scalefac); + write_ancillary_data (ancillary, ancillary_bits); + + if (l3_side->resvDrain) + drain_into_ancillary_data (l3_side->resvDrain); + + sFrameData.frameLength = bitsPerFrame; + sFrameData.nGranules = mode_gr; + sFrameData.nChannels = stereo; + + writeFrame (&sFrameData, &sFrameResults); + + /* we set this here -- it will be tested in the next loops iteration */ + l3_side->main_data_begin = sFrameResults.nextBackPtr; +} + + + + + +void III_FlushBitstream (void) +{ + int gr, ch; + + if (PartHoldersInitialized) + { + exitBitHolder (&sFrameData.header); + exitBitHolder (&sFrameData.frameSI); + + for (ch = 0; ch < MAX_CHANNELS; ch++) + exitBitHolder (&sFrameData.channelSI[ch]); + + + for (gr = 0; gr < MAX_GRANULES; gr++) + { + for (ch = 0; ch < MAX_CHANNELS; ch++) + { + exitBitHolder (&sFrameData. spectrumSI[gr][ch]); + exitBitHolder (&sFrameData.scaleFactors[gr][ch]); + exitBitHolder (&sFrameData. codedData[gr][ch]); + exitBitHolder (&sFrameData.userSpectrum[gr][ch]); + } + } + exitBitHolder (&sFrameData.userFrameData); + + PartHoldersInitialized = 0; + } + + /* BF_FlushBitstream (frameData, frameResults); */ +} + + + + + +static unsigned slen1_tab[16] = { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 }; +static unsigned slen2_tab[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }; + + + + + +static void encodeMainData +( + int l3_enc[2][2][576], + III_side_info_t *side_info, + III_scalefac_t *scalefac +) +{ + int gr, ch, sfb, b, mode_gr; + + mode_gr = 2; + + + for (gr = 0; gr < mode_gr; gr++) + for (ch = 0; ch < stereo; ch++) + scaleFactorsPH[gr][ch]->nrEntries = 0; + + + for (gr = 0; gr < mode_gr; gr++) + for (ch = 0; ch < stereo; ch++) + codedDataPH[gr][ch]->nrEntries = 0; + + + for (gr = 0; gr < 2; gr++) + { + for (ch = 0; ch < stereo; ch++) + { + BitHolder *ph = scaleFactorsPH[gr][ch]; + gr_info *cod_info = &side_info->gr[gr].ch[ch].tt; + unsigned slen1 = slen1_tab[cod_info->scalefac_compress]; + unsigned slen2 = slen2_tab[cod_info->scalefac_compress]; + int *ix = &l3_enc[gr][ch][0]; + + if (cod_info->window_switching_flag && cod_info->block_type == SHORT_TYPE) + { + if (cod_info->mixed_block_flag) + { + for (sfb = 0; sfb < 8; sfb++) + addBits (ph, scalefac->l[gr][ch][sfb], slen1); + + for (sfb = 3; sfb < 6; sfb++) + for (b = 0; b < 3; b++) + addBits (ph, scalefac->s[gr][ch][sfb][b], slen1); + } + else + { + for (sfb = 0; sfb < 6; sfb++) + for (b = 0; b < 3; b++) + addBits (ph, scalefac->s[gr][ch][sfb][b], slen1); + } + + for (sfb = 6; sfb < 12; sfb++) + for (b = 0; b < 3; b++) + addBits (ph, scalefac->s[gr][ch][sfb][b], slen2); + } + else if (gr == 0) + { + for (sfb = 0; sfb < 11; sfb++) + addBits (ph, scalefac->l[gr][ch][sfb], slen1); + + for (sfb = 11; sfb < 21; sfb++) + addBits (ph, scalefac->l[gr][ch][sfb], slen2); + } + else + { + if (!side_info->scfsi[ch][0]) + for (sfb = 0; sfb < 6; sfb++) + addBits (ph, scalefac->l[gr][ch][sfb], slen1); + + if (!side_info->scfsi[ch][1]) + for (sfb = 6; sfb < 11; sfb++) + addBits (ph, scalefac->l[gr][ch][sfb], slen1); + + if (!side_info->scfsi[ch][2]) + for (sfb = 11; sfb < 16; sfb++) + addBits (ph, scalefac->l[gr][ch][sfb], slen2); + + if (!side_info->scfsi[ch][3]) + for (sfb = 16; sfb < 21; sfb++) + addBits (ph, scalefac->l[gr][ch][sfb], slen2); + } + + Huffmancodebits (codedDataPH[gr][ch], ix, cod_info); + } /* for ch */ + } /* for gr */ +} /* main_data */ + + + + + +/*____ encodeSideInfo() _____________________________________________________*/ + +static int encodeSideInfo (III_side_info_t *side_info) +{ + int gr, ch, scfsi_band, region, b, bits_sent, mode_gr; + layer *info = fr_ps->header; + + mode_gr = 2; + + + headerPH->nrEntries = 0; + + addBits (headerPH, 0xfff , 12); + addBits (headerPH, 1 , 1); + addBits (headerPH, 4 - 3 , 2); /* 4 - Layer */ + addBits (headerPH, !info->error_protection , 1); + addBits (headerPH, info->bitrate_index , 4); + addBits (headerPH, info->sampling_frequency, 2); + addBits (headerPH, info->padding , 1); + addBits (headerPH, info->extension , 1); + addBits (headerPH, info->mode , 2); + addBits (headerPH, info->mode_ext , 2); + addBits (headerPH, info->copyright , 1); + addBits (headerPH, info->original , 1); + addBits (headerPH, info->emphasis , 2); + + bits_sent = 32; + + if (info->error_protection) + { + addBits (headerPH, 0, 16); /* Just a dummy add. Real CRC calculated & inserted in writeSideInfo() */ + bits_sent += 16; + } + + + frameSIPH->nrEntries = 0; + + addBits (frameSIPH, side_info->main_data_begin, 9); + + if (stereo == 2) + addBits (frameSIPH, side_info->private_bits, 3); + else + addBits (frameSIPH, side_info->private_bits, 5); + + + for (ch = 0; ch < stereo; ch++) + { + BitHolder *ph = channelSIPH[ch]; + + ph->nrEntries = 0; + + for (scfsi_band = 0; scfsi_band < 4; scfsi_band++) + addBits (ph, side_info->scfsi[ch][scfsi_band], 1); + } + + + for (gr = 0; gr < 2; gr++) + { + for (ch = 0; ch < stereo; ch++) + { + BitHolder *ph = spectrumSIPH[gr][ch]; + gr_info *cod_info = &side_info->gr[gr].ch[ch].tt; + + ph->nrEntries = 0; + + addBits (ph, cod_info->part2_3_length , 12); + addBits (ph, cod_info->big_values , 9); + addBits (ph, cod_info->global_gain , 8); + addBits (ph, cod_info->scalefac_compress , 4); + addBits (ph, cod_info->window_switching_flag, 1); + + if (cod_info->window_switching_flag) + { + addBits (ph, cod_info->block_type , 2); + addBits (ph, cod_info->mixed_block_flag, 1); + + for (region = 0; region < 2; region++) + addBits (ph, cod_info->table_select[region], 5); + + for (b = 0; b < 3; b++) + addBits (ph, cod_info->subblock_gain[b], 3); + } + else + { + for (region = 0; region < 3; region++) + addBits (ph, cod_info->table_select[region], 5); + + addBits (ph, cod_info->region0_count, 4); + addBits (ph, cod_info->region1_count, 3); + } + + addBits (ph, cod_info->preflag , 1); + addBits (ph, cod_info->scalefac_scale , 1); + addBits (ph, cod_info->count1table_select, 1); + } + } + + + if (stereo == 2) + bits_sent += 256; + else + bits_sent += 136; + + + return bits_sent; +} + + + + + +/*____ write_ancillary_data() _______________________________________________*/ + +static void write_ancillary_data +( + char *theData, + int lengthInBits +) +{ + int bytesToSend = lengthInBits / 8; + int remainingBits = lengthInBits % 8; + unsigned wrd; + + userFrameDataPH->nrEntries = 0; + + while (bytesToSend--) + { + wrd = *theData++; + addBits (userFrameDataPH, wrd, 8); + } + if (remainingBits) + { + /* right-justify remaining bits */ + wrd = *theData >> (8 - remainingBits); + addBits (userFrameDataPH, wrd, remainingBits); + } +} + + + + + +/* + Some combinations of bitrate, Fs, and stereo make it impossible to stuff + out a frame using just main_data, due to the limited number of bits to + indicate main_data_length. In these situations, we put stuffing bits into + the ancillary data... +*/ +static void drain_into_ancillary_data (int lengthInBits) +{ + int wordsToSend = lengthInBits / 32; + int remainingBits = lengthInBits % 32; + + /* + userFrameDataPH->part->nrEntries set by call to write_ancillary_data() + */ + + while (wordsToSend--) + addBits (userFrameDataPH, 0, 32); + if (remainingBits) + addBits (userFrameDataPH, 0, remainingBits); +} + + + + + +/* + Note the discussion of huffmancodebits() on pages 28 + and 29 of the IS, as well as the definitions of the side + information on pages 26 and 27. +*/ +static void Huffmancodebits +( + BitHolder *ph, + int *ix, + gr_info *cod_info +) +{ + int sfb, window, line, start, end; + int stuffingBits, table; + + int bitsWritten = 0; + int bigvalues = cod_info->big_values * 2; + + + /* + Within each scalefactor band, data is given for successive time windows, + beginning with window 0 and ending with window 2 (in case of short blocks! + --- there is only one long block window). Within each window, the quantized + values are then arranged in order of increasing frequency... + */ + + /* 1: Write the bigvalues */ + if (bigvalues) + { + if (cod_info->window_switching_flag && (cod_info->block_type == SHORT_TYPE)) + { + int (*ix_s)[3] = (int (*)[3]) ix; + int *scalefac = &sfBandIndex[fr_ps->header->sampling_frequency].s[0]; + + table = cod_info->table_select[0]; + if (table) + { + if (cod_info->mixed_block_flag) /* Mixed blocks long, short */ + { + for (line=0; line<36; line+=2) /* cod_info->address1 = 36 */ + bitsWritten += writeHuffmanCode (ph, table, ix[line], ix[line+1]); + } + else + { + for (sfb=0; sfb<3; sfb++) /* (cod_info->region0_count + 1) / 3 = 3 */ + { + start = scalefac[sfb]; + end = scalefac[sfb+1]; + + for (window=0; window<3; window++) + for (line=start; linetable_select[1]; + if (table) + { + for (sfb=3; sfbaddress1 > bigvalues) ? bigvalues : cod_info->address1; + int region2Start = (cod_info->address2 > bigvalues) ? bigvalues : cod_info->address2; + + table = cod_info->table_select[0]; + if (table) + for (line=0; linetable_select[1]; + if (table) + for (line=region1Start; linetable_select[2]; + if (table) + for (line=region2Start; linecount1) + { + struct huffcodetab *h = ht + (cod_info->count1table_select + 32); + + int *pos = ix + bigvalues; + int *end = ix + bigvalues + (cod_info->count1 * 4); + + while (pos < end) + { + int len, v, w, x, y; + int bits = 0; + int p = 0; + + v = *pos++; if (v) bits++, p |= 1; + w = *pos++; if (w) bits++, p |= 2; + x = *pos++; if (x) bits++, p |= 4; + y = *pos++; if (y) bits++, p |= 8; + + addBits (ph, h->table[p], len = h->hlen[p]); + + if (v) addBits (ph, v<0, 1); + if (w) addBits (ph, w<0, 1); + if (x) addBits (ph, x<0, 1); + if (y) addBits (ph, y<0, 1); + + bitsWritten += bits+len; + } + } + + + stuffingBits = cod_info->part2_3_length - cod_info->part2_length - bitsWritten; + if (stuffingBits) + { + int stuffingWords = stuffingBits / 32; + int remainingBits = stuffingBits % 32; + + /* + Due to the nature of the Huffman code + tables, we will pad with ones + */ + while (stuffingWords--) + addBits (ph, ~0, 32); + if (remainingBits) + addBits (ph, ~0, remainingBits); + + bitsWritten += stuffingBits; + } +} + + + + + +/* + Implements the pseudocode of page 98 of the IS + + aaaaaaaaaaaaaaargh --- why don«t write the code immediately? +*/ + +static int writeHuffmanCode +( + BitHolder *ph, + int table, + int x, + int y +) +{ + struct huffcodetab *h = ht + table; + + unsigned signx = (x <= 0) ? (x = -x, 1) : 0; + unsigned signy = (y <= 0) ? (y = -y, 1) : 0; + + unsigned code, cbits, idx; + +assert (table); +/* + if (table == 0) + return 0; +*/ + + if (table > 15) /* ESC-table is used */ + { + unsigned linbits = h->linbits; + unsigned ext = 0; + unsigned xbits = 0; + + if (x) {if (x > 14) {ext = (x-15); xbits += linbits; x = 15;} ext = (ext << 1) | signx; xbits++;} + if (y) {if (y > 14) {ext = (ext << linbits) | (y-15); xbits += linbits; y = 15;} ext = (ext << 1) | signy; xbits++;} + + idx = x * h->ylen + y; + code = h->table[idx]; + cbits = h->hlen[idx]; + + addBits (ph, code, cbits); + addBits (ph, ext , xbits); + + return cbits + xbits; + } + else /* No ESC-words */ + { + idx = x * h->ylen + y; + code = h->table[idx]; + cbits = h->hlen[idx]; + + if (x) {code = (code << 1) | signx; cbits++;} + if (y) {code = (code << 1) | signy; cbits++;} + + addBits (ph, code, cbits); + + return cbits; + } +} + + + diff -Nru swftools-0.9.2+ds1/lib/bladeenc/l3bitstream.h swftools-0.9.1/lib/bladeenc/l3bitstream.h --- swftools-0.9.2+ds1/lib/bladeenc/l3bitstream.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/l3bitstream.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,79 @@ +/* + (c) Copyright 1998, 1999 - Tord Jansson + ======================================= + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-11 Andre Piotrowski + + - reformatted +*/ + + +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: l3bitstream.h,v 1.1 2002/01/10 17:30:00 kramm Exp $ + * + * $Log: l3bitstream.h,v $ + * Revision 1.1 2002/01/10 17:30:00 kramm + * Version 0.94.1 of the bladeenc mp3 encoder + * + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ + +#ifndef __L3BITSTREAM__ +#define __L3BITSTREAM__ + + + + + +#include "common.h" +#include "encoder.h" + + + + + +void III_format_bitstream +( + int bitsPerFrame, + frame_params *in_fr_ps, + int l3_enc[2][2][576], + III_side_info_t *l3_side, + III_scalefac_t *scalefac, + double (*xr)[2][576], + char *ancillary, + int anc_bits +); + +void III_FlushBitstream (void); + +void fixStatic_l3bitstream (void); + + + + + +#endif /* __L3BITSTREAM__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/l3bitstream-pvt.h swftools-0.9.1/lib/bladeenc/l3bitstream-pvt.h --- swftools-0.9.2+ds1/lib/bladeenc/l3bitstream-pvt.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/l3bitstream-pvt.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,71 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-04 Andre Piotrowski + + - redesigned, reformatted +*/ + +#ifndef __L3BITSTREAM_PVT__ +#define __L3BITSTREAM_PVT__ + + + + + +static void encodeMainData +( + int l3_enc[2][2][576], + III_side_info_t *side_info, + III_scalefac_t *scalefac +); + +static int encodeSideInfo (III_side_info_t *side_info); + +static void write_ancillary_data +( + char *theData, + int lengthInBits +); + +static void drain_into_ancillary_data (int lengthInBits); + +static void Huffmancodebits +( + BitHolder *ph, + int *ix, + gr_info *cod_info +); + +static int writeHuffmanCode +( + BitHolder *ph, + int table, + int x, + int y +); + + + + + +#endif /* __L3BITSTREAM_PVT__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/l3psy.c swftools-0.9.1/lib/bladeenc/l3psy.c --- swftools-0.9.2+ds1/lib/bladeenc/l3psy.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/l3psy.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,1188 @@ +/* + (c) Copyright 1998-2001 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-05 Andre Piotrowski + + - speed up: implemented prepacking of fft-data + + 2000-12-11 ap + + - speed up: faster psycho_anal() + - optional bug fix: integrated better norm calclulation and block selecting + + 2000-12-12 ap + + - use SHORT_FFT_MIN_IDX to allow switching of "ORG_SHORT_CW_LIMIT" in "l3psy.h" + + 2001-01-12 ap + + - use some explicit type casting to avoid compiler warnings +*/ + +#define RING_BUFFER 1 + + + + + +#include + +#include "common.h" +#include "tables.h" +#include "encoder.h" +#include "l3side.h" +#include "l3psy.h" + + + + + +/*____ Global Static Variables ______________________________________________*/ + +/* The static variables "r", "phi_sav", "new_", "old" and "oldest" have */ +/* to be remembered for the unpredictability measure. For "r" and */ +/* "phi_sav", the first index from the left is the channel select and */ +/* the second index is the "age" of the data. */ + + +static int new_, old, oldest; +static int flush, sync_flush, syncsize; + +#if RING_BUFFER==1 +static int savebuf_start_idx[2]; +#endif + + + +#if NEW_L3PARM_TABLES + +static double *minval, *qthr_l; +static double *qthr_s, *SNR_s; +static int *cbw_l, *bu_l, *bo_l; +static int *cbw_s, *bu_s, *bo_s; +static double *w1_l, *w2_l; +static double *w1_s, *w2_s; + +#if ORG_NUMLINES_NORM + +static int cbmax_l = CBANDS, cbmax_s = CBANDS_s; +static int numlines_l [CBANDS]; + +static int partition_l [HBLKSIZE]; +static int partition_s [HBLKSIZE_s]; +static double s3_l [CBANDS][CBANDS]; +static double *norm_l, *norm_s; + +#else + +static int cbmax_l, cbmax_s; +static int *numlines_l; +static int *numlines_s; + + /* the non-zero entries of norm_l[i] * s3_l[i][j] */ +static FLOAT normed_s3_l [900]; /* a bit more space than needed [799|855|735] */ +static int lo_s3_l [CBANDS]; +static int hi_s3_l [CBANDS]; + +static FLOAT normed_s3_s [500]; /* a bit more space than needed [445|395|378] */ +static int lo_s3_s [CBANDS_s]; +static int hi_s3_s [CBANDS_s]; + +#endif /* ORG_NUMLINES_NORM */ + +#else + +static double minval[CBANDS], qthr_l[CBANDS], norm_l[CBANDS]; +static double qthr_s[CBANDS_s], norm_s[CBANDS_s], SNR_s[CBANDS_s]; +static int cbw_l[SBMAX_l],bu_l[SBMAX_l],bo_l[SBMAX_l]; +static int cbw_s[SBMAX_s],bu_s[SBMAX_s],bo_s[SBMAX_s]; +static double w1_l[SBMAX_l], w2_l[SBMAX_l]; +static double w1_s[SBMAX_s], w2_s[SBMAX_s]; + +static int numlines_l [CBANDS]; + +static int partition_l [HBLKSIZE]; +static int partition_s [HBLKSIZE_s]; +static double s3_l [CBANDS][CBANDS]; + +#endif /* NEW_L3PARM_TABLES */ + + + +/* Scale Factor Bands */ +static int blocktype_old[2]; + + + +static double nb_1 [2][CBANDS]; +static double nb_2 [2][CBANDS]; + +static double cw [HBLKSIZE]; + +static FLOAT window [BLKSIZE]; +static FLOAT r [2][2][6]; +static FLOAT phi_sav [2][2][6]; + +static FLOAT window_s [BLKSIZE_s]; + +static double ratio [2][SBMAX_l]; +static double ratio_s [2][SBMAX_s][3]; + + + + + +#if NEW_L3PARM_TABLES + +static void L3para_read (int sfreq); + +#if !ORG_NUMLINES_NORM +static void calc_normed_spreading +( + int cbmax, /* number of lines and rows */ + const double bval[], /* input values to compute the matrix */ + FLOAT s3_ptr[], /* the resulting non-zero entries */ + int lo_s3[], + int hi_s3[], + const double norm[] +); +#endif + +#else + +static void L3para_read +( + int sfreq, + int numlines_l[CBANDS], + int partition_l[HBLKSIZE], + double minval[CBANDS], + double qthr_l[CBANDS], + double norm_l[CBANDS], + double s3_l[CBANDS][CBANDS], + int partition_s[HBLKSIZE_s], + double qthr_s[CBANDS_s], + double norm_s[CBANDS_s], + double SNR_s[CBANDS_s], + int cbw_l[SBMAX_l], + int bu_l[SBMAX_l], + int bo_l[SBMAX_l], + double w1_l[SBMAX_l], + double w2_l[SBMAX_l], + int cbw_s[SBMAX_s], + int bu_s[SBMAX_s], + int bo_s[SBMAX_s], + double w1_s[SBMAX_s], + double w2_s[SBMAX_s] +); + +#endif + + + + + +/*____ psycho_anal_init() ___________________________________________________*/ + +void psycho_anal_init (double sfreq) +{ + unsigned int ch, sfb, b, i, j; + + + /* reset the r, phi_sav "ring buffer" indices */ + + old = 1 - (new_ = oldest = 0); + + + /* clear the ratio arrays */ + + for (ch = 0; ch < 2; ch++) + { + for (sfb = 0; sfb < SBMAX_l; sfb++) + ratio[ch][sfb] = 0.0; + + for (sfb = 0; sfb < SBMAX_s; sfb++) + for (b = 0; b < 3; b++) + ratio_s[ch][sfb][b] = 0.0; + } + + + /* clear preecho arrays */ + + for (ch = 0; ch < 2; ch++) + { + for (i = 0; i < CBANDS; i++) + { + nb_1[ch][i] = 0; + nb_2[ch][i] = 0; + } + } + + + /* clear blocktype information */ + + for (ch = 0; ch < 2; ch++) + blocktype_old[ch] = NORM_TYPE; + + + sync_flush = 768; + flush = 576; + syncsize = 1344; /* sync_flush + flush */ + + +#if RING_BUFFER==1 + for (ch = 0; ch < 2; ch++) + savebuf_start_idx[ch] = 0; +#endif + + + /* calculate HANN window coefficients */ + + for (i = 0; i < BLKSIZE; i++) + window[i] = (FLOAT) (0.5 * (1 - cos (2.0 * PI * (i - 0.5) / BLKSIZE))); + + for (i = 0; i < BLKSIZE_s; i++) + window_s[i] = (FLOAT) (0.5 * (1 - cos (2.0 * PI * (i - 0.5) / BLKSIZE_s))); + + + /* reset states used in unpredictability measure */ + + for (ch = 0; ch < 2; ch++) + { + for (i = 0; i < 2; i++) + { + for (j = 0; j < 6; j++) + { + r[ch][i][j] = 0.0; + phi_sav[ch][i][j] = 0.0; + } + } + } + + +#if NEW_L3PARM_TABLES + L3para_read ((int) sfreq); +#else + L3para_read + ( + (int) sfreq, + numlines_l, partition_l, minval, qthr_l, norm_l, s3_l, + partition_s, qthr_s, norm_s, SNR_s, + cbw_l, bu_l, bo_l, w1_l, w2_l, + cbw_s, bu_s, bo_s, w1_s, w2_s + ); +#endif + + + /* Set unpredicatiblility of remaining spectral lines to 0.4 */ + + for (j = 206; j < HBLKSIZE; j++) + cw[j] = 0.4; +} + + + + + +/*____ psycho_anal_exit() ___________________________________________________*/ + +void psycho_anal_exit( void ) +{ + /* nothing to do */ +} + + + + + +/*____ psycho_anal() ________________________________________________________*/ + +void psycho_anal +( +#if ORG_BUFFERS + short int *buffer, + short int savebuf[2048], +#else + FLOAT *buffer, + int buffer_idx, +#endif + int ch, + int lay, +/* float snr32[32], */ + double ratio_d[SBMAX_l], + double ratio_ds[SBMAX_s][3], + double *pe, + gr_info *cod_info +) +{ + int blocktype; + unsigned int sfb, b, j, k; + double r_prime, phi_prime; /* not FLOAT */ + double temp1, temp2, temp3; + +#if !ORG_NUMLINES_NORM && NEW_L3PARM_TABLES + FLOAT *s3_ptr; +#endif + + int sblock; + + double thr [CBANDS]; + double eb [CBANDS]; + FLOAT cb [CBANDS]; + FLOAT wsamp_r [HBLKSIZE]; + FLOAT wsamp_i [HBLKSIZE]; + + FLOAT energy [HBLKSIZE]; + FLOAT phi [6]; + FLOAT energy_s [3][BLKSIZE_s]; + FLOAT phi_s [3][52]; + +#if ORG_BUFFERS +#if RING_BUFFER==1 + int beg, idx, fin; +#endif +#else +# define savebuf buffer +# define beg buffer_idx + int idx, fin; +#endif + + + for (sfb = 0; sfb < SBMAX_l; sfb++) + ratio_d[sfb] = ratio[ch][sfb]; + + for (sfb = 0; sfb < SBMAX_s; sfb++) + for (b = 0; b < 3; b++) + ratio_ds[sfb][b] = ratio_s[ch][sfb][b]; + + + if (ch == 0) + old = 1 - (new_ = oldest = old); + + +#if ORG_BUFFERS + /********************************************************************** + * Delay signal by sync_flush=768 samples * + **********************************************************************/ + +# if RING_BUFFER==0 + for (j = 0; j < sync_flush; j++) /* for long window samples */ + savebuf[j] = savebuf[j+flush]; + + for (j = sync_flush; j < syncsize; j++) + savebuf[j] = *buffer++; +# else + beg = savebuf_start_idx[ch] = (savebuf_start_idx[ch] + flush) & 2047; + + idx = (beg + sync_flush) & 2047; + fin = (idx + flush) & 2047; + if (idx >= fin) + { + while (idx < 2048) + savebuf[idx++] = *buffer++; + idx = 0; + } + while (idx < fin) + savebuf[idx++] = *buffer++; +# endif +#endif + + +/********************************************************************** +* compute unpredicatability of first six spectral lines * +**********************************************************************/ + +#if RING_BUFFER==0 + for (j = 0, k = 0, idx = 0; j < BLKSIZE/2; j++) + { + wsamp_r[j] = window[k++] * savebuf[idx++]; + wsamp_i[j] = window[k++] * savebuf[idx++]; + } +#else + j = 0; k = 0; + idx = beg; + fin = (idx + BLKSIZE) & 2047; + if (idx >= fin) + { + while (idx < 2048) + { + wsamp_r[j] = window[k++] * savebuf[idx++]; + wsamp_i[j] = window[k++] * savebuf[idx++]; + j++; + } + idx = 0; + } + while (idx < fin) + { + wsamp_r[j] = window[k++] * savebuf[idx++]; + wsamp_i[j] = window[k++] * savebuf[idx++]; + j++; + } +#endif + + fft(wsamp_r, wsamp_i, energy, phi, BLKSIZE); /* long FFT */ + + for (j = 0; j < 6; j++) + { /* calculate unpredictability measure cw */ + double r1, phi1; + r_prime = 2.0 * r[ch][old][j] - r[ch][oldest][j]; + phi_prime = 2.0 * phi_sav[ch][old][j] - phi_sav[ch][oldest][j]; + r[ch][new_][j] = (FLOAT) ( r1 = sqrt((double) energy[j])); + phi_sav[ch][new_][j] = (FLOAT) (phi1 = phi[j] ); + + temp3 = r1 + fabs(r_prime); + if (temp3 != 0.0) + { + temp1 = r1 * cos(phi1) - r_prime * cos(phi_prime); + temp2 = r1 * sin(phi1) - r_prime * sin(phi_prime); + cw[j] = sqrt(temp1*temp1 + temp2*temp2) / temp3; + } + else + cw[j] = 0; + } + + +/********************************************************************** +* compute unpredicatibility of next 200 spectral lines * +**********************************************************************/ + + for (b = 0; b < 3; b++) + { +#if RING_BUFFER==0 + for (j = 0, k = 0, idx = 128*(2 + b); j < BLKSIZE_s/2; j++) + { /* window data with HANN window */ + wsamp_r[j] = window_s[k++] * savebuf[idx++]; + wsamp_i[j] = window_s[k++] * savebuf[idx++]; + } +#else + j = 0; k = 0; + idx = (beg + 128*(2 + b)) & 2047; + fin = (idx + BLKSIZE_s) & 2047; + if (idx >= fin) + { + while (idx < 2048) + { + wsamp_r[j] = window_s[k++] * savebuf[idx++]; + wsamp_i[j] = window_s[k++] * savebuf[idx++]; + j++; + } + idx = 0; + } + while (idx < fin) + { + wsamp_r[j] = window_s[k++] * savebuf[idx++]; + wsamp_i[j] = window_s[k++] * savebuf[idx++]; + j++; + } +#endif + + fft (wsamp_r, wsamp_i, energy_s[b], phi_s[b], BLKSIZE_s); /* short FFT*/ + } + + for (j = 6, k = SHORT_FFT_MIN_IDX; j < 206; j += 4, k++) + { /* calculate unpredictability measure cw */ + double r1, phi1; + + r_prime = 2.0 * sqrt((double) energy_s[0][k]) - sqrt((double) energy_s[2][k]); + phi_prime = 2.0 * phi_s[0][k] - phi_s[2][k]; + r1 = sqrt((double) energy_s[1][k]); + phi1 = phi_s[1][k]; + + temp3 = r1 + fabs(r_prime); + if (temp3 != 0.0) + { + temp1 = r1 * cos(phi1) - r_prime * cos(phi_prime); + temp2 = r1 * sin(phi1) - r_prime * sin(phi_prime); + cw[j] = sqrt(temp1*temp1 + temp2*temp2) / temp3; + } + else + cw[j] = 0.0; + + cw[j+1] = cw[j+2] = cw[j+3] = cw[j]; + } + + +/********************************************************************** +* Calculate the energy and the unpredictability in the threshold * +* calculation partitions * +**********************************************************************/ + +#if ORG_NUMLINES_NORM || !NEW_L3PARM_TABLES + + for (b = 0; b < cbmax_l; b++) + { + eb[b] = 0.0; + cb[b] = 0.0; + } + for (j = 0; j < HBLKSIZE; j++) + { + int tp = partition_l[j]; + if (tp >= 0) + { + eb[tp] += energy[j]; + cb[tp] += cw[j] * energy[j]; + } + } + +#else + + j = 0; + for (b = 0; b < cbmax_l; b++) + { + eb[b] = 0.0; + cb[b] = 0.0; + + /* + Calculate the energy and the unpredictability in the threshold + calculation partitions + + cbmax_l holds the number of valid numlines_l entries + */ + k = numlines_l[b]; + do { + eb[b] += energy[j]; + cb[b] += cw[j] * energy[j]; + } while (j++, --k); + } + + s3_ptr = normed_s3_l; + +#endif + + + *pe = 0.0; + + for (b = 0; b < cbmax_l; b++) + { + FLOAT nb; + FLOAT ecb = 0.0; + double ctb = 0.0; + double SNR_l; + double cbb, tbb; + + + /* + convolve the partitioned energy and unpredictability + with the spreading function, normed_s3_l[b][k] + */ +#if ORG_NUMLINES_NORM || !NEW_L3PARM_TABLES + for (k = 0; k < cbmax_l; k++) + { + ecb += s3_l[b][k] * eb[k]; /* sprdngf for Layer III */ + ctb += s3_l[b][k] * cb[k]; + } +#else + for (k = lo_s3_l[b]; k < hi_s3_l[b]; k++) + { + ecb += *s3_ptr * eb[k]; /* sprdngf for Layer III */ + ctb += *s3_ptr++ * cb[k]; + } +#endif + + + /* + calculate the tonality of each threshold calculation partition + calculate the SNR in each threshhold calculation partition + */ + if (ecb != 0.0) + { + cbb = ctb / ecb; + if (cbb < 0.01) + cbb = 0.01; + tbb = -0.299 - 0.43 * log(cbb); /* conv1=-0.299, conv2=-0.43 */ + tbb = MIN(MAX (0.0, tbb), 1.0) ; /* 0<=tbb<=1 */ + } + else + tbb = 0.0; /* cbb==0 => -0.299-0.43*cbb<0 => tbb=0*/ + + /* TMN=29.0,NMT=6.0 for all calculation partitions */ + SNR_l = MAX (minval[b], 23.0 * tbb + 6.0); /* 29*tbb + 6*(1-tbb) */ + + /* calculate the threshold for each partition */ +#if ORG_NUMLINES_NORM || !NEW_L3PARM_TABLES + nb = ecb * norm_l[b] * exp(-SNR_l * LN_TO_LOG10); +#else + nb = ecb * exp(-SNR_l * LN_TO_LOG10); /* our ecb is already normed */ +#endif + + /* + pre-echo control + */ + thr[b] = MAX (qthr_l[b], MIN(nb, nb_2[ch][b])); + nb_2[ch][b] = MIN(2.0 * nb, 16.0 * nb_1[ch][b]); + nb_1[ch][b] = nb; + + + /* + calculate percetual entropy + + thr[b] -> thr[b]+1.0 : for non sound portition + */ + if (eb[b] > thr[b]) + *pe += numlines_l[b] * log((eb[b]+1.0) / (thr[b]+1.0)); + } + + +#define switch_pe 1800 + + + if (*pe < switch_pe) + { + /* no attack : use long blocks */ + + if (blocktype_old[ch] == SHORT_TYPE) + blocktype = STOP_TYPE; + else /* NORM_TYPE, STOP_TYPE */ + blocktype = NORM_TYPE; + + + /* threshold calculation (part 2) */ + + for (sfb = 0; sfb < SBMAX_l; sfb++) + { + int bu = bu_l[sfb]; + int bo = bo_l[sfb]; + double en = w1_l[sfb] * eb[bu] + w2_l[sfb] * eb[bo]; + + for (b = bu+1; b < bo; b++) + en += eb[b]; + + if (en != 0.0) + { + double thm = w1_l[sfb] * thr[bu] + w2_l[sfb] * thr[bo]; + + for (b = bu+1; b < bo; b++) + thm += thr[b]; + + ratio[ch][sfb] = thm / en; + } + else + ratio[ch][sfb] = 0.0; + } + } + else + { + /* attack : use short blocks */ + blocktype = SHORT_TYPE; +#if ORG_BLOCK_SELECT + if (blocktype_old[ch] == NORM_TYPE) + blocktype_old[ch] = START_TYPE; + else /* SHORT_TYPE, STOP_TYPE */ + blocktype_old[ch] = SHORT_TYPE; +#else /* ISO */ + if (blocktype_old[ch] == SHORT_TYPE) + blocktype_old[ch] = SHORT_TYPE; + else /* NORM_TYPE, STOP_TYPE */ + blocktype_old[ch] = START_TYPE; +#endif + + + /* threshold calculation for short blocks */ + + for (sblock = 0; sblock < 3; sblock++) + { +#if ORG_NUMLINES_NORM || !NEW_L3PARM_TABLES + + for (b = 0; b < cbmax_s; b++) + eb[b] = 0.0; + + for (j = 0; j < HBLKSIZE_s; j++) + eb[partition_s[j]] += energy_s[sblock][j]; + +#else + + j = 0; + for (b = 0; b < cbmax_s; b++) + { + eb[b] = 0.0; + + /* + Calculate the energy and the unpredictability in the threshold + calculation partitions + + cbmax_s holds the number of valid numlines_s entries + */ + k = numlines_s[b]; + do { + eb[b] += energy_s[sblock][j]; + } while (j++, --k); + } + + s3_ptr = normed_s3_s; +#endif + + for (b = 0; b < cbmax_s; b++) + { + FLOAT nb; + FLOAT ecb = 0.0; + +#if ORG_NUMLINES_NORM || !NEW_L3PARM_TABLES + for (k = 0; k < cbmax_s; k++) + ecb += s3_l[b][k] * eb[k]; + + nb = ecb * norm_l[b] * exp((double) SNR_s[b] * LN_TO_LOG10); +#else + for (k = lo_s3_s[b]; k < hi_s3_s[b]; k++) + ecb += *s3_ptr++ * eb[k]; + + nb = ecb * exp((double) SNR_s[b] * LN_TO_LOG10); /* our ecb is already normed */ +#endif + thr[b] = MAX(qthr_s[b], nb); + } + + for (sfb = 0; sfb < SBMAX_s; sfb++) + { + int bu = bu_s[sfb]; + int bo = bo_s[sfb]; + double en = w1_s[sfb] * eb[bu] + w2_s[sfb] * eb[bo]; + + for (b = bu+1; b < bo; b++) + en += eb[b]; + if (en != 0.0) + { + double thm = w1_s[sfb] * thr[bu] + w2_s[sfb] * thr[bo]; + + for (b = bu+1; b < bo; b++) + thm += thr[b]; + + ratio_s[ch][sfb][sblock] = thm / en; + } + else + ratio_s[ch][sfb][sblock] = 0.0; + } + } + } + + cod_info->block_type = blocktype_old[ch]; + blocktype_old[ch] = blocktype; + + if ( cod_info->block_type == NORM_TYPE ) + cod_info->window_switching_flag = 0; + else + cod_info->window_switching_flag = 1; + + cod_info->mixed_block_flag = 0; +} + + + + + +/*____ L3para_read() __________________________________________________________*/ + +#if NEW_L3PARM_TABLES + +static void L3para_read (int sfreq) +{ + int sfreq_idx; + l3_parm_block *parm; + double *bval_l, *bval_s; + +#if ORG_NUMLINES_NORM + int cbmax_l, cbmax_s; + int i, j, k; +#else + double *norm_l, *norm_s; +#endif + + + /* + Set parameter block + */ + switch (sfreq) + { + case 32000: sfreq_idx = 2; break; + case 44100: sfreq_idx = 0; break; + case 48000: sfreq_idx = 1; break; + default : return; /* Just to avoid compiler warnings */ + } + parm = l3_parm + sfreq_idx; + + + /* + Read long block data + */ + cbmax_l = parm->long_data.cbmax_l; + +#if ORG_NUMLINES_NORM + for (i = 0, j = 0; i < cbmax_l; i++) + { + numlines_l[i] = parm->long_data.numlines_l[i]; + + for (k = 0; k < numlines_l[i]; k++) + partition_l[j++] = i; + } +#else + numlines_l = parm->long_data.numlines_l; +#endif + + minval = parm->long_data.minval; + qthr_l = parm->long_data.qthr_l; + norm_l = parm->long_data.norm_l; + bval_l = parm->long_data.bval_l; + + + /* + Compute the normed spreading function norm_l[i] * s3_l[i][j] + */ +#if ORG_NUMLINES_NORM + for (i = 0; i < cbmax_l; i++) + { + double x, temp, tempx, tempy; + + for (j = 0; j < cbmax_l; j++) + { +/* tempx = (bval_l[i]-bval_l[j]) * 1.05; */ + if (j >= i) + tempx = (bval_l[i]-bval_l[j]) * 3.0; + else + tempx = (bval_l[i]-bval_l[j]) * 1.5; +/* if (j >= i) tempx = (bval_l[j]-bval_l[i]) * 3.0; + else tempx = (bval_l[j]-bval_l[i]) * 1.5; */ + if (tempx > 0.5 && tempx < 2.5) + { + temp = tempx - 0.5; + x = 8.0 * temp * (temp-2.0); + } + else x = 0.0; + tempx += 0.474; + tempy = 15.811389 + 7.5*tempx - 17.5*sqrt(1.0+tempx*tempx); + if (tempy <= -60.0) s3_l[i][j] = 0.0; + else s3_l[i][j] = exp((x + tempy) * LN_TO_LOG10); + } + } +#else + calc_normed_spreading (cbmax_l, bval_l, normed_s3_l, lo_s3_l, hi_s3_l, norm_l); +#endif + + + /* + Read short block data + */ + cbmax_s = parm->short_data.cbmax_s; + +#if ORG_NUMLINES_NORM + for (i = 0, j = 0; i < cbmax_s; i++) + { + numlines_l[i] = parm->short_data.numlines_s[i]; + + for (k = 0; k < numlines_l[i]; k++) + partition_s[j++] = i; + } +#else + numlines_s = parm->short_data.numlines_s; +#endif + + qthr_s = parm->short_data.qthr_s; + norm_s = parm->short_data.norm_s; + SNR_s = parm->short_data.SNR_s; + bval_s = parm->short_data.bval_s; + + +#if !ORG_NUMLINES_NORM + + /* + Compute the normed spreading function norm_s[i] * s3_s[i][j] + */ + calc_normed_spreading (cbmax_s, bval_s, normed_s3_s, lo_s3_s, hi_s3_s, norm_s); + +#endif + + + /* + Read long block data for converting threshold + calculation partitions to scale factor bands + */ + cbw_l = parm->long_thres.cbw_l; + bu_l = parm->long_thres.bu_l; + bo_l = parm->long_thres.bo_l; + w1_l = parm->long_thres.w1_l; + w2_l = parm->long_thres.w2_l; + + + /* + Read short block data for converting threshold + calculation partitions to scale factor bands + */ + cbw_s = parm->short_thres.cbw_s; + bu_s = parm->short_thres.bu_s; + bo_s = parm->short_thres.bo_s; + w1_s = parm->short_thres.w1_s; + w2_s = parm->short_thres.w2_s; +} + +#else /* NEW_L3PARM_TABLES */ + +static void L3para_read +( + int sfreq, + int numlines_l[CBANDS], + int partition_l[HBLKSIZE], + double minval[CBANDS], + double qthr_l[CBANDS], + double norm_l[CBANDS], + double s3_l[CBANDS][CBANDS], + int partition_s[HBLKSIZE_s], + double qthr_s[CBANDS_s], + double norm_s[CBANDS_s], + double SNR_s[CBANDS_s], + int cbw_l[SBMAX_l], + int bu_l[SBMAX_l], + int bo_l[SBMAX_l], + double w1_l[SBMAX_l], + double w2_l[SBMAX_l], + int cbw_s[SBMAX_s], + int bu_s[SBMAX_s], + int bo_s[SBMAX_s], + double w1_s[SBMAX_s], + double w2_s[SBMAX_s] +) +{ + static double bval_l[CBANDS]; + int cbmax_tp; + + int sbmax; + int i, j, k, k2; + + + psyDataElem *rpa1; + psyDataElem2 *rpa2; + psyDataElem3 *rpa3; + + +/* Read long block data */ + + switch (sfreq) + { + case 32000: rpa1 = psy_longBlock_32000_58; cbmax_tp = 59; break; + case 44100: rpa1 = psy_longBlock_44100_62; cbmax_tp = 63; break; + case 48000: rpa1 = psy_longBlock_48000_61; cbmax_tp = 62; break; + default : return; /* Just to avoid compiler warnings */ + } + + for (i = 0, k2 = 0; i < cbmax_tp; i++) + { + numlines_l[i] = rpa1->lines; + minval[i] = rpa1->minVal; + qthr_l[i] = rpa1->qthr; + norm_l[i] = rpa1->norm; + bval_l[i] = rpa1->bVal; + rpa1++; + + for (k = 0; k < numlines_l[i]; k++) + partition_l[k2++] = i; + } + + +/************************************************************************ + * Now compute the spreading function, s[j][i], the value of the spread-* + * ing function, centered at band j, for band i, store for later use * + ************************************************************************/ + + for (i = 0; i < cbmax_tp; i++) + { + double x, temp, tempx, tempy; + + for (j = 0; j < cbmax_tp; j++) + { +/* tempx = (bval_l[i]-bval_l[j]) * 1.05; */ + if (j >= i) + tempx = (bval_l[i]-bval_l[j]) * 3.0; + else + tempx = (bval_l[i]-bval_l[j]) * 1.5; +/* if (j >= i) tempx = (bval_l[j]-bval_l[i]) * 3.0; + else tempx = (bval_l[j]-bval_l[i]) * 1.5; */ + if (tempx > 0.5 && tempx < 2.5) + { + temp = tempx - 0.5; + x = 8.0 * temp * (temp-2.0); + } + else x = 0.0; + tempx += 0.474; + tempy = 15.811389 + 7.5*tempx - 17.5*sqrt(1.0+tempx*tempx); + if (tempy <= -60.0) s3_l[i][j] = 0.0; + else s3_l[i][j] = exp((x + tempy) * LN_TO_LOG10); + } + } + + +/* Read short block data */ + + switch (sfreq) + { + case 32000: rpa2 = psy_shortBlock_32000_41; cbmax_tp = 42; break; + case 44100: rpa2 = psy_shortBlock_44100_38; cbmax_tp = 39; break; + case 48000: rpa2 = psy_shortBlock_48000_37; cbmax_tp = 38; break; + default : return; /* Just to avoid compiler warnings */ + } + + for (i = 0, k2 = 0; i < cbmax_tp; i++) + { + numlines_l[i] = rpa2->lines; + qthr_s[i] = rpa2->qthr; + norm_s[i] = rpa2->norm; + SNR_s[i] = rpa2->snr; + rpa2++; + + for (k = 0; k < numlines_l[i]; k++) + partition_s[k2++] = i; + } + + +/* Read long block data for converting threshold calculation + partitions to scale factor bands */ + + switch (sfreq) + { + case 32000: rpa3 = psy_data3_32000_20; break; + case 44100: rpa3 = psy_data3_44100_20; break; + case 48000: rpa3 = psy_data3_48000_20; break; + default : return; /* Just to avoid compiler warnings */ + } + sbmax = SBMAX_l; + + for (i = 0; i < sbmax; i++) + { + cbw_l[i] = rpa3->cbw; + bu_l[i] = rpa3->bu; + bo_l[i] = rpa3->bo; + w1_l[i] = rpa3->w1; + w2_l[i] = rpa3->w2; + rpa3++; + } + + +/* Read short block data for converting threshold calculation + partitions to scale factor bands */ + + switch (sfreq) + { + case 32000: rpa3 = psy_data4_32000_11; break; + case 44100: rpa3 = psy_data4_44100_11; break; + case 48000: rpa3 = psy_data4_48000_11; break; + default : return; /* Just to avoid compiler warnings */ + } + sbmax = SBMAX_s; + + for (i = 0; i < sbmax; i++) + { + cbw_s[i] = rpa3->cbw; + bu_s[i] = rpa3->bu; + bo_s[i] = rpa3->bo; + w1_s[i] = rpa3->w1; + w2_s[i] = rpa3->w2; + rpa3++; + } +} + +#endif /* NEW_L3PARM_TABLES */ + + + + + +#if !ORG_NUMLINES_NORM && NEW_L3PARM_TABLES + +/* ======================================================================================== */ +/* calc_normed_spreading */ +/* ======================================================================================== */ +/* + Compute the normed spreading function, + the normed value of the spreading function, + centered at band j, for band i, store for later use + + Since this is a band matrix, we store only the non-zero entries + in linear order in the single dimension array normed_s3. + + The array has to be accessed in linear order, too, starting with line 0, + up to line cbmax-1. For line b, the current entries represent + + norm[b] * s3[b][lo_s3[b]] ... norm[b] * s3[b][hi_s3[b]-1] + + Normally, we could easily compute the norm [building the reciprocal of the line sum]. + Alas, dist10 uses somewhat (strange and) different, that made our norm differring too + much at the last few lines. Thus, we renounce and use the original values. +*/ + +static void calc_normed_spreading +( + int cbmax, /* number of lines and rows */ + const double bval[], /* input values to compute the matrix */ + FLOAT s3_ptr[], /* the resulting non-zero entries */ + int lo_s3[], + int hi_s3[], + const double norm[] +) +{ + double arg, x, y; + double s3[CBANDS]; + int i, j; + int non_zero_part; + + + + for (i = 0; i < cbmax; i++) + { + non_zero_part = FALSE; + hi_s3[i] = cbmax; /* we preset this value for the case that the line ends with a non-zero entry */ + + for (j = 0; j < cbmax; j++) + { + if (j >= i) + arg = (bval[i] - bval[j]) * 3.0; + else + arg = (bval[i] - bval[j]) * 1.5; + + if (arg > 0.5 && arg < 2.5) + x = 8.0 * (arg - 0.5) * (arg - 2.5); + else + x = 0.0; + + arg += 0.474; + + y = 15.811389 + 7.5 * arg - 17.5 * sqrt(1.0 + arg * arg); + + if (y <= -60.0) + { + if (non_zero_part) /* only zeroes will follow */ + { + hi_s3[i] = j; + break; /* so cut the computing for this line */ + } + } + else + { + s3[j] = exp((x + y) * LN_TO_LOG10); + + if (! non_zero_part) + { + lo_s3[i] = j; + non_zero_part = TRUE; /* the first non-zero entry ends the non_zero_part */ + } + } + } + + for (j = lo_s3[i]; j < hi_s3[i]; j++) + *s3_ptr++ = s3[j] * norm[i]; + } +} + +#endif /* ORG_NUMLINES_NORM */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/l3psy.h swftools-0.9.1/lib/bladeenc/l3psy.h --- swftools-0.9.2+ds1/lib/bladeenc/l3psy.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/l3psy.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,162 @@ +/* + (c) Copyright 1998-2001 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-11 Andre Piotrowski + + - reformatted + + 2000-12-12 ap + + - removed fft() prototype from "encoder.h" to this file + - removed the fft configuration switches from "subs.c" to this file + - implemented ORG_SHORT_CW_LIMIT + + 2001-01-12 ap + + - bug fix: include encoder.h for definition of ORG_BUFFERS + - clear some backward compatability flags for 0.93.10 +*/ + +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: l3psy.h,v 1.1 2002/01/10 17:30:00 kramm Exp $ + * + + * $Log: l3psy.h,v $ + * Revision 1.1 2002/01/10 17:30:00 kramm + * Version 0.94.1 of the bladeenc mp3 encoder + * + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ + +#ifndef __L3PSY__ +#define __L3PSY__ + + + +#include "encoder.h" + + + + + +/* ======================================================================================== */ +/* keeping backward compatability */ +/* ======================================================================================== */ + +#define ORG_NUMLINES_NORM 0 /* 0 = don't overwrite long numline entries with short numline entries */ +#define ORG_BLOCK_SELECT 0 /* 0 = ISO draft paper states slightly different block selection */ +#define ORG_SHORT_CW_LIMIT 0 /* 0 = ISO draft paper says first element starts at 6/4 = 1 (not 2) */ + + + + + +/* #define CBANDS 63 */ +#define CBANDS_s 42 +#define BLKSIZE_s 256 +#define HBLKSIZE_s 129 +#define TCBMAX_l 63 +#define TCBMAX_s 42 +#define SBMAX_l 21 +#define SBMAX_s 12 + + + +/* #define switch_pe 1800 */ +#define NORM_TYPE 0 +#define START_TYPE 1 +#define SHORT_TYPE 2 +#define STOP_TYPE 3 + + + + + +void psycho_anal +( +#if ORG_BUFFERS + short int *buffer, + short int savebuf[2048], +#else + FLOAT *buffer, + int buffer_idx, +#endif + int ch, + int lay, +/* FLOAT snr32[32], */ + double ratio_d[SBMAX_l], + double ratio_ds[SBMAX_s][3], + double *pe, + gr_info *cod_info +); + +void psycho_anal_init (double sfreq); + +void psycho_anal_exit (void); + + + + + +void fft (FLOAT[], FLOAT[], FLOAT[], FLOAT[], int); + + + +/* + Switches for configuring the fft in "subs.c" +*/ + +/* Do we want to reorder the data? */ +#define REORDER_DATA 0 /* no need to do that */ + +/* To get the inverse fft, set NORMAL_FFT to 0 */ +#define NORMAL_FFT 1 /* si */ + +/* Try this to speed up the fft when using non-complex sequences */ +#define REAL_SEQUENCE 1 /* no complex values needed */ + +/* We assume, the real data gets prepacked externally */ +#define PREPACKED 1 /* yes */ + +/* No one needs all the phi values in layer 3 !!! */ +#define USED_VALUES_ONLY 1 +#define LONG_FFT_MIN_IDX 0 +#define LONG_FFT_MAX_IDX 5 +#if ORG_SHORT_CW_LIMIT +#define SHORT_FFT_MIN_IDX 2 /* ( 6+2)/4 */ +#define SHORT_FFT_MAX_IDX 51 /* (206+2)/4 - 1 */ +#else /* according to ISO */ +#define SHORT_FFT_MIN_IDX 1 /* 6/4 */ +#define SHORT_FFT_MAX_IDX 50 /* 206/4 - 1 */ +#endif + + + + + +#endif /* __L3PSY__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/l3side.h swftools-0.9.1/lib/bladeenc/l3side.h --- swftools-0.9.2+ds1/lib/bladeenc/l3side.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/l3side.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,170 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-04 Andre Piotrowski + + - reformatted, slimmed +*/ + + + +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: l3side.h,v 1.1 2002/01/10 17:30:00 kramm Exp $ + * + * $Log: l3side.h,v $ + * Revision 1.1 2002/01/10 17:30:00 kramm + * Version 0.94.1 of the bladeenc mp3 encoder + * + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ +/********************************************************************** + * date programmers comment * + * 25. 6.92 Toshiyuki Ishino Ver 1.0 * + * 29.10.92 Masahiro Iwadare Ver 2.0 * + * 17. 4.93 Masahiro Iwadare Updated for IS Modification * + * * + *********************************************************************/ + +#ifndef __L3SIDE__ +#define __L3SIDE__ + + + + + +/* #define CBLIMIT_SHORT 12 */ + + + + + +/* void l3deco (void); */ + + + + + +/* Layer III side information. */ + +/* typedef double D576[576]; */ +/* typedef int I576[576]; */ +/* typedef double D192_3[192][3]; */ +/* typedef int I192_3[192][3]; */ +/* typedef char C192_3[192][3]; */ + + + +/* typedef struct + { + unsigned cbl_max; + unsigned cbs_start; + } III_cb_info; */ + +typedef struct + { + double l[2][2][21]; + double s[2][2][12][3]; + } III_psy_ratio; + +/* typedef struct + { + double l[2][2][21]; + double s[2][2][12][3]; + } III_psy_xmin;*/ + +/* typedef struct + { + double xr[576]; + double xr_s[3][192]; + double xmin[21]; + double xmin_s[3][192]; + int ix[576]; + int ix_s[3][192]; + } III_input3;*/ /* ch */ + +typedef struct + { + unsigned part2_3_length; + unsigned big_values; + unsigned count1; + unsigned global_gain; + unsigned scalefac_compress; + unsigned window_switching_flag; + unsigned block_type; + unsigned mixed_block_flag; + unsigned table_select[3]; + int /* unsigned */ subblock_gain[3]; + unsigned region0_count; + unsigned region1_count; + unsigned preflag; + unsigned scalefac_scale; + unsigned count1table_select; + unsigned part2_length; + unsigned sfb_lmax; + unsigned sfb_smax; + unsigned address1; + unsigned address2; + unsigned address3; + double quantizerStepSize; + /* added for LSF */ + unsigned *sfb_partition_table; + unsigned slen[4]; + } gr_info; + +typedef struct + { + int main_data_begin; /* unsigned -> int */ + unsigned private_bits; + int resvDrain; + unsigned scfsi[2][4]; + struct + { + struct gr_info_s + { + gr_info tt; + } ch[2]; + } gr[2]; + } III_side_info_t; + + + + + +/* Layer III scale factors. */ + +typedef struct + { + int l[2][2][22]; /* [cb] */ + int s[2][2][13][3]; /* [window][cb] */ + } III_scalefac_t; /* [gr][ch] */ + + + + + +#endif /* __L3SIDE__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/loop.c swftools-0.9.1/lib/bladeenc/loop.c --- swftools-0.9.2+ds1/lib/bladeenc/loop.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/loop.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,2590 @@ +/* + (c) Copyright 1998-2001 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-11-10 Andre Piotrowski + + - reformatted, used 'static' functions, global variables, less parameters + + 2000-11-11 ap + + - a lot of functions redesigned to let the bladetable become superfluous: + genNoisePowTab(), iteration_loop(), calc_noise(), preemphasis(), amp_scalefac_bands() + - bladTabValue() replaced by cutting_crew() + + 2000-11-22 ap + + - bug fix: module - reset fInit_huffman_read_flag + + 2000-11-28 ap + - speed up : implemented partial quantizing + + 2000-11-30 ap + - speed up : implemented faster Huffman coding + - integration : improved (optional) Huffman coding + [choosing better tables] + - integration : improved (optional) binary search + [in fact, this is a BUG FIX (original dist10 bug)] + + 2000-12-02 ap + - bug fix : original dist10's outer_loop could cause an endless loop (huff_bits <= 0). + - speed up : faster part2_length/scale_bitcount calculation + - integration : improved (optional) scalefactor compression + [smart preflag switching and choosing best compression] + + 2000-12-03 ap + - integration : improved (optional) quantanf algorithm + [calculating exact quantizer step boundaries] + - integration : improved (optional) preemphasing/amplifying algorithm + [preemphase only if iteration==1, according to ISO] + - integration : improved (optional) outer_loop algorithm + [amplify the bands, marked as "should be amplified"] + + 2000-12-10 ap + - definitely killed SCFSI + + 2001-01-12 ap + + - use some explicit type casting to avoid compiler warnings + - clear some backward compatability flags for 0.93.10 + + 2001-04-07 ap + - implemented flag CHECK_TJ_OVERFLOW to check for huffman table overflow +*/ + + + + + +/* ======================================================================================== */ +/* keeping backward compatability */ +/* ======================================================================================== */ + +#define ORG_HUFFMAN_CODING 0 /* 0 = use better Huffman tables for shorter code */ +#define ORG_BINARY_SEARCH 0 /* 0 = use a correct implemented binary search */ +#define ORG_QUANTANF_INIT 0 /* 0 = use better quantization start value */ +#define ORG_PREEMPHASING 0 /* 0 = use a more ISO-like preemphasing algorithm */ +#define ORG_SCF_COMPRESS 0 /* 0 = choose better scalefactor compression tables and smart preemphasing */ +#define ORG_OUTER_LOOP 0 /* 0 = differ between marked as "been amplified" and "should be amplified" */ +#define ORG_HIGHEST_SFB 1 /* 0 = cut off highest frequencies (in last scale factor band) */ + +#define CHECK_TJ_OVERFLOW 1 /* 1 = check for huffman table overflow */ + + + + + +#define infinity 99999999 + + + + + +#include +#include +#include +#include + +#include "system.h" +#include "common.h" + +#include "l3side.h" +#include "l3psy.h" +#include "huffman.h" +#include "l3bitstream.h" +#include "reservoir.h" +#include "loop.h" +#include "loop-pvt.h" + + + + + +#if ORG_HUFFMAN_CODING +static void tiny_single_Huffman_2 /* Escape tables */ +( + unsigned start, + unsigned end, + unsigned table0, /* 15... */ + unsigned *choice, + unsigned *sum +); +#endif + + + +static int amplify_short (void); +static int amplify_long +( + int iteration +); + + + + + +int my_nint (double in) +{ + + if (in < 0) + return (int)(in - 0.5); + else + return (int)(in + 0.5); +} + + + + + +/* + Here are MPEG1 Table B.8 and MPEG2 Table B.1 + -- Layer III scalefactor bands. + Index into this using a method such as: + idx = fr_ps->header->sampling_frequency + + (fr_ps->header->version * 3) +*/ + +struct scalefac_struct sfBandIndex[3] = +{ + { /* Table B.8.b: 44.1 kHz */ + {0,4,8,12,16,20,24,30,36,44,52,62,74,90,110,134,162,196,238,288,342,418,576}, + {0,4,8,12,16,22,30,40,52,66,84,106,136,192} + }, + { /* Table B.8.c: 48 kHz */ + {0,4,8,12,16,20,24,30,36,42,50,60,72,88,106,128,156,190,230,276,330,384,576}, + {0,4,8,12,16,22,28,38,50,64,80,100,126,192} + }, + { /* Table B.8.a: 32 kHz */ + {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576}, + {0,4,8,12,16,22,30,42,58,78,104,138,180,192} + } +}; + + + +/* + The following table is used to implement the scalefactor + partitioning for MPEG2 as described in section + 2.4.3.2 of the IS. The indexing corresponds to the + way the tables are presented in the IS: + + [table_number][row_in_table][column of nr_of_sfb] +*/ + +static unsigned nr_of_sfb_block[6][3][4] = +{ + { + { 6, 5, 5, 5}, + { 9, 9, 9, 9}, + { 6, 9, 9, 9} + }, + { + {6, 5, 7, 3}, + {9, 9, 12, 6}, + {6, 9, 12, 6} + }, + { + {11,10, 0, 0}, + {18,18, 0, 0}, + {15,18, 0, 0} + }, + { + { 7, 7, 7, 0}, + {12,12,12, 0}, + { 6,15,12, 0} + }, + { + { 6, 6, 6, 3}, + {12, 9, 9, 6}, + { 6,12, 9, 6} + }, + { + { 8, 8, 5, 0}, + {15,12, 9, 0}, + { 6,18, 9, 0} + } +}; + + + +/* Table B.6: layer3 preemphasis */ +int pretab[21] = +{ + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, + 1, 2, 2, 3, 3, 3, 2 +}; + + + +/* This is the scfsi_band table from 2.4.2.7 of the IS */ +int scfsi_band_long[5] = { 0, 6, 11, 16, 21 }; + + + +int *scalefac_band_long; +int *scalefac_band_short; + +int fInit_iteration_loop; + +#if ORG_BINARY_SEARCH || ORG_QUANTANF_INIT || CHECK_TJ_OVERFLOW +int tjBitOverflow2; +#endif + + +/* We need this initialization here since some compilers chokes on the + the declaration if it constains an initialization that point directly + into a struct. +*/ + +void fixStatic_loop( void ) +{ + scalefac_band_long = &sfBandIndex[0].l[0]; + scalefac_band_short = &sfBandIndex[0].s[0]; +} + + + + + +/* ======================================================================== */ +/* generating the power tables */ +/* ======================================================================== */ + + + +#define BOT 200 +#define POW216_MAX (BOT/2 * 16) +#define POW216_MIN (-25 * 16) + + + +static double pow216_space[POW216_MAX-POW216_MIN+1]; +static double *pow216 = pow216_space - POW216_MIN; +static double noisePowTab[8191+15]; + + + +void genNoisePowTab (void) +{ + int i; + + for (i = POW216_MIN; i <= POW216_MAX; i++) + pow216[i] = pow (2.0, (double)i/16.0); + + for (i = 0; i < 8191+15; i++) + noisePowTab[i] = pow (i, 4.0/3.0); +} + + + + + +/* ======================================================================== */ +/* static variables */ +/* ======================================================================== */ + + + +static int gr; /* the current granule */ +static int ch; /* the current channel */ + + + +static III_side_info_t *side_info; /* the current side information */ +static gr_info *cod_info; /* the current coding information */ + + + +static double *xr_org_l; /* the initial magnitudes of the spectral values */ +static double xr34_l[576]; /* the magnitudes powered by 3/4 */ +static int *ix_l; /* quantized values */ + +static double energy_l[SFB_LMAX]; +static double xmin_l[SFB_LMAX]; /* the allowed distortion of the scalefactor band */ +static double xfsf_l[SFB_LMAX]; /* the current distortion of the scalefactor band */ +static int expo16_l[SFB_LMAX]; /* sixteen times the scale factor band exponent */ +static int *scalefac_l; /* the current scale factors */ +static int *scalefac_0_l; /* scale factors for first granule */ + +static double (*xr_org_s)[3]; /* some short block versions */ +static double (*xr34_s)[3] = (double (*)[3]) xr34_l; +static int (*ix_s)[3]; + +static double energy_s[SFB_SMAX][3]; +static double xmin_s[SFB_SMAX][3]; +static double xfsf_s[SFB_SMAX][3]; +static int expo16_s[SFB_SMAX][3]; +static int (*scalefac_s)[3]; + + + +static int max_used_sfb_l; +static int min_used_sfb_s; + +static int end_sfb_l; +static int end_sfb_s; + + + +static double xmax_l[SFB_LMAX]; /* The initial (absolute) maximum magnitude */ +static int xmax_line_l[SFB_LMAX]; /* of the long bands and their line indices */ + +static double xmax_s[SFB_SMAX][3]; /* Guess ... */ +static int xmax_line_s[SFB_SMAX][3]; + + + +static int mark_idx_l; /* speed up - partial quantizing */ +static int mark_tab_l[SFB_LMAX]; /* changed sfb-s */ + +static int mark_idx_s; +static int mark_tab_s[SFB_SMAX*3*2]; /* changed (sfb,b)-s */ + + + +#if !ORG_QUANTANF_INIT + +static int lo_quant_l [SFB_LMAX]; +static int hi_quant_l [SBMAX_l]; + +static int lo_quant_s [SFB_SMAX][3]; +static int hi_quant_s [SFB_SMAX][3]; + +static int the_lo_quant; +static int the_hi_quant; + +static double log_2, cc, dd; + +#endif + + + + + +/* ======================================================================== */ +/* iteration_loop */ +/* ======================================================================== */ + +void iteration_loop +( + double pe[][2], + double xr_org[2][2][576], + III_psy_ratio *ratio, + III_side_info_t *l3_side, + int l3_enc[2][2][576], + int mean_bits, + int stereo, + double xr_dec[2][2][576], + III_scalefac_t *scalefac, + frame_params *fr_ps, + int ancillary_pad, + int bitsPerFrame +) +{ + int max_bits; + int i, sfb, b, scfsi_band; + int mode_gr; + + int *main_data_begin; + layer *info; + + int start, end; + +#if ORG_QUANTANF_INIT + double log_sum; +#endif + double total_energy, temp, x; + + + + side_info = l3_side; + + main_data_begin = &side_info->main_data_begin; + info = fr_ps->header; + + + side_info->resvDrain = 0; + + if (!fInit_iteration_loop) + { + *main_data_begin = 0; + fInit_iteration_loop = 1; + +#if !ORG_QUANTANF_INIT + log_2 = log(2.0); + cc = 4.0/3.0 * log(8205.0 - 0.5 + 0.0946) / log_2; + dd = 4.0/3.0 * log( 1.0 - 0.5 + 0.0946) / log_2; +#endif + } + mode_gr = 2; + + scalefac_band_long = &sfBandIndex[info->sampling_frequency].l[0]; + scalefac_band_short = &sfBandIndex[info->sampling_frequency].s[0]; + + + ResvFrameBegin (fr_ps, side_info, mean_bits, bitsPerFrame); + + for (gr = 0; gr < mode_gr; gr++) + { + for (ch = 0; ch < stereo; ch++) + { + xr_org_l = xr_org[gr][ch]; + xr_org_s = (double (*)[3]) xr_org_l; + + ix_l = l3_enc[gr][ch]; + ix_s = (int (*)[3]) ix_l; + + cod_info = &side_info->gr[gr].ch[ch].tt; + + scalefac_l = scalefac->l[gr][ch]; scalefac_0_l = scalefac->l[0][ch]; + scalefac_s = scalefac->s[gr][ch]; + + + + /* reset of iteration variables */ + + for (scfsi_band = 0; scfsi_band < 4; scfsi_band++) + cod_info->slen[scfsi_band] = 0; + + cod_info->sfb_partition_table = &nr_of_sfb_block[0][0][0]; + cod_info->part2_3_length = 0; + cod_info->big_values = 0; + cod_info->count1 = 0; + cod_info->scalefac_compress = 0; + cod_info->table_select[0] = 0; + cod_info->table_select[1] = 0; + cod_info->table_select[2] = 0; + cod_info->subblock_gain[0] = 0; + cod_info->subblock_gain[1] = 0; + cod_info->subblock_gain[2] = 0; + cod_info->region0_count = 0; + cod_info->region1_count = 0; + cod_info->part2_length = 0; + cod_info->preflag = 0; + cod_info->scalefac_scale = 0; + cod_info->quantizerStepSize = 0.0; + cod_info->count1table_select = 0; + + + +/* ======== gr_deco ======== */ + + if (cod_info->window_switching_flag && (cod_info->block_type == SHORT_TYPE)) + { + if (cod_info->mixed_block_flag) + { + /* + In mixed blocks there come first 8 long scale factor band areas covering + the place normally used by the first 3 short scale factor band areas. + */ + max_used_sfb_l = cod_info->sfb_lmax = 8; + min_used_sfb_s = cod_info->sfb_smax = 3; + + /* The following values don«t need to be set again and again ... */ + cod_info->region0_count = 7; /* scalefac_band_long[7+1 ] = 36 */ + cod_info->region1_count = 13; /* scalefac_band_long[7+13+2] = 576 (no region2) */ + } + else + { + max_used_sfb_l = cod_info->sfb_lmax = 0; /* No long blocks */ + min_used_sfb_s = cod_info->sfb_smax = 0; + + /* The following values don«t need to be set again and again ... */ + cod_info->region0_count = 8; /* scalefac_band_short[(8+1 )/3] = 12 ( 12*3 = 36) */ + cod_info->region1_count = 36; /* 36? should be 29: scalefac_band_short[(8+29+2)/3] = 192 (192*3 = 576) */ + /* probably meant : scalefac_band_short[36/3 + 1 ] = 192 (192*3 = 576) */ + /* 2000-02-27 AP no effect on output because block_type != NORM_TYPE */ + } + + /* to access the entire array we need the last scalefac_band_short area */ + end_sfb_l = max_used_sfb_l; /*cod_info->sfb_lmax;*/ + end_sfb_s = SFB_SMAX; + + /* The following values don«t need to be set again and again ... */ + cod_info->count1 = 0; /* (zero_region-bigv_region) / 4; */ + cod_info->big_values = 288; /* bigv_region / 2; */ + + cod_info->count1table_select = 1; /* sum0 == sum1 == 0 */ + + cod_info->address1 = 36; /* choose one of the region0_count formulas above */ + cod_info->address2 = 576; /* bigv_region; */ + cod_info->address3 = 0; + } + else + { + max_used_sfb_l = cod_info->sfb_lmax = SBMAX_l; + min_used_sfb_s = cod_info->sfb_smax = SBMAX_s; /* No short blocks */ + + /* to access the entire array we need the last scalefac_band_long area */ + end_sfb_l = SFB_LMAX; + end_sfb_s = min_used_sfb_s; /*cod_info->sfb_smax;*/ + } + + + /* reset of iteration variables */ + + for (sfb = 0; sfb < max_used_sfb_l/*SFB_LMAX-1*/; sfb++) + scalefac_l[sfb] = 0; + for (sfb = min_used_sfb_s/*0*/; sfb < SFB_SMAX-1; sfb++) + for (b = 0; b < 3; b++) + scalefac_s[sfb][b] = 0; + +/* ======== calc_xmin and start of quantanf_init ======== */ +/* + Calculate the allowed distortion for each scalefactor band, + as determined by the psychoacoustic model. + xmin(sb) = ratio(sb) * energy(sb) / bandwidth(sb) +*/ + +#if ORG_QUANTANF_INIT + log_sum = 0.0; +#endif + total_energy = 0.0; + + for (sfb = 0; sfb < end_sfb_l; sfb++) + { + start = scalefac_band_long[sfb]; + end = scalefac_band_long[sfb+1]; + + expo16_l[sfb] = 0; + + xmax_l[sfb] = 0.0; + xmax_line_l[sfb] = start; + + temp = 0.0; +#if !ORG_HIGHEST_SFB + if (sfb < max_used_sfb_l) + { +#endif + for (i = start; i < end; i++) + { + if ((x = fabs(xr_org_l[i])) != 0.0) + { + xr34_l[i] = sqrt(x * sqrt(x)); + temp += x*x; +# if ORG_QUANTANF_INIT + log_sum += log(x); +# endif + if (x > xmax_l[sfb]) + { + xmax_l[sfb] = x; + xmax_line_l[sfb] = i; + } + } + else + xr34_l[i] = 0.0; + } +#if !ORG_HIGHEST_SFB + } + else /* cut off the (highest frequency) entries in the unused scale factor band */ + { + for (i = start; i < end; i++) + xr34_l[i] = 0.0; + } +#endif + total_energy += energy_l[sfb] = temp; + + if (sfb < max_used_sfb_l) + xmin_l[sfb] = ratio->l[gr][ch][sfb] * temp; + } + + for (sfb = min_used_sfb_s; sfb < end_sfb_s; sfb++) + { + start = scalefac_band_short[sfb]; + end = scalefac_band_short[sfb+1]; + + for (b = 0; b < 3; b++) + { + expo16_s[sfb][b] = 0; + + xmax_s[sfb][b] = 0.0; + xmax_line_s[sfb][b] = start; + + temp = 0.0; +#if !ORG_HIGHEST_SFB + if (sfb < SBMAX_s) + { +#endif + for (i = start; i < end; i++) + { + if ((x = fabs(xr_org_s[i][b])) != 0.0) + { + xr34_s[i][b] = sqrt(x * sqrt(x)); + temp += x*x; +#if ORG_QUANTANF_INIT + log_sum += log(x); +#endif + if (x > xmax_s[sfb][b]) + { + xmax_s[sfb][b] = x; + xmax_line_s[sfb][b] = i; + } + } + else + xr34_s[i][b] = 0.0; + } +#if !ORG_HIGHEST_SFB + } + else /* cut off the (highest frequency) entries in the unused scale factor band */ + { + for (i = start; i < end; i++) + xr34_s[i][b] = 0.0; + } +#endif + total_energy += energy_s[sfb][b] = temp; + + if (sfb < SFB_SMAX-1) + xmin_s[sfb][b] = ratio->s[gr][ch][sfb][b] * temp; + } + } + + +/* ======== calc_scfsi ======== */ + + /* None of the granules contains short blocks */ + if (!cod_info->window_switching_flag || (cod_info->block_type != SHORT_TYPE)) + { + if (gr == 1) + { + for (scfsi_band = 0; scfsi_band < 4; scfsi_band++) + side_info->scfsi[ch][scfsi_band] = 0; + } + } + + + + /* calculation of number of available bit( per granule ) */ + max_bits = ResvMaxBits (fr_ps, side_info, &pe[gr][ch], mean_bits); + + + + /* all spectral values zero ? */ + if (total_energy != 0.0) + { + + + +#if ORG_QUANTANF_INIT + +/* ======== quantanf_init (remaining) ======== */ + +#define system_const 8.0 +#define minlimit -100.0 + + temp = my_nint (system_const * (log_sum/288.0 - log(total_energy/576.0))); + if (temp < minlimit) + temp = minlimit; + /* + SS 19-12-96. Starting value of + global_gain or quantizerStepSize + has to be reduced for iteration_loop + */ + temp -= 70.0; + + cod_info->quantizerStepSize = temp; + +#else /* ORG_QUANTANF_INIT */ + + double xmax, the_xmax; + + the_lo_quant = -infinity; /* "-infinity" */ + the_hi_quant = -infinity; /* the real maximum for high_quant is about +4 ! */ + + the_xmax = -1.0; + + for (sfb = 0; sfb < end_sfb_l; sfb++) + { + xmax = xmax_l[sfb]; + if (xmax == 0.0) + { + lo_quant_l[sfb] = -infinity; + hi_quant_l[sfb] = -infinity; + } + else + { + lo_quant_l[sfb] = floor (4.0 * (log(xmax)/log_2 - cc)) + 1; + hi_quant_l[sfb] = floor (4.0 * (log(xmax)/log_2 - dd)) + 1; + + if (xmax > the_xmax) + { + the_xmax = xmax; + the_lo_quant = lo_quant_l[sfb]; + the_hi_quant = hi_quant_l[sfb]; + } + } + } + + for (sfb = min_used_sfb_s; sfb < end_sfb_s; sfb++) + { + for (b = 0; b < 3; b++) + { + xmax = xmax_s[sfb][b]; + if (xmax == 0.0) + { + lo_quant_s[sfb][b] = -infinity; + hi_quant_s[sfb][b] = -infinity; + } + else + { + lo_quant_s[sfb][b] = floor (4.0 * (log(xmax)/log_2 - cc) /* - 8 * cod_info->subblock_gain[b] */) + 1; + hi_quant_s[sfb][b] = floor (4.0 * (log(xmax)/log_2 - dd) /* - 8 * cod_info->subblock_gain[b] */) + 1; + + if (xmax > the_xmax) + { + the_xmax = xmax; + the_lo_quant = lo_quant_s[sfb][b]; + the_hi_quant = hi_quant_s[sfb][b]; + } + } + } + } + + + /* + Try the power table at its least boundary + I«ve never reached this deep before! + */ + assert (the_lo_quant > -POW216_MAX); + + cod_info->quantizerStepSize = the_lo_quant; + +#endif /* ORG_QUANTANF_INIT */ + + + + cod_info->part2_3_length = outer_loop (max_bits, fr_ps); + } + + ResvAdjust (fr_ps, cod_info, side_info, mean_bits); + + cod_info->global_gain = my_nint (cod_info->quantizerStepSize + 210.0); +/* assert (cod_info->global_gain < 256); */ + } /* for ch */ + } /* for gr */ + + ResvFrameEnd (fr_ps, side_info, mean_bits); +} + + + + + +/* ======================================================================== */ +/* outer_loop */ +/* ======================================================================== */ +/* + The outer iteration loop controls the masking conditions + of all scalefactorbands. It computes the best scalefac and + global gain. This module calls the inner iteration loop +*/ + +static int outer_loop +( + int max_bits, + frame_params *fr_ps +) +{ + int scalesave_l[SFB_LMAX-1]; + int scalesave_s[SFB_SMAX-1][3]; + int bits, huff_bits, save_preflag, save_compress, save_part2_length; + int sfb, b, over, iteration; + + + /* reset the pointers of our changed sfb [(sfb,b)] indices list */ + mark_idx_l = mark_idx_s = 0; + + +#if 0 + cod_info->preflag = 0; /* assignments are all done in iteration_loop() */ + cod_info->scalefac_compress = 0; /* just to show what«s going on ... */ + cod_info->part2_length = 0; /* == part2_length(fr_ps) because of slen1_tab[0] = slen2_tab[0] = 0 */ +#endif + + huff_bits = max_bits /* - cod_info->part2_length */; /* try first without scaling */ + + + iteration = 1; + + bits = bin_search_StepSize (max_bits, cod_info->quantizerStepSize); /* speeds things up a bit */ + + while (1) + { + for (sfb = 0; sfb < SFB_LMAX-1; sfb++) /* save scaling factors */ + scalesave_l[sfb] = scalefac_l[sfb]; + + for (sfb = 0; sfb < SFB_SMAX-1; sfb++) + for (b = 0; b < 3; b++) + scalesave_s[sfb][b] = scalefac_s[sfb][b]; + + save_preflag = cod_info->preflag; + save_compress = cod_info->scalefac_compress; + save_part2_length = cod_info->part2_length; + + calc_noise (); /* distortion calculation */ + + over = amplify (iteration); + +#if ORG_OUTER_LOOP +/* + misplaced break condition in original dist10: + - There is one flag only for both, marking a scalefactor band as + "should be amplified" or marking it as "is amplified", namely + a corresponding scalefactor greater than zero! + - The desired amplification of the scalefactors bands marked as + "should be amplified" is actually not done before the next call + to quantize(), respectively partial_quantize(). + - Thus, it can happen that all scalefactor bands are marked, but + not all of the marked bands are amplified. + - Since loop_break() doesn't know that, the outer loop frequently + gets terminated to early. +*/ + if (loop_break ()) + break; +#endif + + huff_bits = max_bits - needed_bits_for_storing_scalefactors (fr_ps); + if (huff_bits < 0) + break; /* not enough space to store the scale factors */ + + + /* We have to wait checking this break condition */ + /* until needed_bits_for_storing_scalefactors() */ + /* set the scalefac compress index!!! */ + if (over == 0) + break; /* no more bands to amplify */ + + + iteration++; + + /* + Most of the times, only a few bands will be changed, + so why quantize the whole area? + */ + partial_quantize (); +#if ORG_BINARY_SEARCH || ORG_QUANTANF_INIT || CHECK_TJ_OVERFLOW +assert (!tjBitOverflow2); +#endif + bits = count_bits(); + + while (bits > huff_bits) + { + cod_info->quantizerStepSize += 1.0; + quantize (); +#if ORG_BINARY_SEARCH || ORG_QUANTANF_INIT || CHECK_TJ_OVERFLOW +assert (!tjBitOverflow2); +#endif + bits = count_bits (); + } + +#if !ORG_OUTER_LOOP + /* + A break would mean to restore the parameters of the last iteration, + but we like to accept the current state. If you want to avoid the + 'goto', you have to to take the long way home and place the loop + break condition in front of the call to calc_noise(). + */ + if (loop_break()) + goto take_that_and_party; +#endif + } + + + cod_info->preflag = save_preflag; + cod_info->scalefac_compress = save_compress; + cod_info->part2_length = save_part2_length; + + for (sfb = 0; sfb < SFB_LMAX-1; sfb++) + scalefac_l[sfb] = scalesave_l[sfb]; + + for (sfb = 0; sfb < SFB_SMAX-1; sfb++) + for (b = 0; b < 3; b++) + scalefac_s[sfb][b] = scalesave_s[sfb][b]; + +take_that_and_party: + cod_info->part2_3_length = cod_info->part2_length + bits; + + + return cod_info->part2_3_length; +} + + + + + +/* ======================================================================================== */ +/* needed_bits_for_storing_scalefactors */ +/* ======================================================================================== */ +/* + counts the bits needed to code the scale factors (cod_info->part2_length) + and the compression index (cod_info->scalefac_compress). + + If there is no suitable index, it returns "infinity". +*/ + +static int needed_bits_for_storing_scalefactors +( + frame_params *fr_ps +) +{ +#if 0 + static int slen1[16] = { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 }; + static int slen2[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }; +#endif + + /* 2^^slen1[k] */ + static int pow2_slen1[16] = { 1, 1, 1, 1, 8, 2, 2, 2, 4, 4, 4, 8, 8, 8, 16, 16}; + /* 2^^slen2[k] */ + static int pow2_slen2[16] = { 1, 2, 4, 8, 1, 2, 4, 8, 2, 4, 8, 2, 4, 8, 4, 8}; + + /* (8+9) * slen1[k] + (9+9) * slen2[k] */ + static int part2_len_m[16] = { 0, 18, 36, 54, 51, 35, 53, 71, 52, 70, 88, 69, 87,105,104,122}; + /* (9+9) * slen1[k] + (9+9) * slen2[k] */ + static int part2_len_s[16] = { 0, 18, 36, 54, 54, 36, 54, 72, 54, 72, 90, 72, 90,108,108,126}; + /* (6+5) * slen1[k] + (5+5) * slen2[k] */ + static int part2_len_l[16] = { 0, 10, 20, 30, 33, 21, 31, 41, 32, 42, 52, 43, 53, 63, 64, 74}; + + int sfb, b, k; + int max_slen1, max_slen2, *table; + + + max_slen1 = max_slen2 = 0; + + if (cod_info->window_switching_flag && (cod_info->block_type == SHORT_TYPE)) + { + if (cod_info->mixed_block_flag) + { + table = part2_len_m; + + for (sfb = 0; sfb < 8; sfb++) + if (scalefac_l[sfb] > max_slen1) + max_slen1 = scalefac_l[sfb]; + + for (sfb = 3; sfb < 6; sfb++) + for (b = 0; b < 3; b++) + if (scalefac_s[sfb][b] > max_slen1) + max_slen1 = scalefac_s[sfb][b]; + } + else + { + table = part2_len_s; + + for (sfb = 0; sfb < 6; sfb++) + for (b = 0; b < 3; b++) + if (scalefac_s[sfb][b] > max_slen1) + max_slen1 = scalefac_s[sfb][b]; + } + + for (sfb = 6; sfb < 12/*SBMAX_s*/; sfb++) + for (b = 0; b < 3; b++) + if (scalefac_s[sfb][b] > max_slen2) + max_slen2 = scalefac_s[sfb][b]; + } + else + { + table = part2_len_l; + + for (sfb = 0; sfb < 11; sfb++) + if (scalefac_l[sfb] > max_slen1) + max_slen1 = scalefac_l[sfb]; + + +#if ORG_SCF_COMPRESS && !ORG_PREEMPHASING + /* This was seen in LAME */ + if (!cod_info->preflag) + { + for (sfb = 11; sfb < SBMAX_l; sfb++) + if (scalefac_l[sfb] < (1 + cod_info->scalefac_scale) * pretab[sfb]) + break; + + if (sfb == SBMAX_l) + { + for (sfb = 11; sfb < SBMAX_l; sfb++) + scalefac_l[sfb] -= (1 + cod_info->scalefac_scale) * pretab[sfb]; + cod_info->preflag = 1; + } + } +#endif + + + for (sfb = 11; sfb < 21/*SBMAX_l*/; sfb++) + if (scalefac_l[sfb] > max_slen2) + max_slen2 = scalefac_l[sfb]; + } + + + cod_info->part2_length = infinity; + + for (k = 0; k < 16; k++) + { + if (max_slen1 < pow2_slen1[k] && max_slen2 < pow2_slen2[k]) + { +#if ORG_SCF_COMPRESS + cod_info->scalefac_compress = k; + cod_info->part2_length = table[k]; + break; +#else + if (cod_info->part2_length > table[k]) + { + cod_info->scalefac_compress = k; + cod_info->part2_length = table[k]; + } +#endif + } + } + + + return cod_info->part2_length; +} + + + + + +/* ======================================================================================== */ +/* calc_noise */ +/* ======================================================================================== */ +/* + calculates the distortion introduced by the qunatization + in each scale factor band. +*/ +static void calc_noise (void) +{ + int i, b, sfb, start, end, off; + double f, sum, temp; + + + off = -4 * (int)cod_info->quantizerStepSize; + + + for (sfb = 0; sfb < max_used_sfb_l; sfb++) + { + if (ix_l[xmax_line_l[sfb]] == 0) /* quantized values all zero? */ + { + xfsf_l[sfb] = energy_l[sfb]; /* see calculation of xmin_l */ + } + else + { + start = scalefac_band_long[sfb]; + end = scalefac_band_long[sfb+1]; + + sum = 0.0; + + f = pow216[expo16_l[sfb] + off]; + + for (i = start; i < end; i++) + { + temp = fabs(xr_org_l[i]) - noisePowTab[ix_l[i]] / f; + sum += temp * temp; + } + + xfsf_l[sfb] = sum; + } + } + + for (b = 0; b < 3; b++) + { + off = -4 * ((int)cod_info->quantizerStepSize + 8 * cod_info->subblock_gain[b]); + + for (sfb = min_used_sfb_s; sfb < SFB_SMAX-1; sfb++) + { + if (ix_s[xmax_line_s[sfb][b]] == 0) /* quantized values all zero? */ + { + xfsf_s[sfb][b] = energy_s[sfb][b]; /* see calculation of xmin_s */ + } + else + { + start = scalefac_band_short[sfb]; + end = scalefac_band_short[sfb+1]; + + sum = 0.0; + + f = pow216[expo16_s[sfb][b] + off]; + + for (i = start; i < end; i++) + { + temp = fabs(xr_org_s[i][b]) - noisePowTab[ix_s[i][b]] / f; + sum += temp * temp; + } + + xfsf_s[sfb][b] = sum; + } + } + } +} + + + + + +/* ======================================================================================== */ +/* loop_break */ +/* ======================================================================================== */ +/* + returns zero if there is a scalefac which has not been amplified. + Otherwise it returns one. +*/ + +static int loop_break (void) +{ + int sfb, b; + + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) + if (scalefac_l[sfb] == 0) + return 0; + + for (sfb = min_used_sfb_s; sfb < 12; sfb++) + for (b = 0; b < 3; b++) + if (scalefac_s[sfb][b] == 0) + return 0; + + return 1; +} + + + + + +/* ======================================================================================== */ +/* preemphasing and amplifying */ +/* ======================================================================================== */ +/* + Preemphasing: see ISO 11172-3 section C.1.5.4.3.4 + Amplifying : see ISO 11172-3 section C.1.5.4.3.5 + + amplifying the scalefactor bands that violate the masking threshold. +*/ + +static int amplify +( + int iteration +) +{ + if (cod_info->window_switching_flag && cod_info->block_type == SHORT_TYPE) + return amplify_short (); + else + return amplify_long (iteration); +} + + + + + +static int amplify_short (void) +{ + int sfb, b, over, expo16_off; + + expo16_off = 16 * (1 + cod_info->scalefac_scale) / 2; + over = 0; + +#ifdef MIXED_BLOCKS + for (sfb = 0; sfb < max_used_sfb_l; sfb++) + { + if (xfsf_l[sfb] > xmin_l[sfb]) + { + scalefac_l[sfb]++; + expo16_l[sfb] += expo16_off; + over++; + mark_tab_l[mark_idx_l++] = sfb; + } + } +#endif + + for (sfb = min_used_sfb_s; sfb < SBMAX_s; sfb++) + { + for (b = 0; b < 3; b++) + { + if (xfsf_s[sfb][b] > xmin_s[sfb][b]) + { + scalefac_s[sfb][b]++; + expo16_s[sfb][b] += expo16_off; + over++; + mark_tab_s[mark_idx_s++] = sfb; + mark_tab_s[mark_idx_s++] = b; + } + } + } + + return over; +} + + + + + +static int amplify_long +( + int iteration +) +{ + int pre_expo_off[SFB_LMAX]; + + int sfb, stop_at, over = 0; + int expo16_off; + + + stop_at = max_used_sfb_l; + + expo16_off = 16 * (1 + cod_info->scalefac_scale) / 2; + + + /* + Preemphasis is switched on if in all the upper four scalefactor + bands the actual distortion exceeds the threshold after the + first call of the inner loop. + + Original bug of dist10 - preemphasis() didn't know 'iteration'!!! + */ +#if !ORG_PREEMPHASING + if (iteration == 1) +#endif + if (!cod_info->preflag) + { + for (sfb = max_used_sfb_l-4; sfb < max_used_sfb_l; sfb++) + if (xfsf_l[sfb] <= xmin_l[sfb]) + goto no_preemphasing; + + cod_info->preflag = 1; + + stop_at = 11; /* pretab[sfb] = 0 for sfb = 0..10 */ + + for (sfb = stop_at; sfb < max_used_sfb_l; sfb++) + { + expo16_l[sfb] += pre_expo_off[sfb] = expo16_off * pretab[sfb]; + + mark_tab_l[mark_idx_l++] = sfb; + } + } + + +no_preemphasing: + + + for (sfb = 0; sfb < stop_at; sfb++) + { + if (xfsf_l[sfb] > xmin_l[sfb]) + { + over++; + expo16_l[sfb] += expo16_off; + scalefac_l[sfb]++; + + mark_tab_l[mark_idx_l++] = sfb; + } + } + for (sfb = stop_at; sfb < max_used_sfb_l; sfb++) /* The just preemphased bands have to be treated differently */ + { + if (xfsf_l[sfb] > xmin_l[sfb] * pow216[2*pre_expo_off[sfb]]) + { + over++; + expo16_l[sfb] += expo16_off; + scalefac_l[sfb]++; + } + } + + + return over; +} + + + + + +/* ======================================================================== */ +/* quantize */ +/* ======================================================================== */ +/* + Quantization of the vector xr ( -> ix) +*/ + +static int INLINE cutting_crew (FLOAT in) +{ + int retVal; + + retVal = (int) (in + 0.4054); + +#if ORG_BINARY_SEARCH || ORG_QUANTANF_INIT || CHECK_TJ_OVERFLOW + if (retVal > 8191+14) + tjBitOverflow2 = TRUE; +#endif + + return retVal; +} + + + +static void quantize (void) +{ + int sfb, i, b, start, end; + double f, z, y; + + for (sfb = 0; sfb < end_sfb_l; sfb++) + { + start = scalefac_band_long[sfb]; + end = scalefac_band_long[sfb+1]; + + /* (expo16_l[sfb] - 16/4 * quant_step) * 3/4 */ + f = pow216[(expo16_l[sfb]/4 - (int)cod_info->quantizerStepSize) * 3]; + + for (i = start; i < end; i += 2) + { + z = xr34_l[i ] * f; + y = xr34_l[i+1] * f; + ix_l[i ] = cutting_crew (z); + ix_l[i+1] = cutting_crew (y); + } + } + + for (sfb = min_used_sfb_s; sfb < end_sfb_s; sfb++) + { + start = scalefac_band_short[sfb]; + end = scalefac_band_short[sfb+1]; + + for (b = 0; b < 3; b++) + { + /* (expo_s[sfb][b] - 16/4 * (quant_step + 8 * cod_info->subblock_gain[b])) * 3/4 */ + f = pow216[(expo16_s[sfb][b] / 4 - (int)cod_info->quantizerStepSize - 8 * cod_info->subblock_gain[b]) * 3]; + + for (i = start; i < end; i += 2) + { + z = xr34_s[i ][b] * f; + y = xr34_s[i+1][b] * f; + ix_s[i ][b] = cutting_crew (z); + ix_s[i+1][b] = cutting_crew (y); + } + } + } +} + + + +static void partial_quantize (void) +{ + int sfb, i, b, start, end; + double f, z, y; + + while (mark_idx_l) + { + sfb = mark_tab_l[--mark_idx_l]; + + start = scalefac_band_long[sfb]; + end = scalefac_band_long[sfb+1]; + + /* (expo16_l[sfb] - 16/4 * quant_step) * 3/4 */ + f = pow216[(expo16_l[sfb]/4 - (int)cod_info->quantizerStepSize) * 3]; + + for (i = start; i < end; i += 2) + { + z = xr34_l[i ] * f; + y = xr34_l[i+1] * f; + ix_l[i ] = cutting_crew (z); + ix_l[i+1] = cutting_crew (y); + } + } + + while (mark_idx_s) + { + b = mark_tab_s[--mark_idx_s]; + sfb = mark_tab_s[--mark_idx_s]; + + start = scalefac_band_short[sfb]; + end = scalefac_band_short[sfb+1]; + + /* (expo_16s[sfb][b] - 16/4 * (quant_step + 8 * cod_info->subblock_gain[b])) * 3/4 */ + f = pow216[(expo16_s[sfb][b] / 4 - (int)cod_info->quantizerStepSize - 8 * cod_info->subblock_gain[b]) * 3]; + + for (i = start; i < end; i += 2) + { + z = xr34_s[i ][b] * f; + y = xr34_s[i+1][b] * f; + ix_s[i ][b] = cutting_crew (z); + ix_s[i+1][b] = cutting_crew (y); + } + } +} + + + + + +/* ======================================================================== */ +/* count_bits */ +/* ======================================================================== */ + +struct +{ + unsigned region0_count; + unsigned region1_count; +} subdv_table[ 23 ] = +{ + {0, 0}, /* 0 bands */ + {0, 0}, /* 1 bands */ + {0, 0}, /* 2 bands */ + {0, 0}, /* 3 bands */ + {0, 0}, /* 4 bands */ + {0, 1}, /* 5 bands */ + {1, 1}, /* 6 bands */ + {1, 1}, /* 7 bands */ + {1, 2}, /* 8 bands */ + {2, 2}, /* 9 bands */ + {2, 3}, /* 10 bands */ + {2, 3}, /* 11 bands */ + {3, 4}, /* 12 bands */ + {3, 4}, /* 13 bands */ + {3, 4}, /* 14 bands */ + {4, 5}, /* 15 bands */ + {4, 5}, /* 16 bands */ + {4, 6}, /* 17 bands */ + {5, 6}, /* 18 bands */ + {5, 6}, /* 19 bands */ + {5, 7}, /* 20 bands */ + {6, 7}, /* 21 bands */ + {6, 7}, /* 22 bands */ +}; + + + +/* + Calculation of rzero, count1, big_values + (Partitions ix into big values, quadruples and zeros). + + Determines the number of bits to encode the quadruples. + + Presumable subdivides the bigvalue region which will + use separate Huffman tables. + + Select huffman code tables for bigvalues regions + + Count the number of bits necessary to code the bigvalues region. +*/ + +static int count_bits (void) +{ + cod_info->table_select[0] = 0; + cod_info->table_select[1] = 0; + cod_info->table_select[2] = 0; + + if (cod_info->window_switching_flag && (cod_info->block_type == SHORT_TYPE)) + return count_bits_short (); + else + return count_bits_long (); +} + + + + + +static int count_bits_short (void) +{ + unsigned int bits = 0; + + /* + Within each scalefactor band, data is given for successive + time windows, beginning with window 0 and ending with window 2. + Within each window, the quantized values are then arranged in + order of increasing frequency... + */ + int sfb, b; + unsigned int max, temp; + + + /* + the first part --- 8 long blocks or 3 short blocks + */ + + max = 0; +#ifdef MIXED_BLOCKS + if (cod_info->mixed_block_flag) + { + for (sfb = 0; sfb < 8; sfb++) + if ((temp = ix_l[xmax_line_l[sfb]]) > max) + max = temp; + choose_table_long (0, 36, max, &cod_info->table_select[0], &bits); + } + else +#endif + { + for (sfb = 0; sfb < 3; sfb++) + for (b = 0; b < 3; b++) + if ((temp = ix_s[xmax_line_s[sfb][b]][b]) > max) + max = temp; + choose_table_short (0, 3, max, &cod_info->table_select[0], &bits); + } + + + /* + the second part --- short blocks only + */ + + max = 0; + for (sfb = 3; sfb < SFB_SMAX; sfb++) + for (b = 0; b < 3; b++) + if ((temp = ix_s[xmax_line_s[sfb][b]][b]) > max) + max = temp; + choose_table_short (3, SFB_SMAX, max, &cod_info->table_select[1], &bits); + + return bits; +} + + + + + +static int count_bits_long (void) +{ + int zero_region; + int bigv_region; + + unsigned bits = 0; + int sum0 = 0; + int sum1 = 0; + + int sfb_anz, index0, index1, sfb, i; + unsigned max, temp; + + int p; + + + for (zero_region = 576; zero_region > 1; zero_region -= 2) + if (ix_l[zero_region-1]) break; + else if (ix_l[zero_region-2]) break; + + for (bigv_region = zero_region; bigv_region > 3; bigv_region -= 4) + { + if (ix_l[bigv_region-1] > 1) break; + else if (ix_l[bigv_region-2] > 1) break; + else if (ix_l[bigv_region-3] > 1) break; + else if (ix_l[bigv_region-4] > 1) break; + + p = 0; + if (ix_l[bigv_region-1]) bits++, p |= 8; + if (ix_l[bigv_region-2]) bits++, p |= 4; + if (ix_l[bigv_region-3]) bits++, p |= 2; + if (ix_l[bigv_region-4]) bits++, p |= 1; + + sum0 += ht[32].hlen[p]; + sum1 += ht[33].hlen[p]; + } + + cod_info->count1 = (zero_region-bigv_region) / 4; + cod_info->big_values = bigv_region / 2; + + if (sum0 < sum1) + { + bits += sum0; + cod_info->count1table_select = 0; + } + else + { + bits += sum1; + cod_info->count1table_select = 1; + } + + if (bigv_region) + { + sfb_anz = 1; + while (scalefac_band_long[sfb_anz] < bigv_region) + sfb_anz++; + + if (cod_info->window_switching_flag) /* START_TYPE, STOP_TYPE */ + { + index0 = (cod_info->region0_count = 7) + 1; + cod_info->region1_count = 13; + index1 = sfb_anz - index0; if (index0 + index1 < 22) index1++; + + cod_info->address1 = 36; + cod_info->address2 = bigv_region; + cod_info->address3 = 0; + } + else /* NORM_TYPE */ + { + index0 = (cod_info->region0_count = subdv_table[sfb_anz].region0_count) + 1; + index1 = (cod_info->region1_count = subdv_table[sfb_anz].region1_count) + 1; + + cod_info->address1 = scalefac_band_long[index0]; + cod_info->address2 = scalefac_band_long[index0 + index1]; + cod_info->address3 = bigv_region; + } + + if (cod_info->address1 > 0) + { + max = 0; + for (sfb = 0; sfb < index0; sfb++) + if ((temp = ix_l[xmax_line_l[sfb]]) > max) + max = temp; + choose_table_long (0, cod_info->address1, max, &cod_info->table_select[0], &bits); + } + + if (cod_info->address2 > cod_info->address1) + { + max = 0; + for (sfb = index0; sfb < index0+index1; sfb++) + if ((temp = ix_l[xmax_line_l[sfb]]) > max) + max = temp; + choose_table_long (cod_info->address1, cod_info->address2, max, &cod_info->table_select[1], &bits); + } + + if (bigv_region > cod_info->address2) + { + max = 0; + for (sfb = index0+index1; sfb < sfb_anz-1; sfb++) + if ((temp = ix_l[xmax_line_l[sfb]]) > max) + max = temp; + for (i = scalefac_band_long[sfb_anz-1]; i < bigv_region; i++) + if ((temp = ix_l[i]) > max) + max = temp; + choose_table_long (cod_info->address2, bigv_region, max, &cod_info->table_select[2], &bits); + } + } + else + { /* no big_values region */ + cod_info->region0_count = 0; + cod_info->region1_count = 0; + + cod_info->address1 = 0; + cod_info->address2 = 0; + cod_info->address3 = 0; + } + + + return bits; +} + + + + + +/* ======================================================================== */ +/* bin_search_step_size */ +/* ======================================================================== */ +/* + The following optional code written by Seymour Shlien + will speed up the outer_loop code which is called + by iteration_loop. When BIN_SEARCH is defined, the + outer_loop function precedes the call to the function inner_loop + with a call to bin_search gain defined below, which + returns a good starting quantizerStepSize. + + The function count_bits() [a sequence of statements, originally part of inner_loop()] + was completely rewritten. + + + changed the behaviour: + now, it returns the found number of bits <= desired_rate +*/ + +static int bin_search_StepSize +( + int desired_rate, + double start +) +{ + int bits; + + int top = start; +#if ORG_BINARY_SEARCH || ORG_QUANTANF_INIT + int bot = 200; +#else + int bot = the_hi_quant; +#endif + int next = start; + +#if ORG_BINARY_SEARCH + + int last; + + do + { + last = next; + next = (top + bot) / 2; + cod_info->quantizerStepSize = next; + + tjBitOverflow2 = FALSE; + quantize (); + if (tjBitOverflow2) + bits = infinity; + else + bits = count_bits (); + + if (bits > desired_rate) + top = next; + else + bot = next; + } + while ((bits != desired_rate) && (abs(last-next) > 1)); + +#else /* ORG_BINARY_SEARCH */ + + do + { + next = top + (bot - top) / 2; + cod_info->quantizerStepSize = next; + +#if ORG_BINARY_SEARCH || ORG_QUANTANF_INIT || CHECK_TJ_OVERFLOW + tjBitOverflow2 = FALSE; + quantize (); + if (tjBitOverflow2) + bits = infinity; + else + bits = count_bits (); +#else + quantize (); + bits = count_bits (); +#endif + + if (bits > desired_rate) + top = next + 1; + else + bot = next; + } + while (top < bot); + +#endif /* ORG_BINARY_SEARCH */ + + if (bits > desired_rate) + { + cod_info->quantizerStepSize = next+1; +#if ORG_BINARY_SEARCH || ORG_QUANTANF_INIT || CHECK_TJ_OVERFLOW + tjBitOverflow2 = FALSE; + quantize (); +assert(! tjBitOverflow2); +#else + quantize (); +#endif + bits = count_bits (); +assert(bits <= desired_rate); + } + + return bits; + +} + + + + + +/* ======================================================================================== */ +/* choose_table_long */ +/* ======================================================================================== */ +/* + Choose the Huffman table that will encode ix[start..end] with the fewest + bits and increases the bit_sum by the amount of these bits. + + Note: This code contains knowledge about the sizes and characteristics + of the Huffman tables as defined in the IS (Table B.7), and will not work + with any arbitrary tables. +*/ +static void choose_table_long +( + unsigned start, + unsigned end, + unsigned max, + unsigned *table, + unsigned *bit_sum +) +{ + unsigned choice0, choice1; + + + if (max == 0) + { + *table = 0; + return; + } + + if (max < 15) + { + choice0 = 1; /* we can start with 1 because ht[0].xlen == 0 <= max */ + while (ht[choice0].xlen <= max) + choice0++; + + switch (choice0) + { + case 1: single_Huffman (start, end,/* 1 */ table, bit_sum); break; + case 2: double_Huffman (start, end, 2, 3, table, bit_sum); break; + case 5: double_Huffman (start, end, 5, 6, table, bit_sum); break; + case 7: triple_Huffman (start, end, 7, 8, 9, table, bit_sum); break; + case 10: triple_Huffman (start, end, 10, 11, 12, table, bit_sum); break; + case 13: double_Huffman (start, end, 13, 15, table, bit_sum); break; + } + } +#if !ORG_HUFFMAN_CODING /* no part of original BladeEnc */ + else if (max == 15) + { + triple_Huffman_2 (start, end,/* 13, 15, 24, */ table, bit_sum); + } +#endif + else + { + max -= 15; + +#if ORG_HUFFMAN_CODING + choice0 = 15; while (ht[choice0].linmax < max) choice0++; +#else + choice0 = 16; while (ht[choice0].linmax < max) choice0++; +#endif + +assert(choice0 < 24); + choice1 = 24; while (ht[choice1].linmax < max) choice1++; +assert(choice1 < 32); + +#if ORG_HUFFMAN_CODING + double_Huffman_2 (start, end, choice1, choice0, table, bit_sum); +#else + double_Huffman_2 (start, end, choice0, choice1, table, bit_sum); +#endif + } +} + + + + + +/* ======================================================================================== */ +/* choose_table_short */ +/* ======================================================================================== */ +/* + Choose the Huffman table that will encode ix[start_sfb..end_sfb][0..2] + with the fewest bits and increases the bit_sum by the amount of these bits. + + Note: This code contains knowledge about the sizes and characteristics + of the Huffman tables as defined in the IS (Table B.7), and will not work + with any arbitrary tables. +*/ + +static void choose_table_short +( + unsigned start_sfb, + unsigned end_sfb, + unsigned max, + unsigned *table, + unsigned *bit_sum +) +{ + unsigned choice0; +#if !ORG_HUFFMAN_CODING + unsigned choice1; +#endif + int start, end; + + start = 3 * scalefac_band_short[start_sfb]; + end = 3 * scalefac_band_short[ end_sfb]; + + if (max == 0) + { + *table = 0; + return; + } + + if (max < 15) + { + choice0 = 1; /* we can start with 1 because ht[0].xlen == 0 <= max */ + while (ht[choice0].xlen <= max) + choice0++; + +#if ORG_HUFFMAN_CODING + tiny_single_Huffman (start, end, choice0, table, bit_sum); +#else + switch (choice0) + { + case 1: tiny_single_Huffman (start, end,/* 1 */ table, bit_sum); break; + case 2: tiny_double_Huffman (start, end, 2, 3, table, bit_sum); break; + case 5: tiny_double_Huffman (start, end, 5, 6, table, bit_sum); break; + case 7: tiny_triple_Huffman (start, end, 7, 8, 9, table, bit_sum); break; + case 10: tiny_triple_Huffman (start, end, 10, 11, 12, table, bit_sum); break; + case 13: tiny_double_Huffman (start, end, 13, 15, table, bit_sum); break; + } +#endif + } +#if !ORG_HUFFMAN_CODING /* no part of original BladeEnc */ + else if (max == 15) + { + tiny_triple_Huffman_2 (start, end,/* 13, 15, 24, */ table, bit_sum); + } +#endif + else + { + max -= 15; + +#if ORG_HUFFMAN_CODING + + choice0 = 15; while (ht[choice0].linmax < max) choice0++; +assert(choice0 < 24); + tiny_single_Huffman_2 (start, end, choice0, table, bit_sum); + +#else + + choice0 = 16; while (ht[choice0].linmax < max) choice0++; +assert(choice0 < 24); + choice1 = 24; while (ht[choice1].linmax < max) choice1++; +assert(choice1 < 32); + tiny_double_Huffman_2 (start, end, choice0, choice1, table, bit_sum); + +#endif + } +} + + + + + +/* ======================================================================================== */ +/* Huffmania */ +/* ======================================================================================== */ + + + +/* + That case, we don«t need to decide which is the best table. +*/ + +static void single_Huffman +( + unsigned start, + unsigned end, +/* unsigned table0, == 1 */ + unsigned *choice, + unsigned *sum +) +{ +/* + int v; +*/ + unsigned bits0, signs, idx; + + static struct huffcodetab *h0 = ht + /* table0 */ 1; /* static because of the constant!!! */ + +#if 0 /* not needed */ + static unsigned ylen = h0->ylen; /* == 2 */ +#endif + + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = signs = 0; + + while (pos < fin) + { + idx = 0; +#if 0 + v = *pos++; if (v) {signs++; idx = v /* * ylen */ + v;} + v = *pos++; if (v) {signs++; idx += v;} +#else + if (*pos++) {signs++; idx = 2;} + if (*pos++) {signs++; idx++;} +#endif + bits0 += h0->hlen[idx]; + } + + *choice = /* table0 */ 1; + *sum += bits0 + signs; +} + + + +#if ORG_HUFFMAN_CODING +static void tiny_single_Huffman +( + unsigned start, + unsigned end, + unsigned table0, + unsigned *choice, + unsigned *sum +) +{ + int v0, v1, v2; + unsigned bits0, signs, idx0, idx1, idx2; + + struct huffcodetab *h0 = ht + table0; + + unsigned ylen = h0->ylen; + + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = signs = 0; + + while (pos < fin) + { + idx0 = idx1 = idx2 = 0; + + v0 = *pos++; if (v0) {signs++; idx0 = v0 * ylen;} + v1 = *pos++; if (v1) {signs++; idx1 = v1 * ylen;} + v2 = *pos++; if (v2) {signs++; idx2 = v2 * ylen;} + v0 = *pos++; if (v0) {signs++; idx0 += v0;} + v1 = *pos++; if (v1) {signs++; idx1 += v1;} + v2 = *pos++; if (v2) {signs++; idx2 += v2;} + + bits0 += h0->hlen[idx0] + h0->hlen[idx1] + h0->hlen[idx2]; + } + + *choice = table0; + *sum += bits0 + signs; +} +#else +static void tiny_single_Huffman +( + unsigned start, + unsigned end, +/* unsigned table0 == 1 */ + unsigned *choice, + unsigned *sum +) +{ +/* + int v0, v1, v2; +*/ + unsigned bits0, signs, idx0, idx1, idx2; + + static struct huffcodetab *h0 = ht + /* table0 */ 1; /* static because of the constant!!! */ + +#if 0 /* not needed */ + static unsigned ylen = h0->ylen; /* == 2 --- static because of the constant!!! */ +#endif + + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = signs = 0; + + while (pos < fin) + { + idx0 = idx1 = idx2 = 0; + + if (*pos++) {signs++; idx0 = 2;} + if (*pos++) {signs++; idx1 = 2;} + if (*pos++) {signs++; idx2 = 2;} + if (*pos++) {signs++; idx0++;} + if (*pos++) {signs++; idx1++;} + if (*pos++) {signs++; idx2++;} + + bits0 += h0->hlen[idx0] + h0->hlen[idx1] + h0->hlen[idx2]; + } + + *choice = /* table0 */ 1; + *sum += bits0 + signs; +} +#endif + + + +#if ORG_HUFFMAN_CODING +static void tiny_single_Huffman_2 /* Escape tables */ +( + unsigned start, + unsigned end, + unsigned table0, /* 15... */ + unsigned *choice, + unsigned *sum +) +{ + int v0, v1, v2; + unsigned bits0, signs, xbits, idx0, idx1, idx2; + + struct huffcodetab *h0 = ht + table0; + +#if 0 /* not needed */ + static unsigned ylen = h0->ylen; /* == h1->ylen == 16 --- static because of the constant!!! */ +#endif + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = signs = xbits = 0; + + while (pos < fin) + { + idx0 = idx1 = idx2 = 0; + + v0 = *pos++; if (v0) {if (v0 > 14) {v0 = 15; xbits++;} signs++; idx0 = v0 /* * ylen */ << 4;} + v1 = *pos++; if (v1) {if (v1 > 14) {v1 = 15; xbits++;} signs++; idx1 = v1 /* * ylen */ << 4;} + v2 = *pos++; if (v2) {if (v2 > 14) {v2 = 15; xbits++;} signs++; idx2 = v2 /* * ylen */ << 4;} + v0 = *pos++; if (v0) {if (v0 > 14) {v0 = 15; xbits++;} signs++; idx0 += v0;} + v1 = *pos++; if (v1) {if (v1 > 14) {v1 = 15; xbits++;} signs++; idx1 += v1;} + v2 = *pos++; if (v2) {if (v2 > 14) {v2 = 15; xbits++;} signs++; idx2 += v2;} + + bits0 += h0->hlen[idx0] + h0->hlen[idx1] + h0->hlen[idx2]; + } + + bits0 += xbits * h0->linbits; + + *choice = table0; + *sum += bits0 + signs; +} +#endif + + + + + +/* + The following function is called for the most maximum values below 16 (respectively 15) +*/ + +static void double_Huffman +( + unsigned start, + unsigned end, + unsigned table0, /* 2, 5, 13 */ + unsigned table1, /* 3, 6, 15 */ + unsigned *choice, + unsigned *sum +) +{ + int v; + unsigned bits0, bits1, signs, idx; + + struct huffcodetab *h0 = ht + table0; + struct huffcodetab *h1 = ht + table1; + + unsigned ylen = h0->ylen; /* == h1->ylen */ + + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = bits1 = signs = 0; + + while (pos < fin) + { + idx = 0; + v = *pos++; if (v) {signs++; idx = v * ylen;} + v = *pos++; if (v) {signs++; idx += v;} + bits0 += h0->hlen[idx]; + bits1 += h1->hlen[idx]; + } + + if (bits0 < bits1) + { + *choice = table0; + *sum += bits0 + signs; + } + else + { + *choice = table1; + *sum += bits1 + signs; + } +} + + + +static void tiny_double_Huffman +( + unsigned start, + unsigned end, + unsigned table0, /* 2, 5, 13 */ + unsigned table1, /* 3, 6, 15 */ + unsigned *choice, + unsigned *sum +) +{ + int v0, v1, v2; + unsigned bits0, bits1, signs, idx0, idx1, idx2; + + struct huffcodetab *h0 = ht + table0; + struct huffcodetab *h1 = ht + table1; + + unsigned ylen = h0->ylen; /* == h1->ylen */ + + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = bits1 = signs = 0; + + while (pos < fin) + { + idx0 = idx1 = idx2 = 0; + v0 = *pos++; if (v0) {signs++; idx0 = v0 * ylen;} + v1 = *pos++; if (v1) {signs++; idx1 = v1 * ylen;} + v2 = *pos++; if (v2) {signs++; idx2 = v2 * ylen;} + v0 = *pos++; if (v0) {signs++; idx0 += v0;} + v1 = *pos++; if (v1) {signs++; idx1 += v1;} + v2 = *pos++; if (v2) {signs++; idx2 += v2;} + bits0 += h0->hlen[idx0] + h0->hlen[idx1] + h0->hlen[idx2]; + bits1 += h1->hlen[idx0] + h1->hlen[idx1] + h1->hlen[idx2]; + } + + if (bits0 < bits1) + { + *choice = table0; + *sum += bits0 + signs; + } + else + { + *choice = table1; + *sum += bits1 + signs; + } +} + + + +/* + poor men«s brave tailor --- only three at a blow... +*/ + +static void triple_Huffman +( + unsigned start, + unsigned end, + unsigned table0, /* 7, 10 */ + unsigned table1, /* 8, 11 */ + unsigned table2, /* 9, 12 */ + unsigned *choice, + unsigned *sum +) +{ + int v; + unsigned bits0, bits1, bits2, signs, idx; + + struct huffcodetab *h0 = ht + table0; + struct huffcodetab *h1 = ht + table1; + struct huffcodetab *h2 = ht + table2; + + unsigned ylen = h0->ylen; /* == h1->ylen == h2->ylen */ + + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = bits1 = bits2 = signs = 0; + + while (pos < fin) + { + idx = 0; + v = *pos++; if (v) {signs++; idx = v * ylen;} + v = *pos++; if (v) {signs++; idx += v;} + bits0 += h0->hlen[idx]; + bits1 += h1->hlen[idx]; + bits2 += h2->hlen[idx]; + } + + if (bits0 < bits1 && bits0 < bits2) + { + *choice = table0; + *sum += bits0 + signs; + } + else if (bits1 < bits2) + { + *choice = table1; + *sum += bits1 + signs; + } + else + { + *choice = table2; + *sum += bits2 + signs; + } +} + + + +static void tiny_triple_Huffman +( + unsigned start, + unsigned end, + unsigned table0, /* 7, 10 */ + unsigned table1, /* 8, 11 */ + unsigned table2, /* 9, 12 */ + unsigned *choice, + unsigned *sum +) +{ + int v0, v1, v2; + unsigned bits0, bits1, bits2, signs, idx0, idx1, idx2; + + struct huffcodetab *h0 = ht + table0; + struct huffcodetab *h1 = ht + table1; + struct huffcodetab *h2 = ht + table2; + + unsigned ylen = h0->ylen; /* == h1->ylen == h2->ylen */ + + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = bits1 = bits2 = signs = 0; + + while (pos < fin) + { + idx0 = idx1 = idx2 = 0; + v0 = *pos++; if (v0) {signs++; idx0 = v0 * ylen;} + v1 = *pos++; if (v1) {signs++; idx1 = v1 * ylen;} + v2 = *pos++; if (v2) {signs++; idx2 = v2 * ylen;} + v0 = *pos++; if (v0) {signs++; idx0 += v0;} + v1 = *pos++; if (v1) {signs++; idx1 += v1;} + v2 = *pos++; if (v2) {signs++; idx2 += v2;} + bits0 += h0->hlen[idx0] + h0->hlen[idx1] + h0->hlen[idx2]; + bits1 += h1->hlen[idx0] + h1->hlen[idx1] + h1->hlen[idx2]; + bits2 += h2->hlen[idx0] + h2->hlen[idx1] + h2->hlen[idx2]; + } + + if (bits0 < bits1 && bits0 < bits2) + { + *choice = table0; + *sum += bits0 + signs; + } + else if (bits1 < bits2) + { + *choice = table1; + *sum += bits1 + signs; + } + else + { + *choice = table2; + *sum += bits2 + signs; + } +} + + + + + +/* + The escape table 24 deals with linbits=4 instead of linbits=0 in case of table 13 and 15. + Nevertheless, sometimes it produces the better result... + Furthermore we take advantage because of the constant table numbers. +*/ + +static void triple_Huffman_2 +( + unsigned start, + unsigned end, +/* unsigned table0, == 13 */ +/* unsigned table1, == 15 */ +/* unsigned table2, == 24 */ + unsigned *choice, + unsigned *sum +) +{ + int v; + unsigned bits0, bits1, bits2, signs, idx; + + static struct huffcodetab *h0 = ht + /* table0 */ 13; /* all static declarations because of the constant values!!! */ + static struct huffcodetab *h1 = ht + /* table1 */ 15; + static struct huffcodetab *h2 = ht + /* table2 */ 24; + +#if 0 /* not needed */ + static unsigned ylen = h0->ylen; /* == h1->ylen == h2->ylen */ /* == 16 */ +#endif + + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = bits1 = bits2 = signs = 0; + + while (pos < fin) + { + idx = 0; + v = *pos++; if (v) {if (v == 15) bits2 += /* h2->linbits */ 4; signs++; idx = v /* * ylen */ << 4;} + v = *pos++; if (v) {if (v == 15) bits2 += /* h2->linbits */ 4; signs++; idx += v;} + bits0 += h0->hlen[idx]; + bits1 += h1->hlen[idx]; + bits2 += h2->hlen[idx]; + } + + if (bits0 < bits1 && bits0 < bits2) + { + *choice = /* table0 */ 13; + *sum += bits0 + signs; + } + else if (bits1 < bits2) + { + *choice = /* table1 */ 15; + *sum += bits1 + signs; + } + else + { + *choice = /* table2 */ 24; + *sum += bits2 + signs; + } +} + + + +static void tiny_triple_Huffman_2 +( + unsigned start, + unsigned end, +/* unsigned table0, == 13 */ +/* unsigned table1, == 15 */ +/* unsigned table2, == 24 */ + unsigned *choice, + unsigned *sum +) +{ + int v0, v1, v2; + unsigned bits0, bits1, bits2, signs, idx0, idx1, idx2; + + static struct huffcodetab *h0 = ht + /* table0 */ 13; /* all static declarations because of the constant values!!! */ + static struct huffcodetab *h1 = ht + /* table1 */ 15; + static struct huffcodetab *h2 = ht + /* table2 */ 24; + +#if 0 /* not needed */ + static unsigned ylen = h0->ylen; /* == h1->ylen == h2->ylen */ /* == 16 */ +#endif + + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = bits1 = bits2 = signs = 0; + + while (pos < fin) + { + idx0 = idx1 = idx2 = 0; + v0 = *pos++; if (v0) {if (v0 == 15) bits2 += /* h2->linbits */ 4; signs++; idx0 = v0 /* * ylen */ << 4;} + v1 = *pos++; if (v1) {if (v1 == 15) bits2 += /* h2->linbits */ 4; signs++; idx1 = v1 /* * ylen */ << 4;} + v2 = *pos++; if (v2) {if (v2 == 15) bits2 += /* h2->linbits */ 4; signs++; idx2 = v2 /* * ylen */ << 4;} + v0 = *pos++; if (v0) {if (v0 == 15) bits2 += /* h2->linbits */ 4; signs++; idx0 += v0;} + v1 = *pos++; if (v1) {if (v1 == 15) bits2 += /* h2->linbits */ 4; signs++; idx1 += v1;} + v2 = *pos++; if (v2) {if (v2 == 15) bits2 += /* h2->linbits */ 4; signs++; idx2 += v2;} + bits0 += h0->hlen[idx0] + h0->hlen[idx1] + h0->hlen[idx2]; + bits1 += h1->hlen[idx0] + h1->hlen[idx1] + h1->hlen[idx2]; + bits2 += h2->hlen[idx0] + h2->hlen[idx1] + h2->hlen[idx2]; + } + + if (bits0 < bits1 && bits0 < bits2) + { + *choice = /* table0 */ 13; + *sum += bits0 + signs; + } + else if (bits1 < bits2) + { + *choice = /* table1 */ 15; + *sum += bits1 + signs; + } + else + { + *choice = /* table2 */ 24; + *sum += bits2 + signs; + } +} + + + + + +/* + In case of two escape tables, we esepecially have to take care for + the possibly different linbits values... +*/ + +static void double_Huffman_2 /* Escape tables */ +( + unsigned start, + unsigned end, + unsigned table0, /* 16... */ + unsigned table1, /* 24... */ + unsigned *choice, + unsigned *sum +) +{ + int v; + unsigned bits0, bits1, signs, xbits, idx; + + struct huffcodetab *h0 = ht + table0; + struct huffcodetab *h1 = ht + table1; + +#if 0 /* not needed */ + static unsigned ylen = h0->ylen; /* == h1->ylen */ /* == 16 */ +#endif + unsigned linbits0 = h0->linbits; + unsigned linbits1 = h1->linbits; + + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = bits1 = signs = xbits = 0; + + while (pos < fin) + { + idx = 0; + v = *pos++; if (v) {if (v > 14) {v = 15; xbits++;/*bits0 += linbits0; bits1 += linbits1;*/} signs++; idx = v /* * ylen */ << 4;} + v = *pos++; if (v) {if (v > 14) {v = 15; xbits++;/*bits0 += linbits0; bits1 += linbits1;*/} signs++; idx += v;} + bits0 += h0->hlen[idx]; + bits1 += h1->hlen[idx]; + } + bits0 += xbits * linbits0; + bits1 += xbits * linbits1; + + if (bits0 < bits1) + { + *choice = table0; + *sum += bits0 + signs; + } + else + { + *choice = table1; + *sum += bits1 + signs; + } +} + + + +static void tiny_double_Huffman_2 /* Escape tables */ +( + unsigned start, + unsigned end, + unsigned table0, /* 16... */ + unsigned table1, /* 24... */ + unsigned *choice, + unsigned *sum +) +{ + int v0, v1, v2; + unsigned bits0, bits1, signs, xbits, idx0, idx1, idx2; + + struct huffcodetab *h0 = ht + table0; + struct huffcodetab *h1 = ht + table1; + +#if 0 /* not needed */ + static unsigned ylen = h0->ylen; /* == h1->ylen == 16 --- static because of the constant!!! */ +#endif + int *pos = ix_l + start; + int *fin = ix_l + end; + + bits0 = bits1 = signs = xbits = 0; + + while (pos < fin) + { + idx0 = idx1 = idx2 = 0; + + v0 = *pos++; if (v0) {if (v0 > 14) {v0 = 15; xbits++;} signs++; idx0 = v0 /* * ylen */ << 4;} + v1 = *pos++; if (v1) {if (v1 > 14) {v1 = 15; xbits++;} signs++; idx1 = v1 /* * ylen */ << 4;} + v2 = *pos++; if (v2) {if (v2 > 14) {v2 = 15; xbits++;} signs++; idx2 = v2 /* * ylen */ << 4;} + v0 = *pos++; if (v0) {if (v0 > 14) {v0 = 15; xbits++;} signs++; idx0 += v0;} + v1 = *pos++; if (v1) {if (v1 > 14) {v1 = 15; xbits++;} signs++; idx1 += v1;} + v2 = *pos++; if (v2) {if (v2 > 14) {v2 = 15; xbits++;} signs++; idx2 += v2;} + + bits0 += h0->hlen[idx0] + h0->hlen[idx1] + h0->hlen[idx2]; + bits1 += h1->hlen[idx0] + h1->hlen[idx1] + h1->hlen[idx2]; + } + + bits0 += xbits * h0->linbits; + bits1 += xbits * h1->linbits; + + if (bits0 < bits1) + { + *choice = table0; + *sum += bits0 + signs; + } + else + { + *choice = table1; + *sum += bits1 + signs; + } +} + + + diff -Nru swftools-0.9.2+ds1/lib/bladeenc/loop.h swftools-0.9.1/lib/bladeenc/loop.h --- swftools-0.9.2+ds1/lib/bladeenc/loop.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/loop.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,121 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-11 Andre Piotrowski + + - reformatted, redesigned +*/ + +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: loop.h,v 1.1 2002/01/10 17:30:00 kramm Exp $ + * + * $Log: loop.h,v $ + * Revision 1.1 2002/01/10 17:30:00 kramm + * Version 0.94.1 of the bladeenc mp3 encoder + * + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ + +/********************************************************************** + * date programmers comment * + * 25. 6.92 Toshiyuki Ishino Ver 1.0 * + * 29.10.92 Masahiro Iwadare Ver 2.0 * + * 17. 4.93 Masahiro Iwadare Updated for IS Modification * + * * + *********************************************************************/ + +#ifndef __LOOP__ +#define __LOOP__ + + + + +#include "common.h" +#include "l3side.h" + + + + + +/* #define SBLIMIT 32 */ +#define CBLIMIT 21 + +#define SFB_LMAX 22 +#define SFB_SMAX 13 + + + + +extern int fInit_iteration_loop; +/* NOT NEEDED +extern int fInit_huffman_read_flag; +*/ + + +extern int pretab[]; + + +struct scalefac_struct +{ + int l[23]; + int s[14]; +}; + +extern struct scalefac_struct sfBandIndex[]; /* Table B.8 -- in loop.c */ + + + + + +void iteration_loop +( + double pe[][2], + double xr_org[2][2][576], + III_psy_ratio *ratio, + III_side_info_t *l3_side, + int l3_enc[2][2][576], + int mean_bits, + int stereo, + double xr_dec[2][2][576], + III_scalefac_t *scalefac, + frame_params *fr_ps, + int ancillary_pad, + int bitsPerFrame +); + +int my_nint (double in); + +void fixStatic_loop (void); + +void genNoisePowTab (void); + + + + + +#endif /* __LOOP__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/loop-pvt.h swftools-0.9.1/lib/bladeenc/loop-pvt.h --- swftools-0.9.2+ds1/lib/bladeenc/loop-pvt.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/loop-pvt.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,222 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-02-15 Pirandot + + - reformatted, used 'static', less parameters + + 2000-12-03 ap + - adapted according to changes to "loop.h" +*/ + +#ifndef __LOOP_PVT__ +#define __LOOP_PVT__ + + + + + +static int outer_loop +( + int max_bits, + frame_params *fr_ps +); + +static int needed_bits_for_storing_scalefactors +( + frame_params *fr_ps +); + +static void calc_noise (void); + +static int loop_break (void); + +static int amplify +( + int iteration +); + +static int INLINE cutting_crew (FLOAT in); + +static void quantize (void); + +static void partial_quantize (void); + +static int bin_search_StepSize +( + int desired_rate, + double start +); + + + +/* ------------ bit counting -------------------------------------------------------- */ + + + +static int count_bits (void); + +static int count_bits_short (void); + +static int count_bits_long (void); + +static void choose_table_long +( + unsigned start, + unsigned end, + unsigned max, + unsigned *table, + unsigned *bit_sum +); + +static void choose_table_short +( + unsigned start_sfb, + unsigned end_sfb, + unsigned max, + unsigned *table, + unsigned *bit_sum +); + + + +/* ------------ Huffmania ----------------------------------------------------------- */ + + + +static void single_Huffman +( + unsigned start, + unsigned end, +/* unsigned table0, == 1 */ + unsigned *choice, + unsigned *sum +); + +static void double_Huffman +( + unsigned start, + unsigned end, + unsigned table0, /* 2, 5, 13 */ + unsigned table1, /* 3, 6, 15 */ + unsigned *choice, + unsigned *sum +); + +static void triple_Huffman +( + unsigned start, + unsigned end, + unsigned table0, /* 7, 10 */ + unsigned table1, /* 8, 11 */ + unsigned table2, /* 9, 12 */ + unsigned *choice, + unsigned *sum +); + +static void triple_Huffman_2 +( + unsigned start, + unsigned end, +/* unsigned table0, == 13 */ +/* unsigned table1, == 15 */ +/* unsigned table2, == 24 */ + unsigned *choice, + unsigned *sum +); + +static void double_Huffman_2 /* Escape tables */ +( + unsigned start, + unsigned end, + unsigned table0, /* 16... */ + unsigned table1, /* 24... */ + unsigned *choice, + unsigned *sum +); + + + +/* ------------ the struggle continues ---------------------------------------------- */ + + + +static void tiny_single_Huffman +( + unsigned start, + unsigned end, +#if ORG_HUFFMAN_CODING + unsigned table0, +#else +/* unsigned table0, == 1 */ +#endif + unsigned *choice, + unsigned *sum +); + +static void tiny_double_Huffman +( + unsigned start, + unsigned end, + unsigned table0, /* 2, 5, 13 */ + unsigned table1, /* 3, 6, 15 */ + unsigned *choice, + unsigned *sum +); + +static void tiny_triple_Huffman +( + unsigned start, + unsigned end, + unsigned table0, /* 7, 10 */ + unsigned table1, /* 8, 11 */ + unsigned table2, /* 9, 12 */ + unsigned *choice, + unsigned *sum +); + +static void tiny_triple_Huffman_2 +( + unsigned start, + unsigned end, +/* unsigned table0, == 13 */ +/* unsigned table1, == 15 */ +/* unsigned table2, == 24 */ + unsigned *choice, + unsigned *sum +); + +static void tiny_double_Huffman_2 /* Escape tables */ +( + unsigned start, + unsigned end, + unsigned table0, /* 16... */ + unsigned table1, /* 24... */ + unsigned *choice, + unsigned *sum +); + + + + + +#endif /* __LOOP_PVT__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/Makefile.in swftools-0.9.1/lib/bladeenc/Makefile.in --- swftools-0.9.2+ds1/lib/bladeenc/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/Makefile.in 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,17 @@ +top_builddir = ../.. +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +include ../../Makefile.common + +bladeenc_objects = codec.o common.o encode.o formatbitstream2.o l3bitstream.o l3psy.o loop.o mdct.o reservoir.o subs.o tables.o + +all: $(bladeenc_objects) + +%.o: %.c + $(C) $< -o $@ + +install: +uninstall: +clean: + rm -f *.o *.lo *.a *.la + diff -Nru swftools-0.9.2+ds1/lib/bladeenc/mdct.c swftools-0.9.1/lib/bladeenc/mdct.c --- swftools-0.9.2+ds1/lib/bladeenc/mdct.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/mdct.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,574 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-11-04 Andre Piotrowski + + - some cosmetics + - included "l3psy.h" to use the defined block type constants + - negligible speed up of mdct_sub() + - speed up of mdct() + + 2000-12-10 ap + + - speed up of mdct_sub() and mdct() - MDCT_CHANGE_LEVEL 5 +*/ + +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: mdct.c,v 1.1 2002/01/10 17:30:01 kramm Exp $ + * + * $Log: mdct.c,v $ + * Revision 1.1 2002/01/10 17:30:01 kramm + * Version 0.94.1 of the bladeenc mp3 encoder + * + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ + +#include "common.h" +#include +#include "l3side.h" +#include "l3psy.h" +#include "mdct.h" + + + + + +/* + This is table B.9: coefficients for aliasing reduction +*/ +static double c[8] = { -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037 }; + + + + + +int gr_idx[3] = {0,1,2}; + + + + + +#if 0 +static double ca[8]; +#endif +static double cs[8]; + + + + + +int fInit_mdct_sub; + +void mdct_sub +( + L3SBS (*sb_sample), + double (*mdct_freq)[2][576], + int stereo, + III_side_info_t *l3_side, + int mode_gr +) +{ + gr_info *cod_info; +#if MDCT_CHANGE_LEVEL < 5 + double mdct_in[36]; +#endif + int gr, ch, band, k, j; + double bu, bd; + int block_type; + double (*mdct_enc_long)[2][32][18] = (double (*)[2][32][18]) mdct_freq; + + if (!fInit_mdct_sub) + { + /* prepare the aliasing reduction butterflies */ + for (k = 0; k < 8; k++) + { + double sq = sqrt (1.0 + c[k]*c[k]); +#if 0 + ca[k] = c[k] / sq; +#endif + cs[k] = 1.0 / sq; + } + fInit_mdct_sub++; + } + + + for (gr = 0; gr < mode_gr; gr++) + { + int pre_gr = gr_idx[gr ]; + int cur_gr = gr_idx[gr+1]; + + for (ch = 0; ch < stereo; ch++) + { + double (*mdct_enc)[18] = mdct_enc_long[gr][ch]; + + cod_info = &l3_side->gr[gr].ch[ch].tt; + block_type = cod_info->block_type; + + /* Compensate for inversion in the analysis filter */ + for (k = 1; k < 18; k++) + if (k & 1) + for (band = 1; band < 32; band++) + if (band & 1) + (*sb_sample)[ch][cur_gr][k][band] *= -1.0; + /* + Perform imdct of 18 previous subband samples + + 18 current subband samples + */ + for (band = 0; band < 32; band++) + { +#if MDCT_CHANGE_LEVEL < 5 + for (k = 0; k < 18; k++) + { + mdct_in[k] = (*sb_sample)[ch][pre_gr][k][band]; + mdct_in[k+18] = (*sb_sample)[ch][cur_gr][k][band]; + } + if (cod_info->mixed_block_flag && (band < 2)) + block_type = NORM_TYPE; /* AND WHEN WILL THE BLOCK_TYPE BE SWITCHED BACK? */ + + /* &mdct_enc[gr][ch][band][0] */ + mdct (mdct_in, mdct_enc/*[gr][ch]*/[band], block_type); +#else + mdct ((*sb_sample)[ch][pre_gr], (*sb_sample)[ch][cur_gr], band, mdct_enc[band], block_type); +#endif + } + + /* + Perform aliasing reduction butterfly + on long blocks + */ + + if (block_type != SHORT_TYPE) + for (band = 0; band < 31; band++) + for (k = 0; k < 8; k++) + { +#if 1 /* This is faster because the calculation can be done more sequential */ + bu = (mdct_enc[band ][17-k] + mdct_enc[band+1][ k] * c[k]) * cs[k]; + bd = (mdct_enc[band+1][ k] - mdct_enc[band ][17-k] * c[k]) * cs[k]; + mdct_enc[band ][17-k] = bu; + mdct_enc[band+1][ k] = bd; +#else + bu = mdct_enc[band ][17-k] * cs[k] + mdct_enc[band+1][ k] * ca[k]; + bd = mdct_enc[band+1][ k] * cs[k] - mdct_enc[band ][17-k] * ca[k]; + mdct_enc[band ][17-k] = bu; + mdct_enc[band+1][ k] = bd; +#endif + } + } + } + + /* + Save latest granule's subband samples to be used in + the next mdct call + */ + j = gr_idx[mode_gr]; + for (k = mode_gr; k > 0; k--) + gr_idx[k] = gr_idx[k-1]; + gr_idx[0] = j; +} + + + + + +/*-------------------------------------------------------------------*/ +/* */ +/* Function: Calculation of the MDCT */ +/* In the case of long blocks ( block_type 0,1,3 ) there are */ +/* 36 coefficents in the time domain and 18 in the frequency */ +/* domain. */ +/* In the case of short blocks (block_type 2 ) there are 3 */ +/* transformations with short length. This leads to 12 coefficents */ +/* in the time and 6 in the frequency domain. In this case the */ +/* results are stored side by side in the vector out[]. */ +/* */ +/* New layer3 */ +/* */ +/*-------------------------------------------------------------------*/ + +int fInit_mdct; + + + +#if MDCT_CHANGE_LEVEL == 5 + +void mdct +( + double inA[18][32], + double inB[18][32], + int band, + double *out, + int block_type +) +{ + static double cos_l[18][18]; + static double cos_s[ 6][ 6]; + + static double winNorm [18]; + static double winShort[ 6]; + + int k, m, N; + double t1, t2, t3, t4, t5, t6, u1, u2; + + + if (!fInit_mdct) + { + N = 36; + for (k = 0; k < N/2; k++) winNorm [k] = sin (PI/36 * (k+0.5)); + for (k = 0; k < N/4; k++) for (m = 0; m < N/2; m++) cos_l[k][m] = cos((PI/(2*N)) * (2* k +1+N/2) * (2*m+1)) / (N/4); + for ( ; k < N/2; k++) for (m = 0; m < N/2; m++) cos_l[k][m] = cos((PI/(2*N)) * (2*(k+N/4)+1+N/2) * (2*m+1)) / (N/4); + + N = 12; + for (k = 0; k < N/2; k++) winShort[k] = sin (PI/12 * (k+0.5)); + for (k = 0; k < N/4; k++) for (m = 0; m < N/2; m++) cos_s[k][m] = cos((PI/(2*N)) * (2*k +1+N/2) * (2*m+1)) / (N/4); + for ( ; k < N/2; k++) for (m = 0; m < N/2; m++) cos_s[k][m] = cos((PI/(2*N)) * (2*(k+N/4)+1+N/2) * (2*m+1)) / (N/4); + + fInit_mdct++; + } + + for (m = 0; m < 18; m++) out[m] = 0.0; + switch (block_type) + { + case NORM_TYPE: + for (k = 0; k < 9; k++) + { + t1 = winNorm [ k] * inA[k][band] - winNorm [17-k] * inA[17-k][band]; + t2 = winNorm [17-k] * inB[k][band] + winNorm [ k] * inB[17-k][band]; + for (m = 0; m < 18; m++) + out[m] += t1 * cos_l[k][m] + t2 * cos_l[k+9][m]; + } + break; + + case START_TYPE: + for (k = 0; k < 6; k++) + { + t1 = winNorm [ k] * inA[k][band] - winNorm [17-k] * inA[17-k][band]; + t2 = inB[k][band]; + for (m = 0; m < 18; m++) + out[m] += t1 * cos_l[k][m] + t2 * cos_l[k+9][m]; + } + for (k = 6; k < 9; k++) + { + t1 = winNorm [ k] * inA[k][band] - winNorm [17-k] * inA[17-k][band]; + t2 = winShort[11-k] * inB[k][band] + winShort[k- 6] * inB[17-k][band]; + for (m = 0; m < 18; m++) + out[m] += t1 * cos_l[k][m] + t2 * cos_l[k+9][m]; + } + break; + + case STOP_TYPE: + for (k = 0; k < 6; k++) + { + t1 = -inA[17-k][band]; + t2 = winNorm [17-k] * inB[k][band] + winNorm [ k] * inB[17-k][band]; + for (m = 0; m < 18; m++) + out[m] += t1 * cos_l[k][m] + t2 * cos_l[k+9][m]; + } + for (k = 6; k < 9; k++) + { + t1 = winShort[k- 6] * inA[k][band] - winShort[11-k] * inA[17-k][band]; + t2 = winNorm [17-k] * inB[k][band] + winNorm [ k] * inB[17-k][band]; + for (m = 0; m < 18; m++) + out[m] += t1 * cos_l[k][m] + t2 * cos_l[k+9][m]; + } + break; + + case SHORT_TYPE: + for (k = 0; k < 3; k++) + { + u1 = winShort[k]; u2 = winShort[5-k]; + t1 = u1 * inA[k+ 6][band] - u2 * inA[11-k][band]; + t2 = u2 * inA[k+12][band] + u1 * inA[17-k][band]; + t3 = u1 * inA[k+12][band] - u2 * inA[17-k][band]; + t4 = u2 * inB[k ][band] + u1 * inB[ 5-k][band]; + t5 = u1 * inB[k ][band] - u2 * inB[ 5-k][band]; + t6 = u2 * inB[k+ 6][band] + u1 * inB[11-k][band]; + for (m = 0; m < 6; m++) + { + u1 = cos_s[k][m]; u2 = cos_s[k+3][m]; + out[3*m ] += t1 * u1 + t2 * u2; + out[3*m+1] += t3 * u1 + t4 * u2; + out[3*m+2] += t5 * u1 + t6 * u2; + } + } + } +} + +#elif MDCT_CHANGE_LEVEL == 4 /* reduce number of multiplications to nearly the half once more! (cos_x[9+k][m] = -cos_x[9-k][m] and cos_x[35+k][m] = cos_x[35-k][m]) */ + +void mdct +( + double *in, + double *out, + int block_type +) +{ + static double cos_l[36][18]; + static double cos_s[12][ 6]; + + static double winNorm [36]; + static double winShort[12]; + static double *winStart = winShort-18; + static double *winStop = winShort- 6; + + int l, k, m, N; + double temp; + + + if (!fInit_mdct) + { + N = 36; + for (k = 0; k < N; k++) winNorm [k] = sin (PI/36 * (k+0.5)); + for (k = 0; k < N; k++) for (m = 0; m < N/2; m++) cos_l[k][m] = cos((PI/(2*N)) * (2*k+1+N/2) * (2*m+1)) / (N/4); + + N = 12; + for (k = 0; k < N; k++) winShort[k] = sin (PI/12 * (k+0.5)); + for (k = 0; k < N; k++) for (m = 0; m < N/2; m++) cos_s[k][m] = cos((PI/(2*N)) * (2*k+1+N/2) * (2*m+1)) / (N/4); + + fInit_mdct++; + } + + for (m = 0; m < 18; m++) out[m] = 0.0; + switch (block_type) + { + case NORM_TYPE: + for (k = 0; k < 9; k++) {temp = (winNorm [k] * in[k] - winNorm [17-k] * in[17-k]); for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + for (k = 18; k < 27; k++) {temp = (winNorm [k] * in[k] + winNorm [53-k] * in[53-k]); for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + break; + + case START_TYPE: + for (k = 0; k < 9; k++) {temp = (winNorm [k] * in[k] - winNorm [17-k] * in[17-k]); for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + for (k = 18; k < 24; k++) {temp = in[k]; for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + for (k = 24; k < 27; k++) {temp = (winStart[k] * in[k] + winStart[53-k] * in[53-k]); for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + break; + + case STOP_TYPE: + for (k = 6; k < 9; k++) {temp = (winStop [k] * in[k] - winStop [17-k] * in[17-k]); for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + for (k = 12; k < 18; k++) {temp = in[k]; for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + for (k = 18; k < 27; k++) {temp = (winNorm [k] * in[k] + winNorm [53-k] * in[53-k]); for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + break; + + case SHORT_TYPE: + for (l = 0; l < 3; l++) + { + for (k = 0; k < 3; k++) {temp = (winShort[k] * in[k+6+l*6] - winShort[ 5-k] * in[ 5-k+6+l*6]); for (m = 0; m < 6; m++) out[3*m+l] += temp * cos_s[k][m];} + for (k = 6; k < 9; k++) {temp = (winShort[k] * in[k+6+l*6] + winShort[17-k] * in[17-k+6+l*6]); for (m = 0; m < 6; m++) out[3*m+l] += temp * cos_s[k][m];} + } + } +} + +#elif MDCT_CHANGE_LEVEL == 3 /* reduce number of multiplications to nearly the half (win_x[k]*in[k] is constant in m-loop)! flip cos_x components for faster access */ + +void mdct +( + double *in, + double *out, + int block_type +) +{ + static double cos_l[36][18]; + static double cos_s[12][ 6]; + + static double winNorm [36]; + static double winShort[12]; + static double *winStart = winShort-18; + static double *winStop = winShort- 6; + + int l, k, m, N; + double temp; + + + if (!fInit_mdct) + { + N = 36; + for (k = 0; k < N; k++) winNorm [k] = sin (PI/36 * (k+0.5)); + for (k = 0; k < N; k++) for (m = 0; m < N/2; m++) cos_l[k][m] = cos((PI/(2*N)) * (2*k+1+N/2) * (2*m+1)) / (N/4); + + N = 12; + for (k = 0; k < N; k++) winShort[k] = sin (PI/12 * (k+0.5)); + for (k = 0; k < N; k++) for (m = 0; m < N/2; m++) cos_s[k][m] = cos((PI/(2*N)) * (2*k+1+N/2) * (2*m+1)) / (N/4); + + fInit_mdct++; + } + + for (m = 0; m < 18; m++) out[m] = 0.0; + switch (block_type) + { + case NORM_TYPE: + for (k = 0; k < 36; k++) {temp = winNorm [k] * in[k]; for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + break; + + case START_TYPE: + for (k = 0; k < 18; k++) {temp = winNorm [k] * in[k]; for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + for (k = 18; k < 24; k++) {temp = in[k]; for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + for (k = 24; k < 30; k++) {temp = winStart[k] * in[k]; for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + break; + + case STOP_TYPE: + for (k = 6; k < 12; k++) {temp = winStop [k] * in[k]; for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + for (k = 12; k < 18; k++) {temp = in[k]; for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + for (k = 18; k < 36; k++) {temp = winNorm [k] * in[k]; for (m = 0; m < 18; m++) out[m] += temp * cos_l[k][m];} + break; + + case SHORT_TYPE: + for (l = 0; l < 3; l++) + for (k = 0; k < 12; k++) {temp = winShort[k] * in[k+6+l*6]; for (m = 0; m < 6; m++) out[3*m+l] += temp * cos_s[k][m];} + } +} + +#elif MDCT_CHANGE_LEVEL == 2 /* avoid calculating of some redundant values; take care for some special values */ + +void mdct +( + double *in, + double *out, + int block_type +) +{ + static double cos_l[18][36]; + static double cos_s[ 6][12]; + + static double winNorm [36]; + static double winShort[12]; + static double *winStart = winShort-18; + static double *winStop = winShort- 6; + + int l, k, m, N; + double sum; + + + if (!fInit_mdct) + { + for (k = 0; k < 36; k++) winNorm [k] = sin (PI/36 * (k+0.5)); + for (k = 0; k < 12; k++) winShort[k] = sin (PI/12 * (k+0.5)); + + N = 36; for (m = 0; m < N/2; m++) for (k = 0; k < N; k++) cos_l[m][k] = cos((PI/(2*N)) * (2*k+1+N/2) * (2*m+1)) / (N/4); + N = 12; for (m = 0; m < N/2; m++) for (k = 0; k < N; k++) cos_s[m][k] = cos((PI/(2*N)) * (2*k+1+N/2) * (2*m+1)) / (N/4); + + fInit_mdct++; + } + + switch (block_type) + { + case NORM_TYPE: + for (m = 0; m < 18; m++) + { + sum = 0.0; + for (k = 0; k < 36; k++) sum += winNorm [k] * in[k] * cos_l[m][k]; + out[m] = sum; + } + break; + + case START_TYPE: + for (m = 0; m < 18; m++) + { + sum = 0.0; + for (k = 0; k < 18; k++) sum += winNorm [k] * in[k] * cos_l[m][k]; + for (k = 18; k < 24; k++) sum += in[k] * cos_l[m][k]; + for (k = 24; k < 30; k++) sum += winStart[k] * in[k] * cos_l[m][k]; + out[m] = sum; + } + break; + + case STOP_TYPE: + for (m = 0; m < 18; m++) + { + sum = 0.0; + for (k = 6; k < 12; k++) sum += winStop [k] * in[k] * cos_l[m][k]; + for (k = 12; k < 18; k++) sum += in[k] * cos_l[m][k]; + for (k = 18; k < 36; k++) sum += winNorm [k] * in[k] * cos_l[m][k]; + out[m] = sum; + } + break; + + case SHORT_TYPE: + for (l = 0; l < 3; l++) + { + for (m = 0; m < 6; m++) + { + sum = 0.0; + for (k = 0; k < 12; k++) sum += winShort[k] * in[k+6+l*6] * cos_s[m][k]; + out[3*m+l] = sum; + } + } + } +} + +#elif MDCT_CHANGE_LEVEL == 1 /* reformatted for better overview; use block type constants */ + +void mdct +( + double *in, + double *out, + int block_type +) +{ + static double cos_l[18][36]; + static double cos_s[ 6][12]; + + static double winNorm [36]; + static double winShort[12]; + static double winStart[36]; + static double winStop [36]; + + int l, k, m, N; + double sum; + + + if (!fInit_mdct) + { + /* type 0 -- NORM_TYPE */ + for (k = 0; k < 36; k++) winNorm [k] = sin (PI/36 * (k+0.5)); + /* type 1 -- START_TYPE */ + for (k = 0; k < 18; k++) winStart[k] = sin (PI/36 * (k+0.5)); + for (k = 18; k < 24; k++) winStart[k] = 1.0; + for (k = 24; k < 30; k++) winStart[k] = sin (PI/12 * (k+0.5 - 18)); + for (k = 30; k < 36; k++) winStart[k] = 0.0; + /* type 3 -- STOP_TYPE */ + for (k = 0; k < 6; k++) winStop [k] = 0.0; + for (k = 6; k < 12; k++) winStop [k] = sin (PI/12 * (k+0.5 - 6)); + for (k = 12; k < 18; k++) winStop [k] = 1.0; + for (k = 18; k < 36; k++) winStop [k] = sin (PI/36 * (k+0.5)); + /* type 2 -- SHORT_TYPE */ + for (k = 0; k < 12; k++) winShort[k] = sin (PI/12 * (k+0.5)); + + N = 12; for (m = 0; m < N/2; m++) for (k = 0; k < N; k++) cos_s[m][k] = cos((PI/(2*N)) * (2*k+1+N/2) * (2*m+1)) / (N/4); + N = 36; for (m = 0; m < N/2; m++) for (k = 0; k < N; k++) cos_l[m][k] = cos((PI/(2*N)) * (2*k+1+N/2) * (2*m+1)) / (N/4); + + fInit_mdct++; + } + + switch (block_type) + { + case NORM_TYPE: N = 36; for (m = 0; m < N/2; m++) {sum = 0.0; for (k = 0; k < N; k++) sum += winNorm [k] * in[k ] * cos_l[m][k]; out[ m ] = sum;} break; + case START_TYPE: N = 36; for (m = 0; m < N/2; m++) {sum = 0.0; for (k = 0; k < N; k++) sum += winStart[k] * in[k ] * cos_l[m][k]; out[ m ] = sum;} break; + case STOP_TYPE: N = 36; for (m = 0; m < N/2; m++) {sum = 0.0; for (k = 0; k < N; k++) sum += winStop [k] * in[k ] * cos_l[m][k]; out[ m ] = sum;} break; + case SHORT_TYPE: N = 12; for (l = 0; l < 3; l++) {for (m = 0; m < N/2; m++) {sum = 0.0; for (k = 0; k < N; k++) sum += winShort[k] * in[k+6+l*6] * cos_s[m][k]; out[3*m+l] = sum;}} + } +} + +#endif /* MDCT_CHANGE_LEVEL */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/mdct.h swftools-0.9.1/lib/bladeenc/mdct.h --- swftools-0.9.2+ds1/lib/bladeenc/mdct.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/mdct.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,111 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-10 Andre Piotrowski + + - reformatted, redesigned + - MDCT_CHANGE_LEVEL 5 +*/ + +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: mdct.h,v 1.1 2002/01/10 17:30:01 kramm Exp $ + * + * $Log: mdct.h,v $ + * Revision 1.1 2002/01/10 17:30:01 kramm + * Version 0.94.1 of the bladeenc mp3 encoder + * + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ + +#ifndef __MDCT__ +#define __MDCT__ + + + + + +#define MDCT_CHANGE_LEVEL 5 + + + + + +typedef double L3SBS[2][3][18][SBLIMIT]; /* [gr][ch] */ + + + + + +extern int fInit_mdct_sub; +extern int fInit_mdct; + + +extern int gr_idx[3]; + + + + + +void mdct_sub +( + L3SBS *sb_sample, + double (*mdct_freq)[2][576], + int stereo, + III_side_info_t *l3_side, + int mode_gr +); + + + +#if MDCT_CHANGE_LEVEL < 5 + +void mdct +( + double *in, + double *out, + int block_type +); + +#else + +void mdct +( + double inA[18][32], + double inB[18][32], + int band, + double *out, + int block_type +); + +#endif + + + + + +#endif /* __MDCT__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/README swftools-0.9.1/lib/bladeenc/README --- swftools-0.9.2+ds1/lib/bladeenc/README 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/README 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,2 @@ +BladeEnc is a free cross-platform MP3 encoder released under the LGPL. + diff -Nru swftools-0.9.2+ds1/lib/bladeenc/reservoir.c swftools-0.9.1/lib/bladeenc/reservoir.c --- swftools-0.9.2+ds1/lib/bladeenc/reservoir.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/reservoir.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,268 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-11 Andre Piotrowski + + - reformatted +*/ + +#include +#include +#include +#include + +#include "common.h" +#include "l3side.h" +#include "loop.h" +#include "huffman.h" +#include "l3bitstream.h" +#include "reservoir.h" + + + + + +/* + Layer3 bit reservoir: + Described in C.1.5.4.2.2 of the IS +*/ + +static int ResvSize = 0; /* in bits */ +static int ResvMax = 0; /* in bits */ + + + + + +void fixStatic_reservoir (void) +{ + ResvSize = 0; + ResvMax = 0; +} + + + + + +/* + ResvFrameBegin: + Called at the beginning of a frame. Updates the maximum + size of the reservoir, and checks to make sure main_data_begin + was set properly by the formatter +*/ +void ResvFrameBegin +( + frame_params *fr_ps, + III_side_info_t *l3_side, + int mean_bits, + int frameLength +) +{ + layer *info; + int fullFrameBits, mode_gr; + int expectedResvSize, resvLimit; + + + info = fr_ps->header; + mode_gr = 2; + resvLimit = 4088; /* main_data_begin has 9 bits in MPEG 1 */ + + + /* + main_data_begin was set by the formatter to the + expected value for the next call -- this should + agree with our reservoir size + */ + expectedResvSize = l3_side->main_data_begin * 8; +/* assert (expectedResvSize == ResvSize); */ + + fullFrameBits = mean_bits * mode_gr; + + /* + determine maximum size of reservoir: + ResvMax + frameLength <= 7680; + + limit max size to resvLimit bits because + main_data_begin cannot indicate a + larger value + */ + ResvMax = MIN(MAX (0, 7680-frameLength), resvLimit); +} + + + + + +/* + ResvMaxBits: + Called at the beginning of each granule to get the max bit + allowance for the current granule based on reservoir size + and perceptual entropy. +*/ +int ResvMaxBits +( + frame_params *fr_ps, + III_side_info_t *l3_side, + double *pe, + int mean_bits +) +{ + int more_bits, max_bits, add_bits, over_bits; + + + mean_bits /= fr_ps->stereo; + + max_bits = mean_bits; + + if (ResvMax != 0) + { + more_bits = (int) (*pe * 3.1 - mean_bits); + + if (more_bits > 100) + { + int frac = (ResvSize * 6) / 10; + + add_bits = MIN(frac, more_bits); + } + else + add_bits = 0; + + over_bits = ResvSize - ((ResvMax * 8) / 10) - add_bits; + if (over_bits > 0) + add_bits += over_bits; + + max_bits += add_bits; + } + + if (max_bits > 4095) + max_bits = 4095; + + return max_bits; +} + + + + + +/* + ResvAdjust: + Called after a granule's bit allocation. Readjusts the size of + the reservoir to reflect the granule's usage. +*/ +void ResvAdjust +( + frame_params *fr_ps, + gr_info *cod_info, + III_side_info_t *l3_side, + int mean_bits +) +{ + ResvSize += (mean_bits / fr_ps->stereo) - cod_info->part2_3_length; +} + + + + + +/* + ResvFrameEnd: + Called after all granules in a frame have been allocated. Makes sure + that the reservoir size is within limits, possibly by adding stuffing + bits. Note that stuffing bits are added by increasing a granule's + part2_3_length. The bitstream formatter will detect this and write the + appropriate stuffing bits to the bitstream. +*/ +void ResvFrameEnd +( + frame_params *fr_ps, + III_side_info_t *l3_side, + int mean_bits +) +{ + layer *info; + gr_info *cod_info; + int mode_gr, gr, ch, stereo, ancillary_pad, stuffingBits; + int over_bits; + + info = fr_ps->header; + stereo = fr_ps->stereo; + mode_gr = 2; + + ancillary_pad = 0; + + /* just in case mean_bits is odd, this is necessary... */ + if ((stereo == 2) && (mean_bits & 1)) + ResvSize ++; + + stuffingBits = ancillary_pad; + + if ((over_bits = ResvSize - ResvMax) > 0) + { + stuffingBits += over_bits; + ResvSize -= over_bits; + } + + /* we must be byte aligned */ + if ((over_bits = ResvSize % 8) != 0) + { + stuffingBits += over_bits; + ResvSize -= over_bits; + } + + if (stuffingBits) + { + /* + plan a: put all into the first granule + This was preferred by someone designing a + real-time decoder... + */ + cod_info = &l3_side->gr[0].ch[0].tt; + + if (cod_info->part2_3_length + stuffingBits < 4095) + cod_info->part2_3_length += stuffingBits; + else + { + /* plan b: distribute throughout the granules */ + for (gr = 0; gr < mode_gr; gr++) + { + for (ch = 0; ch < stereo; ch++) + { + int extraBits, bitsThisGr; + gr_info *cod_info = &l3_side->gr[gr].ch[ch].tt; + + if (stuffingBits == 0) + break; + extraBits = 4095 - cod_info->part2_3_length; + bitsThisGr = (extraBits < stuffingBits) ? extraBits : stuffingBits; + cod_info->part2_3_length += bitsThisGr; + stuffingBits -= bitsThisGr; + } + } + /* + If any stuffing bits remain, we elect to spill them + into ancillary data. The bitstream formatter will do this if + l3side->resvDrain is set + */ + l3_side->resvDrain = stuffingBits; + } + } +} diff -Nru swftools-0.9.2+ds1/lib/bladeenc/reservoir.h swftools-0.9.1/lib/bladeenc/reservoir.h --- swftools-0.9.2+ds1/lib/bladeenc/reservoir.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/reservoir.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,96 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-11 Andre Piotrowski + + - reformatted +*/ + +/********************************************************************** + * ISO MPEG Audio Subgroup Software Simulation Group (1996) + * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension + * + * $Id: reservoir.h,v 1.1 2002/01/10 17:30:01 kramm Exp $ + * + * $Log: reservoir.h,v $ + * Revision 1.1 2002/01/10 17:30:01 kramm + * Version 0.94.1 of the bladeenc mp3 encoder + * + * Revision 1.1 1996/02/14 04:04:23 rowlands + * Initial revision + * + * Received from Mike Coleman + **********************************************************************/ +/* + Revision History: + + Date Programmer Comment + ========== ========================= =============================== + 1995/09/06 mc@fivebats.com created + +*/ + +#ifndef __RESERVOIR__ +#define __RESERVOIR__ + + + + + +void ResvFrameBegin +( + frame_params *fr_ps, + III_side_info_t *l3_side, + int mean_bits, + int frameLength +); + +int ResvMaxBits +( + frame_params *fr_ps, + III_side_info_t *l3_side, + double *pe, + int mean_bits +); + +void ResvAdjust +( + frame_params *fr_ps, + gr_info *cod_info, + III_side_info_t *l3_side, + int mean_bits +); + +void ResvFrameEnd +( + frame_params *fr_ps, + III_side_info_t *l3_side, + int mean_bits +); + +void fixStatic_reservoir (void); + + + + + +#endif /* __RESERVOIR__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/subs.c swftools-0.9.1/lib/bladeenc/subs.c --- swftools-0.9.2+ds1/lib/bladeenc/subs.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/subs.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,300 @@ +/* + (c) Copyright 1998-2001 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-11-04 Andre Piotrowski + + - speed up: don«t calculate the unneeded phi values! + + 2000-11-22 ap + + - speed up: slightly improved way to handle the 'special case' + + 2000-12-05 ap + + - speed up: implemented prepacking + + 2000-12-11 ap + + - speed up: avoid data reordering + + 2000-12-12 ap + + - moved fft configuration switches to "l3psy.h" + + 2001-01-12 ap + + - use some explicit type casting to avoid compiler warnings +*/ + +/***************************************************************************** + * FFT computes fast fourier transform of BLKSIZE samples of data * + * based on the decimation-in-frequency algorithm described in "Digital * + * Signal Processing" by Oppenheim and Schafer, refer to pages 304 * + * (flow graph) and 330-332 (Fortran program in problem 5). * + * * + * required constants: * + * PI 3.14159265358979 * + * BLKSIZE should be 2^^M for a positive integer M * + * * + *****************************************************************************/ + +#include "common.h" +#include "encoder.h" +#include "l3psy.h" + + + + + +/* The switches have been moved to "l3psy.h" */ + + + + + +int fInit_fft; + + + + + +void fft (FLOAT x_real[], FLOAT x_imag[], FLOAT energy[], FLOAT phi[], int N) +{ + int i, j, k, off; +#if USED_VALUES_ONLY + int min_i, max_i; +#endif + int ip, le, le1; + static double w_real[BLKSIZE/2], w_imag[BLKSIZE/2]; + double t_real, t_imag, u_real, u_imag; + int N_ORG; + +#if !REORDER_DATA + static int swap_l[BLKSIZE/2+1]; + static int swap_s[BLKSIZE_s/2+1]; + int *pSwap, a, b; +#endif + + double t1, t2, t3, t4, t5, t6; + + if (fInit_fft == 0) + { + for (i = 0; i < BLKSIZE/2; i++) + { + w_real[i] = cos(PI*i/(BLKSIZE/2)); +#if NORMAL_FFT + w_imag[i] = -sin(PI*i/(BLKSIZE/2)); +#else + w_imag[i] = sin(PI*i/(BLKSIZE/2)); +#endif + } + +#if !REORDER_DATA + j = 0; + for (i = 0; i < BLKSIZE/2-1; i++) + { + swap_l[i] = j; k = BLKSIZE/4; while (k <= j) {j -= k; k >>= 1;} j += k; + } + swap_l[i] = i; swap_l[i+1] = i+1; + + j = 0; + for (i = 0; i < BLKSIZE_s/2-1; i++) + { + swap_s[i] = j; k = BLKSIZE_s/4; while (k <= j) {j -= k; k >>= 1;} j += k; + } + swap_s[i] = i; swap_s[i+1] = i+1; +#endif + + fInit_fft++; + } + + +#if REAL_SEQUENCE + N_ORG = N; + N >>= 1; +#if !PREPACKED + /* packing the sequence to the half length */ + for (i = 0; i < N; i++) + { + x_real[i] = x_real[2*i]; + x_imag[i] = x_real[2*i+1]; + } +#endif +#endif + + + off = BLKSIZE/N; + for (le = N; le > 1; le = le1) + { + le1 = le >> 1; + + /* special case: k=0; u_real=1.0; u_imag=0.0; j=0 */ + for (i = 0; i < N; i += le) + { + ip = i + le1; + t_real = x_real[i] - x_real[ip]; + t_imag = x_imag[i] - x_imag[ip]; + x_real[i] += x_real[ip]; + x_imag[i] += x_imag[ip]; + x_real[ip] = (FLOAT) t_real; + x_imag[ip] = (FLOAT) t_imag; + } + + k = off; + for (j = 1; j < le1; j++) + { + u_real = w_real[k]; + u_imag = w_imag[k]; + for (i = j; i < N; i += le) + { + ip = i + le1; + t_real = x_real[i] - x_real[ip]; + t_imag = x_imag[i] - x_imag[ip]; + x_real[i] += x_real[ip]; + x_imag[i] += x_imag[ip]; + x_real[ip] = (FLOAT) (t_real*u_real - t_imag*u_imag); + x_imag[ip] = (FLOAT) (t_imag*u_real + t_real*u_imag); + } + k += off; + } + + off += off; + } + + +#if REORDER_DATA + /* this section reorders the data to the correct ordering */ + j = 0; + for (i = 0; i < N-1; i++) + { + if (i < j) + { + t_real = x_real[j]; + t_imag = x_imag[j]; + x_real[j] = x_real[i]; + x_imag[j] = x_imag[i]; + x_real[i] = (FLOAT) t_real; + x_imag[i] = (FLOAT) t_imag; + } + k=N/2; + while (k <= j) + { + j -= k; + k >>= 1; + } + j += k; + } +#else + /* + We don«t reorder the data to the correct ordering, + but access the data by the bit reverse order index array. + */ + pSwap = (N_ORG == BLKSIZE) ? swap_l : swap_s; +#endif + + +#if REAL_SEQUENCE + /* unpacking the sequence */ + t_real = x_real[0]; + t_imag = x_imag[0]; + x_real[0] = (FLOAT) (t_real+t_imag); + x_imag[0] = 0.0; + x_real[N] = (FLOAT) (t_real-t_imag); + x_imag[N] = 0.0; + + k = off = BLKSIZE/N_ORG; + for (i = 1; i < N/2; i++) + { +#if REORDER_DATA +#define a i +#define b (N-i) +#else + a = pSwap[i]; + b = pSwap[N-i]; +#endif + t1 = x_real[a] + x_real[b]; + t2 = x_real[a] - x_real[b]; + t3 = x_imag[a] + x_imag[b]; + t4 = x_imag[a] - x_imag[b]; + t5 = t2*w_imag[k] + t3*w_real[k]; + t6 = t3*w_imag[k] - t2*w_real[k]; + + x_real[a] = (FLOAT) (t1+t5) / 2.0; + x_imag[a] = (FLOAT) (t6+t4) / 2.0; + x_real[b] = (FLOAT) (t1-t5) / 2.0; + x_imag[b] = (FLOAT) (t6-t4) / 2.0; + + k += off; + } + /* x_real[N/2] doesn«t change */ + /* x_real[N/2] changes the sign in case of a normal fft */ +#if (NORMAL_FFT) +#if REORDER_DATA + x_imag[i] = -x_imag[i]; +#else + x_imag[pSwap[i]] *= -1.0; +#endif /* REORDER_DATA */ +#endif /* NORMAL_FFT */ + N = N_ORG; +#endif /* REAL_SEQUENCE */ + + + /* calculating the energy and phase, phi */ +#if USED_VALUES_ONLY + if (N == BLKSIZE) + { + min_i = LONG_FFT_MIN_IDX; + max_i = LONG_FFT_MAX_IDX; + } + else + { + min_i = SHORT_FFT_MIN_IDX; + max_i = SHORT_FFT_MAX_IDX; + } +#endif +#if REAL_SEQUENCE + for (i = 0; i <= N/2; i++) +#else + for (i = 0; i < N; i++) +#endif + { +#if REORDER_DATA +#define a i +#else + a = pSwap[i]; +#endif + energy[i] = x_real[a]*x_real[a] + x_imag[a]*x_imag[a]; + if(energy[i] <= 0.0005) + { + energy[i] = (FLOAT) 0.0005; /* keep the identity */ + x_real[a] = (FLOAT) sqrt(0.0005); /* energy[i] * cos(phi[i]) == x_real[i] */ + x_imag[a] = 0.0; /* energy[i] * sin(phi[i]) == x_imag[i] */ + } +#if USED_VALUES_ONLY + if (i >= min_i && i <= max_i) +#endif + phi[i] = (FLOAT) atan2((double) x_imag[a], (double) x_real[a]); + } +} + + + diff -Nru swftools-0.9.2+ds1/lib/bladeenc/system.h swftools-0.9.1/lib/bladeenc/system.h --- swftools-0.9.2+ds1/lib/bladeenc/system.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/system.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,330 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression. + + This file doesn't contain any of the ISO reference code and + is copyright Tord Jansson (tord.jansson@swipnet.se). + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + Use TABSIZE 4!!! + + + + ------------ Changes ------------ + + 2000-12-11 Andre Piotrowski + + - added autodetection for Mac OS + + 2001-01-19 Tord Jansson + + - Added Andrea Vallinotto's Amiga WarpOS changes. + - Added some more defines and cleaned up. + +*/ + +#ifndef __SYSTEM__ +#define __SYSTEM__ + + + +/*==== THE SYSTEMS WE KNOW OF AND CAN AUTODETECT ==========================*/ + +#define UNIX_AUTOCONF 1 /* All well behaving UNIX systems where you run configure/make */ + /* Includes Linux, *BSD, Solaris, IRIX, UnixWare, SCO Open Server, AIX, HPUX */ + +#define WIN32_INTEL 2 /* Windows 95/98/NT/2k etc on i386 compatible machines */ + +#define BEOS 3 /* BeOS, version 4.5+ on i386 and PPC */ + +#define MSDOS_DJGPP 4 /* MS-DOS protected mode using DJGPP */ + +#define MAC_OS 5 /* To compile the Mac version you also need Petteri Kamppuri's wrapper */ + + + +/*==== SYSTEMS WE SUPPORT BUT DON'T KNOW HOW TO AUTODETECT YET ==============*/ +/*==== THESE NEEDS TO BE SET EXPLICITLY BELOW!!! ==============*/ + + +#define WIN32_ALPHA 6 /* Windows NT on DEC/Compaq Alpha architectures */ + +#define IBM_OS2 7 + +#define ATARI_TOS 8 + +#define AMIGA_WOS 9 /* Amiga WarpOS */ + + +/*= UNCOMMENT LINE AND SET SYSTEM HERE IF YOUR SYSTEM CAN'T BE AUTODETECTED! */ +/*===========================================================================*/ +/*#define SYSTEM MAC_OS*/ + +/*==== SYSTEM AUTODETECTION PROCEDURE ========================*/ + +#ifndef SYSTEM +# ifdef WIN32 +# define SYSTEM WIN32_INTEL +# endif + +# ifdef __BEOS__ +# define SYSTEM BEOS +# endif + +# ifdef __DJGPP__ +# define SYSTEM MSDOS_DJGPP +# endif + +# if defined(__dest_os) && (__dest_os == __mac_os) /* defined in "ansi_prefix.mac.h" */ +# define SYSTEM MAC_OS +# endif + +# ifndef SYSTEM +# define SYSTEM UNIX_AUTOCONF /* Take UNIX for granted... */ +# endif + +#endif + + + +/*==== Low level defines ======================================================*/ + +/* + LIST OF DEFINES + =============== + + BYTEORDER [byteorder] Should either be set to BIG_ENDIAN or LITTLE_ENDIAN + depending on the processor. + + DRAG_DROP Set if Drag-n-Drop operations are supported. If + defined, the hint for drag and drop is displayed + in the help text. + + PRIO Set if priority can be set with the -PRIO switch + (UNIX_SYSTEM enables this automatically). + + MSWIN Set this for MSWin systems. Includes "windows.h" etc. + + WILDCARDS Set this if the program has to expand wildcards + itself on your system. + + DIRECTORY_SEPARATOR Should either be '\\' or '/'. + (UNIX_SYSTEM automatically gives you '/'). + + WAIT_KEY Set this on systems where we as default want to + wait for a keypress before quiting. + + UNIX_SYSTEM Set this for UNIX-systems that are posix and + (at least to some extent) bsd compliant to enable + stuff like config-file support, priority settings etc. + + PAUSE_25_LINES Wait for keypress after 25 lines of output when + listing important information. +*/ + + +/* Most systems allready have these two defines, but some doesn't + so we have to put them here, before they are used. */ + +#ifndef BIG_ENDIAN +# define BIG_ENDIAN 4321 +#endif + +#ifndef LITTLE_ENDIAN +# define LITTLE_ENDIAN 1234 +#endif + + +/*____ UNIX with Autoconf support _____________________________________________*/ + +#if SYSTEM == UNIX_AUTOCONF +# ifdef BYTE_ORDER +# define BYTEORDER BYTE_ORDER +# else +# include "../../config.h" +# if WORDS_BIGENDIAN +# define BYTEORDER BIG_ENDIAN +# else +# define BYTEORDER LITTLE_ENDIAN +# endif +# endif +# define UNIX_SYSTEM +#endif + +/*_____ Windows 95/98/NT Intel defines ________________________________________*/ + +#if SYSTEM == WIN32_INTEL + +# define BYTEORDER LITTLE_ENDIAN +# define DRAG_DROP +# define PRIO +# define MSWIN +# define WILDCARDS +# define DIRECTORY_SEPARATOR '\\' +# define WAIT_KEY +# define PAUSE_25_LINES +#endif + +/*_____ Windows NT DEC Alpha defines __________________________________________*/ + +#if SYSTEM == WIN32_ALPHA + +# define BYTEORDER LITTLE_ENDIAN +# define DRAG_DROP +# define PRIO +# define MSWIN +# define WILDCARDS +# define DIRECTORY_SEPARATOR '\\' +# define WAIT_KEY +# define PAUSE_25_LINES +#endif + + +/*____ OS/2 _________________________________________________________________*/ + +#if SYSTEM == IBM_OS2 + +# define BYTEORDER LITTLE_ENDIAN +# define PRIO +# define WILDCARDS +# define DIRECTORY_SEPARATOR '\\' +# define OS2 +# define WAIT_KEY +# define PAUSE_25_LINES +#endif + + +/*____ Atari TOS ____________________________________________________________*/ + +#if SYSTEM == ATARI_TOS + +# define BYTEORDER BIG_ENDIAN +# define DIRECTORY_SEPARATOR '\\' +# define TOS +# define PAUSE_25_LINES +#endif + +/*____ MSDOS_DJGPP __________________________________________________________*/ + +#if SYSTEM == MSDOS_DJGPP + +# define BYTEORDER LITTLE_ENDIAN +# define DIRECTORY_SEPARATOR '\\' +#endif + +/*____ MAC_OS ________________________________________________________________*/ + +#if SYSTEM == MAC_OS + +# define BYTEORDER BIG_ENDIAN +# define DIRECTORY_SEPARATOR ':' +#endif + +/*____ BeOS PowerPC & x86 ___________________________________________________*/ + +#if SYSTEM == BEOS + +# ifdef __i386__ +# define BYTEORDER LITTLE_ENDIAN +# else +# define BYTEORDER BIG_ENDIAN +# endif +# define DIRECTORY_SEPARATOR '/' +#endif + +/*____ Amiga PowerPC WarpOS / VBCC or Storm-GCC_______________________________*/ + +#if SYSTEM == AMIGA_WOS +# define BYTEORDER BIG_ENDIAN +# define DIRECTORY_SEPARATOR '/' +# define SECOND_DIRECTORY_SEPARATOR ':' /* Special case for volumes */ +# define PRIO /* Yes, it can be done */ +# define WILDCARDS /* Uses dos/ParsePatternNoCase() and friends.*/ +# define PROTO_ARGS /* Undocumented, it's useful for GCC-Storm */ +# ifdef __VBCC__ +# pragma amiga-align +# endif +# include +# ifdef __VBCC__ +# pragma default-align +# endif + +#endif + + + +/*____ Some defines automatically gives other...*/ + +#ifdef UNIX_SYSTEM +# define PRIO +# define DIRECTORY_SEPARATOR '/' +#endif + + +/*==== COMPILER SPECIFIC DEFINES ============================================ */ +/* + Unfortunately the inline command differs slightly between compilers (for + example GCC calls it 'inline' while VC++ calls it '_inline'), so we have + to use our own define for it to keep everything compiler independent. + + Inline just speeds things up, so if we don't recognice the architecture we + just define an empty INLINE and take a minor performance hit. + +*/ + +#ifdef __GNUC__ /* GNU C and family */ +# define INLINE inline +#endif + +#ifdef __TURBOC__ /* Borland Turbo C, Turbo C++, and Borland C++ */ +# define INLINE __inline +#endif + +#ifdef _MSC /* Visual C++ */ +# define INLINE _inline +#endif + +#ifdef __STORM +# define INLINE __inline /* Storm C4 */ +#endif + +#ifdef __VBCC__ +# define INLINE /* VBCC */ +#endif + +#ifndef INLINE +# define INLINE /* Empty construct default, minor performance hit. */ +#endif + + +/*____ To make sure that certain necessary defines are set... */ + +#ifndef FALSE +# define FALSE 0 +#endif + +#ifndef TRUE +# define TRUE 1 +#endif + +/*==== Other Global Definitions, placed here for convenience ==================*/ + +/*#define PRECISE_TIMER*/ /* Gives more accurate speed calculations, */ + /* just for debug purposes. Disable in release version! */ + +typedef unsigned char uchar; + +#if (defined(UNIX_SYSTEM) && !defined(SYS_TYPES_H) && !defined(_SYS_TYPES_H)) || (!defined UNIX_SYSTEM && !defined(__GNUC__)) + typedef unsigned short ushort; + typedef unsigned int uint; +#endif + + +#endif /* __SYSTEM__ */ diff -Nru swftools-0.9.2+ds1/lib/bladeenc/tables.c swftools-0.9.1/lib/bladeenc/tables.c --- swftools-0.9.2+ds1/lib/bladeenc/tables.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/tables.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,1614 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-11-06 Andre Piotrowski + + - speed up: (for 'encode.c') traversed 'enwindow[]' needed for 'WIND_SB_CHANGE_LEVEL 3' +*/ + +#include "tables.h" +#include "huffman.h" + + + + +/* ======================================================================================== */ +/* L3 parameter tables */ +/* ======================================================================================== */ + + + + + +#if NEW_L3PARM_TABLES + +l3_parm_block l3_parm[3] = +{ + + { /* sfreq_idx_44100 */ + + { /* psy_longBlock_44100_62 */ + + 63, /* cbmax_l */ + + { /* numlines_l */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 4, + 4, 4, 5, 5, 5, 6, 6, 7, 7, + 7, 9, 9, 9, 10, 10, 11, 14, 14, + 15, 20, 20, 21, 27, 27, 36, 73, 18 + }, + { /* minval */ + 24.5, 24.5, 24.5, 24.5, 24.5, 20.0, 20.0, 20.0, 20.0, + 20.0, 20.0, 20.0, 18.0, 18.0, 18.0, 12.0, 6.0, 6.0, + 3.0, 3.0, 3.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, + { /* qthr_l */ + 4.532, 4.532, 4.532, 0.904, 0.904, 0.090, 0.090, 0.029, 0.029, + 0.029, 0.009, 0.009, 0.009, 0.009, 0.009, 0.018, 0.018, 0.018, + 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, + 0.018, 0.027, 0.027, 0.027, 0.027, 0.027, 0.027, 0.027, 0.036, + 0.036, 0.036, 0.045, 0.045, 0.045, 0.054, 0.054, 0.063, 0.063, + 0.063, 0.081, 0.081, 0.081, 0.180, 0.180, 0.198, 0.400, 0.400, + 0.429, 1.808, 1.808, 1.898, 24.416, 24.416, 32.554, 660.124, 162.770 + }, + +#if !CALC_NORM /* do we compute more exact values? */ + { /* norm_l */ + 0.951, 0.700, 0.681, 0.675, 0.667, 0.665, 0.664, 0.664, 0.664, + 0.655, 0.616, 0.597, 0.578, 0.541, 0.575, 0.856, 0.846, 0.840, + 0.822, 0.800, 0.753, 0.704, 0.674, 0.640, 0.609, 0.566, 0.535, + 0.531, 0.615, 0.686, 0.650, 0.612, 0.567, 0.520, 0.513, 0.557, + 0.584, 0.570, 0.579, 0.585, 0.548, 0.536, 0.550, 0.532, 0.504, + 0.496, 0.517, 0.527, 0.516, 0.497, 0.489, 0.502, 0.501, 0.491, + 0.497, 0.504, 0.504, 0.495, 0.486, 0.484, 0.483, 0.475, 0.515 + }, +#endif + { /* bval_l */ + 0.000, 0.431, 0.861, 1.292, 1.723, 2.153, 2.584, 3.015, 3.445, + 3.876, 4.279, 4.670, 5.057, 5.416, 5.774, 6.422, 7.026, 7.609, + 8.168, 8.710, 9.207, 9.662, 10.099, 10.515, 10.917, 11.293, 11.652, + 11.997, 12.394, 12.850, 13.277, 13.681, 14.062, 14.411, 14.751, 15.119, + 15.508, 15.883, 16.263, 16.654, 17.020, 17.374, 17.744, 18.104, 18.447, + 18.782, 19.130, 19.487, 19.838, 20.179, 20.510, 20.852, 21.196, 21.531, + 21.870, 22.214, 22.558, 22.898, 23.232, 23.564, 23.897, 24.229, 24.442 + } + + }, + + { /* psy_shortBlock_44100_38 */ + + 39, /* cbmax_s */ + + { /* numlines_s */ + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 3, 3, 3, + 3, 3, 4, 4, 5, 5, 5, + 7, 7, 7, 19, 0, 0, 0 + }, + { /* qthr_s */ + 4.532, 0.904, 0.029, 0.009, 0.009, 0.009, 0.009, + 0.009, 0.009, 0.009, 0.009, 0.009, 0.009, 0.009, + 0.009, 0.009, 0.009, 0.009, 0.009, 0.018, 0.018, + 0.018, 0.018, 0.018, 0.018, 0.027, 0.027, 0.054, + 0.054, 0.054, 0.114, 0.114, 0.452, 0.452, 0.452, + 6.330, 6.330, 6.330, 171.813, 0.000, 0.000, 0.000 + }, +#if !CALC_NORM /* do we compute more exact values? */ + { /* norm_s */ + 1.000, 0.983, 0.983, 0.982, 0.985, 0.983, 0.978, + 0.967, 0.948, 0.930, 0.914, 0.870, 0.845, 0.800, + 0.749, 0.701, 0.653, 0.590, 0.616, 0.860, 0.823, + 0.762, 0.688, 0.612, 0.594, 0.658, 0.706, 0.660, + 0.606, 0.565, 0.560, 0.579, 0.567, 0.534, 0.514, + 0.520, 0.518, 0.507, 0.447, 0.000, 0.000, 0.000 + }, +#endif + { /* SNR_s */ + -8.240, -8.240, -8.240, -8.240, -8.240, -8.240, -8.240, + -8.240, -8.240, -8.240, -7.447, -7.447, -7.447, -7.447, + -7.447, -7.447, -7.447, -7.447, -7.447, -7.447, -6.990, + -6.990, -6.990, -6.990, -6.990, -6.990, -6.990, -6.990, + -6.990, -6.990, -6.020, -6.020, -6.020, -6.020, -5.229, + -5.229, -5.229, -5.229, -4.559, 0.000, 0.000, 0.000 + }, + { /* bval_s */ + 0.000, 1.723, 3.445, 5.057, 6.422, 7.609, 8.710, + 9.662, 10.515, 11.293, 12.009, 12.625, 13.210, 13.748, + 14.241, 14.695, 15.125, 15.508, 15.891, 16.537, 17.112, + 17.621, 18.073, 18.470, 18.849, 19.271, 19.741, 20.177, + 20.576, 20.950, 21.316, 21.699, 22.078, 22.438, 22.782, + 23.133, 23.484, 23.828, 24.173, 0.000, 0.000, 0.000 + } + + }, + + { /* psy_data3_44100_20 */ + + { /* cbw_l */ + 3, 3, 4, 3, 3, 1, 3, + 3, 3, 3, 3, 3, 4, 3, + 3, 3, 3, 3, 2, 2, 2 + }, + { /* bu_l */ + 0, 4, 7, 11, 14, 17, 18, + 21, 24, 27, 30, 33, 36, 40, + 43, 46, 49, 52, 55, 57, 59 + }, + { /* bo_l */ + 4, 7, 11, 14, 17, 18, 21, + 24, 27, 30, 33, 36, 40, 43, + 46, 49, 52, 55, 57, 59, 61 + }, + { /* w1_l */ + 1.000, 0.944, 0.389, 0.833, 0.278, 0.861, 0.083, + 0.417, 0.750, 0.194, 0.426, 0.463, 0.180, 0.900, + 0.532, 0.376, 0.550, 0.448, 0.597, 0.357, 0.278 + }, + { /* w2_l */ + 0.056, 0.611, 0.167, 0.722, 0.139, 0.917, 0.583, + 0.250, 0.805, 0.574, 0.537, 0.819, 0.100, 0.468, + 0.623, 0.450, 0.552, 0.403, 0.643, 0.722, 0.960 + } + + }, + + { /* psy_data4_44100_11 */ + + { /* cbw_s */ + 2, 2, 3, 3, 4, 5, + 3, 4, 3, 3, 3, 2 + }, + { /* bu_s */ + 0, 3, 5, 8, 11, 15, + 20, 23, 27, 30, 33, 36 + }, + { /* bo_s */ + 2, 5, 8, 11, 15, 20, + 23, 27, 30, 33, 36, 38 + }, + { /* w1_s */ + 1.000, 0.833, 0.167, 0.500, 0.833, 0.833, + 0.750, 0.417, 0.944, 0.625, 0.700, 0.833 + }, + { /* w2_s */ + 0.167, 0.833, 0.500, 0.167, 0.167, 0.250, + 0.583, 0.055, 0.375, 0.300, 0.167, 1.000 + } + + } + + }, + + { /* sfreq_idx_48000 */ + + { /* psy_longBlock_48000_61 */ + + 62, /* cbmax_l */ + + { /* numlines_l */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 4, 4, + 4, 4, 4, 5, 5, 5, 6, 7, 7, + 8, 8, 8, 10, 10, 10, 13, 13, 14, + 18, 18, 20, 25, 25, 35, 67, 67, 0 + }, + { /* minval */ + 24.5, 24.5, 24.5, 24.5, 24.5, 20.0, 20.0, 20.0, 20.0, + 20.0, 20.0, 18.0, 18.0, 18.0, 12.0, 12.0, 6.0, 6.0, + 3.0, 3.0, 3.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, + { /* qthr_l */ + 4.532, 4.532, 4.532, 0.904, 0.904, 0.090, 0.090, 0.029, 0.029, + 0.009, 0.009, 0.009, 0.009, 0.009, 0.009, 0.009, 0.018, 0.018, + 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, + 0.018, 0.018, 0.027, 0.027, 0.027, 0.027, 0.027, 0.036, 0.036, + 0.036, 0.036, 0.036, 0.045, 0.045, 0.045, 0.054, 0.063, 0.063, + 0.072, 0.072, 0.072, 0.180, 0.180, 0.180, 0.372, 0.372, 0.400, + 1.627, 1.627, 1.808, 22.607, 22.607, 31.650, 605.867, 605.867, 0.000 + }, +#if !CALC_NORM /* do we compute more exact values? */ + { /* norm_l */ + 0.970, 0.755, 0.738, 0.730, 0.724, 0.723, 0.723, 0.723, 0.718, + 0.690, 0.660, 0.641, 0.600, 0.584, 0.532, 0.537, 0.857, 0.858, + 0.853, 0.824, 0.778, 0.740, 0.709, 0.676, 0.632, 0.592, 0.553, + 0.510, 0.513, 0.608, 0.673, 0.637, 0.586, 0.571, 0.616, 0.640, + 0.598, 0.538, 0.512, 0.528, 0.517, 0.493, 0.499, 0.525, 0.541, + 0.528, 0.510, 0.506, 0.525, 0.536, 0.518, 0.501, 0.497, 0.497, + 0.495, 0.494, 0.497, 0.494, 0.487, 0.483, 0.482, 0.524, 0.000 + }, +#endif + { /* bval_l */ + 0.000, 0.469, 0.938, 1.406, 1.875, 2.344, 2.813, 3.281, 3.750, + 4.199, 4.625, 5.047, 5.438, 5.828, 6.188, 6.522, 7.174, 7.801, + 8.402, 8.966, 9.484, 9.966, 10.426, 10.866, 11.279, 11.669, 12.042, + 12.386, 12.721, 13.115, 13.562, 13.984, 14.371, 14.741, 15.140, 15.563, + 15.962, 16.324, 16.665, 17.020, 17.373, 17.708, 18.045, 18.398, 18.762, + 19.120, 19.466, 19.807, 20.159, 20.522, 20.874, 21.214, 21.553, 21.892, + 22.231, 22.569, 22.909, 23.248, 23.583, 23.915, 24.246, 24.576, 0.000 + } + + }, + + { /* psy_shortBlock_48000_37 */ + + 38, /* cbmax_s */ + + { /* numlines_s */ + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 3, 3, + 3, 4, 4, 5, 5, 5, 7, + 7, 11, 17, 0, 0, 0, 0 + }, + { /* qthr_s */ + 4.532, 0.904, 0.029, 0.009, 0.009, 0.009, 0.009, + 0.009, 0.009, 0.009, 0.009, 0.009, 0.009, 0.009, + 0.009, 0.009, 0.009, 0.009, 0.009, 0.018, 0.018, + 0.018, 0.018, 0.018, 0.018, 0.018, 0.054, 0.054, + 0.054, 0.114, 0.114, 0.452, 0.452, 0.452, 6.330, + 6.330, 9.947, 153.727, 0.000, 0.000, 0.000, 0.000 + }, +#if !CALC_NORM /* do we compute more exact values? */ + { /* norm_s */ + 1.000, 0.989, 0.989, 0.981, 0.985, 0.984, 0.980, + 0.968, 0.954, 0.929, 0.906, 0.883, 0.844, 0.792, + 0.747, 0.689, 0.644, 0.592, 0.553, 0.850, 0.811, + 0.736, 0.665, 0.610, 0.544, 0.528, 0.621, 0.673, + 0.635, 0.626, 0.636, 0.615, 0.579, 0.551, 0.552, + 0.559, 0.528, 0.479, 0.000, 0.000, 0.000, 0.000 + }, +#endif + { /* SNR_s */ + -8.240, -8.240, -8.240, -8.240, -8.240, -8.240, -8.240, + -8.240, -8.240, -8.240, -7.447, -7.447, -7.447, -7.447, + -7.447, -7.447, -7.447, -7.447, -7.447, -7.447, -6.990, + -6.990, -6.990, -6.990, -6.990, -6.990, -6.990, -6.990, + -6.990, -6.990, -6.020, -6.020, -6.020, -6.020, -5.229, + -5.229, -5.229, -5.229, 0.000, 0.000, 0.000, 0.000 + }, + { /* bval_s */ + 0.000, 1.875, 3.750, 5.438, 6.857, 8.109, 9.237, + 10.202, 11.083, 11.865, 12.554, 13.195, 13.781, 14.309, + 14.803, 15.250, 15.667, 16.068, 16.409, 17.045, 17.607, + 18.097, 18.528, 18.931, 19.295, 19.636, 20.038, 20.486, + 20.900, 21.306, 21.722, 22.128, 22.513, 22.877, 23.241, + 23.616, 23.974, 24.313, 0.000, 0.000, 0.000, 0.000 + } + + }, + + { /* psy_data3_48000_20 */ + + { /* cbw_l */ + 3, 3, 4, 3, 3, 2, 3, + 2, 3, 3, 3, 3, 4, 3, + 3, 3, 3, 2, 3, 2, 1 + }, + { /* bu_l */ + 0, 4, 7, 11, 14, 17, 19, + 22, 24, 27, 30, 33, 36, 40, + 43, 46, 49, 52, 54, 57, 59 + }, + { /* bo_l */ + 4, 7, 11, 14, 17, 19, 22, + 24, 27, 30, 33, 36, 40, 43, + 46, 49, 52, 54, 57, 59, 60 + }, + { /* w1_l */ + 1.000, 0.944, 0.389, 0.833, 0.278, 0.361, 0.583, + 0.917, 0.250, 0.583, 0.352, 0.389, 0.375, 0.856, + 0.611, 0.840, 0.783, 0.816, 0.114, 0.687, 0.548 + }, + { /* w2_l */ + 0.056, 0.611, 0.167, 0.722, 0.639, 0.417, 0.083, + 0.750, 0.417, 0.648, 0.611, 0.625, 0.144, 0.389, + 0.160, 0.217, 0.184, 0.886, 0.313, 0.452, 0.908 + } + + }, + + { /* psy_data4_48000_11 */ + + { /* cbw_s */ + 2, 2, 3, 3, 4, 4, + 3, 4, 4, 2, 3, 2 + }, + { /* bu_s */ + 0, 3, 5, 8, 11, 15, + 19, 22, 26, 30, 32, 35 + }, + { /* bo_s */ + 2, 5, 8, 11, 15, 19, + 22, 26, 30, 32, 35, 37 + }, + { /* w1_s */ + 1.000, 0.833, 0.167, 0.500, 0.833, 0.833, + 0.417, 0.083, 0.055, 0.958, 0.433, 0.833 + }, + { /* w2_s */ + 0.167, 0.833, 0.500, 0.167, 0.167, 0.583, + 0.917, 0.944, 0.042, 0.567, 0.167, 0.618 + } + + } + + }, + + { /* sfreq_idx_32000 */ + + { /* psy_longBlock_32000_58 */ + + 59, /* cbmax_l */ + + { /* numlines_l */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 5, 5, 5, 5, 5, 6, + 6, 6, 8, 8, 8, 10, 10, 10, 12, + 12, 13, 14, 14, 16, 20, 20, 23, 27, + 27, 32, 37, 37, 12, 0, 0, 0, 0 + }, + { /* minval */ + 24.5, 24.5, 24.5, 20.0, 20.0, 20.0, 20.0, 20.0, 18.0, + 18.0, 12.0, 12.0, 6.0, 6.0, 6.0, 3.0, 3.0, 3.0, + 3.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }, + { /* qthr_l */ + 4.532, 4.532, 1.809, 0.181, 0.181, 0.057, 0.018, 0.018, 0.018, + 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, + 0.027, 0.027, 0.027, 0.027, 0.027, 0.027, 0.027, 0.027, 0.027, + 0.036, 0.036, 0.036, 0.045, 0.045, 0.045, 0.045, 0.045, 0.054, + 0.054, 0.054, 0.072, 0.072, 0.072, 0.090, 0.090, 0.090, 0.109, + 0.109, 0.118, 0.252, 0.252, 0.288, 0.572, 0.572, 0.658, 2.441, + 2.441, 2.893, 33.458, 33.458, 10.851, 0.000, 0.000, 0.000, 0.000 + }, +#if !CALC_NORM /* do we compute more exact values? */ + { /* norm_l */ + 0.997, 0.893, 0.881, 0.873, 0.872, 0.871, 0.860, 0.839, 0.812, + 0.784, 0.741, 0.697, 0.674, 0.651, 0.633, 0.611, 0.589, 0.575, + 0.654, 0.724, 0.701, 0.673, 0.631, 0.592, 0.553, 0.510, 0.506, + 0.562, 0.598, 0.589, 0.607, 0.620, 0.580, 0.532, 0.517, 0.517, + 0.509, 0.506, 0.522, 0.531, 0.519, 0.512, 0.509, 0.498, 0.494, + 0.501, 0.508, 0.502, 0.493, 0.497, 0.506, 0.510, 0.504, 0.496, + 0.493, 0.490, 0.482, 0.458, 0.500, 0.000, 0.000, 0.000, 0.000 + }, +#endif + { /* bval_l */ + 0.313, 0.938, 1.563, 2.188, 2.813, 3.438, 4.045, 4.625, 5.173, + 5.698, 6.185, 6.634, 7.070, 7.492, 7.905, 8.305, 8.695, 9.064, + 9.484, 9.966, 10.426, 10.866, 11.279, 11.669, 12.042, 12.386, 12.721, + 13.091, 13.488, 13.873, 14.268, 14.679, 15.067, 15.424, 15.771, 16.120, + 16.466, 16.807, 17.158, 17.518, 17.869, 18.215, 18.563, 18.902, 19.239, + 19.580, 19.925, 20.269, 20.606, 20.944, 21.288, 21.635, 21.980, 22.319, + 22.656, 22.993, 23.326, 23.656, 23.937, 0.000, 0.000, 0.000, 0.000 + } + + }, + + { /* psy_shortBlock_32000_41 */ + + 42, /* cbmax_s */ + + { /* numlines_s */ + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 3, + 3, 3, 3, 3, 4, 4, 4, + 5, 5, 6, 7, 7, 8, 10 + }, + { /* qthr_s */ + 4.532, 0.904, 0.090, 0.029, 0.009, 0.009, 0.009, + 0.009, 0.009, 0.009, 0.009, 0.009, 0.009, 0.009, + 0.009, 0.009, 0.009, 0.009, 0.009, 0.018, 0.018, + 0.018, 0.018, 0.018, 0.018, 0.018, 0.018, 0.027, + 0.027, 0.027, 0.027, 0.027, 0.072, 0.072, 0.072, + 0.143, 0.143, 0.172, 0.633, 0.633, 0.723, 9.043 + }, +#if !CALC_NORM /* do we compute more exact values? */ + { /* norm_s */ + 1.000, 0.985, 0.983, 0.983, 0.981, 0.975, 0.959, + 0.944, 0.933, 0.920, 0.892, 0.863, 0.839, 0.786, + 0.755, 0.698, 0.673, 0.605, 0.629, 0.883, 0.858, + 0.829, 0.767, 0.705, 0.637, 0.564, 0.550, 0.603, + 0.635, 0.592, 0.533, 0.518, 0.568, 0.594, 0.568, + 0.536, 0.522, 0.542, 0.539, 0.519, 0.514, 0.518 + }, +#endif + { /* SNR_s */ + -8.240, -8.240, -8.240, -8.240, -8.240, -8.240, -8.240, + -8.240, -8.240, -8.240, -7.447, -7.447, -7.447, -7.447, + -7.447, -7.447, -7.447, -7.447, -7.447, -7.447, -6.990, + -6.990, -6.990, -6.990, -6.990, -6.990, -6.990, -6.990, + -6.990, -6.990, -6.020, -6.020, -6.020, -6.020, -5.229, + -5.229, -5.229, -5.229, -4.559, -4.559, -3.980, -3.980 + }, + { /* bval_s */ + 0.000, 1.250, 2.500, 3.750, 4.909, 5.958, 6.857, + 7.700, 8.500, 9.237, 9.895, 10.500, 11.083, 11.604, + 12.107, 12.554, 13.000, 13.391, 13.781, 14.474, 15.096, + 15.667, 16.177, 16.636, 17.057, 17.429, 17.786, 18.177, + 18.597, 18.994, 19.352, 19.693, 20.066, 20.462, 20.841, + 21.201, 21.549, 21.911, 22.275, 22.625, 22.971, 23.321 + } + + }, + + { /* psy_data3_32000_20 */ + + { /* cbw_l */ + 1, 2, 2, 1, 2, 2, 3, + 2, 3, 3, 4, 4, 4, 3, + 4, 3, 4, 3, 3, 2, 2 + }, + { /* bu_l */ + 0, 2, 4, 6, 7, 9, 11, + 14, 16, 19, 22, 26, 30, 34, + 37, 41, 44, 48, 51, 54, 56 + }, + { /* bo_l */ + 2, 4, 6, 7, 9, 11, 14, + 16, 19, 22, 26, 30, 34, 37, + 41, 44, 48, 51, 54, 56, 58 + }, + { /* w1_l */ + 1.000, 0.472, 0.694, 0.917, 0.139, 0.361, 0.583, + 0.917, 0.250, 0.130, 0.167, 0.611, 0.522, 0.967, + 0.083, 0.383, 0.005, 0.726, 0.519, 0.739, 0.116 + }, + { /* w2_l */ + 0.528, 0.305, 0.083, 0.861, 0.639, 0.417, 0.083, + 0.750, 0.870, 0.833, 0.389, 0.478, 0.033, 0.917, + 0.617, 0.995, 0.274, 0.480, 0.261, 0.884, 1.000 + } + + }, + + { /* psy_data4_32000_11 */ + + { /* cbw_s */ + 2, 2, 3, 3, 4, 5, + 4, 5, 4, 4, 3, 1 + }, + { /* bu_s */ + 0, 3, 5, 8, 11, 15, + 20, 24, 29, 33, 37, 40 + }, + { /* bo_s */ + 2, 5, 8, 11, 15, 20, + 24, 29, 33, 37, 40, 41 + }, + { /* w1_s */ + 1.000, 0.833, 0.167, 0.500, 0.833, 0.833, + 0.750, 0.750, 0.944, 0.625, 0.528, 0.062 + }, + { /* w2_s */ + 0.167, 0.833, 0.500, 0.167, 0.167, 0.250, + 0.250, 0.055, 0.375, 0.472, 0.937, 1.000 + } + + } + + } + +}; + +#else /* NEW_L3PARM_TABLES */ + +psyDataElem psy_longBlock_48000_61[62] = +{ + { 1 ,24.5 , 4.532 ,0.970 , 0.000 }, + { 1 ,24.5 , 4.532 ,0.755 , 0.469 }, + { 1 ,24.5 , 4.532 ,0.738 , 0.938 }, + { 1 ,24.5 , 0.904 ,0.730 , 1.406 }, + { 1 ,24.5 , 0.904 ,0.724 , 1.875 }, + { 1 ,20.0 , 0.090 ,0.723 , 2.344 }, + { 1 ,20.0 , 0.090 ,0.723 , 2.813 }, + { 1 ,20.0 , 0.029 ,0.723 , 3.281 }, + { 1 ,20.0 , 0.029 ,0.718 , 3.750 }, + { 1 ,20.0 , 0.009 ,0.690 , 4.199 }, + { 1 ,20.0 , 0.009 ,0.660 , 4.625 }, + { 1 ,18.0 , 0.009 ,0.641 , 5.047 }, + { 1 ,18.0 , 0.009 ,0.600 , 5.438 }, + { 1 ,18.0 , 0.009 ,0.584 , 5.828 }, + { 1 ,12.0 , 0.009 ,0.532 , 6.188 }, + { 1 ,12.0 , 0.009 ,0.537 , 6.522 }, + { 2 , 6.0 , 0.018 ,0.857 , 7.174 }, + { 2 , 6.0 , 0.018 ,0.858 , 7.801 }, + { 2 , 3.0 , 0.018 ,0.853 , 8.402 }, + { 2 , 3.0 , 0.018 ,0.824 , 8.966 }, + { 2 , 3.0 , 0.018 ,0.778 , 9.484 }, + { 2 , 3.0 , 0.018 ,0.740 , 9.966 }, + { 2 , 0.0 , 0.018 ,0.709 , 10.426 }, + + { 2 , 0.0 , 0.018 ,0.676 , 10.866 }, + { 2 , 0.0 , 0.018 ,0.632 , 11.279 }, + { 2 , 0.0 , 0.018 ,0.592 , 11.669 }, + { 2 , 0.0 , 0.018 ,0.553 , 12.042 }, + { 2 , 0.0 , 0.018 ,0.510 , 12.386 }, + { 2 , 0.0 , 0.018 ,0.513 , 12.721 }, + { 3 , 0.0 , 0.027 ,0.608 , 13.115 }, + { 3 , 0.0 , 0.027 ,0.673 , 13.562 }, + { 3 , 0.0 , 0.027 ,0.637 , 13.984 }, + { 3 , 0.0 , 0.027 ,0.586 , 14.371 }, + { 3 , 0.0 , 0.027 ,0.571 , 14.741 }, + { 4 , 0.0 , 0.036 ,0.616 , 15.140 }, + { 4 , 0.0 , 0.036 ,0.640 , 15.563 }, + { 4 , 0.0 , 0.036 ,0.598 , 15.962 }, + { 4 , 0.0 , 0.036 ,0.538 , 16.324 }, + { 4 , 0.0 , 0.036 ,0.512 , 16.665 }, + { 5 , 0.0 , 0.045 ,0.528 , 17.020 }, + { 5 , 0.0 , 0.045 ,0.517 , 17.373 }, + { 5 , 0.0 , 0.045 ,0.493 , 17.708 }, + { 6 , 0.0 , 0.054 ,0.499 , 18.045 }, + { 7 , 0.0 , 0.063 ,0.525 , 18.398 }, + { 7 , 0.0 , 0.063 ,0.541 , 18.762 }, + { 8 , 0.0 , 0.072 ,0.528 , 19.120 }, + { 8 , 0.0 , 0.072 ,0.510 , 19.466 }, + { 8 , 0.0 , 0.072 ,0.506 , 19.807 }, + {10 , 0.0 , 0.180 ,0.525 , 20.159 }, + {10 , 0.0 , 0.180 ,0.536 , 20.522 }, + {10 , 0.0 , 0.180 ,0.518 , 20.874 }, + {13 , 0.0 , 0.372 ,0.501 , 21.214 }, + {13 , 0.0 , 0.372 ,0.497 , 21.553 }, + {14 , 0.0 , 0.400 ,0.497 , 21.892 }, + {18 , 0.0 , 1.627 ,0.495 , 22.231 }, + {18 , 0.0 , 1.627 ,0.494 , 22.569 }, + {20 , 0.0 , 1.808 ,0.497 , 22.909 }, + {25 , 0.0 , 22.607 ,0.494 , 23.248 }, + {25 , 0.0 , 22.607 ,0.487 , 23.583 }, + {35 , 0.0 , 31.650 ,0.483 , 23.915 }, + {67 , 0.0 , 605.867 ,0.482 , 24.246 }, + {67 , 0.0 , 605.867 ,0.524 , 24.576 } +}; + +psyDataElem psy_longBlock_44100_62[63] = +{ + { 1 ,24.5 , 4.532 ,0.951 , 0.000 }, + { 1 ,24.5 , 4.532 ,0.700 , 0.431 }, + { 1 ,24.5 , 4.532 ,0.681 , 0.861 }, + { 1 ,24.5 , 0.904 ,0.675 , 1.292 }, + { 1 ,24.5 , 0.904 ,0.667 , 1.723 }, + { 1 ,20.0 , 0.090 ,0.665 , 2.153 }, + { 1 ,20.0 , 0.090 ,0.664 , 2.584 }, + { 1 ,20.0 , 0.029 ,0.664 , 3.015 }, + { 1 ,20.0 , 0.029 ,0.664 , 3.445 }, + { 1 ,20.0 , 0.029 ,0.655 , 3.876 }, + { 1 ,20.0 , 0.009 ,0.616 , 4.279 }, + { 1 ,20.0 , 0.009 ,0.597 , 4.670 }, + { 1 ,18.0 , 0.009 ,0.578 , 5.057 }, + { 1 ,18.0 , 0.009 ,0.541 , 5.416 }, + { 1 ,18.0 , 0.009 ,0.575 , 5.774 }, + { 2 ,12.0 , 0.018 ,0.856 , 6.422 }, + { 2 , 6.0 , 0.018 ,0.846 , 7.026 }, + { 2 , 6.0 , 0.018 ,0.840 , 7.609 }, + { 2 , 3.0 , 0.018 ,0.822 , 8.168 }, + { 2 , 3.0 , 0.018 ,0.800 , 8.710 }, + { 2 , 3.0 , 0.018 ,0.753 , 9.207 }, + { 2 , 3.0 , 0.018 ,0.704 , 9.662 }, + { 2 , 0.0 , 0.018 ,0.674 , 10.099 }, + { 2 , 0.0 , 0.018 ,0.640 , 10.515 }, + { 2 , 0.0 , 0.018 ,0.609 , 10.917 }, + { 2 , 0.0 , 0.018 ,0.566 , 11.293 }, + { 2 , 0.0 , 0.018 ,0.535 , 11.652 }, + { 2 , 0.0 , 0.018 ,0.531 , 11.997 }, + { 3 , 0.0 , 0.027 ,0.615 , 12.394 }, + { 3 , 0.0 , 0.027 ,0.686 , 12.850 }, + { 3 , 0.0 , 0.027 ,0.650 , 13.277 }, + { 3 , 0.0 , 0.027 ,0.612 , 13.681 }, + { 3 , 0.0 , 0.027 ,0.567 , 14.062 }, + { 3 , 0.0 , 0.027 ,0.520 , 14.411 }, + { 3 , 0.0 , 0.027 ,0.513 , 14.751 }, + { 4 , 0.0 , 0.036 ,0.557 , 15.119 }, + { 4 , 0.0 , 0.036 ,0.584 , 15.508 }, + { 4 , 0.0 , 0.036 ,0.570 , 15.883 }, + { 5 , 0.0 , 0.045 ,0.579 , 16.263 }, + { 5 , 0.0 , 0.045 ,0.585 , 16.654 }, + { 5 , 0.0 , 0.045 ,0.548 , 17.020 }, + { 6 , 0.0 , 0.054 ,0.536 , 17.374 }, + { 6 , 0.0 , 0.054 ,0.550 , 17.744 }, + { 7 , 0.0 , 0.063 ,0.532 , 18.104 }, + { 7 , 0.0 , 0.063 ,0.504 , 18.447 }, + { 7 , 0.0 , 0.063 ,0.496 , 18.782 }, + { 9 , 0.0 , 0.081 ,0.517 , 19.130 }, + { 9 , 0.0 , 0.081 ,0.527 , 19.487 }, + { 9 , 0.0 , 0.081 ,0.516 , 19.838 }, + {10 , 0.0 , 0.180 ,0.497 , 20.179 }, + {10 , 0.0 , 0.180 ,0.489 , 20.510 }, + {11 , 0.0 , 0.198 ,0.502 , 20.852 }, + {14 , 0.0 , 0.400 ,0.501 , 21.196 }, + {14 , 0.0 , 0.400 ,0.491 , 21.531 }, + {15 , 0.0 , 0.429 ,0.497 , 21.870 }, + {20 , 0.0 , 1.808 ,0.504 , 22.214 }, + {20 , 0.0 , 1.808 ,0.504 , 22.558 }, + {21 , 0.0 , 1.898 ,0.495 , 22.898 }, + {27 , 0.0 , 24.416 ,0.486 , 23.232 }, + {27 , 0.0 , 24.416 ,0.484 , 23.564 }, + {36 , 0.0 , 32.554 ,0.483 , 23.897 }, + {73 , 0.0 , 660.124 ,0.475 , 24.229 }, + {18 , 0.0 , 162.770 ,0.515 , 24.442 } +}; + +psyDataElem psy_longBlock_32000_58[59] = +{ + { 2 ,24.5 , 4.532 ,0.997 , 0.313 }, + { 2 ,24.5 , 4.532 ,0.893 , 0.938 }, + { 2 ,24.5 , 1.809 ,0.881 , 1.563 }, + { 2 ,20.0 , 0.181 ,0.873 , 2.188 }, + { 2 ,20.0 , 0.181 ,0.872 , 2.813 }, + { 2 ,20.0 , 0.057 ,0.871 , 3.438 }, + { 2 ,20.0 , 0.018 ,0.860 , 4.045 }, + { 2 ,20.0 , 0.018 ,0.839 , 4.625 }, + { 2 ,18.0 , 0.018 ,0.812 , 5.173 }, + { 2 ,18.0 , 0.018 ,0.784 , 5.698 }, + { 2 ,12.0 , 0.018 ,0.741 , 6.185 }, + { 2 ,12.0 , 0.018 ,0.697 , 6.634 }, + { 2 , 6.0 , 0.018 ,0.674 , 7.070 }, + { 2 , 6.0 , 0.018 ,0.651 , 7.492 }, + { 2 , 6.0 , 0.018 ,0.633 , 7.905 }, + { 2 , 3.0 , 0.018 ,0.611 , 8.305 }, + { 2 , 3.0 , 0.018 ,0.589 , 8.695 }, + { 2 , 3.0 , 0.018 ,0.575 , 9.064 }, + { 3 , 3.0 , 0.027 ,0.654 , 9.484 }, + { 3 , 3.0 , 0.027 ,0.724 , 9.966 }, + { 3 , 0.0 , 0.027 ,0.701 , 10.426 }, + { 3 , 0.0 , 0.027 ,0.673 , 10.866 }, + { 3 , 0.0 , 0.027 ,0.631 , 11.279 }, + { 3 , 0.0 , 0.027 ,0.592 , 11.669 }, + { 3 , 0.0 , 0.027 ,0.553 , 12.042 }, + { 3 , 0.0 , 0.027 ,0.510 , 12.386 }, + { 3 , 0.0 , 0.027 ,0.506 , 12.721 }, + { 4 , 0.0 , 0.036 ,0.562 , 13.091 }, + { 4 , 0.0 , 0.036 ,0.598 , 13.488 }, + { 4 , 0.0 , 0.036 ,0.589 , 13.873 }, + { 5 , 0.0 , 0.045 ,0.607 , 14.268 }, + { 5 , 0.0 , 0.045 ,0.620 , 14.679 }, + { 5 , 0.0 , 0.045 ,0.580 , 15.067 }, + { 5 , 0.0 , 0.045 ,0.532 , 15.424 }, + { 5 , 0.0 , 0.045 ,0.517 , 15.771 }, + { 6 , 0.0 , 0.054 ,0.517 , 16.120 }, + { 6 , 0.0 , 0.054 ,0.509 , 16.466 }, + { 6 , 0.0 , 0.054 ,0.506 , 16.807 }, + { 8 , 0.0 , 0.072 ,0.522 , 17.158 }, + { 8 , 0.0 , 0.072 ,0.531 , 17.518 }, + { 8 , 0.0 , 0.072 ,0.519 , 17.869 }, + {10 , 0.0 , 0.090 ,0.512 , 18.215 }, + {10 , 0.0 , 0.090 ,0.509 , 18.563 }, + {10 , 0.0 , 0.090 ,0.498 , 18.902 }, + {12 , 0.0 , 0.109 ,0.494 , 19.239 }, + {12 , 0.0 , 0.109 ,0.501 , 19.580 }, + {13 , 0.0 , 0.118 ,0.508 , 19.925 }, + {14 , 0.0 , 0.252 ,0.502 , 20.269 }, + {14 , 0.0 , 0.252 ,0.493 , 20.606 }, + {16 , 0.0 , 0.288 ,0.497 , 20.944 }, + {20 , 0.0 , 0.572 ,0.506 , 21.288 }, + {20 , 0.0 , 0.572 ,0.510 , 21.635 }, + {23 , 0.0 , 0.658 ,0.504 , 21.980 }, + {27 , 0.0 , 2.441 ,0.496 , 22.319 }, + {27 , 0.0 , 2.441 ,0.493 , 22.656 }, + {32 , 0.0 , 2.893 ,0.490 , 22.993 }, + {37 , 0.0 , 33.458 ,0.482 , 23.326 }, + {37 , 0.0 , 33.458 ,0.458 , 23.656 }, + {12 , 0.0 , 10.851 ,0.500 , 23.937 } +}; + + +psyDataElem2 psy_shortBlock_48000_37[38] = +{ + { 1 , 4.532 ,1.000 ,-8.240 , 0.000 }, + { 1 , 0.904 ,0.989 ,-8.240 , 1.875 }, + { 1 , 0.029 ,0.989 ,-8.240 , 3.750 }, + { 1 , 0.009 ,0.981 ,-8.240 , 5.438 }, + { 1 , 0.009 ,0.985 ,-8.240 , 6.857 }, + { 1 , 0.009 ,0.984 ,-8.240 , 8.109 }, + { 1 , 0.009 ,0.980 ,-8.240 , 9.237 }, + { 1 , 0.009 ,0.968 ,-8.240 , 10.202 }, + { 1 , 0.009 ,0.954 ,-8.240 , 11.083 }, + { 1 , 0.009 ,0.929 ,-8.240 , 11.865 }, + { 1 , 0.009 ,0.906 ,-7.447 , 12.554 }, + { 1 , 0.009 ,0.883 ,-7.447 , 13.195 }, + { 1 , 0.009 ,0.844 ,-7.447 , 13.781 }, + { 1 , 0.009 ,0.792 ,-7.447 , 14.309 }, + { 1 , 0.009 ,0.747 ,-7.447 , 14.803 }, + { 1 , 0.009 ,0.689 ,-7.447 , 15.250 }, + { 1 , 0.009 ,0.644 ,-7.447 , 15.667 }, + { 1 , 0.009 ,0.592 ,-7.447 , 16.068 }, + { 1 , 0.009 ,0.553 ,-7.447 , 16.409 }, + { 2 , 0.018 ,0.850 ,-7.447 , 17.045 }, + { 2 , 0.018 ,0.811 ,-6.990 , 17.607 }, + { 2 , 0.018 ,0.736 ,-6.990 , 18.097 }, + { 2 , 0.018 ,0.665 ,-6.990 , 18.528 }, + { 2 , 0.018 ,0.610 ,-6.990 , 18.931 }, + { 2 , 0.018 ,0.544 ,-6.990 , 19.295 }, + { 2 , 0.018 ,0.528 ,-6.990 , 19.636 }, + { 3 , 0.054 ,0.621 ,-6.990 , 20.038 }, + { 3 , 0.054 ,0.673 ,-6.990 , 20.486 }, + { 3 , 0.054 ,0.635 ,-6.990 , 20.900 }, + { 4 , 0.114 ,0.626 ,-6.990 , 21.306 }, + { 4 , 0.114 ,0.636 ,-6.020 , 21.722 }, + { 5 , 0.452 ,0.615 ,-6.020 , 22.128 }, + { 5 , 0.452 ,0.579 ,-6.020 , 22.513 }, + { 5 , 0.452 ,0.551 ,-6.020 , 22.877 }, + { 7 , 6.330 ,0.552 ,-5.229 , 23.241 }, + { 7 , 6.330 ,0.559 ,-5.229 , 23.616 }, + {11 , 9.947 ,0.528 ,-5.229 , 23.974 }, + {17 , 153.727 ,0.479 ,-5.229 , 24.313 } +}; + +psyDataElem2 psy_shortBlock_44100_38[39] = +{ + { 1 , 4.532 ,1.000 ,-8.240 , 0.000 }, + { 1 , 0.904 ,0.983 ,-8.240 , 1.723 }, + { 1 , 0.029 ,0.983 ,-8.240 , 3.445 }, + { 1 , 0.009 ,0.982 ,-8.240 , 5.057 }, + { 1 , 0.009 ,0.985 ,-8.240 , 6.422 }, + { 1 , 0.009 ,0.983 ,-8.240 , 7.609 }, + { 1 , 0.009 ,0.978 ,-8.240 , 8.710 }, + { 1 , 0.009 ,0.967 ,-8.240 , 9.662 }, + { 1 , 0.009 ,0.948 ,-8.240 , 10.515 }, + { 1 , 0.009 ,0.930 ,-8.240 , 11.293 }, + { 1 , 0.009 ,0.914 ,-7.447 , 12.009 }, + { 1 , 0.009 ,0.870 ,-7.447 , 12.625 }, + { 1 , 0.009 ,0.845 ,-7.447 , 13.210 }, + { 1 , 0.009 ,0.800 ,-7.447 , 13.748 }, + { 1 , 0.009 ,0.749 ,-7.447 , 14.241 }, + { 1 , 0.009 ,0.701 ,-7.447 , 14.695 }, + { 1 , 0.009 ,0.653 ,-7.447 , 15.125 }, + { 1 , 0.009 ,0.590 ,-7.447 , 15.508 }, + { 1 , 0.009 ,0.616 ,-7.447 , 15.891 }, + { 2 , 0.018 ,0.860 ,-7.447 , 16.537 }, + { 2 , 0.018 ,0.823 ,-6.990 , 17.112 }, + { 2 , 0.018 ,0.762 ,-6.990 , 17.621 }, + { 2 , 0.018 ,0.688 ,-6.990 , 18.073 }, + { 2 , 0.018 ,0.612 ,-6.990 , 18.470 }, + { 2 , 0.018 ,0.594 ,-6.990 , 18.849 }, + { 3 , 0.027 ,0.658 ,-6.990 , 19.271 }, + { 3 , 0.027 ,0.706 ,-6.990 , 19.741 }, + { 3 , 0.054 ,0.660 ,-6.990 , 20.177 }, + { 3 , 0.054 ,0.606 ,-6.990 , 20.576 }, + { 3 , 0.054 ,0.565 ,-6.990 , 20.950 }, + { 4 , 0.114 ,0.560 ,-6.020 , 21.316 }, + { 4 , 0.114 ,0.579 ,-6.020 , 21.699 }, + { 5 , 0.452 ,0.567 ,-6.020 , 22.078 }, + { 5 , 0.452 ,0.534 ,-6.020 , 22.438 }, + { 5 , 0.452 ,0.514 ,-5.229 , 22.782 }, + { 7 , 6.330 ,0.520 ,-5.229 , 23.133 }, + { 7 , 6.330 ,0.518 ,-5.229 , 23.484 }, + { 7 , 6.330 ,0.507 ,-5.229 , 23.828 }, + {19 , 171.813 ,0.447 ,-4.559 , 24.173 } +}; + +psyDataElem2 psy_shortBlock_32000_41[42] = +{ + { 1 , 4.532 ,1.000 ,-8.240 , 0.000 }, + { 1 , 0.904 ,0.985 ,-8.240 , 1.250 }, + { 1 , 0.090 ,0.983 ,-8.240 , 2.500 }, + { 1 , 0.029 ,0.983 ,-8.240 , 3.750 }, + { 1 , 0.009 ,0.981 ,-8.240 , 4.909 }, + { 1 , 0.009 ,0.975 ,-8.240 , 5.958 }, + { 1 , 0.009 ,0.959 ,-8.240 , 6.857 }, + { 1 , 0.009 ,0.944 ,-8.240 , 7.700 }, + { 1 , 0.009 ,0.933 ,-8.240 , 8.500 }, + { 1 , 0.009 ,0.920 ,-8.240 , 9.237 }, + { 1 , 0.009 ,0.892 ,-7.447 , 9.895 }, + { 1 , 0.009 ,0.863 ,-7.447 , 10.500 }, + { 1 , 0.009 ,0.839 ,-7.447 , 11.083 }, + { 1 , 0.009 ,0.786 ,-7.447 , 11.604 }, + { 1 , 0.009 ,0.755 ,-7.447 , 12.107 }, + { 1 , 0.009 ,0.698 ,-7.447 , 12.554 }, + { 1 , 0.009 ,0.673 ,-7.447 , 13.000 }, + { 1 , 0.009 ,0.605 ,-7.447 , 13.391 }, + { 1 , 0.009 ,0.629 ,-7.447 , 13.781 }, + { 2 , 0.018 ,0.883 ,-7.447 , 14.474 }, + { 2 , 0.018 ,0.858 ,-6.990 , 15.096 }, + { 2 , 0.018 ,0.829 ,-6.990 , 15.667 }, + { 2 , 0.018 ,0.767 ,-6.990 , 16.177 }, + { 2 , 0.018 ,0.705 ,-6.990 , 16.636 }, + { 2 , 0.018 ,0.637 ,-6.990 , 17.057 }, + { 2 , 0.018 ,0.564 ,-6.990 , 17.429 }, + { 2 , 0.018 ,0.550 ,-6.990 , 17.786 }, + { 3 , 0.027 ,0.603 ,-6.990 , 18.177 }, + { 3 , 0.027 ,0.635 ,-6.990 , 18.597 }, + { 3 , 0.027 ,0.592 ,-6.990 , 18.994 }, + { 3 , 0.027 ,0.533 ,-6.020 , 19.352 }, + { 3 , 0.027 ,0.518 ,-6.020 , 19.693 }, + { 4 , 0.072 ,0.568 ,-6.020 , 20.066 }, + { 4 , 0.072 ,0.594 ,-6.020 , 20.462 }, + { 4 , 0.072 ,0.568 ,-5.229 , 20.841 }, + { 5 , 0.143 ,0.536 ,-5.229 , 21.201 }, + { 5 , 0.143 ,0.522 ,-5.229 , 21.549 }, + { 6 , 0.172 ,0.542 ,-5.229 , 21.911 }, + { 7 , 0.633 ,0.539 ,-4.559 , 22.275 }, + { 7 , 0.633 ,0.519 ,-4.559 , 22.625 }, + { 8 , 0.723 ,0.514 ,-3.980 , 22.971 }, + {10 , 9.043 ,0.518 ,-3.980 , 23.321 } +}; + + +psyDataElem3 psy_data3_48000_20[21] = +{ + { 3 , 0 , 4 ,1.000 ,0.056 }, + { 3 , 4 , 7 ,0.944 ,0.611 }, + { 4 , 7 ,11 ,0.389 ,0.167 }, + { 3 ,11 ,14 ,0.833 ,0.722 }, + { 3 ,14 ,17 ,0.278 ,0.639 }, + { 2 ,17 ,19 ,0.361 ,0.417 }, + { 3 ,19 ,22 ,0.583 ,0.083 }, + { 2 ,22 ,24 ,0.917 ,0.750 }, + { 3 ,24 ,27 ,0.250 ,0.417 }, + { 3 ,27 ,30 ,0.583 ,0.648 }, + { 3 ,30 ,33 ,0.352 ,0.611 }, + { 3 ,33 ,36 ,0.389 ,0.625 }, + { 4 ,36 ,40 ,0.375 ,0.144 }, + { 3 ,40 ,43 ,0.856 ,0.389 }, + { 3 ,43 ,46 ,0.611 ,0.160 }, + { 3 ,46 ,49 ,0.840 ,0.217 }, + { 3 ,49 ,52 ,0.783 ,0.184 }, + { 2 ,52 ,54 ,0.816 ,0.886 }, + { 3 ,54 ,57 ,0.114 ,0.313 }, + { 2 ,57 ,59 ,0.687 ,0.452 }, + { 1 ,59 ,60 ,0.548 ,0.908 } +}; + +psyDataElem3 psy_data3_44100_20[21] = +{ + { 3 , 0 , 4 ,1.000 ,0.056 }, + { 3 , 4 , 7 ,0.944 ,0.611 }, + { 4 , 7 ,11 ,0.389 ,0.167 }, + { 3 ,11 ,14 ,0.833 ,0.722 }, + { 3 ,14 ,17 ,0.278 ,0.139 }, + { 1 ,17 ,18 ,0.861 ,0.917 }, + { 3 ,18 ,21 ,0.083 ,0.583 }, + { 3 ,21 ,24 ,0.417 ,0.250 }, + { 3 ,24 ,27 ,0.750 ,0.805 }, + { 3 ,27 ,30 ,0.194 ,0.574 }, + { 3 ,30 ,33 ,0.426 ,0.537 }, + { 3 ,33 ,36 ,0.463 ,0.819 }, + { 4 ,36 ,40 ,0.180 ,0.100 }, + { 3 ,40 ,43 ,0.900 ,0.468 }, + { 3 ,43 ,46 ,0.532 ,0.623 }, + { 3 ,46 ,49 ,0.376 ,0.450 }, + { 3 ,49 ,52 ,0.550 ,0.552 }, + { 3 ,52 ,55 ,0.448 ,0.403 }, + { 2 ,55 ,57 ,0.597 ,0.643 }, + { 2 ,57 ,59 ,0.357 ,0.722 }, + { 2 ,59 ,61 ,0.278 ,0.960 } +}; + +psyDataElem3 psy_data3_32000_20[21] = +{ + { 1 , 0 , 2 ,1.000 ,0.528 }, + { 2 , 2 , 4 ,0.472 ,0.305 }, + { 2 , 4 , 6 ,0.694 ,0.083 }, + { 1 , 6 , 7 ,0.917 ,0.861 }, + { 2 , 7 , 9 ,0.139 ,0.639 }, + { 2 , 9 ,11 ,0.361 ,0.417 }, + { 3 ,11 ,14 ,0.583 ,0.083 }, + { 2 ,14 ,16 ,0.917 ,0.750 }, + { 3 ,16 ,19 ,0.250 ,0.870 }, + { 3 ,19 ,22 ,0.130 ,0.833 }, + { 4 ,22 ,26 ,0.167 ,0.389 }, + { 4 ,26 ,30 ,0.611 ,0.478 }, + { 4 ,30 ,34 ,0.522 ,0.033 }, + { 3 ,34 ,37 ,0.967 ,0.917 }, + { 4 ,37 ,41 ,0.083 ,0.617 }, + { 3 ,41 ,44 ,0.383 ,0.995 }, + { 4 ,44 ,48 ,0.005 ,0.274 }, + { 3 ,48 ,51 ,0.726 ,0.480 }, + { 3 ,51 ,54 ,0.519 ,0.261 }, + { 2 ,54 ,56 ,0.739 ,0.884 }, + { 2 ,56 ,58 ,0.116 ,1.000 } +}; + + +psyDataElem3 psy_data4_48000_11[12] = +{ + { 2 , 0 , 2 ,1.000 ,0.167 }, + { 2 , 3 , 5 ,0.833 ,0.833 }, + { 3 , 5 , 8 ,0.167 ,0.500 }, + { 3 , 8 ,11 ,0.500 ,0.167 }, + { 4 ,11 ,15 ,0.833 ,0.167 }, + { 4 ,15 ,19 ,0.833 ,0.583 }, + { 3 ,19 ,22 ,0.417 ,0.917 }, + { 4 ,22 ,26 ,0.083 ,0.944 }, + { 4 ,26 ,30 ,0.055 ,0.042 }, + { 2 ,30 ,32 ,0.958 ,0.567 }, + { 3 ,32 ,35 ,0.433 ,0.167 }, + { 2 ,35 ,37 ,0.833 ,0.618 } +}; + +psyDataElem3 psy_data4_44100_11[12] = +{ + { 2 , 0 , 2 ,1.000 ,0.167 }, + { 2 , 3 , 5 ,0.833 ,0.833 }, + { 3 , 5 , 8 ,0.167 ,0.500 }, + { 3 , 8 ,11 ,0.500 ,0.167 }, + { 4 ,11 ,15 ,0.833 ,0.167 }, + { 5 ,15 ,20 ,0.833 ,0.250 }, + { 3 ,20 ,23 ,0.750 ,0.583 }, + { 4 ,23 ,27 ,0.417 ,0.055 }, + { 3 ,27 ,30 ,0.944 ,0.375 }, + { 3 ,30 ,33 ,0.625 ,0.300 }, + { 3 ,33 ,36 ,0.700 ,0.167 }, + { 2 ,36 ,38 ,0.833 ,1.000 } +}; + +psyDataElem3 psy_data4_32000_11[12] = +{ + { 2 , 0 , 2 ,1.000 ,0.167 }, + { 2 , 3 , 5 ,0.833 ,0.833 }, + { 3 , 5 , 8 ,0.167 ,0.500 }, + { 3 , 8 ,11 ,0.500 ,0.167 }, + { 4 ,11 ,15 ,0.833 ,0.167 }, + { 5 ,15 ,20 ,0.833 ,0.250 }, + { 4 ,20 ,24 ,0.750 ,0.250 }, + { 5 ,24 ,29 ,0.750 ,0.055 }, + { 4 ,29 ,33 ,0.944 ,0.375 }, + { 4 ,33 ,37 ,0.625 ,0.472 }, + { 3 ,37 ,40 ,0.528 ,0.937 }, + { 1 ,40 ,41 ,0.062 ,1.000 } +}; + +#endif /* NEW_L3PARM_TABLES */ + + + + + +/*=============================================================================*/ + + + + + +#if 1 /* WIND_SB_CHANGE_LEVEL == 3 */ + +double enwindow[512] = +{ + 0.000000000, 0.000101566, 0.000971317, 0.003134727, 0.035780907, 0.003134727, 0.000971317, 0.000101566, + -0.000000477, 0.000103951, 0.000953674, 0.002841473, 0.035758972, 0.003401756, 0.000983715, 0.000099182, + -0.000000477, 0.000105858, 0.000930786, 0.002521515, 0.035694122, 0.003643036, 0.000991821, 0.000096321, + -0.000000477, 0.000107288, 0.000902653, 0.002174854, 0.035586357, 0.003858566, 0.000995159, 0.000093460, + -0.000000477, 0.000108242, 0.000868797, 0.001800537, 0.035435200, 0.004049301, 0.000994205, 0.000090599, + -0.000000477, 0.000108719, 0.000829220, 0.001399517, 0.035242081, 0.004215240, 0.000989437, 0.000087261, + -0.000000477, 0.000108719, 0.000783920, 0.000971317, 0.035007000, 0.004357815, 0.000980854, 0.000083923, + -0.000000954, 0.000108242, 0.000731945, 0.000515938, 0.034730434, 0.004477024, 0.000968933, 0.000080585, + + -0.000000954, 0.000106812, 0.000674248, 0.000033379, 0.034412861, 0.004573822, 0.000954151, 0.000076771, + -0.000000954, 0.000105381, 0.000610352,-0.000475883, 0.034055710, 0.004649162, 0.000935555, 0.000073433, + -0.000000954, 0.000102520, 0.000539303,-0.001011848, 0.033659935, 0.004703045, 0.000915051, 0.000070095, + -0.000001431, 0.000099182, 0.000462532,-0.001573563, 0.033225536, 0.004737377, 0.000891685, 0.000066280, + -0.000001431, 0.000095367, 0.000378609,-0.002161503, 0.032754898, 0.004752159, 0.000866413, 0.000062943, + -0.000001907, 0.000090122, 0.000288486,-0.002774239, 0.032248020, 0.004748821, 0.000838757, 0.000059605, + -0.000001907, 0.000084400, 0.000191689,-0.003411293, 0.031706810, 0.004728317, 0.000809669, 0.000055790, + -0.000002384, 0.000077724, 0.000088215,-0.004072189, 0.031132698, 0.004691124, 0.000779152, 0.000052929, + + -0.000002384, 0.000069618,-0.000021458,-0.004756451, 0.030526638, 0.004638195, 0.000747204, 0.000049591, + -0.000002861, 0.000060558,-0.000137329,-0.005462170, 0.029890060, 0.004570484, 0.000714302, 0.000046253, + -0.000003338, 0.000050545,-0.000259876,-0.006189346, 0.029224873, 0.004489899, 0.000680923, 0.000043392, + -0.000003338, 0.000039577,-0.000388145,-0.006937027, 0.028532982, 0.004395962, 0.000646591, 0.000040531, + -0.000003815, 0.000027180,-0.000522137,-0.007703304, 0.027815342, 0.004290581, 0.000611782, 0.000037670, + -0.000004292, 0.000013828,-0.000661850,-0.008487225, 0.027073860, 0.004174709, 0.000576973, 0.000034809, + -0.000004768,-0.000000954,-0.000806808,-0.009287834, 0.026310921, 0.004048824, 0.000542164, 0.000032425, + -0.000005245,-0.000017166,-0.000956535,-0.010103703, 0.025527000, 0.003914356, 0.000507355, 0.000030041, + + -0.000006199,-0.000034332,-0.001111031,-0.010933399, 0.024725437, 0.003771782, 0.000472546, 0.000027657, + -0.000006676,-0.000052929,-0.001269817,-0.011775017, 0.023907185, 0.003622532, 0.000438213, 0.000025272, + -0.000007629,-0.000072956,-0.001432419,-0.012627602, 0.023074150, 0.003467083, 0.000404358, 0.000023365, + -0.000008106,-0.000093937,-0.001597881,-0.013489246, 0.022228718, 0.003306866, 0.000371456, 0.000021458, + -0.000009060,-0.000116348,-0.001766682,-0.014358521, 0.021372318, 0.003141880, 0.000339031, 0.000019550, + -0.000010014,-0.000140190,-0.001937389,-0.015233517, 0.020506859, 0.002974033, 0.000307560, 0.000018120, + -0.000011444,-0.000165462,-0.002110004,-0.016112804, 0.019634247, 0.002803326, 0.000277042, 0.000016689, + -0.000012398,-0.000191212,-0.002283096,-0.016994476, 0.018756866, 0.002630711, 0.000247478, 0.000014782, + + -0.000013828,-0.000218868,-0.002457142,-0.017876148, 0.017876148, 0.002457142, 0.000218868, 0.000013828, + -0.000014782,-0.000247478,-0.002630711,-0.018756866, 0.016994476, 0.002283096, 0.000191212, 0.000012398, + -0.000016689,-0.000277042,-0.002803326,-0.019634247, 0.016112804, 0.002110004, 0.000165462, 0.000011444, + -0.000018120,-0.000307560,-0.002974033,-0.020506859, 0.015233517, 0.001937389, 0.000140190, 0.000010014, + -0.000019550,-0.000339031,-0.003141880,-0.021372318, 0.014358521, 0.001766682, 0.000116348, 0.000009060, + -0.000021458,-0.000371456,-0.003306866,-0.022228718, 0.013489246, 0.001597881, 0.000093937, 0.000008106, + -0.000023365,-0.000404358,-0.003467083,-0.023074150, 0.012627602, 0.001432419, 0.000072956, 0.000007629, + -0.000025272,-0.000438213,-0.003622532,-0.023907185, 0.011775017, 0.001269817, 0.000052929, 0.000006676, + + -0.000027657,-0.000472546,-0.003771782,-0.024725437, 0.010933399, 0.001111031, 0.000034332, 0.000006199, + -0.000030041,-0.000507355,-0.003914356,-0.025527000, 0.010103703, 0.000956535, 0.000017166, 0.000005245, + -0.000032425,-0.000542164,-0.004048824,-0.026310921, 0.009287834, 0.000806808, 0.000000954, 0.000004768, + -0.000034809,-0.000576973,-0.004174709,-0.027073860, 0.008487225, 0.000661850,-0.000013828, 0.000004292, + -0.000037670,-0.000611782,-0.004290581,-0.027815342, 0.007703304, 0.000522137,-0.000027180, 0.000003815, + -0.000040531,-0.000646591,-0.004395962,-0.028532982, 0.006937027, 0.000388145,-0.000039577, 0.000003338, + -0.000043392,-0.000680923,-0.004489899,-0.029224873, 0.006189346, 0.000259876,-0.000050545, 0.000003338, + -0.000046253,-0.000714302,-0.004570484,-0.029890060, 0.005462170, 0.000137329,-0.000060558, 0.000002861, + + -0.000049591,-0.000747204,-0.004638195,-0.030526638, 0.004756451, 0.000021458,-0.000069618, 0.000002384, + -0.000052929,-0.000779152,-0.004691124,-0.031132698, 0.004072189,-0.000088215,-0.000077724, 0.000002384, + -0.000055790,-0.000809669,-0.004728317,-0.031706810, 0.003411293,-0.000191689,-0.000084400, 0.000001907, + -0.000059605,-0.000838757,-0.004748821,-0.032248020, 0.002774239,-0.000288486,-0.000090122, 0.000001907, + -0.000062943,-0.000866413,-0.004752159,-0.032754898, 0.002161503,-0.000378609,-0.000095367, 0.000001431, + -0.000066280,-0.000891685,-0.004737377,-0.033225536, 0.001573563,-0.000462532,-0.000099182, 0.000001431, + -0.000070095,-0.000915051,-0.004703045,-0.033659935, 0.001011848,-0.000539303,-0.000102520, 0.000000954, + -0.000073433,-0.000935555,-0.004649162,-0.034055710, 0.000475883,-0.000610352,-0.000105381, 0.000000954, + + -0.000076771,-0.000954151,-0.004573822,-0.034412861,-0.000033379,-0.000674248,-0.000106812, 0.000000954, + -0.000080585,-0.000968933,-0.004477024,-0.034730434,-0.000515938,-0.000731945,-0.000108242, 0.000000954, + -0.000083923,-0.000980854,-0.004357815,-0.035007000,-0.000971317,-0.000783920,-0.000108719, 0.000000477, + -0.000087261,-0.000989437,-0.004215240,-0.035242081,-0.001399517,-0.000829220,-0.000108719, 0.000000477, + -0.000090599,-0.000994205,-0.004049301,-0.035435200,-0.001800537,-0.000868797,-0.000108242, 0.000000477, + -0.000093460,-0.000995159,-0.003858566,-0.035586357,-0.002174854,-0.000902653,-0.000107288, 0.000000477, + -0.000096321,-0.000991821,-0.003643036,-0.035694122,-0.002521515,-0.000930786,-0.000105858, 0.000000477, + -0.000099182,-0.000983715,-0.003401756,-0.035758972,-0.002841473,-0.000953674,-0.000103951, 0.000000477 +}; + +#else /* WIND_SB_CHANGE_LEVEL < 3 */ + +double enwindow[512] = +{ + 0.000000000,-0.000000477,-0.000000477,-0.000000477,-0.000000477,-0.000000477,-0.000000477,-0.000000954, + -0.000000954,-0.000000954,-0.000000954,-0.000001431,-0.000001431,-0.000001907,-0.000001907,-0.000002384, + -0.000002384,-0.000002861,-0.000003338,-0.000003338,-0.000003815,-0.000004292,-0.000004768,-0.000005245, + -0.000006199,-0.000006676,-0.000007629,-0.000008106,-0.000009060,-0.000010014,-0.000011444,-0.000012398, + -0.000013828,-0.000014782,-0.000016689,-0.000018120,-0.000019550,-0.000021458,-0.000023365,-0.000025272, + -0.000027657,-0.000030041,-0.000032425,-0.000034809,-0.000037670,-0.000040531,-0.000043392,-0.000046253, + -0.000049591,-0.000052929,-0.000055790,-0.000059605,-0.000062943,-0.000066280,-0.000070095,-0.000073433, + -0.000076771,-0.000080585,-0.000083923,-0.000087261,-0.000090599,-0.000093460,-0.000096321,-0.000099182, + + 0.000101566, 0.000103951, 0.000105858, 0.000107288, 0.000108242, 0.000108719, 0.000108719, 0.000108242, + 0.000106812, 0.000105381, 0.000102520, 0.000099182, 0.000095367, 0.000090122, 0.000084400, 0.000077724, + 0.000069618, 0.000060558, 0.000050545, 0.000039577, 0.000027180, 0.000013828,-0.000000954,-0.000017166, + -0.000034332,-0.000052929,-0.000072956,-0.000093937,-0.000116348,-0.000140190,-0.000165462,-0.000191212, + -0.000218868,-0.000247478,-0.000277042,-0.000307560,-0.000339031,-0.000371456,-0.000404358,-0.000438213, + -0.000472546,-0.000507355,-0.000542164,-0.000576973,-0.000611782,-0.000646591,-0.000680923,-0.000714302, + -0.000747204,-0.000779152,-0.000809669,-0.000838757,-0.000866413,-0.000891685,-0.000915051,-0.000935555, + -0.000954151,-0.000968933,-0.000980854,-0.000989437,-0.000994205,-0.000995159,-0.000991821,-0.000983715, + + 0.000971317, 0.000953674, 0.000930786, 0.000902653, 0.000868797, 0.000829220, 0.000783920, 0.000731945, + 0.000674248, 0.000610352, 0.000539303, 0.000462532, 0.000378609, 0.000288486, 0.000191689, 0.000088215, + -0.000021458,-0.000137329,-0.000259876,-0.000388145,-0.000522137,-0.000661850,-0.000806808,-0.000956535, + -0.001111031,-0.001269817,-0.001432419,-0.001597881,-0.001766682,-0.001937389,-0.002110004,-0.002283096, + -0.002457142,-0.002630711,-0.002803326,-0.002974033,-0.003141880,-0.003306866,-0.003467083,-0.003622532, + -0.003771782,-0.003914356,-0.004048824,-0.004174709,-0.004290581,-0.004395962,-0.004489899,-0.004570484, + -0.004638195,-0.004691124,-0.004728317,-0.004748821,-0.004752159,-0.004737377,-0.004703045,-0.004649162, + -0.004573822,-0.004477024,-0.004357815,-0.004215240,-0.004049301,-0.003858566,-0.003643036,-0.003401756, + + 0.003134727, 0.002841473, 0.002521515, 0.002174854, 0.001800537, 0.001399517, 0.000971317, 0.000515938, + 0.000033379,-0.000475883,-0.001011848,-0.001573563,-0.002161503,-0.002774239,-0.003411293,-0.004072189, + -0.004756451,-0.005462170,-0.006189346,-0.006937027,-0.007703304,-0.008487225,-0.009287834,-0.010103703, + -0.010933399,-0.011775017,-0.012627602,-0.013489246,-0.014358521,-0.015233517,-0.016112804,-0.016994476, + -0.017876148,-0.018756866,-0.019634247,-0.020506859,-0.021372318,-0.022228718,-0.023074150,-0.023907185, + -0.024725437,-0.025527000,-0.026310921,-0.027073860,-0.027815342,-0.028532982,-0.029224873,-0.029890060, + -0.030526638,-0.031132698,-0.031706810,-0.032248020,-0.032754898,-0.033225536,-0.033659935,-0.034055710, + -0.034412861,-0.034730434,-0.035007000,-0.035242081,-0.035435200,-0.035586357,-0.035694122,-0.035758972, + + 0.035780907, 0.035758972, 0.035694122, 0.035586357, 0.035435200, 0.035242081, 0.035007000, 0.034730434, + 0.034412861, 0.034055710, 0.033659935, 0.033225536, 0.032754898, 0.032248020, 0.031706810, 0.031132698, + 0.030526638, 0.029890060, 0.029224873, 0.028532982, 0.027815342, 0.027073860, 0.026310921, 0.025527000, + 0.024725437, 0.023907185, 0.023074150, 0.022228718, 0.021372318, 0.020506859, 0.019634247, 0.018756866, + 0.017876148, 0.016994476, 0.016112804, 0.015233517, 0.014358521, 0.013489246, 0.012627602, 0.011775017, + 0.010933399, 0.010103703, 0.009287834, 0.008487225, 0.007703304, 0.006937027, 0.006189346, 0.005462170, + 0.004756451, 0.004072189, 0.003411293, 0.002774239, 0.002161503, 0.001573563, 0.001011848, 0.000475883, + -0.000033379,-0.000515938,-0.000971317,-0.001399517,-0.001800537,-0.002174854,-0.002521515,-0.002841473, + + 0.003134727, 0.003401756, 0.003643036, 0.003858566, 0.004049301, 0.004215240, 0.004357815, 0.004477024, + 0.004573822, 0.004649162, 0.004703045, 0.004737377, 0.004752159, 0.004748821, 0.004728317, 0.004691124, + 0.004638195, 0.004570484, 0.004489899, 0.004395962, 0.004290581, 0.004174709, 0.004048824, 0.003914356, + 0.003771782, 0.003622532, 0.003467083, 0.003306866, 0.003141880, 0.002974033, 0.002803326, 0.002630711, + 0.002457142, 0.002283096, 0.002110004, 0.001937389, 0.001766682, 0.001597881, 0.001432419, 0.001269817, + 0.001111031, 0.000956535, 0.000806808, 0.000661850, 0.000522137, 0.000388145, 0.000259876, 0.000137329, + 0.000021458,-0.000088215,-0.000191689,-0.000288486,-0.000378609,-0.000462532,-0.000539303,-0.000610352, + -0.000674248,-0.000731945,-0.000783920,-0.000829220,-0.000868797,-0.000902653,-0.000930786,-0.000953674, + + 0.000971317, 0.000983715, 0.000991821, 0.000995159, 0.000994205, 0.000989437, 0.000980854, 0.000968933, + 0.000954151, 0.000935555, 0.000915051, 0.000891685, 0.000866413, 0.000838757, 0.000809669, 0.000779152, + 0.000747204, 0.000714302, 0.000680923, 0.000646591, 0.000611782, 0.000576973, 0.000542164, 0.000507355, + 0.000472546, 0.000438213, 0.000404358, 0.000371456, 0.000339031, 0.000307560, 0.000277042, 0.000247478, + 0.000218868, 0.000191212, 0.000165462, 0.000140190, 0.000116348, 0.000093937, 0.000072956, 0.000052929, + 0.000034332, 0.000017166, 0.000000954,-0.000013828,-0.000027180,-0.000039577,-0.000050545,-0.000060558, + -0.000069618,-0.000077724,-0.000084400,-0.000090122,-0.000095367,-0.000099182,-0.000102520,-0.000105381, + -0.000106812,-0.000108242,-0.000108719,-0.000108719,-0.000108242,-0.000107288,-0.000105858,-0.000103951, + + 0.000101566, 0.000099182, 0.000096321, 0.000093460, 0.000090599, 0.000087261, 0.000083923, 0.000080585, + 0.000076771, 0.000073433, 0.000070095, 0.000066280, 0.000062943, 0.000059605, 0.000055790, 0.000052929, + 0.000049591, 0.000046253, 0.000043392, 0.000040531, 0.000037670, 0.000034809, 0.000032425, 0.000030041, + 0.000027657, 0.000025272, 0.000023365, 0.000021458, 0.000019550, 0.000018120, 0.000016689, 0.000014782, + 0.000013828, 0.000012398, 0.000011444, 0.000010014, 0.000009060, 0.000008106, 0.000007629, 0.000006676, + 0.000006199, 0.000005245, 0.000004768, 0.000004292, 0.000003815, 0.000003338, 0.000003338, 0.000002861, + 0.000002384, 0.000002384, 0.000001907, 0.000001907, 0.000001431, 0.000001431, 0.000000954, 0.000000954, + 0.000000954, 0.000000954, 0.000000477, 0.000000477, 0.000000477, 0.000000477, 0.000000477, 0.000000477 +}; + +#endif + + + + + +/*=============================================================================*/ +/* >>> HUFFMAN ENCODING RELATED TABLES <<< */ +/*=============================================================================*/ + + +unsigned int huff_tab1[2*2] = { + 1, 1, + 1, 0 +}; + +unsigned int huff_tab2[3*3] = { + 1, 2, 1, + 3, 1, 1, + 3, 2, 0 +}; + +unsigned int huff_tab3[3*3] = { + 3, 2, 1, + 1, 1, 1, + 3, 2, 0 +}; + +unsigned int huff_tab5[4*4] = { + 1, 2, 6, 5, + 3, 1, 4, 4, + 7, 5, 7, 1, + 6, 1, 1, 0 +}; + +unsigned int huff_tab6[4*4] = { + 7, 3, 5, 1, + 6, 2, 3, 2, + 5, 4, 4, 1, + 3, 3, 2, 0 +}; + +unsigned int huff_tab7[6*6] = { + 1, 2, 10, 19, 16, 10, + 3, 3, 7, 10, 5, 3, + 11, 4, 13, 17, 8, 4, + 12, 11, 18, 15, 11, 2, + 7, 6, 9, 14, 3, 1, + 6, 4, 5, 3, 2, 0 +}; + +unsigned int huff_tab8[6*6] = { + 3, 4, 6, 18, 12, 5, + 5, 1, 2, 16, 9, 3, + 7, 3, 5, 14, 7, 3, + 19, 17, 15, 13, 10, 4, + 13, 5, 8, 11, 5, 1, + 12, 4, 4, 1, 1, 0 +}; + +unsigned int huff_tab9[6*6] = { + 7, 5, 9, 14, 15, 7, + 6, 4, 5, 5, 6, 7, + 7, 6, 8, 8, 8, 5, + 15, 6, 9, 10, 5, 1, + 11, 7, 9, 6, 4, 1, + 14, 4, 6, 2, 6, 0 +}; + +unsigned int huff_tab10[8*8] = { + 1, 2, 10, 23, 35, 30, 12, 17, + 3, 3, 8, 12, 18, 21, 12, 7, + 11, 9, 15, 21, 32, 40, 19, 6, + 14, 13, 22, 34, 46, 23, 18, 7, + 20, 19, 33, 47, 27, 22, 9, 3, + 31, 22, 41, 26, 21, 20, 5, 3, + 14, 13, 10, 11, 16, 6, 5, 1, + 9, 8, 7, 8, 4, 4, 2, 0 +}; + +unsigned int huff_tab11[8*8] = { + 3, 4, 10, 24, 34, 33, 21, 15, + 5, 3, 4, 10, 32, 17, 11, 10, + 11, 7, 13, 18, 30, 31, 20, 5, + 25, 11, 19, 59, 27, 18, 12, 5, + 35, 33, 31, 58, 30, 16, 7, 5, + 28, 26, 32, 19, 17, 15, 8, 14, + 14, 12, 9, 13, 14, 9, 4, 1, + 11, 4, 6, 6, 6, 3, 2, 0 +}; + +unsigned int huff_tab12[8*8] = { + 9, 6, 16, 33, 41, 39, 38, 26, + 7, 5, 6, 9, 23, 16, 26, 11, + 17, 7, 11, 14, 21, 30, 10, 7, + 17, 10, 15, 12, 18, 28, 14, 5, + 32, 13, 22, 19, 18, 16, 9, 5, + 40, 17, 31, 29, 17, 13, 4, 2, + 27, 12, 11, 15, 10, 7, 4, 1, + 27, 12, 8, 12, 6, 3, 1, 0 +}; + +unsigned int huff_tab13[16*16] = { + 1, 5, 14, 21, 34, 51, 46, 71, 42, 52, 68, 52, 67, 44, 43, 19, + 3, 4, 12, 19, 31, 26, 44, 33, 31, 24, 32, 24, 31, 35, 22, 14, + 15, 13, 23, 36, 59, 49, 77, 65, 29, 40, 30, 40, 27, 33, 42, 16, + 22, 20, 37, 61, 56, 79, 73, 64, 43, 76, 56, 37, 26, 31, 25, 14, + 35, 16, 60, 57, 97, 75, 114, 91, 54, 73, 55, 41, 48, 53, 23, 24, + 58, 27, 50, 96, 76, 70, 93, 84, 77, 58, 79, 29, 74, 49, 41, 17, + 47, 45, 78, 74, 115, 94, 90, 79, 69, 83, 71, 50, 59, 38, 36, 15, + 72, 34, 56, 95, 92, 85, 91, 90, 86, 73, 77, 65, 51, 44, 43, 42, + 43, 20, 30, 44, 55, 78, 72, 87, 78, 61, 46, 54, 37, 30, 20, 16, + 53, 25, 41, 37, 44, 59, 54, 81, 66, 76, 57, 54, 37, 18, 39, 11, + 35, 33, 31, 57, 42, 82, 72, 80, 47, 58, 55, 21, 22, 26, 38, 22, + 53, 25, 23, 38, 70, 60, 51, 36, 55, 26, 34, 23, 27, 14, 9, 7, + 34, 32, 28, 39, 49, 75, 30, 52, 48, 40, 52, 28, 18, 17, 9, 5, + 45, 21, 34, 64, 56, 50, 49, 45, 31, 19, 12, 15, 10, 7, 6, 3, + 48, 23, 20, 39, 36, 35, 53, 21, 16, 23, 13, 10, 6, 1, 4, 2, + 16, 15, 17, 27, 25, 20, 29, 11, 17, 12, 16, 8, 1, 1, 0, 1 +}; + +unsigned int huff_tab15[16*16] = { + 7, 12, 18, 53, 47, 76, 124, 108, 89, 123, 108, 119, 107, 81, 122, 63, + 13, 5, 16, 27, 46, 36, 61, 51, 42, 70, 52, 83, 65, 41, 59, 36, + 19, 17, 15, 24, 41, 34, 59, 48, 40, 64, 50, 78, 62, 80, 56, 33, + 29, 28, 25, 43, 39, 63, 55, 93, 76, 59, 93, 72, 54, 75, 50, 29, + 52, 22, 42, 40, 67, 57, 95, 79, 72, 57, 89, 69, 49, 66, 46, 27, + 77, 37, 35, 66, 58, 52, 91, 74, 62, 48, 79, 63, 90, 62, 40, 38, + 125, 32, 60, 56, 50, 92, 78, 65, 55, 87, 71, 51, 73, 51, 70, 30, + 109, 53, 49, 94, 88, 75, 66, 122, 91, 73, 56, 42, 64, 44, 21, 25, + 90, 43, 41, 77, 73, 63, 56, 92, 77, 66, 47, 67, 48, 53, 36, 20, + 71, 34, 67, 60, 58, 49, 88, 76, 67, 106, 71, 54, 38, 39, 23, 15, + 109, 53, 51, 47, 90, 82, 58, 57, 48, 72, 57, 41, 23, 27, 62, 9, + 86, 42, 40, 37, 70, 64, 52, 43, 70, 55, 42, 25, 29, 18, 11, 11, + 118, 68, 30, 55, 50, 46, 74, 65, 49, 39, 24, 16, 22, 13, 14, 7, + 91, 44, 39, 38, 34, 63, 52, 45, 31, 52, 28, 19, 14, 8, 9, 3, + 123, 60, 58, 53, 47, 43, 32, 22, 37, 24, 17, 12, 15, 10, 2, 1, + 71, 37, 34, 30, 28, 20, 17, 26, 21, 16, 10, 6, 8, 6, 2, 0 +}; + +unsigned int huff_tab16[16*16] = { + 1, 5, 14, 44, 74, 63, 110, 93, 172, 149, 138, 242, 225, 195, 376, 17, + 3, 4, 12, 20, 35, 62, 53, 47, 83, 75, 68, 119, 201, 107, 207, 9, + 15, 13, 23, 38, 67, 58, 103, 90, 161, 72, 127, 117, 110, 209, 206, 16, + 45, 21, 39, 69, 64, 114, 99, 87, 158, 140, 252, 212, 199, 387, 365, 26, + 75, 36, 68, 65, 115, 101, 179, 164, 155, 264, 246, 226, 395, 382, 362, 9, + 66, 30, 59, 56, 102, 185, 173, 265, 142, 253, 232, 400, 388, 378, 445, 16, + 111, 54, 52, 100, 184, 178, 160, 133, 257, 244, 228, 217, 385, 366, 715, 10, + 98, 48, 91, 88, 165, 157, 148, 261, 248, 407, 397, 372, 380, 889, 884, 8, + 85, 84, 81, 159, 156, 143, 260, 249, 427, 401, 392, 383, 727, 713, 708, 7, + 154, 76, 73, 141, 131, 256, 245, 426, 406, 394, 384, 735, 359, 710, 352, 11, + 139, 129, 67, 125, 247, 233, 229, 219, 393, 743, 737, 720, 885, 882, 439, 4, + 243, 120, 118, 115, 227, 223, 396, 746, 742, 736, 721, 712, 706, 223, 436, 6, + 202, 224, 222, 218, 216, 389, 386, 381, 364, 888, 443, 707, 440, 437, 1728, 4, + 747, 211, 210, 208, 370, 379, 734, 723, 714, 1735, 883, 877, 876, 3459, 865, 2, + 377, 369, 102, 187, 726, 722, 358, 711, 709, 866, 1734, 871, 3458, 870, 434, 0, + 12, 10, 7, 11, 10, 17, 11, 9, 13, 12, 10, 7, 5, 3, 1, 3 +}; + +unsigned int huff_tab24[16*16] = { + 15, 13, 46, 80, 146, 262, 248, 434, 426, 669, 653, 649, 621, 517, 1032, 88, + 14, 12, 21, 38, 71, 130, 122, 216, 209, 198, 327, 345, 319, 297, 279, 42, + 47, 22, 41, 74, 68, 128, 120, 221, 207, 194, 182, 340, 315, 295, 541, 18, + 81, 39, 75, 70, 134, 125, 116, 220, 204, 190, 178, 325, 311, 293, 271, 16, + 147, 72, 69, 135, 127, 118, 112, 210, 200, 188, 352, 323, 306, 285, 540, 14, + 263, 66, 129, 126, 119, 114, 214, 202, 192, 180, 341, 317, 301, 281, 262, 12, + 249, 123, 121, 117, 113, 215, 206, 195, 185, 347, 330, 308, 291, 272, 520, 10, + 435, 115, 111, 109, 211, 203, 196, 187, 353, 332, 313, 298, 283, 531, 381, 17, + 427, 212, 208, 205, 201, 193, 186, 177, 169, 320, 303, 286, 268, 514, 377, 16, + 335, 199, 197, 191, 189, 181, 174, 333, 321, 305, 289, 275, 521, 379, 371, 11, + 668, 184, 183, 179, 175, 344, 331, 314, 304, 290, 277, 530, 383, 373, 366, 10, + 652, 346, 171, 168, 164, 318, 309, 299, 287, 276, 263, 513, 375, 368, 362, 6, + 648, 322, 316, 312, 307, 302, 292, 284, 269, 261, 512, 376, 370, 364, 359, 4, + 620, 300, 296, 294, 288, 282, 273, 266, 515, 380, 374, 369, 365, 361, 357, 2, + 1033, 280, 278, 274, 267, 264, 259, 382, 378, 372, 367, 363, 360, 358, 356, 0, + 43, 20, 19, 17, 15, 13, 11, 9, 7, 6, 4, 7, 5, 3, 1, 3 +}; + +unsigned int huff_tab32[16*1] = { + 1, + 5, + 4, + 5, + 6, + 5, + 4, + 4, + 7, + 3, + 6, + 0, + 7, + 2, + 3, + 1 +}; + +unsigned int huff_tab33[16*1] = { + 15, + 14, + 13, + 12, + 11, + 10, + 9, + 8, + 7, + 6, + 5, + 4, + 3, + 2, + 1, + 0 +}; + +unsigned char huff_hlen1[2*2] = { + 1, 3, + 2, 3 +}; + +unsigned char huff_hlen2[3*3] = { + 1, 3, 6, + 3, 3, 5, + 5, 5, 6 +}; + +unsigned char huff_hlen3[3*3] = { + 2, 2, 6, + 3, 2, 5, + 5, 5, 6 +}; + +unsigned char huff_hlen5[4*4] = { + 1, 3, 6, 7, + 3, 3, 6, 7, + 6, 6, 7, 8, + 7, 6, 7, 8 +}; + +unsigned char huff_hlen6[4*4] = { + 3, 3, 5, 7, + 3, 2, 4, 5, + 4, 4, 5, 6, + 6, 5, 6, 7 +}; + +unsigned char huff_hlen7[6*6] = { + 1, 3, 6, 8, 8, 9, + 3, 4, 6, 7, 7, 8, + 6, 5, 7, 8, 8, 9, + 7, 7, 8, 9, 9, 9, + 7, 7, 8, 9, 9, 10, + 8, 8, 9, 10, 10, 10 +}; + +unsigned char huff_hlen8[6*6] = { + 2, 3, 6, 8, 8, 9, + 3, 2, 4, 8, 8, 8, + 6, 4, 6, 8, 8, 9, + 8, 8, 8, 9, 9, 10, + 8, 7, 8, 9, 10, 10, + 9, 8, 9, 9, 11, 11 +}; + +unsigned char huff_hlen9[6*6] = { + 3, 3, 5, 6, 8, 9, + 3, 3, 4, 5, 6, 8, + 4, 4, 5, 6, 7, 8, + 6, 5, 6, 7, 7, 8, + 7, 6, 7, 7, 8, 9, + 8, 7, 8, 8, 9, 9 +}; + +unsigned char huff_hlen10[8*8] = { + 1, 3, 6, 8, 9, 9, 9, 10, + 3, 4, 6, 7, 8, 9, 8, 8, + 6, 6, 7, 8, 9, 10, 9, 9, + 7, 7, 8, 9, 10, 10, 9, 10, + 8, 8, 9, 10, 10, 10, 10, 10, + 9, 9, 10, 10, 11, 11, 10, 11, + 8, 8, 9, 10, 10, 10, 11, 11, + 9, 8, 9, 10, 10, 11, 11, 11 +}; + +unsigned char huff_hlen11[8*8] = { + 2, 3, 5, 7, 8, 9, 8, 9, + 3, 3, 4, 6, 8, 8, 7, 8, + 5, 5, 6, 7, 8, 9, 8, 8, + 7, 6, 7, 9, 8, 10, 8, 9, + 8, 8, 8, 9, 9, 10, 9, 10, + 8, 8, 9, 10, 10, 11, 10, 11, + 8, 7, 7, 8, 9, 10, 10, 10, + 8, 7, 8, 9, 10, 10, 10, 10 +}; + +unsigned char huff_hlen12[8*8] = { + 4, 3, 5, 7, 8, 9, 9, 9, + 3, 3, 4, 5, 7, 7, 8, 8, + 5, 4, 5, 6, 7, 8, 7, 8, + 6, 5, 6, 6, 7, 8, 8, 8, + 7, 6, 7, 7, 8, 8, 8, 9, + 8, 7, 8, 8, 8, 9, 8, 9, + 8, 7, 7, 8, 8, 9, 9, 10, + 9, 8, 8, 9, 9, 9, 9, 10 +}; + +unsigned char huff_hlen13[16*16] = { + 1, 4, 6, 7, 8, 9, 9, 10, 9, 10, 11, 11, 12, 12, 13, 13, + 3, 4, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 11, 12, 12, 12, + 6, 6, 7, 8, 9, 9, 10, 10, 9, 10, 10, 11, 11, 12, 13, 13, + 7, 7, 8, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 13, 13, + 8, 7, 9, 9, 10, 10, 11, 11, 10, 11, 11, 12, 12, 13, 13, 14, + 9, 8, 9, 10, 10, 10, 11, 11, 11, 11, 12, 11, 13, 13, 14, 14, + 9, 9, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, + 10, 9, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 16, 16, + 9, 8, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 14, 15, 15, + 10, 9, 10, 10, 11, 11, 11, 13, 12, 13, 13, 14, 14, 14, 16, 15, + 10, 10, 10, 11, 11, 12, 12, 13, 12, 13, 14, 13, 14, 15, 16, 17, + 11, 10, 10, 11, 12, 12, 12, 12, 13, 13, 13, 14, 15, 15, 15, 16, + 11, 11, 11, 12, 12, 13, 12, 13, 14, 14, 15, 15, 15, 16, 16, 16, + 12, 11, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 16, 15, 16, 16, + 13, 12, 12, 13, 13, 13, 15, 14, 14, 17, 15, 15, 15, 17, 16, 16, + 12, 12, 13, 14, 14, 14, 15, 14, 15, 15, 16, 16, 19, 18, 19, 16 +}; + +unsigned char huff_hlen15[16*16] = { + 3, 4, 5, 7, 7, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 13, + 4, 3, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, + 5, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 11, 11, 11, + 6, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, + 7, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, + 8, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 11, 11, 11, 12, + 9, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, + 9, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 12, + 9, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 12, 12, 12, + 9, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, + 10, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 13, 12, + 10, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, + 11, 10, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 13, 13, + 11, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, + 12, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 12, 13, + 12, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13 +}; + +unsigned char huff_hlen16[16*16] = { + 1, 4, 6, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 9, + 3, 4, 6, 7, 8, 9, 9, 9, 10, 10, 10, 11, 12, 11, 12, 8, + 6, 6, 7, 8, 9, 9, 10, 10, 11, 10, 11, 11, 11, 12, 12, 9, + 8, 7, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 10, + 9, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 9, + 9, 8, 9, 9, 10, 11, 11, 12, 11, 12, 12, 13, 13, 13, 14, 10, + 10, 9, 9, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 10, + 10, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 15, 15, 10, + 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 10, + 11, 10, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 13, 14, 13, 11, + 11, 11, 10, 11, 12, 12, 12, 12, 13, 14, 14, 14, 15, 15, 14, 10, + 12, 11, 11, 11, 12, 12, 13, 14, 14, 14, 14, 14, 14, 13, 14, 11, + 12, 12, 12, 12, 12, 13, 13, 13, 13, 15, 14, 14, 14, 14, 16, 11, + 14, 12, 12, 12, 13, 13, 14, 14, 14, 16, 15, 15, 15, 17, 15, 11, + 13, 13, 11, 12, 14, 14, 13, 14, 14, 15, 16, 15, 17, 15, 14, 11, + 9, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 8 +}; + +unsigned char huff_hlen24[16*16] = { + 4, 4, 6, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 12, 9, + 4, 4, 5, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10, 8, + 6, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 7, + 7, 6, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 7, + 8, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 7, + 9, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 7, + 9, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 7, + 10, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 8, + 10, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 8, + 10, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 8, + 11, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 8, + 11, 10, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 8, + 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 8, + 11, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 8, + 12, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 8, + 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 4 +}; + +unsigned char huff_hlen32[16*1] = { + 1, + 4, + 4, + 5, + 4, + 6, + 5, + 6, + 4, + 5, + 5, + 6, + 5, + 6, + 6, + 6 +}; + +unsigned char huff_hlen33[16*1] = { + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 +}; + +struct huffcodetab ht[34] = { + { 0, 0, 0, 0, -1, 0, 0 }, + { 2, 2, 0, 0, -1, huff_tab1, huff_hlen1 }, + { 3, 3, 0, 0, -1, huff_tab2, huff_hlen2 }, + { 3, 3, 0, 0, -1, huff_tab3, huff_hlen3 }, + { 0, 0, 0, 0, -1, 0, 0 }, + { 4, 4, 0, 0, -1, huff_tab5, huff_hlen5 }, + { 4, 4, 0, 0, -1, huff_tab6, huff_hlen6 }, + { 6, 6, 0, 0, -1, huff_tab7, huff_hlen7 }, + { 6, 6, 0, 0, -1, huff_tab8, huff_hlen8 }, + { 6, 6, 0, 0, -1, huff_tab9, huff_hlen9 }, + { 8, 8, 0, 0, -1, huff_tab10, huff_hlen10 }, + { 8, 8, 0, 0, -1, huff_tab11, huff_hlen11 }, + { 8, 8, 0, 0, -1, huff_tab12, huff_hlen12 }, + { 16, 16, 0, 0, -1, huff_tab13, huff_hlen13 }, + { 0, 0, 0, 0, -1, 0, 0 }, + { 16, 16, 0, 0, -1, huff_tab15, huff_hlen15 }, + { 16, 16, 1, 1, -1, huff_tab16, huff_hlen16 }, + { 16, 16, 2, 3, 16, huff_tab16, huff_hlen16 }, + { 16, 16, 3, 7, 16, huff_tab16, huff_hlen16 }, + { 16, 16, 4, 15, 16, huff_tab16, huff_hlen16 }, + { 16, 16, 6, 63, 16, huff_tab16, huff_hlen16 }, + { 16, 16, 8, 255, 16, huff_tab16, huff_hlen16 }, + { 16, 16, 10, 1023, 16, huff_tab16, huff_hlen16 }, + { 16, 16, 13, 8191, 16, huff_tab16, huff_hlen16 }, + { 16, 16, 4, 15, -1, huff_tab24, huff_hlen24 }, + { 16, 16, 5, 31, 24, huff_tab24, huff_hlen24 }, + { 16, 16, 6, 63, 24, huff_tab24, huff_hlen24 }, + { 16, 16, 7, 127, 24, huff_tab24, huff_hlen24 }, + { 16, 16, 8, 255, 24, huff_tab24, huff_hlen24 }, + { 16, 16, 9, 511, 24, huff_tab24, huff_hlen24 }, + { 16, 16, 11, 2047, 24, huff_tab24, huff_hlen24 }, + { 16, 16, 13, 8191, 24, huff_tab24, huff_hlen24 }, + { 1, 16, 0, 0, -1, huff_tab32, huff_hlen32 }, + { 1, 16, 0, 0, -1, huff_tab33, huff_hlen33 } +}; diff -Nru swftools-0.9.2+ds1/lib/bladeenc/tables.h swftools-0.9.1/lib/bladeenc/tables.h --- swftools-0.9.2+ds1/lib/bladeenc/tables.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/bladeenc/tables.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,173 @@ +/* + (c) Copyright 1998-2000 - Tord Jansson + ====================================== + + This file is part of the BladeEnc MP3 Encoder, based on + ISO's reference code for MPEG Layer 3 compression, and might + contain smaller or larger sections that are directly taken + from ISO's reference code. + + All changes to the ISO reference code herein are either + copyrighted by Tord Jansson (tord.jansson@swipnet.se) + or sublicensed to Tord Jansson by a third party. + + BladeEnc is free software; you can redistribute this file + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + + + ------------ Changes ------------ + + 2000-12-06 Andre Piotrowski + + - reformatted +*/ +#ifndef __TABLES__ +#define __TABLES__ + + + + + +#define NEW_L3PARM_TABLES 1 +#define CALC_NORM 0 + + + + + +#define CBANDS 63 +#define CBANDS_s 42 + + + + + +#if NEW_L3PARM_TABLES + + + typedef struct + { + int cbmax_l; /* number of valid entries */ + int numlines_l[CBANDS]; + double minval [CBANDS]; + double qthr_l [CBANDS]; +#if !CALC_NORM /* do we compute more exact values? */ + double norm_l [CBANDS]; +#endif + double bval_l [CBANDS]; + } l3_long_data; + + + typedef struct + { + int cbmax_s; /* number of valid entries */ + int numlines_s[CBANDS_s]; + double qthr_s [CBANDS_s]; +#if !CALC_NORM /* do we compute more exact values? */ + double norm_s [CBANDS_s]; +#endif + double SNR_s [CBANDS_s]; + double bval_s [CBANDS_s]; + } l3_short_data; + + + typedef struct + { + int cbw_l [CBANDS]; + int bu_l [CBANDS]; + int bo_l [CBANDS]; + double w1_l [CBANDS]; + double w2_l [CBANDS]; + } l3_long_thres; + + + typedef struct + { + int cbw_s [CBANDS_s]; + int bu_s [CBANDS_s]; + int bo_s [CBANDS_s]; + double w1_s [CBANDS_s]; + double w2_s [CBANDS_s]; + } l3_short_thres; + + + typedef struct + { + l3_long_data long_data; + l3_short_data short_data; + l3_long_thres long_thres; + l3_short_thres short_thres; + } l3_parm_block; + + + extern l3_parm_block l3_parm[3]; + + +#else /* NEW_L3PARM_TABLES */ + + + typedef struct + { + /* int no; */ + int lines; + double minVal; + double qthr; + double norm; + double bVal; + } psyDataElem; + + + typedef struct + { + /* int no; */ + int lines; + double qthr; + double norm; + double snr; + double bVal; + } psyDataElem2; + + typedef struct + { + int cbw; + int bu; + int bo; + float w1; + float w2; + } psyDataElem3; + + + extern psyDataElem psy_longBlock_48000_61[62]; + extern psyDataElem psy_longBlock_44100_62[63]; + extern psyDataElem psy_longBlock_32000_58[59]; + + extern psyDataElem2 psy_shortBlock_48000_37[38]; + extern psyDataElem2 psy_shortBlock_44100_38[39]; + extern psyDataElem2 psy_shortBlock_32000_41[42]; + + extern psyDataElem3 psy_data3_48000_20[21]; + extern psyDataElem3 psy_data3_44100_20[21]; + extern psyDataElem3 psy_data3_32000_20[21]; + + extern psyDataElem3 psy_data4_48000_11[12]; + extern psyDataElem3 psy_data4_44100_11[12]; + extern psyDataElem3 psy_data4_32000_11[12]; + + +#endif /* NEW_L3PARM_TABLES */ + + + + + +extern double enwindow[512]; +extern char aHuffcode[1498][36]; + + + + + +#endif /* __TABLES__ */ diff -Nru swftools-0.9.2+ds1/lib/.ccmalloc swftools-0.9.1/lib/.ccmalloc --- swftools-0.9.2+ds1/lib/.ccmalloc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/.ccmalloc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,31 @@ +%file FILE +%log FILE +%logpid FILE +%dont-log-chain +%only-log-chain +%set only-count 0 +set load-dynlibs 1 + +%set check-start 0 +%set silent +set file-info 1 +%set continue 0 +%set chain-length 0 +%set additional-line 1 +%set sort-by-wasted 1 +%set sort-by-size 1 +%set debug X +%set align-8-byte 0 +set only-wasting-alloc 1 + +set print-addresses 1 +set print-on-one-line 1 +set statistics 1 + +set check-free-space 1 +set check-interval 1 +set check-overwrites 1 +set check-underwrites 1 +set keep-deallocated-data 1 +set library-chains 1 + diff -Nru swftools-0.9.2+ds1/lib/example/alignzones.c swftools-0.9.1/lib/example/alignzones.c --- swftools-0.9.2+ds1/lib/example/alignzones.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/alignzones.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,245 @@ +/* hexfont.c + + Example for how to construct an SWF font from another SWF font. + + Part of the swftools package. + + Copyright (c) 2004 Matthias Kramm + + This file is distributed under the GPL, see file COPYING for details + + 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 "../rfxswf.h" + +static void write_font(SWFFONT * font, char *filename) +{ + SWF swf; + TAG *t; + SRECT r; + RGBA rgb; + int f; + int useDefineFont2 = 1; + int storeGlyphNames = 1; + +#define WRITEFONTID 8888 + font->id = WRITEFONTID; + + memset(&swf, 0x00, sizeof(SWF)); + + swf.fileVersion = 9; + swf.frameRate = 0x4000; + + t = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR); + swf.firstTag = t; + rgb.r = 0xef; + rgb.g = 0xef; + rgb.b = 0xff; + swf_SetRGB(t, &rgb); + + t = swf_InsertTag(t, ST_DEFINEFONT3); + swf_FontSetDefine2(t, font); + + t = swf_InsertTag(t, ST_DEFINEFONTALIGNZONES); + swf_SetU16(t, font->id); + swf_SetU8(t, 0); //thin + int i; + for(i=0;i<256;i++) { + swf_SetU8(t, 2); + swf_SetF16(t, 82.0 / 1024.0); + swf_SetF16(t, 82.0 / 1024.0); + swf_SetF16(t, ((i%16/2)*82.0) / 1024.0); + swf_SetF16(t, ((i/16/2)*82.0) / 1024.0); + /* + if(i<128 && (i&15)<8) { + swf_SetF16(t, 0.0); + swf_SetF16(t, 0.0); + swf_SetF16(t, 640.0 / 1024.0); + swf_SetF16(t, 640.0 / 1024.0); + } else if(i<128 && (i&15)>=8) { + swf_SetF16(t, 0.0 / 1024.0); + swf_SetF16(t, 0.0 / 1024.0); + swf_SetF16(t, 330.0 / 1024.0); + swf_SetF16(t, 640.0 / 1024.0); + } else if(i>=128 && (i&15)<8) { + swf_SetF16(t, 0.0 / 1024.0); + swf_SetF16(t, 0.0 / 1024.0); + swf_SetF16(t, 640.0 / 1024.0); + swf_SetF16(t, 330.0 / 1024.0); + } else { + swf_SetF16(t, 0.0 / 1024.0); + swf_SetF16(t, 0.0 / 1024.0); + swf_SetF16(t, 330.0 / 1024.0); + swf_SetF16(t, 330.0 / 1024.0); + }*/ + swf_SetU8(t, 3); // x and y + } + + int s; + int xmax = 0; + int ymax = 0; + int ypos = 1; + U8 gbits, abits; + int x, y, c; + int range = font->maxascii; + + c = 0; + range = 256; + + xmax = 1280; + ymax = 1280*20; + + swf.movieSize.xmax = xmax * 20; + swf.movieSize.ymax = ymax; + + t = swf_InsertTag(t, ST_DEFINETEXT); + swf_SetU16(t, font->id + 1); // ID + r.xmin = 0; + r.ymin = 0; + r.xmax = swf.movieSize.xmax; + r.ymax = swf.movieSize.ymax; + swf_SetRect(t, &r); + swf_SetMatrix(t, NULL); + abits = swf_CountBits(xmax * 16, 0); + gbits = 8; + swf_SetU8(t, gbits); + swf_SetU8(t, abits); + + rgb.r = 0x00; + rgb.g = 0x00; + rgb.b = 0x00; + ypos = 2; + + int textscale = 1024; + for (y = 0; y < ((range + 15) / 16); y++) { + for (x = 0; x < 16; x++) { + //swf_TextSetInfoRecord(t, font, textscale, &rgb, x*64*20+64*20+10+(x+y)*20, y*64*20+128*20+10+(x^y)*20); + swf_TextSetInfoRecord(t, font, textscale, &rgb, x*64*20+64*20+10, y*64*20+128*20+10); + int g = y * 16 + x; + swf_SetU8(t, 1); + swf_SetBits(t, g, gbits); + swf_SetBits(t, 0, abits); + swf_ResetWriteBits(t); + } + } + swf_SetU8(t, 0); + + t = swf_InsertTag(t, ST_CSMTEXTSETTINGS); + swf_SetU16(t, font->id + 1); + swf_SetU8(t, (1<<3)//grid + |0x40//flashtype + ); + swf_SetU32(t, 0x20000);//thickness + swf_SetU32(t, 0x800000);//sharpness + swf_SetU8(t, 0);//reserved + + t = swf_InsertTag(t, ST_PLACEOBJECT2); + swf_ObjectPlace(t, font->id + 1, 1, NULL, NULL, NULL); + + t = swf_InsertTag(t, ST_SHOWFRAME); + t = swf_InsertTag(t, ST_END); + + f = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0644); + if FAILED + (swf_WriteSWF(f, &swf)) fprintf(stderr, "WriteSWF() failed in writeFont().\n"); + close(f); + + swf_FreeTags(&swf); +} + + +int main() +{ + SWFFONT hexfont; + + memset(&hexfont, 0, sizeof(hexfont)); + hexfont.name = (U8*)"HexFont"; + hexfont.layout = malloc(sizeof(SWFLAYOUT)); + hexfont.numchars = 256; + hexfont.maxascii = 256; + hexfont.encoding = 32; + hexfont.glyph2ascii = malloc(sizeof(U16)*256); + hexfont.ascii2glyph = malloc(sizeof(int)*256); + hexfont.glyph = malloc(sizeof(SWFGLYPH)*256); + hexfont.glyphnames = malloc(sizeof(char*)*256); + hexfont.layout->bounds = malloc(sizeof(SRECT)*256); + hexfont.layout->kerningcount = 0; + hexfont.layout->kerning = 0; + int t; + int ymax =-0x7fffffff; + int ymin = 0x7fffffff; + for(t=0;t<256;t++) + { + drawer_t _draw,*draw=&_draw; + swf_Shape01DrawerInit(draw, 0); + int x,y; + FPOINT d; + int rx = 0;//t&15; + int ry = 0;//(t&15)^0x05; +#define S {d.x*=20*4+2;d.y*=20*4+2;} + if(1) { + for(x=0;x<8;x++) + for(y=0;y<8;y++) { + if((x^y)&1) { + d.x=x;d.y=-y; S;draw->moveTo(draw, &d); + d.x=x+1;d.y=-y; S;draw->lineTo(draw, &d); + d.x=x+1;d.y=-y-1; S;draw->lineTo(draw, &d); + d.x=x;d.y=-y-1; S;draw->lineTo(draw, &d); + d.x=x;d.y=-y; S;draw->lineTo(draw, &d); + } + } + } else { + d.x=0;d.y=-0; S;draw->moveTo(draw, &d); + d.x=0;d.y=-8; S;draw->lineTo(draw, &d); + d.x=8;d.y=-8; S;draw->lineTo(draw, &d); + d.x=8;d.y=-0; S;draw->lineTo(draw, &d); + d.x=0;d.y=-0; S;draw->lineTo(draw, &d); + + d.x=1;d.y=-1; S;draw->moveTo(draw, &d); + d.x=7;d.y=-1; S;draw->lineTo(draw, &d); + d.x=7;d.y=-7; S;draw->lineTo(draw, &d); + d.x=1;d.y=-7; S;draw->lineTo(draw, &d); + d.x=1;d.y=-1; S;draw->lineTo(draw, &d); + } + draw->finish(draw); + hexfont.glyph[t].shape = swf_ShapeDrawerToShape(draw); + hexfont.layout->bounds[t] = swf_ShapeDrawerGetBBox(draw); + hexfont.glyph[t].advance = hexfont.layout->bounds[t].xmax + hexfont.layout->bounds[t].xmin; + draw->dealloc(draw); + + hexfont.glyph2ascii[t] = t; + hexfont.ascii2glyph[t] = t; + hexfont.glyphnames[t] = 0; + if(hexfont.layout->bounds[t].ymax > ymax) + ymax = hexfont.layout->bounds[t].ymax; + if(hexfont.layout->bounds[t].ymin < ymin) + ymin = hexfont.layout->bounds[t].ymin; + + if(t>=0xe4) { + /* breaks flashtype, but not (non-flashtype) definefont2 */ + //hexfont.glyph2ascii[t] = 0; + } + } + hexfont.layout->ascent = ymin<0?-ymin:0; + hexfont.layout->descent = ymax>0?ymax:0; + hexfont.layout->leading = hexfont.layout->ascent + hexfont.layout->descent; + + write_font(&hexfont, "alignzones.swf"); + return 0; +} + diff -Nru swftools-0.9.2+ds1/lib/example/box.c swftools-0.9.1/lib/example/box.c --- swftools-0.9.2+ds1/lib/example/box.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/box.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,320 @@ +/* box.c + + Example for drawing 3D grind objects + + Part of the swftools package. + + Copyright (c) 2000, 2001 Rainer Böhme + 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 "../rfxswf.h" + +#define BANNER_TEXT "reflex" // banner is disabled due to new font handling +#define ID_FONT 2000 +#define ID_BANNER 2001 +#define ID_HIGHLIGHT 2002 +#define ID_BUTTON 2003 + +#define a 200 +int sX[] = { a,-a, a,-a, a,-a, a,-a}; +int sY[] = { a, a,-a,-a, a, a,-a,-a}; +int sZ[] = { a, a, a, a,-a,-a,-a,-a}; +#undef a + +int dX[8]; +int dY[8]; + +int sin_[512],cos_[512]; + +void calcTables() +{ int i; + double d; + for (i=0;i<512;i++) + { d = ((double)i)/128*3.14159; + sin_[i] = (int)(sin(d)*256); + cos_[i] = (int)(cos(d)*256); + } +} + +void ShapeSquare(TAG* t,SHAPE* s,int p1,int p2,int p3,int p4,int dx,int dy) +{ + // Hidden-Line-Check + if (((dX[p2]-dX[p1])*(dY[p3]-dY[p1])-(dX[p3]-dX[p1])*(dY[p2]-dY[p1]))<0) return; + + swf_ShapeSetMove(t,s,dX[p1]+dx,dY[p1]+dy); + swf_ShapeSetLine(t,s,dX[p2]-dX[p1],dY[p2]-dY[p1]); + swf_ShapeSetLine(t,s,dX[p3]-dX[p2],dY[p3]-dY[p2]); + swf_ShapeSetLine(t,s,dX[p4]-dX[p3],dY[p4]-dY[p3]); + swf_ShapeSetLine(t,s,dX[p1]-dX[p4],dY[p1]-dY[p4]); +} + + +void mapBox(int xw,int yw,int zw) +// simple trigonometry without using transformation matrices +{ int i; + int x1,y1,z1,x2,y2,z2,x3,y3,z3; + int y,x,z; + + xw &= 255; + yw &= 255; + zw &= 255; + + for (i=0;i<8;i++) + { x = sX[i]; + y = sY[i]; + z = sZ[i]; + + y1 = ( y*cos_[xw]- z*sin_[xw])>>8; + z1 = ( y*sin_[xw]+ z*cos_[xw])>>8; + x1 = x; + + x2 = (x1*cos_[yw]+z1*sin_[yw])>>8; + y2 = y1; + + x3 = (x2*cos_[zw]-y2*sin_[zw])>>8; + y3 = (x2*sin_[zw]+y2*cos_[zw])>>8; + z3 = (z1*cos_[yw]-x1*sin_[yw])>>8; + + dX[i] = x3*4000/(z3+950); + dY[i] = y3*4000/(z3+950); + + } +} + +int main (int argc,char ** argv) +{ SWF swf; + TAG* t; + RGBA rgb; + SRECT r; + SHAPE* s; + S32 width = 800,height = 800; + U8 gbits,abits; + CXFORM cx1,cx2; + MATRIX m; + + int f,i,j,frame; + +/* f = open("Arial.efont",O_RDONLY); + if (f>=0) + { if (FAILED(swf_FontImport(f,&font))) + { fprintf(stderr,"Font import failed\n"); + close(f); + return -1; + } + } + else + { fprintf(stderr,"Font not found\n"); + return -1; + } + close(f); + + swf_FontSetID(font,ID_FONT); + swf_FontInitUsage(&use); + swf_FontUse(&use,BANNER_TEXT); + swf_FontReduce(font,&use); +*/ + + calcTables(); + + memset(&swf,0x00,sizeof(SWF)); + + swf.fileVersion = 4; + swf.frameRate = 0x4000; + swf.movieSize.xmax = 4*width; + swf.movieSize.ymax = 4*height; + + swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + t = swf.firstTag; + + rgb.r = 0xff; + rgb.g = 0xff; + rgb.b = 0xff; + swf_SetRGB(t,&rgb); + +/* This part can't be used because of missing fonts. Nevertheless it shows, how + rfxswf handles fonts, fontusages (in order to include only the used glyphs + into the output swf) and how to make a simple button + + + t = swf_InsertTag(t,ST_DEFINEFONT); + + swf_FontSetDefine(t,font); + + t = swf_InsertTag(t,ST_DEFINEFONTINFO); + + swf_FontSetInfo(t,font); + + t = swf_InsertTag(t,ST_DEFINETEXT); + + swf_SetU16(t,ID_BANNER); // ID + + r.xmin = 0; + r.ymin = 0; + r.xmax = 400; + r.ymax = 400; + + swf_SetRect(t,&r); + + swf_SetMatrix(t,NULL); + + swf_TextCountBits(font,BANNER_TEXT,80,&gbits,&abits); + + swf_SetU8(t,gbits); + swf_SetU8(t,abits); + + rgb.r = 0xc0; + rgb.g = 0xc0; + rgb.b = 0xc0; + + swf_TextSetInfoRecord(t,font,height/4,&rgb,0,200); + swf_TextSetCharRecord(t,font,BANNER_TEXT,80,gbits,abits); + + swf_SetU8(t,0); + + t = swf_InsertTag(t,ST_DEFINETEXT); + + swf_SetU16(t,ID_HIGHLIGHT); // ID + + r.xmin = 0; + r.ymin = 0; + r.xmax = 800; + r.ymax = 400; + + swf_SetRect(t,&r); + + swf_SetMatrix(t,NULL); + + swf_TextCountBits(font,BANNER_TEXT,80,&gbits,&abits); + + swf_SetU8(t,gbits); + swf_SetU8(t,abits); + + rgb.r = 0x20; + rgb.g = 0x20; + rgb.b = 0x20; + + swf_TextSetInfoRecord(t,font,height/4,&rgb,0,200); + swf_TextSetCharRecord(t,font,BANNER_TEXT,80,gbits,abits); + + swf_SetU8(t,0); + + t = swf_InsertTag(t,ST_DEFINEBUTTON); + + swf_GetMatrix(NULL,&m); + + m.tx = 3*width; + m.ty = 7*height/2; + + swf_SetU16(t,ID_BUTTON); // ID + swf_ButtonSetRecord(t,BS_UP,ID_BANNER,1,&m,NULL); + swf_ButtonSetRecord(t,BS_DOWN|BS_HIT|BS_OVER,ID_HIGHLIGHT,1,&m,NULL); + swf_SetU8(t,0); // End of Button Records + swf_SetU8(t,0); // End of Action Records + + + t = swf_InsertTag(t,ST_PLACEOBJECT2); + + swf_ObjectPlace(t,ID_BUTTON,1,NULL,NULL,NULL); + +*/ + + for (frame=0;frame<256;frame+=2) + { int id = frame +1; + + t = swf_InsertTag(t,ST_DEFINESHAPE); + + swf_ShapeNew(&s); + rgb.r = rgb.g = 0x00; rgb.b = 0xff; + j = swf_ShapeAddLineStyle(s,40,&rgb); + + swf_SetU16(t,id); // ID + + r.xmin = 0; + r.ymin = 0; + r.xmax = 4*width; + r.ymax = 4*height; + + swf_SetRect(t,&r); + swf_SetShapeHeader(t,s); + swf_ShapeSetAll(t,s,0,0,j,0,0); + + mapBox(frame,frame,frame>>1); + + ShapeSquare(t,s,0,2,3,1,2*width,2*height); + ShapeSquare(t,s,4,5,7,6,2*width,2*height); + ShapeSquare(t,s,0,4,6,2,2*width,2*height); + ShapeSquare(t,s,1,3,7,5,2*width,2*height); + ShapeSquare(t,s,0,1,5,4,2*width,2*height); + ShapeSquare(t,s,2,6,7,3,2*width,2*height); + + swf_ShapeSetEnd(t); + swf_ShapeFree(s); + } + + swf_GetCXForm(NULL,&cx1,1); // get default ColorTransforms + swf_GetCXForm(NULL,&cx2,1); + + cx1.r1 = cx1.g1 = 0x80; // set alpha for blur effect + cx2.r1 = cx2.g1 = 0xc0; + + for (frame=0;frame<256;frame+=2) + { int id = frame +1; + int id2 = ((frame-2)&255)+1; + int id3 = ((frame-4)&255)+1; + + if (frame) + { t = swf_InsertTag(t,ST_REMOVEOBJECT2); swf_SetU16(t,2); // depth + t = swf_InsertTag(t,ST_REMOVEOBJECT2); swf_SetU16(t,3); // depth + t = swf_InsertTag(t,ST_REMOVEOBJECT2); swf_SetU16(t,4); // depth + } + + t = swf_InsertTag(t,ST_PLACEOBJECT2); + + swf_ObjectPlace(t,id,4,NULL,NULL,NULL); + + t = swf_InsertTag(t,ST_PLACEOBJECT2); + + swf_ObjectPlace(t,id2,3,NULL,&cx1,NULL); + + t = swf_InsertTag(t,ST_PLACEOBJECT2); + + swf_ObjectPlace(t,id3,2,NULL,&cx2,NULL); + + t = swf_InsertTag(t,ST_SHOWFRAME); + } + + t = swf_InsertTag(t,ST_END); + +// swf_WriteCGI(&swf); + + + f = open("box.swf",O_RDWR|O_CREAT|O_TRUNC|O_BINARY,0644); + if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed.\n"); + close(f); + + swf_FreeTags(&swf); + +#ifdef __NT__ + system("start ..\\box.swf"); +#endif + + return 0; +} + + diff -Nru swftools-0.9.2+ds1/lib/example/buttontest.c swftools-0.9.1/lib/example/buttontest.c --- swftools-0.9.2+ds1/lib/example/buttontest.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/buttontest.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,143 @@ +/* buttontest.c + + Example implementation for creating a button with rfxswf + + Part of the swftools package. + + Copyright (c) 2000, 2001 Matthias Kramm + Rainer Böhme + + 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 "../rfxswf.h" + +TAG* t; + +#define ID_BUTTON 31 + +int useDefineButton2 = 1; // set this to 1 to use DefineButton2 Tags + // instead of DefineButton1 + +int main (int argc,char ** argv) +{ SWF swf; + RGBA rgb; + SRECT r; + SHAPE* s; + ActionTAG*a1,*a2,*a3, *actiontoset; + S32 width=300,height = 300; + + int f,i,ls1,fs1; + int count; + + memset(&swf,0x00,sizeof(SWF)); // set global movie parameters + + swf.fileVersion = 8; // make flash 4 compatible swf + swf.frameRate = 0x1900; // about 0x19 frames per second + + swf.movieSize.xmax = 20*width; // flash units: 1 pixel = 20 units + swf.movieSize.ymax = 20*height; + + swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + t = swf.firstTag; + rgb.r = 0xff; + rgb.g = 0xff; + rgb.b = 0xff; + swf_SetRGB(t,&rgb); + + for(count=1;count<4;count++) + { + t = swf_InsertTag(t,ST_DEFINESHAPE); + swf_ShapeNew(&s); // create new shape instance + rgb.r = rgb.b = rgb.g = 0x00; + ls1 = swf_ShapeAddLineStyle(s,40,&rgb); + rgb.r = count*0x40; rgb.b = 0xff; + fs1 = swf_ShapeAddSolidFillStyle(s,&rgb); + swf_SetU16(t,33+count); // now set character ID + r.xmin = 0; + r.ymin = 0; + r.xmax = 20*width; + r.ymax = 20*height; + swf_SetRect(t,&r); // set shape bounds + swf_SetShapeHeader(t,s); // write all styles to tag + swf_ShapeSetAll(t,s,0,0,ls1,fs1,0); // move to (0,0), select linestyle ls1 and no fillstyle + swf_ShapeSetCircle(t,s,width*10,height*10,width*10,height*10); + swf_ShapeSetEnd(t); // finish drawing + swf_ShapeFree(s); // clean shape structure (which isn't needed anymore after writing the tag) + } + + a1 = action_SetTarget(0, "movie"); + a1 = action_NextFrame(a1); + a1 = action_SetTarget(a1, ""); + a1 = action_End(a1); + + //a2 = action_GetUrl(a2, "test.swf","_level0"); // load a swf + //a2 = action_GetUrl(a2, "index.html","_this"); // load html in new window + a2 = action_GetUrl(0, "http://www.quiss.org/swftools/index.html","_parent"); // load html in this window + a2 = action_End(a2); + + a3 = action_GotoFrame(0,33); + a3 = action_End(a3); + + actiontoset = a2; + + if(!useDefineButton2) + { + t = swf_InsertTag(t,ST_DEFINEBUTTON); + swf_SetU16(t,31); //id + swf_ButtonSetRecord(t,BS_UP|BS_HIT,34,1,NULL,NULL); + swf_ButtonSetRecord(t,BS_OVER,35,1,NULL,NULL); + swf_ButtonSetRecord(t,BS_DOWN,36,1,NULL,NULL); + swf_SetU8(t,0); // end of button records + + swf_ActionSet(t,actiontoset); + } + else + { + t = swf_InsertTag(t,ST_DEFINEBUTTON2); + swf_SetU16(t,ID_BUTTON); //id + swf_ButtonSetFlags(t, 0); //menu=no + swf_ButtonSetRecord(t,BS_UP|BS_HIT,34,1,NULL,NULL); + swf_ButtonSetRecord(t,BS_OVER,35,1,NULL,NULL); + swf_ButtonSetRecord(t,BS_DOWN,36,1,NULL,NULL); + swf_SetU8(t,0); // end of button records + + swf_ButtonSetCondition(t, BC_IDLE_OVERUP); + swf_ActionSet(t,actiontoset); + + swf_ButtonPostProcess(t, 1); // don't forget! + } + + swf_ActionFree(a1); + swf_ActionFree(a2); + swf_ActionFree(a3); + + t = swf_InsertTag(t,ST_PLACEOBJECT2); + swf_ObjectPlace(t, ID_BUTTON, 2,0,0,0); + + t = swf_InsertTag(t,ST_SHOWFRAME); + t = swf_InsertTag(t,ST_END); + + f = open("buttontest.swf",O_WRONLY|O_CREAT|O_BINARY, 0644); + if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed.\n"); + close(f); + + swf_FreeTags(&swf); // cleanup + return 0; +} + + diff -Nru swftools-0.9.2+ds1/lib/example/demofont.c swftools-0.9.1/lib/example/demofont.c --- swftools-0.9.2+ds1/lib/example/demofont.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/demofont.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,140 @@ +/* demofont.c + + Character data for some glyphs needed by text.c + + Dumped with dumpfont.c + + Part of the swftools package. + + 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 */ + +#define addGlyph fn3711 + +void fn3711(SWFFONT * f,int i,U16 ascii,U16 advance,U8 * data,U32 bitlen) +{ SHAPE * s; + U32 l = (bitlen+7)/8; + + if (FAILED(swf_ShapeNew(&s))) return; + s->data = malloc(l); + if (!s->data) { swf_ShapeFree(s); return; } + + f->glyph2ascii[i] = ascii; + f->ascii2glyph[ascii] = i; + f->glyph[i].advance = advance; + f->glyph[i].shape = s; + s->bitlen = bitlen; + s->bits.fill = 1; + memcpy(s->data,data,l); +} + +U8 Glyphs_Demo_Font[] = { + 0x35, 0x66, 0xc2, 0xd5, 0xe3, 0x9b, 0x62, 0x08, + 0xea, 0x09, 0xe2, 0x4c, 0xf8, 0xba, 0x59, 0x2d, + 0x93, 0x1d, 0xe4, 0xc3, 0x6b, 0x40, 0x92, 0x90, + 0x30, 0x36, 0x4c, 0x0c, 0xe5, 0xa9, 0xbe, 0x46, + 0x40, 0x1a, 0xf5, 0x50, 0xec, 0x3b, 0x6a, 0xa4, + 0xd8, 0x8a, 0xe1, 0x4b, 0x66, 0x00, 0x40, 0x0e, + 0x11, 0x91, 0x35, 0x9f, 0x03, 0x51, 0x4e, 0x8a, + 0x5c, 0x17, 0x7e, 0x8d, 0xda, 0x0a, 0x48, 0xa0, + 0x08, 0xed, 0x22, 0x1b, 0x0f, 0x7c, 0xa1, 0xb7, + 0x80, 0x9f, 0xc3, 0x69, 0xec, 0x53, 0xea, 0xdc, + 0xd8, 0x59, 0xd1, 0x8a, 0x60, 0x0b, 0xc1, 0x6d, + 0x09, 0x4b, 0x51, 0x5b, 0x8e, 0x55, 0xb8, 0x9c, + 0x80, 0x95, 0xa0, 0x05, 0x88, 0xa4, 0x75, 0x70, + 0x1c, 0x8c, 0x0f, 0x9b, 0x40, 0x35, 0x62, 0xfa, + 0x9c, 0xf9, 0x53, 0x04, 0xa0, 0x15, 0x86, 0x1d, + 0x19, 0x9c, 0xd3, 0xca, 0x34, 0x3a, 0x40, 0x1a, + 0x29, 0x6e, 0x47, 0xf4, 0x6e, 0xd6, 0xaf, 0xd4, + 0x6c, 0xc9, 0xa3, 0x28, 0x7e, 0x20, 0x2b, 0x70, + 0xcc, 0x13, 0x00, 0x59, 0x7e, 0x77, 0xe9, 0xd6, + 0x7d, 0x36, 0x75, 0xae, 0xf8, 0x8d, 0x3c, 0x5d, + 0xbd, 0x11, 0xc8, 0xd0, 0x5c, 0x00, 0x35, 0x47, + 0x8c, 0x93, 0x92, 0x50, 0x26, 0x42, 0x5c, 0xa4, + 0x37, 0xa7, 0x97, 0x82, 0x80, 0x0f, 0xa6, 0x00, + 0x64, 0x28, 0x48, 0x98, 0x9d, 0x25, 0x04, 0x02, + 0x56, 0x20, 0x0f, 0xd8, 0x98, 0x83, 0x60, 0x02, + 0x7a, 0x60, 0x08, 0x6c, 0xbb, 0xa9, 0x6e, 0xd0, + 0x92, 0x00, 0x15, 0x12, 0x92, 0x3c, 0xac, 0xf1, + 0x39, 0x01, 0x33, 0x40, 0x01, 0xfa, 0x7c, 0xc6, + 0xc8, 0x60, 0x0b, 0x12, 0x80, 0x7b, 0x89, 0xfc, + 0xb8, 0xdf, 0xcc, 0x41, 0x2c, 0xc4, 0x10, 0x40, + 0x4d, 0x30, 0x01, 0x87, 0x5d, 0x36, 0x6d, 0xd0, + 0x05, 0x54, 0xa0, 0x20, 0x9f, 0x85, 0x29, 0xf8, + 0x2c, 0xf1, 0x80, 0x35, 0x4a, 0x44, 0x53, 0xdd, + 0x4e, 0x68, 0x61, 0x37, 0x6d, 0xb7, 0x17, 0x34, + 0xb8, 0xb2, 0xd2, 0x01, 0x2d, 0xd0, 0x1a, 0xc9, + 0xc9, 0x52, 0x40, 0x2f, 0x20, 0x0e, 0x20, 0xa4, + 0xa4, 0x0a, 0x2f, 0x2f, 0xb5, 0x24, 0x92, 0x66, + 0x63, 0x10, 0x05, 0x19, 0x40, 0x3f, 0xa2, 0x9a, + 0x5a, 0x09, 0xa3, 0x00, 0xdb, 0x41, 0xe3, 0xa6, + 0x5e, 0xe3, 0xa0, 0x34, 0xdd, 0x0b, 0xf7, 0x6b, + 0xba, 0x08, 0xcc, 0x1c, 0x8c, 0x4e, 0x47, 0x2a, + 0x84, 0x8c, 0x40, 0x4a, 0x88, 0x01, 0x6d, 0x92, + 0x2d, 0x58, 0x12, 0x4a, 0x02, 0xee, 0x8d, 0x33, + 0x73, 0xf4, 0x5c, 0x6e, 0x4d, 0x6f, 0xb9, 0xd5, + 0xc7, 0x2e, 0x9c, 0x80, 0x2a, 0x4a, 0x02, 0x42, + 0x7b, 0x52, 0xa7, 0xb4, 0xf4, 0x06, 0xd4, 0x20, + 0xbd, 0x68, 0x84, 0x67, 0x67, 0x33, 0xae, 0x3a, + 0x08, 0x00, 0x35, 0x62, 0x96, 0xd0, 0x77, 0x52, + 0xdb, 0x0d, 0x7a, 0xa8, 0xf6, 0x25, 0x78, 0x52, + 0x99, 0x40, 0x2d, 0x1a, 0x3e, 0x43, 0x50, 0x50, + 0x09, 0x10, 0x01, 0x0d, 0xa4, 0x3f, 0x52, 0x6c, + 0xd0, 0x4e, 0x5d, 0xec, 0x70, 0x19, 0x97, 0x01, + 0x9b, 0xc0, 0x24, 0xa4, 0x0a, 0xb3, 0x92, 0xac, + 0xf5, 0xa6, 0x5e, 0xda, 0x00, 0x4e, 0xe1, 0xb3, + 0x36, 0x2d, 0xf4, 0x70, 0x91, 0xcd, 0x5d, 0x9a, + 0x53, 0x99, 0x4b, 0xdc, 0xda, 0x41, 0x77, 0x98, + 0xf0, 0x00, 0x35, 0x48, 0x34, 0x6d, 0xdc, 0x6d, + 0x68, 0xa7, 0x2d, 0xc0, 0x3c, 0x46, 0x49, 0xb1, + 0x00, 0x23, 0xa4, 0x45, 0x78, 0x8d, 0x08, 0x3e, + 0xf3, 0x0c, 0x0b, 0x58, 0xaa, 0xba, 0x76, 0xbf, + 0x5d, 0xaf, 0x1a, 0x36, 0xee, 0x24, 0x34, 0x53, + 0x96, 0xa8, 0x6d, 0x6d, 0x78, 0xec, 0xec, 0x56, + 0x85, 0x9c, 0x78, 0xdb, 0x73, 0x8e, 0xf6, 0x92, + 0x68, 0x5b, 0xc7, 0x6d, 0x9f, 0xe5, 0xe5, 0x73, + 0x97, 0x39, 0x32, 0xce, 0x2e, 0xb4, 0x6d, 0xdc, + 0x60, 0x68, 0xa7, 0xae, 0xe8, 0x98, 0xf0, 0x80, + 0x3a, 0x40, 0x0f, 0x21, 0x6e, 0x23, 0x12, 0x11, + 0xbc, 0xc7, 0x29, 0xdb, 0xcd, 0x7b, 0x26, 0x91, + 0x59, 0xa6, 0xba, 0xfe, 0x34, 0x6d, 0x00, 0x00 }; + +SWFFONT * Font_Demo_Font(U16 id) +{ SWFFONT * f; + int i; + + if (!(f=malloc(sizeof(SWFFONT)))) return NULL; + memset(f,0x00,sizeof(SWFFONT)); + f->id = id; + f->version = 1; + f->name = strdup("Demo Font"); + f->style = 0x00; + f->encoding = 0x00; + f->numchars = 6; + f->maxascii = 256; + f->glyph = (SWFGLYPH*)malloc(sizeof(SWFGLYPH)*6); + f->glyph2ascii = (U16*)malloc(sizeof(U16)*6); + f->ascii2glyph = (int*)malloc(sizeof(int)*256); + memset(f->ascii2glyph, -1, sizeof(int)*256); + + addGlyph(f, 0, 102, 64*20, &Glyphs_Demo_Font[0x0000], 872); // f + addGlyph(f, 1, 108, 53*20, &Glyphs_Demo_Font[0x006d], 452); // l + addGlyph(f, 2, 111, 96*20, &Glyphs_Demo_Font[0x00a6], 743); // o + addGlyph(f, 3, 115, 74*20, &Glyphs_Demo_Font[0x0103], 951); // s + addGlyph(f, 4, 116, 53*20, &Glyphs_Demo_Font[0x017a], 570); // t + addGlyph(f, 5, 119, 138*20, &Glyphs_Demo_Font[0x01c2], 806); // w + return f; +} + +#undef addGlyph diff -Nru swftools-0.9.2+ds1/lib/example/dumpfont.c swftools-0.9.1/lib/example/dumpfont.c --- swftools-0.9.2+ds1/lib/example/dumpfont.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/dumpfont.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,187 @@ +/* dumpfont.c + + Example for font handling + + This tool dumps font information into C files + which can be included to rfxswf applications. + This is an easy way for developers to use + fonts in applications without dealing with + external files. + + Usage: ./dumpfont filename.swf > myfont.c + + Part of the swftools package. + + Copyright (c) 2000, 2001 Rainer Böhme + + 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 "../rfxswf.h" + +#define PRINTABLE(a) (((a>0x20)&&(a<0xff)&&(a!='\\'))?a:0x20) + +SWF swf; + +void DumpFont(SWFFONT * f,char * name) +{ int n,i; + int*gpos = malloc(sizeof(int*)*f->numchars); + memset(gpos,0,sizeof(int*)*f->numchars); + + // Glyph Shapes Data + + n = 0; + printf("U8 Glyphs_%s[] = {\n\t ",name); + + for (i=0;inumchars;i++) + if (f->glyph[i].shape) + { SHAPE * s = f->glyph[i].shape; + int j,l = (s->bitlen+7)/8; + gpos[i] = n; + + for (j=0;jdata[j]); + if ((n&7)==7) printf("\n\t "); + n++; + } + } + printf("0x00 };\n"); + + // SWFFONT function + + printf("\nSWFFONT * Font_%s(U16 id)\n",name); + printf("{ SWFFONT * f;\n int i;\n\n"); + printf(" if (!(f=malloc(sizeof(SWFFONT)))) return NULL;\n"); + printf(" memset(f,0x00,sizeof(SWFFONT));\n"); + printf(" f->id = id;\n"); + printf(" f->version = %d;\n", f->version); + printf(" f->name = strdup(\"%s\");\n",f->name); + printf(" f->style = 0x%02x;\n",f->style); + printf(" f->encoding = 0x%02x;\n",f->encoding); + printf(" f->numchars = %d;\n",f->numchars); + printf(" f->maxascii = %d;\n",f->maxascii); + printf(" f->glyph = (SWFGLYPH*)malloc(sizeof(SWFGLYPH)*%d);\n",f->numchars); + printf(" f->glyph2ascii = (U16*)malloc(sizeof(U16)*%d);\n",f->numchars); + printf(" f->ascii2glyph = (int*)malloc(sizeof(int)*%d);\n",f->maxascii); + printf(" memset(f->ascii2glyph, -1, sizeof(int)*%d);\n\n", f->maxascii); + if(f->layout) { + printf(" f->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));\n"); + printf(" f->layout->ascent = %d;\n", f->layout->ascent); + printf(" f->layout->descent = %d;\n", f->layout->descent); + printf(" f->layout->leading = %d;\n", f->layout->leading); + printf(" f->layout->kerningcount = 0;\n"); + printf(" f->layout->kerning = 0;\n"); + printf(" f->layout->bounds = (SRECT*)malloc(sizeof(SRECT)*%d);\n", f->numchars); + printf(" memset(f->layout->bounds, 0, sizeof(SRECT)*%d);\n\n", f->numchars); + } + + for (i=0;inumchars;i++) + if (f->glyph[i].shape) + { + printf(" addGlyph(f,%3i, 0x%03x,%4i, &Glyphs_%s[0x%04x], %4i, ", + i, f->glyph2ascii[i], f->glyph[i].advance, name, gpos[i], + f->glyph[i].shape->bitlen); + if(f->layout && f->layout->bounds) { + printf("%d, %d, %d, %d);", + f->layout->bounds[i].xmin, + f->layout->bounds[i].ymin, + f->layout->bounds[i].xmax, + f->layout->bounds[i].ymax); + } else { + printf("/* bbox not set */ 0, 0, 0, 0);"); + } + printf(" // %c\n", PRINTABLE(f->glyph2ascii[i])); + } + + printf(" return f;\n}\n\n"); + free(gpos); +} + +void DumpGlobal(char * funcname) +{ printf("\nvoid %s(SWFFONT * f,int i,U16 ascii,U16 advance,U8 * data,U32 bitlen,int xmin,int ymin,int xmax, int ymax)\n",funcname); + printf("{ SHAPE * s;\n U32 l = (bitlen+7)/8;\n\n"); + printf(" if (FAILED(swf_ShapeNew(&s))) return;\n"); + printf(" s->data = malloc(l);\n"); + printf(" if (!s->data) { swf_ShapeFree(s); return; }\n\n"); + printf(" f->glyph2ascii[i] = ascii;\n"); + printf(" f->ascii2glyph[ascii] = i;\n"); + printf(" f->glyph[i].advance = advance;\n"); + printf(" f->glyph[i].shape = s;\n"); + printf(" s->bitlen = bitlen;\n"); + printf(" s->bits.fill = 1;\n"); + printf(" if(f->layout && f->layout->bounds)\n"); + printf(" { f->layout->bounds[i].xmin = xmin;\n"); + printf(" f->layout->bounds[i].ymin = ymin;\n"); + printf(" f->layout->bounds[i].xmax = xmax;\n"); + printf(" f->layout->bounds[i].ymax = ymax;\n"); + printf(" }\n"); + printf(" memcpy(s->data,data,l);\n}\n\n"); +} + + +void fontcallback(U16 id,U8 * name,void*data) +{ SWFFONT * font; + + int f; + char s[500],*ss; + + swf_FontExtract(&swf,id,&font); + sprintf(s,"%s%s%s",name,swf_FontIsBold(font)?"_bold":"",swf_FontIsItalic(font)?"_italic":""); + + ss = s; + while(*ss) + { + if(!((*ss>='a' && *ss<='z') || + (*ss>='A' && *ss<='Z') || + (*ss>='0' && *ss<='9' && ss!=s) || + (*ss=='_'))) + *ss = '_'; + ss++; + } + + DumpFont(font,s); + + swf_FontFree(font); +} + +int main(int argc,char ** argv) +{ int f; + + if (argc>1) + { f = open(argv[1],O_RDONLY); + if (f>=0) + { if FAILED(swf_ReadSWF(f,&swf)) + { fprintf(stderr,"%s is not a valid SWF file or contains errors.\n",argv[1]); + close(f); + } + else + { char fn[200]; + close(f); + sprintf(fn,"fn%04x",getpid()); // avoid name conflicts @ using multiple fonts + printf("#define addGlyph %s\n",fn); + DumpGlobal(fn); + swf_FontEnumerate(&swf,&fontcallback,0); + swf_FreeTags(&swf); + printf("#undef addGlyph\n"); + } + } else fprintf(stderr,"File not found: %s\n",argv[1]); + } + else fprintf(stderr,"\nreflex SWF Font Dump Utility\n(w) 2000 by Rainer Boehme \n\nUsage: dumpfont filename.swf\n"); + + return 0; +} + diff -Nru swftools-0.9.2+ds1/lib/example/edittext.c swftools-0.9.1/lib/example/edittext.c --- swftools-0.9.2+ds1/lib/example/edittext.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/edittext.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,2119 @@ +/* edittext.c + + Demonstrates edittext fields. + + Part of the swftools package. + + Copyright (c) 2000, 2001 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 "../rfxswf.h" + +/* defined below: */ +extern char * longtext; +extern SWFFONT * Font_Courier(U16 id); + +int main (int argc,char ** argv) +{ SWF swf; + RGBA rgb; + SRECT r; + MATRIX m; + TAG* tag; + EditTextLayout layout; + SWFFONT*font; + S32 width=640,height = 480; + int f; + int t; + + memset(&swf,0x00,sizeof(SWF)); + + swf.fileVersion = 5; + swf.frameRate = 0x1900; + + swf.movieSize.xmax = 20*width; + swf.movieSize.ymax = 20*height; + + swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + tag = swf.firstTag; + rgb.r = 0xff; + rgb.g = 0xff; + rgb.b = 0xff; + swf_SetRGB(tag,&rgb); + + swf_GetMatrix(0, &m); + + tag = swf_InsertTag(tag,ST_DEFINEFONT2); + font = Font_Courier(76); + swf_FontSetDefine2(tag, font); + + /* draw 4 edittext fields */ + for(t=0;t<4;t++) + { + tag = swf_InsertTag(tag,ST_DEFINEEDITTEXT); + layout.align = 0; + layout.leftmargin = 0; + layout.rightmargin = 0; + layout.indent = 0; + layout.leading = 0; + + swf_SetU16(tag, t+1);//id + r.xmin = 0; + r.ymin = 0; + r.xmax = width*20/2; + r.ymax = height*20/2; + rgb.r = rgb.g = rgb.b = 0; rgb.a = 255; + + m.tx = (t&1)*width*20/2; + m.ty = (t&2)/2*height*20/2; + + if(t==0) { + /* this is the standard edit field, upper left corner */ + swf_SetEditText(tag, ET_USEOUTLINES|ET_MULTILINE|ET_BORDER, r, + "everything you\ntype in the\nleft box\nalso appears\nin the right\nbox", + &rgb, 0, /*font id*/76, 10*20, &layout, "/:variable1"); + } if (t==1) { + /* this field (upper right corner) mirrors the first field, without being editable */ + swf_SetEditText(tag, ET_NOSELECT|ET_MULTILINE|ET_BORDER|ET_READONLY, r, 0, &rgb, 0, + /*font id*/0, 20*20, &layout, "/:variable1"); + } if (t==2) { + /* another edit field, in brown (lower left corner) */ + rgb.r = 80; + rgb.g = 80; + swf_SetEditText(tag, ET_WORDWRAP|ET_MULTILINE|ET_BORDER, r, longtext, &rgb, 0, + /*font id*/0, 10*20, &layout, "/:variable2"); + } if (t==3) { + m.ty += 40*20; + /* password edit field , lower right corner*/ + swf_SetEditText(tag, ET_PASSWORD, r, 0, &rgb, 0, + /*font id*/0, 24*20, &layout, "/:variable3"); + } + + tag = swf_InsertTag(tag,ST_PLACEOBJECT2); + swf_ObjectPlace(tag, t+1, t, &m, 0, 0); + } + + + tag = swf_InsertTag(tag,ST_DEFINETEXT); + swf_SetU16(tag, 33); //id + swf_SetDefineText(tag, font, &rgb, "Password:", 20); + + tag = swf_InsertTag(tag,ST_PLACEOBJECT2); + m.tx = width/2*20; + m.ty = (height/2+40)*20; + swf_ObjectPlace(tag, 33, t, &m, 0, 0); + + tag = swf_InsertTag(tag,ST_SHOWFRAME); + tag = swf_InsertTag(tag,ST_END); + + f = open("edittext.swf",O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644); + if(swf_WriteSWF(f,&swf)<0) fprintf(stderr,"WriteSWF() failed.\n"); + close(f); + + swf_FreeTags(&swf); + return 0; +} + +/* from "Hitchhikers Guide" by Douglas Adams */ + +char*longtext= +"Another thing that got forgotten was the fact that against all\n" +"probability a sperm whale had suddenly been called into existence\n" +"several miles above the surface of an alien planet.\n" +"\n" +"And since this is not a naturally tenable position for a whale,\n" +"this poor innocent creature had very little time to come to terms\n" +"with its identity as a whale before it then had to come to terms\n" +"with not being a whale any more.\n" +"\n" +"This is a complete record of its thoughts from the moment it\n" +"began its life till the moment it ended it.\n" +"\n" +"Ah ... ! What's happening? it thought.\n" +"\n" +"Er, excuse me, who am I?\n" +"\n" +"Hello?\n" +"Why am I here? What's my purpose in life?\n" +"\n" +"What do I mean by who am I?\n" +"\n" +"Calm down, get a grip now ... oh! this is an interesting\n" +"sensation, what is it? It's a sort of ... yawning, tingling\n" +"sensation in my ... my ... well I suppose I'd better start\n" +"finding names for things if I want to make any headway in what\n" +"for the sake of what I shall call an argument I shall call the\n" +"world, so let's call it my stomach.\n" +"\n" +"Good. Ooooh, it's getting quite strong. And hey, what's about\n" +"this whistling roaring sound going past what I'm suddenly going\n" +"to call my head? Perhaps I can call that ... wind! Is that a good\n" +"name? It'll do ... perhaps I can find a better name for it later\n" +"when I've found out what it's for. It must be something very\n" +"important because there certainly seems to be a hell of a lot of\n" +"it. Hey! What's this thing? This ... let's call it a tail - yeah,\n" +"tail. Hey! I can can really thrash it about pretty good can't I?\n" +"Wow! Wow! That feels great! Doesn't seem to achieve very much but\n" +"I'll probably find out what it's for later on. Now - have I built\n" +"up any coherent picture of things yet?\n" +"\n" +"No. Never mind, hey, this is really exciting, so much to find out\n" +"about, so much to look forward to, I'm quite dizzy with\n" +"anticipation ... Or is it the wind?\n" +"\n" +"There really is a lot of that now isn't it?\n" +"\n" +"And wow! Hey! What's this thing suddenly coming towards me very\n" +"fast? Very very fast. So big and flat and round, it needs a big\n" +"wide sounding name like ... ow ... ound ... round ... ground!\n" +"That's it! That's a good name - ground!\n" +"\n" +"I wonder if it will be friends with me?\n" +"\n" +"And the rest, after a sudden wet thud, was silence.\n" +"\n" +"Curiously enough, the only thing that went through the mind of\n" +"the bowl of petunias as it fell was Oh no, not again. Many people\n" +"have speculated that if we knew exactly why the bowl of petunias\n" +"had thought that we would know a lot more about the nature of the\n" +"universe than we do now.\n"; + +/* the following data was created using makefonts and dumpfont. The command line calls were: + ./makefonts all + ./dumpfont Courier.swf >> edittext.c */ + +#define addGlyph fn5b6e + +void fn5b6e(SWFFONT * f,int i,U16 ascii,U16 advance,U8 * data,U32 bitlen,int xmin,int ymin,int xmax, int ymax) +{ SHAPE * s; + U32 l = (bitlen+7)/8; + + if (FAILED(swf_ShapeNew(&s))) return; + s->data = malloc(l); + if (!s->data) { swf_ShapeFree(s); return; } + + f->glyph2ascii[i] = ascii; + f->ascii2glyph[ascii] = i; + f->glyph[i].advance = advance; + f->glyph[i].shape = s; + s->bitlen = bitlen; + s->bits.fill = 1; + if(f->layout && f->layout->bounds) + { f->layout->bounds[i].xmin = xmin; + f->layout->bounds[i].ymin = ymin; + f->layout->bounds[i].xmax = xmax; + f->layout->bounds[i].ymax = ymax; + } + memcpy(s->data,data,l); +} + +U8 Glyphs_Courier[] = { + 0x00, 0x00, 0x00, 0x92, 0xe6, 0xa0, 0x22, 0x90, + 0x2a, 0xc0, 0xe6, 0x6f, 0xab, 0x8b, 0x8f, 0xa9, + 0xad, 0x41, 0xbe, 0xd2, 0x24, 0xfc, 0xc0, 0xd4, + 0xe6, 0x09, 0x14, 0x64, 0xa0, 0x9c, 0xa6, 0xff, + 0x2a, 0x80, 0x40, 0xa3, 0x73, 0x04, 0x95, 0xd0, + 0x15, 0xa4, 0xae, 0xad, 0x34, 0xf0, 0x47, 0xc2, + 0xe4, 0xc1, 0x0b, 0x8c, 0x41, 0x1a, 0x5a, 0x02, + 0x66, 0x3f, 0x80, 0x9a, 0x49, 0xbd, 0xe9, 0x27, + 0x7e, 0x34, 0xcc, 0x00, 0x00, 0x0a, 0x0b, 0x04, + 0x92, 0xd2, 0x38, 0x88, 0x8f, 0xd4, 0xc0, 0xe9, + 0x46, 0xbf, 0xd3, 0x1a, 0x01, 0x04, 0x5b, 0x71, + 0x11, 0x20, 0x6d, 0xf0, 0x00, 0x00, 0x2c, 0x28, + 0xcb, 0x48, 0xe2, 0x22, 0x3f, 0x53, 0x03, 0xa5, + 0x1a, 0xff, 0x4c, 0x68, 0x04, 0x11, 0x6d, 0xc4, + 0x44, 0x81, 0xb7, 0xc0, 0x00, 0x00, 0x00, 0x0a, + 0x0a, 0xd8, 0x65, 0x30, 0xde, 0xb6, 0x00, 0x4a, + 0xd4, 0x08, 0x1b, 0x10, 0x18, 0x4a, 0x02, 0xcc, + 0xaf, 0xfb, 0xe9, 0xc0, 0x0e, 0x21, 0x04, 0x95, + 0x08, 0xa2, 0xcb, 0xfe, 0x8d, 0x9f, 0xb2, 0xda, + 0x01, 0xf9, 0x97, 0x1f, 0x81, 0xbc, 0xdf, 0x4a, + 0x00, 0x71, 0x07, 0xa4, 0xac, 0xe2, 0x94, 0x06, + 0x52, 0xfb, 0xbb, 0x77, 0xe4, 0xb6, 0x40, 0x7d, + 0x65, 0xc7, 0xe0, 0x6f, 0x37, 0xd7, 0x80, 0x12, + 0xca, 0x02, 0x01, 0x3c, 0xa0, 0x14, 0xb6, 0xff, + 0xbd, 0x38, 0x00, 0xe3, 0xf7, 0x20, 0x9b, 0xe9, + 0xc0, 0x09, 0x65, 0x01, 0x00, 0x9e, 0x50, 0x0a, + 0x5b, 0x7f, 0xde, 0xae, 0x00, 0x71, 0xf8, 0x1b, + 0xed, 0x20, 0x21, 0x28, 0x34, 0xe9, 0x41, 0xca, + 0x94, 0x08, 0x59, 0x7c, 0x41, 0xe8, 0xf3, 0x7a, + 0xd8, 0x01, 0xc7, 0xe2, 0x6f, 0xb4, 0xfc, 0x84, + 0x1a, 0x32, 0x85, 0x44, 0x90, 0x34, 0xa9, 0xc0, + 0x83, 0x97, 0xc4, 0x20, 0x8f, 0x37, 0xa9, 0x80, + 0x12, 0xb5, 0x02, 0x06, 0xc4, 0x00, 0x72, 0x80, + 0xb3, 0x2b, 0xfe, 0xfb, 0x00, 0x03, 0x88, 0x25, + 0x7e, 0x02, 0xb5, 0x75, 0x4c, 0x38, 0xfd, 0xc8, + 0x26, 0xfa, 0x50, 0x03, 0x88, 0x25, 0x7e, 0x6f, + 0x5b, 0x00, 0x00, 0x0a, 0x0b, 0x08, 0xc2, 0xdf, + 0x28, 0xbd, 0x83, 0x2f, 0xc8, 0xec, 0x9b, 0xfd, + 0xe5, 0x5d, 0x0e, 0x71, 0xf0, 0xb1, 0x60, 0x20, + 0x9d, 0x3a, 0x1d, 0x13, 0x06, 0x63, 0x41, 0x12, + 0x49, 0x93, 0x8c, 0x41, 0x97, 0x68, 0xfa, 0x0c, + 0xeb, 0xa8, 0x10, 0x9e, 0x05, 0xee, 0xea, 0x5b, + 0x25, 0xf9, 0x32, 0xe0, 0x29, 0x6b, 0x80, 0x02, + 0xdb, 0x78, 0x01, 0x49, 0x2f, 0xf6, 0x2a, 0x7e, + 0x4a, 0x9c, 0x20, 0x19, 0xfa, 0xc0, 0x5a, 0x99, + 0x05, 0x09, 0xd0, 0x6e, 0x55, 0x02, 0x93, 0x82, + 0xde, 0x00, 0x76, 0xcb, 0xfd, 0xb2, 0x90, 0x12, + 0xa7, 0x00, 0x06, 0x56, 0xf0, 0x04, 0x72, 0x85, + 0x0f, 0xd0, 0x04, 0x70, 0x49, 0xff, 0x57, 0xbc, + 0xf6, 0xf6, 0x0b, 0xb9, 0xf8, 0x7d, 0x2a, 0x1f, + 0x7a, 0x7b, 0x17, 0x97, 0xb1, 0xe1, 0x9b, 0x03, + 0x54, 0x02, 0xb6, 0x70, 0x8d, 0x05, 0xc3, 0xeb, + 0x9d, 0xa0, 0x0f, 0x14, 0x1e, 0xe5, 0x08, 0xb9, + 0x37, 0xe9, 0x53, 0x80, 0x03, 0x2b, 0x68, 0x04, + 0x44, 0xa0, 0x66, 0xd7, 0x07, 0x2d, 0x9f, 0xdf, + 0x5b, 0x4b, 0x67, 0x15, 0xed, 0xd3, 0x64, 0x71, + 0xd7, 0xfc, 0xed, 0x00, 0x98, 0x97, 0xfc, 0x5b, + 0x3e, 0xe5, 0xae, 0x00, 0x0b, 0x6d, 0xa0, 0x0d, + 0xc0, 0x00, 0x0a, 0x0a, 0xd6, 0x96, 0x20, 0x9e, + 0x44, 0x1a, 0xf6, 0x39, 0xa7, 0x0a, 0x38, 0x5c, + 0x01, 0x69, 0xdb, 0x3e, 0x90, 0x9c, 0x92, 0x7f, + 0x84, 0x52, 0x45, 0xe8, 0xc2, 0x00, 0xad, 0x69, + 0x67, 0x09, 0xd2, 0xe1, 0x00, 0x3a, 0x8a, 0x7f, + 0xba, 0x62, 0xda, 0x0e, 0x9e, 0xcf, 0xf3, 0xfa, + 0xd9, 0x67, 0x06, 0x58, 0x12, 0xdf, 0x0c, 0x20, + 0x0b, 0x07, 0x6a, 0xcf, 0x27, 0x8e, 0x05, 0x7c, + 0xce, 0x19, 0xc3, 0x4e, 0x57, 0x30, 0x66, 0x76, + 0xef, 0x9c, 0x2f, 0x1d, 0x9f, 0xd9, 0x1b, 0x8f, + 0x7b, 0x70, 0x80, 0x2c, 0x1d, 0xab, 0x8c, 0x9d, + 0x36, 0x0b, 0x05, 0xa7, 0x67, 0xf8, 0xa6, 0xed, + 0x61, 0x19, 0xec, 0x3f, 0x0f, 0x7d, 0x8a, 0x70, + 0x95, 0x9d, 0x39, 0xf3, 0xc2, 0x00, 0xad, 0xef, + 0x55, 0x09, 0x52, 0xf8, 0xff, 0xa2, 0x5f, 0x97, + 0x31, 0x7a, 0x8f, 0x20, 0xa8, 0xa3, 0xa0, 0x74, + 0x1e, 0x74, 0x58, 0x79, 0x4b, 0x68, 0x58, 0x23, + 0xb2, 0x06, 0xeb, 0x42, 0xc2, 0x83, 0x11, 0x90, + 0x0e, 0xd7, 0x35, 0xf9, 0xc4, 0x00, 0x0a, 0x0a, + 0xd8, 0x90, 0x00, 0xda, 0xe8, 0x01, 0x2b, 0x50, + 0x00, 0x6c, 0xc0, 0x07, 0x28, 0x0b, 0x32, 0xbf, + 0xed, 0xb4, 0x00, 0xdb, 0x95, 0x59, 0x38, 0xfb, + 0x48, 0x2c, 0xae, 0x69, 0x60, 0x09, 0x5a, 0x81, + 0x03, 0x62, 0x00, 0x39, 0x40, 0x59, 0x95, 0xff, + 0x6d, 0x50, 0x04, 0xfe, 0x14, 0x97, 0x0c, 0xe1, + 0xc7, 0x22, 0xa7, 0xa7, 0xd2, 0xdc, 0x41, 0x3c, + 0x79, 0xc1, 0xd6, 0xf4, 0x87, 0xb6, 0x55, 0xa0, + 0x53, 0x99, 0x91, 0x53, 0x15, 0x4b, 0x6a, 0x07, + 0x04, 0xa8, 0xb6, 0x7e, 0xcd, 0x2f, 0xcb, 0x97, + 0xbe, 0x49, 0x98, 0x36, 0x93, 0xa6, 0xc3, 0x25, + 0xbb, 0xb3, 0x0f, 0x69, 0x70, 0x76, 0xbc, 0x02, + 0x79, 0x20, 0x5f, 0xdc, 0xd9, 0x9f, 0xd4, 0x2f, + 0x39, 0x2c, 0xe7, 0x97, 0x12, 0x7f, 0xcd, 0x9a, + 0x01, 0x74, 0x75, 0x01, 0x07, 0xe7, 0x44, 0x00, + 0x0b, 0x18, 0x0d, 0xa7, 0xcc, 0x00, 0xad, 0x52, + 0x75, 0x49, 0xae, 0x9e, 0x65, 0x00, 0xe7, 0xa5, + 0x7a, 0x7e, 0x12, 0xb9, 0xc0, 0x75, 0x35, 0x1f, + 0x4f, 0x89, 0xa4, 0xa5, 0x00, 0x0a, 0x0b, 0x06, + 0x7a, 0xd2, 0x38, 0xee, 0x8f, 0xa4, 0x7c, 0x58, + 0x17, 0x28, 0x56, 0xad, 0x42, 0xc8, 0xd0, 0x49, + 0xcf, 0x21, 0x1b, 0x13, 0x7f, 0x32, 0x45, 0x7b, + 0xb8, 0xde, 0xc0, 0x00, 0x00, 0x0a, 0x0b, 0x0d, + 0xb2, 0xd2, 0x22, 0x90, 0x93, 0x97, 0x70, 0x6b, + 0x8e, 0xe8, 0xc8, 0xd5, 0x6f, 0xe5, 0x38, 0xa0, + 0x03, 0x4c, 0x4c, 0xf5, 0x3e, 0x63, 0xa6, 0x01, + 0x6f, 0xd8, 0x51, 0x42, 0x54, 0xbf, 0x02, 0xdc, + 0x8c, 0x16, 0xd5, 0x28, 0xcb, 0xe9, 0xaf, 0xfe, + 0xcc, 0xa0, 0x01, 0xb2, 0x8d, 0x1a, 0x72, 0x33, + 0x50, 0x16, 0x97, 0xe5, 0xcb, 0x9f, 0x30, 0x80, + 0x00, 0x0a, 0x0b, 0x05, 0x42, 0xd2, 0x25, 0xb4, + 0x13, 0xe2, 0x48, 0xc0, 0xa3, 0x32, 0x83, 0x35, + 0x67, 0xfe, 0xd3, 0x3a, 0x00, 0x34, 0xdf, 0x35, + 0x58, 0xe3, 0xd3, 0x00, 0xa9, 0x41, 0xa4, 0x4a, + 0x12, 0x26, 0x07, 0xd9, 0x49, 0x7a, 0x4b, 0x16, + 0x83, 0x5e, 0xaa, 0x00, 0xec, 0x8a, 0x00, 0x2b, + 0x3b, 0x36, 0xac, 0xa6, 0xc5, 0x9e, 0xea, 0x05, + 0x83, 0xe3, 0x08, 0x00, 0x0a, 0x0a, 0xd1, 0x84, + 0x94, 0xe3, 0x7a, 0x75, 0x91, 0xcb, 0x9a, 0xfc, + 0x37, 0xd1, 0x2d, 0xb0, 0x9f, 0x52, 0x4a, 0x11, + 0x11, 0xc0, 0xd9, 0xd0, 0x2e, 0x28, 0x50, 0xa9, + 0xbe, 0xbc, 0xe0, 0x92, 0xd6, 0x43, 0x26, 0x50, + 0x69, 0xd2, 0x83, 0x8d, 0x61, 0x56, 0x63, 0x4e, + 0x59, 0x1d, 0xea, 0x29, 0x06, 0xf5, 0x23, 0x82, + 0x42, 0xd1, 0x24, 0x68, 0xd0, 0x66, 0x7e, 0x54, + 0x9f, 0x42, 0x5b, 0x93, 0xfc, 0x73, 0xaf, 0x7d, + 0x7a, 0x41, 0xc5, 0x0a, 0xeb, 0x25, 0x57, 0xcf, + 0xfe, 0x19, 0x7e, 0x5d, 0xbd, 0xee, 0x3c, 0x82, + 0x63, 0x8a, 0xc6, 0xcb, 0x8d, 0xf0, 0x2b, 0x71, + 0xff, 0xae, 0xa9, 0x7f, 0xcb, 0xb3, 0xfe, 0x5a, + 0xe0, 0x00, 0xb6, 0xe2, 0x00, 0x22, 0xc0, 0x00, + 0x0a, 0x0a, 0xd4, 0x05, 0xf8, 0xe2, 0xb4, 0x00, + 0x12, 0xb8, 0x02, 0x02, 0xbc, 0xa0, 0x2c, 0xc8, + 0xff, 0xc6, 0x98, 0x00, 0x38, 0x80, 0x13, 0x54, + 0xbf, 0xe5, 0xd9, 0xff, 0x2d, 0x70, 0x00, 0x5b, + 0x71, 0x00, 0x19, 0x6e, 0x34, 0xb0, 0x01, 0x2c, + 0xa0, 0x20, 0x13, 0xca, 0x01, 0x4b, 0x6f, 0xfc, + 0x56, 0xa0, 0x03, 0x88, 0x00, 0xc9, 0x4b, 0xfd, + 0xb2, 0x90, 0x12, 0xa7, 0x00, 0x06, 0x57, 0x10, + 0x02, 0x6e, 0x00, 0x0a, 0x0a, 0x99, 0xeb, 0x7b, + 0x8e, 0xe8, 0xfa, 0x47, 0xc5, 0x81, 0x72, 0x85, + 0x6a, 0xd4, 0x2c, 0x8d, 0x02, 0x9c, 0xf1, 0xa2, + 0xc9, 0x87, 0x32, 0x45, 0x7b, 0xb8, 0xde, 0xc0, + 0x00, 0x00, 0x0a, 0x0a, 0xdf, 0x55, 0xf8, 0x95, + 0xa8, 0x10, 0x36, 0x20, 0x30, 0x94, 0x05, 0x99, + 0x5f, 0xf9, 0xcd, 0xc0, 0x01, 0x2c, 0xa0, 0x20, + 0x13, 0xca, 0x01, 0x4b, 0x6f, 0xfc, 0xd9, 0x20, + 0x00, 0x00, 0x0a, 0x0a, 0xd2, 0x77, 0x18, 0x9a, + 0x00, 0x2b, 0xd9, 0xe2, 0x70, 0x51, 0xe5, 0x00, + 0x0b, 0xd2, 0xa0, 0x13, 0x3f, 0xfb, 0x85, 0xc2, + 0xcd, 0xeb, 0x11, 0x03, 0xed, 0xa6, 0xc0, 0x00, + 0x0a, 0x0b, 0x0f, 0x12, 0xc3, 0xa4, 0x2e, 0xaf, + 0xf6, 0x97, 0xdd, 0xeb, 0xbf, 0x24, 0xaf, 0xfd, + 0x12, 0x8f, 0x48, 0xda, 0xfa, 0xeb, 0x92, 0xb8, + 0x49, 0xaa, 0x80, 0x99, 0x28, 0x54, 0x48, 0xc2, + 0x48, 0xa0, 0x26, 0x5d, 0x19, 0xb0, 0x6a, 0xf5, + 0x28, 0xea, 0x90, 0x00, 0x0a, 0x0a, 0xde, 0xa5, + 0x42, 0xa3, 0xe8, 0x82, 0xa9, 0xcf, 0x9a, 0x8a, + 0x6c, 0x1a, 0xfa, 0x5f, 0x6d, 0xe0, 0x06, 0x45, + 0x00, 0xbb, 0xec, 0xb2, 0x83, 0xd4, 0x2c, 0x9f, + 0x10, 0x31, 0x05, 0x6f, 0x00, 0x4e, 0x01, 0x59, + 0x2c, 0xa9, 0x93, 0x81, 0xe6, 0x66, 0x1b, 0x4c, + 0xe4, 0x4c, 0xd2, 0x00, 0x01, 0x3a, 0x00, 0x00, + 0x44, 0x33, 0x4e, 0x61, 0x4b, 0x81, 0xd9, 0xbb, + 0xc0, 0x0b, 0x29, 0xff, 0x2c, 0xdc, 0xfa, 0x5e, + 0x6b, 0xc6, 0x98, 0x00, 0x39, 0xa0, 0x3f, 0x6f, + 0x25, 0xe7, 0xcf, 0xda, 0x7f, 0x33, 0x3d, 0xe0, + 0x0a, 0x70, 0x00, 0x0a, 0x0b, 0x0a, 0x02, 0xce, + 0x38, 0xd2, 0x03, 0xa4, 0xb4, 0xc6, 0x83, 0x3f, + 0x28, 0x44, 0x07, 0x44, 0x42, 0x83, 0x11, 0x90, + 0x0b, 0xec, 0x4f, 0xed, 0xdc, 0x50, 0x6e, 0xb3, + 0xa8, 0x01, 0x20, 0x57, 0x1b, 0xa8, 0x00, 0x96, + 0x38, 0x10, 0x29, 0xe5, 0x02, 0xa1, 0xb8, 0x0e, + 0x69, 0xf8, 0x00, 0x4a, 0xd4, 0x00, 0x1b, 0x30, + 0x01, 0xca, 0x02, 0xcc, 0xaf, 0xfc, 0x6e, 0x80, + 0x03, 0xa8, 0x00, 0x5c, 0x40, 0x00, 0x0a, 0x0a, + 0x5e, 0xdb, 0x0c, 0xa1, 0x13, 0xa8, 0xaf, 0x0f, + 0xc8, 0x35, 0x0a, 0x35, 0xa5, 0xe9, 0x71, 0x94, + 0x7b, 0xf6, 0x7d, 0x73, 0xef, 0xcf, 0x42, 0x00, + 0xe2, 0x92, 0x33, 0x61, 0xa8, 0xfe, 0x9f, 0xca, + 0x11, 0x02, 0x20, 0x92, 0x9f, 0x02, 0x2e, 0xbc, + 0xe4, 0x49, 0xfb, 0x83, 0xe7, 0x3b, 0xf8, 0x32, + 0x1a, 0x73, 0xce, 0x1f, 0x2f, 0xc1, 0x5d, 0x73, + 0xc7, 0x5c, 0x10, 0xb6, 0xe6, 0xd0, 0x07, 0x8e, + 0x6c, 0x60, 0x00, 0x6f, 0x00, 0x59, 0xa5, 0xff, + 0x2a, 0xc8, 0x09, 0x6b, 0x80, 0x02, 0xdb, 0x68, + 0x02, 0x57, 0x3b, 0x0c, 0x00, 0x00, 0x0a, 0x0a, + 0xd7, 0x65, 0x70, 0x89, 0xb5, 0x3e, 0x75, 0xfe, + 0xa8, 0x17, 0x4a, 0xa3, 0xe3, 0xb9, 0xeb, 0x7f, + 0xae, 0x7a, 0xff, 0xfb, 0x0e, 0x58, 0x9a, 0xf4, + 0xd7, 0xf4, 0x8e, 0x50, 0x68, 0x92, 0x84, 0x8d, + 0x21, 0x3f, 0x24, 0x27, 0xc4, 0x6b, 0x9c, 0xbb, + 0x99, 0x57, 0xff, 0xe7, 0x7f, 0x83, 0xc3, 0x2d, + 0x19, 0xfe, 0xa8, 0x7b, 0xb8, 0xfe, 0x3b, 0x93, + 0x23, 0x9b, 0x5c, 0x4a, 0x2f, 0xf6, 0x59, 0x60, + 0x7f, 0xa7, 0x94, 0x02, 0xa6, 0xc0, 0x28, 0x51, + 0x81, 0xb0, 0x91, 0x05, 0xa3, 0xdf, 0x40, 0xec, + 0xf0, 0x6e, 0x7a, 0x9f, 0xfa, 0xdf, 0x92, 0x8e, + 0x78, 0xc7, 0x62, 0xad, 0x90, 0x96, 0xf0, 0x4f, + 0x88, 0xa6, 0xfc, 0x25, 0x60, 0x31, 0x99, 0xb8, + 0xed, 0x98, 0x42, 0x55, 0x41, 0xd5, 0x7f, 0xa1, + 0x7e, 0xf8, 0x82, 0x6a, 0xc6, 0x7f, 0xbc, 0xaa, + 0x1b, 0x96, 0xc2, 0x00, 0x00, 0x0a, 0x0a, 0xd7, + 0xc6, 0xac, 0xe2, 0x00, 0x20, 0x9b, 0xec, 0x00, + 0x09, 0x65, 0x01, 0x00, 0x9e, 0x50, 0x0a, 0x1b, + 0x00, 0xe2, 0x97, 0x00, 0x12, 0xb5, 0x00, 0x06, + 0xcc, 0x00, 0x72, 0x80, 0xb3, 0x2b, 0xfe, 0xb8, + 0x40, 0x38, 0x80, 0x17, 0xe6, 0xb7, 0xc0, 0x25, + 0x6a, 0x00, 0x0d, 0x98, 0x00, 0xe5, 0x01, 0x5e, + 0x50, 0x1d, 0x70, 0x80, 0x73, 0x00, 0x13, 0x83, + 0x7d, 0x48, 0x01, 0xcf, 0x1c, 0x31, 0x4d, 0xa0, + 0x0b, 0x9c, 0xd1, 0x30, 0x00, 0x05, 0x6b, 0xe3, + 0x2e, 0x71, 0x8a, 0x00, 0x0e, 0x66, 0x82, 0x98, + 0x6b, 0x70, 0x03, 0x98, 0x00, 0x5a, 0x00, 0x00, + 0x0a, 0x0b, 0x05, 0xf2, 0xe3, 0x38, 0xbc, 0x40, + 0x04, 0xae, 0x40, 0x81, 0xaf, 0x2f, 0xfb, 0x31, + 0xff, 0xf3, 0xb9, 0xc0, 0x03, 0x98, 0x00, 0x44, + 0xd2, 0x82, 0x54, 0x90, 0x14, 0x24, 0x21, 0x21, + 0x40, 0x3b, 0x84, 0xaa, 0xb5, 0xaa, 0xe7, 0x32, + 0xbf, 0x3a, 0x88, 0x0d, 0x08, 0x70, 0x1c, 0x09, + 0x23, 0x14, 0x7d, 0x8a, 0x85, 0x8c, 0x0a, 0x4f, + 0x51, 0xff, 0x5b, 0xef, 0x51, 0xce, 0x98, 0xec, + 0x55, 0xb2, 0x12, 0xdb, 0x09, 0xf5, 0x24, 0xdf, + 0xc4, 0x6b, 0xc7, 0xb3, 0xa5, 0x0c, 0x49, 0xe0, + 0x05, 0x0b, 0xff, 0xca, 0x0d, 0xcd, 0x74, 0x7c, + 0xf4, 0xdd, 0x6b, 0xf5, 0xcb, 0x48, 0x05, 0x60, + 0xf3, 0x59, 0x06, 0xd0, 0x14, 0x71, 0xff, 0xa5, + 0xc0, 0x00, 0x0a, 0x0a, 0x96, 0x28, 0x72, 0x2f, + 0xa0, 0xa9, 0x01, 0xa0, 0x2b, 0x64, 0x0e, 0xe0, + 0x73, 0x9f, 0xfd, 0x38, 0x29, 0x5d, 0x27, 0x49, + 0x4b, 0x9b, 0x9e, 0x59, 0x15, 0xf5, 0x50, 0x25, + 0x7b, 0xfd, 0x18, 0xd9, 0x12, 0x34, 0xa1, 0x21, + 0x65, 0x89, 0x51, 0x7c, 0x05, 0x6a, 0x7f, 0x8f, + 0x0a, 0xe3, 0xfa, 0x9e, 0x6e, 0x02, 0xad, 0xa3, + 0x28, 0xca, 0x0b, 0x70, 0x19, 0x55, 0xa4, 0x0a, + 0x23, 0x02, 0xec, 0x08, 0xa8, 0x4f, 0xbe, 0x10, + 0x72, 0x9d, 0xa3, 0xe1, 0xac, 0x6d, 0x1f, 0x8e, + 0x79, 0x6f, 0xef, 0x0e, 0xf1, 0xc2, 0x00, 0xa9, + 0x6e, 0xa2, 0x26, 0x33, 0xa1, 0x1c, 0xdb, 0x8d, + 0x54, 0x5d, 0x26, 0x47, 0xb2, 0x55, 0xea, 0x91, + 0xfe, 0x1f, 0x02, 0x83, 0xa4, 0x18, 0x05, 0xd0, + 0x4a, 0x3e, 0xb4, 0x6b, 0x0d, 0x06, 0x27, 0x98, + 0x7f, 0x35, 0x90, 0x08, 0xb6, 0x3a, 0xa5, 0xfb, + 0xdb, 0xb5, 0x6c, 0x20, 0x00, 0x0a, 0x0b, 0x0d, + 0xc2, 0xef, 0xba, 0xf5, 0xd2, 0x01, 0x47, 0xc7, + 0x81, 0x72, 0x83, 0x4a, 0x94, 0x14, 0xa6, 0xc1, + 0x8d, 0xa9, 0xd4, 0x52, 0xaf, 0xcb, 0x78, 0x02, + 0xe5, 0xce, 0x8e, 0x00, 0x0d, 0xe0, 0x05, 0x24, + 0xbf, 0xdc, 0xa9, 0xff, 0x2a, 0x70, 0x20, 0x63, + 0xed, 0x00, 0xac, 0xe6, 0x91, 0x00, 0x06, 0xb0, + 0x0c, 0x80, 0x0a, 0x0a, 0xd7, 0x75, 0x94, 0x9d, + 0xa7, 0x97, 0xff, 0xd2, 0xe8, 0xf7, 0x2d, 0x7a, + 0xf3, 0xe5, 0xa2, 0xbc, 0x06, 0xfd, 0xc4, 0xa6, + 0x70, 0x02, 0xd5, 0xa4, 0x69, 0x9e, 0x3e, 0x65, + 0xfd, 0xb1, 0x68, 0x08, 0xd4, 0x25, 0x64, 0x1e, + 0xa1, 0x58, 0xf8, 0x82, 0x4a, 0xfa, 0x7f, 0xd4, + 0xea, 0x41, 0x9c, 0xc2, 0x00, 0xb0, 0x96, 0x2e, + 0x0a, 0x77, 0xf0, 0x4c, 0x34, 0xe7, 0x9f, 0xc8, + 0xda, 0x82, 0x05, 0xa7, 0x81, 0x7a, 0xbc, 0xd2, + 0x49, 0xc3, 0x51, 0xb7, 0xf7, 0xb7, 0x08, 0x02, + 0xb4, 0xb1, 0x6f, 0x28, 0x44, 0x81, 0x00, 0x68, + 0xf4, 0xa3, 0xe2, 0x3d, 0xaf, 0x20, 0x62, 0x8b, + 0xc3, 0xe9, 0xf9, 0x30, 0x7a, 0x01, 0xbc, 0x41, + 0x11, 0xfb, 0xb0, 0x80, 0x00, 0x0a, 0x0a, 0xdd, + 0x55, 0x2e, 0x94, 0x13, 0xa0, 0x07, 0x27, 0xff, + 0x32, 0x35, 0x48, 0xc9, 0xed, 0xad, 0x59, 0x20, + 0x7e, 0x4a, 0xc2, 0xb0, 0x09, 0x63, 0x7f, 0xc5, + 0xbe, 0x4b, 0xb5, 0xd4, 0x08, 0x77, 0xa2, 0x5b, + 0xa1, 0x7f, 0xa5, 0x9c, 0x14, 0x3e, 0x46, 0x01, + 0x67, 0x64, 0xff, 0x94, 0xb7, 0x5a, 0x0d, 0xcd, + 0x1f, 0xfe, 0xa9, 0xe9, 0xfd, 0x17, 0x53, 0x43, + 0x7e, 0x0a, 0x2c, 0x50, 0x73, 0xe9, 0x58, 0x28, + 0x06, 0x95, 0x24, 0xb0, 0x20, 0x9d, 0xa6, 0x02, + 0x3c, 0xc3, 0x30, 0x80, 0x2b, 0x73, 0xd3, 0x0a, + 0x6c, 0xc6, 0x0e, 0x42, 0x58, 0xec, 0xcb, 0x2e, + 0x6b, 0x85, 0x0a, 0xb1, 0x99, 0x21, 0x26, 0x20, + 0x28, 0xc6, 0xfe, 0x6f, 0xb6, 0xf8, 0xa0, 0x11, + 0xba, 0x4e, 0xff, 0xae, 0x76, 0x78, 0x04, 0xaa, + 0xfd, 0x8c, 0x49, 0x11, 0xa5, 0x06, 0x28, 0x5a, + 0x9c, 0x20, 0x00, 0x0a, 0x0a, 0xd2, 0x77, 0x18, + 0x9a, 0x00, 0x2b, 0xd9, 0xe2, 0x70, 0x51, 0xe5, + 0x00, 0x0b, 0xd2, 0xa0, 0x13, 0x3f, 0xfb, 0x85, + 0xc2, 0xcd, 0xeb, 0x11, 0x03, 0xed, 0xa6, 0xc0, + 0x01, 0x5a, 0x4e, 0x97, 0x13, 0x40, 0x07, 0x7b, + 0x3e, 0x4e, 0x0a, 0x3d, 0x20, 0x01, 0x5a, 0x54, + 0x02, 0x67, 0xff, 0x60, 0xb8, 0x69, 0xbd, 0x61, + 0x20, 0x7c, 0xb4, 0xd8, 0x00, 0x00, 0x0a, 0x0a, + 0x9a, 0x6b, 0x7b, 0x8e, 0xe8, 0xfa, 0x47, 0xc5, + 0x81, 0x72, 0x85, 0x6a, 0xd4, 0x2c, 0x8d, 0x02, + 0x9c, 0xf1, 0xa2, 0xc9, 0x87, 0x32, 0x45, 0x7b, + 0xb8, 0xde, 0xc0, 0x00, 0x2b, 0x43, 0xd2, 0xe2, + 0x68, 0x00, 0xef, 0x67, 0xc9, 0xc1, 0x47, 0xa4, + 0x00, 0x2b, 0x4a, 0x80, 0x4c, 0xff, 0xec, 0x17, + 0x0d, 0x37, 0xac, 0x24, 0x0f, 0x96, 0x9b, 0x00, + 0x00, 0x0a, 0x0a, 0xc4, 0x85, 0xce, 0xe6, 0xd0, + 0x8e, 0x84, 0x88, 0x14, 0x50, 0x12, 0x27, 0xf9, + 0x76, 0xe5, 0x4a, 0x8c, 0xd6, 0x05, 0xa4, 0x02, + 0xe9, 0xb0, 0xe7, 0x4e, 0xb3, 0xb7, 0x35, 0x8d, + 0x9d, 0xa4, 0x6b, 0x30, 0x29, 0x8c, 0x17, 0xd5, + 0xf2, 0xf5, 0x49, 0x9d, 0xb6, 0xff, 0x1d, 0xc3, + 0x14, 0xf3, 0x97, 0x87, 0x40, 0x00, 0x0a, 0x0b, + 0x10, 0x53, 0x5b, 0x25, 0x6a, 0x04, 0x0d, 0x88, + 0x0c, 0x25, 0x01, 0x66, 0x57, 0xfe, 0x72, 0x20, + 0x00, 0x4b, 0x28, 0x08, 0x04, 0xf2, 0x80, 0x52, + 0xdb, 0xff, 0x36, 0xf0, 0x00, 0x01, 0x62, 0x0a, + 0x74, 0x24, 0xad, 0x40, 0x81, 0xb1, 0x00, 0x1c, + 0xa0, 0x2c, 0xca, 0xff, 0xce, 0x44, 0x00, 0x09, + 0x65, 0x01, 0x00, 0x9e, 0x50, 0x0a, 0x5b, 0x7f, + 0xe6, 0xde, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x10, + 0x83, 0x73, 0xb9, 0xcb, 0xec, 0x61, 0x1c, 0x2f, + 0x6f, 0xc9, 0x60, 0x3b, 0x27, 0x97, 0x1a, 0x3d, + 0x24, 0x09, 0x93, 0xf5, 0x5b, 0x3f, 0x9a, 0xc6, + 0x31, 0x5c, 0xe9, 0xd1, 0x8a, 0x92, 0x53, 0x81, + 0x52, 0x30, 0x30, 0xc8, 0xca, 0x4d, 0x21, 0x07, + 0xa0, 0x2c, 0x48, 0x08, 0x11, 0xa4, 0x0f, 0xb7, + 0x36, 0x89, 0x8c, 0x00, 0x0a, 0x0a, 0xd4, 0x06, + 0x12, 0xa1, 0x65, 0xd9, 0x3e, 0xfc, 0xda, 0x8f, + 0xa2, 0xe2, 0xaa, 0xbf, 0x69, 0x64, 0x00, 0xa0, + 0x22, 0x6b, 0x10, 0xd8, 0xf3, 0x39, 0x31, 0x1a, + 0xe1, 0x63, 0x91, 0x2a, 0x3d, 0xe0, 0x04, 0x44, + 0xbf, 0xd9, 0xa9, 0xfb, 0x2a, 0x70, 0x60, 0x66, + 0xed, 0x00, 0xae, 0x99, 0x7b, 0x45, 0x2f, 0xda, + 0x55, 0xbe, 0x59, 0x00, 0xa1, 0x10, 0x02, 0x41, + 0x83, 0x3e, 0x80, 0x10, 0xa4, 0xaa, 0x08, 0xcd, + 0xe0, 0x04, 0x44, 0xbf, 0xdb, 0x29, 0x01, 0x2a, + 0x70, 0x00, 0x65, 0x6d, 0x00, 0xae, 0x05, 0x68, + 0xf3, 0xab, 0x4d, 0x2a, 0x0b, 0xf6, 0xbf, 0x30, + 0x2a, 0xf3, 0x58, 0x2e, 0xb6, 0x80, 0x26, 0x6e, + 0xfa, 0x08, 0xa3, 0x9b, 0xe2, 0x86, 0x4b, 0xef, + 0x5c, 0xc0, 0x00, 0x00, 0x0a, 0x0a, 0xda, 0x46, + 0xde, 0xda, 0x80, 0x01, 0x2b, 0x5f, 0xbf, 0xe9, + 0xca, 0x03, 0x05, 0xcf, 0x5c, 0xc0, 0x05, 0xda, + 0xa3, 0xe8, 0xb6, 0x2d, 0x8f, 0xb2, 0x8a, 0x60, + 0x20, 0xfb, 0x1e, 0x8e, 0x20, 0x02, 0x8d, 0x3f, + 0xed, 0xac, 0x67, 0x4e, 0x4e, 0x68, 0x4a, 0xac, + 0x3f, 0xb1, 0xa0, 0x08, 0xfc, 0xef, 0xaf, 0x68, + 0x93, 0x35, 0x2f, 0xdb, 0xd7, 0x7e, 0x45, 0x21, + 0x45, 0x26, 0xe1, 0x58, 0x94, 0xfb, 0x81, 0xc5, + 0xd8, 0x05, 0x3d, 0xb4, 0x05, 0xb3, 0xc7, 0x4f, + 0xa8, 0xba, 0x80, 0xa8, 0xfc, 0x40, 0x0b, 0x02, + 0x80, 0x3a, 0x5b, 0x48, 0x3e, 0x79, 0xdb, 0xa0, + 0xd0, 0x8b, 0x7f, 0x68, 0x02, 0xf4, 0x34, 0x61, + 0x45, 0x6e, 0x09, 0xfc, 0xc8, 0x6c, 0xe1, 0x57, + 0x2b, 0xfc, 0x1f, 0x29, 0xa0, 0x0e, 0x3d, 0x69, + 0x09, 0x00, 0x56, 0xd2, 0x34, 0x04, 0x97, 0x89, + 0x68, 0x31, 0x50, 0x50, 0x49, 0x78, 0x19, 0xff, + 0x3d, 0x13, 0xf1, 0xf2, 0xb1, 0x50, 0x0b, 0xe7, + 0xe8, 0x0f, 0xe7, 0xc4, 0x00, 0x5c, 0x00, 0x0a, + 0x0a, 0xda, 0xc6, 0x84, 0xe2, 0x38, 0x25, 0x5b, + 0xed, 0x00, 0x29, 0x65, 0x01, 0x00, 0x9e, 0x50, + 0x0a, 0x1b, 0x00, 0xe2, 0x9c, 0x00, 0x12, 0xb5, + 0x00, 0x06, 0xcc, 0x00, 0x72, 0x80, 0xb3, 0x2b, + 0xfe, 0xdb, 0x60, 0x0e, 0xbc, 0xed, 0x7e, 0x1c, + 0x66, 0x80, 0x02, 0x59, 0x40, 0x40, 0x27, 0x94, + 0x02, 0x96, 0xdf, 0xf7, 0xbc, 0x00, 0x1c, 0xf4, + 0xd3, 0xc0, 0xd7, 0x08, 0x04, 0xb2, 0x80, 0x80, + 0x4f, 0x10, 0x28, 0x24, 0xa1, 0x8f, 0xb0, 0x01, + 0xc5, 0x2e, 0x00, 0x25, 0x6c, 0x00, 0x05, 0x89, + 0x40, 0x59, 0x95, 0xff, 0x7d, 0x88, 0x01, 0xc4, + 0x6c, 0xb5, 0x39, 0xa1, 0x40, 0x00, 0x0a, 0xd9, + 0xd6, 0x34, 0xe3, 0x15, 0x00, 0x1c, 0xc6, 0xc5, + 0xbc, 0xd2, 0xf0, 0x1c, 0xc7, 0x02, 0x44, 0x00, + 0x0a, 0x0a, 0x5e, 0x1b, 0x0d, 0xb3, 0x80, 0x12, + 0xca, 0x02, 0x01, 0x3c, 0xa0, 0x14, 0x36, 0x01, + 0xcd, 0x32, 0x00, 0x0a, 0x12, 0xcf, 0x94, 0x1c, + 0xba, 0x67, 0x00, 0x4e, 0xe0, 0x9a, 0x99, 0xd5, + 0xda, 0x2f, 0xf5, 0xa2, 0x8f, 0x96, 0xf7, 0xb0, + 0xfe, 0xde, 0x77, 0xf0, 0x00, 0x4b, 0x28, 0x08, + 0x04, 0xf2, 0x80, 0x52, 0xdb, 0xfe, 0xd6, 0x40, + 0x0e, 0x60, 0x01, 0xe0, 0x02, 0xb2, 0x81, 0x65, + 0x38, 0x80, 0x12, 0xe7, 0x15, 0x48, 0x00, 0x9d, + 0xe0, 0x0e, 0x0b, 0x2f, 0x28, 0xfa, 0xcc, 0xab, + 0xb4, 0x10, 0xe3, 0x68, 0x00, 0x00, 0xa9, 0x40, + 0xec, 0x38, 0x80, 0x11, 0xa7, 0x14, 0xd0, 0x00, + 0x9d, 0x55, 0xfc, 0x2a, 0x0d, 0x26, 0x72, 0x48, + 0x04, 0x72, 0x9f, 0xd6, 0xce, 0x8b, 0x85, 0x38, + 0xca, 0xc0, 0x00, 0x00, 0x0a, 0x0a, 0xde, 0x04, + 0x0a, 0x9e, 0xdb, 0x7b, 0x9a, 0x80, 0x67, 0x9a, + 0x7f, 0xee, 0xc8, 0xf9, 0xee, 0xa9, 0xbf, 0xbb, + 0x1f, 0x78, 0x01, 0x4d, 0x40, 0x74, 0xe6, 0xba, + 0x41, 0xb4, 0xec, 0x5f, 0xf2, 0x66, 0xeb, 0x32, + 0x65, 0xc7, 0xf7, 0x14, 0xbf, 0xee, 0xdb, 0xfb, + 0x1d, 0x81, 0x92, 0x47, 0x92, 0xd9, 0x71, 0xd9, + 0x77, 0x54, 0xf6, 0xf5, 0x35, 0x13, 0xf7, 0x44, + 0xe3, 0xea, 0x7a, 0x73, 0x66, 0xf0, 0x05, 0xca, + 0x80, 0x9a, 0x78, 0x5d, 0x3d, 0xca, 0x12, 0xe0, + 0x54, 0x30, 0x32, 0xe5, 0x06, 0xb5, 0x2f, 0xd9, + 0x54, 0x83, 0xff, 0x37, 0x78, 0x02, 0x49, 0x2f, + 0xf9, 0x76, 0x40, 0xcb, 0x5f, 0xe8, 0x16, 0x7a, + 0xc0, 0x3a, 0x00, 0x0a, 0x0a, 0x59, 0x1b, 0x0d, + 0x71, 0x00, 0x4b, 0x28, 0x08, 0x04, 0xf2, 0x80, + 0x50, 0xd8, 0x07, 0x16, 0xe0, 0x00, 0xa1, 0xa7, + 0xf5, 0xc2, 0x58, 0xb7, 0x68, 0x04, 0x85, 0x1e, + 0xdc, 0x67, 0x2c, 0xfb, 0x3c, 0x64, 0x80, 0x02, + 0x59, 0x40, 0x40, 0x27, 0x94, 0x02, 0x96, 0xdf, + 0xf5, 0xbc, 0x01, 0xcc, 0x00, 0x3c, 0x00, 0x54, + 0x8c, 0x76, 0x1c, 0xc0, 0x04, 0x40, 0xe2, 0x94, + 0x00, 0x13, 0xa6, 0xbf, 0x86, 0x23, 0x24, 0xe7, + 0xe4, 0x40, 0x19, 0x59, 0xbc, 0x00, 0x92, 0xa3, + 0xd7, 0x5b, 0x2b, 0x70, 0xbb, 0x8d, 0x94, 0x00, + 0x00, 0x0a, 0x0a, 0xca, 0x05, 0xe4, 0xe2, 0x96, + 0x00, 0x1b, 0x40, 0x15, 0xa5, 0xfe, 0xd9, 0x48, + 0x09, 0x53, 0x80, 0x03, 0x2b, 0x88, 0x01, 0x7d, + 0x4b, 0xfe, 0x5d, 0x9f, 0xf2, 0xd7, 0x00, 0x05, + 0xb6, 0xd0, 0x06, 0x0e, 0x36, 0xa0, 0x01, 0xc4, + 0x00, 0x97, 0x39, 0xa5, 0x80, 0x01, 0xbc, 0x00, + 0xc0, 0x94, 0x03, 0x35, 0x1f, 0x65, 0x52, 0x0f, + 0xfc, 0xde, 0x20, 0x05, 0xe1, 0xce, 0x52, 0x00, + 0x09, 0x65, 0x01, 0x00, 0x9e, 0x50, 0x0a, 0x5b, + 0x7f, 0xda, 0xc8, 0x01, 0xcc, 0x00, 0x3c, 0x0d, + 0xb3, 0x80, 0x12, 0xca, 0x02, 0x01, 0x3c, 0xa0, + 0x14, 0x36, 0x01, 0xcd, 0xc2, 0x00, 0x0e, 0x20, + 0x05, 0x81, 0x2f, 0xf9, 0x56, 0x40, 0x4b, 0x5c, + 0x00, 0x16, 0xdb, 0xc0, 0x0f, 0x0e, 0x76, 0x00, + 0x00, 0x71, 0x00, 0x23, 0x40, 0x00, 0x0a, 0x0a, + 0xca, 0x05, 0xe4, 0xe2, 0x96, 0x00, 0x1b, 0x40, + 0x15, 0xa5, 0x00, 0xd9, 0x40, 0x09, 0x54, 0x80, + 0xff, 0x2b, 0x88, 0x01, 0x7d, 0x4a, 0x06, 0x5d, + 0x7f, 0xf2, 0xd8, 0x00, 0x01, 0xb6, 0xd0, 0x06, + 0x0e, 0x36, 0xa0, 0x01, 0xc4, 0x00, 0x97, 0x39, + 0xa8, 0x00, 0x01, 0xbc, 0x00, 0xc0, 0x94, 0x03, + 0x35, 0x1f, 0x65, 0x52, 0x0f, 0xfc, 0xde, 0x20, + 0x05, 0xe1, 0xce, 0x3e, 0x00, 0x09, 0x65, 0x01, + 0x00, 0x9e, 0x50, 0x0a, 0x5b, 0x7f, 0xda, 0xc8, + 0x01, 0xcc, 0x00, 0x3c, 0x0d, 0xb3, 0x80, 0x12, + 0xca, 0x02, 0x01, 0x3c, 0xa0, 0x14, 0x36, 0x01, + 0xc5, 0xd2, 0x00, 0x25, 0x6c, 0x00, 0x05, 0x89, + 0x40, 0xd9, 0x93, 0xff, 0x8d, 0xc4, 0x00, 0x71, + 0x00, 0x23, 0x40, 0x00, 0x0a, 0x0b, 0x10, 0x43, + 0x97, 0x34, 0xb8, 0x04, 0xae, 0x00, 0x80, 0xaf, + 0x28, 0x0b, 0x32, 0x3f, 0xf1, 0x9f, 0x00, 0x09, + 0x65, 0x01, 0x00, 0x9e, 0x50, 0x0a, 0x5b, 0x7f, + 0xe2, 0x8c, 0x00, 0x1c, 0x40, 0x04, 0xba, 0x6a, + 0x52, 0xbb, 0x90, 0xf9, 0xb1, 0x43, 0x6f, 0x7f, + 0xe8, 0x8f, 0x3f, 0x0f, 0xb2, 0x58, 0xde, 0x00, + 0xb7, 0x4e, 0x0a, 0xa0, 0xa3, 0xae, 0xf3, 0x9c, + 0x32, 0xaa, 0x60, 0x1d, 0x09, 0x28, 0x1c, 0x13, + 0x94, 0xd2, 0x02, 0xfa, 0x1e, 0x46, 0x80, 0x37, + 0xf1, 0xa4, 0x28, 0x04, 0xa5, 0x82, 0x81, 0xb9, + 0xbc, 0x01, 0x4e, 0x94, 0x0c, 0xaa, 0xe0, 0xa5, + 0xaf, 0xf4, 0x0b, 0x3d, 0x20, 0x39, 0x3d, 0xe3, + 0x2f, 0x3a, 0x01, 0xcf, 0x37, 0xff, 0xdd, 0xcf, + 0xb3, 0xd8, 0x53, 0xff, 0x77, 0x1e, 0xf0, 0x02, + 0x52, 0x90, 0x36, 0x7c, 0x10, 0x38, 0x18, 0x99, + 0x13, 0xfd, 0x17, 0xca, 0x67, 0xbe, 0x97, 0x2b, + 0xee, 0x20, 0x05, 0x48, 0x00, 0x0a, 0x0a, 0xdb, + 0x85, 0xe4, 0xe2, 0x00, 0x39, 0x9b, 0x63, 0x80, + 0x25, 0x94, 0x04, 0x02, 0x79, 0x40, 0x28, 0x6c, + 0x03, 0x8a, 0x34, 0x00, 0x4a, 0xd0, 0x00, 0x2b, + 0x12, 0x80, 0xb3, 0x2b, 0xfe, 0xda, 0x80, 0x0e, + 0x60, 0x02, 0x20, 0x6b, 0x5c, 0x02, 0x56, 0xa0, + 0x40, 0xd7, 0x94, 0x05, 0x99, 0x5f, 0xf7, 0xc4, + 0x00, 0x12, 0xca, 0x02, 0x01, 0x3c, 0xa0, 0x14, + 0xb6, 0xff, 0xb5, 0xc8, 0x03, 0x88, 0x00, 0xd2, + 0x73, 0xbc, 0x80, 0x03, 0x88, 0x01, 0x2e, 0x6d, + 0x66, 0x00, 0x95, 0xb0, 0x10, 0x15, 0xe5, 0x01, + 0x66, 0x57, 0xfd, 0xf1, 0x00, 0x04, 0xb2, 0x80, + 0x80, 0x4f, 0x28, 0x05, 0x2d, 0xbf, 0xeb, 0x74, + 0x03, 0x98, 0x00, 0x78, 0x1b, 0x67, 0x80, 0x25, + 0x8e, 0x04, 0x0a, 0x79, 0x40, 0xa8, 0x6e, 0x03, + 0x8a, 0x30, 0x00, 0x4a, 0xd8, 0x00, 0x0b, 0x12, + 0x80, 0xb3, 0x2b, 0xfe, 0xd9, 0xa0, 0x0e, 0x20, + 0x04, 0x69, 0xcd, 0x0e, 0x00, 0x00, 0x00, 0x0a, + 0x0b, 0x0a, 0x02, 0xfc, 0x38, 0xa2, 0xc0, 0x04, + 0xae, 0x00, 0x80, 0xaf, 0x28, 0x0b, 0x32, 0x3f, + 0xf3, 0xb0, 0x40, 0x02, 0x59, 0x40, 0x40, 0x27, + 0x94, 0x02, 0x96, 0xdf, 0xf8, 0xa3, 0x00, 0x07, + 0x30, 0x00, 0xf0, 0x38, 0xdd, 0x00, 0x04, 0xb2, + 0x80, 0x80, 0x4f, 0x28, 0x05, 0x0d, 0x80, 0x73, + 0x4f, 0xc0, 0x02, 0x56, 0xe0, 0x00, 0xd8, 0x94, + 0x05, 0x99, 0x1f, 0xf8, 0xdd, 0x40, 0x07, 0x30, + 0x01, 0x10, 0x00, 0x0a, 0x0b, 0x0e, 0x62, 0xfc, + 0x37, 0xb0, 0x00, 0x12, 0xb5, 0x02, 0x06, 0xbc, + 0xa0, 0x2c, 0xca, 0xff, 0xce, 0xd8, 0x00, 0x09, + 0x65, 0x01, 0x00, 0x9e, 0x50, 0x0a, 0x5b, 0x7f, + 0xe2, 0xa0, 0x00, 0x1c, 0xc0, 0x02, 0xc6, 0xa3, + 0xe6, 0x40, 0xaf, 0x40, 0x62, 0x69, 0xb0, 0x09, + 0x9c, 0x39, 0x66, 0x61, 0x9d, 0x4b, 0x88, 0x01, + 0x7e, 0x4b, 0xfe, 0x55, 0x90, 0x12, 0xd7, 0x00, + 0x05, 0xb7, 0x10, 0x01, 0x2a, 0x9d, 0x18, 0x80, + 0x3b, 0x88, 0xa6, 0x3d, 0x12, 0x40, 0x00, 0xa1, + 0x56, 0xf8, 0x02, 0x2a, 0xdb, 0x98, 0x00, 0xa7, + 0x40, 0x00, 0x0a, 0x0a, 0x94, 0x09, 0x1b, 0x7a, + 0xb2, 0xdd, 0x3a, 0xac, 0x5a, 0x6d, 0x66, 0x4e, + 0x42, 0x3c, 0x93, 0x9b, 0x5b, 0xd5, 0xc0, 0x09, + 0x5a, 0x80, 0x03, 0x66, 0x00, 0x39, 0x40, 0x59, + 0x95, 0xff, 0x6c, 0x80, 0x04, 0xfa, 0xb9, 0x2e, + 0xf7, 0x19, 0x3e, 0x72, 0xa5, 0x5a, 0xe2, 0xf1, + 0x6f, 0x27, 0x8d, 0x68, 0x00, 0x4a, 0xe0, 0x08, + 0x0a, 0xf2, 0x80, 0xb3, 0x23, 0xfe, 0xf8, 0xa0, + 0x02, 0x58, 0xe0, 0x40, 0xa7, 0x97, 0xfa, 0x97, + 0x3f, 0xf6, 0xad, 0x00, 0x73, 0xb9, 0x07, 0xbb, + 0x8f, 0xfd, 0x09, 0x6f, 0x50, 0x00, 0x25, 0x6c, + 0x04, 0x05, 0x79, 0x40, 0x59, 0x95, 0xff, 0x8d, + 0x58, 0x00, 0x4b, 0x28, 0x08, 0x04, 0xf2, 0x80, + 0x52, 0xdb, 0xfe, 0xd6, 0x40, 0x0e, 0x60, 0x01, + 0xe0, 0x6d, 0x9c, 0x00, 0x96, 0x50, 0x10, 0x09, + 0xe5, 0x00, 0xa1, 0xb0, 0x0e, 0x2a, 0xa0, 0x01, + 0x2b, 0x60, 0x00, 0x2c, 0x4a, 0x02, 0xcc, 0xaf, + 0xfb, 0xec, 0x00, 0x0e, 0x20, 0x05, 0x2c, 0x00, + 0x0a, 0x0b, 0x07, 0x32, 0xfc, 0x37, 0xae, 0x80, + 0x12, 0xb5, 0x02, 0x06, 0xbc, 0xa0, 0x2c, 0xca, + 0xff, 0xc6, 0x2e, 0x00, 0x25, 0x94, 0x04, 0x02, + 0x79, 0x40, 0x29, 0x6d, 0xff, 0x7b, 0x20, 0x01, + 0xcc, 0x00, 0x3c, 0x0d, 0xf3, 0x80, 0x04, 0xb2, + 0x80, 0x80, 0x4f, 0x28, 0x05, 0x0d, 0x80, 0x73, + 0x70, 0x80, 0x03, 0x88, 0x01, 0x37, 0x4b, 0xfe, + 0x55, 0x90, 0x12, 0xd7, 0x00, 0x05, 0xb7, 0x10, + 0x01, 0x42, 0xe7, 0x79, 0x00, 0x07, 0x30, 0x01, + 0x10, 0x00, 0x0a, 0x0a, 0xd4, 0x66, 0xae, 0xe6, + 0x4e, 0xaa, 0x16, 0x77, 0x03, 0x98, 0x00, 0x78, + 0x1b, 0xed, 0xc0, 0x09, 0x65, 0x01, 0x00, 0x9e, + 0x50, 0x0a, 0x1b, 0x00, 0xe2, 0x95, 0x00, 0x12, + 0xb5, 0x00, 0x06, 0xcc, 0x00, 0x72, 0x80, 0xb3, + 0x2b, 0xfe, 0xdb, 0x80, 0x0e, 0x60, 0x02, 0x20, + 0x6b, 0x6c, 0x02, 0x56, 0xa0, 0x40, 0xd7, 0x94, + 0x05, 0x99, 0x5f, 0xf7, 0xce, 0x00, 0x1c, 0xf6, + 0x62, 0xb2, 0xe7, 0xb1, 0xaa, 0x76, 0xf9, 0xd0, + 0x02, 0x59, 0x40, 0x40, 0x27, 0x84, 0x30, 0xa5, + 0x06, 0x91, 0x9f, 0xfd, 0x6b, 0x80, 0x73, 0x00, + 0x0f, 0x03, 0x5c, 0x00, 0x12, 0xca, 0x02, 0x01, + 0x3c, 0x21, 0x03, 0x28, 0x14, 0xad, 0x40, 0x71, + 0x4a, 0x80, 0x09, 0x5b, 0x80, 0x03, 0x62, 0x50, + 0x16, 0x64, 0x7f, 0xdf, 0x66, 0x00, 0x73, 0x00, + 0x11, 0x03, 0x4a, 0xc0, 0x73, 0x27, 0xca, 0xfb, + 0x6a, 0xe0, 0x00, 0x00, 0x0a, 0x0a, 0xdf, 0x40, + 0x00, 0xea, 0x00, 0x17, 0xe1, 0xb5, 0x18, 0x02, + 0x56, 0xa0, 0x40, 0xd7, 0x94, 0x05, 0x99, 0x5f, + 0xf8, 0xda, 0xc0, 0x04, 0xb1, 0xc0, 0x81, 0x4f, + 0x2f, 0xf5, 0x2e, 0x7f, 0xef, 0x4a, 0x00, 0x39, + 0x80, 0x07, 0x35, 0xce, 0xcf, 0x41, 0x6d, 0xf2, + 0xc0, 0x04, 0xb2, 0x80, 0x80, 0x4f, 0x08, 0x61, + 0x4a, 0x0d, 0x23, 0x3f, 0xfb, 0x59, 0x80, 0x39, + 0x80, 0x07, 0x81, 0xae, 0x10, 0x09, 0x65, 0x01, + 0x00, 0x9e, 0x50, 0x0a, 0x1b, 0x00, 0xe2, 0x96, + 0x00, 0x12, 0xb4, 0x00, 0x0a, 0xc4, 0xa0, 0x2c, + 0xca, 0xff, 0xbe, 0xc4, 0x00, 0xe6, 0x00, 0x23, + 0x07, 0x34, 0xd4, 0xfc, 0x36, 0xb3, 0x00, 0x00, + 0x0a, 0x0b, 0x09, 0x62, 0xe1, 0xa9, 0xc6, 0xa0, + 0xbb, 0xeb, 0xa1, 0xca, 0x41, 0x4a, 0x20, 0x39, + 0x60, 0xc2, 0x93, 0x8f, 0xf3, 0x81, 0x6d, 0xea, + 0xa7, 0xec, 0xdd, 0x8c, 0x67, 0xf5, 0xb0, 0x80, + 0x2c, 0x25, 0x8b, 0xd6, 0xa1, 0x80, 0x0a, 0x02, + 0x47, 0x62, 0x8f, 0x5d, 0xcb, 0xa1, 0x42, 0xfa, + 0x28, 0x3f, 0x4b, 0xd9, 0x8b, 0xa8, 0x09, 0x63, + 0x15, 0xff, 0xd5, 0xc2, 0x00, 0x00, 0x0a, 0x0a, + 0x94, 0x08, 0xd3, 0x8a, 0x20, 0x00, 0x50, 0xbb, + 0xfc, 0x81, 0x0d, 0x99, 0x47, 0xc3, 0x69, 0xd4, + 0x7f, 0x4f, 0x18, 0x80, 0x00, 0x96, 0x50, 0x10, + 0x09, 0xe5, 0x00, 0xa5, 0xb7, 0xfd, 0xac, 0x80, + 0x1c, 0xc0, 0x03, 0xc0, 0xdb, 0x38, 0x01, 0x2c, + 0xa0, 0x20, 0x13, 0xca, 0x01, 0x43, 0x60, 0x1c, + 0x5d, 0x20, 0x02, 0x56, 0xe0, 0x00, 0xd8, 0x94, + 0x05, 0x99, 0x1f, 0xf8, 0xdc, 0x40, 0x07, 0x10, + 0x02, 0x84, 0x05, 0x65, 0x02, 0xf2, 0x71, 0x00, + 0x20, 0xce, 0x29, 0xa0, 0x01, 0x42, 0x10, 0x0a, + 0x03, 0x87, 0x05, 0x1f, 0x09, 0xd1, 0x6e, 0x83, + 0x1c, 0x6e, 0xa0, 0x00, 0x00, 0x0a, 0x0a, 0xd3, + 0x10, 0x20, 0xa4, 0xe2, 0x7c, 0x80, 0x4d, 0x7a, + 0x29, 0xfa, 0xd7, 0x93, 0x1b, 0x7d, 0x2a, 0x71, + 0xa8, 0x2e, 0xfa, 0xe8, 0x72, 0x80, 0x71, 0xd0, + 0x5c, 0x87, 0x4d, 0xf4, 0xc4, 0x34, 0x95, 0x1a, + 0x02, 0x72, 0x83, 0x4e, 0x94, 0x1c, 0x68, 0xfb, + 0x3b, 0x31, 0xa7, 0x8a, 0x07, 0xac, 0xcc, 0xdd, + 0xc7, 0xc0, 0x12, 0xa0, 0xfe, 0x70, 0x24, 0xa8, + 0x42, 0xab, 0x21, 0x2b, 0xa2, 0x47, 0x3f, 0x42, + 0xc3, 0x11, 0xa4, 0x0b, 0x04, 0xa8, 0x3f, 0xa4, + 0xf1, 0x33, 0xe7, 0x00, 0x96, 0x6c, 0xbf, 0x6c, + 0xdd, 0xfb, 0x1d, 0x3f, 0x44, 0xcd, 0x68, 0x5f, + 0x9f, 0xfd, 0x1d, 0xc3, 0x80, 0x47, 0x60, 0x60, + 0x10, 0xe1, 0x44, 0xba, 0xc1, 0x52, 0xe1, 0x2d, + 0x0d, 0xd5, 0xfd, 0xcb, 0x73, 0xe5, 0x90, 0x32, + 0x5f, 0xfe, 0x20, 0xcb, 0x60, 0x1c, 0x21, 0xbb, + 0x5b, 0x2b, 0x01, 0x61, 0x2c, 0x5e, 0xb5, 0x0c, + 0x00, 0x50, 0x12, 0x3b, 0x14, 0x7a, 0xee, 0x55, + 0x0a, 0x17, 0x51, 0x41, 0xfa, 0x7e, 0xcc, 0x5f, + 0x40, 0x4b, 0x18, 0xaf, 0xfe, 0xae, 0x10, 0x00, + 0x0a, 0x0a, 0x94, 0x08, 0x33, 0x8a, 0x24, 0x00, + 0x4c, 0xba, 0x52, 0x98, 0xa3, 0x40, 0xca, 0x35, + 0x12, 0x48, 0x86, 0xd7, 0x20, 0x09, 0x5a, 0x80, + 0x03, 0x66, 0x00, 0x39, 0x40, 0x59, 0x95, 0xff, + 0x5c, 0x20, 0x13, 0xdd, 0xe1, 0xdb, 0x1d, 0x4c, + 0xd9, 0x18, 0x37, 0x1a, 0x14, 0x23, 0x1c, 0xf8, + 0x05, 0x9d, 0xd1, 0xed, 0xdd, 0x35, 0xcf, 0xcb, + 0xc6, 0x10, 0x00, 0x25, 0x94, 0x04, 0x02, 0x79, + 0x40, 0x29, 0x6d, 0xff, 0x6b, 0x20, 0x07, 0x30, + 0x00, 0xf0, 0x36, 0xce, 0x00, 0x4b, 0x28, 0x08, + 0x04, 0xf2, 0x80, 0x50, 0xd8, 0x07, 0x15, 0x50, + 0x00, 0x95, 0xb0, 0x00, 0x16, 0x25, 0x01, 0x66, + 0x57, 0xfd, 0xf6, 0x00, 0x07, 0x10, 0x02, 0x5c, + 0x05, 0x65, 0x02, 0xde, 0x71, 0x00, 0x23, 0x4e, + 0x29, 0xe0, 0x01, 0x3b, 0xe8, 0x2c, 0x22, 0x65, + 0x51, 0xef, 0x1a, 0xd5, 0xc0, 0x2d, 0xbe, 0x24, + 0x00, 0x00, 0x0a, 0x0b, 0x0e, 0x12, 0xfd, 0xa7, + 0xc1, 0x62, 0xea, 0x00, 0x5a, 0x2a, 0xf0, 0x53, + 0xeb, 0x47, 0x27, 0xfe, 0xa1, 0x4c, 0x24, 0xb9, + 0xc9, 0x83, 0xd6, 0x20, 0x7e, 0x75, 0x90, 0x70, + 0x5a, 0x23, 0x89, 0x0d, 0x4a, 0x65, 0xd3, 0x90, + 0x96, 0xfa, 0x3e, 0x23, 0xc2, 0xcc, 0x04, 0xa8, + 0xb4, 0x7e, 0xdf, 0x67, 0x27, 0x97, 0xf5, 0x0b, + 0x40, 0x25, 0xae, 0x00, 0x0b, 0x6d, 0xe0, 0x07, + 0x04, 0xa0, 0x19, 0x22, 0x09, 0x0b, 0x0c, 0x44, + 0xe0, 0xff, 0x29, 0xae, 0xe0, 0x2a, 0x6b, 0x01, + 0x1a, 0x74, 0x12, 0x39, 0xac, 0x01, 0xa1, 0x84, + 0xfa, 0xc1, 0xcb, 0x22, 0x7f, 0xd5, 0x8b, 0x0d, + 0xb2, 0x86, 0x69, 0xa7, 0xe0, 0xf4, 0xe7, 0x3e, + 0x19, 0xeb, 0x9e, 0x8e, 0x37, 0x56, 0x0b, 0xa9, + 0xad, 0x32, 0x40, 0x27, 0xe8, 0x04, 0xf2, 0xc4, + 0x27, 0xf2, 0xa1, 0x03, 0x03, 0x42, 0x53, 0x06, + 0x50, 0x4c, 0x13, 0x00, 0x95, 0x38, 0x00, 0x32, + 0xb7, 0x80, 0x26, 0xd2, 0xff, 0x97, 0x64, 0x0c, + 0xb5, 0xfe, 0x81, 0x67, 0xac, 0x02, 0x60, 0x00, + 0x0a, 0x0a, 0xd4, 0x07, 0xb0, 0xe6, 0x00, 0x22, + 0x07, 0x15, 0x50, 0x00, 0xde, 0x00, 0x47, 0x4a, + 0x09, 0x5a, 0x6f, 0x72, 0xa9, 0x15, 0xfe, 0x86, + 0xf0, 0x04, 0x8b, 0x9c, 0x68, 0x00, 0x1b, 0xc0, + 0x0d, 0xe9, 0x40, 0x2e, 0x51, 0xe2, 0x55, 0x22, + 0x3f, 0xd2, 0xde, 0x00, 0xb9, 0x71, 0x55, 0x00, + 0x0e, 0x60, 0x01, 0xe0, 0x6f, 0x97, 0x00, 0x25, + 0x94, 0x04, 0x02, 0x79, 0x40, 0x28, 0x6c, 0x03, + 0x8b, 0xec, 0x00, 0x4a, 0xd4, 0x00, 0x1b, 0x30, + 0x01, 0xca, 0x02, 0xcc, 0xaf, 0xfb, 0xe5, 0x80, + 0x00, 0x00, 0x0a, 0x0b, 0x0f, 0xa2, 0xfc, 0x36, + 0xa1, 0x00, 0x4a, 0xd4, 0x08, 0x1a, 0xf2, 0x81, + 0xaf, 0x24, 0x0f, 0x1b, 0x58, 0x00, 0x96, 0x47, + 0xf0, 0x4a, 0x65, 0x00, 0xa5, 0xb7, 0xfd, 0xe9, + 0x80, 0x07, 0x30, 0x00, 0xa7, 0xa8, 0xf9, 0x12, + 0x8b, 0x70, 0x1a, 0xa2, 0xda, 0xf9, 0xbe, 0x6b, + 0x63, 0x98, 0x00, 0xac, 0x5b, 0xd3, 0x00, 0x09, + 0x5b, 0x01, 0x01, 0x5e, 0x50, 0x16, 0x65, 0x7f, + 0xe3, 0x6b, 0x00, 0x12, 0xca, 0xfe, 0x01, 0x4c, + 0xa0, 0x14, 0xb6, 0xff, 0xb5, 0x08, 0x03, 0x98, + 0x00, 0x53, 0xd4, 0x03, 0xcb, 0x9a, 0xe4, 0x0f, + 0xd0, 0xb8, 0x7c, 0x21, 0x05, 0x1b, 0xcc, 0x00, + 0x56, 0x20, 0x00, 0x0a, 0x0a, 0xd0, 0xb0, 0x00, + 0xda, 0xe4, 0x01, 0xd4, 0x68, 0xaf, 0xc3, 0x5b, + 0xe0, 0x12, 0xb5, 0x02, 0x06, 0xbc, 0xa0, 0x2b, + 0xca, 0x03, 0xc6, 0xd4, 0x00, 0x25, 0x90, 0x04, + 0x12, 0x79, 0x40, 0x29, 0x6d, 0xff, 0x7a, 0x70, + 0x01, 0xcf, 0x3f, 0x3b, 0xec, 0xb4, 0x1c, 0xf4, + 0x64, 0x44, 0xde, 0x9a, 0xff, 0x4a, 0xd8, 0x08, + 0x0a, 0xf2, 0x80, 0xaf, 0x28, 0x0f, 0x1b, 0x48, + 0x00, 0x96, 0x57, 0xf0, 0x0a, 0x62, 0x05, 0x04, + 0x94, 0x32, 0x06, 0x1f, 0xf5, 0xbe, 0x01, 0xd4, + 0x64, 0x10, 0x40, 0x00, 0x0a, 0x0a, 0x5e, 0x80, + 0x0d, 0xaf, 0xc0, 0x1c, 0xc7, 0x34, 0xe0, 0xe6, + 0x38, 0x19, 0x06, 0xf4, 0x00, 0x03, 0xa8, 0x3e, + 0x5f, 0x86, 0x97, 0x80, 0x95, 0xa8, 0x10, 0x35, + 0xe5, 0x01, 0x66, 0x57, 0xfe, 0x36, 0xa0, 0x01, + 0x2c, 0xa0, 0x20, 0x13, 0xca, 0x01, 0x4b, 0x6f, + 0xfb, 0xd8, 0x00, 0x0e, 0x7e, 0x39, 0xda, 0x73, + 0xe4, 0xd3, 0xc3, 0x6c, 0x20, 0x07, 0x3e, 0x40, + 0xc4, 0x39, 0xf9, 0x08, 0x9d, 0xbd, 0x75, 0xfe, + 0x95, 0xc0, 0x10, 0x15, 0xe5, 0x01, 0x66, 0x47, + 0xfe, 0x36, 0xb0, 0x01, 0x2c, 0xa0, 0x20, 0x13, + 0xc2, 0x18, 0x52, 0x83, 0x48, 0xcf, 0xfe, 0x97, + 0x80, 0xea, 0x0f, 0x08, 0x20, 0x00, 0x0a, 0x0a, + 0xd4, 0x55, 0xc0, 0xe2, 0xb3, 0x46, 0x1a, 0x5e, + 0x02, 0x56, 0xa0, 0x40, 0xd7, 0x94, 0x05, 0x79, + 0x40, 0x77, 0xc8, 0x80, 0x12, 0xca, 0x02, 0x01, + 0x3c, 0xa0, 0x14, 0xb6, 0xff, 0xb5, 0x68, 0x03, + 0x8d, 0x9c, 0xc7, 0x71, 0xb2, 0xa7, 0x4d, 0xaa, + 0xdf, 0xd2, 0xb6, 0x02, 0x02, 0xbc, 0xa0, 0x2c, + 0xca, 0xff, 0xbe, 0x48, 0x00, 0x96, 0x50, 0x10, + 0x09, 0xe5, 0x00, 0xa5, 0xb7, 0xfd, 0x2f, 0x01, + 0xc5, 0x66, 0x74, 0x38, 0xd1, 0x0f, 0x86, 0xbb, + 0xc0, 0x25, 0x94, 0x04, 0x02, 0x79, 0x40, 0x28, + 0x6c, 0x03, 0x8a, 0x0c, 0x00, 0x4a, 0xd8, 0x00, + 0x0b, 0x12, 0x80, 0xb3, 0x2b, 0xfe, 0xd8, 0x00, + 0x0e, 0x2a, 0x44, 0xa5, 0xc5, 0x4a, 0x6b, 0x36, + 0xc2, 0x01, 0x4b, 0x28, 0x08, 0x04, 0xf2, 0x80, + 0x50, 0xd8, 0x07, 0x14, 0x20, 0x00, 0x95, 0xa8, + 0x00, 0x36, 0x60, 0x03, 0x94, 0x05, 0x99, 0x5f, + 0xf5, 0xde, 0x01, 0xc6, 0x82, 0x84, 0x00, 0x0a, + 0x0a, 0xd4, 0x06, 0x04, 0xe6, 0x59, 0x2f, 0x66, + 0xb6, 0x00, 0x25, 0x66, 0x00, 0x1d, 0x89, 0x7f, + 0x5a, 0x99, 0xfb, 0x7c, 0x90, 0x01, 0x2c, 0x70, + 0x20, 0x53, 0xcb, 0xfd, 0x4b, 0x9f, 0xfb, 0x54, + 0x00, 0x38, 0xda, 0x8e, 0x17, 0x1b, 0x4a, 0x40, + 0xda, 0x99, 0xfd, 0x2b, 0x60, 0x20, 0x2b, 0xca, + 0x02, 0xcc, 0xaf, 0xfb, 0xe4, 0x40, 0x09, 0x65, + 0x01, 0x00, 0x9e, 0x50, 0x0a, 0x5b, 0x7f, 0xd6, + 0xc0, 0x07, 0x32, 0xc8, 0x85, 0x38, 0x80, 0x0d, + 0x66, 0xf9, 0x80, 0x02, 0x59, 0x40, 0x40, 0x27, + 0x94, 0x02, 0x86, 0xc0, 0x38, 0xbe, 0xc0, 0x04, + 0xad, 0x40, 0x01, 0xb3, 0x00, 0x1c, 0xa0, 0x2c, + 0xca, 0xff, 0xbe, 0x54, 0x00, 0xe2, 0x00, 0x4a, + 0x80, 0x00, 0x0a, 0x0a, 0xdf, 0x40, 0x00, 0xe2, + 0x00, 0x52, 0x92, 0x81, 0x95, 0x5c, 0x04, 0xb5, + 0xc0, 0x01, 0x6d, 0xc4, 0x00, 0x47, 0x39, 0xd8, + 0x00, 0x01, 0x9c, 0x16, 0xe6, 0xa6, 0xa3, 0x46, + 0xd0, 0x09, 0x2e, 0x74, 0xf8, 0x00, 0x71, 0x00, + 0x13, 0x89, 0x7f, 0xb9, 0x53, 0xfe, 0x54, 0xe0, + 0x40, 0xc7, 0xde, 0x00, 0x8c, 0x73, 0x43, 0xc0, + 0x03, 0x18, 0x5c, 0xeb, 0x83, 0x98, 0xda, 0x00, + 0xed, 0xcd, 0x8d, 0x00, 0x00, 0x00, 0x0a, 0x0b, + 0x0a, 0x02, 0xe3, 0x37, 0xb1, 0x00, 0x12, 0xb5, + 0x02, 0x06, 0xbc, 0xa0, 0x2c, 0xca, 0xff, 0xc6, + 0xec, 0x00, 0x3a, 0x80, 0x02, 0xda, 0x71, 0x45, + 0x00, 0x09, 0x5a, 0x81, 0x03, 0x5e, 0x50, 0x16, + 0x25, 0x00, 0xdf, 0x3c, 0x00, 0x75, 0x00, 0x0a, + 0xec, 0x00, 0x0a, 0x0b, 0x04, 0xda, 0xbb, 0x23, + 0xcc, 0xf3, 0x89, 0x35, 0xc6, 0xf0, 0x25, 0xb4, + 0x13, 0xe2, 0x29, 0x3f, 0x28, 0xb5, 0xba, 0x94, + 0x72, 0xb8, 0x46, 0x55, 0x99, 0x12, 0x18, 0x92, + 0xbf, 0xca, 0x8f, 0xe0, 0x5b, 0xd2, 0x03, 0xa6, + 0xb6, 0x75, 0xd7, 0x2a, 0x90, 0x00, 0x0a, 0x0a, + 0xd1, 0x80, 0xa0, 0xdf, 0x3c, 0x00, 0x4b, 0x2b, + 0xf8, 0x05, 0x32, 0x80, 0x4e, 0xd8, 0x0f, 0x14, + 0x50, 0x00, 0xea, 0x00, 0x14, 0x99, 0xc6, 0xec, + 0x00, 0x25, 0x95, 0xfc, 0x02, 0x99, 0x40, 0x28, + 0x6c, 0x03, 0x7b, 0x10, 0x01, 0xd4, 0x00, 0x14, + 0x50, 0x00, 0x0a, 0x0b, 0x09, 0x62, 0xcc, 0xb8, + 0xd3, 0x8d, 0xf4, 0x96, 0x2a, 0x11, 0xf2, 0x83, + 0x4a, 0x94, 0x1c, 0x6d, 0x0a, 0xef, 0x19, 0xf4, + 0x9a, 0x71, 0x49, 0xa8, 0xee, 0x29, 0x32, 0xe5, + 0x1a, 0x18, 0x73, 0x46, 0xb4, 0xbb, 0xf2, 0xa4, + 0xfa, 0x12, 0xdc, 0x80, 0x63, 0x75, 0x7c, 0x69, + 0xc9, 0x08, 0x00, 0x0a, 0x0b, 0x13, 0x20, 0x28, + 0x3a, 0xd9, 0x00, 0x00, 0x6d, 0x00, 0x50, 0xea, + 0x9c, 0x00, 0x01, 0xb4, 0x02, 0xc0, 0x00, 0x0a, + 0x0b, 0x0c, 0x4a, 0xd2, 0x38, 0xde, 0xc0, 0x07, + 0x14, 0x89, 0xde, 0x8d, 0x0f, 0x42, 0x64, 0x4d, + 0x66, 0xfe, 0x95, 0xaf, 0xb0, 0xb4, 0x63, 0xfd, + 0xbb, 0x6e, 0x3b, 0xa4, 0x7c, 0x00, 0x0a, 0x0a, + 0xda, 0x40, 0x00, 0xde, 0xba, 0x00, 0x4a, 0xd8, + 0x00, 0x0b, 0x30, 0x01, 0xca, 0x02, 0xcc, 0xaf, + 0xfb, 0x65, 0x80, 0x39, 0x80, 0x0b, 0xd1, 0x47, + 0xd5, 0x8c, 0x5a, 0x9f, 0x64, 0xfa, 0x60, 0x15, + 0xe4, 0x47, 0x2d, 0x21, 0x95, 0x47, 0xcb, 0x78, + 0x78, 0x04, 0x32, 0x84, 0x4a, 0x88, 0x1c, 0x67, + 0x03, 0x79, 0x3a, 0xdf, 0x88, 0x47, 0xfd, 0x46, + 0xff, 0x3c, 0x13, 0xba, 0x41, 0xa0, 0xf4, 0xfe, + 0xf0, 0x02, 0x22, 0x69, 0x1e, 0x2b, 0x4f, 0xa9, + 0x6b, 0xfc, 0xa4, 0x02, 0x89, 0xbc, 0x12, 0xf9, + 0xd1, 0x6a, 0x01, 0x23, 0xc9, 0x2a, 0x03, 0xa7, + 0x57, 0x00, 0x52, 0xd8, 0x99, 0x1c, 0xa9, 0xc9, + 0xb7, 0x81, 0x10, 0xc0, 0xad, 0xa4, 0x72, 0x09, + 0xaa, 0xd4, 0x6c, 0x4a, 0xa6, 0x99, 0x37, 0x89, + 0xfe, 0x9e, 0x47, 0xf7, 0xf9, 0xd6, 0xe8, 0x05, + 0xb3, 0x55, 0x53, 0xf1, 0x95, 0x20, 0x14, 0xe0, + 0xe6, 0x65, 0x0b, 0x52, 0x15, 0xde, 0x00, 0x5a, + 0x00, 0x0a, 0x0b, 0x04, 0x62, 0xcf, 0x37, 0xd2, + 0x80, 0x12, 0xc8, 0x03, 0xf9, 0x3c, 0xa0, 0x14, + 0xb6, 0xff, 0xb5, 0xa8, 0x03, 0xa8, 0x00, 0x21, + 0x26, 0xd9, 0xa0, 0x09, 0x64, 0x01, 0xfc, 0x9e, + 0x50, 0x0a, 0x1b, 0x00, 0xde, 0xba, 0x00, 0x6f, + 0x00, 0x54, 0x27, 0x48, 0xb4, 0x1b, 0xff, 0xfa, + 0x18, 0xcf, 0x6c, 0x24, 0x98, 0xa8, 0xf7, 0xe6, + 0x69, 0xc7, 0xda, 0x9e, 0x4a, 0x00, 0xb6, 0xb5, + 0x39, 0xff, 0xeb, 0x98, 0x0a, 0xd4, 0x24, 0xec, + 0xa1, 0x48, 0x08, 0x41, 0xc5, 0x66, 0x8f, 0x7d, + 0x48, 0xaf, 0x42, 0x2a, 0x2b, 0x5f, 0x83, 0xdf, + 0xac, 0x28, 0x08, 0x6a, 0xf5, 0x2f, 0xdd, 0xc2, + 0x00, 0x00, 0x0a, 0x0a, 0xdd, 0x65, 0x10, 0x9f, + 0x05, 0x90, 0xa3, 0x7f, 0x28, 0x93, 0x42, 0x0f, + 0x7d, 0xac, 0xa0, 0x20, 0x67, 0x1a, 0xa0, 0x72, + 0x76, 0x67, 0xf5, 0x41, 0x95, 0x99, 0x5b, 0x14, + 0x0b, 0x66, 0x5f, 0x97, 0xaf, 0x7c, 0x8e, 0xe0, + 0xc9, 0x23, 0xc1, 0x28, 0xc9, 0xec, 0x89, 0x19, + 0x30, 0x06, 0x8a, 0x77, 0xe9, 0xf9, 0x6a, 0xda, + 0x01, 0xaa, 0x79, 0x64, 0xfa, 0x28, 0x45, 0xc1, + 0x40, 0x9c, 0xb2, 0x94, 0x1b, 0x24, 0xbf, 0xa5, + 0x4e, 0x00, 0x0c, 0xad, 0xe0, 0x0a, 0x54, 0xbf, + 0xe2, 0xd9, 0xfb, 0x2d, 0x70, 0x60, 0x5d, 0xe9, + 0x01, 0xa0, 0x00, 0x0a, 0x0b, 0x0f, 0xa2, 0xcf, + 0x37, 0xd1, 0x80, 0x12, 0xca, 0x02, 0x01, 0x3c, + 0xa0, 0x14, 0xb6, 0xff, 0xb5, 0xa8, 0x03, 0x88, + 0x00, 0xf3, 0x4f, 0x72, 0x95, 0xc9, 0x3f, 0xf4, + 0x4e, 0x41, 0x57, 0xb0, 0xcd, 0x50, 0x14, 0x33, + 0x2c, 0x70, 0x4d, 0x23, 0x80, 0x37, 0xec, 0xeb, + 0x6f, 0x49, 0xe6, 0x93, 0xbc, 0x08, 0xb2, 0xde, + 0xba, 0x00, 0x4a, 0xd8, 0x00, 0x0b, 0x30, 0x01, + 0xca, 0x02, 0xcc, 0xaf, 0xfb, 0x65, 0x80, 0x3a, + 0x80, 0x05, 0xc6, 0x02, 0xb4, 0x69, 0x3b, 0x28, + 0x52, 0x42, 0x00, 0x6d, 0x58, 0xa3, 0xe2, 0x53, + 0x2b, 0xc0, 0x82, 0x8a, 0xcf, 0xe1, 0xf7, 0xea, + 0xfa, 0x02, 0x1a, 0xbd, 0x4b, 0xf7, 0x70, 0x80, + 0x00, 0x0a, 0x0b, 0x10, 0x43, 0x9c, 0x26, 0x04, + 0x8c, 0xda, 0xb2, 0xa3, 0x86, 0xbe, 0xed, 0x2f, + 0xce, 0x89, 0x70, 0x23, 0xf7, 0x18, 0xda, 0x02, + 0x76, 0xb5, 0xbd, 0x09, 0xe5, 0x6b, 0xfd, 0xcf, + 0x7a, 0x11, 0x1f, 0x28, 0x27, 0xe7, 0x25, 0xf9, + 0x72, 0xf7, 0xc8, 0x60, 0x86, 0x3b, 0x0a, 0x4b, + 0x9f, 0x38, 0x4b, 0xb2, 0x86, 0xe5, 0x9e, 0x22, + 0x90, 0x0a, 0x2a, 0x9f, 0xbf, 0xc3, 0xac, 0xf9, + 0xb4, 0x0f, 0xfc, 0x0a, 0x8d, 0x08, 0x82, 0x81, + 0x12, 0xdc, 0x4c, 0xbf, 0x0a, 0x13, 0x40, 0x44, + 0x42, 0x48, 0x79, 0xd1, 0x40, 0x04, 0x00, 0x0a, + 0x0a, 0xd0, 0xe5, 0x08, 0xe2, 0xbe, 0x00, 0x12, + 0xb5, 0x02, 0x06, 0xc4, 0x06, 0x12, 0x80, 0xb3, + 0x2b, 0xff, 0x1a, 0x10, 0x00, 0xda, 0x01, 0x19, + 0x38, 0x36, 0xb2, 0xd3, 0xf7, 0xca, 0xa4, 0x13, + 0xb1, 0x92, 0xa9, 0x10, 0x8c, 0x24, 0xce, 0x81, + 0xfd, 0xff, 0xb0, 0x02, 0x4a, 0x9f, 0xb8, 0x3a, + 0x72, 0x80, 0xc7, 0x73, 0xbc, 0xd8, 0xde, 0xd4, + 0xbf, 0x13, 0x5b, 0x7c, 0xe4, 0xff, 0xd1, 0x6f, + 0x82, 0xff, 0x69, 0xe3, 0xb4, 0x01, 0xd3, 0x7d, + 0x40, 0x01, 0x2c, 0xa0, 0x20, 0x13, 0xca, 0x01, + 0x4b, 0x6f, 0xfb, 0xd6, 0x00, 0x0e, 0x60, 0x01, + 0x54, 0x6f, 0x9e, 0x00, 0x25, 0x94, 0x04, 0x02, + 0x79, 0x40, 0x28, 0x6c, 0x03, 0x9a, 0x7a, 0x00, + 0x12, 0xb4, 0x00, 0x0a, 0xc4, 0xa0, 0x2c, 0xca, + 0xff, 0xc6, 0x9a, 0x00, 0x39, 0x80, 0x0a, 0xb0, + 0x00, 0x0a, 0x0a, 0xdb, 0x85, 0x64, 0x9e, 0xff, + 0x38, 0x95, 0x80, 0x28, 0xa1, 0x42, 0x7f, 0x65, + 0x83, 0xa0, 0x27, 0x60, 0x57, 0xb0, 0x96, 0x76, + 0x90, 0x09, 0x05, 0x3c, 0xe2, 0x01, 0x20, 0x53, + 0xfb, 0x1c, 0xd2, 0x00, 0xd6, 0xf8, 0xc0, 0x02, + 0x59, 0x40, 0x00, 0x28, 0x94, 0x02, 0x96, 0xdf, + 0xf7, 0xb9, 0x00, 0x13, 0xa4, 0x3f, 0xa6, 0x4c, + 0x7c, 0xca, 0xf4, 0xbf, 0xb1, 0x7c, 0xc0, 0x04, + 0xd0, 0xda, 0xdc, 0x01, 0x2b, 0x40, 0x3f, 0xab, + 0xca, 0x02, 0xcc, 0xaf, 0xfb, 0xe8, 0xc0, 0x0d, + 0xe0, 0x05, 0x60, 0x2b, 0x44, 0x13, 0xb2, 0x84, + 0xd8, 0x1e, 0x06, 0x94, 0x0a, 0x3e, 0x34, 0xd6, + 0xcd, 0x07, 0x68, 0xb2, 0x3e, 0x4f, 0x82, 0xc6, + 0xa0, 0x1f, 0xb1, 0x93, 0x9f, 0x83, 0x08, 0x00, + 0x0a, 0x0b, 0x05, 0x02, 0xcf, 0x37, 0xd3, 0x00, + 0x12, 0xca, 0x02, 0x01, 0x3c, 0xa0, 0x14, 0xb6, + 0xff, 0xb5, 0x90, 0x03, 0xa8, 0x00, 0x21, 0x26, + 0xda, 0xc0, 0x09, 0x65, 0x01, 0x00, 0x9e, 0x50, + 0x2a, 0x1a, 0x80, 0xe2, 0x84, 0x00, 0x12, 0xb7, + 0x00, 0x06, 0xc4, 0xa0, 0x2c, 0xc8, 0xff, 0xb6, + 0x70, 0x03, 0x88, 0x01, 0x00, 0x6b, 0x41, 0x9a, + 0x64, 0xaa, 0x53, 0x9d, 0x99, 0x8f, 0x75, 0xd5, + 0x00, 0x66, 0x69, 0x02, 0x39, 0x35, 0x89, 0x09, + 0x0e, 0x64, 0xe3, 0xd0, 0x45, 0xbe, 0x20, 0x03, + 0xe1, 0xb6, 0x80, 0x02, 0x59, 0x40, 0x40, 0x27, + 0x94, 0x02, 0x86, 0xc0, 0x38, 0xa0, 0xc0, 0x04, + 0xae, 0x00, 0x00, 0xb1, 0x28, 0x0b, 0x32, 0x3f, + 0xed, 0xaa, 0x00, 0xe2, 0x00, 0x41, 0x54, 0x7d, + 0x57, 0xc5, 0xa9, 0xf5, 0x4f, 0x7b, 0xff, 0xe5, + 0x0c, 0x32, 0xdb, 0x43, 0x69, 0x6f, 0x3f, 0xfd, + 0x7c, 0x80, 0x0a, 0x0a, 0xd4, 0x04, 0xb8, 0xe3, + 0x61, 0x00, 0x12, 0xca, 0x02, 0x01, 0x3c, 0xa0, + 0x14, 0xb6, 0xff, 0xbd, 0xdc, 0x00, 0xe6, 0x00, + 0x15, 0x47, 0x1a, 0xf8, 0x00, 0x96, 0x50, 0x10, + 0x09, 0xe5, 0x00, 0xa1, 0xb0, 0x0e, 0x6b, 0x48, + 0x00, 0x4a, 0xdc, 0x00, 0x1b, 0x12, 0x80, 0xb3, + 0x23, 0xff, 0x1b, 0x00, 0x00, 0xe6, 0x00, 0x28, + 0x40, 0x2c, 0x28, 0x0b, 0x26, 0xdb, 0x10, 0x01, + 0xbc, 0x00, 0xc8, 0xda, 0xf0, 0x01, 0xbc, 0x01, + 0x38, 0x00, 0x0a, 0x0a, 0xda, 0x45, 0x08, 0xe6, + 0x00, 0x19, 0x84, 0xfe, 0xd7, 0x04, 0x9c, 0x29, + 0xbe, 0x00, 0x00, 0x96, 0x50, 0x00, 0x0a, 0x25, + 0x00, 0xa5, 0xb7, 0xfe, 0x28, 0x10, 0x01, 0x42, + 0x4b, 0xf4, 0x82, 0xb6, 0x9f, 0x30, 0x01, 0x20, + 0x39, 0xdc, 0x80, 0x01, 0x2c, 0xa0, 0x20, 0x13, + 0xca, 0x01, 0x4b, 0x6f, 0xfc, 0x5e, 0x80, 0x00, + 0x16, 0x19, 0xa5, 0x93, 0x6d, 0x88, 0x00, 0xde, + 0x00, 0x64, 0x6d, 0x78, 0x00, 0xde, 0x00, 0x9c, + 0x00, 0x0a, 0x0a, 0x96, 0x8a, 0x63, 0x6b, 0x35, + 0x97, 0x15, 0xa1, 0x64, 0xd7, 0x20, 0x14, 0xb2, + 0x80, 0x80, 0x4f, 0x28, 0x05, 0x0d, 0x80, 0x71, + 0x41, 0x80, 0x09, 0x5a, 0x80, 0x03, 0x66, 0x00, + 0x39, 0x40, 0x59, 0x95, 0xff, 0x6d, 0x30, 0x07, + 0x19, 0x8a, 0x66, 0xe2, 0x9d, 0x5e, 0x5b, 0x57, + 0x80, 0x25, 0x6a, 0x04, 0x0d, 0x88, 0x0c, 0x25, + 0x01, 0x66, 0x57, 0xfe, 0x37, 0xe0, 0x01, 0x2c, + 0xa0, 0x20, 0x13, 0xca, 0x01, 0x4b, 0x6f, 0xfa, + 0xd6, 0x00, 0xe3, 0x50, 0x25, 0xdc, 0xff, 0xe5, + 0x06, 0xdf, 0x46, 0x00, 0x4b, 0x28, 0x08, 0x04, + 0xf2, 0x80, 0x52, 0xdb, 0xfe, 0xd6, 0xa0, 0x0e, + 0xa0, 0x00, 0x84, 0x9b, 0x67, 0x00, 0x25, 0x8e, + 0x07, 0xea, 0x79, 0x40, 0x28, 0x6c, 0x03, 0x7a, + 0xe8, 0x01, 0xc4, 0x00, 0xa6, 0x00, 0x0a, 0x0b, + 0x0a, 0x02, 0xcf, 0x38, 0xd8, 0x80, 0x04, 0xb2, + 0x80, 0x80, 0x4f, 0x28, 0x05, 0x2d, 0xbf, 0xef, + 0x76, 0x00, 0x3a, 0x80, 0x02, 0x12, 0x71, 0xaf, + 0x80, 0x09, 0x65, 0x01, 0x00, 0x9e, 0x50, 0x0a, + 0x1b, 0x00, 0xe6, 0xb4, 0x80, 0x04, 0xad, 0xc0, + 0x01, 0xb1, 0x28, 0x0b, 0x32, 0x3f, 0xf1, 0xb0, + 0x00, 0x0e, 0xa0, 0x01, 0x71, 0x80, 0x00, 0x0a, + 0x0a, 0xc6, 0xe4, 0xb8, 0xdf, 0x6e, 0x00, 0x4b, + 0x28, 0x08, 0x04, 0xf1, 0x02, 0x82, 0x4a, 0x19, + 0x03, 0x0f, 0xfb, 0x50, 0x80, 0x39, 0x80, 0x05, + 0x51, 0xae, 0x00, 0x09, 0x64, 0x81, 0xfe, 0x9e, + 0x50, 0x0a, 0x1a, 0x00, 0xde, 0xdc, 0x00, 0x4a, + 0xd0, 0x00, 0x2b, 0x12, 0x80, 0xb3, 0x2b, 0xfe, + 0xdb, 0x80, 0x0e, 0x60, 0x02, 0xf4, 0x4e, 0x59, + 0xbc, 0x14, 0xbc, 0x72, 0x2b, 0xca, 0xc0, 0x4e, + 0x72, 0x0a, 0x03, 0x11, 0x1c, 0xc0, 0x02, 0x78, + 0xde, 0x98, 0x00, 0x4a, 0xd4, 0x00, 0x1b, 0x30, + 0x01, 0xca, 0x02, 0xcc, 0xaf, 0xfb, 0x6e, 0x00, + 0x39, 0x80, 0x0b, 0xd1, 0x32, 0x1c, 0xc1, 0xee, + 0xc4, 0xaa, 0x72, 0x2b, 0x01, 0x39, 0xd0, 0x24, + 0x0c, 0x42, 0x73, 0x00, 0x09, 0xfb, 0x7a, 0x60, + 0x01, 0x2b, 0x50, 0x00, 0x6c, 0xc0, 0x07, 0x28, + 0x0b, 0x32, 0xbf, 0xed, 0xb8, 0x00, 0xe6, 0x00, + 0x2e, 0x54, 0xff, 0x09, 0xcd, 0x0b, 0xd3, 0x35, + 0xb8, 0x05, 0xf1, 0xac, 0xb4, 0xd1, 0xd2, 0x79, + 0x3f, 0x02, 0xdd, 0x82, 0xff, 0x4d, 0x49, 0xff, + 0x74, 0x9b, 0x2e, 0x73, 0x79, 0xd1, 0xed, 0xfe, + 0x92, 0x00, 0x0a, 0x0a, 0xca, 0xa4, 0xb8, 0xdf, + 0x6e, 0x00, 0x4b, 0x28, 0x08, 0x04, 0xf2, 0x80, + 0x52, 0xdb, 0xfe, 0xd4, 0x20, 0x0e, 0x60, 0x01, + 0x54, 0x6d, 0x9e, 0x00, 0x96, 0x38, 0x10, 0x29, + 0xe5, 0xfe, 0xa1, 0xc8, 0x0e, 0x28, 0x30, 0x01, + 0x2b, 0x60, 0x00, 0x2c, 0x4a, 0x02, 0xcc, 0xaf, + 0xfb, 0x6b, 0x00, 0x38, 0x80, 0x10, 0x24, 0xc8, + 0x35, 0x42, 0xfd, 0x31, 0xa6, 0xeb, 0xc4, 0xca, + 0x17, 0x2d, 0xdf, 0xb3, 0x2b, 0x80, 0x18, 0x93, + 0xc6, 0xd4, 0xbd, 0x93, 0x26, 0x1f, 0x81, 0x2c, + 0xf1, 0x00, 0x1f, 0x0d, 0xb7, 0x40, 0x12, 0xca, + 0x02, 0x01, 0x3c, 0xa0, 0x14, 0x36, 0x01, 0xbd, + 0xb4, 0x00, 0x95, 0xa8, 0x00, 0x36, 0x60, 0x03, + 0x94, 0x05, 0x99, 0x5f, 0xf6, 0xde, 0x00, 0x71, + 0x00, 0x20, 0x2a, 0x3e, 0x8c, 0x0a, 0xde, 0xfa, + 0x26, 0xa1, 0xff, 0xbb, 0x2d, 0x9b, 0x10, 0xa2, + 0xc9, 0x63, 0x7f, 0xf2, 0xe0, 0x00, 0x0a, 0x0a, + 0xd2, 0xc4, 0x9c, 0xa2, 0x5b, 0x0a, 0xbd, 0x96, + 0x6a, 0x80, 0x9d, 0x9c, 0x69, 0x42, 0x4a, 0x1a, + 0x3f, 0x68, 0x29, 0x9b, 0x28, 0xf6, 0xa5, 0xd9, + 0x6b, 0xd9, 0xc2, 0x00, 0xad, 0x2c, 0x4e, 0xca, + 0x15, 0xb0, 0x80, 0x21, 0x56, 0xa8, 0xf7, 0x14, + 0xaa, 0xa0, 0x20, 0xa2, 0xa6, 0xf8, 0x7d, 0xea, + 0xbe, 0x80, 0x8a, 0xaf, 0x56, 0xbd, 0xdc, 0x20, + 0x00, 0x0a, 0x0a, 0xc8, 0xc4, 0xb8, 0xdf, 0x46, + 0x00, 0x4b, 0x28, 0x08, 0x04, 0xf0, 0x86, 0x14, + 0xa0, 0xd2, 0x33, 0xff, 0xb5, 0xa8, 0x03, 0xa8, + 0x00, 0x21, 0x26, 0xd9, 0xa0, 0x09, 0x64, 0x00, + 0xfc, 0xa2, 0x50, 0x0a, 0x5b, 0x7f, 0xe2, 0xc3, + 0x00, 0x12, 0xb6, 0x02, 0x02, 0xbc, 0xa0, 0x2c, + 0x4a, 0x01, 0xbe, 0x68, 0x00, 0xe2, 0x00, 0x40, + 0x13, 0xa2, 0x18, 0x6e, 0x6f, 0xed, 0x0c, 0x8f, + 0xc0, 0x10, 0xcf, 0x54, 0x7c, 0x33, 0xcc, 0xdb, + 0xee, 0xcf, 0x30, 0xfe, 0x5c, 0x97, 0x51, 0xe9, + 0x1a, 0x46, 0xff, 0xe5, 0x58, 0x15, 0xa8, 0x49, + 0xd9, 0x42, 0x92, 0x0f, 0x03, 0x6a, 0x05, 0x1f, + 0x0a, 0x6b, 0x5d, 0x83, 0xb4, 0x56, 0xbf, 0x27, + 0xbf, 0x63, 0x50, 0x10, 0xd8, 0xca, 0x5f, 0xc1, + 0x84, 0x00, 0x0a, 0x0a, 0xdc, 0xc5, 0x62, 0x9e, + 0xf7, 0x3a, 0x90, 0x80, 0x28, 0x9a, 0x02, 0x3f, + 0x71, 0x87, 0xa0, 0x24, 0x61, 0x99, 0x60, 0x82, + 0x77, 0x10, 0x0d, 0x05, 0x3d, 0xe6, 0x00, 0x90, + 0x06, 0xf9, 0xf0, 0x02, 0x59, 0x40, 0x00, 0x27, + 0x80, 0x06, 0x50, 0x0a, 0x5b, 0x7f, 0xe2, 0xc1, + 0x00, 0x12, 0xb3, 0x03, 0xf6, 0xbc, 0xa0, 0x2c, + 0x4a, 0x01, 0xb6, 0x58, 0x03, 0xa8, 0x00, 0x5e, + 0xe6, 0xd7, 0x00, 0x09, 0x59, 0x81, 0xfb, 0x5e, + 0x50, 0x16, 0x65, 0x7f, 0xdf, 0x46, 0x00, 0x6f, + 0x00, 0x2a, 0x81, 0x5a, 0x34, 0x9d, 0x94, 0x29, + 0x20, 0xf0, 0x36, 0xa0, 0x51, 0xf1, 0x26, 0xb5, + 0xd0, 0x3b, 0x45, 0x69, 0xf2, 0x7c, 0x16, 0x35, + 0x01, 0x05, 0x8a, 0xa6, 0x7c, 0x38, 0x40, 0x00, + 0x0a, 0x0a, 0xcf, 0xa4, 0xb8, 0xdf, 0x14, 0x00, + 0x4b, 0x2c, 0x17, 0xf4, 0xd2, 0x81, 0x50, 0xd4, + 0x06, 0xf4, 0xe0, 0x03, 0x98, 0x00, 0x55, 0x1b, + 0xe7, 0x40, 0x09, 0x65, 0x82, 0xfe, 0x9a, 0x50, + 0x2a, 0x1a, 0x80, 0xe6, 0x9e, 0x00, 0x04, 0xad, + 0x3f, 0x02, 0xb5, 0x2f, 0xeb, 0x33, 0x3f, 0xf1, + 0xa7, 0x80, 0x0e, 0x20, 0x04, 0x89, 0x42, 0x01, + 0x85, 0x0a, 0x9f, 0xd4, 0x88, 0xf8, 0x98, 0x12, + 0x2a, 0x0a, 0xc4, 0xca, 0xa4, 0x9b, 0x05, 0xf1, + 0xa5, 0x67, 0x1c, 0x66, 0x1a, 0xbf, 0x2a, 0x7f, + 0xa0, 0xec, 0xca, 0x0b, 0x35, 0x0a, 0xd2, 0x47, + 0x4c, 0xd8, 0xcb, 0x4b, 0x44, 0xb0, 0x11, 0xc4, + 0x11, 0x14, 0xf8, 0xa0, 0x4c, 0x61, 0xb7, 0xbf, + 0xfd, 0x2e, 0x00, 0x0a, 0x0a, 0xda, 0xe4, 0xfe, + 0x9f, 0x35, 0xa1, 0xac, 0x7f, 0x68, 0xb2, 0x01, + 0x3f, 0xb8, 0xd5, 0x9b, 0xf9, 0x8d, 0x48, 0xee, + 0x71, 0xe8, 0xb9, 0x8e, 0x12, 0x9d, 0x2e, 0x0f, + 0x20, 0x89, 0xe6, 0x52, 0x33, 0x02, 0x4b, 0xa3, + 0xec, 0x2b, 0x6e, 0x40, 0x36, 0x8b, 0x8b, 0xf1, + 0xf8, 0xb6, 0x7c, 0xe0, 0x94, 0xbf, 0xab, 0xda, + 0xfb, 0x2d, 0x70, 0x00, 0x5b, 0x6f, 0x00, 0x29, + 0xa5, 0xfe, 0xc9, 0x10, 0x48, 0x8c, 0x10, 0x22, + 0x70, 0x6f, 0x94, 0xd7, 0x70, 0x35, 0x34, 0x81, + 0x54, 0xe7, 0xe3, 0x6b, 0x13, 0xfd, 0x42, 0xcd, + 0xf7, 0x02, 0x98, 0x5c, 0xc0, 0x72, 0x34, 0xf7, + 0x73, 0xea, 0x78, 0x95, 0x3f, 0x74, 0xf3, 0xff, + 0x7f, 0xb3, 0xd7, 0x1d, 0xf7, 0x6c, 0xcb, 0x06, + 0xc8, 0x19, 0xb3, 0x84, 0xae, 0x2f, 0x0f, 0x8c, + 0xee, 0xd0, 0x58, 0x65, 0x23, 0x28, 0x55, 0xe8, + 0xff, 0xca, 0x9c, 0x00, 0x19, 0x5b, 0xc0, 0x17, + 0x69, 0x7f, 0xc5, 0xb3, 0xf6, 0x5b, 0x01, 0x80, + 0x38, 0xce, 0x04, 0x00, 0x0a, 0x0a, 0xcb, 0xe4, + 0xb8, 0xde, 0x00, 0x8c, 0x4a, 0x06, 0x65, 0x70, + 0x92, 0xd7, 0xfa, 0x05, 0x9e, 0xf0, 0x03, 0xa3, + 0x7d, 0x88, 0x01, 0x2c, 0x70, 0x20, 0x53, 0xcb, + 0xfd, 0x4b, 0x9f, 0xfb, 0xd3, 0xc0, 0x0e, 0x60, + 0x01, 0x11, 0x50, 0x04, 0x9d, 0x69, 0x18, 0x15, + 0x2b, 0x40, 0x0e, 0x3c, 0x4e, 0xfd, 0xea, 0x89, + 0x75, 0xd2, 0xfc, 0xbb, 0x7b, 0xdc, 0x56, 0x1a, + 0x31, 0xdc, 0x31, 0x54, 0xfa, 0x81, 0x95, 0xf4, + 0x2d, 0x2c, 0x51, 0x52, 0x80, 0x4f, 0x2c, 0xfc, + 0x7f, 0x2b, 0xdc, 0xc0, 0x05, 0xe2, 0xe2, 0xd8, + 0x00, 0x12, 0xb5, 0x02, 0x06, 0xc4, 0x06, 0x12, + 0x80, 0xb3, 0x2b, 0xff, 0x19, 0x40, 0x00, 0x00, + 0x0a, 0x0a, 0xdb, 0x80, 0x00, 0xde, 0x92, 0x00, + 0x4a, 0xd8, 0x00, 0x0b, 0x30, 0x01, 0xca, 0x02, + 0xcc, 0xaf, 0xfb, 0x6f, 0x80, 0x39, 0x80, 0x0a, + 0x11, 0xbe, 0x34, 0x00, 0x96, 0x38, 0x10, 0x29, + 0xe5, 0xfe, 0xa5, 0xcf, 0xfd, 0xe9, 0x60, 0x07, + 0x30, 0x00, 0x84, 0xa7, 0xad, 0x2d, 0x66, 0xc0, + 0x19, 0xea, 0x7f, 0x0f, 0x6d, 0x6b, 0x98, 0x00, + 0xb3, 0xdb, 0xe9, 0x80, 0x09, 0x65, 0x01, 0x00, + 0x9e, 0x50, 0x0a, 0x5b, 0x7f, 0xda, 0xc8, 0x01, + 0xcc, 0x00, 0x21, 0x2a, 0x01, 0x13, 0xe5, 0x01, + 0x03, 0x27, 0x62, 0xff, 0xd4, 0xb5, 0xed, 0xe0, + 0x44, 0x20, 0x00, 0x0a, 0x0a, 0xd5, 0x00, 0x00, + 0xe6, 0x53, 0x28, 0x46, 0xd5, 0x20, 0x09, 0x5a, + 0x81, 0x03, 0x62, 0x03, 0x09, 0x40, 0x59, 0x95, + 0xff, 0x8d, 0xa0, 0x00, 0x4b, 0x28, 0x08, 0x04, + 0xf2, 0x80, 0x52, 0xdb, 0xfe, 0xf4, 0x40, 0x03, + 0x9e, 0xda, 0x55, 0x1a, 0xed, 0x00, 0xe7, 0xb5, + 0x2a, 0xd6, 0xf4, 0x17, 0xfa, 0x57, 0x00, 0x40, + 0x57, 0x94, 0x05, 0x99, 0x1f, 0xf8, 0xda, 0x40, + 0x04, 0xb2, 0x80, 0x80, 0x4f, 0x08, 0x61, 0x4a, + 0x0d, 0x23, 0x3f, 0xfb, 0x54, 0x80, 0x39, 0x95, + 0x05, 0xf1, 0xbd, 0x18, 0x00, 0x00, 0x0a, 0x0a, + 0xdb, 0x90, 0x00, 0xe6, 0x29, 0xa8, 0x46, 0xb4, + 0xc0, 0x25, 0x6a, 0x04, 0x0d, 0x88, 0x0c, 0x25, + 0x01, 0x66, 0x57, 0xfd, 0xf2, 0x20, 0x04, 0xb2, + 0x80, 0x80, 0x4f, 0x28, 0x05, 0x2d, 0xbf, 0xed, + 0x64, 0x00, 0xe7, 0xdd, 0x94, 0x47, 0x1d, 0x3a, + 0x02, 0xdb, 0x34, 0x01, 0xc7, 0x54, 0x7f, 0xb9, + 0xf7, 0x0a, 0xf5, 0xb5, 0xab, 0xfa, 0x56, 0xc0, + 0x40, 0x57, 0x94, 0x05, 0x99, 0x5f, 0xf7, 0xc8, + 0x80, 0x12, 0xca, 0x02, 0x01, 0x3c, 0x21, 0x85, + 0x28, 0x34, 0x8c, 0xff, 0xeb, 0x4c, 0x03, 0x98, + 0xa8, 0x5f, 0x1b, 0x59, 0x80, 0x39, 0x8b, 0x2b, + 0xf5, 0xcc, 0x5b, 0x20, 0x6d, 0xac, 0x80, 0x00, + 0x00, 0x0a, 0x0a, 0xd4, 0x96, 0x4a, 0xe2, 0xa3, + 0x57, 0xd9, 0xdc, 0x09, 0x5a, 0x81, 0x03, 0x62, + 0x03, 0x09, 0x40, 0x59, 0x95, 0xff, 0x7c, 0x90, + 0x01, 0x2c, 0xa0, 0x20, 0x13, 0xca, 0x01, 0x4b, + 0x6f, 0xfb, 0x58, 0x00, 0x38, 0xdd, 0xc8, 0x67, + 0x1b, 0xd2, 0xf6, 0xda, 0xb9, 0xfd, 0x2b, 0x60, + 0x20, 0x2b, 0xca, 0x02, 0xbc, 0xa0, 0x3b, 0xe4, + 0x40, 0x09, 0x65, 0x01, 0x00, 0x9e, 0x50, 0x0a, + 0x5b, 0x7f, 0xce, 0xe0, 0x71, 0x51, 0x94, 0x2e, + 0x34, 0x82, 0xcd, 0xa6, 0xe0, 0x25, 0x94, 0x04, + 0x02, 0x79, 0x40, 0x28, 0x6c, 0x03, 0x8a, 0x14, + 0x00, 0x4a, 0xd8, 0x00, 0x0b, 0x12, 0x80, 0xb3, + 0x2b, 0xfe, 0xfb, 0xc0, 0x03, 0x8a, 0x75, 0x6a, + 0x71, 0x4d, 0x92, 0xad, 0xf7, 0xe0, 0x14, 0xb2, + 0x80, 0x80, 0x4f, 0x28, 0x05, 0x0d, 0x80, 0x71, + 0x42, 0x00, 0x09, 0x5a, 0x80, 0x03, 0x66, 0x00, + 0x39, 0x40, 0x59, 0x95, 0xff, 0x4d, 0xc0, 0x71, + 0xa4, 0x29, 0xa0, 0x00, 0x0a, 0x0a, 0xd1, 0xa0, + 0x00, 0xe3, 0xb9, 0x25, 0x9b, 0xe0, 0x40, 0x09, + 0x65, 0x00, 0x00, 0xa2, 0x50, 0x0a, 0x5b, 0x7f, + 0xe2, 0xe9, 0x00, 0x12, 0xb5, 0x02, 0x06, 0xbc, + 0xa0, 0x2c, 0x4a, 0x01, 0xbe, 0xfc, 0x00, 0xea, + 0x40, 0x17, 0xb9, 0xa5, 0xc0, 0x25, 0x6a, 0x04, + 0x0d, 0x88, 0x0c, 0x25, 0x01, 0x66, 0x57, 0xfd, + 0xf2, 0x40, 0x04, 0xb2, 0x80, 0x80, 0x4f, 0x28, + 0x05, 0x2d, 0xbf, 0xed, 0x6c, 0x00, 0xe7, 0xaf, + 0x94, 0xf7, 0x3d, 0x71, 0x59, 0x36, 0xb4, 0x7f, + 0x4a, 0xd8, 0x08, 0x0a, 0xf2, 0x80, 0xb3, 0x2b, + 0xfe, 0xf8, 0xd0, 0x02, 0x59, 0x40, 0x40, 0x27, + 0x94, 0x02, 0x96, 0xdf, 0xf5, 0xa0, 0x01, 0xcc, + 0xbc, 0x2f, 0x80, 0x00, 0x0a, 0x0a, 0xdd, 0xb4, + 0xb8, 0xe7, 0x4e, 0x80, 0x06, 0xf0, 0x03, 0x1a, + 0x5f, 0xed, 0x94, 0x80, 0x95, 0x38, 0x00, 0x32, + 0xb6, 0x80, 0x45, 0x73, 0x40, 0x00, 0x03, 0x9d, + 0xa6, 0x56, 0x5b, 0x40, 0x11, 0xb9, 0xae, 0xe0, + 0x01, 0xbc, 0x01, 0x3e, 0x97, 0xfc, 0xab, 0x20, + 0x25, 0xae, 0x00, 0x0b, 0x6d, 0xa0, 0x0e, 0x5c, + 0xee, 0x90, 0x00, 0xe6, 0x98, 0x2a, 0x76, 0xd0, + 0x0b, 0xa0, 0x00, 0x0a, 0x0a, 0xd4, 0x04, 0x1a, + 0x98, 0x26, 0x49, 0xa7, 0xba, 0x56, 0xdf, 0x7f, + 0x59, 0x97, 0xf5, 0xaa, 0x5f, 0xa7, 0xa5, 0x04, + 0x7e, 0x0c, 0x1e, 0x20, 0x02, 0xb5, 0x37, 0xdb, + 0xa4, 0x78, 0x74, 0xb4, 0x01, 0x80, 0x4f, 0x28, + 0x05, 0x2c, 0x00, 0xcc, 0xe2, 0x20, 0x0a, 0xe5, + 0xc4, 0x00, 0x56, 0x67, 0x08, 0x30, 0x96, 0xc1, + 0x19, 0x57, 0x7e, 0x05, 0x6a, 0x50, 0x56, 0x65, + 0x7d, 0x9a, 0x5f, 0xbb, 0xde, 0x47, 0x88, 0x01, + 0x53, 0xcc, 0x0f, 0x23, 0x4b, 0x87, 0x32, 0xde, + 0x27, 0xcc, 0x87, 0x10, 0x02, 0xa6, 0x00, 0x0a, + 0x0b, 0x0a, 0x02, 0xdf, 0xa5, 0xff, 0x2e, 0xcf, + 0xf9, 0x6c, 0x00, 0x00, 0xdb, 0xa8, 0x00, 0x2a, + 0x24, 0xa0, 0x1b, 0x28, 0x01, 0x2a, 0x70, 0x00, + 0x65, 0x75, 0x00, 0x0a, 0xbc, 0x00, 0x0a, 0x0a, + 0xd1, 0x80, 0x26, 0x9b, 0xdd, 0xba, 0x5c, 0x4a, + 0x59, 0x20, 0xc1, 0xa7, 0x94, 0x0a, 0x65, 0xe0, + 0xa7, 0x5a, 0xfb, 0xc2, 0x33, 0xee, 0x20, 0x05, + 0x4f, 0x30, 0x2c, 0x63, 0x8f, 0x94, 0xac, 0x3e, + 0x80, 0xb3, 0x28, 0x0b, 0x14, 0x3f, 0x4d, 0x1f, + 0xe3, 0xf7, 0x1b, 0xc4, 0x00, 0xa9, 0xa7, 0xf7, + 0xcf, 0xe9, 0x7e, 0xf9, 0x68, 0x82, 0xfe, 0x9a, + 0x5f, 0xa9, 0xdb, 0x83, 0x99, 0xa4, 0x48, 0x25, + 0xbb, 0x88, 0x00, 0xad, 0x4d, 0xf0, 0xe0, 0xb8, + 0x79, 0x35, 0x21, 0xe8, 0x43, 0x7f, 0x10, 0x01, + 0x5a, 0x00, 0x0a, 0x0a, 0xde, 0x85, 0x68, 0x8e, + 0xa0, 0xc1, 0x65, 0xe6, 0x23, 0x32, 0x99, 0xad, + 0x5b, 0x2e, 0x40, 0xa2, 0xb0, 0xc0, 0x9b, 0x88, + 0x02, 0x56, 0x8a, 0x69, 0x8a, 0xbd, 0x2f, 0x29, + 0x28, 0xe6, 0x40, 0x25, 0xa4, 0x02, 0xb9, 0x89, + 0x69, 0x9b, 0x98, 0xf6, 0x6c, 0x64, 0x70, 0x21, + 0x99, 0x42, 0x21, 0x44, 0x0e, 0x36, 0x85, 0x78, + 0x8c, 0xfa, 0x4d, 0x66, 0x52, 0x91, 0x25, 0xed, + 0x91, 0x3d, 0x98, 0x02, 0x63, 0x10, 0x34, 0x93, + 0xf9, 0xd1, 0x07, 0x81, 0xd0, 0x2a, 0x44, 0x85, + 0x53, 0xf9, 0x1a, 0x01, 0xad, 0xe6, 0x40, 0xe7, + 0x48, 0xa8, 0x95, 0x94, 0x30, 0x19, 0xe5, 0xf9, + 0x7e, 0xe7, 0xdc, 0x20, 0x00, 0x0a, 0x0a, 0xd0, + 0x61, 0x42, 0x87, 0xa0, 0xa4, 0xf9, 0x50, 0x47, + 0x98, 0x19, 0x21, 0x20, 0x1a, 0x64, 0xaf, 0xa0, + 0x6b, 0x89, 0x00, 0xd3, 0xeb, 0x39, 0xfd, 0xca, + 0xe9, 0x2f, 0xe9, 0x16, 0x80, 0x4b, 0x5f, 0xf7, + 0xf7, 0x5c, 0xfe, 0xe2, 0x8c, 0x05, 0x69, 0x9a, + 0xc3, 0x4c, 0xc5, 0xf0, 0x11, 0x49, 0x37, 0xc5, + 0x0c, 0xf7, 0xae, 0x99, 0x80, 0x9a, 0x74, 0x2f, + 0xdd, 0x7e, 0x60, 0x95, 0xc6, 0x30, 0x8d, 0x2d, + 0x00, 0x00, 0x0a, 0x0a, 0xd1, 0x84, 0x1c, 0x9a, + 0x54, 0x63, 0x28, 0x9e, 0x2a, 0x3b, 0x49, 0xeb, + 0xe6, 0xef, 0xcb, 0x0a, 0x80, 0x61, 0x36, 0x4f, + 0x03, 0xad, 0xe0, 0x07, 0x14, 0xbf, 0xda, 0xa9, + 0x01, 0x12, 0x02, 0x04, 0xa7, 0xfd, 0x01, 0xa3, + 0xbc, 0x01, 0x1a, 0x94, 0xff, 0xf4, 0x1e, 0xa7, + 0x66, 0xf5, 0x43, 0xda, 0xe9, 0x7e, 0xda, 0xbb, + 0xfa, 0x2a, 0x0b, 0x28, 0xee, 0x18, 0x36, 0x7c, + 0xe9, 0x32, 0xf2, 0x04, 0x8e, 0xe0, 0xb8, 0x28, + 0xb8, 0x3e, 0xef, 0xa2, 0xf2, 0xa0, 0x17, 0xba, + 0x92, 0x9f, 0xb2, 0x76, 0x58, 0x24, 0x3a, 0x89, + 0x94, 0x2a, 0xf4, 0x7f, 0xe5, 0x4e, 0x04, 0x0c, + 0x7d, 0xa0, 0x10, 0xd2, 0xfe, 0x9f, 0x63, 0xfc, + 0xb8, 0x40, 0xf7, 0x43, 0x35, 0xee, 0x4c, 0xe7, + 0x94, 0x95, 0x7b, 0x58, 0x1b, 0xc0, 0x12, 0xc9, + 0x7f, 0xca, 0xb2, 0x02, 0x5a, 0xe0, 0x00, 0xb6, + 0xde, 0x00, 0x69, 0x00, 0x0a, 0x0a, 0x97, 0x0e, + 0xc2, 0x73, 0x7d, 0xc4, 0x03, 0x2f, 0x97, 0xfd, + 0x0e, 0xf1, 0xb7, 0xac, 0xbf, 0xd2, 0xb5, 0x00, + 0x06, 0xcc, 0x06, 0x12, 0x80, 0xaf, 0x28, 0x0e, + 0xf9, 0xe0, 0x02, 0x4e, 0xa5, 0xfb, 0x79, 0xf9, + 0x75, 0x00, 0x3f, 0x6a, 0x70, 0x9d, 0x29, 0x6b, + 0xee, 0x99, 0x6b, 0xf9, 0x1d, 0x2e, 0x34, 0xa9, + 0x4b, 0x90, 0xd4, 0x8b, 0x12, 0x26, 0x36, 0xf8, + 0x90, 0x13, 0xe4, 0x73, 0x61, 0x25, 0x97, 0xee, + 0x28, 0xb3, 0x26, 0xa8, 0xb2, 0x94, 0x00, 0xa3, + 0x01, 0x05, 0xbe, 0xb4, 0x0a, 0x7f, 0xd9, 0x00, + 0x76, 0xb8, 0xdf, 0x3e, 0x01, 0x4b, 0x28, 0x08, + 0x04, 0xf2, 0x80, 0x52, 0xdb, 0xfe, 0xf6, 0xa0, + 0x02, 0x50, 0xeb, 0x00, 0xb8, 0xa3, 0xea, 0x4f, + 0x35, 0xe0, 0xba, 0x5a, 0xa0, 0xff, 0xa3, 0x94, + 0x02, 0x86, 0xc0, 0x39, 0xa8, 0x60, 0x01, 0x3a, + 0x67, 0xe0, 0x0f, 0xab, 0x4b, 0xfa, 0xbd, 0xaf, + 0xb2, 0xda, 0xff, 0xf1, 0x7c, 0xde, 0xac, 0x96, + 0x20, 0x9c, 0x60, 0xc0, 0x00, 0x00, 0x0a, 0x0b, + 0x10, 0xb3, 0x29, 0x25, 0x43, 0xbb, 0xee, 0xa9, + 0x7d, 0xdd, 0xbb, 0xee, 0x3b, 0x02, 0x27, 0x8a, + 0xcb, 0x0f, 0x9c, 0x82, 0x47, 0x12, 0x40, 0xa0, + 0x4b, 0x4a, 0x15, 0x32, 0x30, 0x91, 0x30, 0x3f, + 0x44, 0xda, 0xf7, 0x9d, 0x1a, 0xe6, 0xdf, 0xae, + 0x40, 0x00, 0x0a, 0x0a, 0xd4, 0x06, 0x20, 0xe2, + 0x84, 0x00, 0x12, 0xad, 0xff, 0xf6, 0xac, 0xa0, + 0xed, 0xd3, 0x03, 0xbe, 0x28, 0x00, 0xe2, 0xa4, + 0x44, 0x1a, 0xd8, 0x00, 0x95, 0xa8, 0x10, 0x35, + 0xe5, 0x01, 0x66, 0x57, 0xfd, 0xf2, 0x40, 0x04, + 0xb2, 0x80, 0x80, 0x4f, 0x28, 0x05, 0x2d, 0xbf, + 0xed, 0x4e, 0x00, 0xe3, 0x69, 0x38, 0x5c, 0x6d, + 0x29, 0x03, 0x6a, 0x77, 0xf4, 0xad, 0x80, 0x80, + 0xaf, 0x28, 0x0b, 0x32, 0xbf, 0xef, 0x92, 0x00, + 0x25, 0x94, 0x04, 0x02, 0x79, 0x40, 0x29, 0x6d, + 0xff, 0x5b, 0x00, 0x1c, 0x54, 0x87, 0x9b, 0x7c, + 0x63, 0xf5, 0x2d, 0x0f, 0xe1, 0x12, 0xcb, 0xf9, + 0x5a, 0xe0, 0x3c, 0x50, 0x40, 0x03, 0x68, 0x03, + 0xc7, 0x1b, 0xf0, 0x00, 0x96, 0x97, 0xf0, 0x49, + 0x65, 0xfc, 0xad, 0x70, 0x1e, 0x28, 0x20, 0x01, + 0xbc, 0x00, 0xc8, 0xdf, 0x54, 0x00, 0x4b, 0x28, + 0x08, 0x04, 0xf2, 0x80, 0x50, 0xd8, 0x07, 0x16, + 0xa8, 0x00, 0x95, 0xa8, 0x00, 0x36, 0x60, 0x03, + 0x94, 0x05, 0x99, 0x5f, 0xf7, 0xd4, 0x80, 0x1b, + 0xc0, 0x13, 0x8e, 0x28, 0x40, 0x01, 0x2a, 0xbf, + 0xff, 0xea, 0xca, 0x06, 0xdd, 0x50, 0x3c, 0x6f, + 0x80, 0x03, 0x68, 0x04, 0x40, 0x00, 0x0a, 0x0a, + 0xd4, 0x05, 0x1c, 0xde, 0x00, 0xa4, 0x4e, 0x0d, + 0x94, 0xb6, 0x7e, 0xb2, 0x1e, 0x02, 0xc0, 0xc8, + 0xc8, 0x28, 0x09, 0x23, 0x64, 0x13, 0xfc, 0x69, + 0xf8, 0xff, 0x08, 0xe8, 0x4a, 0x88, 0x18, 0x4c, + 0x32, 0x03, 0x44, 0x7b, 0x4b, 0x53, 0x6c, 0x6f, + 0x52, 0x53, 0xed, 0x60, 0x51, 0x74, 0x82, 0xff, + 0x4a, 0x37, 0xbc, 0x00, 0xb8, 0xdf, 0x40, 0x00, + 0x4b, 0x28, 0x08, 0x04, 0xf2, 0x80, 0x52, 0xdb, + 0xfe, 0xf6, 0x00, 0x03, 0x98, 0x00, 0x42, 0x93, + 0xfc, 0x9b, 0x13, 0xc0, 0x64, 0x99, 0x01, 0x7f, + 0xf2, 0x46, 0x06, 0x1d, 0xcb, 0x1b, 0x7f, 0xd0, + 0x30, 0x5e, 0xcb, 0x7c, 0x0f, 0xd4, 0x72, 0x00, + 0xbb, 0x05, 0xca, 0x9c, 0x93, 0x91, 0x32, 0x38, + 0x23, 0x40, 0xd0, 0x86, 0xfd, 0x40, 0xbd, 0xdd, + 0xcc, 0x00, 0x5e, 0x0d, 0xec, 0x20, 0x04, 0xad, + 0x40, 0x81, 0xb1, 0x01, 0x84, 0xa0, 0x2c, 0xca, + 0xff, 0xbe, 0x7c, 0x00, 0x00, 0x0a, 0x0b, 0x0f, + 0xa2, 0xd4, 0x38, 0xca, 0x00, 0x04, 0xf1, 0xc0, + 0x9f, 0xb1, 0x9f, 0x2f, 0xf6, 0x66, 0xd4, 0xcf, + 0x3c, 0x0b, 0xfd, 0x91, 0xf4, 0x7e, 0xe4, 0x32, + 0x3a, 0x50, 0x6f, 0x41, 0x12, 0x28, 0x43, 0xc9, + 0x7f, 0xbc, 0x5d, 0x9f, 0xec, 0x88, 0xac, 0x02, + 0xb8, 0xd7, 0xc0, 0x06, 0xf0, 0x05, 0xda, 0x5f, + 0xf4, 0xac, 0xfe, 0x96, 0xb8, 0x20, 0x2b, 0xb7, + 0x80, 0x1b, 0x5c, 0x59, 0x40, 0x02, 0x77, 0x97, + 0xc4, 0x1d, 0x2f, 0x94, 0x04, 0x9c, 0xd5, 0x66, + 0x58, 0xf7, 0x28, 0xe5, 0x85, 0xe7, 0xa6, 0x46, + 0xcf, 0x02, 0xb1, 0xa0, 0x0c, 0xdd, 0x6f, 0x2d, + 0xbf, 0x6c, 0x86, 0x15, 0x15, 0xe6, 0xa8, 0x11, + 0x75, 0x53, 0x83, 0x6f, 0x4a, 0x1f, 0xa7, 0x15, + 0x68, 0x00, 0xde, 0x00, 0x42, 0x4a, 0x01, 0x7a, + 0x80, 0x32, 0xa7, 0xfe, 0x06, 0x8e, 0xf0, 0x04, + 0xb0, 0x15, 0xb0, 0x0b, 0x79, 0x3b, 0x2c, 0xe6, + 0x09, 0x30, 0xcf, 0xfb, 0x27, 0x5d, 0x40, 0xd2, + 0x46, 0x17, 0xa1, 0x41, 0x33, 0x3f, 0x3f, 0x9f, + 0x61, 0xd3, 0xed, 0x84, 0xba, 0x9e, 0x0f, 0x73, + 0x00, 0xea, 0x67, 0x05, 0x6b, 0x11, 0x1f, 0xa9, + 0x15, 0x04, 0x5f, 0xe2, 0x4f, 0x6f, 0x9c, 0x7e, + 0x3d, 0x57, 0x97, 0x77, 0xa0, 0x09, 0x00, 0x00, + 0x0a, 0x0a, 0x98, 0xea, 0xe2, 0x65, 0xa4, 0x57, + 0x0f, 0xf9, 0x9b, 0x00, 0x57, 0xae, 0x76, 0xb4, + 0x3b, 0x46, 0x95, 0xac, 0xb1, 0xbc, 0xeb, 0xfc, + 0xa9, 0x3e, 0x84, 0xb7, 0x27, 0xf5, 0x5b, 0x56, + 0xd8, 0x69, 0x49, 0x91, 0x69, 0x80, 0x63, 0xa6, + 0x00, 0x95, 0xbc, 0xa1, 0xda, 0xf5, 0x21, 0x22, + 0xf5, 0xfb, 0x8c, 0xbf, 0x2c, 0xdc, 0xfb, 0x25, + 0x7f, 0x4a, 0xc6, 0xd9, 0xa6, 0x09, 0xa9, 0xf0, + 0x63, 0x40, 0xe6, 0x8e, 0xfc, 0xa6, 0x40, 0xdb, + 0x31, 0x41, 0x06, 0x04, 0x94, 0x55, 0x58, 0x12, + 0xdb, 0x09, 0xf5, 0x24, 0x9e, 0xa4, 0xca, 0x9b, + 0x5e, 0x1c, 0x26, 0xbd, 0x59, 0xff, 0x73, 0x9b, + 0xfd, 0xad, 0x1d, 0x7f, 0x6c, 0x33, 0x84, 0x94, + 0xac, 0x0a, 0x52, 0x83, 0x4a, 0x9c, 0x1c, 0x89, + 0x06, 0xcd, 0x10, 0x03, 0xed, 0x6a, 0x8c, 0x05, + 0x69, 0x62, 0x5c, 0x4e, 0xdf, 0x0c, 0x04, 0x5d, + 0x53, 0xfb, 0x1b, 0xd2, 0x40, 0xa4, 0xf2, 0x2f, + 0x6f, 0xba, 0x3b, 0x38, 0x4a, 0x36, 0xde, 0xf3, + 0xe1, 0x00, 0x00, 0x0a, 0x0b, 0x07, 0x62, 0xd2, + 0x38, 0x88, 0x8f, 0xd4, 0xc0, 0xe9, 0x46, 0xbf, + 0xd3, 0x1a, 0x01, 0x04, 0x5b, 0x71, 0x11, 0x20, + 0x6d, 0xf0, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0d, + 0x9a, 0xd2, 0x37, 0xc1, 0x80, 0x1c, 0x51, 0x27, + 0x7a, 0x53, 0x2b, 0x92, 0xfe, 0x95, 0xaf, 0xb0, + 0xb4, 0x63, 0xfd, 0xbb, 0x6e, 0x3b, 0xa4, 0x7c, + 0x0b, 0x06, 0xd2, 0xd2, 0x37, 0xc1, 0x80, 0x1c, + 0x51, 0x27, 0x7a, 0x53, 0x2b, 0x92, 0xfe, 0x95, + 0xaf, 0xb0, 0xb4, 0x63, 0xfd, 0xbb, 0x6e, 0x3b, + 0xa4, 0x7c, 0x00, 0x0a, 0x0a, 0x87, 0xe9, 0x7b, + 0x8b, 0x40, 0xc6, 0x48, 0xc2, 0xc9, 0x01, 0x2a, + 0x4f, 0xa1, 0x2d, 0xc8, 0x26, 0x53, 0x4d, 0xc6, + 0xe2, 0xab, 0xb8, 0xa3, 0xd5, 0x84, 0x8d, 0x47, + 0xe5, 0xf2, 0xfc, 0xb9, 0x73, 0xe4, 0x52, 0x12, + 0x71, 0xcc, 0x91, 0x7f, 0x19, 0x81, 0x90, 0x05, + 0x69, 0x23, 0x2f, 0x71, 0x68, 0x18, 0xd9, 0x18, + 0x55, 0x20, 0x25, 0x49, 0xf4, 0x25, 0xb9, 0x04, + 0xca, 0x69, 0xb8, 0xdc, 0x55, 0x77, 0x14, 0x7a, + 0xb0, 0x91, 0xa8, 0xfc, 0xbe, 0x5f, 0x97, 0x2e, + 0x7c, 0x8a, 0x42, 0x4e, 0x39, 0x92, 0x2f, 0xe3, + 0x30, 0x32, 0x00, 0x00, 0x0a, 0x0a, 0x87, 0xe9, + 0x7b, 0x8b, 0x40, 0xc6, 0x48, 0xc2, 0xc9, 0x01, + 0x2a, 0x4f, 0xa1, 0x2d, 0xc8, 0x26, 0x53, 0x4d, + 0xc6, 0xe2, 0xab, 0xb8, 0xa3, 0xd5, 0x84, 0x8d, + 0x47, 0xe5, 0xf2, 0xfc, 0xb9, 0x73, 0xe4, 0x52, + 0x12, 0x71, 0xcc, 0x91, 0x7f, 0x19, 0x81, 0x90, + 0x00, 0x0a, 0x0b, 0x10, 0xeb, 0x98, 0x38, 0xcc, + 0x53, 0x74, 0x94, 0x57, 0x77, 0xf2, 0xdb, 0x09, + 0xf5, 0x24, 0x9e, 0x22, 0xd3, 0xbc, 0x51, 0xc5, + 0x4b, 0x8d, 0xc8, 0xa8, 0x49, 0x33, 0x42, 0x1d, + 0x28, 0x34, 0xa9, 0x41, 0xc4, 0xc0, 0xfd, 0x21, + 0xbe, 0x21, 0x87, 0x16, 0x7a, 0x76, 0x00, 0x0a, + 0x0a, 0xca, 0x05, 0x08, 0xde, 0x92, 0x00, 0x4a, + 0xd8, 0x08, 0x0a, 0xf2, 0x80, 0xb3, 0x2b, 0xfe, + 0xfb, 0x70, 0x03, 0x68, 0x04, 0x84, 0xe0, 0xba, + 0xc9, 0xf7, 0xd7, 0x31, 0x30, 0x32, 0x70, 0xf4, + 0x8b, 0x8e, 0x07, 0xf0, 0x20, 0x40, 0x89, 0x2a, + 0x3e, 0xc0, 0xea, 0x49, 0xfc, 0xd0, 0xe9, 0x2e, + 0x0e, 0x95, 0x7b, 0xcb, 0x53, 0xc6, 0x1f, 0xf3, + 0xcf, 0x03, 0x9e, 0xe7, 0x86, 0xd0, 0x07, 0x0d, + 0xf6, 0x60, 0x04, 0xb2, 0x80, 0x80, 0x4f, 0x08, + 0x40, 0xca, 0x05, 0x33, 0x5f, 0xfb, 0xd3, 0x40, + 0x0e, 0x60, 0x01, 0x54, 0x6f, 0xad, 0x00, 0x25, + 0x94, 0x04, 0x02, 0x78, 0x81, 0x41, 0x25, 0x0c, + 0x7d, 0x80, 0x0e, 0x2c, 0x40, 0x01, 0x2b, 0x60, + 0x00, 0x2c, 0x4a, 0x02, 0xcc, 0xaf, 0xfb, 0xed, + 0xc0, 0x0e, 0x60, 0x02, 0xac, 0x02, 0xb7, 0x81, + 0x2e, 0x37, 0xd0, 0x80, 0x12, 0xca, 0x02, 0x01, + 0x3c, 0xa0, 0x14, 0xb6, 0xff, 0xb5, 0xb8, 0x03, + 0x98, 0x00, 0x55, 0x1b, 0xed, 0x40, 0x09, 0x65, + 0x01, 0x00, 0x9e, 0x50, 0x0a, 0x1b, 0x00, 0xe2, + 0xc1, 0x00, 0x12, 0xb5, 0x00, 0x06, 0xcc, 0x00, + 0x72, 0x80, 0xb3, 0x2b, 0xfe, 0xfb, 0x20, 0x03, + 0x98, 0x00, 0xa1, 0x00, 0xb0, 0xf0, 0x2c, 0x9b, + 0x6c, 0x40, 0x06, 0xf0, 0x03, 0x23, 0x6b, 0xc0, + 0x06, 0xf0, 0x04, 0xe0, 0x00, 0x0a, 0x0a, 0xca, + 0x05, 0x08, 0xde, 0x92, 0x00, 0x4a, 0xd8, 0x08, + 0x0a, 0xf2, 0x80, 0xb3, 0x2b, 0xfe, 0xfb, 0x70, + 0x03, 0x68, 0x04, 0x84, 0xe0, 0xba, 0xc9, 0xef, + 0xd7, 0x31, 0x48, 0x2a, 0xc9, 0x1c, 0x02, 0x91, + 0xa4, 0x44, 0xfc, 0xa8, 0xfb, 0x03, 0xa9, 0x27, + 0xf3, 0x43, 0xa4, 0xb8, 0x7a, 0x54, 0xef, 0x2d, + 0x3f, 0x18, 0xbf, 0xcf, 0x3c, 0x0e, 0x7b, 0x9e, + 0x1b, 0x40, 0x1c, 0x37, 0xd9, 0x80, 0x12, 0xca, + 0x02, 0x01, 0x3c, 0x21, 0x03, 0x28, 0x14, 0xcd, + 0x7f, 0xef, 0x4d, 0x00, 0x39, 0x80, 0x05, 0x51, + 0xbe, 0xb4, 0x00, 0x96, 0x50, 0x10, 0x09, 0xe2, + 0x05, 0x04, 0x94, 0x31, 0xf6, 0x00, 0x38, 0xb1, + 0x00, 0x04, 0xad, 0x00, 0x02, 0xb1, 0x28, 0x0b, + 0x32, 0xbf, 0xef, 0xb7, 0x00, 0x39, 0x80, 0x0a, + 0xb0, 0x0b, 0x0f, 0x02, 0xcf, 0x37, 0xd0, 0x80, + 0x12, 0xca, 0x02, 0x01, 0x3c, 0xa0, 0x14, 0xb6, + 0xff, 0xb5, 0xb8, 0x03, 0xa8, 0x00, 0x21, 0x26, + 0xfb, 0x50, 0x02, 0x59, 0x40, 0x40, 0x27, 0x94, + 0x02, 0x86, 0xc0, 0x38, 0xb0, 0xc0, 0x04, 0xad, + 0x40, 0x01, 0xb3, 0x00, 0x1c, 0xa0, 0x2c, 0xca, + 0xff, 0xbe, 0xc0, 0x00, 0xea, 0x00, 0x17, 0x18, + 0x00, 0x0a, 0x0a, 0xdf, 0x55, 0xf8, 0x95, 0xa8, + 0x10, 0x36, 0x20, 0x30, 0x94, 0x05, 0x99, 0x5f, + 0xf9, 0xcd, 0xc0, 0x01, 0x2c, 0xa0, 0x20, 0x13, + 0xca, 0x01, 0x4b, 0x6f, 0xfc, 0xd9, 0x20, 0x00, + 0x00, 0x0a, 0x0a, 0xd4, 0x05, 0x08, 0xe2, 0x80, + 0x00, 0x12, 0xb8, 0x00, 0x02, 0xc4, 0xa0, 0x2b, + 0xc8, 0x03, 0xbe, 0x00, 0x00, 0xe2, 0x00, 0x58, + 0xd2, 0xff, 0x97, 0x67, 0xfc, 0xb5, 0xc0, 0x01, + 0x6d, 0xc4, 0x00, 0x4f, 0xb8, 0xdf, 0xc0, 0x04, + 0x13, 0x91, 0x4f, 0x66, 0xc9, 0x58, 0xa0, 0x83, + 0x25, 0xa6, 0xfe, 0xac, 0xa0, 0x14, 0x36, 0x01, + 0xc5, 0x02, 0x00, 0x39, 0x80, 0x06, 0x81, 0x2f, + 0xf6, 0xca, 0x40, 0x4a, 0x9c, 0x00, 0x19, 0x5c, + 0xc0, 0x04, 0xc0, 0x00, 0x0a, 0x0a, 0xd4, 0x05, + 0x08, 0xe2, 0x80, 0x00, 0x12, 0xb8, 0x00, 0x02, + 0xc4, 0xa0, 0x2b, 0xc8, 0x03, 0xbe, 0x00, 0x00, + 0xe2, 0x00, 0x58, 0xd2, 0xff, 0x97, 0x67, 0xfc, + 0xb5, 0xc0, 0x01, 0x6d, 0xc4, 0x00, 0x4f, 0xb8, + 0xdf, 0xc0, 0x04, 0x13, 0x91, 0x4f, 0x66, 0xc9, + 0x58, 0xa0, 0x83, 0x25, 0xa6, 0xfe, 0xac, 0xa0, + 0x14, 0x36, 0x01, 0xc5, 0x02, 0x00, 0x38, 0x80, + 0x0d, 0xc7, 0x1b, 0xf8, 0x00, 0x96, 0x50, 0x10, + 0x09, 0xe5, 0x00, 0xa5, 0xb7, 0xfe, 0x28, 0x10, + 0x01, 0xc4, 0x00, 0x4d, 0x65, 0xfe, 0xdd, 0x48, + 0x09, 0x53, 0x80, 0x03, 0x27, 0x88, 0x01, 0x65, + 0xf1, 0x40, 0x00, 0x09, 0x5c, 0x01, 0x01, 0x5e, + 0x50, 0x16, 0x64, 0x7f, 0xdf, 0x00, 0x00, 0x71, + 0x00, 0x24, 0x80, 0x00, 0x0a, 0x0a, 0xd2, 0x75, + 0x48, 0x9a, 0x00, 0x2b, 0xd9, 0xe2, 0x70, 0x51, + 0xe9, 0x00, 0x0a, 0xd2, 0xa0, 0x13, 0x3f, 0xfb, + 0x85, 0xc2, 0xcd, 0xeb, 0x11, 0x03, 0xed, 0xa6, + 0xc0, 0x00, 0x0a, 0x0b, 0x0d, 0xc2, 0xe3, 0x36, + 0xba, 0x00, 0x4a, 0xc4, 0x00, 0x1b, 0x12, 0xff, + 0xb5, 0x3f, 0xf7, 0x19, 0xa0, 0x00, 0xa2, 0x67, + 0x05, 0xbe, 0xd4, 0x93, 0x68, 0x02, 0xf4, 0xe0, + 0x64, 0xea, 0xd0, 0xaf, 0x39, 0x44, 0x4e, 0x85, + 0x04, 0xf3, 0x00, 0x08, 0xc3, 0x7d, 0x18, 0x01, + 0x2c, 0xc0, 0x00, 0x14, 0x4a, 0x09, 0x3b, 0x20, + 0x3c, 0x50, 0x20, 0x02, 0x56, 0xc0, 0x43, 0x57, + 0x97, 0xcd, 0xda, 0x7e, 0xfa, 0x80, 0x05, 0xb2, + 0x6f, 0x50, 0x00, 0x3a, 0x80, 0x02, 0x4e, 0x4b, + 0x50, 0x2f, 0xc4, 0x72, 0x85, 0x4e, 0xcc, 0x0e, + 0xf5, 0xf0, 0x02, 0x56, 0x60, 0x40, 0xd7, 0x97, + 0xfd, 0x89, 0xa0, 0x36, 0xc5, 0x00, 0x75, 0x00, + 0x0b, 0x64, 0x05, 0x68, 0xc2, 0xcd, 0x4f, 0x0a, + 0xec, 0xfc, 0xaa, 0x3b, 0x40, 0x2d, 0xa7, 0x06, + 0xd4, 0x9e, 0xbd, 0x8e, 0x20, 0x13, 0xec, 0x00, + 0x0a, 0x0a, 0xd2, 0xe5, 0x5e, 0x9e, 0x90, 0x10, + 0xf8, 0x2c, 0xa7, 0x08, 0xad, 0x96, 0x61, 0x09, + 0xd6, 0x7e, 0xf0, 0x8d, 0x36, 0x7f, 0x75, 0x3e, + 0xa5, 0xed, 0xc2, 0x00, 0x00, 0x0a, 0x0a, 0x99, + 0xeb, 0x7b, 0x8e, 0xe8, 0xfa, 0x47, 0xc5, 0x81, + 0x72, 0x85, 0x6a, 0xd4, 0x2c, 0x8d, 0x02, 0x9c, + 0xf1, 0xa2, 0xc9, 0x87, 0x32, 0x45, 0x7b, 0xb8, + 0xde, 0xc0, 0x00, 0x00, 0x0a, 0x0a, 0x94, 0xab, + 0x7b, 0x8e, 0xe8, 0xe1, 0x47, 0xc5, 0x01, 0x52, + 0x85, 0x5e, 0xd4, 0x2c, 0xa9, 0x41, 0x19, 0xa5, + 0xc5, 0x12, 0x88, 0xb7, 0xc1, 0x80, 0x00, 0xad, + 0x7e, 0x6d, 0xee, 0x3b, 0xa3, 0x85, 0x1f, 0x14, + 0x05, 0x4a, 0x15, 0x7b, 0x50, 0xb2, 0xa5, 0x04, + 0x66, 0x97, 0x14, 0x4a, 0x22, 0xdf, 0x06, 0x00, + 0x00, 0x0a, 0x0b, 0x05, 0x2a, 0xd2, 0x38, 0xee, + 0x8e, 0x14, 0x7c, 0x50, 0x15, 0x28, 0x55, 0xed, + 0x42, 0xca, 0x94, 0x11, 0x9a, 0x5c, 0x51, 0x28, + 0x8b, 0x7c, 0x18, 0x00, 0x0b, 0x0b, 0xf2, 0xd2, + 0x38, 0xee, 0x8e, 0x14, 0x7c, 0x50, 0x15, 0x28, + 0x55, 0xed, 0x42, 0xca, 0x94, 0x11, 0x9a, 0x5c, + 0x51, 0x28, 0x8b, 0x7c, 0x18, 0x00, 0x00, 0x0a, + 0x0a, 0xd3, 0x76, 0x60, 0xe3, 0x31, 0x4d, 0xd2, + 0x51, 0x5d, 0xdf, 0xcb, 0x6c, 0x27, 0xd4, 0x92, + 0x78, 0x8b, 0x4e, 0xf1, 0x47, 0x15, 0x2e, 0x37, + 0x22, 0xa1, 0x24, 0xcd, 0x08, 0x74, 0xa0, 0xd2, + 0xa5, 0x07, 0x13, 0x03, 0xf4, 0x86, 0xf8, 0x86, + 0x1c, 0x59, 0xe9, 0xd8, 0x16, 0x21, 0xd7, 0x30, + 0x71, 0x98, 0xa6, 0xe9, 0x28, 0xae, 0xef, 0xe5, + 0xb6, 0x13, 0xea, 0x49, 0x3c, 0x45, 0xa7, 0x78, + 0xa3, 0x8a, 0x97, 0x1b, 0x91, 0x50, 0x92, 0x66, + 0x84, 0x3a, 0x50, 0x69, 0x52, 0x83, 0x89, 0x81, + 0xfa, 0x43, 0x7c, 0x43, 0x0e, 0x2c, 0xf4, 0xec, + 0x00, 0x0a, 0x0a, 0x58, 0xd5, 0x89, 0xa9, 0x82, + 0x3e, 0x17, 0x26, 0x09, 0x59, 0x5d, 0x09, 0x99, + 0x63, 0xdc, 0x2a, 0x9e, 0x6f, 0x7a, 0x4a, 0x3f, + 0x8c, 0x20, 0x0a, 0xd2, 0xb7, 0x58, 0x9a, 0x98, + 0x2b, 0xe1, 0x6a, 0x60, 0x85, 0x95, 0xa0, 0x99, + 0x96, 0xfd, 0xc2, 0xe9, 0xe6, 0xf7, 0xa4, 0xa3, + 0xf8, 0xc2, 0x00, 0xad, 0xf5, 0x75, 0x89, 0xa9, + 0x02, 0x7d, 0x96, 0x66, 0x09, 0x5b, 0x5d, 0x09, + 0x99, 0x63, 0xdc, 0x2a, 0x9e, 0x6f, 0x7a, 0x4a, + 0x7f, 0x8c, 0x20, 0x00, 0x0a, 0x0b, 0x04, 0x82, + 0xce, 0xa7, 0x9a, 0x04, 0x7d, 0x0c, 0x79, 0xc3, + 0x0c, 0xe6, 0x60, 0x52, 0x76, 0x77, 0xac, 0x35, + 0x37, 0x9f, 0xcf, 0x34, 0x98, 0xfc, 0x30, 0x80, + 0x2c, 0x12, 0x0b, 0x8a, 0x9d, 0x18, 0x03, 0x06, + 0x21, 0xe7, 0xf9, 0xa1, 0xee, 0xa0, 0x99, 0xee, + 0xff, 0x8f, 0xad, 0xda, 0x70, 0x5d, 0xf5, 0x13, + 0xfb, 0xc2, 0x00, 0xad, 0xf0, 0x4f, 0x89, 0x50, + 0x6f, 0x01, 0x76, 0x4f, 0x64, 0x97, 0xc8, 0xec, + 0x1a, 0x0f, 0x9d, 0x14, 0x20, 0xd2, 0xdd, 0x11, + 0xfc, 0xd4, 0x81, 0x2a, 0xa9, 0x31, 0x31, 0x28, + 0x46, 0x90, 0x37, 0x9c, 0xd7, 0x67, 0x0c, 0x05, + 0x4b, 0x64, 0x91, 0x3c, 0xd8, 0x35, 0xea, 0x68, + 0x4e, 0x16, 0x66, 0xb2, 0x82, 0x53, 0xb1, 0xbd, + 0xa1, 0x29, 0xc4, 0xfe, 0xf9, 0x5c, 0xe7, 0xcf, + 0x84, 0x01, 0x52, 0xd9, 0x4c, 0x4e, 0x84, 0x06, + 0x01, 0x12, 0x13, 0xfe, 0xd0, 0xd7, 0xd0, 0x44, + 0xf7, 0x9f, 0xcf, 0xde, 0xef, 0x38, 0x26, 0xe8, + 0x87, 0xf9, 0x61, 0x00, 0x56, 0xe3, 0x32, 0x44, + 0xf3, 0x40, 0xd7, 0xa1, 0xa1, 0x38, 0x61, 0x9a, + 0xcc, 0x09, 0x4e, 0xce, 0xf6, 0x86, 0xa7, 0x13, + 0xf9, 0xe5, 0x73, 0x1f, 0x3e, 0x10, 0x05, 0x6e, + 0x33, 0x4c, 0x4e, 0x8c, 0x06, 0x03, 0x12, 0x13, + 0xfc, 0xd0, 0xd7, 0x50, 0x44, 0xf7, 0x7f, 0xcf, + 0xd6, 0xef, 0x38, 0x2e, 0xe8, 0x89, 0xf9, 0x61, + 0x00, 0x00, 0x0a, 0x0a, 0xd1, 0x86, 0xca, 0xa2, + 0x9a, 0x26, 0x81, 0x23, 0x1a, 0x80, 0x61, 0x1f, + 0x55, 0x80, 0xb9, 0x5b, 0x80, 0x61, 0xe2, 0x64, + 0xff, 0x37, 0x2c, 0xd9, 0x13, 0xe1, 0x0f, 0xe3, + 0x5f, 0x99, 0xbd, 0xe0, 0x0b, 0xd4, 0xa0, 0x65, + 0x57, 0x01, 0x2d, 0x80, 0x00, 0x1b, 0x6d, 0x00, + 0x52, 0x9a, 0x7c, 0xbe, 0xd8, 0x22, 0x5a, 0x61, + 0x68, 0x00, 0xa2, 0xef, 0xfd, 0xbe, 0x9c, 0xc2, + 0x8f, 0xf3, 0x5e, 0x56, 0x37, 0x8d, 0xe0, 0x0b, + 0xc4, 0xa0, 0x65, 0x57, 0x01, 0x2d, 0x80, 0x00, + 0x1b, 0x6d, 0x00, 0x52, 0x05, 0x69, 0xd2, 0xc0, + 0x4c, 0xd7, 0xf6, 0x0b, 0x43, 0x37, 0xdd, 0x0c, + 0xaf, 0xde, 0xb9, 0x80, 0x26, 0x92, 0x07, 0xf8, + 0x5d, 0x98, 0x21, 0x79, 0xb8, 0x1b, 0x5b, 0x40, + 0x00, 0x00, 0x0a, 0x0b, 0x06, 0x12, 0xc5, 0x24, + 0xbb, 0x3d, 0x3d, 0x86, 0x68, 0x25, 0xb6, 0x13, + 0xea, 0x49, 0x3e, 0x51, 0xa5, 0x37, 0xb9, 0x19, + 0x12, 0x2a, 0x91, 0xe0, 0x4a, 0x9f, 0xe8, 0x3b, + 0x31, 0x8a, 0x94, 0xb6, 0x79, 0x43, 0x7c, 0x72, + 0x70, 0x00, 0x0a, 0x0b, 0x0d, 0x8a, 0xd4, 0xa4, + 0x66, 0xcf, 0xee, 0x97, 0xe5, 0x9b, 0x9f, 0x62, + 0xa0, 0xc2, 0x93, 0x60, 0xae, 0x3b, 0x7c, 0x71, + 0x91, 0x24, 0xab, 0x06, 0x84, 0xa0, 0xd3, 0xa5, + 0x07, 0x12, 0x8a, 0x74, 0x85, 0x7c, 0x9e, 0x3b, + 0xdc, 0x93, 0x80, 0x00, 0x0a, 0x0b, 0x09, 0x62, + 0xc0, 0xb8, 0xdf, 0x06, 0xd4, 0x92, 0x26, 0x12, + 0xb2, 0x83, 0x4a, 0x94, 0x1c, 0x87, 0x80, 0xae, + 0x1b, 0xda, 0xd5, 0x0d, 0xed, 0x65, 0x84, 0x8a, + 0xa0, 0x78, 0x12, 0xa4, 0xfa, 0x12, 0xdc, 0x81, + 0xdb, 0x1d, 0x3c, 0x6f, 0x8c, 0xa0, 0x00, 0x0a, + 0x0b, 0x0d, 0x9a, 0xd0, 0x23, 0xb8, 0x32, 0x48, + 0xf0, 0x3c, 0x26, 0x6c, 0x24, 0x3e, 0x40, 0x98, + 0xe8, 0x4a, 0x02, 0x2a, 0x0b, 0x09, 0xba, 0xff, + 0xaa, 0xb3, 0x25, 0x81, 0x6a, 0xff, 0xb8, 0xe3, + 0xd8, 0x02, 0x49, 0xc0, 0xa0, 0x89, 0x69, 0x8d, + 0x90, 0xd6, 0x5b, 0x2a, 0x00, 0x98, 0x94, 0x1a, + 0x34, 0xa0, 0x62, 0x40, 0x5f, 0x8d, 0xfd, 0x55, + 0x25, 0x67, 0x18, 0xdf, 0x49, 0x11, 0xe1, 0x50, + 0x22, 0x30, 0x41, 0x94, 0xe0, 0x36, 0x68, 0xa6, + 0x60, 0x3c, 0x31, 0x02, 0x8d, 0x00, 0x48, 0x24, + 0x58, 0x05, 0xb9, 0x95, 0x5f, 0x26, 0x73, 0x65, + 0x63, 0x4b, 0xde, 0xc9, 0x7d, 0xdd, 0xbb, 0xf7, + 0x08, 0x00, 0x0a, 0x0b, 0x0d, 0x12, 0xf5, 0xa5, + 0x6a, 0x00, 0x0d, 0x89, 0x40, 0x59, 0x95, 0xff, + 0x8c, 0x50, 0x00, 0x4b, 0x28, 0x08, 0x04, 0xf2, + 0x80, 0x50, 0xd8, 0x07, 0x17, 0x60, 0x00, 0x00, + 0x0a, 0x0b, 0x05, 0x82, 0xca, 0x25, 0xae, 0x0b, + 0xfa, 0xca, 0x01, 0x63, 0x15, 0x0c, 0x04, 0x68, + 0x43, 0x3e, 0xf0, 0x5b, 0x3b, 0x97, 0xe5, 0x4b, + 0x9f, 0xa5, 0xb4, 0x03, 0xe2, 0xc9, 0xfc, 0xc7, + 0xda, 0x50, 0x2e, 0x7a, 0x47, 0xd7, 0xd1, 0x83, + 0x97, 0xdd, 0x4b, 0xa0, 0x30, 0x80, 0x00, 0x0a, + 0x0b, 0x09, 0x62, 0xce, 0xa6, 0xa5, 0x0a, 0xf7, + 0x5a, 0x98, 0x25, 0x6d, 0x6c, 0x26, 0x65, 0xaf, + 0x60, 0xaa, 0x89, 0xbe, 0x28, 0xe9, 0x3d, 0xf0, + 0x80, 0x00, 0x0a, 0x0b, 0x05, 0xf2, 0xce, 0xa6, + 0xa5, 0x0a, 0xf7, 0x5a, 0x98, 0x25, 0x6d, 0x6c, + 0x26, 0x65, 0xaf, 0x60, 0xaa, 0x89, 0xbe, 0x28, + 0xe9, 0x3d, 0xf0, 0x80, 0x2c, 0x33, 0x4b, 0x3a, + 0x9a, 0x94, 0x2b, 0xdd, 0x6a, 0x60, 0x95, 0xb5, + 0xb0, 0x99, 0x96, 0xbd, 0x82, 0xaa, 0x26, 0xf8, + 0xa3, 0xa4, 0xf7, 0xc2, 0x00, 0x00, 0x0a, 0x0b, + 0x09, 0x62, 0xb6, 0x27, 0xa7, 0x84, 0x3d, 0x2a, + 0x29, 0xc2, 0xea, 0x65, 0x88, 0x42, 0x75, 0x87, + 0xbc, 0x31, 0x5f, 0x9f, 0xd5, 0x57, 0xa7, 0x7c, + 0xf0, 0x80, 0x2c, 0x25, 0x8b, 0x28, 0x99, 0xb4, + 0x08, 0x2d, 0x8a, 0x6f, 0x56, 0x19, 0x30, 0x39, + 0xa4, 0xbf, 0x7d, 0xa7, 0x66, 0x0a, 0xa1, 0x6e, + 0xfd, 0xc2, 0x00, 0x00, 0x0a, 0x0a, 0xd0, 0xe0, + 0x00, 0xde, 0x00, 0x50, 0x6b, 0x58, 0x02, 0x65, + 0xe0, 0x00, 0x23, 0x49, 0xbe, 0x4c, 0x6a, 0xff, + 0xe2, 0x90, 0xa0, 0x86, 0x0a, 0x25, 0xc2, 0x0a, + 0x8e, 0x89, 0x2d, 0xdb, 0x80, 0x20, 0xbd, 0x96, + 0xd8, 0x2f, 0xa9, 0x25, 0xfa, 0x5d, 0x38, 0xf9, + 0x4f, 0x90, 0x50, 0x2a, 0x54, 0x62, 0x4f, 0x01, + 0x9d, 0x35, 0xfc, 0x07, 0x62, 0x27, 0xfb, 0xe2, + 0xef, 0xbf, 0xbd, 0xa0, 0x14, 0x5b, 0x6c, 0x00, + 0x00, 0x0a, 0x0b, 0x09, 0x1a, 0xd7, 0xa4, 0x6e, + 0x7f, 0x73, 0x97, 0xe5, 0x9b, 0x9f, 0x63, 0xb8, + 0x2e, 0x58, 0xee, 0x4b, 0xa7, 0x7c, 0xf1, 0x79, + 0x24, 0x6c, 0x0a, 0x74, 0xa0, 0xd3, 0xa5, 0x07, + 0x22, 0x20, 0x2b, 0x76, 0xf6, 0x15, 0x10, 0x16, + 0x1b, 0x15, 0xaf, 0x48, 0xe4, 0xfe, 0x67, 0x2f, + 0xcb, 0x37, 0x3e, 0xc9, 0x70, 0x16, 0x25, 0xbe, + 0x78, 0xbc, 0xcb, 0x4d, 0x25, 0xc7, 0x80, 0x8c, + 0xa0, 0xd3, 0xa5, 0x07, 0x22, 0x20, 0x2b, 0x76, + 0xf6, 0x25, 0x10, 0x00, 0x0a, 0x0a, 0xd9, 0x40, + 0x00, 0xdb, 0x44, 0x01, 0x3d, 0x80, 0x8e, 0x06, + 0x3a, 0xce, 0x04, 0x38, 0xa5, 0x3f, 0xf0, 0xa0, + 0xfc, 0xe8, 0x2f, 0xc8, 0x4f, 0x95, 0x27, 0x92, + 0xd1, 0xec, 0x79, 0x05, 0xcd, 0x2d, 0xa2, 0xdb, + 0x41, 0x47, 0x41, 0x40, 0x11, 0x50, 0x48, 0x4d, + 0x54, 0x06, 0x05, 0x7f, 0x30, 0x0d, 0x6b, 0x8d, + 0xfe, 0xb6, 0xd8, 0x80, 0x0a, 0x0a, 0xd2, 0xc4, + 0x2c, 0xe2, 0x84, 0x65, 0x12, 0x3b, 0x57, 0xb6, + 0x4b, 0xee, 0xed, 0xdf, 0x72, 0x62, 0x0d, 0x67, + 0xef, 0x95, 0x2c, 0x37, 0xca, 0xaa, 0x12, 0x57, + 0x8e, 0x3f, 0xcb, 0x6c, 0x27, 0xd4, 0x92, 0x7c, + 0xbb, 0x88, 0xf1, 0x42, 0x0d, 0xa0, 0x00, 0x0a, + 0x0b, 0x11, 0xe3, 0x7e, 0x25, 0x6a, 0x04, 0x0d, + 0x88, 0x0c, 0x25, 0x01, 0x66, 0x57, 0xfe, 0xb7, + 0x80, 0x00, 0x12, 0xd0, 0x03, 0xe8, 0xfc, 0x40, + 0x80, 0x91, 0x81, 0x01, 0x34, 0xa2, 0x0d, 0xad, + 0xff, 0xd5, 0x10, 0x00, 0x00, 0x00, 0x0a, 0x0a, + 0xd2, 0xc6, 0x84, 0xe2, 0x00, 0x25, 0x9b, 0x64, + 0x80, 0x25, 0x94, 0x04, 0x02, 0x79, 0x40, 0x28, + 0x6c, 0x03, 0x9a, 0xb2, 0x00, 0x1c, 0x40, 0x0b, + 0xd2, 0x5f, 0xf4, 0x2c, 0xfc, 0x96, 0xbf, 0xe0, + 0x2d, 0xb7, 0x80, 0x17, 0x9c, 0x65, 0xc0, 0x03, + 0x88, 0x01, 0x1a, 0x6f, 0x50, 0x00, 0x35, 0x80, + 0x61, 0x28, 0x06, 0x8a, 0x00, 0x4a, 0x9c, 0x08, + 0x19, 0x7b, 0xc0, 0x14, 0x09, 0x40, 0xcb, 0xaf, + 0xfe, 0x5b, 0x00, 0x00, 0x36, 0xda, 0x00, 0x81, + 0xbe, 0xc0, 0x00, 0xe2, 0x00, 0x4b, 0x9c, 0x57, + 0xc0, 0x03, 0x78, 0x01, 0xb5, 0x28, 0x06, 0xca, + 0x00, 0x4a, 0xa4, 0x07, 0xf9, 0x5c, 0x40, 0x0b, + 0x5b, 0x9c, 0xac, 0x00, 0x12, 0xca, 0x02, 0x01, + 0x3c, 0xa0, 0x14, 0xb6, 0xff, 0xb5, 0xf8, 0x03, + 0x9e, 0xf6, 0x78, 0x1b, 0x6d, 0x80, 0x25, 0x94, + 0x04, 0x02, 0x78, 0x81, 0x41, 0x25, 0x0c, 0x7d, + 0x80, 0x0d, 0xed, 0x00, 0x04, 0xad, 0x80, 0x00, + 0xb1, 0x28, 0x0b, 0x32, 0xbf, 0xeb, 0x98, 0x03, + 0x88, 0xa5, 0x6a, 0x71, 0x48, 0x00, 0x00, 0x56, + 0x96, 0x31, 0xa7, 0x1b, 0xd8, 0x00, 0xe6, 0x28, + 0x2d, 0xe6, 0xd6, 0xa0, 0x0e, 0x60, 0x01, 0x22, + 0x00, 0x0a, 0x0a, 0xd6, 0x85, 0xd0, 0xde, 0x86, + 0x00, 0x4a, 0xb3, 0xf8, 0x2b, 0xb2, 0xff, 0xb1, + 0x4f, 0xe6, 0xb9, 0x40, 0x38, 0x80, 0x15, 0x64, + 0xff, 0x1b, 0x35, 0x0f, 0xf1, 0x36, 0x88, 0x0d, + 0xf0, 0x94, 0xb5, 0xc5, 0xdc, 0x1d, 0x2d, 0xe1, + 0x5f, 0x0b, 0x48, 0x1b, 0x2d, 0x97, 0x13, 0x93, + 0x84, 0x28, 0xbf, 0x20, 0xc0, 0xa3, 0xbc, 0xcb, + 0xdc, 0x27, 0x40, 0xb3, 0x3d, 0x7f, 0x83, 0x29, + 0xed, 0x00, 0x4e, 0x96, 0x07, 0x3a, 0x7f, 0x64, + 0xbf, 0xeb, 0x80, 0x9e, 0x04, 0x11, 0xf5, 0x2e, + 0xe7, 0x07, 0xa5, 0x58, 0x20, 0x79, 0x59, 0x81, + 0x5f, 0xd6, 0x63, 0x8f, 0x44, 0x2d, 0xcd, 0x7e, + 0x1d, 0x02, 0xb5, 0xa1, 0x51, 0x24, 0x89, 0x48, + 0xcc, 0x9a, 0xdc, 0x7a, 0xc3, 0xfa, 0x68, 0x80, + 0x0f, 0x8b, 0x89, 0xc1, 0xd8, 0x95, 0xd7, 0xde, + 0x46, 0x00, 0x6c, 0x49, 0x5b, 0x06, 0x46, 0x33, + 0x68, 0x03, 0xb0, 0x00, 0x0a, 0x0b, 0x07, 0x32, + 0xfc, 0x37, 0xae, 0x00, 0x12, 0xb5, 0x02, 0x06, + 0xbc, 0xa0, 0x2c, 0xca, 0xff, 0xc6, 0x2e, 0x00, + 0x25, 0x94, 0x04, 0x02, 0x79, 0x40, 0x29, 0x6d, + 0xff, 0x7b, 0x28, 0x01, 0xc4, 0x00, 0x71, 0xb8, + 0xdf, 0x44, 0xa4, 0xb7, 0x89, 0x82, 0x2b, 0x28, + 0x44, 0x47, 0x44, 0x42, 0x83, 0x11, 0xa4, 0x0f, + 0xd4, 0x4b, 0xab, 0xbb, 0xdb, 0x98, 0x4e, 0x20, + 0x13, 0x39, 0xbe, 0x6c, 0x00, 0x96, 0x50, 0x10, + 0x09, 0xe5, 0x00, 0xa1, 0xb0, 0x0e, 0x6e, 0x18, + 0x00, 0x71, 0x00, 0x26, 0xc9, 0x7f, 0xca, 0xb2, + 0x02, 0x5a, 0xe0, 0x00, 0xb6, 0xe2, 0x00, 0x28, + 0x9c, 0xef, 0x20, 0x00, 0xe2, 0x00, 0x48, 0x5c, + 0x52, 0xcd, 0x22, 0x54, 0x9b, 0xff, 0x69, 0x97, + 0xe5, 0xdb, 0x9e, 0xe3, 0xc0, 0x6a, 0x48, 0xee, + 0x3d, 0x0b, 0x8d, 0xfc, 0x50, 0x71, 0xff, 0xa5, + 0xc0, 0x00, 0x0a, 0x0a, 0x91, 0xae, 0x6a, 0x74, + 0x42, 0x15, 0x6c, 0x01, 0xa4, 0xe5, 0x7d, 0x00, + 0x55, 0x78, 0x27, 0xfe, 0x44, 0xef, 0x95, 0x7d, + 0xe8, 0xca, 0xa4, 0x88, 0xd5, 0xfe, 0x52, 0xfe, + 0xbf, 0x83, 0xec, 0x76, 0x06, 0x4d, 0x1e, 0x4b, + 0x66, 0xef, 0xbc, 0x29, 0xa7, 0xb9, 0x5f, 0xaa, + 0x40, 0x4a, 0x71, 0xa8, 0x2c, 0xfa, 0xe8, 0x7a, + 0x7f, 0xfb, 0x89, 0x0e, 0xb2, 0xdf, 0x76, 0x57, + 0xc9, 0x6a, 0xe1, 0x91, 0x28, 0x24, 0x28, 0x01, + 0xc4, 0xe0, 0xd9, 0x1a, 0x36, 0xd8, 0xef, 0x43, + 0x57, 0x01, 0x52, 0x41, 0x90, 0x4f, 0x95, 0xb3, + 0xff, 0xe9, 0x34, 0x04, 0xb1, 0x8a, 0xff, 0xea, + 0xce, 0x91, 0xfe, 0x9d, 0xce, 0xbc, 0xee, 0x02, + 0xd8, 0x05, 0x6e, 0x42, 0x3f, 0x4e, 0x69, 0x4a, + 0x00, 0xd7, 0xd4, 0x7b, 0x2e, 0x95, 0x06, 0x17, + 0x4f, 0x6c, 0xff, 0xe2, 0xb1, 0x3c, 0xd2, 0x15, + 0x26, 0x00, 0x0a, 0x0a, 0xd5, 0x45, 0xe4, 0xde, + 0xa0, 0x00, 0x6b, 0x00, 0xd2, 0x5f, 0xed, 0x94, + 0x80, 0x95, 0x38, 0x00, 0x32, 0xb7, 0x80, 0x28, + 0x12, 0xff, 0x97, 0x67, 0xfc, 0xb5, 0xc0, 0x01, + 0x6d, 0xac, 0x03, 0xcd, 0xf6, 0x00, 0x07, 0x10, + 0x02, 0x5c, 0xe2, 0xbe, 0x00, 0x1b, 0xc0, 0x0d, + 0xe9, 0x7f, 0xb6, 0x52, 0x02, 0x54, 0xe0, 0x00, + 0xca, 0xe2, 0x00, 0x5a, 0x5c, 0xec, 0x50, 0x00, + 0xa7, 0x18, 0x01, 0xef, 0xcc, 0x84, 0xa9, 0x03, + 0x28, 0x5c, 0xf0, 0x81, 0x9e, 0x6a, 0x38, 0x00, + 0x71, 0x00, 0x2f, 0x69, 0x7f, 0xcd, 0xb3, 0xf6, + 0x5a, 0xff, 0x40, 0xb9, 0xde, 0x00, 0x5d, 0x71, + 0x97, 0x00, 0x0e, 0x20, 0x04, 0x68, 0x0b, 0x09, + 0x62, 0xfc, 0x39, 0x80, 0x07, 0x81, 0xb6, 0xe8, + 0x02, 0x79, 0x60, 0x07, 0x25, 0x71, 0x9f, 0x2b, + 0x7c, 0xff, 0xcd, 0x27, 0x00, 0xcb, 0xcd, 0x77, + 0x79, 0xcd, 0x97, 0x46, 0xb0, 0x13, 0x6a, 0x30, + 0x00, 0x00, 0x0a, 0x0b, 0x09, 0x6a, 0xe1, 0x28, + 0xbb, 0xc1, 0x7f, 0x8d, 0x07, 0xa0, 0x1d, 0x44, + 0x51, 0x10, 0x76, 0x84, 0x37, 0xe2, 0x07, 0x6f, + 0x4a, 0x3e, 0x6b, 0xce, 0xf0, 0xfa, 0xf0, 0x80, + 0x2c, 0x25, 0xab, 0xd4, 0x9d, 0x94, 0x0c, 0x08, + 0x31, 0xa7, 0xf6, 0xb1, 0xa7, 0x21, 0x49, 0xe6, + 0xfe, 0xdf, 0x5c, 0xd6, 0x70, 0x9c, 0xfd, 0x97, + 0xf3, 0xc2, 0x00, 0x00, 0x0a, 0x0a, 0xd4, 0x07, + 0x86, 0x9c, 0xce, 0x96, 0x48, 0x81, 0x23, 0x70, + 0x1f, 0xd9, 0x93, 0x3d, 0x99, 0x6c, 0xe6, 0x41, + 0xcd, 0xfd, 0xe7, 0x97, 0xe5, 0xdb, 0x9e, 0xe2, + 0x91, 0xa2, 0x8a, 0x4e, 0x92, 0x69, 0x66, 0x5c, + 0x70, 0xb9, 0x2f, 0x16, 0xef, 0xe8, 0xc9, 0xfe, + 0xaf, 0x6e, 0xb8, 0xe6, 0x81, 0x3f, 0xf4, 0xff, + 0xeb, 0x5f, 0x7b, 0x37, 0x3e, 0xe6, 0x5f, 0x45, + 0xfb, 0xcf, 0x66, 0x04, 0xeb, 0x94, 0xb3, 0xef, + 0x2b, 0xb6, 0x2f, 0xac, 0xd5, 0x20, 0x12, 0x26, + 0x52, 0xc3, 0x38, 0x0d, 0x14, 0x82, 0x3c, 0xe9, + 0x50, 0xa0, 0xc4, 0x86, 0xfe, 0xbe, 0x72, 0xac, + 0xc6, 0xd7, 0x84, 0xa9, 0x3a, 0x23, 0xff, 0x3a, + 0x84, 0x26, 0x0f, 0x4f, 0xed, 0x00, 0x78, 0x9a, + 0xa7, 0x96, 0xb7, 0xf6, 0x5a, 0xe0, 0x6a, 0x07, + 0x9a, 0x20, 0x52, 0xd4, 0xd2, 0x6a, 0x64, 0x90, + 0x06, 0x7a, 0x01, 0x64, 0x4d, 0x16, 0x05, 0x26, + 0x64, 0x02, 0x58, 0xae, 0x91, 0xaa, 0x5a, 0x83, + 0x58, 0x06, 0x52, 0x80, 0x64, 0x88, 0x24, 0x2c, + 0x31, 0x13, 0x83, 0x7c, 0xa6, 0xbb, 0x81, 0xa9, + 0xb4, 0x02, 0xf0, 0x15, 0xa3, 0x0e, 0x49, 0x3e, + 0x45, 0x23, 0xab, 0x0b, 0x49, 0x60, 0xd6, 0x7f, + 0x3c, 0xd3, 0xe7, 0xec, 0xa5, 0xcc, 0x0f, 0x74, + 0x63, 0xb1, 0x31, 0xbe, 0x83, 0x6f, 0x1c, 0xaa, + 0xfb, 0x27, 0xff, 0x2b, 0x50, 0x6f, 0xc9, 0xc8, + 0xa8, 0xca, 0x8d, 0xbc, 0x00, 0xba, 0x05, 0x6a, + 0x03, 0x10, 0x50, 0x13, 0x5a, 0x05, 0xa7, 0xf9, + 0x33, 0x70, 0x39, 0xc3, 0x7c, 0xe1, 0xe1, 0xb8, + 0x41, 0x0b, 0xc6, 0x52, 0x00, 0x80, 0x0a, 0x0a, + 0xd4, 0x04, 0xb8, 0xe3, 0x61, 0x00, 0x12, 0xca, + 0x02, 0x01, 0x3c, 0xa0, 0x14, 0xb6, 0xff, 0xbd, + 0xdc, 0x00, 0xe6, 0x00, 0x15, 0x47, 0x1a, 0xf8, + 0x00, 0x96, 0x50, 0x10, 0x09, 0xe5, 0x00, 0xa1, + 0xb0, 0x0e, 0x6b, 0x48, 0x00, 0x4a, 0xdc, 0x00, + 0x1b, 0x12, 0x80, 0xb3, 0x23, 0xff, 0x1b, 0x00, + 0x00, 0xe6, 0x00, 0x28, 0x40, 0x00, 0x0a, 0x0b, + 0x0a, 0x02, 0xcf, 0x38, 0xd8, 0x40, 0x04, 0xb2, + 0x80, 0x80, 0x4f, 0x28, 0x05, 0x2d, 0xbf, 0xef, + 0x77, 0x00, 0x38, 0x80, 0x0f, 0x36, 0xf9, 0x31, + 0xea, 0x5b, 0xc4, 0x81, 0x18, 0x94, 0x22, 0x64, + 0x41, 0x22, 0x61, 0x4e, 0x90, 0x8f, 0xd0, 0xdb, + 0x7a, 0xc3, 0x39, 0xc4, 0x02, 0x78, 0x38, 0xd7, + 0xc0, 0x04, 0xb2, 0x80, 0x80, 0x4f, 0x28, 0x05, + 0x0d, 0x80, 0x73, 0x5a, 0x80, 0x02, 0x56, 0xa0, + 0x00, 0xd9, 0x80, 0x0e, 0x50, 0x16, 0x65, 0x7f, + 0xe3, 0x5f, 0x00, 0x1c, 0xc0, 0x05, 0xfe, 0xde, + 0xd6, 0xc2, 0x4a, 0x8b, 0x87, 0xec, 0xd2, 0xfc, + 0xb9, 0x7b, 0xe4, 0x99, 0x01, 0x61, 0x9b, 0xea, + 0x86, 0x6e, 0x7f, 0xfa, 0xf5, 0x00, 0x0a, 0x0a, + 0x93, 0x4e, 0xea, 0x66, 0x24, 0xc7, 0x31, 0x39, + 0x53, 0x07, 0x52, 0x02, 0x86, 0x93, 0xdb, 0x0a, + 0x26, 0x79, 0xff, 0xb5, 0x4c, 0x4d, 0xfb, 0x7a, + 0x02, 0xed, 0x22, 0xd7, 0xfd, 0xbc, 0xbf, 0xaf, + 0xe4, 0xfb, 0x14, 0x86, 0x14, 0x78, 0x24, 0x5d, + 0xbe, 0xf4, 0x84, 0x9f, 0x05, 0x9b, 0xaf, 0x7f, + 0x68, 0x96, 0xc2, 0x8f, 0x65, 0x9c, 0x9c, 0x06, + 0xa7, 0x39, 0xa0, 0xf7, 0xdf, 0x10, 0xf2, 0x54, + 0xa8, 0x46, 0x4a, 0x0d, 0x0a, 0x10, 0x71, 0x28, + 0x1f, 0x46, 0x6e, 0x3a, 0x5b, 0xd1, 0x57, 0x80, + 0x56, 0xdc, 0xab, 0x74, 0xe5, 0xe3, 0x50, 0x11, + 0x15, 0x47, 0xbc, 0xa7, 0xd4, 0xc0, 0xfc, 0xf7, + 0xaf, 0xf6, 0x73, 0x61, 0xcd, 0x02, 0x5f, 0x00, + 0x54, 0x9e, 0x69, 0xd3, 0xe9, 0x33, 0x5f, 0xcb, + 0xc5, 0x01, 0x15, 0x5e, 0xad, 0x7b, 0xb3, 0xa0, + 0x80, 0xa6, 0x42, 0x7f, 0x3b, 0xfc, 0x83, 0x80, + 0x0a, 0x0b, 0x12, 0x0b, 0x9c, 0x27, 0x00, 0xda, + 0xfb, 0xb9, 0xb9, 0xf6, 0xd2, 0xfa, 0x47, 0xde, + 0x6a, 0x20, 0x0b, 0x44, 0x89, 0x6f, 0x20, 0xd2, + 0xb6, 0x5d, 0xe8, 0x76, 0x34, 0x9f, 0x43, 0x22, + 0xa9, 0xfd, 0x28, 0xba, 0x02, 0xcf, 0x89, 0x8e, + 0xa0, 0x1f, 0x67, 0x91, 0x90, 0xb2, 0x75, 0x6f, + 0xec, 0xbb, 0x17, 0x9c, 0xc8, 0xe4, 0x5f, 0x02, + 0xa3, 0x70, 0x1f, 0xd9, 0x93, 0x3d, 0x99, 0x6c, + 0xe6, 0x41, 0xcd, 0xfd, 0xe7, 0x97, 0xdd, 0xdb, + 0xbe, 0xe2, 0x91, 0xa2, 0x8a, 0x4e, 0x92, 0x69, + 0x66, 0x5c, 0x70, 0xb9, 0x2f, 0x16, 0xef, 0xe8, + 0xcb, 0x7e, 0x6f, 0x56, 0xbc, 0xe6, 0x81, 0x3f, + 0xf0, 0x2b, 0x50, 0x18, 0x82, 0x80, 0xa2, 0xd0, + 0x2c, 0xbf, 0xc9, 0x9b, 0xc1, 0xce, 0x5b, 0xe7, + 0x0f, 0x0d, 0xc2, 0x08, 0x5e, 0x32, 0x80, 0x04, + 0x0a, 0xca, 0x64, 0xec, 0xa0, 0xcf, 0x09, 0xc1, + 0x55, 0x3e, 0x8f, 0x9d, 0x46, 0xcd, 0xc2, 0x8a, + 0x32, 0xff, 0x67, 0xe7, 0xad, 0x68, 0x06, 0xab, + 0x63, 0x3b, 0xd8, 0xc2, 0x00, 0x00, 0x0a, 0x0a, + 0x5e, 0x1b, 0x0d, 0xb3, 0x80, 0x12, 0xca, 0x02, + 0x01, 0x3c, 0xa0, 0x14, 0x36, 0x01, 0xbd, 0xb8, + 0x00, 0x95, 0xb0, 0x00, 0x16, 0x25, 0x01, 0x66, + 0x57, 0xfd, 0x76, 0x00, 0x73, 0x00, 0x12, 0x62, + 0x70, 0xb5, 0x65, 0x7d, 0xeb, 0x9d, 0x7e, 0x1a, + 0x08, 0xb1, 0x27, 0xf6, 0xa5, 0xaa, 0xa1, 0x2c, + 0xf6, 0x04, 0xb5, 0x01, 0x7e, 0x4d, 0x28, 0x05, + 0x4d, 0x80, 0x67, 0x50, 0x25, 0x56, 0x05, 0x78, + 0xe9, 0x94, 0x46, 0x0f, 0xcc, 0x67, 0x3d, 0x19, + 0x40, 0xc9, 0xb9, 0xfd, 0xef, 0xea, 0x98, 0x5a, + 0x7c, 0x57, 0xe7, 0xe9, 0x6f, 0x97, 0xed, 0x0b, + 0x20, 0x25, 0xb4, 0x0b, 0xf2, 0xc9, 0xc2, 0x0d, + 0x76, 0x20, 0x4a, 0x83, 0xe7, 0xe7, 0x05, 0x6b, + 0x8a, 0x3f, 0xeb, 0xae, 0xde, 0xe2, 0x66, 0x74, + 0xb2, 0xfc, 0x88, 0xa3, 0xe9, 0xbb, 0xef, 0x7f, + 0x86, 0x8b, 0xe4, 0x1c, 0xf8, 0xcf, 0x0e, 0x60, + 0x01, 0xb4, 0x00, 0x00 }; + +SWFFONT * Font_Courier(U16 id) +{ SWFFONT * f; + int i; + + if (!(f=malloc(sizeof(SWFFONT)))) return NULL; + memset(f,0x00,sizeof(SWFFONT)); + f->id = id; + f->version = 2; + f->name = strdup("Courier"); + f->style = 0x00; + f->encoding = 0x00; + f->numchars = 148; + f->maxascii = 256; + f->glyph = (SWFGLYPH*)malloc(sizeof(SWFGLYPH)*148); + f->glyph2ascii = (U16*)malloc(sizeof(U16)*148); + f->ascii2glyph = (int*)malloc(sizeof(int)*256); + memset(f->ascii2glyph, -1, sizeof(int)*256); + + f->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT)); + f->layout->ascent = 1037; + f->layout->descent = 911; + f->layout->leading = 274; + f->layout->kerningcount = 0; + f->layout->kerning = 0; + f->layout->bounds = (SRECT*)malloc(sizeof(SRECT)*148); + memset(f->layout->bounds, 0, sizeof(SRECT)*148); + + addGlyph(f, 0, 0x020, 36*20, &Glyphs_Courier[0x0000], 14, 480, -1236, 720, 30); // ' ' + addGlyph(f, 1, 0x022, 45*20, &Glyphs_Courier[0x0045], 393, 292, -1208, 908, -628); // " + addGlyph(f, 2, 0x023, 50*20, &Glyphs_Courier[0x0077], 1376, 184, -1294, 1016, 125); // # + addGlyph(f, 3, 0x024, 49*20, &Glyphs_Courier[0x0123], 1393, 219, -1320, 980, 180); // $ + addGlyph(f, 4, 0x025, 51*20, &Glyphs_Courier[0x01d2], 1184, 172, -1220, 1027, 23); // % + addGlyph(f, 5, 0x026, 47*20, &Glyphs_Courier[0x0266], 1207, 220, -1040, 956, 32); // & + addGlyph(f, 6, 0x027, 34*20, &Glyphs_Courier[0x02fd], 251, 270, -1208, 680, -626); // ' + addGlyph(f, 7, 0x028, 45*20, &Glyphs_Courier[0x031d], 475, 580, -1208, 916, 250); // ( + addGlyph(f, 8, 0x029, 31*20, &Glyphs_Courier[0x0359], 471, 294, -1212, 622, 248); // ) + addGlyph(f, 9, 0x02a, 48*20, &Glyphs_Courier[0x0394], 857, 226, -1208, 975, -499); // * + addGlyph(f, 10, 0x02b, 52*20, &Glyphs_Courier[0x0400], 534, 144, -1060, 1056, -64); // + + addGlyph(f, 11, 0x02c, 34*20, &Glyphs_Courier[0x0443], 243, 270, -290, 680, 291); // , + addGlyph(f, 12, 0x02d, 52*20, &Glyphs_Courier[0x0462], 254, 144, -600, 1056, -519); // - + addGlyph(f, 13, 0x02e, 37*20, &Glyphs_Courier[0x0482], 240, 452, -232, 748, 30); // . + addGlyph(f, 14, 0x02f, 48*20, &Glyphs_Courier[0x04a0], 350, 225, -1337, 975, 163); // / + addGlyph(f, 15, 0x030, 49*20, &Glyphs_Courier[0x04cc], 691, 220, -1230, 980, 30); // 0 + addGlyph(f, 16, 0x031, 48*20, &Glyphs_Courier[0x0523], 531, 225, -1224, 974, 0); // 1 + addGlyph(f, 17, 0x032, 49*20, &Glyphs_Courier[0x0566], 704, 168, -1230, 986, 0); // 2 + addGlyph(f, 18, 0x033, 50*20, &Glyphs_Courier[0x05be], 1009, 188, -1232, 1000, 30); // 3 + addGlyph(f, 19, 0x034, 47*20, &Glyphs_Courier[0x063d], 721, 210, -1220, 956, 0); // 4 + addGlyph(f, 20, 0x035, 50*20, &Glyphs_Courier[0x0698], 842, 190, -1220, 1000, 30); // 5 + addGlyph(f, 21, 0x036, 51*20, &Glyphs_Courier[0x0702], 1045, 274, -1230, 1020, 30); // 6 + addGlyph(f, 22, 0x037, 48*20, &Glyphs_Courier[0x0785], 424, 219, -1220, 960, 4); // 7 + addGlyph(f, 23, 0x038, 49*20, &Glyphs_Courier[0x07ba], 851, 220, -1230, 980, 30); // 8 + addGlyph(f, 24, 0x039, 51*20, &Glyphs_Courier[0x0825], 1005, 280, -1230, 1022, 29); // 9 + addGlyph(f, 25, 0x03a, 37*20, &Glyphs_Courier[0x08a3], 467, 452, -840, 748, 30); // : + addGlyph(f, 26, 0x03b, 35*20, &Glyphs_Courier[0x08de], 470, 278, -840, 700, 291); // ; + addGlyph(f, 27, 0x03c, 52*20, &Glyphs_Courier[0x0919], 420, 144, -1036, 1044, -88); // < + addGlyph(f, 28, 0x03d, 54*20, &Glyphs_Courier[0x094e], 499, 102, -740, 1098, -379); // = + addGlyph(f, 29, 0x03e, 52*20, &Glyphs_Courier[0x098d], 440, 155, -1036, 1056, -88); // > + addGlyph(f, 30, 0x03f, 49*20, &Glyphs_Courier[0x09c4], 889, 259, -1148, 997, 29); // ? + addGlyph(f, 31, 0x040, 47*20, &Glyphs_Courier[0x0a34], 1176, 215, -1242, 957, 123); // @ + addGlyph(f, 32, 0x041, 59*20, &Glyphs_Courier[0x0ac7], 902, 18, -1120, 1182, 0); // A + addGlyph(f, 33, 0x042, 54*20, &Glyphs_Courier[0x0b38], 923, 86, -1120, 1080, 0); // B + addGlyph(f, 34, 0x043, 53*20, &Glyphs_Courier[0x0bac], 822, 120, -1147, 1070, 31); // C + addGlyph(f, 35, 0x044, 52*20, &Glyphs_Courier[0x0c13], 687, 86, -1120, 1040, 0); // D + addGlyph(f, 36, 0x045, 52*20, &Glyphs_Courier[0x0c69], 930, 86, -1120, 1040, 0); // E + addGlyph(f, 37, 0x046, 52*20, &Glyphs_Courier[0x0cde], 874, 86, -1120, 1041, 0); // F + addGlyph(f, 38, 0x047, 56*20, &Glyphs_Courier[0x0d4c], 1093, 120, -1149, 1124, 32); // G + addGlyph(f, 39, 0x048, 55*20, &Glyphs_Courier[0x0dd5], 1098, 105, -1120, 1102, 0); // H + addGlyph(f, 40, 0x049, 48*20, &Glyphs_Courier[0x0e5f], 544, 226, -1120, 974, 0); // I + addGlyph(f, 41, 0x04a, 58*20, &Glyphs_Courier[0x0ea3], 689, 159, -1120, 1166, 32); // J + addGlyph(f, 42, 0x04b, 57*20, &Glyphs_Courier[0x0efa], 1133, 86, -1120, 1144, 0); // K + addGlyph(f, 43, 0x04c, 54*20, &Glyphs_Courier[0x0f88], 592, 126, -1120, 1080, 0); // L + addGlyph(f, 44, 0x04d, 59*20, &Glyphs_Courier[0x0fd2], 1035, 22, -1120, 1186, 0); // M + addGlyph(f, 45, 0x04e, 56*20, &Glyphs_Courier[0x1054], 799, 44, -1120, 1124, 0); // N + addGlyph(f, 46, 0x04f, 55*20, &Glyphs_Courier[0x10b8], 489, 100, -1146, 1100, 32); // O + addGlyph(f, 47, 0x050, 50*20, &Glyphs_Courier[0x10f6], 756, 86, -1120, 1000, 0); // P + addGlyph(f, 48, 0x051, 55*20, &Glyphs_Courier[0x1155], 1238, 100, -1146, 1100, 228); // Q + addGlyph(f, 49, 0x052, 58*20, &Glyphs_Courier[0x11f0], 1038, 86, -1120, 1178, 0); // R + addGlyph(f, 50, 0x053, 51*20, &Glyphs_Courier[0x1272], 1194, 179, -1151, 1020, 31); // S + addGlyph(f, 51, 0x054, 53*20, &Glyphs_Courier[0x1308], 650, 140, -1120, 1061, 0); // T + addGlyph(f, 52, 0x055, 56*20, &Glyphs_Courier[0x135a], 770, 80, -1121, 1121, 32); // U + addGlyph(f, 53, 0x056, 59*20, &Glyphs_Courier[0x13bb], 644, 18, -1121, 1182, 0); // V + addGlyph(f, 54, 0x057, 58*20, &Glyphs_Courier[0x140c], 781, 40, -1120, 1160, 0); // W + addGlyph(f, 55, 0x058, 56*20, &Glyphs_Courier[0x146e], 1096, 80, -1121, 1120, 0); // X + addGlyph(f, 56, 0x059, 54*20, &Glyphs_Courier[0x14f7], 849, 102, -1120, 1098, 0); // Y + addGlyph(f, 57, 0x05a, 50*20, &Glyphs_Courier[0x1562], 538, 206, -1120, 1001, 0); // Z + addGlyph(f, 58, 0x05b, 44*20, &Glyphs_Courier[0x15a6], 350, 560, -1220, 890, 241); // [ + addGlyph(f, 59, 0x05c, 48*20, &Glyphs_Courier[0x15d2], 350, 225, -1336, 975, 163); // + addGlyph(f, 60, 0x05d, 32*20, &Glyphs_Courier[0x15fe], 348, 310, -1221, 640, 240); // ] + addGlyph(f, 61, 0x05e, 48*20, &Glyphs_Courier[0x162a], 388, 224, -1230, 974, -707); // ^ + addGlyph(f, 62, 0x05f, 61*20, &Glyphs_Courier[0x165b], 156, -24, 160, 1224, 240); // _ + addGlyph(f, 63, 0x060, 46*20, &Glyphs_Courier[0x166f], 245, 520, -1208, 930, -684); // ` + addGlyph(f, 64, 0x061, 54*20, &Glyphs_Courier[0x168e], 1111, 140, -868, 1080, 33); // a + addGlyph(f, 65, 0x062, 54*20, &Glyphs_Courier[0x1719], 769, 40, -1220, 1080, 32); // b + addGlyph(f, 66, 0x063, 53*20, &Glyphs_Courier[0x177a], 706, 160, -868, 1070, 32); // c + addGlyph(f, 67, 0x064, 58*20, &Glyphs_Courier[0x17d3], 811, 120, -1220, 1160, 31); // d + addGlyph(f, 68, 0x065, 52*20, &Glyphs_Courier[0x1839], 685, 126, -868, 1044, 32); // e + addGlyph(f, 69, 0x066, 54*20, &Glyphs_Courier[0x188f], 973, 210, -1220, 1082, 0); // f + addGlyph(f, 70, 0x067, 56*20, &Glyphs_Courier[0x1909], 887, 120, -868, 1122, 381); // g + addGlyph(f, 71, 0x068, 55*20, &Glyphs_Courier[0x1978], 1040, 86, -1220, 1102, 0); // h + addGlyph(f, 72, 0x069, 50*20, &Glyphs_Courier[0x19fa], 574, 184, -1242, 1016, 0); // i + addGlyph(f, 73, 0x06a, 46*20, &Glyphs_Courier[0x1a42], 567, 294, -1242, 920, 381); // j + addGlyph(f, 74, 0x06b, 54*20, &Glyphs_Courier[0x1a89], 936, 120, -1220, 1082, 0); // k + addGlyph(f, 75, 0x06c, 50*20, &Glyphs_Courier[0x1afe], 449, 184, -1220, 1016, 0); // l + addGlyph(f, 76, 0x06d, 59*20, &Glyphs_Courier[0x1b37], 1302, 20, -869, 1186, 0); // m + addGlyph(f, 77, 0x06e, 54*20, &Glyphs_Courier[0x1bda], 1053, 105, -869, 1082, 0); // n + addGlyph(f, 78, 0x06f, 53*20, &Glyphs_Courier[0x1c5e], 469, 140, -868, 1060, 32); // o + addGlyph(f, 79, 0x070, 54*20, &Glyphs_Courier[0x1c99], 904, 40, -872, 1080, 381); // p + addGlyph(f, 80, 0x071, 58*20, &Glyphs_Courier[0x1d0a], 876, 120, -868, 1163, 381); // q + addGlyph(f, 81, 0x072, 54*20, &Glyphs_Courier[0x1d78], 854, 168, -860, 1084, 0); // r + addGlyph(f, 82, 0x073, 49*20, &Glyphs_Courier[0x1de3], 1159, 199, -868, 983, 33); // s + addGlyph(f, 83, 0x074, 49*20, &Glyphs_Courier[0x1e74], 798, 85, -1124, 998, 31); // t + addGlyph(f, 84, 0x075, 54*20, &Glyphs_Courier[0x1ed8], 723, 86, -840, 1080, 31); // u + addGlyph(f, 85, 0x076, 57*20, &Glyphs_Courier[0x1f33], 662, 60, -840, 1140, 0); // v + addGlyph(f, 86, 0x077, 57*20, &Glyphs_Courier[0x1f86], 785, 60, -840, 1140, 0); // w + addGlyph(f, 87, 0x078, 54*20, &Glyphs_Courier[0x1fe9], 1106, 102, -841, 1098, 0); // x + addGlyph(f, 88, 0x079, 54*20, &Glyphs_Courier[0x2074], 826, 102, -840, 1098, 381); // y + addGlyph(f, 89, 0x07a, 49*20, &Glyphs_Courier[0x20dc], 498, 230, -840, 980, 0); // z + addGlyph(f, 90, 0x07b, 40*20, &Glyphs_Courier[0x211b], 670, 394, -1208, 808, 248); // { + addGlyph(f, 91, 0x07c, 32*20, &Glyphs_Courier[0x216f], 246, 560, -1208, 640, 248); // | + addGlyph(f, 92, 0x07d, 40*20, &Glyphs_Courier[0x218e], 670, 391, -1208, 806, 248); // } + addGlyph(f, 93, 0x07e, 50*20, &Glyphs_Courier[0x21e2], 789, 182, -700, 1016, -419); // ~ + addGlyph(f, 94, 0x0a1, 36*20, &Glyphs_Courier[0x2245], 549, 480, -840, 720, 432); // ¡ + addGlyph(f, 95, 0x0a2, 46*20, &Glyphs_Courier[0x228a], 1039, 220, -1260, 938, 25); // ¢ + addGlyph(f, 96, 0x0a3, 52*20, &Glyphs_Courier[0x230c], 1164, 126, -1150, 1040, 0); // £ + addGlyph(f, 97, 0x0a4, 55*20, &Glyphs_Courier[0x239e], 347, 98, -940, 1101, -276); // ¤ + addGlyph(f, 98, 0x0a5, 54*20, &Glyphs_Courier[0x23ca], 1371, 102, -1120, 1098, 0); // ¥ + addGlyph(f, 99, 0x0a6, 51*20, &Glyphs_Courier[0x2476], 1078, 174, -1230, 1037, 180); // ¦ + addGlyph(f,100, 0x0a7, 53*20, &Glyphs_Courier[0x24fd], 1425, 131, -1200, 1072, 120); // § + addGlyph(f,101, 0x0a8, 49*20, &Glyphs_Courier[0x25b0], 1170, 203, -980, 997, -187); // ¨ + addGlyph(f,102, 0x0a9, 36*20, &Glyphs_Courier[0x2643], 203, 472, -1208, 728, -628); // © + addGlyph(f,103, 0x0aa, 50*20, &Glyphs_Courier[0x265d], 429, 186, -1208, 1014, -684); // ª + addGlyph(f,104, 0x0ab, 54*20, &Glyphs_Courier[0x2693], 705, 126, -840, 1086, 0); // « + addGlyph(f,105, 0x0ac, 31*20, &Glyphs_Courier[0x26ec], 358, 126, -840, 628, 0); // ¬ + addGlyph(f,106, 0x0ad, 54*20, &Glyphs_Courier[0x2719], 366, 582, -840, 1082, 0); // ­ + addGlyph(f,107, 0x0ae, 58*20, &Glyphs_Courier[0x2747], 1516, 20, -1242, 1170, 0); // ® + addGlyph(f,108, 0x0af, 58*20, &Glyphs_Courier[0x2805], 1373, 20, -1220, 1174, 0); // ¯ + addGlyph(f,109, 0x0b1, 52*20, &Glyphs_Courier[0x28b1], 254, 144, -600, 1056, -519); // ± + addGlyph(f,110, 0x0b2, 47*20, &Glyphs_Courier[0x28d1], 598, 248, -1208, 952, 126); // ² + addGlyph(f,111, 0x0b3, 47*20, &Glyphs_Courier[0x291c], 890, 248, -1208, 952, 124); // ³ + addGlyph(f,112, 0x0b4, 37*20, &Glyphs_Courier[0x298c], 240, 452, -696, 748, -434); // ´ + addGlyph(f,113, 0x0b6, 52*20, &Glyphs_Courier[0x29aa], 1005, 160, -1220, 1050, 121); // ¶ + addGlyph(f,114, 0x0b7, 39*20, &Glyphs_Courier[0x2a28], 225, 404, -674, 796, -282); // · + addGlyph(f,115, 0x0b8, 34*20, &Glyphs_Courier[0x2a45], 243, 270, -290, 680, 291); // ¸ + addGlyph(f,116, 0x0b9, 50*20, &Glyphs_Courier[0x2a64], 423, 186, -290, 1014, 234); // ¹ + addGlyph(f,117, 0x0ba, 50*20, &Glyphs_Courier[0x2a99], 429, 186, -1208, 1014, -684); // º + addGlyph(f,118, 0x0bb, 54*20, &Glyphs_Courier[0x2acf], 717, 122, -840, 1082, 0); // » + addGlyph(f,119, 0x0bc, 55*20, &Glyphs_Courier[0x2b29], 597, 100, -168, 1100, 30); // ¼ + addGlyph(f,120, 0x0bd, 57*20, &Glyphs_Courier[0x2b74], 1578, 60, -1222, 1140, 17); // ½ + addGlyph(f,121, 0x0bf, 47*20, &Glyphs_Courier[0x2c3a], 889, 202, -840, 941, 340); // ¿ + addGlyph(f,122, 0x0c1, 32*20, &Glyphs_Courier[0x2caa], 317, 308, -1278, 642, -980); // Á + addGlyph(f,123, 0x0c2, 44*20, &Glyphs_Courier[0x2cd2], 330, 557, -1278, 891, -979); //  + addGlyph(f,124, 0x0c3, 44*20, &Glyphs_Courier[0x2cfc], 340, 308, -1278, 893, -980); // à + addGlyph(f,125, 0x0c4, 45*20, &Glyphs_Courier[0x2d27], 791, 289, -1220, 915, -1040); // Ä + addGlyph(f,126, 0x0c5, 44*20, &Glyphs_Courier[0x2d8a], 238, 310, -1146, 890, -1066); // Å + addGlyph(f,127, 0x0c6, 44*20, &Glyphs_Courier[0x2da8], 371, 310, -1240, 890, -980); // Æ + addGlyph(f,128, 0x0c7, 35*20, &Glyphs_Courier[0x2dd7], 211, 500, -1222, 700, -1022); // Ç + addGlyph(f,129, 0x0c8, 46*20, &Glyphs_Courier[0x2df2], 409, 280, -1222, 920, -1022); // È + addGlyph(f,130, 0x0ca, 40*20, &Glyphs_Courier[0x2e26], 425, 400, -1320, 800, -960); // Ê + addGlyph(f,131, 0x0cb, 38*20, &Glyphs_Courier[0x2e5c], 552, 417, 0, 760, 340); // Ë + addGlyph(f,132, 0x0cd, 44*20, &Glyphs_Courier[0x2ea1], 596, 305, -1266, 894, -980); // Í + addGlyph(f,133, 0x0ce, 43*20, &Glyphs_Courier[0x2eec], 448, 554, 0, 866, 301); // Î + addGlyph(f,134, 0x0cf, 44*20, &Glyphs_Courier[0x2f24], 338, 308, -1278, 893, -980); // Ï + addGlyph(f,135, 0x0d0, 59*20, &Glyphs_Courier[0x2f4f], 308, 2, -600, 1198, -519); // Ð + addGlyph(f,136, 0x0e1, 59*20, &Glyphs_Courier[0x2f76], 1367, 20, -1120, 1180, 0); // á + addGlyph(f,137, 0x0e3, 45*20, &Glyphs_Courier[0x3021], 1043, 300, -1142, 900, -559); // ã + addGlyph(f,138, 0x0e8, 54*20, &Glyphs_Courier[0x30a4], 1002, 84, -1120, 1080, 0); // è + addGlyph(f,139, 0x0e9, 56*20, &Glyphs_Courier[0x3122], 1022, 77, -1210, 1121, 86); // é + addGlyph(f,140, 0x0ea, 59*20, &Glyphs_Courier[0x31a2], 1083, 20, -1120, 1180, 0); // ê + addGlyph(f,141, 0x0eb, 45*20, &Glyphs_Courier[0x322a], 457, 300, -1148, 900, -560); // ë + addGlyph(f,142, 0x0f1, 57*20, &Glyphs_Courier[0x3264], 1808, 20, -868, 1159, 33); // ñ + addGlyph(f,143, 0x0f5, 50*20, &Glyphs_Courier[0x3346], 443, 184, -840, 1016, 0); // õ + addGlyph(f,144, 0x0f8, 50*20, &Glyphs_Courier[0x337e], 831, 184, -1220, 1016, 0); // ø + addGlyph(f,145, 0x0f9, 54*20, &Glyphs_Courier[0x33e6], 1040, 104, -916, 1088, 86); // ù + addGlyph(f,146, 0x0fa, 57*20, &Glyphs_Courier[0x3468], 1193, 20, -868, 1159, 32); // ú + addGlyph(f,147, 0x0fb, 50*20, &Glyphs_Courier[0x34fe], 1063, 86, -1220, 1000, 31); // û + + return f; +} + +#undef addGlyph diff -Nru swftools-0.9.2+ds1/lib/example/glyphshape.c swftools-0.9.1/lib/example/glyphshape.c --- swftools-0.9.2+ds1/lib/example/glyphshape.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/glyphshape.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,173 @@ +/* glyphshape.c + + Part of the swftools package. + + Copyright (c) 2001 Rainer Böhme + + This file is distributed under the GPL, see file COPYING for details + + 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 "../rfxswf.h" + +#include "demofont.c" // six glyphs only: f, l, o, s, t, w +//#include "stdfonts.c" + +#define BANNER_TEXT "swftools" +#define ID_FONT 1000 +#define ID_SHAPES 2000 // to 2255 + +TAG * PlaceGlyph(TAG * t,SWFFONT * font,U8 glyph,U16 depth,int x,int y,int angle) +{ MATRIX m; + t = swf_InsertTag(t,ST_PLACEOBJECT2); + + swf_GetMatrix(NULL,&m); + + if (angle) + { m.sy = m.sx = (int)(cos(((double)(angle))/128*3.14159)*0x10000); + m.r0 = (int)(sin(((double)(angle))/128*3.14159)*0x10000); + m.r1 = -m.r0; + } + else m.sx = m.sy = 0x10000; + + // move origin + + m.tx = x+((m.r1-m.sx)/0x100); // this is correct + m.ty = y+((m.sx-m.r0)/0x100); + +// m.tx = x+((m.r1-m.sx)/0x40); // this looks crazier ;-) +// m.ty = y+((m.sx-m.r0)/0x40); + + + if (font) + swf_ObjectPlace(t,ID_SHAPES+glyph,depth,&m,NULL,NULL); + else swf_ObjectMove(t,depth,&m,NULL); + + return t; +} + +// some helper functions which define the figure + +int posX(int count) +{ return (int)(-sin(((double)count)/1024*3.14159)*3000); +} +int posY(int count) +{ return (int)(sin(((double)count)/2048*3.14159)*3200); +} +int angle(int count) +{ return (int)(pow(cos(((double)count)/2048*3.14159),3)*110); + // this is not the mathematical correct solution, but it works & looks nice +} + +int main(int argc, char ** argv) +{ SWF swf; + TAG * t; + SRECT r; + RGBA rgb; + MATRIX m; + U8 abits, gbits; + + int f,i,frame; + int width = 400; + int height = 400; + char * s = BANNER_TEXT; + + SWFFONT * font = Font_Demo_Font(ID_FONT); // change font name here + + swf_FontInitUsage(font); + swf_FontUse(font,s); + swf_FontReduce(font); // make sure that gid's point to the specific glyphs + + memset(&swf,0x00,sizeof(SWF)); + + swf.fileVersion = 4; + swf.frameRate = 0x1000; + swf.movieSize.xmax = 20*width; + swf.movieSize.ymax = 20*height; + + swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + t = swf.firstTag; + + rgb.r = 0xff; + rgb.g = 0xff; + rgb.b = 0xff; + swf_SetRGB(t,&rgb); + + // define Glyph Shapes + + for (i=0;inumchars;i++) + { if (font->glyph[i].shape) + { SHAPE * s; + int fs; + + t = swf_InsertTag(t,ST_DEFINESHAPE); + + swf_ShapeNew(&s); + + rgb.r = rgb.g = rgb.b = i; + + swf_ShapeAddSolidFillStyle(s,&rgb); + + swf_SetU16(t,ID_SHAPES+i); + + r.xmin = -50*20; r.ymin = -50*20; // Glyph Shapes are placed into a 2000*2000 box + r.ymax = 50*20; r.xmax = 50*20; // where (1000,1000) is the origin + + swf_SetRect(t,&r); + + swf_SetShapeStyles(t,s); // rest of header is set by swf_SetSimpleShape + swf_SetSimpleShape(t,font->glyph[i].shape); + swf_ShapeFree(s); + + } + } + + for (frame=0;frame<128;frame++) + { int cnt = 4096-frame*32; + for (i=0;iascii2glyph[s[i]]; + int advance = font->glyph[glyph].advance/2; + int cnt2 = cnt+=advance/2; + t = PlaceGlyph(t,frame?NULL:font,glyph,i+1, + 200*20+posX(cnt2), + 200*20+posY(cnt2), + angle(cnt2)); + cnt+=advance; + } + t = swf_InsertTag(t,ST_SHOWFRAME); + } + + + t = swf_InsertTag(t,ST_END); + +// swf_WriteCGI(&swf); + + f = open("glyphshape.swf",O_RDWR|O_CREAT|O_TRUNC|O_BINARY,0644); + if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed.\n"); + close(f); + + swf_FreeTags(&swf); + +#ifdef __NT__ + system("start ..\\glyphshape.swf"); +#endif + + return 0; +} + + diff -Nru swftools-0.9.2+ds1/lib/example/hexfont.c swftools-0.9.1/lib/example/hexfont.c --- swftools-0.9.2+ds1/lib/example/hexfont.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/hexfont.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,87 @@ +/* hexfont.c + + Example for how to construct an SWF font from another SWF font. + + Part of the swftools package. + + Copyright (c) 2004 Matthias Kramm + + This file is distributed under the GPL, see file COPYING for details + + 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 "../rfxswf.h" + +int main() +{ + char* hex = "0123456789ABCDEF"; + SWFFONT* font = swf_LoadFont("../../doc/Courier.swf"); + SWFFONT hexfont; + + memset(&hexfont, 0, sizeof(hexfont)); + hexfont.name = (char*)"HexFont"; + hexfont.layout = malloc(sizeof(SWFLAYOUT)); + hexfont.numchars = 256; + hexfont.maxascii = 256; + hexfont.encoding = 32; + hexfont.glyph2ascii = malloc(sizeof(U16)*256); + hexfont.ascii2glyph = malloc(sizeof(int)*256); + hexfont.glyph = malloc(sizeof(SWFGLYPH)*256); + hexfont.glyphnames = malloc(sizeof(char*)*256); + hexfont.layout->bounds = malloc(sizeof(SRECT)*256); + hexfont.layout->kerningcount = 0; + hexfont.layout->kerning = 0; + int t; + int ymax =-0x7fffffff; + int ymin = 0x7fffffff; + for(t=0;t<256;t++) + { + char nr[5]; + nr[0] = '['; + nr[1] = hex[t/16]; + nr[2] = hex[t&15]; + nr[3] = ']'; + nr[4] = 0; + drawer_t draw; + swf_Shape01DrawerInit(&draw, 0); + swf_DrawText(&draw, font, (int)(10*20), nr); + draw.finish(&draw); + hexfont.glyph[t].shape = swf_ShapeDrawerToShape(&draw); + hexfont.layout->bounds[t] = swf_ShapeDrawerGetBBox(&draw); + hexfont.glyph[t].advance = hexfont.layout->bounds[t].xmax + hexfont.layout->bounds[t].xmin; + draw.dealloc(&draw); + hexfont.glyph2ascii[t] = t; + hexfont.ascii2glyph[t] = t; + hexfont.glyphnames[t] = strdup(nr); + if(hexfont.layout->bounds[t].ymax > ymax) + ymax = hexfont.layout->bounds[t].ymax; + if(hexfont.layout->bounds[t].ymin < ymin) + ymin = hexfont.layout->bounds[t].ymin; + if(t>=0xe4) { + hexfont.glyph2ascii[t] = 0; + } + } + + hexfont.layout->ascent = ymin<0?-ymin:0; + hexfont.layout->descent = ymax>0?ymax:0; + hexfont.layout->leading = hexfont.layout->ascent + hexfont.layout->descent; + + swf_WriteFont(&hexfont, "hexfont.swf"); + return 0; +} + diff -Nru swftools-0.9.2+ds1/lib/example/jpegtest.c swftools-0.9.1/lib/example/jpegtest.c --- swftools-0.9.2+ds1/lib/example/jpegtest.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/jpegtest.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,158 @@ +/* jpegtest.c + + Example for including and mapping jpeg images to swf shapes + + Part of the swftools package. + + Copyright (c) 2000, 2001 Rainer Böhme + + 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 "../rfxswf.h" + +#define WIDTH 256 +#define HEIGHT 256 +#define QUALITY 85 + +#define ID_BITS 1 +#define ID_SHAPE 2 + +int main( int argc, char ** argv) +{ SWF swf; + TAG* t; + RGBA rgb; + SHAPE* s; + MATRIX m; + SRECT r; + JPEGBITS* jpeg; + + int f; // file handle + + int ls; // line style + int fs; // fill style + int frame; + + memset(&swf,0x00,sizeof(SWF)); + + swf.fileVersion = 4; + swf.frameRate = 0x1800; + swf.movieSize.xmax = 20*WIDTH; + swf.movieSize.ymax = 20*HEIGHT; + + swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + t = swf.firstTag; + + rgb.r = 0xff; + rgb.b = 0xff; + rgb.g = 0xff; + swf_SetRGB(t,&rgb); + + t = swf_InsertTag(t,ST_DEFINEBITSJPEG2); + + swf_SetU16(t,ID_BITS); +// swf_SetJPEGBits(t,"test.jpg",QUALITY); <- use this to include an image from disk + +// That's the way to use memory bitmaps (24bit,RGB) + + jpeg = swf_SetJPEGBitsStart(t,WIDTH,HEIGHT,QUALITY); + { int y; + for (y=0;y +#include "../rfxswf.h" + +int main(int argn,char ** argv) +{ + int fi; + SWF swf; + TAG* tag; + char* outfilename = "test.swf"; + char*oldpassword = "fireworks"; + char*newpassword = "cyberdine"; + + if (argn<1) + { + return 0; + } + + fi = open(argv[1],O_RDONLY|O_BINARY); + + if (fi<=0) + { + fprintf(stderr,"Couldn't open %s\n", argv[1]); + } + + if(swf_ReadSWF(fi,&swf)<0) + { + fprintf(stderr,"%s is not a valid SWF file or contains errors.\n",argv[1]); + close(fi); + } + + tag = swf.firstTag; + + while(tag) { + TAG*next = tag->next; + //void swf_SetPassword(TAG * t, const char * password); + //int swf_VerifyPassword(TAG * t, const char * password); + if(tag->id == ST_PROTECT) { + int ret; + ret = swf_VerifyPassword(tag, oldpassword); + if(!ret) printf("Password validation failed\n"); + else printf("Password ok\n"); + + swf_DeleteTag(&swf, tag); + } + tag = next; + } + + tag = swf_InsertTag(swf.firstTag, ST_PROTECT); + swf_SetPassword(tag, newpassword); + + fi = open(outfilename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644); + if(fi<0) { + fprintf(stderr, "couldn't create output file %s", outfilename); + } + if(swf_WriteSWF(fi, &swf)<0) + fprintf(stderr, "WriteSWF() failed.\n"); + + close(fi); + + return 0; +} + diff -Nru swftools-0.9.2+ds1/lib/example/shape1.c swftools-0.9.1/lib/example/shape1.c --- swftools-0.9.2+ds1/lib/example/shape1.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/shape1.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,119 @@ +/* shape1.c + + Example implementation for drawing a shape with rfxswf + + Part of the swftools package. + + Copyright (c) 2000, 2001 Rainer Böhme + + 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 "../rfxswf.h" + + +int main (int argc,char ** argv) +{ SWF swf; + TAG* t; + RGBA rgb; + SRECT r; + SHAPE* s; + S32 width=300,height = 300; + + int f,i,ls1,ls2; + + memset(&swf,0x00,sizeof(SWF)); // set global movie parameters + + swf.fileVersion = 4; // make flash 4 compatible swf + swf.frameRate = 0x1900; // about 0x19 frames per second + + swf.movieSize.xmax = 20*width; // flash units: 1 pixel = 20 units + swf.movieSize.ymax = 20*height; + + swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + + // now create a tag list be connecting one after another + + t = swf.firstTag; + + rgb.r = 0xff; + rgb.g = 0xff; + rgb.b = 0xff; + swf_SetRGB(t,&rgb); + + t = swf_InsertTag(t,ST_DEFINESHAPE); + + swf_ShapeNew(&s); // create new shape instance + + // add two different linestyles + rgb.b = rgb.g = 0x00; + ls1 = swf_ShapeAddLineStyle(s,40,&rgb); + + rgb.r = 0; rgb.b = 0xff; + ls2 = swf_ShapeAddLineStyle(s,40,&rgb); + + swf_SetU16(t,1); // now set character ID + + r.xmin = 0; + r.ymin = 0; + r.xmax = 20*width; + r.ymax = 20*height; + + swf_SetRect(t,&r); // set shape bounds + + + swf_SetShapeHeader(t,s); // write all styles to tag + + swf_ShapeSetAll(t,s,0,0,ls1,0,0); // move to (0,0), select linestyle ls1 and no fillstyle + + + swf_ShapeSetLine(t,s,10*width,10*height); // draw something + swf_ShapeSetStyle(t,s,ls2,0,0); // change to second linestyle + + for (i=1;i<10;i++) + swf_ShapeSetCircle(t,s,10*width,10*height,i*width,i*height); + + swf_ShapeSetEnd(t); // finish drawing + + swf_ShapeFree(s); // clean shape structure (which isn't needed anymore after writing the tag) + + t = swf_InsertTag(t,ST_PLACEOBJECT2); // append tag to place your shape into the scene + + swf_ObjectPlace(t,1,1,NULL,NULL,NULL); // set character with id 1 (our shape) to depth 1 (upper most layer) + + t = swf_InsertTag(t,ST_SHOWFRAME); // finish current frame + + t = swf_InsertTag(t,ST_END); // finish current movie (which has just one frame) + +// swf_WriteCGI(&swf); <- use this to create direct CGI output + + // write movie to file + + f = open("shape1.swf",O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644); + if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed.\n"); + close(f); + + swf_FreeTags(&swf); // cleanup + +#ifdef __NT__ // start flash player to show result on windows systems + system("start ..\\shape1.swf"); +#endif + + return 0; +} + + diff -Nru swftools-0.9.2+ds1/lib/example/sound.c swftools-0.9.1/lib/example/sound.c --- swftools-0.9.2+ds1/lib/example/sound.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/sound.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,81 @@ +/* sound.c + + Generates a sine wave and tries to create an swf which + plays it as mp3 sound. + + Part of the swftools package. + + Copyright (c) 2002 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 "../rfxswf.h" + +int main (int argc,char ** argv) +{ SWF swf; + RGBA rgb; + SRECT r; + int blocksize = 2304; + S32 width=300,height = 300; + U16 block[blocksize]; + TAG * tag; + + int f,i,ls1,fs1; + int count; + int t; + + memset(&swf,0x00,sizeof(SWF)); // set global movie parameters + + swf.fileVersion = 4; // make flash 4 compatible swf + swf.frameRate = 18*256; // about 18 frames per second + + swf.movieSize.xmax = 20*width; // flash units: 1 pixel = 20 units ("twips") + swf.movieSize.ymax = 20*height; + + swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + tag = swf.firstTag; + rgb.r = 0xff; + rgb.g = 0xff; + rgb.b = 0xff; + swf_SetRGB(tag,&rgb); + + tag = swf_InsertTag(tag, ST_SOUNDSTREAMHEAD2); + swf_SetSoundStreamHead(tag, 11025/18); + + for(t=256;t>=0;t--) { + int s; + tag = swf_InsertTag(tag, ST_SOUNDSTREAMBLOCK); + for(s=0;s + + 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 "../rfxswf.h" + + +RGBA rgba(U8 r,U8 g,U8 b,U8 a) +{ RGBA c; c.r = r; c.g = g; c.b = b; c.a = a; + return c; +} + +U16 last_id; +U16 last_depth; + +#define GET_ID (last_id++) +#define GET_DEPTH (last_depth++) + +int main(int argc, char ** argv) +{ SWF swf; + RGBA rgb; + + TAG* t; + SHAPE* s; + SRECT r; + + U16 id_circle; + U16 id_sprite; + U16 id_sprite2; + + int ls,fs,i,j,f; + + U32 width = 400; + U32 height = 400; + + last_id = last_depth = 1; + + memset(&swf,0x00,sizeof(SWF)); + + swf.fileVersion = 4; + swf.frameRate = 0x1000; + swf.movieSize.xmax = width*20; + swf.movieSize.ymax = height*20; + + + t = swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + + rgb.r = rgb.g = rgb.b = rgb.a = 0xff; + swf_SetRGB(t,&rgb); + + t = swf_InsertTag(t,ST_DEFINESHAPE); + + swf_ShapeNew(&s); + rgb.b = rgb.g = 0x00; + ls = swf_ShapeAddLineStyle(s,40,&rgb); + + id_circle = GET_ID; + swf_SetU16(t,id_circle); + + r.xmin = 0; + r.ymin = 0; + r.xmax = width; + r.ymax = height; + swf_SetRect(t,&r); + + swf_SetShapeHeader(t,s); + swf_ShapeSetAll(t,s,0,0,ls,0,0); + swf_ShapeSetCircle(t,s,width/2,height/2,width/2,height/2); + swf_ShapeSetEnd(t); + + // SPRITE #1 TIMELINE + + t = swf_InsertTag(t,ST_DEFINESPRITE); + + id_sprite = GET_ID; + swf_SetU16(t,id_sprite); + swf_SetU16(t,32); // frame count + + for (i=0;i<32;i++) // 32 frames + { MATRIX m; + swf_GetMatrix(NULL,&m); + m.tx = width*2+(int)((float)width*2*sin((float)i/16*3.14152)); + m.ty = width*2+(int)((float)height*2*cos((float)i/16*3.14152)); + t = swf_InsertTag(t,ST_PLACEOBJECT2); + swf_ObjectPlace(t,(i==0)?id_circle:0,1,&m,NULL,NULL); + t = swf_InsertTag(t,ST_SHOWFRAME); + } + + t = swf_InsertTag(t,ST_END); + + // SPRITE #2 TIMELINE + + t = swf_InsertTag(t,ST_DEFINESPRITE); + + id_sprite2 = GET_ID; + swf_SetU16(t,id_sprite2); + swf_SetU16(t,80); // frame count + + for (i=0;i<80;i++) // 80 frames + { MATRIX m; + swf_GetMatrix(NULL,&m); + m.tx = width*4+(int)((float)width*4*sin((float)i/40*3.14152)); + m.ty = width*4+(int)((float)height*4*cos((float)i/40*3.14152)); + t = swf_InsertTag(t,ST_PLACEOBJECT2); + swf_ObjectPlace(t,(i==0)?id_sprite:0,1,&m,NULL,NULL); + m.sx *= -1; + m.tx += 4*width; + m.ty += 4*height; + t = swf_InsertTag(t,ST_PLACEOBJECT2); + swf_ObjectPlace(t,(i==0)?id_sprite:0,2,&m,NULL,NULL); + t = swf_InsertTag(t,ST_SHOWFRAME); + } + + t = swf_InsertTag(t,ST_END); + + // MAIN MOVIE TIMELINE + + t = swf_InsertTag(t,ST_PLACEOBJECT2); + + swf_ObjectPlace(t,id_sprite2,1,NULL,NULL,NULL); + + t = swf_InsertTag(t,ST_SHOWFRAME); // just one frame + + t = swf_InsertTag(t,ST_END); + +// swf_WriteCGI(&swf); + + f = open("sprites.swf",O_RDWR|O_CREAT|O_TRUNC|O_BINARY,0644); + if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed.\n"); + close(f); + + swf_FreeTags(&swf); + +#ifdef __NT__ + system("start ..\\sprites.swf"); +#endif + + return(0); +} + + diff -Nru swftools-0.9.2+ds1/lib/example/text.c swftools-0.9.1/lib/example/text.c --- swftools-0.9.2+ds1/lib/example/text.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/text.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,159 @@ +/* text.c + + Example for including and using fonts + + Part of the swftools package. + + Copyright (c) 2001 Rainer Böhme + + 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 "../rfxswf.h" + +#include "demofont.c" // five glyphs only: f, l, o, s, w + +/* + Due to copyright reasons we don't include full typesets into + the swftools package. But you can easily create fontdumps + of your desired typo: + + * Create a swf file with all characters of your desired fonts + (with any tool that can output swf files) + + * use the dumpfont example in this directory to dump font code + + * include dump code and adjust Font_() calls. + + Note: pdf2swf (Version 0.1.0) doesn't write ST_DEFINEFONTINFO tags, + so you can't extract fonts out of documents made with pdf2swf. + +*/ + +#define BANNER_TEXT "swftools" +#define ID_FONT 2000 +#define ID_BANNER 2001 + +int main(int argc, char ** argv) +{ SWF swf; + TAG * t; + SRECT r; + RGBA rgb; + U8 abits, gbits; + int definefont2 = 1; + + int f; + int width = 170; + int height = 60; + + int points = 50; // <- change global text size here + + int textsize = points*20; // adjust height + int textscale = points*10; // adjust spacing + + SWFFONT * font = Font_Demo_Font(ID_FONT); // change font name here + + /* adding layout to a font has the side effect that the + advance information is stored in the font itself, not + in accompanying textfields- this is needed e.g. for + edittext tags */ + if(definefont2) + swf_FontAddLayout(font,0,0,0); + + swf_FontInitUsage(font); + swf_FontUse(font,BANNER_TEXT); // SWF reduces font information to the used glyphs + swf_FontReduce(font); + + memset(&swf,0x00,sizeof(SWF)); + + swf.fileVersion = 4; + swf.frameRate = 0x4000; + swf.movieSize.xmax = 20*width; + swf.movieSize.ymax = 20*height; + + swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + t = swf.firstTag; + + rgb.r = 0xff; + rgb.g = 0xff; + rgb.b = 0xff; + swf_SetRGB(t,&rgb); + + if(definefont2) { + t = swf_InsertTag(t,ST_DEFINEFONT2); + swf_FontSetDefine2(t, font); + } else { + t = swf_InsertTag(t,ST_DEFINEFONT); + swf_FontSetDefine(t, font); + t = swf_InsertTag(t,ST_DEFINEFONTINFO); + swf_FontSetInfo(t, font); + } + + t = swf_InsertTag(t,ST_DEFINETEXT); + + swf_SetU16(t,ID_BANNER); // ID + + r.xmin = 0; + r.ymin = 0; + r.xmax = swf_TextGetWidth(font,BANNER_TEXT,textscale); + r.ymax = textsize; + + swf_SetRect(t,&r); + + swf_SetMatrix(t,NULL); + + swf_TextCountBits(font,BANNER_TEXT,textscale,&gbits,&abits); + + swf_SetU8(t,gbits); + swf_SetU8(t,abits); + + rgb.r = 0x00; + rgb.g = 0x00; + rgb.b = 0x00; + + swf_TextSetInfoRecord(t,font,textsize,&rgb,0,textsize); + swf_TextSetCharRecord(t,font,BANNER_TEXT,textscale,gbits,abits); + + swf_SetU8(t,0); + + + t = swf_InsertTag(t,ST_PLACEOBJECT2); + + swf_ObjectPlace(t,ID_BANNER,1,NULL,NULL,NULL); + + t = swf_InsertTag(t,ST_SHOWFRAME); + + t = swf_InsertTag(t,ST_END); + +// swf_WriteCGI(&swf); + + + f = open("text.swf",O_RDWR|O_CREAT|O_TRUNC|O_BINARY,0644); + if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed.\n"); + close(f); + + swf_FreeTags(&swf); +// swf_FontFree(font); + +#ifdef __NT__ + system("start ..\\text.swf"); +#endif + + return 0; +} + + diff -Nru swftools-0.9.2+ds1/lib/example/transtest.c swftools-0.9.1/lib/example/transtest.c --- swftools-0.9.2+ds1/lib/example/transtest.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/transtest.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,167 @@ +/* transtest.c + + Example for transforming a textured triangle + + Part of the swftools package. + + Copyright (c) 2001 Rainer Böhme + + 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 "../rfxswf.h" + +#define QUALITY 80 +#define ID_BITMAP 2004 +#define ID_SHAPE 2005 + + +int main (int argc,char ** argv) +{ SWF swf; + TAG* t; + RGBA rgb; + SRECT r; + SHAPE* s; + S32 width = 800,height = 800; + int fs,ls; // line & fillstyle + JPEGBITS* jpeg; + MATRIX m; + + int f,i,j,frame; + + memset(&swf,0x00,sizeof(SWF)); + + swf.fileVersion = 4; + swf.frameRate = 0x4000; + swf.movieSize.xmax = 4*width; + swf.movieSize.ymax = 4*height; + + swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + t = swf.firstTag; + + rgb.r = 0xff; + rgb.g = 0xff; + rgb.b = 0xff; + swf_SetRGB(t,&rgb); + + t = swf_InsertTag(t,ST_DEFINEBITSJPEG2); + + swf_SetU16(t,ID_BITMAP); + + if (FAILED(swf_SetJPEGBits(t,"texture.jpg",QUALITY))) + { fprintf(stderr,"Error: texture.jpg (256x256) not found in work directory.\n"); + exit(1); + } + + t = swf_InsertTag(t,ST_DEFINESHAPE); + + swf_ShapeNew(&s); + rgb.b = rgb.g = rgb.r = 0x00; + ls = 0; + rgb.b = 0xff; + + fs = swf_ShapeAddBitmapFillStyle(s,NULL,ID_BITMAP,0); + + swf_SetU16(t,ID_SHAPE); // ID + + r.xmin = 0; + r.ymin = 0; + r.xmax = 2*width; + r.ymax = 2*height; + + swf_SetRect(t,&r); + + swf_SetShapeHeader(t,s); + + swf_ShapeSetAll(t,s,0,0,ls,fs,0); + swf_ShapeSetLine(t,s,width,0); + swf_ShapeSetLine(t,s,-width,height); + swf_ShapeSetLine(t,s,0,-height); + swf_ShapeSetEnd(t); + + swf_ShapeFree(s); + + for (frame=0;frame<64;frame++) + { + + /* Test procedure for swf_MatrixJoin + + MATRIX m1,m2; + + // set m1 to left rotation + + m1.sy = m1.sx = (int)(cos(((float)(frame))/32*3.141)*0x10000); + m1.r0 = (int)(sin(((float)(frame))/32*3.141)*0x10000); + m1.r1 = -m1.r0; + m1.tx = width+frame*4; m1.ty = height; + + // set m2 to right rotation + + m2.sy = m2.sx = (int)(cos(((float)(64-frame))/32*3.141)*0x10000); + m2.r0 = (int)(sin(((float)(64-frame))/32*3.141)*0x10000); + m2.r1 = -m2.r0; + m2.tx = width; m2.ty = height; + + // joining m1 and m2 should lead to no transformation + + swf_MatrixJoin(&m,&m1,&m2); + + */ + + int dx0 = width; // constants of shape + int dy0 = width; + + int px0 = 2*width; // destination of mapping + int py0 = 2*width; + + int px1 = 3*width; + int py1 = 2*width-frame*4; + + int px2 = 2*width-frame*8; + int py2 = 3*width; + + swf_MatrixMapTriangle(&m,dx0,dy0,px0,py0,px1,py1,px2,py2); + + t = swf_InsertTag(t,ST_PLACEOBJECT2); + + if (!frame) + swf_ObjectPlace(t,ID_SHAPE,1,&m,NULL,NULL); + else + swf_ObjectMove(t,1,&m,NULL); + + t = swf_InsertTag(t,ST_SHOWFRAME); + } + + + t = swf_InsertTag(t,ST_END); + +// swf_WriteCGI(&swf); + + f = open("transtest.swf",O_RDWR|O_CREAT|O_TRUNC|O_BINARY,0644); + if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed.\n"); + close(f); + + swf_FreeTags(&swf); + +#ifdef __NT__ + system("start ..\\transtest.swf"); +#endif + + return 0; +} + + diff -Nru swftools-0.9.2+ds1/lib/example/zlibtest.c swftools-0.9.1/lib/example/zlibtest.c --- swftools-0.9.2+ds1/lib/example/zlibtest.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/example/zlibtest.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,217 @@ +/* zlibtest.c + + Little example for rfxswf's lossless bitmap functions. + This program creates a swf with three zlib compressed + images: 8 bit indexed, 16 and 32 bit + + Part of the swftools package. + + Copyright (c) 2001 Rainer Böhme + + 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 "../rfxswf.h" + +#define WIDTH 256 +#define HEIGHT 256 + +#define ID_BITS 1 +#define ID_SHAPE 16 + + +int main ( int argc, char ** argv) +{ SWF swf; + TAG* t; + RGBA rgb; + SHAPE* s; + MATRIX m; + SRECT r; + JPEGBITS* jpeg; + int i,f; + + int ls; // line style + int fs; // fill style + + int dx = 256; // bitmap size + int dy = 256; + int bps8, bps16, bps32; // bytes per scanline + + U8 * bitmap8; + U16 * bitmap16; + RGBA * bitmap32; + RGBA * pal; + + // create test texture + + bps8 = BYTES_PER_SCANLINE(dx*sizeof(U8)); + bps16 = BYTES_PER_SCANLINE(dx*sizeof(U16)); + bps32 = BYTES_PER_SCANLINE(dx*sizeof(U32)); + + pal = malloc(256*sizeof(RGBA)); + + bitmap8 = malloc(bps8*dy); + bitmap16 = malloc(bps16*dy); + bitmap32 = malloc(bps32*dy); + + if ((bitmap8) && (pal) && (bitmap16)) + { int x,y; + for (y=0;y>1)+x] = ((green/0x40)&0x03)| + ((red/4)&0x3f)<<2| + ((blue/8)&0x1f)<<8| + ((green/0x08)&0x07)<<13; + } + + for (y=0;y>2)+x].r = /*((x&0x10)==(y&0x10))?*/((x&4)==(y&4))?y:x; + bitmap32[y*(bps32>>2)+x].g = x; + bitmap32[y*(bps32>>2)+x].b = y; + } + + } + + // put texture into flash movie + + memset(&swf,0x00,sizeof(SWF)); + + swf.fileVersion = 4; + swf.frameRate = 0x1800; + swf.movieSize.xmax = 20*WIDTH; + swf.movieSize.ymax = 20*HEIGHT; + + swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + t = swf.firstTag; + + rgb.r = 0x00; + rgb.b = 0x00; + rgb.g = 0x00; + swf_SetRGB(t,&rgb); + + t = swf_InsertTag(t,ST_DEFINEBITSLOSSLESS); + + swf_SetU16(t,ID_BITS); + swf_SetLosslessBits(t,dx,dy,bitmap32,BMF_32BIT); + + t = swf_InsertTag(t,ST_DEFINEBITSLOSSLESS2); + + /* be careful with ST_DEFINEBITSLOSSLESS2, because + the Flash player produces great bugs if you use too many + alpha colors in your palette. The only sensible result that + can be archeived is setting one color to r=0,b=0,g=0,a=0 to + make transparent parts in sprites. That's the cause why alpha + handling is implemented in lossless routines of rfxswf. + */ + + swf_SetU16(t,ID_BITS+1); + swf_SetLosslessBitsIndexed(t,dx,dy,bitmap8,pal,256); + + t = swf_InsertTag(t,ST_DEFINEBITSLOSSLESS); + + swf_SetU16(t,ID_BITS+2); + swf_SetLosslessBits(t,dx,dy,bitmap16,BMF_16BIT); + + /* By the way: ST_DEFINELOSSLESS2 produces stange output on + 16 and 32 bits image data, too.... it seems that the + ming developers deal with the same problem. + */ + + for (i=0;i<9;i++) + { + t = swf_InsertTag(t,ST_DEFINESHAPE); + + swf_ShapeNew(&s); + rgb.b = rgb.g = rgb.r = 0x00; + ls = swf_ShapeAddLineStyle(s,10,&rgb); + + swf_GetMatrix(NULL,&m); + m.sx = (6*WIDTH/dx)<<16; + m.sy = (6*HEIGHT/dy)<<16; + + fs = swf_ShapeAddBitmapFillStyle(s,&m,ID_BITS+((i+(i/3))%3),0); + + swf_SetU16(t,ID_SHAPE+i); // ID + + r.xmin = 0; + r.ymin = 0; + r.xmax = 6*WIDTH; + r.ymax = 6*HEIGHT; + + swf_SetRect(t,&r); + + swf_SetShapeStyles(t,s); + swf_ShapeCountBits(s,NULL,NULL); + swf_SetShapeBits(t,s); + + swf_ShapeSetAll(t,s,0,0,ls,fs,0); + + swf_ShapeSetLine(t,s,6*WIDTH,0); + swf_ShapeSetLine(t,s,0,6*HEIGHT); + swf_ShapeSetLine(t,s,-6*WIDTH,0); + swf_ShapeSetLine(t,s,0,-6*HEIGHT); + swf_ShapeSetEnd(t); + + swf_GetMatrix(NULL,&m); + m.tx = (i%3) * (6*WIDTH+60); + m.ty = (i/3) * (6*HEIGHT+60); + + t = swf_InsertTag(t,ST_PLACEOBJECT2); + swf_ObjectPlace(t,ID_SHAPE+i,1+i,&m,NULL,NULL); + } + + t = swf_InsertTag(t,ST_SHOWFRAME); + + t = swf_InsertTag(t,ST_END); + +// swf_WriteCGI(&swf); + + f = open("zlibtest.swf",O_RDWR|O_CREAT|O_TRUNC|O_BINARY,0644); + if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed.\n"); + close(f); + + swf_FreeTags(&swf); + +#ifdef __NT__ + system("start ..\\zlibtest.swf"); +#endif + + free(pal); + free(bitmap8); + free(bitmap16); + free(bitmap32); + return 0; +} diff -Nru swftools-0.9.2+ds1/lib/gfxpoly/Makefile swftools-0.9.1/lib/gfxpoly/Makefile --- swftools-0.9.2+ds1/lib/gfxpoly/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/gfxpoly/Makefile 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,55 @@ +all: test speedtest stroke +include ../../Makefile.common + +CC = gcc -DCHECKS -O2 -g -pg +CCO = gcc -O2 -fno-inline -g -pg + +../libbase.a: ../q.c ../q.h ../mem.c ../mem.h + cd ..; make libbase.a + +../libgfx.a: ../gfxtools.h ../gfxtools.c ../gfxpoly.h ../gfxpoly.c + cd ..; make libgfx.a + +testheap: ../libbase.a testheap.c + $(CC) testheap.c ../libbase.a -o testheap -lm -lz -ljpeg + +SRC = active.c convert.c poly.c wind.c renderpoly.c xrow.c stroke.c moments.c +OBJS = active.o convert.o poly.o wind.o renderpoly.o xrow.o stroke.o moments.o + +active.o: active.c active.h poly.h Makefile + $(CC) -c active.c -o active.o + +convert.o: convert.c convert.h poly.h Makefile + $(CC) -c convert.c -o convert.o + +poly.o: poly.c poly.h active.h heap.h ../q.h Makefile + $(CC) -c poly.c -o poly.o + +wind.o: wind.c wind.h poly.h Makefile + $(CC) -c wind.c -o wind.o + +renderpoly.o: renderpoly.c wind.h poly.h renderpoly.h Makefile + $(CC) -c renderpoly.c -o renderpoly.o + +xrow.o: xrow.c xrow.h ../q.h ../mem.h Makefile + $(CC) -c xrow.c -o xrow.o + +stroke.o: stroke.c poly.h convert.h wind.h Makefile + $(CC) -c stroke.c -o stroke.o + +moments.o: moments.c moments.h ../q.h ../mem.h Makefile + $(CC) -c moments.c -o moments.o + +GFX=../gfxfont.o ../gfxtools.o ../gfximage.o ../devices/ops.o ../devices/polyops.o ../devices/text.o ../devices/bbox.o ../devices/render.o ../devices/rescale.o ../devices/record.o +stroke: test_stroke.c $(OBJS) ../libgfxswf.a ../librfxswf.a ../libbase.a + $(CC) test_stroke.c $(OBJS) ../libgfxswf.a ../librfxswf.a $(GFX) ../libbase.a -o stroke $(LIBS) + +SWF = ../librfxswf.a ../libgfxpdf.a -lstdc++ +test: ../libbase.a test.c $(OBJS) poly.h convert.h $(GFX) Makefile + $(CC) test.c $(OBJS) $(SWF) $(GFX) ../libbase.a -o test $(LIBS) + +speedtest: ../libbase.a speedtest.c $(SRC) poly.h convert.h $(GFX) + $(CCO) speedtest.c $(SRC) $(GFX) ../libbase.a -o speedtest $(LIBS) + +clean: + rm -f *.o test stroke diff -Nru swftools-0.9.2+ds1/lib/gfxpoly/speedtest.c swftools-0.9.1/lib/gfxpoly/speedtest.c --- swftools-0.9.2+ds1/lib/gfxpoly/speedtest.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/gfxpoly/speedtest.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include "../gfxtools.h" +#include "poly.h" +#include "convert.h" +#include "renderpoly.h" +#include "stroke.h" + +#ifdef CHECKS +#error "speedtest must be compiled without CHECKS" +#endif + +#ifdef DEBUG +#error "speedtest must be compiled without DEBUG" +#endif + +gfxline_t* mkchessboard() +{ + gfxline_t*b = 0; + int x,y; + unsigned int r = 0; + int spacing = 20; + + int num_caros = 40; + int l = 5; + char do_centerpiece=1; + + //int num_caros = 4; + //int l=1; + //char do_centerpiece=0; + + for(x=-l;x<=l;x++) + for(y=-l;y<=l;y++) { + /* pseudo random */ + r = crc32_add_byte(r, x);r = crc32_add_byte(r, y); + if(r&1) { + gfxline_t*box; + if(r&2) { + box = gfxline_makerectangle(x*spacing,y*spacing,(x+1)*spacing,(y+1)*spacing); + } else { + box = gfxline_makerectangle((x+1)*spacing,y*spacing,x*spacing,(y+1)*spacing); + } + b = gfxline_append(b, box); + } + } + + int t; + for(t=0;t>4)%10-5)*spacing; + int sizex = ((r>>8)%4)*spacing; + int sizey = sizex; + if(r&65536) + sizex = -sizex; + gfxline_t*l = malloc(sizeof(gfxline_t)*5); + l[0].type = gfx_moveTo;l[0].next = &l[1]; + l[1].type = gfx_lineTo;l[1].next = &l[2]; + l[2].type = gfx_lineTo;l[2].next = &l[3]; + l[3].type = gfx_lineTo;l[3].next = &l[4]; + l[4].type = gfx_lineTo;l[4].next = 0; + l[0].x = x; + l[0].y = y-sizey; + l[1].x = x+sizex; + l[1].y = y; + l[2].x = x; + l[2].y = y+sizey; + l[3].x = x-sizex; + l[3].y = y; + l[4].x = x; + l[4].y = y-sizey; + gfxline_append(b, l); + } + if(do_centerpiece) { + for(t=0;t<5;t++) { + gfxline_t*l = gfxline_makerectangle(-9*spacing,-10,9*spacing,10); + gfxmatrix_t matrix; + memset(&matrix, 0, sizeof(gfxmatrix_t)); + double ua=t*0.43; + matrix.m00=cos(ua);matrix.m10=sin(ua); + matrix.m01=-sin(ua);matrix.m11=cos(ua); + gfxline_transform(l, &matrix); + gfxline_append(b, l); + } + gfxline_append(b, gfxline_makecircle(100,100,100,100)); + } + return b; +} + +gfxline_t* make_circles(gfxline_t*b, int n) +{ + unsigned int c = 0; + int t; + for(t=0;t +#include +#include +#include +#include "../gfxtools.h" +#include "poly.h" +#include "convert.h" +#include "renderpoly.h" +#include "stroke.h" + +gfxline_t*mkstar(int x1, int y1, int x2, int y2) +{ + gfxline_t*l=0,*line = 0; + int x; + for(x=x1;x<=x2;x+=50) { + l = rfx_calloc(sizeof(gfxline_t)); + l->type = gfx_moveTo; + l->x = x;l->y = y1; + line = gfxline_append(line, l); + + l = rfx_calloc(sizeof(gfxline_t)); + l->type = gfx_lineTo; + l->x = x2-x;l->y = y2; + line = gfxline_append(line, l); + } + return line; +} + +gfxline_t* mkrandomshape(int range, int n) +{ + int i; + gfxline_t* line = malloc(sizeof(gfxline_t)*n); + for(i=0;i>4)%10-5)*spacing; + int sizex = ((r>>8)%4)*spacing; + int sizey = sizex; + if(r&65536) + sizex = -sizex; + gfxline_t*l = malloc(sizeof(gfxline_t)*5); + l[0].type = gfx_moveTo;l[0].next = &l[1]; + l[1].type = gfx_lineTo;l[1].next = &l[2]; + l[2].type = gfx_lineTo;l[2].next = &l[3]; + l[3].type = gfx_lineTo;l[3].next = &l[4]; + l[4].type = gfx_lineTo;l[4].next = 0; + l[0].x = x; + l[0].y = y-sizey; + l[1].x = x+sizex; + l[1].y = y; + l[2].x = x; + l[2].y = y+sizey; + l[3].x = x-sizex; + l[3].y = y; + l[4].x = x; + l[4].y = y-sizey; + gfxline_append(b, l); + } + if(do_centerpiece) { + for(t=0;t<5;t++) { + gfxline_t*l = gfxline_makerectangle(-9*spacing,-10,9*spacing,10); + gfxmatrix_t matrix; + memset(&matrix, 0, sizeof(gfxmatrix_t)); + double ua=t*0.43; + matrix.m00=cos(ua);matrix.m10=sin(ua); + matrix.m01=-sin(ua);matrix.m11=cos(ua); + gfxline_transform(l, &matrix); + gfxline_append(b, l); + } + gfxline_append(b, gfxline_makecircle(100,100,100,100)); + } + return b; +} + +gfxline_t* make_circles(int n) +{ + gfxline_t*b = 0; + unsigned int c = 0; + int t; + for(t=0;tstrokes; + for(;stroke;stroke=stroke->next) { + for(j=0;jnum_points-1;j++) { + point_t a = stroke->points[j]; + point_t b = stroke->points[j+1]; +#define ROTATE +#ifdef ROTATE + swf_ShapeSetMove(tag, s, a.y, a.x); + swf_ShapeSetLine(tag, s, b.y - a.y, b.x - a.x); +#else + swf_ShapeSetMove(tag, s, a.x, a.y); + swf_ShapeSetLine(tag, s, b.x - a.x, b.y - a.y); +#endif + } + } +#else + swf_ShapeSetAll(tag,s,0,0,ls,0,0); + edge_t*e = poly2->edges; + while(e) { + swf_ShapeSetMove(tag, s, e->a.x, e->a.y); + swf_ShapeSetLine(tag, s, e->b.x - e->a.x, e->b.y - e->a.y); + + swf_ShapeSetCircle(tag, s, e->a.x, e->a.y, 5*20, 5*20); + swf_ShapeSetCircle(tag, s, e->b.x, e->b.y, 5*20, 5*20); + e = e->next; + } +#endif + + swf_ShapeSetEnd(tag); + swf_ShapeFree(s); + + gfxpoly_destroy(poly1); + gfxpoly_destroy(poly2); + + gfxline_free(l); + + if(t) { + tag = swf_InsertTag(tag,ST_REMOVEOBJECT2); + swf_SetU16(tag, t); + } + tag = swf_InsertTag(tag,ST_PLACEOBJECT2); + swf_ObjectPlace(tag,t+1,t+1,NULL,NULL,NULL); + + tag = swf_InsertTag(tag, ST_SHOWFRAME); + } + tag = swf_InsertTag(tag, ST_END); + + swf_SaveSWF(&swf, "test.swf"); +} + +void rotate90(gfxpoly_t*poly) +{ + int i,j; + gfxpolystroke_t*stroke = poly->strokes; + for(;stroke;stroke=stroke->next) { + for(j=0;jnum_points;j++) { + point_t a = stroke->points[j]; + stroke->points[j].x = a.y; + stroke->points[j].y = a.x; + } + } +} + +#include +void test4(int argn, char*argv[]) +{ + char*dir = "ps"; + DIR*_dir = opendir(dir); + if(!_dir) return; + struct dirent*file; + while(1) { + file = readdir(_dir); + if (!file) + break; + if(!strstr(file->d_name, ".ps")) + continue; + + char* filename; + + if(argn<2) + filename = allocprintf("%s/%s", dir, file->d_name); + else + filename = argv[1]; + + windrule_t*rule = &windrule_evenodd; + gfxpoly_t*poly1 = gfxpoly_from_file(filename, 1.0);//0.01); + + if(argn!=2) + free(filename); + + double zoom = 1.0; + + if(!gfxpoly_check(poly1, 0)) { + printf("bad polygon\n"); + goto end_of_loop; + } + + gfxpoly_t*poly2 = gfxpoly_process(poly1, 0, rule, &onepolygon, 0); + gfxpoly_dump(poly2); + assert(gfxpoly_check(poly2, 1)); + + int pass; + for(pass=0;pass<2;pass++) { + intbbox_t bbox = intbbox_from_polygon(poly1, zoom); + unsigned char*bitmap1 = render_polygon(poly1, &bbox, zoom, rule, &onepolygon); + unsigned char*bitmap2 = render_polygon(poly2, &bbox, zoom, &windrule_circular, &onepolygon); + if(!bitmap_ok(&bbox, bitmap1) || !bitmap_ok(&bbox, bitmap2)) { + save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png"); + assert(!"error in bitmaps"); + } + if(!compare_bitmaps(&bbox, bitmap1, bitmap2)) { + save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png"); + assert(!"bitmaps don't match"); + } + free(bitmap1); + free(bitmap2); + + // second pass renders the 90° rotated version + rotate90(poly1); + rotate90(poly2); + } + + gfxpoly_destroy(poly1); + gfxpoly_destroy(poly2); + + end_of_loop: + if(argn==2) + break; + } + closedir(_dir); +} + +#include "../gfxdevice.h" +#include "../pdf/pdf.h" + +static int max_segments = 0; +static int max_any_segments = 0; +void extract_polygons_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) +{ + //gfxpoly_t*c = gfxpoly_from_fill(line, 0.05); + //gfxpoly_free(c); + + //gfxpoly_t*poly1 = gfxpoly_from_fill(line, 0.05); + gfxpoly_t*poly1 = gfxpoly_from_fill(line, 0.05); + + //gfxline_dump(line, stderr, ""); + //gfxpoly_dump(poly); + + int size = gfxpoly_size(poly1); + if(size == 4) { + //rectangles are boring. + gfxpoly_destroy(poly1); + return; + } + + max_any_segments = size > max_any_segments? size : max_any_segments; + if(size>100000) { + fprintf(stderr, "%d segments (skipping)\n", size); + return; + } else { + max_segments = size > max_segments? size : max_segments; + fprintf(stderr, "%d segments (max so far: %d/%d)\n", size, max_segments, max_any_segments); + } + + if(!gfxpoly_check(poly1, 0)) { + gfxpoly_destroy(poly1); + fprintf(stderr, "bad polygon\n"); + return; + } + + windrule_t*rule = &windrule_evenodd; + + double zoom = 1.0; + intbbox_t bbox = intbbox_from_polygon(poly1, zoom); + unsigned char*bitmap1 = render_polygon(poly1, &bbox, zoom, rule, &onepolygon); + if(!bitmap_ok(&bbox, bitmap1)) { + fprintf(stderr, "bad polygon or error in renderer\n"); + return; + } + gfxpoly_t*poly2 = gfxpoly_process(poly1, 0, rule, &onepolygon, 0); + unsigned char*bitmap2 = render_polygon(poly2, &bbox, zoom, &windrule_evenodd, &onepolygon); + if(!bitmap_ok(&bbox, bitmap2)) { + save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png"); + assert(!"error in bitmap"); + } + if(!compare_bitmaps(&bbox, bitmap1, bitmap2)) { + save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png"); + assert(!"bitmaps don't match"); + } + free(bitmap1); + free(bitmap2); + + gfxpoly_destroy(poly1); + gfxpoly_destroy(poly2); +} +int extract_polygons_setparameter(gfxdevice_t*dev, const char*key, const char*value) { + return 0; +} +void extract_polygons_startclip(gfxdevice_t*dev, gfxline_t*line) +{ + extract_polygons_fill(dev, line, 0); +} +void extract_polygons_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*imgcoord2devcoord, gfxcxform_t*cxform) +{ + extract_polygons_fill(dev, line, 0); +} +void extract_polygons_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*gradcoord2devcoord) +{ + extract_polygons_fill(dev, line, 0); +} +void extract_polygons_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action, const char*text) +{ + extract_polygons_fill(dev, line, 0); +} +void extract_polygons_addfont(gfxdevice_t*dev, gfxfont_t*font) +{ + int t; + for(t=0;tnum_glyphs;t++) { + //extract_polygons_fill(dev, font->glyphs[t].line, 0); + } +} +void extract_polygons_endclip(gfxdevice_t*dev) +{ +} +void extract_polygons_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit) +{ +} +void extract_polygons_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix) +{ +} + +gfxdevice_t extract_polygons = +{ +name: "extract polygons", +setparameter:extract_polygons_setparameter, +startclip: extract_polygons_startclip, +endclip: extract_polygons_endclip, +stroke: extract_polygons_stroke, +fill: extract_polygons_fill, +fillbitmap: extract_polygons_fillbitmap, +fillgradient: extract_polygons_fillgradient, +addfont: extract_polygons_addfont, +drawchar: extract_polygons_drawchar, +drawlink: extract_polygons_drawlink, +startpage: 0, +endpage: 0, +geterror: 0, +finish: 0, +internal: 0 +}; + +#if 0 +void test5(int argn, char*argv[]) +{ + gfxsource_t*driver = gfxsource_pdf_create(); + char*dir = "pdfs"; + DIR*_dir = opendir(dir); + if(!_dir) return; + struct dirent*file; + while(1) { + file = readdir(_dir); + if (!file) + break; + if(!strstr(file->d_name, ".pdf")) + continue; + char* filename = allocprintf("%s/%s", dir, file->d_name); + + if(argn>1) + filename = argv[1]; + + gfxdocument_t*doc = driver->open(driver, filename); + gfxdevice_t*out = &extract_polygons; + int t; + for(t=1;t<=doc->num_pages;t++) { + fprintf(stderr, "%s (page %d)\n", filename, t); + gfxpage_t* page = doc->getpage(doc, t); + page->render(page, out); + page->destroy(page); + } + doc->destroy(doc); + if(argn>1) + break; + free(filename); + } + closedir(_dir); + driver->destroy(driver); +} +#endif + +int main(int argn, char*argv[]) +{ + test_area(argn, argv); +} + diff -Nru swftools-0.9.2+ds1/lib/gfxpoly/test_stroke.c swftools-0.9.1/lib/gfxpoly/test_stroke.c --- swftools-0.9.2+ds1/lib/gfxpoly/test_stroke.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/gfxpoly/test_stroke.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,201 @@ +#include +#include "../gfxtools.h" +#include "convert.h" +#include "stroke.h" +#include "convert.h" + +int test_stroke1() +{ + gfxline_t l[512], f[256*5]; + + int width=700,height=700; + gfxdevice_t dev; + gfxdevice_swf_init(&dev); + dev.setparameter(&dev, "framerate", "25.0"); + dev.setparameter(&dev, "disable_polygon_conversion", "1"); + int t; + for(t=0;t<300;t++) { + dev.startpage(&dev, 700,700); + /*gfxline_t*g = l; + while(g) { + g->x += g->sx; + g->y += g->sy; + if(g->sx || g->sy) { + if(g->x<200) {g->x=400-g->x;g->sx=-g->sx;} + if(g->y<200) {g->y=400-g->y;g->sy=-g->sy;} + if(g->x>500) {g->x=1000-g->x;g->sx=-g->sx;} + if(g->y>500) {g->y=1000-g->y;g->sy=-g->sy;} + } + g = g->next; + }*/ + + int i; + for(i=0;i<512;i++) { + double a = i*0.05+t*M_PI/150; + double r = 50+i*0.5; + l[i].x = cos(a)*r + width/2; + l[i].y = sin(a)*r + height/2; + l[i].sx = (int)((l[i].x-width/2)/30); + l[i].sy = (int)((l[i].y-height/2)/30); + l[i].sx = l[i].sy = 0; + l[i].type = gfx_lineTo; + l[i].next = &l[i+1]; + } + l[0].type = gfx_moveTo; + l[i-1].next = 0; + + int xx,yy; + i = 0; + for(yy=0;yy<16;yy++) + for(xx=0;xx<16;xx++) if((xx^yy)&1) { + double x = -128+xx*64+t*128.0/300; + double y = -128+yy*64;//+t*64.0/300; + f[i].x = x; + f[i].y = y; + f[i].next = &f[i+1];f[i++].type = gfx_moveTo; + f[i].x = x+64; + f[i].y = y; + f[i].next = &f[i+1];f[i++].type = gfx_lineTo; + f[i].x = x+64; + f[i].y = y+64; + f[i].next = &f[i+1];f[i++].type = gfx_lineTo; + f[i].x = x; + f[i].y = y+64; + f[i].next = &f[i+1];f[i++].type = gfx_lineTo; + f[i].x = x; + f[i].y = y; + f[i].next = &f[i+1];f[i++].type = gfx_lineTo; + } + f[i-1].next = 0; + + double width = 40; + + //gfxdrawer_t d; + //gfxdrawer_target_gfxline(&d); + //draw_stroke(l, &d, width, gfx_capRound, gfx_joinBevel, 500); + //gfxline_t*line = (gfxline_t*)d.result(&d); + + //gfxpoly_t*p = gfxpoly_fromstroke(l, width, gfx_capRound, gfx_joinRound, 500); + gfxpoly_t*p1 = gfxpoly_from_stroke(l, width, gfx_capRound, gfx_joinRound, 500, 0.05); + assert(gfxpoly_check(p1, 1)); + + //gfxpoly_t*p2 = gfxpoly_from_fill(f, 0.05); + gfxline_t*l2 = gfxline_clone(l); + + double c = cos(t*M_PI/50.0); + double s = sin(t*M_PI/50.0); + static int x1 = 0, xdir = 1; + static int y1 = 0, ydir = 5; + x1 = sin(t*M_PI/60.0)*50; + y1 = -sin(t*M_PI/50.0)*50; + gfxmatrix_t m = { c, s, -(350+x1)*c-(350+y1)*s+350, + s, -c, -(350+x1)*s+(350+y1)*c+350}; + gfxline_transform(l2, &m); + gfxpoly_t*p2 = gfxpoly_from_stroke(l2, width, gfx_capRound, gfx_joinRound, 500, 0.05); + assert(gfxpoly_check(p2, 1)); + + gfxpoly_t*p3 = gfxpoly_intersect(p1, p2); + assert(gfxpoly_check(p3, 1)); + + //gfxpoly_t*p4 = gfxpoly_from_fill(f, 0.05); + //gfxpoly_t*p5 = gfxpoly_intersect(p1, p4); + + gfxline_t*line = gfxline_from_gfxpoly(p3); + gfxpoly_destroy(p1); + gfxpoly_destroy(p2); + gfxpoly_destroy(p3); + + //gfxline_dump(line, stdout, ""); + + gfxcolor_t blue = {255,0,0,255}; + gfxline_t*r = gfxline_makerectangle(0,0,700,700); + dev.fill(&dev, r, &blue); + + gfxcolor_t black = {255,0,0,64}; + gfxcolor_t white = {255,255,255,255}; + gfxcolor_t cyan = {255,0,192,192}; + //dev.stroke(&dev, l, 2, &black, gfx_capRound, gfx_joinRound, 0); + //dev.stroke(&dev, line, 2, &cyan, gfx_capRound, gfx_joinRound, 0); + dev.fill(&dev, line, &black); + gfxmatrix_t m2 = {1.0, 0, -10, + 0, 1.0, -10}; + gfxline_transform(line, &m2); + dev.fill(&dev, line, &cyan); + dev.stroke(&dev, line, 2.0, &white, gfx_capRound, gfx_joinRound, 0); + + gfxline_free(line); + dev.endpage(&dev); + } + + gfxresult_t* result = dev.finish(&dev); + result->save(result, "test.swf"); + result->destroy(result); +} + +int test_stroke2() +{ + gfxline_t l[4]; + l[0].type = gfx_moveTo; + l[0].x = 100;l[0].sx=2; + l[0].y = 100;l[0].sy=2; + l[0].next = &l[1]; + l[1].type = gfx_lineTo; + l[1].x = 100;l[1].sx=2; + l[1].y = 200;l[1].sy=-2; + l[1].next = &l[2]; + l[2].type = gfx_lineTo; + l[2].x = 250;l[2].sx=4; + l[2].y = 200;l[2].sy=0; + l[2].next = &l[3]; + l[3].type = gfx_lineTo; + l[3].x = 200;l[3].sx=0; + l[3].y = 150;l[3].sy=4; + l[3].next = 0; + + + gfxdevice_t dev; + gfxdevice_swf_init(&dev); + dev.setparameter(&dev, "framerate", "25.0"); + int t; + for(t=0;t<300;t++) { + dev.startpage(&dev, 700,700); + gfxline_t*g = l; + while(g) { + g->x += g->sx; + g->y += g->sy; + if(g->x<200) {g->x=400-g->x;g->sx=-g->sx;} + if(g->y<200) {g->y=400-g->y;g->sy=-g->sy;} + if(g->x>500) {g->x=1000-g->x;g->sx=-g->sx;} + if(g->y>500) {g->y=1000-g->y;g->sy=-g->sy;} + g = g->next; + } + //l[3].x = l[0].x; + //l[3].y = l[0].y; + + gfxdrawer_t d; + gfxdrawer_target_gfxline(&d); + double width = t/3.0; + if(width>50) width=100-width; + width = 40; + + draw_stroke(l, &d, width, gfx_capSquare, gfx_joinMiter, 500); + gfxline_t*line = (gfxline_t*)d.result(&d); + //gfxline_dump(line, stdout, ""); + + gfxcolor_t black = {255,0,0,0}; + gfxcolor_t cyan = {255,0,128,128}; + dev.stroke(&dev, l, 2, &black, gfx_capRound, gfx_joinRound, 0); + dev.stroke(&dev, line, 2, &cyan, gfx_capRound, gfx_joinRound, 0); + gfxline_free(line); + dev.endpage(&dev); + } + + gfxresult_t* result = dev.finish(&dev); + result->save(result, "test.swf"); + result->destroy(result); +} + +int main() +{ + test_stroke2(); +} diff -Nru swftools-0.9.2+ds1/lib/gfxwindow.c swftools-0.9.1/lib/gfxwindow.c --- swftools-0.9.2+ds1/lib/gfxwindow.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/gfxwindow.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,27 @@ +/* gfxwindow.h + + Simple GUI abstraction. + + Part of the swftools package. + + Copyright (c) 2005 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 */ + +#ifdef WIN32 +#include "gfxwindow_win32.c" +#else +#include "gfxwindow_unix.c" +#endif diff -Nru swftools-0.9.2+ds1/lib/gfxwindow.h swftools-0.9.1/lib/gfxwindow.h --- swftools-0.9.2+ds1/lib/gfxwindow.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/gfxwindow.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,73 @@ +/* gfxwindow.h + + Simple GUI abstraction. + + Part of the swftools package. + + Copyright (c) 2005 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 __gfxwindow_h__ +#define __gfxwindow_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define GFXEVENT_NOTHING 0 + +#define GFXEVENT_KEY 4 +#define GFXEVENT_KEYPRESS 4 +#define GFXEVENT_KEYRELEASE 5 + +#define GFXEVENT_MOUSEPRESS 8 +#define GFXEVENT_MOUSERELEASE 9 +#define GFXEVENT_MOUSEMOVE 10 +#define GFXEVENT_MOUSEENTER 11 +#define GFXEVENT_MOUSELEAVE 12 + +#define GFXEVENT_DESTROY 16 + +typedef struct _gfxevent +{ + void * internal; + int type; + int key; //if type == KEY + int x,y; //if type == MOUSEMOVED + int button; //if type = MOUSEPRESSED/RELEASED +} gfxevent_t; + +typedef struct _gfxwindow +{ + void * internal; + unsigned char* currentscr; + unsigned char* lastscr; + int width; + int height; + void (*flippage)(struct _gfxwindow*win); + void (*move)(struct _gfxwindow*win,int x, int y); + void (*resize)(struct _gfxwindow*win,int width, int height); + gfxevent_t (*getEvent)(struct _gfxwindow*win); + void (*destroy)(struct _gfxwindow*win); +} gfxwindow_t; + +gfxwindow_t* gfxwindow_new(int width, int height); + +#ifdef __cplusplus +} +#endif + +#endif diff -Nru swftools-0.9.2+ds1/lib/gfxwindow_unix.c swftools-0.9.1/lib/gfxwindow_unix.c --- swftools-0.9.2+ds1/lib/gfxwindow_unix.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/gfxwindow_unix.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,857 @@ +/* gfxwindow.h + + Simple GUI abstraction- Unix implementation + + Part of the swftools package. + + Copyright (c) 2005 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 +#include +#include +#include +#include +#include +#include +#include "gfxwindow.h" +#include "types.h" + +#define USE_SHM 1 +#define USE_PIXMAP 1 // use pixmap instead of ximage for off-screen rendering + +#define initMutex(mutex) {pthread_mutex_init(mutex, 0);} +#define destroyMutex(mutex) {pthread_mutex_destroy((mutex));} +#define lockMutex(mutex) pthread_mutex_lock(mutex) +#define unlockMutex(mutex) pthread_mutex_unlock(mutex) + +typedef struct _queue +{ + char* data; + int readpos; + int writepos; + int number; + int size; + int nmemb; + pthread_mutex_t mutex; +} queue_t; + + +queue_t* queue_init(int size, int nmemb) +{ + queue_t* queue = malloc(sizeof(queue_t)); + queue->data = (char*)malloc(size * nmemb); + queue->size = size; + queue->nmemb = nmemb; + queue->readpos = 0; + queue->writepos = 0; + queue->number = 0; + initMutex(&queue->mutex); + return queue; +} + +void queue_destroy(queue_t*queue) +{ + free(queue->data);queue->data = 0; + destroyMutex(&queue->mutex); + memset(queue, 0, sizeof(queue_t)); +} + +int queue_put(queue_t*queue, void*data) +{ + int tmp = queue->writepos+1; + tmp%=queue->nmemb; + + lockMutex(&queue->mutex); + if(tmp==queue->readpos) { + unlockMutex(&queue->mutex); + return 0; + } + memcpy(&queue->data[queue->writepos*queue->size], data, queue->size); + queue->writepos = tmp; + queue->number++; + unlockMutex(&queue->mutex); + return 1; +} + +int queue_get(queue_t*queue, void*data) +{ + lockMutex(&queue->mutex); + if(queue->writepos == queue->readpos) { + unlockMutex(&queue->mutex); + return 0; + } + memcpy(data, &queue->data[queue->readpos*queue->size], queue->size); + queue->readpos++; + queue->readpos %= queue->nmemb; + queue->number--; + unlockMutex(&queue->mutex); + return 1; +} + +void queue_flush(queue_t*queue) +{ + lockMutex(&queue->mutex); + queue->number = 0; + queue->readpos = 0; + queue->writepos = 0; + unlockMutex(&queue->mutex); +} + +int queue_num(queue_t*queue) +{ + return queue->number; +} + +static int initializexwindows(); + +struct _QXWindow; +struct X +{ + char isnative24; + char isnative16; + char isnative8; + int bpp; + int bypp; + Atom atom_wm; + Atom atom_wmdelete; + + int rootsizex; + int rootsizey; + + Display *d; + Window root; + int s; + Visual*v; + + char running; + pthread_t eventhandler; + pthread_mutex_t xmutex; + + struct _QXWindow*windowring; + + int stopall; + Colormap cmap; + U32 white; + U32 black; +}; +static struct X X; + +static int initialized = 0; + +void destroyX() { + X.stopall=1; + if(X.running) + pthread_cancel(X.eventhandler); + if(X.d) + XCloseDisplay(X.d); + pthread_mutex_destroy(&X.xmutex); +} + +typedef struct _QXWindow { + struct _QXWindow*next; + struct _QXWindow*prev; + + XWMHints *xwmh; + XClassHint *xch; + + GC gc; + //XFontStruct *xfs; + + XSetWindowAttributes xswa; + XWindowAttributes xwa; + +#ifdef USE_PIXMAP + Pixmap offscreen_pixmap; +#else + XImage* offscreen_ximage; +#endif + + U8*currentscr; + + int x,y; + int lenx,leny; + int bpp; + int bypp; + Window mywin; + XGCValues xgcv; + XSizeHints *xsh; + + pthread_mutex_t wmutex; + + queue_t* queue; +} QXWindow; + +static int lastbit(U32 bits) +{ + int t; + for(t=0;t<32;t++) + { + if(bits&1) break; + bits>>=1; + } + return t; +} + +static int firstbit(U32 bits) +{ + int t,s=-1; + for(t=0;t<32;t++) + { + if(bits&1) s=t; + bits>>=1; + } + return s; +} + +static U32 shiftl(U32 bits,int shift) +{ + if(shift>0) return bits<>-shift; +} + +static U32 getColorFromRGB(U8 r,U8 g,U8 b) +{ + U32 ret=0; + ret|=shiftl(r,(firstbit(X.v->red_mask)-7))&X.v->red_mask; + ret|=shiftl(g,(firstbit(X.v->green_mask)-7))&X.v->green_mask; + ret|=shiftl(b,(firstbit(X.v->blue_mask)-7))&X.v->blue_mask; + return ret; +} + +static void whatever() +{ + XrmValue xrmvalue; + XrmDatabase rdb; + return; +} + +static void*eventloop(void*); +static int debug; +static int initializexwindows() +{ + if(initialized) + return 1; + X.windowring=0; + X.d=0; + X.running=0; + pthread_mutex_init(&X.xmutex, 0); + + //whatever(); + /* open display, and show some information */ + X.d=XOpenDisplay(0);//getenv("DISPLAY")); + if(!X.d) {return 0;} +/* printf("Xprotocol V%d.%d Vendor:%s Name:%s Defaults:%s",X.d->proto_major_version, + X.d->proto_minor_version, + X.d->vendor,X.d->display_name,X.d->defaults); + int t; + printf("Formats:\n"); + for(t=0;tnformats;t++) { + ScreenFormat*sf=&X.d->pixmap_formats[t]; + printf("%d:depth:%d, bpp:%d, scanline:%d\n",sf->depth,sf->bits_per_pixel,sf->scanline_pad); + } + printf("Screens:\n"); + for(t=0;tnscreens;t++) { + Screen*s=&X.d->screens[t]; + printf("%d*%d, bpp:%d\n",s->width,s->height,s->root_depth); + }*/ + + /* open screen */ + X.s=DefaultScreen(X.d); + if(debug) printf("Display:\n"); + int xbig=DisplayWidth(X.d, X.s); + int ybig=DisplayHeight(X.d, X.s); + X.rootsizex=xbig; + X.rootsizey=ybig; + int bppbig=X.bpp=DisplayPlanes(X.d, X.s); + if(X.bpp==24) X.bypp=4; //Can this be 3, also? + if(X.bpp==16) X.bypp=2; + if(X.bpp==8) X.bypp=1; + if(debug) printf("%d*%d:%d/%d/%d\n",xbig,ybig,bppbig, X.bpp, X.bypp); + if(debug) printf("%d screens, vendor:%s, Ver:%d.%d(%d), at %s\n", + ScreenCount(X.d), + ServerVendor(X.d), + ProtocolVersion(X.d), + ProtocolRevision(X.d), + VendorRelease(X.d), + DisplayString(X.d)); + + /* open visual */ + X.v=XDefaultVisualOfScreen(DefaultScreenOfDisplay(X.d)); + + X.isnative24 = (bppbig==24 && X.v->red_mask==0xff0000 && + X.v->green_mask==0x00ff00 && + X.v->blue_mask==0x0000ff); + X.isnative16 = (bppbig==16 && X.v->red_mask==0xf800 && + X.v->green_mask==0x07e0 && + X.v->blue_mask==0x1f); + X.isnative8 = (bppbig==8); + if(debug) printf("8bpp:%d 16bpp:%d 24(32)bpp:%d\n",X.isnative8,X.isnative16,X.isnative24); + + X.root=DefaultRootWindow(X.d); + if(!X.root) {return 0;} + + X.atom_wm = XInternAtom( X.d, "WM_PROTOCOLS", False ); + X.atom_wmdelete = XInternAtom( X.d, "WM_DELETE_WINDOW", False ); + + X.cmap=DefaultColormap(X.d,X.s); + X.white=WhitePixel(X.d,X.s); + X.black=BlackPixel(X.d,X.s); + + /* start event handler thread */ + X.running = 1; + pthread_create(&X.eventhandler,0,eventloop,0); + + X.stopall=0; + + initialized=1; + return 1; +} + +//needed to set the border attribute +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_HINTS_INPUT_MODE (1L << 2) +#define MWM_HINTS_STATUS (1L << 3) + +#define MWM_FUNC_ALL (1L << 0) +#define MWM_FUNC_RESIZE (1L << 1) +#define MWM_FUNC_MOVE (1L << 2) +#define MWM_FUNC_MINIMIZE (1L << 3) +#define MWM_FUNC_MAXIMIZE (1L << 4) +#define MWM_FUNC_CLOSE (1L << 5) + +#define MWM_DECOR_ALL (1L << 0) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) + +#define MWM_INPUT_MODELESS 0 +#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 +#define MWM_INPUT_SYSTEM_MODAL 2 +#define MWM_INPUT_FULL_APPLICATION_MODAL 3 +#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL + +typedef struct _mwmhints { + unsigned int flags; + unsigned int functions; + unsigned int decorations; + int input_mode; + unsigned int status; +} MWMHints; + +static QXWindow* openwindow(int posx,int posy,int w,int h,char*winName) +{ + int noborder = 0; + XTextProperty iname; + XTextProperty wname; + + pthread_mutex_lock(&X.xmutex); + + if(!initialized) { + fprintf(stderr, "Error: XWindows not yet initialized!\n"); + pthread_mutex_unlock(&X.xmutex); + return 0; + } + + QXWindow*qx= malloc(sizeof(QXWindow)); + if(!X.windowring) { + qx->next=qx; + qx->prev=qx; + X.windowring=qx; + } else { + qx->next=X.windowring; + qx->prev=X.windowring->prev; + qx->prev->next=qx; + X.windowring->prev=qx; + X.windowring=qx; + } + + char*iconName=winName; + qx->x = posx; + qx->y = posy; + qx->lenx=w; + qx->leny=h; + + qx->mywin=0; + qx->mywin=XCreateSimpleWindow(X.d,X.root,posx,posy,qx->lenx,qx->leny,0,X.white,X.black); + + if(!qx->mywin) { + printf("Error: Couldn't create SimpleWindow\n"); + pthread_mutex_unlock(&X.xmutex); + return 0; + } + qx->xwmh=XAllocWMHints(); + qx->xsh=XAllocSizeHints(); + qx->xch=XAllocClassHint(); + + qx->xsh->flags=(PPosition|PSize|PMinSize|PMaxSize); + qx->xsh->height=qx->xsh->min_height=qx->xsh->max_height=h; + qx->xsh->width =qx->xsh->min_width =qx->xsh->max_width =w; + qx->xsh->x=0; + qx->xsh->y=0; + + if(!XStringListToTextProperty(&winName, 1, &wname)) { + printf("Error: XStringToTextProperty failed\n"); + pthread_mutex_unlock(&X.xmutex); + return 0; + } + if(!XStringListToTextProperty(&iconName, 1, &iname)) { + printf("Error: XStringToTextProperty failed\n"); + pthread_mutex_unlock(&X.xmutex); + return 0; + } + + XSetWMProperties(X.d,qx->mywin,&wname,&iname,0,0,qx->xsh,qx->xwmh,qx->xch); + + qx->xgcv.foreground=X.white; + qx->xgcv.background=X.black; + //qx->gc=XDefaultGC(X.d,qx->mywin); + qx->gc=XCreateGC(X.d,qx->mywin,GCForeground|GCBackground,&qx->xgcv); + + XGetWindowAttributes(X.d,qx->mywin,&qx->xwa); + + // enable events for close window + XChangeProperty(X.d, qx->mywin, X.atom_wm, XA_ATOM, 32, PropModeReplace, (unsigned char *)(&X.atom_wmdelete), 1 ); + + // no border + // (This code comes from the project xine (xine.sourceforge.net) + // I wonder if this works with all windowmanagers, though) + if(noborder>0) + { + Atom atomprop = XInternAtom(X.d, "_MOTIF_WM_HINTS", True); + if(atomprop) + { + MWMHints mwmhints; + mwmhints.flags = MWM_HINTS_DECORATIONS; + if(noborder==1) mwmhints.decorations = 2; + if(noborder>1) mwmhints.decorations = 0; + XChangeProperty(X.d, qx->mywin, atomprop, atomprop, 32, + PropModeReplace, (unsigned char *) &mwmhints, 5); + XSetTransientForHint (X.d, qx->mywin, X.root); + } + } + + qx->bpp=qx->xwa.depth; + if(qx->bpp==24) qx->bypp=4; //Can this be 3, also? + if(qx->bpp==16) qx->bypp=2; + if(qx->bpp==8) qx->bypp=1; + +#ifdef USE_SHM + XShmSegmentInfo segInfo; + int bpl = qx->lenx*qx->bypp; + segInfo.readOnly = 0; + segInfo.shmid = shmget(IPC_PRIVATE,qx->leny*bpl,IPC_CREAT|0777); + struct shmid_ds buf; + if (segInfo.shmid <0) { + perror("shmget"); + fprintf(stderr,"Size = %d x %d\n", qx->lenx, qx->leny); + } + segInfo.shmaddr = (char*)shmat (segInfo.shmid, 0, 0); + if ((long)segInfo.shmaddr == -1) { + perror("shmat"); + } + XShmAttach(X.d, &segInfo); + if (shmctl(segInfo.shmid, IPC_RMID, &buf) < 0) + perror("shmctl"); + + qx->currentscr = (U8*)segInfo.shmaddr; + +# ifdef USE_PIXMAP + qx->offscreen_pixmap = XShmCreatePixmap(X.d,qx->mywin,segInfo.shmaddr,&segInfo,qx->lenx,qx->leny,DefaultDepth(X.d, DefaultScreen(X.d))); +# else + qx->offscreen_ximage = XShmCreateImage(X.d,X.v,24,ZPixmap,(char*)segInfo.shmaddr, &segInfo, qx->lenx,qx->leny); + XInitImage(qx->offscreen_ximage); +# endif + +#else + + qx->currentscr = malloc(qx->lenx*qx->leny*4); +# ifdef USE_PIXMAP + qx->offscreen_pixmap = XCreatePixmapFromBitmapData(X.d,qx->mywin,qx->currentscr,qx->lenx,qx->leny,0,0,DefaultDepth(X.d,X.s)); +# else + qx->offscreen_ximage = XCreateImage(X.d,X.v,24,ZPixmap,0,(char*)qx->currentscr,qx->lenx,qx->leny,8,qx->lenx*4); + XInitImage(qx->offscreen_ximage); +# endif + +#endif + XSync(X.d, False); + + /* get the image data for the area this window will be/is placed on */ + /*{ + Window tmpwin; + XImage*background; + int x,y; + XTranslateCoordinates(X.d,qx->mywin,X.root,0,0,&x,&y,&tmpwin); + qx->background = XGetImage(X.d, DefaultRootWindow(X.d), x, y, qx->lenx, qx->leny, AllPlanes, ZPixmap); + printf("%d %d\n",x,y); + }*/ + + XMapRaised(X.d,qx->mywin); + XFlush(X.d); + + qx->xswa.event_mask=(qx->xwa.your_event_mask|= + ButtonPressMask| + ButtonReleaseMask| + //ExposureMask| + KeyPressMask| + MotionNotify| + EnterWindowMask| + LeaveWindowMask| + PointerMotionMask + ); + XChangeWindowAttributes(X.d,qx->mywin,CWEventMask,&qx->xswa); + + qx->queue = queue_init(sizeof(gfxevent_t), 256); + + pthread_mutex_unlock(&X.xmutex); + + pthread_mutex_init(&qx->wmutex, 0); + return qx; +} + +static void closeWindow(QXWindow*qx) +{ + if(qx->mywin) { + pthread_mutex_lock(&X.xmutex); + XDestroyWindow(X.d,qx->mywin); + pthread_mutex_unlock(&X.xmutex); + qx->mywin = 0; + } +} + +static void processEvent(gfxevent_t*event) +{ + fd_set fdset; + struct timeval de; + int status; + + XEvent xe; + + FD_ZERO(&fdset); + FD_SET(ConnectionNumber(X.d),&fdset); + de.tv_sec = 0; + de.tv_usec = 5000; // 1/200 s + + pthread_mutex_lock(&X.xmutex); + FD_ZERO(&fdset); + FD_SET(ConnectionNumber(X.d),&fdset); + de.tv_sec = de.tv_usec = 0; + if(!select(ConnectionNumber(X.d)+1, &fdset, 0, 0, &de)) { + pthread_mutex_unlock(&X.xmutex); + usleep(1000); + return; + } + XNextEvent(X.d,&xe); + pthread_mutex_unlock(&X.xmutex); + + /* 1: find out which windows the message is for */ + Window w = 0; + switch(xe.type) + { + case ClientMessage: w = xe.xclient.window;break; + case Expose: w = xe.xexpose.window;break; + case NoExpose: w = xe.xexpose.window;break; + case ButtonPress: w = xe.xbutton.window;break; + case ButtonRelease: w = xe.xbutton.window;break; + case KeyPress: w = xe.xkey.window; break; + case KeyRelease: w = xe.xkey.window; break; + case MotionNotify: w = xe.xmotion.window;break; + case EnterNotify: w = xe.xmotion.window;break; + case LeaveNotify: w = xe.xmotion.window;break; + default: + /* this usually happens for unknown events which + we don't care about */ + return; + } + + QXWindow*qx=X.windowring; + QXWindow*win=0; + event->internal = 0; + do { + if(w == qx->mywin) { + win = qx; + } + } + while(qx!=X.windowring); + + if(!win) { + /* Not one of our windows. This may be a bug */ + return; + } + event->internal = win; + + /* 2: Go for the event construction */ + + switch(xe.type) + { + case ButtonPress: + event->type = GFXEVENT_MOUSEPRESS; + event->button = xe.xbutton.button; + break; + case ButtonRelease: + event->type = GFXEVENT_MOUSERELEASE; + event->button = xe.xbutton.button; + break; + case KeyPress: + event->type = GFXEVENT_KEYPRESS; + event->key = xe.xkey.keycode; + break; + case KeyRelease: + event->type = GFXEVENT_KEYRELEASE; + event->key = xe.xkey.keycode; + break; + case MotionNotify: + event->type = GFXEVENT_MOUSEMOVE; + pthread_mutex_lock(&qx->wmutex); + event->x = xe.xmotion.x_root - win->x; + event->y = xe.xmotion.y_root - win->y; + if(!queue_put(win->queue, event)) { + printf("Queue overflow for window %08x!\n", win); + } + pthread_mutex_unlock(&qx->wmutex); + break; + case EnterNotify: + event->type = GFXEVENT_MOUSEENTER; + pthread_mutex_lock(&qx->wmutex); + event->x = xe.xmotion.x_root - win->x; + event->y = xe.xmotion.y_root - win->y; + pthread_mutex_unlock(&qx->wmutex); + break; + case LeaveNotify: + event->type = GFXEVENT_MOUSELEAVE; + pthread_mutex_lock(&qx->wmutex); + event->x = xe.xmotion.x - win->x; + event->y = xe.xmotion.y - win->y; + pthread_mutex_unlock(&qx->wmutex); + break; + case ClientMessage: + if ((xe.xclient.message_type == X.atom_wm ) && + ((unsigned)xe.xclient.data.l[0] == X.atom_wmdelete) ) { + pthread_mutex_lock(&qx->wmutex); + closeWindow(win); + event->type = GFXEVENT_DESTROY; + pthread_mutex_unlock(&qx->wmutex); + } + break; + } +} + +static void*eventloop(void*r) +{ + //while(!XEventsQueued(X.d,QueuedAfterReading)) + while(X.running) + { + gfxevent_t event; + event.type = GFXEVENT_NOTHING; + event.key = event.x = event.y = event.button = -1; + processEvent(&event); + if(event.type != GFXEVENT_NOTHING && event.type != GFXEVENT_MOUSEMOVE) { + QXWindow*win = (QXWindow*)event.internal; + pthread_mutex_lock(&win->wmutex); + if(!queue_put(win->queue,&event)) { + fprintf(stderr, "Queue overflow for window %08x!\n", win); + } + pthread_mutex_unlock(&win->wmutex); + } + } + return 0; +} + +typedef struct _internal { + GC gc; + char*name; + QXWindow*qx; + int lenx, leny; + int tmplenx, tmpleny; + void*currentscr2; +} internal_t; + +static void gfxwindow_on(gfxwindow_t*win) +{ + internal_t*i = (internal_t*)win->internal; + + i->qx=openwindow(64, 64, win->width, win->height, i->name); + if(!i->qx) + return; + i->currentscr2=0; + if(i->qx->bypp != 4) { + fprintf(stderr, "Warning: Not a native 32 bit screen, using second buffer\n"); + i->currentscr2 = malloc(win->width*win->height*4); + win->currentscr = (unsigned char*)i->currentscr2; + } else { + win->currentscr = i->qx->currentscr; + } + win->lastscr = 0; +} + +static void gfxwindow_off(gfxwindow_t*win) +{ + internal_t*i = (internal_t*)win->internal; + if(i->currentscr2) + free(i->currentscr2); + closeWindow(i->qx); +} + +static void gfxwindow_flippage(gfxwindow_t*win) +{ + internal_t*i = (internal_t*)win->internal; + pthread_mutex_lock(&X.xmutex); + + if(i->currentscr2) { + if(i->qx->bypp==2 && X.isnative16) { + int t; + int l = win->width*win->height; + unsigned char*dest = i->qx->currentscr; + unsigned char*src = (unsigned char*)i->currentscr2; + do { + dest[1] = (src[2]&0xf8)|(src[1]>>5); + dest[0] = ((src[1]<<5)&0xe0)|(src[0]>>3); + dest+=2; + src+=4; + } while(--l); + } else { + memcpy(i->qx->currentscr, i->currentscr2, i->lenx*i->leny*i->qx->bypp); + } + } + + XSetFunction(X.d,i->qx->gc,GXcopy); +#ifdef USE_PIXMAP +# ifndef USE_SHM + if(i->qx->offscreen_pixmap) { + XFreePixmap(X.d,i->qx->offscreen_pixmap);i->qx->offscreen_pixmap = 0; + } + i->qx->offscreen_pixmap = XCreatePixmapFromBitmapData(X.d,i->qx->mywin,i->qx->currentscr,i->qx->lenx,i->qx->leny,X.white,X.black,DefaultDepth(X.d,X.s)); +# endif + XCopyArea(X.d,i->qx->offscreen_pixmap,i->qx->mywin,i->qx->gc, 0, 0, i->qx->lenx,i->qx->leny, 0, 0); + XFlush(X.d); +#else + XPutImage(X.d,i->qx->mywin,i->qx->gc,i->qx->offscreen_ximage,0,0,0,0,i->qx->lenx,i->qx->leny); +#endif + pthread_mutex_unlock(&X.xmutex); +} + +void gfxwindow_setcolor(gfxwindow_t*win, U32 c) +{ + internal_t*i = (internal_t*)win->internal; + pthread_mutex_lock(&X.xmutex); + i->qx->xgcv.foreground=getColorFromRGB((U8)(c>>16),(U8)(c>>8),(U8)c); + i->gc=XCreateGC(X.d,i->qx->mywin,GCForeground|GCBackground,&i->qx->xgcv); + pthread_mutex_unlock(&X.xmutex); +} +void gfxwindow_putpixel(gfxwindow_t*win, int x, int y, unsigned char c) +{ + internal_t*i = (internal_t*)win->internal; + if(((U32)x)<(U32)win->width && ((U32)y)<(U32)win->height) + *(U32*)&win->currentscr[y*win->width*i->qx->bypp+x*i->qx->bypp]=c; +} +static gfxevent_t gfxwindow_getEvent(gfxwindow_t*win) +{ + internal_t*i = (internal_t*)win->internal; + gfxevent_t event; + pthread_mutex_lock(&i->qx->wmutex); + if(!i->qx->queue || !queue_get(i->qx->queue,&event)) { + event.type = GFXEVENT_NOTHING; + } else if(event.type == GFXEVENT_DESTROY) { + queue_destroy(i->qx->queue);i->qx->queue=0; + } + pthread_mutex_unlock(&i->qx->wmutex); + return event; +} + +static void gfxwindow_move(gfxwindow_t*win, int x,int y) +{ + internal_t*i = (internal_t*)win->internal; + pthread_mutex_lock(&i->qx->wmutex); + pthread_mutex_lock(&X.xmutex); + XWindowAttributes a; + i->qx->x += x; + i->qx->y += y; + XMoveResizeWindow(X.d, i->qx->mywin, i->qx->x, i->qx->y, i->tmplenx, i->tmpleny); + + queue_t* queue2 = queue_init(sizeof(gfxevent_t), 256); + gfxevent_t event; + /* HACK: now that we have moved the window, all mouse move events + are outdated- remove them*/ + while(queue_get(i->qx->queue, &event)) { + if(event.type!=GFXEVENT_MOUSEMOVE) + queue_put(queue2, &event); + } + queue_destroy(i->qx->queue); + i->qx->queue = queue2; + + pthread_mutex_unlock(&X.xmutex); + pthread_mutex_unlock(&i->qx->wmutex); +} + +static void gfxwindow_resize(gfxwindow_t*win, int x,int y) +{ + internal_t*i = (internal_t*)win->internal; + if(x>win->width || y>win->height) { + fprintf(stderr, "resize: can only make windows smaller\n"); + return; + } + if(x<1) x=1; + if(y<1) y=1; + pthread_mutex_lock(&i->qx->wmutex); + i->tmplenx=x; + i->tmpleny=y; + pthread_mutex_lock(&X.xmutex); + XMoveResizeWindow(X.d, i->qx->mywin, i->qx->x, i->qx->y, i->tmplenx, i->tmpleny); + pthread_mutex_unlock(&X.xmutex); + pthread_mutex_unlock(&i->qx->wmutex); +} +static void gfxwindow_destroy(gfxwindow_t*win) +{ + internal_t*i = (internal_t*)win->internal; + gfxwindow_off(win); + pthread_mutex_destroy(&i->qx->wmutex); +} + +gfxwindow_t* gfxwindow_new(int width, int height) +{ + gfxwindow_t*w = (gfxwindow_t*)malloc(sizeof(gfxwindow_t)); + if(!initializexwindows()) { + fprintf(stderr, "Warning: Couldn't initialize X-Windows\n"); + } + internal_t*i = malloc(sizeof(internal_t)); + w->internal = i; + w->move = gfxwindow_move; + w->resize = gfxwindow_resize; + w->flippage = gfxwindow_flippage; + w->getEvent = gfxwindow_getEvent; + w->width = width; + w->height = height; + w->destroy = gfxwindow_destroy; + + i->lenx = i->tmplenx = width; + i->leny = i->tmpleny = height; + i->name = ""; + + gfxwindow_on(w); + return w; +}; + diff -Nru swftools-0.9.2+ds1/lib/gfxwindow_win32.c swftools-0.9.1/lib/gfxwindow_win32.c --- swftools-0.9.2+ds1/lib/gfxwindow_win32.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/gfxwindow_win32.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,430 @@ +/* gfxwindow.h + + Simple GUI abstraction- Windows implementation + + Part of the swftools package. + + Copyright (c) 2005 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 "gfx.h" + +static LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + +static char szWinName[] = "MyWin"; +static HDC hdc; +static HWND hwnd; +static char*text=""; +static int textx; +static int texty; +static int a = 0; +static HDC dc, memDc; +static HBITMAP piccy; + +static int sizex=640; +static int sizey=388; +static char *screen; +static char *offscreen; +static int screensize; + +static DWORD threadID; +static DWORD mainthreadID; +static HANDLE thread; +static HINSTANCE me,prev; +static int nWinMode; +static int posx,posy; +static RECT desktopSize; +static int initialized = 0; + +static int cwidth=640,cheight=388; + +#define DIB + +static void openWindow(int _sizex, int _sizey) +{ + RECT r;int ok; + + sizex = _sizex; + sizey = _sizey; + + ok = (int)GetClientRect(GetDesktopWindow(), &r); + if(!ok) { + r.left = r.top = 0; + r.right = 1280; + r.bottom = 1024; + } + desktopSize = r; + + hwnd=CreateWindow(szWinName, + 0, //window title + WS_POPUP|WS_VISIBLE, + posx=100, //CW_USEDEFAULT, + posy=200, //CW_USEDEFAULT, + 640,388, + HWND_DESKTOP, + NULL,me,NULL); + SendMessage(hwnd, 1024+5 /*SB_SETBORDERS*/, 0, 0); + + ShowWindow(hwnd,nWinMode); + UpdateWindow(hwnd); + + dc=GetDC(hwnd); + memDc=CreateCompatibleDC(dc); +// SetTimer(hwnd,1,1000,NULL); +// SetTimer(hwnd,1,33,NULL); + +#ifdef DIB + void * ppvBits = 0; + BITMAPINFO info; + memset(&info, sizeof(info), 0); + info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + info.bmiHeader.biWidth = sizex; + info.bmiHeader.biHeight = sizey; + info.bmiHeader.biPlanes= 1; + info.bmiHeader.biBitCount = 24; + info.bmiHeader.biCompression = BI_RGB; + info.bmiHeader.biSizeImage = sizex*sizey*3; + + piccy = CreateDIBSection(0, &info, DIB_RGB_COLORS, &ppvBits, 0,0); + screen = (char*)ppvBits; + offscreen = (char*)malloc(sizex*sizey*4); + screensize = sizex*sizey*3; + GdiFlush(); +#else + screen = (char*)malloc(sizex*sizey*3); + offscreen = (char*)malloc(sizex*sizey*4); + screensize = sizex*sizey*3; + piccy = CreateBitmap(sizex, sizey, 1, 24, screen); +#endif + + SelectObject(memDc,piccy); + +} + +static void closeWindow() +{ + DeleteDC(memDc); + ReleaseDC(hwnd,dc); + KillTimer(hwnd,1); +} + +static int initwin32() +{ + MSG msg; + int ret; + WNDCLASS wcl; + + me = GetModuleHandle(NULL); + prev = NULL; + nWinMode = SW_SHOW; + + if(GetClassInfo(0, szWinName, &wcl)) { + /* already registered */ + exit(1); + } + wcl.hInstance =me; + wcl.lpszClassName=szWinName; + wcl.lpfnWndProc =WindowFunc; + wcl.style =2; + wcl.hIcon =LoadIcon (NULL, IDI_HAND); + wcl.hCursor =LoadCursor(NULL, IDC_HAND);//IDC_CROSS); + wcl.lpszMenuName =NULL; + wcl.cbClsExtra =0; + wcl.cbWndExtra =0; + wcl.hbrBackground=(HBRUSH)GetStockObject(NULL_BRUSH);//WHITE_BRUSH); + + if(!RegisterClass(&wcl)) + exit(1); + + //mainthreadID = GetCurrentThreadId(); + + //openWindow(640,388); + + //thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(maincaller), (/*data*/0), 0, (LPDWORD)&(threadID)); + + /*while(GetMessage(&msg,NULL,0,0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + }*/ + + //closeWindow(); + //ret = msg.wParam; + + initialized = 1; + + return ret; +} + +#define Q_REDRAW 0x7f01 +#define Q_DUMMY 0x7f02 + +static LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_DESTROY: + PostQuitMessage(0); + break; + case WM_PAINT: + BitBlt(dc,0,0,sizex,sizey,memDc,0,0,SRCCOPY); + break; + case Q_DUMMY: + break; + case Q_REDRAW: { + int x,y; + for(y=0;ycurrentscr = (unsigned char*)offscreen; + + while(GetMessage(&msg,NULL,0,0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + if(msg.message == WM_PAINT) + break; + } +} +static void ModeRGB_off(window_t*win) +{ + MSG msg; + //printf("off()\n"); + //TODO: shouldn't this be DestroyWindow(hwnd)? + PostMessage(hwnd, WM_DESTROY, 0, 0); + while(GetMessage(&msg,NULL,0,0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + if(msg.message == WM_DESTROY) + break; + } + closeWindow(); + win->currentscr = win->lastscr = 0; +} +static void ModeRGB_flippage(window_t*win) +{ + MSG msg; + PostMessage(hwnd, Q_REDRAW, 0, 0); + while(GetMessage(&msg,NULL,0,0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + if(msg.message == Q_REDRAW) + break; + } + win->currentscr = (byte*)offscreen; +} +static gfxevent_t ModeRGB_getEvent(window_t*win) +{ + MSG msg; + WPARAM wParam; + LPARAM lParam; + gfxevent_t event; + + //PostMessage(hwnd, Q_DUMMY, 0, 0); + + event.type = GFXEVENT_NOTHING; + event.key = 0; + event.x = 0; + event.y = 0; + event.type = 0; + event.button = 0; + + if(!PeekMessage(&msg,NULL,0,0,0)) + return event;//nothing + + while(GetMessage(&msg,NULL,0,0)) + { + lParam = msg.lParam; + wParam = msg.wParam; + if(msg.message == Q_DUMMY) { + event.type = GFXEVENT_NOTHING; + break; + } else if(msg.message == WM_LBUTTONDOWN) { + event.type = GFXEVENT_MOUSEPRESS; + event.button = 1; + event.x = (signed short int)LOWORD(lParam); + event.y = (signed short int)HIWORD(lParam); + SetCapture(hwnd); + break; + } else if(msg.message == WM_LBUTTONUP) { + event.type = GFXEVENT_MOUSERELEASE; + event.button = 1; + event.x = (signed short int)LOWORD(lParam); + event.y = (signed short int)HIWORD(lParam); + ReleaseCapture(); + break; + } else if(msg.message == WM_MBUTTONDOWN) { + event.type = GFXEVENT_MOUSEPRESS; + event.button = 2; + event.x = (signed short int)LOWORD(lParam); + event.y = (signed short int)HIWORD(lParam); + SetCapture(hwnd); + break; + } else if(msg.message == WM_MBUTTONUP) { + event.type = GFXEVENT_MOUSERELEASE; + event.button = 1; + event.x = (signed short int)LOWORD(lParam); + event.y = (signed short int)HIWORD(lParam); + ReleaseCapture(); + break; + } else if(msg.message == WM_RBUTTONDOWN) { + event.type = GFXEVENT_MOUSEPRESS; + event.button = 3; + event.x = (signed short int)LOWORD(lParam); + event.y = (signed short int)HIWORD(lParam); + SetCapture(hwnd); + break; + } else if(msg.message == WM_RBUTTONUP) { + event.type = GFXEVENT_MOUSERELEASE; + event.button = 3; + event.x = (signed short int)LOWORD(lParam); + event.y = (signed short int)HIWORD(lParam); + ReleaseCapture(); + break; + } else if(msg.message == WM_MOUSEMOVE) { + event.type = GFXEVENT_MOUSEMOVE; + event.x = (signed short int)LOWORD(lParam); + event.y = (signed short int)HIWORD(lParam); + break; + } else if(msg.message == WM_CHAR) { + event.type = GFXEVENT_KEYPRESS; + event.key = (char)wParam; + break; + } else { + TranslateMessage(&msg); + DispatchMessage(&msg); + event.type = GFXEVENT_NOTHING; + break; + } + } + return event; +} +static void ModeRGB_move(window_t*win, int relx,int rely) +{ + MSG msg; + PostMessage(hwnd, Q_DUMMY, 0, 0); + while(GetMessage(&msg,NULL,0,0)) + { + if(msg.message == WM_LBUTTONUP) { + SendMessage(hwnd, msg.message, msg.wParam, msg.lParam); + return; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + if(msg.message == Q_DUMMY) + break; + } + posx+=relx; + posy+=rely; + + if(posx > desktopSize.right-cwidth) posx = desktopSize.right-cwidth; + if(posy > desktopSize.bottom-cheight) posy = desktopSize.bottom-cheight; + if(posx < desktopSize.left) posx = desktopSize.left; + if(posy < desktopSize.top) posy = desktopSize.top; + + SetWindowPos(hwnd, HWND_TOP, posx, posy, 0, 0, SWP_NOSIZE); + PostMessage(hwnd, Q_DUMMY, 0, 0); + while(GetMessage(&msg,NULL,0,0)) + { + if(msg.message == WM_LBUTTONUP) { + SendMessage(hwnd, msg.message, msg.wParam, msg.lParam); + break;; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + if(msg.message == Q_DUMMY) + break; + } +} +static void ModeRGB_resize(window_t*win, int width,int height) +{ + if(width>sizex || height>sizey) { + printf("mode24::resize: can only make windows smaller\n"); + return; + } + if(width<1) width=1; + if(height<1) height=1; + cwidth = width; + cheight = height; + SetWindowPos(hwnd, HWND_TOP, 0, 0, width, height, SWP_NOMOVE); + win->move(win,0,0); +} + + +window_t* window_new(window_t*win, int width, int height) +{ + window_t*w = (window_t*)malloc(sizeof(window_t)); + memset(w, 0, sizeof(window_t)); + if(!initialized) + initwin32(); + w->currentscr = w->lastscr = 0; + sizex = width; + sizey = height; + cwidth = sizex; + cheight = sizey; + //printf("contruct(%d, %d)\n", x, y); + w->on = ModeRGB_on; + w->off = ModeRGB_off; + w->move = ModeRGB_move; + w->resize = ModeRGB_resize; + w->flippage = ModeRGB_flippage; + w->getEvent = ModeRGB_getEvent; + w->width = width; + w->height = height; + return w; +} + diff -Nru swftools-0.9.2+ds1/lib/h.263/video.c swftools-0.9.1/lib/h.263/video.c --- swftools-0.9.2+ds1/lib/h.263/video.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/h.263/video.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,696 @@ +/* video.c + Shows the structure of a swf file containing video + + Part of the swftools package. + + Copyright (c) 2003 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 "../../config.h" +#include +#include +#include +#include +#include +#include "../rfxswf.h" +#include "../args.h" +#include "h263tables.h" + +static char * filename = 0; +static char * indent = " "; +int hex = 0; +int debug = 0; + +struct options_t options[] = +{ + {"v","verbose"}, + {"V","version"}, + {"d","hex"}, + {"M","video"}, + {0,0} +}; + +/* TODO: + * check rle tables +*/ +int args_callback_option(char*name,char*val) +{ + if(!strcmp(name, "V")) { + printf("swfdump - part of %s %s\n", PACKAGE, VERSION); + exit(0); + } + else if(name[0]=='d') { + hex = 1; + return 0; + } + else if(name[0]=='v') { + debug = 1; + return 0; + } + else { + printf("Unknown option: -%s\n", name); + exit(1); + } + + return 0; +} +int args_callback_longoption(char*name,char*val) +{ + return args_long2shortoption(options, name, val); +} +void args_callback_usage(char*name) +{ + printf("Usage: %s [-at] file.swf\n", name); + printf("\t-h , --help\t\t Print help and exit\n"); + printf("\t-d , --hex\t\t Print hex output of tag data, too\n"); + printf("\t-v , --verbose\t\t Print debugging information\n"); + printf("\t-V , --version\t\t Print program version and exit\n"); +} +int args_callback_command(char*name,char*val) +{ + if(filename) { + fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n", + filename, name); + } + filename = name; + return 0; +} + +#define DEBUG if(debug) + +void handleVideoStream(TAG*tag, char*prefix) +{ + U16 id = swf_GetU16(tag); + U16 frames = swf_GetU16(tag); + U16 width = swf_GetU16(tag); + U16 height = swf_GetU16(tag); + U8 flags = swf_GetU8(tag); //5-2(videopacket 01=off 10=on)-1(smoothing 1=on) + U8 codec = swf_GetU8(tag); + printf(" (%d frames, %dx%d", frames, width, height); + if(flags&1) + printf(" smoothed"); + if(codec == 2) + printf(" sorenson h.263)"); + else + printf(" codec 0x%02x)", codec); +} + +int checkhufftable(struct huffcode*code, char*name) +{ + int t=0; + while(code[t].code) { + int s=0; + if(strlen(code[t].code)!=code[t].len) { + printf("len mismatch in %s, index %d\n", name, t); + exit(1); + } + if(t != code[t].index) { + printf("index mismatch in %s, index %d\n", name, t); + exit(1); + } + while(code[s].code) { + char*a = code[s].code; + char*b = code[t].code; + int ai = s; + int bi = t; + if(s==t) {s++;continue;} + if(code[t].len < code[s].len) { + a = code[t].code; + b = code[s].code; + ai = t; bi = s; + } + if(!strncmp(a,b,strlen(a))) { + printf("index %d (%s) is prefix of %d (%s)\n", ai, a, bi, b); + exit(1); + } + + s++; + } + + t++; + } +} + + +struct hufftree +{ + struct hufftree*left;//0 + struct hufftree*right;//1 + int index; +}; + +struct hufftree * rle_tree; +struct hufftree * mcbpc_intra_tree; +struct hufftree * mcbpc_inter_tree; +struct hufftree * cbpy_tree; +struct hufftree * mvd_tree; + +static void insert(struct hufftree*tree, char*code, int index) +{ + if(!*code) { + assert(!tree->left); //shannon conditional + assert(!tree->right); + tree->left = 0; + tree->right = 0; + tree->index = index; + return; + } + if(code[0] == '0') { + if(!tree->left) { + tree->left = (struct hufftree*)malloc(sizeof(struct hufftree)); + memset(tree->left, 0, sizeof(struct hufftree)); + tree->left->index = -1; + } + insert(tree->left, code+1, index); + return; + } else { + assert(code[0] == '1'); + if(!tree->right) { + tree->right = (struct hufftree*)malloc(sizeof(struct hufftree)); + memset(tree->right, 0, sizeof(struct hufftree)); + tree->right->index = -1; + } + insert(tree->right, code+1, index); + return; + } +} + +struct hufftree* huffcode2tree(struct huffcode*code) +{ + struct hufftree* t = malloc(sizeof(struct hufftree)); + memset(t, 0, sizeof(struct hufftree)); + t->index = -1; + while(code->code) { + insert(t, code->code, code->index); + code++; + } + return t; +} + +int gethuffvalue(TAG*tag, struct huffcode*code) +{ + int len = 0; + char bits[80]; + while(1) { + int t=0,pot=0; + bits[len] = swf_GetBits(tag, 1)+0x30; + len++; + bits[len] = 0; + while(code[t].code) { + if(!strcmp(bits, code[t].code)) + return t; + t++; + if(code[t].len >= len) + pot++; + } + if(!pot) { + int nr=0; + printf("error: %s\n", bits); + while(tag->pos < tag->len && nr<80) { + int b = swf_GetBits(tag, 1); + printf("%d", b); + nr++; + } + if(nr==80) + printf("..."); + printf("\n"); + exit(1); + return -1; + } + } + + /*type = 0; // mb-type =3, cbpc = 00 + if(!bit) { + printf("can't handle i-frame mcbpc bits %d yet\n", bit); + } + bit = swf_GetBits(tag, 1); + type = 0; // mb-type =0, cbpc = 00 + if(!bit) { + bit = swf_GetBits(tag, 2); + type = 8; // mb-type =2, cbpc = 00 + if(bit!=3) { + printf("can't handle p-frame mcbpc bits 0-%d yet\n", bit); + exit(1); + } + }*/ +} + +int gethuffvalue2(TAG*tag, struct huffcode*code, struct hufftree*tree) +{ + while(1) { + if(tree->index>=0) { + return tree->index; + } + if(!swf_GetBits(tag, 1)) { + assert(tree->left); + tree=tree->left; + } else { + assert(tree->right); + tree=tree->right; + } + } +} + +void get_DC_TCOEF(TAG*tag, int t, int has_dc, int has_tcoef) +{ + int dc; + int ac;// = swf_GetBits(); + int index; + int pos = 0; + int line[64]; + int show_rle_code=0; + memset(line, 0, sizeof(line)); + + //printf("DC:%d\n", dc); + if(has_dc) { + dc = swf_GetBits(tag, 8); + if(dc == 0 || dc == 128) { + printf("error: dc=%d\n", dc); + exit(1); + } + DEBUG if(show_rle_code) printf(" %d ", dc); + line[pos] = dc; + pos++; + } + + if(has_tcoef) { + DEBUG if(show_rle_code) printf("["); + while(1) { + int last; + int run; + int level; + index = gethuffvalue2(tag, rle, rle_tree); + last = rle_params[index].last; + run = rle_params[index].run; + level = rle_params[index].level; + //DEBUG printf("index:%d\n", index); + if(index == RLE_ESCAPE) { + last = swf_GetBits(tag, 1); + run = swf_GetBits(tag, 6); + level = swf_GetBits(tag, 8); + if(run) { + DEBUG if(show_rle_code) printf(" (%d) E%d", run, level); + } else { + DEBUG if(show_rle_code) printf("E"); + } + if(level == 0 || level == 128) { + printf("error: level=%d\n", level); + exit(1); + } + level = (int)((signed char)level); + } else { + int sign = swf_GetBits(tag, 1); + if(sign) { + level = -level; + } + if(run) { + DEBUG if(show_rle_code) printf(" (%d) %s%d", run, level>0?"+":"",level); + } else { + DEBUG if(show_rle_code) printf(" %s%d", level>0?"+":"",level); + } + } + pos += run; + if(pos>=64) { + printf("\nerror:bad pos: %d\n", pos); + exit(1); + } + line[pos++] = level; + //DEBUG printf("run:%d level:%d\n", run, level); + if(last) { + DEBUG if(show_rle_code) printf("] pos: %d", pos); + if(pos>64) { + printf("\nerror:bad pos (%d)\n", pos); + exit(1); + } + break; + } + } + } + DEBUG if(show_rle_code) printf("\n"); + + DEBUG printf("["); + for(t=0;t>t); + DEBUG printf("luminance%d ", t); + get_DC_TCOEF(tag, t, has_intradc, has_tcoef); /*luminance - affected by cbpy*/ + } + for(t=0;t<2;t++) { + int has_intradc = intrablock; + int has_tcoef = cbpc & (2>>t); + DEBUG printf("chrominance%d ", t); + get_DC_TCOEF(tag, t, has_intradc, has_tcoef); /*chrominance - affected by mcbc*/ + } +} + +void handleVideoFrame(TAG*tag, char*prefix) +{ + U32 code, version, reference, sizeflags; + U32 width, height; + U8 blocktype, pictype; + U16 id = swf_GetU16(tag); + U16 frame = swf_GetU16(tag); + U8 deblock,flags, tmp, bit; + U32 quantizer, extrainfo; + int skipped = 0; + int pos=0; + int num; + int disposable = 0; + int blocknum; + int bbx,bby,bx,by; + char*types[] = {"intra- (I-)frame", "inter- (P-)frame", "disposable interframe", ""}; + printf("============================= frame %d ===================================", frame); + + /* video packet follows */ + printf("\n"); + code = swf_GetBits(tag, 17); + if(code!=1) { + printf("code: %x (?)\n", code); + return; + } + version = swf_GetBits(tag, 5); /*actually, part of the picture start code */ + //printf("version: %x\n", version); /*usually 0*/ + if(version >= 1) { + /* version 1 has some different transform coefficient coding which we + can't handle yet */ + printf("spark version %d not supported yet\n", version); + exit(1); + } + reference = swf_GetBits(tag, 8); + DEBUG printf("reference: %d\n", reference); /*usually same as frame number (unless frames were skipped while encoding)*/ + + sizeflags = swf_GetBits(tag, 3); + switch(sizeflags) + { + case 0: width = swf_GetBits(tag,8); height = swf_GetBits(tag,8); break; + case 1: width = swf_GetBits(tag, 16); height = swf_GetBits(tag, 16); break; + case 2: width = 352; height = 288; break; + case 3: width = 176; height = 144; break; + case 4: width = 128; height = 96; break; + case 5: width = 320; height = 240; break; + case 6: width = 160; height = 120; break; + case 7: width = -1; height = -1;/*reserved*/ break; + } + + pictype = swf_GetBits(tag, 2); + if(pictype==3) { + printf("error: unknown pictype: %d\n", pictype); + exit(1); + } + if(pictype==2) { + pictype = TYPE_INTER; + disposable = 1; + } + if(pictype==TYPE_INTER) + printf("INTER P%s", disposable?" (disposeable)":""); + else + printf("INTRA I"); + + deblock = swf_GetBits(tag, 1); /*usually 0*/ + DEBUG printf("deblock: %d\n", deblock); + quantizer = swf_GetBits(tag, 5); /*usually 9*/ + DEBUG printf("quantizer: %d\n", quantizer); + + extrainfo = swf_GetBits(tag, 1); /*usually none */ + while(extrainfo) { + extrainfo = swf_GetBits(tag, 8); + printf("extrainfo: %02x\n", extrainfo); + extrainfo = swf_GetBits(tag, 1); + } + + /* macro block */ + bbx = (width+15)/16; + bby = (height+15)/16; + blocknum = bbx*bby; + printf("%dx%d [blocks: %dx%d=%d]\n", width, height, bbx,bby, blocknum); + + /*if(pictype == TYPE_INTER) + return;*/ + /*if(pictype == TYPE_INTRA) + return;*/ + + /*tagnr++; + if(tagnr!=2) + return;*/ + + DEBUG printf("\n"); + for(by=0;by ",prefix); + for(t=0;tlen;t++) { + printf("%02x ", tag->data[t]); + if((t && ((t&15)==15)) || (t==tag->len-1)) + { + if(t==tag->len-1) + printf("\n"); + else + printf("\n %s-=> ",prefix); + } + } +} + +int main (int argc,char ** argv) +{ + TAG*tag; + SWF swf; + int f; + char prefix[128]; + int filesize = 0; + prefix[0] = 0; + + checkhufftable(rle, "rle"); + checkhufftable(mcbpc_intra, "intra"); + checkhufftable(mcbpc_inter, "inter"); + checkhufftable(cbpy, "cbpy"); + checkhufftable(mvd, "mvd"); + + rle_tree = huffcode2tree(rle); + mcbpc_intra_tree = huffcode2tree(mcbpc_intra); + mcbpc_inter_tree = huffcode2tree(mcbpc_inter); + cbpy_tree = huffcode2tree(cbpy); + mvd_tree = huffcode2tree(mvd); + + processargs(argc, argv); + if(!filename) { + fprintf(stderr, "You must supply a filename.\n"); + return 1; + } + + f = open(filename,O_RDONLY); + + if (f<0) { + perror("Couldn't open file: "); + exit(1); + } + if FAILED(swf_ReadSWF(f,&swf)) { + fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename); + close(f); + exit(1); + } + + close(f); + + printf("[HEADER] File version: %d\n", swf.fileVersion); + if(swf.compressed) { + printf("[HEADER] File is zlib compressed."); + if(filesize && swf.fileSize) + printf(" Ratio: %02d%%\n", filesize*100/(swf.fileSize)); + else + printf("\n"); + } + printf("[HEADER] File size: %ld%s\n", swf.fileSize, swf.compressed?" (Depacked)":""); + printf("[HEADER] Frame rate: %f\n",swf.frameRate/256.0); + printf("[HEADER] Frame count: %d\n",swf.frameCount); + printf("[HEADER] Movie width: %.2f",(swf.movieSize.xmax-swf.movieSize.xmin)/20.0); + if(swf.movieSize.xmin) + printf(" (left offset: %.2f)\n", swf.movieSize.xmin/20.0); + else + printf("\n"); + printf("[HEADER] Movie height: %.2f",(swf.movieSize.ymax-swf.movieSize.ymin)/20.0); + if(swf.movieSize.ymin) + printf(" (top offset: %.2f)\n", swf.movieSize.ymin/20.0); + else + printf("\n"); + + tag = swf.firstTag; + + while(tag) { + char*name = swf_TagGetName(tag); + char myprefix[128]; + //printf("[%03x] %9ld %s%s", tag->id, tag->len, prefix, swf_TagGetName(tag)); + + if(swf_isDefiningTag(tag)) { + U16 id = swf_GetDefineID(tag); + //printf(" defines id %04d", id); + } + else if(swf_isPseudoDefiningTag(tag)) { + U16 id = swf_GetDefineID(tag); + //printf(" adds information to id %04d", id); + } + + if(tag->id == ST_VIDEOFRAME) { + handleVideoFrame(tag, myprefix); + //printf("\n"); + } + else if(tag->id == ST_DEFINEVIDEOSTREAM) { + handleVideoStream(tag, myprefix); + printf("\n"); + } + else { + //printf("\n"); + } + + sprintf(myprefix, " %s", prefix); + + if(tag->len && hex) { + hexdumpTag(tag, prefix); + } + tag = tag->next; + fflush(stdout); + } + + swf_FreeTags(&swf); + return 0; +} + + diff -Nru swftools-0.9.2+ds1/lib/lame/bitstream.c swftools-0.9.1/lib/lame/bitstream.c --- swftools-0.9.2+ds1/lib/lame/bitstream.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/bitstream.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,978 @@ +/* + * MP3 bitstream Output interface for LAME + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * 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. + * + * $Id: bitstream.c,v 1.3 2006/02/09 16:56:23 kramm Exp $ + */ + + +#include +#include "config_static.h" + +#include +#include +#include +#include "tables.h" +#include "bitstream.h" +#include "quantize.h" +#include "quantize_pvt.h" +#include "version.h" +#include "VbrTag.h" + +#ifdef WITH_DMALLOC +#include +#endif + +/* This is the scfsi_band table from 2.4.2.7 of the IS */ +const int scfsi_band[5] = { 0, 6, 11, 16, 21 }; + + +/* unsigned int is at least this large: */ +/* we work with ints, so when doing bit manipulation, we limit + * ourselves to MAX_LENGTH-2 just to be on the safe side */ +#define MAX_LENGTH 32 + + + +#ifdef DEBUG +static int hoge, hogege; +#endif + + + + + +void putheader_bits(lame_internal_flags *gfc,int w_ptr) +{ + Bit_stream_struc *bs; + bs = &gfc->bs; +#ifdef DEBUG + hoge += gfc->sideinfo_len * 8; + hogege += gfc->sideinfo_len * 8; +#endif + memcpy(&bs->buf[bs->buf_byte_idx], gfc->header[gfc->w_ptr].buf, + gfc->sideinfo_len); + bs->buf_byte_idx += gfc->sideinfo_len; + bs->totbit += gfc->sideinfo_len * 8; + gfc->w_ptr = (gfc->w_ptr + 1) & (MAX_HEADER_BUF - 1); +} + + + + +/*write j bits into the bit stream */ +inline static void +putbits2(lame_global_flags *gfp, int val, int j) +{ + lame_internal_flags *gfc=gfp->internal_flags; + Bit_stream_struc *bs; + bs = &gfc->bs; + + assert(j < MAX_LENGTH-2); + + while (j > 0) { + int k; + if (bs->buf_bit_idx == 0) { + bs->buf_bit_idx = 8; + bs->buf_byte_idx++; + assert(bs->buf_byte_idx < BUFFER_SIZE); + assert(gfc->header[gfc->w_ptr].write_timing >= bs->totbit); + if (gfc->header[gfc->w_ptr].write_timing == bs->totbit) { + putheader_bits(gfc,gfc->w_ptr); + } + bs->buf[bs->buf_byte_idx] = 0; + } + + k = Min(j, bs->buf_bit_idx); + j -= k; + + bs->buf_bit_idx -= k; + + assert (j < MAX_LENGTH); /* 32 too large on 32 bit machines */ + assert (bs->buf_bit_idx < MAX_LENGTH); + + bs->buf[bs->buf_byte_idx] |= ((val >> j) << bs->buf_bit_idx); + bs->totbit += k; + } +} + +/*write j bits into the bit stream, ignoring frame headers */ +inline static void +putbits_noheaders(lame_global_flags *gfp, int val, int j) +{ + lame_internal_flags *gfc=gfp->internal_flags; + Bit_stream_struc *bs; + bs = &gfc->bs; + + assert(j < MAX_LENGTH-2); + + while (j > 0) { + int k; + if (bs->buf_bit_idx == 0) { + bs->buf_bit_idx = 8; + bs->buf_byte_idx++; + assert(bs->buf_byte_idx < BUFFER_SIZE); + bs->buf[bs->buf_byte_idx] = 0; + } + + k = Min(j, bs->buf_bit_idx); + j -= k; + + bs->buf_bit_idx -= k; + + assert (j < MAX_LENGTH); /* 32 too large on 32 bit machines */ + assert (bs->buf_bit_idx < MAX_LENGTH); + + bs->buf[bs->buf_byte_idx] |= ((val >> j) << bs->buf_bit_idx); + bs->totbit += k; + } +} + + +/* + Some combinations of bitrate, Fs, and stereo make it impossible to stuff + out a frame using just main_data, due to the limited number of bits to + indicate main_data_length. In these situations, we put stuffing bits into + the ancillary data... +*/ + +inline static void +drain_into_ancillary(lame_global_flags *gfp,int remainingBits) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int i; + assert(remainingBits >= 0); + + if (remainingBits >= 8) { + putbits2(gfp,0x4c,8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfp,0x41,8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfp,0x4d,8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfp,0x45,8); + remainingBits -= 8; + } + + if (remainingBits >= 32) { + const char *version = get_lame_short_version (); + if (remainingBits >= 32) + for (i=0; i<(int)strlen(version) && remainingBits >=8 ; ++i) { + remainingBits -= 8; + putbits2(gfp,version[i],8); + } + } + + for (; remainingBits >= 1; remainingBits -= 1 ) { + putbits2 ( gfp, gfc->ancillary_flag, 1 ); + gfc->ancillary_flag ^= 1; + } + + assert (remainingBits == 0); + +} + +/*write N bits into the header */ +inline static void +writeheader(lame_internal_flags *gfc,int val, int j) +{ + int ptr = gfc->header[gfc->h_ptr].ptr; + + while (j > 0) { + int k = Min(j, 8 - (ptr & 7)); + j -= k; + assert (j < MAX_LENGTH); /* >> 32 too large for 32 bit machines */ + gfc->header[gfc->h_ptr].buf[ptr >> 3] + |= ((val >> j)) << (8 - (ptr & 7) - k); + ptr += k; + } + gfc->header[gfc->h_ptr].ptr = ptr; +} + + +static int +CRC_update(int value, int crc) +{ + int i; + value <<= 8; + for (i = 0; i < 8; i++) { + value <<= 1; + crc <<= 1; + + if (((crc ^ value) & 0x10000)) + crc ^= CRC16_POLYNOMIAL; + } + return crc; +} + + +void +CRC_writeheader(lame_internal_flags *gfc, char *header) +{ + int crc = 0xffff; /* (jo) init crc16 for error_protection */ + int i; + + crc = CRC_update(((unsigned char*)header)[2], crc); + crc = CRC_update(((unsigned char*)header)[3], crc); + for (i = 6; i < gfc->sideinfo_len; i++) { + crc = CRC_update(((unsigned char*)header)[i], crc); + } + + header[4] = crc >> 8; + header[5] = crc & 255; +} + +inline static void +encodeSideInfo2(lame_global_flags *gfp,int bitsPerFrame) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_side_info_t *l3_side; + int gr, ch; + + l3_side = &gfc->l3_side; + gfc->header[gfc->h_ptr].ptr = 0; + memset(gfc->header[gfc->h_ptr].buf, 0, gfc->sideinfo_len); + if (gfp->out_samplerate < 16000) + writeheader(gfc,0xffe, 12); + else + writeheader(gfc,0xfff, 12); + writeheader(gfc,(gfp->version), 1); + writeheader(gfc,4 - 3, 2); + writeheader(gfc,(!gfp->error_protection), 1); + writeheader(gfc,(gfc->bitrate_index), 4); + writeheader(gfc,(gfc->samplerate_index), 2); + writeheader(gfc,(gfc->padding), 1); + writeheader(gfc,(gfp->extension), 1); + writeheader(gfc,(gfp->mode), 2); + writeheader(gfc,(gfc->mode_ext), 2); + writeheader(gfc,(gfp->copyright), 1); + writeheader(gfc,(gfp->original), 1); + writeheader(gfc,(gfp->emphasis), 2); + if (gfp->error_protection) { + writeheader(gfc,0, 16); /* dummy */ + } + + if (gfp->version == 1) { + /* MPEG1 */ + assert(l3_side->main_data_begin >= 0); + writeheader(gfc,(l3_side->main_data_begin), 9); + + if (gfc->channels_out == 2) + writeheader(gfc,l3_side->private_bits, 3); + else + writeheader(gfc,l3_side->private_bits, 5); + + for (ch = 0; ch < gfc->channels_out; ch++) { + int band; + for (band = 0; band < 4; band++) { + writeheader(gfc,l3_side->scfsi[ch][band], 1); + } + } + + for (gr = 0; gr < 2; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *gi = &l3_side->gr[gr].ch[ch].tt; + writeheader(gfc,gi->part2_3_length, 12); + writeheader(gfc,gi->big_values / 2, 9); + writeheader(gfc,gi->global_gain, 8); + writeheader(gfc,gi->scalefac_compress, 4); + writeheader(gfc,gi->window_switching_flag, 1); + + if (gi->window_switching_flag) { + writeheader(gfc,gi->block_type, 2); + writeheader(gfc,gi->mixed_block_flag, 1); + + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc,gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc,gi->table_select[1], 5); + + writeheader(gfc,gi->subblock_gain[0], 3); + writeheader(gfc,gi->subblock_gain[1], 3); + writeheader(gfc,gi->subblock_gain[2], 3); + } else { + assert(gi->block_type == NORM_TYPE); + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc,gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc,gi->table_select[1], 5); + if (gi->table_select[2] == 14) + gi->table_select[2] = 16; + writeheader(gfc,gi->table_select[2], 5); + + assert(gi->region0_count < 16U); + assert(gi->region1_count < 8U); + writeheader(gfc,gi->region0_count, 4); + writeheader(gfc,gi->region1_count, 3); + } + writeheader(gfc,gi->preflag, 1); + writeheader(gfc,gi->scalefac_scale, 1); + writeheader(gfc,gi->count1table_select, 1); + } + } + } else { + /* MPEG2 */ + assert(l3_side->main_data_begin >= 0); + writeheader(gfc,(l3_side->main_data_begin), 8); + writeheader(gfc,l3_side->private_bits, gfc->channels_out); + + gr = 0; + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *gi = &l3_side->gr[gr].ch[ch].tt; + writeheader(gfc,gi->part2_3_length, 12); + writeheader(gfc,gi->big_values / 2, 9); + writeheader(gfc,gi->global_gain, 8); + writeheader(gfc,gi->scalefac_compress, 9); + writeheader(gfc,gi->window_switching_flag, 1); + + if (gi->window_switching_flag) { + writeheader(gfc,gi->block_type, 2); + writeheader(gfc,gi->mixed_block_flag, 1); + + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc,gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc,gi->table_select[1], 5); + + writeheader(gfc,gi->subblock_gain[0], 3); + writeheader(gfc,gi->subblock_gain[1], 3); + writeheader(gfc,gi->subblock_gain[2], 3); + } else { + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc,gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc,gi->table_select[1], 5); + if (gi->table_select[2] == 14) + gi->table_select[2] = 16; + writeheader(gfc,gi->table_select[2], 5); + + assert(gi->region0_count < 16U); + assert(gi->region1_count < 8U); + writeheader(gfc,gi->region0_count, 4); + writeheader(gfc,gi->region1_count, 3); + } + + writeheader(gfc,gi->scalefac_scale, 1); + writeheader(gfc,gi->count1table_select, 1); + } + } + + if (gfp->error_protection) { + /* (jo) error_protection: add crc16 information to header */ + CRC_writeheader(gfc, gfc->header[gfc->h_ptr].buf); + } + + { + int old = gfc->h_ptr; + assert(gfc->header[old].ptr == gfc->sideinfo_len * 8); + + gfc->h_ptr = (old + 1) & (MAX_HEADER_BUF - 1); + gfc->header[gfc->h_ptr].write_timing = + gfc->header[old].write_timing + bitsPerFrame; + + if (gfc->h_ptr == gfc->w_ptr) { + /* yikes! we are out of header buffer space */ + ERRORF(gfc,"Error: MAX_HEADER_BUF too small in bitstream.c \n"); + } + + } +} + + +inline static int +huffman_coder_count1(lame_global_flags *gfp,int *ix, gr_info *gi) +{ +#ifdef DEBUG + lame_internal_flags *gfc = gfp->internal_flags; +#endif + /* Write count1 area */ + const struct huffcodetab *h = &ht[gi->count1table_select + 32]; + int i,bits=0; +#ifdef DEBUG + int gegebo = gfc->bs.totbit; +#endif + + ix += gi->big_values; + assert(gi->count1table_select < 2); + + + for (i = (gi->count1 - gi->big_values) / 4; i > 0; --i) { + int huffbits = 0; + int p = 0, v; + + v = ix[0]; + if (v) { + p += 8; + if (v < 0) + huffbits++; + assert(-1 <= v && v <= 1); + } + + v = ix[1]; + if (v) { + p += 4; + huffbits *= 2; + if (v < 0) + huffbits++; + assert(-1 <= v && v <= 1); + } + + v = ix[2]; + if (v) { + p += 2; + huffbits *= 2; + if (v < 0) + huffbits++; + assert(-1 <= v && v <= 1); + } + + v = ix[3]; + if (v) { + p++; + huffbits *= 2; + if (v < 0) + huffbits++; + assert(-1 <= v && v <= 1); + } + + ix += 4; + putbits2(gfp,huffbits + h->table[p], h->hlen[p]); + bits += h->hlen[p]; + } +#ifdef DEBUG + DEBUGF(gfc,"%ld %d %d %d\n",gfc->bs.totbit -gegebo, gi->count1bits, gi->big_values, gi->count1); +#endif + return bits; +} + + + +/* + Implements the pseudocode of page 98 of the IS + */ + +inline static int +HuffmanCode ( lame_global_flags* const gfp, const int table_select, int x1, int x2 ) +{ + const struct huffcodetab* h = ht + table_select; + int code = 0; + int cbits = 0; + int xbits = 0; + int sgn_x1 = 0; + int sgn_x2 = 0; + int linbits = h->xlen; + int xlen = h->xlen; + int ext; + + assert ( table_select > 0 ); + + if (x1 < 0) { + sgn_x1++; + x1 = -x1; + } + + if (x2 < 0) { + sgn_x2++; + x2 = -x2; + } + + ext = sgn_x1; + + if (table_select > 15) { + /* use ESC-words */ + if (x1 > 14) { + int linbits_x1 = x1 - 15; + assert ( linbits_x1 <= h->linmax ); + ext |= linbits_x1 << 1; + xbits = linbits; + x1 = 15; + } + + if (x2 > 14) { + int linbits_x2 = x2 - 15; + assert ( linbits_x2 <= h->linmax ); + ext <<= linbits; + ext |= linbits_x2; + xbits += linbits; + x2 = 15; + } + xlen = 16; + } + + if (x1 != 0) { + cbits--; + } + + if (x2 != 0) { + ext <<= 1; + ext |= sgn_x2; + cbits--; + } + + xbits -= cbits; + + assert ( (x1|x2) < 16u ); + + x1 = x1 * xlen + x2; + + code = h->table [x1]; + cbits += h->hlen [x1]; + + assert ( cbits <= MAX_LENGTH ); + assert ( xbits <= MAX_LENGTH ); + + putbits2 ( gfp, code, cbits ); + putbits2 ( gfp, ext, xbits ); + + return cbits + xbits; +} + +static int +Huffmancodebits(lame_global_flags *gfp, int tableindex, int start, int end, int *ix) +{ + int i,bits; + + assert(tableindex < 32); + if (!tableindex) return 0; + + bits=0; + for (i = start; i < end; i += 2) { + bits +=HuffmanCode(gfp,tableindex, ix[i], ix[i + 1]); + } + return bits; +} + + + +/* + Note the discussion of huffmancodebits() on pages 28 + and 29 of the IS, as well as the definitions of the side + information on pages 26 and 27. + */ +static int +ShortHuffmancodebits(lame_global_flags *gfp,int *ix, gr_info *gi) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int bits; + int region1Start; + + region1Start = 3*gfc->scalefac_band.s[3]; + if (region1Start > gi->big_values) + region1Start = gi->big_values; + + /* short blocks do not have a region2 */ + bits = Huffmancodebits(gfp,gi->table_select[0], 0, region1Start, ix); + bits += Huffmancodebits(gfp,gi->table_select[1], region1Start, gi->big_values, ix); + return bits; +} + +static int +LongHuffmancodebits(lame_global_flags *gfp,int *ix, gr_info *gi) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int i, bigvalues,bits=0; + int region1Start, region2Start; + + bigvalues = gi->big_values; + assert(0 <= bigvalues && bigvalues <= 576); + + i = gi->region0_count + 1; + assert(i < 23); + region1Start = gfc->scalefac_band.l[i]; + i += gi->region1_count + 1; + assert(i < 23); + region2Start = gfc->scalefac_band.l[i]; + + if (region1Start > bigvalues) + region1Start = bigvalues; + + if (region2Start > bigvalues) + region2Start = bigvalues; + + bits +=Huffmancodebits(gfp,gi->table_select[0], 0, region1Start, ix); + bits +=Huffmancodebits(gfp,gi->table_select[1], region1Start, region2Start, ix); + bits +=Huffmancodebits(gfp,gi->table_select[2], region2Start, bigvalues, ix); + return bits; +} + +inline static int +writeMainData ( lame_global_flags * const gfp, + int l3_enc [2] [2] [576], + III_scalefac_t scalefac [2] [2] ) +{ + int gr, ch, sfb,data_bits,scale_bits,tot_bits=0; + lame_internal_flags *gfc=gfp->internal_flags; + III_side_info_t *l3_side; + + l3_side = &gfc->l3_side; + if (gfp->version == 1) { + /* MPEG 1 */ + for (gr = 0; gr < 2; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *gi = &l3_side->gr[gr].ch[ch].tt; + int slen1 = slen1_tab[gi->scalefac_compress]; + int slen2 = slen2_tab[gi->scalefac_compress]; + data_bits=0; + scale_bits=0; + +#ifdef DEBUG + hogege = gfc->bs.totbit; +#endif + if (gi->block_type == SHORT_TYPE) { + for (sfb = 0; sfb < SBPSY_s; sfb++) { + int slen = sfb < 6 ? slen1 : slen2; + + assert(scalefac[gr][ch].s[sfb][0]>=0); + assert(scalefac[gr][ch].s[sfb][1]>=0); + assert(scalefac[gr][ch].s[sfb][2]>=0); + + putbits2(gfp,scalefac[gr][ch].s[sfb][0], slen); + putbits2(gfp,scalefac[gr][ch].s[sfb][1], slen); + putbits2(gfp,scalefac[gr][ch].s[sfb][2], slen); + scale_bits += 3*slen; + } + data_bits += ShortHuffmancodebits(gfp,l3_enc[gr][ch], gi); + } else { + int i; + for (i = 0; i < sizeof(scfsi_band) / sizeof(int) - 1; + i++) { + if (gr != 0 && l3_side->scfsi[ch][i]) + continue; + + for (sfb = scfsi_band[i]; sfb < scfsi_band[i + 1]; + sfb++) { + + assert(scalefac[gr][ch].l[sfb]>=0); + putbits2(gfp,scalefac[gr][ch].l[sfb], + sfb < 11 ? slen1 : slen2); + scale_bits += sfb < 11 ? slen1 : slen2; + } + } + data_bits +=LongHuffmancodebits(gfp,l3_enc[gr][ch], gi); + } + data_bits +=huffman_coder_count1(gfp,l3_enc[gr][ch], gi); +#ifdef DEBUG + DEBUGF(gfc,"<%ld> ", gfc->bs.totbit-hogege); +#endif + /* does bitcount in quantize.c agree with actual bit count?*/ + assert(data_bits==gi->part2_3_length-gi->part2_length); + assert(scale_bits==gi->part2_length); + tot_bits += scale_bits + data_bits; + + } /* for ch */ + } /* for gr */ + } else { + /* MPEG 2 */ + gr = 0; + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *gi = &l3_side->gr[gr].ch[ch].tt; + int i, sfb_partition; + assert(gi->sfb_partition_table); + data_bits = 0; + scale_bits=0; + + sfb = 0; + sfb_partition = 0; + if (gi->block_type == SHORT_TYPE) { + for (; sfb_partition < 4; sfb_partition++) { + int sfbs = gi->sfb_partition_table[sfb_partition] / 3; + int slen = gi->slen[sfb_partition]; + for (i = 0; i < sfbs; i++, sfb++) { + putbits2(gfp,Max(scalefac[gr][ch].s[sfb][0], 0U), slen); + putbits2(gfp,Max(scalefac[gr][ch].s[sfb][1], 0U), slen); + putbits2(gfp,Max(scalefac[gr][ch].s[sfb][2], 0U), slen); + scale_bits += 3*slen; + } + } + data_bits += ShortHuffmancodebits(gfp,l3_enc[gr][ch], gi); + } else { + for (; sfb_partition < 4; sfb_partition++) { + int sfbs = gi->sfb_partition_table[sfb_partition]; + int slen = gi->slen[sfb_partition]; + for (i = 0; i < sfbs; i++, sfb++) { + putbits2(gfp,Max(scalefac[gr][ch].l[sfb], 0U), slen); + scale_bits += slen; + } + } + data_bits +=LongHuffmancodebits(gfp,l3_enc[gr][ch], gi); + } + data_bits +=huffman_coder_count1(gfp,l3_enc[gr][ch], gi); + + /* does bitcount in quantize.c agree with actual bit count?*/ + assert(data_bits==gi->part2_3_length-gi->part2_length); + assert(scale_bits==gi->part2_length); + tot_bits += scale_bits + data_bits; + } /* for ch */ + } /* for gf */ + return tot_bits; +} /* main_data */ + + + +/* compute the number of bits required to flush all mp3 frames + currently in the buffer. This should be the same as the + reservoir size. Only call this routine between frames - i.e. + only after all headers and data have been added to the buffer + by format_bitstream(). + + Also compute total_bits_output = + size of mp3 buffer (including frame headers which may not + have yet been send to the mp3 buffer) + + number of bits needed to flush all mp3 frames. + + total_bytes_output is the size of the mp3 output buffer if + lame_encode_flush_nogap() was called right now. + + */ +int +compute_flushbits( const lame_global_flags * gfp, int *total_bytes_output ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int flushbits,remaining_headers; + int bitsPerFrame, mean_bits; + int last_ptr,first_ptr; + first_ptr=gfc->w_ptr; /* first header to add to bitstream */ + last_ptr = gfc->h_ptr - 1; /* last header to add to bitstream */ + if (last_ptr==-1) last_ptr=MAX_HEADER_BUF-1; + + /* add this many bits to bitstream so we can flush all headers */ + flushbits = gfc->header[last_ptr].write_timing - gfc->bs.totbit; + *total_bytes_output=flushbits; + + if (flushbits >= 0) { + /* if flushbits >= 0, some headers have not yet been written */ + /* reduce flushbits by the size of the headers */ + remaining_headers= 1+last_ptr - first_ptr; + if (last_ptr < first_ptr) + remaining_headers= 1+last_ptr - first_ptr + MAX_HEADER_BUF; + flushbits -= remaining_headers*8*gfc->sideinfo_len; + } + + + /* finally, add some bits so that the last frame is complete + * these bits are not necessary to decode the last frame, but + * some decoders will ignore last frame if these bits are missing + */ + getframebits(gfp,&bitsPerFrame,&mean_bits); + flushbits += bitsPerFrame; + *total_bytes_output += bitsPerFrame; + // round up: + if (*total_bytes_output % 8) + *total_bytes_output = 1 + (*total_bytes_output/8); + else + *total_bytes_output = (*total_bytes_output/8); + *total_bytes_output += gfc->bs.buf_byte_idx + 1; + + + if (flushbits<0) { +#if 0 + /* if flushbits < 0, this would mean that the buffer looks like: + * (data...) last_header (data...) (extra data that should not be here...) + */ + DEBUGF(gfc,"last header write_timing = %i \n",gfc->header[last_ptr].write_timing); + DEBUGF(gfc,"first header write_timing = %i \n",gfc->header[first_ptr].write_timing); + DEBUGF(gfc,"bs.totbit: %i \n",gfc->bs.totbit); + DEBUGF(gfc,"first_ptr, last_ptr %i %i \n",first_ptr,last_ptr); + DEBUGF(gfc,"remaining_headers = %i \n",remaining_headers); + DEBUGF(gfc,"bitsperframe: %i \n",bitsPerFrame); + DEBUGF(gfc,"sidelen: %i \n",gfc->sideinfo_len); +#endif +// ERRORF(gfc,"strange error flushing buffer ... \n"); + } + return flushbits; +} + + + +void +flush_bitstream(lame_global_flags *gfp) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_side_info_t *l3_side; + int nbytes; + int flushbits; + int bitsPerFrame, mean_bits; + int last_ptr,first_ptr; + first_ptr=gfc->w_ptr; /* first header to add to bitstream */ + last_ptr = gfc->h_ptr - 1; /* last header to add to bitstream */ + if (last_ptr==-1) last_ptr=MAX_HEADER_BUF-1; + l3_side = &gfc->l3_side; + + + if ((flushbits = compute_flushbits(gfp,&nbytes)) < 0) return; + drain_into_ancillary(gfp,flushbits); + + /* check that the 100% of the last frame has been written to bitstream */ + getframebits(gfp,&bitsPerFrame,&mean_bits); + assert (gfc->header[last_ptr].write_timing + bitsPerFrame == gfc->bs.totbit); + + /* we have padded out all frames with ancillary data, which is the + same as filling the bitreservoir with ancillary data, so : */ + gfc->ResvSize=0; + l3_side->main_data_begin = 0; + +} + + + + +void add_dummy_byte ( lame_global_flags* const gfp, unsigned char val ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int i; + + putbits_noheaders(gfp,val,8); + + for (i=0 ; i< MAX_HEADER_BUF ; ++i) + gfc->header[i].write_timing += 8; +} + + +/* + format_bitstream() + + This is called after a frame of audio has been quantized and coded. + It will write the encoded audio to the bitstream. Note that + from a layer3 encoder's perspective the bit stream is primarily + a series of main_data() blocks, with header and side information + inserted at the proper locations to maintain framing. (See Figure A.7 + in the IS). + */ +int +format_bitstream(lame_global_flags *gfp, int bitsPerFrame, + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int bits,nbytes; + III_side_info_t *l3_side; + l3_side = &gfc->l3_side; + + drain_into_ancillary(gfp,l3_side->resvDrain_pre); + + encodeSideInfo2(gfp,bitsPerFrame); + bits = 8*gfc->sideinfo_len; + bits+=writeMainData(gfp,l3_enc,scalefac); + drain_into_ancillary(gfp,l3_side->resvDrain_post); + bits += l3_side->resvDrain_post; + + l3_side->main_data_begin += (bitsPerFrame-bits)/8; + + /* compare number of bits needed to clear all buffered mp3 frames + * with what we think the resvsize is: */ + if (compute_flushbits(gfp,&nbytes) != gfc->ResvSize) { + ERRORF(gfc,"Internal buffer inconsistency. flushbits <> ResvSize"); + } + + + /* compare main_data_begin for the next frame with what we + * think the resvsize is: */ + if ((l3_side->main_data_begin * 8) != gfc->ResvSize ) { + ERRORF(gfc,"bit reservoir error: \n" + "l3_side->main_data_begin: %i \n" + "Resvoir size: %i \n" + "resv drain (post) %i \n" + "resv drain (pre) %i \n" + "header and sideinfo: %i \n" + "data bits: %i \n" + "total bits: %i (remainder: %i) \n" + "bitsperframe: %i \n", + + 8*l3_side->main_data_begin, + gfc->ResvSize, + l3_side->resvDrain_post, + l3_side->resvDrain_pre, + 8*gfc->sideinfo_len, + bits-l3_side->resvDrain_post-8*gfc->sideinfo_len, + bits, bits % 8, + bitsPerFrame + ); + + gfc->ResvSize = l3_side->main_data_begin*8; + }; + assert(gfc->bs.totbit % 8 == 0); + + if (gfc->bs.totbit > 1000000000 ) { + /* to avoid totbit overflow, (at 8h encoding at 128kbs) lets reset bit counter*/ + int i; + for (i=0 ; i< MAX_HEADER_BUF ; ++i) + gfc->header[i].write_timing -= gfc->bs.totbit; + gfc->bs.totbit=0; + } + + + return 0; +} + + + + + +/* copy data out of the internal MP3 bit buffer into a user supplied + unsigned char buffer. + + mp3data=0 indicates data in buffer is an id3tags and VBR tags + mp3data=1 data is real mp3 frame data. + + +*/ +int copy_buffer(lame_internal_flags *gfc,unsigned char *buffer,int size,int mp3data) +{ + Bit_stream_struc *bs=&gfc->bs; + int minimum = bs->buf_byte_idx + 1; + if (minimum <= 0) return 0; + if (size!=0 && minimum>size) return -1; /* buffer is too small */ + memcpy(buffer,bs->buf,minimum); + bs->buf_byte_idx = -1; + bs->buf_bit_idx = 0; + + if (mp3data) { + UpdateMusicCRC(&gfc->nMusicCRC,buffer,minimum); + } + return minimum; +} + + +void init_bit_stream_w(lame_internal_flags *gfc) +{ + gfc->bs.buf = (unsigned char *) malloc(BUFFER_SIZE); + gfc->bs.buf_size = BUFFER_SIZE; + + gfc->h_ptr = gfc->w_ptr = 0; + gfc->header[gfc->h_ptr].write_timing = 0; + gfc->bs.buf_byte_idx = -1; + gfc->bs.buf_bit_idx = 0; + gfc->bs.totbit = 0; +} + +/* end of bitstream.c */ diff -Nru swftools-0.9.2+ds1/lib/lame/bitstream.h swftools-0.9.1/lib/lame/bitstream.h --- swftools-0.9.2+ds1/lib/lame/bitstream.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/bitstream.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * MP3 bitstream Output interface for LAME + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * 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 LAME_BITSTREAM_H +#define LAME_BITSTREAM_H +#include "util.h" + +int format_bitstream(lame_global_flags *gfp, int i, + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2] ); + +void flush_bitstream(lame_global_flags *gfp); +void add_dummy_byte ( lame_global_flags* const gfp, unsigned char val ); + +int copy_buffer(lame_internal_flags *gfc,unsigned char *buffer,int buffer_size,int update_crc); +void init_bit_stream_w(lame_internal_flags *gfc); +void CRC_writeheader (lame_internal_flags *gfc, char *buffer); +int compute_flushbits(const lame_global_flags *gfp, int *nbytes); + + +#endif diff -Nru swftools-0.9.2+ds1/lib/lame/config_static.h swftools-0.9.1/lib/lame/config_static.h --- swftools-0.9.2+ds1/lib/lame/config_static.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/config_static.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,120 @@ +#include "../../config.h" + +/* Define if you have alloca, as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define if you have and it should be used (not on Ultrix). */ +#define HAVE_ALLOCA_H 1 + +/* Define if the `long double' type works. */ +#define HAVE_LONG_DOUBLE 1 + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* #undef int8_t */ +#define uint8_t unsigned char +/* #undef int18_t */ +#define uint16_t unsigned short +/* #undef int32_t */ +#define uint32_t unsigned int +/* #undef int64_t */ +#define uint64_t unsigned long long +#define ieee854_float80_t long double +#define ieee754_float64_t double +#define ieee754_float32_t float + +/* The number of bytes in a double. */ +#define SIZEOF_DOUBLE 8 + +/* The number of bytes in a float. */ +#define SIZEOF_FLOAT 4 + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/* The number of bytes in a long double. */ +/* #undef SIZEOF_LONG_DOUBLE */ + +/* The number of bytes in a long long. */ +#define SIZEOF_LONG_LONG 8 + +/* The number of bytes in a short. */ +#define SIZEOF_SHORT 2 + +/* The number of bytes in a unsigned int. */ +#define SIZEOF_UNSIGNED_INT 4 + +/* The number of bytes in a unsigned long. */ +#define SIZEOF_UNSIGNED_LONG 4 + +/* The number of bytes in a unsigned long long. */ +#define SIZEOF_UNSIGNED_LONG_LONG 8 + +/* The number of bytes in a unsigned short. */ +#define SIZEOF_UNSIGNED_SHORT 2 + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_TERMCAP_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if compiler has function prototypes */ +#define PROTOTYPES 1 + +/* system has 80 bit floats */ +#define HAVE_IEEE854_FLOAT80 1 + +/* requested by Frank, seems to be temporary needed for a smooth transition */ +#define LAME_LIBRARY_BUILD 1 + +/* have working GTK */ +#define HAVE_GTK 1 + +/* build with layer 1 decoding */ +#define USE_LAYER_1 1 + +/* build with layer 2 decoding */ +#define USE_LAYER_2 1 + +/* enable VBR bitrate histogram */ +#define BRHIST 1 + +/* have termcap */ +#define HAVE_TERMCAP 1 + +/* IEEE754 compatible machine */ +#define TAKEHIRO_IEEE754_HACK 1 + +/* no debug build */ +#define NDEBUG 1 + diff -Nru swftools-0.9.2+ds1/lib/lame/encoder.c swftools-0.9.1/lib/lame/encoder.c --- swftools-0.9.2+ds1/lib/lame/encoder.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/encoder.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,666 @@ +/* + * LAME MP3 encoding engine + * + * Copyright (c) 1999 Mark Taylor + * + * 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. + */ + +/* $Id: encoder.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#include + +#include "lame.h" +#include "util.h" +#include "newmdct.h" +#include "psymodel.h" +#include "quantize.h" +#include "quantize_pvt.h" +#include "bitstream.h" +#include "VbrTag.h" +#include "vbrquantize.h" + +#ifdef WITH_DMALLOC +#include +#endif + + +/* + * auto-adjust of ATH, useful for low volume + * Gabriel Bouvigne 3 feb 2001 + * + * modifies some values in + * gfp->internal_flags->ATH + * (gfc->ATH) + */ +void +adjust_ATH( lame_global_flags* const gfp, + FLOAT8 tot_ener[2][4] ) +{ + lame_internal_flags* const gfc = gfp->internal_flags; + int gr, channel; + FLOAT max_pow, max_pow_alt; + FLOAT8 max_val; + + if (gfc->ATH->use_adjust == 0) { + gfc->ATH->adjust = 1.0; /* no adjustment */ + return; + } + + switch( gfp->athaa_loudapprox ) { + case 1: + /* flat approximation for loudness (squared) */ + max_pow = 0; + for ( gr = 0; gr < gfc->mode_gr; ++gr ) + for ( channel = 0; channel < gfc->channels_out; ++channel ) + max_pow = Max( max_pow, tot_ener[gr][channel] ); + max_pow *= 0.25/ 5.6e13; /* scale to 0..1 (5.6e13), and tune (0.25) */ + break; + + case 2: /* jd - 2001 mar 12, 27, jun 30 */ + { /* loudness based on equal loudness curve; */ + /* use granule with maximum combined loudness*/ + FLOAT gr2_max; + max_pow = gfc->loudness_sq[0][0]; + if( gfc->channels_out == 2 ) { + max_pow += gfc->loudness_sq[0][1]; + gr2_max = gfc->loudness_sq[1][0] + gfc->loudness_sq[1][1]; + } else { + gr2_max = gfc->loudness_sq[1][0]; + max_pow += max_pow; + gr2_max += gr2_max; + } + if( gfc->mode_gr == 2 ) { + max_pow = Max( max_pow, gr2_max ); + } + max_pow *= 0.5; /* max_pow approaches 1.0 for full band noise*/ + break; + } + + default: /* jd - 2001 mar 27, 31, jun 30 */ + /* no adaptive threshold */ + max_pow = 1.0 / gfc->athaa_sensitivity_p; + break; + } + + /* jd - 2001 mar 31, jun 30 */ + /* user tuning of ATH adjustment region */ + max_pow_alt = max_pow; + max_pow *= gfc->athaa_sensitivity_p; + if (gfc->presetTune.use) + max_pow_alt *= pow( 10.0, gfc->presetTune.athadjust_safe_athaasensitivity / -10.0 ); + + /* adjust ATH depending on range of maximum value + */ + switch ( gfc->ATH->use_adjust ) { + + case 1: + max_val = sqrt( max_pow ); /* GB's original code requires a maximum */ + max_val *= 32768; /* sample or loudness value up to 32768 */ + + /* by Gabriel Bouvigne */ + if (0.5 < max_val / 32768) { /* value above 50 % */ + gfc->ATH->adjust = 1.0; /* do not reduce ATH */ + } + else if (0.3 < max_val / 32768) { /* value above 30 % */ + gfc->ATH->adjust *= 0.955; /* reduce by ~0.2 dB */ + if (gfc->ATH->adjust < 0.3) /* but ~5 dB in maximum */ + gfc->ATH->adjust = 0.3; + } + else { /* value below 30 % */ + gfc->ATH->adjust *= 0.93; /* reduce by ~0.3 dB */ + if (gfc->ATH->adjust < 0.01) /* but 20 dB in maximum */ + gfc->ATH->adjust = 0.01; + } + break; + + case 2: + max_val = Min( max_pow, 1.0 ) * 32768; /* adapt for RH's adjust */ + + { /* by Robert Hegemann */ + /* this code reduces slowly the ATH (speed of 12 dB per second) + */ + FLOAT8 + //x = Max (640, 320*(int)(max_val/320)); + x = Max (32, 32*(int)(max_val/32)); + x = x/32768; + gfc->ATH->adjust *= gfc->ATH->decay; + if (gfc->ATH->adjust < x) /* but not more than f(x) dB */ + gfc->ATH->adjust = x; + } + break; + + case 3: + { /* jd - 2001 feb27, mar12,20, jun30, jul22 */ + /* continuous curves based on approximation */ + /* to GB's original values. */ + FLOAT8 adj_lim_new; + /* For an increase in approximate loudness, */ + /* set ATH adjust to adjust_limit immediately*/ + /* after a delay of one frame. */ + /* For a loudness decrease, reduce ATH adjust*/ + /* towards adjust_limit gradually. */ + /* max_pow is a loudness squared or a power. */ + if( max_pow > 0.03125) { /* ((1 - 0.000625)/ 31.98) from curve below */ + if( gfc->ATH->adjust >= 1.0) { + gfc->ATH->adjust = 1.0; + if (gfc->presetTune.use) { + if (max_pow_alt > gfc->presetTune.athadjust_safe_noiseshaping_thre) + gfc->presetTune.athadjust_safe_noiseshaping = 1; + else + gfc->presetTune.athadjust_safe_noiseshaping = 0; + } + } else { + /* preceding frame has lower ATH adjust; */ + /* ascend only to the preceding adjust_limit */ + /* in case there is leading low volume */ + if( gfc->ATH->adjust < gfc->ATH->adjust_limit) { + gfc->ATH->adjust = gfc->ATH->adjust_limit; + if (gfc->presetTune.use) { + if (max_pow_alt > gfc->presetTune.athadjust_safe_noiseshaping_thre) + gfc->presetTune.athadjust_safe_noiseshaping = 1; + else + gfc->presetTune.athadjust_safe_noiseshaping = 0; + } + } + } + gfc->ATH->adjust_limit = 1.0; + } else { /* adjustment curve */ + /* about 32 dB maximum adjust (0.000625) */ + adj_lim_new = 31.98 * max_pow + 0.000625; + if( gfc->ATH->adjust >= adj_lim_new) { /* descend gradually */ + gfc->ATH->adjust *= adj_lim_new * 0.075 + 0.925; + if( gfc->ATH->adjust < adj_lim_new) { /* stop descent */ + gfc->ATH->adjust = adj_lim_new; + } + } else { /* ascend */ + if( gfc->ATH->adjust_limit >= adj_lim_new) { + gfc->ATH->adjust = adj_lim_new; + } else { /* preceding frame has lower ATH adjust; */ + /* ascend only to the preceding adjust_limit */ + if( gfc->ATH->adjust < gfc->ATH->adjust_limit) { + gfc->ATH->adjust = gfc->ATH->adjust_limit; + } + } + } + gfc->ATH->adjust_limit = adj_lim_new; + } + } + break; + + default: + gfc->ATH->adjust = 1.0; /* no adjustment */ + break; + } /* switch */ +} + +/************************************************************************ +* +* encodeframe() Layer 3 +* +* encode a single frame +* +************************************************************************ +lame_encode_frame() + + + gr 0 gr 1 +inbuf: |--------------|---------------|-------------| +MDCT output: |--------------|---------------|-------------| + +FFT's <---------1024----------> + <---------1024--------> + + + + inbuf = buffer of PCM data size=MP3 framesize + encoder acts on inbuf[ch][0], but output is delayed by MDCTDELAY + so the MDCT coefficints are from inbuf[ch][-MDCTDELAY] + + psy-model FFT has a 1 granule delay, so we feed it data for the + next granule. + FFT is centered over granule: 224+576+224 + So FFT starts at: 576-224-MDCTDELAY + + MPEG2: FFT ends at: BLKSIZE+576-224-MDCTDELAY + MPEG1: FFT ends at: BLKSIZE+2*576-224-MDCTDELAY (1904) + + FFT starts at 576-224-MDCTDELAY (304) = 576-FFTOFFSET + +*/ + +typedef FLOAT8 chgrdata[2][2]; + +int lame_encode_mp3_frame ( // Output + lame_global_flags* const gfp, // Context + sample_t* inbuf_l, // Input + sample_t* inbuf_r, // Input + unsigned char* mp3buf, // Output + int mp3buf_size ) // Output +{ +#ifdef macintosh /* PLL 14/04/2000 */ + static FLOAT8 xr[2][2][576]; + static int l3_enc[2][2][576]; +#else + FLOAT8 xr[2][2][576]; + int l3_enc[2][2][576]; +#endif + int mp3count; + III_psy_ratio masking_LR[2][2]; /*LR masking & energy */ + III_psy_ratio masking_MS[2][2]; /*MS masking & energy */ + III_psy_ratio (*masking)[2][2]; /*pointer to selected maskings*/ + III_scalefac_t scalefac[2][2]; + const sample_t *inbuf[2]; + lame_internal_flags *gfc=gfp->internal_flags; + + FLOAT8 tot_ener[2][4]; + FLOAT8 ms_ener_ratio[2]={.5,.5}; + chgrdata pe,pe_MS; + chgrdata *pe_use; + + int ch,gr,mean_bits; + int bitsPerFrame; + + int check_ms_stereo; + FLOAT8 ms_ratio_next = 0.; + FLOAT8 ms_ratio_prev = 0.; + + + memset((char *) masking_LR, 0, sizeof(masking_LR)); + memset((char *) masking_MS, 0, sizeof(masking_MS)); + memset((char *) scalefac, 0, sizeof(scalefac)); + inbuf[0]=inbuf_l; + inbuf[1]=inbuf_r; + + check_ms_stereo = (gfp->mode == JOINT_STEREO); + gfc->mode_ext = MPG_MD_LR_LR; + + if (gfc->lame_encode_frame_init==0 ) { + gfc->lame_encode_frame_init=1; + + /* padding method as described in + * "MPEG-Layer3 / Bitstream Syntax and Decoding" + * by Martin Sieler, Ralph Sperschneider + * + * note: there is no padding for the very first frame + * + * Robert.Hegemann@gmx.de 2000-06-22 + */ + + gfc->frac_SpF = ((gfp->version+1)*72000L*gfp->brate) % gfp->out_samplerate; + gfc->slot_lag = gfc->frac_SpF; + + /* check FFT will not use a negative starting offset */ +#if 576 < FFTOFFSET +# error FFTOFFSET greater than 576: FFT uses a negative offset +#endif + /* check if we have enough data for FFT */ + assert(gfc->mf_size>=(BLKSIZE+gfp->framesize-FFTOFFSET)); + /* check if we have enough data for polyphase filterbank */ + /* it needs 1152 samples + 286 samples ignored for one granule */ + /* 1152+576+286 samples for two granules */ + assert(gfc->mf_size>=(286+576*(1+gfc->mode_gr))); + + /* prime the MDCT/polyphase filterbank with a short block */ + { + int i,j; + sample_t primebuff0[286+1152+576]; + sample_t primebuff1[286+1152+576]; + for (i=0, j=0; i<286+576*(1+gfc->mode_gr); ++i) { + if (i<576*gfc->mode_gr) { + primebuff0[i]=0; + if (gfc->channels_out==2) + primebuff1[i]=0; + }else{ + primebuff0[i]=inbuf[0][j]; + if (gfc->channels_out==2) + primebuff1[i]=inbuf[1][j]; + ++j; + } + } + /* polyphase filtering / mdct */ + for ( gr = 0; gr < gfc->mode_gr; gr++ ) { + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + gfc->l3_side.gr[gr].ch[ch].tt.block_type=SHORT_TYPE; + } + } + mdct_sub48(gfc, primebuff0, primebuff1, xr); + } + + iteration_init(gfp); + + /* prepare for ATH auto adjustment: + * we want to decrease the ATH by 12 dB per second + */ { + FLOAT8 frame_duration = 576. * gfc->mode_gr / gfp->out_samplerate; + gfc->ATH->decay = pow(10., -12./10. * frame_duration); + gfc->ATH->adjust = 0.01; /* minimum, for leading low loudness */ + gfc->ATH->adjust_limit = 1.0; /* on lead, allow adjust up to maximum */ + } + } + + + /********************** padding *****************************/ + switch (gfp->padding_type) { + case PAD_NO: + gfc->padding = FALSE; + break; + case PAD_ALL: + gfc->padding = TRUE; + break; + case PAD_ADJUST: + default: + if (gfp->VBR!=vbr_off) { + gfc->padding = FALSE; + } else { + if (gfp->disable_reservoir) { + gfc->padding = FALSE; + /* if the user specified --nores, dont very gfc->padding either */ + /* tiny changes in frac_SpF rounding will cause file differences */ + }else{ + /* padding method as described in + * "MPEG-Layer3 / Bitstream Syntax and Decoding" + * by Martin Sieler, Ralph Sperschneider + * + * note: there is no padding for the very first frame + * + * Robert.Hegemann@gmx.de 2000-06-22 + */ + + gfc->slot_lag -= gfc->frac_SpF; + if (gfc->slot_lag < 0) { + gfc->slot_lag += gfp->out_samplerate; + gfc->padding = TRUE; + } else { + gfc->padding = FALSE; + } + } /* reservoir enabled */ + } + } + + + if (gfc->psymodel) { + /* psychoacoustic model + * psy model has a 1 granule (576) delay that we must compensate for + * (mt 6/99). + */ + int ret; + const sample_t *bufp[2]; /* address of beginning of left & right granule */ + int blocktype[2]; + + ms_ratio_prev=gfc->ms_ratio[gfc->mode_gr-1]; + for (gr=0; gr < gfc->mode_gr ; gr++) { + + for ( ch = 0; ch < gfc->channels_out; ch++ ) + bufp[ch] = &inbuf[ch][576 + gr*576-FFTOFFSET]; + + if (gfc->nsPsy.use) { + ret=L3psycho_anal_ns( gfp, bufp, gr, + &gfc->ms_ratio[gr],&ms_ratio_next, + masking_LR, masking_MS, + pe[gr],pe_MS[gr],tot_ener[gr],blocktype); + } else { + ret=L3psycho_anal( gfp, bufp, gr, + &gfc->ms_ratio[gr],&ms_ratio_next, + masking_LR, masking_MS, + pe[gr],pe_MS[gr],tot_ener[gr],blocktype); + } + if (ret!=0) return -4; + + for ( ch = 0; ch < gfc->channels_out; ch++ ) + gfc->l3_side.gr[gr].ch[ch].tt.block_type=blocktype[ch]; + + if (check_ms_stereo) { + ms_ener_ratio[gr] = tot_ener[gr][2]+tot_ener[gr][3]; + if (ms_ener_ratio[gr]>0) + ms_ener_ratio[gr] = tot_ener[gr][3]/ms_ener_ratio[gr]; + } + + } + }else{ + for (gr=0; gr < gfc->mode_gr ; gr++) + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + gfc->l3_side.gr[gr].ch[ch].tt.block_type=NORM_TYPE; + pe_MS[gr][ch]=pe[gr][ch]=700; + } + } + + + + /* auto-adjust of ATH, useful for low volume */ + adjust_ATH( gfp, tot_ener ); + + + + /* block type flags */ + for( gr = 0; gr < gfc->mode_gr; gr++ ) { + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + gr_info *cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + cod_info->mixed_block_flag = 0; /* never used by this model */ + if (cod_info->block_type == NORM_TYPE ) + cod_info->window_switching_flag = 0; + else + cod_info->window_switching_flag = 1; + } + } + + + /* polyphase filtering / mdct */ + mdct_sub48(gfc, inbuf[0], inbuf[1], xr); + /* re-order the short blocks, for more efficient encoding below */ + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + if (cod_info->block_type==SHORT_TYPE) { + freorder(gfc->scalefac_band.s,xr[gr][ch]); + } + } + } + + + /* use m/s gfc->channels_out? */ + if (check_ms_stereo) { + int gr0 = 0, gr1 = gfc->mode_gr-1; + /* make sure block type is the same in each channel */ + check_ms_stereo = + (gfc->l3_side.gr[gr0].ch[0].tt.block_type==gfc->l3_side.gr[gr0].ch[1].tt.block_type) && + (gfc->l3_side.gr[gr1].ch[0].tt.block_type==gfc->l3_side.gr[gr1].ch[1].tt.block_type); + } + + /* Here will be selected MS or LR coding of the 2 stereo channels */ + + assert ( gfc->mode_ext == MPG_MD_LR_LR ); + gfc->mode_ext = MPG_MD_LR_LR; + + if (gfp->force_ms) { + gfc->mode_ext = MPG_MD_MS_LR; + } else if (check_ms_stereo) { + /* ms_ratio = is scaled, for historical reasons, to look like + a ratio of side_channel / total. + 0 = signal is 100% mono + .5 = L & R uncorrelated + */ + + /* [0] and [1] are the results for the two granules in MPEG-1, + * in MPEG-2 it's only a faked averaging of the same value + * _prev is the value of the last granule of the previous frame + * _next is the value of the first granule of the next frame + */ + FLOAT8 ms_ratio_ave1; + FLOAT8 ms_ratio_ave2; + FLOAT8 threshold1 = 0.35; + FLOAT8 threshold2 = 0.45; + + /* take an average */ + if (gfc->mode_gr==1) { + /* MPEG2 - no second granule */ + ms_ratio_ave1 = 0.33 * ( gfc->ms_ratio[0] + ms_ratio_prev + ms_ratio_next ); + ms_ratio_ave2 = gfc->ms_ratio[0]; + }else{ + ms_ratio_ave1 = 0.25 * ( gfc->ms_ratio[0] + gfc->ms_ratio[1] + ms_ratio_prev + ms_ratio_next ); + ms_ratio_ave2 = 0.50 * ( gfc->ms_ratio[0] + gfc->ms_ratio[1] ); + } + + if (gfp->mode_automs) { + if ( gfp->compression_ratio < 11.025 ) { + /* 11.025 => 1, 6.3 => 0 */ + double thr = (gfp->compression_ratio - 6.3) / (11.025 - 6.3); + if (thr<0) thr=0; + threshold1 *= thr; + threshold2 *= thr; + } + } + + if ((ms_ratio_ave1 < threshold1 && ms_ratio_ave2 < threshold2) || gfc->nsPsy.use) { + int sum_pe_MS = 0; + int sum_pe_LR = 0; + for ( gr = 0; gr < gfc->mode_gr; gr++ ) { + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + sum_pe_MS += pe_MS[gr][ch]; + sum_pe_LR += pe[gr][ch]; + } + } + + /* based on PE: M/S coding would not use much more bits than L/R coding */ + + if (sum_pe_MS <= 1.07 * sum_pe_LR && !gfc->nsPsy.use) gfc->mode_ext = MPG_MD_MS_LR; + if (sum_pe_MS <= 1.00 * sum_pe_LR && gfc->nsPsy.use) gfc->mode_ext = MPG_MD_MS_LR; + } + } + + +#if defined(HAVE_GTK) + /* copy data for MP3 frame analyzer */ + if (gfp->analysis && gfc->pinfo != NULL) { + for ( gr = 0; gr < gfc->mode_gr; gr++ ) { + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + gfc->pinfo->ms_ratio[gr]=gfc->ms_ratio[gr]; + gfc->pinfo->ms_ener_ratio[gr]=ms_ener_ratio[gr]; + gfc->pinfo->blocktype[gr][ch]= + gfc->l3_side.gr[gr].ch[ch].tt.block_type; + memcpy(gfc->pinfo->xr[gr][ch],xr[gr][ch],sizeof(xr[gr][ch])); + /* in psymodel, LR and MS data was stored in pinfo. + switch to MS data: */ + if (gfc->mode_ext==MPG_MD_MS_LR) { + gfc->pinfo->pe[gr][ch]=gfc->pinfo->pe[gr][ch+2]; + gfc->pinfo->ers[gr][ch]=gfc->pinfo->ers[gr][ch+2]; + memcpy(gfc->pinfo->energy[gr][ch],gfc->pinfo->energy[gr][ch+2], + sizeof(gfc->pinfo->energy[gr][ch])); + } + } + } + } +#endif + + + + + /* bit and noise allocation */ + if (MPG_MD_MS_LR == gfc->mode_ext) { + masking = &masking_MS; /* use MS masking */ + pe_use = &pe_MS; + } else { + masking = &masking_LR; /* use LR masking */ + pe_use = &pe; + } + + + if (gfc->nsPsy.use && (gfp->VBR == vbr_off || gfp->VBR == vbr_abr)) { + static FLOAT fircoef[19] = { + -0.0207887,-0.0378413,-0.0432472,-0.031183, + 7.79609e-18,0.0467745,0.10091,0.151365, + 0.187098,0.2,0.187098,0.151365, + 0.10091,0.0467745,7.79609e-18,-0.031183, + -0.0432472,-0.0378413,-0.0207887, + }; + int i; + FLOAT8 f; + + for(i=0;i<18;i++) gfc->nsPsy.pefirbuf[i] = gfc->nsPsy.pefirbuf[i+1]; + + i=0; + gfc->nsPsy.pefirbuf[18] = 0; + for ( gr = 0; gr < gfc->mode_gr; gr++ ) { + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + gfc->nsPsy.pefirbuf[18] += (*pe_use)[gr][ch]; + i++; + } + } + + gfc->nsPsy.pefirbuf[18] = gfc->nsPsy.pefirbuf[18] / i; + f = 0; + for(i=0;i<19;i++) f += gfc->nsPsy.pefirbuf[i] * fircoef[i]; + + for ( gr = 0; gr < gfc->mode_gr; gr++ ) { + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + (*pe_use)[gr][ch] *= 670 / f; + } + } + } + + switch (gfp->VBR){ + default: + case vbr_off: + iteration_loop( gfp,*pe_use,ms_ener_ratio, xr, *masking, l3_enc, scalefac); + break; + case vbr_mt: + VBR_quantize( gfp,*pe_use,ms_ener_ratio, xr, *masking, l3_enc, scalefac); + break; + case vbr_rh: + case vbr_mtrh: + VBR_iteration_loop( gfp,*pe_use,ms_ener_ratio, xr, *masking, l3_enc, scalefac); + break; + case vbr_abr: + ABR_iteration_loop( gfp,*pe_use,ms_ener_ratio, xr, *masking, l3_enc, scalefac); + break; + } + + /* write the frame to the bitstream */ + getframebits(gfp, &bitsPerFrame, &mean_bits); + + format_bitstream( gfp, bitsPerFrame, l3_enc, scalefac); + + /* copy mp3 bit buffer into array */ + mp3count = copy_buffer(gfc,mp3buf,mp3buf_size,1); + + + + + if (gfp->bWriteVbrTag) AddVbrFrame(gfp); + + +#if defined(HAVE_GTK) + /* copy data for MP3 frame analyzer */ + if (gfp->analysis && gfc->pinfo != NULL) { + int j; + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + for ( j = 0; j < FFTOFFSET; j++ ) + gfc->pinfo->pcmdata[ch][j] = gfc->pinfo->pcmdata[ch][j+gfp->framesize]; + for ( j = FFTOFFSET; j < 1600; j++ ) { + gfc->pinfo->pcmdata[ch][j] = inbuf[ch][j-FFTOFFSET]; + } + } + set_frame_pinfo (gfp, xr, *masking, l3_enc, scalefac); + } +#endif + + updateStats( gfc ); + + return mp3count; +} diff -Nru swftools-0.9.2+ds1/lib/lame/encoder.h swftools-0.9.1/lib/lame/encoder.h --- swftools-0.9.2+ds1/lib/lame/encoder.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/encoder.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,148 @@ +/* + * encoder.h include file + * + * Copyright (c) 2000 Mark Taylor + * + * 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 LAME_ENCODER_H +#define LAME_ENCODER_H + +/*********************************************************************** +* +* encoder and decoder delays +* +***********************************************************************/ + +/* + * layer III enc->dec delay: 1056 (1057?) (observed) + * layer II enc->dec delay: 480 (481?) (observed) + * + * polyphase 256-16 (dec or enc) = 240 + * mdct 256+32 (9*32) (dec or enc) = 288 + * total: 512+16 + * + * My guess is that delay of polyphase filterbank is actualy 240.5 + * (there are technical reasons for this, see postings in mp3encoder). + * So total Encode+Decode delay = ENCDELAY + 528 + 1 + */ + +/* + * ENCDELAY The encoder delay. + * + * Minimum allowed is MDCTDELAY (see below) + * + * The first 96 samples will be attenuated, so using a value less than 96 + * will result in corrupt data for the first 96-ENCDELAY samples. + * + * suggested: 576 + * set to 1160 to sync with FhG. + */ + +#define ENCDELAY 576 + + + +/* + * make sure there is at least one complete frame after the + * last frame containing real data + * + * Using a value of 288 would be sufficient for a + * a very sophisticated decoder that can decode granule-by-granule instead + * of frame by frame. But lets not assume this, and assume the decoder + * will not decode frame N unless it also has data for frame N+1 + * + */ +/*#define POSTDELAY 288*/ +#define POSTDELAY 1152 + + + +/* + * delay of the MDCT used in mdct.c + * original ISO routines had a delay of 528! + * Takehiro's routines: + */ + +#define MDCTDELAY 48 +#define FFTOFFSET (224+MDCTDELAY) + +/* + * Most decoders, including the one we use, have a delay of 528 samples. + */ + +#define DECDELAY 528 + + +/* number of subbands */ +#define SBLIMIT 32 + +/* parition bands bands */ +#define CBANDS 64 + +/* number of critical bands/scale factor bands where masking is computed*/ +#define SBPSY_l 21 +#define SBPSY_s 12 + +/* total number of scalefactor bands encoded */ +#define SBMAX_l 22 +#define SBMAX_s 13 + + + +/* FFT sizes */ +#define BLKSIZE 1024 +#define HBLKSIZE (BLKSIZE/2 + 1) +#define BLKSIZE_s 256 +#define HBLKSIZE_s (BLKSIZE_s/2 + 1) + + +/* #define switch_pe 1800 */ +#define NORM_TYPE 0 +#define START_TYPE 1 +#define SHORT_TYPE 2 +#define STOP_TYPE 3 + +/* + * Mode Extention: + * When we are in stereo mode, there are 4 possible methods to store these + * two channels. The stereo modes -m? are using a subset of them. + * + * -ms: MPG_MD_LR_LR + * -mj: MPG_MD_LR_LR and MPG_MD_MS_LR + * -mf: MPG_MD_MS_LR + * -mi: all + */ + +#define MPG_MD_LR_LR 0 +#define MPG_MD_LR_I 1 +#define MPG_MD_MS_LR 2 +#define MPG_MD_MS_I 3 + + +#include "machine.h" +#include "lame.h" + +int lame_encode_mp3_frame ( + lame_global_flags* const gfp, + sample_t* inbuf_l, + sample_t* inbuf_r, + unsigned char* mp3buf, + int mp3buf_size ); + +#endif /* LAME_ENCODER_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/fft.c swftools-0.9.1/lib/lame/fft.c --- swftools-0.9.2+ds1/lib/lame/fft.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/fft.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,310 @@ +/* +** FFT and FHT routines +** Copyright 1988, 1993; Ron Mayer +** +** fht(fz,n); +** Does a hartley transform of "n" points in the array "fz". +** +** NOTE: This routine uses at least 2 patented algorithms, and may be +** under the restrictions of a bunch of different organizations. +** Although I wrote it completely myself; it is kind of a derivative +** of a routine I once authored and released under the GPL, so it +** may fall under the free software foundation's restrictions; +** it was worked on as a Stanford Univ project, so they claim +** some rights to it; it was further optimized at work here, so +** I think this company claims parts of it. The patents are +** held by R. Bracewell (the FHT algorithm) and O. Buneman (the +** trig generator), both at Stanford Univ. +** If it were up to me, I'd say go do whatever you want with it; +** but it would be polite to give credit to the following people +** if you use this anywhere: +** Euler - probable inventor of the fourier transform. +** Gauss - probable inventor of the FFT. +** Hartley - probable inventor of the hartley transform. +** Buneman - for a really cool trig generator +** Mayer(me) - for authoring this particular version and +** including all the optimizations in one package. +** Thanks, +** Ron Mayer; mayer@acuson.com +** and added some optimization by +** Mather - idea of using lookup table +** Takehiro - some dirty hack for speed up +*/ + +/* $Id: fft.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#include +#include "util.h" +#include "fft.h" + + + + +#ifdef WITH_DMALLOC +#include +#endif + +#define TRI_SIZE (5-1) /* 1024 = 4**5 */ + +static const FLOAT costab[TRI_SIZE*2] = { + 9.238795325112867e-01, 3.826834323650898e-01, + 9.951847266721969e-01, 9.801714032956060e-02, + 9.996988186962042e-01, 2.454122852291229e-02, + 9.999811752826011e-01, 6.135884649154475e-03 +}; + +static void fht(FLOAT *fz, int n) +{ + const FLOAT *tri = costab; + int k4; + FLOAT *fi, *fn, *gi; + + n <<= 1; /* to get BLKSIZE, because of 3DNow! ASM routine */ + fn = fz + n; + k4 = 4; + do { + FLOAT s1, c1; + int i, k1, k2, k3, kx; + kx = k4 >> 1; + k1 = k4; + k2 = k4 << 1; + k3 = k2 + k1; + k4 = k2 << 1; + fi = fz; + gi = fi + kx; + do { + FLOAT f0,f1,f2,f3; + f1 = fi[0] - fi[k1]; + f0 = fi[0] + fi[k1]; + f3 = fi[k2] - fi[k3]; + f2 = fi[k2] + fi[k3]; + fi[k2] = f0 - f2; + fi[0 ] = f0 + f2; + fi[k3] = f1 - f3; + fi[k1] = f1 + f3; + f1 = gi[0] - gi[k1]; + f0 = gi[0] + gi[k1]; + f3 = SQRT2 * gi[k3]; + f2 = SQRT2 * gi[k2]; + gi[k2] = f0 - f2; + gi[0 ] = f0 + f2; + gi[k3] = f1 - f3; + gi[k1] = f1 + f3; + gi += k4; + fi += k4; + } while (fiwindow_s[0]; + int i; + int j; + int b; + + for (b = 0; b < 3; b++) { + FLOAT *x = &x_real[b][BLKSIZE_s / 2]; + short k = (576 / 3) * (b + 1); + j = BLKSIZE_s / 8 - 1; + do { + FLOAT f0,f1,f2,f3, w; + + i = rv_tbl[j << 2]; + + f0 = ms00(ch01); w = ms10(ch01); f1 = f0 - w; f0 = f0 + w; + f2 = ms20(ch01); w = ms30(ch01); f3 = f2 - w; f2 = f2 + w; + + x -= 4; + x[0] = f0 + f2; + x[2] = f0 - f2; + x[1] = f1 + f3; + x[3] = f1 - f3; + + f0 = ms01(ch01); w = ms11(ch01); f1 = f0 - w; f0 = f0 + w; + f2 = ms21(ch01); w = ms31(ch01); f3 = f2 - w; f2 = f2 + w; + + x[BLKSIZE_s / 2 + 0] = f0 + f2; + x[BLKSIZE_s / 2 + 2] = f0 - f2; + x[BLKSIZE_s / 2 + 1] = f1 + f3; + x[BLKSIZE_s / 2 + 3] = f1 - f3; + } while (--j >= 0); + + gfc->fft_fht(x, BLKSIZE_s/2); + /* BLKSIZE_s/2 because of 3DNow! ASM routine */ + } +} + +void fft_long(lame_internal_flags * const gfc, + FLOAT x[BLKSIZE], int chn, const sample_t *buffer[2] ) +{ + const FLOAT* window = (const FLOAT *)&gfc->window[0]; + int i; + int jj = BLKSIZE / 8 - 1; + x += BLKSIZE / 2; + + do { + FLOAT f0,f1,f2,f3, w; + + i = rv_tbl[jj]; + f0 = ml00(ch01); w = ml10(ch01); f1 = f0 - w; f0 = f0 + w; + f2 = ml20(ch01); w = ml30(ch01); f3 = f2 - w; f2 = f2 + w; + + x -= 4; + x[0] = f0 + f2; + x[2] = f0 - f2; + x[1] = f1 + f3; + x[3] = f1 - f3; + + f0 = ml01(ch01); w = ml11(ch01); f1 = f0 - w; f0 = f0 + w; + f2 = ml21(ch01); w = ml31(ch01); f3 = f2 - w; f2 = f2 + w; + + x[BLKSIZE / 2 + 0] = f0 + f2; + x[BLKSIZE / 2 + 2] = f0 - f2; + x[BLKSIZE / 2 + 1] = f1 + f3; + x[BLKSIZE / 2 + 3] = f1 - f3; + } while (--jj >= 0); + + gfc->fft_fht(x, BLKSIZE/2); + /* BLKSIZE/2 because of 3DNow! ASM routine */ +} + + +void init_fft(lame_internal_flags * const gfc) +{ + FLOAT *window = &gfc->window[0]; + FLOAT *window_s = &gfc->window_s[0]; + int i; + +#if 0 + if (gfc->nsPsy.use) { + for (i = 0; i < BLKSIZE ; i++) + /* blackman window */ + window[i] = 0.42-0.5*cos(2*PI*i/(BLKSIZE-1))+0.08*cos(4*PI*i/(BLKSIZE-1)); + } else { + /* + * calculate HANN window coefficients + */ + for (i = 0; i < BLKSIZE ; i++) + window[i] = 0.5 * (1.0 - cos(2.0 * PI * (i + 0.5) / BLKSIZE)); + } +#endif + + // The type of window used here will make no real difference, but + // in the interest of merging nspsytune stuff - switch to blackman window + for (i = 0; i < BLKSIZE ; i++) + /* blackman window */ + window[i] = 0.42-0.5*cos(2*PI*(i+.5)/BLKSIZE)+ + 0.08*cos(4*PI*(i+.5)/BLKSIZE); + + for (i = 0; i < BLKSIZE_s/2 ; i++) + window_s[i] = 0.5 * (1.0 - cos(2.0 * PI * (i + 0.5) / BLKSIZE_s)); + +#ifdef HAVE_NASM + if (gfc->CPU_features.AMD_3DNow) { + extern void fht_3DN(FLOAT *fz, int n); + gfc->fft_fht = fht_3DN; + } else +#endif +#ifdef USE_FFTSSE + if (gfc->CPU_features.SIMD) { + extern void fht_SSE(FLOAT *fz, int n); + gfc->fft_fht = fht_SSE; + } else +#endif +#ifdef USE_FFTFPU + if (gfc->CPU_features.i387) { + extern void fht_FPU(FLOAT *fz, int n); + gfc->fft_fht = fht_FPU; + } else +#endif + gfc->fft_fht = fht; +} diff -Nru swftools-0.9.2+ds1/lib/lame/fft.h swftools-0.9.1/lib/lame/fft.h --- swftools-0.9.2+ds1/lib/lame/fft.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/fft.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Fast Fourier Transform include file + * + * Copyright (c) 2000 Mark Taylor + * + * 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 LAME_FFT_H +#define LAME_FFT_H + +#include "encoder.h" + +void fft_long(lame_internal_flags* const gfc, FLOAT x_real[BLKSIZE], + int chn, const sample_t *data[2] ); + +void fft_short(lame_internal_flags* const gfc, FLOAT x_real[3][BLKSIZE_s], + int chn, const sample_t *data[2] ); + +void init_fft(lame_internal_flags* const gfc ); + +#endif + +/* End of fft.h */ diff -Nru swftools-0.9.2+ds1/lib/lame/id3tag.c swftools-0.9.1/lib/lame/id3tag.c --- swftools-0.9.2+ds1/lib/lame/id3tag.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/id3tag.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,533 @@ +/* + * id3tag.c -- Write ID3 version 1 and 2 tags. + * + * Copyright (C) 2000 Don Melton. + * + * 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. + */ + +/* + * HISTORY: This source file is part of LAME (see http://www.mp3dev.org/mp3/) + * and was originally adapted by Conrad Sanderson + * from mp3info by Ricardo Cerqueira to write only ID3 version 1 + * tags. Don Melton COMPLETELY rewrote it to support version + * 2 tags and be more conformant to other standards while remaining flexible. + * + * NOTE: See http://id3.org/ for more information about ID3 tag formats. + */ + +/* $Id: id3tag.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#ifdef STDC_HEADERS +# include +# include +# include +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr (), *strrchr (); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#include "lame.h" +#include "id3tag.h" +#include "util.h" +#include "bitstream.h" + +#ifdef WITH_DMALLOC +#include +#endif + +static const char *const genre_names[] = +{ + /* + * NOTE: The spelling of these genre names is identical to those found in + * Winamp and mp3info. + */ + "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", + "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", + "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", + "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", + "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", + "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alt. Rock", + "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", + "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", + "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", + "Cult", "Gangsta Rap", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", + "Native American", "Cabaret", "New Wave", "Psychedelic", "Rave", + "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", + "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", + "Folk/Rock", "National Folk", "Swing", "Fast-Fusion", "Bebob", "Latin", + "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", + "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", + "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", + "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", + "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", + "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", + "Punk Rock", "Drum Solo", "A Cappella", "Euro-House", "Dance Hall", + "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie", + "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap", + "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian", + "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", + "Synthpop" +}; + +#define GENRE_NAME_COUNT \ + ((int)(sizeof genre_names / sizeof (const char *const))) + +static const int genre_alpha_map [] = { + 123, 34, 74, 73, 99, 20, 40, 26, 145, 90, 116, 41, 135, 85, 96, 138, 89, 0, + 107, 132, 65, 88, 104, 102, 97, 136, 61, 141, 32, 1, 112, 128, 57, 140, 2, + 139, 58, 3, 125, 50, 22, 4, 55, 127, 122, 120, 98, 52, 48, 54, 124, 25, 84, + 80, 115, 81, 119, 5, 30, 36, 59, 126, 38, 49, 91, 6, 129, 79, 137, 7, 35, + 100, 131, 19, 33, 46, 47, 8, 29, 146, 63, 86, 71, 45, 142, 9, 77, 82, 64, + 133, 10, 66, 39, 11, 103, 12, 75, 134, 13, 53, 62, 109, 117, 23, 108, 92, + 67, 93, 43, 121, 15, 68, 14, 16, 76, 87, 118, 17, 78, 143, 114, 110, 69, 21, + 111, 95, 105, 42, 37, 24, 56, 44, 101, 83, 94, 106, 147, 113, 18, 51, 130, + 144, 60, 70, 31, 72, 27, 28 +}; + +#define GENRE_ALPHA_COUNT ((int)(sizeof genre_alpha_map / sizeof (int))) + +void +id3tag_genre_list(void (*handler)(int, const char *, void *), void *cookie) +{ + if (handler) { + int i; + for (i = 0; i < GENRE_NAME_COUNT; ++i) { + if (i < GENRE_ALPHA_COUNT) { + int j = genre_alpha_map[i]; + handler(j, genre_names[j], cookie); + } + } + } +} + +#define GENRE_NUM_UNKNOWN 255 + +void +id3tag_init(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + memset(&gfc->tag_spec, 0, sizeof gfc->tag_spec); + gfc->tag_spec.genre = GENRE_NUM_UNKNOWN; +} + + + +void +id3tag_add_v2(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= ADD_V2_FLAG; +} + +void +id3tag_v1_only(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~(ADD_V2_FLAG | V2_ONLY_FLAG); + gfc->tag_spec.flags |= V1_ONLY_FLAG; +} + +void +id3tag_v2_only(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= V2_ONLY_FLAG; +} + +void +id3tag_space_v1(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V2_ONLY_FLAG; + gfc->tag_spec.flags |= SPACE_V1_FLAG; +} + +void +id3tag_pad_v2(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= PAD_V2_FLAG; +} + +void +id3tag_set_title(lame_global_flags *gfp, const char *title) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (title && *title) { + gfc->tag_spec.title = title; + gfc->tag_spec.flags |= CHANGED_FLAG; + } +} + +void +id3tag_set_artist(lame_global_flags *gfp, const char *artist) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (artist && *artist) { + gfc->tag_spec.artist = artist; + gfc->tag_spec.flags |= CHANGED_FLAG; + } +} + +void +id3tag_set_album(lame_global_flags *gfp, const char *album) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (album && *album) { + gfc->tag_spec.album = album; + gfc->tag_spec.flags |= CHANGED_FLAG; + } +} + +void +id3tag_set_year(lame_global_flags *gfp, const char *year) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (year && *year) { + int num = atoi(year); + if (num < 0) { + num = 0; + } + /* limit a year to 4 digits so it fits in a version 1 tag */ + if (num > 9999) { + num = 9999; + } + if (num) { + gfc->tag_spec.year = num; + gfc->tag_spec.flags |= CHANGED_FLAG; + } + } +} + +void +id3tag_set_comment(lame_global_flags *gfp, const char *comment) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (comment && *comment) { + gfc->tag_spec.comment = comment; + gfc->tag_spec.flags |= CHANGED_FLAG; + } +} + +void +id3tag_set_track(lame_global_flags *gfp, const char *track) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (track && *track) { + int num = atoi(track); + if (num < 0) { + num = 0; + } + /* limit a track to 255 so it fits in a version 1 tag even though CD + * audio doesn't allow more than 99 tracks */ + if (num > 255) { + num = 255; + } + if (num) { + gfc->tag_spec.track = num; + gfc->tag_spec.flags |= CHANGED_FLAG; + } + } +} + +/* would use real "strcasecmp" but it isn't portable */ +static int +local_strcasecmp(const char *s1, const char *s2) +{ + unsigned char c1; + unsigned char c2; + do { + c1 = tolower(*s1); + c2 = tolower(*s2); + if (!c1) { + break; + } + ++s1; + ++s2; + } while (c1 == c2); + return c1 - c2; +} + +int +id3tag_set_genre(lame_global_flags *gfp, const char *genre) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (genre && *genre) { + char *str; + int num = strtol(genre, &str, 10); + /* is the input a string or a valid number? */ + if (*str) { + int i; + for (i = 0; i < GENRE_NAME_COUNT; ++i) { + if (!local_strcasecmp(genre, genre_names[i])) { + num = i; + break; + } + } + if (i == GENRE_NAME_COUNT) { + return -1; + } + } else if ((num < 0) || (num >= GENRE_NAME_COUNT)) { + return -1; + } + gfc->tag_spec.genre = num; + gfc->tag_spec.flags |= CHANGED_FLAG; + } + return 0; +} + +static unsigned char * +set_4_byte_value(unsigned char *bytes, unsigned long value) +{ + int index; + for (index = 3; index >= 0; --index) { + bytes[index] = value & 0xfful; + value >>= 8; + } + return bytes + 4; +} + +#define FRAME_ID(a, b, c, d) \ + ( ((unsigned long)(a) << 24) \ + | ((unsigned long)(b) << 16) \ + | ((unsigned long)(c) << 8) \ + | ((unsigned long)(d) << 0) ) +#define TITLE_FRAME_ID FRAME_ID('T', 'I', 'T', '2') +#define ARTIST_FRAME_ID FRAME_ID('T', 'P', 'E', '1') +#define ALBUM_FRAME_ID FRAME_ID('T', 'A', 'L', 'B') +#define YEAR_FRAME_ID FRAME_ID('T', 'Y', 'E', 'R') +#define COMMENT_FRAME_ID FRAME_ID('C', 'O', 'M', 'M') +#define TRACK_FRAME_ID FRAME_ID('T', 'R', 'C', 'K') +#define GENRE_FRAME_ID FRAME_ID('T', 'C', 'O', 'N') + +static unsigned char * +set_frame(unsigned char *frame, unsigned long id, const char *text, + size_t length) +{ + if (length) { + frame = set_4_byte_value(frame, id); + /* Set frame size = total size - header size. Frame header and field + * bytes include 2-byte header flags, 1 encoding descriptor byte, and + * for comment frames: 3-byte language descriptor and 1 content + * descriptor byte */ + frame = set_4_byte_value(frame, ((id == COMMENT_FRAME_ID) ? 5 : 1) + + length); + /* clear 2-byte header flags */ + *frame++ = 0; + *frame++ = 0; + /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */ + *frame++ = 0; + if (id == COMMENT_FRAME_ID) { + /* use id3lib-compatible bogus language descriptor */ + *frame++ = 'X'; + *frame++ = 'X'; + *frame++ = 'X'; + /* clear 1 byte to make content descriptor empty string */ + *frame++ = 0; + } + while (length--) { + *frame++ = *text++; + } + } + return frame; +} + +int +id3tag_write_v2(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if ((gfc->tag_spec.flags & CHANGED_FLAG) + && !(gfc->tag_spec.flags & V1_ONLY_FLAG)) { + /* calculate length of four fields which may not fit in verion 1 tag */ + size_t title_length = gfc->tag_spec.title + ? strlen(gfc->tag_spec.title) : 0; + size_t artist_length = gfc->tag_spec.artist + ? strlen(gfc->tag_spec.artist) : 0; + size_t album_length = gfc->tag_spec.album + ? strlen(gfc->tag_spec.album) : 0; + size_t comment_length = gfc->tag_spec.comment + ? strlen(gfc->tag_spec.comment) : 0; + /* write tag if explicitly requested or if fields overflow */ + if ((gfc->tag_spec.flags & (ADD_V2_FLAG | V2_ONLY_FLAG)) + || (title_length > 30) + || (artist_length > 30) || (album_length > 30) + || (comment_length > 30) + || (gfc->tag_spec.track && (comment_length > 28))) { + size_t tag_size; + char year[5]; + size_t year_length; + char track[3]; + size_t track_length; + char genre[6]; + size_t genre_length; + unsigned char *tag; + unsigned char *p; + size_t adjusted_tag_size; + unsigned int index; + /* calulate size of tag starting with 10-byte tag header */ + tag_size = 10; + if (title_length) { + /* add 10-byte frame header, 1 encoding descriptor byte ... */ + tag_size += 11 + title_length; + } + if (artist_length) { + tag_size += 11 + artist_length; + } + if (album_length) { + tag_size += 11 + album_length; + } + if (gfc->tag_spec.year) { + year_length = sprintf(year, "%d", gfc->tag_spec.year); + tag_size += 11 + year_length; + } else { + year_length = 0; + } + if (comment_length) { + /* add 10-byte frame header, 1 encoding descriptor byte, + * 3-byte language descriptor, 1 content descriptor byte ... */ + tag_size += 15 + comment_length; + } + if (gfc->tag_spec.track) { + track_length = sprintf(track, "%d", gfc->tag_spec.track); + tag_size += 11 + track_length; + } else { + track_length = 0; + } + if (gfc->tag_spec.genre != GENRE_NUM_UNKNOWN) { + genre_length = sprintf(genre, "(%d)", gfc->tag_spec.genre); + tag_size += 11 + genre_length; + } else { + genre_length = 0; + } + if (gfc->tag_spec.flags & PAD_V2_FLAG) { + /* add 128 bytes of padding */ + tag_size += 128; + } + tag = (unsigned char *)malloc(tag_size); + if (!tag) { + return -1; + } + p = tag; + /* set tag header starting with file identifier */ + *p++ = 'I'; *p++ = 'D'; *p++ = '3'; + /* set version number word */ + *p++ = 3; *p++ = 0; + /* clear flags byte */ + *p++ = 0; + /* calculate and set tag size = total size - header size */ + adjusted_tag_size = tag_size - 10; + /* encode adjusted size into four bytes where most significant + * bit is clear in each byte, for 28-bit total */ + *p++ = (adjusted_tag_size >> 21) & 0x7fu; + *p++ = (adjusted_tag_size >> 14) & 0x7fu; + *p++ = (adjusted_tag_size >> 7) & 0x7fu; + *p++ = adjusted_tag_size & 0x7fu; + + /* + * NOTE: The remainder of the tag (frames and padding, if any) + * are not "unsynchronized" to prevent false MPEG audio headers + * from appearing in the bitstream. Why? Well, most players + * and utilities know how to skip the ID3 version 2 tag by now + * even if they don't read its contents, and it's actually + * very unlikely that such a false "sync" pattern would occur + * in just the simple text frames added here. + */ + + /* set each frame in tag */ + p = set_frame(p, TITLE_FRAME_ID, gfc->tag_spec.title, title_length); + p = set_frame(p, ARTIST_FRAME_ID, gfc->tag_spec.artist, + artist_length); + p = set_frame(p, ALBUM_FRAME_ID, gfc->tag_spec.album, album_length); + p = set_frame(p, YEAR_FRAME_ID, year, year_length); + p = set_frame(p, COMMENT_FRAME_ID, gfc->tag_spec.comment, + comment_length); + p = set_frame(p, TRACK_FRAME_ID, track, track_length); + p = set_frame(p, GENRE_FRAME_ID, genre, genre_length); + /* clear any padding bytes */ + memset(p, 0, tag_size - (p - tag)); + /* write tag directly into bitstream at current position */ + for (index = 0; index < tag_size; ++index) { + add_dummy_byte(gfp, tag[index]); + } + free(tag); + return tag_size; + } + } + return 0; +} + +static unsigned char * +set_text_field(unsigned char *field, const char *text, size_t size, int pad) +{ + while (size--) { + if (text && *text) { + *field++ = *text++; + } else { + *field++ = pad; + } + } + return field; +} + +int +id3tag_write_v1(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if ((gfc->tag_spec.flags & CHANGED_FLAG) + && !(gfc->tag_spec.flags & V2_ONLY_FLAG)) { + unsigned char tag[128]; + unsigned char *p = tag; + int pad = (gfc->tag_spec.flags & SPACE_V1_FLAG) ? ' ' : 0; + char year[5]; + unsigned int index; + /* set tag identifier */ + *p++ = 'T'; *p++ = 'A'; *p++ = 'G'; + /* set each field in tag */ + p = set_text_field(p, gfc->tag_spec.title, 30, pad); + p = set_text_field(p, gfc->tag_spec.artist, 30, pad); + p = set_text_field(p, gfc->tag_spec.album, 30, pad); + sprintf(year, "%d", gfc->tag_spec.year); + p = set_text_field(p, gfc->tag_spec.year ? year : NULL, 4, pad); + /* limit comment field to 28 bytes if a track is specified */ + p = set_text_field(p, gfc->tag_spec.comment, gfc->tag_spec.track + ? 28 : 30, pad); + if (gfc->tag_spec.track) { + /* clear the next byte to indicate a version 1.1 tag */ + *p++ = 0; + *p++ = gfc->tag_spec.track; + } + *p++ = gfc->tag_spec.genre; + /* write tag directly into bitstream at current position */ + for (index = 0; index < 128; ++index) { + add_dummy_byte(gfp, tag[index]); + } + return 128; + } + return 0; +} diff -Nru swftools-0.9.2+ds1/lib/lame/id3tag.h swftools-0.9.1/lib/lame/id3tag.h --- swftools-0.9.2+ds1/lib/lame/id3tag.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/id3tag.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,38 @@ + +#ifndef LAME_ID3_H +#define LAME_ID3_H + +#include "lame.h" + + +#define CHANGED_FLAG (1U << 0) +#define ADD_V2_FLAG (1U << 1) +#define V1_ONLY_FLAG (1U << 2) +#define V2_ONLY_FLAG (1U << 3) +#define SPACE_V1_FLAG (1U << 4) +#define PAD_V2_FLAG (1U << 5) + +struct id3tag_spec +{ + /* private data members */ + int flags; + const char *title; + const char *artist; + const char *album; + int year; + const char *comment; + int track; + int genre; +}; + + +/* write tag into stream at current position */ +extern int id3tag_write_v2(lame_global_flags *gfp); +extern int id3tag_write_v1(lame_global_flags *gfp); +/* + * NOTE: A version 2 tag will NOT be added unless one of the text fields won't + * fit in a version 1 tag (e.g. the title string is longer than 30 characters), + * or the "id3tag_add_v2" or "id3tag_v2_only" functions are used. + */ + +#endif diff -Nru swftools-0.9.2+ds1/lib/lame/l3side.h swftools-0.9.1/lib/lame/l3side.h --- swftools-0.9.2+ds1/lib/lame/l3side.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/l3side.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,100 @@ +/* + * Layer 3 side include file + * + * Copyright (c) 1999 Mark Taylor + * + * 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 LAME_L3SIDE_H +#define LAME_L3SIDE_H + +#include "encoder.h" +#include "machine.h" + +/* Layer III side information. */ + +typedef FLOAT8 D576[576]; +typedef int I576[576]; +typedef FLOAT8 D192_3[192][3]; +typedef int I192_3[192][3]; + + +typedef struct +{ + int l[1+SBMAX_l]; + int s[1+SBMAX_s]; +} scalefac_struct; + + +typedef struct { + FLOAT8 l[SBMAX_l]; + FLOAT8 s[SBMAX_s][3]; +} III_psy_xmin; + +typedef struct { + III_psy_xmin thm; + III_psy_xmin en; +} III_psy_ratio; + +typedef struct { + int part2_3_length; + int big_values; + int count1; + int global_gain; + int scalefac_compress; + int window_switching_flag; + int block_type; + int mixed_block_flag; + int table_select[3]; + int subblock_gain[3]; + int region0_count; + int region1_count; + int preflag; + int scalefac_scale; + int count1table_select; + + int part2_length; + int sfb_lmax; + int sfb_smin; + int count1bits; + /* added for LSF */ + const int *sfb_partition_table; + int slen[4]; +} gr_info; + +typedef struct { + int main_data_begin; + int private_bits; + int resvDrain_pre; + int resvDrain_post; + int scfsi[2][4]; + struct { + struct gr_info_ss { + gr_info tt; + } ch[2]; + } gr[2]; + } III_side_info_t; + +/* Layer III scale factors. */ +/* note: there are only SBPSY_l=(SBMAX_l-1) and SBPSY_s=(SBMAX_s-1) scalefactors. + * Dont know why these would be dimensioned SBMAX_l and SBMAX-s */ +typedef struct { + int l[SBMAX_l]; /* [cb] */ + int s[SBMAX_s][3]; /* [window][cb] */ +} III_scalefac_t; /* [gr][ch] */ + +#endif diff -Nru swftools-0.9.2+ds1/lib/lame/lame-analysis.h swftools-0.9.1/lib/lame/lame-analysis.h --- swftools-0.9.2+ds1/lib/lame/lame-analysis.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/lame-analysis.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * GTK plotting routines source file + * + * Copyright (c) 1999 Mark Taylor + * + * 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 LAME_GTKANAL_H +#define LAME_GTKANAL_H + +#include "encoder.h" + +#define READ_AHEAD 10 /* number of frames to read ahead */ +#define MAXMPGLAG READ_AHEAD /* if the mpg123 lag becomes bigger than this we have to stop */ +#define NUMBACK 6 /* number of frames we can back up */ +#define NUMPINFO (NUMBACK+READ_AHEAD+1) + + + +typedef struct { + int frameNum; /* current frame number */ + int frameNum123; + int num_samples; /* number of pcm samples read for this frame */ + double frametime; /* starting time of frame, in seconds */ + double pcmdata[2][1600]; + double pcmdata2[2][1152+1152-DECDELAY]; + double xr[2][2][576]; + double mpg123xr[2][2][576]; + double ms_ratio[2]; + double ms_ener_ratio[2]; + + /* L,R, M and S values */ + double energy[2][4][BLKSIZE]; + double pe[2][4]; + double thr[2][4][SBMAX_l]; + double en[2][4][SBMAX_l]; + double thr_s[2][4][3*SBMAX_s]; + double en_s[2][4][3*SBMAX_s]; + double ers[2][4]; + + double sfb[2][2][SBMAX_l]; + double sfb_s[2][2][3*SBMAX_s]; + double LAMEsfb[2][2][SBMAX_l]; + double LAMEsfb_s[2][2][3*SBMAX_s]; + + int LAMEqss[2][2]; + int qss[2][2]; + int big_values[2][2]; + int sub_gain[2][2][3]; + + double xfsf[2][2][SBMAX_l]; + double xfsf_s[2][2][3*SBMAX_s]; + + int over[2][2]; + double tot_noise[2][2]; + double max_noise[2][2]; + double over_noise[2][2]; + int blocktype[2][2]; + int scalefac_scale[2][2]; + int preflag[2][2]; + int mpg123blocktype[2][2]; + int mixed[2][2]; + int mainbits[2][2]; + int sfbits[2][2]; + int LAMEmainbits[2][2]; + int LAMEsfbits[2][2]; + int framesize,stereo,js,ms_stereo,i_stereo,emph,bitrate,sampfreq,maindata; + int crc,padding; + int scfsi[2],mean_bits,resvsize; + int totbits; +} plotting_data; + + +extern plotting_data *pinfo; + +#endif diff -Nru swftools-0.9.2+ds1/lib/lame/lame.c swftools-0.9.1/lib/lame/lame.c --- swftools-0.9.2+ds1/lib/lame/lame.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/lame.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,2240 @@ +/* -*- mode: C; mode: fold -*- */ +/* + * LAME MP3 encoding engine + * + * Copyright (c) 1999 Mark Taylor + * + * 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. + */ + +/* $Id: lame.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + + +#include +#include "lame-analysis.h" +#include "lame.h" +#include "util.h" +#include "bitstream.h" +#include "version.h" +#include "tables.h" +#include "quantize_pvt.h" +#include "VbrTag.h" + +#if defined(__FreeBSD__) && !defined(__alpha__) +#include +#endif +#ifdef __riscos__ +#include "asmstuff.h" +#endif + +#ifdef WITH_DMALLOC +#include +#endif + + +static void +lame_init_params_ppflt_lowpass(FLOAT8 amp_lowpass[32], FLOAT lowpass1, + FLOAT lowpass2, int *lowpass_band, + int *minband, int *maxband) +{ + int band; + FLOAT8 freq; + + for (band = 0; band <= 31; band++) { + freq = band / 31.0; + amp_lowpass[band] = 1; + /* this band and above will be zeroed: */ + if (freq >= lowpass2) { + *lowpass_band = Min(*lowpass_band, band); + amp_lowpass[band] = 0; + } + if (lowpass1 < freq && freq < lowpass2) { + *minband = Min(*minband, band); + *maxband = Max(*maxband, band); + amp_lowpass[band] = cos((PI / 2) * + (lowpass1 - freq) / (lowpass2 - lowpass1)); + } + /* + * DEBUGF("lowpass band=%i amp=%f \n", + * band, gfc->amp_lowpass[band]); + */ + } +} + +/* lame_init_params_ppflt */ + +/*}}}*/ +/* static void lame_init_params_ppflt (lame_internal_flags *gfc) *//*{{{ */ + +static void +lame_init_params_ppflt(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + /***************************************************************/ + /* compute info needed for polyphase filter (filter type==0, default) */ + /***************************************************************/ + + int band, maxband, minband; + FLOAT8 freq; + + if (gfc->lowpass1 > 0) { + minband = 999; + maxband = -1; + lame_init_params_ppflt_lowpass(gfc->amp_lowpass, + gfc->lowpass1, gfc->lowpass2, + &gfc->lowpass_band, &minband, &maxband); + /* compute the *actual* transition band implemented by + * the polyphase filter */ + if (minband == 999) { + gfc->lowpass1 = (gfc->lowpass_band - .75) / 31.0; + } + else { + gfc->lowpass1 = (minband - .75) / 31.0; + } + gfc->lowpass2 = gfc->lowpass_band / 31.0; + + gfc->lowpass_start_band = minband; + gfc->lowpass_end_band = maxband; + + /* as the lowpass may have changed above + * calculate the amplification here again + */ + for (band = minband; band <= maxband; band++) { + freq = band / 31.0; + gfc->amp_lowpass[band] = + cos((PI / 2) * (gfc->lowpass1 - freq) / + (gfc->lowpass2 - gfc->lowpass1)); + } + } + else { + gfc->lowpass_start_band = 0; + gfc->lowpass_end_band = -1; /* do not to run into for-loops */ + } + + /* make sure highpass filter is within 90% of what the effective + * highpass frequency will be */ + if (gfc->highpass2 > 0) { + if (gfc->highpass2 < .9 * (.75 / 31.0)) { + gfc->highpass1 = 0; + gfc->highpass2 = 0; + MSGF(gfc, "Warning: highpass filter disabled. " + "highpass frequency too small\n"); + } + } + + if (gfc->highpass2 > 0) { + minband = 999; + maxband = -1; + for (band = 0; band <= 31; band++) { + freq = band / 31.0; + gfc->amp_highpass[band] = 1; + /* this band and below will be zereod */ + if (freq <= gfc->highpass1) { + gfc->highpass_band = Max(gfc->highpass_band, band); + gfc->amp_highpass[band] = 0; + } + if (gfc->highpass1 < freq && freq < gfc->highpass2) { + minband = Min(minband, band); + maxband = Max(maxband, band); + gfc->amp_highpass[band] = + cos((PI / 2) * + (gfc->highpass2 - freq) / + (gfc->highpass2 - gfc->highpass1)); + } + /* + DEBUGF("highpass band=%i amp=%f \n", + band, gfc->amp_highpass[band]); + */ + } + /* compute the *actual* transition band implemented by + * the polyphase filter */ + gfc->highpass1 = gfc->highpass_band / 31.0; + if (maxband == -1) { + gfc->highpass2 = (gfc->highpass_band + .75) / 31.0; + } + else { + gfc->highpass2 = (maxband + .75) / 31.0; + } + + gfc->highpass_start_band = minband; + gfc->highpass_end_band = maxband; + + /* as the highpass may have changed above + * calculate the amplification here again + */ + for (band = minband; band <= maxband; band++) { + freq = band / 31.0; + gfc->amp_highpass[band] = + cos((PI / 2) * (gfc->highpass2 - freq) / + (gfc->highpass2 - gfc->highpass1)); + } + } + else { + gfc->highpass_start_band = 0; + gfc->highpass_end_band = -1; /* do not to run into for-loops */ + } + /* + DEBUGF("lowpass band with amp=0: %i \n",gfc->lowpass_band); + DEBUGF("highpass band with amp=0: %i \n",gfc->highpass_band); + DEBUGF("lowpass band start: %i \n",gfc->lowpass_start_band); + DEBUGF("lowpass band end: %i \n",gfc->lowpass_end_band); + DEBUGF("highpass band start: %i \n",gfc->highpass_start_band); + DEBUGF("highpass band end: %i \n",gfc->highpass_end_band); + */ +} + +/*}}}*/ + + +static void +optimum_bandwidth(double *const lowerlimit, + double *const upperlimit, + const unsigned bitrate, + const int samplefreq, + const double channels) +{ +/* + * Input: + * bitrate total bitrate in bps + * samplefreq output sampling frequency in Hz + * channels 1 for mono, 2+epsilon for MS stereo, 3 for LR stereo + * epsilon is the percentage of LR frames for typical audio + * (I use 'Fade to Gray' by Metallica) + * + * Output: + * lowerlimit: best lowpass frequency limit for input filter in Hz + * upperlimit: best highpass frequency limit for input filter in Hz + */ + double f_low; + double f_high; + double br; + + assert(bitrate >= 8000 && bitrate <= 320000); + assert(samplefreq >= 8000 && samplefreq <= 48000); + assert(channels == 1 || (channels >= 2 && channels <= 3)); + + if (samplefreq >= 32000) + br = + bitrate - (channels == + 1 ? (17 + 4) * 8 : (32 + 4) * 8) * samplefreq / 1152; + else + br = + bitrate - (channels == + 1 ? (9 + 4) * 8 : (17 + 4) * 8) * samplefreq / 576; + + if (channels >= 2.) + br /= 1.75 + 0.25 * (channels - 2.); // MS needs 1.75x mono, LR needs 2.00x mono (experimental data of a lot of albums) + + br *= 0.5; // the sine and cosine term must share the bitrate + +/* + * So, now we have the bitrate for every spectral line. + * Let's look at the current settings: + * + * Bitrate limit bits/line + * 8 kbps 0.34 kHz 4.76 + * 16 kbps 1.9 kHz 2.06 + * 24 kbps 2.8 kHz 2.21 + * 32 kbps 3.85 kHz 2.14 + * 40 kbps 5.1 kHz 2.06 + * 48 kbps 5.6 kHz 2.21 + * 56 kbps 7.0 kHz 2.10 + * 64 kbps 7.7 kHz 2.14 + * 80 kbps 10.1 kHz 2.08 + * 96 kbps 11.2 kHz 2.24 + * 112 kbps 14.0 kHz 2.12 + * 128 kbps 15.4 kHz 2.17 + * 160 kbps 18.2 kHz 2.05 + * 192 kbps 21.1 kHz 2.14 + * 224 kbps 22.0 kHz 2.41 + * 256 kbps 22.0 kHz 2.78 + * + * What can we see? + * Value for 8 kbps is nonsense (although 8 kbps and stereo is nonsense) + * Values are between 2.05 and 2.24 for 16...192 kbps + * Some bitrate lack the following bitrates have: 16, 40, 80, 160 kbps + * A lot of bits per spectral line have: 24, 48, 96 kbps + * + * What I propose? + * A slightly with the bitrate increasing bits/line function. It is + * better to decrease NMR for low bitrates to get a little bit more + * bandwidth. So we have a better trade off between twickling and + * muffled sound. + */ + + f_low = br / log10(br * 4.425e-3); // Tests with 8, 16, 32, 64, 112 and 160 kbps + +/* +GB 04/04/01 +sfb21 is a huge bitrate consumer in vbr with the new ath. +Need to reduce the lowpass to more reasonable values. This extra lowpass +won't reduce quality over 3.87 as the previous ath was doing this lowpass +*/ +/*GB 22/05/01 +I'm also extending this to CBR as tests showed that a +limited bandwidth is increasing quality +*/ + if (f_low>18400) + f_low = 18400+(f_low-18400)/4; + +/* + * What we get now? + * + * Bitrate limit bits/line difference + * 8 kbps (8) 1.89 kHz 0.86 +1.6 kHz + * 16 kbps (8) 3.16 kHz 1.24 +1.2 kHz + * 32 kbps(16) 5.08 kHz 1.54 +1.2 kHz + * 56 kbps(22) 7.88 kHz 1.80 +0.9 kHz + * 64 kbps(22) 8.83 kHz 1.86 +1.1 kHz + * 112 kbps(32) 14.02 kHz 2.12 0.0 kHz + * 112 kbps(44) 13.70 kHz 2.11 -0.3 kHz + * 128 kbps 15.40 kHz 2.17 0.0 kHz + * 160 kbps 16.80 kHz 2.22 -1.4 kHz + * 192 kbps 19.66 kHz 2.30 -1.4 kHz + * 256 kbps 22.05 kHz 2.78 0.0 kHz + */ + + +/* + * Now we try to choose a good high pass filtering frequency. + * This value is currently not used. + * For fu < 16 kHz: sqrt(fu*fl) = 560 Hz + * For fu = 18 kHz: no high pass filtering + * This gives: + * + * 2 kHz => 160 Hz + * 3 kHz => 107 Hz + * 4 kHz => 80 Hz + * 8 kHz => 40 Hz + * 16 kHz => 20 Hz + * 17 kHz => 10 Hz + * 18 kHz => 0 Hz + * + * These are ad hoc values and these can be optimized if a high pass is available. + */ + if (f_low <= 16000) + f_high = 16000. * 20. / f_low; + else if (f_low <= 18000) + f_high = 180. - 0.01 * f_low; + else + f_high = 0.; + + /* + * When we sometimes have a good highpass filter, we can add the highpass + * frequency to the lowpass frequency + */ + + if (lowerlimit != NULL) + *lowerlimit = (f_low>0.5 * samplefreq ? 0.5 * samplefreq : f_low); // roel - fixes mono "-b320 -a" + if (upperlimit != NULL) + *upperlimit = f_high; +/* + * Now the weak points: + * + * - the formula f_low=br/log10(br*4.425e-3) is an ad hoc formula + * (but has a physical background and is easy to tune) + * - the switch to the ATH based bandwidth selecting is the ad hoc + * value of 128 kbps + */ +} + +static int +optimum_samplefreq(int lowpassfreq, int input_samplefreq) +{ +/* + * Rules: + * + * - output sample frequency should NOT be decreased by more than 3% if lowpass allows this + * - if possible, sfb21 should NOT be used + * + * Problem: Switches to 32 kHz at 112 kbps + */ + if (input_samplefreq <= 8000 * 1.03 || lowpassfreq <= 3622) + return 8000; + if (input_samplefreq <= 11025 * 1.03 || lowpassfreq <= 4991) + return 11025; + if (input_samplefreq <= 12000 * 1.03 || lowpassfreq <= 5620) + return 12000; + if (input_samplefreq <= 16000 * 1.03 || lowpassfreq <= 7244) + return 16000; + if (input_samplefreq <= 22050 * 1.03 || lowpassfreq <= 9982) + return 22050; + if (input_samplefreq <= 24000 * 1.03 || lowpassfreq <= 11240) + return 24000; + if (input_samplefreq <= 32000 * 1.03 || lowpassfreq <= 15264) + return 32000; + if (input_samplefreq <= 44100 * 1.03) + return 44100; + return 48000; +} + + +/* set internal feature flags. USER should not access these since + * some combinations will produce strange results */ +void +lame_init_qval(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + switch (gfp->quality) { + case 9: /* no psymodel, no noise shaping */ + gfc->filter_type = 0; + gfc->psymodel = 0; + gfc->quantization = 0; + gfc->noise_shaping = 0; + gfc->noise_shaping_amp = 0; + gfc->noise_shaping_stop = 0; + gfc->use_best_huffman = 0; + break; + + case 8: + gfp->quality = 7; + case 7: /* use psymodel (for short block and m/s switching), but no noise shapping */ + gfc->filter_type = 0; + gfc->psymodel = 1; + gfc->quantization = 0; + gfc->noise_shaping = 0; + gfc->noise_shaping_amp = 0; + gfc->noise_shaping_stop = 0; + gfc->use_best_huffman = 0; + break; + + case 6: + gfp->quality = 5; + case 5: /* the default */ + gfc->filter_type = 0; + gfc->psymodel = 1; + gfc->quantization = 0; + gfc->noise_shaping = 1; + /**/ gfc->noise_shaping_amp = 0; + gfc->noise_shaping_stop = 0; + gfc->use_best_huffman = 0; + break; + + case 4: + gfp->quality = 3; + case 3: + gfc->filter_type = 0; + gfc->psymodel = 1; + gfc->quantization = 1; + gfc->noise_shaping = 1; + gfc->noise_shaping_amp = 0; + gfc->noise_shaping_stop = 0; + gfc->use_best_huffman = 1; + break; + + case 2: + gfc->filter_type = 0; + gfc->psymodel = 1; + gfc->quantization = 1; + gfc->noise_shaping = 1; + gfc->noise_shaping_amp = 1; + gfc->noise_shaping_stop = 1; + gfc->use_best_huffman = 1; + break; + + case 1: + gfc->filter_type = 0; + gfc->psymodel = 1; + gfc->quantization = 1; + gfc->noise_shaping = 1; + gfc->noise_shaping_amp = 2; + gfc->noise_shaping_stop = 1; + gfc->use_best_huffman = 1; + break; + + case 0: /* 0..1 quality */ + gfc->filter_type = 0; /* 1 not yet coded */ + gfc->psymodel = 1; + gfc->quantization = 1; + gfc->noise_shaping = 1; /* 2=usually lowers quality */ + gfc->noise_shaping_amp = 3; + gfc->noise_shaping_stop = 1; + gfc->use_best_huffman = 1; /* 2 not yet coded */ + } + + /* modifications to the above rules: */ + + /* -Z option toggles scalefactor_scale: */ + if ( (gfp->experimentalZ & 1) > 0) { + gfc->noise_shaping = 2; + } +} + + + + + + + +/* int lame_init_params (lame_global_flags *gfp) *//*{{{ */ + +/******************************************************************** + * initialize internal params based on data in gf + * (globalflags struct filled in by calling program) + * + * OUTLINE: + * + * We first have some complex code to determine bitrate, + * output samplerate and mode. It is complicated by the fact + * that we allow the user to set some or all of these parameters, + * and need to determine best possible values for the rest of them: + * + * 1. set some CPU related flags + * 2. check if we are mono->mono, stereo->mono or stereo->stereo + * 3. compute bitrate and output samplerate: + * user may have set compression ratio + * user may have set a bitrate + * user may have set a output samplerate + * 4. set some options which depend on output samplerate + * 5. compute the actual compression ratio + * 6. set mode based on compression ratio + * + * The remaining code is much simpler - it just sets options + * based on the mode & compression ratio: + * + * set allow_diff_short based on mode + * select lowpass filter based on compression ratio & mode + * set the bitrate index, and min/max bitrates for VBR modes + * disable VBR tag if it is not appropriate + * initialize the bitstream + * initialize scalefac_band data + * set sideinfo_len (based on channels, CRC, out_samplerate) + * write an id3v2 tag into the bitstream + * write VBR tag into the bitstream + * set mpeg1/2 flag + * estimate the number of frames (based on a lot of data) + * + * now we set more flags: + * nspsytune: + * see code + * VBR modes + * see code + * CBR/ABR + * see code + * + * Finally, we set the algorithm flags based on the gfp->quality value + * lame_init_qval(gfp); + * + ********************************************************************/ +int +lame_init_params(lame_global_flags * const gfp) +{ + + int i; + int j; + lame_internal_flags *gfc = gfp->internal_flags; + + gfc->gfp = gfp; + + gfc->Class_ID = 0; + + /* report functions */ + gfc->report.msgf = gfp->report.msgf; + gfc->report.debugf = gfp->report.debugf; + gfc->report.errorf = gfp->report.errorf; + + gfc->CPU_features.i387 = has_i387(); + gfc->CPU_features.AMD_3DNow = has_3DNow(); + gfc->CPU_features.MMX = has_MMX(); + gfc->CPU_features.SIMD = has_SIMD(); + gfc->CPU_features.SIMD2 = has_SIMD2(); + + + if (NULL == gfc->ATH) + gfc->ATH = calloc(1, sizeof(ATH_t)); + + if (NULL == gfc->ATH) + return -2; // maybe error codes should be enumerated in lame.h ?? + + if (NULL == gfc->VBR) + gfc->VBR = calloc(1, sizeof(VBR_t)); + if (NULL == gfc->VBR) + return -2; + + if (NULL == gfc->PSY) + gfc->PSY = calloc(1, sizeof(PSY_t)); + if (NULL == gfc->PSY) + return -2; + +#ifdef KLEMM_44 + /* Select the fastest functions for this CPU */ + init_scalar_functions(gfc); +#endif + + gfc->channels_in = gfp->num_channels; + if (gfc->channels_in == 1) + gfp->mode = MONO; + gfc->channels_out = (gfp->mode == MONO) ? 1 : 2; + gfc->mode_ext = MPG_MD_LR_LR; + if (gfp->mode == MONO) + gfp->force_ms = 0; // don't allow forced mid/side stereo for mono output + + + if (gfp->VBR != vbr_off) { + gfp->free_format = 0; /* VBR can't be mixed with free format */ + } + + if (gfp->VBR == vbr_off && gfp->brate == 0) { + /* no bitrate or compression ratio specified, use a compression ratio of 11.025 */ + if (gfp->compression_ratio == 0) + gfp->compression_ratio = 11.025; /* rate to compress a CD down to exactly 128000 bps */ + } + + + if (gfp->VBR == vbr_off && gfp->brate == 0) { + /* no bitrate or compression ratio specified, use 11.025 */ + if (gfp->compression_ratio == 0) + gfp->compression_ratio = 11.025; /* rate to compress a CD down to exactly 128000 bps */ + } + + /* find bitrate if user specify a compression ratio */ + if (gfp->VBR == vbr_off && gfp->compression_ratio > 0) { + + if (gfp->out_samplerate == 0) + gfp->out_samplerate = map2MP3Frequency( (int)( 0.97 * gfp->in_samplerate ) ); /* round up with a margin of 3% */ + + /* choose a bitrate for the output samplerate which achieves + * specified compression ratio + */ + gfp->brate = + gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 * + gfp-> + compression_ratio); + + /* we need the version for the bitrate table look up */ + gfc->samplerate_index = SmpFrqIndex(gfp->out_samplerate, &gfp->version); + + if (!gfp->free_format) /* for non Free Format find the nearest allowed bitrate */ + gfp->brate = + FindNearestBitrate(gfp->brate, gfp->version, + gfp->out_samplerate); + } + + if (gfp->VBR != vbr_off && gfp->brate >= 320) + gfp->VBR = vbr_off; /* at 160 kbps (MPEG-2/2.5)/ 320 kbps (MPEG-1) only Free format or CBR are possible, no VBR */ + + + if (gfp->out_samplerate == 0) { /* if output sample frequency is not given, find an useful value */ + gfp->out_samplerate = map2MP3Frequency( (int)( 0.97 * gfp->in_samplerate ) ); + + + /* check if user specified bitrate requires downsampling, if compression */ + /* ratio is > 13, choose a new samplerate to get the ratio down to about 10 */ + + if (gfp->VBR == vbr_off && gfp->brate > 0) { + gfp->compression_ratio = + gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 * + gfp->brate); + if (gfp->compression_ratio > 13.) + gfp->out_samplerate = + map2MP3Frequency( (int)( (10. * 1.e3 * gfp->brate) / + (16 * gfc->channels_out))); + } + if (gfp->VBR == vbr_abr) { + gfp->compression_ratio = + gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 * + gfp-> + VBR_mean_bitrate_kbps); + if (gfp->compression_ratio > 13.) + gfp->out_samplerate = + map2MP3Frequency((int)((10. * 1.e3 * gfp->VBR_mean_bitrate_kbps) / + (16 * gfc->channels_out))); + } + } + + if (gfp->ogg) { + gfp->framesize = 1024; + gfp->encoder_delay = ENCDELAY; + gfc->coding = coding_Ogg_Vorbis; + } + else { + gfc->mode_gr = gfp->out_samplerate <= 24000 ? 1 : 2; // Number of granules per frame + gfp->framesize = 576 * gfc->mode_gr; + gfp->encoder_delay = ENCDELAY; + gfc->coding = coding_MPEG_Layer_3; + } + + gfc->frame_size = gfp->framesize; + + gfc->resample_ratio = (double) gfp->in_samplerate / gfp->out_samplerate; + + /* + * sample freq bitrate compression ratio + * [kHz] [kbps/channel] for 16 bit input + * 44.1 56 12.6 + * 44.1 64 11.025 + * 44.1 80 8.82 + * 22.05 24 14.7 + * 22.05 32 11.025 + * 22.05 40 8.82 + * 16 16 16.0 + * 16 24 10.667 + * + */ + /* + * For VBR, take a guess at the compression_ratio. + * For example: + * + * VBR_q compression like + * - 4.4 320 kbps/44 kHz + * 0...1 5.5 256 kbps/44 kHz + * 2 7.3 192 kbps/44 kHz + * 4 8.8 160 kbps/44 kHz + * 6 11 128 kbps/44 kHz + * 9 14.7 96 kbps + * + * for lower bitrates, downsample with --resample + */ + + switch (gfp->VBR) { + case vbr_mt: + case vbr_rh: + case vbr_mtrh: + { + FLOAT8 cmp[] = { 5.7, 6.5, 7.3, 8.2, 9.1, 10, 11, 12, 13, 14 }; + gfp->compression_ratio = cmp[gfp->VBR_q]; + } + break; + case vbr_abr: + gfp->compression_ratio = + gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 * + gfp-> + VBR_mean_bitrate_kbps); + break; + default: + gfp->compression_ratio = + gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 * gfp->brate); + break; + } + + + /* mode = -1 (not set by user) or + * mode = MONO (because of only 1 input channel). + * If mode has been set, then select between STEREO or J-STEREO + * At higher quality (lower compression) use STEREO instead of J-STEREO. + * (unless the user explicitly specified a mode) + * + * The threshold to switch to STEREO is: + * 48 kHz: 171 kbps (used at 192+) + * 44.1 kHz: 160 kbps (used at 160+) + * 32 kHz: 119 kbps (used at 128+) + * + * Note, that for 32 kHz/128 kbps J-STEREO FM recordings sound much + * better than STEREO, so I'm not so very happy with that. + * fs < 32 kHz I have not tested. + */ + if (gfp->mode == NOT_SET) { + if (gfp->compression_ratio < 8) + gfp->mode = STEREO; + else + gfp->mode = JOINT_STEREO; + } + + /* KLEMM's jstereo with ms threshold adjusted via compression ratio */ + if (gfp->mode_automs) { + if (gfp->mode != MONO && gfp->compression_ratio < 6.6) + gfp->mode = STEREO; + } + + + + + + + /****************************************************************/ + /* if a filter has not been enabled, see if we should add one: */ + /****************************************************************/ + if (gfp->lowpassfreq == 0) { + double lowpass; + double highpass; + double channels; + + switch (gfp->mode) { + case MONO: + channels = 1.; + break; + case JOINT_STEREO: + channels = 2. + 0.00; + break; + case DUAL_CHANNEL: + case STEREO: + channels = 3.; + break; + default: + channels = 1.; // just to make data flow analysis happy :-) + assert(0); + break; + } + + optimum_bandwidth(&lowpass, + &highpass, + gfp->out_samplerate * 16 * gfc->channels_out / + gfp->compression_ratio, gfp->out_samplerate, channels); + +/* roel - is this still needed? + if (lowpass > 0.5 * gfp->out_samplerate) { + //MSGF(gfc,"Lowpass @ %7.1f Hz\n", lowpass); + gfc->lowpass1 = gfc->lowpass2 = + lowpass / (0.5 * gfp->out_samplerate); + } +*/ + gfp->lowpassfreq = lowpass; + +#if 0 + if (gfp->out_samplerate != + optimum_samplefreq(lowpass, gfp->in_samplerate)) { + MSGF(gfc, + "I would suggest to use %u Hz instead of %u Hz sample frequency\n", + optimum_samplefreq(lowpass, gfp->in_samplerate), + gfp->out_samplerate); + } + fflush(stderr); +#endif + } + + /* apply user driven high pass filter */ + if (gfp->highpassfreq > 0) { + gfc->highpass1 = 2. * gfp->highpassfreq / gfp->out_samplerate; /* will always be >=0 */ + if (gfp->highpasswidth >= 0) + gfc->highpass2 = + 2. * (gfp->highpassfreq + + gfp->highpasswidth) / gfp->out_samplerate; + else /* 0% above on default */ + gfc->highpass2 = + (1 + 0.00) * 2. * gfp->highpassfreq / gfp->out_samplerate; + } + + /* apply user driven low pass filter */ + if (gfp->lowpassfreq > 0) { + gfc->lowpass2 = 2. * gfp->lowpassfreq / gfp->out_samplerate; /* will always be >=0 */ + if (gfp->lowpasswidth >= 0) { + gfc->lowpass1 = + 2. * (gfp->lowpassfreq - + gfp->lowpasswidth) / gfp->out_samplerate; + if (gfc->lowpass1 < 0) /* has to be >= 0 */ + gfc->lowpass1 = 0; + } + else { /* 0% below on default */ + gfc->lowpass1 = + (1 - 0.00) * 2. * gfp->lowpassfreq / gfp->out_samplerate; + } + } + + + + + /**********************************************************************/ + /* compute info needed for polyphase filter (filter type==0, default) */ + /**********************************************************************/ + lame_init_params_ppflt(gfp); + + + /*******************************************************/ + /* compute info needed for FIR filter (filter_type==1) */ + /*******************************************************/ + /* not yet coded */ + + + + /******************************************************* + * samplerate and bitrate index + *******************************************************/ + gfc->samplerate_index = SmpFrqIndex(gfp->out_samplerate, &gfp->version); + if (gfc->samplerate_index < 0) + return -1; + + if (gfp->VBR == vbr_off) { + if (gfp->free_format) { + gfc->bitrate_index = 0; + } + else { + gfc->bitrate_index = BitrateIndex(gfp->brate, gfp->version, + gfp->out_samplerate); + if (gfc->bitrate_index < 0) + return -1; + } + } + else { /* choose a min/max bitrate for VBR */ + /* if the user didn't specify VBR_max_bitrate: */ + gfc->VBR_min_bitrate = 1; /* default: allow 8 kbps (MPEG-2) or 32 kbps (MPEG-1) */ + gfc->VBR_max_bitrate = 14; /* default: allow 160 kbps (MPEG-2) or 320 kbps (MPEG-1) */ + + if (gfp->VBR_min_bitrate_kbps) + if ( + (gfc->VBR_min_bitrate = + BitrateIndex(gfp->VBR_min_bitrate_kbps, gfp->version, + gfp->out_samplerate)) < 0) return -1; + if (gfp->VBR_max_bitrate_kbps) + if ( + (gfc->VBR_max_bitrate = + BitrateIndex(gfp->VBR_max_bitrate_kbps, gfp->version, + gfp->out_samplerate)) < 0) return -1; + + gfp->VBR_min_bitrate_kbps = + bitrate_table[gfp->version][gfc->VBR_min_bitrate]; + gfp->VBR_max_bitrate_kbps = + bitrate_table[gfp->version][gfc->VBR_max_bitrate]; + + gfp->VBR_mean_bitrate_kbps = + Min(bitrate_table[gfp->version][gfc->VBR_max_bitrate], + gfp->VBR_mean_bitrate_kbps); + gfp->VBR_mean_bitrate_kbps = + Max(bitrate_table[gfp->version][gfc->VBR_min_bitrate], + gfp->VBR_mean_bitrate_kbps); + + + } + + /* for CBR, we will write an "info" tag. */ + // if ((gfp->VBR == vbr_off)) + // gfp->bWriteVbrTag = 0; + + if (gfp->ogg) + gfp->bWriteVbrTag = 0; +#if defined(HAVE_GTK) + if (gfp->analysis) + gfp->bWriteVbrTag = 0; +#endif + + /* some file options not allowed if output is: not specified or stdout */ + if (gfc->pinfo != NULL) + gfp->bWriteVbrTag = 0; /* disable Xing VBR tag */ + + init_bit_stream_w(gfc); + + j = + gfc->samplerate_index + (3 * gfp->version) + 6 * (gfp->out_samplerate < + 16000); + for (i = 0; i < SBMAX_l + 1; i++) + gfc->scalefac_band.l[i] = sfBandIndex[j].l[i]; + for (i = 0; i < SBMAX_s + 1; i++) + gfc->scalefac_band.s[i] = sfBandIndex[j].s[i]; + + /* determine the mean bitrate for main data */ + if (gfp->version == 1) /* MPEG 1 */ + gfc->sideinfo_len = (gfc->channels_out == 1) ? 4 + 17 : 4 + 32; + else /* MPEG 2 */ + gfc->sideinfo_len = (gfc->channels_out == 1) ? 4 + 9 : 4 + 17; + + if (gfp->error_protection) + gfc->sideinfo_len += 2; + + lame_init_bitstream(gfp); + + + if (gfp->version == 1) /* 0 indicates use lower sample freqs algorithm */ + gfc->is_mpeg1 = 1; /* yes */ + else + gfc->is_mpeg1 = 0; /* no */ + + gfc->Class_ID = LAME_ID; + + + if (gfp->exp_nspsytune & 1) { + int i,j; + + gfc->nsPsy.use = 1; + gfc->nsPsy.safejoint = (gfp->exp_nspsytune & 2) != 0; + for (i = 0; i < 19; i++) + gfc->nsPsy.pefirbuf[i] = 700; + + if (gfp->ATHtype == -1) + gfp->ATHtype = 4; + + gfc->nsPsy.bass = gfc->nsPsy.alto = gfc->nsPsy.treble = 0; + + i = (gfp->exp_nspsytune >> 2) & 63; + if (i >= 32) + i -= 64; + gfc->nsPsy.bass = pow(10, i / 4.0 / 10.0); + i = (gfp->exp_nspsytune >> 8) & 63; + if (i >= 32) + i -= 64; + gfc->nsPsy.alto = pow(10, i / 4.0 / 10.0); + i = (gfp->exp_nspsytune >> 14) & 63; + if (i >= 32) + i -= 64; + gfc->nsPsy.treble = pow(10, i / 4.0 / 10.0); + /* to be compatible with Naoki's original code, the next 6 bits + * define only the amount of changing treble for sfb21 */ + j = (gfp->exp_nspsytune >> 20) & 63; + if (j >= 32) + j -= 64; + gfc->nsPsy.sfb21 = pow(10, (i+j) / 4.0 / 10.0); + } + + assert( gfp->VBR_q <= 9 ); + assert( gfp->VBR_q >= 0 ); + + gfc->PSY->tonalityPatch = 0; + + switch (gfp->VBR) { + + case vbr_mt: + gfp->VBR = vbr_mtrh; + + case vbr_mtrh: + + if (gfp->ATHtype < 0) gfp->ATHtype = 4; + if (gfp->quality < 0) gfp->quality = 2; + if (gfp->quality > 7) { + gfp->quality = 7; // needs psymodel + ERRORF( gfc, "VBR needs a psymodel, switching to quality level 7\n"); + } + + /* tonality + */ + if (gfp->cwlimit <= 0) gfp->cwlimit = 0.42 * gfp->out_samplerate; + gfc->PSY->tonalityPatch = 1; + + if ( gfp->experimentalX <= 4 && gfp->experimentalX >= 0 ) + { /* map experimentalX settings to internal secltions */ + static char const map[] = {2,1,0,3,6}; + gfc->VBR->quality = map[gfp->experimentalX]; + } + else /* defaulting to */ + { + gfc->VBR->quality = 2; + } + if ( gfc->VBR->quality > 5 ) { + static float const dbQ[10] = { -6,-4.75,-3.5,-2.25,-1,.25,1.5,2.75,4,5.25 }; + gfc->VBR->mask_adjust = dbQ[gfp->VBR_q]; + gfc->VBR->smooth = 1; // not finally + } + else { + static const float dbQ[10]={-2.,-1.0,-.66,-.33,0.,0.33,.66,1.0,1.33,1.66}; + gfc->VBR->mask_adjust = dbQ[gfp->VBR_q]; + gfc->VBR->smooth = 1; + } + if ( gfc->VBR->quality == 1 ) { + static float const dbQ[10] = { -2., -1.4, -.7, 0, .7, 1.5, 2.3, 3.1, 4., 5 }; + gfc->VBR->mask_adjust = dbQ[gfp->VBR_q]; + gfc->VBR->smooth = 0; + } + if ( gfc->VBR->quality == 0 ) { + static float const dbQ[10] = { -1., -.6, -.3, 0, 1, 2, 3, 4, 5, 6}; + gfc->VBR->mask_adjust = dbQ[gfp->VBR_q]; + gfc->VBR->smooth = 0; + gfc->PSY->tonalityPatch = 0; + } + + gfc->VBR->bitpressure = 1; + + if (gfp->experimentalY) + gfc->sfb21_extra = 0; + else + gfc->sfb21_extra = (gfp->out_samplerate > 44000); + + if ( gfp->athaa_type < 0 ) + gfc->ATH->use_adjust = 3; + else + gfc->ATH->use_adjust = gfp->athaa_type; + + break; + + + case vbr_rh: + + if (gfp->VBR == vbr_rh) /* because of above fall thru */ + { static const FLOAT8 dbQ[10]={-2.,-1.0,-.66,-.33,0.,0.33,.66,1.0,1.33,1.66}; + static const FLOAT8 dbQns[10]={- 4,- 3,-2,-1,0,0.7,1.4,2.1,2.8,3.5}; + /*static const FLOAT8 atQns[10]={-16,-12,-8,-4,0, 1, 2, 3, 4, 5};*/ + if ( gfc->nsPsy.use ) + gfc->VBR->mask_adjust = dbQns[gfp->VBR_q]; + else { + gfc->PSY->tonalityPatch = 1; + gfc->VBR->mask_adjust = dbQ[gfp->VBR_q]; + } + } + gfc->VBR->bitpressure = 1; + + /* use Gabriel's adaptative ATH shape for VBR by default + */ + if (gfp->ATHtype == -1) + gfp->ATHtype = 4; + + /* automatic ATH adjustment on, VBR modes need it + */ + if ( gfp->athaa_type < 0 ) + gfc->ATH->use_adjust = 3; + else + gfc->ATH->use_adjust = gfp->athaa_type; + + /* sfb21 extra only with MPEG-1 at higher sampling rates + */ + if ( gfp->experimentalY ) + gfc->sfb21_extra = 0; + else + gfc->sfb21_extra = (gfp->out_samplerate > 44000); + + /* VBR needs at least the output of GPSYCHO, + * so we have to garantee that by setting a minimum + * quality level, actually level 5 does it. + * the -v and -V x settings switch the quality to level 2 + * you would have to add a -q 5 to reduce the quality + * down to level 5 + */ + if (gfp->quality > 5) + gfp->quality = 5; + + + /* default quality setting is 2 + */ + if (gfp->quality < 0) + gfp->quality = 2; + + break; + + default: + + if (gfp->ATHtype == -1) + gfp->ATHtype = 2; + + /* automatic ATH adjustment off by default + * not so important for CBR code? + */ + if ( gfp->athaa_type < 0 ) + gfc->ATH->use_adjust = 0; + else + gfc->ATH->use_adjust = gfp->athaa_type; + + + /* no sfb21 extra with CBR code + */ + gfc->sfb21_extra = 0; + + /* default quality setting for CBR/ABR is 5 + */ + if (gfp->quality < 0) + gfp->quality = 5; + + break; + } + /* just another daily changing developer switch */ + if ( gfp->tune ) gfc->VBR->mask_adjust = gfp->tune_value_a; + + /* initialize internal qval settings */ + lame_init_qval(gfp); + +#ifdef KLEMM_44 + gfc->mfbuf[0] = (sample_t *) calloc(sizeof(sample_t), MFSIZE); + gfc->mfbuf[1] = (sample_t *) calloc(sizeof(sample_t), MFSIZE); + gfc->sampfreq_in = unround_samplefrequency(gfp->in_samplerate); + gfc->sampfreq_out = gfp->out_samplerate; + gfc->resample_in = resample_open(gfc->sampfreq_in, + gfc->sampfreq_out, -1.0 /* Auto */, 32); +#endif + + /* initialize internal adaptive ATH settings -jd */ + gfc->athaa_sensitivity_p = pow( 10.0, gfp->athaa_sensitivity / -10.0 ); + + + gfc->PSY->cwlimit = gfp->cwlimit <= 0 ? 8871.7f : gfp->cwlimit; + + if (gfp->short_blocks == short_block_not_set) { + gfp->short_blocks = short_block_allowed; + } + if (gfp->short_blocks == short_block_allowed && gfp->mode == JOINT_STEREO) { + gfp->short_blocks = short_block_coupled; + } + + if ( gfp->athaa_loudapprox < 0 ) gfp->athaa_loudapprox = 2; + + if (gfp->useTemporal < 0 ) gfp->useTemporal = 1; // on by default + + + if ( gfp->experimentalY ) + MSGF(gfc,"\n *** WARNING *** the meaning of the experimental -Y has changed!\n" + " now it tells LAME to ignore sfb21 noise shaping (VBR)\n\n"); + + if ( gfp->preset_expopts && gfc->presetTune.use < 1 ) + MSGF(gfc,"\n*** WARNING ***\n\n" + "Specialized tunings for the preset you are using have been deactivated.\n" + "This is *NOT* recommended and will lead to a decrease in quality!\n" + "\n*** WARNING ***\n\n"); + + return 0; +} + +/*}}}*/ +/* void lame_print_config (lame_global_flags *gfp) *//*{{{ */ + +/* + * print_config + * + * Prints some selected information about the coding parameters via + * the macro command MSGF(), which is currently mapped to lame_errorf + * (reports via a error function?), which is a printf-like function + * for . + */ + +void +lame_print_config(const lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + double out_samplerate = gfp->out_samplerate; + double in_samplerate = gfp->out_samplerate * gfc->resample_ratio; + + MSGF(gfc, "LAME version %s (%s)\n", get_lame_version(), get_lame_url()); + + if (gfc->CPU_features.MMX + || gfc->CPU_features.AMD_3DNow + || gfc->CPU_features.SIMD || gfc->CPU_features.SIMD2) { + MSGF(gfc, "CPU features:"); + + if (gfc->CPU_features.i387) + MSGF(gfc, " i387"); + if (gfc->CPU_features.MMX) +#ifdef MMX_choose_table + MSGF(gfc, ", MMX (ASM used)"); +#else + MSGF(gfc, ", MMX"); +#endif + if (gfc->CPU_features.AMD_3DNow) + MSGF(gfc, ", 3DNow!"); + if (gfc->CPU_features.SIMD) + MSGF(gfc, ", SIMD"); + if (gfc->CPU_features.SIMD2) + MSGF(gfc, ", SIMD2"); + MSGF(gfc, "\n"); + } + + if (gfp->num_channels == 2 && gfc->channels_out == 1 /* mono */ ) { + MSGF + (gfc, + "Autoconverting from stereo to mono. Setting encoding to mono mode.\n"); + } + + if (gfc->resample_ratio != 1.) { + MSGF(gfc, "Resampling: input %g kHz output %g kHz\n", + 1.e-3 * in_samplerate, 1.e-3 * out_samplerate); + } + + if (gfc->filter_type == 0) { + if (gfc->highpass2 > 0.) + MSGF + (gfc, + "Using polyphase highpass filter, transition band: %5.0f Hz - %5.0f Hz\n", + 0.5 * gfc->highpass1 * out_samplerate, + 0.5 * gfc->highpass2 * out_samplerate); + if (gfc->lowpass1 > 0.) { + MSGF + (gfc, + "Using polyphase lowpass filter, transition band: %5.0f Hz - %5.0f Hz\n", + 0.5 * gfc->lowpass1 * out_samplerate, + 0.5 * gfc->lowpass2 * out_samplerate); + } + else { + MSGF(gfc, "polyphase lowpass filter disabled\n"); + } + } + else { + MSGF(gfc, "polyphase filters disabled\n"); + } + + if (gfp->free_format) { + MSGF(gfc, + "Warning: many decoders cannot handle free format bitstreams\n"); + if (gfp->brate > 320) { + MSGF + (gfc, + "Warning: many decoders cannot handle free format bitrates >320 kbps (see documentation)\n"); + } + } +} + + +/** rh: + * some pretty printing is very welcome at this point! + * so, if someone is willing to do so, please do it! + * add more, if you see more... + */ +void +lame_print_internals( const lame_global_flags * gfp ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + const char * pc = ""; + + /* compiler/processor optimizations, operational, etc. + */ + MSGF( gfc, "\nmisc:\n\n" ); + + MSGF( gfc, "\tscaling: %f\n", gfp->scale ); + MSGF( gfc, "\tch0 (left) scaling: %f\n", gfp->scale_left ); + MSGF( gfc, "\tch1 (right) scaling: %f\n", gfp->scale_right ); + MSGF( gfc, "\tfilter type: %d\n", gfc->filter_type ); + pc = gfc->quantization ? "xr^3/4" : "ISO"; + MSGF( gfc, "\tquantization: %s\n", pc ); + switch( gfc->use_best_huffman ) { + default: pc = "normal"; break; + case 1: pc = "best (outside loop)"; break; + case 2: pc = "best (inside loop, slow)"; break; + } + MSGF( gfc, "\thuffman search: %s\n", pc ); + MSGF( gfc, "\texperimental X=%d Y=%d Z=%d\n", gfp->experimentalX, gfp->experimentalY, gfp->experimentalZ ); + MSGF( gfc, "\t...\n" ); + + /* everything controlling the stream format + */ + MSGF( gfc, "\nstream format:\n\n" ); + switch ( gfp->version ) { + case 0: pc = "2.5"; break; + case 1: pc = "1"; break; + case 2: pc = "2"; break; + default: pc = "?"; break; + } + MSGF( gfc, "\tMPEG-%s Layer 3\n", pc ); + switch ( gfp->mode ) { + case JOINT_STEREO: pc = "joint stereo"; break; + case STEREO : pc = "stereo"; break; + case DUAL_CHANNEL: pc = "dual channel"; break; + case MONO : pc = "mono"; break; + case NOT_SET : pc = "not set (error)"; break; + default : pc = "unknown (error)"; break; + } + MSGF( gfc, "\t%d channel - %s\n", gfc->channels_out, pc ); + switch ( gfp->padding_type ) { + case PAD_NO : pc = "off"; break; + case PAD_ALL : pc = "all"; break; + case PAD_ADJUST: pc = "auto"; break; + default : pc = "(error)"; break; + } + MSGF( gfc, "\tpadding: %s\n", pc ); + + if ( vbr_default == gfp->VBR ) pc = "(default)"; + else if ( gfp->free_format ) pc = "(free format)"; + else pc = ""; + switch ( gfp->VBR ) { + case vbr_off : MSGF( gfc, "\tconstant bitrate - CBR %s\n", pc ); break; + case vbr_abr : MSGF( gfc, "\tvariable bitrate - ABR %s\n", pc ); break; + case vbr_rh : MSGF( gfc, "\tvariable bitrate - VBR rh %s\n", pc ); break; + case vbr_mt : MSGF( gfc, "\tvariable bitrate - VBR mt %s\n", pc ); break; + case vbr_mtrh: MSGF( gfc, "\tvariable bitrate - VBR mtrh %s\n", pc ); break; + default : MSGF( gfc, "\t ?? oops, some new one ?? \n" ); break; + } + if (gfp->bWriteVbrTag) + MSGF( gfc, "\tusing LAME Tag\n" ); + MSGF( gfc, "\t...\n" ); + + /* everything controlling psychoacoustic settings, like ATH, etc. + */ + MSGF( gfc, "\npsychoacoustic:\n\n" ); + + MSGF( gfc, "\ttonality estimation limit: %f Hz\n", gfc->PSY->cwlimit ); + switch ( gfp->short_blocks ) { + default: + case short_block_not_set: pc = "?"; break; + case short_block_allowed: pc = "allowed"; break; + case short_block_coupled: pc = "channel coupled"; break; + case short_block_dispensed: pc = "dispensed"; break; + case short_block_forced: pc = "forced"; break; + } + MSGF( gfc, "\tusing short blocks: %s\n", pc ); + MSGF( gfc, "\tadjust masking: %f dB\n", gfc->VBR->mask_adjust ); + MSGF( gfc, "\tpsymodel: %d\n", gfc->psymodel ); + MSGF( gfc, "\tnoise shaping: %d\n", gfc->noise_shaping ); + MSGF( gfc, "\t ^ amplification: %d\n", gfc->noise_shaping_amp ); + MSGF( gfc, "\t ^ stopping: %d\n", gfc->noise_shaping_stop ); + + pc = "using"; + if ( gfp->ATHshort ) pc = "the only masking for short blocks"; + if ( gfp->ATHonly ) pc = "the only masking"; + if ( gfp->noATH ) pc = "not used"; + MSGF( gfc, "\tATH: %s\n", pc ); + MSGF( gfc, "\t ^ type: %d\n", gfp->ATHtype ); + MSGF( gfc, "\t ^ adjust type: %d\n", gfc->ATH->use_adjust ); + MSGF( gfc, "\t ^ adapt threshold type: %d\n", gfp->athaa_loudapprox ); + + if ( gfc->nsPsy.use ) { + MSGF( gfc, "\texperimental psy tunings by Naoki Shibata\n" ); + MSGF( gfc, "\t adjust masking bass=%g dB, alto=%g dB, treble=%g dB, sfb21=%g dB\n", + 10*log10(gfc->nsPsy.bass), 10*log10(gfc->nsPsy.alto), + 10*log10(gfc->nsPsy.treble), 10*log10(gfc->nsPsy.sfb21) ); + } + pc = gfp->useTemporal ? "yes" : "no"; + MSGF( gfc, "\tusing temporal masking effect: %s\n", pc ); + MSGF( gfc, "\t...\n" ); + + /* that's all ? + */ + MSGF( gfc, "\n" ); + return; +} + + + +/* int lame_encode_frame (lame_global_flags *gfp, sample_t inbuf_l[],sample_t inbuf_r[], char *mp3buf, int mp3buf_size) *//*{{{ */ + +/* routine to feed exactly one frame (gfp->framesize) worth of data to the +encoding engine. All buffering, resampling, etc, handled by calling +program. +*/ +int +lame_encode_frame(lame_global_flags * gfp, + sample_t inbuf_l[], sample_t inbuf_r[], + unsigned char *mp3buf, int mp3buf_size) +{ + int ret; + if (gfp->ogg) { +#ifdef HAVE_VORBIS_ENCODER + ret = lame_encode_ogg_frame(gfp, inbuf_l, inbuf_r, mp3buf, mp3buf_size); +#else + return -5; /* wanna encode ogg without vorbis */ +#endif + } + else { + ret = lame_encode_mp3_frame(gfp, inbuf_l, inbuf_r, mp3buf, mp3buf_size); + } + + + + gfp->frameNum++; + return ret; +} + +/*}}}*/ +/* int lame_encode_buffer (lame_global_flags* gfp, short int buffer_l[], short int buffer_r[], int nsamples, char* mp3buf, int mp3buf_size )*//*{{{ */ + + + +/* + * THE MAIN LAME ENCODING INTERFACE + * mt 3/00 + * + * input pcm data, output (maybe) mp3 frames. + * This routine handles all buffering, resampling and filtering for you. + * The required mp3buffer_size can be computed from num_samples, + * samplerate and encoding rate, but here is a worst case estimate: + * + * mp3buffer_size in bytes = 1.25*num_samples + 7200 + * + * return code = number of bytes output in mp3buffer. can be 0 +*/ +int +lame_encode_buffer_sample_t(lame_global_flags * gfp, + sample_t buffer_l[], + sample_t buffer_r[], + int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int mp3size = 0, ret, i, ch, mf_needed; + int mp3out; + sample_t *mfbuf[2]; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + /* copy out any tags that may have been written into bitstream */ + mp3out = copy_buffer(gfc,mp3buf,mp3buf_size,0); + if (mp3out<0) return mp3out; // not enough buffer space + mp3buf += mp3out; + mp3size += mp3out; + + + in_buffer[0]=buffer_l; + in_buffer[1]=buffer_r; + + + /* some sanity checks */ +#if ENCDELAY < MDCTDELAY +# error ENCDELAY is less than MDCTDELAY, see encoder.h +#endif +#if FFTOFFSET > BLKSIZE +# error FFTOFFSET is greater than BLKSIZE, see encoder.h +#endif + + mf_needed = BLKSIZE + gfp->framesize - FFTOFFSET; /* amount needed for FFT */ + mf_needed = Max(mf_needed, 286 + 576 * (1 + gfc->mode_gr)); /* amount needed for MDCT/filterbank */ + assert(MFSIZE >= mf_needed); + + mfbuf[0] = gfc->mfbuf[0]; + mfbuf[1] = gfc->mfbuf[1]; + + if (gfp->num_channels == 2 && gfc->channels_out == 1) { + /* downsample to mono */ + for (i = 0; i < nsamples; ++i) { + in_buffer[0][i] = + 0.5 * ((FLOAT8) in_buffer[0][i] + in_buffer[1][i]); + in_buffer[1][i] = 0.0; + } + } + + + while (nsamples > 0) { + int n_in = 0; /* number of input samples processed with fill_buffer */ + int n_out = 0; /* number of samples output with fill_buffer */ + /* n_in <> n_out if we are resampling */ + + /* copy in new samples into mfbuf, with resampling & scaling if necessary */ + fill_buffer(gfp, mfbuf, in_buffer, nsamples, &n_in, &n_out); + + /* update in_buffer counters */ + nsamples -= n_in; + in_buffer[0] += n_in; + if (gfc->channels_out == 2) + in_buffer[1] += n_in; + + /* update mfbuf[] counters */ + gfc->mf_size += n_out; + assert(gfc->mf_size <= MFSIZE); + gfc->mf_samples_to_encode += n_out; + + + if (gfc->mf_size >= mf_needed) { + /* encode the frame. */ + // mp3buf = pointer to current location in buffer + // mp3buf_size = size of original mp3 output buffer + // = 0 if we should not worry about the + // buffer size because calling program is + // to lazy to compute it + // mp3size = size of data written to buffer so far + // mp3buf_size-mp3size = amount of space avalable + + int buf_size=mp3buf_size - mp3size; + if (mp3buf_size==0) buf_size=0; + + ret = + lame_encode_frame(gfp, mfbuf[0], mfbuf[1], mp3buf,buf_size); + + if (ret < 0) goto retr; + mp3buf += ret; + mp3size += ret; + + /* shift out old samples */ + gfc->mf_size -= gfp->framesize; + gfc->mf_samples_to_encode -= gfp->framesize; + for (ch = 0; ch < gfc->channels_out; ch++) + for (i = 0; i < gfc->mf_size; i++) + mfbuf[ch][i] = mfbuf[ch][i + gfp->framesize]; + } + } + assert(nsamples == 0); + ret = mp3size; + + retr: + return ret; +} + + +int +lame_encode_buffer(lame_global_flags * gfp, + const short int buffer_l[], + const short int buffer_r[], + const int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ret, i; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -7; //-3 + + if (nsamples == 0) + return 0; + + in_buffer[0] = calloc(sizeof(sample_t), nsamples); + in_buffer[1] = calloc(sizeof(sample_t), nsamples); + + if (in_buffer[0] == NULL || in_buffer[1] == NULL) { + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + + /* make a copy of input buffer, changing type to sample_t */ + for (i = 0; i < nsamples; i++) { + in_buffer[0][i] = buffer_l[i]; + in_buffer[1][i] = buffer_r[i]; + } + + ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1], + nsamples, mp3buf, mp3buf_size); + + free(in_buffer[0]); + free(in_buffer[1]); + return ret; +} + + +int +lame_encode_buffer_float(lame_global_flags * gfp, + const float buffer_l[], + const float buffer_r[], + const int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ret, i; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + in_buffer[0] = calloc(sizeof(sample_t), nsamples); + in_buffer[1] = calloc(sizeof(sample_t), nsamples); + + if (in_buffer[0] == NULL || in_buffer[1] == NULL) { + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + + /* make a copy of input buffer, changing type to sample_t */ + for (i = 0; i < nsamples; i++) { + in_buffer[0][i] = buffer_l[i]; + in_buffer[1][i] = buffer_r[i]; + } + + ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1], + nsamples, mp3buf, mp3buf_size); + + free(in_buffer[0]); + free(in_buffer[1]); + return ret; +} + + + +int +lame_encode_buffer_int(lame_global_flags * gfp, + const int buffer_l[], + const int buffer_r[], + const int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ret, i; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + in_buffer[0] = calloc(sizeof(sample_t), nsamples); + in_buffer[1] = calloc(sizeof(sample_t), nsamples); + + if (in_buffer[0] == NULL || in_buffer[1] == NULL) { + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + + /* make a copy of input buffer, changing type to sample_t */ + for (i = 0; i < nsamples; i++) { + /* internal code expects +/- 32768.0 */ + in_buffer[0][i] = buffer_l[i] * (1.0 / ( 1 << (8 * sizeof(int) - 16))); + in_buffer[1][i] = buffer_r[i] * (1.0 / ( 1 << (8 * sizeof(int) - 16))); + } + + ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1], + nsamples, mp3buf, mp3buf_size); + + free(in_buffer[0]); + free(in_buffer[1]); + return ret; + +} + + + + +int +lame_encode_buffer_long2(lame_global_flags * gfp, + const long buffer_l[], + const long buffer_r[], + const int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ret, i; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + in_buffer[0] = calloc(sizeof(sample_t), nsamples); + in_buffer[1] = calloc(sizeof(sample_t), nsamples); + + if (in_buffer[0] == NULL || in_buffer[1] == NULL) { + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + + /* make a copy of input buffer, changing type to sample_t */ + for (i = 0; i < nsamples; i++) { + /* internal code expects +/- 32768.0 */ + in_buffer[0][i] = buffer_l[i] * (1.0 / ( 1 << (8 * sizeof(long) - 16))); + in_buffer[1][i] = buffer_r[i] * (1.0 / ( 1 << (8 * sizeof(long) - 16))); + } + + ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1], + nsamples, mp3buf, mp3buf_size); + + free(in_buffer[0]); + free(in_buffer[1]); + return ret; + +} + + + +int +lame_encode_buffer_long(lame_global_flags * gfp, + const long buffer_l[], + const long buffer_r[], + const int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ret, i; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + in_buffer[0] = calloc(sizeof(sample_t), nsamples); + in_buffer[1] = calloc(sizeof(sample_t), nsamples); + + if (in_buffer[0] == NULL || in_buffer[1] == NULL) { + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + + /* make a copy of input buffer, changing type to sample_t */ + for (i = 0; i < nsamples; i++) { + in_buffer[0][i] = buffer_l[i]; + in_buffer[1][i] = buffer_r[i]; + } + + ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1], + nsamples, mp3buf, mp3buf_size); + + free(in_buffer[0]); + free(in_buffer[1]); + return ret; +} + + + + + + + + + + + +int +lame_encode_buffer_interleaved(lame_global_flags * gfp, + short int buffer[], + int nsamples, + unsigned char *mp3buf, int mp3buf_size) +{ + int ret, i; + short int *buffer_l; + short int *buffer_r; + + buffer_l = malloc(sizeof(short int) * nsamples); + buffer_r = malloc(sizeof(short int) * nsamples); + if (buffer_l == NULL || buffer_r == NULL) { + return -2; + } + for (i = 0; i < nsamples; i++) { + buffer_l[i] = buffer[2 * i]; + buffer_r[i] = buffer[2 * i + 1]; + } + ret = + lame_encode_buffer(gfp, buffer_l, buffer_r, nsamples, mp3buf, + mp3buf_size); + free(buffer_l); + free(buffer_r); + return ret; + +} + + +/*}}}*/ +/* int lame_encode (lame_global_flags* gfp, short int in_buffer[2][1152], char* mp3buf, int size ) *//*{{{ */ + + +/* old LAME interface. use lame_encode_buffer instead */ + +int +lame_encode(lame_global_flags * const gfp, + const short int in_buffer[2][1152], + unsigned char *const mp3buf, const int size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + if (gfc->Class_ID != LAME_ID) + return -3; + + return lame_encode_buffer(gfp, in_buffer[0], in_buffer[1], gfp->framesize, + mp3buf, size); +} + +/*}}}*/ +/* int lame_encode_flush (lame_global_flags* gfp, char* mp3buffer, int mp3buffer_size ) *//*{{{ */ + + + +/***************************************************************** + Flush mp3 buffer, pad with ancillary data so last frame is complete. + Reset reservoir size to 0 + but keep all PCM samples and MDCT data in memory + This option is used to break a large file into several mp3 files + that when concatenated together will decode with no gaps + Because we set the reservoir=0, they will also decode seperately + with no errors. +*********************************************************************/ +int +lame_encode_flush_nogap(lame_global_flags * gfp, + unsigned char *mp3buffer, int mp3buffer_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + flush_bitstream(gfp); + return copy_buffer(gfc,mp3buffer, mp3buffer_size,1); +} + + +/* called by lame_init_params. You can also call this after flush_nogap + if you want to write new id3v2 and Xing VBR tags into the bitstream */ +int +lame_init_bitstream(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int i; + gfp->frameNum=0; + + if (!gfp->ogg) + id3tag_write_v2(gfp); + + /* initialize histogram data optionally used by frontend */ + for ( i = 0; i < 16; i++ ) + gfc->bitrate_stereoMode_Hist [i] [0] = + gfc->bitrate_stereoMode_Hist [i] [1] = + gfc->bitrate_stereoMode_Hist [i] [2] = + gfc->bitrate_stereoMode_Hist [i] [3] = + gfc->bitrate_stereoMode_Hist [i] [4] = 0; + + /* Write initial VBR Header to bitstream and init VBR data */ + if (gfp->bWriteVbrTag) + InitVbrTag(gfp); + + + return 0; +} + + +/*****************************************************************/ +/* flush internal PCM sample buffers, then mp3 buffers */ +/* then write id3 v1 tags into bitstream. */ +/*****************************************************************/ + +int +lame_encode_flush(lame_global_flags * gfp, + unsigned char *mp3buffer, int mp3buffer_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + short int buffer[2][1152]; + int imp3 = 0, mp3count, mp3buffer_size_remaining; + + /* we always add POSTDELAY=288 padding to make sure granule with real + * data can be complety decoded (because of 50% overlap with next granule */ + int end_padding=POSTDELAY; + + memset(buffer, 0, sizeof(buffer)); + mp3count = 0; + + + while (gfc->mf_samples_to_encode > 0) { + + mp3buffer_size_remaining = mp3buffer_size - mp3count; + + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = 0; + + /* send in a frame of 0 padding until all internal sample buffers + * are flushed + */ + imp3 = lame_encode_buffer(gfp, buffer[0], buffer[1], gfp->framesize, + mp3buffer, mp3buffer_size_remaining); + + /* don't count the above padding: */ + gfc->mf_samples_to_encode -= gfp->framesize; + if (gfc->mf_samples_to_encode < 0) { + /* we added extra padding to the end */ + end_padding += -gfc->mf_samples_to_encode; + } + + + if (imp3 < 0) { + /* some type of fatal error */ + return imp3; + } + mp3buffer += imp3; + mp3count += imp3; + } + + mp3buffer_size_remaining = mp3buffer_size - mp3count; + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = 0; + + if (gfp->ogg) { +#ifdef HAVE_VORBIS_ENCODER + /* ogg related stuff */ + imp3 = lame_encode_ogg_finish(gfp, mp3buffer, mp3buffer_size_remaining); +#endif + } + else { + /* mp3 related stuff. bit buffer might still contain some mp3 data */ + flush_bitstream(gfp); + imp3 = copy_buffer(gfc,mp3buffer, mp3buffer_size_remaining, 1); + if (imp3 < 0) { + /* some type of fatal error */ + return imp3; + } + mp3buffer += imp3; + mp3count += imp3; + mp3buffer_size_remaining = mp3buffer_size - mp3count; + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = 0; + + + /* write a id3 tag to the bitstream */ + id3tag_write_v1(gfp); + imp3 = copy_buffer(gfc,mp3buffer, mp3buffer_size_remaining, 0); + } + + if (imp3 < 0) { + return imp3; + } + mp3count += imp3; + gfp->encoder_padding=end_padding; + return mp3count; +} + +/*}}}*/ +/* void lame_close (lame_global_flags *gfp) *//*{{{ */ + +/*********************************************************************** + * + * lame_close () + * + * frees internal buffers + * + ***********************************************************************/ + +int +lame_close(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + if (gfc->Class_ID != LAME_ID) + return -3; + + gfc->Class_ID = 0; + + // this routien will free all malloc'd data in gfc, and then free gfc: + freegfc(gfc); + + gfp->internal_flags = NULL; + + if (gfp->lame_allocated_gfp) + free(gfp); + + return 0; +} + + +/*}}}*/ +/* int lame_encode_finish (lame_global_flags* gfp, char* mp3buffer, int mp3buffer_size ) *//*{{{ */ + + +/*****************************************************************/ +/* flush internal mp3 buffers, and free internal buffers */ +/*****************************************************************/ + +int +lame_encode_finish(lame_global_flags * gfp, + unsigned char *mp3buffer, int mp3buffer_size) +{ + int ret = lame_encode_flush(gfp, mp3buffer, mp3buffer_size); + + lame_close(gfp); + + return ret; +} + +/*}}}*/ +/* void lame_mp3_tags_fid (lame_global_flags *gfp,FILE *fpStream) *//*{{{ */ + +/*****************************************************************/ +/* write VBR Xing header, and ID3 version 1 tag, if asked for */ +/*****************************************************************/ +void +lame_mp3_tags_fid(lame_global_flags * gfp, FILE * fpStream) +{ + if (gfp->bWriteVbrTag) { + /* Map VBR_q to Xing quality value: 0=worst, 100=best */ + int nQuality = ((9-gfp->VBR_q) * 100) / 9; + + /* Write Xing header again */ + if (fpStream && !fseek(fpStream, 0, SEEK_SET)) + PutVbrTag(gfp, fpStream, nQuality); + } + + +} +/*}}}*/ +/* lame_global_flags *lame_init (void) *//*{{{ */ + +lame_global_flags * +lame_init(void) +{ + lame_global_flags *gfp; + int ret; + + gfp = calloc(1, sizeof(lame_global_flags)); + if (gfp == NULL) + return NULL; + + ret = lame_init_old(gfp); + if (ret != 0) { + free(gfp); + return NULL; + } + + gfp->lame_allocated_gfp = 1; + return gfp; +} + +/*}}}*/ +/* int lame_init_old (lame_global_flags *gfp) *//*{{{ */ + +/* initialize mp3 encoder */ +int +lame_init_old(lame_global_flags * gfp) +{ + lame_internal_flags *gfc; + + disable_FPE(); // disable floating point exceptions + + memset(gfp, 0, sizeof(lame_global_flags)); + + if (NULL == + (gfc = gfp->internal_flags = + calloc(1, sizeof(lame_internal_flags)))) return -1; + + /* Global flags. set defaults here for non-zero values */ + /* see lame.h for description */ + /* set integer values to -1 to mean that LAME will compute the + * best value, UNLESS the calling program as set it + * (and the value is no longer -1) + */ + + + gfp->mode = NOT_SET; + gfp->original = 1; + gfp->in_samplerate = 1000 * 44.1; + gfp->num_channels = 2; + gfp->num_samples = MAX_U_32_NUM; + + gfp->bWriteVbrTag = 1; + gfp->quality = -1; + gfp->short_blocks = short_block_not_set; + + gfp->lowpassfreq = 0; + gfp->highpassfreq = 0; + gfp->lowpasswidth = -1; + gfp->highpasswidth = -1; + + gfp->padding_type = PAD_ADJUST; + gfp->VBR = vbr_off; + gfp->VBR_q = 4; + gfp->VBR_mean_bitrate_kbps = 128; + gfp->VBR_min_bitrate_kbps = 0; + gfp->VBR_max_bitrate_kbps = 0; + gfp->VBR_hard_min = 0; + + + gfc->resample_ratio = 1; + gfc->lowpass_band = 32; + gfc->highpass_band = -1; + gfc->VBR_min_bitrate = 1; /* not 0 ????? */ + gfc->VBR_max_bitrate = 13; /* not 14 ????? */ + + gfc->OldValue[0] = 180; + gfc->OldValue[1] = 180; + gfc->CurrentStep = 4; + gfc->masking_lower = 1; + + gfp->athaa_type = -1; + gfp->ATHtype = -1; /* default = -1 = set in lame_init_params */ + gfp->athaa_loudapprox = -1; /* 1 = flat loudness approx. (total energy) */ + /* 2 = equal loudness curve */ + gfp->athaa_sensitivity = 0.0; /* no offset */ + gfp->useTemporal = -1; + + /* The reason for + * int mf_samples_to_encode = ENCDELAY + POSTDELAY; + * ENCDELAY = internal encoder delay. And then we have to add POSTDELAY=288 + * because of the 50% MDCT overlap. A 576 MDCT granule decodes to + * 1152 samples. To synthesize the 576 samples centered under this granule + * we need the previous granule for the first 288 samples (no problem), and + * the next granule for the next 288 samples (not possible if this is last + * granule). So we need to pad with 288 samples to make sure we can + * encode the 576 samples we are interested in. + */ + gfc->mf_samples_to_encode = ENCDELAY + POSTDELAY; + gfp->encoder_padding = 0; + gfc->mf_size = ENCDELAY - MDCTDELAY; /* we pad input with this many 0's */ + +#ifdef KLEMM_44 + /* XXX: this wasn't protectes by KLEMM_44 initially! */ + gfc->last_ampl = gfc->ampl = +1.0; +#endif + return 0; +} + +/*}}}*/ + +/*********************************************************************** + * + * some simple statistics + * + * Robert Hegemann 2000-10-11 + * + ***********************************************************************/ + +/* histogram of used bitrate indexes: + * One has to weight them to calculate the average bitrate in kbps + * + * bitrate indices: + * there are 14 possible bitrate indices, 0 has the special meaning + * "free format" which is not possible to mix with VBR and 15 is forbidden + * anyway. + * + * stereo modes: + * 0: LR number of left-right encoded frames + * 1: LR-I number of left-right and intensity encoded frames + * 2: MS number of mid-side encoded frames + * 3: MS-I number of mid-side and intensity encoded frames + * + * 4: number of encoded frames + * + */ + +void +lame_bitrate_hist(const lame_global_flags * const gfp, int bitrate_count[14]) +{ + const lame_internal_flags *gfc; + int i; + + if (NULL == bitrate_count) + return; + if (NULL == gfp) + return; + gfc = gfp->internal_flags; + if (NULL == gfc) + return; + + for (i = 0; i < 14; i++) + bitrate_count[i] = gfc->bitrate_stereoMode_Hist[i + 1][4]; +} + + +void +lame_bitrate_kbps(const lame_global_flags * const gfp, int bitrate_kbps[14]) +{ + const lame_internal_flags *gfc; + int i; + + if (NULL == bitrate_kbps) + return; + if (NULL == gfp) + return; + gfc = gfp->internal_flags; + if (NULL == gfc) + return; + + for (i = 0; i < 14; i++) + bitrate_kbps[i] = bitrate_table[gfp->version][i + 1]; +} + + + +void +lame_stereo_mode_hist(const lame_global_flags * const gfp, int stmode_count[4]) +{ + const lame_internal_flags *gfc; + int i; + + if (NULL == stmode_count) + return; + if (NULL == gfp) + return; + gfc = gfp->internal_flags; + if (NULL == gfc) + return; + + for (i = 0; i < 4; i++) { + int j, sum = 0; + for (j = 0; j < 14; j++) + sum += gfc->bitrate_stereoMode_Hist[j + 1][i]; + stmode_count[i] = sum; + } +} + + + +void +lame_bitrate_stereo_mode_hist(const lame_global_flags * const gfp, + int bitrate_stmode_count[14][4]) +{ + const lame_internal_flags *gfc; + int i; + int j; + + if (NULL == bitrate_stmode_count) + return; + if (NULL == gfp) + return; + gfc = gfp->internal_flags; + if (NULL == gfc) + return; + + for (j = 0; j < 14; j++) + for (i = 0; i < 4; i++) + bitrate_stmode_count[j][i] = gfc->bitrate_stereoMode_Hist[j + 1][i]; +} + +/* end of lame.c */ diff -Nru swftools-0.9.2+ds1/lib/lame/lameerror.h swftools-0.9.1/lib/lame/lameerror.h --- swftools-0.9.2+ds1/lib/lame/lameerror.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/lameerror.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,26 @@ +/* + * A collection of LAME Error Codes + * + * Please use the constants defined here instead of some arbitrary + * values. Currently the values starting at -10 to avoid intersection + * with the -1, -2, -3 and -4 used in the current code. + * + * May be this should be a part of the include/lame.h. + */ + +typedef enum { + LAME_OKAY = 0, + LAME_NOERROR = 0, + LAME_GENERICERROR = -1, + LAME_NOMEM = -10, + LAME_BADBITRATE = -11, + LAME_BADSAMPFREQ = -12, + LAME_INTERNALERROR = -13, + + FRONTEND_READERROR = -80, + FRONTEND_WRITEERROR = -81, + FRONTEND_FILETOOLARGE = -82, + +} lame_errorcodes_t; + +/* end of lameerror.h */ diff -Nru swftools-0.9.2+ds1/lib/lame/lame_global_flags.h swftools-0.9.1/lib/lame/lame_global_flags.h --- swftools-0.9.2+ds1/lib/lame/lame_global_flags.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/lame_global_flags.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,178 @@ + +#ifndef LAME_GLOBAL_FLAGS_H +#define LAME_GLOBAL_FLAGS_H + +struct lame_internal_flags; +typedef struct lame_internal_flags lame_internal_flags; + + +typedef enum short_block_e { + short_block_not_set = -1, /* allow LAME to decide */ + short_block_allowed = 0, /* LAME may use them, even different block types for L/R */ + short_block_coupled, /* LAME may use them, but always same block types in L/R */ + short_block_dispensed, /* LAME will not use short blocks, long blocks only */ + short_block_forced /* LAME will not use long blocks, short blocks only */ +} short_block_t; + +/*********************************************************************** +* +* Control Parameters set by User. These parameters are here for +* backwards compatibility with the old, non-shared lib API. +* Please use the lame_set_variablename() functions below +* +* +***********************************************************************/ +struct lame_global_struct { + /* input description */ + unsigned long num_samples; /* number of samples. default=2^32-1 */ + int num_channels; /* input number of channels. default=2 */ + int in_samplerate; /* input_samp_rate in Hz. default=44.1 kHz */ + int out_samplerate; /* output_samp_rate. + default: LAME picks best value + at least not used for MP3 decoding: + Remember 44.1 kHz MP3s and AC97 */ + float scale; /* scale input by this amount before encoding + at least not used for MP3 decoding */ + float scale_left; /* scale input of channel 0 (left) by this + amount before encoding */ + float scale_right; /* scale input of channel 1 (right) by this + amount before encoding */ + + /* general control params */ + int analysis; /* collect data for a MP3 frame analyzer? */ + int bWriteVbrTag; /* add Xing VBR tag? */ + int decode_only; /* use lame/mpglib to convert mp3/ogg to wav */ + int ogg; /* encode to Vorbis .ogg file */ + + int quality; /* quality setting 0=best, 9=worst default=5 */ + MPEG_mode mode; /* see enum in lame.h + default = LAME picks best value */ + int mode_fixed; /* ignored */ + int mode_automs; /* use a m/s threshold based on compression + ratio */ + int force_ms; /* force M/S mode. requires mode=1 */ + int free_format; /* use free format? default=0 */ + + /* + * set either brate>0 or compression_ratio>0, LAME will compute + * the value of the variable not set. + * Default is compression_ratio = 11.025 + */ + int brate; /* bitrate */ + float compression_ratio; /* sizeof(wav file)/sizeof(mp3 file) */ + + + /* frame params */ + int copyright; /* mark as copyright. default=0 */ + int original; /* mark as original. default=1 */ + int error_protection; /* use 2 bytes per frame for a CRC + checksum. default=0 */ + Padding_type padding_type; /* PAD_NO = no padding, + PAD_ALL = always pad, + PAD_ADJUST = adjust padding, + default=2 */ + int extension; /* the MP3 'private extension' bit. + Meaningless */ + int strict_ISO; /* enforce ISO spec as much as possible */ + + /* quantization/noise shaping */ + int disable_reservoir; /* use bit reservoir? */ + int experimentalX; + int experimentalY; + int experimentalZ; + int exp_nspsytune; + + double newmsfix; + int preset_expopts; + + /* VBR control */ + vbr_mode VBR; + int VBR_q; + int VBR_mean_bitrate_kbps; + int VBR_min_bitrate_kbps; + int VBR_max_bitrate_kbps; + int VBR_hard_min; /* strictly enforce VBR_min_bitrate + normaly, it will be violated for analog + silence */ + + + /* resampling and filtering */ + int lowpassfreq; /* freq in Hz. 0=lame choses. + -1=no filter */ + int highpassfreq; /* freq in Hz. 0=lame choses. + -1=no filter */ + int lowpasswidth; /* freq width of filter, in Hz + (default=15%) */ + int highpasswidth; /* freq width of filter, in Hz + (default=15%) */ + + + + /* + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + */ + int ATHonly; /* only use ATH */ + int ATHshort; /* only use ATH for short blocks */ + int noATH; /* disable ATH */ + int ATHtype; /* select ATH formula */ + float ATHlower; /* lower ATH by this many db */ + int athaa_type; /* select ATH auto-adjust scheme */ + int athaa_loudapprox; /* select ATH auto-adjust loudness calc */ + float athaa_sensitivity; /* dB, tune active region of auto-level */ + int cwlimit; /* predictability limit */ + short_block_t short_blocks; +/* int allow_diff_short; allow blocktypes to differ between + channels? */ + int useTemporal; /* use temporal masking effect */ +/* int no_short_blocks; disable short blocks */ + int emphasis; /* Input PCM is emphased PCM (for + instance from one of the rarely + emphased CDs), it is STRONGLY not + recommended to use this, because + psycho does not take it into account, + and last but not least many decoders + don't care about these bits */ + float msfix; /* Naoki's adjustment of Mid/Side maskings */ + + int tune; /* 0 off, 1 on */ + float tune_value_a; /* used to pass values for debugging and stuff */ + + + struct { + void (*msgf) (const char *format, va_list ap); + void (*debugf)(const char *format, va_list ap); + void (*errorf)(const char *format, va_list ap); + } report; + + /************************************************************************/ + /* internal variables, do not set... */ + /* provided because they may be of use to calling application */ + /************************************************************************/ + + int version; /* 0=MPEG-2/2.5 1=MPEG-1 */ + int encoder_delay; + int encoder_padding; /* number of samples of padding appended to input */ + int framesize; + int frameNum; /* number of frames encoded */ + int lame_allocated_gfp; /* is this struct owned by calling + program or lame? */ + + + + /****************************************************************************/ + /* more internal variables, which will not exist after lame_encode_finish() */ + /****************************************************************************/ + lame_internal_flags *internal_flags; + + /* VBR tags. This data is here because VBR header is writen after + * input file is closed and *internal_flags struct is free'd */ + int TotalFrameSize; + //int* pVbrFrames; + int nVbrNumFrames; + int nVbrFrameBufferSize; + + +} ; + +#endif /* LAME_GLOBAL_FLAGS_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/lame.h swftools-0.9.1/lib/lame/lame.h --- swftools-0.9.2+ds1/lib/lame/lame.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/lame.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,902 @@ +/* + * Interface to MP3 LAME encoding engine + * + * Copyright (c) 1999 Mark Taylor + * + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Id: lame.h,v 1.1 2002/04/28 17:30:20 kramm Exp $ */ + +#ifndef LAME_LAME_H +#define LAME_LAME_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(WIN32) +#undef CDECL +#define CDECL _cdecl +#else +#define CDECL +#endif + + +typedef enum vbr_mode_e { + vbr_off=0, + vbr_mt, /* obsolete, same as vbr_mtrh */ + vbr_rh, + vbr_abr, + vbr_mtrh, + vbr_max_indicator, /* Don't use this! It's used for sanity checks. */ + vbr_default=vbr_rh /* change this to change the default VBR mode of LAME */ +} vbr_mode; + + +/* MPEG modes */ +typedef enum MPEG_mode_e { + STEREO = 0, + JOINT_STEREO, + DUAL_CHANNEL, /* LAME doesn't supports this! */ + MONO, + NOT_SET, + MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ +} MPEG_mode; + +/* Padding types */ +typedef enum Padding_type_e { + PAD_NO = 0, + PAD_ALL, + PAD_ADJUST, + PAD_MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ +} Padding_type; + + + +struct lame_global_struct; +typedef struct lame_global_struct lame_global_flags; +typedef lame_global_flags *lame_t; + + + + +/*********************************************************************** + * + * The LAME API + * These functions should be called, in this order, for each + * MP3 file to be encoded + * + ***********************************************************************/ + + +/* + * REQUIRED: + * initialize the encoder. sets default for all encoder paramters, + * returns -1 if some malloc()'s failed + * otherwise returns 0 + */ +lame_global_flags * CDECL lame_init(void); +/* obsolete version */ +int CDECL lame_init_old(lame_global_flags *); + + +/* + * OPTIONAL: + * set as needed to override defaults + */ + +/******************************************************************** + * input stream description + ***********************************************************************/ +// number of samples. default = 2^32-1 +int CDECL lame_set_num_samples(lame_global_flags *, unsigned long); +unsigned long CDECL lame_get_num_samples(const lame_global_flags *); + +// input sample rate in Hz. default = 44100hz +int CDECL lame_set_in_samplerate(lame_global_flags *, int); +int CDECL lame_get_in_samplerate(const lame_global_flags *); + +// number of channels in input stream. default=2 +int CDECL lame_set_num_channels(lame_global_flags *, int); +int CDECL lame_get_num_channels(const lame_global_flags *); + +// scale the input by this amount before encoding. default=0 (disabled) +// (not used by decoding routines) +int CDECL lame_set_scale(lame_global_flags *, float); +float CDECL lame_get_scale(const lame_global_flags *); + +// scale the channel 0 (left) input by this amount before encoding. +// default=0 (disabled) +// (not used by decoding routines) +int CDECL lame_set_scale_left(lame_global_flags *, float); +float CDECL lame_get_scale_left(const lame_global_flags *); + +// scale the channel 1 (right) input by this amount before encoding. +// default=0 (disabled) +// (not used by decoding routines) +int CDECL lame_set_scale_right(lame_global_flags *, float); +float CDECL lame_get_scale_right(const lame_global_flags *); + +// output sample rate in Hz. default = 0, which means LAME picks best value +// based on the amount of compression. MPEG only allows: +// MPEG1 32, 44.1, 48khz +// MPEG2 16, 22.05, 24 +// MPEG2.5 8, 11.025, 12 +// (not used by decoding routines) +int CDECL lame_set_out_samplerate(lame_global_flags *, int); +int CDECL lame_get_out_samplerate(const lame_global_flags *); + + +/******************************************************************** + * general control parameters + ***********************************************************************/ +// 1=cause LAME to collect data for an MP3 frame analyzer. default=0 +int CDECL lame_set_analysis(lame_global_flags *, int); +int CDECL lame_get_analysis(const lame_global_flags *); + +// 1 = write a Xing VBR header frame. +// default = 1 for VBR/ABR modes, 0 for CBR mode +// this variable must have been added by a Hungarian notation Windows programmer :-) +int CDECL lame_set_bWriteVbrTag(lame_global_flags *, int); +int CDECL lame_get_bWriteVbrTag(const lame_global_flags *); + +// 1=decode only. use lame/mpglib to convert mp3/ogg to wav. default=0 +int CDECL lame_set_decode_only(lame_global_flags *, int); +int CDECL lame_get_decode_only(const lame_global_flags *); + +// 1=encode a Vorbis .ogg file. default=0 +int CDECL lame_set_ogg(lame_global_flags *, int); +int CDECL lame_get_ogg(const lame_global_flags *); + +// internal algorithm selection. True quality is determined by the bitrate +// but this variable will effect quality by selecting expensive or cheap algorithms. +// quality=0..9. 0=best (very slow). 9=worst. +// recommended: 2 near-best quality, not too slow +// 5 good quality, fast +// 7 ok quality, really fast +int CDECL lame_set_quality(lame_global_flags *, int); +int CDECL lame_get_quality(const lame_global_flags *); + +// mode = 0,1,2,3 = stereo, jstereo, dual channel (not supported), mono +// default: lame picks based on compression ration and input channels +int CDECL lame_set_mode(lame_global_flags *, MPEG_mode); +MPEG_mode CDECL lame_get_mode(const lame_global_flags *); + +// mode_automs. Use a M/S mode with a switching threshold based on +// compression ratio +// default = 0 (disabled) +int CDECL lame_set_mode_automs(lame_global_flags *, int); +int CDECL lame_get_mode_automs(const lame_global_flags *); + +// force_ms. Force M/S for all frames. For testing only. +// default = 0 (disabled) +int CDECL lame_set_force_ms(lame_global_flags *, int); +int CDECL lame_get_force_ms(const lame_global_flags *); + +// use free_format? default = 0 (disabled) +int CDECL lame_set_free_format(lame_global_flags *, int); +int CDECL lame_get_free_format(const lame_global_flags *); + +/* + * OPTIONAL: + * Set printf like error/debug/message reporting functions. + * The second argument has to be a pointer to a function which looks like + * void my_debugf(const char *format, va_list ap) + * { + * (void) vfprintf(stdout, format, ap); + * } + * If you use NULL as the value of the pointer in the set function, the + * lame buildin function will be used (prints to stderr). + * To quiet any output you have to replace the body of the example function + * with just "return;" and use it in the set function. + */ +int CDECL lame_set_errorf(lame_global_flags *, + void (*func)(const char *, va_list)); +int CDECL lame_set_debugf(lame_global_flags *, + void (*func)(const char *, va_list)); +int CDECL lame_set_msgf (lame_global_flags *, + void (*func)(const char *, va_list)); + + + +/* set one of brate compression ratio. default is compression ratio of 11. */ +int CDECL lame_set_brate(lame_global_flags *, int); +int CDECL lame_get_brate(const lame_global_flags *); +int CDECL lame_set_compression_ratio(lame_global_flags *, float); +float CDECL lame_get_compression_ratio(const lame_global_flags *); + +/******************************************************************** + * frame params + ***********************************************************************/ +// mark as copyright. default=0 +int CDECL lame_set_copyright(lame_global_flags *, int); +int CDECL lame_get_copyright(const lame_global_flags *); + +// mark as original. default=1 +int CDECL lame_set_original(lame_global_flags *, int); +int CDECL lame_get_original(const lame_global_flags *); + +// error_protection. Use 2 bytes from each frame for CRC checksum. default=0 +int CDECL lame_set_error_protection(lame_global_flags *, int); +int CDECL lame_get_error_protection(const lame_global_flags *); + +// padding_type. 0=pad no frames 1=pad all frames 2=adjust padding(default) +int CDECL lame_set_padding_type(lame_global_flags *, Padding_type); +Padding_type CDECL lame_get_padding_type(const lame_global_flags *); + +// MP3 'private extension' bit Meaningless. default=0 +int CDECL lame_set_extension(lame_global_flags *, int); +int CDECL lame_get_extension(const lame_global_flags *); + +// enforce strict ISO compliance. default=0 +int CDECL lame_set_strict_ISO(lame_global_flags *, int); +int CDECL lame_get_strict_ISO(const lame_global_flags *); + + +/******************************************************************** + * quantization/noise shaping + ***********************************************************************/ + +// disable the bit reservoir. For testing only. default=0 +int CDECL lame_set_disable_reservoir(lame_global_flags *, int); +int CDECL lame_get_disable_reservoir(const lame_global_flags *); + +// select a different "best quantization" function. default=0 +int CDECL lame_set_experimentalX(lame_global_flags *, int); +int CDECL lame_get_experimentalX(const lame_global_flags *); + +// another experimental option. for testing only +int CDECL lame_set_experimentalY(lame_global_flags *, int); +int CDECL lame_get_experimentalY(const lame_global_flags *); + +// another experimental option. for testing only +int CDECL lame_set_experimentalZ(lame_global_flags *, int); +int CDECL lame_get_experimentalZ(const lame_global_flags *); + +// Naoki's psycho acoustic model. default=0 +int CDECL lame_set_exp_nspsytune(lame_global_flags *, int); +int CDECL lame_get_exp_nspsytune(const lame_global_flags *); + + + +/******************************************************************** + * VBR control + ***********************************************************************/ +// Types of VBR. default = vbr_off = CBR +int CDECL lame_set_VBR(lame_global_flags *, vbr_mode); +vbr_mode CDECL lame_get_VBR(const lame_global_flags *); + +// VBR quality level. 0=highest 9=lowest +int CDECL lame_set_VBR_q(lame_global_flags *, int); +int CDECL lame_get_VBR_q(const lame_global_flags *); + +// Ignored except for VBR=vbr_abr (ABR mode) +int CDECL lame_set_VBR_mean_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_mean_bitrate_kbps(const lame_global_flags *); + +int CDECL lame_set_VBR_min_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_min_bitrate_kbps(const lame_global_flags *); + +int CDECL lame_set_VBR_max_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_max_bitrate_kbps(const lame_global_flags *); + +// 1=stricetly enforce VBR_min_bitrate. Normally it will be violated for +// analog silence +int CDECL lame_set_VBR_hard_min(lame_global_flags *, int); +int CDECL lame_get_VBR_hard_min(const lame_global_flags *); + + +/******************************************************************** + * Filtering control + ***********************************************************************/ +// freq in Hz to apply lowpass. Default = 0 = lame chooses. -1 = disabled +int CDECL lame_set_lowpassfreq(lame_global_flags *, int); +int CDECL lame_get_lowpassfreq(const lame_global_flags *); +// width of transition band, in Hz. Default = one polyphase filter band +int CDECL lame_set_lowpasswidth(lame_global_flags *, int); +int CDECL lame_get_lowpasswidth(const lame_global_flags *); + +// freq in Hz to apply highpass. Default = 0 = lame chooses. -1 = disabled +int CDECL lame_set_highpassfreq(lame_global_flags *, int); +int CDECL lame_get_highpassfreq(const lame_global_flags *); +// width of transition band, in Hz. Default = one polyphase filter band +int CDECL lame_set_highpasswidth(lame_global_flags *, int); +int CDECL lame_get_highpasswidth(const lame_global_flags *); + + +/******************************************************************** + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + ***********************************************************************/ +// only use ATH for masking +int CDECL lame_set_ATHonly(lame_global_flags *, int); +int CDECL lame_get_ATHonly(const lame_global_flags *); + +// only use ATH for short blocks +int CDECL lame_set_ATHshort(lame_global_flags *, int); +int CDECL lame_get_ATHshort(const lame_global_flags *); + +// disable ATH +int CDECL lame_set_noATH(lame_global_flags *, int); +int CDECL lame_get_noATH(const lame_global_flags *); + +// select ATH formula +int CDECL lame_set_ATHtype(lame_global_flags *, int); +int CDECL lame_get_ATHtype(const lame_global_flags *); + +// lower ATH by this many db +int CDECL lame_set_ATHlower(lame_global_flags *, float); +float CDECL lame_get_ATHlower(const lame_global_flags *); + +// select ATH adaptive adjustment type +int CDECL lame_set_athaa_type( lame_global_flags *, int); +int CDECL lame_get_athaa_type( const lame_global_flags *); + +// select the loudness approximation used by the ATH adaptive auto-leveling +int CDECL lame_set_athaa_loudapprox( lame_global_flags *, int); +int CDECL lame_get_athaa_loudapprox( const lame_global_flags *); + +// adjust (in dB) the point below which adaptive ATH level adjustment occurs +int CDECL lame_set_athaa_sensitivity( lame_global_flags *, float); +float CDECL lame_get_athaa_sensitivity( const lame_global_flags* ); + +// predictability limit (ISO tonality formula) +int CDECL lame_set_cwlimit(lame_global_flags *, int); +int CDECL lame_get_cwlimit(const lame_global_flags *); + +// allow blocktypes to differ between channels? +// default: 0 for jstereo, 1 for stereo +int CDECL lame_set_allow_diff_short(lame_global_flags *, int); +int CDECL lame_get_allow_diff_short(const lame_global_flags *); + +// use temporal masking effect (default = 1) +int CDECL lame_set_useTemporal(lame_global_flags *, int); +int CDECL lame_get_useTemporal(const lame_global_flags *); + +// disable short blocks +int CDECL lame_set_no_short_blocks(lame_global_flags *, int); +int CDECL lame_get_no_short_blocks(const lame_global_flags *); + +// force short blocks +int CDECL lame_set_force_short_blocks(lame_global_flags *, int); +int CDECL lame_get_force_short_blocks(const lame_global_flags *); + +/* Input PCM is emphased PCM (for instance from one of the rarely + emphased CDs), it is STRONGLY not recommended to use this, because + psycho does not take it into account, and last but not least many decoders + ignore these bits */ +int CDECL lame_set_emphasis(lame_global_flags *, int); +int CDECL lame_get_emphasis(const lame_global_flags *); + + + +/************************************************************************/ +/* internal variables, cannot be set... */ +/* provided because they may be of use to calling application */ +/************************************************************************/ +// version 0=MPEG-2 1=MPEG-1 (2=MPEG-2.5) +int CDECL lame_get_version(const lame_global_flags *); + +// encoder delay +int CDECL lame_get_encoder_delay(const lame_global_flags *); + +// padding appended to the input to make sure decoder can fully decode +// all input. Note that this value can only be calculated during the +// call to lame_encoder_flush(). Before lame_encoder_flush() has +// been called, the value of encoder_padding = 0. +int CDECL lame_get_encoder_padding(const lame_global_flags *); + +// size of MPEG frame +int CDECL lame_get_framesize(const lame_global_flags *); + +// number of PCM samples buffered, but not yet encoded to mp3 data. +int CDECL lame_get_mf_samples_to_encode( const lame_global_flags* gfp ); + +// size (bytes) of mp3 data buffered, but not yet encoded. +// this is the number of bytes which would be output by a call to +// lame_encode_flush_nogap. NOTE: lame_encode_flush() will return +// more bytes than this because it will encode the reamining buffered +// PCM samples before flushing the mp3 buffers. +int CDECL lame_get_size_mp3buffer( const lame_global_flags* gfp ); + +// number of frames encoded so far +int CDECL lame_get_frameNum(const lame_global_flags *); + +// lame's estimate of the total number of frames to be encoded +// only valid if calling program set num_samples +int CDECL lame_get_totalframes(const lame_global_flags *); + + + + + + + + +/* + * REQUIRED: + * sets more internal configuration based on data provided above. + * returns -1 if something failed. + */ +int CDECL lame_init_params(lame_global_flags * const ); + + +/* + * OPTIONAL: + * get the version number, in a string. of the form: + * "3.63 (beta)" or just "3.63". + */ +const char* CDECL get_lame_version ( void ); +const char* CDECL get_lame_short_version ( void ); +const char* CDECL get_lame_very_short_version ( void ); +const char* CDECL get_psy_version ( void ); +const char* CDECL get_lame_url ( void ); + +/* + * OPTIONAL: + * get the version numbers in numerical form. + */ +typedef struct { + /* generic LAME version */ + int major; + int minor; + int alpha; /* 0 if not an alpha version */ + int beta; /* 0 if not a beta version */ + + /* version of the psy model */ + int psy_major; + int psy_minor; + int psy_alpha; /* 0 if not an alpha version */ + int psy_beta; /* 0 if not a beta version */ + + /* compile time features */ + const char *features; /* Don't make assumptions about the contents! */ +} lame_version_t; +void CDECL get_lame_version_numerical ( lame_version_t *const ); + + +/* + * OPTIONAL: + * print internal lame configuration to message handler + */ +void CDECL lame_print_config(const lame_global_flags* gfp); + +void CDECL lame_print_internals( const lame_global_flags *gfp); + + +/* + * input pcm data, output (maybe) mp3 frames. + * This routine handles all buffering, resampling and filtering for you. + * + * return code number of bytes output in mp3buf. Can be 0 + * -1: mp3buf was too small + * -2: malloc() problem + * -3: lame_init_params() not called + * -4: psycho acoustic problems + * -5: ogg cleanup encoding error + * -6: ogg frame encoding error + * + * The required mp3buf_size can be computed from num_samples, + * samplerate and encoding rate, but here is a worst case estimate: + * + * mp3buf_size in bytes = 1.25*num_samples + 7200 + * + * I think a tighter bound could be: (mt, March 2000) + * MPEG1: + * num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512 + * MPEG2: + * num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256 + * + * but test first if you use that! + * + * set mp3buf_size = 0 and LAME will not check if mp3buf_size is + * large enough. + * + * NOTE: + * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels + * will be averaged into the L channel before encoding only the L channel + * This will overwrite the data in buffer_l[] and buffer_r[]. + * +*/ +int CDECL lame_encode_buffer ( + lame_global_flags* gfp, /* global context handle */ + const short int buffer_l [], /* PCM data for left channel */ + const short int buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* + * as above, but input has L & R channel data interleaved. + * NOTE: + * num_samples = number of samples in the L (or R) + * channel, not the total number of samples in pcm[] + */ +int CDECL lame_encode_buffer_interleaved( + lame_global_flags* gfp, /* global context handlei */ + short int pcm[], /* PCM data for left and right + channel, interleaved */ + int num_samples, /* number of samples per channel, + _not_ number of samples in + pcm[] */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int mp3buf_size ); /* number of valid octets in this + stream */ + + +/* as lame_encode_buffer, but for 'float's. + * !! NOTE: !! data must still be scaled to be in the same range as + * short int, +/- 32768 + */ +int CDECL lame_encode_buffer_float( + lame_global_flags* gfp, /* global context handle */ + const float buffer_l [], /* PCM data for left channel */ + const float buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + + +/* as lame_encode_buffer, but for long's + * !! NOTE: !! data must still be scaled to be in the same range as + * short int, +/- 32768 + * + * This scaling was a mistake (doesn't allow one to exploit full + * precision of type 'long'. Use lame_encode_buffer_long2() instead. + * + */ +int CDECL lame_encode_buffer_long( + lame_global_flags* gfp, /* global context handle */ + const long buffer_l [], /* PCM data for left channel */ + const long buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* Same as lame_encode_buffer_long(), but with correct scaling. + * !! NOTE: !! data must still be scaled to be in the same range as + * type 'long'. Data should be in the range: +/- 2^(8*size(long)-1) + * + */ +int CDECL lame_encode_buffer_long2( + lame_global_flags* gfp, /* global context handle */ + const long buffer_l [], /* PCM data for left channel */ + const long buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* as lame_encode_buffer, but for int's + * !! NOTE: !! input should be scaled to the maximum range of 'int' + * If int is 4 bytes, then the values should range from + * +/- 2147483648. + * + * This routine does not (and cannot, without loosing precision) use + * the same scaling as the rest of the lame_encode_buffer() routines. + * + */ +int CDECL lame_encode_buffer_int( + lame_global_flags* gfp, /* global context handle */ + const int buffer_l [], /* PCM data for left channel */ + const int buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + + + + + +/* + * REQUIRED: + * lame_encode_flush will flush the intenal PCM buffers, padding with + * 0's to make sure the final frame is complete, and then flush + * the internal MP3 buffers, and thus may return a + * final few mp3 frames. 'mp3buf' should be at least 7200 bytes long + * to hold all possible emitted data. + * + * will also write id3v1 tags (if any) into the bitstream + * + * return code = number of bytes output to mp3buf. Can be 0 + */ +int CDECL lame_encode_flush( + lame_global_flags * gfp, /* global context handle */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int size); /* number of valid octets in this stream */ + +/* + * OPTIONAL: + * lame_encode_flush_nogap will flush the internal mp3 buffers and pad + * the last frame with ancillary data so it is a complete mp3 frame. + * + * 'mp3buf' should be at least 7200 bytes long + * to hold all possible emitted data. + * + * After a call to this routine, the outputed mp3 data is complete, but + * you may continue to encode new PCM samples and write future mp3 data + * to a different file. The two mp3 files will play back with no gaps + * if they are concatenated together. + * + * This routine will NOT write id3v1 tags into the bitstream. + * + * return code = number of bytes output to mp3buf. Can be 0 + */ +int CDECL lame_encode_flush_nogap( + lame_global_flags * gfp, /* global context handle */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int size); /* number of valid octets in this stream */ + +/* + * OPTIONAL: + * Normally, this is called by lame_init_params(). It writes id3v2 and + * Xing headers into the front of the bitstream, and sets frame counters + * and bitrate histogram data to 0. You can also call this after + * lame_encode_flush_nogap(). + */ +int CDECL lame_init_bitstream( + lame_global_flags * gfp); /* global context handle */ + + + +/* + * OPTIONAL: some simple statistics + * a bitrate histogram to visualize the distribution of used frame sizes + * a stereo mode histogram to visualize the distribution of used stereo + * modes, useful in joint-stereo mode only + * 0: LR left-right encoded + * 1: LR-I left-right and intensity encoded (currently not supported) + * 2: MS mid-side encoded + * 3: MS-I mid-side and intensity encoded (currently not supported) + * + * attention: don't call them after lame_encode_finish + * suggested: lame_encode_flush -> lame_*_hist -> lame_close + */ + +void CDECL lame_bitrate_hist( + const lame_global_flags *const gfp, + int bitrate_count[14] ); +void CDECL lame_bitrate_kbps( + const lame_global_flags *const gfp, + int bitrate_kbps [14] ); +void CDECL lame_stereo_mode_hist( + const lame_global_flags *const gfp, + int stereo_mode_count[4] ); + +void CDECL lame_bitrate_stereo_mode_hist ( + const lame_global_flags * const gfp, + int bitrate_stmode_count [14] [4] ); + + +/* + * OPTIONAL: + * lame_mp3_tags_fid will append a Xing VBR tag to the mp3 file with file + * pointer fid. These calls perform forward and backwards seeks, so make + * sure fid is a real file. Make sure lame_encode_flush has been called, + * and all mp3 data has been written to the file before calling this + * function. + * NOTE: + * if VBR tags are turned off by the user, or turned off by LAME because + * the output is not a regular file, this call does nothing +*/ +void CDECL lame_mp3_tags_fid(lame_global_flags *,FILE* fid); + + +/* + * REQUIRED: + * final call to free all remaining buffers + */ +int CDECL lame_close (lame_global_flags *); + +/* + * OBSOLETE: + * lame_encode_finish combines lame_encode_flush() and lame_close() in + * one call. However, once this call is made, the statistics routines + * will no longer work because the data will have been cleared + */ +int CDECL lame_encode_finish( + lame_global_flags* gfp, + unsigned char* mp3buf, + int size ); + + + + + + + +/********************************************************************* + * + * decoding + * + * a simple interface to mpglib, part of mpg123, is also included if + * libmp3lame is compiled with HAVE_MPGLIB + * + *********************************************************************/ +typedef struct { + int header_parsed; /* 1 if header was parsed and following data was + computed */ + int stereo; /* number of channels */ + int samplerate; /* sample rate */ + int bitrate; /* bitrate */ + int mode; /* mp3 frame type */ + int mode_ext; /* mp3 frame type */ + int framesize; /* number of samples per mp3 frame */ + + /* this data is only computed if mpglib detects a Xing VBR header */ + unsigned long nsamp; /* number of samples in mp3 file. */ + int totalframes; /* total number of frames in mp3 file */ + + /* this data is not currently computed by the mpglib routines */ + int framenum; /* frames decoded counter */ +} mp3data_struct; + + +/* required call to initialize decoder */ +int CDECL lame_decode_init(void); + +/********************************************************************* + * input 1 mp3 frame, output (maybe) pcm data. + * lame_decode() return code: + * -1: error + * 0: need more data + * n>0: size of pcm output + *********************************************************************/ +int CDECL lame_decode( + unsigned char * mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); + +/* same as lame_decode, and also returns mp3 header data */ +int CDECL lame_decode_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); + +/* same as lame_decode, but returns at most one frame */ +int CDECL lame_decode1( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); + +/* same as lame_decode1, but returns at most one frame and mp3 header data */ +int CDECL lame_decode1_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); + +/* same as lame_decode1_headers, but also returns enc_delay and enc_padding + from VBR Info tag, (-1 if no info tag was found) */ +int CDECL lame_decode1_headersB( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data, + int *enc_delay, + int *enc_padding ); + + + + + +/********************************************************************* + * + * id3tag stuff + * + *********************************************************************/ + +/* + * id3tag.h -- Interface to write ID3 version 1 and 2 tags. + * + * Copyright (C) 2000 Don Melton. + * + * 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. + */ + +/* utility to obtain alphabetically sorted list of genre names with numbers */ +extern void id3tag_genre_list( + void (*handler)(int, const char *, void *), + void* cookie); + +extern void id3tag_init (lame_global_flags *gfp); + +/* force addition of version 2 tag */ +extern void id3tag_add_v2 (lame_global_flags *gfp); + +/* add only a version 1 tag */ +extern void id3tag_v1_only (lame_global_flags *gfp); + +/* add only a version 2 tag */ +extern void id3tag_v2_only (lame_global_flags *gfp); + +/* pad version 1 tag with spaces instead of nulls */ +extern void id3tag_space_v1 (lame_global_flags *gfp); + +/* pad version 2 tag with extra 128 bytes */ +extern void id3tag_pad_v2 (lame_global_flags *gfp); + +extern void id3tag_set_title( + lame_global_flags* gfp, + const char* title ); +extern void id3tag_set_artist( + lame_global_flags* gfp, + const char* artist ); +extern void id3tag_set_album( + lame_global_flags* gfp, + const char* album ); +extern void id3tag_set_year( + lame_global_flags* gfp, + const char* year ); +extern void id3tag_set_comment( + lame_global_flags* gfp, + const char* comment ); +extern void id3tag_set_track( + lame_global_flags* gfp, + const char* track ); + +/* return non-zero result if genre name or number is invalid */ +extern int id3tag_set_genre( + lame_global_flags* gfp, + const char* genre ); + +/*********************************************************************** +* +* list of valid bitrates [kbps] & sample frequencies [Hz]. +* first index: 0: MPEG-2 values (sample frequencies 16...24 kHz) +* 1: MPEG-1 values (sample frequencies 32...48 kHz) +* 2: MPEG-2.5 values (sample frequencies 8...12 kHz) +***********************************************************************/ +extern const int bitrate_table [3] [16]; +extern const int samplerate_table [3] [ 4]; + + + +/* maximum size of mp3buffer needed if you encode at most 1152 samples for + each call to lame_encode_buffer. see lame_encode_buffer() below + (LAME_MAXMP3BUFFER is now obsolete) */ +#define LAME_MAXMP3BUFFER 16384 + + +#if defined(__cplusplus) +} +#endif +#endif /* LAME_LAME_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/machine.h swftools-0.9.1/lib/lame/machine.h --- swftools-0.9.2+ds1/lib/lame/machine.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/machine.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,163 @@ +/* + * Machine dependent defines/includes for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * 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 LAME_MACHINE_H +#define LAME_MACHINE_H + +#include + +#ifdef STDC_HEADERS +# include +# include +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr (), *strrchr (); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#if defined(__riscos__) && defined(FPA10) +# include "ymath.h" +#else +# include +#endif + +#include + +#ifdef HAVE_ERRNO_H +# include +#endif +#ifdef HAVE_FCNTL_H +# include +#endif + +#if defined(macintosh) +# include +# include +#else +# include +# include +#endif + +/* + * 3 different types of pow() functions: + * - table lookup + * - pow() + * - exp() on some machines this is claimed to be faster than pow() + */ + +#define POW20(x) pow20[x] +//#define POW20(x) pow(2.0,((double)(x)-210)*.25) +//#define POW20(x) exp( ((double)(x)-210)*(.25*LOG2) ) + +#define IPOW20(x) ipow20[x] +//#define IPOW20(x) exp( -((double)(x)-210)*.1875*LOG2 ) +//#define IPOW20(x) pow(2.0,-((double)(x)-210)*.1875) + +#define IIPOW20_(x) iipow20_[x] + +/* in case this is used without configure */ +#ifndef inline +# define inline +#endif +/* compatibility */ +#define INLINE inline + +#if defined(_MSC_VER) +# undef inline +# define inline _inline +#elif defined(__SASC) || defined(__GNUC__) || defined(__ICC) || defined(__ECC) +/* if __GNUC__ we always want to inline, not only if the user requests it */ +# undef inline +# define inline __inline +#endif + +#if defined(_MSC_VER) +# pragma warning( disable : 4244 ) +//# pragma warning( disable : 4305 ) +#endif + +/* + * FLOAT for variables which require at least 32 bits + * FLOAT8 for variables which require at least 64 bits + * + * On some machines, 64 bit will be faster than 32 bit. Also, some math + * routines require 64 bit float, so setting FLOAT=float will result in a + * lot of conversions. + */ + +#if ( defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) ) +# define WIN32_LEAN_AND_MEAN +# include +#else +# ifndef FLOAT +typedef float FLOAT; +# ifdef FLT_MAX +# define FLOAT_MAX FLT_MAX +# else +# define FLOAT_MAX 1e99 /* approx */ +# endif +# endif +#endif + +#ifndef FLOAT8 /* NOTE: RH: 7/00: if FLOAT8=float, it breaks resampling and VBR code */ +typedef double FLOAT8; +# ifdef DBL_MAX +# define FLOAT8_MAX DBL_MAX +# else +# define FLOAT8_MAX 1e99 /* approx */ +# endif +#else +# ifdef FLT_MAX +# define FLOAT8_MAX FLT_MAX +# else +# define FLOAT8_MAX 1e99 /* approx */ +# endif +#endif + +/* Various integer types */ + +#if defined _WIN32 && !defined __CYGWIN__ +typedef unsigned char u_char; +#elif defined __DECALPHA__ +// do nothing +#elif defined OS_AMIGAOS +// do nothing +#elif defined __DJGPP__ +typedef unsigned char u_char; +#elif !defined __GNUC__ || defined __STRICT_ANSI__ +typedef unsigned char u_char; +#else +// do nothing +#endif + +/* sample_t must be floating point, at least 32 bits */ +typedef FLOAT sample_t; +typedef sample_t stereo_t [2]; + +#endif + +/* end of machine.h */ diff -Nru swftools-0.9.2+ds1/lib/lame/Makefile.in swftools-0.9.1/lib/lame/Makefile.in --- swftools-0.9.2+ds1/lib/lame/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/Makefile.in 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,49 @@ +top_builddir = ../.. +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +include ../../Makefile.common + +lame_objects = psymodel.$(O) fft.$(O) newmdct.$(O) quantize.$(O) takehiro.$(O) reservoir.$(O) quantize_pvt.$(O) vbrquantize.$(O) encoder.$(O) id3tag.$(O) version.$(O) tables.$(O) util.$(O) bitstream.$(O) set_get.$(O) VbrTag.$(O) lame.$(O) + +all: $(lame_objects) + +psymodel.$(O): psymodel.c + $(C) psymodel.c -o $@ +fft.$(O): fft.c + $(C) fft.c -o $@ +newmdct.$(O): newmdct.c + $(C) newmdct.c -o $@ +quantize.$(O): quantize.c + $(C) quantize.c -o $@ +takehiro.$(O): takehiro.c + $(C) takehiro.c -o $@ +reservoir.$(O): reservoir.c + $(C) reservoir.c -o $@ +quantize_pvt.$(O): quantize_pvt.c + $(C) quantize_pvt.c -o $@ +vbrquantize.$(O): vbrquantize.c + $(C) vbrquantize.c -o $@ +encoder.$(O): encoder.c + $(C) encoder.c -o $@ +id3tag.$(O): id3tag.c + $(C) id3tag.c -o $@ +version.$(O): version.c + $(C) version.c -o $@ +tables.$(O): tables.c + $(C) tables.c -o $@ +util.$(O): util.c + $(C) util.c -o $@ +bitstream.$(O): bitstream.c + $(C) bitstream.c -o $@ +set_get.$(O): set_get.c + $(C) set_get.c -o $@ +VbrTag.$(O): VbrTag.c + $(C) VbrTag.c -o $@ +lame.$(O): lame.c + $(C) lame.c -o $@ + +install: +uninstall: +clean: + rm -f *.o *.obj *.lo *.a *.lib *.la gmon.out + diff -Nru swftools-0.9.2+ds1/lib/lame/newmdct.c swftools-0.9.1/lib/lame/newmdct.c --- swftools-0.9.2+ds1/lib/lame/newmdct.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/newmdct.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,791 @@ +/* + * MP3 window subband -> subband filtering -> mdct routine + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * + * 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. + */ + +/* + * Special Thanks to Patrick De Smet for your advices. + */ + +/* $Id: newmdct.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#include "util.h" +#include "l3side.h" +#include "newmdct.h" + +#ifdef WITH_DMALLOC +#include +#endif + +#define SCALE (32768.0/ 2.384e-06) + +#ifndef USE_GOGO_SUBBAND +static const FLOAT8 enwindow[] = +{ + -4.77e-07*0.740951125354959/2.384e-06, 1.03951e-04*0.740951125354959/2.384e-06, 9.53674e-04*0.740951125354959/2.384e-06, 2.841473e-03*0.740951125354959/2.384e-06, + 3.5758972e-02*0.740951125354959/2.384e-06, 3.401756e-03*0.740951125354959/2.384e-06, 9.83715e-04*0.740951125354959/2.384e-06, 9.9182e-05*0.740951125354959/2.384e-06, /* 15*/ + 1.2398e-05*0.740951125354959/2.384e-06, 1.91212e-04*0.740951125354959/2.384e-06, 2.283096e-03*0.740951125354959/2.384e-06,1.6994476e-02*0.740951125354959/2.384e-06, + -1.8756866e-02*0.740951125354959/2.384e-06,-2.630711e-03*0.740951125354959/2.384e-06, -2.47478e-04*0.740951125354959/2.384e-06, -1.4782e-05*0.740951125354959/2.384e-06, + 9.063471690191471e-01, + 1.960342806591213e-01, + + + -4.77e-07*0.773010453362737/2.384e-06, 1.05858e-04*0.773010453362737/2.384e-06, 9.30786e-04*0.773010453362737/2.384e-06, 2.521515e-03*0.773010453362737/2.384e-06, + 3.5694122e-02*0.773010453362737/2.384e-06, 3.643036e-03*0.773010453362737/2.384e-06, 9.91821e-04*0.773010453362737/2.384e-06, 9.6321e-05*0.773010453362737/2.384e-06, /* 14*/ + 1.1444e-05*0.773010453362737/2.384e-06, 1.65462e-04*0.773010453362737/2.384e-06, 2.110004e-03*0.773010453362737/2.384e-06,1.6112804e-02*0.773010453362737/2.384e-06, + -1.9634247e-02*0.773010453362737/2.384e-06,-2.803326e-03*0.773010453362737/2.384e-06, -2.77042e-04*0.773010453362737/2.384e-06, -1.6689e-05*0.773010453362737/2.384e-06, + 8.206787908286602e-01, + 3.901806440322567e-01, + + + -4.77e-07*0.803207531480645/2.384e-06, 1.07288e-04*0.803207531480645/2.384e-06, 9.02653e-04*0.803207531480645/2.384e-06, 2.174854e-03*0.803207531480645/2.384e-06, + 3.5586357e-02*0.803207531480645/2.384e-06, 3.858566e-03*0.803207531480645/2.384e-06, 9.95159e-04*0.803207531480645/2.384e-06, 9.3460e-05*0.803207531480645/2.384e-06, /* 13*/ + 1.0014e-05*0.803207531480645/2.384e-06, 1.40190e-04*0.803207531480645/2.384e-06, 1.937389e-03*0.803207531480645/2.384e-06,1.5233517e-02*0.803207531480645/2.384e-06, + -2.0506859e-02*0.803207531480645/2.384e-06,-2.974033e-03*0.803207531480645/2.384e-06, -3.07560e-04*0.803207531480645/2.384e-06, -1.8120e-05*0.803207531480645/2.384e-06, + 7.416505462720353e-01, + 5.805693545089249e-01, + + + -4.77e-07*0.831469612302545/2.384e-06, 1.08242e-04*0.831469612302545/2.384e-06, 8.68797e-04*0.831469612302545/2.384e-06, 1.800537e-03*0.831469612302545/2.384e-06, + 3.5435200e-02*0.831469612302545/2.384e-06, 4.049301e-03*0.831469612302545/2.384e-06, 9.94205e-04*0.831469612302545/2.384e-06, 9.0599e-05*0.831469612302545/2.384e-06, /* 12*/ + 9.060e-06*0.831469612302545/2.384e-06, 1.16348e-04*0.831469612302545/2.384e-06, 1.766682e-03*0.831469612302545/2.384e-06,1.4358521e-02*0.831469612302545/2.384e-06, + -2.1372318e-02*0.831469612302545/2.384e-06, -3.14188e-03*0.831469612302545/2.384e-06, -3.39031e-04*0.831469612302545/2.384e-06, -1.9550e-05*0.831469612302545/2.384e-06, + 6.681786379192989e-01, + 7.653668647301797e-01, + + + -4.77e-07*0.857728610000272/2.384e-06, 1.08719e-04*0.857728610000272/2.384e-06, 8.29220e-04*0.857728610000272/2.384e-06, 1.399517e-03*0.857728610000272/2.384e-06, + 3.5242081e-02*0.857728610000272/2.384e-06, 4.215240e-03*0.857728610000272/2.384e-06, 9.89437e-04*0.857728610000272/2.384e-06, 8.7261e-05*0.857728610000272/2.384e-06, /* 11*/ + 8.106e-06*0.857728610000272/2.384e-06, 9.3937e-05*0.857728610000272/2.384e-06, 1.597881e-03*0.857728610000272/2.384e-06,1.3489246e-02*0.857728610000272/2.384e-06, + -2.2228718e-02*0.857728610000272/2.384e-06,-3.306866e-03*0.857728610000272/2.384e-06, -3.71456e-04*0.857728610000272/2.384e-06, -2.1458e-05*0.857728610000272/2.384e-06, + 5.993769336819237e-01, + 9.427934736519954e-01, + + + -4.77e-07*0.881921264348355/2.384e-06, 1.08719e-04*0.881921264348355/2.384e-06, 7.8392e-04*0.881921264348355/2.384e-06, 9.71317e-04*0.881921264348355/2.384e-06, + 3.5007000e-02*0.881921264348355/2.384e-06, 4.357815e-03*0.881921264348355/2.384e-06, 9.80854e-04*0.881921264348355/2.384e-06, 8.3923e-05*0.881921264348355/2.384e-06, /* 10*/ + 7.629e-06*0.881921264348355/2.384e-06, 7.2956e-05*0.881921264348355/2.384e-06, 1.432419e-03*0.881921264348355/2.384e-06,1.2627602e-02*0.881921264348355/2.384e-06, + -2.3074150e-02*0.881921264348355/2.384e-06,-3.467083e-03*0.881921264348355/2.384e-06, -4.04358e-04*0.881921264348355/2.384e-06, -2.3365e-05*0.881921264348355/2.384e-06, + 5.345111359507916e-01, + 1.111140466039205e+00, + + + -9.54e-07*0.903989293123443/2.384e-06, 1.08242e-04*0.903989293123443/2.384e-06, 7.31945e-04*0.903989293123443/2.384e-06, 5.15938e-04*0.903989293123443/2.384e-06, + 3.4730434e-02*0.903989293123443/2.384e-06, 4.477024e-03*0.903989293123443/2.384e-06, 9.68933e-04*0.903989293123443/2.384e-06, 8.0585e-05*0.903989293123443/2.384e-06, /* 9*/ + 6.676e-06*0.903989293123443/2.384e-06, 5.2929e-05*0.903989293123443/2.384e-06, 1.269817e-03*0.903989293123443/2.384e-06,1.1775017e-02*0.903989293123443/2.384e-06, + -2.3907185e-02*0.903989293123443/2.384e-06,-3.622532e-03*0.903989293123443/2.384e-06, -4.38213e-04*0.903989293123443/2.384e-06, -2.5272e-05*0.903989293123443/2.384e-06, + 4.729647758913199e-01, + 1.268786568327291e+00, + + + -9.54e-07*0.92387953251128675613/2.384e-06, 1.06812e-04*0.92387953251128675613/2.384e-06, 6.74248e-04*0.92387953251128675613/2.384e-06, 3.3379e-05*0.92387953251128675613/2.384e-06, + 3.4412861e-02*0.92387953251128675613/2.384e-06, 4.573822e-03*0.92387953251128675613/2.384e-06, 9.54151e-04*0.92387953251128675613/2.384e-06, 7.6771e-05*0.92387953251128675613/2.384e-06, + 6.199e-06*0.92387953251128675613/2.384e-06, 3.4332e-05*0.92387953251128675613/2.384e-06, 1.111031e-03*0.92387953251128675613/2.384e-06,1.0933399e-02*0.92387953251128675613/2.384e-06, + -2.4725437e-02*0.92387953251128675613/2.384e-06,-3.771782e-03*0.92387953251128675613/2.384e-06, -4.72546e-04*0.92387953251128675613/2.384e-06, -2.7657e-05*0.92387953251128675613/2.384e-06, + 4.1421356237309504879e-01, /* tan(PI/8) */ + 1.414213562373095e+00, + + + -9.54e-07*0.941544065183021/2.384e-06, 1.05381e-04*0.941544065183021/2.384e-06, 6.10352e-04*0.941544065183021/2.384e-06, -4.75883e-04*0.941544065183021/2.384e-06, + 3.4055710e-02*0.941544065183021/2.384e-06, 4.649162e-03*0.941544065183021/2.384e-06, 9.35555e-04*0.941544065183021/2.384e-06, 7.3433e-05*0.941544065183021/2.384e-06, /* 7*/ + 5.245e-06*0.941544065183021/2.384e-06, 1.7166e-05*0.941544065183021/2.384e-06, 9.56535e-04*0.941544065183021/2.384e-06,1.0103703e-02*0.941544065183021/2.384e-06, + -2.5527000e-02*0.941544065183021/2.384e-06,-3.914356e-03*0.941544065183021/2.384e-06, -5.07355e-04*0.941544065183021/2.384e-06, -3.0041e-05*0.941544065183021/2.384e-06, + 3.578057213145241e-01, + 1.546020906725474e+00, + + + -9.54e-07*0.956940335732209/2.384e-06, 1.02520e-04*0.956940335732209/2.384e-06, 5.39303e-04*0.956940335732209/2.384e-06,-1.011848e-03*0.956940335732209/2.384e-06, + 3.3659935e-02*0.956940335732209/2.384e-06, 4.703045e-03*0.956940335732209/2.384e-06, 9.15051e-04*0.956940335732209/2.384e-06, 7.0095e-05*0.956940335732209/2.384e-06, /* 6*/ + 4.768e-06*0.956940335732209/2.384e-06, 9.54e-07*0.956940335732209/2.384e-06, 8.06808e-04*0.956940335732209/2.384e-06, 9.287834e-03*0.956940335732209/2.384e-06, + -2.6310921e-02*0.956940335732209/2.384e-06,-4.048824e-03*0.956940335732209/2.384e-06, -5.42164e-04*0.956940335732209/2.384e-06, -3.2425e-05*0.956940335732209/2.384e-06, + 3.033466836073424e-01, + 1.662939224605090e+00, + + + -1.431e-06*0.970031253194544/2.384e-06, 9.9182e-05*0.970031253194544/2.384e-06, 4.62532e-04*0.970031253194544/2.384e-06,-1.573563e-03*0.970031253194544/2.384e-06, + 3.3225536e-02*0.970031253194544/2.384e-06, 4.737377e-03*0.970031253194544/2.384e-06, 8.91685e-04*0.970031253194544/2.384e-06, 6.6280e-05*0.970031253194544/2.384e-06, /* 5*/ + 4.292e-06*0.970031253194544/2.384e-06, -1.3828e-05*0.970031253194544/2.384e-06, 6.61850e-04*0.970031253194544/2.384e-06, 8.487225e-03*0.970031253194544/2.384e-06, + -2.7073860e-02*0.970031253194544/2.384e-06,-4.174709e-03*0.970031253194544/2.384e-06, -5.76973e-04*0.970031253194544/2.384e-06, -3.4809e-05*0.970031253194544/2.384e-06, + 2.504869601913055e-01, + 1.763842528696710e+00, + + + -1.431e-06*0.98078528040323/2.384e-06, 9.5367e-05*0.98078528040323/2.384e-06, 3.78609e-04*0.98078528040323/2.384e-06,-2.161503e-03*0.98078528040323/2.384e-06, + 3.2754898e-02*0.98078528040323/2.384e-06, 4.752159e-03*0.98078528040323/2.384e-06, 8.66413e-04*0.98078528040323/2.384e-06, 6.2943e-05*0.98078528040323/2.384e-06, /* 4*/ + 3.815e-06*0.98078528040323/2.384e-06, -2.718e-05*0.98078528040323/2.384e-06, 5.22137e-04*0.98078528040323/2.384e-06, 7.703304e-03*0.98078528040323/2.384e-06, + -2.7815342e-02*0.98078528040323/2.384e-06,-4.290581e-03*0.98078528040323/2.384e-06, -6.11782e-04*0.98078528040323/2.384e-06, -3.7670e-05*0.98078528040323/2.384e-06, + 1.989123673796580e-01, + 1.847759065022573e+00, + + + -1.907e-06*0.989176509964781/2.384e-06, 9.0122e-05*0.989176509964781/2.384e-06, 2.88486e-04*0.989176509964781/2.384e-06,-2.774239e-03*0.989176509964781/2.384e-06, + 3.2248020e-02*0.989176509964781/2.384e-06, 4.748821e-03*0.989176509964781/2.384e-06, 8.38757e-04*0.989176509964781/2.384e-06, 5.9605e-05*0.989176509964781/2.384e-06, /* 3*/ + 3.338e-06*0.989176509964781/2.384e-06, -3.9577e-05*0.989176509964781/2.384e-06, 3.88145e-04*0.989176509964781/2.384e-06, 6.937027e-03*0.989176509964781/2.384e-06, + -2.8532982e-02*0.989176509964781/2.384e-06,-4.395962e-03*0.989176509964781/2.384e-06, -6.46591e-04*0.989176509964781/2.384e-06, -4.0531e-05*0.989176509964781/2.384e-06, + 1.483359875383474e-01, + 1.913880671464418e+00, + + + -1.907e-06*0.995184726672197/2.384e-06, 8.4400e-05*0.995184726672197/2.384e-06, 1.91689e-04*0.995184726672197/2.384e-06,-3.411293e-03*0.995184726672197/2.384e-06, + 3.1706810e-02*0.995184726672197/2.384e-06, 4.728317e-03*0.995184726672197/2.384e-06, 8.09669e-04*0.995184726672197/2.384e-06, 5.579e-05*0.995184726672197/2.384e-06, + 3.338e-06*0.995184726672197/2.384e-06, -5.0545e-05*0.995184726672197/2.384e-06, 2.59876e-04*0.995184726672197/2.384e-06, 6.189346e-03*0.995184726672197/2.384e-06, + -2.9224873e-02*0.995184726672197/2.384e-06,-4.489899e-03*0.995184726672197/2.384e-06, -6.80923e-04*0.995184726672197/2.384e-06, -4.3392e-05*0.995184726672197/2.384e-06, + 9.849140335716425e-02, + 1.961570560806461e+00, + + + -2.384e-06*0.998795456205172/2.384e-06, 7.7724e-05*0.998795456205172/2.384e-06, 8.8215e-05*0.998795456205172/2.384e-06,-4.072189e-03*0.998795456205172/2.384e-06, + 3.1132698e-02*0.998795456205172/2.384e-06, 4.691124e-03*0.998795456205172/2.384e-06, 7.79152e-04*0.998795456205172/2.384e-06, 5.2929e-05*0.998795456205172/2.384e-06, + 2.861e-06*0.998795456205172/2.384e-06, -6.0558e-05*0.998795456205172/2.384e-06, 1.37329e-04*0.998795456205172/2.384e-06, 5.462170e-03*0.998795456205172/2.384e-06, + -2.9890060e-02*0.998795456205172/2.384e-06,-4.570484e-03*0.998795456205172/2.384e-06, -7.14302e-04*0.998795456205172/2.384e-06, -4.6253e-05*0.998795456205172/2.384e-06, + 4.912684976946725e-02, + 1.990369453344394e+00, + + + 3.5780907e-02 * SQRT2*0.5/2.384e-06,1.7876148e-02 * SQRT2*0.5/2.384e-06, 3.134727e-03 * SQRT2*0.5/2.384e-06, 2.457142e-03 * SQRT2*0.5/2.384e-06, + 9.71317e-04 * SQRT2*0.5/2.384e-06, 2.18868e-04 * SQRT2*0.5/2.384e-06, 1.01566e-04 * SQRT2*0.5/2.384e-06, 1.3828e-05 * SQRT2*0.5/2.384e-06, + + 3.0526638e-02/2.384e-06, 4.638195e-03/2.384e-06, 7.47204e-04/2.384e-06, 4.9591e-05/2.384e-06, + 4.756451e-03/2.384e-06, 2.1458e-05/2.384e-06, -6.9618e-05/2.384e-06,/* 2.384e-06/2.384e-06*/ +}; +#endif + + +#define NS 12 +#define NL 36 + +static const FLOAT8 win[4][NL] = { + { + 2.382191739347913e-13, + 6.423305872147834e-13, + 9.400849094049688e-13, + 1.122435026096556e-12, + 1.183840321267481e-12, + 1.122435026096556e-12, + 9.400849094049690e-13, + 6.423305872147839e-13, + 2.382191739347918e-13, + + 5.456116108943412e-12, + 4.878985199565852e-12, + 4.240448995017367e-12, + 3.559909094758252e-12, + 2.858043359288075e-12, + 2.156177623817898e-12, + 1.475637723558783e-12, + 8.371015190102974e-13, + 2.599706096327376e-13, + + -5.456116108943412e-12, + -4.878985199565852e-12, + -4.240448995017367e-12, + -3.559909094758252e-12, + -2.858043359288076e-12, + -2.156177623817898e-12, + -1.475637723558783e-12, + -8.371015190102975e-13, + -2.599706096327376e-13, + + -2.382191739347923e-13, + -6.423305872147843e-13, + -9.400849094049696e-13, + -1.122435026096556e-12, + -1.183840321267481e-12, + -1.122435026096556e-12, + -9.400849094049694e-13, + -6.423305872147840e-13, + -2.382191739347918e-13, + }, + { + 2.382191739347913e-13, + 6.423305872147834e-13, + 9.400849094049688e-13, + 1.122435026096556e-12, + 1.183840321267481e-12, + 1.122435026096556e-12, + 9.400849094049688e-13, + 6.423305872147841e-13, + 2.382191739347918e-13, + + 5.456116108943413e-12, + 4.878985199565852e-12, + 4.240448995017367e-12, + 3.559909094758253e-12, + 2.858043359288075e-12, + 2.156177623817898e-12, + 1.475637723558782e-12, + 8.371015190102975e-13, + 2.599706096327376e-13, + + -5.461314069809755e-12, + -4.921085770524055e-12, + -4.343405037091838e-12, + -3.732668368707687e-12, + -3.093523840190885e-12, + -2.430835727329465e-12, + -1.734679010007751e-12, + -9.748253656609281e-13, + -2.797435120168326e-13, + + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + -2.283748241799531e-13, + -4.037858874020686e-13, + -2.146547464825323e-13, + }, + { + 1.316524975873958e-01, /* win[SHORT_TYPE] */ + 4.142135623730950e-01, + 7.673269879789602e-01, + + 1.091308501069271e+00, /* tantab_l */ + 1.303225372841206e+00, + 1.569685577117490e+00, + 1.920982126971166e+00, + 2.414213562373094e+00, + 3.171594802363212e+00, + 4.510708503662055e+00, + 7.595754112725146e+00, + 2.290376554843115e+01, + + 0.98480775301220802032, /* cx */ + 0.64278760968653936292, + 0.34202014332566882393, + 0.93969262078590842791, + -0.17364817766693030343, + -0.76604444311897790243, + 0.86602540378443870761, + 0.500000000000000e+00, + + -5.144957554275265e-01, /* ca */ + -4.717319685649723e-01, + -3.133774542039019e-01, + -1.819131996109812e-01, + -9.457419252642064e-02, + -4.096558288530405e-02, + -1.419856857247115e-02, + -3.699974673760037e-03, + + 8.574929257125442e-01, /* cs */ + 8.817419973177052e-01, + 9.496286491027329e-01, + 9.833145924917901e-01, + 9.955178160675857e-01, + 9.991605581781475e-01, + 9.998991952444470e-01, + 9.999931550702802e-01, + }, + { + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 2.283748241799531e-13, + 4.037858874020686e-13, + 2.146547464825323e-13, + + 5.461314069809755e-12, + 4.921085770524055e-12, + 4.343405037091838e-12, + 3.732668368707687e-12, + 3.093523840190885e-12, + 2.430835727329466e-12, + 1.734679010007751e-12, + 9.748253656609281e-13, + 2.797435120168326e-13, + + -5.456116108943413e-12, + -4.878985199565852e-12, + -4.240448995017367e-12, + -3.559909094758253e-12, + -2.858043359288075e-12, + -2.156177623817898e-12, + -1.475637723558782e-12, + -8.371015190102975e-13, + -2.599706096327376e-13, + + -2.382191739347913e-13, + -6.423305872147834e-13, + -9.400849094049688e-13, + -1.122435026096556e-12, + -1.183840321267481e-12, + -1.122435026096556e-12, + -9.400849094049688e-13, + -6.423305872147841e-13, + -2.382191739347918e-13, + } +}; + +#define tantab_l (win[SHORT_TYPE]+3) +#define cx (win[SHORT_TYPE]+12) +#define ca (win[SHORT_TYPE]+20) +#define cs (win[SHORT_TYPE]+28) + +/************************************************************************ +* +* window_subband() +* +* PURPOSE: Overlapping window on PCM samples +* +* SEMANTICS: +* 32 16-bit pcm samples are scaled to fractional 2's complement and +* concatenated to the end of the window buffer #x#. The updated window +* buffer #x# is then windowed by the analysis window #c# to produce the +* windowed sample #z# +* +************************************************************************/ + +/* + * new IDCT routine written by Takehiro TOMINAGA + */ +static const int order[] = { + 0, 1,16,17, 8, 9,24,25, 4, 5,20,21,12,13,28,29, + 2, 3,18,19,10,11,26,27, 6, 7,22,23,14,15,30,31 +}; + + +/* returns sum_j=0^31 a[j]*cos(PI*j*(k+1/2)/32), 0<=k<32 */ +INLINE static void +window_subband(const sample_t *x1, FLOAT8 a[SBLIMIT]) +{ + int i; + FLOAT8 const *wp = enwindow+10; + + const sample_t *x2 = &x1[238-14-286]; + + for (i = -15; i < 0; i++) { + FLOAT8 w, s, t; + + w = wp[-10]; s = x2[-224] * w; t = x1[ 224] * w; + w = wp[-9]; s += x2[-160] * w; t += x1[ 160] * w; + w = wp[-8]; s += x2[- 96] * w; t += x1[ 96] * w; + w = wp[-7]; s += x2[- 32] * w; t += x1[ 32] * w; + w = wp[-6]; s += x2[ 32] * w; t += x1[- 32] * w; + w = wp[-5]; s += x2[ 96] * w; t += x1[- 96] * w; + w = wp[-4]; s += x2[ 160] * w; t += x1[-160] * w; + w = wp[-3]; s += x2[ 224] * w; t += x1[-224] * w; + + w = wp[-2]; s += x1[-256] * w; t -= x2[ 256] * w; + w = wp[-1]; s += x1[-192] * w; t -= x2[ 192] * w; + w = wp[ 0]; s += x1[-128] * w; t -= x2[ 128] * w; + w = wp[ 1]; s += x1[- 64] * w; t -= x2[ 64] * w; + w = wp[ 2]; s += x1[ 0] * w; t -= x2[ 0] * w; + w = wp[ 3]; s += x1[ 64] * w; t -= x2[- 64] * w; + w = wp[ 4]; s += x1[ 128] * w; t -= x2[-128] * w; + w = wp[ 5]; s += x1[ 192] * w; t -= x2[-192] * w; + + /* + * this multiplyer could be removed, but it needs more 256 FLOAT data. + * thinking about the data cache performance, I think we should not + * use such a huge table. tt 2000/Oct/25 + */ + s *= wp[6]; + w = t - s; + a[30+i*2] = t + s; + a[31+i*2] = wp[7] * w; + wp += 18; + x1--; + x2++; + } + { + FLOAT8 s,t,u,v; + t = x1[- 16] * wp[-10]; s = x1[ -32] * wp[-2]; + t += (x1[- 48] - x1[ 16]) * wp[-9]; s += x1[ -96] * wp[-1]; + t += (x1[- 80] + x1[ 48]) * wp[-8]; s += x1[-160] * wp[ 0]; + t += (x1[-112] - x1[ 80]) * wp[-7]; s += x1[-224] * wp[ 1]; + t += (x1[-144] + x1[112]) * wp[-6]; s -= x1[ 32] * wp[ 2]; + t += (x1[-176] - x1[144]) * wp[-5]; s -= x1[ 96] * wp[ 3]; + t += (x1[-208] + x1[176]) * wp[-4]; s -= x1[ 160] * wp[ 4]; + t += (x1[-240] - x1[208]) * wp[-3]; s -= x1[ 224]; + + u = s - t; + v = s + t; + + t = a[14]; + s = a[15] - t; + + a[31] = v + t; // A0 + a[30] = u + s; // A1 + a[15] = u - s; // A2 + a[14] = v - t; // A3 + } +{ + FLOAT8 xr; + xr = a[28] - a[ 0]; a[ 0] += a[28]; a[28] = xr * wp[-2*18+7]; + xr = a[29] - a[ 1]; a[ 1] += a[29]; a[29] = xr * wp[-2*18+7]; + + xr = a[26] - a[ 2]; a[ 2] += a[26]; a[26] = xr * wp[-4*18+7]; + xr = a[27] - a[ 3]; a[ 3] += a[27]; a[27] = xr * wp[-4*18+7]; + + xr = a[24] - a[ 4]; a[ 4] += a[24]; a[24] = xr * wp[-6*18+7]; + xr = a[25] - a[ 5]; a[ 5] += a[25]; a[25] = xr * wp[-6*18+7]; + + xr = a[22] - a[ 6]; a[ 6] += a[22]; a[22] = xr * SQRT2; + xr = a[23] - a[ 7]; a[ 7] += a[23]; a[23] = xr * SQRT2 - a[ 7]; + a[ 7] -= a[ 6]; + a[22] -= a[ 7]; + a[23] -= a[22]; + + xr = a[ 6]; a[ 6] = a[31] - xr; a[31] = a[31] + xr; + xr = a[ 7]; a[ 7] = a[30] - xr; a[30] = a[30] + xr; + xr = a[22]; a[22] = a[15] - xr; a[15] = a[15] + xr; + xr = a[23]; a[23] = a[14] - xr; a[14] = a[14] + xr; + + xr = a[20] - a[ 8]; a[ 8] += a[20]; a[20] = xr * wp[-10*18+7]; + xr = a[21] - a[ 9]; a[ 9] += a[21]; a[21] = xr * wp[-10*18+7]; + + xr = a[18] - a[10]; a[10] += a[18]; a[18] = xr * wp[-12*18+7]; + xr = a[19] - a[11]; a[11] += a[19]; a[19] = xr * wp[-12*18+7]; + + xr = a[16] - a[12]; a[12] += a[16]; a[16] = xr * wp[-14*18+7]; + xr = a[17] - a[13]; a[13] += a[17]; a[17] = xr * wp[-14*18+7]; + + xr = -a[20] + a[24]; a[20] += a[24]; a[24] = xr * wp[-12*18+7]; + xr = -a[21] + a[25]; a[21] += a[25]; a[25] = xr * wp[-12*18+7]; + + xr = a[ 4] - a[ 8]; a[ 4] += a[ 8]; a[ 8] = xr * wp[-12*18+7]; + xr = a[ 5] - a[ 9]; a[ 5] += a[ 9]; a[ 9] = xr * wp[-12*18+7]; + + xr = a[ 0] - a[12]; a[ 0] += a[12]; a[12] = xr * wp[-4*18+7]; + xr = a[ 1] - a[13]; a[ 1] += a[13]; a[13] = xr * wp[-4*18+7]; + xr = a[16] - a[28]; a[16] += a[28]; a[28] = xr * wp[-4*18+7]; + xr = -a[17] + a[29]; a[17] += a[29]; a[29] = xr * wp[-4*18+7]; + + xr = SQRT2 * (a[ 2] - a[10]); a[ 2] += a[10]; a[10] = xr; + xr = SQRT2 * (a[ 3] - a[11]); a[ 3] += a[11]; a[11] = xr; + xr = SQRT2 * (-a[18] + a[26]); a[18] += a[26]; a[26] = xr - a[18]; + xr = SQRT2 * (-a[19] + a[27]); a[19] += a[27]; a[27] = xr - a[19]; + + xr = a[ 2]; a[19] -= a[ 3]; a[ 3] -= xr; a[ 2] = a[31] - xr; a[31] += xr; + xr = a[ 3]; a[11] -= a[19]; a[18] -= xr; a[ 3] = a[30] - xr; a[30] += xr; + xr = a[18]; a[27] -= a[11]; a[19] -= xr; a[18] = a[15] - xr; a[15] += xr; + + xr = a[19]; a[10] -= xr; a[19] = a[14] - xr; a[14] += xr; + xr = a[10]; a[11] -= xr; a[10] = a[23] - xr; a[23] += xr; + xr = a[11]; a[26] -= xr; a[11] = a[22] - xr; a[22] += xr; + xr = a[26]; a[27] -= xr; a[26] = a[ 7] - xr; a[ 7] += xr; + + xr = a[27]; a[27] = a[ 6] - xr; a[ 6] += xr; + + xr = SQRT2 * (a[ 0] - a[ 4]); a[ 0] += a[ 4]; a[ 4] = xr; + xr = SQRT2 * (a[ 1] - a[ 5]); a[ 1] += a[ 5]; a[ 5] = xr; + xr = SQRT2 * (a[16] - a[20]); a[16] += a[20]; a[20] = xr; + xr = SQRT2 * (a[17] - a[21]); a[17] += a[21]; a[21] = xr; + + xr = -SQRT2 * (a[ 8] - a[12]); a[ 8] += a[12]; a[12] = xr - a[ 8]; + xr = -SQRT2 * (a[ 9] - a[13]); a[ 9] += a[13]; a[13] = xr - a[ 9]; + xr = -SQRT2 * (a[25] - a[29]); a[25] += a[29]; a[29] = xr - a[25]; + xr = -SQRT2 * (a[24] + a[28]); a[24] -= a[28]; a[28] = xr - a[24]; + + xr = a[24] - a[16]; a[24] = xr; + xr = a[20] - xr; a[20] = xr; + xr = a[28] - xr; a[28] = xr; + + xr = a[25] - a[17]; a[25] = xr; + xr = a[21] - xr; a[21] = xr; + xr = a[29] - xr; a[29] = xr; + + xr = a[17] - a[ 1]; a[17] = xr; + xr = a[ 9] - xr; a[ 9] = xr; + xr = a[25] - xr; a[25] = xr; + xr = a[ 5] - xr; a[ 5] = xr; + xr = a[21] - xr; a[21] = xr; + xr = a[13] - xr; a[13] = xr; + xr = a[29] - xr; a[29] = xr; + + xr = a[ 1] - a[ 0]; a[ 1] = xr; + xr = a[16] - xr; a[16] = xr; + xr = a[17] - xr; a[17] = xr; + xr = a[ 8] - xr; a[ 8] = xr; + xr = a[ 9] - xr; a[ 9] = xr; + xr = a[24] - xr; a[24] = xr; + xr = a[25] - xr; a[25] = xr; + xr = a[ 4] - xr; a[ 4] = xr; + xr = a[ 5] - xr; a[ 5] = xr; + xr = a[20] - xr; a[20] = xr; + xr = a[21] - xr; a[21] = xr; + xr = a[12] - xr; a[12] = xr; + xr = a[13] - xr; a[13] = xr; + xr = a[28] - xr; a[28] = xr; + xr = a[29] - xr; a[29] = xr; + + xr = a[ 0]; a[ 0] += a[31]; a[31] -= xr; + xr = a[ 1]; a[ 1] += a[30]; a[30] -= xr; + xr = a[16]; a[16] += a[15]; a[15] -= xr; + xr = a[17]; a[17] += a[14]; a[14] -= xr; + xr = a[ 8]; a[ 8] += a[23]; a[23] -= xr; + xr = a[ 9]; a[ 9] += a[22]; a[22] -= xr; + xr = a[24]; a[24] += a[ 7]; a[ 7] -= xr; + xr = a[25]; a[25] += a[ 6]; a[ 6] -= xr; + xr = a[ 4]; a[ 4] += a[27]; a[27] -= xr; + xr = a[ 5]; a[ 5] += a[26]; a[26] -= xr; + xr = a[20]; a[20] += a[11]; a[11] -= xr; + xr = a[21]; a[21] += a[10]; a[10] -= xr; + xr = a[12]; a[12] += a[19]; a[19] -= xr; + xr = a[13]; a[13] += a[18]; a[18] -= xr; + xr = a[28]; a[28] += a[ 3]; a[ 3] -= xr; + xr = a[29]; a[29] += a[ 2]; a[ 2] -= xr; +} + +} + + +/*-------------------------------------------------------------------*/ +/* */ +/* Function: Calculation of the MDCT */ +/* In the case of long blocks (type 0,1,3) there are */ +/* 36 coefficents in the time domain and 18 in the frequency */ +/* domain. */ +/* In the case of short blocks (type 2) there are 3 */ +/* transformations with short length. This leads to 12 coefficents */ +/* in the time and 6 in the frequency domain. In this case the */ +/* results are stored side by side in the vector out[]. */ +/* */ +/* New layer3 */ +/* */ +/*-------------------------------------------------------------------*/ + +inline static void mdct_short(FLOAT8 *inout) +{ + int l; + for ( l = 0; l < 3; l++ ) { + FLOAT8 tc0,tc1,tc2,ts0,ts1,ts2; + + ts0 = inout[2*3] * win[SHORT_TYPE][0] - inout[5*3]; + tc0 = inout[0*3] * win[SHORT_TYPE][2] - inout[3*3]; + tc1 = ts0 + tc0; + tc2 = ts0 - tc0; + + ts0 = inout[5*3] * win[SHORT_TYPE][0] + inout[2*3]; + tc0 = inout[3*3] * win[SHORT_TYPE][2] + inout[0*3]; + ts1 = ts0 + tc0; + ts2 = -ts0 + tc0; + + tc0 = (inout[1*3] * win[SHORT_TYPE][1] - inout[4*3]) * 2.069978111953089e-11; /* tritab_s[1] */ + ts0 = (inout[4*3] * win[SHORT_TYPE][1] + inout[1*3]) * 2.069978111953089e-11; /* tritab_s[1] */ + + inout[3*0] = tc1 * 1.907525191737280e-11 /* tritab_s[2] */ + tc0; + inout[3*5] = -ts1 * 1.907525191737280e-11 /* tritab_s[0] */ + ts0; + + tc2 = tc2 * 0.86602540378443870761 * 1.907525191737281e-11 /* tritab_s[2] */; + ts1 = ts1 * 0.5 * 1.907525191737281e-11 + ts0; + inout[3*1] = tc2-ts1; + inout[3*2] = tc2+ts1; + + tc1 = tc1 * 0.5 * 1.907525191737281e-11 - tc0; + ts2 = ts2 * 0.86602540378443870761 * 1.907525191737281e-11 /* tritab_s[0] */; + inout[3*3] = tc1+ts2; + inout[3*4] = tc1-ts2; + + inout++; + } +} + +inline static void mdct_long(FLOAT8 *out, FLOAT8 *in) +{ + FLOAT8 ct,st; + { + FLOAT8 tc1, tc2, tc3, tc4, ts5, ts6, ts7, ts8; + // 1,2, 5,6, 9,10, 13,14, 17 + tc1 = in[17]-in[ 9]; + tc3 = in[15]-in[11]; + tc4 = in[14]-in[12]; + ts5 = in[ 0]+in[ 8]; + ts6 = in[ 1]+in[ 7]; + ts7 = in[ 2]+in[ 6]; + ts8 = in[ 3]+in[ 5]; + + out[17] = (ts5+ts7-ts8)-(ts6-in[4]); + st = (ts5+ts7-ts8)*cx[7]+(ts6-in[4]); + ct = (tc1-tc3-tc4)*cx[6]; + out[5] = ct+st; + out[6] = ct-st; + + tc2 = (in[16]-in[10])*cx[6]; + ts6 = ts6*cx[7] + in[4]; + ct = tc1*cx[0] + tc2 + tc3*cx[1] + tc4*cx[2]; + st = -ts5*cx[4] + ts6 - ts7*cx[5] + ts8*cx[3]; + out[1] = ct+st; + out[2] = ct-st; + + ct = tc1*cx[1] - tc2 - tc3*cx[2] + tc4*cx[0]; + st = -ts5*cx[5] + ts6 - ts7*cx[3] + ts8*cx[4]; + out[ 9] = ct+st; + out[10] = ct-st; + + ct = tc1*cx[2] - tc2 + tc3*cx[0] - tc4*cx[1]; + st = ts5*cx[3] - ts6 + ts7*cx[4] - ts8*cx[5]; + out[13] = ct+st; + out[14] = ct-st; + } + { + FLOAT8 ts1, ts2, ts3, ts4, tc5, tc6, tc7, tc8; + + ts1 = in[ 8]-in[ 0]; + ts3 = in[ 6]-in[ 2]; + ts4 = in[ 5]-in[ 3]; + tc5 = in[17]+in[ 9]; + tc6 = in[16]+in[10]; + tc7 = in[15]+in[11]; + tc8 = in[14]+in[12]; + + out[0] = (tc5+tc7+tc8)+(tc6+in[13]); + ct = (tc5+tc7+tc8)*cx[7]-(tc6+in[13]); + st = (ts1-ts3+ts4)*cx[6]; + out[11] = ct+st; + out[12] = ct-st; + + ts2 = (in[7]-in[1])*cx[6]; + tc6 = in[13] - tc6*cx[7]; + ct = tc5*cx[3] - tc6 + tc7*cx[4] + tc8*cx[5]; + st = ts1*cx[2] + ts2 + ts3*cx[0] + ts4*cx[1]; + out[3] = ct+st; + out[4] = ct-st; + + ct = -tc5*cx[5] + tc6 - tc7*cx[3] - tc8*cx[4]; + st = ts1*cx[1] + ts2 - ts3*cx[2] - ts4*cx[0]; + out[7] = ct+st; + out[8] = ct-st; + + ct = -tc5*cx[4] + tc6 - tc7*cx[5] - tc8*cx[3]; + st = ts1*cx[0] - ts2 + ts3*cx[1] - ts4*cx[2]; + out[15] = ct+st; + out[16] = ct-st; + } +} + + +void mdct_sub48( lame_internal_flags *gfc, const sample_t *w0, const sample_t *w1, + FLOAT8 mdct_freq[2][2][576] ) +{ + int gr, k, ch; + const sample_t *wk; + + wk = w0 + 286; + /* thinking cache performance, ch->gr loop is better than gr->ch loop */ + for (ch = 0; ch < gfc->channels_out; ch++) { + for (gr = 0; gr < gfc->mode_gr; gr++) { + int band; + FLOAT8 *mdct_enc = &mdct_freq[gr][ch][0]; + gr_info *gi = &(gfc->l3_side.gr[gr].ch[ch].tt); + FLOAT8 *samp = gfc->sb_sample[ch][1 - gr][0]; + + for (k = 0; k < 18 / 2; k++) { + window_subband(wk, samp); + window_subband(wk + 32, samp + 32); + samp += 64; + wk += 64; + /* + * Compensate for inversion in the analysis filter + */ + for (band = 1; band < 32; band+=2) { + samp[band-32] *= -1; + } + } + + + /* apply filters on the polyphase filterbank outputs */ + /* bands <= gfc->highpass_band will be zeroed out below */ + /* bands >= gfc->lowpass_band will be zeroed out below */ + if (gfc->filter_type==0) { + for (band=gfc->highpass_start_band; band <= gfc->highpass_end_band; band++) { + for (k=0; k<18; k++) + gfc->sb_sample[ch][1-gr][k][order[band]]*=gfc->amp_highpass[band]; + } + for (band=gfc->lowpass_start_band; band <= gfc->lowpass_end_band; band++) { + for (k=0; k<18; k++) + gfc->sb_sample[ch][1-gr][k][order[band]]*=gfc->amp_lowpass[band]; + } + } + + + + /* + * Perform imdct of 18 previous subband samples + * + 18 current subband samples + */ + for (band = 0; band < 32; band++, mdct_enc += 18) { + int type = gi->block_type; + FLOAT8 *band0, *band1; + band0 = gfc->sb_sample[ch][ gr][0] + order[band]; + band1 = gfc->sb_sample[ch][1-gr][0] + order[band]; + if (gi->mixed_block_flag && band < 2) + type = 0; + if (band >= gfc->lowpass_band || band <= gfc->highpass_band) { + memset((char *)mdct_enc,0,18*sizeof(FLOAT8)); + } else { + if (type == SHORT_TYPE) { + for (k = -NS/4; k < 0; k++) { + FLOAT8 w = win[SHORT_TYPE][k+3]; + mdct_enc[k*3+ 9] = band0[( 9+k)*32] * w - band0[( 8-k)*32]; + mdct_enc[k*3+18] = band0[(14-k)*32] * w + band0[(15+k)*32]; + mdct_enc[k*3+10] = band0[(15+k)*32] * w - band0[(14-k)*32]; + mdct_enc[k*3+19] = band1[( 2-k)*32] * w + band1[( 3+k)*32]; + mdct_enc[k*3+11] = band1[( 3+k)*32] * w - band1[( 2-k)*32]; + mdct_enc[k*3+20] = band1[( 8-k)*32] * w + band1[( 9+k)*32]; + } + mdct_short(mdct_enc); + } else { + FLOAT8 work[18]; + for (k = -NL/4; k < 0; k++) { + FLOAT8 a, b; + a = win[type][k+27] * band1[(k+9)*32] + + win[type][k+36] * band1[(8-k)*32]; + b = win[type][k+ 9] * band0[(k+9)*32] + - win[type][k+18] * band0[(8-k)*32]; + work[k+ 9] = a - b*tantab_l[k+9]; + work[k+18] = a*tantab_l[k+9] + b; + } + + mdct_long(mdct_enc, work); + } + } + /* + * Perform aliasing reduction butterfly + */ + if (type != SHORT_TYPE) { + if (band == 0) + continue; + for (k = 7; k >= 0; --k) { + FLOAT8 bu,bd; + bu = mdct_enc[k] * ca[k] + mdct_enc[-1-k] * cs[k]; + bd = mdct_enc[k] * cs[k] - mdct_enc[-1-k] * ca[k]; + + mdct_enc[-1-k] = bu; + mdct_enc[k] = bd; + } + } + } + } + wk = w1 + 286; + if (gfc->mode_gr == 1) { + memcpy(gfc->sb_sample[ch][0], gfc->sb_sample[ch][1], 576 * sizeof(FLOAT8)); + } + } +} diff -Nru swftools-0.9.2+ds1/lib/lame/newmdct.h swftools-0.9.1/lib/lame/newmdct.h --- swftools-0.9.2+ds1/lib/lame/newmdct.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/newmdct.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,28 @@ +/* + * New Modified DCT include file + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * 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 LAME_NEWMDCT_H +#define LAME_NEWMDCT_H + +void mdct_sub48(lame_internal_flags *gfc,const sample_t *w0, const sample_t *w1, + FLOAT8 mdct_freq[2][2][576]); + +#endif /* LAME_NEWMDCT_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/psymodel.c swftools-0.9.1/lib/lame/psymodel.c --- swftools-0.9.2+ds1/lib/lame/psymodel.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/psymodel.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,2539 @@ +/* + * psymodel.c + * + * Copyright (c) 1999 Mark Taylor + * + * 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. + */ + +/* $Id: psymodel.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + + +/* +PSYCHO ACOUSTICS + + +This routine computes the psycho acoustics, delayed by +one granule. + +Input: buffer of PCM data (1024 samples). + +This window should be centered over the 576 sample granule window. +The routine will compute the psycho acoustics for +this granule, but return the psycho acoustics computed +for the *previous* granule. This is because the block +type of the previous granule can only be determined +after we have computed the psycho acoustics for the following +granule. + +Output: maskings and energies for each scalefactor band. +block type, PE, and some correlation measures. +The PE is used by CBR modes to determine if extra bits +from the bit reservoir should be used. The correlation +measures are used to determine mid/side or regular stereo. + + +Notation: + +barks: a non-linear frequency scale. Mapping from frequency to + barks is given by freq2bark() + +scalefactor bands: The spectrum (frequencies) are broken into + SBMAX "scalefactor bands". Thes bands + are determined by the MPEG ISO spec. In + the noise shaping/quantization code, we allocate + bits among the partition bands to achieve the + best possible quality + +partition bands: The spectrum is also broken into about + 64 "partition bands". Each partition + band is about .34 barks wide. There are about 2-5 + partition bands for each scalefactor band. + +LAME computes all psycho acoustic information for each partition +band. Then at the end of the computations, this information +is mapped to scalefactor bands. The energy in each scalefactor +band is taken as the sum of the energy in all partition bands +which overlap the scalefactor band. The maskings can be computed +in the same way (and thus represent the average masking in that band) +or by taking the minmum value multiplied by the number of +partition bands used (which represents a minimum masking in that band). + + +The general outline is as follows: + + +1. compute the energy in each partition band +2. compute the tonality in each partition band +3. compute the strength of each partion band "masker" +4. compute the masking (via the spreading function applied to each masker) +5. Modifications for mid/side masking. + +Each partition band is considiered a "masker". The strength +of the i'th masker in band j is given by: + + s3(bark(i)-bark(j))*strength(i) + +The strength of the masker is a function of the energy and tonality. +The more tonal, the less masking. LAME uses a simple linear formula +(controlled by NMT and TMN) which says the strength is given by the +energy divided by a linear function of the tonality. + + +s3() is the "spreading function". It is given by a formula +determined via listening tests. + +The total masking in the j'th partition band is the sum over +all maskings i. It is thus given by the convolution of +the strength with s3(), the "spreading function." + +masking(j) = sum_over_i s3(i-j)*strength(i) = s3 o strength + +where "o" = convolution operator. s3 is given by a formula determined +via listening tests. It is normalized so that s3 o 1 = 1. + +Note: instead of a simple convolution, LAME also has the +option of using "additive masking" + +The most critical part is step 2, computing the tonality of each +partition band. LAME has two tonality estimators. The first +is based on the ISO spec, and measures how predictiable the +signal is over time. The more predictable, the more tonal. +The second measure is based on looking at the spectrum of +a single granule. The more peaky the spectrum, the more +tonal. By most indications, the latter approach is better. + +Finally, in step 5, the maskings for the mid and side +channel are possibly increased. Under certain circumstances, +noise in the mid & side channels is assumed to also +be masked by strong maskers in the L or R channels. + + +Other data computed by the psy-model: + +ms_ratio side-channel / mid-channel masking ratio (for previous granule) +ms_ratio_next side-channel / mid-channel masking ratio for this granule + +percep_entropy[2] L and R values (prev granule) of PE - A measure of how + much pre-echo is in the previous granule +percep_entropy_MS[2] mid and side channel values (prev granule) of percep_entropy +energy[4] L,R,M,S energy in each channel, prev granule +blocktype_d[2] block type to use for previous granule + + +*/ + + + + +#include +#include "config_static.h" + +#include "util.h" +#include "encoder.h" +#include "psymodel.h" +#include "l3side.h" +#include +#include "tables.h" +#include "fft.h" + +#ifdef WITH_DMALLOC +#include +#endif + +#define NSFIRLEN 21 +#define rpelev 2 +#define rpelev2 16 +#define rpelev_s 2 +#define rpelev2_s 16 + +/* size of each partition band, in barks: */ +#define DELBARK .34 + + +#if 1 + /* AAC values, results in more masking over MP3 values */ +# define TMN 18 +# define NMT 6 +#else + /* MP3 values */ +# define TMN 29 +# define NMT 6 +#endif + +#define NBPSY_l (SBMAX_l) +#define NBPSY_s (SBMAX_s) + + +#ifdef M_LN10 +#define LN_TO_LOG10 (M_LN10/10) +#else +#define LN_TO_LOG10 0.2302585093 +#endif + +FLOAT +psycho_loudness_approx( FLOAT *energy, lame_global_flags *gfp ); + + + + + +/* + L3psycho_anal. Compute psycho acoustics. + + Data returned to the calling program must be delayed by one + granule. + + This is done in two places. + If we do not need to know the blocktype, the copying + can be done here at the top of the program: we copy the data for + the last granule (computed during the last call) before it is + overwritten with the new data. It looks like this: + + 0. static psymodel_data + 1. calling_program_data = psymodel_data + 2. compute psymodel_data + + For data which needs to know the blocktype, the copying must be + done at the end of this loop, and the old values must be saved: + + 0. static psymodel_data_old + 1. compute psymodel_data + 2. compute possible block type of this granule + 3. compute final block type of previous granule based on #2. + 4. calling_program_data = psymodel_data_old + 5. psymodel_data_old = psymodel_data +*/ +int L3psycho_anal( lame_global_flags * gfp, + const sample_t *buffer[2], int gr_out, + FLOAT8 *ms_ratio, + FLOAT8 *ms_ratio_next, + III_psy_ratio masking_ratio[2][2], + III_psy_ratio masking_MS_ratio[2][2], + FLOAT8 percep_entropy[2],FLOAT8 percep_MS_entropy[2], + FLOAT8 energy[4], + int blocktype_d[2]) +{ +/* to get a good cache performance, one has to think about + * the sequence, in which the variables are used. + * (Note: these static variables have been moved to the gfc-> struct, + * and their order in memory is layed out in util.h) + */ + lame_internal_flags *gfc=gfp->internal_flags; + + + /* fft and energy calculation */ + FLOAT (*wsamp_l)[BLKSIZE]; + FLOAT (*wsamp_s)[3][BLKSIZE_s]; + + /* convolution */ + FLOAT8 eb[CBANDS]; + FLOAT8 cb[CBANDS]; + FLOAT8 thr[CBANDS]; + + /* ratios */ + FLOAT8 ms_ratio_l=0,ms_ratio_s=0; + + /* block type */ + int blocktype[2],uselongblock[2]; + + /* usual variables like loop indices, etc.. */ + int numchn, chn; + int b, i, j, k; + int sb,sblock; + + + if(gfc->psymodel_init==0) { + psymodel_init(gfp); + init_fft(gfc); + gfc->psymodel_init=1; + + for (chn = 0; chn < 4; ++chn ) + for (b = 0; b < CBANDS; ++b ) + gfc->nb_s1[chn][b] = gfc->nb_s2[chn][b] = 1.0; + + } + + + + + + numchn = gfc->channels_out; + /* chn=2 and 3 = Mid and Side channels */ + if (gfp->mode == JOINT_STEREO) numchn=4; + + for (chn=0; chntot_ener[chn]; + } + } + + for (chn=0; chn pe [chn]; + masking_ratio [gr_out] [chn] .en = gfc -> en [chn]; + masking_ratio [gr_out] [chn] .thm = gfc -> thm [chn]; + } else { + /* MS maskings */ + percep_MS_entropy [chn-2] = gfc -> pe [chn]; + masking_MS_ratio [gr_out] [chn-2].en = gfc -> en [chn]; + masking_MS_ratio [gr_out] [chn-2].thm = gfc -> thm [chn]; + } + + + + /********************************************************************** + * compute FFTs + **********************************************************************/ + wsamp_s = gfc->wsamp_S+(chn & 1); + wsamp_l = gfc->wsamp_L+(chn & 1); + if (chn<2) { + fft_long ( gfc, *wsamp_l, chn, buffer); + fft_short( gfc, *wsamp_s, chn, buffer); + } + /* FFT data for mid and side channel is derived from L & R */ + if (chn == 2) + { + for (j = BLKSIZE-1; j >=0 ; --j) + { + FLOAT l = gfc->wsamp_L[0][j]; + FLOAT r = gfc->wsamp_L[1][j]; + gfc->wsamp_L[0][j] = (l+r)*(FLOAT)(SQRT2*0.5); + gfc->wsamp_L[1][j] = (l-r)*(FLOAT)(SQRT2*0.5); + } + for (b = 2; b >= 0; --b) + { + for (j = BLKSIZE_s-1; j >= 0 ; --j) + { + FLOAT l = gfc->wsamp_S[0][b][j]; + FLOAT r = gfc->wsamp_S[1][b][j]; + gfc->wsamp_S[0][b][j] = (l+r)*(FLOAT)(SQRT2*0.5); + gfc->wsamp_S[1][b][j] = (l-r)*(FLOAT)(SQRT2*0.5); + } + } + } + + + /********************************************************************** + * compute energies + **********************************************************************/ + + + + gfc->energy[0] = (*wsamp_l)[0]; + gfc->energy[0] *= gfc->energy[0]; + + gfc->tot_ener[chn] = gfc->energy[0]; /* sum total energy at nearly no extra cost */ + + for (j=BLKSIZE/2-1; j >= 0; --j) + { + FLOAT re = (*wsamp_l)[BLKSIZE/2-j]; + FLOAT im = (*wsamp_l)[BLKSIZE/2+j]; + gfc->energy[BLKSIZE/2-j] = (re * re + im * im) * (FLOAT)0.5; + + if (BLKSIZE/2-j > 10) + gfc->tot_ener[chn] += gfc->energy[BLKSIZE/2-j]; + } + for (b = 2; b >= 0; --b) + { + gfc->energy_s[b][0] = (*wsamp_s)[b][0]; + gfc->energy_s[b][0] *= gfc->energy_s [b][0]; + for (j=BLKSIZE_s/2-1; j >= 0; --j) + { + FLOAT re = (*wsamp_s)[b][BLKSIZE_s/2-j]; + FLOAT im = (*wsamp_s)[b][BLKSIZE_s/2+j]; + gfc->energy_s[b][BLKSIZE_s/2-j] = (re * re + im * im) * (FLOAT)0.5; + } + } + +#if defined(HAVE_GTK) + if (gfp->analysis) { + for (j=0; jpinfo->energy[gr_out][chn][j]=gfc->energy_save[chn][j]; + gfc->energy_save[chn][j]=gfc->energy[j]; + } + } +#endif + + + + /********************************************************************** + * compute loudness approximation (used for ATH auto-level adjustment) + **********************************************************************/ + if( gfp->athaa_loudapprox == 2 ) { + if( chn < 2 ) { /* no loudness for mid and side channels */ + gfc->loudness_sq[gr_out][chn] = gfc->loudness_sq_save[chn]; + gfc->loudness_sq_save[chn] + = psycho_loudness_approx( gfc->energy, gfp); + } + } + + + + /********************************************************************** + * compute unpredicatability of first six spectral lines * + **********************************************************************/ + for ( j = 0; j < gfc->cw_lower_index; j++ ) + { /* calculate unpredictability measure cw */ + FLOAT an, a1, a2; + FLOAT bn, b1, b2; + FLOAT rn, r1, r2; + FLOAT numre, numim, den; + + a2 = gfc-> ax_sav[chn][1][j]; + b2 = gfc-> bx_sav[chn][1][j]; + r2 = gfc-> rx_sav[chn][1][j]; + a1 = gfc-> ax_sav[chn][1][j] = gfc-> ax_sav[chn][0][j]; + b1 = gfc-> bx_sav[chn][1][j] = gfc-> bx_sav[chn][0][j]; + r1 = gfc-> rx_sav[chn][1][j] = gfc-> rx_sav[chn][0][j]; + an = gfc-> ax_sav[chn][0][j] = (*wsamp_l)[j]; + bn = gfc-> bx_sav[chn][0][j] = j==0 ? (*wsamp_l)[0] : (*wsamp_l)[BLKSIZE-j]; + rn = gfc-> rx_sav[chn][0][j] = sqrt(gfc->energy[j]); + + { /* square (x1,y1) */ + if( r1 != 0 ) { + numre = (a1*b1); + numim = (a1*a1-b1*b1)*(FLOAT)0.5; + den = r1*r1; + } else { + numre = 1; + numim = 0; + den = 1; + } + } + + { /* multiply by (x2,-y2) */ + if( r2 != 0 ) { + FLOAT tmp2 = (numim+numre)*(a2+b2)*(FLOAT)0.5; + FLOAT tmp1 = -a2*numre+tmp2; + numre = -b2*numim+tmp2; + numim = tmp1; + den *= r2; + } else { + /* do nothing */ + } + } + + { /* r-prime factor */ + FLOAT tmp = (2*r1-r2)/den; + numre *= tmp; + numim *= tmp; + } + den=rn+fabs(2*r1-r2); + if( den != 0 ) { + numre = (an+bn)*(FLOAT)0.5-numre; + numim = (an-bn)*(FLOAT)0.5-numim; + den = sqrt(numre*numre+numim*numim)/den; + } + gfc->cw[j] = den; + } + + + + /********************************************************************** + * compute unpredicatibility of next 200 spectral lines * + **********************************************************************/ + for ( j = gfc->cw_lower_index; j < gfc->cw_upper_index; j += 4 ) + {/* calculate unpredictability measure cw */ + FLOAT rn, r1, r2; + FLOAT numre, numim, den; + + k = (j+2) / 4; + + { /* square (x1,y1) */ + r1 = gfc->energy_s[0][k]; + if( r1 != 0 ) { + FLOAT a1 = (*wsamp_s)[0][k]; + FLOAT b1 = (*wsamp_s)[0][BLKSIZE_s-k]; /* k is never 0 */ + numre = (a1*b1); + numim = (a1*a1-b1*b1)*(FLOAT)0.5; + den = r1; + r1 = sqrt(r1); + } else { + numre = 1; + numim = 0; + den = 1; + } + } + + + { /* multiply by (x2,-y2) */ + r2 = gfc->energy_s[2][k]; + if( r2 != 0 ) { + FLOAT a2 = (*wsamp_s)[2][k]; + FLOAT b2 = (*wsamp_s)[2][BLKSIZE_s-k]; + + + FLOAT tmp2 = (numim+numre)*(a2+b2)*(FLOAT)0.5; + FLOAT tmp1 = -a2*numre+tmp2; + numre = -b2*numim+tmp2; + numim = tmp1; + + r2 = sqrt(r2); + den *= r2; + } else { + /* do nothing */ + } + } + + { /* r-prime factor */ + FLOAT tmp = (2*r1-r2)/den; + numre *= tmp; + numim *= tmp; + } + + rn = sqrt(gfc->energy_s[1][k]); + den=rn+fabs(2*r1-r2); + if( den != 0 ) { + FLOAT an = (*wsamp_s)[1][k]; + FLOAT bn = (*wsamp_s)[1][BLKSIZE_s-k]; + numre = (an+bn)*(FLOAT)0.5-numre; + numim = (an-bn)*(FLOAT)0.5-numim; + den = sqrt(numre*numre+numim*numim)/den; + } + + gfc->cw[j+1] = gfc->cw[j+2] = gfc->cw[j+3] = gfc->cw[j] = den; + } + +#if 0 + for ( j = 14; j < HBLKSIZE-4; j += 4 ) + {/* calculate energy from short ffts */ + FLOAT8 tot,ave; + k = (j+2) / 4; + for (tot=0, sblock=0; sblock < 3; sblock++) + tot+=gfc->energy_s[sblock][k]; + ave = gfc->energy[j+1]+ gfc->energy[j+2]+ gfc->energy[j+3]+ gfc->energy[j]; + ave /= 4.; + gfc->energy[j+1] = gfc->energy[j+2] = gfc->energy[j+3] = gfc->energy[j]=tot; + } +#endif + + /********************************************************************** + * Calculate the energy and the unpredictability in the threshold * + * calculation partitions * + **********************************************************************/ + + b = 0; + for (j = 0; j < gfc->cw_upper_index && gfc->numlines_l[b] && bnpart_l_orig; ) + { + FLOAT8 ebb, cbb; + + ebb = gfc->energy[j]; + cbb = gfc->energy[j] * gfc->cw[j]; + j++; + + for (i = gfc->numlines_l[b] - 1; i > 0; i--) + { + ebb += gfc->energy[j]; + cbb += gfc->energy[j] * gfc->cw[j]; + j++; + } + eb[b] = ebb; + cb[b] = cbb; + b++; + } + + for (; b < gfc->npart_l_orig; b++ ) + { + FLOAT8 ebb = gfc->energy[j++]; + assert(gfc->numlines_l[b]); + for (i = gfc->numlines_l[b] - 1; i > 0; i--) + { + ebb += gfc->energy[j++]; + } + eb[b] = ebb; + cb[b] = ebb * 0.4; + } + + /********************************************************************** + * convolve the partitioned energy and unpredictability * + * with the spreading function, s3_l[b][k](packed into s3_ll) * + ******************************************************************** */ + gfc->pe[chn] = 0; /* calculate percetual entropy */ + { + int kk = 0; + for ( b = 0;b < gfc->npart_l; b++ ) + { + FLOAT8 tbb,ecb,ctb; + + ecb = 0; + ctb = 0; + + for ( k = gfc->s3ind[b][0]; k <= gfc->s3ind[b][1]; k++ ) + { + ecb += gfc->s3_ll[kk] * eb[k]; /* sprdngf for Layer III */ + ctb += gfc->s3_ll[kk] * cb[k]; + kk++; + } + + /* calculate the tonality of each threshold calculation partition + * calculate the SNR in each threshold calculation partition + * tonality = -0.299 - .43*log(ctb/ecb); + * tonality = 0: use NMT (lots of masking) + * tonality = 1: use TMN (little masking) + */ + +/* ISO values */ +#define CONV1 (-.299) +#define CONV2 (-.43) + + tbb = ecb; + if (tbb != 0) + { + tbb = ctb / tbb; + if (tbb <= exp((1-CONV1)/CONV2)) + { /* tonality near 1 */ + tbb = exp(-LN_TO_LOG10 * TMN); + } + else if (tbb >= exp((0-CONV1)/CONV2)) + {/* tonality near 0 */ + tbb = exp(-LN_TO_LOG10 * NMT); + } + else + { + /* convert to tonality index */ + /* tonality small: tbb=1 */ + /* tonality large: tbb=-.299 */ + tbb = CONV1 + CONV2*log(tbb); + tbb = exp(-LN_TO_LOG10 * ( TMN*tbb + (1-tbb)*NMT) ); + } + } + + /* at this point, tbb represents the amount the spreading function + * will be reduced. The smaller the value, the less masking. + * minval[] = 1 (0db) says just use tbb. + * minval[]= .01 (-20db) says reduce spreading function by + * at least 20db. + */ + + tbb = Min(gfc->minval[b], tbb); + + /* stabilize tonality estimation */ + if ( gfc->PSY->tonalityPatch ) { + if ( b > 5 ) + { + FLOAT8 const x = 1.8699422; + FLOAT8 w = gfc->PSY->prvTonRed[b/2] * x; + if (tbb > w) + tbb = w; + } + gfc->PSY->prvTonRed[b] = tbb; + } + + ecb *= tbb; + + /* long block pre-echo control. */ + /* rpelev=2.0, rpelev2=16.0 */ + /* note: all surges in PE are because of this pre-echo formula + * for thr[b]. If it this is not used, PE is always around 600 + */ + /* dont use long block pre-echo control if previous granule was + * a short block. This is to avoid the situation: + * frame0: quiet (very low masking) + * frame1: surge (triggers short blocks) + * frame2: regular frame. looks like pre-echo when compared to + * frame0, but all pre-echo was in frame1. + */ + /* chn=0,1 L and R channels + chn=2,3 S and M channels. + */ + + if (gfc->blocktype_old[chn>1 ? chn-2 : chn] == SHORT_TYPE ) + thr[b] = ecb; /* Min(ecb, rpelev*gfc->nb_1[chn][b]); */ + else + thr[b] = Min(ecb, Min(rpelev*gfc->nb_1[chn][b],rpelev2*gfc->nb_2[chn][b]) ); + + { + FLOAT8 thrpe; + thrpe = Max(thr[b],gfc->ATH->cb[b]); + /* + printf("%i thr=%e ATH=%e \n",b,thr[b],gfc->ATH->cb[b]); + */ + if (thrpe < eb[b]) + gfc->pe[chn] -= gfc->numlines_l[b] * log(thrpe / eb[b]); + } + + if ( gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh ) { + thr[b] = Min(ecb, rpelev*gfc->nb_1[chn][b]); + if (gfc->blocktype_old[chn>1 ? chn-2 : chn] != SHORT_TYPE ) + thr[b] = Min(thr[b], rpelev2*gfc->nb_2[chn][b]); + thr[b] = Max( thr[b], 1e-37 ); + } + + gfc->nb_2[chn][b] = gfc->nb_1[chn][b]; + gfc->nb_1[chn][b] = ecb; + } + } + + /*************************************************************** + * determine the block type (window type) based on L & R channels + * + ***************************************************************/ + { /* compute PE for all 4 channels */ + FLOAT mn,mx,ma=0,mb=0,mc=0; + + for ( j = HBLKSIZE_s/2; j < HBLKSIZE_s; j ++) + { + ma += gfc->energy_s[0][j]; + mb += gfc->energy_s[1][j]; + mc += gfc->energy_s[2][j]; + } + mn = Min(ma,mb); + mn = Min(mn,mc); + mx = Max(ma,mb); + mx = Max(mx,mc); + + /* bit allocation is based on pe. */ + if (mx>mn) { + FLOAT8 tmp = 400*log(mx/(1e-12+mn)); + if (tmp>gfc->pe[chn]) gfc->pe[chn]=tmp; + } + + /* block type is based just on L or R channel */ + if (chn<2) { + uselongblock[chn] = 1; + + /* tuned for t1.wav. doesnt effect most other samples */ + if (gfc->pe[chn] > 3000) + uselongblock[chn]=0; + + if ( mx > 30*mn ) + {/* big surge of energy - always use short blocks */ + uselongblock[chn] = 0; + } + else if ((mx > 10*mn) && (gfc->pe[chn] > 1000)) + {/* medium surge, medium pe - use short blocks */ + uselongblock[chn] = 0; + } + + /* disable short blocks */ + if (gfp->short_blocks == short_block_dispensed) + uselongblock[chn]=1; + if (gfp->short_blocks == short_block_forced) + uselongblock[chn]=0; + } + } + +#if defined(HAVE_GTK) + if (gfp->analysis) { + FLOAT mn,mx,ma=0,mb=0,mc=0; + + for ( j = HBLKSIZE_s/2; j < HBLKSIZE_s; j ++) + { + ma += gfc->energy_s[0][j]; + mb += gfc->energy_s[1][j]; + mc += gfc->energy_s[2][j]; + } + mn = Min(ma,mb); + mn = Min(mn,mc); + mx = Max(ma,mb); + mx = Max(mx,mc); + + gfc->pinfo->ers[gr_out][chn]=gfc->ers_save[chn]; + gfc->ers_save[chn]=(mx/(1e-12+mn)); + gfc->pinfo->pe[gr_out][chn]=gfc->pe_save[chn]; + gfc->pe_save[chn]=gfc->pe[chn]; + } +#endif + + + /*************************************************************** + * compute masking thresholds for both short and long blocks + ***************************************************************/ + /* longblock threshold calculation (part 2) */ + for ( sb = 0; sb < NBPSY_l; sb++ ) + { + FLOAT8 enn = gfc->w1_l[sb] * eb[gfc->bu_l[sb]] + gfc->w2_l[sb] * eb[gfc->bo_l[sb]]; + FLOAT8 thmm = gfc->w1_l[sb] *thr[gfc->bu_l[sb]] + gfc->w2_l[sb] * thr[gfc->bo_l[sb]]; + + for ( b = gfc->bu_l[sb]+1; b < gfc->bo_l[sb]; b++ ) + { + enn += eb[b]; + thmm += thr[b]; + } + + gfc->en [chn].l[sb] = enn; + gfc->thm[chn].l[sb] = thmm; + } + + + /* threshold calculation for short blocks */ + for ( sblock = 0; sblock < 3; sblock++ ) + { + j = 0; + for ( b = 0; b < gfc->npart_s_orig; b++ ) + { + FLOAT ecb = gfc->energy_s[sblock][j++]; + for (i = 1 ; inumlines_s[b]; ++i) + { + ecb += gfc->energy_s[sblock][j++]; + } + eb[b] = ecb; + } + { + int kk = 0; + for ( b = 0; b < gfc->npart_s; b++ ) + { + FLOAT8 ecb = 0; + for ( k = gfc->s3ind_s[b][0]; k <= gfc->s3ind_s[b][1]; k++ ) { + ecb += gfc->s3_ss[kk++] * eb[k]; + } + ecb *= gfc->SNR_s[b]; + +/* 2001-07-13 */ + if ( gfp->VBR == vbr_off || gfp->VBR == vbr_abr ) { + /* this looks like a BUG to me. robert */ + thr[b] = Max (1e-6, ecb); + } + else { + thr[b] = Min( ecb, rpelev_s * gfc->nb_s1[chn][b] ); + if (gfc->blocktype_old[chn>1 ? chn-2 : chn] == SHORT_TYPE ) { + thr[b] = Min( thr[b], rpelev2_s * gfc->nb_s2[chn][b] ); + } + thr[b] = Max( thr[b], 1e-37 ); + gfc->nb_s2[chn][b] = gfc->nb_s1[chn][b]; + gfc->nb_s1[chn][b] = ecb; + } + + } + + for ( sb = 0; sb < NBPSY_s; sb++ ) + { + FLOAT8 enn = gfc->w1_s[sb] * eb[gfc->bu_s[sb]] + gfc->w2_s[sb] * eb[gfc->bo_s[sb]]; + FLOAT8 thmm = gfc->w1_s[sb] *thr[gfc->bu_s[sb]] + gfc->w2_s[sb] * thr[gfc->bo_s[sb]]; + + for ( b = gfc->bu_s[sb]+1; b < gfc->bo_s[sb]; b++ ) { + enn += eb[b]; + thmm += thr[b]; + } + + gfc->en [chn].s[sb][sblock] = enn; + gfc->thm[chn].s[sb][sblock] = thmm; + } + } + } + } /* end loop over chn */ + + + + /*************************************************************** + * compute M/S thresholds + ***************************************************************/ + /* compute M/S thresholds from Johnston & Ferreira 1992 ICASSP paper */ + if (gfp->mode == JOINT_STEREO) { + FLOAT8 rside,rmid,mld; + int chmid=2,chside=3; + + for ( sb = 0; sb < NBPSY_l; sb++ ) { + /* use this fix if L & R masking differs by 2db or less */ + /* if db = 10*log10(x2/x1) < 2 */ + /* if (x2 < 1.58*x1) { */ + if (gfc->thm[0].l[sb] <= 1.58*gfc->thm[1].l[sb] + && gfc->thm[1].l[sb] <= 1.58*gfc->thm[0].l[sb]) { + + mld = gfc->mld_l[sb]*gfc->en[chside].l[sb]; + rmid = Max(gfc->thm[chmid].l[sb], Min(gfc->thm[chside].l[sb],mld)); + + mld = gfc->mld_l[sb]*gfc->en[chmid].l[sb]; + rside = Max(gfc->thm[chside].l[sb],Min(gfc->thm[chmid].l[sb],mld)); + + gfc->thm[chmid].l[sb]=rmid; + gfc->thm[chside].l[sb]=rside; + } + } + for ( sb = 0; sb < NBPSY_s; sb++ ) { + for ( sblock = 0; sblock < 3; sblock++ ) { + if (gfc->thm[0].s[sb][sblock] <= 1.58*gfc->thm[1].s[sb][sblock] + && gfc->thm[1].s[sb][sblock] <= 1.58*gfc->thm[0].s[sb][sblock]) { + + mld = gfc->mld_s[sb]*gfc->en[chside].s[sb][sblock]; + rmid = Max(gfc->thm[chmid].s[sb][sblock],Min(gfc->thm[chside].s[sb][sblock],mld)); + + mld = gfc->mld_s[sb]*gfc->en[chmid].s[sb][sblock]; + rside = Max(gfc->thm[chside].s[sb][sblock],Min(gfc->thm[chmid].s[sb][sblock],mld)); + + gfc->thm[chmid].s[sb][sblock]=rmid; + gfc->thm[chside].s[sb][sblock]=rside; + } + } + } + } + + + + /*************************************************************** + * Adjust M/S maskings if user set "msfix" + ***************************************************************/ + /* Naoki Shibata 2000 */ + if (numchn == 4 && gfp->msfix!=0) { + FLOAT msfix = gfp->msfix; + + for ( sb = 0; sb < NBPSY_l; sb++ ) + { + FLOAT8 thmL,thmR,thmM,thmS,ath; + ath = (gfc->ATH->cb[(gfc->bu_l[sb] + gfc->bo_l[sb])/2])*pow(10,-gfp->ATHlower/10.0); + thmL = Max(gfc->thm[0].l[sb],ath); + thmR = Max(gfc->thm[1].l[sb],ath); + thmM = Max(gfc->thm[2].l[sb],ath); + thmS = Max(gfc->thm[3].l[sb],ath); + + if (thmL*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmL*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + if (thmR*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmR*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + + gfc->thm[2].l[sb] = Min(thmM,gfc->thm[2].l[sb]); + gfc->thm[3].l[sb] = Min(thmS,gfc->thm[3].l[sb]); + } + + for ( sb = 0; sb < NBPSY_s; sb++ ) { + for ( sblock = 0; sblock < 3; sblock++ ) { + FLOAT8 thmL,thmR,thmM,thmS,ath; + ath = (gfc->ATH->cb[(gfc->bu_s[sb] + gfc->bo_s[sb])/2])*pow(10,-gfp->ATHlower/10.0); + thmL = Max(gfc->thm[0].s[sb][sblock],ath); + thmR = Max(gfc->thm[1].s[sb][sblock],ath); + thmM = Max(gfc->thm[2].s[sb][sblock],ath); + thmS = Max(gfc->thm[3].s[sb][sblock],ath); + + if (thmL*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmL*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + if (thmR*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmR*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + + gfc->thm[2].s[sb][sblock] = Min(gfc->thm[2].s[sb][sblock],thmM); + gfc->thm[3].s[sb][sblock] = Min(gfc->thm[3].s[sb][sblock],thmS); + } + } + } + + + + + + + + + + + + if (gfp->mode == JOINT_STEREO) { + /* determin ms_ratio from masking thresholds*/ + /* use ms_stereo (ms_ratio < .35) if average thresh. diff < 5 db */ + FLOAT8 db,x1,x2,sidetot=0,tot=0; + for (sb= NBPSY_l/4 ; sb< NBPSY_l; sb ++ ) { + x1 = Min(gfc->thm[0].l[sb],gfc->thm[1].l[sb]); + x2 = Max(gfc->thm[0].l[sb],gfc->thm[1].l[sb]); + /* thresholds difference in db */ + if (x2 >= 1000*x1) db=3; + else db = log10(x2/x1); + /* DEBUGF(gfc,"db = %f %e %e \n",db,gfc->thm[0].l[sb],gfc->thm[1].l[sb]);*/ + sidetot += db; + tot++; + } + ms_ratio_l= (sidetot/tot)*0.7; /* was .35*(sidetot/tot)/5.0*10 */ + ms_ratio_l = Min(ms_ratio_l,0.5); + + sidetot=0; tot=0; + for ( sblock = 0; sblock < 3; sblock++ ) + for ( sb = NBPSY_s/4; sb < NBPSY_s; sb++ ) { + x1 = Min(gfc->thm[0].s[sb][sblock],gfc->thm[1].s[sb][sblock]); + x2 = Max(gfc->thm[0].s[sb][sblock],gfc->thm[1].s[sb][sblock]); + /* thresholds difference in db */ + if (x2 >= 1000*x1) db=3; + else db = log10(x2/x1); + sidetot += db; + tot++; + } + ms_ratio_s = (sidetot/tot)*0.7; /* was .35*(sidetot/tot)/5.0*10 */ + ms_ratio_s = Min(ms_ratio_s,.5); + } + + /*************************************************************** + * determine final block type + ***************************************************************/ + + for (chn=0; chnchannels_out; chn++) { + blocktype[chn] = NORM_TYPE; + } + + + if (gfp->short_blocks == short_block_coupled) { + /* force both channels to use the same block type */ + /* this is necessary if the frame is to be encoded in ms_stereo. */ + /* But even without ms_stereo, FhG does this */ + int bothlong= (uselongblock[0] && uselongblock[1]); + if (!bothlong) { + uselongblock[0]=0; + uselongblock[1]=0; + } + } + + + + /* update the blocktype of the previous granule, since it depends on what + * happend in this granule */ + for (chn=0; chnchannels_out; chn++) { + if ( uselongblock[chn]) + { /* no attack : use long blocks */ + assert( gfc->blocktype_old[chn] != START_TYPE ); + switch( gfc->blocktype_old[chn] ) + { + case NORM_TYPE: + case STOP_TYPE: + blocktype[chn] = NORM_TYPE; + break; + case SHORT_TYPE: + blocktype[chn] = STOP_TYPE; + break; + } + } else { + /* attack : use short blocks */ + blocktype[chn] = SHORT_TYPE; + if ( gfc->blocktype_old[chn] == NORM_TYPE ) { + gfc->blocktype_old[chn] = START_TYPE; + } + if ( gfc->blocktype_old[chn] == STOP_TYPE ) { + gfc->blocktype_old[chn] = SHORT_TYPE ; + } + } + + blocktype_d[chn] = gfc->blocktype_old[chn]; /* value returned to calling program */ + gfc->blocktype_old[chn] = blocktype[chn]; /* save for next call to l3psy_anal */ + } + + if (blocktype_d[0]==2 && blocktype_d[1]==2) + *ms_ratio = gfc->ms_ratio_s_old; + else + *ms_ratio = gfc->ms_ratio_l_old; + + gfc->ms_ratio_s_old = ms_ratio_s; + gfc->ms_ratio_l_old = ms_ratio_l; + + /* we dont know the block type of this frame yet - assume long */ + *ms_ratio_next = ms_ratio_l; + + return 0; +} + +/* addition of simultaneous masking Naoki Shibata 2000/7 */ +inline static FLOAT8 mask_add(FLOAT8 m1,FLOAT8 m2,int k,int b, lame_internal_flags * const gfc) +{ + static const FLOAT8 table1[] = { + 3.3246 *3.3246 ,3.23837*3.23837,3.15437*3.15437,3.00412*3.00412,2.86103*2.86103,2.65407*2.65407,2.46209*2.46209,2.284 *2.284 , + 2.11879*2.11879,1.96552*1.96552,1.82335*1.82335,1.69146*1.69146,1.56911*1.56911,1.46658*1.46658,1.37074*1.37074,1.31036*1.31036, + 1.25264*1.25264,1.20648*1.20648,1.16203*1.16203,1.12765*1.12765,1.09428*1.09428,1.0659 *1.0659 ,1.03826*1.03826,1.01895*1.01895, + 1 + }; + + static const FLOAT8 table2[] = { + 1.33352*1.33352,1.35879*1.35879,1.38454*1.38454,1.39497*1.39497,1.40548*1.40548,1.3537 *1.3537 ,1.30382*1.30382,1.22321*1.22321, + 1.14758*1.14758 + }; + + static const FLOAT8 table3[] = { + 2.35364*2.35364,2.29259*2.29259,2.23313*2.23313,2.12675*2.12675,2.02545*2.02545,1.87894*1.87894,1.74303*1.74303,1.61695*1.61695, + 1.49999*1.49999,1.39148*1.39148,1.29083*1.29083,1.19746*1.19746,1.11084*1.11084,1.03826*1.03826 + }; + + + int i; + FLOAT8 m; + + if (m1 == 0) return m2; + + if (b < 0) b = -b; + + i = 10*log10(m2 / m1)/10*16; + m = 10*log10((m1+m2)/gfc->ATH->cb[k]); + + if (i < 0) i = -i; + + if (b <= 3) { /* approximately, 1 bark = 3 partitions */ + if (i > 8) return m1+m2; + return (m1+m2)*table2[i]; + } + + if (m<15) { + if (m > 0) { + FLOAT8 f=1.0,r; + if (i > 24) return m1+m2; + if (i > 13) f = 1; else f = table3[i]; + r = (m-0)/15; + return (m1+m2)*(table1[i]*r+f*(1-r)); + } + if (i > 13) return m1+m2; + return (m1+m2)*table3[i]; + } + + if (i > 24) return m1+m2; + return (m1+m2)*table1[i]; +} + +int L3psycho_anal_ns( lame_global_flags * gfp, + const sample_t *buffer[2], int gr_out, + FLOAT8 *ms_ratio, + FLOAT8 *ms_ratio_next, + III_psy_ratio masking_ratio[2][2], + III_psy_ratio masking_MS_ratio[2][2], + FLOAT8 percep_entropy[2],FLOAT8 percep_MS_entropy[2], + FLOAT8 energy[4], + int blocktype_d[2]) +{ +/* to get a good cache performance, one has to think about + * the sequence, in which the variables are used. + * (Note: these static variables have been moved to the gfc-> struct, + * and their order in memory is layed out in util.h) + */ + lame_internal_flags *gfc=gfp->internal_flags; + + /* fft and energy calculation */ + FLOAT (*wsamp_l)[BLKSIZE]; + FLOAT (*wsamp_s)[3][BLKSIZE_s]; + + /* convolution */ + FLOAT8 eb[CBANDS],eb2[CBANDS]; + FLOAT8 thr[CBANDS]; + + FLOAT8 max[CBANDS],avg[CBANDS],tonality2[CBANDS]; + + /* ratios */ + FLOAT8 ms_ratio_l=0,ms_ratio_s=0; + + /* block type */ + int blocktype[2],uselongblock[2]; + + /* usual variables like loop indices, etc.. */ + int numchn, chn; + int b, i, j, k; + int sb,sblock; + + /* variables used for --nspsytune */ + int ns_attacks[4]; + FLOAT ns_hpfsmpl[4][576+576/3+NSFIRLEN]; + FLOAT pe_l[4],pe_s[4]; + FLOAT pcfact; + + + if(gfc->psymodel_init==0) { + psymodel_init(gfp); + init_fft(gfc); + gfc->psymodel_init=1; + } + + + numchn = gfc->channels_out; + /* chn=2 and 3 = Mid and Side channels */ + if (gfp->mode == JOINT_STEREO) numchn=4; + + if (gfp->VBR==vbr_off) pcfact = gfc->ResvMax == 0 ? 0 : ((FLOAT)gfc->ResvSize)/gfc->ResvMax*0.5; + else if (gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh || gfp->VBR == vbr_mt) { + static const FLOAT8 pcQns[10]={1.0,1.0,1.0,0.8,0.6,0.5,0.4,0.3,0.2,0.1}; + pcfact = pcQns[gfp->VBR_q]; + } else pcfact = 1; + + /********************************************************************** + * Apply HPF of fs/4 to the input signal. + * This is used for attack detection / handling. + **********************************************************************/ + + { + static const FLOAT fircoef[] = { + -8.65163e-18,-0.00851586,-6.74764e-18, 0.0209036, + -3.36639e-17,-0.0438162 ,-1.54175e-17, 0.0931738, + -5.52212e-17,-0.313819 , 0.5 ,-0.313819, + -5.52212e-17, 0.0931738 ,-1.54175e-17,-0.0438162, + -3.36639e-17, 0.0209036 ,-6.74764e-18,-0.00851586, + -8.65163e-18, + }; + + for(chn=0;chnchannels_out;chn++) + { + FLOAT firbuf[576+576/3+NSFIRLEN]; + + /* apply high pass filter of fs/4 */ + + for(i=-NSFIRLEN;i<576+576/3;i++) + firbuf[i+NSFIRLEN] = buffer[chn][576-350+(i)]; + + for(i=0;i<576+576/3-NSFIRLEN;i++) + { + FLOAT sum = 0; + for(j=0;jmode == JOINT_STEREO) { + for(i=0;i<576+576/3;i++) + { + ns_hpfsmpl[2][i] = ns_hpfsmpl[0][i]+ns_hpfsmpl[1][i]; + ns_hpfsmpl[3][i] = ns_hpfsmpl[0][i]-ns_hpfsmpl[1][i]; + } + } + } + + + + /* there is a one granule delay. Copy maskings computed last call + * into masking_ratio to return to calling program. + */ + for (chn=0; chntot_ener[chn]; + } + } + + + for (chn=0; chnnsPsy.pe_l[chn]; + pe_s[chn] = gfc->nsPsy.pe_s[chn]; + + if (chn < 2) { + /* LR maskings */ + //percep_entropy [chn] = gfc -> pe [chn]; + masking_ratio [gr_out] [chn] .en = gfc -> en [chn]; + masking_ratio [gr_out] [chn] .thm = gfc -> thm [chn]; + } else { + /* MS maskings */ + //percep_MS_entropy [chn-2] = gfc -> pe [chn]; + masking_MS_ratio [gr_out] [chn-2].en = gfc -> en [chn]; + masking_MS_ratio [gr_out] [chn-2].thm = gfc -> thm [chn]; + } + } + + for (chn=0; chnwsamp_S+(chn & 1); + wsamp_l = gfc->wsamp_L+(chn & 1); + + if (chn<2) { + fft_long ( gfc, *wsamp_l, chn, buffer); + fft_short( gfc, *wsamp_s, chn, buffer); + } + + /* FFT data for mid and side channel is derived from L & R */ + + if (chn == 2) + { + for (j = BLKSIZE-1; j >=0 ; --j) + { + FLOAT l = gfc->wsamp_L[0][j]; + FLOAT r = gfc->wsamp_L[1][j]; + gfc->wsamp_L[0][j] = (l+r)*(FLOAT)(SQRT2*0.5); + gfc->wsamp_L[1][j] = (l-r)*(FLOAT)(SQRT2*0.5); + } + for (b = 2; b >= 0; --b) + { + for (j = BLKSIZE_s-1; j >= 0 ; --j) + { + FLOAT l = gfc->wsamp_S[0][b][j]; + FLOAT r = gfc->wsamp_S[1][b][j]; + gfc->wsamp_S[0][b][j] = (l+r)*(FLOAT)(SQRT2*0.5); + gfc->wsamp_S[1][b][j] = (l-r)*(FLOAT)(SQRT2*0.5); + } + } + } + + + /********************************************************************** + * compute energies for each spectral line + **********************************************************************/ + + /* long block */ + + gfc->energy[0] = (*wsamp_l)[0]; + gfc->energy[0] *= gfc->energy[0]; + + gfc->tot_ener[chn] = gfc->energy[0]; /* sum total energy at nearly no extra cost */ + + for (j=BLKSIZE/2-1; j >= 0; --j) + { + FLOAT re = (*wsamp_l)[BLKSIZE/2-j]; + FLOAT im = (*wsamp_l)[BLKSIZE/2+j]; + gfc->energy[BLKSIZE/2-j] = (re * re + im * im) * (FLOAT)0.5; + + if (BLKSIZE/2-j > 10) + gfc->tot_ener[chn] += gfc->energy[BLKSIZE/2-j]; + } + + + /* short block */ + + for (b = 2; b >= 0; --b) + { + gfc->energy_s[b][0] = (*wsamp_s)[b][0]; + gfc->energy_s[b][0] *= gfc->energy_s [b][0]; + for (j=BLKSIZE_s/2-1; j >= 0; --j) + { + FLOAT re = (*wsamp_s)[b][BLKSIZE_s/2-j]; + FLOAT im = (*wsamp_s)[b][BLKSIZE_s/2+j]; + gfc->energy_s[b][BLKSIZE_s/2-j] = (re * re + im * im) * (FLOAT)0.5; + } + } + + + /* output data for analysis */ + +#if defined(HAVE_GTK) + if (gfp->analysis) { + for (j=0; jpinfo->energy[gr_out][chn][j]=gfc->energy_save[chn][j]; + gfc->energy_save[chn][j]=gfc->energy[j]; + } + } +#endif + + + /********************************************************************** + * compute loudness approximation (used for ATH auto-level adjustment) + **********************************************************************/ + if( gfp->athaa_loudapprox == 2 ) { + if( chn < 2 ) { /* no loudness for mid and side channels */ + gfc->loudness_sq[gr_out][chn] = gfc->loudness_sq_save[chn]; + gfc->loudness_sq_save[chn] + = psycho_loudness_approx( gfc->energy, gfp); + } + } + + + + /********************************************************************** + * Calculate the energy and the tonality of each partition. + **********************************************************************/ + + for (b=0, j=0; bnpart_l_orig; b++) + { + FLOAT8 ebb,m,a; + + ebb = gfc->energy[j]; + m = a = gfc->energy[j]; + j++; + + for (i = gfc->numlines_l[b] - 1; i > 0; i--) + { + FLOAT8 el = gfc->energy[j]; + ebb += gfc->energy[j]; + a += el; + m = m < el ? el : m; + j++; + } + eb[b] = ebb; + max[b] = m; + avg[b] = a / gfc->numlines_l[b]; + } + + j = 0; + for (b=0; b < gfc->npart_l_orig; b++ ) + { + int c1,c2; + FLOAT8 m,a; + tonality2[b] = 0; + c1 = c2 = 0; + m = a = 0; + for(k=b-1;k<=b+1;k++) + { + if (k >= 0 && k < gfc->npart_l_orig) { + c1++; + c2 += gfc->numlines_l[k]; + a += avg[k]; + m = m < max[k] ? max[k] : m; + } + } + + a /= c1; + tonality2[b] = a == 0 ? 0 : (m / a - 1)/(c2-1); + } + + for (b=0; b < gfc->npart_l_orig; b++ ) + { +#if 0 + static FLOAT8 tab[20] = + { 0, 1, 2, 2, 2, 2, 2, 6,9.3,9.3,9.3,9.3,9.3,9.3,9.3,9.3,9.3,9.3,9.3,9.3}; + + static int init = 1; + if (init) { + int j; + for(j=0;j<20;j++) { + tab[j] = pow(10.0,-tab[j]/10.0); + } + init = 0; + } +#else + static FLOAT8 tab[20] = { + 1,0.79433,0.63096,0.63096,0.63096,0.63096,0.63096,0.25119,0.11749,0.11749, + 0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749 + }; +#endif + + int t = 20*tonality2[b]; + if (t > 19) t = 19; + eb2[b] = eb[b] * tab[t]; + } + + + /********************************************************************** + * convolve the partitioned energy and unpredictability + * with the spreading function, s3_l[b][k] + ******************************************************************** */ + { + int kk = 0; + for ( b = 0;b < gfc->npart_l; b++ ) + { + FLOAT8 ecb; + + /**** convolve the partitioned energy with the spreading function ****/ + + ecb = 0; + +#if 1 + for ( k = gfc->s3ind[b][0]; k <= gfc->s3ind[b][1]; k++ ) + { + ecb = mask_add(ecb,gfc->s3_ll[kk++] * eb2[k],k,k-b,gfc); + } + + ecb *= 0.158489319246111; // pow(10,-0.8) +#endif + +#if 0 + for ( k = gfc->s3ind[b][0]; k <= gfc->s3ind[b][1]; k++ ) + { + ecb += gfc->s3_ll[kk++] * eb2[k]; + } + + ecb *= 0.223872113856834; // pow(10,-0.65); +#endif + + /**** long block pre-echo control ****/ + + /* dont use long block pre-echo control if previous granule was + * a short block. This is to avoid the situation: + * frame0: quiet (very low masking) + * frame1: surge (triggers short blocks) + * frame2: regular frame. looks like pre-echo when compared to + * frame0, but all pre-echo was in frame1. + */ + + /* chn=0,1 L and R channels + chn=2,3 S and M channels. + */ + +#define NS_INTERP(x,y,r) (pow((x),(r))*pow((y),1-(r))) + + if (gfc->blocktype_old[chn>1 ? chn-2 : chn] == SHORT_TYPE ) + thr[b] = ecb; /* Min(ecb, rpelev*gfc->nb_1[chn][b]); */ + else + thr[b] = NS_INTERP(Min(ecb, Min(rpelev*gfc->nb_1[chn][b],rpelev2*gfc->nb_2[chn][b])),ecb,pcfact); + + gfc->nb_2[chn][b] = gfc->nb_1[chn][b]; + gfc->nb_1[chn][b] = ecb; + } + } + + /*************************************************************** + * determine the block type (window type) + ***************************************************************/ + + { + static int count=0; + FLOAT en_subshort[12]; + FLOAT attack_intensity[12]; + int ns_uselongblock = 1; + + /* calculate energies of each sub-shortblocks */ + + k = 0; + for(i=0;i<12;i++) + { + en_subshort[i] = 0; + for(j=0;j<576/9;j++) + { + en_subshort[i] += ns_hpfsmpl[chn][k] * ns_hpfsmpl[chn][k]; + k++; + } + + if (en_subshort[i] < 100) en_subshort[i] = 100; + } + + /* compare energies between sub-shortblocks */ + +#define NSATTACKTHRE 150 +#define NSATTACKTHRE_S 300 + + for(i=0;i<2;i++) { + attack_intensity[i] = en_subshort[i] / gfc->nsPsy.last_en_subshort[chn][7+i]; + } + + for(;i<12;i++) { + attack_intensity[i] = en_subshort[i] / en_subshort[i-2]; + } + + ns_attacks[0] = ns_attacks[1] = ns_attacks[2] = ns_attacks[3] = 0; + + for(i=0;i<12;i++) + { + if (!ns_attacks[i/3] && attack_intensity[i] > (chn == 3 ? (gfc->presetTune.use ? gfc->presetTune.attackthre_s : NSATTACKTHRE_S) + : (gfc->presetTune.use ? gfc->presetTune.attackthre : NSATTACKTHRE))) ns_attacks[i/3] = (i % 3)+1; + } + + if (ns_attacks[0] && gfc->nsPsy.last_attacks[chn][2]) ns_attacks[0] = 0; + if (ns_attacks[1] && ns_attacks[0]) ns_attacks[1] = 0; + if (ns_attacks[2] && ns_attacks[1]) ns_attacks[2] = 0; + if (ns_attacks[3] && ns_attacks[2]) ns_attacks[3] = 0; + + if (gfc->nsPsy.last_attacks[chn][2] == 3 || + ns_attacks[0] || ns_attacks[1] || ns_attacks[2] || ns_attacks[3]) ns_uselongblock = 0; + + if (chn < 4) count++; + + for(i=0;i<9;i++) + { + gfc->nsPsy.last_en_subshort[chn][i] = en_subshort[i]; + gfc->nsPsy.last_attack_intensity[chn][i] = attack_intensity[i]; + } + + if (gfp->short_blocks == short_block_dispensed) { + uselongblock[chn] = 1; + } + else if (gfp->short_blocks == short_block_forced) { + uselongblock[chn] = 0; + } + else { + if (chn < 2) { + uselongblock[chn] = ns_uselongblock; + } else { + if (ns_uselongblock == 0) uselongblock[0] = uselongblock[1] = 0; + } + } + } + +#if defined(HAVE_GTK) + if (gfp->analysis) { + FLOAT mn,mx,ma=0,mb=0,mc=0; + + for ( j = HBLKSIZE_s/2; j < HBLKSIZE_s; j ++) + { + ma += gfc->energy_s[0][j]; + mb += gfc->energy_s[1][j]; + mc += gfc->energy_s[2][j]; + } + mn = Min(ma,mb); + mn = Min(mn,mc); + mx = Max(ma,mb); + mx = Max(mx,mc); + + gfc->pinfo->ers[gr_out][chn]=gfc->ers_save[chn]; + gfc->ers_save[chn]=(mx/(1e-12+mn)); + } +#endif + + + /*************************************************************** + * compute masking thresholds for long blocks + ***************************************************************/ + + for ( sb = 0; sb < NBPSY_l; sb++ ) + { + FLOAT8 enn = gfc->w1_l[sb] * eb[gfc->bu_l[sb]] + gfc->w2_l[sb] * eb[gfc->bo_l[sb]]; + FLOAT8 thmm = gfc->w1_l[sb] *thr[gfc->bu_l[sb]] + gfc->w2_l[sb] * thr[gfc->bo_l[sb]]; + + for ( b = gfc->bu_l[sb]+1; b < gfc->bo_l[sb]; b++ ) + { + enn += eb[b]; + thmm += thr[b]; + } + + gfc->en [chn].l[sb] = enn; + gfc->thm[chn].l[sb] = thmm; + } + + + /*************************************************************** + * compute masking thresholds for short blocks + ***************************************************************/ + + for ( sblock = 0; sblock < 3; sblock++ ) + { + j = 0; + for ( b = 0; b < gfc->npart_s_orig; b++ ) + { + FLOAT ecb = gfc->energy_s[sblock][j++]; + for (i = 1 ; inumlines_s[b]; ++i) + { + ecb += gfc->energy_s[sblock][j++]; + } + eb[b] = ecb; + } + + { + int kk = 0; + for ( b = 0; b < gfc->npart_s; b++ ) + { + FLOAT8 ecb = 0; + for ( k = gfc->s3ind_s[b][0]; k <= gfc->s3ind_s[b][1]; k++ ) + { + ecb += gfc->s3_ss[kk++] * eb[k]; + } + +/* 2001-07-13 */ + /* this looks like a BUG */ + thr[b] = Max (1e-6, ecb); + + if (gfp->VBR == vbr_mtrh) { + thr[b] = Min( ecb, rpelev_s * gfc->nb_s1[chn][b] ); + if (gfc->blocktype_old[chn>1 ? chn-2 : chn] == SHORT_TYPE ) { + thr[b] = Min( thr[b], rpelev2_s * gfc->nb_s2[chn][b] ); + } + thr[b] = Max( thr[b], 1e-37 ); + gfc->nb_s2[chn][b] = gfc->nb_s1[chn][b]; + gfc->nb_s1[chn][b] = ecb; + } + } + } + for ( sb = 0; sb < NBPSY_s; sb++ ) + { + FLOAT8 enn = gfc->w1_s[sb] * eb[gfc->bu_s[sb]] + gfc->w2_s[sb] * eb[gfc->bo_s[sb]]; + FLOAT8 thmm = gfc->w1_s[sb] *thr[gfc->bu_s[sb]] + gfc->w2_s[sb] * thr[gfc->bo_s[sb]]; + + for ( b = gfc->bu_s[sb]+1; b < gfc->bo_s[sb]; b++ ) + { + enn += eb[b]; + thmm += thr[b]; + } + + /**** short block pre-echo control ****/ + +#define NS_PREECHO_ATT0 0.8 +#define NS_PREECHO_ATT1 0.6 +#define NS_PREECHO_ATT2 0.3 + + thmm *= NS_PREECHO_ATT0; + + if (ns_attacks[sblock] >= 2) { + if (sblock != 0) { + double p = NS_INTERP(gfc->thm[chn].s[sb][sblock-1],thmm,NS_PREECHO_ATT1*pcfact); + thmm = Min(thmm,p); + } else { + double p = NS_INTERP(gfc->nsPsy.last_thm[chn][sb][2],thmm,NS_PREECHO_ATT1*pcfact); + thmm = Min(thmm,p); + } + } else if (ns_attacks[sblock+1] == 1) { + if (sblock != 0) { + double p = NS_INTERP(gfc->thm[chn].s[sb][sblock-1],thmm,NS_PREECHO_ATT1*pcfact); + thmm = Min(thmm,p); + } else { + double p = NS_INTERP(gfc->nsPsy.last_thm[chn][sb][2],thmm,NS_PREECHO_ATT1*pcfact); + thmm = Min(thmm,p); + } + } + + if (ns_attacks[sblock] == 1) { + double p = sblock == 0 ? gfc->nsPsy.last_thm[chn][sb][2] : gfc->thm[chn].s[sb][sblock-1]; + p = NS_INTERP(p,thmm,NS_PREECHO_ATT2*pcfact); + thmm = Min(thmm,p); + } else if ((sblock != 0 && ns_attacks[sblock-1] == 3) || + (sblock == 0 && gfc->nsPsy.last_attacks[chn][2] == 3)) { + double p = sblock <= 1 ? gfc->nsPsy.last_thm[chn][sb][sblock+1] : gfc->thm[chn].s[sb][0]; + p = NS_INTERP(p,thmm,NS_PREECHO_ATT2*pcfact); + thmm = Min(thmm,p); + } + + gfc->en [chn].s[sb][sblock] = enn; + gfc->thm[chn].s[sb][sblock] = thmm; + } + } + + + /*************************************************************** + * save some values for analysis of the next granule + ***************************************************************/ + + for ( sblock = 0; sblock < 3; sblock++ ) + { + for ( sb = 0; sb < NBPSY_s; sb++ ) + { + gfc->nsPsy.last_thm[chn][sb][sblock] = gfc->thm[chn].s[sb][sblock]; + } + } + + for(i=0;i<3;i++) + gfc->nsPsy.last_attacks[chn][i] = ns_attacks[i]; + + } /* end loop over chn */ + + + + /*************************************************************** + * compute M/S thresholds + ***************************************************************/ + + /* from Johnston & Ferreira 1992 ICASSP paper */ + + if ( numchn==4 /* mid/side and r/l */) { + FLOAT8 rside,rmid,mld; + int chmid=2,chside=3; + + for ( sb = 0; sb < NBPSY_l; sb++ ) { + /* use this fix if L & R masking differs by 2db or less */ + /* if db = 10*log10(x2/x1) < 2 */ + /* if (x2 < 1.58*x1) { */ + if (gfc->thm[0].l[sb] <= 1.58*gfc->thm[1].l[sb] + && gfc->thm[1].l[sb] <= 1.58*gfc->thm[0].l[sb]) { + + mld = gfc->mld_l[sb]*gfc->en[chside].l[sb]; + rmid = Max(gfc->thm[chmid].l[sb], Min(gfc->thm[chside].l[sb],mld)); + + mld = gfc->mld_l[sb]*gfc->en[chmid].l[sb]; + rside = Max(gfc->thm[chside].l[sb],Min(gfc->thm[chmid].l[sb],mld)); + + gfc->thm[chmid].l[sb]=rmid; + gfc->thm[chside].l[sb]=rside; + } + } + for ( sb = 0; sb < NBPSY_s; sb++ ) { + for ( sblock = 0; sblock < 3; sblock++ ) { + if (gfc->thm[0].s[sb][sblock] <= 1.58*gfc->thm[1].s[sb][sblock] + && gfc->thm[1].s[sb][sblock] <= 1.58*gfc->thm[0].s[sb][sblock]) { + + mld = gfc->mld_s[sb]*gfc->en[chside].s[sb][sblock]; + rmid = Max(gfc->thm[chmid].s[sb][sblock],Min(gfc->thm[chside].s[sb][sblock],mld)); + + mld = gfc->mld_s[sb]*gfc->en[chmid].s[sb][sblock]; + rside = Max(gfc->thm[chside].s[sb][sblock],Min(gfc->thm[chmid].s[sb][sblock],mld)); + + gfc->thm[chmid].s[sb][sblock]=rmid; + gfc->thm[chside].s[sb][sblock]=rside; + } + } + } + } + + + /* Naoki Shibata 2000 */ + +#define NS_MSFIX 3.5 + + if (numchn == 4) { + FLOAT msfix = NS_MSFIX; + if (gfc->nsPsy.safejoint) msfix = 1; + if (gfp->msfix) msfix = gfp->msfix; + + if (gfc->presetTune.use && gfc->ATH->adjust >= + gfc->presetTune.athadjust_switch_level && + gfc->presetTune.athadjust_msfix > 0) + msfix = gfc->presetTune.athadjust_msfix; + + for ( sb = 0; sb < NBPSY_l; sb++ ) + { + FLOAT8 thmL,thmR,thmM,thmS,ath; + ath = (gfc->ATH->cb[(gfc->bu_l[sb] + gfc->bo_l[sb])/2])*pow(10,-gfp->ATHlower/10.0); + thmL = Max(gfc->thm[0].l[sb],ath); + thmR = Max(gfc->thm[1].l[sb],ath); + thmM = Max(gfc->thm[2].l[sb],ath); + thmS = Max(gfc->thm[3].l[sb],ath); + + if (thmL*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmL * (gfc->presetTune.use ? gfc->presetTune.ms_maskadjust : msfix) / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + if (thmR*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmR * (gfc->presetTune.use ? gfc->presetTune.ms_maskadjust : msfix) / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + + gfc->thm[2].l[sb] = Min(thmM,gfc->thm[2].l[sb]); + gfc->thm[3].l[sb] = Min(thmS,gfc->thm[3].l[sb]); + } + + for ( sb = 0; sb < NBPSY_s; sb++ ) { + for ( sblock = 0; sblock < 3; sblock++ ) { + FLOAT8 thmL,thmR,thmM,thmS,ath; + ath = (gfc->ATH->cb[(gfc->bu_s[sb] + gfc->bo_s[sb])/2])*pow(10,-gfp->ATHlower/10.0); + thmL = Max(gfc->thm[0].s[sb][sblock],ath); + thmR = Max(gfc->thm[1].s[sb][sblock],ath); + thmM = Max(gfc->thm[2].s[sb][sblock],ath); + thmS = Max(gfc->thm[3].s[sb][sblock],ath); + + if (thmL*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmL*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + if (thmR*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmR*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + + gfc->thm[2].s[sb][sblock] = Min(gfc->thm[2].s[sb][sblock],thmM); + gfc->thm[3].s[sb][sblock] = Min(gfc->thm[3].s[sb][sblock],thmS); + } + } + } + + ms_ratio_l = 0; + ms_ratio_s = 0; + + + /*************************************************************** + * compute estimation of the amount of bit used in the granule + ***************************************************************/ + + for(chn=0;chnthm[chn].l[sb]*gfc->masking_lower != 0 && + gfc->en[chn].l[sb]/(gfc->thm[chn].l[sb]*gfc->masking_lower) > 1) + t = log(gfc->en[chn].l[sb]/(gfc->thm[chn].l[sb]*gfc->masking_lower)); + else + t = 0; + msum += regcoef[sb+1] * t; + } + + gfc->nsPsy.pe_l[chn] = msum; + } + + { + static FLOAT8 regcoef[] = { + 1236.28,0,0,0,0.434542,25.0738,0,0,0,19.5442,19.7486,60,100,0 + }; + + FLOAT8 msum = regcoef[0]/4; + int sb,sblock; + + for(sblock=0;sblock<3;sblock++) + { + for ( sb = 0; sb < NBPSY_s; sb++ ) + { + FLOAT8 t; + + if (gfc->thm[chn].s[sb][sblock] * gfc->masking_lower != 0 && + gfc->en[chn].s[sb][sblock] / (gfc->thm[chn].s[sb][sblock] * gfc->masking_lower) > 1) + t = log(gfc->en[chn].s[sb][sblock] / (gfc->thm[chn].s[sb][sblock] * gfc->masking_lower)); + else + t = 0; + msum += regcoef[sb+1] * t; + } + } + + gfc->nsPsy.pe_s[chn] = msum; + } + + //gfc->pe[chn] -= 150; + } + + /*************************************************************** + * determine final block type + ***************************************************************/ + + for (chn=0; chnchannels_out; chn++) { + blocktype[chn] = NORM_TYPE; + } + + if (gfp->short_blocks == short_block_coupled) { + /* force both channels to use the same block type */ + /* this is necessary if the frame is to be encoded in ms_stereo. */ + /* But even without ms_stereo, FhG does this */ + int bothlong= (uselongblock[0] && uselongblock[1]); + if (!bothlong) { + uselongblock[0]=0; + uselongblock[1]=0; + } + } + + /* update the blocktype of the previous granule, since it depends on what + * happend in this granule */ + for (chn=0; chnchannels_out; chn++) { + if ( uselongblock[chn]) + { /* no attack : use long blocks */ + assert( gfc->blocktype_old[chn] != START_TYPE ); + switch( gfc->blocktype_old[chn] ) + { + case NORM_TYPE: + case STOP_TYPE: + blocktype[chn] = NORM_TYPE; + break; + case SHORT_TYPE: + blocktype[chn] = STOP_TYPE; + break; + } + } else { + /* attack : use short blocks */ + blocktype[chn] = SHORT_TYPE; + if ( gfc->blocktype_old[chn] == NORM_TYPE ) { + gfc->blocktype_old[chn] = START_TYPE; + } + if ( gfc->blocktype_old[chn] == STOP_TYPE ) { + gfc->blocktype_old[chn] = SHORT_TYPE ; + } + } + + blocktype_d[chn] = gfc->blocktype_old[chn]; /* value returned to calling program */ + gfc->blocktype_old[chn] = blocktype[chn]; /* save for next call to l3psy_anal */ + + if (gfc->presetTune.use) { + if (blocktype_d[chn] != NORM_TYPE) + gfc->presetTune.quantcomp_current = gfc->presetTune.quantcomp_type_s; + else + gfc->presetTune.quantcomp_current = gfp->experimentalX; + + if (gfc->ATH->adjust >= gfc->presetTune.athadjust_switch_level && + blocktype_d[chn] == NORM_TYPE && + gfc->presetTune.quantcomp_alt_type > -1) { + gfc->presetTune.quantcomp_current = gfc->presetTune.quantcomp_alt_type; + } + } + } + + /********************************************************************* + * compute the value of PE to return (one granule delay) + *********************************************************************/ + for(chn=0;chnanalysis) gfc->pinfo->pe[gr_out][chn] = percep_entropy[chn]; + } else { + if (blocktype_d[0] == SHORT_TYPE) { + percep_MS_entropy[chn-2] = pe_s[chn]; + } else { + percep_MS_entropy[chn-2] = pe_l[chn]; + } + if (gfp->analysis) gfc->pinfo->pe[gr_out][chn] = percep_MS_entropy[chn-2]; + } + } + + return 0; +} + + + + + +/* + * The spreading function. Values returned in units of energy + */ +FLOAT8 s3_func(FLOAT8 bark) { + + FLOAT8 tempx,x,tempy,temp; + tempx = bark; + if (tempx>=0) tempx *= 3; + else tempx *=1.5; + + if(tempx>=0.5 && tempx<=2.5) + { + temp = tempx - 0.5; + x = 8.0 * (temp*temp - 2.0 * temp); + } + else x = 0.0; + tempx += 0.474; + tempy = 15.811389 + 7.5*tempx - 17.5*sqrt(1.0+tempx*tempx); + + if (tempy <= -60.0) return 0.0; + + tempx = exp( (x + tempy)*LN_TO_LOG10 ); + + /* Normalization. The spreading function should be normalized so that: + +inf + / + | s3 [ bark ] d(bark) = 1 + / + -inf + */ + tempx /= .6609193; + return tempx; + +} + + + + + + + + +int L3para_read(lame_global_flags * gfp, FLOAT8 sfreq, int *numlines_l,int *numlines_s, +FLOAT8 *minval, +FLOAT8 s3_l[CBANDS][CBANDS], FLOAT8 s3_s[CBANDS][CBANDS], +FLOAT8 *SNR, +int *bu_l, int *bo_l, FLOAT8 *w1_l, FLOAT8 *w2_l, +int *bu_s, int *bo_s, FLOAT8 *w1_s, FLOAT8 *w2_s, +int *npart_l_orig,int *npart_l,int *npart_s_orig,int *npart_s) +{ + lame_internal_flags *gfc=gfp->internal_flags; + + + FLOAT8 bval_l[CBANDS], bval_s[CBANDS]; + FLOAT8 bval_l_width[CBANDS], bval_s_width[CBANDS]; + int i,j; + int partition[HBLKSIZE]; + + + + /* compute numlines, the number of spectral lines in each partition band */ + /* each partition band should be about DELBARK wide. */ + j=0; + for(i=0;i= j so that (bark - bark_l[i-1]) < DELBARK */ + ji = j; + bark1 = freq2bark(sfreq*ji/BLKSIZE); + + ++j2; + ji = j2; + bark2 = freq2bark(sfreq*ji/BLKSIZE); + } while ((bark2 - bark1) < DELBARK && j2<=BLKSIZE/2); + + for (k=j; k BLKSIZE/2) break; + } + *npart_l_orig = i+1; + assert(*npart_l_orig <= CBANDS); + + /* compute which partition bands are in which scalefactor bands */ + { int i1,i2,sfb,start,end; + FLOAT8 freq1,freq2; + for ( sfb = 0; sfb < SBMAX_l; sfb++ ) { + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + freq1 = sfreq*(start-.5)/(2*576); + freq2 = sfreq*(end-1+.5)/(2*576); + + i1 = floor(.5 + BLKSIZE*freq1/sfreq); + if (i1<0) i1=0; + i2 = floor(.5 + BLKSIZE*freq2/sfreq); + if (i2>BLKSIZE/2) i2=BLKSIZE/2; + + // DEBUGF(gfc,"longblock: old: (%i,%i) new: (%i,%i) %i %i \n",bu_l[sfb],bo_l[sfb],partition[i1],partition[i2],i1,i2); + + w1_l[sfb]=.5; + w2_l[sfb]=.5; + bu_l[sfb]=partition[i1]; + bo_l[sfb]=partition[i2]; + + } + } + + + /* compute bark value and ATH of each critical band */ + j = 0; + for ( i = 0; i < *npart_l_orig; i++ ) { + int k; + FLOAT8 bark1,bark2; + /* FLOAT8 mval,freq; */ + + // Calculating the medium bark scaled frequency of the spectral lines + // from j ... j + numlines[i]-1 (=spectral lines in parition band i) + + k = numlines_l[i] - 1; + bark1 = freq2bark(sfreq*(j+0)/BLKSIZE); + bark2 = freq2bark(sfreq*(j+k)/BLKSIZE); + bval_l[i] = .5*(bark1+bark2); + + bark1 = freq2bark(sfreq*(j+0-.5)/BLKSIZE); + bark2 = freq2bark(sfreq*(j+k+.5)/BLKSIZE); + bval_l_width[i] = bark2-bark1; + + gfc->ATH->cb [i] = 1.e37; // preinit for minimum search + for (k=0; k < numlines_l[i]; k++, j++) { + FLOAT8 freq = sfreq*j/(1000.0*BLKSIZE); + FLOAT8 level; + assert( freq <= 24 ); // or only '<' + // freq = Min(.1,freq); // ATH below 100 Hz constant, not further climbing + level = ATHformula (freq*1000, gfp) - 20; // scale to FFT units; returned value is in dB + level = pow ( 10., 0.1*level ); // convert from dB -> energy + level *= numlines_l [i]; + if ( level < gfc->ATH->cb [i] ) + gfc->ATH->cb [i] = level; + } + + + } + + /* MINVAL. For low freq, the strength of the masking is limited by minval + * this is an ISO MPEG1 thing, dont know if it is really needed */ + for(i=0;i<*npart_l_orig;i++){ + double x = (-20+bval_l[i]*20.0/10.0); + if (bval_l[i]>10) x = 0; + minval[i]=pow(10.0,x/10); + gfc->PSY->prvTonRed[i] = minval[i]; + } + + + + + + + + /************************************************************************/ + /* SHORT BLOCKS */ + /************************************************************************/ + + /* compute numlines */ + j=0; + for(i=0;i= j so that (bark - bark_s[i-1]) < DELBARK */ + ji = j; + bark1 = freq2bark(sfreq*ji/BLKSIZE_s); + + ++j2; + ji = j2; + bark2 = freq2bark(sfreq*ji/BLKSIZE_s); + + } while ((bark2 - bark1) < DELBARK && j2<=BLKSIZE_s/2); + + for (k=j; k BLKSIZE_s/2) break; + } + *npart_s_orig = i+1; + assert(*npart_s_orig <= CBANDS); + + /* compute which partition bands are in which scalefactor bands */ + { int i1,i2,sfb,start,end; + FLOAT8 freq1,freq2; + for ( sfb = 0; sfb < SBMAX_s; sfb++ ) { + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb+1 ]; + freq1 = sfreq*(start-.5)/(2*192); + freq2 = sfreq*(end-1+.5)/(2*192); + + i1 = floor(.5 + BLKSIZE_s*freq1/sfreq); + if (i1<0) i1=0; + i2 = floor(.5 + BLKSIZE_s*freq2/sfreq); + if (i2>BLKSIZE_s/2) i2=BLKSIZE_s/2; + + //DEBUGF(gfc,"shortblock: old: (%i,%i) new: (%i,%i) %i %i \n",bu_s[sfb],bo_s[sfb], partition[i1],partition[i2],i1,i2); + + w1_s[sfb]=.5; + w2_s[sfb]=.5; + bu_s[sfb]=partition[i1]; + bo_s[sfb]=partition[i2]; + + } + } + + + + + + /* compute bark values of each critical band */ + j = 0; + for(i=0;i<*npart_s_orig;i++) + { + int k; + FLOAT8 bark1,bark2,snr; + k = numlines_s[i] - 1; + + bark1 = freq2bark (sfreq*(j+0)/BLKSIZE_s); + bark2 = freq2bark (sfreq*(j+k)/BLKSIZE_s); + bval_s[i] = .5*(bark1+bark2); + + bark1 = freq2bark (sfreq*(j+0-.5)/BLKSIZE_s); + bark2 = freq2bark (sfreq*(j+k+.5)/BLKSIZE_s); + bval_s_width[i] = bark2-bark1; + j += k+1; + + /* SNR formula */ + if (bval_s[i]<13) + snr=-8.25; + else + snr = -4.5 * (bval_s[i]-13)/(24.0-13.0) + + -8.25*(bval_s[i]-24)/(13.0-24.0); + + SNR[i]=pow(10.0,snr/10.0); + } + + + + + + + /************************************************************************ + * Now compute the spreading function, s[j][i], the value of the spread-* + * ing function, centered at band j, for band i, store for later use * + ************************************************************************/ + /* i.e.: sum over j to spread into signal barkval=i + NOTE: i and j are used opposite as in the ISO docs */ + for(i=0;i<*npart_l_orig;i++) { + for(j=0;j<*npart_l_orig;j++) { + s3_l[i][j]=s3_func(bval_l[i]-bval_l[j])*bval_l_width[j]; + } + } + for(i=0;i<*npart_s_orig;i++) { + for(j=0;j<*npart_s_orig;j++) { + s3_s[i][j]=s3_func(bval_s[i]-bval_s[j])*bval_s_width[j]; + } + } + + + + + /* compute: */ + /* npart_l_orig = number of partition bands before convolution */ + /* npart_l = number of partition bands after convolution */ + + *npart_l=bo_l[NBPSY_l-1]+1; + *npart_s=bo_s[NBPSY_s-1]+1; + + assert(*npart_l <= *npart_l_orig); + assert(*npart_s <= *npart_s_orig); + + + /* setup stereo demasking thresholds */ + /* formula reverse enginerred from plot in paper */ + for ( i = 0; i < NBPSY_s; i++ ) { + FLOAT8 arg,mld; + arg = freq2bark(sfreq*gfc->scalefac_band.s[i]/(2*192)); + arg = (Min(arg, 15.5)/15.5); + + mld = 1.25*(1-cos(PI*arg))-2.5; + gfc->mld_s[i] = pow(10.0,mld); + } + for ( i = 0; i < NBPSY_l; i++ ) { + FLOAT8 arg,mld; + arg = freq2bark(sfreq*gfc->scalefac_band.l[i]/(2*576)); + arg = (Min(arg, 15.5)/15.5); + + mld = 1.25*(1-cos(PI*arg))-2.5; + gfc->mld_l[i] = pow(10.0,mld); + } + +#define temporalmask_sustain_sec 0.01 + + /* setup temporal masking */ + gfc->decay = exp(-1.0*LOG10/(temporalmask_sustain_sec*sfreq/192.0)); + + return 0; +} + + + + + + + + + + + +int psymodel_init(lame_global_flags *gfp) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int i,j,b,sb,k,samplerate; + + FLOAT8 s3_s[CBANDS][CBANDS]; + FLOAT8 s3_l[CBANDS][CBANDS]; + int numberOfNoneZero; + + samplerate = gfp->out_samplerate; + gfc->ms_ener_ratio_old=.25; + gfc->blocktype_old[0]=STOP_TYPE; + gfc->blocktype_old[1]=STOP_TYPE; + gfc->blocktype_old[0]=SHORT_TYPE; + gfc->blocktype_old[1]=SHORT_TYPE; + + for (i=0; i<4; ++i) { + for (j=0; jnb_1[i][j]=1e20; + gfc->nb_2[i][j]=1e20; + } + for ( sb = 0; sb < NBPSY_l; sb++ ) { + gfc->en[i].l[sb] = 1e20; + gfc->thm[i].l[sb] = 1e20; + } + for (j=0; j<3; ++j) { + for ( sb = 0; sb < NBPSY_s; sb++ ) { + gfc->en[i].s[sb][j] = 1e20; + gfc->thm[i].s[sb][j] = 1e20; + } + } + } + for (i=0; i<4; ++i) { + for (j=0; j<3; ++j) { + for ( sb = 0; sb < NBPSY_s; sb++ ) { + gfc->nsPsy.last_thm[i][sb][j] = 1e20; + } + } + } + for(i=0;i<4;i++) { + for(j=0;j<9;j++) + gfc->nsPsy.last_en_subshort[i][j] = 100; + for(j=0;j<3;j++) + gfc->nsPsy.last_attacks[i][j] = 0; + gfc->nsPsy.pe_l[i] = gfc->nsPsy.pe_s[i] = 0; + } + + + + + /* gfp->cwlimit = sfreq*j/1024.0; */ + gfc->cw_lower_index=6; + gfc->cw_upper_index = gfc->PSY->cwlimit*1024.0/gfp->out_samplerate; + gfc->cw_upper_index=Min(HBLKSIZE-4,gfc->cw_upper_index); /* j+3 < HBLKSIZE-1 */ + gfc->cw_upper_index=Max(6,gfc->cw_upper_index); + + for ( j = 0; j < HBLKSIZE; j++ ) + gfc->cw[j] = 0.4f; + + + + i=L3para_read( gfp,(FLOAT8) samplerate,gfc->numlines_l,gfc->numlines_s, + gfc->minval,s3_l,s3_s,gfc->SNR_s,gfc->bu_l, + gfc->bo_l,gfc->w1_l,gfc->w2_l, gfc->bu_s,gfc->bo_s, + gfc->w1_s,gfc->w2_s,&gfc->npart_l_orig,&gfc->npart_l, + &gfc->npart_s_orig,&gfc->npart_s ); + if (i!=0) return -1; + + + + /* npart_l_orig = number of partition bands before convolution */ + /* npart_l = number of partition bands after convolution */ + + numberOfNoneZero = 0; + for (i=0; inpart_l; i++) { + for (j = 0; j < gfc->npart_l_orig; j++) { + if (s3_l[i][j] != 0.0) + break; + } + gfc->s3ind[i][0] = j; + + for (j = gfc->npart_l_orig - 1; j > 0; j--) { + if (s3_l[i][j] != 0.0) + break; + } + gfc->s3ind[i][1] = j; + numberOfNoneZero += (gfc->s3ind[i][1] - gfc->s3ind[i][0] + 1); + } + gfc->s3_ll = malloc(sizeof(FLOAT8)*numberOfNoneZero); + if (!gfc->s3_ll) + return -1; + + k = 0; + for (i=0; inpart_l; i++) { + for (j = gfc->s3ind[i][0]; j <= gfc->s3ind[i][1]; j++) { + gfc->s3_ll[k++] = s3_l[i][j]; + } + } + + + + numberOfNoneZero = 0; + for (i=0; inpart_s; i++) { + for (j = 0; j < gfc->npart_s_orig; j++) { + if (s3_s[i][j] != 0.0) + break; + } + gfc->s3ind_s[i][0] = j; + + for (j = gfc->npart_s_orig - 1; j > 0; j--) { + if (s3_s[i][j] != 0.0) + break; + } + gfc->s3ind_s[i][1] = j; + numberOfNoneZero += (gfc->s3ind_s[i][1] - gfc->s3ind_s[i][0] + 1); + } + gfc->s3_ss = malloc(sizeof(FLOAT8)*numberOfNoneZero); + if (!gfc->s3_ss) + return -1; + + + + + /* + #include "debugscalefac.c" + */ + + + + if (gfc->nsPsy.use) { + /* long block spreading function normalization */ + for ( b = 0;b < gfc->npart_l; b++ ) { + for ( k = gfc->s3ind[b][0]; k <= gfc->s3ind[b][1]; k++ ) { + // spreading function has been properly normalized by + // multiplying by DELBARK/.6609193 = .515. + // It looks like Naoki was + // way ahead of me and added this factor here! + // it is no longer needed. + //gfc->s3_l[b][k] *= 0.5; + } + } + /* short block spreading function normalization */ + // no longer needs to be normalized, but nspsytune wants + // SNR_s applied here istead of later to save CPU cycles + for ( b = 0;b < gfc->npart_s; b++ ) { + FLOAT8 norm=0; + for ( k = gfc->s3ind_s[b][0]; k <= gfc->s3ind_s[b][1]; k++ ) { + norm += s3_s[b][k]; + } + for ( k = gfc->s3ind_s[b][0]; k <= gfc->s3ind_s[b][1]; k++ ) { + s3_s[b][k] *= gfc->SNR_s[b] /* / norm */; + } + } + } + + + + if (gfc->nsPsy.use) { +#if 1 + /* spread only from npart_l bands. Normally, we use the spreading + * function to convolve from npart_l_orig down to npart_l bands + */ + for(b=0;bnpart_l;b++) + if (gfc->s3ind[b][1] > gfc->npart_l-1) gfc->s3ind[b][1] = gfc->npart_l-1; +#endif + } + k = 0; + for (i=0; inpart_s; i++) { + for (j = gfc->s3ind_s[i][0]; j <= gfc->s3ind_s[i][1]; j++) { + gfc->s3_ss[k++] = s3_s[i][j]; + } + } + + + + /* init. for loudness approx. -jd 2001 mar 27*/ + gfc->loudness_sq_save[0] = 0.0; + gfc->loudness_sq_save[1] = 0.0; + + + + return 0; +} + + + + + +/* psycho_loudness_approx + jd - 2001 mar 12 +in: energy - BLKSIZE/2 elements of frequency magnitudes ^ 2 + gfp - uses out_samplerate, ATHtype (also needed for ATHformula) +returns: loudness^2 approximation, a positive value roughly tuned for a value + of 1.0 for signals near clipping. +notes: When calibrated, feeding this function binary white noise at sample + values +32767 or -32768 should return values that approach 3. + ATHformula is used to approximate an equal loudness curve. +future: Data indicates that the shape of the equal loudness curve varies + with intensity. This function might be improved by using an equal + loudness curve shaped for typical playback levels (instead of the + ATH, that is shaped for the threshold). A flexible realization might + simply bend the existing ATH curve to achieve the desired shape. + However, the potential gain may not be enough to justify an effort. +*/ +FLOAT +psycho_loudness_approx( FLOAT *energy, lame_global_flags *gfp ) +{ + int i; + static int eql_type = -1; + static FLOAT eql_w[BLKSIZE/2];/* equal loudness weights (based on ATH) */ + const FLOAT vo_scale= 1./( 14752 ); /* tuned for output level */ + /* (sensitive to energy scale) */ + FLOAT loudness_power; + + if( eql_type != gfp->ATHtype ) { + /* compute equal loudness weights (eql_w) */ + FLOAT freq; + FLOAT freq_inc = gfp->out_samplerate / (BLKSIZE); + FLOAT eql_balance = 0.0; + eql_type = gfp->ATHtype; + freq = 0.0; + for( i = 0; i < BLKSIZE/2; ++i ) { + freq += freq_inc; + /* convert ATH dB to relative power (not dB) */ + /* to determine eql_w */ + eql_w[i] = 1. / pow( 10, ATHformula( freq, gfp ) / 10 ); + eql_balance += eql_w[i]; + } + eql_balance = 1 / eql_balance; + for( i = BLKSIZE/2; --i >= 0; ) { /* scale weights */ + eql_w[i] *= eql_balance; + } + } + + loudness_power = 0.0; + for( i = 0; i < BLKSIZE/2; ++i ) { /* apply weights to power in freq. bands*/ + loudness_power += energy[i] * eql_w[i]; + } + loudness_power /= (BLKSIZE/2); + loudness_power *= vo_scale * vo_scale; + + return( loudness_power ); +} diff -Nru swftools-0.9.2+ds1/lib/lame/psymodel.h swftools-0.9.1/lib/lame/psymodel.h --- swftools-0.9.2+ds1/lib/lame/psymodel.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/psymodel.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * psymodel.h + * + * Copyright (c) 1999 Mark Taylor + * + * 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 LAME_PSYMODEL_H +#define LAME_PSYMODEL_H + +#include "l3side.h" + +int L3psycho_anal( lame_global_flags *gfc, + const sample_t *buffer[2], int gr, + FLOAT8 *ms_ratio, + FLOAT8 *ms_ratio_next, + III_psy_ratio ratio[2][2], + III_psy_ratio MS_ratio[2][2], + FLOAT8 pe[2], FLOAT8 pe_MS[2], FLOAT8 ener[2], + int blocktype_d[2]); + +int L3psycho_anal_ns( lame_global_flags *gfc, + const sample_t *buffer[2], int gr, + FLOAT8 *ms_ratio, + FLOAT8 *ms_ratio_next, + III_psy_ratio ratio[2][2], + III_psy_ratio MS_ratio[2][2], + FLOAT8 pe[2], FLOAT8 pe_MS[2], FLOAT8 ener[2], + int blocktype_d[2]); + + +int psymodel_init(lame_global_flags *gfp); + + +#endif /* LAME_PSYMODEL_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/quantize.c swftools-0.9.1/lib/lame/quantize.c --- swftools-0.9.2+ds1/lib/lame/quantize.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/quantize.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,1777 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999 Mark Taylor + * + * 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. + */ + +/* $Id: quantize.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#include +#include +#include "util.h" +#include "l3side.h" +#include "quantize.h" +#include "reservoir.h" +#include "quantize_pvt.h" +#include "lame-analysis.h" +#include "vbrquantize.h" + +#ifdef WITH_DMALLOC +#include +#endif + + +/************************************************************************ + * + * init_outer_loop() + * mt 6/99 + * + * initializes cod_info, scalefac and xrpow + * + * returns 0 if all energies in xr are zero, else 1 + * + ************************************************************************/ + +static int +init_outer_loop( + lame_internal_flags *gfc, + gr_info *const cod_info, + III_scalefac_t *const scalefac, + const FLOAT8 xr[576], + FLOAT8 xrpow[576] ) +{ + FLOAT8 tmp, sum = 0; + int i; + + /* initialize fresh cod_info + */ + cod_info->part2_3_length = 0; + cod_info->big_values = 0; + cod_info->count1 = 0; + cod_info->global_gain = 210; + cod_info->scalefac_compress = 0; + /* window_switching_flag was set in psymodel.c? */ + /* block_type was set in psymodel.c? */ + /* mixed_block_flag would be set in ^ */ + cod_info->table_select [0] = 0; + cod_info->table_select [1] = 0; + cod_info->table_select [2] = 0; + cod_info->subblock_gain[0] = 0; + cod_info->subblock_gain[1] = 0; + cod_info->subblock_gain[2] = 0; + cod_info->region0_count = 0; + cod_info->region1_count = 0; + cod_info->preflag = 0; + cod_info->scalefac_scale = 0; + cod_info->count1table_select = 0; + cod_info->part2_length = 0; + if (cod_info->block_type == SHORT_TYPE) { + cod_info->sfb_lmax = 0; + cod_info->sfb_smin = 0; + if (cod_info->mixed_block_flag) { + /* + * MPEG-1: sfbs 0-7 long block, 3-12 short blocks + * MPEG-2(.5): sfbs 0-5 long block, 3-12 short blocks + */ + cod_info->sfb_lmax = gfc->is_mpeg1 ? 8 : 6; + cod_info->sfb_smin = 3; + } + } else { + cod_info->sfb_lmax = SBPSY_l; + cod_info->sfb_smin = SBPSY_s; + } + cod_info->count1bits = 0; + cod_info->sfb_partition_table = nr_of_sfb_block[0][0]; + cod_info->slen[0] = 0; + cod_info->slen[1] = 0; + cod_info->slen[2] = 0; + cod_info->slen[3] = 0; + + /* fresh scalefactors are all zero + */ + memset(scalefac, 0, sizeof(III_scalefac_t)); + memset(&gfc->pseudohalf, 0, sizeof(gfc->pseudohalf)); + + /* check if there is some energy we have to quantize + * and calculate xrpow matching our fresh scalefactors + */ + for (i = 0; i < 576; ++i) { + tmp = fabs (xr[i]); + sum += tmp; + xrpow[i] = sqrt (tmp * sqrt(tmp)); + } + /* return 1 if we have something to quantize, else 0 + */ + return sum > (FLOAT8)1E-20; +} + + + +/************************************************************************ + * + * bin_search_StepSize() + * + * author/date?? + * + * binary step size search + * used by outer_loop to get a quantizer step size to start with + * + ************************************************************************/ + +typedef enum { + BINSEARCH_NONE, + BINSEARCH_UP, + BINSEARCH_DOWN +} binsearchDirection_t; + +int +bin_search_StepSize( + lame_internal_flags * const gfc, + gr_info * const cod_info, + const int desired_rate, + const int start, + const FLOAT8 xrpow [576], + int l3enc [576] ) +{ + int nBits; + int CurrentStep; + int flag_GoneOver = 0; + int StepSize = start; + + binsearchDirection_t Direction = BINSEARCH_NONE; + assert(gfc->CurrentStep); + CurrentStep = gfc->CurrentStep; + + do { + cod_info->global_gain = StepSize; + nBits = count_bits(gfc,l3enc,xrpow,cod_info); + + if (CurrentStep == 1) break; /* nothing to adjust anymore */ + + if (flag_GoneOver) CurrentStep /= 2; + + if (nBits > desired_rate) { + /* increase Quantize_StepSize */ + if (Direction == BINSEARCH_DOWN && !flag_GoneOver) { + flag_GoneOver = 1; + CurrentStep /= 2; /* late adjust */ + } + Direction = BINSEARCH_UP; + StepSize += CurrentStep; + if (StepSize > 255) break; + } + else if (nBits < desired_rate) { + /* decrease Quantize_StepSize */ + if (Direction == BINSEARCH_UP && !flag_GoneOver) { + flag_GoneOver = 1; + CurrentStep /= 2; /* late adjust */ + } + Direction = BINSEARCH_DOWN; + StepSize -= CurrentStep; + if (StepSize < 0) break; + } + else break; /* nBits == desired_rate;; most unlikely to happen.*/ + } while (1); /* For-ever, break is adjusted. */ + + CurrentStep = start - StepSize; + + gfc->CurrentStep = CurrentStep/4 != 0 ? 4 : 2; + + return nBits; +} + + + + +/*************************************************************************** + * + * inner_loop () + * + * author/date?? + * + * The code selects the best global gain for a particular set of scalefacs + * + ***************************************************************************/ + +int +inner_loop( + lame_internal_flags * const gfc, + gr_info * const cod_info, + const int max_bits, + const FLOAT8 xrpow [576], + int l3enc [576] ) +{ + int bits; + + assert(max_bits >= 0); + + /* scalefactors may have changed, so count bits + */ + bits=count_bits(gfc,l3enc,xrpow,cod_info); + + /* increase quantizer stepsize until needed bits are below maximum + */ + while (bits > max_bits) { + cod_info->global_gain++; + bits = count_bits (gfc, l3enc, xrpow, cod_info); + } + + return bits; +} + + + +/************************************************************************* + * + * loop_break() + * + * author/date?? + * + * Function: Returns zero if there is a scalefac which has not been + * amplified. Otherwise it returns one. + * + *************************************************************************/ + +inline +static int +loop_break( + const gr_info * const cod_info, + const III_scalefac_t * const scalefac ) +{ + int i, sfb; + + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) + if (scalefac->l[sfb] == 0) + return 0; + + for (sfb = cod_info->sfb_smin; sfb < SBPSY_s; sfb++) + for (i = 0; i < 3; i++) + if (scalefac->s[sfb][i] == 0 && cod_info->subblock_gain[i] == 0) + return 0; + + return 1; +} + + + + +/************************************************************************* + * + * quant_compare() + * + * author/date?? + * + * several different codes to decide which quantization is better + * + *************************************************************************/ + +inline +static int +quant_compare( + const int experimentalX, + lame_internal_flags * const gfc, + const calc_noise_result * const best, + const calc_noise_result * const calc, + const int block_type ) +{ + /* + noise is given in decibels (dB) relative to masking thesholds. + + over_noise: ??? (the previous comment is fully wrong) + tot_noise: ??? (the previous comment is fully wrong) + max_noise: max quantization noise + + */ + int better; + + switch (experimentalX) { + default: + case 0: + better = calc->over_count < best->over_count + || ( calc->over_count == best->over_count && + calc->over_noise < best->over_noise ) + || ( calc->over_count == best->over_count && + calc->over_noise == best->over_noise && + calc->tot_noise < best->tot_noise ); + break; + case 1: + better = calc->max_noise < best->max_noise; + break; + case 2: + better = calc->tot_noise < best->tot_noise; + break; + case 3: + better = ( calc->tot_noise < (gfc->presetTune.use && + block_type != NORM_TYPE ? (best->tot_noise - gfc->presetTune.quantcomp_adjust_rh_tot) + : best->tot_noise ) && + calc->max_noise < (gfc->presetTune.use && + block_type != NORM_TYPE ? (best->max_noise - gfc->presetTune.quantcomp_adjust_rh_max) + : best->max_noise )); + break; + case 4: + better = ( calc->max_noise <= 0 && + best->max_noise > 2 ) + || ( calc->max_noise <= 0 && + best->max_noise < 0 && + best->max_noise > calc->max_noise-2 && + calc->tot_noise < best->tot_noise ) + || ( calc->max_noise <= 0 && + best->max_noise > 0 && + best->max_noise > calc->max_noise-2 && + calc->tot_noise < best->tot_noise+best->over_noise ) + || ( calc->max_noise > 0 && + best->max_noise > -0.5 && + best->max_noise > calc->max_noise-1 && + calc->tot_noise+calc->over_noise < best->tot_noise+best->over_noise ) + || ( calc->max_noise > 0 && + best->max_noise > -1 && + best->max_noise > calc->max_noise-1.5 && + calc->tot_noise+calc->over_noise+calc->over_noise < best->tot_noise+best->over_noise+best->over_noise ); + break; + case 5: + better = calc->over_noise < best->over_noise + || ( calc->over_noise == best->over_noise && + calc->tot_noise < best->tot_noise ); + break; + case 6: + better = calc->over_noise < best->over_noise + || ( calc->over_noise == best->over_noise && + ( calc->max_noise < best->max_noise + || ( calc->max_noise == best->max_noise && + calc->tot_noise <= best->tot_noise ) + )); + break; + case 7: + better = calc->over_count < best->over_count + || calc->over_noise < best->over_noise; + break; + case 8: + better = calc->klemm_noise < best->klemm_noise; + break; + } + + return better; +} + + + +/************************************************************************* + * + * amp_scalefac_bands() + * + * author/date?? + * + * Amplify the scalefactor bands that violate the masking threshold. + * See ISO 11172-3 Section C.1.5.4.3.5 + * + * distort[] = noise/masking + * distort[] > 1 ==> noise is not masked + * distort[] < 1 ==> noise is masked + * max_dist = maximum value of distort[] + * + * Three algorithms: + * noise_shaping_amp + * 0 Amplify all bands with distort[]>1. + * + * 1 Amplify all bands with distort[] >= max_dist^(.5); + * ( 50% in the db scale) + * + * 2 Amplify first band with distort[] >= max_dist; + * + * + * For algorithms 0 and 1, if max_dist < 1, then amplify all bands + * with distort[] >= .95*max_dist. This is to make sure we always + * amplify at least one band. + * + * + *************************************************************************/ +static void +amp_scalefac_bands( + lame_global_flags *gfp, + const gr_info *const cod_info, + III_scalefac_t *const scalefac, + III_psy_xmin *distort, + FLOAT8 xrpow[576] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int start, end, l,i,j,sfb; + FLOAT8 ifqstep34, trigger; + + if (cod_info->scalefac_scale == 0) { + ifqstep34 = 1.29683955465100964055; /* 2**(.75*.5)*/ + } else { + ifqstep34 = 1.68179283050742922612; /* 2**(.75*1) */ + } + + /* compute maximum value of distort[] */ + trigger = 0; + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) { + if (trigger < distort->l[sfb]) + trigger = distort->l[sfb]; + } + for (sfb = cod_info->sfb_smin; sfb < SBPSY_s; sfb++) { + for (i = 0; i < 3; i++ ) { + if (trigger < distort->s[sfb][i]) + trigger = distort->s[sfb][i]; + } + } + + switch (gfc->noise_shaping_amp) { + + case 3: + case 2: + /* amplify exactly 1 band */ + //trigger = distort_thresh; + break; + + case 1: + /* amplify bands within 50% of max (on db scale) */ + if (trigger>1.0) + trigger = pow(trigger, .5); + else + trigger *= .95; + break; + + case 0: + default: + /* ISO algorithm. amplify all bands with distort>1 */ + if (trigger>1.0) + trigger=1.0; + else + trigger *= .95; + break; + } + + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++ ) { + start = gfc->scalefac_band.l[sfb]; + end = gfc->scalefac_band.l[sfb+1]; + if (distort->l[sfb]>=trigger ) { + if (gfc->noise_shaping_amp==3) { + if (gfc->pseudohalf.l[sfb]) { + gfc->pseudohalf.l[sfb] = 0; + goto done; + } + gfc->pseudohalf.l[sfb] = 1; + } + scalefac->l[sfb]++; + for ( l = start; l < end; l++ ) + xrpow[l] *= ifqstep34; + if (gfc->noise_shaping_amp==2 + ||gfc->noise_shaping_amp==3) goto done; + } + } + + for ( j=0,sfb = cod_info->sfb_smin; sfb < SBPSY_s; sfb++ ) { + start = gfc->scalefac_band.s[sfb]; + end = gfc->scalefac_band.s[sfb+1]; + for ( i = 0; i < 3; i++ ) { + int j2 = j; + if ( distort->s[sfb][i]>=trigger) { + if (gfc->noise_shaping_amp==3) { + if (gfc->pseudohalf.s[sfb][i]) { + gfc->pseudohalf.s[sfb][i] = 0; + goto done; + } + gfc->pseudohalf.s[sfb][i] = 1; + } + scalefac->s[sfb][i]++; + for (l = start; l < end; l++) + xrpow[j2++] *= ifqstep34; + if (gfc->noise_shaping_amp==2 + ||gfc->noise_shaping_amp==3) goto done; + } + j += end-start; + } + } + done: + return; +} + +/************************************************************************* + * + * inc_scalefac_scale() + * + * Takehiro Tominaga 2000-xx-xx + * + * turns on scalefac scale and adjusts scalefactors + * + *************************************************************************/ + +static void +inc_scalefac_scale ( + const lame_internal_flags * const gfc, + gr_info * const cod_info, + III_scalefac_t * const scalefac, + FLOAT8 xrpow[576] ) +{ + int start, end, l,i,j; + int sfb; + const FLOAT8 ifqstep34 = 1.29683955465100964055; + + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) { + int s = scalefac->l[sfb] + (cod_info->preflag ? pretab[sfb] : 0); + if (s & 1) { + s++; + start = gfc->scalefac_band.l[sfb]; + end = gfc->scalefac_band.l[sfb+1]; + for (l = start; l < end; l++) + xrpow[l] *= ifqstep34; + } + scalefac->l[sfb] = s >> 1; + cod_info->preflag = 0; + } + + for (j = 0, sfb = cod_info->sfb_smin; sfb < SBPSY_s; sfb++) { + start = gfc->scalefac_band.s[sfb]; + end = gfc->scalefac_band.s[sfb+1]; + for (i = 0; i < 3; i++) { + int j2 = j; + if (scalefac->s[sfb][i] & 1) { + scalefac->s[sfb][i]++; + for (l = start; l < end; l++) + xrpow[j2++] *= ifqstep34; + } + scalefac->s[sfb][i] >>= 1; + j += end-start; + } + } + cod_info->scalefac_scale = 1; +} + + + +/************************************************************************* + * + * inc_subblock_gain() + * + * Takehiro Tominaga 2000-xx-xx + * + * increases the subblock gain and adjusts scalefactors + * + *************************************************************************/ + +static int +inc_subblock_gain ( + const lame_internal_flags * const gfc, + gr_info * const cod_info, + III_scalefac_t * const scalefac, + FLOAT8 xrpow[576] ) +{ + int window; + + for (window = 0; window < 3; window++) { + int s1, s2, l; + int sfb; + s1 = s2 = 0; + + for (sfb = cod_info->sfb_smin; sfb < 6; sfb++) { + if (s1 < scalefac->s[sfb][window]) + s1 = scalefac->s[sfb][window]; + } + for (; sfb < SBPSY_s; sfb++) { + if (s2 < scalefac->s[sfb][window]) + s2 = scalefac->s[sfb][window]; + } + + if (s1 < 16 && s2 < 8) + continue; + + if (cod_info->subblock_gain[window] >= 7) + return 1; + + /* even though there is no scalefactor for sfb12 + * subblock gain affects upper frequencies too, that's why + * we have to go up to SBMAX_s + */ + cod_info->subblock_gain[window]++; + for (sfb = cod_info->sfb_smin; sfb < SBMAX_s; sfb++) { + int i, width; + int s = scalefac->s[sfb][window]; + FLOAT8 amp; + + if (s < 0) + continue; + s = s - (4 >> cod_info->scalefac_scale); + if (s >= 0) { + scalefac->s[sfb][window] = s; + continue; + } + + scalefac->s[sfb][window] = 0; + width = gfc->scalefac_band.s[sfb] - gfc->scalefac_band.s[sfb+1]; + i = gfc->scalefac_band.s[sfb] * 3 + width * window; + amp = IPOW20(210 + (s << (cod_info->scalefac_scale + 1))); + for (l = 0; l < width; l++) { + xrpow[i++] *= amp; + } + } + } + return 0; +} + + + +/******************************************************************** + * + * balance_noise() + * + * Takehiro Tominaga /date?? + * Robert Hegemann 2000-09-06: made a function of it + * + * amplifies scalefactor bands, + * - if all are already amplified returns 0 + * - if some bands are amplified too much: + * * try to increase scalefac_scale + * * if already scalefac_scale was set + * try on short blocks to increase subblock gain + * + ********************************************************************/ +inline +static int +balance_noise ( + lame_global_flags *const gfp, + gr_info * const cod_info, + III_scalefac_t * const scalefac, + III_psy_xmin *distort, + FLOAT8 xrpow[576] ) +{ + lame_internal_flags *const gfc = (lame_internal_flags *)gfp->internal_flags; + int status; + + amp_scalefac_bands ( gfp, cod_info, scalefac, distort, xrpow); + + /* check to make sure we have not amplified too much + * loop_break returns 0 if there is an unamplified scalefac + * scale_bitcount returns 0 if no scalefactors are too large + */ + + status = loop_break (cod_info, scalefac); + + if (status) + return 0; /* all bands amplified */ + + /* not all scalefactors have been amplified. so these + * scalefacs are possibly valid. encode them: + */ + if (gfc->is_mpeg1) + status = scale_bitcount (scalefac, cod_info); + else + status = scale_bitcount_lsf (gfc, scalefac, cod_info); + + if (!status) + return 1; /* amplified some bands not exceeding limits */ + + /* some scalefactors are too large. + * lets try setting scalefac_scale=1 + */ + if ((gfc->noise_shaping > 1) && (!(gfc->presetTune.use && + gfc->ATH->adjust < gfc->presetTune.athadjust_switch_level))) { + memset(&gfc->pseudohalf, 0, sizeof(gfc->pseudohalf)); + if (!cod_info->scalefac_scale) { + inc_scalefac_scale (gfc, cod_info, scalefac, xrpow); + status = 0; + } else { + if (cod_info->block_type == SHORT_TYPE ) { + status = inc_subblock_gain (gfc, cod_info, scalefac, xrpow) + || loop_break (cod_info, scalefac); + } + } + } + + if (!status) { + if (gfc->is_mpeg1 == 1) + status = scale_bitcount (scalefac, cod_info); + else + status = scale_bitcount_lsf (gfc, scalefac, cod_info); + } + return !status; +} + + + +/************************************************************************ + * + * outer_loop () + * + * Function: The outer iteration loop controls the masking conditions + * of all scalefactorbands. It computes the best scalefac and + * global gain. This module calls the inner iteration loop + * + * mt 5/99 completely rewritten to allow for bit reservoir control, + * mid/side channels with L/R or mid/side masking thresholds, + * and chooses best quantization instead of last quantization when + * no distortion free quantization can be found. + * + * added VBR support mt 5/99 + * + * some code shuffle rh 9/00 + ************************************************************************/ + +static int +outer_loop ( + lame_global_flags *gfp, + gr_info * const cod_info, + const FLOAT8 xr[576], /* magnitudes of spectral values */ + const III_psy_xmin * const l3_xmin, /* allowed distortion of the scalefactor */ + III_scalefac_t * const scalefac, /* scalefactors */ + FLOAT8 xrpow[576], /* coloured magnitudes of spectral values */ + int l3enc[576], /* vector of quantized values ix(0..575) */ + const int ch, + const int targ_bits ) /* maximum allowed bits */ +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_scalefac_t save_scalefac; + gr_info save_cod_info; + FLOAT8 save_xrpow[576]; + III_psy_xmin distort; + calc_noise_result noise_info; + calc_noise_result best_noise_info; + int l3_enc_w[576]; + int iteration = 0; + int bits_found; + int huff_bits; + int real_bits; + int better; + int over; + + int copy = 0; + int age = 0; + + noise_info.over_count = 100; + noise_info.max_noise = 0; + noise_info.tot_noise = 0; + noise_info.over_noise = 0; + + best_noise_info.over_count = 100; + + bits_found = bin_search_StepSize (gfc, cod_info, targ_bits, + gfc->OldValue[ch], xrpow, l3_enc_w); + gfc->OldValue[ch] = cod_info->global_gain; + + /* BEGIN MAIN LOOP */ + do { + iteration ++; + + /* inner_loop starts with the initial quantization step computed above + * and slowly increases until the bits < huff_bits. + * Thus it is important not to start with too large of an inital + * quantization step. Too small is ok, but inner_loop will take longer + */ + huff_bits = targ_bits - cod_info->part2_length; + if (huff_bits < 0) { + assert(iteration != 1); + /* scale factors too large, not enough bits. + * use previous quantizaton */ + break; + } + /* if this is the first iteration, + * see if we can reuse the quantization computed in + * bin_search_StepSize above */ + + if (iteration == 1) { + if (bits_found > huff_bits) { + cod_info->global_gain++; + real_bits = inner_loop (gfc, cod_info, huff_bits, xrpow, + l3_enc_w); + } else { + real_bits = bits_found; + } + } else { + real_bits = inner_loop (gfc, cod_info, huff_bits, xrpow, + l3_enc_w); + } + + cod_info->part2_3_length = real_bits; + + /* compute the distortion in this quantization */ + if (gfc->noise_shaping) + /* coefficients and thresholds both l/r (or both mid/side) */ + over = calc_noise (gfc, xr, l3_enc_w, cod_info, l3_xmin, + scalefac, &distort, &noise_info); + else { + /* fast mode, no noise shaping, we are ready */ + best_noise_info = noise_info; + copy = 0; + memcpy(l3enc, l3_enc_w, sizeof(int)*576); + break; + } + + + /* check if this quantization is better + * than our saved quantization */ + if (iteration == 1) /* the first iteration is always better */ + better = 1; + else + better = quant_compare ((gfc->presetTune.use ? gfc->presetTune.quantcomp_current + : gfp->experimentalX), + gfc, &best_noise_info, &noise_info, cod_info->block_type); + + /* save data so we can restore this quantization later */ + if (better) { + copy = 0; + best_noise_info = noise_info; + memcpy(l3enc, l3_enc_w, sizeof(int)*576); + age = 0; + } + else + age ++; + + + /******************************************************************/ + /* stopping criterion */ + /******************************************************************/ + /* if no bands with distortion and -X0, we are done */ + if (0==gfc->noise_shaping_stop && + 0==gfp->experimentalX && + (over == 0 || best_noise_info.over_count == 0) ) + break; + /* Otherwise, allow up to 3 unsuccesful tries in serial, then stop + * if our best quantization so far had no distorted bands. This + * gives us more possibilities for different quant_compare modes. + * Much more than 3 makes not a big difference, it is only slower. + */ + if (age > 3 && best_noise_info.over_count == 0) + break; + + /* Check if the last scalefactor band is distorted. + * in VBR mode we can't get rid of the distortion, so quit now + * and VBR mode will try again with more bits. + * (makes a 10% speed increase, the files I tested were + * binary identical, 2000/05/20 Robert.Hegemann@gmx.de) + * distort[] > 1 means noise > allowed noise + */ + if (gfc->sfb21_extra) { + if (cod_info->block_type == SHORT_TYPE) { + if (distort.s[SBMAX_s-1][0] > 1 || + distort.s[SBMAX_s-1][1] > 1 || + distort.s[SBMAX_s-1][2] > 1) break; + } else { + if (distort.l[SBMAX_l-1] > 1) break; + } + } + + /* save data so we can restore this quantization later */ + if (better) { + copy = 1; + save_scalefac = *scalefac; + save_cod_info = *cod_info; + if (gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh) { + /* store for later reuse */ + memcpy(save_xrpow, xrpow, sizeof(FLOAT8)*576); + } + } + + if (balance_noise (gfp, cod_info, scalefac, &distort, xrpow) == 0) + break; + } + while (1); /* main iteration loop, breaks adjusted */ + + /* finish up + */ + if (copy) { + *cod_info = save_cod_info; + *scalefac = save_scalefac; + if (gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh) + /* restore for reuse on next try */ + memcpy(xrpow, save_xrpow, sizeof(FLOAT8)*576); + } + cod_info->part2_3_length += cod_info->part2_length; + + assert (cod_info->global_gain < 256); + + return best_noise_info.over_count; +} + + + + +/************************************************************************ + * + * iteration_finish() + * + * Robert Hegemann 2000-09-06 + * + * update reservoir status after FINAL quantization/bitrate + * + * rh 2000-09-06: it will not work with CBR due to the bitstream formatter + * you will get "Error: MAX_HEADER_BUF too small in bitstream.c" + * + ************************************************************************/ + +static void +iteration_finish ( + lame_internal_flags *gfc, + FLOAT8 xr [2][2][576], + int l3_enc [2][2][576], + III_scalefac_t scalefac[2][2], + const int mean_bits ) +{ + III_side_info_t *l3_side = &gfc->l3_side; + int gr, ch, i; + + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *cod_info = &l3_side->gr[gr].ch[ch].tt; + + /* try some better scalefac storage + */ + best_scalefac_store (gfc, gr, ch, l3_enc, l3_side, scalefac); + + /* best huffman_divide may save some bits too + */ + if (gfc->use_best_huffman == 1) + best_huffman_divide (gfc, cod_info, l3_enc[gr][ch]); + + /* update reservoir status after FINAL quantization/bitrate + */ + ResvAdjust (gfc, cod_info, l3_side, mean_bits); + + /* set the sign of l3_enc from the sign of xr + */ + for (i = 0; i < 576; i++) { + if (xr[gr][ch][i] < 0) l3_enc[gr][ch][i] *= -1; + } + } /* for ch */ + } /* for gr */ + + ResvFrameEnd (gfc, l3_side, mean_bits); +} + + + +/********************************************************************* + * + * VBR_encode_granule() + * + * 2000-09-04 Robert Hegemann + * + *********************************************************************/ + +static void +VBR_encode_granule ( + lame_global_flags *gfp, + gr_info * const cod_info, + FLOAT8 xr[576], /* magnitudes of spectral values */ + const III_psy_xmin * const l3_xmin, /* allowed distortion of the scalefactor */ + III_scalefac_t * const scalefac, /* scalefactors */ + FLOAT8 xrpow[576], /* coloured magnitudes of spectral values */ + int l3_enc[576], /* vector of quantized values ix(0..575) */ + const int ch, + int min_bits, + int max_bits ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + gr_info bst_cod_info; + III_scalefac_t bst_scalefac; + FLOAT8 bst_xrpow [576]; + int bst_l3_enc[576]; + int Max_bits = max_bits; + int real_bits = max_bits+1; + int this_bits = (max_bits+min_bits)/2; + int dbits, over, found = 0; + int sfb21_extra = gfc->sfb21_extra; + + assert(Max_bits <= MAX_BITS); + + /* search within round about 40 bits of optimal + */ + do { + assert(this_bits >= min_bits); + assert(this_bits <= max_bits); + assert(min_bits <= max_bits); + + if (this_bits > Max_bits-42) + gfc->sfb21_extra = 0; + else + gfc->sfb21_extra = sfb21_extra; + + over = outer_loop ( gfp, cod_info, xr, l3_xmin, scalefac, + xrpow, l3_enc, ch, this_bits ); + + /* is quantization as good as we are looking for ? + * in this case: is no scalefactor band distorted? + */ + if (over <= 0) { + found = 1; + /* now we know it can be done with "real_bits" + * and maybe we can skip some iterations + */ + real_bits = cod_info->part2_3_length; + + /* store best quantization so far + */ + bst_cod_info = *cod_info; + bst_scalefac = *scalefac; + memcpy(bst_xrpow, xrpow, sizeof(FLOAT8)*576); + memcpy(bst_l3_enc, l3_enc, sizeof(int)*576); + + /* try with fewer bits + */ + max_bits = real_bits-32; + dbits = max_bits-min_bits; + this_bits = (max_bits+min_bits)/2; + } + else { + /* try with more bits + */ + min_bits = this_bits+32; + dbits = max_bits-min_bits; + this_bits = (max_bits+min_bits)/2; + + if (found) { + found = 2; + /* start again with best quantization so far + */ + *cod_info = bst_cod_info; + *scalefac = bst_scalefac; + memcpy(xrpow, bst_xrpow, sizeof(FLOAT8)*576); + } + } + } while (dbits>12); + + gfc->sfb21_extra = sfb21_extra; + + /* found=0 => nothing found, use last one + * found=1 => we just found the best and left the loop + * found=2 => we restored a good one and have now l3_enc to restore too + */ + if (found==2) { + memcpy(l3_enc, bst_l3_enc, sizeof(int)*576); + } + assert(cod_info->part2_3_length <= Max_bits); + +} + + + +/************************************************************************ + * + * get_framebits() + * + * Robert Hegemann 2000-09-05 + * + * calculates + * * how many bits are available for analog silent granules + * * how many bits to use for the lowest allowed bitrate + * * how many bits each bitrate would provide + * + ************************************************************************/ + +static void +get_framebits ( + lame_global_flags *gfp, + int * const analog_mean_bits, + int * const min_mean_bits, + int frameBits[15] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int bitsPerFrame, mean_bits, i; + III_side_info_t *l3_side = &gfc->l3_side; + + /* always use at least this many bits per granule per channel + * unless we detect analog silence, see below + */ + gfc->bitrate_index = gfc->VBR_min_bitrate; + getframebits (gfp, &bitsPerFrame, &mean_bits); + *min_mean_bits = mean_bits / gfc->channels_out; + + /* bits for analog silence + */ + gfc->bitrate_index = 1; + getframebits (gfp, &bitsPerFrame, &mean_bits); + *analog_mean_bits = mean_bits / gfc->channels_out; + + for (i = 1; i <= gfc->VBR_max_bitrate; i++) { + gfc->bitrate_index = i; + getframebits (gfp, &bitsPerFrame, &mean_bits); + frameBits[i] = ResvFrameBegin (gfp, l3_side, mean_bits, bitsPerFrame); + } +} + + + +/************************************************************************ + * + * calc_min_bits() + * + * Robert Hegemann 2000-09-04 + * + * determine minimal bit skeleton + * + ************************************************************************/ +inline +static int +calc_min_bits ( + lame_global_flags *gfp, + const gr_info * const cod_info, + const int pe, + const FLOAT8 ms_ener_ratio, + const int bands, + const int mch_bits, + const int analog_mean_bits, + const int min_mean_bits, + const int analog_silence, + const int ch ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int min_bits, min_pe_bits; + + if (gfc->nsPsy.use) return 126; + /* changed minimum from 1 to 126 bits + * the iteration loops require a minimum of bits + * for each granule to start with; robert 2001-07-02 */ + + /* base amount of minimum bits + */ + min_bits = Max (126, min_mean_bits); + + if (gfc->mode_ext == MPG_MD_MS_LR && ch == 1) + min_bits = Max (min_bits, mch_bits/5); + + /* bit skeleton based on PE + */ + if (cod_info->block_type == SHORT_TYPE) + /* if LAME switches to short blocks then pe is + * >= 1000 on medium surge + * >= 3000 on big surge + */ + min_pe_bits = (pe-350) * bands/39; + else + min_pe_bits = (pe-350) * bands/22; + + if (gfc->mode_ext == MPG_MD_MS_LR && ch == 1) { + /* side channel will use a lower bit skeleton based on PE + */ + FLOAT8 fac = .33 * (.5 - ms_ener_ratio) / .5; + min_pe_bits = (int)(min_pe_bits * ((1-fac)/(1+fac))); + } + min_pe_bits = Min (min_pe_bits, (1820 * gfp->out_samplerate / 44100)); + + /* determine final minimum bits + */ + if (analog_silence && !gfp->VBR_hard_min) + min_bits = analog_mean_bits; + else + min_bits = Max (min_bits, min_pe_bits); + + return min_bits; +} + + + +/********************************************************************* + * + * VBR_prepare() + * + * 2000-09-04 Robert Hegemann + * + * * converts LR to MS coding when necessary + * * calculates allowed/adjusted quantization noise amounts + * * detects analog silent frames + * + * some remarks: + * - lower masking depending on Quality setting + * - quality control together with adjusted ATH MDCT scaling + * on lower quality setting allocate more noise from + * ATH masking, and on higher quality setting allocate + * less noise from ATH masking. + * - experiments show that going more than 2dB over GPSYCHO's + * limits ends up in very annoying artefacts + * + *********************************************************************/ + +/* RH: this one needs to be overhauled sometime */ + +static int +VBR_prepare ( + lame_global_flags *gfp, + FLOAT8 pe [2][2], + FLOAT8 ms_ener_ratio [2], + FLOAT8 xr [2][2][576], + III_psy_ratio ratio [2][2], + III_psy_xmin l3_xmin [2][2], + int frameBits [16], + int *analog_mean_bits, + int *min_mean_bits, + int min_bits [2][2], + int max_bits [2][2], + int bands [2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + + + FLOAT8 masking_lower_db, adjust = 0.0; + int gr, ch; + int analog_silence = 1; + int bpf, avg, mxb, bits = 0; + + gfc->bitrate_index = gfc->VBR_max_bitrate; + getframebits (gfp, &bpf, &avg); + bpf = ResvFrameBegin (gfp, &gfc->l3_side, avg, bpf ); + avg = (bpf - 8*gfc->sideinfo_len) / gfc->mode_gr; + + get_framebits (gfp, analog_mean_bits, min_mean_bits, frameBits); + + for (gr = 0; gr < gfc->mode_gr; gr++) { + mxb = on_pe (gfp, pe, &gfc->l3_side, max_bits[gr], avg, gr); + if (gfc->mode_ext == MPG_MD_MS_LR) { + ms_convert (xr[gr], xr[gr]); + reduce_side (max_bits[gr], ms_ener_ratio[gr], avg, mxb); + } + for (ch = 0; ch < gfc->channels_out; ++ch) { + gr_info *cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + + if (gfc->nsPsy.use && gfp->VBR == vbr_rh) { + if (cod_info->block_type == NORM_TYPE) + adjust = 1.28/(1+exp(3.5-pe[gr][ch]/300.))-0.05; + else + adjust = 2.56/(1+exp(3.5-pe[gr][ch]/300.))-0.14; + } + masking_lower_db = gfc->VBR->mask_adjust - adjust; + gfc->masking_lower = pow (10.0, masking_lower_db * 0.1); + + bands[gr][ch] = calc_xmin (gfp, xr[gr][ch], ratio[gr]+ch, + cod_info, l3_xmin[gr]+ch); + if (bands[gr][ch]) + analog_silence = 0; + + min_bits[gr][ch] = calc_min_bits (gfp, cod_info, (int)pe[gr][ch], + ms_ener_ratio[gr], bands[gr][ch], + 0, *analog_mean_bits, + *min_mean_bits, analog_silence, ch); + + bits += max_bits[gr][ch]; + } + } + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + if (bits > frameBits[gfc->VBR_max_bitrate]) { + max_bits[gr][ch] *= frameBits[gfc->VBR_max_bitrate]; + max_bits[gr][ch] /= bits; + } + if (min_bits[gr][ch] > max_bits[gr][ch]) + min_bits[gr][ch] = max_bits[gr][ch]; + + } /* for ch */ + } /* for gr */ + + *min_mean_bits = Max(*min_mean_bits, 126); + + return analog_silence; +} + + +inline +void bitpressure_strategy1( + lame_internal_flags * gfc, + III_psy_xmin l3_xmin[2][2], + int min_bits[2][2], + int max_bits[2][2] ) +{ + int gr, ch, sfb; + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + if (gfc->l3_side.gr[gr].ch[ch].tt.block_type == SHORT_TYPE) { + for (sfb = 0; sfb < SBMAX_s; sfb++) { + l3_xmin[gr][ch].s[sfb][0] *= 1.+.029*sfb*sfb/SBMAX_s/SBMAX_s; + l3_xmin[gr][ch].s[sfb][1] *= 1.+.029*sfb*sfb/SBMAX_s/SBMAX_s; + l3_xmin[gr][ch].s[sfb][2] *= 1.+.029*sfb*sfb/SBMAX_s/SBMAX_s; + } + } + else { + for (sfb = 0; sfb < SBMAX_l; sfb++) + l3_xmin[gr][ch].l[sfb] *= 1.+.029*sfb*sfb/SBMAX_l/SBMAX_l; + } + max_bits[gr][ch] = Max(min_bits[gr][ch], 0.9*max_bits[gr][ch]); + } + } +} + +inline +void bitpressure_strategy2( + lame_internal_flags * gfc, + int bpf, int used, int save_bits[2][2], + int min_bits[2][2], int max_bits[2][2] ) +{ + int gr, ch; + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + max_bits[gr][ch] = save_bits[gr][ch]; + max_bits[gr][ch] *= bpf; + max_bits[gr][ch] /= used; + max_bits[gr][ch] = Max(min_bits[gr][ch],max_bits[gr][ch]); + } + } +} + +/************************************************************************ + * + * VBR_iteration_loop() + * + * tries to find out how many bits are needed for each granule and channel + * to get an acceptable quantization. An appropriate bitrate will then be + * choosed for quantization. rh 8/99 + * + * Robert Hegemann 2000-09-06 rewrite + * + ************************************************************************/ + +void +VBR_iteration_loop ( + lame_global_flags *gfp, + FLOAT8 pe [2][2], + FLOAT8 ms_ener_ratio[2], + FLOAT8 xr [2][2][576], + III_psy_ratio ratio [2][2], + int l3_enc [2][2][576], + III_scalefac_t scalefac [2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_psy_xmin l3_xmin[2][2]; + + FLOAT8 xrpow[576]; + int bands[2][2]; + int frameBits[15]; + int bitsPerFrame; + int save_bits[2][2]; + int used_bits, used_bits2; + int bits; + int min_bits[2][2], max_bits[2][2]; + int analog_mean_bits, min_mean_bits; + int mean_bits; + int ch, gr, analog_silence; + gr_info *cod_info; + III_side_info_t *l3_side = &gfc->l3_side; + + analog_silence = VBR_prepare (gfp, pe, ms_ener_ratio, xr, ratio, + l3_xmin, frameBits, &analog_mean_bits, + &min_mean_bits, min_bits, max_bits, bands); + + /*---------------------------------*/ + for(;;) { + + /* quantize granules with lowest possible number of bits + */ + + used_bits = 0; + used_bits2 = 0; + + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + int ret; + cod_info = &l3_side->gr[gr].ch[ch].tt; + + /* init_outer_loop sets up cod_info, scalefac and xrpow + */ + ret = init_outer_loop(gfc, cod_info, &scalefac[gr][ch], + xr[gr][ch], xrpow); + if (ret == 0 || max_bits[gr][ch] == 0) { + /* xr contains no energy + * l3_enc, our encoding data, will be quantized to zero + */ + memset(l3_enc[gr][ch], 0, sizeof(int)*576); + save_bits[gr][ch] = 0; + continue; /* with next channel */ + } + + if (gfp->VBR == vbr_mtrh) { + ret = VBR_noise_shaping2 (gfp, xr[gr][ch], xrpow, l3_enc[gr][ch], + min_bits[gr][ch], max_bits[gr][ch], + &scalefac[gr][ch], + &l3_xmin[gr][ch], gr, ch ); + if (ret < 0) + cod_info->part2_3_length = 100000; + } + else + VBR_encode_granule (gfp, cod_info, xr[gr][ch], &l3_xmin[gr][ch], + &scalefac[gr][ch], xrpow, l3_enc[gr][ch], + ch, min_bits[gr][ch], max_bits[gr][ch] ); + + used_bits += cod_info->part2_3_length; + save_bits[gr][ch] = Min(MAX_BITS, cod_info->part2_3_length); + used_bits2 += Min(MAX_BITS, cod_info->part2_3_length); + } /* for ch */ + } /* for gr */ + + /* find lowest bitrate able to hold used bits + */ + if (analog_silence && !gfp->VBR_hard_min) + /* we detected analog silence and the user did not specify + * any hard framesize limit, so start with smallest possible frame + */ + gfc->bitrate_index = 1; + else + gfc->bitrate_index = gfc->VBR_min_bitrate; + + for( ; gfc->bitrate_index < gfc->VBR_max_bitrate; gfc->bitrate_index++) { + if (used_bits <= frameBits[gfc->bitrate_index]) break; + } + + getframebits (gfp, &bitsPerFrame, &mean_bits); + bits = ResvFrameBegin (gfp, l3_side, mean_bits, bitsPerFrame); + + if (used_bits <= bits) break; + + switch ( gfc -> VBR -> bitpressure ) { + default: + case 1: bitpressure_strategy1( gfc, l3_xmin, min_bits, max_bits ); + break; + case 2: bitpressure_strategy2( gfc, frameBits[gfc->bitrate_index], + used_bits2, save_bits, min_bits, max_bits ); + break; + } + + } /* breaks adjusted */ + /*--------------------------------------*/ + + iteration_finish (gfc, xr, l3_enc, scalefac, mean_bits); +} + + + + + + +/******************************************************************** + * + * calc_target_bits() + * + * calculates target bits for ABR encoding + * + * mt 2000/05/31 + * + ********************************************************************/ + +static void +calc_target_bits ( + lame_global_flags * gfp, + FLOAT8 pe [2][2], + FLOAT8 ms_ener_ratio [2], + int targ_bits [2][2], + int *analog_silence_bits, + int *max_frame_bits ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_side_info_t *l3_side = &gfc->l3_side; + FLOAT8 res_factor; + int gr, ch, totbits, mean_bits, bitsPerFrame; + + gfc->bitrate_index = gfc->VBR_max_bitrate; + getframebits (gfp, &bitsPerFrame, &mean_bits); + *max_frame_bits = ResvFrameBegin (gfp, l3_side, mean_bits, bitsPerFrame); + + gfc->bitrate_index = 1; + getframebits (gfp, &bitsPerFrame, &mean_bits); + *analog_silence_bits = mean_bits / gfc->channels_out; + + mean_bits = gfp->VBR_mean_bitrate_kbps * gfp->framesize * 1000; + mean_bits /= gfp->out_samplerate; + mean_bits -= gfc->sideinfo_len*8; + mean_bits /= gfc->mode_gr; + + /* + res_factor is the percentage of the target bitrate that should + be used on average. the remaining bits are added to the + bitreservoir and used for difficult to encode frames. + + Since we are tracking the average bitrate, we should adjust + res_factor "on the fly", increasing it if the average bitrate + is greater than the requested bitrate, and decreasing it + otherwise. Reasonable ranges are from .9 to 1.0 + + Until we get the above suggestion working, we use the following + tuning: + compression ratio res_factor + 5.5 (256kbps) 1.0 no need for bitreservoir + 11 (128kbps) .93 7% held for reservoir + + with linear interpolation for other values. + + */ + res_factor = .93 + .07 * (11.0 - gfp->compression_ratio) / (11.0 - 5.5); + if (res_factor < .90) + res_factor = .90; + if (res_factor > 1.00) + res_factor = 1.00; + + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + targ_bits[gr][ch] = res_factor * (mean_bits / gfc->channels_out); + + if (pe[gr][ch] > 700) { + int add_bits = (pe[gr][ch] - 700) / 1.4; + + gr_info *cod_info = &l3_side->gr[gr].ch[ch].tt; + targ_bits[gr][ch] = res_factor * (mean_bits / gfc->channels_out); + + /* short blocks use a little extra, no matter what the pe */ + if (cod_info->block_type == SHORT_TYPE) { + if (add_bits < mean_bits/4) + add_bits = mean_bits/4; + } + /* at most increase bits by 1.5*average */ + if (add_bits > mean_bits*3/4) + add_bits = mean_bits*3/4; + else + if (add_bits < 0) + add_bits = 0; + + targ_bits[gr][ch] += add_bits; + } + }/* for ch */ + } /* for gr */ + + if (gfc->mode_ext == MPG_MD_MS_LR) + for (gr = 0; gr < gfc->mode_gr; gr++) { + reduce_side (targ_bits[gr], ms_ener_ratio[gr], mean_bits, + MAX_BITS); + } + + /* sum target bits + */ + totbits=0; + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + if (targ_bits[gr][ch] > MAX_BITS) + targ_bits[gr][ch] = MAX_BITS; + totbits += targ_bits[gr][ch]; + } + } + + /* repartion target bits if needed + */ + if (totbits > *max_frame_bits) { + for(gr = 0; gr < gfc->mode_gr; gr++) { + for(ch = 0; ch < gfc->channels_out; ch++) { + targ_bits[gr][ch] *= *max_frame_bits; + targ_bits[gr][ch] /= totbits; + } + } + } +} + + + + + + +/******************************************************************** + * + * ABR_iteration_loop() + * + * encode a frame with a disired average bitrate + * + * mt 2000/05/31 + * + ********************************************************************/ + +void +ABR_iteration_loop( + lame_global_flags *gfp, + FLOAT8 pe [2][2], + FLOAT8 ms_ener_ratio[2], + FLOAT8 xr [2][2][576], + III_psy_ratio ratio [2][2], + int l3_enc [2][2][576], + III_scalefac_t scalefac [2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_psy_xmin l3_xmin; + FLOAT8 xrpow[576]; + int targ_bits[2][2]; + int bitsPerFrame, mean_bits, totbits, max_frame_bits; + int ch, gr, ath_over, ret; + int analog_silence_bits; + gr_info *cod_info; + III_side_info_t *l3_side = &gfc->l3_side; + + calc_target_bits (gfp, pe, ms_ener_ratio, targ_bits, + &analog_silence_bits, &max_frame_bits); + + /* encode granules + */ + totbits=0; + for (gr = 0; gr < gfc->mode_gr; gr++) { + + if (gfc->mode_ext == MPG_MD_MS_LR) + ms_convert (xr[gr], xr[gr]); + + for (ch = 0; ch < gfc->channels_out; ch++) { + cod_info = &l3_side->gr[gr].ch[ch].tt; + + /* cod_info, scalefac and xrpow get initialized in init_outer_loop + */ + ret = init_outer_loop(gfc, cod_info, &scalefac[gr][ch], + xr[gr][ch], xrpow); + if (ret == 0) { + /* xr contains no energy + * l3_enc, our encoding data, will be quantized to zero + */ + memset(l3_enc[gr][ch], 0, sizeof(int)*576); + } + else { + /* xr contains energy we will have to encode + * calculate the masking abilities + * find some good quantization in outer_loop + */ + ath_over = calc_xmin (gfp, xr[gr][ch], &ratio[gr][ch], + cod_info, &l3_xmin); + if (0 == ath_over) /* analog silence */ + targ_bits[gr][ch] = analog_silence_bits; + + outer_loop (gfp, cod_info, xr[gr][ch], &l3_xmin, + &scalefac[gr][ch], xrpow, l3_enc[gr][ch], + ch, targ_bits[gr][ch]); + } + + totbits += cod_info->part2_3_length; + } /* ch */ + } /* gr */ + + /* find a bitrate which can handle totbits + */ + for (gfc->bitrate_index = gfc->VBR_min_bitrate ; + gfc->bitrate_index <= gfc->VBR_max_bitrate; + gfc->bitrate_index++ ) { + getframebits (gfp, &bitsPerFrame, &mean_bits); + max_frame_bits = ResvFrameBegin (gfp, l3_side, mean_bits, bitsPerFrame); + if (totbits <= max_frame_bits) break; + } + assert (gfc->bitrate_index <= gfc->VBR_max_bitrate); + + iteration_finish (gfc, xr, l3_enc, scalefac, mean_bits); +} + + + + + + +/************************************************************************ + * + * iteration_loop() + * + * author/date?? + * + * encodes one frame of MP3 data with constant bitrate + * + ************************************************************************/ + +void +iteration_loop( + lame_global_flags *gfp, + FLOAT8 pe [2][2], + FLOAT8 ms_ener_ratio[2], + FLOAT8 xr [2][2][576], + III_psy_ratio ratio [2][2], + int l3_enc [2][2][576], + III_scalefac_t scalefac [2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_psy_xmin l3_xmin[2]; + FLOAT8 xrpow[576]; + int targ_bits[2]; + int bitsPerFrame; + int mean_bits, max_bits; + int gr, ch, i; + III_side_info_t *l3_side = &gfc->l3_side; + gr_info *cod_info; + + getframebits (gfp, &bitsPerFrame, &mean_bits); + ResvFrameBegin (gfp, l3_side, mean_bits, bitsPerFrame ); + + /* quantize! */ + for (gr = 0; gr < gfc->mode_gr; gr++) { + + /* calculate needed bits + */ + max_bits = on_pe (gfp, pe, l3_side, targ_bits, mean_bits, gr); + + if (gfc->mode_ext == MPG_MD_MS_LR) { + ms_convert (xr[gr], xr[gr]); + reduce_side (targ_bits, ms_ener_ratio[gr], mean_bits, max_bits); + } + + for (ch=0 ; ch < gfc->channels_out ; ch ++) { + cod_info = &l3_side->gr[gr].ch[ch].tt; + + /* init_outer_loop sets up cod_info, scalefac and xrpow + */ + i = init_outer_loop(gfc, cod_info, &scalefac[gr][ch], + xr[gr][ch], xrpow); + if (i == 0) { + /* xr contains no energy, l3_enc will be quantized to zero + */ + memset(l3_enc[gr][ch], 0, sizeof(int)*576); + } + else { + /* xr contains energy we will have to encode + * calculate the masking abilities + * find some good quantization in outer_loop + */ + calc_xmin (gfp, xr[gr][ch], &ratio[gr][ch], cod_info, + &l3_xmin[ch]); + outer_loop (gfp, cod_info, xr[gr][ch], &l3_xmin[ch], + &scalefac[gr][ch], xrpow, l3_enc[gr][ch], + ch, targ_bits[ch]); + } + assert (cod_info->part2_3_length <= MAX_BITS); + + /* try some better scalefac storage + */ + best_scalefac_store (gfc, gr, ch, l3_enc, l3_side, scalefac); + + /* best huffman_divide may save some bits too + */ + if (gfc->use_best_huffman == 1) + best_huffman_divide (gfc, cod_info, l3_enc[gr][ch]); + + /* update reservoir status after FINAL quantization/bitrate + */ +#undef NORES_TEST +#ifndef NORES_TEST + ResvAdjust (gfc, cod_info, l3_side, mean_bits); +#endif + /* set the sign of l3_enc from the sign of xr + */ + for (i = 0; i < 576; i++) { + if (xr[gr][ch][i] < 0) l3_enc[gr][ch][i] *= -1; + } + } /* for ch */ + } /* for gr */ + +#ifdef NORES_TEST + /* replace ResvAdjust above with this code if you do not want + the second granule to use bits saved by the first granule. + Requires using the --nores. This is useful for testing only */ + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + cod_info = &l3_side->gr[gr].ch[ch].tt; + ResvAdjust (gfc, cod_info, l3_side, mean_bits); + } + } +#endif + + ResvFrameEnd (gfc, l3_side, mean_bits); +} + + + diff -Nru swftools-0.9.2+ds1/lib/lame/quantize.h swftools-0.9.1/lib/lame/quantize.h --- swftools-0.9.2+ds1/lib/lame/quantize.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/quantize.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999 Mark Taylor + * + * 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 LAME_QUANTIZE_H +#define LAME_QUANTIZE_H + +#include "util.h" + +void iteration_loop( lame_global_flags *gfp, + FLOAT8 pe[2][2], FLOAT8 ms_ratio[2], + FLOAT8 xr_org[2][2][576], III_psy_ratio ratio[2][2], + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]); + +void VBR_iteration_loop( lame_global_flags *gfp, + FLOAT8 pe[2][2], FLOAT8 ms_ratio[2], + FLOAT8 xr_org[2][2][576], III_psy_ratio ratio[2][2], + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]); + +void ABR_iteration_loop( lame_global_flags *gfp, + FLOAT8 pe[2][2], FLOAT8 ms_ratio[2], + FLOAT8 xr_org[2][2][576], III_psy_ratio ratio[2][2], + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]); + +#endif /* LAME_QUANTIZE_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/quantize_pvt.c swftools-0.9.1/lib/lame/quantize_pvt.c --- swftools-0.9.2+ds1/lib/lame/quantize_pvt.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/quantize_pvt.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,1207 @@ +/* + * quantize_pvt source file + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * 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. + */ + +/* $Id: quantize_pvt.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ +#include +#include "config_static.h" + +#include +#include "util.h" +#include "lame-analysis.h" +#include "tables.h" +#include "reservoir.h" +#include "quantize_pvt.h" + +#ifdef WITH_DMALLOC +#include +#endif + + +#define NSATHSCALE 100 // Assuming dynamic range=96dB, this value should be 92 + +const char slen1_tab [16] = { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 }; +const char slen2_tab [16] = { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }; + + +/* + The following table is used to implement the scalefactor + partitioning for MPEG2 as described in section + 2.4.3.2 of the IS. The indexing corresponds to the + way the tables are presented in the IS: + + [table_number][row_in_table][column of nr_of_sfb] +*/ +const int nr_of_sfb_block [6] [3] [4] = +{ + { + {6, 5, 5, 5}, + {9, 9, 9, 9}, + {6, 9, 9, 9} + }, + { + {6, 5, 7, 3}, + {9, 9, 12, 6}, + {6, 9, 12, 6} + }, + { + {11, 10, 0, 0}, + {18, 18, 0, 0}, + {15,18,0,0} + }, + { + {7, 7, 7, 0}, + {12, 12, 12, 0}, + {6, 15, 12, 0} + }, + { + {6, 6, 6, 3}, + {12, 9, 9, 6}, + {6, 12, 9, 6} + }, + { + {8, 8, 5, 0}, + {15,12,9,0}, + {6,18,9,0} + } +}; + + +/* Table B.6: layer3 preemphasis */ +const char pretab [SBMAX_l] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 +}; + +/* + Here are MPEG1 Table B.8 and MPEG2 Table B.1 + -- Layer III scalefactor bands. + Index into this using a method such as: + idx = fr_ps->header->sampling_frequency + + (fr_ps->header->version * 3) +*/ + + +const scalefac_struct sfBandIndex[9] = +{ + { /* Table B.2.b: 22.05 kHz */ + {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {0,4,8,12,18,24,32,42,56,74,100,132,174,192} + }, + { /* Table B.2.c: 24 kHz */ /* docs: 332. mpg123(broken): 330 */ + {0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278, 332, 394,464,540,576}, + {0,4,8,12,18,26,36,48,62,80,104,136,180,192} + }, + { /* Table B.2.a: 16 kHz */ + {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {0,4,8,12,18,26,36,48,62,80,104,134,174,192} + }, + { /* Table B.8.b: 44.1 kHz */ + {0,4,8,12,16,20,24,30,36,44,52,62,74,90,110,134,162,196,238,288,342,418,576}, + {0,4,8,12,16,22,30,40,52,66,84,106,136,192} + }, + { /* Table B.8.c: 48 kHz */ + {0,4,8,12,16,20,24,30,36,42,50,60,72,88,106,128,156,190,230,276,330,384,576}, + {0,4,8,12,16,22,28,38,50,64,80,100,126,192} + }, + { /* Table B.8.a: 32 kHz */ + {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576}, + {0,4,8,12,16,22,30,42,58,78,104,138,180,192} + }, + { /* MPEG-2.5 11.025 kHz */ + {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {0/3,12/3,24/3,36/3,54/3,78/3,108/3,144/3,186/3,240/3,312/3,402/3,522/3,576/3} + }, + { /* MPEG-2.5 12 kHz */ + {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {0/3,12/3,24/3,36/3,54/3,78/3,108/3,144/3,186/3,240/3,312/3,402/3,522/3,576/3} + }, + { /* MPEG-2.5 8 kHz */ + {0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576}, + {0/3,24/3,48/3,72/3,108/3,156/3,216/3,288/3,372/3,480/3,486/3,492/3,498/3,576/3} + } +}; + + + +FLOAT8 pow20[Q_MAX]; +FLOAT8 ipow20[Q_MAX]; +FLOAT8 iipow20[Q_MAX]; +FLOAT8 *iipow20_; +FLOAT8 pow43[PRECALC_SIZE]; +/* initialized in first call to iteration_init */ +FLOAT8 adj43asm[PRECALC_SIZE]; +FLOAT8 adj43[PRECALC_SIZE]; + +/************************************************************************/ +/* initialization for iteration_loop */ +/************************************************************************/ +void +iteration_init( lame_global_flags *gfp) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_side_info_t * const l3_side = &gfc->l3_side; + int i; + + if ( gfc->iteration_init_init==0 ) { + gfc->iteration_init_init=1; + + l3_side->main_data_begin = 0; + compute_ath(gfp,gfc->ATH->l,gfc->ATH->s); + + pow43[0] = 0.0; + for(i=1;iinternal_flags; + FLOAT8 ath; + + ath = ATHformula( f , gfp ); + + if (gfc->nsPsy.use) { + ath -= NSATHSCALE; + } else { + ath -= 114; + } + + /* modify the MDCT scaling for the ATH */ + ath -= gfp->ATHlower; + + /* convert to energy */ + ath = pow( 10.0, ath/10.0 ); + return ath; +} + + +void compute_ath( lame_global_flags *gfp, FLOAT8 ATH_l[], FLOAT8 ATH_s[] ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int sfb, i, start, end; + FLOAT8 ATH_f; + FLOAT8 samp_freq = gfp->out_samplerate; + + for (sfb = 0; sfb < SBMAX_l; sfb++) { + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + ATH_l[sfb]=FLOAT8_MAX; + for (i = start ; i < end; i++) { + FLOAT8 freq = i*samp_freq/(2*576); + ATH_f = ATHmdct( gfp, freq ); /* freq in kHz */ + ATH_l[sfb] = Min( ATH_l[sfb], ATH_f ); + } + } + + for (sfb = 0; sfb < SBMAX_s; sfb++){ + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb+1 ]; + ATH_s[sfb] = FLOAT8_MAX; + for (i = start ; i < end; i++) { + FLOAT8 freq = i*samp_freq/(2*192); + ATH_f = ATHmdct( gfp, freq ); /* freq in kHz */ + ATH_s[sfb] = Min( ATH_s[sfb], ATH_f ); + } + } + + /* no-ATH mode: + * reduce ATH to -200 dB + */ + + if (gfp->noATH) { + for (sfb = 0; sfb < SBMAX_l; sfb++) { + ATH_l[sfb] = 1E-37; + } + for (sfb = 0; sfb < SBMAX_s; sfb++) { + ATH_s[sfb] = 1E-37; + } + } + + /* work in progress, don't rely on it too much + */ + gfc->ATH-> floor = 10. * log10( ATHmdct( gfp, -1. ) ); + + /* + { FLOAT8 g=10000, t=1e30, x; + for ( f = 100; f < 10000; f++ ) { + x = ATHmdct( gfp, f ); + if ( t > x ) t = x, g = f; + } + printf("min=%g\n", g); + }*/ +} + + + + + +/* convert from L/R <-> Mid/Side, src == dst allowed */ +void ms_convert(FLOAT8 dst[2][576], FLOAT8 src[2][576]) +{ + FLOAT8 l; + FLOAT8 r; + int i; + for (i = 0; i < 576; ++i) { + l = src[0][i]; + r = src[1][i]; + dst[0][i] = (l+r) * (FLOAT8)(SQRT2*0.5); + dst[1][i] = (l-r) * (FLOAT8)(SQRT2*0.5); + } +} + + + +/************************************************************************ + * allocate bits among 2 channels based on PE + * mt 6/99 + * bugfixes rh 8/01: often allocated more than the allowed 4095 bits + ************************************************************************/ +int on_pe( lame_global_flags *gfp, FLOAT8 pe[][2], III_side_info_t *l3_side, + int targ_bits[2], int mean_bits, int gr ) +{ + lame_internal_flags * gfc = gfp->internal_flags; + gr_info * cod_info; + int extra_bits, tbits, bits; + int add_bits[2]; + int max_bits; /* maximum allowed bits for this granule */ + int ch; + + /* allocate targ_bits for granule */ + ResvMaxBits( gfp, mean_bits, &tbits, &extra_bits ); + max_bits = tbits + extra_bits; + if (max_bits > MAX_BITS) /* hard limit per granule */ + max_bits = MAX_BITS; + + for ( bits = 0, ch = 0; ch < gfc->channels_out; ++ch ) { + /****************************************************************** + * allocate bits for each channel + ******************************************************************/ + cod_info = &l3_side->gr[gr].ch[ch].tt; + + targ_bits[ch] = Min( MAX_BITS, tbits/gfc->channels_out ); + + if (gfc->nsPsy.use) { + add_bits[ch] = targ_bits[ch] * pe[gr][ch] / 700.0 - targ_bits[ch]; + } + else { + add_bits[ch] = (pe[gr][ch]-750) / 1.4; + /* short blocks us a little extra, no matter what the pe */ + if ( cod_info->block_type == SHORT_TYPE ) { + if (add_bits[ch] < mean_bits/4) + add_bits[ch] = mean_bits/4; + } + } + + /* at most increase bits by 1.5*average */ + if (add_bits[ch] > mean_bits*3/4) + add_bits[ch] = mean_bits*3/4; + if (add_bits[ch] < 0) + add_bits[ch] = 0; + + if (add_bits[ch]+targ_bits[ch] > MAX_BITS) + add_bits[ch] = Max( 0, MAX_BITS-targ_bits[ch] ); + + bits += add_bits[ch]; + } + if (bits > extra_bits) { + for ( ch = 0; ch < gfc->channels_out; ++ch ) { + add_bits[ch] = extra_bits * add_bits[ch] / bits; + } + } + + for ( ch = 0; ch < gfc->channels_out; ++ch ) { + targ_bits[ch] += add_bits[ch]; + extra_bits -= add_bits[ch]; + assert( targ_bits[ch] <= MAX_BITS ); + } + assert( max_bits <= MAX_BITS ); + return max_bits; +} + + + + +void reduce_side(int targ_bits[2],FLOAT8 ms_ener_ratio,int mean_bits,int max_bits) +{ + int move_bits; + FLOAT fac; + + + /* ms_ener_ratio = 0: allocate 66/33 mid/side fac=.33 + * ms_ener_ratio =.5: allocate 50/50 mid/side fac= 0 */ + /* 75/25 split is fac=.5 */ + /* float fac = .50*(.5-ms_ener_ratio[gr])/.5;*/ + fac = .33*(.5-ms_ener_ratio)/.5; + if (fac<0) fac=0; + if (fac>.5) fac=.5; + + /* number of bits to move from side channel to mid channel */ + /* move_bits = fac*targ_bits[1]; */ + move_bits = fac*.5*(targ_bits[0]+targ_bits[1]); + + if (move_bits > MAX_BITS - targ_bits[0]) { + move_bits = MAX_BITS - targ_bits[0]; + } + if (move_bits<0) move_bits=0; + + if (targ_bits[1] >= 125) { + /* dont reduce side channel below 125 bits */ + if (targ_bits[1]-move_bits > 125) { + + /* if mid channel already has 2x more than average, dont bother */ + /* mean_bits = bits per granule (for both channels) */ + if (targ_bits[0] < mean_bits) + targ_bits[0] += move_bits; + targ_bits[1] -= move_bits; + } else { + targ_bits[0] += targ_bits[1] - 125; + targ_bits[1] = 125; + } + } + + move_bits=targ_bits[0]+targ_bits[1]; + if (move_bits > max_bits) { + targ_bits[0]=(max_bits*targ_bits[0])/move_bits; + targ_bits[1]=(max_bits*targ_bits[1])/move_bits; + } + assert (targ_bits[0] <= MAX_BITS); + assert (targ_bits[1] <= MAX_BITS); +} + + +/** + * Robert Hegemann 2001-04-27: + * this adjusts the ATH, keeping the original noise floor + * affects the higher frequencies more than the lower ones + */ + +FLOAT8 athAdjust( FLOAT8 a, FLOAT8 x, FLOAT8 athFloor ) +{ + /* work in progress + */ + FLOAT8 const o = 90.30873362; + FLOAT8 const p = 94.82444863; + FLOAT8 u = 10. * log10(x); + FLOAT8 v = a*a; + FLOAT8 w = 0.0; + u -= athFloor; // undo scaling + if ( v > 1E-20 ) w = 1. + 10. * log10(v) / o; + if ( w < 0 ) w = 0.; + u *= w; + u += athFloor + o-p; // redo scaling + + return pow( 10., 0.1*u ); +} + + +/*************************************************************************/ +/* calc_xmin */ +/*************************************************************************/ + +/* + Calculate the allowed distortion for each scalefactor band, + as determined by the psychoacoustic model. + xmin(sb) = ratio(sb) * en(sb) / bw(sb) + + returns number of sfb's with energy > ATH +*/ +int calc_xmin( + lame_global_flags *gfp, + const FLOAT8 xr [576], + const III_psy_ratio * const ratio, + const gr_info * const cod_info, + III_psy_xmin * const l3_xmin ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int sfb,j,start, end, bw,l, b, ath_over=0; + FLOAT8 en0, xmin, ener, tmpATH; + ATH_t * ATH = gfc->ATH; + + if (cod_info->block_type == SHORT_TYPE) { + + for ( j = 0, sfb = 0; sfb < SBMAX_s; sfb++ ) { + if ( gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh ) + tmpATH = athAdjust( ATH->adjust, ATH->s[sfb], ATH->floor ); + else + tmpATH = ATH->adjust * ATH->s[sfb]; + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb + 1 ]; + bw = end - start; + + for ( b = 0; b < 3; b++ ) { + for (en0 = 0.0, l = start; l < end; l++) { + ener = xr[j++]; + ener = ener * ener; + en0 += ener; + } + en0 /= bw; + + if (gfp->ATHonly || gfp->ATHshort) { + xmin = tmpATH; + } + else { + xmin = ratio->en.s[sfb][b]; + if (xmin > 0.0) + xmin = en0 * ratio->thm.s[sfb][b] * gfc->masking_lower / xmin; + if (xmin < tmpATH) + xmin = tmpATH; + } + xmin *= bw; + + if (gfc->nsPsy.use) { + if (sfb <= 5) xmin *= gfc->nsPsy.bass; + else if (sfb <= 10) xmin *= gfc->nsPsy.alto; + else xmin *= gfc->nsPsy.treble; + if ((gfp->VBR == vbr_off || gfp->VBR == vbr_abr) && gfp->quality <= 1) + xmin *= 0.001; + } + l3_xmin->s[sfb][b] = xmin; + if (en0 > tmpATH) ath_over++; + } /* b */ + } /* sfb */ + + if (gfp->useTemporal) { + for (sfb = 0; sfb < SBMAX_s; sfb++ ) { + for ( b = 1; b < 3; b++ ) { + xmin = l3_xmin->s[sfb][b] * (1.0 - gfc->decay) + + l3_xmin->s[sfb][b-1] * gfc->decay; + if (l3_xmin->s[sfb][b] < xmin) + l3_xmin->s[sfb][b] = xmin; + } + } + } + + } /* end of short block case */ + else { + + for ( sfb = 0; sfb < SBMAX_l; sfb++ ){ + if ( gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh ) + tmpATH = athAdjust( ATH->adjust, ATH->l[sfb], ATH->floor ); + else + tmpATH = ATH->adjust * ATH->l[sfb]; + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + bw = end - start; + + for (en0 = 0.0, l = start; l < end; l++ ) { + ener = xr[l] * xr[l]; + en0 += ener; + } + /* why is it different from short blocks */ + if ( !gfc->nsPsy.use ) en0 /= bw; + + if (gfp->ATHonly) { + xmin = tmpATH; + } + else { + xmin = ratio->en.l[sfb]; + if (xmin > 0.0) + xmin = en0 * ratio->thm.l[sfb] * gfc->masking_lower / xmin; + if (xmin < tmpATH) + xmin = tmpATH; + } + /* why is it different from short blocks */ + if ( !gfc->nsPsy.use ) { + xmin *= bw; + } + else { + if (sfb <= 6) xmin *= gfc->nsPsy.bass; + else if (sfb <= 13) xmin *= gfc->nsPsy.alto; + else if (sfb <= 20) xmin *= gfc->nsPsy.treble; + else xmin *= gfc->nsPsy.sfb21; + if ((gfp->VBR == vbr_off || gfp->VBR == vbr_abr) && gfp->quality <= 1) + xmin *= 0.001; + } + l3_xmin->l[sfb] = xmin; + if (en0 > tmpATH) ath_over++; + } /* sfb */ + + } /* end of long block case */ + + return ath_over; +} + + + + + + + +/*************************************************************************/ +/* calc_noise */ +/*************************************************************************/ + +// -oo dB => -1.00 +// - 6 dB => -0.97 +// - 3 dB => -0.80 +// - 2 dB => -0.64 +// - 1 dB => -0.38 +// 0 dB => 0.00 +// + 1 dB => +0.49 +// + 2 dB => +1.06 +// + 3 dB => +1.68 +// + 6 dB => +3.69 +// +10 dB => +6.45 + +double penalties ( double noise ) +{ + return log ( 0.368 + 0.632 * noise * noise * noise ); +} + +/* mt 5/99: Function: Improved calc_noise for a single channel */ + +int calc_noise( + const lame_internal_flags * const gfc, + const FLOAT8 xr [576], + const int ix [576], + const gr_info * const cod_info, + const III_psy_xmin * const l3_xmin, + const III_scalefac_t * const scalefac, + III_psy_xmin * xfsf, + calc_noise_result * const res ) +{ + int sfb,start, end, j,l, i, over=0; + FLOAT8 sum; + + int count=0; + FLOAT8 noise,noise_db; + FLOAT8 over_noise_db = 0; + FLOAT8 tot_noise_db = 0; /* 0 dB relative to masking */ + FLOAT8 max_noise = 1E-20; /* -200 dB relative to masking */ + double klemm_noise = 1E-37; + + if (cod_info->block_type == SHORT_TYPE) { + int max_index = gfc->sfb21_extra ? SBMAX_s : SBPSY_s; + + for ( j=0, sfb = 0; sfb < max_index; sfb++ ) { + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb+1 ]; + for ( i = 0; i < 3; i++ ) { + FLOAT8 step; + int s; + + s = (scalefac->s[sfb][i] << (cod_info->scalefac_scale + 1)) + + cod_info->subblock_gain[i] * 8; + s = cod_info->global_gain - s; + + assert(s=0); + step = POW20(s); + sum = 0.0; + l = start; + do { + FLOAT8 temp; + temp = pow43[ix[j]]; + temp *= step; + temp -= fabs(xr[j]); + ++j; + sum += temp * temp; + l++; + } while (l < end); + noise = xfsf->s[sfb][i] = sum / l3_xmin->s[sfb][i]; + + max_noise = Max(max_noise,noise); + klemm_noise += penalties (noise); + + noise_db=10*log10(Max(noise,1E-20)); + tot_noise_db += noise_db; + + if (noise > 1) { + over++; + over_noise_db += noise_db; + } + count++; + } + } + }else{ /* cod_info->block_type == SHORT_TYPE */ + int max_index = gfc->sfb21_extra ? SBMAX_l : SBPSY_l; + + for ( sfb = 0; sfb < max_index; sfb++ ) { + FLOAT8 step; + int s = scalefac->l[sfb]; + + if (cod_info->preflag) + s += pretab[sfb]; + + s = cod_info->global_gain - (s << (cod_info->scalefac_scale + 1)); + assert(s=0); + step = POW20(s); + + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + + for ( sum = 0.0, l = start; l < end; l++ ) { + FLOAT8 temp; + temp = fabs(xr[l]) - pow43[ix[l]] * step; + sum += temp * temp; + } + noise = xfsf->l[sfb] = sum / l3_xmin->l[sfb]; + max_noise=Max(max_noise,noise); + klemm_noise += penalties (noise); + + noise_db=10*log10(Max(noise,1E-20)); + /* multiplying here is adding in dB, but can overflow */ + //tot_noise *= Max(noise, 1E-20); + tot_noise_db += noise_db; + + if (noise > 1) { + over++; + /* multiplying here is adding in dB -but can overflow */ + //over_noise *= noise; + over_noise_db += noise_db; + } + + count++; + } + } /* cod_info->block_type == SHORT_TYPE */ + + /* normalization at this point by "count" is not necessary, since + * the values are only used to compare with previous values */ + res->over_count = over; + + /* convert to db. DO NOT CHANGE THESE */ + /* tot_noise = is really the average over each sfb of: + [noise(db) - allowed_noise(db)] + + and over_noise is the same average, only over only the + bands with noise > allowed_noise. + + */ + + //res->tot_noise = 10.*log10(Max(1e-20,tot_noise )); + //res->over_noise = 10.*log10(Max(1e+00,over_noise)); + res->tot_noise = tot_noise_db; + res->over_noise = over_noise_db; + res->max_noise = 10.*log10(Max(1e-20,max_noise )); + res->klemm_noise = 10.*log10(Max(1e-20,klemm_noise)); + + return over; +} + + + + + + + + + + + + + + +/************************************************************************ + * + * set_pinfo() + * + * updates plotting data + * + * Mark Taylor 2000-??-?? + * + * Robert Hegemann: moved noise/distortion calc into it + * + ************************************************************************/ + +static +void set_pinfo ( + lame_global_flags *gfp, + const gr_info * const cod_info, + const III_psy_ratio * const ratio, + const III_scalefac_t * const scalefac, + const FLOAT8 xr[576], + const int l3_enc[576], + const int gr, + const int ch ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int sfb; + int j,i,l,start,end,bw; + FLOAT8 en0,en1; + FLOAT ifqstep = ( cod_info->scalefac_scale == 0 ) ? .5 : 1.0; + + + III_psy_xmin l3_xmin; + calc_noise_result noise; + III_psy_xmin xfsf; + + calc_xmin (gfp,xr, ratio, cod_info, &l3_xmin); + + calc_noise (gfc, xr, l3_enc, cod_info, &l3_xmin, scalefac, &xfsf, &noise); + + if (cod_info->block_type == SHORT_TYPE) { + for (j=0, sfb = 0; sfb < SBMAX_s; sfb++ ) { + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb + 1 ]; + bw = end - start; + for ( i = 0; i < 3; i++ ) { + for ( en0 = 0.0, l = start; l < end; l++ ) { + en0 += xr[j] * xr[j]; + ++j; + } + en0=Max(en0/bw,1e-20); + + +#if 0 +{ + double tot1,tot2; + if (sfben.s[sfb][i]; + + DEBUGF("%i %i sfb=%i mdct=%f fft=%f fft-mdct=%f db \n", + gr,ch,sfb, + 10*log10(Max(1e-25,ratio->en.s[sfb][i])), + 10*log10(Max(1e-25,en0)), + 10*log10((Max(1e-25,en0)/Max(1e-25,ratio->en.s[sfb][i])))); + + if (sfb==SBMAX_s-2) { + DEBUGF("%i %i toti %f %f ratio=%f db \n",gr,ch, + 10*log10(Max(1e-25,tot2)), + 10*log(Max(1e-25,tot1)), + 10*log10(Max(1e-25,tot1)/(Max(1e-25,tot2)))); + + } + } + /* + masking: multiplied by en0/fft_energy + average seems to be about -135db. + */ +} +#endif + + + /* convert to MDCT units */ + en1=1e15; /* scaling so it shows up on FFT plot */ + gfc->pinfo->xfsf_s[gr][ch][3*sfb+i] + = en1*xfsf.s[sfb][i]*l3_xmin.s[sfb][i]/bw; + gfc->pinfo->en_s[gr][ch][3*sfb+i] = en1*en0; + + if (ratio->en.s[sfb][i]>0) + en0 = en0/ratio->en.s[sfb][i]; + else + en0=0; + if (gfp->ATHonly || gfp->ATHshort) + en0=0; + + gfc->pinfo->thr_s[gr][ch][3*sfb+i] = + en1*Max(en0*ratio->thm.s[sfb][i],gfc->ATH->s[sfb]); + + + /* there is no scalefactor bands >= SBPSY_s */ + if (sfb < SBPSY_s) { + gfc->pinfo->LAMEsfb_s[gr][ch][3*sfb+i]= + -ifqstep*scalefac->s[sfb][i]; + } else { + gfc->pinfo->LAMEsfb_s[gr][ch][3*sfb+i]=0; + } + gfc->pinfo->LAMEsfb_s[gr][ch][3*sfb+i] -= + 2*cod_info->subblock_gain[i]; + } + } + } else { + for ( sfb = 0; sfb < SBMAX_l; sfb++ ) { + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + bw = end - start; + for ( en0 = 0.0, l = start; l < end; l++ ) + en0 += xr[l] * xr[l]; + if (!gfc->nsPsy.use) en0/=bw; + /* + DEBUGF("diff = %f \n",10*log10(Max(ratio[gr][ch].en.l[sfb],1e-20)) + -(10*log10(en0)+150)); + */ + +#if 0 + { + double tot1,tot2; + if (sfb==0) { + tot1=0; + tot2=0; + } + tot1 += en0; + tot2 += ratio->en.l[sfb]; + + + DEBUGF("%i %i sfb=%i mdct=%f fft=%f fft-mdct=%f db \n", + gr,ch,sfb, + 10*log10(Max(1e-25,ratio->en.l[sfb])), + 10*log10(Max(1e-25,en0)), + 10*log10((Max(1e-25,en0)/Max(1e-25,ratio->en.l[sfb])))); + + if (sfb==SBMAX_l-1) { + DEBUGF("%i %i toti %f %f ratio=%f db \n", + gr,ch, + 10*log10(Max(1e-25,tot2)), + 10*log(Max(1e-25,tot1)), + 10*log10(Max(1e-25,tot1)/(Max(1e-25,tot2)))); + } + /* + masking: multiplied by en0/fft_energy + average seems to be about -147db. + */ +} +#endif + + + /* convert to MDCT units */ + en1=1e15; /* scaling so it shows up on FFT plot */ + gfc->pinfo->xfsf[gr][ch][sfb] = en1*xfsf.l[sfb]*l3_xmin.l[sfb]/bw; + gfc->pinfo->en[gr][ch][sfb] = en1*en0; + if (ratio->en.l[sfb]>0) + en0 = en0/ratio->en.l[sfb]; + else + en0=0; + if (gfp->ATHonly) + en0=0; + gfc->pinfo->thr[gr][ch][sfb] = + en1*Max(en0*ratio->thm.l[sfb],gfc->ATH->l[sfb]); + + /* there is no scalefactor bands >= SBPSY_l */ + if (sfbl[sfb]<0) /* scfsi! */ + gfc->pinfo->LAMEsfb[gr][ch][sfb] = + gfc->pinfo->LAMEsfb[0][ch][sfb]; + else + gfc->pinfo->LAMEsfb[gr][ch][sfb] = -ifqstep*scalefac->l[sfb]; + }else{ + gfc->pinfo->LAMEsfb[gr][ch][sfb] = 0; + } + + if (cod_info->preflag && sfb>=11) + gfc->pinfo->LAMEsfb[gr][ch][sfb] -= ifqstep*pretab[sfb]; + } /* for sfb */ + } /* block type long */ + gfc->pinfo->LAMEqss [gr][ch] = cod_info->global_gain; + gfc->pinfo->LAMEmainbits[gr][ch] = cod_info->part2_3_length; + gfc->pinfo->LAMEsfbits [gr][ch] = cod_info->part2_length; + + gfc->pinfo->over [gr][ch] = noise.over_count; + gfc->pinfo->max_noise [gr][ch] = noise.max_noise; + gfc->pinfo->over_noise[gr][ch] = noise.over_noise; + gfc->pinfo->tot_noise [gr][ch] = noise.tot_noise; +} + + +/************************************************************************ + * + * set_frame_pinfo() + * + * updates plotting data for a whole frame + * + * Robert Hegemann 2000-10-21 + * + ************************************************************************/ + +void set_frame_pinfo( + lame_global_flags *gfp, + FLOAT8 xr [2][2][576], + III_psy_ratio ratio [2][2], + int l3_enc [2][2][576], + III_scalefac_t scalefac [2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + unsigned int sfb; + int ch; + int gr; + int act_l3enc[576]; + III_scalefac_t act_scalefac [2]; + int scsfi[2] = {0,0}; + + + gfc->masking_lower = 1.0; + + /* reconstruct the scalefactors in case SCSFI was used + */ + for (ch = 0; ch < gfc->channels_out; ch ++) { + for (sfb = 0; sfb < SBMAX_l; sfb ++) { + if (scalefac[1][ch].l[sfb] == -1) {/* scfsi */ + act_scalefac[ch].l[sfb] = scalefac[0][ch].l[sfb]; + scsfi[ch] = 1; + } else { + act_scalefac[ch].l[sfb] = scalefac[1][ch].l[sfb]; + } + } + } + + /* for every granule and channel patch l3_enc and set info + */ + for (gr = 0; gr < gfc->mode_gr; gr ++) { + for (ch = 0; ch < gfc->channels_out; ch ++) { + int i; + gr_info *cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + + /* revert back the sign of l3enc */ + for ( i = 0; i < 576; i++) { + if (xr[gr][ch][i] < 0) + act_l3enc[i] = -l3_enc[gr][ch][i]; + else + act_l3enc[i] = +l3_enc[gr][ch][i]; + } + if (gr == 1 && scsfi[ch]) + set_pinfo (gfp, cod_info, &ratio[gr][ch], &act_scalefac[ch], + xr[gr][ch], act_l3enc, gr, ch); + else + set_pinfo (gfp, cod_info, &ratio[gr][ch], &scalefac[gr][ch], + xr[gr][ch], act_l3enc, gr, ch); + } /* for ch */ + } /* for gr */ +} + + + + +/********************************************************************* + * nonlinear quantization of xr + * More accurate formula than the ISO formula. Takes into account + * the fact that we are quantizing xr -> ix, but we want ix^4/3 to be + * as close as possible to x^4/3. (taking the nearest int would mean + * ix is as close as possible to xr, which is different.) + * From Segher Boessenkool 11/1999 + * ASM optimization from + * Mathew Hendry 11/1999 + * Acy Stapp 11/1999 + * Takehiro Tominaga 11/1999 + * 9/00: ASM code removed in favor of IEEE754 hack. If you need + * the ASM code, check CVS circa Aug 2000. + *********************************************************************/ + + +#ifdef TAKEHIRO_IEEE754_HACK + +typedef union { + float f; + int i; +} fi_union; + +#define MAGIC_FLOAT (65536*(128)) +#define MAGIC_INT 0x4b000000 + +void quantize_xrpow(const FLOAT8 *xp, int *pi, FLOAT8 istep) +{ + /* quantize on xr^(3/4) instead of xr */ + int j; + fi_union *fi; + + fi = (fi_union *)pi; + for (j = 576 / 4 - 1; j >= 0; --j) { + double x0 = istep * xp[0]; + double x1 = istep * xp[1]; + double x2 = istep * xp[2]; + double x3 = istep * xp[3]; + + x0 += MAGIC_FLOAT; fi[0].f = x0; + x1 += MAGIC_FLOAT; fi[1].f = x1; + x2 += MAGIC_FLOAT; fi[2].f = x2; + x3 += MAGIC_FLOAT; fi[3].f = x3; + + fi[0].f = x0 + (adj43asm - MAGIC_INT)[fi[0].i]; + fi[1].f = x1 + (adj43asm - MAGIC_INT)[fi[1].i]; + fi[2].f = x2 + (adj43asm - MAGIC_INT)[fi[2].i]; + fi[3].f = x3 + (adj43asm - MAGIC_INT)[fi[3].i]; + + fi[0].i -= MAGIC_INT; + fi[1].i -= MAGIC_INT; + fi[2].i -= MAGIC_INT; + fi[3].i -= MAGIC_INT; + fi += 4; + xp += 4; + } +} + +# define ROUNDFAC -0.0946 +void quantize_xrpow_ISO(const FLOAT8 *xp, int *pi, FLOAT8 istep) +{ + /* quantize on xr^(3/4) instead of xr */ + int j; + fi_union *fi; + + fi = (fi_union *)pi; + for (j=576/4 - 1;j>=0;j--) { + fi[0].f = istep * xp[0] + (ROUNDFAC + MAGIC_FLOAT); + fi[1].f = istep * xp[1] + (ROUNDFAC + MAGIC_FLOAT); + fi[2].f = istep * xp[2] + (ROUNDFAC + MAGIC_FLOAT); + fi[3].f = istep * xp[3] + (ROUNDFAC + MAGIC_FLOAT); + + fi[0].i -= MAGIC_INT; + fi[1].i -= MAGIC_INT; + fi[2].i -= MAGIC_INT; + fi[3].i -= MAGIC_INT; + fi+=4; + xp+=4; + } +} + +#else + +/********************************************************************* + * XRPOW_FTOI is a macro to convert floats to ints. + * if XRPOW_FTOI(x) = nearest_int(x), then QUANTFAC(x)=adj43asm[x] + * ROUNDFAC= -0.0946 + * + * if XRPOW_FTOI(x) = floor(x), then QUANTFAC(x)=asj43[x] + * ROUNDFAC=0.4054 + * + * Note: using floor() or (int) is extermely slow. On machines where + * the TAKEHIRO_IEEE754_HACK code above does not work, it is worthwile + * to write some ASM for XRPOW_FTOI(). + *********************************************************************/ +#define XRPOW_FTOI(src,dest) ((dest) = (int)(src)) +#define QUANTFAC(rx) adj43[rx] +#define ROUNDFAC 0.4054 + + +void quantize_xrpow(const FLOAT8 *xr, int *ix, FLOAT8 istep) { + /* quantize on xr^(3/4) instead of xr */ + /* from Wilfried.Behne@t-online.de. Reported to be 2x faster than + the above code (when not using ASM) on PowerPC */ + int j; + + for ( j = 576/8; j > 0; --j) { + FLOAT8 x1, x2, x3, x4, x5, x6, x7, x8; + int rx1, rx2, rx3, rx4, rx5, rx6, rx7, rx8; + x1 = *xr++ * istep; + x2 = *xr++ * istep; + XRPOW_FTOI(x1, rx1); + x3 = *xr++ * istep; + XRPOW_FTOI(x2, rx2); + x4 = *xr++ * istep; + XRPOW_FTOI(x3, rx3); + x5 = *xr++ * istep; + XRPOW_FTOI(x4, rx4); + x6 = *xr++ * istep; + XRPOW_FTOI(x5, rx5); + x7 = *xr++ * istep; + XRPOW_FTOI(x6, rx6); + x8 = *xr++ * istep; + XRPOW_FTOI(x7, rx7); + x1 += QUANTFAC(rx1); + XRPOW_FTOI(x8, rx8); + x2 += QUANTFAC(rx2); + XRPOW_FTOI(x1,*ix++); + x3 += QUANTFAC(rx3); + XRPOW_FTOI(x2,*ix++); + x4 += QUANTFAC(rx4); + XRPOW_FTOI(x3,*ix++); + x5 += QUANTFAC(rx5); + XRPOW_FTOI(x4,*ix++); + x6 += QUANTFAC(rx6); + XRPOW_FTOI(x5,*ix++); + x7 += QUANTFAC(rx7); + XRPOW_FTOI(x6,*ix++); + x8 += QUANTFAC(rx8); + XRPOW_FTOI(x7,*ix++); + XRPOW_FTOI(x8,*ix++); + } +} + + + + + + +void quantize_xrpow_ISO( const FLOAT8 *xr, int *ix, FLOAT8 istep ) +{ + /* quantize on xr^(3/4) instead of xr */ + const FLOAT8 compareval0 = (1.0 - 0.4054)/istep; + int j; + /* depending on architecture, it may be worth calculating a few more + compareval's. + + eg. compareval1 = (2.0 - 0.4054/istep); + .. and then after the first compare do this ... + if compareval1>*xr then ix = 1; + + On a pentium166, it's only worth doing the one compare (as done here), + as the second compare becomes more expensive than just calculating + the value. Architectures with slow FP operations may want to add some + more comparevals. try it and send your diffs statistically speaking + + 73% of all xr*istep values give ix=0 + 16% will give 1 + 4% will give 2 + */ + for (j=576;j>0;j--) { + if (compareval0 > *xr) { + *(ix++) = 0; + xr++; + } else { + /* *(ix++) = (int)( istep*(*(xr++)) + 0.4054); */ + XRPOW_FTOI( istep*(*(xr++)) + ROUNDFAC , *(ix++) ); + } + } +} + +#endif diff -Nru swftools-0.9.2+ds1/lib/lame/quantize_pvt.h swftools-0.9.1/lib/lame/quantize_pvt.h --- swftools-0.9.2+ds1/lib/lame/quantize_pvt.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/quantize_pvt.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,124 @@ +/* + * quantize_pvt include file + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * 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 LAME_QUANTIZE_PVT_H +#define LAME_QUANTIZE_PVT_H + +#include "l3side.h" +#define IXMAX_VAL 8206 /* ix always <= 8191+15. see count_bits() */ + +/* buggy Winamp decoder cannot handle values > 8191 */ +/* #define IXMAX_VAL 8191 */ + +#define PRECALC_SIZE (IXMAX_VAL+2) + + +extern const int nr_of_sfb_block[6][3][4]; +extern const char pretab[SBMAX_l]; +extern const char slen1_tab[16]; +extern const char slen2_tab[16]; + +extern const scalefac_struct sfBandIndex[9]; + +extern FLOAT8 pow43[PRECALC_SIZE]; +extern FLOAT8 adj43[PRECALC_SIZE]; +extern FLOAT8 adj43asm[PRECALC_SIZE]; + +#define Q_MAX 330 + +extern FLOAT8 pow20[Q_MAX]; +extern FLOAT8 ipow20[Q_MAX]; +extern FLOAT8 *iipow20_; + +typedef struct calc_noise_result_t { + int over_count; /* number of quantization noise > masking */ + FLOAT8 over_noise; /* sum of quantization noise > masking */ + FLOAT8 tot_noise; /* sum of all quantization noise */ + FLOAT8 max_noise; /* max quantization noise */ + float klemm_noise; +} calc_noise_result; + +void compute_ath (lame_global_flags * gfp, FLOAT8 ATH_l[SBPSY_l], + FLOAT8 ATH_s[SBPSY_l]); + +void ms_convert (FLOAT8 xr[2][576], FLOAT8 xr_org[2][576]); + +int on_pe (lame_global_flags *gfp, FLOAT8 pe[2][2], III_side_info_t * l3_side, + int targ_bits[2], int mean_bits, int gr); + +void reduce_side (int targ_bits[2], FLOAT8 ms_ener_ratio, int mean_bits, + int max_bits); + + +int bin_search_StepSize (lame_internal_flags * const gfc, gr_info * const cod_info, + const int desired_rate, const int start, + const FLOAT8 xrpow[576], int l3enc[576]); + +int inner_loop (lame_internal_flags * const gfc, gr_info * const cod_info, const int max_bits, + const FLOAT8 xrpow[576], int l3enc[576]); + +void iteration_init (lame_global_flags *gfp); + + +int calc_xmin (lame_global_flags *gfp, const FLOAT8 xr[576], + const III_psy_ratio * const ratio, const gr_info * const cod_info, + III_psy_xmin * const l3_xmin); + +int calc_noise (const lame_internal_flags * const gfc, const FLOAT8 xr[576], + const int ix[576], const gr_info * const cod_info, + const III_psy_xmin * const l3_xmin, + const III_scalefac_t * const scalefac, + III_psy_xmin * distort, calc_noise_result * const res); + +void set_frame_pinfo (lame_global_flags *gfp, FLOAT8 xr[2][2][576], + III_psy_ratio ratio[2][2], int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]); + + +void quantize_xrpow (const FLOAT8 *xr, int *ix, FLOAT8 istep); + +void quantize_xrpow_ISO (const FLOAT8 *xr, int *ix, FLOAT8 istep); + + + +/* takehiro.c */ + +int count_bits (lame_internal_flags * const gfc, int * const ix, const FLOAT8 * const xr, + gr_info * const cod_info); + + +void best_huffman_divide (const lame_internal_flags * const gfc, + gr_info * const cod_info, int * const ix); + +void best_scalefac_store (const lame_internal_flags * gfc, const int gr, const int ch, + int l3_enc[2][2][576], III_side_info_t * const l3_side, + III_scalefac_t scalefac[2][2]); + +int scale_bitcount (III_scalefac_t * const scalefac, gr_info * const cod_info); + +int scale_bitcount_lsf (const lame_internal_flags *gfp, const III_scalefac_t * const scalefac, + gr_info * const cod_info); + +void huffman_init (lame_internal_flags * const gfc); + +#define LARGE_BITS 100000 + +#endif /* LAME_QUANTIZE_PVT_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/reservoir.c swftools-0.9.1/lib/lame/reservoir.c --- swftools-0.9.2+ds1/lib/lame/reservoir.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/reservoir.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,289 @@ +/* + * bit reservoir source file + * + * Copyright (c) 1999 Mark Taylor + * + * 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. + */ + +/* $Id: reservoir.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#include +#include "util.h" +#include "reservoir.h" + +#ifdef WITH_DMALLOC +#include +#endif + +/* + ResvFrameBegin: + Called (repeatedly) at the beginning of a frame. Updates the maximum + size of the reservoir, and checks to make sure main_data_begin + was set properly by the formatter +*/ + +/* + * Background information: + * + * This is the original text from the ISO standard. Because of + * sooo many bugs and irritations correcting comments are added + * in brackets []. A '^W' means you should remove the last word. + * + * 1) The following rule can be used to calculate the maximum + * number of bits used for one granule [^W frame]: + * At the highest possible bitrate of Layer III (320 kbps + * per stereo signal [^W^W^W], 48 kHz) the frames must be of + * [^W^W^W are designed to have] constant length, i.e. + * one buffer [^W^W the frame] length is: + * + * 320 kbps * 1152/48 kHz = 7680 bit = 960 byte + * + * This value is used as the maximum buffer per channel [^W^W] at + * lower bitrates [than 320 kbps]. At 64 kbps mono or 128 kbps + * stereo the main granule length is 64 kbps * 576/48 kHz = 768 bit + * [per granule and channel] at 48 kHz sampling frequency. + * This means that there is a maximum deviation (short time buffer + * [= reservoir]) of 7680 - 2*2*768 = 4608 bits is allowed at 64 kbps. + * The actual deviation is equal to the number of bytes [with the + * meaning of octets] denoted by the main_data_end offset pointer. + * The actual maximum deviation is (2^9-1)*8 bit = 4088 bits + * [for MPEG-1 and (2^8-1)*8 bit for MPEG-2, both are hard limits]. + * ... The xchange of buffer bits between the left and right channel + * is allowed without restrictions [exception: dual channel]. + * Because of the [constructed] constraint on the buffer size + * main_data_end is always set to 0 in the case of bit_rate_index==14, + * i.e. data rate 320 kbps per stereo signal [^W^W^W]. In this case + * all data are allocated between adjacent header [^W sync] words + * [, i.e. there is no buffering at all]. + */ + +int +ResvFrameBegin(lame_global_flags *gfp,III_side_info_t *l3_side, int mean_bits, int frameLength ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int fullFrameBits; + int resvLimit; + int maxmp3buf; + +/* + * Meaning of the variables: + * resvLimit: (0, 8, ..., 8*255 (MPEG-2), 8*511 (MPEG-1)) + * Number of bits can be stored in previous frame(s) due to + * counter size constaints + * maxmp3buf: ( ??? ... 8*1951 (MPEG-1 and 2), 8*2047 (MPEG-2.5)) + * Number of bits allowed to encode one frame (you can take 8*511 bit + * from the bit reservoir and at most 8*1440 bit from the current + * frame (320 kbps, 32 kHz), so 8*1951 bit is the largest possible + * value for MPEG-1 and -2) + * + * maximum allowed granule/channel size times 4 = 8*2047 bits., + * so this is the absolute maximum supported by the format. + * + * + * fullFrameBits: maximum number of bits available for encoding + * the current frame. + * + * mean_bits: target number of bits per granule. + * + * frameLength: + * + * gfc->ResvMax: maximum allowed reservoir + * + * gfc->ResvSize: current reservoir size + * + * l3_side->resvDrain_pre: + * ancillary data to be added to previous frame: + * (only usefull in VBR modes if it is possible to have + * maxmp3buf < fullFrameBits)). Currently disabled, + * see #define NEW_DRAIN + * + * l3_side->resvDrain_post: + * ancillary data to be added to this frame: + * + */ + + /* main_data_begin has 9 bits in MPEG-1, 8 bits MPEG-2 */ + resvLimit = (gfp->version==1) ? 8*511 : 8*255 ; + + + /* maximum allowed frame size. dont use more than this number of + bits, even if the frame has the space for them: */ + /* Bouvigne suggests this more lax interpretation of the ISO doc + instead of using 8*960. */ + if (gfp->strict_ISO) { + if (gfp->version==1) + maxmp3buf=8*((int)(320000/(gfp->out_samplerate / (FLOAT8)1152)/8 +.5)); + else + maxmp3buf=8*((int)(160000/(gfp->out_samplerate / (FLOAT8)576)/8 +.5)); + } else + /*all mp3 decoders should have enough buffer to handle this value: size of a 320kbps 32kHz frame*/ + maxmp3buf = 8*1440; + + + if ( frameLength > maxmp3buf || gfp->disable_reservoir ) { + gfc->ResvMax = 0; + } else { + gfc->ResvMax = maxmp3buf - frameLength; + if ( gfc->ResvMax > resvLimit ) + gfc->ResvMax = resvLimit; + } + + fullFrameBits = mean_bits * gfc->mode_gr + Min ( gfc->ResvSize, gfc->ResvMax ); + + if ( fullFrameBits > maxmp3buf ) + fullFrameBits = maxmp3buf; + + assert ( 0 == gfc->ResvMax % 8 ); + assert ( gfc->ResvMax >= 0 ); + + l3_side->resvDrain_pre = 0; + + if ( gfc->pinfo != NULL ) { + gfc->pinfo->mean_bits = mean_bits / 2; /* expected bits per channel per granule [is this also right for mono/stereo, MPEG-1/2 ?] */ + gfc->pinfo->resvsize = gfc->ResvSize; + } + + return fullFrameBits; +} + + +/* + ResvMaxBits + returns targ_bits: target number of bits to use for 1 granule + extra_bits: amount extra available from reservoir + Mark Taylor 4/99 +*/ +void ResvMaxBits(lame_global_flags *gfp, int mean_bits, int *targ_bits, int *extra_bits) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int add_bits; + int full_fac; + + *targ_bits = mean_bits ; + + /* extra bits if the reservoir is almost full */ + full_fac=9; + if (gfc->ResvSize > ((gfc->ResvMax * full_fac) / 10)) { + add_bits= gfc->ResvSize-((gfc->ResvMax * full_fac) / 10); + *targ_bits += add_bits; + }else { + add_bits =0 ; + /* build up reservoir. this builds the reservoir a little slower + * than FhG. It could simple be mean_bits/15, but this was rigged + * to always produce 100 (the old value) at 128kbs */ + /* *targ_bits -= (int) (mean_bits/15.2);*/ + if (!gfp->disable_reservoir) + *targ_bits -= .1*mean_bits; + } + + + /* amount from the reservoir we are allowed to use. ISO says 6/10 */ + *extra_bits = + (gfc->ResvSize < (gfc->ResvMax*6)/10 ? gfc->ResvSize : (gfc->ResvMax*6)/10); + *extra_bits -= add_bits; + + if (*extra_bits < 0) *extra_bits=0; + + +} + +/* + ResvAdjust: + Called after a granule's bit allocation. Readjusts the size of + the reservoir to reflect the granule's usage. +*/ +void +ResvAdjust(lame_internal_flags *gfc,gr_info *gi, III_side_info_t *l3_side, int mean_bits ) +{ + gfc->ResvSize += (mean_bits / gfc->channels_out) - gi->part2_3_length; +#if 0 + printf("part2_3_length: %i avg=%i incres: %i resvsize=%i\n",gi->part2_3_length, + mean_bits/gfc->channels_out, +mean_bits/gfc->channels_out-gi->part2_3_length,gfc->ResvSize); +#endif +} + + +/* + ResvFrameEnd: + Called after all granules in a frame have been allocated. Makes sure + that the reservoir size is within limits, possibly by adding stuffing + bits. +*/ +void +ResvFrameEnd(lame_internal_flags *gfc, III_side_info_t *l3_side, int mean_bits) +{ + int stuffingBits; + int over_bits; + + + /* just in case mean_bits is odd, this is necessary... */ + if ( gfc->channels_out == 2 && (mean_bits & 1) ) + gfc->ResvSize += 1; + + stuffingBits=0; + l3_side->resvDrain_post = 0; + l3_side->resvDrain_pre = 0; + + /* we must be byte aligned */ + if ( (over_bits = gfc->ResvSize % 8) != 0 ) + stuffingBits += over_bits; + + + over_bits = (gfc->ResvSize - stuffingBits) - gfc->ResvMax; + if (over_bits > 0) { + assert ( 0 == over_bits % 8 ); + assert ( over_bits >= 0 ); + stuffingBits += over_bits; + } + + +#undef NEW_DRAIN +#ifdef NEW_DRAIN + /* drain as many bits as possible into previous frame ancillary data + * In particular, in VBR mode ResvMax may have changed, and we have + * to make sure main_data_begin does not create a reservoir bigger + * than ResvMax mt 4/00*/ + { + int mdb_bytes = Min(l3_side->main_data_begin*8,stuffingBits)/8; + l3_side->resvDrain_pre += 8*mdb_bytes; + stuffingBits -= 8*mdb_bytes; + gfc->ResvSize -= 8*mdb_bytes; + l3_side->main_data_begin -= mdb_bytes; + + + /* drain just enough to be byte aligned. The remaining bits will + * be added to the reservoir, and we will deal with them next frame. + * If the next frame is at a lower bitrate, it may have a larger ResvMax, + * and we will not have to waste these bits! mt 4/00 */ + assert ( stuffingBits >= 0 ); + l3_side->resvDrain_post += (stuffingBits % 8); + gfc->ResvSize -= stuffingBits % 8; + } +#else + /* drain the rest into this frames ancillary data*/ + l3_side->resvDrain_post += stuffingBits; + gfc->ResvSize -= stuffingBits; +#endif + + return; +} + + diff -Nru swftools-0.9.2+ds1/lib/lame/reservoir.h swftools-0.9.1/lib/lame/reservoir.h --- swftools-0.9.2+ds1/lib/lame/reservoir.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/reservoir.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * bit reservoir include file + * + * Copyright (c) 1999 Mark Taylor + * + * 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 LAME_RESERVOIR_H +#define LAME_RESERVOIR_H + +int ResvFrameBegin(lame_global_flags *gfp,III_side_info_t *l3_side, int mean_bits, int frameLength ); +void ResvMaxBits(lame_global_flags *gfp, int mean_bits, int *targ_bits, int *max_bits); +void ResvAdjust(lame_internal_flags *gfc,gr_info *gi, III_side_info_t *l3_side, int mean_bits ); +void ResvFrameEnd(lame_internal_flags *gfc,III_side_info_t *l3_side, int mean_bits ); + +#endif /* LAME_RESERVOIR_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/set_get.c swftools-0.9.1/lib/lame/set_get.c --- swftools-0.9.2+ds1/lib/lame/set_get.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/set_get.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,1551 @@ +/* -*- mode: C; mode: fold -*- */ +/* + * set/get functions for lame_global_flags + * + * Copyright (c) 2001 Alexander Leidinger + * + * 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. + */ + +/* $Id: set_get.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#include +#include "util.h" +#include "bitstream.h" /* because of compute_flushbits */ + +#ifdef WITH_DMALLOC +#include +#endif + + +/* + * input stream description + */ + +/* number of samples */ +/* it's unlikely for this function to return an error */ +int +lame_set_num_samples( lame_global_flags* gfp, + unsigned long num_samples) +{ + /* default = 2^32-1 */ + + gfp->num_samples = num_samples; + + return 0; +} + +unsigned long +lame_get_num_samples( const lame_global_flags* gfp ) +{ + return gfp->num_samples; +} + + +/* input samplerate */ +int +lame_set_in_samplerate( lame_global_flags* gfp, + int in_samplerate ) +{ + /* input sample rate in Hz, default = 44100 Hz */ + gfp->in_samplerate = in_samplerate; + + return 0; +} + +int +lame_get_in_samplerate( const lame_global_flags* gfp ) +{ + return gfp->in_samplerate; +} + + +/* number of channels in input stream */ +int +lame_set_num_channels( lame_global_flags* gfp, + int num_channels ) +{ + /* default = 2 */ + + if ( 2 < num_channels || 0 == num_channels ) + return -1; /* we don't support more than 2 channels */ + + gfp->num_channels = num_channels; + + return 0; +} + +int +lame_get_num_channels( const lame_global_flags* gfp ) +{ + return gfp->num_channels; +} + + +/* scale the input by this amount before encoding (not used for decoding) */ +int +lame_set_scale( lame_global_flags* gfp, + float scale ) +{ + /* default = 0 */ + gfp->scale = scale; + + return 0; +} + +float +lame_get_scale( const lame_global_flags* gfp ) +{ + return gfp->scale; +} + + +/* scale the channel 0 (left) input by this amount before + encoding (not used for decoding) */ +int +lame_set_scale_left( lame_global_flags* gfp, + float scale ) +{ + /* default = 0 */ + gfp->scale_left = scale; + + return 0; +} + +float +lame_get_scale_left( const lame_global_flags* gfp ) +{ + return gfp->scale_left; +} + + +/* scale the channel 1 (right) input by this amount before + encoding (not used for decoding) */ +int +lame_set_scale_right( lame_global_flags* gfp, + float scale ) +{ + /* default = 0 */ + gfp->scale_right = scale; + + return 0; +} + +float +lame_get_scale_right( const lame_global_flags* gfp ) +{ + return gfp->scale_right; +} + + +/* output sample rate in Hz */ +int +lame_set_out_samplerate( lame_global_flags* gfp, + int out_samplerate ) +{ + /* + * default = 0: LAME picks best value based on the amount + * of compression + * MPEG only allows: + * MPEG1 32, 44.1, 48khz + * MPEG2 16, 22.05, 24 + * MPEG2.5 8, 11.025, 12 + * + * (not used by decoding routines) + */ + gfp->out_samplerate = out_samplerate; + + return 0; +} + +int +lame_get_out_samplerate( const lame_global_flags* gfp ) +{ + return gfp->out_samplerate; +} + + + + +/* + * general control parameters + */ + +/* collect data for an MP3 frame analzyer */ +int +lame_set_analysis( lame_global_flags* gfp, + int analysis ) +{ + /* default = 0 */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > analysis || 1 < analysis ) + return -1; + + gfp->analysis = analysis; + + return 0; +} + +int +lame_get_analysis( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->analysis && 1 >= gfp->analysis ); + + return gfp->analysis; +} + + +/* write a Xing VBR header frame */ +int +lame_set_bWriteVbrTag( lame_global_flags* gfp, + int bWriteVbrTag ) +{ + /* default = 1 (on) for VBR/ABR modes, 0 (off) for CBR mode */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > bWriteVbrTag || 1 < bWriteVbrTag ) + return -1; + + gfp->bWriteVbrTag = bWriteVbrTag; + + return 0; +} + +int +lame_get_bWriteVbrTag( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->bWriteVbrTag && 1 >= gfp->bWriteVbrTag ); + + return gfp->bWriteVbrTag; +} + + + +/* decode only, use lame/mpglib to convert mp3/ogg to wav */ +int +lame_set_decode_only( lame_global_flags* gfp, + int decode_only ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > decode_only || 1 < decode_only ) + return -1; + + gfp->decode_only = decode_only; + + return 0; +} + +int +lame_get_decode_only( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->decode_only && 1 >= gfp->decode_only ); + + return gfp->decode_only; +} + + +/* encode a Vorbis .ogg file */ +int +lame_set_ogg( lame_global_flags* gfp, + int ogg ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > ogg || 1 < ogg ) + return -1; + + gfp->ogg = ogg; + + return 0; +} + +int +lame_get_ogg( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->ogg && 1 >= gfp->ogg ); + + return gfp->ogg; +} + + +/* + * Internal algorithm selection. + * True quality is determined by the bitrate but this variable will effect + * quality by selecting expensive or cheap algorithms. + * quality=0..9. 0=best (very slow). 9=worst. + * recommended: 2 near-best quality, not too slow + * 5 good quality, fast + * 7 ok quality, really fast + */ +int +lame_set_quality( lame_global_flags* gfp, + int quality ) +{ + gfp->quality = quality; + + return 0; +} + +int +lame_get_quality( const lame_global_flags* gfp ) +{ + return gfp->quality; +} + + +/* mode = STEREO, JOINT_STEREO, DUAL_CHANNEL (not supported), MONO */ +int +lame_set_mode( lame_global_flags* gfp, + MPEG_mode mode ) +{ + /* default: lame chooses based on compression ratio and input channels */ + + if( 0 > mode || MAX_INDICATOR <= mode ) + return -1; /* Unknown MPEG mode! */ + + gfp->mode = mode; + + return 0; +} + +MPEG_mode +lame_get_mode( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->mode && MAX_INDICATOR > gfp->mode ); + + return gfp->mode; +} + + +/* Us a M/S mode with a switching threshold based on compression ratio */ +int +lame_set_mode_automs( lame_global_flags* gfp, + int mode_automs ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > mode_automs || 1 < mode_automs ) + return -1; + + gfp->mode_automs = mode_automs; + + return 0; +} + +int +lame_get_mode_automs( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->mode_automs && 1 >= gfp->mode_automs ); + + return gfp->mode_automs; +} + + +/* + * Force M/S for all frames. For testing only. + * Requires mode = 1. + */ +int +lame_set_force_ms( lame_global_flags* gfp, + int force_ms ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > force_ms || 1 < force_ms ) + return -1; + + gfp->force_ms = force_ms; + + return 0; +} + +int +lame_get_force_ms( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->force_ms && 1 >= gfp->force_ms ); + + return gfp->force_ms; +} + + +/* Use free_format. */ +int +lame_set_free_format( lame_global_flags* gfp, + int free_format ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > free_format || 1 < free_format ) + return -1; + + gfp->free_format = free_format; + + return 0; +} + +int +lame_get_free_format( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->free_format && 1 >= gfp->free_format ); + + return gfp->free_format; +} + + +/* message handlers */ +int +lame_set_errorf( lame_global_flags* gfp, + void (*func)( const char*, va_list ) ) +{ + gfp->report.errorf = func; + + return 0; +} + +int +lame_set_debugf( lame_global_flags* gfp, + void (*func)( const char*, va_list ) ) +{ + gfp->report.debugf = func; + + return 0; +} + +int +lame_set_msgf( lame_global_flags* gfp, + void (*func)( const char *, va_list ) ) +{ + gfp->report.msgf = func; + + return 0; +} + + +/* + * Set one of + * - brate + * - compression ratio. + * + * Default is compression ratio of 11. + */ +int +lame_set_brate( lame_global_flags* gfp, + int brate ) +{ + gfp->brate = brate; + + return 0; +} + +int +lame_get_brate( const lame_global_flags* gfp ) +{ + return gfp->brate; +} + +int +lame_set_compression_ratio( lame_global_flags* gfp, + float compression_ratio ) +{ + gfp->compression_ratio = compression_ratio; + + return 0; +} + +float +lame_get_compression_ratio( const lame_global_flags* gfp ) +{ + return gfp->compression_ratio; +} + + + + +/* + * frame parameters + */ + +/* Mark as copyright protected. */ +int +lame_set_copyright( lame_global_flags* gfp, + int copyright ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > copyright || 1 < copyright ) + return -1; + + gfp->copyright = copyright; + + return 0; +} + +int +lame_get_copyright( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->copyright && 1 >= gfp->copyright ); + + return gfp->copyright; +} + + +/* Mark as original. */ +int +lame_set_original( lame_global_flags* gfp, + int original ) +{ + /* default = 1 (enabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > original || 1 < original ) + return -1; + + gfp->original = original; + + return 0; +} + +int +lame_get_original( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->original && 1 >= gfp->original ); + + return gfp->original; +} + + +/* + * error_protection. + * Use 2 bytes from each frame for CRC checksum. + */ +int +lame_set_error_protection( lame_global_flags* gfp, + int error_protection ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > error_protection || 1 < error_protection ) + return -1; + + gfp->error_protection = error_protection; + + return 0; +} + +int +lame_get_error_protection( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->error_protection && 1 >= gfp->error_protection ); + + return gfp->error_protection; +} + + +/* + * padding_type. + * PAD_NO = pad no frames + * PAD_ALL = pad all frames + * PAD_ADJUST = adjust padding + */ +int +lame_set_padding_type( lame_global_flags* gfp, + Padding_type padding_type ) +{ + /* default = 2 */ + + if ( 0 > padding_type || PAD_MAX_INDICATOR < padding_type ) + return -1; /* Unknown padding type */ + + gfp->padding_type = padding_type; + + return 0; +} + +Padding_type +lame_get_padding_type( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->padding_type && PAD_MAX_INDICATOR > gfp->padding_type ); + + return gfp->padding_type; +} + + +/* MP3 'private extension' bit. Meaningless. */ +int +lame_set_extension( lame_global_flags* gfp, + int extension ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > extension || 1 < extension ) + return -1; + + gfp->extension = extension; + + return 0; +} + +int +lame_get_extension( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->extension && 1 >= gfp->extension ); + + return gfp->extension; +} + + +/* Enforce strict ISO compliance. */ +int +lame_set_strict_ISO( lame_global_flags* gfp, + int strict_ISO ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > strict_ISO || 1 < strict_ISO ) + return -1; + + gfp->strict_ISO = strict_ISO; + + return 0; +} + +int +lame_get_strict_ISO( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->strict_ISO && 1 >= gfp->strict_ISO ); + + return gfp->strict_ISO; +} + + + + +/******************************************************************** + * quantization/noise shaping + ***********************************************************************/ + +/* Disable the bit reservoir. For testing only. */ +int +lame_set_disable_reservoir( lame_global_flags* gfp, + int disable_reservoir ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > disable_reservoir || 1 < disable_reservoir ) + return -1; + + gfp->disable_reservoir = disable_reservoir; + + return 0; +} + +int +lame_get_disable_reservoir( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->disable_reservoir && 1 >= gfp->disable_reservoir ); + + return gfp->disable_reservoir; +} + + + + +/* Select a different "best quantization" function. default = 0 */ +int +lame_set_experimentalX( lame_global_flags* gfp, + int experimentalX ) +{ + gfp->experimentalX = experimentalX; + + return 0; +} + +int +lame_get_experimentalX( const lame_global_flags* gfp ) +{ + return gfp->experimentalX; +} + + +/* Another experimental option. For testing only. */ +int +lame_set_experimentalY( lame_global_flags* gfp, + int experimentalY ) +{ + gfp->experimentalY = experimentalY; + + return 0; +} + +int +lame_get_experimentalY( const lame_global_flags* gfp ) +{ + return gfp->experimentalY; +} + + +/* Another experimental option. For testing only. */ +int +lame_set_experimentalZ( lame_global_flags* gfp, + int experimentalZ ) +{ + gfp->experimentalZ += experimentalZ; + + return 0; +} + +int +lame_get_experimentalZ( const lame_global_flags* gfp ) +{ + return gfp->experimentalZ; +} + + +/* Naoki's psycho acoustic model. */ +int +lame_set_exp_nspsytune( lame_global_flags* gfp, + int exp_nspsytune ) +{ + /* default = 0 (disabled) */ + + gfp->exp_nspsytune = exp_nspsytune; + + return 0; +} + +int +lame_get_exp_nspsytune( const lame_global_flags* gfp ) +{ + return gfp->exp_nspsytune; +} + + + + +/******************************************************************** + * VBR control + ***********************************************************************/ + +// Types of VBR. default = vbr_off = CBR +int +lame_set_VBR( lame_global_flags* gfp, + vbr_mode VBR ) +{ + if( 0 > VBR || vbr_max_indicator <= VBR ) + return -1; /* Unknown VBR mode! */ + + gfp->VBR = VBR; + + return 0; +} + +vbr_mode +lame_get_VBR( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->VBR && vbr_max_indicator > gfp->VBR ); + + return gfp->VBR; +} + + +/* + * VBR quality level. + * 0 = highest + * 9 = lowest + */ +int +lame_set_VBR_q( lame_global_flags* gfp, + int VBR_q ) +{ + /* XXX: This should be an enum */ + /* to whoever added this note: why should it be an enum? + do you want to call a specific setting by name? + say VBR quality level red? */ + /* No, but VBR_Q_HIGHEST, VBR_Q_HIGH, ..., VBR_Q_MID, ... + VBR_Q_LOW, VBR_Q_LOWEST (or something like that )and a + VBR_Q_DEFAULT, which aliases the default setting of + e.g. VBR_Q_MID. */ + + + if( 0 > VBR_q || 10 <= VBR_q ) + return -1; /* Unknown VBR quality level! */ + + gfp->VBR_q = VBR_q; + + return 0; +} + +int +lame_get_VBR_q( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->VBR_q && 10 > gfp->VBR_q ); + + return gfp->VBR_q; +} + + +/* Ignored except for VBR = vbr_abr (ABR mode) */ +int +lame_set_VBR_mean_bitrate_kbps( lame_global_flags* gfp, + int VBR_mean_bitrate_kbps ) +{ + gfp->VBR_mean_bitrate_kbps = VBR_mean_bitrate_kbps; + + return 0; +} + +int +lame_get_VBR_mean_bitrate_kbps( const lame_global_flags* gfp ) +{ + return gfp->VBR_mean_bitrate_kbps; +} + +int +lame_set_VBR_min_bitrate_kbps( lame_global_flags* gfp, + int VBR_min_bitrate_kbps ) +{ + gfp->VBR_min_bitrate_kbps = VBR_min_bitrate_kbps; + + return 0; +} + +int +lame_get_VBR_min_bitrate_kbps( const lame_global_flags* gfp ) +{ + return gfp->VBR_min_bitrate_kbps; +} + +int +lame_set_VBR_max_bitrate_kbps( lame_global_flags* gfp, + int VBR_max_bitrate_kbps ) +{ + gfp->VBR_max_bitrate_kbps = VBR_max_bitrate_kbps; + + return 0; +} + +int +lame_get_VBR_max_bitrate_kbps( const lame_global_flags* gfp ) +{ + return gfp->VBR_max_bitrate_kbps; +} + + +/* + * Strictly enforce VBR_min_bitrate. + * Normally it will be violated for analog silence. + */ +int +lame_set_VBR_hard_min( lame_global_flags* gfp, + int VBR_hard_min ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > VBR_hard_min || 1 < VBR_hard_min ) + return -1; + + gfp->VBR_hard_min = VBR_hard_min; + + return 0; +} + +int +lame_get_VBR_hard_min( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->VBR_hard_min && 1 >= gfp->VBR_hard_min ); + + return gfp->VBR_hard_min; +} + + +/******************************************************************** + * Filtering control + ***********************************************************************/ + +/* + * Freqency in Hz to apply lowpass. + * 0 = default = lame chooses + * -1 = disabled + */ +int +lame_set_lowpassfreq( lame_global_flags* gfp, + int lowpassfreq ) +{ + gfp->lowpassfreq = lowpassfreq; + + return 0; +} + +int +lame_get_lowpassfreq( const lame_global_flags* gfp ) +{ + return gfp->lowpassfreq; +} + + +/* + * Width of transition band (in Hz). + * default = one polyphase filter band + */ +int +lame_set_lowpasswidth( lame_global_flags* gfp, + int lowpasswidth ) +{ + gfp->lowpasswidth = lowpasswidth; + + return 0; +} + +int +lame_get_lowpasswidth( const lame_global_flags* gfp ) +{ + return gfp->lowpasswidth; +} + + +/* + * Frequency in Hz to apply highpass. + * 0 = default = lame chooses + * -1 = disabled + */ +int +lame_set_highpassfreq( lame_global_flags* gfp, + int highpassfreq ) +{ + gfp->highpassfreq = highpassfreq; + + return 0; +} + +int +lame_get_highpassfreq( const lame_global_flags* gfp ) +{ + return gfp->highpassfreq; +} + + +/* + * Width of transition band (in Hz). + * default = one polyphase filter band + */ +int +lame_set_highpasswidth( lame_global_flags* gfp, + int highpasswidth ) +{ + gfp->highpasswidth = highpasswidth; + + return 0; +} + +int +lame_get_highpasswidth( const lame_global_flags* gfp ) +{ + return gfp->highpasswidth; +} + + + + +/* + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + */ + +/* Only use ATH for masking. */ +int +lame_set_ATHonly( lame_global_flags* gfp, + int ATHonly ) +{ + gfp->ATHonly = ATHonly; + + return 0; +} + +int +lame_get_ATHonly( const lame_global_flags* gfp ) +{ + return gfp->ATHonly; +} + + +/* Only use ATH for short blocks. */ +int +lame_set_ATHshort( lame_global_flags* gfp, + int ATHshort ) +{ + gfp->ATHshort = ATHshort; + + return 0; +} + +int +lame_get_ATHshort( const lame_global_flags* gfp ) +{ + return gfp->ATHshort; +} + + +/* Disable ATH. */ +int +lame_set_noATH( lame_global_flags* gfp, + int noATH ) +{ + gfp->noATH = noATH; + + return 0; +} + +int +lame_get_noATH( const lame_global_flags* gfp ) +{ + return gfp->noATH; +} + + +/* Select ATH formula. */ +int +lame_set_ATHtype( lame_global_flags* gfp, + int ATHtype ) +{ + /* XXX: ATHtype should be converted to an enum. */ + gfp->ATHtype = ATHtype; + + return 0; +} + +int +lame_get_ATHtype( const lame_global_flags* gfp ) +{ + return gfp->ATHtype; +} + + +/* Lower ATH by this many db. */ +int +lame_set_ATHlower( lame_global_flags* gfp, + float ATHlower ) +{ + gfp->ATHlower = ATHlower; + return 0; +} + +float +lame_get_ATHlower( const lame_global_flags* gfp ) +{ + return gfp->ATHlower; +} + + +/* Select ATH adaptive adjustment scheme. */ +int +lame_set_athaa_type( lame_global_flags* gfp, + int athaa_type ) +{ + gfp->athaa_type = athaa_type; + + return 0; +} + +int +lame_get_athaa_type( const lame_global_flags* gfp ) +{ + return gfp->athaa_type; +} + + +/* Select the loudness approximation used by the ATH adaptive auto-leveling. */ +int +lame_set_athaa_loudapprox( lame_global_flags* gfp, + int athaa_loudapprox ) +{ + gfp->athaa_loudapprox = athaa_loudapprox; + + return 0; +} + +int +lame_get_athaa_loudapprox( const lame_global_flags* gfp ) +{ + return gfp->athaa_loudapprox; +} + + +/* Adjust (in dB) the point below which adaptive ATH level adjustment occurs. */ +int +lame_set_athaa_sensitivity( lame_global_flags* gfp, + float athaa_sensitivity ) +{ + gfp->athaa_sensitivity = athaa_sensitivity; + + return 0; +} + +float +lame_get_athaa_sensitivity( const lame_global_flags* gfp ) +{ + return gfp->athaa_sensitivity; +} + + +/* Predictability limit (ISO tonality formula) */ +int +lame_set_cwlimit( lame_global_flags* gfp, + int cwlimit ) +{ + gfp->cwlimit = cwlimit; + + return 0; +} + +int +lame_get_cwlimit( const lame_global_flags* gfp ) +{ + return gfp->cwlimit; +} + + + +/* + * Allow blocktypes to differ between channels. + * default: + * 0 for jstereo => block types coupled + * 1 for stereo => block types may differ + */ +int +lame_set_allow_diff_short( lame_global_flags* gfp, + int allow_diff_short ) +{ + gfp->short_blocks = + allow_diff_short ? short_block_allowed : short_block_coupled; + + return 0; +} + +int +lame_get_allow_diff_short( const lame_global_flags* gfp ) +{ + if ( gfp->short_blocks == short_block_allowed ) + return 1; /* short blocks allowed to differ */ + else + return 0; /* not set, dispensed, forced or coupled */ +} + + +/* Use temporal masking effect */ +int +lame_set_useTemporal( lame_global_flags* gfp, + int useTemporal ) +{ + /* default = 1 (enabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > useTemporal || 1 < useTemporal ) + return -1; + + gfp->useTemporal = useTemporal; + + return 0; +} + +int +lame_get_useTemporal( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->useTemporal && 1 >= gfp->useTemporal ); + + return gfp->useTemporal; +} + + +/* Disable short blocks. */ +int +lame_set_no_short_blocks( lame_global_flags* gfp, + int no_short_blocks ) +{ + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > no_short_blocks || 1 < no_short_blocks ) + return -1; + + gfp->short_blocks = + no_short_blocks ? short_block_dispensed : short_block_allowed; + + return 0; +} +int +lame_get_no_short_blocks( const lame_global_flags* gfp ) +{ + switch ( gfp->short_blocks ) { + default: + case short_block_not_set: return -1; + case short_block_dispensed: return 1; + case short_block_allowed: + case short_block_coupled: + case short_block_forced: return 0; + } +} + + +/* Force short blocks. */ +int +lame_set_force_short_blocks( lame_global_flags* gfp, + int short_blocks ) +{ + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > short_blocks || 1 < short_blocks ) + return -1; + + if (short_blocks == 1) + gfp->short_blocks = short_block_forced; + else if (gfp->short_blocks == short_block_forced) + gfp->short_blocks = short_block_allowed; + + return 0; +} +int +lame_get_force_short_blocks( const lame_global_flags* gfp ) +{ + switch ( gfp->short_blocks ) { + default: + case short_block_not_set: return -1; + case short_block_dispensed: + case short_block_allowed: + case short_block_coupled: return 0; + case short_block_forced: return 1; + } +} + + +/* + * Input PCM is emphased PCM + * (for instance from one of the rarely emphased CDs). + * + * It is STRONGLY not recommended to use this, because psycho does not + * take it into account, and last but not least many decoders + * ignore these bits + */ +int +lame_set_emphasis( lame_global_flags* gfp, + int emphasis ) +{ + /* XXX: emphasis should be converted to an enum */ + if ( 0 > emphasis || 4 <= emphasis ) + return -1; + + gfp->emphasis = emphasis; + + return 0; +} + +int +lame_get_emphasis( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->emphasis && 4 > gfp->emphasis ); + + return gfp->emphasis; +} + + + + +/***************************************************************/ +/* internal variables, cannot be set... */ +/* provided because they may be of use to calling application */ +/***************************************************************/ + +/* MPEG version. + * 0 = MPEG-2 + * 1 = MPEG-1 + * (2 = MPEG-2.5) + */ +int +lame_get_version( const lame_global_flags* gfp ) +{ + return gfp->version; +} + + +/* Encoder delay. */ +int +lame_get_encoder_delay( const lame_global_flags* gfp ) +{ + return gfp->encoder_delay; +} + +/* padding added to the end of the input */ +int +lame_get_encoder_padding( const lame_global_flags* gfp ) +{ + return gfp->encoder_padding; +} + + +/* Size of MPEG frame. */ +int +lame_get_framesize( const lame_global_flags* gfp ) +{ + return gfp->framesize; +} + + +/* Number of frames encoded so far. */ +int +lame_get_frameNum( const lame_global_flags* gfp ) +{ + return gfp->frameNum; +} + +int +lame_get_mf_samples_to_encode( const lame_global_flags* gfp ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + return gfc->mf_samples_to_encode; +} + + +int CDECL lame_get_size_mp3buffer( const lame_global_flags* gfp ) +{ + int size; + compute_flushbits(gfp,&size); + return size; +} + + + +/* + * LAME's estimate of the total number of frames to be encoded. + * Only valid if calling program set num_samples. + */ +int +lame_get_totalframes( const lame_global_flags* gfp ) +{ + int totalframes; + /* estimate based on user set num_samples: */ + totalframes = + 2 + ((double)gfp->num_samples * gfp->out_samplerate) / + ((double)gfp->in_samplerate * gfp->framesize); + + /* check to see if we underestimated totalframes */ + // if (totalframes < gfp->frameNum) + // totalframes = gfp->frameNum; + + return totalframes; +} + + +/* + +UNDOCUMENTED, experimental settings. These routines are not prototyped +in lame.h. You should not use them, they are experimental and may +change. + +*/ + + +/* + * just another daily changing developer switch + */ +void lame_set_tune( lame_global_flags* gfp, float val ) +{ + gfp->tune_value_a = val; + gfp->tune = 1; +} + +/* Custom msfix hack */ +void +lame_set_msfix( lame_global_flags* gfp, double msfix ) +{ + /* default = 0 */ + gfp->msfix = msfix; + +} + +int +lame_set_preset_expopts( lame_global_flags* gfp, int preset_expopts ) +{ + + lame_internal_flags *gfc = gfp->internal_flags; + + gfc->presetTune.use = 1; + + /* default = 0 (disabled) */ + gfp->preset_expopts = preset_expopts; + + switch (preset_expopts) + { + case 1: + + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 1); + lame_set_experimentalX(gfp, 3); + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); // safejoint + lame_set_ATHtype(gfp, 2); + + gfc->presetTune.attackthre = 35; + gfc->presetTune.attackthre_s = 150; + gfc->presetTune.ms_maskadjust = .5; + gfc->presetTune.quantcomp_type_s = 3; + gfc->presetTune.quantcomp_alt_type = 3; + gfc->presetTune.athadjust_switch_level = 2; // Always switch + + break; + + case 2: + + if (gfp->VBR == vbr_mtrh) { + lame_set_experimentalX(gfp, 2); + gfc->presetTune.quantcomp_adjust_mtrh = 9; + gfc->presetTune.quantcomp_type_s = 4; + gfc->presetTune.quantcomp_alt_type = 0; + gfc->presetTune.athadjust_safe_noiseshaping_thre = 0.0; + gfc->presetTune.athadjust_safe_athaasensitivity = 8.0; + } + else { + lame_set_experimentalX(gfp, 3); + gfc->presetTune.quantcomp_adjust_rh_tot = 600; + gfc->presetTune.quantcomp_adjust_rh_max = 60; + gfc->presetTune.quantcomp_type_s = 3; + gfc->presetTune.quantcomp_alt_type = 1; + } + + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 1); + lame_set_experimentalZ(gfp, 1); + lame_set_VBR_q(gfp, 2); + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); // safejoint + lame_set_ATHtype(gfp, 2); + // modify sfb21 by 3 dB plus ns-treble=0 + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (12 << 20)); + + gfc->presetTune.attackthre = 35; + gfc->presetTune.attackthre_s = 150; + gfc->presetTune.ms_maskadjust = .5; + gfc->presetTune.athadjust_switch_level = 1; + gfc->presetTune.athadjust_msfix = 2.13; + + break; + + case 3: + + if (gfp->VBR == vbr_mtrh) { + gfc->presetTune.quantcomp_type_s = 4; + gfc->presetTune.quantcomp_adjust_mtrh = 9; + gfc->presetTune.quantcomp_alt_type = 0; + (void) lame_set_ATHlower( gfp, -2 ); + gfc->presetTune.athadjust_safe_noiseshaping_thre = 0.0; + gfc->presetTune.athadjust_safe_athaasensitivity = 8.0; + } + else { + gfc->presetTune.quantcomp_type_s = 3; + gfc->presetTune.quantcomp_adjust_rh_tot = 600; + gfc->presetTune.quantcomp_adjust_rh_max = 60; + (void) lame_set_ATHlower( gfp, -1 ); + } + + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 1); + lame_set_experimentalZ(gfp, 1); + lame_set_experimentalX(gfp, 1); + lame_set_VBR_q(gfp, 2); + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); // safejoint + (void) lame_set_msfix( gfp, 2.13 ); + lame_set_ATHtype(gfp, 4); + // modify sfb21 by 3.75 dB plus ns-treble=0 + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (15 << 20)); + + gfc->presetTune.attackthre = 35; + gfc->presetTune.attackthre_s = 150; + gfc->presetTune.ms_maskadjust = .5; + gfc->presetTune.athadjust_switch_level = 1; + + break; + } + return 0; +} + +int +lame_set_preset_notune( lame_global_flags* gfp, int preset_notune ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + gfc->presetTune.use = 0; // Turn off specialized preset tunings + + return 0; +} + + + + + + + + + + + + + + + + + + + diff -Nru swftools-0.9.2+ds1/lib/lame/tables.c swftools-0.9.1/lib/lame/tables.c --- swftools-0.9.2+ds1/lib/lame/tables.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/tables.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,508 @@ +/* + * MPEG layer 3 tables source file + * + * Copyright (c) 1999 Albert L Faber + * + * 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. + */ + +/* $Id: tables.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#include "util.h" +#include "tables.h" + +#ifdef WITH_DMALLOC +#include +#endif + +static const short t1HB[] = { + 1, 1, + 1, 0}; + +static const short t2HB[] = { + 1, 2, 1, + 3, 1, 1, + 3, 2, 0}; + +static const short t3HB[] = { + 3, 2, 1, + 1, 1, 1, + 3, 2, 0}; + +static const short t5HB[] = { + 1, 2, 6, 5, + 3, 1, 4, 4, + 7, 5, 7, 1, + 6, 1, 1, 0}; + +static const short t6HB[] = { + 7, 3, 5, 1, + 6, 2, 3, 2, + 5, 4, 4, 1, + 3, 3, 2, 0}; + +static const short t7HB[] = { + 1, 2,10,19,16,10, + 3, 3, 7,10, 5, 3, + 11, 4,13,17, 8, 4, + 12,11,18,15,11, 2, + 7, 6, 9,14, 3, 1, + 6, 4, 5, 3, 2, 0}; + +static const short t8HB[] = { + 3, 4, 6, 18,12, 5, + 5, 1, 2, 16, 9, 3, + 7, 3, 5, 14, 7, 3, + 19,17,15, 13,10, 4, + 13, 5, 8, 11, 5, 1, + 12, 4, 4, 1, 1, 0}; + +static const short t9HB[] = { + 7, 5, 9, 14, 15, 7, + 6, 4, 5, 5, 6, 7, + 7, 6, 8, 8, 8, 5, + 15, 6, 9, 10, 5, 1, + 11, 7, 9, 6, 4, 1, + 14, 4, 6, 2, 6, 0}; + +static const short t10HB[] = { + 1, 2, 10, 23, 35, 30, 12, 17, + 3, 3, 8, 12, 18, 21, 12, 7, + 11, 9, 15, 21, 32, 40, 19, 6, + 14,13, 22, 34, 46, 23, 18, 7, + 20,19, 33, 47, 27, 22, 9, 3, + 31,22, 41, 26, 21, 20, 5, 3, + 14,13, 10, 11, 16, 6, 5, 1, + 9, 8, 7, 8, 4, 4, 2, 0}; + +static const short t11HB[] = { + 3, 4, 10, 24, 34, 33, 21, 15, + 5, 3, 4, 10, 32, 17, 11, 10, + 11, 7, 13, 18, 30, 31, 20, 5, + 25,11, 19, 59, 27, 18, 12, 5, + 35,33, 31, 58, 30, 16, 7, 5, + 28,26, 32, 19, 17, 15, 8, 14, + 14,12, 9, 13, 14, 9, 4, 1, + 11, 4, 6, 6, 6, 3, 2, 0}; + +static const short t12HB[] = { + 9, 6, 16, 33, 41, 39, 38,26, + 7, 5, 6, 9, 23, 16, 26,11, + 17, 7, 11, 14, 21, 30, 10, 7, + 17, 10, 15, 12, 18, 28, 14, 5, + 32, 13, 22, 19, 18, 16, 9, 5, + 40, 17, 31, 29, 17, 13, 4, 2, + 27, 12, 11, 15, 10, 7, 4, 1, + 27, 12, 8, 12, 6, 3, 1, 0}; + +static const short t13HB[] = { + 1, 5, 14, 21, 34, 51, 46, 71, 42, 52, 68, 52, 67, 44, 43, 19, + 3, 4, 12, 19, 31, 26, 44, 33, 31, 24, 32, 24, 31, 35, 22, 14, + 15, 13, 23, 36, 59, 49, 77, 65, 29, 40, 30, 40, 27, 33, 42, 16, + 22, 20, 37, 61, 56, 79, 73, 64, 43, 76, 56, 37, 26, 31, 25, 14, + 35, 16, 60, 57, 97, 75,114, 91, 54, 73, 55, 41, 48, 53, 23, 24, + 58, 27, 50, 96, 76, 70, 93, 84, 77, 58, 79, 29, 74, 49, 41, 17, + 47, 45, 78, 74,115, 94, 90, 79, 69, 83, 71, 50, 59, 38, 36, 15, + 72, 34, 56, 95, 92, 85, 91, 90, 86, 73, 77, 65, 51, 44, 43, 42, + 43, 20, 30, 44, 55, 78, 72, 87, 78, 61, 46, 54, 37, 30, 20, 16, + 53, 25, 41, 37, 44, 59, 54, 81, 66, 76, 57, 54, 37, 18, 39, 11, + 35, 33, 31, 57, 42, 82, 72, 80, 47, 58, 55, 21, 22, 26, 38, 22, + 53, 25, 23, 38, 70, 60, 51, 36, 55, 26, 34, 23, 27, 14, 9, 7, + 34, 32, 28, 39, 49, 75, 30, 52, 48, 40, 52, 28, 18, 17, 9, 5, + 45, 21, 34, 64, 56, 50, 49, 45, 31, 19, 12, 15, 10, 7, 6, 3, + 48, 23, 20, 39, 36, 35, 53, 21, 16, 23, 13, 10, 6, 1, 4, 2, + 16, 15, 17, 27, 25, 20, 29, 11, 17, 12, 16, 8, 1, 1, 0, 1}; + +static const short t15HB[] = { + 7, 12, 18, 53, 47, 76,124,108, 89,123,108,119,107, 81,122, 63, + 13, 5, 16, 27, 46, 36, 61, 51, 42, 70, 52, 83, 65, 41, 59, 36, + 19, 17, 15, 24, 41, 34, 59, 48, 40, 64, 50, 78, 62, 80, 56, 33, + 29, 28, 25, 43, 39, 63, 55, 93, 76, 59, 93, 72, 54, 75, 50, 29, + 52, 22, 42, 40, 67, 57, 95, 79, 72, 57, 89, 69, 49, 66, 46, 27, + 77, 37, 35, 66, 58, 52, 91, 74, 62, 48, 79, 63, 90, 62, 40, 38, + 125, 32, 60, 56, 50, 92, 78, 65, 55, 87, 71, 51, 73, 51, 70, 30, + 109, 53, 49, 94, 88, 75, 66,122, 91, 73, 56, 42, 64, 44, 21, 25, + 90, 43, 41, 77, 73, 63, 56, 92, 77, 66, 47, 67, 48, 53, 36, 20, + 71, 34, 67, 60, 58, 49, 88, 76, 67,106, 71, 54, 38, 39, 23, 15, + 109, 53, 51, 47, 90, 82, 58, 57, 48, 72, 57, 41, 23, 27, 62, 9, + 86, 42, 40, 37, 70, 64, 52, 43, 70, 55, 42, 25, 29, 18, 11, 11, + 118, 68, 30, 55, 50, 46, 74, 65, 49, 39, 24, 16, 22, 13, 14, 7, + 91, 44, 39, 38, 34, 63, 52, 45, 31, 52, 28, 19, 14, 8, 9, 3, + 123, 60, 58, 53, 47, 43, 32, 22, 37, 24, 17, 12, 15, 10, 2, 1, + 71, 37, 34, 30, 28, 20, 17, 26, 21, 16, 10, 6, 8, 6, 2, 0}; + +static const short t16HB[] = { + 1, 5, 14, 44, 74, 63, 110, 93, 172, 149, 138, 242, 225, 195, 376, 17, + 3, 4, 12, 20, 35, 62, 53, 47, 83, 75, 68, 119, 201, 107, 207, 9, + 15, 13, 23, 38, 67, 58, 103, 90, 161, 72, 127, 117, 110, 209, 206, 16, + 45, 21, 39, 69, 64,114, 99, 87, 158, 140, 252, 212, 199, 387, 365, 26, + 75, 36, 68, 65,115,101, 179,164, 155, 264, 246, 226, 395, 382, 362, 9, + 66, 30, 59, 56,102,185, 173,265, 142, 253, 232, 400, 388, 378, 445, 16, + 111, 54, 52,100,184,178, 160,133, 257, 244, 228, 217, 385, 366, 715, 10, + 98, 48, 91, 88,165,157, 148,261, 248, 407, 397, 372, 380, 889, 884, 8, + 85, 84, 81,159,156,143, 260,249, 427, 401, 392, 383, 727, 713, 708, 7, + 154, 76, 73,141,131,256, 245,426, 406, 394, 384, 735, 359, 710, 352, 11, + 139, 129, 67,125,247,233, 229,219, 393, 743, 737, 720, 885, 882, 439, 4, + 243, 120,118,115,227,223, 396,746, 742, 736, 721, 712, 706, 223, 436, 6, + 202, 224,222,218,216,389, 386,381, 364, 888, 443, 707, 440, 437,1728, 4, + 747, 211,210,208,370,379, 734,723, 714,1735, 883, 877, 876,3459, 865, 2, + 377, 369,102,187,726,722, 358,711, 709, 866,1734, 871,3458, 870, 434, 0, + 12, 10, 7, 11, 10, 17, 11, 9, 13, 12, 10, 7, 5, 3, 1, 3}; + +static const short t24HB[] = { + 15, 13, 46, 80, 146, 262, 248, 434, 426, 669, 653, 649, 621, 517, 1032, 88, + 14, 12, 21, 38, 71, 130, 122, 216, 209, 198, 327, 345, 319, 297, 279, 42, + 47, 22, 41, 74, 68, 128, 120, 221, 207, 194, 182, 340, 315, 295, 541, 18, + 81, 39, 75, 70, 134, 125, 116, 220, 204, 190, 178, 325, 311, 293, 271, 16, + 147, 72, 69,135, 127, 118, 112, 210, 200, 188, 352, 323, 306, 285, 540, 14, + 263, 66,129,126, 119, 114, 214, 202, 192, 180, 341, 317, 301, 281, 262, 12, + 249,123,121,117, 113, 215, 206, 195, 185, 347, 330, 308, 291, 272, 520, 10, + 435,115,111,109, 211, 203, 196, 187, 353, 332, 313, 298, 283, 531, 381, 17, + 427,212,208,205, 201, 193, 186, 177, 169, 320, 303, 286, 268, 514, 377, 16, + 335,199,197,191, 189, 181, 174, 333, 321, 305, 289, 275, 521, 379, 371, 11, + 668,184,183,179, 175, 344, 331, 314, 304, 290, 277, 530, 383, 373, 366, 10, + 652,346,171,168, 164, 318, 309, 299, 287, 276, 263, 513, 375, 368, 362, 6, + 648,322,316,312, 307, 302, 292, 284, 269, 261, 512, 376, 370, 364, 359, 4, + 620,300,296,294, 288, 282, 273, 266, 515, 380, 374, 369, 365, 361, 357, 2, + 1033,280,278,274, 267, 264, 259, 382, 378, 372, 367, 363, 360, 358, 356, 0, + 43, 20, 19, 17, 15, 13, 11, 9, 7, 6, 4, 7, 5, 3, 1, 3}; + +static const short t32HB[] = { + 1 << 0, 5 << 1, 4 << 1, 5 << 2, 6 << 1, 5 << 2, 4 << 2, 4 << 3, + 7 << 1, 3 << 2, 6 << 2, 0 << 3, 7 << 2, 2 << 3, 3 << 3, 1 << 4}; + +static const short t33HB[] = { + 15 << 0, 14 << 1, 13 << 1, 12 << 2, 11 << 1, 10 << 2, 9 << 2, 8 << 3, + 7 << 1, 6 << 2, 5 << 2, 4 << 3, 3 << 2, 2 << 3, 1 << 3, 0 << 4}; + + +const char t1l[] = { + 1, 4, + 3, 5}; + +const char t2l[] = { + 1, 4, 7, + 4, 5, 7, + 6, 7, 8}; + +const char t3l[] = { + 2, 3, 7, + 4, 4, 7, + 6, 7, 8}; + +const char t5l[] = { + 1, 4, 7, 8, + 4, 5, 8, 9, + 7, 8, 9, 10, + 8, 8, 9, 10}; + +const char t6l[] = { + 3, 4, 6, 8, + 4, 4, 6, 7, + 5, 6, 7, 8, + 7, 7, 8, 9}; + +const char t7l[] = { + 1, 4, 7, 9, 9, 10, + 4, 6, 8, 9, 9, 10, + 7, 7, 9, 10, 10, 11, + 8, 9, 10, 11, 11, 11, + 8, 9, 10, 11, 11, 12, + 9, 10, 11, 12, 12, 12}; + +const char t8l[] = { + 2, 4, 7, 9, 9, 10, + 4, 4, 6, 10, 10, 10, + 7, 6, 8, 10, 10, 11, + 9, 10, 10, 11, 11, 12, + 9, 9, 10, 11, 12, 12, +10, 10, 11, 11, 13, 13}; + +const char t9l[] = { + 3, 4, 6, 7, 9, 10, + 4, 5, 6, 7, 8, 10, + 5, 6, 7, 8, 9, 10, + 7, 7, 8, 9, 9, 10, + 8, 8, 9, 9, 10, 11, + 9, 9, 10, 10, 11, 11}; + +const char t10l[] = { + 1, 4, 7, 9, 10, 10, 10, 11, + 4, 6, 8, 9, 10, 11, 10, 10, + 7, 8, 9, 10, 11, 12, 11, 11, + 8, 9, 10, 11, 12, 12, 11, 12, + 9, 10, 11, 12, 12, 12, 12, 12, +10, 11, 12, 12, 13, 13, 12, 13, + 9, 10, 11, 12, 12, 12, 13, 13, +10, 10, 11, 12, 12, 13, 13, 13}; + +const char t11l[] = { + 2, 4, 6, 8, 9, 10, 9, 10, + 4, 5, 6, 8, 10, 10, 9, 10, + 6, 7, 8, 9, 10, 11, 10, 10, + 8, 8, 9, 11, 10, 12, 10, 11, + 9, 10, 10, 11, 11, 12, 11, 12, + 9, 10, 11, 12, 12, 13, 12, 13, + 9, 9, 9, 10, 11, 12, 12, 12, + 9, 9, 10, 11, 12, 12, 12, 12}; + +const char t12l[] = { + 4, 4, 6, 8, 9, 10, 10, 10, + 4, 5, 6, 7, 9, 9, 10, 10, + 6, 6, 7, 8, 9, 10, 9, 10, + 7, 7, 8, 8, 9, 10, 10, 10, + 8, 8, 9, 9, 10, 10, 10, 11, + 9, 9, 10, 10, 10, 11, 10, 11, + 9, 9, 9, 10, 10, 11, 11, 12, +10, 10, 10, 11, 11, 11, 11, 12}; + +const char t13l[] = { + 1, 5, 7, 8, 9, 10, 10, 11, 10, 11, 12, 12, 13, 13, 14, 14, + 4, 6, 8, 9, 10, 10, 11, 11, 11, 11, 12, 12, 13, 14, 14, 14, + 7, 8, 9, 10, 11, 11, 12, 12, 11, 12, 12, 13, 13, 14, 15, 15, + 8, 9, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 15, 15, + 9, 9, 11, 11, 12, 12, 13, 13, 12, 13, 13, 14, 14, 15, 15, 16, +10, 10, 11, 12, 12, 12, 13, 13, 13, 13, 14, 13, 15, 15, 16, 16, +10, 11, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, +11, 11, 12, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 16, 18, 18, +10, 10, 11, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 16, 17, 17, +11, 11, 12, 12, 13, 13, 13, 15, 14, 15, 15, 16, 16, 16, 18, 17, +11, 12, 12, 13, 13, 14, 14, 15, 14, 15, 16, 15, 16, 17, 18, 19, +12, 12, 12, 13, 14, 14, 14, 14, 15, 15, 15, 16, 17, 17, 17, 18, +12, 13, 13, 14, 14, 15, 14, 15, 16, 16, 17, 17, 17, 18, 18, 18, +13, 13, 14, 15, 15, 15, 16, 16, 16, 16, 16, 17, 18, 17, 18, 18, +14, 14, 14, 15, 15, 15, 17, 16, 16, 19, 17, 17, 17, 19, 18, 18, +13, 14, 15, 16, 16, 16, 17, 16, 17, 17, 18, 18, 21, 20, 21, 18}; + +const char t15l[] = { + 3, 5, 6, 8, 8, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 14, + 5, 5, 7, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, + 6, 7, 7, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, + 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, + 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, + 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, 13, 14, +10, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, +10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 14, +10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 14, 14, +10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, +11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 15, 14, +11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, +12, 12, 11, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14, 14, 15, 15, +12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 14, 15, +13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15}; + +const char t16_5l[] = { + 1, 5, 7, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 11, + 4, 6, 8, 9, 10, 11, 11, 11, 12, 12, 12, 13, 14, 13, 14, 11, + 7, 8, 9, 10, 11, 11, 12, 12, 13, 12, 13, 13, 13, 14, 14, 12, + 9, 9, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 13, +10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 12, +10, 10, 11, 11, 12, 13, 13, 14, 13, 14, 14, 15, 15, 15, 16, 13, +11, 11, 11, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 13, +11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 17, 17, 13, +11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 13, +12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 15, 16, 15, 14, +12, 13, 12, 13, 14, 14, 14, 14, 15, 16, 16, 16, 17, 17, 16, 13, +13, 13, 13, 13, 14, 14, 15, 16, 16, 16, 16, 16, 16, 15, 16, 14, +13, 14, 14, 14, 14, 15, 15, 15, 15, 17, 16, 16, 16, 16, 18, 14, +15, 14, 14, 14, 15, 15, 16, 16, 16, 18, 17, 17, 17, 19, 17, 14, +14, 15, 13, 14, 16, 16, 15, 16, 16, 17, 18, 17, 19, 17, 16, 14, +11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 12}; + +const char t16l[] = { + 1, 5, 7, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 10, + 4, 6, 8, 9, 10, 11, 11, 11, 12, 12, 12, 13, 14, 13, 14, 10, + 7, 8, 9, 10, 11, 11, 12, 12, 13, 12, 13, 13, 13, 14, 14, 11, + 9, 9, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 12, +10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 11, +10, 10, 11, 11, 12, 13, 13, 14, 13, 14, 14, 15, 15, 15, 16, 12, +11, 11, 11, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 12, +11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 17, 17, 12, +11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 12, +12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 15, 16, 15, 13, +12, 13, 12, 13, 14, 14, 14, 14, 15, 16, 16, 16, 17, 17, 16, 12, +13, 13, 13, 13, 14, 14, 15, 16, 16, 16, 16, 16, 16, 15, 16, 13, +13, 14, 14, 14, 14, 15, 15, 15, 15, 17, 16, 16, 16, 16, 18, 13, +15, 14, 14, 14, 15, 15, 16, 16, 16, 18, 17, 17, 17, 19, 17, 13, +14, 15, 13, 14, 16, 16, 15, 16, 16, 17, 18, 17, 19, 17, 16, 13, +10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 10}; + +const char t24l[] = { + 4, 5, 7, 8, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 13, 10, + 5, 6, 7, 8, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 12, 10, + 7, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 9, + 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 9, + 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 9, +10, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 9, +10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 9, +11, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 10, +11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 10, +11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 10, +12, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 10, +12, 12, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 10, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 10, +12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 10, +13, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 6}; + +const char t32l[] = { + 1+0, 4+1, 4+1, 5+2, 4+1, 6+2, 5+2, 6+3, + 4+1, 5+2, 5+2, 6+3, 5+2, 6+3, 6+3, 6+4}; + +const char t33l[] = { + 4+0, 4+1, 4+1, 4+2, 4+1, 4+2, 4+2, 4+3, + 4+1, 4+2, 4+2, 4+3, 4+2, 4+3, 4+3, 4+4}; + + +const struct huffcodetab ht[HTN] = +{ + /* xlen, linmax, table, hlen */ + { 0, 0,NULL,NULL}, + { 2, 0,t1HB, t1l}, + { 3, 0,t2HB, t2l}, + { 3, 0,t3HB, t3l}, + { 0, 0,NULL,NULL},/* Apparently not used */ + { 4, 0,t5HB, t5l}, + { 4, 0,t6HB, t6l}, + { 6, 0,t7HB, t7l}, + { 6, 0,t8HB, t8l}, + { 6, 0,t9HB, t9l}, + { 8, 0,t10HB, t10l}, + { 8, 0,t11HB, t11l}, + { 8, 0,t12HB, t12l}, + {16, 0,t13HB, t13l}, + { 0, 0,NULL, t16_5l},/* Apparently not used */ + {16, 0,t15HB, t15l}, + + { 1, 1,t16HB, t16l}, + { 2, 3,t16HB, t16l}, + { 3, 7,t16HB, t16l}, + { 4, 15,t16HB, t16l}, + { 6, 63,t16HB, t16l}, + { 8, 255,t16HB, t16l}, + {10,1023,t16HB, t16l}, + {13,8191,t16HB, t16l}, + + { 4, 15,t24HB, t24l}, + { 5, 31,t24HB, t24l}, + { 6, 63,t24HB, t24l}, + { 7, 127,t24HB, t24l}, + { 8, 255,t24HB, t24l}, + { 9, 511,t24HB, t24l}, + {11,2047,t24HB, t24l}, + {13,8191,t24HB, t24l}, + + { 0, 0,t32HB, t32l}, + { 0, 0,t33HB, t33l}, +}; + + + + + +/* for (i = 0; i < 16*16; i++) { + * largetbl[i] = ((ht[16].hlen[i]) << 16) + ht[24].hlen[i]; + * } + */ +const unsigned int largetbl[16*16] = { +0x010004, 0x050005, 0x070007, 0x090008, 0x0a0009, 0x0a000a, 0x0b000a, 0x0b000b, +0x0c000b, 0x0c000c, 0x0c000c, 0x0d000c, 0x0d000c, 0x0d000c, 0x0e000d, 0x0a000a, +0x040005, 0x060006, 0x080007, 0x090008, 0x0a0009, 0x0b000a, 0x0b000a, 0x0b000b, +0x0c000b, 0x0c000b, 0x0c000c, 0x0d000c, 0x0e000c, 0x0d000c, 0x0e000c, 0x0a000a, +0x070007, 0x080007, 0x090008, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000b, +0x0d000b, 0x0c000b, 0x0d000b, 0x0d000c, 0x0d000c, 0x0e000c, 0x0e000d, 0x0b0009, +0x090008, 0x090008, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000a, 0x0c000b, +0x0d000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0c0009, +0x0a0009, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000a, 0x0d000a, 0x0d000b, +0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000d, 0x0b0009, +0x0a000a, 0x0a0009, 0x0b000a, 0x0b000a, 0x0c000a, 0x0d000a, 0x0d000b, 0x0e000b, +0x0d000b, 0x0e000b, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x0c0009, +0x0b000a, 0x0b000a, 0x0b000a, 0x0c000a, 0x0d000a, 0x0d000b, 0x0d000b, 0x0d000b, +0x0e000b, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x10000d, 0x0c0009, +0x0b000b, 0x0b000a, 0x0c000a, 0x0c000a, 0x0d000b, 0x0d000b, 0x0d000b, 0x0e000b, +0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x11000d, 0x11000d, 0x0c000a, +0x0b000b, 0x0c000b, 0x0c000b, 0x0d000b, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000b, +0x0f000b, 0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x10000d, 0x10000d, 0x0c000a, +0x0c000b, 0x0c000b, 0x0c000b, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000b, 0x0f000c, +0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x0f000d, 0x10000d, 0x0f000d, 0x0d000a, +0x0c000c, 0x0d000b, 0x0c000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0e000c, +0x0f000c, 0x10000c, 0x10000c, 0x10000d, 0x11000d, 0x11000d, 0x10000d, 0x0c000a, +0x0d000c, 0x0d000c, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0f000c, 0x10000c, +0x10000c, 0x10000c, 0x10000c, 0x10000d, 0x10000d, 0x0f000d, 0x10000d, 0x0d000a, +0x0d000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, +0x0f000c, 0x11000c, 0x10000d, 0x10000d, 0x10000d, 0x10000d, 0x12000d, 0x0d000a, +0x0f000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x10000c, 0x10000c, +0x10000d, 0x12000d, 0x11000d, 0x11000d, 0x11000d, 0x13000d, 0x11000d, 0x0d000a, +0x0e000d, 0x0f000c, 0x0d000c, 0x0e000c, 0x10000c, 0x10000c, 0x0f000c, 0x10000d, +0x10000d, 0x11000d, 0x12000d, 0x11000d, 0x13000d, 0x11000d, 0x10000d, 0x0d000a, +0x0a0009, 0x0a0009, 0x0a0009, 0x0b0009, 0x0b0009, 0x0c0009, 0x0c0009, 0x0c0009, +0x0d0009, 0x0d0009, 0x0d0009, 0x0d000a, 0x0d000a, 0x0d000a, 0x0d000a, 0x0a0006 +}; + +/* for (i = 0; i < 3*3; i++) { + * table23[i] = ((ht[2].hlen[i]) << 16) + ht[3].hlen[i]; + * } + */ +const unsigned int table23[3*3] = { +0x010002, 0x040003, 0x070007, +0x040004, 0x050004, 0x070007, +0x060006, 0x070007, 0x080008 +}; + +/* for (i = 0; i < 4*4; i++) { + * table56[i] = ((ht[5].hlen[i]) << 16) + ht[6].hlen[i]; + * } + */ +const unsigned int table56[4*4] = { +0x010003, 0x040004, 0x070006, 0x080008, 0x040004, 0x050004, 0x080006, 0x090007, +0x070005, 0x080006, 0x090007, 0x0a0008, 0x080007, 0x080007, 0x090008, 0x0a0009 +}; + + + +/* + * 0: MPEG-2 LSF + * 1: MPEG-1 + * 2: MPEG-2.5 LSF FhG extention (1995-07-11 shn) + */ + +typedef enum { + MPEG_2 = 0, + MPEG_1 = 1, + MPEG_25 = 2 +} MPEG_t; + +const int bitrate_table [3] [16] = { + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, + { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 }, + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, +}; + +const int samplerate_table [3] [4] = { + { 22050, 24000, 16000, -1 }, /* MPEG 2 */ + { 44100, 48000, 32000, -1 }, /* MPEG 1 */ + { 11025, 12000, 8000, -1 }, /* MPEG 2.5 */ +}; + +const char* version_string [3] = { "2", "1", "2.5" }; + +const unsigned header_word [3] = { 0xFFF00000, 0xFFF80000, 0xFFE00000 }; + +/* end of tables.h */ diff -Nru swftools-0.9.2+ds1/lib/lame/tables.h swftools-0.9.1/lib/lame/tables.h --- swftools-0.9.2+ds1/lib/lame/tables.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/tables.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * MPEG layer 3 tables include file + * + * Copyright (c) 1999 Albert L Faber + * + * 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 LAME_TABLES_H +#define LAME_TABLES_H + +#include "machine.h" + +typedef struct { + unsigned char no; + unsigned char width; + unsigned char minval_2; + float quiet_thr; + float norm; + float bark; +} type1_t; + +typedef struct { + unsigned char no; + unsigned char width; + float quiet_thr; + float norm; + float SNR; + float bark; +} type2_t; + +typedef struct { + unsigned int no : 5; + unsigned int cbw : 3; + unsigned int bu : 6; + unsigned int bo : 6; + unsigned int w1_576 : 10; + unsigned int w2_576 : 10; +} type34_t; + +typedef struct { + size_t len1; + const type1_t* const tab1; + size_t len2; + const type2_t* const tab2; + size_t len3; + const type34_t* const tab3; + size_t len4; + const type34_t* const tab4; +} type5_t; + +extern const type5_t table5 [6]; + + + +#define HTN 34 + +struct huffcodetab { + const int xlen; /* max. x-index+ */ + const int linmax; /* max number to be stored in linbits */ + const short* table; /* pointer to array[xlen][ylen] */ + const char* hlen; /* pointer to array[xlen][ylen] */ +}; + +extern const struct huffcodetab ht [HTN]; + /* global memory block */ + /* array of all huffcodtable headers */ + /* 0..31 Huffman code table 0..31 */ + /* 32,33 count1-tables */ + +extern const char t32l []; +extern const char t33l []; + +extern const unsigned int largetbl [16*16]; +extern const unsigned int table23 [3*3]; +extern const unsigned int table56 [4*4]; +#endif /* LAME_TABLES_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/takehiro.c swftools-0.9.1/lib/lame/takehiro.c --- swftools-0.9.2+ds1/lib/lame/takehiro.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/takehiro.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,1031 @@ +/* + * MP3 huffman table selecting and bit counting + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * 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. + */ + +/* $Id: takehiro.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#include +#include "util.h" +#include "l3side.h" +#include "tables.h" +#include "quantize_pvt.h" + +#ifdef WITH_DMALLOC +#include +#endif + +static const struct +{ + const int region0_count; + const int region1_count; +} subdv_table[ 23 ] = +{ +{0, 0}, /* 0 bands */ +{0, 0}, /* 1 bands */ +{0, 0}, /* 2 bands */ +{0, 0}, /* 3 bands */ +{0, 0}, /* 4 bands */ +{0, 1}, /* 5 bands */ +{1, 1}, /* 6 bands */ +{1, 1}, /* 7 bands */ +{1, 2}, /* 8 bands */ +{2, 2}, /* 9 bands */ +{2, 3}, /* 10 bands */ +{2, 3}, /* 11 bands */ +{3, 4}, /* 12 bands */ +{3, 4}, /* 13 bands */ +{3, 4}, /* 14 bands */ +{4, 5}, /* 15 bands */ +{4, 5}, /* 16 bands */ +{4, 6}, /* 17 bands */ +{5, 6}, /* 18 bands */ +{5, 6}, /* 19 bands */ +{5, 7}, /* 20 bands */ +{6, 7}, /* 21 bands */ +{6, 7}, /* 22 bands */ +}; + + + + +/*************************************************************************/ +/* ix_max */ +/*************************************************************************/ + +int +ix_max(const int *ix, const int *end) +{ + int max1 = 0, max2 = 0; + + do { + int x1 = *ix++; + int x2 = *ix++; + if (max1 < x1) + max1 = x1; + + if (max2 < x2) + max2 = x2; + } while (ix < end); + if (max1 < max2) + max1 = max2; + return max1; +} + + + + + + + + +int +count_bit_ESC( + const int * ix, + const int * const end, + int t1, + const int t2, + int * const s ) +{ + /* ESC-table is used */ + int linbits = ht[t1].xlen * 65536 + ht[t2].xlen; + int sum = 0, sum2; + + do { + int x = *ix++; + int y = *ix++; + + if (x != 0) { + if (x > 14) { + x = 15; + sum += linbits; + } + x *= 16; + } + + if (y != 0) { + if (y > 14) { + y = 15; + sum += linbits; + } + x += y; + } + + sum += largetbl[x]; + } while (ix < end); + + sum2 = sum & 0xffff; + sum >>= 16; + + if (sum > sum2) { + sum = sum2; + t1 = t2; + } + + *s += sum; + return t1; +} + + +inline static int +count_bit_noESC(const int * ix, const int * const end, int * const s) +{ + /* No ESC-words */ + int sum1 = 0; + const char *hlen1 = ht[1].hlen; + + do { + int x = ix[0] * 2 + ix[1]; + ix += 2; + sum1 += hlen1[x]; + } while (ix < end); + + *s += sum1; + return 1; +} + + + +inline static int +count_bit_noESC_from2( + const int * ix, + const int * const end, + int t1, + int * const s ) +{ + /* No ESC-words */ + unsigned int sum = 0, sum2; + const int xlen = ht[t1].xlen; + const unsigned int *hlen; + if (t1 == 2) + hlen = table23; + else + hlen = table56; + + do { + int x = ix[0] * xlen + ix[1]; + ix += 2; + sum += hlen[x]; + } while (ix < end); + + sum2 = sum & 0xffff; + sum >>= 16; + + if (sum > sum2) { + sum = sum2; + t1++; + } + + *s += sum; + return t1; +} + + +inline static int +count_bit_noESC_from3( + const int * ix, + const int * const end, + int t1, + int * const s ) +{ + /* No ESC-words */ + int sum1 = 0; + int sum2 = 0; + int sum3 = 0; + const int xlen = ht[t1].xlen; + const char *hlen1 = ht[t1].hlen; + const char *hlen2 = ht[t1+1].hlen; + const char *hlen3 = ht[t1+2].hlen; + int t; + + do { + int x = ix[0] * xlen + ix[1]; + ix += 2; + sum1 += hlen1[x]; + sum2 += hlen2[x]; + sum3 += hlen3[x]; + } while (ix < end); + + t = t1; + if (sum1 > sum2) { + sum1 = sum2; + t++; + } + if (sum1 > sum3) { + sum1 = sum3; + t = t1+2; + } + *s += sum1; + + return t; +} + + +/*************************************************************************/ +/* choose table */ +/*************************************************************************/ + +/* + Choose the Huffman table that will encode ix[begin..end] with + the fewest bits. + + Note: This code contains knowledge about the sizes and characteristics + of the Huffman tables as defined in the IS (Table B.7), and will not work + with any arbitrary tables. +*/ + +static int choose_table_nonMMX( + const int * ix, + const int * const end, + int * const s ) +{ + int max; + int choice, choice2; + static const int huf_tbl_noESC[] = { + 1, 2, 5, 7, 7,10,10,13,13,13,13,13,13,13,13 /* char not enough ? */ + }; + + max = ix_max(ix, end); + + switch (max) { + case 0: + return max; + + case 1: + return count_bit_noESC(ix, end, s); + + case 2: + case 3: + return count_bit_noESC_from2(ix, end, huf_tbl_noESC[max - 1], s); + + case 4: case 5: case 6: + case 7: case 8: case 9: + case 10: case 11: case 12: + case 13: case 14: case 15: + return count_bit_noESC_from3(ix, end, huf_tbl_noESC[max - 1], s); + + default: + /* try tables with linbits */ + if (max > IXMAX_VAL) { + *s = LARGE_BITS; + return -1; + } + max -= 15; + for (choice2 = 24; choice2 < 32; choice2++) { + if (ht[choice2].linmax >= max) { + break; + } + } + + for (choice = choice2 - 8; choice < 24; choice++) { + if (ht[choice].linmax >= max) { + break; + } + } + return count_bit_ESC(ix, end, choice, choice2, s); + } +} + + + +/*************************************************************************/ +/* count_bit */ +/*************************************************************************/ + +int count_bits( + lame_internal_flags * const gfc, + int * const ix, + const FLOAT8 * const xr, + gr_info * const gi) +{ + int bits = 0; + int i, a1, a2; + /* since quantize_xrpow uses table lookup, we need to check this first: */ + FLOAT8 w = (IXMAX_VAL) / IPOW20(gi->global_gain); + for ( i = 0; i < 576; i++ ) { + if (xr[i] > w) + return LARGE_BITS; + } + + if (gfc->quantization) + quantize_xrpow(xr, ix, IPOW20(gi->global_gain)); + else + quantize_xrpow_ISO(xr, ix, IPOW20(gi->global_gain)); + + if (gfc->noise_shaping_amp==3) { + int sfb; + // 0.634521682242439 = 0.5946*2**(.5*0.1875) + FLOAT8 roundfac = 0.634521682242439 / IPOW20(gi->global_gain+gi->scalefac_scale); + i = 0; + for (sfb = 0; sfb < gi->sfb_lmax; sfb++) { + int end; + if (!gfc->pseudohalf.l[sfb]) + continue; + + end = gfc->scalefac_band.l[sfb+1]; + for (; i < end; i++) + if (xr[i] < roundfac) + ix[i] = 0; + } + + for (sfb = gi->sfb_smin; sfb < SBPSY_s; sfb++) { + int start, end, win; + start = gfc->scalefac_band.s[sfb]; + end = gfc->scalefac_band.s[sfb+1]; + for (win = 0; win < 3; win++) { + int j; + if (!gfc->pseudohalf.s[sfb][win]) + continue; + for (j = start; j < end; j++, i++) + if (xr[i] < roundfac) + ix[i] = 0; + } + } + } + + + + + + + i=576; + /* Determine count1 region */ + for (; i > 1; i -= 2) + if (ix[i - 1] | ix[i - 2]) + break; + gi->count1 = i; + + /* Determines the number of bits to encode the quadruples. */ + a1 = a2 = 0; + for (; i > 3; i -= 4) { + int p; + /* hack to check if all values <= 1 */ + if ((unsigned int)(ix[i-1] | ix[i-2] | ix[i-3] | ix[i-4]) > 1) + break; + + p = ((ix[i-4] * 2 + ix[i-3]) * 2 + ix[i-2]) * 2 + ix[i-1]; + a1 += t32l[p]; + a2 += t33l[p]; + } + + bits = a1; + gi->count1table_select = 0; + if (a1 > a2) { + bits = a2; + gi->count1table_select = 1; + } + + gi->count1bits = bits; + gi->big_values = i; + if (i == 0) + return bits; + + if (gi->block_type == SHORT_TYPE) { + a1=3*gfc->scalefac_band.s[3]; + if (a1 > gi->big_values) a1 = gi->big_values; + a2 = gi->big_values; + + }else if (gi->block_type == NORM_TYPE) { + assert(i <= 576); /* bv_scf has 576 entries (0..575) */ + a1 = gi->region0_count = gfc->bv_scf[i-2]; + a2 = gi->region1_count = gfc->bv_scf[i-1]; + + assert(a1+a2+2 < SBPSY_l); + a2 = gfc->scalefac_band.l[a1 + a2 + 2]; + a1 = gfc->scalefac_band.l[a1 + 1]; + if (a2 < i) + gi->table_select[2] = gfc->choose_table(ix + a2, ix + i, &bits); + + } else { + gi->region0_count = 7; + /*gi->region1_count = SBPSY_l - 7 - 1;*/ + gi->region1_count = SBMAX_l -1 - 7 - 1; + a1 = gfc->scalefac_band.l[7 + 1]; + a2 = i; + if (a1 > a2) { + a1 = a2; + } + } + + + /* have to allow for the case when bigvalues < region0 < region1 */ + /* (and region0, region1 are ignored) */ + a1 = Min(a1,i); + a2 = Min(a2,i); + + assert( a1 >= 0 ); + assert( a2 >= 0 ); + + /* Count the number of bits necessary to code the bigvalues region. */ + if (0 < a1) + gi->table_select[0] = gfc->choose_table(ix, ix + a1, &bits); + if (a1 < a2) + gi->table_select[1] = gfc->choose_table(ix + a1, ix + a2, &bits); + return bits; +} + +/*********************************************************************** + re-calculate the best scalefac_compress using scfsi + the saved bits are kept in the bit reservoir. + **********************************************************************/ + + +inline static void +recalc_divide_init( + const lame_internal_flags * const gfc, + gr_info cod_info, + int * const ix, + int r01_bits[], + int r01_div [], + int r0_tbl [], + int r1_tbl [] ) +{ + int r0, r1, bigv, r0t, r1t, bits; + + bigv = cod_info.big_values; + + for (r0 = 0; r0 <= 7 + 15; r0++) { + r01_bits[r0] = LARGE_BITS; + } + + for (r0 = 0; r0 < 16; r0++) { + int a1 = gfc->scalefac_band.l[r0 + 1], r0bits; + if (a1 >= bigv) + break; + r0bits = cod_info.part2_length; + r0t = gfc->choose_table(ix, ix + a1, &r0bits); + + for (r1 = 0; r1 < 8; r1++) { + int a2 = gfc->scalefac_band.l[r0 + r1 + 2]; + if (a2 >= bigv) + break; + + bits = r0bits; + r1t = gfc->choose_table(ix + a1, ix + a2, &bits); + if (r01_bits[r0 + r1] > bits) { + r01_bits[r0 + r1] = bits; + r01_div[r0 + r1] = r0; + r0_tbl[r0 + r1] = r0t; + r1_tbl[r0 + r1] = r1t; + } + } + } +} + +inline static void +recalc_divide_sub( + const lame_internal_flags * const gfc, + const gr_info cod_info2, + gr_info * const gi, + const int * const ix, + const int r01_bits[], + const int r01_div [], + const int r0_tbl [], + const int r1_tbl [] ) +{ + int bits, r2, a2, bigv, r2t; + + bigv = cod_info2.big_values; + + for (r2 = 2; r2 < SBMAX_l + 1; r2++) { + a2 = gfc->scalefac_band.l[r2]; + if (a2 >= bigv) + break; + + bits = r01_bits[r2 - 2] + cod_info2.count1bits; + if (gi->part2_3_length <= bits) + break; + + r2t = gfc->choose_table(ix + a2, ix + bigv, &bits); + if (gi->part2_3_length <= bits) + continue; + + memcpy(gi, &cod_info2, sizeof(gr_info)); + gi->part2_3_length = bits; + gi->region0_count = r01_div[r2 - 2]; + gi->region1_count = r2 - 2 - r01_div[r2 - 2]; + gi->table_select[0] = r0_tbl[r2 - 2]; + gi->table_select[1] = r1_tbl[r2 - 2]; + gi->table_select[2] = r2t; + } +} + + + + +void best_huffman_divide( + const lame_internal_flags * const gfc, + gr_info * const gi, + int * const ix ) +{ + int i, a1, a2; + gr_info cod_info2; + + int r01_bits[7 + 15 + 1]; + int r01_div[7 + 15 + 1]; + int r0_tbl[7 + 15 + 1]; + int r1_tbl[7 + 15 + 1]; + + + /* SHORT BLOCK stuff fails for MPEG2 */ + if (gi->block_type == SHORT_TYPE && gfc->mode_gr==1) + return; + + + memcpy(&cod_info2, gi, sizeof(gr_info)); + if (gi->block_type == NORM_TYPE) { + recalc_divide_init(gfc, cod_info2, ix, r01_bits,r01_div,r0_tbl,r1_tbl); + recalc_divide_sub(gfc, cod_info2, gi, ix, r01_bits,r01_div,r0_tbl,r1_tbl); + } + + i = cod_info2.big_values; + if (i == 0 || (unsigned int)(ix[i-2] | ix[i-1]) > 1) + return; + + i = gi->count1 + 2; + if (i > 576) + return; + + /* Determines the number of bits to encode the quadruples. */ + memcpy(&cod_info2, gi, sizeof(gr_info)); + cod_info2.count1 = i; + a1 = a2 = 0; + + assert(i <= 576); + + for (; i > cod_info2.big_values; i -= 4) { + int p = ((ix[i-4] * 2 + ix[i-3]) * 2 + ix[i-2]) * 2 + ix[i-1]; + a1 += t32l[p]; + a2 += t33l[p]; + } + cod_info2.big_values = i; + + cod_info2.count1table_select = 0; + if (a1 > a2) { + a1 = a2; + cod_info2.count1table_select = 1; + } + + cod_info2.count1bits = a1; + cod_info2.part2_3_length = a1 + cod_info2.part2_length; + + if (cod_info2.block_type == NORM_TYPE) + recalc_divide_sub(gfc, cod_info2, gi, ix, r01_bits,r01_div,r0_tbl,r1_tbl); + else { + /* Count the number of bits necessary to code the bigvalues region. */ + a1 = gfc->scalefac_band.l[7 + 1]; + if (a1 > i) { + a1 = i; + } + if (a1 > 0) + cod_info2.table_select[0] = + gfc->choose_table(ix, ix + a1, (int *)&cod_info2.part2_3_length); + if (i > a1) + cod_info2.table_select[1] = + gfc->choose_table(ix + a1, ix + i, (int *)&cod_info2.part2_3_length); + if (gi->part2_3_length > cod_info2.part2_3_length) + memcpy(gi, &cod_info2, sizeof(gr_info)); + } +} + +static const int slen1_n[16] = { 1, 1, 1, 1, 8, 2, 2, 2, 4, 4, 4, 8, 8, 8,16,16 }; +static const int slen2_n[16] = { 1, 2, 4, 8, 1, 2, 4, 8, 2, 4, 8, 2, 4, 8, 4, 8 }; + +void +scfsi_calc(int ch, + III_side_info_t *l3_side, + III_scalefac_t scalefac[2][2]) +{ + int i, s1, s2, c1, c2; + int sfb; + gr_info *gi = &l3_side->gr[1].ch[ch].tt; + + static const int scfsi_band[5] = { 0, 6, 11, 16, 21 }; +#if 0 + static const int slen1_n[16] = { 0, 1, 1, 1, 8, 2, 2, 2, 4, 4, 4, 8, 8, 8,16,16 }; + static const int slen2_n[16] = { 0, 2, 4, 8, 1, 2, 4, 8, 2, 4, 8, 2, 4, 8, 4, 8 }; +#endif + + for (i = 0; i < 4; i++) + l3_side->scfsi[ch][i] = 0; + + for (i = 0; i < (sizeof(scfsi_band) / sizeof(int)) - 1; i++) { + for (sfb = scfsi_band[i]; sfb < scfsi_band[i + 1]; sfb++) { + if (scalefac[0][ch].l[sfb] != scalefac[1][ch].l[sfb]) + break; + } + if (sfb == scfsi_band[i + 1]) { + for (sfb = scfsi_band[i]; sfb < scfsi_band[i + 1]; sfb++) { + scalefac[1][ch].l[sfb] = -1; + } + l3_side->scfsi[ch][i] = 1; + } + } + + s1 = c1 = 0; + for (sfb = 0; sfb < 11; sfb++) { + if (scalefac[1][ch].l[sfb] < 0) + continue; + c1++; + if (s1 < scalefac[1][ch].l[sfb]) + s1 = scalefac[1][ch].l[sfb]; + } + + s2 = c2 = 0; + for (; sfb < SBPSY_l; sfb++) { + if (scalefac[1][ch].l[sfb] < 0) + continue; + c2++; + if (s2 < scalefac[1][ch].l[sfb]) + s2 = scalefac[1][ch].l[sfb]; + } + + for (i = 0; i < 16; i++) { + if (s1 < slen1_n[i] && s2 < slen2_n[i]) { + int c = slen1_tab[i] * c1 + slen2_tab[i] * c2; + if (gi->part2_length > c) { + gi->part2_length = c; + gi->scalefac_compress = i; + } + } + } +} + +/* +Find the optimal way to store the scalefactors. +Only call this routine after final scalefactors have been +chosen and the channel/granule will not be re-encoded. + */ +void best_scalefac_store( + const lame_internal_flags *gfc, + const int gr, + const int ch, + int l3_enc[2][2][576], + III_side_info_t * const l3_side, + III_scalefac_t scalefac[2][2] ) +{ + + /* use scalefac_scale if we can */ + gr_info *gi = &l3_side->gr[gr].ch[ch].tt; + int sfb,i,j,j2,l,start,end; + + /* remove scalefacs from bands with ix=0. This idea comes + * from the AAC ISO docs. added mt 3/00 */ + /* check if l3_enc=0 */ + for ( sfb = 0; sfb < gi->sfb_lmax; sfb++ ) { + if (scalefac[gr][ch].l[sfb]>0) { + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + for ( l = start; l < end; l++ ) if (l3_enc[gr][ch][l]!=0) break; + if (l==end) scalefac[gr][ch].l[sfb]=0; + } + } + for ( j=0, sfb = gi->sfb_smin; sfb < SBPSY_s; sfb++ ) { + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb+1 ]; + for ( i = 0; i < 3; i++ ) { + if (scalefac[gr][ch].s[sfb][i]>0) { + j2 = j; + for ( l = start; l < end; l++ ) + if (l3_enc[gr][ch][j2++ /*3*l+i*/]!=0) break; + if (l==end) scalefac[gr][ch].s[sfb][i]=0; + } + j += end-start; + } + } + + + gi->part2_3_length -= gi->part2_length; + if (!gi->scalefac_scale && !gi->preflag) { + int b, s = 0; + for (sfb = 0; sfb < gi->sfb_lmax; sfb++) { + s |= scalefac[gr][ch].l[sfb]; + } + + for (sfb = gi->sfb_smin; sfb < SBPSY_s; sfb++) { + for (b = 0; b < 3; b++) { + s |= scalefac[gr][ch].s[sfb][b]; + } + } + + if (!(s & 1) && s != 0) { + for (sfb = 0; sfb < gi->sfb_lmax; sfb++) { + scalefac[gr][ch].l[sfb] /= 2; + } + for (sfb = gi->sfb_smin; sfb < SBPSY_s; sfb++) { + for (b = 0; b < 3; b++) { + scalefac[gr][ch].s[sfb][b] /= 2; + } + } + + gi->scalefac_scale = 1; + gi->part2_length = 99999999; + if (gfc->mode_gr == 2) { + scale_bitcount(&scalefac[gr][ch], gi); + } else { + scale_bitcount_lsf(gfc,&scalefac[gr][ch], gi); + } + } + } + + + for ( i = 0; i < 4; i++ ) + l3_side->scfsi[ch][i] = 0; + + if (gfc->mode_gr==2 && gr == 1 + && l3_side->gr[0].ch[ch].tt.block_type != SHORT_TYPE + && l3_side->gr[1].ch[ch].tt.block_type != SHORT_TYPE) { + scfsi_calc(ch, l3_side, scalefac); + } + gi->part2_3_length += gi->part2_length; +} + + +/* number of bits used to encode scalefacs */ + +/* 18*slen1_tab[i] + 18*slen2_tab[i] */ +static const int scale_short[16] = { + 0, 18, 36, 54, 54, 36, 54, 72, 54, 72, 90, 72, 90, 108, 108, 126 }; + +/* 17*slen1_tab[i] + 18*slen2_tab[i] */ +static const int scale_mixed[16] = { + 0, 18, 36, 54, 51, 35, 53, 71, 52, 70, 88, 69, 87, 105, 104, 122 }; + +/* 11*slen1_tab[i] + 10*slen2_tab[i] */ +static const int scale_long[16] = { + 0, 10, 20, 30, 33, 21, 31, 41, 32, 42, 52, 43, 53, 63, 64, 74 }; + + +/*************************************************************************/ +/* scale_bitcount */ +/*************************************************************************/ + +/* Also calculates the number of bits necessary to code the scalefactors. */ + +int scale_bitcount( + III_scalefac_t * const scalefac, gr_info * const cod_info) +{ + int i, k, sfb, max_slen1 = 0, max_slen2 = 0, ep = 2; + + /* maximum values */ + const int *tab; + + + if ( cod_info->block_type == SHORT_TYPE ) { + tab = scale_short; + if (cod_info->mixed_block_flag) { + tab = scale_mixed; + for ( sfb = 0 ; sfb < cod_info->sfb_lmax; sfb++ ) + if (max_slen1 < scalefac->l[sfb]) + max_slen1 = scalefac->l[sfb]; + } + + for ( i = 0; i < 3; i++ ) { + for ( sfb = cod_info->sfb_smin; sfb < 6; sfb++ ) + if (max_slen1 < scalefac->s[sfb][i]) + max_slen1 = scalefac->s[sfb][i]; + for (sfb = 6; sfb < SBPSY_s; sfb++ ) + if (max_slen2 < scalefac->s[sfb][i]) + max_slen2 = scalefac->s[sfb][i]; + } + } + else + { /* block_type == 1,2,or 3 */ + tab = scale_long; + for ( sfb = 0; sfb < 11; sfb++ ) + if ( scalefac->l[sfb] > max_slen1 ) + max_slen1 = scalefac->l[sfb]; + + if (!cod_info->preflag) { + for ( sfb = 11; sfb < SBPSY_l; sfb++ ) + if (scalefac->l[sfb] < pretab[sfb]) + break; + + if (sfb == SBPSY_l) { + cod_info->preflag = 1; + for ( sfb = 11; sfb < SBPSY_l; sfb++ ) + scalefac->l[sfb] -= pretab[sfb]; + } + } + + for ( sfb = 11; sfb < SBPSY_l; sfb++ ) + if ( scalefac->l[sfb] > max_slen2 ) + max_slen2 = scalefac->l[sfb]; + } + + + /* from Takehiro TOMINAGA 10/99 + * loop over *all* posible values of scalefac_compress to find the + * one which uses the smallest number of bits. ISO would stop + * at first valid index */ + cod_info->part2_length = LARGE_BITS; + for ( k = 0; k < 16; k++ ) + { + if ( (max_slen1 < slen1_n[k]) && (max_slen2 < slen2_n[k]) && + (cod_info->part2_length > tab[k])) { + cod_info->part2_length=tab[k]; + cod_info->scalefac_compress=k; + ep=0; /* we found a suitable scalefac_compress */ + } + } + return ep; +} + + + +/* + table of largest scalefactor values for MPEG2 +*/ +static const int max_range_sfac_tab[6][4] = +{ + { 15, 15, 7, 7}, + { 15, 15, 7, 0}, + { 7, 3, 0, 0}, + { 15, 31, 31, 0}, + { 7, 7, 7, 0}, + { 3, 3, 0, 0} +}; + + + + +/*************************************************************************/ +/* scale_bitcount_lsf */ +/*************************************************************************/ + +/* Also counts the number of bits to encode the scalefacs but for MPEG 2 */ +/* Lower sampling frequencies (24, 22.05 and 16 kHz.) */ + +/* This is reverse-engineered from section 2.4.3.2 of the MPEG2 IS, */ +/* "Audio Decoding Layer III" */ + +int scale_bitcount_lsf(const lame_internal_flags *gfc, + const III_scalefac_t * const scalefac, gr_info * const cod_info) +{ + int table_number, row_in_table, partition, nr_sfb, window, over; + int i, sfb, max_sfac[ 4 ]; + const int *partition_table; + + /* + Set partition table. Note that should try to use table one, + but do not yet... + */ + if ( cod_info->preflag ) + table_number = 2; + else + table_number = 0; + + for ( i = 0; i < 4; i++ ) + max_sfac[i] = 0; + + if ( cod_info->block_type == SHORT_TYPE ) + { + row_in_table = 1; + partition_table = &nr_of_sfb_block[table_number][row_in_table][0]; + for ( sfb = 0, partition = 0; partition < 4; partition++ ) + { + nr_sfb = partition_table[ partition ] / 3; + for ( i = 0; i < nr_sfb; i++, sfb++ ) + for ( window = 0; window < 3; window++ ) + if ( scalefac->s[sfb][window] > max_sfac[partition] ) + max_sfac[partition] = scalefac->s[sfb][window]; + } + } + else + { + row_in_table = 0; + partition_table = &nr_of_sfb_block[table_number][row_in_table][0]; + for ( sfb = 0, partition = 0; partition < 4; partition++ ) + { + nr_sfb = partition_table[ partition ]; + for ( i = 0; i < nr_sfb; i++, sfb++ ) + if ( scalefac->l[sfb] > max_sfac[partition] ) + max_sfac[partition] = scalefac->l[sfb]; + } + } + + for ( over = 0, partition = 0; partition < 4; partition++ ) + { + if ( max_sfac[partition] > max_range_sfac_tab[table_number][partition] ) + over++; + } + if ( !over ) + { + /* + Since no bands have been over-amplified, we can set scalefac_compress + and slen[] for the formatter + */ + static const int log2tab[] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 }; + + int slen1, slen2, slen3, slen4; + + cod_info->sfb_partition_table = nr_of_sfb_block[table_number][row_in_table]; + for ( partition = 0; partition < 4; partition++ ) + cod_info->slen[partition] = log2tab[max_sfac[partition]]; + + /* set scalefac_compress */ + slen1 = cod_info->slen[ 0 ]; + slen2 = cod_info->slen[ 1 ]; + slen3 = cod_info->slen[ 2 ]; + slen4 = cod_info->slen[ 3 ]; + + switch ( table_number ) + { + case 0: + cod_info->scalefac_compress = (((slen1 * 5) + slen2) << 4) + + (slen3 << 2) + + slen4; + break; + + case 1: + cod_info->scalefac_compress = 400 + + (((slen1 * 5) + slen2) << 2) + + slen3; + break; + + case 2: + cod_info->scalefac_compress = 500 + (slen1 * 3) + slen2; + break; + + default: + ERRORF(gfc,"intensity stereo not implemented yet\n" ); + break; + } + } +#ifdef DEBUG + if ( over ) + ERRORF(gfc, "---WARNING !! Amplification of some bands over limits\n" ); +#endif + if (!over) { + assert( cod_info->sfb_partition_table ); + cod_info->part2_length=0; + for ( partition = 0; partition < 4; partition++ ) + cod_info->part2_length += cod_info->slen[partition] * cod_info->sfb_partition_table[partition]; + } + return over; +} + + + +void huffman_init(lame_internal_flags * const gfc) +{ + int i; + + gfc->choose_table = choose_table_nonMMX; + +#ifdef MMX_choose_table + if (gfc->CPU_features.MMX) { + extern int choose_table_MMX(const int *ix, const int *end, int *s); + gfc->choose_table = choose_table_MMX; + } +#endif + + for (i = 2; i <= 576; i += 2) { + int scfb_anz = 0, index; + while (gfc->scalefac_band.l[++scfb_anz] < i) + ; + + index = subdv_table[scfb_anz].region0_count; + while (gfc->scalefac_band.l[index + 1] > i) + index--; + + if (index < 0) { + /* this is an indication that everything is going to + be encoded as region0: bigvalues < region0 < region1 + so lets set region0, region1 to some value larger + than bigvalues */ + index = subdv_table[scfb_anz].region0_count; + } + + gfc->bv_scf[i-2] = index; + + index = subdv_table[scfb_anz].region1_count; + while (gfc->scalefac_band.l[index + gfc->bv_scf[i-2] + 2] > i) + index--; + + if (index < 0) { + index = subdv_table[scfb_anz].region1_count; + } + + gfc->bv_scf[i-1] = index; + } +} diff -Nru swftools-0.9.2+ds1/lib/lame/tools.h swftools-0.9.1/lib/lame/tools.h --- swftools-0.9.2+ds1/lib/lame/tools.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/tools.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,101 @@ +/* + * LAME tools library include file + * Simple context free functions + * - no references to gfc, to gfp, or to any other function not defined + * in this module + * + * Copyright (c) 2000 Frank Klemm + * Copyright (c) 2001 John Dahlstrom + * + * 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. + */ + +/* $Id: tools.h,v 1.1 2002/04/28 17:30:30 kramm Exp $ */ + +#ifndef LAME_TOOLS_H +#define LAME_TOOLS_H + +#include "machine.h" + + + +/*********************************************************************** +* Function Prototype Declarations +***********************************************************************/ + +static inline void qinterp_cf_42( const FLOAT y[4], FLOAT c[3] ); +static inline void qinterp_cf_3( const FLOAT y[3], FLOAT c[3] ); +static inline FLOAT qinterp_eval( const FLOAT c[3], FLOAT x, + FLOAT xtrans, FLOAT xratio ); + + + +/*********************************************************************** +* Macros and Static Inline Function Definitions +***********************************************************************/ + +/* qinterp_cf_42 - Given 4 points, find the coefficients for a quadratic + that connects the 2 center points. -jd + in: y coordinate values, paired with constant x coordinates, -1, 0, 1, 2 + out: c coefficients ordered for quadratic, (c[2] * x*x + c[1] * x + c[0]) +design note: + Utilize the inverse of two constant 3x3 matrices to compute two quadratics, + one from the points at (-1,0,1), and the other from the points at (0,1,2). + The mean of the two yields a quadratic between the points at 0 and 1. +*/ +static inline void +qinterp_cf_42( const FLOAT y[4], FLOAT c[3] ) +{ + c[2] = ( y[0] - y[1] - y[2] + y[3]) * 0.25; /* ([1 -1 -1 1] .* Y) * 0.25 */ + c[1] = y[2] - y[1] - c[2]; /* ([-1 -3 5 -1] .* Y) * 0.25 */ + c[0] = y[1]; +} + +/* qinterp_cf_3 - Given 3 points, find the coefficients for a quadratic + that connects the 3 points. -jd + in: y coordinate values, paired with constant x coordinates, 0, 1, 2 + out: c coefficients ordered for quadratic, (c[2] * x*x + c[1] * x + c[0]) +*/ +static inline void +qinterp_cf_3( const FLOAT y[3], FLOAT c[3] ) +{ + c[2] = ( y[0] + y[2]) * 0.5 - y[1]; /* ([1 -2 1] .* Y) * 0.5 */ + c[1] = y[1] - y[0] - c[2]; /* ([-3 4 -1] .* Y) * 0.5 */ + c[0] = y[0]; +} + + + +/* qinterp_eval - Evaluate a quadratic at a point, given polynomial + coefficients, and an x coordinate with translation and scale + ratio values. This function evaluates the quadratic at the + transformed x coordinate ((x - xtrans) * xratio)). -jd + in: c quadratic coefficients, for (c[2] * x * x + c[1] * x + c[0]) + x + xtrans + xratio +returns: y coordinate (the quadratic evaluated) +*/ +static inline FLOAT +qinterp_eval( const FLOAT c[3], FLOAT x, FLOAT xtrans, FLOAT xratio ) +{ + x = (x - xtrans) * xratio; + return( (c[2] * x + c[1]) * x + c[0] ); +} + + + +#endif /* LAME_TOOLS_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/util.c swftools-0.9.1/lib/lame/util.c --- swftools-0.9.2+ds1/lib/lame/util.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/util.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,990 @@ +/* + * lame utility library source file + * + * Copyright (c) 1999 Albert L Faber + * + * 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. + */ + +/* $Id: util.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#define PRECOMPUTE + +#include "util.h" +#include "tools.h" +#include +#include +#include + +#if defined(__FreeBSD__) && !defined(__alpha__) +# include +#endif + +#ifdef WITH_DMALLOC +#include +#endif + +/*********************************************************************** +* +* Global Function Definitions +* +***********************************************************************/ +/*empty and close mallocs in gfc */ + +void freegfc ( lame_internal_flags* const gfc ) /* bit stream structure */ +{ + int i; + +#ifdef KLEMM_44 + if (gfc->resample_in != NULL) { + resample_close(gfc->resample_in); + gfc->resample_in = NULL; + } + free(gfc->mfbuf[0]); + free(gfc->mfbuf[1]); +#endif + + for ( i = 0 ; i <= 2*BPC; i++ ) + if ( gfc->blackfilt[i] != NULL ) { + free ( gfc->blackfilt[i] ); + gfc->blackfilt[i] = NULL; + } + if ( gfc->inbuf_old[0] ) { + free ( gfc->inbuf_old[0] ); + gfc->inbuf_old[0] = NULL; + } + if ( gfc->inbuf_old[1] ) { + free ( gfc->inbuf_old[1] ); + gfc->inbuf_old[1] = NULL; + } + + if ( gfc->bs.buf != NULL ) { + free ( gfc->bs.buf ); + gfc->bs.buf = NULL; + } + + if ( gfc->VBR_seek_table.bag ) { + free ( gfc->VBR_seek_table.bag ); + } + if ( gfc->ATH ) { + free ( gfc->ATH ); + } + if ( gfc->VBR ) { + free ( gfc->VBR ); + } + if ( gfc->PSY ) { + free ( gfc->PSY ); + } + if ( gfc->s3_ll ) { + /* XXX allocated in psymodel_init() */ + free ( gfc->s3_ll ); + } + if ( gfc->s3_ss ) { + /* XXX allocated in psymodel_init() */ + free ( gfc->s3_ss ); + } + free ( gfc ); +} + + + +/*those ATH formulas are returning +their minimum value for input = -1*/ + +FLOAT8 ATHformula_GB(FLOAT8 f, FLOAT8 value) +{ + /* from Painter & Spanias + modified by Gabriel Bouvigne to better fit the reality + ath = 3.640 * pow(f,-0.8) + - 6.800 * exp(-0.6*pow(f-3.4,2.0)) + + 6.000 * exp(-0.15*pow(f-8.7,2.0)) + + 0.6* 0.001 * pow(f,4.0); + + + In the past LAME was using the Painter &Spanias formula. + But we had some recurrent problems with HF content. + We measured real ATH values, and found the older formula + to be inacurate in the higher part. So we made this new + formula and this solved most of HF problematic testcases. + The tradeoff is that in VBR mode it increases a lot the + bitrate.*/ + + +/*this curve can be udjusted according to the VBR scale: +it adjusts from something close to Painter & Spanias +on V9 up to Bouvigne's formula for V0. This way the VBR +bitrate is more balanced according to the -V value.*/ + + FLOAT8 ath; + + if (f < -.3) + f=3410; + + f /= 1000; // convert to khz + f = Max(0.01, f); + f = Min(18.0, f); + + ath = 3.640 * pow(f,-0.8) + - 6.800 * exp(-0.6*pow(f-3.4,2.0)) + + 6.000 * exp(-0.15*pow(f-8.7,2.0)) + + (0.6+0.04*value)* 0.001 * pow(f,4.0); + return ath; +} + + +/* + * Klemm 1994 and 1997. Experimental data. Sorry, data looks a little bit + * dodderly. Data below 30 Hz is extrapolated from other material, above 18 + * kHz the ATH is limited due to the original purpose (too much noise at + * ATH is not good even if it's theoretically inaudible). + */ + +FLOAT8 ATHformula_Frank( FLOAT8 freq ) +{ + /* + * one value per 100 cent = 1 + * semitone = 1/4 + * third = 1/12 + * octave = 1/40 decade + * rest is linear interpolated, values are currently in decibel rel. 20 µPa + */ + static FLOAT tab [] = { + /* 10.0 */ 96.69, 96.69, 96.26, 95.12, + /* 12.6 */ 93.53, 91.13, 88.82, 86.76, + /* 15.8 */ 84.69, 82.43, 79.97, 77.48, + /* 20.0 */ 74.92, 72.39, 70.00, 67.62, + /* 25.1 */ 65.29, 63.02, 60.84, 59.00, + /* 31.6 */ 57.17, 55.34, 53.51, 51.67, + /* 39.8 */ 50.04, 48.12, 46.38, 44.66, + /* 50.1 */ 43.10, 41.73, 40.50, 39.22, + /* 63.1 */ 37.23, 35.77, 34.51, 32.81, + /* 79.4 */ 31.32, 30.36, 29.02, 27.60, + /* 100.0 */ 26.58, 25.91, 24.41, 23.01, + /* 125.9 */ 22.12, 21.25, 20.18, 19.00, + /* 158.5 */ 17.70, 16.82, 15.94, 15.12, + /* 199.5 */ 14.30, 13.41, 12.60, 11.98, + /* 251.2 */ 11.36, 10.57, 9.98, 9.43, + /* 316.2 */ 8.87, 8.46, 7.44, 7.12, + /* 398.1 */ 6.93, 6.68, 6.37, 6.06, + /* 501.2 */ 5.80, 5.55, 5.29, 5.02, + /* 631.0 */ 4.75, 4.48, 4.22, 3.98, + /* 794.3 */ 3.75, 3.51, 3.27, 3.22, + /* 1000.0 */ 3.12, 3.01, 2.91, 2.68, + /* 1258.9 */ 2.46, 2.15, 1.82, 1.46, + /* 1584.9 */ 1.07, 0.61, 0.13, -0.35, + /* 1995.3 */ -0.96, -1.56, -1.79, -2.35, + /* 2511.9 */ -2.95, -3.50, -4.01, -4.21, + /* 3162.3 */ -4.46, -4.99, -5.32, -5.35, + /* 3981.1 */ -5.13, -4.76, -4.31, -3.13, + /* 5011.9 */ -1.79, 0.08, 2.03, 4.03, + /* 6309.6 */ 5.80, 7.36, 8.81, 10.22, + /* 7943.3 */ 11.54, 12.51, 13.48, 14.21, + /* 10000.0 */ 14.79, 13.99, 12.85, 11.93, + /* 12589.3 */ 12.87, 15.19, 19.14, 23.69, + /* 15848.9 */ 33.52, 48.65, 59.42, 61.77, + /* 19952.6 */ 63.85, 66.04, 68.33, 70.09, + /* 25118.9 */ 70.66, 71.27, 71.91, 72.60, + }; + FLOAT8 freq_log; + unsigned index; + + if (freq < -.3) + freq=3758; + + if ( freq < 10. ) freq = 10.; + if ( freq > 29853. ) freq = 29853.; + + freq_log = 40. * log10 (0.1 * freq); /* 4 steps per third, starting at 10 Hz */ + index = (unsigned) freq_log; + assert ( index < sizeof(tab)/sizeof(*tab) ); + return tab [index] * (1 + index - freq_log) + tab [index+1] * (freq_log - index); +} + + + +/* ATHformula_jd - Compute ATH at a given frequency from experimental data. + Below 15000 Hz, this ATH curve is based on data merged from + various existing sources. New experimental data covers + frequencies above 15000 Hz. -jd + in: freq (Hz) +returns: ATH value at freq in dB, or minimum ATH value if input freq is -1 +design notes: + Above 15000 Hz, my data indicates roughly 10 dB between the edge of + ready detection, and statistical indistinguishability. To provide a + balance between my data, and ATH data from other sources, roughly 5 dB + is added above 15000 Hz, except at frequencies above 20500 Hz. The ATH + of 21000+ Hz frequencies is decreased by 5 dB, to reduce the possibility + of extra distortion that some output systems exhibit when given a contrived + sample with an intense, but hardly audible frequency. +*/ +FLOAT8 +ATHformula_jd( FLOAT8 freq ) +{ + int i; + int ifreq; + int at_i; + int tstep; + int xtrans; + FLOAT coeff[3]; + FLOAT8 rval; + + const FLOAT ath_lt100[] /* 20 - 120 Hz (for computing 0 - 100 Hz) */ + = { 74.0, 47.9, 35.2, 28.1, 23.5, 20.4 }; + + const FLOAT ath_lt500[] /* 100 - 600 Hz (for 100 - 500 Hz) */ + = { 23.5, 13.4, 9.4, 6.9, 5.9, 5.0 }; + + const FLOAT ath_gt500[] /* 500 Hz and above */ + = { /* 500 */ 5.9, 3.2, 1.6, -0.7, + /* 2500 */ -2.7, -4.5, -5.2, -4.8, -3.7, + /* 5000 */ -1.6, 1.5, 3.8, 5.3, 6.8, + /* 7500 */ 8.2, 9.5, 10.5, 11.3, 11.8, + /* 10000 */ 12.1, 12.2, 12.4, 12.4, 12.4, + /* 12500 */ 12.8, 13.5, 14.9, 16.8, 19.0, + /* 15000 */ 23.0, 27.0, 33.0, 36.5, 39.5, + /* 17500 */ 43.5, 51.5, 58.5, 65.0, 71.5, + /* 20000 */ 78.0, 79.5, 80.0, 80.5, 80.5, 80.5 }; + + const FLOAT *ath_table[4]; + const int ath_table_step[4] = { 20, 100, 500, 500 }; + const FLOAT ath_table_xratio[4] = { 0.05, 0.01, 0.002, 0.002 }; + + ath_table[0] = ath_lt100; + ath_table[1] = ath_lt500; + ath_table[3] = ath_gt500; + + if( freq >= -0.5 && freq < 22000 ) { + ifreq = (int) freq; + at_i = ( (((99 - ifreq) >> (sizeof(int) * 8 - 1)) & 0x1) + | (((499 - ifreq) >> (sizeof(int) * 8 - 2)) & 0x3) ); + tstep = ath_table_step[at_i]; + + i = (ifreq / tstep); + i -= 2; + if( i >= 0 ) { + qinterp_cf_42( ath_table[at_i] + i, coeff ); + xtrans = (i + 2) * tstep; + } else { /* leading edge */ + qinterp_cf_3( ath_table[at_i], coeff ); + xtrans = tstep; + } + rval = qinterp_eval( coeff, freq, (FLOAT)xtrans, ath_table_xratio[at_i]); + return(rval); + } else if( freq < 0 ) { + return(-5.2); /* minimum value from table */ + } else { + return( ath_gt500[ 22000 / 500 - 1 ] ); /* 22kHz ATH used for 22kHz+ */ + } +} + + + +FLOAT8 ATHformula(FLOAT8 f,lame_global_flags *gfp) +{ + switch(gfp->ATHtype) + { + case 0: + return ATHformula_GB(f, 9); + case 1: + return ATHformula_Frank(f); + case 2: + return ATHformula_GB(f, 0); + case 3: + return ATHformula_GB(f, 1) +6; /*modification of GB formula by Roel*/ + case 4: + if (!(gfp->VBR == vbr_off || gfp->VBR == vbr_abr)) /*this case should be used with true vbr only*/ + return ATHformula_GB(f,gfp->VBR_q); + case 5: + return ATHformula_jd(f); + } + + return ATHformula_GB(f, 0); +} + +/* see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */ +FLOAT8 freq2bark(FLOAT8 freq) +{ + /* input: freq in hz output: barks */ + if (freq<0) freq=0; + freq = freq * 0.001; + return 13.0*atan(.76*freq) + 3.5*atan(freq*freq/(7.5*7.5)); +} + +/* see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */ +FLOAT8 freq2cbw(FLOAT8 freq) +{ + /* input: freq in hz output: critical band width */ + freq = freq * 0.001; + return 25+75*pow(1+1.4*(freq*freq),0.69); +} + + + + + + +/*********************************************************************** + * compute bitsperframe and mean_bits for a layer III frame + **********************************************************************/ +void getframebits(const lame_global_flags * gfp, int *bitsPerFrame, int *mean_bits) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int whole_SpF; /* integral number of Slots per Frame without padding */ + int bit_rate; + + /* get bitrate in kbps [?] */ + if (gfc->bitrate_index) + bit_rate = bitrate_table[gfp->version][gfc->bitrate_index]; + else + bit_rate = gfp->brate; + assert ( bit_rate <= 550 ); + + // bytes_per_frame = bitrate * 1000 / ( gfp->out_samplerate / (gfp->version == 1 ? 1152 : 576 )) / 8; + // bytes_per_frame = bitrate * 1000 / gfp->out_samplerate * (gfp->version == 1 ? 1152 : 576 ) / 8; + // bytes_per_frame = bitrate * ( gfp->version == 1 ? 1152/8*1000 : 576/8*1000 ) / gfp->out_samplerate; + + whole_SpF = (gfp->version+1)*72000*bit_rate / gfp->out_samplerate; + + /* main encoding routine toggles padding on and off */ + /* one Layer3 Slot consists of 8 bits */ + *bitsPerFrame = 8 * (whole_SpF + gfc->padding); + + // sideinfo_len + *mean_bits = (*bitsPerFrame - 8*gfc->sideinfo_len) / gfc->mode_gr; +} + + + + +#define ABS(A) (((A)>0) ? (A) : -(A)) + +int FindNearestBitrate( +int bRate, /* legal rates from 32 to 448 */ +int version, /* MPEG-1 or MPEG-2 LSF */ +int samplerate) /* convert bitrate in kbps to index */ +{ + int bitrate = 0; + int i; + + for ( i = 1; i <= 14; i++ ) + if ( ABS (bitrate_table[version][i] - bRate) < ABS (bitrate - bRate) ) + bitrate = bitrate_table [version] [i]; + + return bitrate; +} + + +/* map frequency to a valid MP3 sample frequency + * + * Robert.Hegemann@gmx.de 2000-07-01 + */ +int map2MP3Frequency(int freq) +{ + if (freq <= 8000) return 8000; + if (freq <= 11025) return 11025; + if (freq <= 12000) return 12000; + if (freq <= 16000) return 16000; + if (freq <= 22050) return 22050; + if (freq <= 24000) return 24000; + if (freq <= 32000) return 32000; + if (freq <= 44100) return 44100; + + return 48000; +} + +int BitrateIndex( +int bRate, /* legal rates from 32 to 448 kbps */ +int version, /* MPEG-1 or MPEG-2/2.5 LSF */ +int samplerate) /* convert bitrate in kbps to index */ +{ + int i; + + for ( i = 0; i <= 14; i++) + if ( bitrate_table [version] [i] == bRate ) + return i; + + return -1; +} + +/* convert samp freq in Hz to index */ + +int SmpFrqIndex ( int sample_freq, int* const version ) +{ + switch ( sample_freq ) { + case 44100: *version = 1; return 0; + case 48000: *version = 1; return 1; + case 32000: *version = 1; return 2; + case 22050: *version = 0; return 0; + case 24000: *version = 0; return 1; + case 16000: *version = 0; return 2; + case 11025: *version = 0; return 0; + case 12000: *version = 0; return 1; + case 8000: *version = 0; return 2; + default: *version = 0; return -1; + } +} + + +/***************************************************************************** +* +* End of bit_stream.c package +* +*****************************************************************************/ + +/* reorder the three short blocks By Takehiro TOMINAGA */ +/* + Within each scalefactor band, data is given for successive + time windows, beginning with window 0 and ending with window 2. + Within each window, the quantized values are then arranged in + order of increasing frequency... +*/ +void freorder(int scalefac_band[],FLOAT8 ix_orig[576]) { + int i,sfb, window, j=0; + FLOAT8 ix[576]; + for (sfb = 0; sfb < SBMAX_s; sfb++) { + int start = scalefac_band[sfb]; + int end = scalefac_band[sfb + 1]; + for (window = 0; window < 3; window++) { + for (i = start; i < end; ++i) { + ix[j++] = ix_orig[3*i+window]; + } + } + } + memcpy(ix_orig,ix,576*sizeof(FLOAT8)); +} + + + + + + + +#ifndef KLEMM_44 + + +/* resampling via FIR filter, blackman window */ +inline static FLOAT8 blackman(FLOAT8 x,FLOAT8 fcn,int l) +{ + /* This algorithm from: +SIGNAL PROCESSING ALGORITHMS IN FORTRAN AND C +S.D. Stearns and R.A. David, Prentice-Hall, 1992 + */ + FLOAT8 bkwn,x2; + FLOAT8 wcn = (PI * fcn); + + x /= l; + if (x<0) x=0; + if (x>1) x=1; + x2 = x - .5; + + bkwn = 0.42 - 0.5*cos(2*x*PI) + 0.08*cos(4*x*PI); + if (fabs(x2)<1e-9) return wcn/PI; + else + return ( bkwn*sin(l*wcn*x2) / (PI*l*x2) ); + + +} + +/* gcd - greatest common divisor */ +/* Joint work of Euclid and M. Hendry */ + +int gcd ( int i, int j ) +{ +// assert ( i > 0 && j > 0 ); + return j ? gcd(j, i % j) : i; +} + + + +/* copy in new samples from in_buffer into mfbuf, with resampling & scaling + if necessary. n_in = number of samples from the input buffer that + were used. n_out = number of samples copied into mfbuf */ + +void fill_buffer(lame_global_flags *gfp, + sample_t *mfbuf[2], + sample_t *in_buffer[2], + int nsamples, int *n_in, int *n_out) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ch,i; + + /* copy in new samples into mfbuf, with resampling if necessary */ + if (gfc->resample_ratio != 1.0) { + for (ch = 0; ch < gfc->channels_out; ch++) { + *n_out = + fill_buffer_resample(gfp, &mfbuf[ch][gfc->mf_size], + gfp->framesize, in_buffer[ch], + nsamples, n_in, ch); + } + } + else { + *n_out = Min(gfp->framesize, nsamples); + *n_in = *n_out; + for (i = 0; i < *n_out; ++i) { + mfbuf[0][gfc->mf_size + i] = in_buffer[0][i]; + if (gfc->channels_out == 2) + mfbuf[1][gfc->mf_size + i] = in_buffer[1][i]; + } + } + + /* user selected scaling of the samples */ + if (gfp->scale != 0 && gfp->scale != 1.0) { + for (i=0 ; i<*n_out; ++i) { + mfbuf[0][gfc->mf_size+i] *= gfp->scale; + if (gfc->channels_out == 2) + mfbuf[1][gfc->mf_size + i] *= gfp->scale; + } + } + + /* user selected scaling of the channel 0 (left) samples */ + if (gfp->scale_left != 0 && gfp->scale_left != 1.0) { + for (i=0 ; i<*n_out; ++i) { + mfbuf[0][gfc->mf_size+i] *= gfp->scale_left; + } + } + + /* user selected scaling of the channel 1 (right) samples */ + if (gfc->channels_out == 2) { + if (gfp->scale_right != 0 && gfp->scale_right != 1.0) { + for (i=0 ; i<*n_out; ++i) { + mfbuf[1][gfc->mf_size + i] *= gfp->scale_right; + } + } + } +} + + + + +int fill_buffer_resample( + lame_global_flags *gfp, + sample_t *outbuf, + int desired_len, + sample_t *inbuf, + int len, + int *num_used, + int ch) +{ + + + lame_internal_flags *gfc=gfp->internal_flags; + int BLACKSIZE; + FLOAT8 offset,xvalue; + int i,j=0,k; + int filter_l; + FLOAT8 fcn,intratio; + FLOAT *inbuf_old; + int bpc; /* number of convolution functions to pre-compute */ + bpc = gfp->out_samplerate/gcd(gfp->out_samplerate,gfp->in_samplerate); + if (bpc>BPC) bpc = BPC; + + intratio=( fabs(gfc->resample_ratio - floor(.5+gfc->resample_ratio)) < .0001 ); + fcn = 1.00/gfc->resample_ratio; + if (fcn>1.00) fcn=1.00; + filter_l = gfp->quality < 7 ? 31 : 7; + filter_l = 31; + if (0==filter_l % 2 ) --filter_l;/* must be odd */ + filter_l += intratio; /* unless resample_ratio=int, it must be even */ + + + BLACKSIZE = filter_l+1; /* size of data needed for FIR */ + + if ( gfc->fill_buffer_resample_init == 0 ) { + gfc->inbuf_old[0]=calloc(BLACKSIZE,sizeof(gfc->inbuf_old[0][0])); + gfc->inbuf_old[1]=calloc(BLACKSIZE,sizeof(gfc->inbuf_old[0][0])); + for (i=0; i<=2*bpc; ++i) + gfc->blackfilt[i]=calloc(BLACKSIZE,sizeof(gfc->blackfilt[0][0])); + + gfc->itime[0]=0; + gfc->itime[1]=0; + + /* precompute blackman filter coefficients */ + for ( j = 0; j <= 2*bpc; j++ ) { + FLOAT8 sum = 0.; + offset = (j-bpc) / (2.*bpc); + for ( i = 0; i <= filter_l; i++ ) + sum += + gfc->blackfilt[j][i] = blackman(i-offset,fcn,filter_l); + for ( i = 0; i <= filter_l; i++ ) + gfc->blackfilt[j][i] /= sum; + } + gfc->fill_buffer_resample_init = 1; + } + + inbuf_old=gfc->inbuf_old[ch]; + + /* time of j'th element in inbuf = itime + j/ifreq; */ + /* time of k'th element in outbuf = j/ofreq */ + for (k=0;kresample_ratio; /* time of k'th output sample */ + j = floor( time0 -gfc->itime[ch] ); + + /* check if we need more input data */ + if ((filter_l + j - filter_l/2) >= len) break; + + /* blackman filter. by default, window centered at j+.5(filter_l%2) */ + /* but we want a window centered at time0. */ + offset = ( time0 -gfc->itime[ch] - (j + .5*(filter_l%2))); + assert(fabs(offset)<=.501); + + /* find the closest precomputed window for this offset: */ + joff = floor((offset*2*bpc) + bpc +.5); + + xvalue = 0.; + for (i=0 ; i<=filter_l ; ++i) { + int j2 = i+j-filter_l/2; + int y; + assert(j2= 0); + y = (j2<0) ? inbuf_old[BLACKSIZE+j2] : inbuf[j2]; +#define PRECOMPUTE +#ifdef PRECOMPUTE + xvalue += y*gfc->blackfilt[joff][i]; +#else + xvalue += y*blackman(i-offset,fcn,filter_l); /* very slow! */ +#endif + } + outbuf[k]=xvalue; + } + + + /* k = number of samples added to outbuf */ + /* last k sample used data from [j-filter_l/2,j+filter_l-filter_l/2] */ + + /* how many samples of input data were used: */ + *num_used = Min(len,filter_l+j-filter_l/2); + + /* adjust our input time counter. Incriment by the number of samples used, + * then normalize so that next output sample is at time 0, next + * input buffer is at time itime[ch] */ + gfc->itime[ch] += *num_used - k*gfc->resample_ratio; + + /* save the last BLACKSIZE samples into the inbuf_old buffer */ + if (*num_used >= BLACKSIZE) { + for (i=0;ireport.debugf != NULL ) { + gfc->report.debugf( format, args ); + } else { + (void) vfprintf ( stderr, format, args ); + fflush ( stderr ); /* an debug function should flush immediately */ + } + + va_end ( args ); +} + + +void lame_msgf (const lame_internal_flags *gfc, const char* format, ... ) +{ + va_list args; + + va_start ( args, format ); + + if ( gfc->report.msgf != NULL ) { + gfc->report.msgf( format, args ); + } else { + (void) vfprintf ( stderr, format, args ); + fflush ( stderr ); /* we print to stderr, so me may want to flush */ + } + + va_end ( args ); +} + + +void lame_errorf (const lame_internal_flags *gfc, const char* format, ... ) +{ + va_list args; + + va_start ( args, format ); + + if ( gfc->report.errorf != NULL ) { + gfc->report.errorf( format, args ); + } else { + (void) vfprintf ( stderr, format, args ); + fflush ( stderr ); /* an error function should flush immediately */ + } + + va_end ( args ); +} + + + +/*********************************************************************** + * + * routines to detect CPU specific features like 3DNow, MMX, SIMD + * + * donated by Frank Klemm + * added Robert Hegemann 2000-10-10 + * + ***********************************************************************/ + +int has_i387 ( void ) +{ +#ifdef HAVE_NASM + return 1; +#else + return 0; /* don't know, assume not */ +#endif +} + +int has_MMX ( void ) +{ +#ifdef HAVE_NASM + extern int has_MMX_nasm ( void ); + return has_MMX_nasm (); +#else + return 0; /* don't know, assume not */ +#endif +} + +int has_3DNow ( void ) +{ +#ifdef HAVE_NASM + extern int has_3DNow_nasm ( void ); + return has_3DNow_nasm (); +#else + return 0; /* don't know, assume not */ +#endif +} + +int has_SIMD ( void ) +{ +#ifdef HAVE_NASM + extern int has_SIMD_nasm ( void ); + return has_SIMD_nasm (); +#else + return 0; /* don't know, assume not */ +#endif +} + +int has_SIMD2 ( void ) +{ +#ifdef HAVE_NASM + extern int has_SIMD2_nasm ( void ); + return has_SIMD2_nasm (); +#else + return 0; /* don't know, assume not */ +#endif +} + +/*********************************************************************** + * + * some simple statistics + * + * bitrate index 0: free bitrate -> not allowed in VBR mode + * : bitrates, kbps depending on MPEG version + * bitrate index 15: forbidden + * + * mode_ext: + * 0: LR + * 1: LR-i + * 2: MS + * 3: MS-i + * + ***********************************************************************/ + +void updateStats( lame_internal_flags * const gfc ) +{ + assert ( gfc->bitrate_index < 16u ); + assert ( gfc->mode_ext < 4u ); + + /* count bitrate indices */ + gfc->bitrate_stereoMode_Hist [gfc->bitrate_index] [4] ++; + + /* count 'em for every mode extension in case of 2 channel encoding */ + if (gfc->channels_out == 2) + gfc->bitrate_stereoMode_Hist [gfc->bitrate_index] [gfc->mode_ext]++; +} + + + +/* caution: a[] will be resorted!! + */ +int select_kth_int(int a[], int N, int k) +{ + int i, j, l, r, v, w; + + l = 0; + r = N-1; + while (r > l) { + v = a[r]; + i = l-1; + j = r; + for (;;) { + while (a[++i] < v) /*empty*/; + while (a[--j] > v) /*empty*/; + if (i >= j) + break; + /* swap i and j */ + w = a[i]; + a[i] = a[j]; + a[j] = w; + } + /* swap i and r */ + w = a[i]; + a[i] = a[r]; + a[r] = w; + if (i >= k) + r = i-1; + if (i <= k) + l = i+1; + } + return a[k]; +} + + + +void disable_FPE(void) { +/* extremly system dependent stuff, move to a lib to make the code readable */ +/*==========================================================================*/ + + + + /* + * Disable floating point exceptions + */ + + + + +#if defined(__FreeBSD__) && !defined(__alpha__) + { + /* seet floating point mask to the Linux default */ + fp_except_t mask; + mask = fpgetmask(); + /* if bit is set, we get SIGFPE on that error! */ + fpsetmask(mask & ~(FP_X_INV | FP_X_DZ)); + /* DEBUGF("FreeBSD mask is 0x%x\n",mask); */ + } +#endif + +#if defined(__riscos__) && !defined(ABORTFP) + /* Disable FPE's under RISC OS */ + /* if bit is set, we disable trapping that error! */ + /* _FPE_IVO : invalid operation */ + /* _FPE_DVZ : divide by zero */ + /* _FPE_OFL : overflow */ + /* _FPE_UFL : underflow */ + /* _FPE_INX : inexact */ + DisableFPETraps(_FPE_IVO | _FPE_DVZ | _FPE_OFL); +#endif + + /* + * Debugging stuff + * The default is to ignore FPE's, unless compiled with -DABORTFP + * so add code below to ENABLE FPE's. + */ + +#if defined(ABORTFP) +#if defined(_MSC_VER) + { + + /* set affinity to a single CPU. Fix for EAC/lame on SMP systems from + "Todd Richmond" */ + SYSTEM_INFO si; + GetSystemInfo(&si); + SetProcessAffinityMask(GetCurrentProcess(), si.dwActiveProcessorMask); + +#include + unsigned int mask; + mask = _controlfp(0, 0); + mask &= ~(_EM_OVERFLOW | _EM_UNDERFLOW | _EM_ZERODIVIDE | _EM_INVALID); + mask = _controlfp(mask, _MCW_EM); + } +#elif defined(__CYGWIN__) +# define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) + +# define _EM_INEXACT 0x00000020 /* inexact (precision) */ +# define _EM_UNDERFLOW 0x00000010 /* underflow */ +# define _EM_OVERFLOW 0x00000008 /* overflow */ +# define _EM_ZERODIVIDE 0x00000004 /* zero divide */ +# define _EM_INVALID 0x00000001 /* invalid */ + { + unsigned int mask; + _FPU_GETCW(mask); + /* Set the FPU control word to abort on most FPEs */ + mask &= ~(_EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID); + _FPU_SETCW(mask); + } +# elif defined(__linux__) + { + +# include +# ifndef _FPU_GETCW +# define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) +# endif +# ifndef _FPU_SETCW +# define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) +# endif + + /* + * Set the Linux mask to abort on most FPE's + * if bit is set, we _mask_ SIGFPE on that error! + * mask &= ~( _FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM ); + */ + + unsigned int mask; + _FPU_GETCW(mask); + mask &= ~(_FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM); + _FPU_SETCW(mask); + } +#endif +#endif /* ABORTFP */ +} + + +/* end of util.c */ diff -Nru swftools-0.9.2+ds1/lib/lame/util.h swftools-0.9.1/lib/lame/util.h --- swftools-0.9.2+ds1/lib/lame/util.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/util.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,615 @@ +/* + * lame utility library include file + * + * Copyright (c) 1999 Albert L Faber + * + * 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 LAME_UTIL_H +#define LAME_UTIL_H + +/*********************************************************************** +* +* Global Include Files +* +***********************************************************************/ +#include "machine.h" +#include "encoder.h" +#include "lame.h" +#include "lame_global_flags.h" +#include "lame-analysis.h" +#include "id3tag.h" + +/*********************************************************************** +* +* Global Definitions +* +***********************************************************************/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#ifdef UINT_MAX +# define MAX_U_32_NUM UINT_MAX +#else +# define MAX_U_32_NUM 0xFFFFFFFF +#endif + +#ifndef PI +# ifdef M_PI +# define PI M_PI +# else +# define PI 3.14159265358979323846 +# endif +#endif + + +#ifdef M_LN2 +# define LOG2 M_LN2 +#else +# define LOG2 0.69314718055994530942 +#endif + +#ifdef M_LN10 +# define LOG10 M_LN10 +#else +# define LOG10 2.30258509299404568402 +#endif + + +#ifdef M_SQRT2 +# define SQRT2 M_SQRT2 +#else +# define SQRT2 1.41421356237309504880 +#endif + + +#define HAN_SIZE 512 +#define CRC16_POLYNOMIAL 0x8005 +#define MAX_BITS 4095 + +/* "bit_stream.h" Definitions */ +#define BUFFER_SIZE LAME_MAXMP3BUFFER + +#define Min(A, B) ((A) < (B) ? (A) : (B)) +#define Max(A, B) ((A) > (B) ? (A) : (B)) + + + + + +/*********************************************************************** +* +* Global Type Definitions +* +***********************************************************************/ + + + +/* "bit_stream.h" Type Definitions */ + +typedef struct bit_stream_struc { + unsigned char *buf; /* bit stream buffer */ + int buf_size; /* size of buffer (in number of bytes) */ + int totbit; /* bit counter of bit stream */ + int buf_byte_idx; /* pointer to top byte in buffer */ + int buf_bit_idx; /* pointer to top bit of top byte in buffer */ + + /* format of file in rd mode (BINARY/ASCII) */ +} Bit_stream_struc; + +#include "l3side.h" + + +/* variables used for --nspsytune */ +typedef struct { + int use; /* indicates the use of exp_nspsytune */ + int safejoint; /* safe joint stereo mode */ + FLOAT last_en_subshort[4][9]; + FLOAT last_attack_intensity[4][9]; + FLOAT last_thm[4][SBMAX_s][3]; + int last_attacks[4][3]; + FLOAT pe_l[4],pe_s[4]; + FLOAT pefirbuf[19]; + FLOAT bass,alto,treble,sfb21; +} nsPsy_t; + +/* variables used for --alt-preset */ +typedef struct { + + // indicates the use of alt-preset + int use; + + // short block tuning + int attackthre; + int attackthre_s; + + // adjustment to joint stereo + FLOAT8 ms_maskadjust; + + // adjustments to quantization selection + int quantcomp_current; // current quant_compare mode we are using + FLOAT8 quantcomp_adjust_rh_tot; // adjustments for tot_noise with vbr-old + FLOAT8 quantcomp_adjust_rh_max; // adjustments for max_noise with vbr-old + FLOAT8 quantcomp_adjust_mtrh; // adjustments for calc_scalefac "c" with vbr-mtrh + int quantcomp_type_s; // quantization comparison to switch to on non-normal blocks + int quantcomp_alt_type; // third quantization comparison to use for special cases + // such as high athadjust values, or long blocks, etc + + // tunings reliant upon athadjust + FLOAT8 athadjust_max_val; // maximum value of athadjust before limit is applied + FLOAT8 athadjust_switch_level; // level of athadjust at which to apply tunings at + // x <= 0 == never switch, x >= 1 == always switch + FLOAT8 athadjust_msfix; // msfix adjustment based on athadjust + int athadjust_safe_noiseshaping; // if 0, noise shaping 2 will not be used no matter what + // the noise shaping type would normally be set to + FLOAT8 athadjust_safe_noiseshaping_thre; // value which max_pow_alt must be greater than + // for noise shaping 2 to be used "safely" + FLOAT8 athadjust_safe_athaasensitivity; // used for second determination if it is safe to switch + // to noise shaping 2 +} presetTune_t; + +typedef struct +{ + int sum; // what we have seen so far + int seen; // how many frames we have seen in this chunk + int want; // how many frames we want to collect into one chunk + int pos; // actual position in our bag + int size; // size of our bag + int *bag; // pointer to our bag +} VBR_seek_info_t; + + +/** + * ATH related stuff, if something new ATH related has to be added, + * please plugg it here into the ATH_t struct + */ +typedef struct +{ + int use_adjust; // method for the auto adjustment + FLOAT8 adjust; // lowering based on peak volume, 1 = no lowering + FLOAT8 adjust_limit; // limit for dynamic ATH adjust + FLOAT8 decay; // determined to lower x dB each second + FLOAT8 floor; // lowest ATH value + FLOAT8 l[SBMAX_l]; // ATH for sfbs in long blocks + FLOAT8 s[SBMAX_s]; // ATH for sfbs in short blocks + FLOAT8 cb[CBANDS]; // ATH for convolution bands +} ATH_t; + +/** + * VBR related stuff + */ +typedef struct +{ + int quality; + FLOAT8 mask_adjust; // the dbQ stuff + int smooth; // 0=no, 1=peaks, 2=+-4 + int bitpressure; // strategy for bitpressure situations + FLOAT8 scratch[192]; +} VBR_t; + +/** + * PSY Model related stuff + */ +typedef struct +{ + int tonalityPatch; // temporaly needed by VBR + FLOAT cwlimit; + FLOAT8 prvTonRed[CBANDS]; +} PSY_t; + + +/* Guest structure, only temporarly here */ + +typedef enum { + coding_MPEG_Layer_1 = 1, + coding_MPEG_Layer_2 = 2, + coding_MPEG_Layer_3 = 3, + coding_MPEG_AAC = 4, + coding_Ogg_Vorbis = 5, + coding_MPEG_plus = 6 +} coding_t; + +#define MAX_CHANNELS 2 + +typedef struct { + unsigned long Class_ID; /* Class ID to recognize a resample_t + object */ + FLOAT8 sample_freq_in; /* Input sample frequency in Hz */ + FLOAT8 sample_freq_out; /* requested Output sample frequency in Hz */ + FLOAT8 lowpass_freq; /* lowpass frequency, this is the -6 dB + point */ + int scale_in; /* the resampling is actually done by + scale_out: */ + int scale_out; /* frequency is + samplefreq_in * scale_out / scal */ + int taps; /* number of taps for every FIR resample + filter */ + + sample_t** fir; /* the FIR resample filters: + fir [scale_out] [taps */ + void* firfree; /* start address of the alloced memory for + fir, */ + unsigned char* src_step; + sample_t* in_old [MAX_CHANNELS]; + // uint64_t sample_count [MAX_CHANNELS]; + unsigned fir_stepper [MAX_CHANNELS]; + int inp_stepper [MAX_CHANNELS]; + +} resample_t; + + +struct lame_internal_flags { + + /******************************************************************** + * internal variables NOT set by calling program, and should not be * + * modified by the calling program * + ********************************************************************/ + + /* + * Some remarks to the Class_ID field: + * The Class ID is an Identifier for a pointer to this struct. + * It is very unlikely that a pointer to lame_global_flags has the same 32 bits + * in it's structure (large and other special properties, for instance prime). + * + * To test that the structure is right and initialized, use: + * if ( gfc -> Class_ID == LAME_ID ) ... + * Other remark: + * If you set a flag to 0 for uninit data and 1 for init data, the right test + * should be "if (flag == 1)" and NOT "if (flag)". Unintended modification + * of this element will be otherwise misinterpreted as an init. + */ + + #define LAME_ID 0xFFF88E3B + unsigned long Class_ID; + + struct { + void (*msgf) (const char *format, va_list ap); + void (*debugf)(const char *format, va_list ap); + void (*errorf)(const char *format, va_list ap); + } report; + + int lame_encode_frame_init; + int iteration_init_init; + int fill_buffer_resample_init; + int psymodel_init; + + int padding; /* padding for the current frame? */ + int mode_gr; /* granules per frame */ + int channels_in; /* number of channels in the input data stream (PCM or decoded PCM) */ + int channels_out; /* number of channels in the output data stream (not used for decoding) */ + resample_t* resample_in; /* context for coding (PCM=>MP3) resampling */ + resample_t* resample_out; /* context for decoding (MP3=>PCM) resampling */ + FLOAT8 samplefreq_in; + FLOAT8 samplefreq_out; + uint16_t nMusicCRC; + +#ifndef MFSIZE +# define MFSIZE ( 3*1152 + ENCDELAY - MDCTDELAY ) +#endif +#ifdef KLEMM_44 + sample_t* mfbuf [MAX_CHANNELS]; +#else + sample_t mfbuf [2] [MFSIZE]; +#endif + size_t frame_size; /* size of one frame in samples per channel */ + lame_global_flags* gfp; /* needed as long as the frame encoding functions must access gfp (all needed information can be added to gfc) */ + coding_t coding; /* MPEG Layer 1/2/3, Ogg Vorbis, MPEG AAC, ... */ + unsigned long frame_count; /* Number of frames coded, 2^32 > 3 years */ + int mf_samples_to_encode; + int mf_size; + FLOAT8 ampl; /* amplification at the end of the current chunk (1. = 0 dB) */ + FLOAT8 last_ampl; /* amplification at the end of the last chunk (1. = 0 dB) */ + int VBR_min_bitrate; /* min bitrate index */ + int VBR_max_bitrate; /* max bitrate index */ + FLOAT resample_ratio; /* input_samp_rate/output_samp_rate */ + int bitrate_index; + int samplerate_index; + int mode_ext; + + + /* lowpass and highpass filter control */ + FLOAT8 lowpass1,lowpass2; /* normalized frequency bounds of passband */ + FLOAT8 highpass1,highpass2; /* normalized frequency bounds of passband */ + + /* polyphase filter (filter_type=0) */ + int lowpass_band; /* zero bands >= lowpass_band in the polyphase filterbank */ + int highpass_band; /* zero bands <= highpass_band */ + int lowpass_start_band; /* amplify bands between start */ + int lowpass_end_band; /* and end for lowpass */ + int highpass_start_band; /* amplify bands between start */ + int highpass_end_band; /* and end for highpass */ + + + int filter_type; /* 0=polyphase filter, 1= FIR filter 2=MDCT filter(bad)*/ + int quantization; /* 0 = ISO formual, 1=best amplitude */ + int noise_shaping; /* 0 = none + 1 = ISO AAC model + 2 = allow scalefac_select=1 + */ + + int noise_shaping_amp; /* 0 = ISO model: amplify all distorted bands + 1 = amplify within 50% of max (on db scale) + 2 = amplify only most distorted band + 3 = amplify only most distorted band and + use pseudo half step + */ + + int psymodel; /* 1 = gpsycho. 0 = none */ + int noise_shaping_stop; /* 0 = stop at over=0, all scalefacs amplified or + a scalefac has reached max value + 1 = stop when all scalefacs amplified or + a scalefac has reached max value + 2 = stop when all scalefacs amplified + */ + + int use_best_huffman; /* 0 = no. 1=outside loop 2=inside loop(slow) */ + + + + + /* variables used by lame.c */ + Bit_stream_struc bs; + III_side_info_t l3_side; + FLOAT8 ms_ratio[2]; + /* used for padding */ + int frac_SpF; + int slot_lag; + + + /* optional ID3 tags, used in id3tag.c */ + struct id3tag_spec tag_spec; + + + /* variables used by quantize.c */ + int OldValue[2]; + int CurrentStep; + FLOAT8 decay; + FLOAT8 masking_lower; + + char bv_scf[576]; + + int sfb21_extra; /* will be set in lame_init_params */ + + int is_mpeg1; /* 1 for MPEG-1, 0 for MPEG-2(.5) */ + +#ifndef KLEMM_44 + /* variables used by util.c */ + /* BPC = maximum number of filter convolution windows to precompute */ +#define BPC 320 + sample_t *inbuf_old [2]; + sample_t *blackfilt [2*BPC+1]; + FLOAT8 itime[2]; +#endif + int sideinfo_len; + + /* variables for newmdct.c */ + FLOAT8 sb_sample[2][2][18][SBLIMIT]; + FLOAT8 amp_lowpass[32]; + FLOAT8 amp_highpass[32]; + + /* variables for bitstream.c */ + /* mpeg1: buffer=511 bytes smallest frame: 96-38(sideinfo)=58 + * max number of frames in reservoir: 8 + * mpeg2: buffer=255 bytes. smallest frame: 24-23bytes=1 + * with VBR, if you are encoding all silence, it is possible to + * have 8kbs/24khz frames with 1byte of data each, which means we need + * to buffer up to 255 headers! */ + /* also, max_header_buf has to be a power of two */ +#define MAX_HEADER_BUF 256 +#define MAX_HEADER_LEN 40 /* max size of header is 38 */ + struct { + int write_timing; + int ptr; + char buf[MAX_HEADER_LEN]; + } header[MAX_HEADER_BUF]; + + int h_ptr; + int w_ptr; + int ancillary_flag; + + + /* variables for reservoir.c */ + int ResvSize; /* in bits */ + int ResvMax; /* in bits */ + + + scalefac_struct scalefac_band; + + /* DATA FROM PSYMODEL.C */ +/* The static variables "r", "phi_sav", "new", "old" and "oldest" have */ +/* to be remembered for the unpredictability measure. For "r" and */ +/* "phi_sav", the first index from the left is the channel select and */ +/* the second index is the "age" of the data. */ + FLOAT8 minval[CBANDS]; + FLOAT8 nb_1[4][CBANDS], nb_2[4][CBANDS]; + FLOAT8 nb_s1[4][CBANDS], nb_s2[4][CBANDS]; + FLOAT8 *s3_ss; + FLOAT8 *s3_ll; + + III_psy_xmin thm[4]; + III_psy_xmin en[4]; + + /* unpredictability calculation + */ + int cw_upper_index; + int cw_lower_index; + FLOAT ax_sav[4][2][HBLKSIZE]; + FLOAT bx_sav[4][2][HBLKSIZE]; + FLOAT rx_sav[4][2][HBLKSIZE]; + FLOAT cw[HBLKSIZE]; + + /* fft and energy calculation */ + FLOAT wsamp_L[2][BLKSIZE]; + FLOAT energy[HBLKSIZE]; + FLOAT wsamp_S[2][3][BLKSIZE_s]; + FLOAT energy_s[3][HBLKSIZE_s]; + FLOAT tot_ener[4]; + + + /* loudness calculation (for adaptive threshold of hearing) */ + FLOAT loudness_sq[2][2]; /* loudness^2 approx. per granule and channel */ + FLOAT loudness_sq_save[2];/* account for granule delay of L3psycho_anal */ + + /* factor for tuning the (sample power) point below which adaptive threshold + of hearing adjustment occurs + */ + FLOAT athaa_sensitivity_p; + + + /* fft.c */ + FLOAT window[BLKSIZE], window_s[BLKSIZE_s/2]; + + + /* Scale Factor Bands */ + III_scalefac_t pseudohalf; + FLOAT8 w1_l[SBMAX_l], w2_l[SBMAX_l]; + FLOAT8 w1_s[SBMAX_s], w2_s[SBMAX_s]; + FLOAT8 mld_l[SBMAX_l],mld_s[SBMAX_s]; + int bu_l[SBMAX_l],bo_l[SBMAX_l] ; + int bu_s[SBMAX_s],bo_s[SBMAX_s] ; + int npart_l,npart_s; + int npart_l_orig,npart_s_orig; + + int s3ind[CBANDS][2]; + int s3ind_s[CBANDS][2]; + FLOAT8 SNR_s[CBANDS]; + + int numlines_s[CBANDS]; + int numlines_l[CBANDS]; + + + /* frame analyzer */ + FLOAT energy_save[4][HBLKSIZE]; + FLOAT8 pe_save[4]; + FLOAT8 ers_save[4]; + + /* simple statistics */ + int bitrate_stereoMode_Hist [16] [4+1]; + + /* ratios */ + FLOAT8 pe[4]; + FLOAT8 ms_ratio_s_old,ms_ratio_l_old; + FLOAT8 ms_ener_ratio_old; + + /* block type */ + int blocktype_old[2]; + + /* used by the frame analyzer */ + plotting_data *pinfo; + + /* CPU features */ + struct { + unsigned int i387 : 1; /* FPU is a normal Intel CPU */ + unsigned int MMX : 1; /* Pentium MMX, Pentium II...IV, K6, K6-2, + K6-III, Athlon */ + unsigned int AMD_3DNow : 1; /* K6-2, K6-III, Athlon */ + unsigned int SIMD : 1; /* Pentium III, Pentium 4 */ + unsigned int SIMD2 : 1; /* Pentium 4, K8 */ + } CPU_features; + + /* functions to replace with CPU feature optimized versions in takehiro.c */ + int (*choose_table)(const int *ix, const int *end, int *s); + + void (*fft_fht)(FLOAT *, int); + + nsPsy_t nsPsy; /* variables used for --nspsytune */ + presetTune_t presetTune; /* variables used for --alt-preset */ + + unsigned crcvalue; + + VBR_seek_info_t VBR_seek_table; // used for Xing VBR header + + ATH_t *ATH; // all ATH related stuff + VBR_t *VBR; + PSY_t *PSY; + + int nogap_total; + int nogap_current; +}; + + + + + +/*********************************************************************** +* +* Global Function Prototype Declarations +* +***********************************************************************/ +void freegfc(lame_internal_flags * const gfc); +extern int BitrateIndex(int, int,int); +extern int FindNearestBitrate(int,int,int); +extern int map2MP3Frequency(int freq); +extern int SmpFrqIndex(int, int* const); +extern FLOAT8 ATHformula(FLOAT8 f,lame_global_flags *gfp); +extern FLOAT8 freq2bark(FLOAT8 freq); +extern FLOAT8 freq2cbw(FLOAT8 freq); +extern void freorder(int scalefac_band[],FLOAT8 ix_orig[576]); +void disable_FPE(void); + +extern void +getframebits( const lame_global_flags *gfp, int *bitsPerFrame, int *mean_bits); + +void fill_buffer(lame_global_flags *gfp, + sample_t *mfbuf[2], + sample_t *in_buffer[2], + int nsamples, int *n_in, int *n_out); + +int fill_buffer_resample ( + lame_global_flags *gfp, + sample_t* outbuf, + int desired_len, + sample_t* inbuf, + int len, + int* num_used, + int channels ); + + +extern int has_i387 ( void ); +extern int has_MMX ( void ); +extern int has_3DNow ( void ); +extern int has_SIMD ( void ); +extern int has_SIMD2 ( void ); + +extern void updateStats (lame_internal_flags * const gfc); + + + +/*********************************************************************** +* +* Macros about Message Printing and Exit +* +***********************************************************************/ +extern void lame_errorf(const lame_internal_flags *gfc, const char *, ...); +extern void lame_debugf(const lame_internal_flags *gfc, const char *, ...); +extern void lame_msgf (const lame_internal_flags *gfc, const char *, ...); +#define DEBUGF lame_debugf +#define ERRORF lame_errorf +#define MSGF lame_msgf + + +int select_kth_int(int b[], int N, int k); + + + +#endif /* LAME_UTIL_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/vbrquantize.c swftools-0.9.1/lib/lame/vbrquantize.c --- swftools-0.9.2+ds1/lib/lame/vbrquantize.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/vbrquantize.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,1770 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999 Mark Taylor + * + * 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. + */ + +/* $Id: vbrquantize.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#include +#include "util.h" +#include "l3side.h" +#include "reservoir.h" +#include "quantize_pvt.h" +#include "vbrquantize.h" + +#ifdef WITH_DMALLOC +#include +#endif + + + +typedef union { + float f; + int i; +} fi_union; + +#define MAGIC_FLOAT (65536*(128)) +#define MAGIC_INT 0x4b000000 + +#ifdef TAKEHIRO_IEEE754_HACK + +#define DUFFBLOCKMQ() do { \ + xp = xr34[0] * sfpow34_p1; \ + xe = xr34[0] * sfpow34_eq; \ + xm = xr34[0] * sfpow34_m1; \ + if (xm > IXMAX_VAL) \ + return -1; \ + xp += MAGIC_FLOAT; \ + xe += MAGIC_FLOAT; \ + xm += MAGIC_FLOAT; \ + fi[0].f = xp; \ + fi[1].f = xe; \ + fi[2].f = xm; \ + fi[0].f = xp + (adj43asm - MAGIC_INT)[fi[0].i]; \ + fi[1].f = xe + (adj43asm - MAGIC_INT)[fi[1].i]; \ + fi[2].f = xm + (adj43asm - MAGIC_INT)[fi[2].i]; \ + fi[0].i -= MAGIC_INT; \ + fi[1].i -= MAGIC_INT; \ + fi[2].i -= MAGIC_INT; \ + x0 = fabs(xr[0]); \ + xp = x0 - pow43[fi[0].i] * sfpow_p1; \ + xe = x0 - pow43[fi[1].i] * sfpow_eq; \ + xm = x0 - pow43[fi[2].i] * sfpow_m1; \ + xp *= xp; \ + xe *= xe; \ + xm *= xm; \ + xfsf_eq = Max(xfsf_eq, xe); \ + xfsf_p1 = Max(xfsf_p1, xp); \ + xfsf_m1 = Max(xfsf_m1, xm); \ + ++xr; \ + ++xr34; \ + } while(0) + +#define DUFFBLOCK() do { \ + xp = xr34[0] * sfpow34_p1; \ + xe = xr34[0] * sfpow34_eq; \ + xm = xr34[0] * sfpow34_m1; \ + if (xm > IXMAX_VAL) \ + return -1; \ + xp += MAGIC_FLOAT; \ + xe += MAGIC_FLOAT; \ + xm += MAGIC_FLOAT; \ + fi[0].f = xp; \ + fi[1].f = xe; \ + fi[2].f = xm; \ + fi[0].f = xp + (adj43asm - MAGIC_INT)[fi[0].i]; \ + fi[1].f = xe + (adj43asm - MAGIC_INT)[fi[1].i]; \ + fi[2].f = xm + (adj43asm - MAGIC_INT)[fi[2].i]; \ + fi[0].i -= MAGIC_INT; \ + fi[1].i -= MAGIC_INT; \ + fi[2].i -= MAGIC_INT; \ + x0 = fabs(xr[0]); \ + xp = x0 - pow43[fi[0].i] * sfpow_p1; \ + xe = x0 - pow43[fi[1].i] * sfpow_eq; \ + xm = x0 - pow43[fi[2].i] * sfpow_m1; \ + xfsf_p1 += xp * xp; \ + xfsf_eq += xe * xe; \ + xfsf_m1 += xm * xm; \ + ++xr; \ + ++xr34; \ + } while(0) + +#else + +/********************************************************************* + * XRPOW_FTOI is a macro to convert floats to ints. + * if XRPOW_FTOI(x) = nearest_int(x), then QUANTFAC(x)=adj43asm[x] + * ROUNDFAC= -0.0946 + * + * if XRPOW_FTOI(x) = floor(x), then QUANTFAC(x)=asj43[x] + * ROUNDFAC=0.4054 + *********************************************************************/ +# define QUANTFAC(rx) adj43[rx] +# define ROUNDFAC 0.4054 +# define XRPOW_FTOI(src,dest) ((dest) = (int)(src)) + + +#endif + +/* caution: a[] will be resorted!! + */ +FLOAT8 select_kth(FLOAT8 a[], int N, int k) +{ + int i, j, l, r; + FLOAT8 v, w; + + l = 0; + r = N-1; + while (r > l) { + v = a[r]; + i = l-1; + j = r; + for (;;) { + while (a[++i] < v) /*empty*/; + while (a[--j] > v) /*empty*/; + if (i >= j) + break; + /* swap i and j */ + w = a[i]; + a[i] = a[j]; + a[j] = w; + } + /* swap i and r */ + w = a[i]; + a[i] = a[r]; + a[r] = w; + if (i >= k) + r = i-1; + if (i <= k) + l = i+1; + } + return a[k]; +} + + + + +static FLOAT8 +calc_sfb_noise(const FLOAT8 *xr, const FLOAT8 *xr34, int bw, int sf) +{ + int j; + fi_union fi; + FLOAT8 temp; + FLOAT8 xfsf = 0; + FLOAT8 sfpow, sfpow34; + + sfpow = POW20(sf+210); /*pow(2.0,sf/4.0); */ + sfpow34 = IPOW20(sf+210); /*pow(sfpow,-3.0/4.0);*/ + + for ( j = 0; j < bw ; ++j ) { + if ( xr34[j]*sfpow34 > IXMAX_VAL ) return -1; + +#ifdef TAKEHIRO_IEEE754_HACK + temp = sfpow34*xr34[j]; + temp += MAGIC_FLOAT; + fi.f = temp; + fi.f = temp + (adj43asm - MAGIC_INT)[fi.i]; + fi.i -= MAGIC_INT; +#else + temp = xr34[j]*sfpow34; + XRPOW_FTOI(temp, fi.i); + XRPOW_FTOI(temp + QUANTFAC(fi.i), fi.i); +#endif + + temp = fabs(xr[j])- pow43[fi.i]*sfpow; + xfsf += temp*temp; + } + return xfsf; +} + + + + +static FLOAT8 +calc_sfb_noise_mq( const FLOAT8 *xr, const FLOAT8 *xr34, int bw, int sf, + int mq, FLOAT8 *scratch ) +{ + int j, k; + fi_union fi; + FLOAT8 temp; + FLOAT8 sfpow, sfpow34, xfsfm = 0, xfsf = 0; + + sfpow = POW20(sf+210); /*pow(2.0,sf/4.0); */ + sfpow34 = IPOW20(sf+210); /*pow(sfpow,-3.0/4.0);*/ + + for ( j = 0; j < bw; ++j ) { + if ( xr34[j]*sfpow34 > IXMAX_VAL ) return -1; + +#ifdef TAKEHIRO_IEEE754_HACK + temp = sfpow34*xr34[j]; + temp += MAGIC_FLOAT; + fi.f = temp; + fi.f = temp + (adj43asm - MAGIC_INT)[fi.i]; + fi.i -= MAGIC_INT; +#else + temp = xr34[j]*sfpow34; + XRPOW_FTOI(temp, fi.i); + XRPOW_FTOI(temp + QUANTFAC(fi.i), fi.i); +#endif + + temp = fabs(xr[j])- pow43[fi.i]*sfpow; + temp *= temp; + + scratch[j] = temp; + if ( xfsfm < temp ) xfsfm = temp; + xfsf += temp; + } + if ( mq == 1 ) return bw*select_kth(scratch,bw,bw*13/16); + + xfsf /= bw; + for ( k = 1, j = 0; j < bw; ++j ) { + if ( scratch[j] > xfsf ) { + xfsfm += scratch[j]; + ++k; + } + } + return xfsfm/k * bw; +} + + + + +static FLOAT8 +calc_sfb_noise_ave(const FLOAT8 *xr, const FLOAT8 *xr34, int bw, int sf) +{ + double xp; + double xe; + double xm; +#ifdef TAKEHIRO_IEEE754_HACK + double x0; +#endif + int xx[3], j; + fi_union *fi = (fi_union *)xx; + FLOAT8 sfpow34_eq, sfpow34_p1, sfpow34_m1; + FLOAT8 sfpow_eq, sfpow_p1, sfpow_m1; + FLOAT8 xfsf_eq = 0, xfsf_p1 = 0, xfsf_m1 = 0; + + sfpow_eq = POW20(sf + 210); /*pow(2.0,sf/4.0); */ + sfpow_m1 = sfpow_eq * .8408964153; /* pow(2,(sf-1)/4.0) */ + sfpow_p1 = sfpow_eq * 1.189207115; + + sfpow34_eq = IPOW20(sf + 210); /*pow(sfpow,-3.0/4.0);*/ + sfpow34_m1 = sfpow34_eq * 1.13878863476; /* .84089 ^ -3/4 */ + sfpow34_p1 = sfpow34_eq * 0.878126080187; + +#ifdef TAKEHIRO_IEEE754_HACK + /* + * loop unrolled into "Duff's Device". Robert Hegemann + */ + j = (bw+3) / 4; + switch (bw % 4) { + default: + case 0: do{ DUFFBLOCK(); + case 3: DUFFBLOCK(); + case 2: DUFFBLOCK(); + case 1: DUFFBLOCK(); } while (--j); + } +#else + for (j = 0; j < bw; ++j) { + + if (xr34[j]*sfpow34_m1 > IXMAX_VAL) return -1; + + xe = xr34[j]*sfpow34_eq; + XRPOW_FTOI(xe, fi[0].i); + XRPOW_FTOI(xe + QUANTFAC(fi[0].i), fi[0].i); + xe = fabs(xr[j])- pow43[fi[0].i]*sfpow_eq; + xe *= xe; + + xp = xr34[j]*sfpow34_p1; + XRPOW_FTOI(xp, fi[0].i); + XRPOW_FTOI(xp + QUANTFAC(fi[0].i), fi[0].i); + xp = fabs(xr[j])- pow43[fi[0].i]*sfpow_p1; + xp *= xp; + + xm = xr34[j]*sfpow34_m1; + XRPOW_FTOI(xm, fi[0].i); + XRPOW_FTOI(xm + QUANTFAC(fi[0].i), fi[0].i); + xm = fabs(xr[j])- pow43[fi[0].i]*sfpow_m1; + xm *= xm; + + xfsf_eq += xe; + xfsf_p1 += xp; + xfsf_m1 += xm; + } +#endif + + if ( xfsf_eq < xfsf_p1 ) xfsf_eq = xfsf_p1; + if ( xfsf_eq < xfsf_m1 ) xfsf_eq = xfsf_m1; + return xfsf_eq; +} + + + +INLINE int +find_scalefac( const FLOAT8 *xr, const FLOAT8 *xr34, FLOAT8 l3_xmin, int bw ) +{ + FLOAT8 xfsf; + int i, sf, sf_ok, delsf; + + /* search will range from sf: -209 -> 45 */ + sf = -82; + delsf = 128; + + sf_ok = 10000; + for (i = 0; i < 7; ++i) { + delsf /= 2; + xfsf = calc_sfb_noise( xr, xr34, bw, sf ); + + if (xfsf < 0) { + /* scalefactors too small */ + sf += delsf; + } + else { + if (xfsf > l3_xmin) { + /* distortion. try a smaller scalefactor */ + sf -= delsf; + } + else { + sf_ok = sf; + sf += delsf; + } + } + } + + /* returning a scalefac without distortion, if possible + */ + return sf_ok > 45 ? sf : sf_ok; +} + +INLINE int +find_scalefac_mq( const FLOAT8 *xr, const FLOAT8 *xr34, FLOAT8 l3_xmin, + int bw, int mq, FLOAT8 *scratch ) +{ + FLOAT8 xfsf; + int i, sf, sf_ok, delsf; + + /* search will range from sf: -209 -> 45 */ + sf = -82; + delsf = 128; + + sf_ok = 10000; + for (i = 0; i < 7; ++i) { + delsf /= 2; + xfsf = calc_sfb_noise_mq( xr, xr34, bw, sf, mq, scratch ); + + if (xfsf < 0) { + /* scalefactors too small */ + sf += delsf; + } + else { + if (xfsf > l3_xmin) { + /* distortion. try a smaller scalefactor */ + sf -= delsf; + } + else { + sf_ok = sf; + sf += delsf; + } + } + } + + /* returning a scalefac without distortion, if possible + */ + return sf_ok > 45 ? sf : sf_ok; +} + +INLINE int +find_scalefac_ave( const FLOAT8 *xr, const FLOAT8 *xr34, FLOAT8 l3_xmin, int bw ) +{ + FLOAT8 xfsf; + int i, sf, sf_ok, delsf; + + /* search will range from sf: -209 -> 45 */ + sf = -82; + delsf = 128; + + sf_ok = 10000; + for (i = 0; i < 7; ++i) { + delsf /= 2; + xfsf = calc_sfb_noise_ave( xr, xr34, bw, sf ); + + if (xfsf < 0) { + /* scalefactors too small */ + sf += delsf; + } + else{ + if (xfsf > l3_xmin) { + /* distortion. try a smaller scalefactor */ + sf -= delsf; + } + else { + sf_ok = sf; + sf += delsf; + } + } + } + + /* returning a scalefac without distortion, if possible + */ + return sf_ok > 45 ? sf : sf_ok; +} + + +/** + * Robert Hegemann 2001-05-01 + * calculates quantization step size determined by allowed masking + */ +INLINE int +calc_scalefac( FLOAT8 l3_xmin, int bw, FLOAT8 preset_tune ) +{ + FLOAT8 const c = (preset_tune > 0 ? preset_tune + : 5.799142446); // 10 * 10^(2/3) * log10(4/3) + return (int)(c*log10(l3_xmin/bw)-.5); +} + + + +static const int max_range_short[SBMAX_s] = +{15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7, 7, 0 }; + +static const int max_range_long[SBMAX_l] = +{15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0}; + +static const int max_range_long_lsf_pretab[SBMAX_l] = +{ 7,7,7,7,7,7, 3,3,3,3,3, 0,0,0,0, 0,0,0, 0,0,0, 0 }; + + + +/* + sfb=0..5 scalefac < 16 + sfb>5 scalefac < 8 + + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + ol_sf = (cod_info->global_gain-210.0); + ol_sf -= 8*cod_info->subblock_gain[i]; + ol_sf -= ifqstep*scalefac[gr][ch].s[sfb][i]; + +*/ +INLINE int +compute_scalefacs_short( + int sf[][3], const gr_info *cod_info, int scalefac[][3], int *sbg ) +{ + const int maxrange1 = 15, maxrange2 = 7; + int maxrange, maxover = 0; + int sfb, i; + int ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + + for (i = 0; i < 3; ++i) { + int maxsf1 = 0, maxsf2 = 0, minsf = 1000; + /* see if we should use subblock gain */ + for (sfb = 0; sfb < 6; ++sfb) { /* part 1 */ + if (maxsf1 < -sf[sfb][i]) maxsf1 = -sf[sfb][i]; + if (minsf > -sf[sfb][i]) minsf = -sf[sfb][i]; + } + for (; sfb < SBPSY_s; ++sfb) { /* part 2 */ + if (maxsf2 < -sf[sfb][i]) maxsf2 = -sf[sfb][i]; + if (minsf > -sf[sfb][i]) minsf = -sf[sfb][i]; + } + + /* boost subblock gain as little as possible so we can + * reach maxsf1 with scalefactors + * 8*sbg >= maxsf1 + */ + maxsf1 = Max (maxsf1-maxrange1*ifqstep, maxsf2-maxrange2*ifqstep); + sbg[i] = 0; + if (minsf > 0) sbg[i] = floor (.125*minsf + .001); + if (maxsf1 > 0) sbg[i] = Max (sbg[i], (maxsf1/8 + (maxsf1 % 8 != 0))); + if (sbg[i] > 7) sbg[i] = 7; + + for (sfb = 0; sfb < SBPSY_s; ++sfb) { + sf[sfb][i] += 8*sbg[i]; + + if (sf[sfb][i] < 0) { + maxrange = sfb < 6 ? maxrange1 : maxrange2; + + scalefac[sfb][i] + = -sf[sfb][i]/ifqstep + (-sf[sfb][i]%ifqstep != 0); + + if (scalefac[sfb][i] > maxrange) + scalefac[sfb][i] = maxrange; + + if (maxover < -(sf[sfb][i] + scalefac[sfb][i]*ifqstep)) + maxover = -(sf[sfb][i] + scalefac[sfb][i]*ifqstep); + } + } + scalefac[sfb][i] = 0; + } + + return maxover; +} + + + +/* + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + ol_sf = (cod_info->global_gain-210.0); + ol_sf -= ifqstep*scalefac[gr][ch].l[sfb]; + if (cod_info->preflag && sfb>=11) + ol_sf -= ifqstep*pretab[sfb]; +*/ +INLINE int +compute_scalefacs_long_lsf( int *sf, const gr_info * cod_info, int *scalefac ) +{ + const int * max_range = max_range_long; + int ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + int sfb; + int maxover; + + if (cod_info->preflag) { + max_range = max_range_long_lsf_pretab; + for (sfb = 11; sfb < SBPSY_l; ++sfb) + sf[sfb] += pretab[sfb] * ifqstep; + } + + maxover = 0; + for (sfb = 0; sfb < SBPSY_l; ++sfb) { + + if (sf[sfb] < 0) { + /* ifqstep*scalefac >= -sf[sfb], so round UP */ + scalefac[sfb] = -sf[sfb]/ifqstep + (-sf[sfb] % ifqstep != 0); + if (scalefac[sfb] > max_range[sfb]) + scalefac[sfb] = max_range[sfb]; + + /* sf[sfb] should now be positive: */ + if (-(sf[sfb] + scalefac[sfb]*ifqstep) > maxover) { + maxover = -(sf[sfb] + scalefac[sfb]*ifqstep); + } + } + } + scalefac[sfb] = 0; /* sfb21 */ + + return maxover; +} + + + + + +/* + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + ol_sf = (cod_info->global_gain-210.0); + ol_sf -= ifqstep*scalefac[gr][ch].l[sfb]; + if (cod_info->preflag && sfb>=11) + ol_sf -= ifqstep*pretab[sfb]; +*/ +INLINE int +compute_scalefacs_long( int *sf, const gr_info * cod_info, int *scalefac ) +{ + int ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + int sfb; + int maxover; + + if (cod_info->preflag) { + for (sfb = 11; sfb < SBPSY_l; ++sfb) + sf[sfb] += pretab[sfb] * ifqstep; + } + + maxover = 0; + for (sfb = 0; sfb < SBPSY_l; ++sfb) { + + if (sf[sfb] < 0) { + /* ifqstep*scalefac >= -sf[sfb], so round UP */ + scalefac[sfb] = -sf[sfb]/ifqstep + (-sf[sfb] % ifqstep != 0); + if (scalefac[sfb] > max_range_long[sfb]) + scalefac[sfb] = max_range_long[sfb]; + + /* sf[sfb] should now be positive: */ + if (-(sf[sfb] + scalefac[sfb]*ifqstep) > maxover) { + maxover = -(sf[sfb] + scalefac[sfb]*ifqstep); + } + } + } + scalefac[sfb] = 0; /* sfb21 */ + + return maxover; +} + + + + + + + + +/************************************************************************ + * + * quantize and encode with the given scalefacs and global gain + * + * compute scalefactors, l3_enc, and return number of bits needed to encode + * + * + ************************************************************************/ + +static int +VBR_quantize_granule( + lame_internal_flags * gfc, + FLOAT8 * xr34, + int * l3_enc, + III_scalefac_t * scalefac, + int gr, int ch ) +{ + int status; + III_side_info_t * l3_side = & gfc->l3_side; + gr_info * cod_info = & l3_side->gr[gr].ch[ch].tt; + + /* encode scalefacs */ + if ( gfc->is_mpeg1 ) + status = scale_bitcount( scalefac, cod_info ); + else + status = scale_bitcount_lsf( gfc, scalefac, cod_info ); + + if (status != 0) { + return -1; + } + + /* quantize xr34 */ + cod_info->part2_3_length = count_bits(gfc,l3_enc,xr34,cod_info); + if (cod_info->part2_3_length >= LARGE_BITS) return -2; + cod_info->part2_3_length += cod_info->part2_length; + + + if (gfc->use_best_huffman == 1) { + best_huffman_divide(gfc, cod_info, l3_enc); + } + return 0; +} + + + +/*********************************************************************** + * + * calc_short_block_vbr_sf() + * calc_long_block_vbr_sf() + * + * Mark Taylor 2000-??-?? + * Robert Hegemann 2000-10-25 made functions of it + * + ***********************************************************************/ +static const int MAX_SF_DELTA = 4; + +static void +short_block_sf ( + const lame_internal_flags * gfc, + const III_psy_xmin * l3_xmin, + const FLOAT8 * xr34_orig, + const FLOAT8 * xr34, + III_scalefac_t * vbrsf, + int * vbrmin, + int * vbrmax ) +{ + int j, sfb, b; + int vbrmean, vbrmn; + int sf_cache[SBMAX_s]; + int scalefac_criteria; + + if (gfc->presetTune.use) { + /* map experimentalX settings to internal selections */ + static char const map[] = {2,1,0,3,6}; + scalefac_criteria = map[gfc->presetTune.quantcomp_current]; + } + else { + scalefac_criteria = gfc->VBR->quality; + } + + for (j = 0, sfb = 0; sfb < SBMAX_s; ++sfb) { + for (b = 0; b < 3; ++b) { + const int start = gfc->scalefac_band.s[ sfb ]; + const int end = gfc->scalefac_band.s[ sfb+1 ]; + const int width = end - start; + + switch( scalefac_criteria ) { + default: + /* the fastest + */ + vbrsf->s[sfb][b] = calc_scalefac( l3_xmin->s[sfb][b], width, + gfc->presetTune.quantcomp_adjust_mtrh ); + break; + case 5: + case 4: + case 3: + /* the faster and sloppier mode to use at lower quality + */ + vbrsf->s[sfb][b] = find_scalefac (&xr34[j], &xr34_orig[j], + l3_xmin->s[sfb][b], width); + break; + case 2: + /* the slower and better mode to use at higher quality + */ + vbrsf->s[sfb][b] = find_scalefac_ave (&xr34[j], &xr34_orig[j], + l3_xmin->s[sfb][b], width); + break; + case 1: + /* maxnoise mode to use at higher quality + */ + vbrsf->s[sfb][b] = find_scalefac_mq (&xr34[j], &xr34_orig[j], + l3_xmin->s[sfb][b], width, + 1, gfc->VBR->scratch); + break; + case 0: + /* maxnoise mode to use at higher quality + */ + vbrsf->s[sfb][b] = find_scalefac_mq (&xr34[j], &xr34_orig[j], + l3_xmin->s[sfb][b], width, + 0, gfc->VBR->scratch); + break; + } + j += width; + } + } + + *vbrmax = -10000; + *vbrmin = +10000; + + for (b = 0; b < 3; ++b) { + + /* smoothing + */ + switch( gfc->VBR->smooth ) { + default: + case 0: + break; + + case 1: + /* make working copy, get min value, select_kth_int will reorder! + */ + for (vbrmn = +10000, sfb = 0; sfb < SBMAX_s; ++sfb) { + sf_cache[sfb] = vbrsf->s[sfb][b]; + if (vbrmn > vbrsf->s[sfb][b]) + vbrmn = vbrsf->s[sfb][b]; + } + + /* find median value, take it as mean + */ + vbrmean = select_kth_int (sf_cache, SBMAX_s, (SBMAX_s+1)/2); + + /* cut peaks + */ + for (sfb = 0; sfb < SBMAX_s; ++sfb) { + if (vbrsf->s[sfb][b] > vbrmean+(vbrmean-vbrmn)) + vbrsf->s[sfb][b] = vbrmean+(vbrmean-vbrmn); + } + break; + + case 2: + for (sfb = 0; sfb < SBMAX_s; ++sfb) { + if (sfb > 0) + if (vbrsf->s[sfb][b] > vbrsf->s[sfb-1][b]+MAX_SF_DELTA) + vbrsf->s[sfb][b] = vbrsf->s[sfb-1][b]+MAX_SF_DELTA; + if (sfb < SBMAX_s-1) + if (vbrsf->s[sfb][b] > vbrsf->s[sfb+1][b]+MAX_SF_DELTA) + vbrsf->s[sfb][b] = vbrsf->s[sfb+1][b]+MAX_SF_DELTA; + } + break; + } + + /* get max value + */ + for (sfb = 0; sfb < SBMAX_s; ++sfb) { + if (*vbrmax < vbrsf->s[sfb][b]) + *vbrmax = vbrsf->s[sfb][b]; + if (*vbrmin > vbrsf->s[sfb][b]) + *vbrmin = vbrsf->s[sfb][b]; + } + } +} + + + /* a variation for vbr-mtrh */ +static void +long_block_sf ( + const lame_internal_flags * gfc, + const III_psy_xmin * l3_xmin, + const FLOAT8 * xr34_orig, + const FLOAT8 * xr34, + III_scalefac_t * vbrsf, + int * vbrmin, + int * vbrmax ) +{ + int sfb; + int vbrmean, vbrmn; + int sf_cache[SBMAX_l]; + int scalefac_criteria; + + if (gfc->presetTune.use) { + /* map experimentalX settings to internal selections */ + static char const map[] = {2,1,0,3,6}; + scalefac_criteria = map[gfc->presetTune.quantcomp_current]; + } + else { + scalefac_criteria = gfc->VBR->quality; + } + + for (sfb = 0; sfb < SBMAX_l; ++sfb) { + const int start = gfc->scalefac_band.l[ sfb ]; + const int end = gfc->scalefac_band.l[ sfb+1 ]; + const int width = end - start; + + switch( scalefac_criteria ) { + default: + /* the fastest + */ + vbrsf->l[sfb] = calc_scalefac( l3_xmin->l[sfb], width, + gfc->presetTune.quantcomp_adjust_mtrh ); + break; + case 5: + case 4: + case 3: + /* the faster and sloppier mode to use at lower quality + */ + vbrsf->l[sfb] = find_scalefac (&xr34[start], &xr34_orig[start], + l3_xmin->l[sfb], width); + break; + case 2: + /* the slower and better mode to use at higher quality + */ + vbrsf->l[sfb] = find_scalefac_ave (&xr34[start], &xr34_orig[start], + l3_xmin->l[sfb], width); + break; + case 1: + /* maxnoise mode to use at higher quality + */ + vbrsf->l[sfb] = find_scalefac_mq (&xr34[start], &xr34_orig[start], + l3_xmin->l[sfb], width, + 1, gfc->VBR->scratch); + break; + case 0: + /* maxnoise mode to use at higher quality + */ + vbrsf->l[sfb] = find_scalefac_mq (&xr34[start], &xr34_orig[start], + l3_xmin->l[sfb], width, + 0, gfc->VBR->scratch); + break; + } + } + + switch( gfc->VBR->smooth ) { + default: + case 0: + break; + + case 1: + /* make working copy, get min value, select_kth_int will reorder! + */ + for (vbrmn = +10000, sfb = 0; sfb < SBMAX_l; ++sfb) { + sf_cache[sfb] = vbrsf->l[sfb]; + if (vbrmn > vbrsf->l[sfb]) + vbrmn = vbrsf->l[sfb]; + } + /* find median value, take it as mean + */ + vbrmean = select_kth_int (sf_cache, SBMAX_l, (SBMAX_l+1)/2); + + /* cut peaks + */ + for (sfb = 0; sfb < SBMAX_l; ++sfb) { + if (vbrsf->l[sfb] > vbrmean+(vbrmean-vbrmn)) + vbrsf->l[sfb] = vbrmean+(vbrmean-vbrmn); + } + break; + + case 2: + for (sfb = 0; sfb < SBMAX_l; ++sfb) { + if (sfb > 0) + if (vbrsf->l[sfb] > vbrsf->l[sfb-1]+MAX_SF_DELTA) + vbrsf->l[sfb] = vbrsf->l[sfb-1]+MAX_SF_DELTA; + if (sfb < SBMAX_l-1) + if (vbrsf->l[sfb] > vbrsf->l[sfb+1]+MAX_SF_DELTA) + vbrsf->l[sfb] = vbrsf->l[sfb+1]+MAX_SF_DELTA; + } + break; + } + + /* get max value + */ + for (*vbrmin = +10000, *vbrmax = -10000, sfb = 0; sfb < SBMAX_l; ++sfb) { + if (*vbrmax < vbrsf->l[sfb]) + *vbrmax = vbrsf->l[sfb]; + if (*vbrmin > vbrsf->l[sfb]) + *vbrmin = vbrsf->l[sfb]; + } +} + + + +/****************************************************************** + * + * short block scalefacs + * + ******************************************************************/ + +static void +short_block_scalefacs ( + const lame_internal_flags * gfc, + gr_info * cod_info, + III_scalefac_t * scalefac, + III_scalefac_t * vbrsf, + int * VBRmax ) +{ + int sfb, maxsfb, b; + int maxover, maxover0, maxover1, mover; + int v0, v1; + int minsfb; + int vbrmax = *VBRmax; + + maxover0 = 0; + maxover1 = 0; + maxsfb = gfc->sfb21_extra ? SBMAX_s : SBPSY_s; + for (sfb = 0; sfb < maxsfb; ++sfb) { + for (b = 0; b < 3; ++b) { + v0 = (vbrmax - vbrsf->s[sfb][b]) - (4*14 + 2*max_range_short[sfb]); + v1 = (vbrmax - vbrsf->s[sfb][b]) - (4*14 + 4*max_range_short[sfb]); + if (maxover0 < v0) + maxover0 = v0; + if (maxover1 < v1) + maxover1 = v1; + } + } + + if ((gfc->noise_shaping == 2) && (gfc->presetTune.use && !(gfc->presetTune.athadjust_safe_noiseshaping || gfc->ATH->adjust < 1.0))) + /* allow scalefac_scale=1 */ + mover = Min (maxover0, maxover1); + else + mover = maxover0; + + vbrmax -= mover; + maxover0 -= mover; + maxover1 -= mover; + + if (maxover0 == 0) + cod_info->scalefac_scale = 0; + else if (maxover1 == 0) + cod_info->scalefac_scale = 1; + + /* sf = (cod_info->global_gain-210.0) */ + cod_info->global_gain = vbrmax + 210; + assert(cod_info->global_gain < 256); + + if (cod_info->global_gain < 0) { + cod_info->global_gain = 0; + } + else + if (cod_info->global_gain > 255) { + cod_info->global_gain = 255; + } + for (sfb = 0; sfb < SBMAX_s; ++sfb) { + for (b = 0; b < 3; ++b) { + vbrsf->s[sfb][b] -= vbrmax; + } + } + maxover = compute_scalefacs_short (vbrsf->s, cod_info, scalefac->s, + cod_info->subblock_gain); + + assert (maxover <= 0); + + /* adjust global_gain so at least 1 subblock gain = 0 */ + minsfb = 999; /* prepare for minimum search */ + for (b = 0; b < 3; ++b) + if (minsfb > cod_info->subblock_gain[b]) + minsfb = cod_info->subblock_gain[b]; + + if (minsfb > cod_info->global_gain/8) + minsfb = cod_info->global_gain/8; + + vbrmax -= 8*minsfb; + cod_info->global_gain -= 8*minsfb; + + for (b = 0; b < 3; ++b) + cod_info->subblock_gain[b] -= minsfb; + + *VBRmax = vbrmax; +} + + + +/****************************************************************** + * + * long block scalefacs + * + ******************************************************************/ + +static void +long_block_scalefacs ( + const lame_internal_flags * gfc, + gr_info * cod_info, + III_scalefac_t * scalefac, + III_scalefac_t * vbrsf, + int * VBRmax ) +{ + const int * max_rangep; + int sfb, maxsfb; + int maxover, maxover0, maxover1, maxover0p, maxover1p, mover; + int v0, v1, v0p, v1p; + int vbrmax = *VBRmax; + + max_rangep = gfc->is_mpeg1 ? max_range_long : max_range_long_lsf_pretab; + + maxover0 = 0; + maxover1 = 0; + maxover0p = 0; /* pretab */ + maxover1p = 0; /* pretab */ + + maxsfb = gfc->sfb21_extra ? SBMAX_l : SBPSY_l; + for ( sfb = 0; sfb < maxsfb; ++sfb ) { + v0 = (vbrmax - vbrsf->l[sfb]) - 2*max_range_long[sfb]; + v1 = (vbrmax - vbrsf->l[sfb]) - 4*max_range_long[sfb]; + v0p = (vbrmax - vbrsf->l[sfb]) - 2*(max_rangep[sfb]+pretab[sfb]); + v1p = (vbrmax - vbrsf->l[sfb]) - 4*(max_rangep[sfb]+pretab[sfb]); + if (maxover0 < v0) + maxover0 = v0; + if (maxover1 < v1) + maxover1 = v1; + if (maxover0p < v0p) + maxover0p = v0p; + if (maxover1p < v1p) + maxover1p = v1p; + } + + mover = Min (maxover0, maxover0p); + if ((gfc->noise_shaping == 2) && (gfc->presetTune.use && !(gfc->presetTune.athadjust_safe_noiseshaping || gfc->ATH->adjust < 1.0))) { + /* allow scalefac_scale=1 */ + mover = Min (mover, maxover1); + mover = Min (mover, maxover1p); + } + + vbrmax -= mover; + maxover0 -= mover; + maxover0p -= mover; + maxover1 -= mover; + maxover1p -= mover; + + if (maxover0 <= 0) { + cod_info->scalefac_scale = 0; + cod_info->preflag = 0; + vbrmax -= maxover0; + } else if (maxover0p <= 0) { + cod_info->scalefac_scale = 0; + cod_info->preflag = 1; + vbrmax -= maxover0p; + } else if (maxover1 == 0) { + cod_info->scalefac_scale = 1; + cod_info->preflag = 0; + } else if (maxover1p == 0) { + cod_info->scalefac_scale = 1; + cod_info->preflag = 1; + } else { + assert(0); /* this should not happen */ + } + + /* sf = (cod_info->global_gain-210.0) */ + cod_info->global_gain = vbrmax + 210; + assert (cod_info->global_gain < 256); + + if (cod_info->global_gain < 0) { + cod_info->global_gain = 0; + } + else + if (cod_info->global_gain > 255) + cod_info->global_gain = 255; + + for (sfb = 0; sfb < SBMAX_l; ++sfb) + vbrsf->l[sfb] -= vbrmax; + + if ( gfc->is_mpeg1 == 1 ) + maxover = compute_scalefacs_long (vbrsf->l, cod_info, scalefac->l); + else + maxover = compute_scalefacs_long_lsf (vbrsf->l, cod_info, scalefac->l); + + assert (maxover <= 0); + + *VBRmax = vbrmax; +} + + + +/*********************************************************************** + * + * quantize xr34 based on scalefactors + * + * calc_short_block_xr34 + * calc_long_block_xr34 + * + * Mark Taylor 2000-??-?? + * Robert Hegemann 2000-10-20 made functions of them + * + ***********************************************************************/ + +static void +short_block_xr34 ( + const lame_internal_flags * gfc, + const gr_info * cod_info, + const III_scalefac_t * scalefac, + const FLOAT8 * xr34_orig, + FLOAT8 * xr34 ) +{ + int sfb, l, j, b; + int ifac, ifqstep, start, end; + FLOAT8 fac; + + /* even though there is no scalefactor for sfb12 + * subblock gain affects upper frequencies too, that's why + * we have to go up to SBMAX_s + */ + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + for ( j = 0, sfb = 0; sfb < SBMAX_s; ++sfb ) { + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb+1 ]; + for (b = 0; b < 3; ++b) { + ifac = 8*cod_info->subblock_gain[b]+ifqstep*scalefac->s[sfb][b]; + + if ( ifac == 0 ) { /* just copy */ + l = (end-start+7) / 8; + switch ((end-start) % 8) { + default: + case 0: do{ xr34[j] = xr34_orig[j]; ++j; + case 7: xr34[j] = xr34_orig[j]; ++j; + case 6: xr34[j] = xr34_orig[j]; ++j; + case 5: xr34[j] = xr34_orig[j]; ++j; + case 4: xr34[j] = xr34_orig[j]; ++j; + case 3: xr34[j] = xr34_orig[j]; ++j; + case 2: xr34[j] = xr34_orig[j]; ++j; + case 1: xr34[j] = xr34_orig[j]; ++j; } while (--l); + } + continue; + } + if (ifac < Q_MAX-210) + fac = IIPOW20_(ifac); + else + fac = pow (2.0, 0.1875*ifac); + + /* + * loop unrolled into "Duff's Device". Robert Hegemann + */ + l = (end-start+7) / 8; + switch ((end-start) % 8) { + default: + case 0: do{ xr34[j] = xr34_orig[j]*fac; ++j; + case 7: xr34[j] = xr34_orig[j]*fac; ++j; + case 6: xr34[j] = xr34_orig[j]*fac; ++j; + case 5: xr34[j] = xr34_orig[j]*fac; ++j; + case 4: xr34[j] = xr34_orig[j]*fac; ++j; + case 3: xr34[j] = xr34_orig[j]*fac; ++j; + case 2: xr34[j] = xr34_orig[j]*fac; ++j; + case 1: xr34[j] = xr34_orig[j]*fac; ++j; } while (--l); + } + } + } +} + + + +static void +long_block_xr34 ( + const lame_internal_flags * gfc, + const gr_info * cod_info, + const III_scalefac_t * scalefac, + const FLOAT8 * xr34_orig, + FLOAT8 * xr34 ) +{ + int sfb, l, j; + int ifac, ifqstep, start, end; + FLOAT8 fac; + + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + for ( sfb = 0; sfb < SBMAX_l; ++sfb ) { + + ifac = ifqstep*scalefac->l[sfb]; + if (cod_info->preflag) + ifac += ifqstep*pretab[sfb]; + + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + + if ( ifac == 0 ) { /* just copy */ + j = start; + l = (end-start+7) / 8; + switch ((end-start) % 8) { + default: + case 0: do{ xr34[j] = xr34_orig[j]; ++j; + case 7: xr34[j] = xr34_orig[j]; ++j; + case 6: xr34[j] = xr34_orig[j]; ++j; + case 5: xr34[j] = xr34_orig[j]; ++j; + case 4: xr34[j] = xr34_orig[j]; ++j; + case 3: xr34[j] = xr34_orig[j]; ++j; + case 2: xr34[j] = xr34_orig[j]; ++j; + case 1: xr34[j] = xr34_orig[j]; ++j; } while (--l); + } + continue; + } + if (ifac < Q_MAX-210) + fac = IIPOW20_(ifac); + else + fac = pow (2.0, 0.1875*ifac); + + /* + * loop unrolled into "Duff's Device". Robert Hegemann + */ + j = start; + l = (end-start+7) / 8; + switch ((end-start) % 8) { + default: + case 0: do{ xr34[j] = xr34_orig[j]*fac; ++j; + case 7: xr34[j] = xr34_orig[j]*fac; ++j; + case 6: xr34[j] = xr34_orig[j]*fac; ++j; + case 5: xr34[j] = xr34_orig[j]*fac; ++j; + case 4: xr34[j] = xr34_orig[j]*fac; ++j; + case 3: xr34[j] = xr34_orig[j]*fac; ++j; + case 2: xr34[j] = xr34_orig[j]*fac; ++j; + case 1: xr34[j] = xr34_orig[j]*fac; ++j; } while (--l); + } + } +} + + + + + + + +/************************************************************************ + * + * VBR_noise_shaping2() + * + * may result in a need of too many bits, then do it CBR like + * + * Robert Hegemann 2000-10-25 + * + ***********************************************************************/ + +int +VBR_noise_shaping2 ( + lame_global_flags * gfp, + FLOAT8 * xr, + FLOAT8 * xr34orig, + int * l3_enc, + int minbits, + int maxbits, + III_scalefac_t * scalefac, + III_psy_xmin * l3_xmin, + int gr, + int ch ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + III_scalefac_t vbrsf; + III_scalefac_t vbrsf2; + gr_info *cod_info; + FLOAT8 xr34[576]; + int shortblock, ret, bits, huffbits; + int vbrmin, vbrmax, vbrmin2, vbrmax2; + int best_huffman = gfc->use_best_huffman; + int count=6; + + gfc->use_best_huffman = 0; /* we will do it later */ + + cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + shortblock = (cod_info->block_type == SHORT_TYPE); + + if (shortblock) { + short_block_sf (gfc, l3_xmin, xr34orig, xr, &vbrsf2, &vbrmin2, &vbrmax2); + } else { + long_block_sf (gfc, l3_xmin, xr34orig, xr, &vbrsf2, &vbrmin2, &vbrmax2); + } + vbrsf = vbrsf2; + vbrmin = vbrmin2; + vbrmax = vbrmax2; + +do { +--count; + + if (shortblock) { + short_block_scalefacs (gfc, cod_info, scalefac, &vbrsf, &vbrmax); + short_block_xr34 (gfc, cod_info, scalefac, xr34orig, xr34); + } else { + long_block_scalefacs (gfc, cod_info, scalefac, &vbrsf, &vbrmax); + long_block_xr34 (gfc, cod_info, scalefac, xr34orig, xr34); + } + + ret = VBR_quantize_granule (gfc, xr34, l3_enc, scalefac, gr, ch); + + if (vbrmin == vbrmax) break; + else if (cod_info->part2_3_length < minbits) { + int i; + vbrmax = vbrmin2 + (vbrmax2-vbrmin2) * count/6; + vbrmin = vbrmin2; + if (shortblock) { + for (i = 0; i < SBMAX_s; ++i) { + //vbrsf.s[i][0] = vbrmin2 + (vbrsf2.s[i][0]-vbrmin2) * count/6; + //vbrsf.s[i][1] = vbrmin2 + (vbrsf2.s[i][1]-vbrmin2) * count/6; + //vbrsf.s[i][2] = vbrmin2 + (vbrsf2.s[i][2]-vbrmin2) * count/6; + vbrsf.s[i][0] = Min(vbrsf2.s[i][0], vbrmax); + vbrsf.s[i][1] = Min(vbrsf2.s[i][1], vbrmax); + vbrsf.s[i][2] = Min(vbrsf2.s[i][2], vbrmax); + } + } + else { + for (i = 0; i < SBMAX_l; ++i) { + //vbrsf.l[i] = vbrmin2 + (vbrsf2.l[i]-vbrmin2) * count/6; + vbrsf.l[i] = Min(vbrsf2.l[i], vbrmax); + } + } + } + else if (cod_info->part2_3_length > maxbits) { + int i; + vbrmax = vbrmax2; + vbrmin = vbrmax2 + (vbrmin2-vbrmax2) * count/6; + if (shortblock) { + for (i = 0; i < SBMAX_s; ++i) { + //vbrsf.s[i][0] = vbrmax2 + (vbrsf2.s[i][0]-vbrmax2) * count/6; + //vbrsf.s[i][1] = vbrmax2 + (vbrsf2.s[i][1]-vbrmax2) * count/6; + //vbrsf.s[i][2] = vbrmax2 + (vbrsf2.s[i][2]-vbrmax2) * count/6; + vbrsf.s[i][0] = Max(vbrsf2.s[i][0], vbrmin); + vbrsf.s[i][1] = Max(vbrsf2.s[i][1], vbrmin); + vbrsf.s[i][2] = Max(vbrsf2.s[i][2], vbrmin); + } + } + else { + for (i = 0; i < SBMAX_l; ++i) { + //vbrsf.l[i] = vbrmax2 + (vbrsf2.l[i]-vbrmax2) * count/6; + vbrsf.l[i] = Max(vbrsf2.l[i], vbrmin); + } + } + } + else break; +} while(1 && ret != -1); + + + gfc->use_best_huffman = best_huffman; + + if (ret == -1) /* Houston, we have a problem */ + return -1; + + if (cod_info->part2_3_length < minbits) { + huffbits = minbits - cod_info->part2_length; + bits = bin_search_StepSize (gfc, cod_info, huffbits, + gfc->OldValue[ch], xr34, l3_enc); + gfc->OldValue[ch] = cod_info->global_gain; + cod_info->part2_3_length = bits + cod_info->part2_length; + } + if (cod_info->part2_3_length > maxbits) { + huffbits = maxbits - cod_info->part2_length; + if (huffbits < 0) huffbits = 0; + bits = bin_search_StepSize (gfc, cod_info, huffbits, + gfc->OldValue[ch], xr34, l3_enc); + gfc->OldValue[ch] = cod_info->global_gain; + cod_info->part2_3_length = bits; + if (bits > huffbits) { + bits = inner_loop (gfc, cod_info, huffbits, xr34, l3_enc); + cod_info->part2_3_length = bits; + } + if (bits >= LARGE_BITS) /* Houston, we have a problem */ + return -2; + cod_info->part2_3_length += cod_info->part2_length; + } + + if (cod_info->part2_length >= LARGE_BITS) /* Houston, we have a problem */ + return -2; + + assert (cod_info->global_gain < 256); + + return 0; +} + + + + + + +/************************************************************************ + * + * VBR_noise_shaping() + * + * compute scalefactors, l3_enc, and return number of bits needed to encode + * + * return code: 0 scalefactors were found with all noise < masking + * + * n>0 scalefactors required too many bits. global gain + * was decreased by n + * If n is large, we should probably recompute scalefacs + * with a lower quality. + * + * n<0 scalefactors used less than minbits. + * global gain was increased by n. + * If n is large, might want to recompute scalefacs + * with a higher quality setting? + * + ************************************************************************/ +static int +VBR_noise_shaping ( + lame_global_flags *gfp, + FLOAT8 xr [576], + FLOAT8 xr34orig [576], + int l3_enc [576], + int digital_silence, + int minbits, + int maxbits, + III_scalefac_t *scalefac, + III_psy_xmin *l3_xmin, + int gr, + int ch ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_scalefac_t save_sf; + III_scalefac_t vbrsf; + gr_info *cod_info; + FLOAT8 xr34[576]; + int shortblock; + int vbrmax, vbrmin; + int global_gain_adjust = 0; + + cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + shortblock = (cod_info->block_type == SHORT_TYPE); + + if (shortblock) + short_block_sf (gfc, l3_xmin, xr34orig, xr, &vbrsf, &vbrmin, &vbrmax); + else + long_block_sf (gfc, l3_xmin, xr34orig, xr, &vbrsf, &vbrmin, &vbrmax); + + /* save a copy of vbrsf, incase we have to recomptue scalefacs */ + memcpy (&save_sf, &vbrsf, sizeof(III_scalefac_t)); + + do { + memset (scalefac, 0, sizeof(III_scalefac_t)); + + if (shortblock) { + short_block_scalefacs (gfc, cod_info, scalefac, &vbrsf, &vbrmax); + short_block_xr34 (gfc, cod_info, scalefac, xr34orig, xr34); + } else { + long_block_scalefacs (gfc, cod_info, scalefac, &vbrsf, &vbrmax); + long_block_xr34 (gfc, cod_info, scalefac, xr34orig, xr34); + } + VBR_quantize_granule (gfc, xr34, l3_enc, scalefac, gr, ch); + + + /* decrease noise until we use at least minbits + */ + if (cod_info->part2_3_length < minbits) { + if (digital_silence) break; + //if (cod_info->part2_3_length == cod_info->part2_length) break; + if (vbrmax+210 == 0) break; + + /* decrease global gain, recompute scale factors */ + --vbrmax; + --global_gain_adjust; + memcpy (&vbrsf, &save_sf, sizeof(III_scalefac_t)); + } + + } while (cod_info->part2_3_length < minbits); + + /* inject noise until we meet our bit limit + */ + while (cod_info->part2_3_length > Min (maxbits, MAX_BITS)) { + /* increase global gain, keep existing scale factors */ + ++cod_info->global_gain; + if (cod_info->global_gain > 255) + ERRORF (gfc,"%ld impossible to encode ??? frame! bits=%d\n", + // gfp->frameNum, cod_info->part2_3_length); + -1, cod_info->part2_3_length); + VBR_quantize_granule (gfc, xr34, l3_enc, scalefac, gr, ch); + + ++global_gain_adjust; + } + + return global_gain_adjust; +} + + + +void +VBR_quantize(lame_global_flags *gfp, + FLOAT8 pe[2][2], FLOAT8 ms_ener_ratio[2], + FLOAT8 xr[2][2][576], III_psy_ratio ratio[2][2], + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_psy_xmin l3_xmin[2][2]; + int minbits,maxbits,max_frame_bits,totbits,gr,ch,i,bits_ok; + int bitsPerFrame,mean_bits; + int analog_silence; + FLOAT8 qadjust; + III_side_info_t * l3_side; + gr_info *cod_info; + int digital_silence[2][2]; + FLOAT8 masking_lower_db=0; + FLOAT8 xr34[2][2][576]; + + qadjust=0; /* start with -1 db quality improvement over quantize.c VBR */ + + l3_side = &gfc->l3_side; + + /* now find out: if the frame can be considered analog silent + * if each granule can be considered digital silent + * and calculate l3_xmin and the fresh xr34 array + */ + + assert( gfp->VBR_q <= 9 ); + assert( gfp->VBR_q >= 0 ); + analog_silence=1; + for (gr = 0; gr < gfc->mode_gr; ++gr) { + /* copy data to be quantized into xr */ + if (gfc->mode_ext==MPG_MD_MS_LR) { + ms_convert(xr[gr],xr[gr]); + } + for (ch = 0; ch < gfc->channels_out; ++ch) { + /* if in the following sections the quality would not be adjusted + * then we would only have to call calc_xmin once here and + * could drop subsequently calls (rh 2000/07/17) + */ + int over_ath; + cod_info = &l3_side->gr[gr].ch[ch].tt; + cod_info->part2_3_length=LARGE_BITS; + + if (cod_info->block_type == SHORT_TYPE) { + cod_info->sfb_lmax = 0; /* No sb*/ + cod_info->sfb_smin = 0; + } else { + /* MPEG 1 doesnt use last scalefactor band */ + cod_info->sfb_lmax = SBPSY_l; + cod_info->sfb_smin = SBPSY_s; /* No sb */ + if (cod_info->mixed_block_flag) { + cod_info->sfb_lmax = gfc->is_mpeg1 ? 8 : 6; + cod_info->sfb_smin = 3; + } + } + + /* quality setting */ + masking_lower_db = gfc->VBR->mask_adjust; + if (pe[gr][ch]>750) { + masking_lower_db -= Min(10,4*(pe[gr][ch]-750.)/750.); + } + gfc->masking_lower = pow(10.0,masking_lower_db/10); + + /* masking thresholds */ + over_ath = calc_xmin(gfp,xr[gr][ch],&ratio[gr][ch],cod_info,&l3_xmin[gr][ch]); + + /* if there are bands with more energy than the ATH + * then we say the frame is not analog silent */ + if (over_ath) { + analog_silence = 0; + } + + /* if there is no line with more energy than 1e-20 + * then this granule is considered to be digital silent + * plus calculation of xr34 */ + digital_silence[gr][ch] = 1; + for(i=0;i<576;++i) { + FLOAT8 temp=fabs(xr[gr][ch][i]); + xr34[gr][ch][i]=sqrt(sqrt(temp)*temp); + digital_silence[gr][ch] &= temp < 1E-20; + } + } /* ch */ + } /* gr */ + + + /* compute minimum allowed bits from minimum allowed bitrate */ + if (analog_silence) { + gfc->bitrate_index=1; + } else { + gfc->bitrate_index=gfc->VBR_min_bitrate; + } + getframebits(gfp, &bitsPerFrame, &mean_bits); + minbits = (mean_bits/gfc->channels_out); + + /* compute maximum allowed bits from max allowed bitrate */ + gfc->bitrate_index=gfc->VBR_max_bitrate; + getframebits(gfp, &bitsPerFrame, &mean_bits); + max_frame_bits = ResvFrameBegin(gfp, l3_side, mean_bits, bitsPerFrame); + maxbits=2.5*(mean_bits/gfc->channels_out); + + { + /* compute a target mean_bits based on compression ratio + * which was set based on VBR_q + */ + int bit_rate = gfp->out_samplerate*16*gfc->channels_out/(1000.0*gfp->compression_ratio); + bitsPerFrame = (bit_rate*gfp->framesize*1000)/gfp->out_samplerate; + mean_bits = (bitsPerFrame - 8*gfc->sideinfo_len) / gfc->mode_gr; + } + + + minbits = Max(minbits,125); + minbits=Max(minbits,.40*(mean_bits/gfc->channels_out)); + maxbits=Min(maxbits,2.5*(mean_bits/gfc->channels_out)); + + + + + + + + /* + * loop over all ch,gr, encoding anything with bits > .5*(max_frame_bits/4) + * + * If a particular granule uses way too many bits, it will be re-encoded + * on the next iteration of the loop (with a lower quality setting). + * But granules which dont use + * use too many bits will not be re-encoded. + * + * minbits: minimum allowed bits for 1 granule 1 channel + * maxbits: maximum allowwed bits for 1 granule 1 channel + * max_frame_bits: maximum allowed bits for entire frame + * (max_frame_bits/4) estimate of average bits per granule per channel + * + */ + + do { + + totbits=0; + for (gr = 0; gr < gfc->mode_gr; ++gr) { + int minbits_lr[2]; + minbits_lr[0]=minbits; + minbits_lr[1]=minbits; + +#if 0 + if (gfc->mode_ext==MPG_MD_MS_LR) { + FLOAT8 fac; + fac = .33*(.5-ms_ener_ratio[gr])/.5; + if (fac<0) fac=0; + if (fac>.5) fac=.5; + minbits_lr[0] = (1+fac)*minbits; + minbits_lr[1] = Max(125,(1-fac)*minbits); + } +#endif + + + for (ch = 0; ch < gfc->channels_out; ++ch) { + int adjusted,shortblock; + cod_info = &l3_side->gr[gr].ch[ch].tt; + + /* ENCODE this data first pass, and on future passes unless it uses + * a very small percentage of the max_frame_bits */ + if (cod_info->part2_3_length > (max_frame_bits/(2*gfc->channels_out*gfc->mode_gr))) { + + shortblock = (cod_info->block_type == SHORT_TYPE); + + /* Adjust allowed masking based on quality setting */ + if (qadjust!=0 /*|| shortblock*/) { + masking_lower_db = gfc->VBR->mask_adjust + qadjust; + + /* + if (shortblock) masking_lower_db -= 4; + */ + + if (pe[gr][ch]>750) + masking_lower_db -= Min(10,4*(pe[gr][ch]-750.)/750.); + gfc->masking_lower = pow(10.0,masking_lower_db/10); + calc_xmin( gfp, xr[gr][ch], ratio[gr]+ch, cod_info, l3_xmin[gr]+ch); + } + + /* digital silent granules do not need the full round trip, + * but this can be optimized later on + */ + adjusted = VBR_noise_shaping (gfp,xr[gr][ch],xr34[gr][ch], + l3_enc[gr][ch], + digital_silence[gr][ch], + minbits_lr[ch], + maxbits,scalefac[gr]+ch, + l3_xmin[gr]+ch,gr,ch); + if (adjusted>10) { + /* global_gain was changed by a large amount to get bits < maxbits */ + /* quality is set to high. we could set bits = LARGE_BITS + * to force re-encoding. But most likely the other channels/granules + * will also use too many bits, and the entire frame will + * be > max_frame_bits, forcing re-encoding below. + */ + // cod_info->part2_3_bits = LARGE_BITS; + } + } + totbits += cod_info->part2_3_length; + } + } + bits_ok=1; + if (totbits>max_frame_bits) { + /* lower quality */ + qadjust += Max(.125,Min(1,(totbits-max_frame_bits)/300.0)); + /* adjusting minbits and maxbits is necessary too + * cos lowering quality is not enough in rare cases + * when each granule still needs almost maxbits, it wont fit */ + minbits = Max(125,minbits*0.975); + maxbits = Max(minbits,maxbits*0.975); + // DEBUGF("%i totbits>max_frame_bits totbits=%i maxbits=%i \n",gfp->frameNum,totbits,max_frame_bits); + // DEBUGF("next masking_lower_db = %f \n",masking_lower_db + qadjust); + bits_ok=0; + } + + } while (!bits_ok); + + + + /* find optimal scalefac storage. Cant be done above because + * might enable scfsi which breaks the interation loops */ + totbits=0; + for (gr = 0; gr < gfc->mode_gr; ++gr) { + for (ch = 0; ch < gfc->channels_out; ++ch) { + best_scalefac_store(gfc, gr, ch, l3_enc, l3_side, scalefac); + totbits += l3_side->gr[gr].ch[ch].tt.part2_3_length; + } + } + + + + + if (analog_silence && !gfp->VBR_hard_min) { + gfc->bitrate_index = 1; + } else { + gfc->bitrate_index = gfc->VBR_min_bitrate; + } + for( ; gfc->bitrate_index < gfc->VBR_max_bitrate; ++gfc->bitrate_index ) { + + getframebits (gfp, &bitsPerFrame, &mean_bits); + maxbits = ResvFrameBegin(gfp, l3_side, mean_bits, bitsPerFrame); + if (totbits <= maxbits) break; + } + if (gfc->bitrate_index == gfc->VBR_max_bitrate) { + getframebits (gfp, &bitsPerFrame, &mean_bits); + maxbits = ResvFrameBegin(gfp, l3_side, mean_bits, bitsPerFrame); + } + + // DEBUGF("%i total_bits=%i max_frame_bits=%i index=%i \n",gfp->frameNum,totbits,max_frame_bits,gfc->bitrate_index); + + for (gr = 0; gr < gfc->mode_gr; ++gr) { + for (ch = 0; ch < gfc->channels_out; ++ch) { + cod_info = &l3_side->gr[gr].ch[ch].tt; + + + ResvAdjust (gfc, cod_info, l3_side, mean_bits); + + /******************************************************************* + * set the sign of l3_enc from the sign of xr + *******************************************************************/ + for ( i = 0; i < 576; ++i) { + if (xr[gr][ch][i] < 0) l3_enc[gr][ch][i] *= -1; + } + } + } + ResvFrameEnd (gfc, l3_side, mean_bits); + + + +} + + + + diff -Nru swftools-0.9.2+ds1/lib/lame/vbrquantize.h swftools-0.9.1/lib/lame/vbrquantize.h --- swftools-0.9.2+ds1/lib/lame/vbrquantize.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/vbrquantize.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * MP3 VBR quantization + * + * Copyright (c) 1999 Mark Taylor + * + * 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 LAME_VBRQUANTIZE_H +#define LAME_VBRQUANTIZE_H + +void VBR_quantize( + lame_global_flags *gfp, + FLOAT8 pe[2][2], + FLOAT8 ms_ener_ratio[2], + FLOAT8 xr[2][2][576], + III_psy_ratio ratio[2][2], + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]); + + +int VBR_noise_shaping2( + lame_global_flags * gfp, + FLOAT8 * xr, + FLOAT8 * xr34orig, + int * l3_enc, + int minbits, + int maxbits, + III_scalefac_t * scalefac, + III_psy_xmin * l3_xmin, + int gr, + int ch ); + +#endif /* LAME_VBRQUANTIZE_H */ diff -Nru swftools-0.9.2+ds1/lib/lame/VbrTag.c swftools-0.9.1/lib/lame/VbrTag.c --- swftools-0.9.2+ds1/lib/lame/VbrTag.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/VbrTag.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,945 @@ +/* + * Xing VBR tagging for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * 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. + */ + +/* $Id: VbrTag.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */ + +#include +#include "config_static.h" + +#include "machine.h" +#if defined(__riscos__) && defined(FPA10) +#include "ymath.h" +#else +#include +#endif + + +#include "bitstream.h" +#include "lame.h" +#include "VbrTag.h" +#include "version.h" + +#include +#include +#include + +#ifdef WITH_DMALLOC +#include +#endif + +#ifdef _DEBUG +/* #define DEBUG_VBRTAG */ +#endif + +/* +// 4 bytes for Header Tag +// 4 bytes for Header Flags +// 100 bytes for entry (NUMTOCENTRIES) +// 4 bytes for FRAME SIZE +// 4 bytes for STREAM_SIZE +// 4 bytes for VBR SCALE. a VBR quality indicator: 0=best 100=worst +// 20 bytes for LAME tag. for example, "LAME3.12 (beta 6)" +// ___________ +// 140 bytes +*/ +#define VBRHEADERSIZE (NUMTOCENTRIES+4+4+4+4+4) + +#define LAMEHEADERSIZE (VBRHEADERSIZE + 9 + 1 + 1 + 8 + 1 + 1 + 3 + 1 + 1 + 2 + 4 + 2 + 2) + +/* the size of the Xing header (MPEG1 and MPEG2) in kbps */ +#define XING_BITRATE1 128 +#define XING_BITRATE2 64 +#define XING_BITRATE25 32 + + + +const static char VBRTag[]={"Xing"}; +const static char VBRTag2[]={"Info"}; + + + + +/* Lookup table for fast CRC computation + * See 'CRC_update_lookup' + * Uses the polynomial x^16+x^15+x^2+1 */ + +unsigned int crc16_lookup[256] = +{ + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + + + + + +/*********************************************************************** + * Robert Hegemann 2001-01-17 + ***********************************************************************/ + +static void addVbr(VBR_seek_info_t * v, int bitrate) +{ + int i; + + v->sum += bitrate; + v->seen ++; + + if (v->seen < v->want) { + return; + } + + if (v->pos < v->size) { + v->bag[v->pos] = v->sum; + v->pos ++; + v->seen = 0; + } + if (v->pos == v->size) { + for (i = 1; i < v->size; i += 2) { + v->bag[i/2] = v->bag[i]; + } + v->want *= 2; + v->pos /= 2; + } +} + +static void Xing_seek_table(VBR_seek_info_t * v, unsigned char *t) +{ + int i, index; + int seek_point; + + if (v->pos <= 0) + return; + + for (i = 1; i < NUMTOCENTRIES; ++i) { + float j = i/(float)NUMTOCENTRIES, act, sum; + index = (int)(floor(j * v->pos)); + if (index > v->pos-1) + index = v->pos-1; + act = v->bag[index]; + sum = v->sum; + seek_point = (int)(256. * act / sum); + if (seek_point > 255) + seek_point = 255; + t[i] = seek_point; + } +} + +#if 0 +void print_seeking(unsigned char *t) +{ + int i; + + printf("seeking table "); + for (i = 0; i < NUMTOCENTRIES; ++i) { + printf(" %d ", t[i]); + } + printf("\n"); +} +#endif + + + +/**************************************************************************** + * AddVbrFrame: Add VBR entry, used to fill the VBR the TOC entries + * Paramters: + * nStreamPos: how many bytes did we write to the bitstream so far + * (in Bytes NOT Bits) + **************************************************************************** +*/ +void AddVbrFrame(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + int kbps = bitrate_table[gfp->version][gfc->bitrate_index]; + + if (gfc->VBR_seek_table.bag == NULL) { + gfc->VBR_seek_table.sum = 0; + gfc->VBR_seek_table.seen = 0; + gfc->VBR_seek_table.want = 1; + gfc->VBR_seek_table.pos = 0; + gfc->VBR_seek_table.bag = malloc (400*sizeof(int)); + if (gfc->VBR_seek_table.bag != NULL) { + gfc->VBR_seek_table.size = 400; + } + else { + gfc->VBR_seek_table.size = 0; + ERRORF (gfc,"Error: can't allocate VbrFrames buffer\n"); + return; + } + } + addVbr(&gfc->VBR_seek_table, kbps); + gfp->nVbrNumFrames++; +} + + +/*-------------------------------------------------------------*/ +static int ExtractI4(unsigned char *buf) +{ + int x; + /* big endian extract */ + x = buf[0]; + x <<= 8; + x |= buf[1]; + x <<= 8; + x |= buf[2]; + x <<= 8; + x |= buf[3]; + return x; +} + +static void CreateI4(unsigned char *buf, int nValue) +{ + /* big endian create */ + buf[0]=(nValue>>24)&0xff; + buf[1]=(nValue>>16)&0xff; + buf[2]=(nValue>> 8)&0xff; + buf[3]=(nValue )&0xff; +} + + + +static void CreateI2(unsigned char *buf, int nValue) +{ + /* big endian create */ + buf[0]=(nValue>> 8)&0xff; + buf[1]=(nValue )&0xff; +} + + +/*-------------------------------------------------------------*/ +/* Same as GetVbrTag below, but only checks for the Xing tag. + requires buf to contain only 40 bytes */ +/*-------------------------------------------------------------*/ +int CheckVbrTag(unsigned char *buf) +{ + int h_id, h_mode, h_sr_index; + + /* get selected MPEG header data */ + h_id = (buf[1] >> 3) & 1; + h_sr_index = (buf[2] >> 2) & 3; + h_mode = (buf[3] >> 6) & 3; + + /* determine offset of header */ + if( h_id ) + { + /* mpeg1 */ + if( h_mode != 3 ) buf+=(32+4); + else buf+=(17+4); + } + else + { + /* mpeg2 */ + if( h_mode != 3 ) buf+=(17+4); + else buf+=(9+4); + } + + if( buf[0] != VBRTag[0] && buf[0] != VBRTag2[0] ) return 0; /* fail */ + if( buf[1] != VBRTag[1] && buf[1] != VBRTag2[1]) return 0; /* header not found*/ + if( buf[2] != VBRTag[2] && buf[2] != VBRTag2[2]) return 0; + if( buf[3] != VBRTag[3] && buf[3] != VBRTag2[3]) return 0; + return 1; +} + +int GetVbrTag(VBRTAGDATA *pTagData, unsigned char *buf) +{ + int i, head_flags; + int h_bitrate,h_id, h_mode, h_sr_index; + int enc_delay,enc_padding; + + /* get Vbr header data */ + pTagData->flags = 0; + + /* get selected MPEG header data */ + h_id = (buf[1] >> 3) & 1; + h_sr_index = (buf[2] >> 2) & 3; + h_mode = (buf[3] >> 6) & 3; + h_bitrate = ((buf[2]>>4)&0xf); + h_bitrate = bitrate_table[h_id][h_bitrate]; + + /* check for FFE syncword */ + if ((buf[1]>>4)==0xE) + pTagData->samprate = samplerate_table[2][h_sr_index]; + else + pTagData->samprate = samplerate_table[h_id][h_sr_index]; + // if( h_id == 0 ) + // pTagData->samprate >>= 1; + + + + /* determine offset of header */ + if( h_id ) + { + /* mpeg1 */ + if( h_mode != 3 ) buf+=(32+4); + else buf+=(17+4); + } + else + { + /* mpeg2 */ + if( h_mode != 3 ) buf+=(17+4); + else buf+=(9+4); + } + + if( buf[0] != VBRTag[0] && buf[0] != VBRTag2[0] ) return 0; /* fail */ + if( buf[1] != VBRTag[1] && buf[1] != VBRTag2[1]) return 0; /* header not found*/ + if( buf[2] != VBRTag[2] && buf[2] != VBRTag2[2]) return 0; + if( buf[3] != VBRTag[3] && buf[3] != VBRTag2[3]) return 0; + + buf+=4; + + pTagData->h_id = h_id; + + head_flags = pTagData->flags = ExtractI4(buf); buf+=4; /* get flags */ + + if( head_flags & FRAMES_FLAG ) + { + pTagData->frames = ExtractI4(buf); buf+=4; + } + + if( head_flags & BYTES_FLAG ) + { + pTagData->bytes = ExtractI4(buf); buf+=4; + } + + if( head_flags & TOC_FLAG ) + { + if( pTagData->toc != NULL ) + { + for(i=0;itoc[i] = buf[i]; + } + buf+=NUMTOCENTRIES; + } + + pTagData->vbr_scale = -1; + + if( head_flags & VBR_SCALE_FLAG ) + { + pTagData->vbr_scale = ExtractI4(buf); buf+=4; + } + + pTagData->headersize = + ((h_id+1)*72000*h_bitrate) / pTagData->samprate; + + buf+=21; + enc_delay = buf[0] << 4; + enc_delay += buf[1] >> 4; + enc_padding= (buf[1] & 0x0F)<<8; + enc_padding += buf[2]; + // check for reasonable values (this may be an old Xing header, + // not a INFO tag) + if (enc_delay<0 || enc_delay > 3000) enc_delay=-1; + if (enc_padding<0 || enc_padding > 3000) enc_padding=-1; + + pTagData->enc_delay=enc_delay; + pTagData->enc_padding=enc_padding; + +#ifdef DEBUG_VBRTAG + fprintf(stderr,"\n\n********************* VBR TAG INFO *****************\n"); + fprintf(stderr,"tag :%s\n",VBRTag); + fprintf(stderr,"head_flags :%d\n",head_flags); + fprintf(stderr,"bytes :%d\n",pTagData->bytes); + fprintf(stderr,"frames :%d\n",pTagData->frames); + fprintf(stderr,"VBR Scale :%d\n",pTagData->vbr_scale); + fprintf(stderr,"enc_delay = %i \n",enc_delay); + fprintf(stderr,"enc_padding= %i \n",enc_padding); + fprintf(stderr,"toc:\n"); + if( pTagData->toc != NULL ) + { + for(i=0;itoc[i])); + } + } + fprintf(stderr,"\n***************** END OF VBR TAG INFO ***************\n"); +#endif + return 1; /* success */ +} + + +/**************************************************************************** + * InitVbrTag: Initializes the header, and write empty frame to stream + * Paramters: + * fpStream: pointer to output file stream + * nMode : Channel Mode: 0=STEREO 1=JS 2=DS 3=MONO + **************************************************************************** +*/ +int InitVbrTag(lame_global_flags *gfp) +{ + int nMode,SampIndex; + lame_internal_flags *gfc = gfp->internal_flags; +#define MAXFRAMESIZE 2880 // or 0xB40, the max freeformat 640 32kHz framesize + // uint8_t pbtStreamBuffer[MAXFRAMESIZE]; + nMode = gfp->mode; + SampIndex = gfc->samplerate_index; + + + /* Clear Frame position array variables */ + //gfp->pVbrFrames=NULL; + gfp->nVbrNumFrames=0; + gfp->nVbrFrameBufferSize=0; + + + /* Clear stream buffer */ + // memset(pbtStreamBuffer,0x00,sizeof(pbtStreamBuffer)); + + + + /* + // Xing VBR pretends to be a 48kbs layer III frame. (at 44.1kHz). + // (at 48kHz they use 56kbs since 48kbs frame not big enough for + // table of contents) + // let's always embed Xing header inside a 64kbs layer III frame. + // this gives us enough room for a LAME version string too. + // size determined by sampling frequency (MPEG1) + // 32kHz: 216 bytes@48kbs 288bytes@ 64kbs + // 44.1kHz: 156 bytes 208bytes@64kbs (+1 if padding = 1) + // 48kHz: 144 bytes 192 + // + // MPEG 2 values are the same since the framesize and samplerate + // are each reduced by a factor of 2. + */ + { + int i,bitrate,tot; + if (1==gfp->version) { + bitrate = XING_BITRATE1; + } else { + if (gfp->out_samplerate < 16000 ) + bitrate = XING_BITRATE25; + else + bitrate = XING_BITRATE2; + } + + if (gfp->VBR==vbr_off) + bitrate = gfp->brate; + + gfp->TotalFrameSize= + ((gfp->version+1)*72000*bitrate) / gfp->out_samplerate; + + tot = (gfc->sideinfo_len+LAMEHEADERSIZE); + + if (gfp->TotalFrameSize < tot || + gfp->TotalFrameSize > MAXFRAMESIZE ) { + // disable tag, it wont fit + gfp->bWriteVbrTag = 0; + return 0; + } + + for (i=0; iTotalFrameSize; ++i) + add_dummy_byte(gfp,0); + } + + /* Success */ + return 0; +} + + + +/* fast CRC-16 computation - uses table crc16_lookup 8*/ +int CRC_update_lookup(int value, int crc) +{ + int tmp; + tmp=crc^value; + crc=(crc>>8)^crc16_lookup[tmp & 0xff]; + return crc; +} + +void UpdateMusicCRC(uint16_t *crc,unsigned char *buffer, int size){ + int i; + for (i=0; ibWriteVbrTag) + return; + + if (nStart) + MSGF( gfp->internal_flags, "Writing LAME Tag..."); + else + MSGF( gfp->internal_flags, "done\n"); + +} + + +/**************************************************************************** + * Jonathan Dee 2001/08/31 + * + * PutLameVBR: Write LAME info: mini version + info on various switches used + * Paramters: + * pbtStreamBuffer : pointer to output buffer + * id3v2size : size of id3v2 tag in bytes + * crc : computation of crc-16 of Lame Tag so far (starting at frame sync) + * + **************************************************************************** +*/ +int PutLameVBR(lame_global_flags *gfp, FILE *fpStream, uint8_t *pbtStreamBuffer, uint32_t id3v2size, uint16_t crc) +{ + lame_internal_flags *gfc = gfp->internal_flags; +// FLOAT fVersion = LAME_MAJOR_VERSION + 0.01 * LAME_MINOR_VERSION; + + int nBytesWritten = 0; + int nFilesize = 0; //size of fpStream. Will be equal to size after process finishes. + int i; + + int enc_delay=lame_get_encoder_delay(gfp); // encoder delay + int enc_padding=lame_get_encoder_padding(gfp); // encoder padding + + //recall: gfp->VBR_q is for example set by the switch -V + // gfp->quality by -q, -h, -f, etc + + int nQuality = (100 - 10 * gfp->VBR_q - gfp->quality); + + + const char *szVersion = get_lame_very_short_version(); + uint8_t nVBR; + uint8_t nRevision = 0x00; + uint8_t nRevMethod; + uint8_t vbr_type_translator[] = {1,5,3,2,4,0,3}; //numbering different in vbr_mode vs. Lame tag + + uint8_t nLowpass = ( ((gfp->lowpassfreq / 100.0)+.5) > 255 ? 255 : (gfp->lowpassfreq / 100.0)+.5 ); + + ieee754_float32_t fPeakSignalAmplitude = 0; //TODO... + uint16_t nRadioReplayGain = 0; //TODO... + uint16_t nAudioPhileReplayGain = 0; //TODO... + + + + + uint8_t nNoiseShaping = gfp->internal_flags->noise_shaping; + uint8_t nStereoMode = 0; + int bNonOptimal = 0; + uint8_t nSourceFreq = 0; + uint8_t nMisc = 0; + uint32_t nMusicLength = 0; + int bId3v1Present = ((gfp->internal_flags->tag_spec.flags & CHANGED_FLAG) + && !(gfp->internal_flags->tag_spec.flags & V2_ONLY_FLAG)); + uint16_t nMusicCRC = 0; + + //psy model type: Gpsycho or NsPsytune + unsigned char bExpNPsyTune = gfp->exp_nspsytune & 1; + unsigned char bSafeJoint = (gfp->exp_nspsytune & 2)!=0; + + unsigned char bNoGapMore = 0; + unsigned char bNoGapPrevious = 0; + + int nNoGapCount = gfp->internal_flags->nogap_total; + int nNoGapCurr = gfp->internal_flags->nogap_current; + + + uint8_t nAthType = gfp->ATHtype; //4 bits. + + uint8_t nFlags = 0; + + // if ABR, {store bitrate <=255} else { store "-b"} + int nABRBitrate = (gfp->VBR==vbr_abr)?gfp->VBR_mean_bitrate_kbps:gfp->brate; + + //revision and vbr method + if (gfp->VBR>=0 && gfp->VBR < sizeof(vbr_type_translator)) + nVBR = vbr_type_translator[gfp->VBR]; + else + nVBR = 0x00; //unknown. + + nRevMethod = 0x10 * nRevision + nVBR; + + //nogap + if (nNoGapCount != -1) + { + if (nNoGapCurr > 0) + bNoGapPrevious = 1; + + if (nNoGapCurr < nNoGapCount-1) + bNoGapMore = 1; + } + + //flags + + nFlags = nAthType + (bExpNPsyTune << 4) + + (bSafeJoint << 5) + + (bNoGapMore << 6) + + (bNoGapPrevious << 7); + + + if (nQuality < 0) + nQuality = 0; + + /*stereo mode field... a bit ugly.*/ + + switch(gfp->mode) + { + case MONO: + nStereoMode = 0; + break; + case STEREO: + nStereoMode = 1; + break; + case DUAL_CHANNEL: + nStereoMode = 2; + break; + case JOINT_STEREO: + if (gfp->force_ms) + nStereoMode = 4; + else + nStereoMode = 3; + break; + case NOT_SET: + /* FALLTHROUGH */ + default: + nStereoMode = 7; + break; + } + + if (gfp->mode_automs) + nStereoMode = 5; + + /*Intensity stereo : nStereoMode = 6. IS is not implemented */ + + if (gfp->in_samplerate <= 32000) + nSourceFreq = 0x00; + else if (gfp->in_samplerate ==48000) + nSourceFreq = 0x02; + else if (gfp->in_samplerate > 48000) + nSourceFreq = 0x03; + else + nSourceFreq = 0x01; //default is 44100Hz. + + + //Check if the user overrided the default LAME behaviour with some nasty options + + if (gfp->short_blocks == short_block_forced || + gfp->short_blocks == short_block_dispensed || + ((gfp->lowpassfreq == -1) && (gfp->highpassfreq == -1)) || // "-k" + (gfp->scale_left != gfp->scale_right) || + gfp->disable_reservoir || + gfp->noATH || + gfp->ATHonly || + (nAthType == 0) || + gfp->in_samplerate <= 32000) + bNonOptimal = 1; + + nMisc = nNoiseShaping + + (nStereoMode << 2) + + (bNonOptimal << 5) + + (nSourceFreq << 6); + + + + //get filesize + fseek(fpStream, 0, SEEK_END); + nFilesize = ftell(fpStream); + + + nMusicLength = nFilesize - id3v2size; //omit current frame + if (bId3v1Present) + nMusicLength-=128; //id3v1 present. + nMusicCRC = gfc->nMusicCRC; + + + /*Write all this information into the stream*/ + CreateI4(&pbtStreamBuffer[nBytesWritten], nQuality); + nBytesWritten+=4; + + strncpy(&pbtStreamBuffer[nBytesWritten], szVersion, 9); + nBytesWritten+=9; + + pbtStreamBuffer[nBytesWritten] = nRevMethod ; + nBytesWritten++; + + pbtStreamBuffer[nBytesWritten] = nLowpass; + nBytesWritten++; + + memmove(&pbtStreamBuffer[nBytesWritten], &fPeakSignalAmplitude, 4); + nBytesWritten+=4; + + CreateI2(&pbtStreamBuffer[nBytesWritten],nRadioReplayGain); + nBytesWritten+=2; + + CreateI2(&pbtStreamBuffer[nBytesWritten],nAudioPhileReplayGain); + nBytesWritten+=2; + + pbtStreamBuffer[nBytesWritten] = nFlags; + nBytesWritten++; + + if (nABRBitrate >= 255) + pbtStreamBuffer[nBytesWritten] = 0xFF; + else + pbtStreamBuffer[nBytesWritten] = nABRBitrate; + nBytesWritten++; + + pbtStreamBuffer[nBytesWritten ] = enc_delay >> 4; // works for win32, does it for unix? + pbtStreamBuffer[nBytesWritten +1] = (enc_delay << 4) + (enc_padding >> 8); + pbtStreamBuffer[nBytesWritten +2] = enc_padding; + + nBytesWritten+=3; + + pbtStreamBuffer[nBytesWritten] = nMisc; + nBytesWritten++; + + + memset(pbtStreamBuffer+nBytesWritten,0, 3); //unused in rev0 + nBytesWritten+=3; + + CreateI4(&pbtStreamBuffer[nBytesWritten], nMusicLength); + nBytesWritten+=4; + + CreateI2(&pbtStreamBuffer[nBytesWritten], nMusicCRC); + nBytesWritten+=2; + + /*Calculate tag CRC.... must be done here, since it includes + *previous information*/ + + for (i = 0;iinternal_flags; + + long lFileSize; + int nStreamIndex; + char abyte,bbyte; + uint8_t btToc[NUMTOCENTRIES]; + uint8_t pbtStreamBuffer[MAXFRAMESIZE]; + + int i; + uint16_t crc = 0x00; + + unsigned char id3v2Header[10]; + size_t id3v2TagSize; + + if (gfc->VBR_seek_table.pos <= 0) + return -1; + + + /* Clear stream buffer */ + memset(pbtStreamBuffer,0x00,sizeof(pbtStreamBuffer)); + + /* Seek to end of file*/ + fseek(fpStream,0,SEEK_END); + + /* Get file size */ + lFileSize=ftell(fpStream); + + /* Abort if file has zero length. Yes, it can happen :) */ + if (lFileSize==0) + return -1; + + /* + * The VBR tag may NOT be located at the beginning of the stream. + * If an ID3 version 2 tag was added, then it must be skipped to write + * the VBR tag data. + */ + + /* seek to the beginning of the stream */ + fseek(fpStream,0,SEEK_SET); + /* read 10 bytes in case there's an ID3 version 2 header here */ + fread(id3v2Header,1,sizeof id3v2Header,fpStream); + /* does the stream begin with the ID3 version 2 file identifier? */ + if (!strncmp((char *)id3v2Header,"ID3",3)) { + /* the tag size (minus the 10-byte header) is encoded into four + * bytes where the most significant bit is clear in each byte */ + id3v2TagSize=(((id3v2Header[6] & 0x7f)<<21) + | ((id3v2Header[7] & 0x7f)<<14) + | ((id3v2Header[8] & 0x7f)<<7) + | (id3v2Header[9] & 0x7f)) + + sizeof id3v2Header; + } else { + /* no ID3 version 2 tag in this stream */ + id3v2TagSize=0; + } + + /* Seek to first real frame */ + fseek(fpStream,id3v2TagSize+gfp->TotalFrameSize,SEEK_SET); + + /* Read the header (first valid frame) */ + fread(pbtStreamBuffer,4,1,fpStream); + + /* the default VBR header. 48 kbps layer III, no padding, no crc */ + /* but sampling freq, mode andy copyright/copy protection taken */ + /* from first valid frame */ + pbtStreamBuffer[0]=(uint8_t) 0xff; + abyte = (pbtStreamBuffer[1] & (char) 0xf1); + { + int bitrate; + if (1==gfp->version) { + bitrate = XING_BITRATE1; + } else { + if (gfp->out_samplerate < 16000 ) + bitrate = XING_BITRATE25; + else + bitrate = XING_BITRATE2; + } + + if (gfp->VBR==vbr_off) + bitrate = gfp->brate; + + bbyte = 16*BitrateIndex(bitrate,gfp->version,gfp->out_samplerate); + } + + /* Use as much of the info from the real frames in the + * Xing header: samplerate, channels, crc, etc... + */ + if (gfp->version==1) { + /* MPEG1 */ + pbtStreamBuffer[1]=abyte | (char) 0x0a; /* was 0x0b; */ + abyte = pbtStreamBuffer[2] & (char) 0x0d; /* AF keep also private bit */ + pbtStreamBuffer[2]=(char) bbyte | abyte; /* 64kbs MPEG1 frame */ + }else{ + /* MPEG2 */ + pbtStreamBuffer[1]=abyte | (char) 0x02; /* was 0x03; */ + abyte = pbtStreamBuffer[2] & (char) 0x0d; /* AF keep also private bit */ + pbtStreamBuffer[2]=(char) bbyte | abyte; /* 64kbs MPEG2 frame */ + } + + /* Clear all TOC entries */ + memset(btToc,0,sizeof(btToc)); + + Xing_seek_table (&gfc->VBR_seek_table, btToc); + /* print_seeking (btToc); */ + + /* Start writing the tag after the zero frame */ + nStreamIndex=gfc->sideinfo_len; + /* note! Xing header specifies that Xing data goes in the + * ancillary data with NO ERROR PROTECTION. If error protecton + * in enabled, the Xing data still starts at the same offset, + * and now it is in sideinfo data block, and thus will not + * decode correctly by non-Xing tag aware players */ + if (gfp->error_protection) nStreamIndex -= 2; + + /* Put Vbr tag */ + if (gfp->VBR == vbr_off) + { + pbtStreamBuffer[nStreamIndex++]=VBRTag2[0]; + pbtStreamBuffer[nStreamIndex++]=VBRTag2[1]; + pbtStreamBuffer[nStreamIndex++]=VBRTag2[2]; + pbtStreamBuffer[nStreamIndex++]=VBRTag2[3]; + + } + else + { + pbtStreamBuffer[nStreamIndex++]=VBRTag[0]; + pbtStreamBuffer[nStreamIndex++]=VBRTag[1]; + pbtStreamBuffer[nStreamIndex++]=VBRTag[2]; + pbtStreamBuffer[nStreamIndex++]=VBRTag[3]; + } + + /* Put header flags */ + CreateI4(&pbtStreamBuffer[nStreamIndex],FRAMES_FLAG+BYTES_FLAG+TOC_FLAG+VBR_SCALE_FLAG); + nStreamIndex+=4; + + /* Put Total Number of frames */ + CreateI4(&pbtStreamBuffer[nStreamIndex],gfp->nVbrNumFrames); + nStreamIndex+=4; + + /* Put Total file size */ + CreateI4(&pbtStreamBuffer[nStreamIndex],(int)lFileSize); + nStreamIndex+=4; + + /* Put TOC */ + memcpy(&pbtStreamBuffer[nStreamIndex],btToc,sizeof(btToc)); + nStreamIndex+=sizeof(btToc); + + + if (gfp->error_protection) { + /* (jo) error_protection: add crc16 information to header */ + CRC_writeheader(gfc, pbtStreamBuffer); + } + + + + //work out CRC so far: initially crc = 0 + for (i = 0;i< nStreamIndex ;i++) + crc = CRC_update_lookup(pbtStreamBuffer[i], crc); + + /*Put LAME VBR info*/ + nStreamIndex+=PutLameVBR(gfp, fpStream, pbtStreamBuffer + nStreamIndex, id3v2TagSize,crc); + +#ifdef DEBUG_VBRTAG + { + VBRTAGDATA TestHeader; + GetVbrTag(&TestHeader,pbtStreamBuffer); + } +#endif + + /*Seek to the beginning of the stream */ + fseek(fpStream,id3v2TagSize,SEEK_SET); + + /* Put it all to disk again */ + if (fwrite(pbtStreamBuffer,(unsigned int)gfp->TotalFrameSize,1,fpStream)!=1) + { + return -1; + } + /* Save to delete the frame buffer */ + //free(gfp->pVbrFrames); see HACKING for instructions on how + //gfp->pVbrFrames=NULL; memory in 'gfp' is allocated/free'd + + return 0; /* success */ +} + diff -Nru swftools-0.9.2+ds1/lib/lame/VbrTag.h swftools-0.9.1/lib/lame/VbrTag.h --- swftools-0.9.2+ds1/lib/lame/VbrTag.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/VbrTag.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * Xing VBR tagging for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * 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 LAME_VRBTAG_H +#define LAME_VRBTAG_H +#include "lame.h" +/* ----------------------------------------------------------- + * A Vbr header may be present in the ancillary + * data field of the first frame of an mp3 bitstream + * The Vbr header (optionally) contains + * frames total number of audio frames in the bitstream + * bytes total number of bytes in the bitstream + * toc table of contents + + * toc (table of contents) gives seek points + * for random access + * the ith entry determines the seek point for + * i-percent duration + * seek point in bytes = (toc[i]/256.0) * total_bitstream_bytes + * e.g. half duration seek point = (toc[50]/256.0) * total_bitstream_bytes + */ + + +#define FRAMES_FLAG 0x0001 +#define BYTES_FLAG 0x0002 +#define TOC_FLAG 0x0004 +#define VBR_SCALE_FLAG 0x0008 + +#define NUMTOCENTRIES 100 + +#define FRAMES_AND_BYTES (FRAMES_FLAG | BYTES_FLAG) + + + +/*structure to receive extracted header */ +/* toc may be NULL*/ +typedef struct +{ + int h_id; /* from MPEG header, 0=MPEG2, 1=MPEG1 */ + int samprate; /* determined from MPEG header */ + int flags; /* from Vbr header data */ + int frames; /* total bit stream frames from Vbr header data */ + int bytes; /* total bit stream bytes from Vbr header data*/ + int vbr_scale; /* encoded vbr scale from Vbr header data*/ + unsigned char toc[NUMTOCENTRIES]; /* may be NULL if toc not desired*/ + int headersize; /* size of VBR header, in bytes */ + int enc_delay; /* encoder delay */ + int enc_padding; /* encoder paddign added at end of stream */ +} VBRTAGDATA; + +int CheckVbrTag(unsigned char *buf); +int GetVbrTag(VBRTAGDATA *pTagData, unsigned char *buf); + +int SeekPoint(unsigned char TOC[NUMTOCENTRIES], int file_bytes, float percent); +int InitVbrTag(lame_global_flags *gfp); +int PutVbrTag(lame_global_flags *gfp,FILE *fid,int nVbrScale); +int PutLameVBR(lame_global_flags *gfp, FILE *fpStream, uint8_t *pbtStreamBuffer, uint32_t id3v2size, uint16_t crc); +void AddVbrFrame(lame_global_flags *gfp); +void ReportLameTagProgress(lame_global_flags *gfp,int nStart); +void UpdateMusicCRC(uint16_t *crc,unsigned char *buffer, int size); + +#endif diff -Nru swftools-0.9.2+ds1/lib/lame/version.c swftools-0.9.1/lib/lame/version.c --- swftools-0.9.2+ds1/lib/lame/version.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/version.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,215 @@ +/* + * Version numbering for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * 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. + */ + +/*! + \file version.c + \brief Version numbering for LAME. + + Contains functions which describe the version of LAME. + + \author A.L. Faber + \version \$Id: version.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ + \ingroup libmp3lame +*/ + + +#include +#include "config_static.h" + + +#include +#include "version.h" /* macros of version numbers */ + +#ifdef WITH_DMALLOC +#include +#endif + +//! Stringify \a x. +#define STR(x) #x +//! Stringify \a x, perform macro expansion. +#define XSTR(x) STR(x) + +#if defined(MMX_choose_table) +# define V1 "MMX " +#else +# define V1 "" +#endif + +#if defined(KLEMM) +# define V2 "KLM " +#else +# define V2 "" +#endif + +#if defined(RH) +# define V3 "RH " +#else +# define V3 "" +#endif + +//! Compile time features. +#define V V1 V2 V3 + +//! Get the LAME version string. +/*! + \param void + \return a pointer to a string which describes the version of LAME. +*/ +const char* get_lame_version ( void ) /* primary to write screen reports */ +{ + /* Here we can also add informations about compile time configurations */ + +#if LAME_ALPHA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " " V + "(alpha " XSTR(LAME_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")"; +#elif LAME_BETA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " " V + "(beta " XSTR(LAME_BETA_VERSION) ", " __DATE__ ")"; +#else + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " " V; +#endif + + return str; +} + + +//! Get the short LAME version string. +/*! + It's mainly for inclusion into the MP3 stream. + + \param void + \return a pointer to the short version of the LAME version string. +*/ +const char* get_lame_short_version ( void ) +{ + /* adding date and time to version string makes it harder for output + validation */ + +#if LAME_ALPHA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " (alpha)"; +#elif LAME_BETA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " (beta)"; +#else + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION); +#endif + + return str; +} + +//! Get the _very_ short LAME version string. +/*! + It's used in the LAME VBR tag only. + + \param void + \return a pointer to the short version of the LAME version string. +*/ +const char* get_lame_very_short_version ( void ) +{ + /* adding date and time to version string makes it harder for output + validation */ + +#if LAME_ALPHA_VERSION > 0 + static /*@observer@*/ const char *const str = + "LAME" XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) "a"; +#elif LAME_BETA_VERSION > 0 + static /*@observer@*/ const char *const str = + "LAME" XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) "b"; +#else + static /*@observer@*/ const char *const str = + "LAME" XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " "; +#endif + + return str; +} + +//! Get the version string for GPSYCHO. +/*! + \param void + \return a pointer to a string which describes the version of GPSYCHO. +*/ +const char* get_psy_version ( void ) +{ +#if PSY_ALPHA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(PSY_MAJOR_VERSION) "." XSTR(PSY_MINOR_VERSION) + " (alpha " XSTR(PSY_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")"; +#elif PSY_BETA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(PSY_MAJOR_VERSION) "." XSTR(PSY_MINOR_VERSION) + " (beta " XSTR(PSY_BETA_VERSION) ", " __DATE__ ")"; +#else + static /*@observer@*/ const char *const str = + XSTR(PSY_MAJOR_VERSION) "." XSTR(PSY_MINOR_VERSION); +#endif + + return str; +} + + +//! Get the URL for the LAME website. +/*! + \param void + \return a pointer to a string which is a URL for the LAME website. +*/ +const char* get_lame_url ( void ) +{ + static /*@observer@*/ const char *const str = LAME_URL; + + return str; +} + + +//! Get the numerical representation of the version. +/*! + Writes the numerical representation of the version of LAME and + GPSYCHO into lvp. + + \param lvp +*/ +void get_lame_version_numerical ( lame_version_t *const lvp ) +{ + static /*@observer@*/ const char *const features = V; + + /* generic version */ + lvp->major = LAME_MAJOR_VERSION; + lvp->minor = LAME_MINOR_VERSION; + lvp->alpha = LAME_ALPHA_VERSION; + lvp->beta = LAME_BETA_VERSION; + + /* psy version */ + lvp->psy_major = PSY_MAJOR_VERSION; + lvp->psy_minor = PSY_MINOR_VERSION; + lvp->psy_alpha = PSY_ALPHA_VERSION; + lvp->psy_beta = PSY_BETA_VERSION; + + /* compile time features */ + /*@-mustfree@*/ + lvp->features = features; + /*@=mustfree@*/ +} + +/* end of version.c */ diff -Nru swftools-0.9.2+ds1/lib/lame/version.h swftools-0.9.1/lib/lame/version.h --- swftools-0.9.2+ds1/lib/lame/version.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/lame/version.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * Version numbering for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * 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 LAME_VERSION_H +#define LAME_VERSION_H + +# include "lame.h" + +/* + * To make a string from a token, use the # operator: + * + * #define __STR(x) #x + * #define STR(x) __STR(x) + */ + +# define LAME_URL "http://www.mp3dev.org/" + +# define LAME_MAJOR_VERSION 3 /* Major version number */ +# define LAME_MINOR_VERSION 91 /* Minor version number */ +# define LAME_ALPHA_VERSION 0 /* Patch level of alpha version, otherwise zero */ +# define LAME_BETA_VERSION 0 /* Patch level of beta version, otherwise zero */ + +# define PSY_MAJOR_VERSION 0 /* Major version number */ +# define PSY_MINOR_VERSION 89 /* Minor version number */ +# define PSY_ALPHA_VERSION 0 /* Set number if this is an alpha version, otherwise zero */ +# define PSY_BETA_VERSION 0 /* Set number if this is a beta version, otherwise zero */ + + +const char* get_lame_version ( void ); +const char* get_lame_short_version ( void ); +const char* get_psy_version ( void ); +const char* get_lame_url ( void ); +void get_lame_version_numerical ( lame_version_t *const lvp ); + +#endif /* LAME_VERSION_H */ + +/* End of version.h */ diff -Nru swftools-0.9.2+ds1/lib/mkshared swftools-0.9.1/lib/mkshared --- swftools-0.9.2+ds1/lib/mkshared 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/mkshared 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,27 @@ +#!/bin/sh +INCLUDEDIR=/usr/local/include +LIBDIR=/usr/local/lib + +files=lame/*.c +files="$files rfxswf.c bitio.c" +for file in $files +do + libtool gcc -g -c $file +done +lofiles=*.lo + +libtool gcc -g -o librfxswf.la $lofiles -rpath ${LIBDIR} -lm -lz -ljpeg + + +#perl -pe 's/^#include "\.\.\/config"/#define WORDS_BIGENDIAN/' rfxswf.h > rfxswf.tmp +perl -pe 's/^#include "\.\.\/config.h"//' rfxswf.h > rfxswf.tmp + +su -c "cp rfxswf.tmp ${INCLUDEDIR}/rfxswf.h; + cp ../config.h ${INCLUDEDIR}/rfxswf_config.h; + cp bitio.h ${INCLUDEDIR}/bitio.h; + libtool cp librfxswf.la $LIBDIR/librfxswf.la; + ldconfig $LIBDIR + " + +rm -f *.o *.lo rfxswf.tmp + diff -Nru swftools-0.9.2+ds1/lib/modules/swfscripts.c swftools-0.9.1/lib/modules/swfscripts.c --- swftools-0.9.2+ds1/lib/modules/swfscripts.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/modules/swfscripts.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,368 @@ +/* swfscripts.c + + AVM2 Utility Actionscripts + + Extension module for the rfxswf library. + Part of the swftools package. + + Copyright (c) 2007 Alessandro Molina + Copyright (c) 2007,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 "../rfxswf.h" + +static unsigned AVM2_uint32toU30(unsigned val, char * out) +{ + unsigned len = 0; + + while(val) { + out[len++] = (val&~0x7f?0x80:0) | (val & 0x7F); + val >>= 7; + } + + return len; +} + +void AVM2_InsertStops(SWF*swf) +{ + TAG * t; + + //MAIN AS3 CLASS INIT + unsigned frame_nums = 0; + + /* Count number of pages to set up stop callback for every frame */ + t = swf->firstTag; + while(t) { + if (t->id == ST_SHOWFRAME) ++frame_nums; + t = t->next; + } + + TAG * classCall = swf_InsertTagBefore(swf, swf->firstTag, ST_SYMBOLCLASS); + swf_SetU16(classCall, 1); // number of symbols + swf_SetU16(classCall, 0); // object id + swf_SetString(classCall, "stop_fla:MainTimeline"); // class to associate with the symbol + + //0x52 is the Flash9 equivalent to DoAction + char init_pool[322] = { + 0x01,0x00,0x00,0x00, /* Flag Parameter to ST_DOABC (1 = lazy load)*/ + 0x00, /* 0 terminated class name */ + 0x10,0x00,0x2e,0x00, /* ABC file magic number (minor version, major version) */ + 0x00, /* zero integers */ + 0x00, /* zero unsigned integers */ + 0x00, /* zero doubles */ + + 0x11, /* 16 strings (+1) */ + 0x08, 's','t','o','p','_','f','l','a', + 0x0c, 'M','a','i','n','T','i','m','e','l','i','n','e', + 0x0d, 'f','l','a','s','h','.','d','i','s','p','l','a','y', + 0x09, 'M','o','v','i','e','C','l','i','p', + 0x15, 's','t','o','p','_','f','l','a',':','M','a','i','n','T','i','m','e','l','i','n','e', + 0x06, 'd','o','s','t','o','p', + 0x00, // Empty string: ref. to the global namespace + 0x04, 's','t','o','p', + 0x0e, 'a','d','d','F','r','a','m','e','S','c','r','i','p','t', + 0x06, 'O','b','j','e','c','t', + 0x0c, 'f','l','a','s','h','.','e','v','e','n','t','s', + 0x0f, 'E','v','e','n','t','D','i','s','p','a','t','c','h','e','r', + 0x0d, 'D','i','s','p','l','a','y','O','b','j','e','c','t', + 0x11, 'I','n','t','e','r','a','c','t','i','v','e','O','b','j','e','c','t', + 0x16, 'D','i','s','p','l','a','y','O','b','j','e','c','t','C','o','n','t','a','i','n','e','r', + 0x06, 'S','p','r','i','t','e', + + 0x07, /* 6 namespaces (+1) */ + 0x16,0x01, /* kind: CONSTANT_PackageNamespace, ref. to: stop_fla */ + 0x16,0x03, /* kind: CONSTANT_PackageNamespace, ref. to: flash.display */ + 0x18,0x05, /* kind: CONSTANT_ProtectedNamespace, ref. to: stop_fla:MainTimeline */ + 0x17,0x01, /* kind: CONSTANT_PackageInternalNs, ref. to: MainTimeline */ + 0x16,0x07, /* kind: CONSTANT_PackageNamespace, ref. to the global namespace */ + 0x16,0x0b, /* kind: CONSTANT_PackageNamespace, ref. to: flash.events */ + + 0x00, /* zero namespace sets */ + + 0x0c, /* 11 MultiNames (+1) */ + /* 1st value: Multiname kind (0x07 = Qualified Name, a multiname with 1 namespace, refers to a method) + 2nd value: refers to namespace name index in the namespace table + 3rd value: refers to method name index in the string table */ + 0x07,0x01,0x02, /* stop_fla:MainTimeLine */ + 0x07,0x02,0x04, /* flash.display:MovieClip */ + 0x07,0x04,0x06, /* <4th namespace>:dostop */ + 0x07,0x05,0x08, /* :stop */ + 0x07,0x05,0x09, /* :addFrameScript */ + 0x07,0x05,0x0a, /* :Object */ + 0x07,0x06,0x0c, /* flash.events:EventDispatcher */ + 0x07,0x02,0x0d, /* flash.display:DisplayObject */ + 0x07,0x02,0x0e, /* flash.display:InteractiveObject */ + 0x07,0x02,0x0f, /* flash.display:DisplayObjectContainer */ + 0x07,0x02,0x10, /* flash.display:Sprite */ + + 0x04, /* 4 Methods */ + /* METHOD 1 */ + 0x00,0x00,0x00,0x00, /* No params (nor params types), no return type, no method name, flags */ + 0x00,0x00,0x00,0x00, /* No params (nor params types), no return type, no method name, flags */ + 0x00,0x00,0x00,0x00, /* No params (nor params types), no return type, no method name, flags */ + 0x00,0x00,0x00,0x00, /* No params (nor params types), no return type, no method name, flags */ + + 0x00, /* Zero Metadata */ + + 0x01, /* 1 Class */ + 0x01, /* Name: ref. to multiname no. 1 (MainTimeline) */ + 0x02, /* Super_name (base class): ref. to multiname no. 2 (flash.display) */ + 0x08, /* Flags: 0x08 value indicates that it uses its protected namespace (and make next field exists) */ + 0x03, /* Ref. to namespace no. 3 (MainTimeline, protected namespace for this class) */ + 0x00, /* No. of interfaces: there are no interfaces (nor interface definition) */ + 0x02, /* Initializer index: ref. to method no. 2 */ + 0x01, /* No. of traits */ + /* Trait section */ + 0x03, /* Name: ref. to multiname no. 3 (stop) */ + 0x01, /* 0000: no attributes (nor metadata in the next subsection); + then 1: type is Trait_Method */ + /* Trait_method section */ + 0x00, /* NO optimization for virtual calls */ + 0x01, /* Ref. to method no. 1 */ + /* HERE FOLLOW THE CLASS DATA */ + 0x00, /* Ref. to method no. 0 as static initializer for this class */ + 0x00, /* No. of traits for this class (no ones) */ + + 0x01, /* 1 Script */ + 0x03, /* Ref. to method no. 3, invoked prior to any other code in the script */ + 0x01, /* No. of traits */ + /* Trait section */ + 0x01, /* Name: ref. to multiname no. 1 (flash.display:MovieClip) */ + 0x04, /* 0000: no attributes (nor metadata in the next subsection); + then 4: type is Trait_Class*/ + /* Trait_class section */ + 0x01, /* Slot ID where the trait resides */ + 0x00, /* Class index (there is only one class)*/ + + 0x04, /* Method body count: there are 4 method bodies */ + /* HERE FOLLOW THE METHOD BODY DATA */ + 0x00, /* Method index, ref. to method no. 0 */ + 0x01, /* Max stack slots the method can use */ + 0x01, /* No. of registers +1 the method can use: this one cannot use registers */ + 0x09,0x0a, /* Min and max scope depth the method can access*/ + 0x03, /* Code length (in bytes) */ + /* The actual method code: + this is the function stop_fla::MainTimeline$cinit()*/ + 0xd0,0x30,0x47, + 0x00, /* No. of exceptions (no exceptions) */ + 0x00, /* No. of traits (no traits) */ + + 0x01, /* Method index, ref. to method no. 1 */ + 0x01, /* Max stack slots the method can use */ + 0x01, /* No. of registers +1 the method can use: this one cannot use registers */ + 0x0a,0x0b, /* Min and max scope depth the method can access*/ + 0x08, /* Code length (in bytes) */ + /* The actual method code: + this is the function stop_fla::dostop(), + the one that actually executes the stop() */ + 0xd0,0x30,0x5d,0x04,0x4f,0x04,0x00,0x47, + 0x00, /* No. of exceptions (no exceptions) */ + 0x00, /* No. of traits (no traits) */ + }; + + /* Header of stop_fla::MainTimeline() method */ + char constructor_header[5] = { + 0x02, /* Method index, ref. to method no. 2 */ + 0x03, /* Max stack slots the method can use */ + 0x01, /* No. of registers +1 the method can use: this one cannot use registers */ + 0x0a,0x0b /* Min and max scope depth the method can access*/ + }; + + char constructor_first[5] = { + /* The actual method code: + This is the function stop_fla::MainTimeline() + Does: calls the super constructor for class #0 (MainTimeline), + then puts on the stack the object, namespace and name of the arguments + needed by the addFrameScripts, then calls the addFrameScripts + */ + 0xd0, /* getlocal0 */ + 0x30, /* pushscope */ + 0xd0, /* getlocal0 */ + 0x49, /* constructsuper */ + 0x00 /* 0 */ + }; + + char constructor_frame_register[10] = { + 0x5d, /* findpropstrict */ + 0x05, /* 'addFrameScript' */ + 0x25, /* pushshort */ + 0x00, /* frame number for pushshort */ + 0x02, /* NOP (hack to write u30 value of frame number when > 127) */ + 0x60, /* getlex */ + 0x03, /* 'stop_fla::dostop' */ + 0x4f, /* callpropvoid */ + 0x05, /* 'addFrameScript' */ + 0x02 /* 2*/ + }; + + char constructor_return[3] = { + 0x47, /* returnvoid */ + 0x00, /* No. of exceptions (no exceptions) */ + 0x00, /* No. of traits (no traits) */ + }; + + char script_init_pool[47] = { + 0x03, /* Method index, ref. to method no. 3 */ + 0x02, /* Max stack slots the method can use */ + 0x01, /* No. of registers +1 the method can use: this one cannot use registers */ + 0x01,0x09, /* Min and max scope depth the method can access*/ + 0x27, /* Code length (in bytes) */ + /* The actual method code: + this is the function script0$init() */ + 0xd0,0x30,0x65,0x00,0x60,0x06,0x30,0x60,0x07,0x30,0x60,0x08,0x30,0x60,0x09,0x30,0x60,0x0a,0x30,0x60, + 0x0b,0x30,0x60,0x02,0x30,0x60,0x02,0x58,0x00,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x68,0x01,0x47, + 0x00, /* No. of exceptions (no exceptions) */ + 0x00 /* No. of traits (no traits) */ + }; + /* END OF THE ABCFILE (Actionscript Byte Code) */ + + char code_len[5] = {0, }; + unsigned clen_len = AVM2_uint32toU30((6 + sizeof(constructor_frame_register) * frame_nums), code_len); + unsigned i, offset = 0; + + TAG *classInit = swf_InsertTagBefore(swf, swf->firstTag, ST_DOABC); + + /* Copy the environment Initialization code */ + swf_SetBlock(classInit, (U8*)init_pool,sizeof(init_pool)); + /* Copy Constructor Method header */ + swf_SetBlock(classInit, (U8*)constructor_header, sizeof(constructor_header)); + /* Add Code block size (u30) to the method header */ + swf_SetBlock(classInit, (U8*)code_len, clen_len); + + /* Copy Constructor Method body first part */ + swf_SetBlock(classInit, (U8*)constructor_first, sizeof(constructor_first)); + + /* Register the callback for every frame */ + for (i = 0; i < frame_nums; ++i) { + AVM2_uint32toU30(i,constructor_frame_register + 3); // Write current frame number + swf_SetBlock(classInit, (U8*)constructor_frame_register, sizeof(constructor_frame_register)); + } + + /* Copy Constructor method body ending, just a return */ + swf_SetBlock(classInit, (U8*)constructor_return, sizeof(constructor_return)); + + /* Copy the script init code */ + swf_SetBlock(classInit, (U8*)script_init_pool, sizeof(script_init_pool)); +} + +void AVM2_InsertButtonLink(SWF*swf) +{ + unsigned char displayEventCode[] = { + // button.dispatchEvent(new Event("pdflinkdown"),true,true) + + 0x01, 0x00, 0x00, 0x00, //flags + 0x00, + 0x10, 0x00, 0x2e, 0x00, //version + 0x00, //no ints + 0x00, //no uints + 0x00, //no floats + 0x14, //19 strings + 0x17, 'e','v','e','n','t','_','o','h','n','e','_','l','i','s','t','e','n','e','r','_','f','l','a', + 0x0c, 'M','a','i','n','t','i','m','e','l','i','n','e', + 0x0d, 'f','l','a','s','h','.','d','i','s','p','l','a','y', + 0x09, 'M','o','v','i','e','c','l','i','p', + 0x24, 'e','v','e','n','t','_','o','h','n','e','_','l','i','s','t','e','n','e','r','_','f','l','a',':','M','a','i','n','t','i','m','e','l','i','n','e', + 0x00, + 0x06, 'b','u','t','t','o','n', + 0x06, 'f','r','a','m','e','1', + 0x0c, 'f','l','a','s','h','.','e','v','e','n','t','s', + 0x05, 'E','v','e','n','t', + 0x0b, 'p','d','f','l','i','n','k','d','o','w','n', + 0x0d, 'd','i','s','p','a','t','c','h','E','v','e','n','t', + 0x0e, 'a','d','d','F','r','a','m','e','S','c','r','i','p','t', + 0x06, 'O','b','j','e','c','t', + 0x0f, 'E','v','e','n','t','d','i','s','p','a','t','c','h','e','r', + 0x0d, 'D','i','s','p','l','a','y','O','b','j','e','c','t', + 0x11, 'I','n','t','e','r','a','c','t','i','v','e','O','b','j','e','c','t', + 0x16, 'D','i','s','p','l','a','y','O','b','j','e','c','t','C','o','n','t','a','i','n','e','r', + 0x06, 'S','p','r','i','t','e', + + 0x07, // 6 namespaces + 0x16, 0x01, + 0x16, 0x03, + 0x18, 0x05, + 0x16, 0x06, + 0x17, 0x01, + 0x16, 0x09, + + 0x00, //zero namespace sets + + 0x0e, //13 multinames + 0x07, 0x01, 0x02, + 0x07, 0x02, 0x04, + 0x07, 0x04, 0x07, + 0x07, 0x05, 0x08, + 0x07, 0x06, 0x0a, + 0x07, 0x04, 0x0c, + 0x07, 0x04, 0x0d, + 0x07, 0x04, 0x0e, + 0x07, 0x06, 0x0f, + 0x07, 0x02, 0x10, + 0x07, 0x02, 0x11, + 0x07, 0x02, 0x12, + 0x07, 0x02, 0x13, + + 0x04, // 4 methods + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + 0x00, // zero metadata + + 0x01, // 1 class + 0x01, 0x02, 0x08, 0x03, 0x00, 0x02, + 0x02, // 2 traits + 0x03, 0x00, // name, slot + 0x00, 0x02, 0x00, + 0x04, 0x01, // name, method, + 0x00, 0x01, + 0x00, // ref to method 0 (initializer) + 0x00, // no traits + + 0x01, // 1 script + 0x03, 0x01, 0x01, 0x04, 0x01, 0x00, + + 0x04, // 4 method bodies + // method 1 + 0x00, 0x01, 0x01, 0x09, 0x0a, + 0x03, 0xd0, 0x30, 0x47, // code + 0x00, 0x00, + // method 2 + 0x01, 0x05, 0x01, 0x0a, 0x0b, + 0x11, 0xd0, 0x30, 0x60, 0x03, 0x5d, 0x05, 0x2c, 0x0b, 0x26, 0x26, 0x4a, 0x05, 0x03, 0x4f, 0x06, 0x01, 0x47, // code + 0x00, 0x00, + // method 3 + 0x02, 0x03, 0x01, 0x0a, 0x0b, + 0x0f, 0xd0, 0x30, 0xd0, 0x49, 0x00, 0x5d, 0x07, 0x24, 0x00, 0x60, 0x04, 0x4f, 0x07, 0x02, 0x47, // code + 0x00, 0x00, + // method 4 + 0x03, 0x02, 0x01, 0x01, 0x09, + 0x27, 0xd0, 0x30, 0x65, 0x00, 0x60, 0x08, 0x30, 0x60, 0x09, 0x30, 0x60, 0x0a, 0x30, 0x60, 0x0b, //code + 0x30, 0x60, 0x0c, 0x30, 0x60, 0x0d, 0x30, 0x60, 0x02, 0x30, 0x60, 0x02, 0x58, 0x00, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x68, 0x01, 0x47, + 0x00, 0x00, + }; +} + + + + + + + + diff -Nru swftools-0.9.2+ds1/lib/pdf/CharOutputDev.cc swftools-0.9.1/lib/pdf/CharOutputDev.cc --- swftools-0.9.2+ds1/lib/pdf/CharOutputDev.cc 2011-12-12 21:29:27.000000000 +0000 +++ swftools-0.9.1/lib/pdf/CharOutputDev.cc 2012-06-20 15:37:18.000000000 +0000 @@ -675,7 +675,13 @@ void CharOutputDev::endPage() { msg(" endPage (GfxOutputDev)"); - + + if(this->previous_link) { + if(device->setparameter) { + device->setparameter(device, "link", ""); + } + } + if(this->links) { kdtree_destroy(this->links); this->links = 0; @@ -688,6 +694,7 @@ l = last; } this->last_link = 0; + this->previous_link = 0; } static inline double sqr(double x) {return x*x;} @@ -796,7 +803,9 @@ } // check for invisible text -- this is used by Acrobat Capture - if (render == RENDER_INVISIBLE) { + if (render == RENDER_INVISIBLE || + render == RENDER_FILL && state->getFillColorSpace()->isNonMarking() || + render == RENDER_STROKE && state->getStrokeColorSpace()->isNonMarking()) { col.a = 0; if(!config_extrafontdata) return; @@ -1200,7 +1209,7 @@ printf("adding link %p at %f %f %f %f to tree\n", this->last_link, x1, y1, x2, y2); #endif - msg(" storing \"%s\" link to \"%s\"", type, FIXNULL(action)); + msg(" storing \"%s\" link to \"%s\" (%f %f %f %f)", type, FIXNULL(action), x1, y1, x2, y2); free(s);s=0; } diff -Nru swftools-0.9.2+ds1/lib/pdf/DummyOutputDev.cc swftools-0.9.1/lib/pdf/DummyOutputDev.cc --- swftools-0.9.2+ds1/lib/pdf/DummyOutputDev.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/DummyOutputDev.cc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,377 @@ +/* DummyOutputDev.h + + Output Device which serves as "passthrough" + + Copyright (c) 2007 Matthias Kramm + + Swftools 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. + + Swftools 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 swftools; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include +#include +#include +#include "config.h" +#include "DummyOutputDev.h" +#include "GFXOutputDev.h" +#include "SplashBitmap.h" +#include "SplashPattern.h" +#include "Splash.h" +#include "../log.h" + +DummyOutputDev::DummyOutputDev(OutputDev*target) +{ + this->rgbdev = target; +} +DummyOutputDev::~DummyOutputDev() +{ + if(this->rgbdev) { + delete this->rgbdev;this->rgbdev= 0; + } +} +void DummyOutputDev::startPage(int pageNum, GfxState *state) +{ + rgbdev->startPage(pageNum, state); +} + +void DummyOutputDev::endPage() +{ + rgbdev->endPage(); +} + +GBool DummyOutputDev::upsideDown() +{ + return rgbdev->upsideDown(); +} + +GBool DummyOutputDev::useDrawChar() +{ + return rgbdev->useDrawChar(); +} + +GBool DummyOutputDev::useTilingPatternFill() +{ + return rgbdev->useTilingPatternFill(); +} + +GBool DummyOutputDev::useShadedFills() +{ + return rgbdev->useShadedFills(); +} + +GBool DummyOutputDev::useDrawForm() +{ + return rgbdev->useDrawForm(); +} + +GBool DummyOutputDev::interpretType3Chars() +{ + return rgbdev->interpretType3Chars(); +} + +GBool DummyOutputDev::needNonText() +{ + return rgbdev->needNonText(); +} +void DummyOutputDev::setDefaultCTM(double *ctm) +{ + rgbdev->setDefaultCTM(ctm); +} +void DummyOutputDev::saveState(GfxState *state) +{ + rgbdev->saveState(state); +} +void DummyOutputDev::restoreState(GfxState *state) +{ + rgbdev->restoreState(state); +} +void DummyOutputDev::updateAll(GfxState *state) +{ + rgbdev->updateAll(state); +} +void DummyOutputDev::updateCTM(GfxState *state, double m11, double m12, double m21, double m22, double m31, double m32) +{ + rgbdev->updateCTM(state,m11,m12,m21,m22,m31,m32); +} +void DummyOutputDev::updateLineDash(GfxState *state) +{ + rgbdev->updateLineDash(state); +} +void DummyOutputDev::updateFlatness(GfxState *state) +{ + rgbdev->updateFlatness(state); +} +void DummyOutputDev::updateLineJoin(GfxState *state) +{ + rgbdev->updateLineJoin(state); +} +void DummyOutputDev::updateLineCap(GfxState *state) +{ + rgbdev->updateLineCap(state); +} +void DummyOutputDev::updateMiterLimit(GfxState *state) +{ + rgbdev->updateMiterLimit(state); +} +void DummyOutputDev::updateLineWidth(GfxState *state) +{ + rgbdev->updateLineWidth(state); +} +void DummyOutputDev::updateStrokeAdjust(GfxState *state) +{ + rgbdev->updateStrokeAdjust(state); +} +void DummyOutputDev::updateFillColorSpace(GfxState *state) +{ + rgbdev->updateFillColorSpace(state); +} +void DummyOutputDev::updateStrokeColorSpace(GfxState *state) +{ + rgbdev->updateStrokeColorSpace(state); +} +void DummyOutputDev::updateFillColor(GfxState *state) +{ + rgbdev->updateFillColor(state); +} +void DummyOutputDev::updateStrokeColor(GfxState *state) +{ + rgbdev->updateStrokeColor(state); +} +void DummyOutputDev::updateBlendMode(GfxState *state) +{ + rgbdev->updateBlendMode(state); +} +void DummyOutputDev::updateFillOpacity(GfxState *state) +{ + rgbdev->updateFillOpacity(state); +} +void DummyOutputDev::updateStrokeOpacity(GfxState *state) +{ + rgbdev->updateStrokeOpacity(state); +} +void DummyOutputDev::updateFillOverprint(GfxState *state) +{ + rgbdev->updateFillOverprint(state); +} +void DummyOutputDev::updateStrokeOverprint(GfxState *state) +{ + rgbdev->updateStrokeOverprint(state); +} +void DummyOutputDev::updateTransfer(GfxState *state) +{ + rgbdev->updateTransfer(state); +} +void DummyOutputDev::updateFont(GfxState *state) +{ + rgbdev->updateFont(state); +} +void DummyOutputDev::updateTextMat(GfxState *state) +{ + rgbdev->updateTextMat(state); +} +void DummyOutputDev::updateCharSpace(GfxState *state) +{ + rgbdev->updateCharSpace(state); +} +void DummyOutputDev::updateRender(GfxState *state) +{ + rgbdev->updateRender(state); +} +void DummyOutputDev::updateRise(GfxState *state) +{ + rgbdev->updateRise(state); +} +void DummyOutputDev::updateWordSpace(GfxState *state) +{ + rgbdev->updateWordSpace(state); +} +void DummyOutputDev::updateHorizScaling(GfxState *state) +{ + rgbdev->updateHorizScaling(state); +} +void DummyOutputDev::updateTextPos(GfxState *state) +{ + rgbdev->updateTextPos(state); +} +void DummyOutputDev::updateTextShift(GfxState *state, double shift) +{ + rgbdev->updateTextShift(state, shift); +} +void DummyOutputDev::stroke(GfxState *state) +{ + rgbdev->stroke(state); +} +void DummyOutputDev::fill(GfxState *state) +{ + rgbdev->fill(state); +} +void DummyOutputDev::eoFill(GfxState *state) +{ + rgbdev->eoFill(state); +} +#if (xpdfMajorVersion < 3) || (xpdfMinorVersion < 2) || (xpdfUpdateVersion < 7) +void DummyOutputDev::tilingPatternFill(GfxState *state, Object *str, + int paintType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep) +{ + rgbdev->tilingPatternFill(state, str, paintType, resDict, mat, bbox, x0, y0, x1, y1, xStep, yStep); +} +#else +void DummyOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, + int paintType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep) +{ + rgbdev->tilingPatternFill(state, gfx, str, paintType, resDict, mat, bbox, x0, y0, x1, y1, xStep, yStep); +} +#endif + +GBool DummyOutputDev::functionShadedFill(GfxState *state, GfxFunctionShading *shading) +{ + return rgbdev->functionShadedFill(state, shading); +} +GBool DummyOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading) +{ + return rgbdev->axialShadedFill(state, shading); +} +GBool DummyOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading) +{ + return rgbdev->radialShadedFill(state, shading); +} + +void DummyOutputDev::clip(GfxState *state) +{ + rgbdev->clip(state); +} +void DummyOutputDev::eoClip(GfxState *state) +{ + rgbdev->eoClip(state); +} +void DummyOutputDev::clipToStrokePath(GfxState *state) +{ + rgbdev->clipToStrokePath(state); +} + +void DummyOutputDev::beginStringOp(GfxState *state) +{ + rgbdev->beginStringOp(state); +} +void DummyOutputDev::endStringOp(GfxState *state) +{ + rgbdev->endStringOp(state); +} +void DummyOutputDev::beginString(GfxState *state, GString *s) +{ + rgbdev->beginString(state, s); +} +void DummyOutputDev::endString(GfxState *state) +{ + rgbdev->endString(state); +} +void DummyOutputDev::drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, Unicode *u, int uLen) +{ + rgbdev->drawChar(state, x, y, dx, dy, originX, originY, code, nBytes, u, uLen); +} +void DummyOutputDev::drawString(GfxState *state, GString *s) +{ + rgbdev->drawString(state, s); +} +void DummyOutputDev::endTextObject(GfxState *state) +{ + rgbdev->endTextObject(state); +} +GBool DummyOutputDev::beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen) +{ + return rgbdev->beginType3Char(state, x, y, dx, dy, code, u, uLen); +} +void DummyOutputDev::type3D0(GfxState *state, double wx, double wy) +{ + rgbdev->type3D0(state, wx, wy); +} +void DummyOutputDev::type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury) +{ + rgbdev->type3D1(state, wx, wy, llx, lly, urx, ury); +} +void DummyOutputDev::endType3Char(GfxState *state) +{ + rgbdev->endType3Char(state); +} +void DummyOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg) +{ + rgbdev->drawImageMask(state, ref, str, width, height, invert, inlineImg); +} +void DummyOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg) +{ + rgbdev->drawImage(state, ref, str, width, height, colorMap, maskColors, inlineImg); +} +void DummyOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, int maskWidth, int maskHeight, + GBool maskInvert) +{ + rgbdev->drawMaskedImage(state, ref, str, width, height, colorMap, maskStr, maskWidth, maskHeight, maskInvert); +} +void DummyOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap) +{ + rgbdev->drawSoftMaskedImage(state, ref, str, width, height, colorMap, maskStr, maskWidth, maskHeight, maskColorMap); +} +void DummyOutputDev::drawForm(Ref id) +{ + rgbdev->drawForm(id); +} + +void DummyOutputDev::processLink(Link *link, Catalog *catalog) +{ +} + +void DummyOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask) +{ + rgbdev->beginTransparencyGroup(state, bbox, blendingColorSpace, isolated, knockout, forSoftMask); +} +void DummyOutputDev::endTransparencyGroup(GfxState *state) +{ + rgbdev->endTransparencyGroup(state); +} +void DummyOutputDev::paintTransparencyGroup(GfxState *state, double *bbox) +{ + rgbdev->paintTransparencyGroup(state,bbox); +} +void DummyOutputDev::setSoftMask(GfxState *state, double *bbox, GBool alpha, Function *transferFunc, GfxColor *backdropColor) +{ + rgbdev->setSoftMask(state, bbox, alpha, transferFunc, backdropColor); +} +void DummyOutputDev::clearSoftMask(GfxState *state) +{ + rgbdev->clearSoftMask(state); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/DummyOutputDev.h swftools-0.9.1/lib/pdf/DummyOutputDev.h --- swftools-0.9.2+ds1/lib/pdf/DummyOutputDev.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/DummyOutputDev.h 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,170 @@ +/* DummyOutputDev.cc + Output Device which serves as "passthrough" + This file is part of swftools. + + Copyright (c) 2007 Matthias Kramm + + Swftools 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. + + Swftools 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 swftools; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef __DummyOutputDev_h__ +#define __DummyOutputDev_h__ + +#include "../gfxdevice.h" +#include "../gfxsource.h" +#include "../gfxtools.h" + +#include "config.h" +#include "GFXOutputDev.h" +#include "InfoOutputDev.h" +#include "PDFDoc.h" +#include "CommonOutputDev.h" +#include "SplashOutputDev.h" + +class DummyOutputDev: public OutputDev { +public: + DummyOutputDev(OutputDev*target); + virtual ~DummyOutputDev(); + + // OutputDev: + virtual GBool upsideDown(); + virtual GBool useDrawChar(); + virtual GBool useTilingPatternFill(); + virtual GBool useShadedFills(); + virtual GBool useDrawForm(); + virtual GBool interpretType3Chars(); + virtual GBool needNonText(); + virtual void setDefaultCTM(double *ctm); +/* virtual GBool checkPageSlice(Page *page, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool printing, Catalog *catalog, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL);*/ + + virtual void startPage(int pageNum, GfxState *state); + virtual void endPage(); + + virtual void saveState(GfxState *state); + virtual void restoreState(GfxState *state); + + virtual void updateAll(GfxState *state); + virtual void updateCTM(GfxState *state, double m11, double m12, double m21, double m22, double m31, double m32); + virtual void updateLineDash(GfxState *state); + virtual void updateFlatness(GfxState *state); + virtual void updateLineJoin(GfxState *state); + virtual void updateLineCap(GfxState *state); + virtual void updateMiterLimit(GfxState *state); + virtual void updateLineWidth(GfxState *state); + virtual void updateStrokeAdjust(GfxState *state); + virtual void updateFillColorSpace(GfxState *state); + virtual void updateStrokeColorSpace(GfxState *state); + virtual void updateFillColor(GfxState *state); + virtual void updateStrokeColor(GfxState *state); + virtual void updateBlendMode(GfxState *state); + virtual void updateFillOpacity(GfxState *state); + virtual void updateStrokeOpacity(GfxState *state); + virtual void updateFillOverprint(GfxState *state); + virtual void updateStrokeOverprint(GfxState *state); + virtual void updateTransfer(GfxState *state); + virtual void updateFont(GfxState *state); + virtual void updateTextMat(GfxState *state); + virtual void updateCharSpace(GfxState *state); + virtual void updateRender(GfxState *state); + virtual void updateRise(GfxState *state); + virtual void updateWordSpace(GfxState *state); + virtual void updateHorizScaling(GfxState *state); + virtual void updateTextPos(GfxState *state); + virtual void updateTextShift(GfxState *state, double shift); + + virtual void stroke(GfxState *state); + virtual void fill(GfxState *state); + virtual void eoFill(GfxState *state); +#if (xpdfMajorVersion < 3) || (xpdfMinorVersion < 2) || (xpdfUpdateVersion < 7) + virtual void tilingPatternFill(GfxState *state, Object *str, + int paintType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep); +#else + virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *str, + int paintType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep); +#endif + + virtual GBool functionShadedFill(GfxState *state, + GfxFunctionShading *shading); + virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading); + virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading); + + virtual void clip(GfxState *state); + virtual void eoClip(GfxState *state); + virtual void clipToStrokePath(GfxState *state); + + virtual void beginStringOp(GfxState *state); + virtual void endStringOp(GfxState *state); + virtual void beginString(GfxState *state, GString *s); + virtual void endString(GfxState *state); + virtual void drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, Unicode *u, int uLen); + virtual void drawString(GfxState *state, GString *s); + virtual GBool beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen); + virtual void endType3Char(GfxState *state); + virtual void endTextObject(GfxState *state); + + virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, int maskWidth, int maskHeight, + GBool maskInvert); + virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap); + + virtual void type3D0(GfxState *state, double wx, double wy); + virtual void type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury); + + virtual void drawForm(Ref id); + + virtual void beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask); + virtual void endTransparencyGroup(GfxState *state); + virtual void paintTransparencyGroup(GfxState *state, double *bbox); + virtual void setSoftMask(GfxState *state, double *bbox, GBool alpha, Function *transferFunc, GfxColor *backdropColor); + virtual void clearSoftMask(GfxState *state); + + virtual void processLink(Link *link, Catalog *catalog); + + OutputDev*rgbdev; +private: +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/inject-xpdf.pl swftools-0.9.1/lib/pdf/inject-xpdf.pl --- swftools-0.9.2+ds1/lib/pdf/inject-xpdf.pl 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/inject-xpdf.pl 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,73 @@ +#!/usr/bin/perl + +$filename = $ARGV[0]; + +$filename or die "no filename"; + +$basename = $filename; +$basename =~ s/.tar.gz$//g; +$directory = $basename; + +mkdir("$directory"); +mkdir("$directory/tmp/"); + +chdir("$directory/tmp/") or die; + +sub cleanup_and_die +{ + system("rm -f xpdf"); + system("rm -f $directory"); +} + +print "Extracting $filename\n"; +system("tar -zxf ../../$filename") and die; +system("find . -type f -exec mv {} .. \\;") and cleanup_and_die; +chdir(".."); +system("find . -type d -exec rmdir {} \\; 2> /dev/null"); + +print "Applying security patches...\n"; +for($a=1;$a<10;$a++) { + $patchname = "../${basename}pl$a.patch"; + if(-f $patchname) { + print "*pl$a.patch\n"; + system("patch -s < $patchname") and cleanup_and_die; + } +} + +$c = 'find . \( -name "*.cc" -or -name "*.h" -or -name "*.c" \) -exec cp {} {}.orig \;'; +print "$c\n"; +system($c); + +system("patch < ../xpdf-changes.patch 2>&1 | grep -i failed"); +chdir(".."); +system("rm -f xpdf"); +system("ln -s $directory xpdf"); + +system("touch xpdf/*"); + +open(fi, ">switch"); + +print fi <> xpdf-changes.patch;done + diff -Nru swftools-0.9.2+ds1/lib/pdf/pdf.cc swftools-0.9.1/lib/pdf/pdf.cc --- swftools-0.9.2+ds1/lib/pdf/pdf.cc 2011-01-02 03:30:29.000000000 +0000 +++ swftools-0.9.1/lib/pdf/pdf.cc 2012-06-20 15:37:24.000000000 +0000 @@ -107,8 +107,8 @@ pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; gfxsource_internal_t*i = (gfxsource_internal_t*)pi->parent->internal; - if(!pi->config_print && pi->nocopy) {msg(" PDF disallows copying");exit(0);} - if(pi->config_print && pi->noprint) {msg(" PDF disallows printing");exit(0);} + //if(!pi->config_print && pi->nocopy) {msg(" PDF disallows copying");exit(0);} + //if(pi->config_print && pi->noprint) {msg(" PDF disallows printing");exit(0);} CommonOutputDev*outputDev = 0; if(pi->config_full_bitmap_optimizing) { diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/about-text.h swftools-0.9.1/lib/pdf/xpdf/about-text.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/about-text.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/about-text.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,48 @@ +//======================================================================== +// +// about-text.h +// +// Copyright 2002-2007 Glyph & Cog, LLC +// +//======================================================================== + +static char *aboutWinText[] = { + "http://www.foolabs.com/xpdf/", + "derekn@foolabs.com", + " ", + "Licensed under the GNU General Public License (GPL).", + "See the 'COPYING' file for details.", + " ", + "Supports PDF version " supportedPDFVersionStr ".", + " ", + "The PDF data structures, operators, and specification", + "are copyright 1985-2006 Adobe Systems Inc.", + " ", + "Mouse bindings:", + " button 1: select text / follow link", + " button 2: pan window", + " button 3: menu", + " ", + "Key bindings:", + " o = open file", + " r = reload", + " f / ctrl-F = find text", + " ctrl-G = find next", + " ctrl-P = print", + " n = next page", + " p = previous page", + " = = scroll down", + " = = = scroll up", + " v = forward (history path)", + " b = backward (history path)", + " 0 / + / - = zoom zero / in / out", + " z / w = zoom page / page width", + " alt-F = toggle full-screen mode", + " ctrl-L = redraw", + " q = quit", + " / = top / bottom of page", + " = scroll", + " ", + "For more information, please read the xpdf(1) man page.", + NULL +}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/about.xbm swftools-0.9.1/lib/pdf/xpdf/about.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/about.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/about.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define about_width 10 +#define about_height 15 +static unsigned char about_bits[] = { + 0x78, 0x00, 0xfc, 0x00, 0xce, 0x01, 0x86, 0x01, 0x80, 0x01, 0x80, 0x01, + 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x30, 0x00}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/aclocal.m4 swftools-0.9.1/lib/pdf/xpdf/aclocal.m4 --- swftools-0.9.2+ds1/lib/pdf/xpdf/aclocal.m4 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/aclocal.m4 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,274 @@ +# <<< smr.m4 from smr_macros 0.2.4 >>> + +dnl ####################### -*- Mode: M4 -*- ########################### +dnl smr.m4 -- +dnl +dnl Copyright (C) 1999 Matthew D. Langston +dnl Copyright (C) 1998 Steve Robbins +dnl +dnl This file is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This file is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this file; if not, write to: +dnl +dnl Free Software Foundation, Inc. +dnl Suite 330 +dnl 59 Temple Place +dnl Boston, MA 02111-1307, USA. +dnl #################################################################### + + +dnl NOTE: The macros in this file are extensively documented in the +dnl accompanying `smr_macros.texi' Texinfo file. Please see the +dnl Texinfo documentation for the definitive specification of how +dnl these macros are supposed to work. If the macros work +dnl differently than the Texinfo documentation says they should, +dnl then the macros (and not the Texinfo documentation) has the +dnl bug(s). + +dnl This is a convenient macro which translates illegal characters for +dnl bourne shell variables into legal characters. It has the same +dnl functionality as sed 'y%./+-:%__p__%'. +AC_DEFUN([smr_safe_translation], [patsubst(patsubst([$1], [+], [p]), [./-:], [_])]) + +AC_DEFUN(smr_SWITCH, +[ + dnl Define convenient aliases for the arguments since there are so + dnl many of them and I keep confusing myself whenever I have to edit + dnl this macro. + pushdef([smr_name], $1) + pushdef([smr_help_string], $2) + pushdef([smr_default], $3) + pushdef([smr_yes_define], $4) + pushdef([smr_no_define], $5) + + dnl Do some sanity checking of the arguments. + ifelse([regexp(smr_default, [^\(yes\|no\)$])], -1, [AC_MSG_ERROR($0: third arg must be either yes or no)]) + + dnl Create the help string + pushdef([smr_lhs], [--ifelse(smr_default, yes, disable, enable)-smr_name])dnl + pushdef([smr_rhs], [ifelse(smr_default, yes, disable, enable) smr_help_string (default is smr_default)])dnl + + dnl Add the option to `configure --help'. We don't need to supply the + dnl 4th argument to AC_ARG_ENABLE (i.e. the code to set the default + dnl value) because that is done below by AC_CACHE_CHECK. + AC_ARG_ENABLE([smr_name], + AC_HELP_STRING([smr_lhs], [smr_rhs]), + smr_cv_enable_[]smr_name=$enableval) + + dnl We cache the result so that the user doesn't have to remember + dnl which flags they passed to `configure'. + AC_CACHE_CHECK([whether to enable smr_help_string], + smr_cv_enable_[]smr_name, + smr_cv_enable_[]smr_name=smr_default) + + ifelse(smr_yes_define, , , test x"[$]smr_cv_enable_[]smr_name" = xyes && AC_DEFINE(smr_yes_define)) + ifelse(smr_no_define, , , test x"[$]smr_cv_enable_[]smr_name" = xno && AC_DEFINE(smr_no_define)) + + dnl Sanity check the value assigned to smr_cv_enable_$1 to force it to + dnl be either `yes' or `no'. + if test ! x"[$]smr_cv_enable_[]smr_name" = xyes; then + if test ! x"[$]smr_cv_enable_[]smr_name" = xno; then + AC_MSG_ERROR([smr_lhs must be either yes or no]) + fi + fi + + popdef([smr_name]) + popdef([smr_help_string]) + popdef([smr_default]) + popdef([smr_yes_define]) + popdef([smr_no_define]) + popdef([smr_lhs]) + popdef([smr_rhs]) +]) + + +AC_DEFUN(smr_ARG_WITHLIB, +[ + dnl Define convenient aliases for the arguments since there are so + dnl many of them and I keep confusing myself whenever I have to edit + dnl this macro. + pushdef([smr_name], $1) + pushdef([smr_libname], ifelse($2, , smr_name, $2)) + pushdef([smr_help_string], $3) + pushdef([smr_safe_name], smr_safe_translation(smr_name)) + + dnl Add the option to `configure --help'. We don't need to supply the + dnl 4th argument to AC_ARG_WITH (i.e. the code to set the default + dnl value) because that is done below by AC_CACHE_CHECK. + AC_ARG_WITH(smr_safe_name-library, + AC_HELP_STRING([--with-smr_safe_name-library[[=PATH]]], + [use smr_name library ifelse(smr_help_string, , , (smr_help_string))]), + smr_cv_with_[]smr_safe_name[]_library=$withval) + + dnl We cache the result so that the user doesn't have to remember + dnl which flags they passed to `configure'. + AC_CACHE_CHECK([whether to use smr_name library], + smr_cv_with_[]smr_safe_name[]_library, + smr_cv_with_[]smr_safe_name[]_library=maybe) + + + case x"[$]smr_cv_with_[]smr_safe_name[]_library" in + xyes | xmaybe) + smr_safe_name[]_LIBS="-l[]smr_libname" + with_[]smr_safe_name=[$]smr_cv_with_[]smr_safe_name[]_library + ;; + xno) + smr_safe_name[]_LIBS= + with_[]smr_safe_name=no + ;; + *) + if test -f "[$]smr_cv_with_[]smr_safe_name[]_library"; then + smr_safe_name[]_LIBS=[$]smr_cv_with_[]smr_safe_name[]_library + elif test -d "[$]smr_cv_with_[]smr_safe_name[]_library"; then + smr_safe_name[]_LIBS="-L[$]smr_cv_with_[]smr_safe_name[]_library -l[]smr_libname" + else + AC_MSG_ERROR([argument must be boolean, file, or directory]) + fi + with_[]smr_safe_name=yes + ;; + esac + + popdef([smr_name]) + popdef([smr_libname]) + popdef([smr_help_string]) + popdef([smr_safe_name]) +]) + + +AC_DEFUN(smr_ARG_WITHINCLUDES, +[ + dnl Define convenient aliases for the arguments since there are so + dnl many of them and I keep confusing myself whenever I have to edit + dnl this macro. + pushdef([smr_name], $1) + pushdef([smr_header], $2) + pushdef([smr_extra_flags], $3) + pushdef([smr_safe_name], smr_safe_translation(smr_name)) + + dnl Add the option to `configure --help'. We don't need to supply the + dnl 4th argument to AC_ARG_WITH (i.e. the code to set the default + dnl value) because that is done below by AC_CACHE_CHECK. + AC_ARG_WITH(smr_safe_name-includes, + AC_HELP_STRING([--with-smr_safe_name-includes[[=DIR]]], + [set directory for smr_name headers]), + smr_cv_with_[]smr_safe_name[]_includes=$withval) + + dnl We cache the result so that the user doesn't have to remember + dnl which flags they passed to `configure'. + AC_CACHE_CHECK([where to find the smr_name header files], + smr_cv_with_[]smr_safe_name[]_includes, + smr_cv_with_[]smr_safe_name[]_includes=) + + if test ! x"[$]smr_cv_with_[]smr_safe_name[]_includes" = x; then + if test -d "[$]smr_cv_with_[]smr_safe_name[]_includes"; then + smr_safe_name[]_CFLAGS="-I[$]smr_cv_with_[]smr_safe_name[]_includes" + else + AC_MSG_ERROR([argument must be a directory]) + fi + else + smr_safe_name[]_CFLAGS= + fi + + dnl This bit of logic comes from the autoconf AC_PROG_CC macro. We + dnl need to put the given include directory into CPPFLAGS temporarily, + dnl but then restore CPPFLAGS to its old value. + smr_test_CPPFLAGS="${CPPFLAGS+set}" + smr_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS [$]smr_safe_name[]_CFLAGS smr_extra_flags" + + dnl If the header file smr_header exists, then define + dnl HAVE_[]smr_header (in all capitals). + AC_CHECK_HEADERS([smr_header], + smr_have_[]smr_safe_name[]_header=yes, + smr_have_[]smr_safe_name[]_header=no) + + if test x"$smr_test_CPPFLAGS" = xset; then + CPPFLAGS=$smr_save_CPPFLAGS + else + unset CPPFLAGS + fi + + popdef([smr_name]) + popdef([smr_header]) + popdef([smr_extra_flags]) + popdef([smr_safe_name]) +]) + + +AC_DEFUN(smr_CHECK_LIB, +[ + dnl Define convenient aliases for the arguments since there are so + dnl many of them and I keep confusing myself whenever I have to edit + dnl this macro. + pushdef([smr_name], $1) + pushdef([smr_libname], ifelse($2, , smr_name, $2)) + pushdef([smr_help_string], $3) + pushdef([smr_function], $4) + pushdef([smr_header], $5) + pushdef([smr_extra_libs], $6) + pushdef([smr_extra_flags], $7) + pushdef([smr_prototype], $8) + pushdef([smr_safe_name], smr_safe_translation(smr_name)) + + dnl Give the user (via "configure --help") an interface to specify + dnl whether we should use the library or not, and possibly where we + dnl should find it. + smr_ARG_WITHLIB([smr_name], [smr_libname], [smr_help_string]) + + if test ! x"$with_[]smr_safe_name" = xno; then + + # If we got this far, then the user didn't explicitly ask not to use + # the library. + + dnl If the caller of smr_CHECK_LIB specified a header file for this + dnl library, then give the user (via "configure --help") an + dnl interface to specify where this header file can be found (if it + dnl isn't found by the compiler by default). + ifelse(smr_header, , , [smr_ARG_WITHINCLUDES(smr_name, smr_header, smr_extra_flags)]) + + # We need only look for the library if the header has been found + # (or no header is needed). + if test [$]smr_have_[]smr_safe_name[]_header != no; then + + AC_CHECK_LIB(smr_libname, + smr_function, + smr_have_[]smr_safe_name[]_library=yes, + smr_have_[]smr_safe_name[]_library=no, + [$]smr_safe_name[]_CFLAGS [smr_extra_flags] [$]smr_safe_name[]_LIBS [smr_extra_libs], + [ifelse(smr_prototype, , , [[#]include ])], + smr_prototype) + fi + + if test x"[$]smr_have_[]smr_safe_name[]_library" = xyes; then + AC_MSG_RESULT([using smr_name library]) + else + smr_safe_name[]_LIBS= + smr_safe_name[]_CFLAGS= + + if test x"$with_[]smr_safe_name" = xmaybe; then + AC_MSG_RESULT([not using smr_name library]) + else + AC_MSG_WARN([requested smr_name library not found!]) + fi + fi + fi + + popdef([smr_name]) + popdef([smr_libname]) + popdef([smr_help_string]) + popdef([smr_function]) + popdef([smr_header]) + popdef([smr_extra_libs]) + popdef([smr_extra_flags]) + popdef([smr_prototype]) + popdef([smr_safe_name]) +]) diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/aconf2.h swftools-0.9.1/lib/pdf/xpdf/aconf2.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/aconf2.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/aconf2.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * aconf2.h + * + * This gets included by aconf.h, and contains miscellaneous global + * settings not directly controlled by autoconf. This is a separate + * file because otherwise the configure script will munge any + * #define/#undef constructs. + * + * Copyright 2002-2003 Glyph & Cog, LLC + */ + +#ifndef ACONF2_H +#define ACONF2_H + +/* + * This controls the use of the interface/implementation pragmas. + */ +#ifdef __GNUC__ +#define USE_GCC_PRAGMAS +#endif +/* There is a bug in the version of gcc which ships with MacOS X 10.2 */ +#if defined(__APPLE__) && defined(__MACH__) +# include +#endif +#ifdef MAC_OS_X_VERSION_MAX_ALLOWED +# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_2 +# undef USE_GCC_PRAGMAS +# endif +#endif + +/* + * Make sure WIN32 is defined if appropriate. + */ +#if defined(_WIN32) && !defined(WIN32) +# define WIN32 +#endif + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/aconf-dj.h swftools-0.9.1/lib/pdf/xpdf/aconf-dj.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/aconf-dj.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/aconf-dj.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * aconf-dj.h + * + * Copyright 2002-2003 Glyph & Cog, LLC + */ + +#ifndef ACONF_H +#define ACONF_H + +/* + * Use A4 paper size instead of Letter for PostScript output. + */ +#undef A4_PAPER + +/* + * Do not allow text selection. + */ +#undef NO_TEXT_SELECT + +/* + * Include support for OPI comments. + */ +#undef OPI_SUPPORT + +/* + * Directory with the Xpdf app-defaults file. + */ +#undef APPDEFDIR + +/* + * Full path for the system-wide xpdfrc file. + */ +#undef SYSTEM_XPDFRC + +/* + * Various include files and functions. + */ +#define HAVE_DIRENT_H 1 +#undef HAVE_SYS_NDIR_H +#undef HAVE_SYS_DIR_H +#undef HAVE_NDIR_H +#undef HAVE_SYS_SELECT_H +#undef HAVE_SYS_BSDTYPES_H +#undef HAVE_STRINGS_H +#undef HAVE_BSTRING_H +#define HAVE_POPEN 1 +#undef HAVE_MKSTEMP +#undef SELECT_TAKES_INT +#undef HAVE_FSEEK64 + +/* + * This is defined if using libXpm. + */ +#undef HAVE_X11_XPM_H + +/* + * This is defined if using t1lib. + */ +#undef HAVE_T1LIB_H + +/* + * One of these is defined if using FreeType (version 1 or 2). + */ +#undef HAVE_FREETYPE_H +#undef HAVE_FREETYPE_FREETYPE_H + +/* + * This is defined if using FreeType version 2. + */ +#undef FREETYPE2 + +/* + * This is defined if using libpaper. + */ +#undef HAVE_PAPER_H + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/aconf.h.in swftools-0.9.1/lib/pdf/xpdf/aconf.h.in --- swftools-0.9.2+ds1/lib/pdf/xpdf/aconf.h.in 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/aconf.h.in 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,115 @@ +/* + * aconf.h + * + * Copyright 2002-2003 Glyph & Cog, LLC + */ + +#ifndef ACONF_H +#define ACONF_H + +#include + +/* + * Use A4 paper size instead of Letter for PostScript output. + */ +#undef A4_PAPER + +/* + * Do not allow text selection. + */ +#undef NO_TEXT_SELECT + +/* + * Include support for OPI comments. + */ +#undef OPI_SUPPORT + +/* + * Enable multithreading support. + */ +#undef MULTITHREADED + +/* + * Enable C++ exceptions. + */ +#undef USE_EXCEPTIONS + +/* + * Enable word list support. + */ +#undef TEXTOUT_WORD_LIST + +/* + * Use fixed point (instead of floating point) arithmetic. + */ +#undef USE_FIXEDPOINT + +/* + * Directory with the Xpdf app-defaults file. + */ +#undef APPDEFDIR + +/* + * Full path for the system-wide xpdfrc file. + */ +#undef SYSTEM_XPDFRC + +/* + * Various include files and functions. + */ +#undef HAVE_DIRENT_H +#undef HAVE_SYS_NDIR_H +#undef HAVE_SYS_DIR_H +#undef HAVE_NDIR_H +#undef HAVE_SYS_SELECT_H +#undef HAVE_SYS_BSDTYPES_H +#undef HAVE_STRINGS_H +#undef HAVE_BSTRING_H +#undef HAVE_POPEN +#undef HAVE_MKSTEMP +#undef HAVE_MKSTEMPS +#undef SELECT_TAKES_INT +#undef HAVE_FSEEKO +#undef HAVE_FSEEK64 +#undef _FILE_OFFSET_BITS +#undef _LARGE_FILES +#undef _LARGEFILE_SOURCE +#undef HAVE_XTAPPSETEXITFLAG + +/* + * This is defined if using libXpm. + */ +#undef HAVE_X11_XPM_H + +/* + * This is defined if using t1lib. + */ +#undef HAVE_T1LIB_H + +/* + * One of these is defined if using FreeType 2. + */ +#undef HAVE_FREETYPE_H +#undef HAVE_FREETYPE_FREETYPE_H + +/* + * This is defined if using libpaper. + */ +#undef HAVE_PAPER_H + +/* + * Enable support for loading plugins. + */ +#undef ENABLE_PLUGINS + +/* + * Defined if the Splash library is avaiable. + */ +#undef HAVE_SPLASH + +/* + * Enable support for CMYK output. + */ +#undef SPLASH_CMYK + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/aconf-win32.h swftools-0.9.1/lib/pdf/xpdf/aconf-win32.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/aconf-win32.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/aconf-win32.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * aconf-win32.h + * + * Copyright 2002-2003 Glyph & Cog, LLC + */ + +#ifndef ACONF_H +#define ACONF_H + +#include + +/* + * Use A4 paper size instead of Letter for PostScript output. + */ +#undef A4_PAPER + +/* + * Do not allow text selection. + */ +#undef NO_TEXT_SELECT + +/* + * Include support for OPI comments. + */ +#undef OPI_SUPPORT + +/* + * Enable multithreading support. + */ +#define MULTITHREADED 1 + +/* + * Enable C++ exceptions. + */ +#define USE_EXCEPTIONS 1 + +/* + * Enable word list support. + */ +#undef TEXTOUT_WORD_LIST + +/* + * Use fixed point (instead of floating point) arithmetic. + */ +#undef USE_FIXEDPOINT + +/* + * Directory with the Xpdf app-defaults file. + */ +#undef APPDEFDIR + +/* + * Full path for the system-wide xpdfrc file. + */ +#undef SYSTEM_XPDFRC + +/* + * Various include files and functions. + */ +#undef HAVE_DIRENT_H +#undef HAVE_SYS_NDIR_H +#undef HAVE_SYS_DIR_H +#undef HAVE_NDIR_H +#undef HAVE_SYS_SELECT_H +#undef HAVE_SYS_BSDTYPES_H +#undef HAVE_STRINGS_H +#undef HAVE_BSTRING_H +#undef HAVE_POPEN +#undef HAVE_MKSTEMP +#undef HAVE_MKSTEMPS +#undef SELECT_TAKES_INT +#undef HAVE_FSEEKO +#undef HAVE_FSEEK64 +#undef _FILE_OFFSET_BITS +#undef _LARGE_FILES +#undef _LARGEFILE_SOURCE +#undef HAVE_XTAPPSETEXITFLAG + +/* + * This is defined if using libXpm. + */ +#undef HAVE_X11_XPM_H + +/* + * This is defined if using t1lib. + */ +#undef HAVE_T1LIB_H + +/* + * One of these is defined if using FreeType (version 1 or 2). + */ +#undef HAVE_FREETYPE_H +#define HAVE_FREETYPE_FREETYPE_H 1 + +/* + * This is defined if using FreeType version 2. + */ +#define FREETYPE2 + +/* + * This is defined if using libpaper. + */ +#undef HAVE_PAPER_H + +/* + * Enable support for loading plugins. + */ +#undef ENABLE_PLUGINS + +/* + * Defined if the Splash library is avaiable. + */ +#undef HAVE_SPLASH + +/* + * Enable support for CMYK output. + */ +#undef SPLASH_CMYK + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Annot.cc swftools-0.9.1/lib/pdf/xpdf/Annot.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Annot.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Annot.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,1556 @@ +//======================================================================== +// +// Annot.cc +// +// Copyright 2000-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "GList.h" +#include "Error.h" +#include "Object.h" +#include "Catalog.h" +#include "Gfx.h" +#include "GfxFont.h" +#include "Lexer.h" +#include "Annot.h" + +//------------------------------------------------------------------------ + +#define annotFlagHidden 0x0002 +#define annotFlagPrint 0x0004 +#define annotFlagNoView 0x0020 + +#define fieldFlagReadOnly 0x00000001 +#define fieldFlagRequired 0x00000002 +#define fieldFlagNoExport 0x00000004 +#define fieldFlagMultiline 0x00001000 +#define fieldFlagPassword 0x00002000 +#define fieldFlagNoToggleToOff 0x00004000 +#define fieldFlagRadio 0x00008000 +#define fieldFlagPushbutton 0x00010000 +#define fieldFlagCombo 0x00020000 +#define fieldFlagEdit 0x00040000 +#define fieldFlagSort 0x00080000 +#define fieldFlagFileSelect 0x00100000 +#define fieldFlagMultiSelect 0x00200000 +#define fieldFlagDoNotSpellCheck 0x00400000 +#define fieldFlagDoNotScroll 0x00800000 +#define fieldFlagComb 0x01000000 +#define fieldFlagRichText 0x02000000 +#define fieldFlagRadiosInUnison 0x02000000 +#define fieldFlagCommitOnSelChange 0x04000000 + +#define fieldQuadLeft 0 +#define fieldQuadCenter 1 +#define fieldQuadRight 2 + +// distance of Bezier control point from center for circle approximation +// = (4 * (sqrt(2) - 1) / 3) * r +#define bezierCircle 0.55228475 + +//------------------------------------------------------------------------ +// AnnotBorderStyle +//------------------------------------------------------------------------ + +AnnotBorderStyle::AnnotBorderStyle(AnnotBorderType typeA, double widthA, + double *dashA, int dashLengthA, + double rA, double gA, double bA) { + type = typeA; + width = widthA; + dash = dashA; + dashLength = dashLengthA; + r = rA; + g = gA; + b = bA; +} + +AnnotBorderStyle::~AnnotBorderStyle() { + if (dash) { + gfree(dash); + } +} + +//------------------------------------------------------------------------ +// Annot +//------------------------------------------------------------------------ + +Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Ref *refA) { + Object apObj, asObj, obj1, obj2, obj3; + AnnotBorderType borderType; + double borderWidth; + double *borderDash; + int borderDashLength; + double borderR, borderG, borderB; + double t; + int i; + + ok = gTrue; + xref = xrefA; + ref = *refA; + type = NULL; + appearBuf = NULL; + borderStyle = NULL; + + //----- parse the type + + if (dict->lookup("Subtype", &obj1)->isName()) { + type = new GString(obj1.getName()); + } + obj1.free(); + + //----- parse the rectangle + + if (dict->lookup("Rect", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + xMin = yMin = xMax = yMax = 0; + if (obj1.arrayGet(0, &obj2)->isNum()) { + xMin = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(1, &obj2)->isNum()) { + yMin = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(2, &obj2)->isNum()) { + xMax = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGet(3, &obj2)->isNum()) { + yMax = obj2.getNum(); + } + obj2.free(); + if (xMin > xMax) { + t = xMin; xMin = xMax; xMax = t; + } + if (yMin > yMax) { + t = yMin; yMin = yMax; yMax = t; + } + } else { + error(-1, "Bad bounding box for annotation"); + ok = gFalse; + } + obj1.free(); + + //----- parse the flags + + if (dict->lookup("F", &obj1)->isInt()) { + flags = obj1.getInt(); + } else { + flags = 0; + } + obj1.free(); + + //----- parse the border style + + borderType = annotBorderSolid; + borderWidth = 1; + borderDash = NULL; + borderDashLength = 0; + borderR = 0; + borderG = 0; + borderB = 1; + if (dict->lookup("BS", &obj1)->isDict()) { + if (obj1.dictLookup("S", &obj2)->isName()) { + if (obj2.isName("S")) { + borderType = annotBorderSolid; + } else if (obj2.isName("D")) { + borderType = annotBorderDashed; + } else if (obj2.isName("B")) { + borderType = annotBorderBeveled; + } else if (obj2.isName("I")) { + borderType = annotBorderInset; + } else if (obj2.isName("U")) { + borderType = annotBorderUnderlined; + } + } + obj2.free(); + if (obj1.dictLookup("W", &obj2)->isNum()) { + borderWidth = obj2.getNum(); + } + obj2.free(); + if (obj1.dictLookup("D", &obj2)->isArray()) { + borderDashLength = obj2.arrayGetLength(); + borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); + for (i = 0; i < borderDashLength; ++i) { + if (obj2.arrayGet(i, &obj3)->isNum()) { + borderDash[i] = obj3.getNum(); + } else { + borderDash[i] = 1; + } + obj3.free(); + } + } + obj2.free(); + } else { + obj1.free(); + if (dict->lookup("Border", &obj1)->isArray()) { + if (obj1.arrayGetLength() >= 3) { + if (obj1.arrayGet(2, &obj2)->isNum()) { + borderWidth = obj2.getNum(); + } + obj2.free(); + if (obj1.arrayGetLength() >= 4) { + if (obj1.arrayGet(3, &obj2)->isArray()) { + borderType = annotBorderDashed; + borderDashLength = obj2.arrayGetLength(); + borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); + for (i = 0; i < borderDashLength; ++i) { + if (obj2.arrayGet(i, &obj3)->isNum()) { + borderDash[i] = obj3.getNum(); + } else { + borderDash[i] = 1; + } + obj3.free(); + } + } else { + // Adobe draws no border at all if the last element is of + // the wrong type. + borderWidth = 0; + } + obj2.free(); + } + } + } + } + obj1.free(); + if (dict->lookup("C", &obj1)->isArray() && obj1.arrayGetLength() == 3) { + if (obj1.arrayGet(0, &obj2)->isNum()) { + borderR = obj2.getNum(); + } + obj1.free(); + if (obj1.arrayGet(1, &obj2)->isNum()) { + borderG = obj2.getNum(); + } + obj1.free(); + if (obj1.arrayGet(2, &obj2)->isNum()) { + borderB = obj2.getNum(); + } + obj1.free(); + } + obj1.free(); + borderStyle = new AnnotBorderStyle(borderType, borderWidth, + borderDash, borderDashLength, + borderR, borderG, borderB); + + //----- get the annotation appearance + + if (dict->lookup("AP", &apObj)->isDict()) { + if (dict->lookup("AS", &asObj)->isName()) { + if (apObj.dictLookup("N", &obj1)->isDict()) { + if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) { + obj2.copy(&appearance); + ok = gTrue; + } else { + obj2.free(); + if (obj1.dictLookupNF("Off", &obj2)->isRef()) { + obj2.copy(&appearance); + } + } + obj2.free(); + } + obj1.free(); + } else { + if (apObj.dictLookupNF("N", &obj1)->isRef()) { + obj1.copy(&appearance); + } + obj1.free(); + } + asObj.free(); + } + apObj.free(); +} + +Annot::~Annot() { + if (type) { + delete type; + } + appearance.free(); + if (appearBuf) { + delete appearBuf; + } + if (borderStyle) { + delete borderStyle; + } +} + +void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) { + Object mkObj, ftObj, appearDict, drObj, obj1, obj2, obj3; + Dict *mkDict; + MemStream *appearStream; + GfxFontDict *fontDict; + GBool hasCaption; + double w, dx, dy, r; + double *dash; + GString *caption, *da; + GString **text; + GBool *selection; + int dashLength, ff, quadding, comb, nOptions, topIdx, i, j; + + // must be a Widget annotation + if (type->cmp("Widget")) { + return; + } + + appearBuf = new GString(); + + // get the appearance characteristics (MK) dictionary + if (annot->lookup("MK", &mkObj)->isDict()) { + mkDict = mkObj.getDict(); + } else { + mkDict = NULL; + } + + // draw the background + if (mkDict) { + if (mkDict->lookup("BG", &obj1)->isArray() && + obj1.arrayGetLength() > 0) { + setColor(obj1.getArray(), gTrue, 0); + appearBuf->appendf("0 0 {0:.2f} {1:.2f} re f\n", + xMax - xMin, yMax - yMin); + } + obj1.free(); + } + + // get the field type + fieldLookup(field, "FT", &ftObj); + + // get the field flags (Ff) value + if (fieldLookup(field, "Ff", &obj1)->isInt()) { + ff = obj1.getInt(); + } else { + ff = 0; + } + obj1.free(); + + // draw the border + if (mkDict) { + w = borderStyle->getWidth(); + if (w > 0) { + mkDict->lookup("BC", &obj1); + if (!(obj1.isArray() && obj1.arrayGetLength() > 0)) { + mkDict->lookup("BG", &obj1); + } + if (obj1.isArray() && obj1.arrayGetLength() > 0) { + dx = xMax - xMin; + dy = yMax - yMin; + + // radio buttons with no caption have a round border + hasCaption = mkDict->lookup("CA", &obj2)->isString(); + obj2.free(); + if (ftObj.isName("Btn") && (ff & fieldFlagRadio) && !hasCaption) { + r = 0.5 * (dx < dy ? dx : dy); + switch (borderStyle->getType()) { + case annotBorderDashed: + appearBuf->append("["); + borderStyle->getDash(&dash, &dashLength); + for (i = 0; i < dashLength; ++i) { + appearBuf->appendf(" {0:.2f}", dash[i]); + } + appearBuf->append("] 0 d\n"); + // fall through to the solid case + case annotBorderSolid: + case annotBorderUnderlined: + appearBuf->appendf("{0:.2f} w\n", w); + setColor(obj1.getArray(), gFalse, 0); + drawCircle(0.5 * dx, 0.5 * dy, r - 0.5 * w, gFalse); + break; + case annotBorderBeveled: + case annotBorderInset: + appearBuf->appendf("{0:.2f} w\n", 0.5 * w); + setColor(obj1.getArray(), gFalse, 0); + drawCircle(0.5 * dx, 0.5 * dy, r - 0.25 * w, gFalse); + setColor(obj1.getArray(), gFalse, + borderStyle->getType() == annotBorderBeveled ? 1 : -1); + drawCircleTopLeft(0.5 * dx, 0.5 * dy, r - 0.75 * w); + setColor(obj1.getArray(), gFalse, + borderStyle->getType() == annotBorderBeveled ? -1 : 1); + drawCircleBottomRight(0.5 * dx, 0.5 * dy, r - 0.75 * w); + break; + } + + } else { + switch (borderStyle->getType()) { + case annotBorderDashed: + appearBuf->append("["); + borderStyle->getDash(&dash, &dashLength); + for (i = 0; i < dashLength; ++i) { + appearBuf->appendf(" {0:.2f}", dash[i]); + } + appearBuf->append("] 0 d\n"); + // fall through to the solid case + case annotBorderSolid: + appearBuf->appendf("{0:.2f} w\n", w); + setColor(obj1.getArray(), gFalse, 0); + appearBuf->appendf("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re s\n", + 0.5 * w, dx - w, dy - w); + break; + case annotBorderBeveled: + case annotBorderInset: + setColor(obj1.getArray(), gTrue, + borderStyle->getType() == annotBorderBeveled ? 1 : -1); + appearBuf->append("0 0 m\n"); + appearBuf->appendf("0 {0:.2f} l\n", dy); + appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy); + appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, dy - w); + appearBuf->appendf("{0:.2f} {1:.2f} l\n", w, dy - w); + appearBuf->appendf("{0:.2f} {0:.2f} l\n", w); + appearBuf->append("f\n"); + setColor(obj1.getArray(), gTrue, + borderStyle->getType() == annotBorderBeveled ? -1 : 1); + appearBuf->append("0 0 m\n"); + appearBuf->appendf("{0:.2f} 0 l\n", dx); + appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy); + appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, dy - w); + appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, w); + appearBuf->appendf("{0:.2f} {0:.2f} l\n", w); + appearBuf->append("f\n"); + break; + case annotBorderUnderlined: + appearBuf->appendf("{0:.2f} w\n", w); + setColor(obj1.getArray(), gFalse, 0); + appearBuf->appendf("0 0 m {0:.2f} 0 l s\n", dx); + break; + } + + // clip to the inside of the border + appearBuf->appendf("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re W n\n", + w, dx - 2 * w, dy - 2 * w); + } + } + obj1.free(); + } + } + + // get the resource dictionary + acroForm->lookup("DR", &drObj); + + // build the font dictionary + if (drObj.isDict() && drObj.dictLookup("Font", &obj1)->isDict()) { + fontDict = new GfxFontDict(xref, NULL, obj1.getDict()); + } else { + fontDict = NULL; + } + obj1.free(); + + // get the default appearance string + if (fieldLookup(field, "DA", &obj1)->isNull()) { + obj1.free(); + acroForm->lookup("DA", &obj1); + } + if (obj1.isString()) { + da = obj1.getString()->copy(); + } else { + da = NULL; + } + obj1.free(); + + // draw the field contents + if (ftObj.isName("Btn")) { + caption = NULL; + if (mkDict) { + if (mkDict->lookup("CA", &obj1)->isString()) { + caption = obj1.getString()->copy(); + } + obj1.free(); + } + // radio button + if (ff & fieldFlagRadio) { + //~ Acrobat doesn't draw a caption if there is no AP dict (?) + if (fieldLookup(field, "V", &obj1)->isName()) { + if (annot->lookup("AS", &obj2)->isName(obj1.getName())) { + if (caption) { + drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter, + gFalse, gTrue); + } else { + if (mkDict) { + if (mkDict->lookup("BC", &obj3)->isArray() && + obj3.arrayGetLength() > 0) { + dx = xMax - xMin; + dy = yMax - yMin; + setColor(obj3.getArray(), gTrue, 0); + drawCircle(0.5 * dx, 0.5 * dy, 0.2 * (dx < dy ? dx : dy), + gTrue); + } + obj3.free(); + } + } + } + obj2.free(); + } + obj1.free(); + // pushbutton + } else if (ff & fieldFlagPushbutton) { + if (caption) { + drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter, + gFalse, gFalse); + } + // checkbox + } else { + // According to the PDF spec the off state must be named "Off", + // and the on state can be named anything, but Acrobat apparently + // looks for "Yes" and treats anything else as off. + if (fieldLookup(field, "V", &obj1)->isName("Yes")) { + if (!caption) { + caption = new GString("3"); // ZapfDingbats checkmark + } + drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter, + gFalse, gTrue); + } + obj1.free(); + } + if (caption) { + delete caption; + } + } else if (ftObj.isName("Tx")) { + //~ value strings can be Unicode + if (fieldLookup(field, "V", &obj1)->isString()) { + if (fieldLookup(field, "Q", &obj2)->isInt()) { + quadding = obj2.getInt(); + } else { + quadding = fieldQuadLeft; + } + obj2.free(); + comb = 0; + if (ff & fieldFlagComb) { + if (fieldLookup(field, "MaxLen", &obj2)->isInt()) { + comb = obj2.getInt(); + } + obj2.free(); + } + drawText(obj1.getString(), da, fontDict, + ff & fieldFlagMultiline, comb, quadding, gTrue, gFalse); + } + obj1.free(); + } else if (ftObj.isName("Ch")) { + //~ value/option strings can be Unicode + if (fieldLookup(field, "Q", &obj1)->isInt()) { + quadding = obj1.getInt(); + } else { + quadding = fieldQuadLeft; + } + obj1.free(); + // combo box + if (ff & fieldFlagCombo) { + if (fieldLookup(field, "V", &obj1)->isString()) { + drawText(obj1.getString(), da, fontDict, + gFalse, 0, quadding, gTrue, gFalse); + //~ Acrobat draws a popup icon on the right side + } + obj1.free(); + // list box + } else { + if (field->lookup("Opt", &obj1)->isArray()) { + nOptions = obj1.arrayGetLength(); + // get the option text + text = (GString **)gmallocn(nOptions, sizeof(GString *)); + for (i = 0; i < nOptions; ++i) { + text[i] = NULL; + obj1.arrayGet(i, &obj2); + if (obj2.isString()) { + text[i] = obj2.getString()->copy(); + } else if (obj2.isArray() && obj2.arrayGetLength() == 2) { + if (obj2.arrayGet(1, &obj3)->isString()) { + text[i] = obj3.getString()->copy(); + } + obj3.free(); + } + obj2.free(); + if (!text[i]) { + text[i] = new GString(); + } + } + // get the selected option(s) + selection = (GBool *)gmallocn(nOptions, sizeof(GBool)); + //~ need to use the I field in addition to the V field + fieldLookup(field, "V", &obj2); + for (i = 0; i < nOptions; ++i) { + selection[i] = gFalse; + if (obj2.isString()) { + if (!obj2.getString()->cmp(text[i])) { + selection[i] = gTrue; + } + } else if (obj2.isArray()) { + for (j = 0; j < obj2.arrayGetLength(); ++j) { + if (obj2.arrayGet(j, &obj3)->isString() && + !obj3.getString()->cmp(text[i])) { + selection[i] = gTrue; + } + obj3.free(); + } + } + } + obj2.free(); + // get the top index + if (field->lookup("TI", &obj2)->isInt()) { + topIdx = obj2.getInt(); + } else { + topIdx = 0; + } + obj2.free(); + // draw the text + drawListBox(text, selection, nOptions, topIdx, da, fontDict, quadding); + for (i = 0; i < nOptions; ++i) { + delete text[i]; + } + gfree(text); + gfree(selection); + } + obj1.free(); + } + } else if (ftObj.isName("Sig")) { + //~unimp + } else { + error(-1, "Unknown field type"); + } + + if (da) { + delete da; + } + + // build the appearance stream dictionary + appearDict.initDict(xref); + appearDict.dictAdd(copyString("Length"), + obj1.initInt(appearBuf->getLength())); + appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); + obj1.initArray(xref); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(0)); + obj1.arrayAdd(obj2.initReal(xMax - xMin)); + obj1.arrayAdd(obj2.initReal(yMax - yMin)); + appearDict.dictAdd(copyString("BBox"), &obj1); + + // set the resource dictionary + if (drObj.isDict()) { + appearDict.dictAdd(copyString("Resources"), drObj.copy(&obj1)); + } + drObj.free(); + + // build the appearance stream + appearStream = new MemStream(appearBuf->getCString(), 0, + appearBuf->getLength(), &appearDict); + appearance.free(); + appearance.initStream(appearStream); + + if (fontDict) { + delete fontDict; + } + ftObj.free(); + mkObj.free(); +} + +// Set the current fill or stroke color, based on (which should +// have 1, 3, or 4 elements). If is +1, color is brightened; +// if is -1, color is darkened; otherwise color is not +// modified. +void Annot::setColor(Array *a, GBool fill, int adjust) { + Object obj1; + double color[4]; + int nComps, i; + + nComps = a->getLength(); + if (nComps > 4) { + nComps = 4; + } + for (i = 0; i < nComps && i < 4; ++i) { + if (a->get(i, &obj1)->isNum()) { + color[i] = obj1.getNum(); + } else { + color[i] = 0; + } + obj1.free(); + } + if (nComps == 4) { + adjust = -adjust; + } + if (adjust > 0) { + for (i = 0; i < nComps; ++i) { + color[i] = 0.5 * color[i] + 0.5; + } + } else if (adjust < 0) { + for (i = 0; i < nComps; ++i) { + color[i] = 0.5 * color[i]; + } + } + if (nComps == 4) { + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:c}\n", + color[0], color[1], color[2], color[3], + fill ? 'k' : 'K'); + } else if (nComps == 3) { + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:s}\n", + color[0], color[1], color[2], + fill ? "rg" : "RG"); + } else { + appearBuf->appendf("{0:.2f} {1:c}\n", + color[0], + fill ? 'g' : 'G'); + } +} + +// Draw the variable text or caption for a field. +void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict, + GBool multiline, int comb, int quadding, + GBool txField, GBool forceZapfDingbats) { + GList *daToks; + GString *tok; + GfxFont *font; + double fontSize, fontSize2, border, x, xPrev, y, w, w2, wMax; + int tfPos, tmPos, i, j, k, c; + + //~ if there is no MK entry, this should use the existing content stream, + //~ and only replace the marked content portion of it + //~ (this is only relevant for Tx fields) + + // parse the default appearance string + tfPos = tmPos = -1; + if (da) { + daToks = new GList(); + i = 0; + while (i < da->getLength()) { + while (i < da->getLength() && Lexer::isSpace(da->getChar(i))) { + ++i; + } + if (i < da->getLength()) { + for (j = i + 1; + j < da->getLength() && !Lexer::isSpace(da->getChar(j)); + ++j) ; + daToks->append(new GString(da, i, j - i)); + i = j; + } + } + for (i = 2; i < daToks->getLength(); ++i) { + if (i >= 2 && !((GString *)daToks->get(i))->cmp("Tf")) { + tfPos = i - 2; + } else if (i >= 6 && !((GString *)daToks->get(i))->cmp("Tm")) { + tmPos = i - 6; + } + } + } else { + daToks = NULL; + } + + // force ZapfDingbats + //~ this should create the font if needed (?) + if (forceZapfDingbats) { + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos); + if (tok->cmp("/ZaDb")) { + tok->clear(); + tok->append("/ZaDb"); + } + } + } + + // get the font and font size + font = NULL; + fontSize = 0; + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos); + if (tok->getLength() >= 1 && tok->getChar(0) == '/') { + if (!fontDict || !(font = fontDict->lookup(tok->getCString() + 1))) { + error(-1, "Unknown font in field's DA string"); + } + } else { + error(-1, "Invalid font name in 'Tf' operator in field's DA string"); + } + tok = (GString *)daToks->get(tfPos + 1); + fontSize = atof(tok->getCString()); + } else { + error(-1, "Missing 'Tf' operator in field's DA string"); + } + + // get the border width + border = borderStyle->getWidth(); + + // setup + if (txField) { + appearBuf->append("/Tx BMC\n"); + } + appearBuf->append("q\n"); + appearBuf->append("BT\n"); + + // multi-line text + if (multiline) { + // note: the comb flag is ignored in multiline mode + + wMax = xMax - xMin - 2 * border - 4; + + // compute font autosize + if (fontSize == 0) { + for (fontSize = 20; fontSize > 1; --fontSize) { + y = yMax - yMin; + w2 = 0; + i = 0; + while (i < text->getLength()) { + getNextLine(text, i, font, fontSize, wMax, &j, &w, &k); + if (w > w2) { + w2 = w; + } + i = k; + y -= fontSize; + } + // approximate the descender for the last line + if (y >= 0.33 * fontSize) { + break; + } + } + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos + 1); + tok->clear(); + tok->appendf("{0:.2f}", fontSize); + } + } + + // starting y coordinate + // (note: each line of text starts with a Td operator that moves + // down a line) + y = yMax - yMin; + + // set the font matrix + if (tmPos >= 0) { + tok = (GString *)daToks->get(tmPos + 4); + tok->clear(); + tok->append('0'); + tok = (GString *)daToks->get(tmPos + 5); + tok->clear(); + tok->appendf("{0:.2f}", y); + } + + // write the DA string + if (daToks) { + for (i = 0; i < daToks->getLength(); ++i) { + appearBuf->append((GString *)daToks->get(i))->append(' '); + } + } + + // write the font matrix (if not part of the DA string) + if (tmPos < 0) { + appearBuf->appendf("1 0 0 1 0 {0:.2f} Tm\n", y); + } + + // write a series of lines of text + i = 0; + xPrev = 0; + while (i < text->getLength()) { + + getNextLine(text, i, font, fontSize, wMax, &j, &w, &k); + + // compute text start position + switch (quadding) { + case fieldQuadLeft: + default: + x = border + 2; + break; + case fieldQuadCenter: + x = (xMax - xMin - w) / 2; + break; + case fieldQuadRight: + x = xMax - xMin - border - 2 - w; + break; + } + + // draw the line + appearBuf->appendf("{0:.2f} {1:.2f} Td\n", x - xPrev, -fontSize); + appearBuf->append('('); + for (; i < j; ++i) { + c = text->getChar(i) & 0xff; + if (c == '(' || c == ')' || c == '\\') { + appearBuf->append('\\'); + appearBuf->append(c); + } else if (c < 0x20 || c >= 0x80) { + appearBuf->appendf("\\{0:03o}", c); + } else { + appearBuf->append(c); + } + } + appearBuf->append(") Tj\n"); + + // next line + i = k; + xPrev = x; + } + + // single-line text + } else { + //~ replace newlines with spaces? - what does Acrobat do? + + // comb formatting + if (comb > 0) { + + // compute comb spacing + w = (xMax - xMin - 2 * border) / comb; + + // compute font autosize + if (fontSize == 0) { + fontSize = yMax - yMin - 2 * border; + if (w < fontSize) { + fontSize = w; + } + fontSize = floor(fontSize); + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos + 1); + tok->clear(); + tok->appendf("{0:.2f}", fontSize); + } + } + + // compute text start position + switch (quadding) { + case fieldQuadLeft: + default: + x = border + 2; + break; + case fieldQuadCenter: + x = border + 2 + 0.5 * (comb - text->getLength()) * w; + break; + case fieldQuadRight: + x = border + 2 + (comb - text->getLength()) * w; + break; + } + y = 0.5 * (yMax - yMin) - 0.4 * fontSize; + + // set the font matrix + if (tmPos >= 0) { + tok = (GString *)daToks->get(tmPos + 4); + tok->clear(); + tok->appendf("{0:.2f}", x); + tok = (GString *)daToks->get(tmPos + 5); + tok->clear(); + tok->appendf("{0:.2f}", y); + } + + // write the DA string + if (daToks) { + for (i = 0; i < daToks->getLength(); ++i) { + appearBuf->append((GString *)daToks->get(i))->append(' '); + } + } + + // write the font matrix (if not part of the DA string) + if (tmPos < 0) { + appearBuf->appendf("1 0 0 1 {0:.2f} {1:.2f} Tm\n", x, y); + } + + // write the text string + //~ this should center (instead of left-justify) each character within + //~ its comb cell + for (i = 0; i < text->getLength(); ++i) { + if (i > 0) { + appearBuf->appendf("{0:.2f} 0 Td\n", w); + } + appearBuf->append('('); + c = text->getChar(i) & 0xff; + if (c == '(' || c == ')' || c == '\\') { + appearBuf->append('\\'); + appearBuf->append(c); + } else if (c < 0x20 || c >= 0x80) { + appearBuf->appendf("{0:.2f} 0 Td\n", w); + } else { + appearBuf->append(c); + } + appearBuf->append(") Tj\n"); + } + + // regular (non-comb) formatting + } else { + + // compute string width + if (font && !font->isCIDFont()) { + w = 0; + for (i = 0; i < text->getLength(); ++i) { + w += ((Gfx8BitFont *)font)->getWidth(text->getChar(i)); + } + } else { + // otherwise, make a crude estimate + w = text->getLength() * 0.5; + } + + // compute font autosize + if (fontSize == 0) { + fontSize = yMax - yMin - 2 * border; + fontSize2 = (xMax - xMin - 4 - 2 * border) / w; + if (fontSize2 < fontSize) { + fontSize = fontSize2; + } + fontSize = floor(fontSize); + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos + 1); + tok->clear(); + tok->appendf("{0:.2f}", fontSize); + } + } + + // compute text start position + w *= fontSize; + switch (quadding) { + case fieldQuadLeft: + default: + x = border + 2; + break; + case fieldQuadCenter: + x = (xMax - xMin - w) / 2; + break; + case fieldQuadRight: + x = xMax - xMin - border - 2 - w; + break; + } + y = 0.5 * (yMax - yMin) - 0.4 * fontSize; + + // set the font matrix + if (tmPos >= 0) { + tok = (GString *)daToks->get(tmPos + 4); + tok->clear(); + tok->appendf("{0:.2f}", x); + tok = (GString *)daToks->get(tmPos + 5); + tok->clear(); + tok->appendf("{0:.2f}", y); + } + + // write the DA string + if (daToks) { + for (i = 0; i < daToks->getLength(); ++i) { + appearBuf->append((GString *)daToks->get(i))->append(' '); + } + } + + // write the font matrix (if not part of the DA string) + if (tmPos < 0) { + appearBuf->appendf("1 0 0 1 {0:.2f} {1:.2f} Tm\n", x, y); + } + + // write the text string + appearBuf->append('('); + for (i = 0; i < text->getLength(); ++i) { + c = text->getChar(i) & 0xff; + if (c == '(' || c == ')' || c == '\\') { + appearBuf->append('\\'); + appearBuf->append(c); + } else if (c < 0x20 || c >= 0x80) { + appearBuf->appendf("\\{0:03o}", c); + } else { + appearBuf->append(c); + } + } + appearBuf->append(") Tj\n"); + } + } + + // cleanup + appearBuf->append("ET\n"); + appearBuf->append("Q\n"); + if (txField) { + appearBuf->append("EMC\n"); + } + + if (daToks) { + deleteGList(daToks, GString); + } +} + +// Draw the variable text or caption for a field. +void Annot::drawListBox(GString **text, GBool *selection, + int nOptions, int topIdx, + GString *da, GfxFontDict *fontDict, GBool quadding) { + GList *daToks; + GString *tok; + GfxFont *font; + double fontSize, fontSize2, border, x, y, w, wMax; + int tfPos, tmPos, i, j, c; + + //~ if there is no MK entry, this should use the existing content stream, + //~ and only replace the marked content portion of it + //~ (this is only relevant for Tx fields) + + // parse the default appearance string + tfPos = tmPos = -1; + if (da) { + daToks = new GList(); + i = 0; + while (i < da->getLength()) { + while (i < da->getLength() && Lexer::isSpace(da->getChar(i))) { + ++i; + } + if (i < da->getLength()) { + for (j = i + 1; + j < da->getLength() && !Lexer::isSpace(da->getChar(j)); + ++j) ; + daToks->append(new GString(da, i, j - i)); + i = j; + } + } + for (i = 2; i < daToks->getLength(); ++i) { + if (i >= 2 && !((GString *)daToks->get(i))->cmp("Tf")) { + tfPos = i - 2; + } else if (i >= 6 && !((GString *)daToks->get(i))->cmp("Tm")) { + tmPos = i - 6; + } + } + } else { + daToks = NULL; + } + + // get the font and font size + font = NULL; + fontSize = 0; + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos); + if (tok->getLength() >= 1 && tok->getChar(0) == '/') { + if (!fontDict || !(font = fontDict->lookup(tok->getCString() + 1))) { + error(-1, "Unknown font in field's DA string"); + } + } else { + error(-1, "Invalid font name in 'Tf' operator in field's DA string"); + } + tok = (GString *)daToks->get(tfPos + 1); + fontSize = atof(tok->getCString()); + } else { + error(-1, "Missing 'Tf' operator in field's DA string"); + } + + // get the border width + border = borderStyle->getWidth(); + + // compute font autosize + if (fontSize == 0) { + wMax = 0; + for (i = 0; i < nOptions; ++i) { + if (font && !font->isCIDFont()) { + w = 0; + for (j = 0; j < text[i]->getLength(); ++j) { + w += ((Gfx8BitFont *)font)->getWidth(text[i]->getChar(j)); + } + } else { + // otherwise, make a crude estimate + w = text[i]->getLength() * 0.5; + } + if (w > wMax) { + wMax = w; + } + } + fontSize = yMax - yMin - 2 * border; + fontSize2 = (xMax - xMin - 4 - 2 * border) / wMax; + if (fontSize2 < fontSize) { + fontSize = fontSize2; + } + fontSize = floor(fontSize); + if (tfPos >= 0) { + tok = (GString *)daToks->get(tfPos + 1); + tok->clear(); + tok->appendf("{0:.2f}", fontSize); + } + } + + // draw the text + y = yMax - yMin - 1.1 * fontSize; + for (i = topIdx; i < nOptions; ++i) { + + // setup + appearBuf->append("q\n"); + + // draw the background if selected + if (selection[i]) { + appearBuf->append("0 g f\n"); + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} re f\n", + border, + y - 0.2 * fontSize, + xMax - xMin - 2 * border, + 1.1 * fontSize); + } + + // setup + appearBuf->append("BT\n"); + + // compute string width + if (font && !font->isCIDFont()) { + w = 0; + for (j = 0; j < text[i]->getLength(); ++j) { + w += ((Gfx8BitFont *)font)->getWidth(text[i]->getChar(j)); + } + } else { + // otherwise, make a crude estimate + w = text[i]->getLength() * 0.5; + } + + // compute text start position + w *= fontSize; + switch (quadding) { + case fieldQuadLeft: + default: + x = border + 2; + break; + case fieldQuadCenter: + x = (xMax - xMin - w) / 2; + break; + case fieldQuadRight: + x = xMax - xMin - border - 2 - w; + break; + } + + // set the font matrix + if (tmPos >= 0) { + tok = (GString *)daToks->get(tmPos + 4); + tok->clear(); + tok->appendf("{0:.2f}", x); + tok = (GString *)daToks->get(tmPos + 5); + tok->clear(); + tok->appendf("{0:.2f}", y); + } + + // write the DA string + if (daToks) { + for (j = 0; j < daToks->getLength(); ++j) { + appearBuf->append((GString *)daToks->get(j))->append(' '); + } + } + + // write the font matrix (if not part of the DA string) + if (tmPos < 0) { + appearBuf->appendf("1 0 0 1 {0:.2f} {1:.2f} Tm\n", x, y); + } + + // change the text color if selected + if (selection[i]) { + appearBuf->append("1 g\n"); + } + + // write the text string + appearBuf->append('('); + for (j = 0; j < text[i]->getLength(); ++j) { + c = text[i]->getChar(j) & 0xff; + if (c == '(' || c == ')' || c == '\\') { + appearBuf->append('\\'); + appearBuf->append(c); + } else if (c < 0x20 || c >= 0x80) { + appearBuf->appendf("\\{0:03o}", c); + } else { + appearBuf->append(c); + } + } + appearBuf->append(") Tj\n"); + + // cleanup + appearBuf->append("ET\n"); + appearBuf->append("Q\n"); + + // next line + y -= 1.1 * fontSize; + } + + if (daToks) { + deleteGList(daToks, GString); + } +} + +// Figure out how much text will fit on the next line. Returns: +// *end = one past the last character to be included +// *width = width of the characters start .. end-1 +// *next = index of first character on the following line +void Annot::getNextLine(GString *text, int start, + GfxFont *font, double fontSize, double wMax, + int *end, double *width, int *next) { + double w, dw; + int j, k, c; + + // figure out how much text will fit on the line + //~ what does Adobe do with tabs? + w = 0; + for (j = start; j < text->getLength() && w <= wMax; ++j) { + c = text->getChar(j) & 0xff; + if (c == 0x0a || c == 0x0d) { + break; + } + if (font && !font->isCIDFont()) { + dw = ((Gfx8BitFont *)font)->getWidth(c) * fontSize; + } else { + // otherwise, make a crude estimate + dw = 0.5 * fontSize; + } + w += dw; + } + if (w > wMax) { + for (k = j; k > start && text->getChar(k-1) != ' '; --k) ; + for (; k > start && text->getChar(k-1) == ' '; --k) ; + if (k > start) { + j = k; + } + if (j == start) { + // handle the pathological case where the first character is + // too wide to fit on the line all by itself + j = start + 1; + } + } + *end = j; + + // compute the width + w = 0; + for (k = start; k < j; ++k) { + if (font && !font->isCIDFont()) { + dw = ((Gfx8BitFont *)font)->getWidth(text->getChar(k)) * fontSize; + } else { + // otherwise, make a crude estimate + dw = 0.5 * fontSize; + } + w += dw; + } + *width = w; + + // next line + while (j < text->getLength() && text->getChar(j) == ' ') { + ++j; + } + if (j < text->getLength() && text->getChar(j) == 0x0d) { + ++j; + } + if (j < text->getLength() && text->getChar(j) == 0x0a) { + ++j; + } + *next = j; +} + +// Draw an (approximate) circle of radius centered at (, ). +// If is true, the circle is filled; otherwise it is stroked. +void Annot::drawCircle(double cx, double cy, double r, GBool fill) { + appearBuf->appendf("{0:.2f} {1:.2f} m\n", + cx + r, cy); + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + cx + r, cy + bezierCircle * r, + cx + bezierCircle * r, cy + r, + cx, cy + r); + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + cx - bezierCircle * r, cy + r, + cx - r, cy + bezierCircle * r, + cx - r, cy); + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + cx - r, cy - bezierCircle * r, + cx - bezierCircle * r, cy - r, + cx, cy - r); + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + cx + bezierCircle * r, cy - r, + cx + r, cy - bezierCircle * r, + cx + r, cy); + appearBuf->append(fill ? "f\n" : "s\n"); +} + +// Draw the top-left half of an (approximate) circle of radius +// centered at (, ). +void Annot::drawCircleTopLeft(double cx, double cy, double r) { + double r2; + + r2 = r / sqrt(2.0); + appearBuf->appendf("{0:.2f} {1:.2f} m\n", + cx + r2, cy + r2); + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + cx + (1 - bezierCircle) * r2, + cy + (1 + bezierCircle) * r2, + cx - (1 - bezierCircle) * r2, + cy + (1 + bezierCircle) * r2, + cx - r2, + cy + r2); + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + cx - (1 + bezierCircle) * r2, + cy + (1 - bezierCircle) * r2, + cx - (1 + bezierCircle) * r2, + cy - (1 - bezierCircle) * r2, + cx - r2, + cy - r2); + appearBuf->append("S\n"); +} + +// Draw the bottom-right half of an (approximate) circle of radius +// centered at (, ). +void Annot::drawCircleBottomRight(double cx, double cy, double r) { + double r2; + + r2 = r / sqrt(2.0); + appearBuf->appendf("{0:.2f} {1:.2f} m\n", + cx - r2, cy - r2); + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + cx - (1 - bezierCircle) * r2, + cy - (1 + bezierCircle) * r2, + cx + (1 - bezierCircle) * r2, + cy - (1 + bezierCircle) * r2, + cx + r2, + cy - r2); + appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + cx + (1 + bezierCircle) * r2, + cy - (1 - bezierCircle) * r2, + cx + (1 + bezierCircle) * r2, + cy + (1 - bezierCircle) * r2, + cx + r2, + cy + r2); + appearBuf->append("S\n"); +} + +// Look up an inheritable field dictionary entry. +Object *Annot::fieldLookup(Dict *field, char *key, Object *obj) { + Dict *dict; + Object parent; + + dict = field; + if (!dict->lookup(key, obj)->isNull()) { + return obj; + } + obj->free(); + if (dict->lookup("Parent", &parent)->isDict()) { + fieldLookup(parent.getDict(), key, obj); + } else { + obj->initNull(); + } + parent.free(); + return obj; +} + +void Annot::draw(Gfx *gfx, GBool printing) { + Object obj; + GBool isLink; + + // check the flags + if ((flags & annotFlagHidden) || + (printing && !(flags & annotFlagPrint)) || + (!printing && (flags & annotFlagNoView))) { + return; + } + + // draw the appearance stream + isLink = type && !type->cmp("Link"); + appearance.fetch(xref, &obj); + gfx->drawAnnot(&obj, isLink ? borderStyle : (AnnotBorderStyle *)NULL, + xMin, yMin, xMax, yMax); + obj.free(); +} + +//------------------------------------------------------------------------ +// Annots +//------------------------------------------------------------------------ + +Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) { + Dict *acroForm; + Annot *annot; + Object obj1; + Ref ref; + int size; + int i; + + annots = NULL; + size = 0; + nAnnots = 0; + + acroForm = catalog->getAcroForm()->isDict() ? + catalog->getAcroForm()->getDict() : NULL; + if (annotsObj->isArray()) { + for (i = 0; i < annotsObj->arrayGetLength(); ++i) { + if (annotsObj->arrayGetNF(i, &obj1)->isRef()) { + ref = obj1.getRef(); + obj1.free(); + annotsObj->arrayGet(i, &obj1); + } else { + ref.num = ref.gen = -1; + } + if (obj1.isDict()) { + annot = new Annot(xref, acroForm, obj1.getDict(), &ref); + if (annot->isOk()) { + if (nAnnots >= size) { + size += 16; + annots = (Annot **)greallocn(annots, size, sizeof(Annot *)); + } + annots[nAnnots++] = annot; + } else { + delete annot; + } + } + obj1.free(); + } + } +} + +Annots::~Annots() { + int i; + + for (i = 0; i < nAnnots; ++i) { + delete annots[i]; + } + gfree(annots); +} + +void Annots::generateAppearances(Dict *acroForm) { + Object obj1, obj2; + Ref ref; + int i; + + if (acroForm->lookup("Fields", &obj1)->isArray()) { + for (i = 0; i < obj1.arrayGetLength(); ++i) { + if (obj1.arrayGetNF(i, &obj2)->isRef()) { + ref = obj2.getRef(); + obj2.free(); + obj1.arrayGet(i, &obj2); + } else { + ref.num = ref.gen = -1; + } + if (obj2.isDict()) { + scanFieldAppearances(obj2.getDict(), &ref, NULL, acroForm); + } + obj2.free(); + } + } + obj1.free(); +} + +void Annots::scanFieldAppearances(Dict *node, Ref *ref, Dict *parent, + Dict *acroForm) { + Annot *annot; + Object obj1, obj2; + Ref ref2; + int i; + + // non-terminal node: scan the children + if (node->lookup("Kids", &obj1)->isArray()) { + for (i = 0; i < obj1.arrayGetLength(); ++i) { + if (obj1.arrayGetNF(i, &obj2)->isRef()) { + ref2 = obj2.getRef(); + obj2.free(); + obj1.arrayGet(i, &obj2); + } else { + ref2.num = ref2.gen = -1; + } + if (obj2.isDict()) { + scanFieldAppearances(obj2.getDict(), &ref2, node, acroForm); + } + obj2.free(); + } + obj1.free(); + return; + } + obj1.free(); + + // terminal node: this is either a combined annot/field dict, or an + // annot dict whose parent is a field + if ((annot = findAnnot(ref))) { + node->lookupNF("Parent", &obj1); + if (!parent || !obj1.isNull()) { + annot->generateFieldAppearance(node, node, acroForm); + } else { + annot->generateFieldAppearance(parent, node, acroForm); + } + obj1.free(); + } +} + +Annot *Annots::findAnnot(Ref *ref) { + int i; + + for (i = 0; i < nAnnots; ++i) { + if (annots[i]->match(ref)) { + return annots[i]; + } + } + return NULL; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Annot.h swftools-0.9.1/lib/pdf/xpdf/Annot.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Annot.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Annot.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,142 @@ +//======================================================================== +// +// Annot.h +// +// Copyright 2000-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef ANNOT_H +#define ANNOT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +class XRef; +class Catalog; +class Gfx; +class GfxFontDict; + +//------------------------------------------------------------------------ +// AnnotBorderStyle +//------------------------------------------------------------------------ + +enum AnnotBorderType { + annotBorderSolid, + annotBorderDashed, + annotBorderBeveled, + annotBorderInset, + annotBorderUnderlined +}; + +class AnnotBorderStyle { +public: + + AnnotBorderStyle(AnnotBorderType typeA, double widthA, + double *dashA, int dashLengthA, + double rA, double gA, double bA); + ~AnnotBorderStyle(); + + AnnotBorderType getType() { return type; } + double getWidth() { return width; } + void getDash(double **dashA, int *dashLengthA) + { *dashA = dash; *dashLengthA = dashLength; } + void getColor(double *rA, double *gA, double *bA) + { *rA = r; *gA = g; *bA = b; } + +private: + + AnnotBorderType type; + double width; + double *dash; + int dashLength; + double r, g, b; +}; + +//------------------------------------------------------------------------ +// Annot +//------------------------------------------------------------------------ + +class Annot { +public: + + Annot(XRef *xrefA, Dict *acroForm, Dict *dict, Ref *refA); + ~Annot(); + GBool isOk() { return ok; } + + void draw(Gfx *gfx, GBool printing); + + // Get appearance object. + Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); } + + AnnotBorderStyle *getBorderStyle() { return borderStyle; } + + GBool match(Ref *refA) + { return ref.num == refA->num && ref.gen == refA->gen; } + + void generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm); + +private: + + void setColor(Array *a, GBool fill, int adjust); + void drawText(GString *text, GString *da, GfxFontDict *fontDict, + GBool multiline, int comb, int quadding, + GBool txField, GBool forceZapfDingbats); + void drawListBox(GString **text, GBool *selection, + int nOptions, int topIdx, + GString *da, GfxFontDict *fontDict, GBool quadding); + void getNextLine(GString *text, int start, + GfxFont *font, double fontSize, double wMax, + int *end, double *width, int *next); + void drawCircle(double cx, double cy, double r, GBool fill); + void drawCircleTopLeft(double cx, double cy, double r); + void drawCircleBottomRight(double cx, double cy, double r); + Object *fieldLookup(Dict *field, char *key, Object *obj); + + XRef *xref; // the xref table for this PDF file + Ref ref; // object ref identifying this annotation + GString *type; // annotation type + Object appearance; // a reference to the Form XObject stream + // for the normal appearance + GString *appearBuf; + double xMin, yMin, // annotation rectangle + xMax, yMax; + Guint flags; + AnnotBorderStyle *borderStyle; + GBool ok; +}; + +//------------------------------------------------------------------------ +// Annots +//------------------------------------------------------------------------ + +class Annots { +public: + + // Build a list of Annot objects. + Annots(XRef *xref, Catalog *catalog, Object *annotsObj); + + ~Annots(); + + // Iterate through list of annotations. + int getNumAnnots() { return nAnnots; } + Annot *getAnnot(int i) { return annots[i]; } + + // (Re)generate the appearance streams for all annotations belonging + // to a form field. + void generateAppearances(Dict *acroForm); + +private: + + void scanFieldAppearances(Dict *node, Ref *ref, Dict *parent, + Dict *acroForm); + Annot *findAnnot(Ref *ref); + + Annot **annots; + int nAnnots; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/ANNOUNCE swftools-0.9.1/lib/pdf/xpdf/ANNOUNCE --- swftools-0.9.2+ds1/lib/pdf/xpdf/ANNOUNCE 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/ANNOUNCE 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,34 @@ +Subject: ANNOUNCE: Xpdf 3.02 - a PDF viewer for X + + +Glyph & Cog, LLC is pleased to announce a new version of Xpdf, the +open source Portable Document Format (PDF) viewer for X. The Xpdf +project also includes a PDF text extractor, PDF-to-PostScript +converter, and various other utilities. + +Xpdf runs under the X Window System on Unix, VMS, and OS/2. The non-X +components (pdftops, pdftotext, etc.) also run on Win32 systems and +should run on pretty much any system with a decent C++ compiler. + +Major changes: +* Anti-aliased vector graphics, including stroke adjustment. +* Support for PDF 1.6 and PDF 1.7, including AES decryption and + OpenType fonts. +* User-configurable key/mouse bindings. +* Improved full-screen mode, with the ability to toggle on the fly. + +See the `CHANGES' file for a complete list of changes. + +Source (C++ and C) is available, and it should be fairly easy to +compile for UNIX, VMS, OS/2, and Win32. + +More information, source code, and precompiled binaries are on the +xpdf web page and ftp site: + + http://www.foolabs.com/xpdf/ + ftp://ftp.foolabs.com/pub/xpdf/ + +For information on commercial licensing and consulting, please see the +Glyph & Cog web site: + + http://www.glyphandcog.com/ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Array.cc swftools-0.9.1/lib/pdf/xpdf/Array.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Array.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Array.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,73 @@ +//======================================================================== +// +// Array.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "Object.h" +#include "Array.h" + +//------------------------------------------------------------------------ +// Array +//------------------------------------------------------------------------ + +Array::Array(XRef *xrefA) { + xref = xrefA; + elems = NULL; + size = length = 0; + ref = 1; +} + +Array::~Array() { + int i; + + for (i = 0; i < length; ++i) + elems[i].free(); + gfree(elems); +} + +void Array::add(Object *elem) { + if (length == size) { + if (length == 0) { + size = 8; + } else { + size *= 2; + } + elems = (Object *)greallocn(elems, size, sizeof(Object)); + } + elems[length] = *elem; + ++length; +} + +Object *Array::get(int i, Object *obj) { + if (i < 0 || i >= length) { +#ifdef DEBUG_MEM + abort(); +#else + return obj->initNull(); +#endif + } + return elems[i].fetch(xref, obj); +} + +Object *Array::getNF(int i, Object *obj) { + if (i < 0 || i >= length) { +#ifdef DEBUG_MEM + abort(); +#else + return obj->initNull(); +#endif + } + return elems[i].copy(obj); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Array.h swftools-0.9.1/lib/pdf/xpdf/Array.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Array.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Array.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,58 @@ +//======================================================================== +// +// Array.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef ARRAY_H +#define ARRAY_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Object.h" + +class XRef; + +//------------------------------------------------------------------------ +// Array +//------------------------------------------------------------------------ + +class Array { +public: + + // Constructor. + Array(XRef *xrefA); + + // Destructor. + ~Array(); + + // Reference counting. + int incRef() { return ++ref; } + int decRef() { return --ref; } + + // Get number of elements. + int getLength() { return length; } + + // Add an element. + void add(Object *elem); + + // Accessors. + Object *get(int i, Object *obj); + Object *getNF(int i, Object *obj); + +private: + + XRef *xref; // the xref table for this PDF file + Object *elems; // array of elements + int size; // size of array + int length; // number of elements in array + int ref; // reference count +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/backArrowDis.xbm swftools-0.9.1/lib/pdf/xpdf/backArrowDis.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/backArrowDis.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/backArrowDis.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define backArrowDis_width 16 +#define backArrowDis_height 15 +static unsigned char backArrowDis_bits[] = { + 0x80, 0x00, 0x40, 0x00, 0xa0, 0x00, 0x50, 0x00, 0xa8, 0x00, 0x54, 0x44, + 0xaa, 0x88, 0x55, 0x44, 0xaa, 0x88, 0x54, 0x44, 0xa8, 0x88, 0x50, 0x00, + 0xa0, 0x00, 0x40, 0x00, 0x80, 0x00}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/backArrow.xbm swftools-0.9.1/lib/pdf/xpdf/backArrow.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/backArrow.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/backArrow.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define backArrow_width 16 +#define backArrow_height 15 +static unsigned char backArrow_bits[] = { + 0x80, 0x00, 0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf8, 0x00, 0xfc, 0xcc, + 0xfe, 0xcc, 0xff, 0xcc, 0xfe, 0xcc, 0xfc, 0xcc, 0xf8, 0xcc, 0xf0, 0x00, + 0xe0, 0x00, 0xc0, 0x00, 0x80, 0x00}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/BuiltinFont.cc swftools-0.9.1/lib/pdf/xpdf/BuiltinFont.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/BuiltinFont.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/BuiltinFont.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,65 @@ +//======================================================================== +// +// BuiltinFont.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "FontEncodingTables.h" +#include "BuiltinFont.h" + +//------------------------------------------------------------------------ + +BuiltinFontWidths::BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA) { + int i, h; + + size = sizeA; + tab = (BuiltinFontWidth **)gmallocn(size, sizeof(BuiltinFontWidth *)); + for (i = 0; i < size; ++i) { + tab[i] = NULL; + } + for (i = 0; i < sizeA; ++i) { + h = hash(widths[i].name); + widths[i].next = tab[h]; + tab[h] = &widths[i]; + } +} + +BuiltinFontWidths::~BuiltinFontWidths() { + gfree(tab); +} + +GBool BuiltinFontWidths::getWidth(char *name, Gushort *width) { + int h; + BuiltinFontWidth *p; + + h = hash(name); + for (p = tab[h]; p; p = p->next) { + if (!strcmp(p->name, name)) { + *width = p->width; + return gTrue; + } + } + return gFalse; +} + +int BuiltinFontWidths::hash(char *name) { + char *p; + unsigned int h; + + h = 0; + for (p = name; *p; ++p) { + h = 17 * h + (int)(*p & 0xff); + } + return (int)(h % size); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/BuiltinFont.h swftools-0.9.1/lib/pdf/xpdf/BuiltinFont.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/BuiltinFont.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/BuiltinFont.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,57 @@ +//======================================================================== +// +// BuiltinFont.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef BUILTINFONT_H +#define BUILTINFONT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +struct BuiltinFont; +class BuiltinFontWidths; + +//------------------------------------------------------------------------ + +struct BuiltinFont { + char *name; + char **defaultBaseEnc; + short ascent; + short descent; + short bbox[4]; + BuiltinFontWidths *widths; +}; + +//------------------------------------------------------------------------ + +struct BuiltinFontWidth { + char *name; + Gushort width; + BuiltinFontWidth *next; +}; + +class BuiltinFontWidths { +public: + + BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA); + ~BuiltinFontWidths(); + GBool getWidth(char *name, Gushort *width); + +private: + + int hash(char *name); + + BuiltinFontWidth **tab; + int size; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/BuiltinFontTables.cc swftools-0.9.1/lib/pdf/xpdf/BuiltinFontTables.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/BuiltinFontTables.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/BuiltinFontTables.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,4284 @@ +//======================================================================== +// +// BuiltinFontTables.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include "FontEncodingTables.h" +#include "BuiltinFontTables.h" + +static BuiltinFontWidth courierWidthsTab[] = { + { "Ntilde", 600, NULL }, + { "rcaron", 600, NULL }, + { "kcommaaccent", 600, NULL }, + { "Ncommaaccent", 600, NULL }, + { "Zacute", 600, NULL }, + { "comma", 600, NULL }, + { "cedilla", 600, NULL }, + { "plusminus", 600, NULL }, + { "circumflex", 600, NULL }, + { "dotaccent", 600, NULL }, + { "edotaccent", 600, NULL }, + { "asciitilde", 600, NULL }, + { "colon", 600, NULL }, + { "onehalf", 600, NULL }, + { "dollar", 600, NULL }, + { "Lcaron", 600, NULL }, + { "ntilde", 600, NULL }, + { "Aogonek", 600, NULL }, + { "ncommaaccent", 600, NULL }, + { "minus", 600, NULL }, + { "Iogonek", 600, NULL }, + { "zacute", 600, NULL }, + { "yen", 600, NULL }, + { "space", 600, NULL }, + { "Omacron", 600, NULL }, + { "questiondown", 600, NULL }, + { "emdash", 600, NULL }, + { "Agrave", 600, NULL }, + { "three", 600, NULL }, + { "numbersign", 600, NULL }, + { "lcaron", 600, NULL }, + { "A", 600, NULL }, + { "B", 600, NULL }, + { "C", 600, NULL }, + { "aogonek", 600, NULL }, + { "D", 600, NULL }, + { "E", 600, NULL }, + { "onequarter", 600, NULL }, + { "F", 600, NULL }, + { "G", 600, NULL }, + { "H", 600, NULL }, + { "I", 600, NULL }, + { "J", 600, NULL }, + { "K", 600, NULL }, + { "iogonek", 600, NULL }, + { "L", 600, NULL }, + { "backslash", 600, NULL }, + { "periodcentered", 600, NULL }, + { "M", 600, NULL }, + { "N", 600, NULL }, + { "omacron", 600, NULL }, + { "Tcommaaccent", 600, NULL }, + { "O", 600, NULL }, + { "P", 600, NULL }, + { "Q", 600, NULL }, + { "Uhungarumlaut", 600, NULL }, + { "R", 600, NULL }, + { "Aacute", 600, NULL }, + { "caron", 600, NULL }, + { "S", 600, NULL }, + { "T", 600, NULL }, + { "U", 600, NULL }, + { "agrave", 600, NULL }, + { "V", 600, NULL }, + { "W", 600, NULL }, + { "equal", 600, NULL }, + { "question", 600, NULL }, + { "X", 600, NULL }, + { "Y", 600, NULL }, + { "Z", 600, NULL }, + { "four", 600, NULL }, + { "a", 600, NULL }, + { "Gcommaaccent", 600, NULL }, + { "b", 600, NULL }, + { "c", 600, NULL }, + { "d", 600, NULL }, + { "e", 600, NULL }, + { "f", 600, NULL }, + { "g", 600, NULL }, + { "bullet", 600, NULL }, + { "h", 600, NULL }, + { "i", 600, NULL }, + { "Oslash", 600, NULL }, + { "dagger", 600, NULL }, + { "j", 600, NULL }, + { "k", 600, NULL }, + { "l", 600, NULL }, + { "m", 600, NULL }, + { "n", 600, NULL }, + { "tcommaaccent", 600, NULL }, + { "o", 600, NULL }, + { "ordfeminine", 600, NULL }, + { "ring", 600, NULL }, + { "p", 600, NULL }, + { "q", 600, NULL }, + { "uhungarumlaut", 600, NULL }, + { "r", 600, NULL }, + { "twosuperior", 600, NULL }, + { "aacute", 600, NULL }, + { "s", 600, NULL }, + { "OE", 600, NULL }, + { "t", 600, NULL }, + { "divide", 600, NULL }, + { "u", 600, NULL }, + { "Ccaron", 600, NULL }, + { "v", 600, NULL }, + { "w", 600, NULL }, + { "x", 600, NULL }, + { "y", 600, NULL }, + { "z", 600, NULL }, + { "Gbreve", 600, NULL }, + { "commaaccent", 600, NULL }, + { "hungarumlaut", 600, NULL }, + { "Idotaccent", 600, NULL }, + { "Nacute", 600, NULL }, + { "quotedbl", 600, NULL }, + { "gcommaaccent", 600, NULL }, + { "mu", 600, NULL }, + { "greaterequal", 600, NULL }, + { "Scaron", 600, NULL }, + { "Lslash", 600, NULL }, + { "semicolon", 600, NULL }, + { "oslash", 600, NULL }, + { "lessequal", 600, NULL }, + { "lozenge", 600, NULL }, + { "parenright", 600, NULL }, + { "ccaron", 600, NULL }, + { "Ecircumflex", 600, NULL }, + { "gbreve", 600, NULL }, + { "trademark", 600, NULL }, + { "daggerdbl", 600, NULL }, + { "nacute", 600, NULL }, + { "macron", 600, NULL }, + { "Otilde", 600, NULL }, + { "Emacron", 600, NULL }, + { "ellipsis", 600, NULL }, + { "scaron", 600, NULL }, + { "AE", 600, NULL }, + { "Ucircumflex", 600, NULL }, + { "lslash", 600, NULL }, + { "quotedblleft", 600, NULL }, + { "hyphen", 600, NULL }, + { "guilsinglright", 600, NULL }, + { "quotesingle", 600, NULL }, + { "eight", 600, NULL }, + { "exclamdown", 600, NULL }, + { "endash", 600, NULL }, + { "oe", 600, NULL }, + { "Abreve", 600, NULL }, + { "Umacron", 600, NULL }, + { "ecircumflex", 600, NULL }, + { "Adieresis", 600, NULL }, + { "copyright", 600, NULL }, + { "Egrave", 600, NULL }, + { "slash", 600, NULL }, + { "Edieresis", 600, NULL }, + { "otilde", 600, NULL }, + { "Idieresis", 600, NULL }, + { "parenleft", 600, NULL }, + { "one", 600, NULL }, + { "emacron", 600, NULL }, + { "Odieresis", 600, NULL }, + { "ucircumflex", 600, NULL }, + { "bracketleft", 600, NULL }, + { "Ugrave", 600, NULL }, + { "quoteright", 600, NULL }, + { "Udieresis", 600, NULL }, + { "perthousand", 600, NULL }, + { "Ydieresis", 600, NULL }, + { "umacron", 600, NULL }, + { "abreve", 600, NULL }, + { "Eacute", 600, NULL }, + { "adieresis", 600, NULL }, + { "egrave", 600, NULL }, + { "edieresis", 600, NULL }, + { "idieresis", 600, NULL }, + { "Eth", 600, NULL }, + { "ae", 600, NULL }, + { "asterisk", 600, NULL }, + { "odieresis", 600, NULL }, + { "Uacute", 600, NULL }, + { "ugrave", 600, NULL }, + { "five", 600, NULL }, + { "nine", 600, NULL }, + { "udieresis", 600, NULL }, + { "Zcaron", 600, NULL }, + { "Scommaaccent", 600, NULL }, + { "threequarters", 600, NULL }, + { "guillemotright", 600, NULL }, + { "Ccedilla", 600, NULL }, + { "ydieresis", 600, NULL }, + { "tilde", 600, NULL }, + { "at", 600, NULL }, + { "eacute", 600, NULL }, + { "underscore", 600, NULL }, + { "Euro", 600, NULL }, + { "Dcroat", 600, NULL }, + { "zero", 600, NULL }, + { "multiply", 600, NULL }, + { "eth", 600, NULL }, + { "Scedilla", 600, NULL }, + { "Racute", 600, NULL }, + { "Ograve", 600, NULL }, + { "partialdiff", 600, NULL }, + { "uacute", 600, NULL }, + { "braceleft", 600, NULL }, + { "Thorn", 600, NULL }, + { "zcaron", 600, NULL }, + { "scommaaccent", 600, NULL }, + { "ccedilla", 600, NULL }, + { "Dcaron", 600, NULL }, + { "dcroat", 600, NULL }, + { "scedilla", 600, NULL }, + { "Oacute", 600, NULL }, + { "Ocircumflex", 600, NULL }, + { "ogonek", 600, NULL }, + { "ograve", 600, NULL }, + { "racute", 600, NULL }, + { "Tcaron", 600, NULL }, + { "Eogonek", 600, NULL }, + { "thorn", 600, NULL }, + { "degree", 600, NULL }, + { "registered", 600, NULL }, + { "radical", 600, NULL }, + { "Aring", 600, NULL }, + { "percent", 600, NULL }, + { "six", 600, NULL }, + { "paragraph", 600, NULL }, + { "dcaron", 600, NULL }, + { "Uogonek", 600, NULL }, + { "two", 600, NULL }, + { "summation", 600, NULL }, + { "Igrave", 600, NULL }, + { "Lacute", 600, NULL }, + { "ocircumflex", 600, NULL }, + { "oacute", 600, NULL }, + { "Uring", 600, NULL }, + { "Lcommaaccent", 600, NULL }, + { "tcaron", 600, NULL }, + { "eogonek", 600, NULL }, + { "Delta", 600, NULL }, + { "Ohungarumlaut", 600, NULL }, + { "asciicircum", 600, NULL }, + { "aring", 600, NULL }, + { "grave", 600, NULL }, + { "uogonek", 600, NULL }, + { "bracketright", 600, NULL }, + { "ampersand", 600, NULL }, + { "Iacute", 600, NULL }, + { "lacute", 600, NULL }, + { "igrave", 600, NULL }, + { "Ncaron", 600, NULL }, + { "plus", 600, NULL }, + { "uring", 600, NULL }, + { "quotesinglbase", 600, NULL }, + { "lcommaaccent", 600, NULL }, + { "Yacute", 600, NULL }, + { "ohungarumlaut", 600, NULL }, + { "threesuperior", 600, NULL }, + { "acute", 600, NULL }, + { "section", 600, NULL }, + { "dieresis", 600, NULL }, + { "quotedblbase", 600, NULL }, + { "iacute", 600, NULL }, + { "ncaron", 600, NULL }, + { "florin", 600, NULL }, + { "yacute", 600, NULL }, + { "Rcommaaccent", 600, NULL }, + { "fi", 600, NULL }, + { "fl", 600, NULL }, + { "Acircumflex", 600, NULL }, + { "Cacute", 600, NULL }, + { "Icircumflex", 600, NULL }, + { "guillemotleft", 600, NULL }, + { "germandbls", 600, NULL }, + { "seven", 600, NULL }, + { "Amacron", 600, NULL }, + { "Sacute", 600, NULL }, + { "ordmasculine", 600, NULL }, + { "dotlessi", 600, NULL }, + { "sterling", 600, NULL }, + { "notequal", 600, NULL }, + { "Imacron", 600, NULL }, + { "rcommaaccent", 600, NULL }, + { "Zdotaccent", 600, NULL }, + { "acircumflex", 600, NULL }, + { "cacute", 600, NULL }, + { "Ecaron", 600, NULL }, + { "braceright", 600, NULL }, + { "icircumflex", 600, NULL }, + { "quotedblright", 600, NULL }, + { "amacron", 600, NULL }, + { "sacute", 600, NULL }, + { "imacron", 600, NULL }, + { "cent", 600, NULL }, + { "currency", 600, NULL }, + { "logicalnot", 600, NULL }, + { "zdotaccent", 600, NULL }, + { "Atilde", 600, NULL }, + { "breve", 600, NULL }, + { "bar", 600, NULL }, + { "fraction", 600, NULL }, + { "less", 600, NULL }, + { "ecaron", 600, NULL }, + { "guilsinglleft", 600, NULL }, + { "exclam", 600, NULL }, + { "period", 600, NULL }, + { "Rcaron", 600, NULL }, + { "Kcommaaccent", 600, NULL }, + { "greater", 600, NULL }, + { "atilde", 600, NULL }, + { "brokenbar", 600, NULL }, + { "quoteleft", 600, NULL }, + { "Edotaccent", 600, NULL }, + { "onesuperior", 600, NULL } +}; + +static BuiltinFontWidth courierBoldWidthsTab[] = { + { "Ntilde", 600, NULL }, + { "rcaron", 600, NULL }, + { "kcommaaccent", 600, NULL }, + { "Ncommaaccent", 600, NULL }, + { "Zacute", 600, NULL }, + { "comma", 600, NULL }, + { "cedilla", 600, NULL }, + { "plusminus", 600, NULL }, + { "circumflex", 600, NULL }, + { "dotaccent", 600, NULL }, + { "edotaccent", 600, NULL }, + { "asciitilde", 600, NULL }, + { "colon", 600, NULL }, + { "onehalf", 600, NULL }, + { "dollar", 600, NULL }, + { "Lcaron", 600, NULL }, + { "ntilde", 600, NULL }, + { "Aogonek", 600, NULL }, + { "ncommaaccent", 600, NULL }, + { "minus", 600, NULL }, + { "Iogonek", 600, NULL }, + { "zacute", 600, NULL }, + { "yen", 600, NULL }, + { "space", 600, NULL }, + { "Omacron", 600, NULL }, + { "questiondown", 600, NULL }, + { "emdash", 600, NULL }, + { "Agrave", 600, NULL }, + { "three", 600, NULL }, + { "numbersign", 600, NULL }, + { "lcaron", 600, NULL }, + { "A", 600, NULL }, + { "B", 600, NULL }, + { "C", 600, NULL }, + { "aogonek", 600, NULL }, + { "D", 600, NULL }, + { "E", 600, NULL }, + { "onequarter", 600, NULL }, + { "F", 600, NULL }, + { "G", 600, NULL }, + { "H", 600, NULL }, + { "I", 600, NULL }, + { "J", 600, NULL }, + { "K", 600, NULL }, + { "iogonek", 600, NULL }, + { "backslash", 600, NULL }, + { "L", 600, NULL }, + { "periodcentered", 600, NULL }, + { "M", 600, NULL }, + { "N", 600, NULL }, + { "omacron", 600, NULL }, + { "Tcommaaccent", 600, NULL }, + { "O", 600, NULL }, + { "P", 600, NULL }, + { "Q", 600, NULL }, + { "Uhungarumlaut", 600, NULL }, + { "R", 600, NULL }, + { "Aacute", 600, NULL }, + { "caron", 600, NULL }, + { "S", 600, NULL }, + { "T", 600, NULL }, + { "U", 600, NULL }, + { "agrave", 600, NULL }, + { "V", 600, NULL }, + { "W", 600, NULL }, + { "X", 600, NULL }, + { "question", 600, NULL }, + { "equal", 600, NULL }, + { "Y", 600, NULL }, + { "Z", 600, NULL }, + { "four", 600, NULL }, + { "a", 600, NULL }, + { "Gcommaaccent", 600, NULL }, + { "b", 600, NULL }, + { "c", 600, NULL }, + { "d", 600, NULL }, + { "e", 600, NULL }, + { "f", 600, NULL }, + { "g", 600, NULL }, + { "bullet", 600, NULL }, + { "h", 600, NULL }, + { "i", 600, NULL }, + { "Oslash", 600, NULL }, + { "dagger", 600, NULL }, + { "j", 600, NULL }, + { "k", 600, NULL }, + { "l", 600, NULL }, + { "m", 600, NULL }, + { "n", 600, NULL }, + { "tcommaaccent", 600, NULL }, + { "o", 600, NULL }, + { "ordfeminine", 600, NULL }, + { "ring", 600, NULL }, + { "p", 600, NULL }, + { "q", 600, NULL }, + { "uhungarumlaut", 600, NULL }, + { "r", 600, NULL }, + { "twosuperior", 600, NULL }, + { "aacute", 600, NULL }, + { "s", 600, NULL }, + { "OE", 600, NULL }, + { "t", 600, NULL }, + { "divide", 600, NULL }, + { "u", 600, NULL }, + { "Ccaron", 600, NULL }, + { "v", 600, NULL }, + { "w", 600, NULL }, + { "x", 600, NULL }, + { "y", 600, NULL }, + { "z", 600, NULL }, + { "Gbreve", 600, NULL }, + { "commaaccent", 600, NULL }, + { "hungarumlaut", 600, NULL }, + { "Idotaccent", 600, NULL }, + { "Nacute", 600, NULL }, + { "quotedbl", 600, NULL }, + { "gcommaaccent", 600, NULL }, + { "mu", 600, NULL }, + { "greaterequal", 600, NULL }, + { "Scaron", 600, NULL }, + { "Lslash", 600, NULL }, + { "semicolon", 600, NULL }, + { "oslash", 600, NULL }, + { "lessequal", 600, NULL }, + { "lozenge", 600, NULL }, + { "parenright", 600, NULL }, + { "ccaron", 600, NULL }, + { "Ecircumflex", 600, NULL }, + { "gbreve", 600, NULL }, + { "trademark", 600, NULL }, + { "daggerdbl", 600, NULL }, + { "nacute", 600, NULL }, + { "macron", 600, NULL }, + { "Otilde", 600, NULL }, + { "Emacron", 600, NULL }, + { "ellipsis", 600, NULL }, + { "scaron", 600, NULL }, + { "AE", 600, NULL }, + { "Ucircumflex", 600, NULL }, + { "lslash", 600, NULL }, + { "quotedblleft", 600, NULL }, + { "guilsinglright", 600, NULL }, + { "hyphen", 600, NULL }, + { "quotesingle", 600, NULL }, + { "eight", 600, NULL }, + { "exclamdown", 600, NULL }, + { "endash", 600, NULL }, + { "oe", 600, NULL }, + { "Abreve", 600, NULL }, + { "Umacron", 600, NULL }, + { "ecircumflex", 600, NULL }, + { "Adieresis", 600, NULL }, + { "copyright", 600, NULL }, + { "Egrave", 600, NULL }, + { "slash", 600, NULL }, + { "Edieresis", 600, NULL }, + { "otilde", 600, NULL }, + { "Idieresis", 600, NULL }, + { "parenleft", 600, NULL }, + { "one", 600, NULL }, + { "emacron", 600, NULL }, + { "Odieresis", 600, NULL }, + { "ucircumflex", 600, NULL }, + { "bracketleft", 600, NULL }, + { "Ugrave", 600, NULL }, + { "quoteright", 600, NULL }, + { "Udieresis", 600, NULL }, + { "perthousand", 600, NULL }, + { "Ydieresis", 600, NULL }, + { "umacron", 600, NULL }, + { "abreve", 600, NULL }, + { "Eacute", 600, NULL }, + { "adieresis", 600, NULL }, + { "egrave", 600, NULL }, + { "edieresis", 600, NULL }, + { "idieresis", 600, NULL }, + { "Eth", 600, NULL }, + { "ae", 600, NULL }, + { "asterisk", 600, NULL }, + { "odieresis", 600, NULL }, + { "Uacute", 600, NULL }, + { "ugrave", 600, NULL }, + { "nine", 600, NULL }, + { "five", 600, NULL }, + { "udieresis", 600, NULL }, + { "Zcaron", 600, NULL }, + { "Scommaaccent", 600, NULL }, + { "threequarters", 600, NULL }, + { "guillemotright", 600, NULL }, + { "Ccedilla", 600, NULL }, + { "ydieresis", 600, NULL }, + { "tilde", 600, NULL }, + { "at", 600, NULL }, + { "eacute", 600, NULL }, + { "underscore", 600, NULL }, + { "Euro", 600, NULL }, + { "Dcroat", 600, NULL }, + { "multiply", 600, NULL }, + { "zero", 600, NULL }, + { "eth", 600, NULL }, + { "Scedilla", 600, NULL }, + { "Ograve", 600, NULL }, + { "Racute", 600, NULL }, + { "partialdiff", 600, NULL }, + { "uacute", 600, NULL }, + { "braceleft", 600, NULL }, + { "Thorn", 600, NULL }, + { "zcaron", 600, NULL }, + { "scommaaccent", 600, NULL }, + { "ccedilla", 600, NULL }, + { "Dcaron", 600, NULL }, + { "dcroat", 600, NULL }, + { "Ocircumflex", 600, NULL }, + { "Oacute", 600, NULL }, + { "scedilla", 600, NULL }, + { "ogonek", 600, NULL }, + { "ograve", 600, NULL }, + { "racute", 600, NULL }, + { "Tcaron", 600, NULL }, + { "Eogonek", 600, NULL }, + { "thorn", 600, NULL }, + { "degree", 600, NULL }, + { "registered", 600, NULL }, + { "radical", 600, NULL }, + { "Aring", 600, NULL }, + { "percent", 600, NULL }, + { "six", 600, NULL }, + { "paragraph", 600, NULL }, + { "dcaron", 600, NULL }, + { "Uogonek", 600, NULL }, + { "two", 600, NULL }, + { "summation", 600, NULL }, + { "Igrave", 600, NULL }, + { "Lacute", 600, NULL }, + { "ocircumflex", 600, NULL }, + { "oacute", 600, NULL }, + { "Uring", 600, NULL }, + { "Lcommaaccent", 600, NULL }, + { "tcaron", 600, NULL }, + { "eogonek", 600, NULL }, + { "Delta", 600, NULL }, + { "Ohungarumlaut", 600, NULL }, + { "asciicircum", 600, NULL }, + { "aring", 600, NULL }, + { "grave", 600, NULL }, + { "uogonek", 600, NULL }, + { "bracketright", 600, NULL }, + { "Iacute", 600, NULL }, + { "ampersand", 600, NULL }, + { "igrave", 600, NULL }, + { "lacute", 600, NULL }, + { "Ncaron", 600, NULL }, + { "plus", 600, NULL }, + { "uring", 600, NULL }, + { "quotesinglbase", 600, NULL }, + { "lcommaaccent", 600, NULL }, + { "Yacute", 600, NULL }, + { "ohungarumlaut", 600, NULL }, + { "threesuperior", 600, NULL }, + { "acute", 600, NULL }, + { "section", 600, NULL }, + { "dieresis", 600, NULL }, + { "iacute", 600, NULL }, + { "quotedblbase", 600, NULL }, + { "ncaron", 600, NULL }, + { "florin", 600, NULL }, + { "yacute", 600, NULL }, + { "Rcommaaccent", 600, NULL }, + { "fi", 600, NULL }, + { "fl", 600, NULL }, + { "Acircumflex", 600, NULL }, + { "Cacute", 600, NULL }, + { "Icircumflex", 600, NULL }, + { "guillemotleft", 600, NULL }, + { "germandbls", 600, NULL }, + { "Amacron", 600, NULL }, + { "seven", 600, NULL }, + { "Sacute", 600, NULL }, + { "ordmasculine", 600, NULL }, + { "dotlessi", 600, NULL }, + { "sterling", 600, NULL }, + { "notequal", 600, NULL }, + { "Imacron", 600, NULL }, + { "rcommaaccent", 600, NULL }, + { "Zdotaccent", 600, NULL }, + { "acircumflex", 600, NULL }, + { "cacute", 600, NULL }, + { "Ecaron", 600, NULL }, + { "icircumflex", 600, NULL }, + { "braceright", 600, NULL }, + { "quotedblright", 600, NULL }, + { "amacron", 600, NULL }, + { "sacute", 600, NULL }, + { "imacron", 600, NULL }, + { "cent", 600, NULL }, + { "currency", 600, NULL }, + { "logicalnot", 600, NULL }, + { "zdotaccent", 600, NULL }, + { "Atilde", 600, NULL }, + { "breve", 600, NULL }, + { "bar", 600, NULL }, + { "fraction", 600, NULL }, + { "less", 600, NULL }, + { "ecaron", 600, NULL }, + { "guilsinglleft", 600, NULL }, + { "exclam", 600, NULL }, + { "period", 600, NULL }, + { "Rcaron", 600, NULL }, + { "Kcommaaccent", 600, NULL }, + { "greater", 600, NULL }, + { "atilde", 600, NULL }, + { "brokenbar", 600, NULL }, + { "quoteleft", 600, NULL }, + { "Edotaccent", 600, NULL }, + { "onesuperior", 600, NULL } +}; + +static BuiltinFontWidth courierBoldObliqueWidthsTab[] = { + { "Ntilde", 600, NULL }, + { "rcaron", 600, NULL }, + { "kcommaaccent", 600, NULL }, + { "Ncommaaccent", 600, NULL }, + { "Zacute", 600, NULL }, + { "comma", 600, NULL }, + { "cedilla", 600, NULL }, + { "plusminus", 600, NULL }, + { "circumflex", 600, NULL }, + { "dotaccent", 600, NULL }, + { "edotaccent", 600, NULL }, + { "asciitilde", 600, NULL }, + { "colon", 600, NULL }, + { "onehalf", 600, NULL }, + { "dollar", 600, NULL }, + { "Lcaron", 600, NULL }, + { "ntilde", 600, NULL }, + { "Aogonek", 600, NULL }, + { "ncommaaccent", 600, NULL }, + { "minus", 600, NULL }, + { "Iogonek", 600, NULL }, + { "zacute", 600, NULL }, + { "yen", 600, NULL }, + { "space", 600, NULL }, + { "Omacron", 600, NULL }, + { "questiondown", 600, NULL }, + { "emdash", 600, NULL }, + { "Agrave", 600, NULL }, + { "three", 600, NULL }, + { "numbersign", 600, NULL }, + { "lcaron", 600, NULL }, + { "A", 600, NULL }, + { "B", 600, NULL }, + { "C", 600, NULL }, + { "aogonek", 600, NULL }, + { "D", 600, NULL }, + { "E", 600, NULL }, + { "onequarter", 600, NULL }, + { "F", 600, NULL }, + { "G", 600, NULL }, + { "H", 600, NULL }, + { "I", 600, NULL }, + { "J", 600, NULL }, + { "K", 600, NULL }, + { "iogonek", 600, NULL }, + { "backslash", 600, NULL }, + { "L", 600, NULL }, + { "periodcentered", 600, NULL }, + { "M", 600, NULL }, + { "N", 600, NULL }, + { "omacron", 600, NULL }, + { "Tcommaaccent", 600, NULL }, + { "O", 600, NULL }, + { "P", 600, NULL }, + { "Q", 600, NULL }, + { "Uhungarumlaut", 600, NULL }, + { "R", 600, NULL }, + { "Aacute", 600, NULL }, + { "caron", 600, NULL }, + { "S", 600, NULL }, + { "T", 600, NULL }, + { "U", 600, NULL }, + { "agrave", 600, NULL }, + { "V", 600, NULL }, + { "W", 600, NULL }, + { "X", 600, NULL }, + { "question", 600, NULL }, + { "equal", 600, NULL }, + { "Y", 600, NULL }, + { "Z", 600, NULL }, + { "four", 600, NULL }, + { "a", 600, NULL }, + { "Gcommaaccent", 600, NULL }, + { "b", 600, NULL }, + { "c", 600, NULL }, + { "d", 600, NULL }, + { "e", 600, NULL }, + { "f", 600, NULL }, + { "g", 600, NULL }, + { "bullet", 600, NULL }, + { "h", 600, NULL }, + { "i", 600, NULL }, + { "Oslash", 600, NULL }, + { "dagger", 600, NULL }, + { "j", 600, NULL }, + { "k", 600, NULL }, + { "l", 600, NULL }, + { "m", 600, NULL }, + { "n", 600, NULL }, + { "tcommaaccent", 600, NULL }, + { "o", 600, NULL }, + { "ordfeminine", 600, NULL }, + { "ring", 600, NULL }, + { "p", 600, NULL }, + { "q", 600, NULL }, + { "uhungarumlaut", 600, NULL }, + { "r", 600, NULL }, + { "twosuperior", 600, NULL }, + { "aacute", 600, NULL }, + { "s", 600, NULL }, + { "OE", 600, NULL }, + { "t", 600, NULL }, + { "divide", 600, NULL }, + { "u", 600, NULL }, + { "Ccaron", 600, NULL }, + { "v", 600, NULL }, + { "w", 600, NULL }, + { "x", 600, NULL }, + { "y", 600, NULL }, + { "z", 600, NULL }, + { "Gbreve", 600, NULL }, + { "commaaccent", 600, NULL }, + { "hungarumlaut", 600, NULL }, + { "Idotaccent", 600, NULL }, + { "Nacute", 600, NULL }, + { "quotedbl", 600, NULL }, + { "gcommaaccent", 600, NULL }, + { "mu", 600, NULL }, + { "greaterequal", 600, NULL }, + { "Scaron", 600, NULL }, + { "Lslash", 600, NULL }, + { "semicolon", 600, NULL }, + { "oslash", 600, NULL }, + { "lessequal", 600, NULL }, + { "lozenge", 600, NULL }, + { "parenright", 600, NULL }, + { "ccaron", 600, NULL }, + { "Ecircumflex", 600, NULL }, + { "gbreve", 600, NULL }, + { "trademark", 600, NULL }, + { "daggerdbl", 600, NULL }, + { "nacute", 600, NULL }, + { "macron", 600, NULL }, + { "Otilde", 600, NULL }, + { "Emacron", 600, NULL }, + { "ellipsis", 600, NULL }, + { "scaron", 600, NULL }, + { "AE", 600, NULL }, + { "Ucircumflex", 600, NULL }, + { "lslash", 600, NULL }, + { "quotedblleft", 600, NULL }, + { "guilsinglright", 600, NULL }, + { "hyphen", 600, NULL }, + { "quotesingle", 600, NULL }, + { "eight", 600, NULL }, + { "exclamdown", 600, NULL }, + { "endash", 600, NULL }, + { "oe", 600, NULL }, + { "Abreve", 600, NULL }, + { "Umacron", 600, NULL }, + { "ecircumflex", 600, NULL }, + { "Adieresis", 600, NULL }, + { "copyright", 600, NULL }, + { "Egrave", 600, NULL }, + { "slash", 600, NULL }, + { "Edieresis", 600, NULL }, + { "otilde", 600, NULL }, + { "Idieresis", 600, NULL }, + { "parenleft", 600, NULL }, + { "one", 600, NULL }, + { "emacron", 600, NULL }, + { "Odieresis", 600, NULL }, + { "ucircumflex", 600, NULL }, + { "bracketleft", 600, NULL }, + { "Ugrave", 600, NULL }, + { "quoteright", 600, NULL }, + { "Udieresis", 600, NULL }, + { "perthousand", 600, NULL }, + { "Ydieresis", 600, NULL }, + { "umacron", 600, NULL }, + { "abreve", 600, NULL }, + { "Eacute", 600, NULL }, + { "adieresis", 600, NULL }, + { "egrave", 600, NULL }, + { "edieresis", 600, NULL }, + { "idieresis", 600, NULL }, + { "Eth", 600, NULL }, + { "ae", 600, NULL }, + { "asterisk", 600, NULL }, + { "odieresis", 600, NULL }, + { "Uacute", 600, NULL }, + { "ugrave", 600, NULL }, + { "nine", 600, NULL }, + { "five", 600, NULL }, + { "udieresis", 600, NULL }, + { "Zcaron", 600, NULL }, + { "Scommaaccent", 600, NULL }, + { "threequarters", 600, NULL }, + { "guillemotright", 600, NULL }, + { "Ccedilla", 600, NULL }, + { "ydieresis", 600, NULL }, + { "tilde", 600, NULL }, + { "at", 600, NULL }, + { "eacute", 600, NULL }, + { "underscore", 600, NULL }, + { "Euro", 600, NULL }, + { "Dcroat", 600, NULL }, + { "multiply", 600, NULL }, + { "zero", 600, NULL }, + { "eth", 600, NULL }, + { "Scedilla", 600, NULL }, + { "Ograve", 600, NULL }, + { "Racute", 600, NULL }, + { "partialdiff", 600, NULL }, + { "uacute", 600, NULL }, + { "braceleft", 600, NULL }, + { "Thorn", 600, NULL }, + { "zcaron", 600, NULL }, + { "scommaaccent", 600, NULL }, + { "ccedilla", 600, NULL }, + { "Dcaron", 600, NULL }, + { "dcroat", 600, NULL }, + { "Ocircumflex", 600, NULL }, + { "Oacute", 600, NULL }, + { "scedilla", 600, NULL }, + { "ogonek", 600, NULL }, + { "ograve", 600, NULL }, + { "racute", 600, NULL }, + { "Tcaron", 600, NULL }, + { "Eogonek", 600, NULL }, + { "thorn", 600, NULL }, + { "degree", 600, NULL }, + { "registered", 600, NULL }, + { "radical", 600, NULL }, + { "Aring", 600, NULL }, + { "percent", 600, NULL }, + { "six", 600, NULL }, + { "paragraph", 600, NULL }, + { "dcaron", 600, NULL }, + { "Uogonek", 600, NULL }, + { "two", 600, NULL }, + { "summation", 600, NULL }, + { "Igrave", 600, NULL }, + { "Lacute", 600, NULL }, + { "ocircumflex", 600, NULL }, + { "oacute", 600, NULL }, + { "Uring", 600, NULL }, + { "Lcommaaccent", 600, NULL }, + { "tcaron", 600, NULL }, + { "eogonek", 600, NULL }, + { "Delta", 600, NULL }, + { "Ohungarumlaut", 600, NULL }, + { "asciicircum", 600, NULL }, + { "aring", 600, NULL }, + { "grave", 600, NULL }, + { "uogonek", 600, NULL }, + { "bracketright", 600, NULL }, + { "Iacute", 600, NULL }, + { "ampersand", 600, NULL }, + { "igrave", 600, NULL }, + { "lacute", 600, NULL }, + { "Ncaron", 600, NULL }, + { "plus", 600, NULL }, + { "uring", 600, NULL }, + { "quotesinglbase", 600, NULL }, + { "lcommaaccent", 600, NULL }, + { "Yacute", 600, NULL }, + { "ohungarumlaut", 600, NULL }, + { "threesuperior", 600, NULL }, + { "acute", 600, NULL }, + { "section", 600, NULL }, + { "dieresis", 600, NULL }, + { "iacute", 600, NULL }, + { "quotedblbase", 600, NULL }, + { "ncaron", 600, NULL }, + { "florin", 600, NULL }, + { "yacute", 600, NULL }, + { "Rcommaaccent", 600, NULL }, + { "fi", 600, NULL }, + { "fl", 600, NULL }, + { "Acircumflex", 600, NULL }, + { "Cacute", 600, NULL }, + { "Icircumflex", 600, NULL }, + { "guillemotleft", 600, NULL }, + { "germandbls", 600, NULL }, + { "Amacron", 600, NULL }, + { "seven", 600, NULL }, + { "Sacute", 600, NULL }, + { "ordmasculine", 600, NULL }, + { "dotlessi", 600, NULL }, + { "sterling", 600, NULL }, + { "notequal", 600, NULL }, + { "Imacron", 600, NULL }, + { "rcommaaccent", 600, NULL }, + { "Zdotaccent", 600, NULL }, + { "acircumflex", 600, NULL }, + { "cacute", 600, NULL }, + { "Ecaron", 600, NULL }, + { "icircumflex", 600, NULL }, + { "braceright", 600, NULL }, + { "quotedblright", 600, NULL }, + { "amacron", 600, NULL }, + { "sacute", 600, NULL }, + { "imacron", 600, NULL }, + { "cent", 600, NULL }, + { "currency", 600, NULL }, + { "logicalnot", 600, NULL }, + { "zdotaccent", 600, NULL }, + { "Atilde", 600, NULL }, + { "breve", 600, NULL }, + { "bar", 600, NULL }, + { "fraction", 600, NULL }, + { "less", 600, NULL }, + { "ecaron", 600, NULL }, + { "guilsinglleft", 600, NULL }, + { "exclam", 600, NULL }, + { "period", 600, NULL }, + { "Rcaron", 600, NULL }, + { "Kcommaaccent", 600, NULL }, + { "greater", 600, NULL }, + { "atilde", 600, NULL }, + { "brokenbar", 600, NULL }, + { "quoteleft", 600, NULL }, + { "Edotaccent", 600, NULL }, + { "onesuperior", 600, NULL } +}; + +static BuiltinFontWidth courierObliqueWidthsTab[] = { + { "Ntilde", 600, NULL }, + { "rcaron", 600, NULL }, + { "kcommaaccent", 600, NULL }, + { "Ncommaaccent", 600, NULL }, + { "Zacute", 600, NULL }, + { "comma", 600, NULL }, + { "cedilla", 600, NULL }, + { "plusminus", 600, NULL }, + { "circumflex", 600, NULL }, + { "dotaccent", 600, NULL }, + { "edotaccent", 600, NULL }, + { "asciitilde", 600, NULL }, + { "colon", 600, NULL }, + { "onehalf", 600, NULL }, + { "dollar", 600, NULL }, + { "Lcaron", 600, NULL }, + { "ntilde", 600, NULL }, + { "Aogonek", 600, NULL }, + { "ncommaaccent", 600, NULL }, + { "minus", 600, NULL }, + { "Iogonek", 600, NULL }, + { "zacute", 600, NULL }, + { "yen", 600, NULL }, + { "space", 600, NULL }, + { "Omacron", 600, NULL }, + { "questiondown", 600, NULL }, + { "emdash", 600, NULL }, + { "Agrave", 600, NULL }, + { "three", 600, NULL }, + { "numbersign", 600, NULL }, + { "lcaron", 600, NULL }, + { "A", 600, NULL }, + { "B", 600, NULL }, + { "C", 600, NULL }, + { "aogonek", 600, NULL }, + { "D", 600, NULL }, + { "E", 600, NULL }, + { "onequarter", 600, NULL }, + { "F", 600, NULL }, + { "G", 600, NULL }, + { "H", 600, NULL }, + { "I", 600, NULL }, + { "J", 600, NULL }, + { "K", 600, NULL }, + { "iogonek", 600, NULL }, + { "backslash", 600, NULL }, + { "L", 600, NULL }, + { "periodcentered", 600, NULL }, + { "M", 600, NULL }, + { "N", 600, NULL }, + { "omacron", 600, NULL }, + { "Tcommaaccent", 600, NULL }, + { "O", 600, NULL }, + { "P", 600, NULL }, + { "Q", 600, NULL }, + { "Uhungarumlaut", 600, NULL }, + { "R", 600, NULL }, + { "Aacute", 600, NULL }, + { "caron", 600, NULL }, + { "S", 600, NULL }, + { "T", 600, NULL }, + { "U", 600, NULL }, + { "agrave", 600, NULL }, + { "V", 600, NULL }, + { "W", 600, NULL }, + { "X", 600, NULL }, + { "question", 600, NULL }, + { "equal", 600, NULL }, + { "Y", 600, NULL }, + { "Z", 600, NULL }, + { "four", 600, NULL }, + { "a", 600, NULL }, + { "Gcommaaccent", 600, NULL }, + { "b", 600, NULL }, + { "c", 600, NULL }, + { "d", 600, NULL }, + { "e", 600, NULL }, + { "f", 600, NULL }, + { "g", 600, NULL }, + { "bullet", 600, NULL }, + { "h", 600, NULL }, + { "i", 600, NULL }, + { "Oslash", 600, NULL }, + { "dagger", 600, NULL }, + { "j", 600, NULL }, + { "k", 600, NULL }, + { "l", 600, NULL }, + { "m", 600, NULL }, + { "n", 600, NULL }, + { "tcommaaccent", 600, NULL }, + { "o", 600, NULL }, + { "ordfeminine", 600, NULL }, + { "ring", 600, NULL }, + { "p", 600, NULL }, + { "q", 600, NULL }, + { "uhungarumlaut", 600, NULL }, + { "r", 600, NULL }, + { "twosuperior", 600, NULL }, + { "aacute", 600, NULL }, + { "s", 600, NULL }, + { "OE", 600, NULL }, + { "t", 600, NULL }, + { "divide", 600, NULL }, + { "u", 600, NULL }, + { "Ccaron", 600, NULL }, + { "v", 600, NULL }, + { "w", 600, NULL }, + { "x", 600, NULL }, + { "y", 600, NULL }, + { "z", 600, NULL }, + { "Gbreve", 600, NULL }, + { "commaaccent", 600, NULL }, + { "hungarumlaut", 600, NULL }, + { "Idotaccent", 600, NULL }, + { "Nacute", 600, NULL }, + { "quotedbl", 600, NULL }, + { "gcommaaccent", 600, NULL }, + { "mu", 600, NULL }, + { "greaterequal", 600, NULL }, + { "Scaron", 600, NULL }, + { "Lslash", 600, NULL }, + { "semicolon", 600, NULL }, + { "oslash", 600, NULL }, + { "lessequal", 600, NULL }, + { "lozenge", 600, NULL }, + { "parenright", 600, NULL }, + { "ccaron", 600, NULL }, + { "Ecircumflex", 600, NULL }, + { "gbreve", 600, NULL }, + { "trademark", 600, NULL }, + { "daggerdbl", 600, NULL }, + { "nacute", 600, NULL }, + { "macron", 600, NULL }, + { "Otilde", 600, NULL }, + { "Emacron", 600, NULL }, + { "ellipsis", 600, NULL }, + { "scaron", 600, NULL }, + { "AE", 600, NULL }, + { "Ucircumflex", 600, NULL }, + { "lslash", 600, NULL }, + { "quotedblleft", 600, NULL }, + { "guilsinglright", 600, NULL }, + { "hyphen", 600, NULL }, + { "quotesingle", 600, NULL }, + { "eight", 600, NULL }, + { "exclamdown", 600, NULL }, + { "endash", 600, NULL }, + { "oe", 600, NULL }, + { "Abreve", 600, NULL }, + { "Umacron", 600, NULL }, + { "ecircumflex", 600, NULL }, + { "Adieresis", 600, NULL }, + { "copyright", 600, NULL }, + { "Egrave", 600, NULL }, + { "slash", 600, NULL }, + { "Edieresis", 600, NULL }, + { "otilde", 600, NULL }, + { "Idieresis", 600, NULL }, + { "parenleft", 600, NULL }, + { "one", 600, NULL }, + { "emacron", 600, NULL }, + { "Odieresis", 600, NULL }, + { "ucircumflex", 600, NULL }, + { "bracketleft", 600, NULL }, + { "Ugrave", 600, NULL }, + { "quoteright", 600, NULL }, + { "Udieresis", 600, NULL }, + { "perthousand", 600, NULL }, + { "Ydieresis", 600, NULL }, + { "umacron", 600, NULL }, + { "abreve", 600, NULL }, + { "Eacute", 600, NULL }, + { "adieresis", 600, NULL }, + { "egrave", 600, NULL }, + { "edieresis", 600, NULL }, + { "idieresis", 600, NULL }, + { "Eth", 600, NULL }, + { "ae", 600, NULL }, + { "asterisk", 600, NULL }, + { "odieresis", 600, NULL }, + { "Uacute", 600, NULL }, + { "ugrave", 600, NULL }, + { "nine", 600, NULL }, + { "five", 600, NULL }, + { "udieresis", 600, NULL }, + { "Zcaron", 600, NULL }, + { "Scommaaccent", 600, NULL }, + { "threequarters", 600, NULL }, + { "guillemotright", 600, NULL }, + { "Ccedilla", 600, NULL }, + { "ydieresis", 600, NULL }, + { "tilde", 600, NULL }, + { "at", 600, NULL }, + { "eacute", 600, NULL }, + { "underscore", 600, NULL }, + { "Euro", 600, NULL }, + { "Dcroat", 600, NULL }, + { "multiply", 600, NULL }, + { "zero", 600, NULL }, + { "eth", 600, NULL }, + { "Scedilla", 600, NULL }, + { "Ograve", 600, NULL }, + { "Racute", 600, NULL }, + { "partialdiff", 600, NULL }, + { "uacute", 600, NULL }, + { "braceleft", 600, NULL }, + { "Thorn", 600, NULL }, + { "zcaron", 600, NULL }, + { "scommaaccent", 600, NULL }, + { "ccedilla", 600, NULL }, + { "Dcaron", 600, NULL }, + { "dcroat", 600, NULL }, + { "Ocircumflex", 600, NULL }, + { "Oacute", 600, NULL }, + { "scedilla", 600, NULL }, + { "ogonek", 600, NULL }, + { "ograve", 600, NULL }, + { "racute", 600, NULL }, + { "Tcaron", 600, NULL }, + { "Eogonek", 600, NULL }, + { "thorn", 600, NULL }, + { "degree", 600, NULL }, + { "registered", 600, NULL }, + { "radical", 600, NULL }, + { "Aring", 600, NULL }, + { "percent", 600, NULL }, + { "six", 600, NULL }, + { "paragraph", 600, NULL }, + { "dcaron", 600, NULL }, + { "Uogonek", 600, NULL }, + { "two", 600, NULL }, + { "summation", 600, NULL }, + { "Igrave", 600, NULL }, + { "Lacute", 600, NULL }, + { "ocircumflex", 600, NULL }, + { "oacute", 600, NULL }, + { "Uring", 600, NULL }, + { "Lcommaaccent", 600, NULL }, + { "tcaron", 600, NULL }, + { "eogonek", 600, NULL }, + { "Delta", 600, NULL }, + { "Ohungarumlaut", 600, NULL }, + { "asciicircum", 600, NULL }, + { "aring", 600, NULL }, + { "grave", 600, NULL }, + { "uogonek", 600, NULL }, + { "bracketright", 600, NULL }, + { "Iacute", 600, NULL }, + { "ampersand", 600, NULL }, + { "igrave", 600, NULL }, + { "lacute", 600, NULL }, + { "Ncaron", 600, NULL }, + { "plus", 600, NULL }, + { "uring", 600, NULL }, + { "quotesinglbase", 600, NULL }, + { "lcommaaccent", 600, NULL }, + { "Yacute", 600, NULL }, + { "ohungarumlaut", 600, NULL }, + { "threesuperior", 600, NULL }, + { "acute", 600, NULL }, + { "section", 600, NULL }, + { "dieresis", 600, NULL }, + { "iacute", 600, NULL }, + { "quotedblbase", 600, NULL }, + { "ncaron", 600, NULL }, + { "florin", 600, NULL }, + { "yacute", 600, NULL }, + { "Rcommaaccent", 600, NULL }, + { "fi", 600, NULL }, + { "fl", 600, NULL }, + { "Acircumflex", 600, NULL }, + { "Cacute", 600, NULL }, + { "Icircumflex", 600, NULL }, + { "guillemotleft", 600, NULL }, + { "germandbls", 600, NULL }, + { "Amacron", 600, NULL }, + { "seven", 600, NULL }, + { "Sacute", 600, NULL }, + { "ordmasculine", 600, NULL }, + { "dotlessi", 600, NULL }, + { "sterling", 600, NULL }, + { "notequal", 600, NULL }, + { "Imacron", 600, NULL }, + { "rcommaaccent", 600, NULL }, + { "Zdotaccent", 600, NULL }, + { "acircumflex", 600, NULL }, + { "cacute", 600, NULL }, + { "Ecaron", 600, NULL }, + { "icircumflex", 600, NULL }, + { "braceright", 600, NULL }, + { "quotedblright", 600, NULL }, + { "amacron", 600, NULL }, + { "sacute", 600, NULL }, + { "imacron", 600, NULL }, + { "cent", 600, NULL }, + { "currency", 600, NULL }, + { "logicalnot", 600, NULL }, + { "zdotaccent", 600, NULL }, + { "Atilde", 600, NULL }, + { "breve", 600, NULL }, + { "bar", 600, NULL }, + { "fraction", 600, NULL }, + { "less", 600, NULL }, + { "ecaron", 600, NULL }, + { "guilsinglleft", 600, NULL }, + { "exclam", 600, NULL }, + { "period", 600, NULL }, + { "Rcaron", 600, NULL }, + { "Kcommaaccent", 600, NULL }, + { "greater", 600, NULL }, + { "atilde", 600, NULL }, + { "brokenbar", 600, NULL }, + { "quoteleft", 600, NULL }, + { "Edotaccent", 600, NULL }, + { "onesuperior", 600, NULL } +}; + +static BuiltinFontWidth helveticaWidthsTab[] = { + { "Ntilde", 722, NULL }, + { "rcaron", 333, NULL }, + { "kcommaaccent", 500, NULL }, + { "Ncommaaccent", 722, NULL }, + { "Zacute", 611, NULL }, + { "comma", 278, NULL }, + { "cedilla", 333, NULL }, + { "plusminus", 584, NULL }, + { "circumflex", 333, NULL }, + { "dotaccent", 333, NULL }, + { "edotaccent", 556, NULL }, + { "asciitilde", 584, NULL }, + { "colon", 278, NULL }, + { "onehalf", 834, NULL }, + { "dollar", 556, NULL }, + { "Lcaron", 556, NULL }, + { "ntilde", 556, NULL }, + { "Aogonek", 667, NULL }, + { "ncommaaccent", 556, NULL }, + { "minus", 584, NULL }, + { "Iogonek", 278, NULL }, + { "zacute", 500, NULL }, + { "yen", 556, NULL }, + { "space", 278, NULL }, + { "Omacron", 778, NULL }, + { "questiondown", 611, NULL }, + { "emdash", 1000, NULL }, + { "Agrave", 667, NULL }, + { "three", 556, NULL }, + { "numbersign", 556, NULL }, + { "lcaron", 299, NULL }, + { "A", 667, NULL }, + { "B", 667, NULL }, + { "C", 722, NULL }, + { "aogonek", 556, NULL }, + { "D", 722, NULL }, + { "E", 667, NULL }, + { "onequarter", 834, NULL }, + { "F", 611, NULL }, + { "G", 778, NULL }, + { "H", 722, NULL }, + { "I", 278, NULL }, + { "J", 500, NULL }, + { "K", 667, NULL }, + { "iogonek", 222, NULL }, + { "backslash", 278, NULL }, + { "L", 556, NULL }, + { "periodcentered", 278, NULL }, + { "M", 833, NULL }, + { "N", 722, NULL }, + { "omacron", 556, NULL }, + { "Tcommaaccent", 611, NULL }, + { "O", 778, NULL }, + { "P", 667, NULL }, + { "Q", 778, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "R", 722, NULL }, + { "Aacute", 667, NULL }, + { "caron", 333, NULL }, + { "S", 667, NULL }, + { "T", 611, NULL }, + { "U", 722, NULL }, + { "agrave", 556, NULL }, + { "V", 667, NULL }, + { "W", 944, NULL }, + { "X", 667, NULL }, + { "question", 556, NULL }, + { "equal", 584, NULL }, + { "Y", 667, NULL }, + { "Z", 611, NULL }, + { "four", 556, NULL }, + { "a", 556, NULL }, + { "Gcommaaccent", 778, NULL }, + { "b", 556, NULL }, + { "c", 500, NULL }, + { "d", 556, NULL }, + { "e", 556, NULL }, + { "f", 278, NULL }, + { "g", 556, NULL }, + { "bullet", 350, NULL }, + { "h", 556, NULL }, + { "i", 222, NULL }, + { "Oslash", 778, NULL }, + { "dagger", 556, NULL }, + { "j", 222, NULL }, + { "k", 500, NULL }, + { "l", 222, NULL }, + { "m", 833, NULL }, + { "n", 556, NULL }, + { "tcommaaccent", 278, NULL }, + { "o", 556, NULL }, + { "ordfeminine", 370, NULL }, + { "ring", 333, NULL }, + { "p", 556, NULL }, + { "q", 556, NULL }, + { "uhungarumlaut", 556, NULL }, + { "r", 333, NULL }, + { "twosuperior", 333, NULL }, + { "aacute", 556, NULL }, + { "s", 500, NULL }, + { "OE", 1000, NULL }, + { "t", 278, NULL }, + { "divide", 584, NULL }, + { "u", 556, NULL }, + { "Ccaron", 722, NULL }, + { "v", 500, NULL }, + { "w", 722, NULL }, + { "x", 500, NULL }, + { "y", 500, NULL }, + { "z", 500, NULL }, + { "Gbreve", 778, NULL }, + { "commaaccent", 250, NULL }, + { "hungarumlaut", 333, NULL }, + { "Idotaccent", 278, NULL }, + { "Nacute", 722, NULL }, + { "quotedbl", 355, NULL }, + { "gcommaaccent", 556, NULL }, + { "mu", 556, NULL }, + { "greaterequal", 549, NULL }, + { "Scaron", 667, NULL }, + { "Lslash", 556, NULL }, + { "semicolon", 278, NULL }, + { "oslash", 611, NULL }, + { "lessequal", 549, NULL }, + { "lozenge", 471, NULL }, + { "parenright", 333, NULL }, + { "ccaron", 500, NULL }, + { "Ecircumflex", 667, NULL }, + { "gbreve", 556, NULL }, + { "trademark", 1000, NULL }, + { "daggerdbl", 556, NULL }, + { "nacute", 556, NULL }, + { "macron", 333, NULL }, + { "Otilde", 778, NULL }, + { "Emacron", 667, NULL }, + { "ellipsis", 1000, NULL }, + { "scaron", 500, NULL }, + { "AE", 1000, NULL }, + { "Ucircumflex", 722, NULL }, + { "lslash", 222, NULL }, + { "quotedblleft", 333, NULL }, + { "guilsinglright", 333, NULL }, + { "hyphen", 333, NULL }, + { "quotesingle", 191, NULL }, + { "eight", 556, NULL }, + { "exclamdown", 333, NULL }, + { "endash", 556, NULL }, + { "oe", 944, NULL }, + { "Abreve", 667, NULL }, + { "Umacron", 722, NULL }, + { "ecircumflex", 556, NULL }, + { "Adieresis", 667, NULL }, + { "copyright", 737, NULL }, + { "Egrave", 667, NULL }, + { "slash", 278, NULL }, + { "Edieresis", 667, NULL }, + { "otilde", 556, NULL }, + { "Idieresis", 278, NULL }, + { "parenleft", 333, NULL }, + { "one", 556, NULL }, + { "emacron", 556, NULL }, + { "Odieresis", 778, NULL }, + { "ucircumflex", 556, NULL }, + { "bracketleft", 278, NULL }, + { "Ugrave", 722, NULL }, + { "quoteright", 222, NULL }, + { "Udieresis", 722, NULL }, + { "perthousand", 1000, NULL }, + { "Ydieresis", 667, NULL }, + { "umacron", 556, NULL }, + { "abreve", 556, NULL }, + { "Eacute", 667, NULL }, + { "adieresis", 556, NULL }, + { "egrave", 556, NULL }, + { "edieresis", 556, NULL }, + { "idieresis", 278, NULL }, + { "Eth", 722, NULL }, + { "ae", 889, NULL }, + { "asterisk", 389, NULL }, + { "odieresis", 556, NULL }, + { "Uacute", 722, NULL }, + { "ugrave", 556, NULL }, + { "nine", 556, NULL }, + { "five", 556, NULL }, + { "udieresis", 556, NULL }, + { "Zcaron", 611, NULL }, + { "Scommaaccent", 667, NULL }, + { "threequarters", 834, NULL }, + { "guillemotright", 556, NULL }, + { "Ccedilla", 722, NULL }, + { "ydieresis", 500, NULL }, + { "tilde", 333, NULL }, + { "at", 1015, NULL }, + { "eacute", 556, NULL }, + { "underscore", 556, NULL }, + { "Euro", 556, NULL }, + { "Dcroat", 722, NULL }, + { "multiply", 584, NULL }, + { "zero", 556, NULL }, + { "eth", 556, NULL }, + { "Scedilla", 667, NULL }, + { "Ograve", 778, NULL }, + { "Racute", 722, NULL }, + { "partialdiff", 476, NULL }, + { "uacute", 556, NULL }, + { "braceleft", 334, NULL }, + { "Thorn", 667, NULL }, + { "zcaron", 500, NULL }, + { "scommaaccent", 500, NULL }, + { "ccedilla", 500, NULL }, + { "Dcaron", 722, NULL }, + { "dcroat", 556, NULL }, + { "Ocircumflex", 778, NULL }, + { "Oacute", 778, NULL }, + { "scedilla", 500, NULL }, + { "ogonek", 333, NULL }, + { "ograve", 556, NULL }, + { "racute", 333, NULL }, + { "Tcaron", 611, NULL }, + { "Eogonek", 667, NULL }, + { "thorn", 556, NULL }, + { "degree", 400, NULL }, + { "registered", 737, NULL }, + { "radical", 453, NULL }, + { "Aring", 667, NULL }, + { "percent", 889, NULL }, + { "six", 556, NULL }, + { "paragraph", 537, NULL }, + { "dcaron", 643, NULL }, + { "Uogonek", 722, NULL }, + { "two", 556, NULL }, + { "summation", 600, NULL }, + { "Igrave", 278, NULL }, + { "Lacute", 556, NULL }, + { "ocircumflex", 556, NULL }, + { "oacute", 556, NULL }, + { "Uring", 722, NULL }, + { "Lcommaaccent", 556, NULL }, + { "tcaron", 317, NULL }, + { "eogonek", 556, NULL }, + { "Delta", 612, NULL }, + { "Ohungarumlaut", 778, NULL }, + { "asciicircum", 469, NULL }, + { "aring", 556, NULL }, + { "grave", 333, NULL }, + { "uogonek", 556, NULL }, + { "bracketright", 278, NULL }, + { "Iacute", 278, NULL }, + { "ampersand", 667, NULL }, + { "igrave", 278, NULL }, + { "lacute", 222, NULL }, + { "Ncaron", 722, NULL }, + { "plus", 584, NULL }, + { "uring", 556, NULL }, + { "quotesinglbase", 222, NULL }, + { "lcommaaccent", 222, NULL }, + { "Yacute", 667, NULL }, + { "ohungarumlaut", 556, NULL }, + { "threesuperior", 333, NULL }, + { "acute", 333, NULL }, + { "section", 556, NULL }, + { "dieresis", 333, NULL }, + { "iacute", 278, NULL }, + { "quotedblbase", 333, NULL }, + { "ncaron", 556, NULL }, + { "florin", 556, NULL }, + { "yacute", 500, NULL }, + { "Rcommaaccent", 722, NULL }, + { "fi", 500, NULL }, + { "fl", 500, NULL }, + { "Acircumflex", 667, NULL }, + { "Cacute", 722, NULL }, + { "Icircumflex", 278, NULL }, + { "guillemotleft", 556, NULL }, + { "germandbls", 611, NULL }, + { "Amacron", 667, NULL }, + { "seven", 556, NULL }, + { "Sacute", 667, NULL }, + { "ordmasculine", 365, NULL }, + { "dotlessi", 278, NULL }, + { "sterling", 556, NULL }, + { "notequal", 549, NULL }, + { "Imacron", 278, NULL }, + { "rcommaaccent", 333, NULL }, + { "Zdotaccent", 611, NULL }, + { "acircumflex", 556, NULL }, + { "cacute", 500, NULL }, + { "Ecaron", 667, NULL }, + { "icircumflex", 278, NULL }, + { "braceright", 334, NULL }, + { "quotedblright", 333, NULL }, + { "amacron", 556, NULL }, + { "sacute", 500, NULL }, + { "imacron", 278, NULL }, + { "cent", 556, NULL }, + { "currency", 556, NULL }, + { "logicalnot", 584, NULL }, + { "zdotaccent", 500, NULL }, + { "Atilde", 667, NULL }, + { "breve", 333, NULL }, + { "bar", 260, NULL }, + { "fraction", 167, NULL }, + { "less", 584, NULL }, + { "ecaron", 556, NULL }, + { "guilsinglleft", 333, NULL }, + { "exclam", 278, NULL }, + { "period", 278, NULL }, + { "Rcaron", 722, NULL }, + { "Kcommaaccent", 667, NULL }, + { "greater", 584, NULL }, + { "atilde", 556, NULL }, + { "brokenbar", 260, NULL }, + { "quoteleft", 222, NULL }, + { "Edotaccent", 667, NULL }, + { "onesuperior", 333, NULL } +}; + +static BuiltinFontWidth helveticaBoldWidthsTab[] = { + { "Ntilde", 722, NULL }, + { "rcaron", 389, NULL }, + { "kcommaaccent", 556, NULL }, + { "Ncommaaccent", 722, NULL }, + { "Zacute", 611, NULL }, + { "comma", 278, NULL }, + { "cedilla", 333, NULL }, + { "plusminus", 584, NULL }, + { "circumflex", 333, NULL }, + { "dotaccent", 333, NULL }, + { "edotaccent", 556, NULL }, + { "asciitilde", 584, NULL }, + { "colon", 333, NULL }, + { "onehalf", 834, NULL }, + { "dollar", 556, NULL }, + { "Lcaron", 611, NULL }, + { "ntilde", 611, NULL }, + { "Aogonek", 722, NULL }, + { "ncommaaccent", 611, NULL }, + { "minus", 584, NULL }, + { "Iogonek", 278, NULL }, + { "zacute", 500, NULL }, + { "yen", 556, NULL }, + { "space", 278, NULL }, + { "Omacron", 778, NULL }, + { "questiondown", 611, NULL }, + { "emdash", 1000, NULL }, + { "Agrave", 722, NULL }, + { "three", 556, NULL }, + { "numbersign", 556, NULL }, + { "lcaron", 400, NULL }, + { "A", 722, NULL }, + { "B", 722, NULL }, + { "C", 722, NULL }, + { "aogonek", 556, NULL }, + { "D", 722, NULL }, + { "E", 667, NULL }, + { "onequarter", 834, NULL }, + { "F", 611, NULL }, + { "G", 778, NULL }, + { "H", 722, NULL }, + { "I", 278, NULL }, + { "J", 556, NULL }, + { "K", 722, NULL }, + { "iogonek", 278, NULL }, + { "backslash", 278, NULL }, + { "L", 611, NULL }, + { "periodcentered", 278, NULL }, + { "M", 833, NULL }, + { "N", 722, NULL }, + { "omacron", 611, NULL }, + { "Tcommaaccent", 611, NULL }, + { "O", 778, NULL }, + { "P", 667, NULL }, + { "Q", 778, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "R", 722, NULL }, + { "Aacute", 722, NULL }, + { "caron", 333, NULL }, + { "S", 667, NULL }, + { "T", 611, NULL }, + { "U", 722, NULL }, + { "agrave", 556, NULL }, + { "V", 667, NULL }, + { "W", 944, NULL }, + { "X", 667, NULL }, + { "question", 611, NULL }, + { "equal", 584, NULL }, + { "Y", 667, NULL }, + { "Z", 611, NULL }, + { "four", 556, NULL }, + { "a", 556, NULL }, + { "Gcommaaccent", 778, NULL }, + { "b", 611, NULL }, + { "c", 556, NULL }, + { "d", 611, NULL }, + { "e", 556, NULL }, + { "f", 333, NULL }, + { "g", 611, NULL }, + { "bullet", 350, NULL }, + { "h", 611, NULL }, + { "i", 278, NULL }, + { "Oslash", 778, NULL }, + { "dagger", 556, NULL }, + { "j", 278, NULL }, + { "k", 556, NULL }, + { "l", 278, NULL }, + { "m", 889, NULL }, + { "n", 611, NULL }, + { "tcommaaccent", 333, NULL }, + { "o", 611, NULL }, + { "ordfeminine", 370, NULL }, + { "ring", 333, NULL }, + { "p", 611, NULL }, + { "q", 611, NULL }, + { "uhungarumlaut", 611, NULL }, + { "r", 389, NULL }, + { "twosuperior", 333, NULL }, + { "aacute", 556, NULL }, + { "s", 556, NULL }, + { "OE", 1000, NULL }, + { "t", 333, NULL }, + { "divide", 584, NULL }, + { "u", 611, NULL }, + { "Ccaron", 722, NULL }, + { "v", 556, NULL }, + { "w", 778, NULL }, + { "x", 556, NULL }, + { "y", 556, NULL }, + { "z", 500, NULL }, + { "Gbreve", 778, NULL }, + { "commaaccent", 250, NULL }, + { "hungarumlaut", 333, NULL }, + { "Idotaccent", 278, NULL }, + { "Nacute", 722, NULL }, + { "quotedbl", 474, NULL }, + { "gcommaaccent", 611, NULL }, + { "mu", 611, NULL }, + { "greaterequal", 549, NULL }, + { "Scaron", 667, NULL }, + { "Lslash", 611, NULL }, + { "semicolon", 333, NULL }, + { "oslash", 611, NULL }, + { "lessequal", 549, NULL }, + { "lozenge", 494, NULL }, + { "parenright", 333, NULL }, + { "ccaron", 556, NULL }, + { "Ecircumflex", 667, NULL }, + { "gbreve", 611, NULL }, + { "trademark", 1000, NULL }, + { "daggerdbl", 556, NULL }, + { "nacute", 611, NULL }, + { "macron", 333, NULL }, + { "Otilde", 778, NULL }, + { "Emacron", 667, NULL }, + { "ellipsis", 1000, NULL }, + { "scaron", 556, NULL }, + { "AE", 1000, NULL }, + { "Ucircumflex", 722, NULL }, + { "lslash", 278, NULL }, + { "quotedblleft", 500, NULL }, + { "guilsinglright", 333, NULL }, + { "hyphen", 333, NULL }, + { "quotesingle", 238, NULL }, + { "eight", 556, NULL }, + { "exclamdown", 333, NULL }, + { "endash", 556, NULL }, + { "oe", 944, NULL }, + { "Abreve", 722, NULL }, + { "Umacron", 722, NULL }, + { "ecircumflex", 556, NULL }, + { "Adieresis", 722, NULL }, + { "copyright", 737, NULL }, + { "Egrave", 667, NULL }, + { "slash", 278, NULL }, + { "Edieresis", 667, NULL }, + { "otilde", 611, NULL }, + { "Idieresis", 278, NULL }, + { "parenleft", 333, NULL }, + { "one", 556, NULL }, + { "emacron", 556, NULL }, + { "Odieresis", 778, NULL }, + { "ucircumflex", 611, NULL }, + { "bracketleft", 333, NULL }, + { "Ugrave", 722, NULL }, + { "quoteright", 278, NULL }, + { "Udieresis", 722, NULL }, + { "perthousand", 1000, NULL }, + { "Ydieresis", 667, NULL }, + { "umacron", 611, NULL }, + { "abreve", 556, NULL }, + { "Eacute", 667, NULL }, + { "adieresis", 556, NULL }, + { "egrave", 556, NULL }, + { "edieresis", 556, NULL }, + { "idieresis", 278, NULL }, + { "Eth", 722, NULL }, + { "ae", 889, NULL }, + { "asterisk", 389, NULL }, + { "odieresis", 611, NULL }, + { "Uacute", 722, NULL }, + { "ugrave", 611, NULL }, + { "nine", 556, NULL }, + { "five", 556, NULL }, + { "udieresis", 611, NULL }, + { "Zcaron", 611, NULL }, + { "Scommaaccent", 667, NULL }, + { "threequarters", 834, NULL }, + { "guillemotright", 556, NULL }, + { "Ccedilla", 722, NULL }, + { "ydieresis", 556, NULL }, + { "tilde", 333, NULL }, + { "dbldaggerumlaut", 556, NULL }, + { "at", 975, NULL }, + { "eacute", 556, NULL }, + { "underscore", 556, NULL }, + { "Euro", 556, NULL }, + { "Dcroat", 722, NULL }, + { "multiply", 584, NULL }, + { "zero", 556, NULL }, + { "eth", 611, NULL }, + { "Scedilla", 667, NULL }, + { "Ograve", 778, NULL }, + { "Racute", 722, NULL }, + { "partialdiff", 494, NULL }, + { "uacute", 611, NULL }, + { "braceleft", 389, NULL }, + { "Thorn", 667, NULL }, + { "zcaron", 500, NULL }, + { "scommaaccent", 556, NULL }, + { "ccedilla", 556, NULL }, + { "Dcaron", 722, NULL }, + { "dcroat", 611, NULL }, + { "Ocircumflex", 778, NULL }, + { "Oacute", 778, NULL }, + { "scedilla", 556, NULL }, + { "ogonek", 333, NULL }, + { "ograve", 611, NULL }, + { "racute", 389, NULL }, + { "Tcaron", 611, NULL }, + { "Eogonek", 667, NULL }, + { "thorn", 611, NULL }, + { "degree", 400, NULL }, + { "registered", 737, NULL }, + { "radical", 549, NULL }, + { "Aring", 722, NULL }, + { "percent", 889, NULL }, + { "six", 556, NULL }, + { "paragraph", 556, NULL }, + { "dcaron", 743, NULL }, + { "Uogonek", 722, NULL }, + { "two", 556, NULL }, + { "summation", 600, NULL }, + { "Igrave", 278, NULL }, + { "Lacute", 611, NULL }, + { "ocircumflex", 611, NULL }, + { "oacute", 611, NULL }, + { "Uring", 722, NULL }, + { "Lcommaaccent", 611, NULL }, + { "tcaron", 389, NULL }, + { "eogonek", 556, NULL }, + { "Delta", 612, NULL }, + { "Ohungarumlaut", 778, NULL }, + { "asciicircum", 584, NULL }, + { "aring", 556, NULL }, + { "grave", 333, NULL }, + { "uogonek", 611, NULL }, + { "bracketright", 333, NULL }, + { "Iacute", 278, NULL }, + { "ampersand", 722, NULL }, + { "igrave", 278, NULL }, + { "lacute", 278, NULL }, + { "Ncaron", 722, NULL }, + { "plus", 584, NULL }, + { "uring", 611, NULL }, + { "quotesinglbase", 278, NULL }, + { "lcommaaccent", 278, NULL }, + { "Yacute", 667, NULL }, + { "ohungarumlaut", 611, NULL }, + { "threesuperior", 333, NULL }, + { "acute", 333, NULL }, + { "section", 556, NULL }, + { "dieresis", 333, NULL }, + { "iacute", 278, NULL }, + { "quotedblbase", 500, NULL }, + { "ncaron", 611, NULL }, + { "florin", 556, NULL }, + { "yacute", 556, NULL }, + { "Rcommaaccent", 722, NULL }, + { "fi", 611, NULL }, + { "fl", 611, NULL }, + { "Acircumflex", 722, NULL }, + { "Cacute", 722, NULL }, + { "Icircumflex", 278, NULL }, + { "guillemotleft", 556, NULL }, + { "germandbls", 611, NULL }, + { "Amacron", 722, NULL }, + { "seven", 556, NULL }, + { "Sacute", 667, NULL }, + { "ordmasculine", 365, NULL }, + { "dotlessi", 278, NULL }, + { "sterling", 556, NULL }, + { "notequal", 549, NULL }, + { "Imacron", 278, NULL }, + { "rcommaaccent", 389, NULL }, + { "Zdotaccent", 611, NULL }, + { "acircumflex", 556, NULL }, + { "cacute", 556, NULL }, + { "Ecaron", 667, NULL }, + { "icircumflex", 278, NULL }, + { "braceright", 389, NULL }, + { "quotedblright", 500, NULL }, + { "amacron", 556, NULL }, + { "sacute", 556, NULL }, + { "imacron", 278, NULL }, + { "cent", 556, NULL }, + { "currency", 556, NULL }, + { "logicalnot", 584, NULL }, + { "zdotaccent", 500, NULL }, + { "Atilde", 722, NULL }, + { "breve", 333, NULL }, + { "bar", 280, NULL }, + { "fraction", 167, NULL }, + { "less", 584, NULL }, + { "ecaron", 556, NULL }, + { "guilsinglleft", 333, NULL }, + { "exclam", 333, NULL }, + { "period", 278, NULL }, + { "Rcaron", 722, NULL }, + { "Kcommaaccent", 722, NULL }, + { "greater", 584, NULL }, + { "atilde", 556, NULL }, + { "brokenbar", 280, NULL }, + { "quoteleft", 278, NULL }, + { "Edotaccent", 667, NULL }, + { "onesuperior", 333, NULL } +}; + +static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = { + { "Ntilde", 722, NULL }, + { "rcaron", 389, NULL }, + { "kcommaaccent", 556, NULL }, + { "Ncommaaccent", 722, NULL }, + { "Zacute", 611, NULL }, + { "comma", 278, NULL }, + { "cedilla", 333, NULL }, + { "plusminus", 584, NULL }, + { "circumflex", 333, NULL }, + { "dotaccent", 333, NULL }, + { "edotaccent", 556, NULL }, + { "asciitilde", 584, NULL }, + { "colon", 333, NULL }, + { "onehalf", 834, NULL }, + { "dollar", 556, NULL }, + { "Lcaron", 611, NULL }, + { "ntilde", 611, NULL }, + { "Aogonek", 722, NULL }, + { "ncommaaccent", 611, NULL }, + { "minus", 584, NULL }, + { "Iogonek", 278, NULL }, + { "zacute", 500, NULL }, + { "yen", 556, NULL }, + { "space", 278, NULL }, + { "Omacron", 778, NULL }, + { "questiondown", 611, NULL }, + { "emdash", 1000, NULL }, + { "Agrave", 722, NULL }, + { "three", 556, NULL }, + { "numbersign", 556, NULL }, + { "lcaron", 400, NULL }, + { "A", 722, NULL }, + { "B", 722, NULL }, + { "C", 722, NULL }, + { "aogonek", 556, NULL }, + { "D", 722, NULL }, + { "E", 667, NULL }, + { "onequarter", 834, NULL }, + { "F", 611, NULL }, + { "G", 778, NULL }, + { "H", 722, NULL }, + { "I", 278, NULL }, + { "J", 556, NULL }, + { "K", 722, NULL }, + { "iogonek", 278, NULL }, + { "backslash", 278, NULL }, + { "L", 611, NULL }, + { "periodcentered", 278, NULL }, + { "M", 833, NULL }, + { "N", 722, NULL }, + { "omacron", 611, NULL }, + { "Tcommaaccent", 611, NULL }, + { "O", 778, NULL }, + { "P", 667, NULL }, + { "Q", 778, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "R", 722, NULL }, + { "Aacute", 722, NULL }, + { "caron", 333, NULL }, + { "S", 667, NULL }, + { "T", 611, NULL }, + { "U", 722, NULL }, + { "agrave", 556, NULL }, + { "V", 667, NULL }, + { "W", 944, NULL }, + { "X", 667, NULL }, + { "question", 611, NULL }, + { "equal", 584, NULL }, + { "Y", 667, NULL }, + { "Z", 611, NULL }, + { "four", 556, NULL }, + { "a", 556, NULL }, + { "Gcommaaccent", 778, NULL }, + { "b", 611, NULL }, + { "c", 556, NULL }, + { "d", 611, NULL }, + { "e", 556, NULL }, + { "f", 333, NULL }, + { "g", 611, NULL }, + { "bullet", 350, NULL }, + { "h", 611, NULL }, + { "i", 278, NULL }, + { "Oslash", 778, NULL }, + { "dagger", 556, NULL }, + { "j", 278, NULL }, + { "k", 556, NULL }, + { "l", 278, NULL }, + { "m", 889, NULL }, + { "n", 611, NULL }, + { "tcommaaccent", 333, NULL }, + { "o", 611, NULL }, + { "ordfeminine", 370, NULL }, + { "ring", 333, NULL }, + { "p", 611, NULL }, + { "q", 611, NULL }, + { "uhungarumlaut", 611, NULL }, + { "r", 389, NULL }, + { "twosuperior", 333, NULL }, + { "aacute", 556, NULL }, + { "s", 556, NULL }, + { "OE", 1000, NULL }, + { "t", 333, NULL }, + { "divide", 584, NULL }, + { "u", 611, NULL }, + { "Ccaron", 722, NULL }, + { "v", 556, NULL }, + { "w", 778, NULL }, + { "x", 556, NULL }, + { "y", 556, NULL }, + { "z", 500, NULL }, + { "Gbreve", 778, NULL }, + { "commaaccent", 250, NULL }, + { "hungarumlaut", 333, NULL }, + { "Idotaccent", 278, NULL }, + { "Nacute", 722, NULL }, + { "quotedbl", 474, NULL }, + { "gcommaaccent", 611, NULL }, + { "mu", 611, NULL }, + { "greaterequal", 549, NULL }, + { "Scaron", 667, NULL }, + { "Lslash", 611, NULL }, + { "semicolon", 333, NULL }, + { "oslash", 611, NULL }, + { "lessequal", 549, NULL }, + { "lozenge", 494, NULL }, + { "parenright", 333, NULL }, + { "ccaron", 556, NULL }, + { "Ecircumflex", 667, NULL }, + { "gbreve", 611, NULL }, + { "trademark", 1000, NULL }, + { "daggerdbl", 556, NULL }, + { "nacute", 611, NULL }, + { "macron", 333, NULL }, + { "Otilde", 778, NULL }, + { "Emacron", 667, NULL }, + { "ellipsis", 1000, NULL }, + { "scaron", 556, NULL }, + { "AE", 1000, NULL }, + { "Ucircumflex", 722, NULL }, + { "lslash", 278, NULL }, + { "quotedblleft", 500, NULL }, + { "guilsinglright", 333, NULL }, + { "hyphen", 333, NULL }, + { "quotesingle", 238, NULL }, + { "eight", 556, NULL }, + { "exclamdown", 333, NULL }, + { "endash", 556, NULL }, + { "oe", 944, NULL }, + { "Abreve", 722, NULL }, + { "Umacron", 722, NULL }, + { "ecircumflex", 556, NULL }, + { "Adieresis", 722, NULL }, + { "copyright", 737, NULL }, + { "Egrave", 667, NULL }, + { "slash", 278, NULL }, + { "Edieresis", 667, NULL }, + { "otilde", 611, NULL }, + { "Idieresis", 278, NULL }, + { "parenleft", 333, NULL }, + { "one", 556, NULL }, + { "emacron", 556, NULL }, + { "Odieresis", 778, NULL }, + { "ucircumflex", 611, NULL }, + { "bracketleft", 333, NULL }, + { "Ugrave", 722, NULL }, + { "quoteright", 278, NULL }, + { "Udieresis", 722, NULL }, + { "perthousand", 1000, NULL }, + { "Ydieresis", 667, NULL }, + { "umacron", 611, NULL }, + { "abreve", 556, NULL }, + { "Eacute", 667, NULL }, + { "adieresis", 556, NULL }, + { "egrave", 556, NULL }, + { "edieresis", 556, NULL }, + { "idieresis", 278, NULL }, + { "Eth", 722, NULL }, + { "ae", 889, NULL }, + { "asterisk", 389, NULL }, + { "odieresis", 611, NULL }, + { "Uacute", 722, NULL }, + { "ugrave", 611, NULL }, + { "nine", 556, NULL }, + { "five", 556, NULL }, + { "udieresis", 611, NULL }, + { "Zcaron", 611, NULL }, + { "Scommaaccent", 667, NULL }, + { "threequarters", 834, NULL }, + { "guillemotright", 556, NULL }, + { "Ccedilla", 722, NULL }, + { "ydieresis", 556, NULL }, + { "tilde", 333, NULL }, + { "at", 975, NULL }, + { "eacute", 556, NULL }, + { "underscore", 556, NULL }, + { "Euro", 556, NULL }, + { "Dcroat", 722, NULL }, + { "multiply", 584, NULL }, + { "zero", 556, NULL }, + { "eth", 611, NULL }, + { "Scedilla", 667, NULL }, + { "Ograve", 778, NULL }, + { "Racute", 722, NULL }, + { "partialdiff", 494, NULL }, + { "uacute", 611, NULL }, + { "braceleft", 389, NULL }, + { "Thorn", 667, NULL }, + { "zcaron", 500, NULL }, + { "scommaaccent", 556, NULL }, + { "ccedilla", 556, NULL }, + { "Dcaron", 722, NULL }, + { "dcroat", 611, NULL }, + { "Ocircumflex", 778, NULL }, + { "Oacute", 778, NULL }, + { "scedilla", 556, NULL }, + { "ogonek", 333, NULL }, + { "ograve", 611, NULL }, + { "racute", 389, NULL }, + { "Tcaron", 611, NULL }, + { "Eogonek", 667, NULL }, + { "thorn", 611, NULL }, + { "degree", 400, NULL }, + { "registered", 737, NULL }, + { "radical", 549, NULL }, + { "Aring", 722, NULL }, + { "percent", 889, NULL }, + { "six", 556, NULL }, + { "paragraph", 556, NULL }, + { "dcaron", 743, NULL }, + { "Uogonek", 722, NULL }, + { "two", 556, NULL }, + { "summation", 600, NULL }, + { "Igrave", 278, NULL }, + { "Lacute", 611, NULL }, + { "ocircumflex", 611, NULL }, + { "oacute", 611, NULL }, + { "Uring", 722, NULL }, + { "Lcommaaccent", 611, NULL }, + { "tcaron", 389, NULL }, + { "eogonek", 556, NULL }, + { "Delta", 612, NULL }, + { "Ohungarumlaut", 778, NULL }, + { "asciicircum", 584, NULL }, + { "aring", 556, NULL }, + { "grave", 333, NULL }, + { "uogonek", 611, NULL }, + { "bracketright", 333, NULL }, + { "Iacute", 278, NULL }, + { "ampersand", 722, NULL }, + { "igrave", 278, NULL }, + { "lacute", 278, NULL }, + { "Ncaron", 722, NULL }, + { "plus", 584, NULL }, + { "uring", 611, NULL }, + { "quotesinglbase", 278, NULL }, + { "lcommaaccent", 278, NULL }, + { "Yacute", 667, NULL }, + { "ohungarumlaut", 611, NULL }, + { "threesuperior", 333, NULL }, + { "acute", 333, NULL }, + { "section", 556, NULL }, + { "dieresis", 333, NULL }, + { "iacute", 278, NULL }, + { "quotedblbase", 500, NULL }, + { "ncaron", 611, NULL }, + { "florin", 556, NULL }, + { "yacute", 556, NULL }, + { "Rcommaaccent", 722, NULL }, + { "fi", 611, NULL }, + { "fl", 611, NULL }, + { "Acircumflex", 722, NULL }, + { "Cacute", 722, NULL }, + { "Icircumflex", 278, NULL }, + { "guillemotleft", 556, NULL }, + { "germandbls", 611, NULL }, + { "Amacron", 722, NULL }, + { "seven", 556, NULL }, + { "Sacute", 667, NULL }, + { "ordmasculine", 365, NULL }, + { "dotlessi", 278, NULL }, + { "sterling", 556, NULL }, + { "notequal", 549, NULL }, + { "Imacron", 278, NULL }, + { "rcommaaccent", 389, NULL }, + { "Zdotaccent", 611, NULL }, + { "acircumflex", 556, NULL }, + { "cacute", 556, NULL }, + { "Ecaron", 667, NULL }, + { "icircumflex", 278, NULL }, + { "braceright", 389, NULL }, + { "quotedblright", 500, NULL }, + { "amacron", 556, NULL }, + { "sacute", 556, NULL }, + { "imacron", 278, NULL }, + { "cent", 556, NULL }, + { "currency", 556, NULL }, + { "logicalnot", 584, NULL }, + { "zdotaccent", 500, NULL }, + { "Atilde", 722, NULL }, + { "breve", 333, NULL }, + { "bar", 280, NULL }, + { "fraction", 167, NULL }, + { "less", 584, NULL }, + { "ecaron", 556, NULL }, + { "guilsinglleft", 333, NULL }, + { "exclam", 333, NULL }, + { "period", 278, NULL }, + { "Rcaron", 722, NULL }, + { "Kcommaaccent", 722, NULL }, + { "greater", 584, NULL }, + { "atilde", 556, NULL }, + { "brokenbar", 280, NULL }, + { "quoteleft", 278, NULL }, + { "Edotaccent", 667, NULL }, + { "onesuperior", 333, NULL } +}; + +static BuiltinFontWidth helveticaObliqueWidthsTab[] = { + { "Ntilde", 722, NULL }, + { "rcaron", 333, NULL }, + { "kcommaaccent", 500, NULL }, + { "Ncommaaccent", 722, NULL }, + { "Zacute", 611, NULL }, + { "comma", 278, NULL }, + { "cedilla", 333, NULL }, + { "plusminus", 584, NULL }, + { "circumflex", 333, NULL }, + { "dotaccent", 333, NULL }, + { "edotaccent", 556, NULL }, + { "asciitilde", 584, NULL }, + { "colon", 278, NULL }, + { "onehalf", 834, NULL }, + { "dollar", 556, NULL }, + { "Lcaron", 556, NULL }, + { "ntilde", 556, NULL }, + { "Aogonek", 667, NULL }, + { "ncommaaccent", 556, NULL }, + { "minus", 584, NULL }, + { "Iogonek", 278, NULL }, + { "zacute", 500, NULL }, + { "yen", 556, NULL }, + { "space", 278, NULL }, + { "Omacron", 778, NULL }, + { "questiondown", 611, NULL }, + { "emdash", 1000, NULL }, + { "Agrave", 667, NULL }, + { "three", 556, NULL }, + { "numbersign", 556, NULL }, + { "lcaron", 299, NULL }, + { "A", 667, NULL }, + { "B", 667, NULL }, + { "C", 722, NULL }, + { "aogonek", 556, NULL }, + { "D", 722, NULL }, + { "E", 667, NULL }, + { "onequarter", 834, NULL }, + { "F", 611, NULL }, + { "G", 778, NULL }, + { "H", 722, NULL }, + { "I", 278, NULL }, + { "J", 500, NULL }, + { "K", 667, NULL }, + { "iogonek", 222, NULL }, + { "backslash", 278, NULL }, + { "L", 556, NULL }, + { "periodcentered", 278, NULL }, + { "M", 833, NULL }, + { "N", 722, NULL }, + { "omacron", 556, NULL }, + { "Tcommaaccent", 611, NULL }, + { "O", 778, NULL }, + { "P", 667, NULL }, + { "Q", 778, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "R", 722, NULL }, + { "Aacute", 667, NULL }, + { "caron", 333, NULL }, + { "S", 667, NULL }, + { "T", 611, NULL }, + { "U", 722, NULL }, + { "agrave", 556, NULL }, + { "V", 667, NULL }, + { "W", 944, NULL }, + { "X", 667, NULL }, + { "question", 556, NULL }, + { "equal", 584, NULL }, + { "Y", 667, NULL }, + { "Z", 611, NULL }, + { "four", 556, NULL }, + { "a", 556, NULL }, + { "Gcommaaccent", 778, NULL }, + { "b", 556, NULL }, + { "c", 500, NULL }, + { "d", 556, NULL }, + { "e", 556, NULL }, + { "f", 278, NULL }, + { "g", 556, NULL }, + { "bullet", 350, NULL }, + { "h", 556, NULL }, + { "i", 222, NULL }, + { "Oslash", 778, NULL }, + { "dagger", 556, NULL }, + { "j", 222, NULL }, + { "k", 500, NULL }, + { "l", 222, NULL }, + { "m", 833, NULL }, + { "n", 556, NULL }, + { "tcommaaccent", 278, NULL }, + { "o", 556, NULL }, + { "ordfeminine", 370, NULL }, + { "ring", 333, NULL }, + { "p", 556, NULL }, + { "q", 556, NULL }, + { "uhungarumlaut", 556, NULL }, + { "r", 333, NULL }, + { "twosuperior", 333, NULL }, + { "aacute", 556, NULL }, + { "s", 500, NULL }, + { "OE", 1000, NULL }, + { "t", 278, NULL }, + { "divide", 584, NULL }, + { "u", 556, NULL }, + { "Ccaron", 722, NULL }, + { "v", 500, NULL }, + { "w", 722, NULL }, + { "x", 500, NULL }, + { "y", 500, NULL }, + { "z", 500, NULL }, + { "Gbreve", 778, NULL }, + { "commaaccent", 250, NULL }, + { "hungarumlaut", 333, NULL }, + { "Idotaccent", 278, NULL }, + { "Nacute", 722, NULL }, + { "quotedbl", 355, NULL }, + { "gcommaaccent", 556, NULL }, + { "mu", 556, NULL }, + { "greaterequal", 549, NULL }, + { "Scaron", 667, NULL }, + { "Lslash", 556, NULL }, + { "semicolon", 278, NULL }, + { "oslash", 611, NULL }, + { "lessequal", 549, NULL }, + { "lozenge", 471, NULL }, + { "parenright", 333, NULL }, + { "ccaron", 500, NULL }, + { "Ecircumflex", 667, NULL }, + { "gbreve", 556, NULL }, + { "trademark", 1000, NULL }, + { "daggerdbl", 556, NULL }, + { "nacute", 556, NULL }, + { "macron", 333, NULL }, + { "Otilde", 778, NULL }, + { "Emacron", 667, NULL }, + { "ellipsis", 1000, NULL }, + { "scaron", 500, NULL }, + { "AE", 1000, NULL }, + { "Ucircumflex", 722, NULL }, + { "lslash", 222, NULL }, + { "quotedblleft", 333, NULL }, + { "guilsinglright", 333, NULL }, + { "hyphen", 333, NULL }, + { "quotesingle", 191, NULL }, + { "eight", 556, NULL }, + { "exclamdown", 333, NULL }, + { "endash", 556, NULL }, + { "oe", 944, NULL }, + { "Abreve", 667, NULL }, + { "Umacron", 722, NULL }, + { "ecircumflex", 556, NULL }, + { "Adieresis", 667, NULL }, + { "copyright", 737, NULL }, + { "Egrave", 667, NULL }, + { "slash", 278, NULL }, + { "Edieresis", 667, NULL }, + { "otilde", 556, NULL }, + { "Idieresis", 278, NULL }, + { "parenleft", 333, NULL }, + { "one", 556, NULL }, + { "emacron", 556, NULL }, + { "Odieresis", 778, NULL }, + { "ucircumflex", 556, NULL }, + { "bracketleft", 278, NULL }, + { "Ugrave", 722, NULL }, + { "quoteright", 222, NULL }, + { "Udieresis", 722, NULL }, + { "perthousand", 1000, NULL }, + { "Ydieresis", 667, NULL }, + { "umacron", 556, NULL }, + { "abreve", 556, NULL }, + { "Eacute", 667, NULL }, + { "adieresis", 556, NULL }, + { "egrave", 556, NULL }, + { "edieresis", 556, NULL }, + { "idieresis", 278, NULL }, + { "Eth", 722, NULL }, + { "ae", 889, NULL }, + { "asterisk", 389, NULL }, + { "odieresis", 556, NULL }, + { "Uacute", 722, NULL }, + { "ugrave", 556, NULL }, + { "nine", 556, NULL }, + { "five", 556, NULL }, + { "udieresis", 556, NULL }, + { "Zcaron", 611, NULL }, + { "Scommaaccent", 667, NULL }, + { "threequarters", 834, NULL }, + { "guillemotright", 556, NULL }, + { "Ccedilla", 722, NULL }, + { "ydieresis", 500, NULL }, + { "tilde", 333, NULL }, + { "at", 1015, NULL }, + { "eacute", 556, NULL }, + { "underscore", 556, NULL }, + { "Euro", 556, NULL }, + { "Dcroat", 722, NULL }, + { "multiply", 584, NULL }, + { "zero", 556, NULL }, + { "eth", 556, NULL }, + { "Scedilla", 667, NULL }, + { "Ograve", 778, NULL }, + { "Racute", 722, NULL }, + { "partialdiff", 476, NULL }, + { "uacute", 556, NULL }, + { "braceleft", 334, NULL }, + { "Thorn", 667, NULL }, + { "zcaron", 500, NULL }, + { "scommaaccent", 500, NULL }, + { "ccedilla", 500, NULL }, + { "Dcaron", 722, NULL }, + { "dcroat", 556, NULL }, + { "Ocircumflex", 778, NULL }, + { "Oacute", 778, NULL }, + { "scedilla", 500, NULL }, + { "ogonek", 333, NULL }, + { "ograve", 556, NULL }, + { "racute", 333, NULL }, + { "Tcaron", 611, NULL }, + { "Eogonek", 667, NULL }, + { "thorn", 556, NULL }, + { "degree", 400, NULL }, + { "registered", 737, NULL }, + { "radical", 453, NULL }, + { "Aring", 667, NULL }, + { "percent", 889, NULL }, + { "six", 556, NULL }, + { "paragraph", 537, NULL }, + { "dcaron", 643, NULL }, + { "Uogonek", 722, NULL }, + { "two", 556, NULL }, + { "summation", 600, NULL }, + { "Igrave", 278, NULL }, + { "Lacute", 556, NULL }, + { "ocircumflex", 556, NULL }, + { "oacute", 556, NULL }, + { "Uring", 722, NULL }, + { "Lcommaaccent", 556, NULL }, + { "tcaron", 317, NULL }, + { "eogonek", 556, NULL }, + { "Delta", 612, NULL }, + { "Ohungarumlaut", 778, NULL }, + { "asciicircum", 469, NULL }, + { "aring", 556, NULL }, + { "grave", 333, NULL }, + { "uogonek", 556, NULL }, + { "bracketright", 278, NULL }, + { "Iacute", 278, NULL }, + { "ampersand", 667, NULL }, + { "igrave", 278, NULL }, + { "lacute", 222, NULL }, + { "Ncaron", 722, NULL }, + { "plus", 584, NULL }, + { "uring", 556, NULL }, + { "quotesinglbase", 222, NULL }, + { "lcommaaccent", 222, NULL }, + { "Yacute", 667, NULL }, + { "ohungarumlaut", 556, NULL }, + { "threesuperior", 333, NULL }, + { "acute", 333, NULL }, + { "section", 556, NULL }, + { "dieresis", 333, NULL }, + { "iacute", 278, NULL }, + { "quotedblbase", 333, NULL }, + { "ncaron", 556, NULL }, + { "florin", 556, NULL }, + { "yacute", 500, NULL }, + { "Rcommaaccent", 722, NULL }, + { "fi", 500, NULL }, + { "fl", 500, NULL }, + { "Acircumflex", 667, NULL }, + { "Cacute", 722, NULL }, + { "Icircumflex", 278, NULL }, + { "guillemotleft", 556, NULL }, + { "germandbls", 611, NULL }, + { "Amacron", 667, NULL }, + { "seven", 556, NULL }, + { "Sacute", 667, NULL }, + { "ordmasculine", 365, NULL }, + { "dotlessi", 278, NULL }, + { "sterling", 556, NULL }, + { "notequal", 549, NULL }, + { "Imacron", 278, NULL }, + { "rcommaaccent", 333, NULL }, + { "Zdotaccent", 611, NULL }, + { "acircumflex", 556, NULL }, + { "cacute", 500, NULL }, + { "Ecaron", 667, NULL }, + { "icircumflex", 278, NULL }, + { "braceright", 334, NULL }, + { "quotedblright", 333, NULL }, + { "amacron", 556, NULL }, + { "sacute", 500, NULL }, + { "imacron", 278, NULL }, + { "cent", 556, NULL }, + { "currency", 556, NULL }, + { "logicalnot", 584, NULL }, + { "zdotaccent", 500, NULL }, + { "Atilde", 667, NULL }, + { "breve", 333, NULL }, + { "bar", 260, NULL }, + { "fraction", 167, NULL }, + { "less", 584, NULL }, + { "ecaron", 556, NULL }, + { "guilsinglleft", 333, NULL }, + { "exclam", 278, NULL }, + { "period", 278, NULL }, + { "Rcaron", 722, NULL }, + { "Kcommaaccent", 667, NULL }, + { "greater", 584, NULL }, + { "atilde", 556, NULL }, + { "brokenbar", 260, NULL }, + { "quoteleft", 222, NULL }, + { "Edotaccent", 667, NULL }, + { "onesuperior", 333, NULL } +}; + +static BuiltinFontWidth symbolWidthsTab[] = { + { "bracketleftex", 384, NULL }, + { "alpha", 631, NULL }, + { "union", 768, NULL }, + { "infinity", 713, NULL }, + { "comma", 250, NULL }, + { "copyrightsans", 790, NULL }, + { "plusminus", 549, NULL }, + { "arrowup", 603, NULL }, + { "apple", 790, NULL }, + { "parenleftbt", 384, NULL }, + { "notelement", 713, NULL }, + { "colon", 278, NULL }, + { "beta", 549, NULL }, + { "braceleftbt", 494, NULL }, + { "Lambda", 686, NULL }, + { "Phi", 763, NULL }, + { "minus", 549, NULL }, + { "space", 250, NULL }, + { "Sigma", 592, NULL }, + { "approxequal", 549, NULL }, + { "minute", 247, NULL }, + { "circleplus", 768, NULL }, + { "Omicron", 722, NULL }, + { "three", 500, NULL }, + { "numbersign", 500, NULL }, + { "lambda", 549, NULL }, + { "phi", 521, NULL }, + { "aleph", 823, NULL }, + { "Tau", 611, NULL }, + { "spade", 753, NULL }, + { "logicaland", 603, NULL }, + { "sigma", 603, NULL }, + { "propersuperset", 713, NULL }, + { "omicron", 549, NULL }, + { "question", 444, NULL }, + { "equal", 549, NULL }, + { "Epsilon", 611, NULL }, + { "emptyset", 823, NULL }, + { "diamond", 753, NULL }, + { "four", 500, NULL }, + { "Mu", 889, NULL }, + { "parenlefttp", 384, NULL }, + { "club", 753, NULL }, + { "bullet", 460, NULL }, + { "Omega", 768, NULL }, + { "tau", 439, NULL }, + { "Upsilon", 690, NULL }, + { "bracelefttp", 494, NULL }, + { "heart", 753, NULL }, + { "divide", 549, NULL }, + { "epsilon", 439, NULL }, + { "logicalor", 603, NULL }, + { "parenleftex", 384, NULL }, + { "greaterequal", 549, NULL }, + { "mu", 576, NULL }, + { "Nu", 722, NULL }, + { "therefore", 863, NULL }, + { "notsubset", 713, NULL }, + { "omega", 686, NULL }, + { "semicolon", 278, NULL }, + { "element", 713, NULL }, + { "upsilon", 576, NULL }, + { "existential", 549, NULL }, + { "integralbt", 686, NULL }, + { "lessequal", 549, NULL }, + { "phi1", 603, NULL }, + { "lozenge", 494, NULL }, + { "trademarkserif", 890, NULL }, + { "parenright", 333, NULL }, + { "reflexsuperset", 713, NULL }, + { "sigma1", 439, NULL }, + { "nu", 521, NULL }, + { "Gamma", 603, NULL }, + { "angleright", 329, NULL }, + { "ellipsis", 1000, NULL }, + { "Rho", 556, NULL }, + { "parenrightbt", 384, NULL }, + { "radicalex", 500, NULL }, + { "eight", 500, NULL }, + { "angleleft", 329, NULL }, + { "arrowdbldown", 603, NULL }, + { "congruent", 549, NULL }, + { "Theta", 741, NULL }, + { "intersection", 768, NULL }, + { "Pi", 768, NULL }, + { "slash", 278, NULL }, + { "registerserif", 790, NULL }, + { "parenleft", 333, NULL }, + { "one", 500, NULL }, + { "gamma", 411, NULL }, + { "bracketleft", 333, NULL }, + { "rho", 549, NULL }, + { "circlemultiply", 768, NULL }, + { "Chi", 722, NULL }, + { "theta", 521, NULL }, + { "pi", 549, NULL }, + { "integraltp", 686, NULL }, + { "Eta", 722, NULL }, + { "product", 823, NULL }, + { "nine", 500, NULL }, + { "five", 500, NULL }, + { "propersubset", 713, NULL }, + { "bracketrightbt", 384, NULL }, + { "trademarksans", 786, NULL }, + { "dotmath", 250, NULL }, + { "integralex", 686, NULL }, + { "chi", 549, NULL }, + { "parenrighttp", 384, NULL }, + { "eta", 603, NULL }, + { "underscore", 500, NULL }, + { "Euro", 750, NULL }, + { "multiply", 549, NULL }, + { "zero", 500, NULL }, + { "partialdiff", 494, NULL }, + { "angle", 768, NULL }, + { "arrowdblleft", 987, NULL }, + { "braceleft", 480, NULL }, + { "parenrightex", 384, NULL }, + { "Rfraktur", 795, NULL }, + { "Zeta", 611, NULL }, + { "braceex", 494, NULL }, + { "arrowdblup", 603, NULL }, + { "arrowdown", 603, NULL }, + { "Ifraktur", 686, NULL }, + { "degree", 400, NULL }, + { "Iota", 333, NULL }, + { "perpendicular", 658, NULL }, + { "radical", 549, NULL }, + { "asteriskmath", 500, NULL }, + { "percent", 833, NULL }, + { "zeta", 494, NULL }, + { "six", 500, NULL }, + { "two", 500, NULL }, + { "weierstrass", 987, NULL }, + { "summation", 713, NULL }, + { "bracketrighttp", 384, NULL }, + { "carriagereturn", 658, NULL }, + { "suchthat", 439, NULL }, + { "arrowvertex", 603, NULL }, + { "Delta", 612, NULL }, + { "iota", 329, NULL }, + { "arrowhorizex", 1000, NULL }, + { "bracketrightex", 384, NULL }, + { "bracketright", 333, NULL }, + { "ampersand", 778, NULL }, + { "plus", 549, NULL }, + { "proportional", 713, NULL }, + { "delta", 494, NULL }, + { "copyrightserif", 790, NULL }, + { "bracerightmid", 494, NULL }, + { "arrowleft", 987, NULL }, + { "second", 411, NULL }, + { "arrowdblboth", 1042, NULL }, + { "florin", 500, NULL }, + { "Psi", 795, NULL }, + { "bracerightbt", 494, NULL }, + { "bracketleftbt", 384, NULL }, + { "seven", 500, NULL }, + { "braceleftmid", 494, NULL }, + { "notequal", 549, NULL }, + { "psi", 686, NULL }, + { "equivalence", 549, NULL }, + { "universal", 713, NULL }, + { "arrowdblright", 987, NULL }, + { "braceright", 480, NULL }, + { "reflexsubset", 713, NULL }, + { "Xi", 645, NULL }, + { "theta1", 631, NULL }, + { "logicalnot", 713, NULL }, + { "Kappa", 722, NULL }, + { "similar", 549, NULL }, + { "bar", 200, NULL }, + { "fraction", 167, NULL }, + { "less", 549, NULL }, + { "registersans", 790, NULL }, + { "omega1", 713, NULL }, + { "exclam", 333, NULL }, + { "Upsilon1", 620, NULL }, + { "bracerighttp", 494, NULL }, + { "xi", 493, NULL }, + { "period", 250, NULL }, + { "Alpha", 722, NULL }, + { "arrowright", 987, NULL }, + { "greater", 549, NULL }, + { "bracketlefttp", 384, NULL }, + { "kappa", 549, NULL }, + { "gradient", 713, NULL }, + { "integral", 274, NULL }, + { "arrowboth", 1042, NULL }, + { "Beta", 667, NULL } +}; + +static BuiltinFontWidth timesBoldWidthsTab[] = { + { "Ntilde", 722, NULL }, + { "rcaron", 444, NULL }, + { "kcommaaccent", 556, NULL }, + { "Ncommaaccent", 722, NULL }, + { "Zacute", 667, NULL }, + { "comma", 250, NULL }, + { "cedilla", 333, NULL }, + { "plusminus", 570, NULL }, + { "circumflex", 333, NULL }, + { "dotaccent", 333, NULL }, + { "edotaccent", 444, NULL }, + { "asciitilde", 520, NULL }, + { "colon", 333, NULL }, + { "onehalf", 750, NULL }, + { "dollar", 500, NULL }, + { "Lcaron", 667, NULL }, + { "ntilde", 556, NULL }, + { "Aogonek", 722, NULL }, + { "ncommaaccent", 556, NULL }, + { "minus", 570, NULL }, + { "Iogonek", 389, NULL }, + { "zacute", 444, NULL }, + { "yen", 500, NULL }, + { "space", 250, NULL }, + { "Omacron", 778, NULL }, + { "questiondown", 500, NULL }, + { "emdash", 1000, NULL }, + { "Agrave", 722, NULL }, + { "three", 500, NULL }, + { "numbersign", 500, NULL }, + { "lcaron", 394, NULL }, + { "A", 722, NULL }, + { "B", 667, NULL }, + { "C", 722, NULL }, + { "aogonek", 500, NULL }, + { "D", 722, NULL }, + { "E", 667, NULL }, + { "onequarter", 750, NULL }, + { "F", 611, NULL }, + { "G", 778, NULL }, + { "H", 778, NULL }, + { "I", 389, NULL }, + { "J", 500, NULL }, + { "K", 778, NULL }, + { "iogonek", 278, NULL }, + { "backslash", 278, NULL }, + { "L", 667, NULL }, + { "periodcentered", 250, NULL }, + { "M", 944, NULL }, + { "N", 722, NULL }, + { "omacron", 500, NULL }, + { "Tcommaaccent", 667, NULL }, + { "O", 778, NULL }, + { "P", 611, NULL }, + { "Q", 778, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "R", 722, NULL }, + { "Aacute", 722, NULL }, + { "caron", 333, NULL }, + { "S", 556, NULL }, + { "T", 667, NULL }, + { "U", 722, NULL }, + { "agrave", 500, NULL }, + { "V", 722, NULL }, + { "W", 1000, NULL }, + { "X", 722, NULL }, + { "question", 500, NULL }, + { "equal", 570, NULL }, + { "Y", 722, NULL }, + { "Z", 667, NULL }, + { "four", 500, NULL }, + { "a", 500, NULL }, + { "Gcommaaccent", 778, NULL }, + { "b", 556, NULL }, + { "c", 444, NULL }, + { "d", 556, NULL }, + { "e", 444, NULL }, + { "f", 333, NULL }, + { "g", 500, NULL }, + { "bullet", 350, NULL }, + { "h", 556, NULL }, + { "i", 278, NULL }, + { "Oslash", 778, NULL }, + { "dagger", 500, NULL }, + { "j", 333, NULL }, + { "k", 556, NULL }, + { "l", 278, NULL }, + { "m", 833, NULL }, + { "n", 556, NULL }, + { "tcommaaccent", 333, NULL }, + { "o", 500, NULL }, + { "ordfeminine", 300, NULL }, + { "ring", 333, NULL }, + { "p", 556, NULL }, + { "q", 556, NULL }, + { "uhungarumlaut", 556, NULL }, + { "r", 444, NULL }, + { "twosuperior", 300, NULL }, + { "aacute", 500, NULL }, + { "s", 389, NULL }, + { "OE", 1000, NULL }, + { "t", 333, NULL }, + { "divide", 570, NULL }, + { "u", 556, NULL }, + { "Ccaron", 722, NULL }, + { "v", 500, NULL }, + { "w", 722, NULL }, + { "x", 500, NULL }, + { "y", 500, NULL }, + { "z", 444, NULL }, + { "Gbreve", 778, NULL }, + { "commaaccent", 250, NULL }, + { "hungarumlaut", 333, NULL }, + { "Idotaccent", 389, NULL }, + { "Nacute", 722, NULL }, + { "quotedbl", 555, NULL }, + { "gcommaaccent", 500, NULL }, + { "mu", 556, NULL }, + { "greaterequal", 549, NULL }, + { "Scaron", 556, NULL }, + { "Lslash", 667, NULL }, + { "semicolon", 333, NULL }, + { "oslash", 500, NULL }, + { "lessequal", 549, NULL }, + { "lozenge", 494, NULL }, + { "parenright", 333, NULL }, + { "ccaron", 444, NULL }, + { "Ecircumflex", 667, NULL }, + { "gbreve", 500, NULL }, + { "trademark", 1000, NULL }, + { "daggerdbl", 500, NULL }, + { "nacute", 556, NULL }, + { "macron", 333, NULL }, + { "Otilde", 778, NULL }, + { "Emacron", 667, NULL }, + { "ellipsis", 1000, NULL }, + { "scaron", 389, NULL }, + { "AE", 1000, NULL }, + { "Ucircumflex", 722, NULL }, + { "lslash", 278, NULL }, + { "quotedblleft", 500, NULL }, + { "guilsinglright", 333, NULL }, + { "hyphen", 333, NULL }, + { "quotesingle", 278, NULL }, + { "eight", 500, NULL }, + { "exclamdown", 333, NULL }, + { "endash", 500, NULL }, + { "oe", 722, NULL }, + { "Abreve", 722, NULL }, + { "Umacron", 722, NULL }, + { "ecircumflex", 444, NULL }, + { "Adieresis", 722, NULL }, + { "copyright", 747, NULL }, + { "Egrave", 667, NULL }, + { "slash", 278, NULL }, + { "Edieresis", 667, NULL }, + { "otilde", 500, NULL }, + { "Idieresis", 389, NULL }, + { "parenleft", 333, NULL }, + { "one", 500, NULL }, + { "emacron", 444, NULL }, + { "Odieresis", 778, NULL }, + { "ucircumflex", 556, NULL }, + { "bracketleft", 333, NULL }, + { "Ugrave", 722, NULL }, + { "quoteright", 333, NULL }, + { "Udieresis", 722, NULL }, + { "perthousand", 1000, NULL }, + { "Ydieresis", 722, NULL }, + { "umacron", 556, NULL }, + { "abreve", 500, NULL }, + { "Eacute", 667, NULL }, + { "adieresis", 500, NULL }, + { "egrave", 444, NULL }, + { "edieresis", 444, NULL }, + { "idieresis", 278, NULL }, + { "Eth", 722, NULL }, + { "ae", 722, NULL }, + { "asterisk", 500, NULL }, + { "odieresis", 500, NULL }, + { "Uacute", 722, NULL }, + { "ugrave", 556, NULL }, + { "nine", 500, NULL }, + { "five", 500, NULL }, + { "udieresis", 556, NULL }, + { "Zcaron", 667, NULL }, + { "Scommaaccent", 556, NULL }, + { "threequarters", 750, NULL }, + { "guillemotright", 500, NULL }, + { "Ccedilla", 722, NULL }, + { "ydieresis", 500, NULL }, + { "tilde", 333, NULL }, + { "at", 930, NULL }, + { "eacute", 444, NULL }, + { "underscore", 500, NULL }, + { "Euro", 500, NULL }, + { "Dcroat", 722, NULL }, + { "multiply", 570, NULL }, + { "zero", 500, NULL }, + { "eth", 500, NULL }, + { "Scedilla", 556, NULL }, + { "Ograve", 778, NULL }, + { "Racute", 722, NULL }, + { "partialdiff", 494, NULL }, + { "uacute", 556, NULL }, + { "braceleft", 394, NULL }, + { "Thorn", 611, NULL }, + { "zcaron", 444, NULL }, + { "scommaaccent", 389, NULL }, + { "ccedilla", 444, NULL }, + { "Dcaron", 722, NULL }, + { "dcroat", 556, NULL }, + { "Ocircumflex", 778, NULL }, + { "Oacute", 778, NULL }, + { "scedilla", 389, NULL }, + { "ogonek", 333, NULL }, + { "ograve", 500, NULL }, + { "racute", 444, NULL }, + { "Tcaron", 667, NULL }, + { "Eogonek", 667, NULL }, + { "thorn", 556, NULL }, + { "degree", 400, NULL }, + { "registered", 747, NULL }, + { "radical", 549, NULL }, + { "Aring", 722, NULL }, + { "percent", 1000, NULL }, + { "six", 500, NULL }, + { "paragraph", 540, NULL }, + { "dcaron", 672, NULL }, + { "Uogonek", 722, NULL }, + { "two", 500, NULL }, + { "summation", 600, NULL }, + { "Igrave", 389, NULL }, + { "Lacute", 667, NULL }, + { "ocircumflex", 500, NULL }, + { "oacute", 500, NULL }, + { "Uring", 722, NULL }, + { "Lcommaaccent", 667, NULL }, + { "tcaron", 416, NULL }, + { "eogonek", 444, NULL }, + { "Delta", 612, NULL }, + { "Ohungarumlaut", 778, NULL }, + { "asciicircum", 581, NULL }, + { "aring", 500, NULL }, + { "grave", 333, NULL }, + { "uogonek", 556, NULL }, + { "bracketright", 333, NULL }, + { "Iacute", 389, NULL }, + { "ampersand", 833, NULL }, + { "igrave", 278, NULL }, + { "lacute", 278, NULL }, + { "Ncaron", 722, NULL }, + { "plus", 570, NULL }, + { "uring", 556, NULL }, + { "quotesinglbase", 333, NULL }, + { "lcommaaccent", 278, NULL }, + { "Yacute", 722, NULL }, + { "ohungarumlaut", 500, NULL }, + { "threesuperior", 300, NULL }, + { "acute", 333, NULL }, + { "section", 500, NULL }, + { "dieresis", 333, NULL }, + { "iacute", 278, NULL }, + { "quotedblbase", 500, NULL }, + { "ncaron", 556, NULL }, + { "florin", 500, NULL }, + { "yacute", 500, NULL }, + { "Rcommaaccent", 722, NULL }, + { "fi", 556, NULL }, + { "fl", 556, NULL }, + { "Acircumflex", 722, NULL }, + { "Cacute", 722, NULL }, + { "Icircumflex", 389, NULL }, + { "guillemotleft", 500, NULL }, + { "germandbls", 556, NULL }, + { "Amacron", 722, NULL }, + { "seven", 500, NULL }, + { "Sacute", 556, NULL }, + { "ordmasculine", 330, NULL }, + { "dotlessi", 278, NULL }, + { "sterling", 500, NULL }, + { "notequal", 549, NULL }, + { "Imacron", 389, NULL }, + { "rcommaaccent", 444, NULL }, + { "Zdotaccent", 667, NULL }, + { "acircumflex", 500, NULL }, + { "cacute", 444, NULL }, + { "Ecaron", 667, NULL }, + { "icircumflex", 278, NULL }, + { "braceright", 394, NULL }, + { "quotedblright", 500, NULL }, + { "amacron", 500, NULL }, + { "sacute", 389, NULL }, + { "imacron", 278, NULL }, + { "cent", 500, NULL }, + { "currency", 500, NULL }, + { "logicalnot", 570, NULL }, + { "zdotaccent", 444, NULL }, + { "Atilde", 722, NULL }, + { "breve", 333, NULL }, + { "bar", 220, NULL }, + { "fraction", 167, NULL }, + { "less", 570, NULL }, + { "ecaron", 444, NULL }, + { "guilsinglleft", 333, NULL }, + { "exclam", 333, NULL }, + { "period", 250, NULL }, + { "Rcaron", 722, NULL }, + { "Kcommaaccent", 778, NULL }, + { "greater", 570, NULL }, + { "atilde", 500, NULL }, + { "brokenbar", 220, NULL }, + { "quoteleft", 333, NULL }, + { "Edotaccent", 667, NULL }, + { "onesuperior", 300, NULL } +}; + +static BuiltinFontWidth timesBoldItalicWidthsTab[] = { + { "Ntilde", 722, NULL }, + { "rcaron", 389, NULL }, + { "kcommaaccent", 500, NULL }, + { "Ncommaaccent", 722, NULL }, + { "Zacute", 611, NULL }, + { "comma", 250, NULL }, + { "cedilla", 333, NULL }, + { "plusminus", 570, NULL }, + { "circumflex", 333, NULL }, + { "dotaccent", 333, NULL }, + { "edotaccent", 444, NULL }, + { "asciitilde", 570, NULL }, + { "colon", 333, NULL }, + { "onehalf", 750, NULL }, + { "dollar", 500, NULL }, + { "Lcaron", 611, NULL }, + { "ntilde", 556, NULL }, + { "Aogonek", 667, NULL }, + { "ncommaaccent", 556, NULL }, + { "minus", 606, NULL }, + { "Iogonek", 389, NULL }, + { "zacute", 389, NULL }, + { "yen", 500, NULL }, + { "space", 250, NULL }, + { "Omacron", 722, NULL }, + { "questiondown", 500, NULL }, + { "emdash", 1000, NULL }, + { "Agrave", 667, NULL }, + { "three", 500, NULL }, + { "numbersign", 500, NULL }, + { "lcaron", 382, NULL }, + { "A", 667, NULL }, + { "B", 667, NULL }, + { "C", 667, NULL }, + { "aogonek", 500, NULL }, + { "D", 722, NULL }, + { "E", 667, NULL }, + { "onequarter", 750, NULL }, + { "F", 667, NULL }, + { "G", 722, NULL }, + { "H", 778, NULL }, + { "I", 389, NULL }, + { "J", 500, NULL }, + { "K", 667, NULL }, + { "iogonek", 278, NULL }, + { "backslash", 278, NULL }, + { "L", 611, NULL }, + { "periodcentered", 250, NULL }, + { "M", 889, NULL }, + { "N", 722, NULL }, + { "omacron", 500, NULL }, + { "Tcommaaccent", 611, NULL }, + { "O", 722, NULL }, + { "P", 611, NULL }, + { "Q", 722, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "R", 667, NULL }, + { "Aacute", 667, NULL }, + { "caron", 333, NULL }, + { "S", 556, NULL }, + { "T", 611, NULL }, + { "U", 722, NULL }, + { "agrave", 500, NULL }, + { "V", 667, NULL }, + { "W", 889, NULL }, + { "X", 667, NULL }, + { "question", 500, NULL }, + { "equal", 570, NULL }, + { "Y", 611, NULL }, + { "Z", 611, NULL }, + { "four", 500, NULL }, + { "a", 500, NULL }, + { "Gcommaaccent", 722, NULL }, + { "b", 500, NULL }, + { "c", 444, NULL }, + { "d", 500, NULL }, + { "e", 444, NULL }, + { "f", 333, NULL }, + { "g", 500, NULL }, + { "bullet", 350, NULL }, + { "h", 556, NULL }, + { "i", 278, NULL }, + { "Oslash", 722, NULL }, + { "dagger", 500, NULL }, + { "j", 278, NULL }, + { "k", 500, NULL }, + { "l", 278, NULL }, + { "m", 778, NULL }, + { "n", 556, NULL }, + { "tcommaaccent", 278, NULL }, + { "o", 500, NULL }, + { "ordfeminine", 266, NULL }, + { "ring", 333, NULL }, + { "p", 500, NULL }, + { "q", 500, NULL }, + { "uhungarumlaut", 556, NULL }, + { "r", 389, NULL }, + { "twosuperior", 300, NULL }, + { "aacute", 500, NULL }, + { "s", 389, NULL }, + { "OE", 944, NULL }, + { "t", 278, NULL }, + { "divide", 570, NULL }, + { "u", 556, NULL }, + { "Ccaron", 667, NULL }, + { "v", 444, NULL }, + { "w", 667, NULL }, + { "x", 500, NULL }, + { "y", 444, NULL }, + { "z", 389, NULL }, + { "Gbreve", 722, NULL }, + { "commaaccent", 250, NULL }, + { "hungarumlaut", 333, NULL }, + { "Idotaccent", 389, NULL }, + { "Nacute", 722, NULL }, + { "quotedbl", 555, NULL }, + { "gcommaaccent", 500, NULL }, + { "mu", 576, NULL }, + { "greaterequal", 549, NULL }, + { "Scaron", 556, NULL }, + { "Lslash", 611, NULL }, + { "semicolon", 333, NULL }, + { "oslash", 500, NULL }, + { "lessequal", 549, NULL }, + { "lozenge", 494, NULL }, + { "parenright", 333, NULL }, + { "ccaron", 444, NULL }, + { "Ecircumflex", 667, NULL }, + { "gbreve", 500, NULL }, + { "trademark", 1000, NULL }, + { "daggerdbl", 500, NULL }, + { "nacute", 556, NULL }, + { "macron", 333, NULL }, + { "Otilde", 722, NULL }, + { "Emacron", 667, NULL }, + { "ellipsis", 1000, NULL }, + { "scaron", 389, NULL }, + { "AE", 944, NULL }, + { "Ucircumflex", 722, NULL }, + { "lslash", 278, NULL }, + { "quotedblleft", 500, NULL }, + { "guilsinglright", 333, NULL }, + { "hyphen", 333, NULL }, + { "quotesingle", 278, NULL }, + { "eight", 500, NULL }, + { "exclamdown", 389, NULL }, + { "endash", 500, NULL }, + { "oe", 722, NULL }, + { "Abreve", 667, NULL }, + { "Umacron", 722, NULL }, + { "ecircumflex", 444, NULL }, + { "Adieresis", 667, NULL }, + { "copyright", 747, NULL }, + { "Egrave", 667, NULL }, + { "slash", 278, NULL }, + { "Edieresis", 667, NULL }, + { "otilde", 500, NULL }, + { "Idieresis", 389, NULL }, + { "parenleft", 333, NULL }, + { "one", 500, NULL }, + { "emacron", 444, NULL }, + { "Odieresis", 722, NULL }, + { "ucircumflex", 556, NULL }, + { "bracketleft", 333, NULL }, + { "Ugrave", 722, NULL }, + { "quoteright", 333, NULL }, + { "Udieresis", 722, NULL }, + { "perthousand", 1000, NULL }, + { "Ydieresis", 611, NULL }, + { "umacron", 556, NULL }, + { "abreve", 500, NULL }, + { "Eacute", 667, NULL }, + { "adieresis", 500, NULL }, + { "egrave", 444, NULL }, + { "edieresis", 444, NULL }, + { "idieresis", 278, NULL }, + { "Eth", 722, NULL }, + { "ae", 722, NULL }, + { "asterisk", 500, NULL }, + { "odieresis", 500, NULL }, + { "Uacute", 722, NULL }, + { "ugrave", 556, NULL }, + { "nine", 500, NULL }, + { "five", 500, NULL }, + { "udieresis", 556, NULL }, + { "Zcaron", 611, NULL }, + { "Scommaaccent", 556, NULL }, + { "threequarters", 750, NULL }, + { "guillemotright", 500, NULL }, + { "Ccedilla", 667, NULL }, + { "ydieresis", 444, NULL }, + { "tilde", 333, NULL }, + { "at", 832, NULL }, + { "eacute", 444, NULL }, + { "underscore", 500, NULL }, + { "Euro", 500, NULL }, + { "Dcroat", 722, NULL }, + { "multiply", 570, NULL }, + { "zero", 500, NULL }, + { "eth", 500, NULL }, + { "Scedilla", 556, NULL }, + { "Ograve", 722, NULL }, + { "Racute", 667, NULL }, + { "partialdiff", 494, NULL }, + { "uacute", 556, NULL }, + { "braceleft", 348, NULL }, + { "Thorn", 611, NULL }, + { "zcaron", 389, NULL }, + { "scommaaccent", 389, NULL }, + { "ccedilla", 444, NULL }, + { "Dcaron", 722, NULL }, + { "dcroat", 500, NULL }, + { "Ocircumflex", 722, NULL }, + { "Oacute", 722, NULL }, + { "scedilla", 389, NULL }, + { "ogonek", 333, NULL }, + { "ograve", 500, NULL }, + { "racute", 389, NULL }, + { "Tcaron", 611, NULL }, + { "Eogonek", 667, NULL }, + { "thorn", 500, NULL }, + { "degree", 400, NULL }, + { "registered", 747, NULL }, + { "radical", 549, NULL }, + { "Aring", 667, NULL }, + { "percent", 833, NULL }, + { "six", 500, NULL }, + { "paragraph", 500, NULL }, + { "dcaron", 608, NULL }, + { "Uogonek", 722, NULL }, + { "two", 500, NULL }, + { "summation", 600, NULL }, + { "Igrave", 389, NULL }, + { "Lacute", 611, NULL }, + { "ocircumflex", 500, NULL }, + { "oacute", 500, NULL }, + { "Uring", 722, NULL }, + { "Lcommaaccent", 611, NULL }, + { "tcaron", 366, NULL }, + { "eogonek", 444, NULL }, + { "Delta", 612, NULL }, + { "Ohungarumlaut", 722, NULL }, + { "asciicircum", 570, NULL }, + { "aring", 500, NULL }, + { "grave", 333, NULL }, + { "uogonek", 556, NULL }, + { "bracketright", 333, NULL }, + { "Iacute", 389, NULL }, + { "ampersand", 778, NULL }, + { "igrave", 278, NULL }, + { "lacute", 278, NULL }, + { "Ncaron", 722, NULL }, + { "plus", 570, NULL }, + { "uring", 556, NULL }, + { "quotesinglbase", 333, NULL }, + { "lcommaaccent", 278, NULL }, + { "Yacute", 611, NULL }, + { "ohungarumlaut", 500, NULL }, + { "threesuperior", 300, NULL }, + { "acute", 333, NULL }, + { "section", 500, NULL }, + { "dieresis", 333, NULL }, + { "iacute", 278, NULL }, + { "quotedblbase", 500, NULL }, + { "ncaron", 556, NULL }, + { "florin", 500, NULL }, + { "yacute", 444, NULL }, + { "Rcommaaccent", 667, NULL }, + { "fi", 556, NULL }, + { "fl", 556, NULL }, + { "Acircumflex", 667, NULL }, + { "Cacute", 667, NULL }, + { "Icircumflex", 389, NULL }, + { "guillemotleft", 500, NULL }, + { "germandbls", 500, NULL }, + { "Amacron", 667, NULL }, + { "seven", 500, NULL }, + { "Sacute", 556, NULL }, + { "ordmasculine", 300, NULL }, + { "dotlessi", 278, NULL }, + { "sterling", 500, NULL }, + { "notequal", 549, NULL }, + { "Imacron", 389, NULL }, + { "rcommaaccent", 389, NULL }, + { "Zdotaccent", 611, NULL }, + { "acircumflex", 500, NULL }, + { "cacute", 444, NULL }, + { "Ecaron", 667, NULL }, + { "icircumflex", 278, NULL }, + { "braceright", 348, NULL }, + { "quotedblright", 500, NULL }, + { "amacron", 500, NULL }, + { "sacute", 389, NULL }, + { "imacron", 278, NULL }, + { "cent", 500, NULL }, + { "currency", 500, NULL }, + { "logicalnot", 606, NULL }, + { "zdotaccent", 389, NULL }, + { "Atilde", 667, NULL }, + { "breve", 333, NULL }, + { "bar", 220, NULL }, + { "fraction", 167, NULL }, + { "less", 570, NULL }, + { "ecaron", 444, NULL }, + { "guilsinglleft", 333, NULL }, + { "exclam", 389, NULL }, + { "period", 250, NULL }, + { "Rcaron", 667, NULL }, + { "Kcommaaccent", 667, NULL }, + { "greater", 570, NULL }, + { "atilde", 500, NULL }, + { "brokenbar", 220, NULL }, + { "quoteleft", 333, NULL }, + { "Edotaccent", 667, NULL }, + { "onesuperior", 300, NULL } +}; + +static BuiltinFontWidth timesItalicWidthsTab[] = { + { "Ntilde", 667, NULL }, + { "rcaron", 389, NULL }, + { "kcommaaccent", 444, NULL }, + { "Ncommaaccent", 667, NULL }, + { "Zacute", 556, NULL }, + { "comma", 250, NULL }, + { "cedilla", 333, NULL }, + { "plusminus", 675, NULL }, + { "circumflex", 333, NULL }, + { "dotaccent", 333, NULL }, + { "edotaccent", 444, NULL }, + { "asciitilde", 541, NULL }, + { "colon", 333, NULL }, + { "onehalf", 750, NULL }, + { "dollar", 500, NULL }, + { "Lcaron", 611, NULL }, + { "ntilde", 500, NULL }, + { "Aogonek", 611, NULL }, + { "ncommaaccent", 500, NULL }, + { "minus", 675, NULL }, + { "Iogonek", 333, NULL }, + { "zacute", 389, NULL }, + { "yen", 500, NULL }, + { "space", 250, NULL }, + { "Omacron", 722, NULL }, + { "questiondown", 500, NULL }, + { "emdash", 889, NULL }, + { "Agrave", 611, NULL }, + { "three", 500, NULL }, + { "numbersign", 500, NULL }, + { "lcaron", 300, NULL }, + { "A", 611, NULL }, + { "B", 611, NULL }, + { "C", 667, NULL }, + { "aogonek", 500, NULL }, + { "D", 722, NULL }, + { "E", 611, NULL }, + { "onequarter", 750, NULL }, + { "F", 611, NULL }, + { "G", 722, NULL }, + { "H", 722, NULL }, + { "I", 333, NULL }, + { "J", 444, NULL }, + { "K", 667, NULL }, + { "iogonek", 278, NULL }, + { "backslash", 278, NULL }, + { "L", 556, NULL }, + { "periodcentered", 250, NULL }, + { "M", 833, NULL }, + { "N", 667, NULL }, + { "omacron", 500, NULL }, + { "Tcommaaccent", 556, NULL }, + { "O", 722, NULL }, + { "P", 611, NULL }, + { "Q", 722, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "R", 611, NULL }, + { "Aacute", 611, NULL }, + { "caron", 333, NULL }, + { "S", 500, NULL }, + { "T", 556, NULL }, + { "U", 722, NULL }, + { "agrave", 500, NULL }, + { "V", 611, NULL }, + { "W", 833, NULL }, + { "X", 611, NULL }, + { "question", 500, NULL }, + { "equal", 675, NULL }, + { "Y", 556, NULL }, + { "Z", 556, NULL }, + { "four", 500, NULL }, + { "a", 500, NULL }, + { "Gcommaaccent", 722, NULL }, + { "b", 500, NULL }, + { "c", 444, NULL }, + { "d", 500, NULL }, + { "e", 444, NULL }, + { "f", 278, NULL }, + { "g", 500, NULL }, + { "bullet", 350, NULL }, + { "h", 500, NULL }, + { "i", 278, NULL }, + { "Oslash", 722, NULL }, + { "dagger", 500, NULL }, + { "j", 278, NULL }, + { "k", 444, NULL }, + { "l", 278, NULL }, + { "m", 722, NULL }, + { "n", 500, NULL }, + { "tcommaaccent", 278, NULL }, + { "o", 500, NULL }, + { "ordfeminine", 276, NULL }, + { "ring", 333, NULL }, + { "p", 500, NULL }, + { "q", 500, NULL }, + { "uhungarumlaut", 500, NULL }, + { "r", 389, NULL }, + { "twosuperior", 300, NULL }, + { "aacute", 500, NULL }, + { "s", 389, NULL }, + { "OE", 944, NULL }, + { "t", 278, NULL }, + { "divide", 675, NULL }, + { "u", 500, NULL }, + { "Ccaron", 667, NULL }, + { "v", 444, NULL }, + { "w", 667, NULL }, + { "x", 444, NULL }, + { "y", 444, NULL }, + { "z", 389, NULL }, + { "Gbreve", 722, NULL }, + { "commaaccent", 250, NULL }, + { "hungarumlaut", 333, NULL }, + { "Idotaccent", 333, NULL }, + { "Nacute", 667, NULL }, + { "quotedbl", 420, NULL }, + { "gcommaaccent", 500, NULL }, + { "mu", 500, NULL }, + { "greaterequal", 549, NULL }, + { "Scaron", 500, NULL }, + { "Lslash", 556, NULL }, + { "semicolon", 333, NULL }, + { "oslash", 500, NULL }, + { "lessequal", 549, NULL }, + { "lozenge", 471, NULL }, + { "parenright", 333, NULL }, + { "ccaron", 444, NULL }, + { "Ecircumflex", 611, NULL }, + { "gbreve", 500, NULL }, + { "trademark", 980, NULL }, + { "daggerdbl", 500, NULL }, + { "nacute", 500, NULL }, + { "macron", 333, NULL }, + { "Otilde", 722, NULL }, + { "Emacron", 611, NULL }, + { "ellipsis", 889, NULL }, + { "scaron", 389, NULL }, + { "AE", 889, NULL }, + { "Ucircumflex", 722, NULL }, + { "lslash", 278, NULL }, + { "quotedblleft", 556, NULL }, + { "guilsinglright", 333, NULL }, + { "hyphen", 333, NULL }, + { "quotesingle", 214, NULL }, + { "eight", 500, NULL }, + { "exclamdown", 389, NULL }, + { "endash", 500, NULL }, + { "oe", 667, NULL }, + { "Abreve", 611, NULL }, + { "Umacron", 722, NULL }, + { "ecircumflex", 444, NULL }, + { "Adieresis", 611, NULL }, + { "copyright", 760, NULL }, + { "Egrave", 611, NULL }, + { "slash", 278, NULL }, + { "Edieresis", 611, NULL }, + { "otilde", 500, NULL }, + { "Idieresis", 333, NULL }, + { "parenleft", 333, NULL }, + { "one", 500, NULL }, + { "emacron", 444, NULL }, + { "Odieresis", 722, NULL }, + { "ucircumflex", 500, NULL }, + { "bracketleft", 389, NULL }, + { "Ugrave", 722, NULL }, + { "quoteright", 333, NULL }, + { "Udieresis", 722, NULL }, + { "perthousand", 1000, NULL }, + { "Ydieresis", 556, NULL }, + { "umacron", 500, NULL }, + { "abreve", 500, NULL }, + { "Eacute", 611, NULL }, + { "adieresis", 500, NULL }, + { "egrave", 444, NULL }, + { "edieresis", 444, NULL }, + { "idieresis", 278, NULL }, + { "Eth", 722, NULL }, + { "ae", 667, NULL }, + { "asterisk", 500, NULL }, + { "odieresis", 500, NULL }, + { "Uacute", 722, NULL }, + { "ugrave", 500, NULL }, + { "nine", 500, NULL }, + { "five", 500, NULL }, + { "udieresis", 500, NULL }, + { "Zcaron", 556, NULL }, + { "Scommaaccent", 500, NULL }, + { "threequarters", 750, NULL }, + { "guillemotright", 500, NULL }, + { "Ccedilla", 667, NULL }, + { "ydieresis", 444, NULL }, + { "tilde", 333, NULL }, + { "at", 920, NULL }, + { "eacute", 444, NULL }, + { "underscore", 500, NULL }, + { "Euro", 500, NULL }, + { "Dcroat", 722, NULL }, + { "multiply", 675, NULL }, + { "zero", 500, NULL }, + { "eth", 500, NULL }, + { "Scedilla", 500, NULL }, + { "Ograve", 722, NULL }, + { "Racute", 611, NULL }, + { "partialdiff", 476, NULL }, + { "uacute", 500, NULL }, + { "braceleft", 400, NULL }, + { "Thorn", 611, NULL }, + { "zcaron", 389, NULL }, + { "scommaaccent", 389, NULL }, + { "ccedilla", 444, NULL }, + { "Dcaron", 722, NULL }, + { "dcroat", 500, NULL }, + { "Ocircumflex", 722, NULL }, + { "Oacute", 722, NULL }, + { "scedilla", 389, NULL }, + { "ogonek", 333, NULL }, + { "ograve", 500, NULL }, + { "racute", 389, NULL }, + { "Tcaron", 556, NULL }, + { "Eogonek", 611, NULL }, + { "thorn", 500, NULL }, + { "degree", 400, NULL }, + { "registered", 760, NULL }, + { "radical", 453, NULL }, + { "Aring", 611, NULL }, + { "percent", 833, NULL }, + { "six", 500, NULL }, + { "paragraph", 523, NULL }, + { "dcaron", 544, NULL }, + { "Uogonek", 722, NULL }, + { "two", 500, NULL }, + { "summation", 600, NULL }, + { "Igrave", 333, NULL }, + { "Lacute", 556, NULL }, + { "ocircumflex", 500, NULL }, + { "oacute", 500, NULL }, + { "Uring", 722, NULL }, + { "Lcommaaccent", 556, NULL }, + { "tcaron", 300, NULL }, + { "eogonek", 444, NULL }, + { "Delta", 612, NULL }, + { "Ohungarumlaut", 722, NULL }, + { "asciicircum", 422, NULL }, + { "aring", 500, NULL }, + { "grave", 333, NULL }, + { "uogonek", 500, NULL }, + { "bracketright", 389, NULL }, + { "Iacute", 333, NULL }, + { "ampersand", 778, NULL }, + { "igrave", 278, NULL }, + { "lacute", 278, NULL }, + { "Ncaron", 667, NULL }, + { "plus", 675, NULL }, + { "uring", 500, NULL }, + { "quotesinglbase", 333, NULL }, + { "lcommaaccent", 278, NULL }, + { "Yacute", 556, NULL }, + { "ohungarumlaut", 500, NULL }, + { "threesuperior", 300, NULL }, + { "acute", 333, NULL }, + { "section", 500, NULL }, + { "dieresis", 333, NULL }, + { "iacute", 278, NULL }, + { "quotedblbase", 556, NULL }, + { "ncaron", 500, NULL }, + { "florin", 500, NULL }, + { "yacute", 444, NULL }, + { "Rcommaaccent", 611, NULL }, + { "fi", 500, NULL }, + { "fl", 500, NULL }, + { "Acircumflex", 611, NULL }, + { "Cacute", 667, NULL }, + { "Icircumflex", 333, NULL }, + { "guillemotleft", 500, NULL }, + { "germandbls", 500, NULL }, + { "Amacron", 611, NULL }, + { "seven", 500, NULL }, + { "Sacute", 500, NULL }, + { "ordmasculine", 310, NULL }, + { "dotlessi", 278, NULL }, + { "sterling", 500, NULL }, + { "notequal", 549, NULL }, + { "Imacron", 333, NULL }, + { "rcommaaccent", 389, NULL }, + { "Zdotaccent", 556, NULL }, + { "acircumflex", 500, NULL }, + { "cacute", 444, NULL }, + { "Ecaron", 611, NULL }, + { "icircumflex", 278, NULL }, + { "braceright", 400, NULL }, + { "quotedblright", 556, NULL }, + { "amacron", 500, NULL }, + { "sacute", 389, NULL }, + { "imacron", 278, NULL }, + { "cent", 500, NULL }, + { "currency", 500, NULL }, + { "logicalnot", 675, NULL }, + { "zdotaccent", 389, NULL }, + { "Atilde", 611, NULL }, + { "breve", 333, NULL }, + { "bar", 275, NULL }, + { "fraction", 167, NULL }, + { "less", 675, NULL }, + { "ecaron", 444, NULL }, + { "guilsinglleft", 333, NULL }, + { "exclam", 333, NULL }, + { "period", 250, NULL }, + { "Rcaron", 611, NULL }, + { "Kcommaaccent", 667, NULL }, + { "greater", 675, NULL }, + { "atilde", 500, NULL }, + { "brokenbar", 275, NULL }, + { "quoteleft", 333, NULL }, + { "Edotaccent", 611, NULL }, + { "onesuperior", 300, NULL } +}; + +static BuiltinFontWidth timesRomanWidthsTab[] = { + { "Ntilde", 722, NULL }, + { "rcaron", 333, NULL }, + { "kcommaaccent", 500, NULL }, + { "Ncommaaccent", 722, NULL }, + { "Zacute", 611, NULL }, + { "comma", 250, NULL }, + { "cedilla", 333, NULL }, + { "plusminus", 564, NULL }, + { "circumflex", 333, NULL }, + { "dotaccent", 333, NULL }, + { "edotaccent", 444, NULL }, + { "asciitilde", 541, NULL }, + { "colon", 278, NULL }, + { "onehalf", 750, NULL }, + { "dollar", 500, NULL }, + { "Lcaron", 611, NULL }, + { "ntilde", 500, NULL }, + { "Aogonek", 722, NULL }, + { "ncommaaccent", 500, NULL }, + { "minus", 564, NULL }, + { "Iogonek", 333, NULL }, + { "zacute", 444, NULL }, + { "yen", 500, NULL }, + { "space", 250, NULL }, + { "Omacron", 722, NULL }, + { "questiondown", 444, NULL }, + { "emdash", 1000, NULL }, + { "Agrave", 722, NULL }, + { "three", 500, NULL }, + { "numbersign", 500, NULL }, + { "lcaron", 344, NULL }, + { "A", 722, NULL }, + { "B", 667, NULL }, + { "C", 667, NULL }, + { "aogonek", 444, NULL }, + { "D", 722, NULL }, + { "E", 611, NULL }, + { "onequarter", 750, NULL }, + { "F", 556, NULL }, + { "G", 722, NULL }, + { "H", 722, NULL }, + { "I", 333, NULL }, + { "J", 389, NULL }, + { "K", 722, NULL }, + { "iogonek", 278, NULL }, + { "backslash", 278, NULL }, + { "L", 611, NULL }, + { "periodcentered", 250, NULL }, + { "M", 889, NULL }, + { "N", 722, NULL }, + { "omacron", 500, NULL }, + { "Tcommaaccent", 611, NULL }, + { "O", 722, NULL }, + { "P", 556, NULL }, + { "Q", 722, NULL }, + { "Uhungarumlaut", 722, NULL }, + { "R", 667, NULL }, + { "Aacute", 722, NULL }, + { "caron", 333, NULL }, + { "S", 556, NULL }, + { "T", 611, NULL }, + { "U", 722, NULL }, + { "agrave", 444, NULL }, + { "V", 722, NULL }, + { "W", 944, NULL }, + { "X", 722, NULL }, + { "question", 444, NULL }, + { "equal", 564, NULL }, + { "Y", 722, NULL }, + { "Z", 611, NULL }, + { "four", 500, NULL }, + { "a", 444, NULL }, + { "Gcommaaccent", 722, NULL }, + { "b", 500, NULL }, + { "c", 444, NULL }, + { "d", 500, NULL }, + { "e", 444, NULL }, + { "f", 333, NULL }, + { "g", 500, NULL }, + { "bullet", 350, NULL }, + { "h", 500, NULL }, + { "i", 278, NULL }, + { "Oslash", 722, NULL }, + { "dagger", 500, NULL }, + { "j", 278, NULL }, + { "k", 500, NULL }, + { "l", 278, NULL }, + { "m", 778, NULL }, + { "n", 500, NULL }, + { "tcommaaccent", 278, NULL }, + { "o", 500, NULL }, + { "ordfeminine", 276, NULL }, + { "ring", 333, NULL }, + { "p", 500, NULL }, + { "q", 500, NULL }, + { "uhungarumlaut", 500, NULL }, + { "r", 333, NULL }, + { "twosuperior", 300, NULL }, + { "aacute", 444, NULL }, + { "s", 389, NULL }, + { "OE", 889, NULL }, + { "t", 278, NULL }, + { "divide", 564, NULL }, + { "u", 500, NULL }, + { "Ccaron", 667, NULL }, + { "v", 500, NULL }, + { "w", 722, NULL }, + { "x", 500, NULL }, + { "y", 500, NULL }, + { "z", 444, NULL }, + { "Gbreve", 722, NULL }, + { "commaaccent", 250, NULL }, + { "hungarumlaut", 333, NULL }, + { "Idotaccent", 333, NULL }, + { "Nacute", 722, NULL }, + { "quotedbl", 408, NULL }, + { "gcommaaccent", 500, NULL }, + { "mu", 500, NULL }, + { "greaterequal", 549, NULL }, + { "Scaron", 556, NULL }, + { "Lslash", 611, NULL }, + { "semicolon", 278, NULL }, + { "oslash", 500, NULL }, + { "lessequal", 549, NULL }, + { "lozenge", 471, NULL }, + { "parenright", 333, NULL }, + { "ccaron", 444, NULL }, + { "Ecircumflex", 611, NULL }, + { "gbreve", 500, NULL }, + { "trademark", 980, NULL }, + { "daggerdbl", 500, NULL }, + { "nacute", 500, NULL }, + { "macron", 333, NULL }, + { "Otilde", 722, NULL }, + { "Emacron", 611, NULL }, + { "ellipsis", 1000, NULL }, + { "scaron", 389, NULL }, + { "AE", 889, NULL }, + { "Ucircumflex", 722, NULL }, + { "lslash", 278, NULL }, + { "quotedblleft", 444, NULL }, + { "guilsinglright", 333, NULL }, + { "hyphen", 333, NULL }, + { "quotesingle", 180, NULL }, + { "eight", 500, NULL }, + { "exclamdown", 333, NULL }, + { "endash", 500, NULL }, + { "oe", 722, NULL }, + { "Abreve", 722, NULL }, + { "Umacron", 722, NULL }, + { "ecircumflex", 444, NULL }, + { "Adieresis", 722, NULL }, + { "copyright", 760, NULL }, + { "Egrave", 611, NULL }, + { "slash", 278, NULL }, + { "Edieresis", 611, NULL }, + { "otilde", 500, NULL }, + { "Idieresis", 333, NULL }, + { "parenleft", 333, NULL }, + { "one", 500, NULL }, + { "emacron", 444, NULL }, + { "Odieresis", 722, NULL }, + { "ucircumflex", 500, NULL }, + { "bracketleft", 333, NULL }, + { "Ugrave", 722, NULL }, + { "quoteright", 333, NULL }, + { "Udieresis", 722, NULL }, + { "perthousand", 1000, NULL }, + { "Ydieresis", 722, NULL }, + { "umacron", 500, NULL }, + { "abreve", 444, NULL }, + { "Eacute", 611, NULL }, + { "adieresis", 444, NULL }, + { "egrave", 444, NULL }, + { "edieresis", 444, NULL }, + { "idieresis", 278, NULL }, + { "Eth", 722, NULL }, + { "ae", 667, NULL }, + { "asterisk", 500, NULL }, + { "odieresis", 500, NULL }, + { "Uacute", 722, NULL }, + { "ugrave", 500, NULL }, + { "nine", 500, NULL }, + { "five", 500, NULL }, + { "udieresis", 500, NULL }, + { "Zcaron", 611, NULL }, + { "Scommaaccent", 556, NULL }, + { "threequarters", 750, NULL }, + { "guillemotright", 500, NULL }, + { "Ccedilla", 667, NULL }, + { "ydieresis", 500, NULL }, + { "tilde", 333, NULL }, + { "at", 921, NULL }, + { "eacute", 444, NULL }, + { "underscore", 500, NULL }, + { "Euro", 500, NULL }, + { "Dcroat", 722, NULL }, + { "multiply", 564, NULL }, + { "zero", 500, NULL }, + { "eth", 500, NULL }, + { "Scedilla", 556, NULL }, + { "Ograve", 722, NULL }, + { "Racute", 667, NULL }, + { "partialdiff", 476, NULL }, + { "uacute", 500, NULL }, + { "braceleft", 480, NULL }, + { "Thorn", 556, NULL }, + { "zcaron", 444, NULL }, + { "scommaaccent", 389, NULL }, + { "ccedilla", 444, NULL }, + { "Dcaron", 722, NULL }, + { "dcroat", 500, NULL }, + { "Ocircumflex", 722, NULL }, + { "Oacute", 722, NULL }, + { "scedilla", 389, NULL }, + { "ogonek", 333, NULL }, + { "ograve", 500, NULL }, + { "racute", 333, NULL }, + { "Tcaron", 611, NULL }, + { "Eogonek", 611, NULL }, + { "thorn", 500, NULL }, + { "degree", 400, NULL }, + { "registered", 760, NULL }, + { "radical", 453, NULL }, + { "Aring", 722, NULL }, + { "percent", 833, NULL }, + { "six", 500, NULL }, + { "paragraph", 453, NULL }, + { "dcaron", 588, NULL }, + { "Uogonek", 722, NULL }, + { "two", 500, NULL }, + { "summation", 600, NULL }, + { "Igrave", 333, NULL }, + { "Lacute", 611, NULL }, + { "ocircumflex", 500, NULL }, + { "oacute", 500, NULL }, + { "Uring", 722, NULL }, + { "Lcommaaccent", 611, NULL }, + { "tcaron", 326, NULL }, + { "eogonek", 444, NULL }, + { "Delta", 612, NULL }, + { "Ohungarumlaut", 722, NULL }, + { "asciicircum", 469, NULL }, + { "aring", 444, NULL }, + { "grave", 333, NULL }, + { "uogonek", 500, NULL }, + { "bracketright", 333, NULL }, + { "Iacute", 333, NULL }, + { "ampersand", 778, NULL }, + { "igrave", 278, NULL }, + { "lacute", 278, NULL }, + { "Ncaron", 722, NULL }, + { "plus", 564, NULL }, + { "uring", 500, NULL }, + { "quotesinglbase", 333, NULL }, + { "lcommaaccent", 278, NULL }, + { "Yacute", 722, NULL }, + { "ohungarumlaut", 500, NULL }, + { "threesuperior", 300, NULL }, + { "acute", 333, NULL }, + { "section", 500, NULL }, + { "dieresis", 333, NULL }, + { "iacute", 278, NULL }, + { "quotedblbase", 444, NULL }, + { "ncaron", 500, NULL }, + { "florin", 500, NULL }, + { "yacute", 500, NULL }, + { "Rcommaaccent", 667, NULL }, + { "fi", 556, NULL }, + { "fl", 556, NULL }, + { "Acircumflex", 722, NULL }, + { "Cacute", 667, NULL }, + { "Icircumflex", 333, NULL }, + { "guillemotleft", 500, NULL }, + { "germandbls", 500, NULL }, + { "Amacron", 722, NULL }, + { "seven", 500, NULL }, + { "Sacute", 556, NULL }, + { "ordmasculine", 310, NULL }, + { "dotlessi", 278, NULL }, + { "sterling", 500, NULL }, + { "notequal", 549, NULL }, + { "Imacron", 333, NULL }, + { "rcommaaccent", 333, NULL }, + { "Zdotaccent", 611, NULL }, + { "acircumflex", 444, NULL }, + { "cacute", 444, NULL }, + { "Ecaron", 611, NULL }, + { "icircumflex", 278, NULL }, + { "braceright", 480, NULL }, + { "quotedblright", 444, NULL }, + { "amacron", 444, NULL }, + { "sacute", 389, NULL }, + { "imacron", 278, NULL }, + { "cent", 500, NULL }, + { "currency", 500, NULL }, + { "logicalnot", 564, NULL }, + { "zdotaccent", 444, NULL }, + { "Atilde", 722, NULL }, + { "breve", 333, NULL }, + { "bar", 200, NULL }, + { "fraction", 167, NULL }, + { "less", 564, NULL }, + { "ecaron", 444, NULL }, + { "guilsinglleft", 333, NULL }, + { "exclam", 333, NULL }, + { "period", 250, NULL }, + { "Rcaron", 667, NULL }, + { "Kcommaaccent", 722, NULL }, + { "greater", 564, NULL }, + { "atilde", 444, NULL }, + { "brokenbar", 200, NULL }, + { "quoteleft", 333, NULL }, + { "Edotaccent", 611, NULL }, + { "onesuperior", 300, NULL } +}; + +static BuiltinFontWidth zapfDingbatsWidthsTab[] = { + { "a81", 438, NULL }, + { "a82", 138, NULL }, + { "a83", 277, NULL }, + { "a84", 415, NULL }, + { "a85", 509, NULL }, + { "a86", 410, NULL }, + { "a87", 234, NULL }, + { "a88", 234, NULL }, + { "a89", 390, NULL }, + { "a140", 788, NULL }, + { "a141", 788, NULL }, + { "a142", 788, NULL }, + { "a143", 788, NULL }, + { "a144", 788, NULL }, + { "a145", 788, NULL }, + { "a146", 788, NULL }, + { "a147", 788, NULL }, + { "a148", 788, NULL }, + { "a149", 788, NULL }, + { "a90", 390, NULL }, + { "a91", 276, NULL }, + { "a92", 276, NULL }, + { "space", 278, NULL }, + { "a93", 317, NULL }, + { "a94", 317, NULL }, + { "a95", 334, NULL }, + { "a96", 334, NULL }, + { "a97", 392, NULL }, + { "a98", 392, NULL }, + { "a99", 668, NULL }, + { "a150", 788, NULL }, + { "a151", 788, NULL }, + { "a152", 788, NULL }, + { "a153", 788, NULL }, + { "a154", 788, NULL }, + { "a155", 788, NULL }, + { "a156", 788, NULL }, + { "a157", 788, NULL }, + { "a158", 788, NULL }, + { "a159", 788, NULL }, + { "a160", 894, NULL }, + { "a161", 838, NULL }, + { "a162", 924, NULL }, + { "a163", 1016, NULL }, + { "a164", 458, NULL }, + { "a165", 924, NULL }, + { "a166", 918, NULL }, + { "a167", 927, NULL }, + { "a168", 928, NULL }, + { "a169", 928, NULL }, + { "a170", 834, NULL }, + { "a171", 873, NULL }, + { "a172", 828, NULL }, + { "a173", 924, NULL }, + { "a174", 917, NULL }, + { "a175", 930, NULL }, + { "a176", 931, NULL }, + { "a177", 463, NULL }, + { "a178", 883, NULL }, + { "a179", 836, NULL }, + { "a180", 867, NULL }, + { "a181", 696, NULL }, + { "a182", 874, NULL }, + { "a183", 760, NULL }, + { "a184", 946, NULL }, + { "a185", 865, NULL }, + { "a186", 967, NULL }, + { "a187", 831, NULL }, + { "a188", 873, NULL }, + { "a189", 927, NULL }, + { "a1", 974, NULL }, + { "a2", 961, NULL }, + { "a3", 980, NULL }, + { "a4", 719, NULL }, + { "a5", 789, NULL }, + { "a6", 494, NULL }, + { "a7", 552, NULL }, + { "a8", 537, NULL }, + { "a9", 577, NULL }, + { "a190", 970, NULL }, + { "a191", 918, NULL }, + { "a192", 748, NULL }, + { "a193", 836, NULL }, + { "a194", 771, NULL }, + { "a195", 888, NULL }, + { "a196", 748, NULL }, + { "a197", 771, NULL }, + { "a198", 888, NULL }, + { "a199", 867, NULL }, + { "a10", 692, NULL }, + { "a11", 960, NULL }, + { "a12", 939, NULL }, + { "a13", 549, NULL }, + { "a14", 855, NULL }, + { "a15", 911, NULL }, + { "a16", 933, NULL }, + { "a17", 945, NULL }, + { "a18", 974, NULL }, + { "a19", 755, NULL }, + { "a20", 846, NULL }, + { "a21", 762, NULL }, + { "a22", 761, NULL }, + { "a23", 571, NULL }, + { "a24", 677, NULL }, + { "a25", 763, NULL }, + { "a26", 760, NULL }, + { "a27", 759, NULL }, + { "a28", 754, NULL }, + { "a29", 786, NULL }, + { "a30", 788, NULL }, + { "a31", 788, NULL }, + { "a32", 790, NULL }, + { "a33", 793, NULL }, + { "a34", 794, NULL }, + { "a35", 816, NULL }, + { "a36", 823, NULL }, + { "a37", 789, NULL }, + { "a38", 841, NULL }, + { "a39", 823, NULL }, + { "a40", 833, NULL }, + { "a41", 816, NULL }, + { "a42", 831, NULL }, + { "a43", 923, NULL }, + { "a44", 744, NULL }, + { "a45", 723, NULL }, + { "a46", 749, NULL }, + { "a47", 790, NULL }, + { "a48", 792, NULL }, + { "a49", 695, NULL }, + { "a100", 668, NULL }, + { "a101", 732, NULL }, + { "a102", 544, NULL }, + { "a103", 544, NULL }, + { "a104", 910, NULL }, + { "a105", 911, NULL }, + { "a106", 667, NULL }, + { "a107", 760, NULL }, + { "a108", 760, NULL }, + { "a109", 626, NULL }, + { "a50", 776, NULL }, + { "a51", 768, NULL }, + { "a52", 792, NULL }, + { "a53", 759, NULL }, + { "a54", 707, NULL }, + { "a55", 708, NULL }, + { "a56", 682, NULL }, + { "a57", 701, NULL }, + { "a58", 826, NULL }, + { "a59", 815, NULL }, + { "a110", 694, NULL }, + { "a111", 595, NULL }, + { "a112", 776, NULL }, + { "a117", 690, NULL }, + { "a118", 791, NULL }, + { "a119", 790, NULL }, + { "a60", 789, NULL }, + { "a61", 789, NULL }, + { "a62", 707, NULL }, + { "a63", 687, NULL }, + { "a64", 696, NULL }, + { "a65", 689, NULL }, + { "a66", 786, NULL }, + { "a67", 787, NULL }, + { "a68", 713, NULL }, + { "a69", 791, NULL }, + { "a200", 696, NULL }, + { "a201", 874, NULL }, + { "a120", 788, NULL }, + { "a121", 788, NULL }, + { "a202", 974, NULL }, + { "a122", 788, NULL }, + { "a203", 762, NULL }, + { "a123", 788, NULL }, + { "a204", 759, NULL }, + { "a124", 788, NULL }, + { "a205", 509, NULL }, + { "a125", 788, NULL }, + { "a206", 410, NULL }, + { "a126", 788, NULL }, + { "a127", 788, NULL }, + { "a128", 788, NULL }, + { "a129", 788, NULL }, + { "a70", 785, NULL }, + { "a71", 791, NULL }, + { "a72", 873, NULL }, + { "a73", 761, NULL }, + { "a74", 762, NULL }, + { "a75", 759, NULL }, + { "a76", 892, NULL }, + { "a77", 892, NULL }, + { "a78", 788, NULL }, + { "a79", 784, NULL }, + { "a130", 788, NULL }, + { "a131", 788, NULL }, + { "a132", 788, NULL }, + { "a133", 788, NULL }, + { "a134", 788, NULL }, + { "a135", 788, NULL }, + { "a136", 788, NULL }, + { "a137", 788, NULL }, + { "a138", 788, NULL }, + { "a139", 788, NULL } +}; + +BuiltinFont builtinFonts[] = { + { "Courier", standardEncoding, 629, -157, { -23, -250, 715, 805}, NULL }, + { "Courier-Bold", standardEncoding, 629, -157, {-113, -250, 749, 801}, NULL }, + { "Courier-BoldOblique", standardEncoding, 629, -157, { -57, -250, 869, 801}, NULL }, + { "Courier-Oblique", standardEncoding, 629, -157, { -27, -250, 849, 805}, NULL }, + { "Helvetica", standardEncoding, 718, -207, {-166, -225, 1000, 931}, NULL }, + { "Helvetica-Bold", standardEncoding, 718, -207, {-170, -228, 1003, 962}, NULL }, + { "Helvetica-BoldOblique", standardEncoding, 718, -207, {-174, -228, 1114, 962}, NULL }, + { "Helvetica-Oblique", standardEncoding, 718, -207, {-170, -225, 1116, 931}, NULL }, + { "Symbol", symbolEncoding, 1010, -293, {-180, -293, 1090, 1010}, NULL }, + { "Times-Bold", standardEncoding, 683, -217, {-168, -218, 1000, 935}, NULL }, + { "Times-BoldItalic", standardEncoding, 683, -217, {-200, -218, 996, 921}, NULL }, + { "Times-Italic", standardEncoding, 683, -217, {-169, -217, 1010, 883}, NULL }, + { "Times-Roman", standardEncoding, 683, -217, {-168, -218, 1000, 898}, NULL }, + { "ZapfDingbats", zapfDingbatsEncoding, 820, -143, { -1, -143, 981, 820}, NULL } +}; + +BuiltinFont *builtinFontSubst[] = { + &builtinFonts[0], + &builtinFonts[3], + &builtinFonts[1], + &builtinFonts[2], + &builtinFonts[4], + &builtinFonts[7], + &builtinFonts[5], + &builtinFonts[6], + &builtinFonts[12], + &builtinFonts[11], + &builtinFonts[9], + &builtinFonts[10] +}; + +void initBuiltinFontTables() { + builtinFonts[0].widths = new BuiltinFontWidths(courierWidthsTab, 315); + builtinFonts[1].widths = new BuiltinFontWidths(courierBoldWidthsTab, 315); + builtinFonts[2].widths = new BuiltinFontWidths(courierBoldObliqueWidthsTab, 315); + builtinFonts[3].widths = new BuiltinFontWidths(courierObliqueWidthsTab, 315); + builtinFonts[4].widths = new BuiltinFontWidths(helveticaWidthsTab, 315); + builtinFonts[5].widths = new BuiltinFontWidths(helveticaBoldWidthsTab, 316); + builtinFonts[6].widths = new BuiltinFontWidths(helveticaBoldObliqueWidthsTab, 315); + builtinFonts[7].widths = new BuiltinFontWidths(helveticaObliqueWidthsTab, 315); + builtinFonts[8].widths = new BuiltinFontWidths(symbolWidthsTab, 190); + builtinFonts[9].widths = new BuiltinFontWidths(timesBoldWidthsTab, 315); + builtinFonts[10].widths = new BuiltinFontWidths(timesBoldItalicWidthsTab, 315); + builtinFonts[11].widths = new BuiltinFontWidths(timesItalicWidthsTab, 315); + builtinFonts[12].widths = new BuiltinFontWidths(timesRomanWidthsTab, 315); + builtinFonts[13].widths = new BuiltinFontWidths(zapfDingbatsWidthsTab, 202); +} + +void freeBuiltinFontTables() { + int i; + + for (i = 0; i < 14; ++i) { + delete builtinFonts[i].widths; + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/BuiltinFontTables.h swftools-0.9.1/lib/pdf/xpdf/BuiltinFontTables.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/BuiltinFontTables.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/BuiltinFontTables.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,23 @@ +//======================================================================== +// +// BuiltinFontTables.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef BUILTINFONTTABLES_H +#define BUILTINFONTTABLES_H + +#include "BuiltinFont.h" + +#define nBuiltinFonts 14 +#define nBuiltinFontSubsts 12 + +extern BuiltinFont builtinFonts[nBuiltinFonts]; +extern BuiltinFont *builtinFontSubst[nBuiltinFontSubsts]; + +extern void initBuiltinFontTables(); +extern void freeBuiltinFontTables(); + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Catalog.cc swftools-0.9.1/lib/pdf/xpdf/Catalog.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Catalog.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Catalog.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,374 @@ +//======================================================================== +// +// Catalog.cc +// +// Copyright 1996-2007 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "Object.h" +#include "XRef.h" +#include "Array.h" +#include "Dict.h" +#include "Page.h" +#include "Error.h" +#include "Link.h" +#include "Catalog.h" + +//------------------------------------------------------------------------ +// Catalog +//------------------------------------------------------------------------ + +Catalog::Catalog(XRef *xrefA) { + Object catDict, pagesDict, pagesDictRef; + Object obj, obj2; + char *alreadyRead; + int numPages0; + int i; + + ok = gTrue; + xref = xrefA; + pages = NULL; + pageRefs = NULL; + numPages = pagesSize = 0; + baseURI = NULL; + + xref->getCatalog(&catDict); + if (!catDict.isDict()) { + error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName()); + goto err1; + } + + // read page tree + catDict.dictLookup("Pages", &pagesDict); + // This should really be isDict("Pages"), but I've seen at least one + // PDF file where the /Type entry is missing. + if (!pagesDict.isDict()) { + error(-1, "Top-level pages object is wrong type (%s)", + pagesDict.getTypeName()); + goto err2; + } + pagesDict.dictLookup("Count", &obj); + // some PDF files actually use real numbers here ("/Count 9.0") + if (!obj.isNum()) { + error(-1, "Page count in top-level pages object is wrong type (%s)", + obj.getTypeName()); + goto err3; + } + pagesSize = numPages0 = (int)obj.getNum(); + obj.free(); + pages = (Page **)gmallocn(pagesSize, sizeof(Page *)); + pageRefs = (Ref *)gmallocn(pagesSize, sizeof(Ref)); + for (i = 0; i < pagesSize; ++i) { + pages[i] = NULL; + pageRefs[i].num = -1; + pageRefs[i].gen = -1; + } + alreadyRead = (char *)gmalloc(xref->getNumObjects()); + memset(alreadyRead, 0, xref->getNumObjects()); + if (catDict.dictLookupNF("Pages", &pagesDictRef)->isRef() && + pagesDictRef.getRefNum() >= 0 && + pagesDictRef.getRefNum() < xref->getNumObjects()) { + alreadyRead[pagesDictRef.getRefNum()] = 1; + } + pagesDictRef.free(); + numPages = readPageTree(pagesDict.getDict(), NULL, 0, alreadyRead); + gfree(alreadyRead); + if (numPages != numPages0) { + error(-1, "Page count in top-level pages object is incorrect"); + } + pagesDict.free(); + + // read named destination dictionary + catDict.dictLookup("Dests", &dests); + + // read root of named destination tree + if (catDict.dictLookup("Names", &obj)->isDict()) + obj.dictLookup("Dests", &nameTree); + else + nameTree.initNull(); + obj.free(); + + // read base URI + if (catDict.dictLookup("URI", &obj)->isDict()) { + if (obj.dictLookup("Base", &obj2)->isString()) { + baseURI = obj2.getString()->copy(); + } + obj2.free(); + } + obj.free(); + + // get the metadata stream + catDict.dictLookup("Metadata", &metadata); + + // get the structure tree root + catDict.dictLookup("StructTreeRoot", &structTreeRoot); + + // get the outline dictionary + catDict.dictLookup("Outlines", &outline); + + // get the AcroForm dictionary + catDict.dictLookup("AcroForm", &acroForm); + + catDict.free(); + return; + + err3: + obj.free(); + err2: + pagesDict.free(); + err1: + catDict.free(); + dests.initNull(); + nameTree.initNull(); + ok = gFalse; +} + +Catalog::~Catalog() { + int i; + + if (pages) { + for (i = 0; i < pagesSize; ++i) { + if (pages[i]) { + delete pages[i]; + } + } + gfree(pages); + gfree(pageRefs); + } + dests.free(); + nameTree.free(); + if (baseURI) { + delete baseURI; + } + metadata.free(); + structTreeRoot.free(); + outline.free(); + acroForm.free(); +} + +GString *Catalog::readMetadata() { + GString *s; + Dict *dict; + Object obj; + int c; + + if (!metadata.isStream()) { + return NULL; + } + dict = metadata.streamGetDict(); + if (!dict->lookup("Subtype", &obj)->isName("XML")) { + error(-1, "Unknown Metadata type: '%s'", + obj.isName() ? obj.getName() : "???"); + } + obj.free(); + s = new GString(); + metadata.streamReset(); + while ((c = metadata.streamGetChar()) != EOF) { + s->append(c); + } + metadata.streamClose(); + return s; +} + +int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start, + char *alreadyRead) { + Object kids; + Object kid; + Object kidRef; + PageAttrs *attrs1, *attrs2; + Page *page; + int i, j; + + attrs1 = new PageAttrs(attrs, pagesDict); + pagesDict->lookup("Kids", &kids); + if (!kids.isArray()) { + error(-1, "Kids object (page %d) is wrong type (%s)", + start+1, kids.getTypeName()); + return start; + } + for (i = 0; i < kids.arrayGetLength(); ++i) { + kids.arrayGetNF(i, &kidRef); + if (kidRef.isRef() && + kidRef.getRefNum() >= 0 && + kidRef.getRefNum() < xref->getNumObjects()) { + if (alreadyRead[kidRef.getRefNum()]) { + error(-1, "Loop in Pages tree"); + kidRef.free(); + continue; + } + alreadyRead[kidRef.getRefNum()] = 1; + } + kids.arrayGet(i, &kid); + if (kid.isDict("Page")) { + attrs2 = new PageAttrs(attrs1, kid.getDict()); + page = new Page(xref, start+1, kid.getDict(), attrs2); + if (!page->isOk()) { + ++start; + goto err3; + } + if (start >= pagesSize) { + pagesSize += 32; + pages = (Page **)greallocn(pages, pagesSize, sizeof(Page *)); + pageRefs = (Ref *)greallocn(pageRefs, pagesSize, sizeof(Ref)); + for (j = pagesSize - 32; j < pagesSize; ++j) { + pages[j] = NULL; + pageRefs[j].num = -1; + pageRefs[j].gen = -1; + } + } + pages[start] = page; + if (kidRef.isRef()) { + pageRefs[start].num = kidRef.getRefNum(); + pageRefs[start].gen = kidRef.getRefGen(); + } + ++start; + // This should really be isDict("Pages"), but I've seen at least one + // PDF file where the /Type entry is missing. + } else if (kid.isDict()) { + if ((start = readPageTree(kid.getDict(), attrs1, start, alreadyRead)) + < 0) + goto err2; + } else { + error(-1, "Kid object (page %d) is wrong type (%s)", + start+1, kid.getTypeName()); + } + kid.free(); + kidRef.free(); + } + delete attrs1; + kids.free(); + return start; + + err3: + delete page; + err2: + kid.free(); + err1: + kids.free(); + delete attrs1; + ok = gFalse; + return -1; +} + +int Catalog::findPage(int num, int gen) { + int i; + + for (i = 0; i < numPages; ++i) { + if (pageRefs[i].num == num && pageRefs[i].gen == gen) + return i + 1; + } + return 0; +} + +LinkDest *Catalog::findDest(GString *name) { + LinkDest *dest; + Object obj1, obj2; + GBool found; + + // try named destination dictionary then name tree + found = gFalse; + if (dests.isDict()) { + if (!dests.dictLookup(name->getCString(), &obj1)->isNull()) + found = gTrue; + else + obj1.free(); + } + if (!found && nameTree.isDict()) { + if (!findDestInTree(&nameTree, name, &obj1)->isNull()) + found = gTrue; + else + obj1.free(); + } + if (!found) + return NULL; + + // construct LinkDest + dest = NULL; + if (obj1.isArray()) { + dest = new LinkDest(obj1.getArray()); + } else if (obj1.isDict()) { + if (obj1.dictLookup("D", &obj2)->isArray()) + dest = new LinkDest(obj2.getArray()); + else + error(-1, "Bad named destination value"); + obj2.free(); + } else { + error(-1, "Bad named destination value"); + } + obj1.free(); + if (dest && !dest->isOk()) { + delete dest; + dest = NULL; + } + + return dest; +} + +Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) { + Object names, name1; + Object kids, kid, limits, low, high; + GBool done, found; + int cmp, i; + + // leaf node + if (tree->dictLookup("Names", &names)->isArray()) { + done = found = gFalse; + for (i = 0; !done && i < names.arrayGetLength(); i += 2) { + if (names.arrayGet(i, &name1)->isString()) { + cmp = name->cmp(name1.getString()); + if (cmp == 0) { + names.arrayGet(i+1, obj); + found = gTrue; + done = gTrue; + } else if (cmp < 0) { + done = gTrue; + } + } + name1.free(); + } + names.free(); + if (!found) + obj->initNull(); + return obj; + } + names.free(); + + // root or intermediate node + done = gFalse; + if (tree->dictLookup("Kids", &kids)->isArray()) { + for (i = 0; !done && i < kids.arrayGetLength(); ++i) { + if (kids.arrayGet(i, &kid)->isDict()) { + if (kid.dictLookup("Limits", &limits)->isArray()) { + if (limits.arrayGet(0, &low)->isString() && + name->cmp(low.getString()) >= 0) { + if (limits.arrayGet(1, &high)->isString() && + name->cmp(high.getString()) <= 0) { + findDestInTree(&kid, name, obj); + done = gTrue; + } + high.free(); + } + low.free(); + } + limits.free(); + } + kid.free(); + } + } + kids.free(); + + // name was outside of ranges of all kids + if (!done) + obj->initNull(); + + return obj; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Catalog.h swftools-0.9.1/lib/pdf/xpdf/Catalog.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Catalog.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Catalog.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,97 @@ +//======================================================================== +// +// Catalog.h +// +// Copyright 1996-2007 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef CATALOG_H +#define CATALOG_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +class XRef; +class Object; +class Page; +class PageAttrs; +struct Ref; +class LinkDest; + +//------------------------------------------------------------------------ +// Catalog +//------------------------------------------------------------------------ + +class Catalog { +public: + + // Constructor. + Catalog(XRef *xrefA); + + // Destructor. + ~Catalog(); + + // Is catalog valid? + GBool isOk() { return ok; } + + // Get number of pages. + int getNumPages() { return numPages; } + + // Get a page. + Page *getPage(int i) { return pages[i-1]; } + + // Get the reference for a page object. + Ref *getPageRef(int i) { return &pageRefs[i-1]; } + + // Return base URI, or NULL if none. + GString *getBaseURI() { return baseURI; } + + // Return the contents of the metadata stream, or NULL if there is + // no metadata. + GString *readMetadata(); + + // Return the structure tree root object. + Object *getStructTreeRoot() { return &structTreeRoot; } + + // Find a page, given its object ID. Returns page number, or 0 if + // not found. + int findPage(int num, int gen); + + // Find a named destination. Returns the link destination, or + // NULL if is not a destination. + LinkDest *findDest(GString *name); + + Object *getDests() { return &dests; } + + Object *getNameTree() { return &nameTree; } + + Object *getOutline() { return &outline; } + + Object *getAcroForm() { return &acroForm; } + +private: + + XRef *xref; // the xref table for this PDF file + Page **pages; // array of pages + Ref *pageRefs; // object ID for each page + int numPages; // number of pages + int pagesSize; // size of pages array + Object dests; // named destination dictionary + Object nameTree; // name tree + GString *baseURI; // base URI for URI-type links + Object metadata; // metadata stream + Object structTreeRoot; // structure tree root dictionary + Object outline; // outline dictionary + Object acroForm; // AcroForm dictionary + GBool ok; // true if catalog is valid + + int readPageTree(Dict *pages, PageAttrs *attrs, int start, + char *alreadyRead); + Object *findDestInTree(Object *tree, GString *name, Object *obj); +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/CHANGES swftools-0.9.1/lib/pdf/xpdf/CHANGES --- swftools-0.9.2+ds1/lib/pdf/xpdf/CHANGES 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/CHANGES 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,1762 @@ +0.2 (95-dec-12) +--------------- +First public release. + + +0.3 (96-jan-13) +--------------- +LZW patent workaround. +Implemented inline images. +Fixed (mostly) disjoint polygon fills. +Added remote server stuff. +Added page number on command line. +Fixed problem with font encodings which caused character misalignment. +Fixed inverted CCITT decoding and inverted image mask drawing. +Now compiles under gcc 2.7.x (ignore those stupid 'unused parameter' + warnings). +Many minor bug fixes and optimizations. + + +0.4 (96-apr-24) +--------------- +Implemented DCT filter. +Implemented PostScript output; wrote pdftops program. +Implemented links. +Implemented font rotation -- I was wrong: X11R6 servers *do* support + font rotation (by specifying a matrix in place of a size). +Added bindings for Home/End, Page Up/Down, arrow keys. +Added initialZoom resource and -z option. +Added geometry resource and -g option. +Fixed image size off-by-one bug. +Fixed bug where page content is reference to an array of streams. +Cleaned up uninitialized variables which were causing random problems + on various platforms. +Manually skip whitespace before calling atoi() for startxref. +Replaced calls to XrmCombineFileDatabase() with calls to + XrmGetFileDatabase() and XrmMergeDatabases() so it will work under + older versions of X. +Fixed problem with reading multiple xref tables in updated PDF files. +Check for encryption and print appropriate error message. +Rudimentary dithering of images. +Fixed bug in CCITTFax filter (pass mode followed by horizontal mode). +Optimized drawImage() and drawImageMask(). +Changed several things to ease porting: + - changed '__inline' to 'inline' (to adhere to the ANSI standard) + - surrounded interface/implementation pragmas with #ifdef _GNUC__ + - got rid of empty array initializer lists + - moved Operator type definition from Gfx.cc to Gfx.h + - renamed String, uint, etc. + - ability to uncompress to file (NO_POPEN and USE_GZIP flags) + - added definitions of XK_Page_Up/Down and XPointer for old versions + of X +For VMS port: + - use correct Xdefaults name for VMS, get rid of ltkGetHomeDir() + - added '#include ' before all X includes + - renamed files with multiple periods in their names +Fixed window resizing infinite oscillation bug. +Fixed problem with string-type (as opposed to stream-type) indexed + color space lookup tables (which are used in inline images). +If an X font is not found, try smaller and then larger sizes (this is + useful for old or broken X servers which can't scale bitmap fonts). +Added -rgb (color cube size) option. +Various minor bug fixes. + + +0.5 (96-may-23) +--------------- +Fixed bug in LTKWindow which broke the remote server mode. +Fixed PostScript output: + - doesn't seg fault if file is unwritable. + - incorrect DSC comment - need colon in '%%Page:'. + - use 'imagemask' command for masks. + - output filters in the correct order. + - Stream::isBinary() checks the next-to-bottom, not top, stream. + - if page width > height, rotate it 90 degrees. + - if page is larger than paper size, scale it down. +Set default MediaBox to 8.5" x 11" to deal with non-compliant PDF + files which don't specify a MediaBox. +Added DEBUG_MEM stuff in gmem.c and gmempp.cc. +Fixed memory leaks: + - LTKWindow didn't delete the LTKBox. + - LinkAction needs a virtual destructor. +Use $(RANLIB) variable in goo/Makefile and ltk/Makefile. +Allocate image data after calling XCreateImage, using + image->bytes_per_line -- works in 24-bit mode now. +DCTStream rounds width of rowBuf lines up to the next multiple of + mcuWidth, so last MCU doesn't run off end of buffer. +Increase size of block (from 255 to 1024 bytes) read at end of file to + search for 'startxref'. +Skip past garbage at start of file, look for '%PDF'. +Moved more compiler options out of Makefiles into Makefile.config. +Top-level Makefile uses '$(MAKE)' instead of 'make' for making + subdirectories. +Space/PageDown/Next and Backspace/PageUp/Previous now moves to + next/previous page if already scrolled to bottom/top of current + page. + + +0.5a (96-jul-09) +---------------- +[not a public release] +For PDF 1.2 (a.k.a. Amber, a.k.a. Acrobat 3) support: + - look for trailer after first xref instead of at end of file. +Deal with font subsets by converting character names of the form + 'Cnnnn' to the appropriate character from the standard encoding. +Extract encoding from embedded Type 1 fonts. +Kludge to fill one-pixel thick polygons. +Changed X font encoding to use endash for hyphen (gets rid of too-long + hyphens). +Handle Resources key in Pages dictionaries (needed for pstoedit + output). +Fix comment handling in Parser (needed for pstoedit output). +Move Bezier curve conversion from GfxState to XOutputDev; look at + flatness parameter in GfxState. +Change all of the path functions in XOutputDev (stroke, fill, clip) to + use the same path transformation/conversion function. +Rewrote PostScript output driver as a subclass of OutputDev; removed + duplicated code (ps_ functions) from Gfx. +Fixed bug in xref code with small (< 1024 bytes) PDF files. +Implemented BX/EX operators. +Added PDFDoc class. + + +0.6 (96-nov-12) +--------------- +Add support for PostScript output to stdout (-) and to a command + (|lpr); added -ps option and psFile resource. +Decryption is implemented but not included in the distribution due to + legal restrictions: the decryption algorithm is a trade secret of + RSA, Inc., and the U.S.A. still has bogus export controls on + cryptography software. +Added .xpdfrc config file: + - Added fontmap parameter: user can map PDF font names to X fonts. + - Added fontpath parameter: search for Type 1 font if encoding is + not in PDF file. +Incremental display: display is updated after every 200 commands. +Added forward and backward by-10-page buttons. +Links: + - Implement links with "Launch" actions that point to PDF files. + - Draw borders around links. + - Handle links with named destinations. + - GoToR links specify a page number instead of a page reference. +Optimizations: + - Rewrote Stream to use buffering, and added lookChar() functions; + rewrote Lexer to take advantage of this. + - Use hash tables for name->code mapping in font encodings. + - Made XOutputDev::doCurve() iterative, changed /2 to *0.5, and + changed the flatness test. +Added file name to window title. +Implemented RunLength filter. +Implemented forms. +Convert ObjType to an enum. +Changed isDict("Pages") to isDict() (in Catalog.cc) to deal with + incorrect PDF files. +Changed color selection so that very pale colors don't map to white. +Fixed bug in CCITTFax filter (multiple make-up codes). +In GString::clear(): need to set length to 0 before calling resize(). +Base initial window size on first displayed page, not page 1; deal + correctly with rotated pages. +Added ltkGetIntResource() and LTKApp::getIntResource(). +PostScript output fixes: + - Escape backslashes in strings. + - When doing ASCII85 encoding, keep both chars of EOF marker ('~>') + on same line. + - Add extra line '%-EOD-' after image data streams; call wrapper + functions for image and imagemask which look for this line -- this + should fix the 'too much data in stream' bug. + - Font tags can be reused for different fonts on different pages -- + so use font object reference (number/generation) instead. +Initialize character widths to zero (this caused crashes on OSF/1). +Handle image masks which go outside of pixmap. +Makefile.config changes: + - Remove -o in C++ compile rule. + - Add $(AR) variable. +Code which read char widths from font dictionary read all but the last + width. +Add 'return 0;' to main() in xpdf and pdftops. +Allow fonts to use StandardEncoding. +Convert man pages to VMS help files. + +0.7 (97-may-28) +--------------- +Implemented FlateDecode filter (for PDF 1.2). +Basic xref table reconstruction for damaged files +New pdftotext program converts PDF to plain text. +Implemented menus in LTK; added a menu to xpdf. +Added open and save functions; allow xpdf to start without any PDF + file. +Implemented text find. +Implemented text select/copy. +Change mouse cursor when it's over a link. +Embed Type 1 fonts in PostScript output. +Moved rotate functions to menu; added quit to menu. +Fixed stroke color bug in PostScript output (was using fill color + instead of stroke color; this sometimes caused lines to be missing + (white) in PostScript output). +Support Launch-type links -- pops up a dialog before executing + anything. Expects the A (action) dictionary to contain a Unix + dictionary with F (file) and P (paremeter) keys just like the Win + dictionary. +A moveto op all by itself should just be discarded, instead of + generating a subpath with one point (this was causing seg faults). +Balanced parentheses in strings don't need to be escaped. +Tj operator in PostScript prolog didn't check for zero when dividing + by length of string. +Implemented selection in LTK; TextIn widgets support dragging/copy/ + paste. +Handle font subsets that use hex character codes. +Added icon pixmap; added the XPMLIB and NO_XPM variables to + Makefile.config. +Fixed subtle bug in use of horizontal scaling parameter (it affects + only the width of drawn characters, not positioning done in text + space). +Memory testing (with DEBUG_MEM): + - gmalloc now fills memory blocks with garbage to catch unitialized + fields. + - gfree fills memory blocks with garbage to catch uses of freed + blocks. +Handle image masks which go off the pixmap on the top and/or left. +Fixed inline functions which had two return statements (to make the + HP, SCO, and other cfront-based compilers happy). +Fixed bug which caused seg faults when following a link to a different + file (info in LinkGoto object was used after link was deleted by + loadFile). +If page content is an array of streams, the streams are concatenated; + objects and commands can span multiple streams. +If file open fails, try lower-casing and upper-casing the file name. +Commands should end when lexer sees a '/' character. +GString::append(char *, int) was broken. +Changed LTKScrollingCanvas redraw to be more efficient: copy as much + as possible from window before copying from off-screen pixmap. +Ignore gs (set extended graphics state) operator. +Handle colorspaces (CalGray/RGB are treated as DeviceGray/RGB; the + weird colorspaces are not yet implemented). +Named destinations (for links) can be strings as well as names; deal + with the names tree in the catalog. +Clip to the page CropBox. +Added '-q' to gzip options (to suppress warnings, in case user has -v + in GZIP env var). +Added 'include Makefile.config' to top-level Makefile. +Added INSTALL variable to Makefile.config; used in top-level + Makefile. +Always initialize LinkDest left/bottom/top/right/zoom fields (bogus + floating point values were causing crashes on Alpha). +Added Makefile.config options for Digital Unix (DEC compilers), HP-UX + (HP compilers), SCO Unix, and Evans & Sutherland ES/OS. +Added flag to set stream mode in fopen call for VMS. +Rewrote Link module. +Pages with no contents shouldn't cause an error message. +In PostScript output: pdfImM needs to set fill color before doing + imagemask. +If font doesn't specify character widths, use widths from built-in + font, based on font flags. +Fixed LTK scrollbar to delay before repeating and to control the + period between repeats. +Removed window/widget copy() methods (they were untested and unused). +Unknown filter types produce a single error message instead of a + stream of errors. +Added a dummy target in top-level Makefile so making individual + executables (e.g., 'make pdftops') should now work. +Added optional xpdf-flip.ltk with buttons on right side instead of + bottom of window. + +0.7a (98-feb-22) +---------------- +Moved find command from menu to toolbar button ('f' key still works). +Support TrueColor visuals. +Added a -cmap option and a installCmap resource to install a private + colormap. +Mouse button 2 pans the window. +Selecting a URI link now executes a configurable command (from the + urlCommand resource). +Added a "link info" display which shows the URL or file for the link + under the mouse. +Don't draw (or convert to PostScript) text drawn in render modes 3 and + 7 -- this is invisible text, used by Acrobat Capture; this text is + still passed to the TextPage object so that selection works. +Recognize (and quietly ignore) marked content operators (BMC, BDC, + EMC, MP, DP). +Recognize new color-setting operators (scn, SCN). +Added A4_PAPER option. +Embed external Type 1 font files (this currently only works with PFA + files). +Added "-level1" option (in xpdf and pdftops) to generate Level 1 + PostScript. +Setup autoconf -- replaced Makefile.config. Added SELECT_TAKES_INT + flag, and use configure to autodetect (for HP-UX). +Fixed appendToPath() to behave reasonably when appending ".." to root + directory. +Fixed array size in FlateStream::compHuffmanCodes() (was causing xpdf + to crash under OSF/1). +ASCII85Stream, ASCIIHexStream, and DCTStream didn't check for EOF and + could run past the end of the stream in damaged files. +Handle hex escapes (#xx) in names. Still allow the name /# for + backward-compatibility. +Check for NULL characters in encoding array in GfxFont.cc (was calling + strcmp() with NULL which crashed under Solaris). +PageAttrs::PageAttrs() didn't initialize crop box boundaries. +Changed uses of lookup() to lookupNF() in XRef.cc. +Fixed type checking of operators which take a variable number of + args. +Gfx::buildImageStream() doesn't need to check for parser (since I got + rid of the bogus array-of-command thing). +XOutputFont matches on font reference instead of font tag (similar to + PSOutputDev fix). +Fixed bug in position calculation for multi-char substitutions in + XOutputDev. +Cleaned up local variables which hid class variables. +Optimized variable length decoding in CCITTFaxStream. +Set link border width to zero if Border dictionary entry is missing. +Throw away zero-length strings in TextOutputDev -- they don't have + valid xMin/xMax values. +Swapped order of XLIBS and XPMLIB in xpdf/Makefile. +Deleted 'LTKApp::' in function declaration in LTKApp.h. +Changed '(XKeyEvent *)&event' to '&event.xkey' in LTKApp.cc. +Check that the link rectangle coordinates are in the correct order, + and swap if necessary. +TextOutputDev didn't set text to NULL, which caused pdftotext to + segfault if it couldn't open it's output file. +Fixed a hash table search bug in GfxFontEncoding::getCharCode(). +Cleaned up colorspace code: rewrote GfxColorSpace and added + GfxImageColorMap; cleaned up PSOutputDev::doImage. +Handle named colorspaces in images. +Correctly set the default color after a colorspace change. +Old setcolor operators now set the colorspace. +Fixed bug with uncompressed blocks in FlateStream. +Fixed bug with fixed Huffman code table in FlateStream. +Added hash table of X windows (for LTKWindow and LTKWidget) to LTKApp + and replaced calls to XQueryTree with hash table searches -- this + avoids a roundtrip to the server for each event and also fixes the + problem where XQueryTree crashed if the window no longer existed + (with leftover events from a destroyed window). (Thanks to Yair + Lenga for the suggestion.) +Create a new GC for selection -- xor black and white (instead of LTK + foreground and background). +Fixed crash with blank lines in .xpdfrc. +Allow spaces in font descriptors in fontmap lines in .xpdfrc. +Check for bogus object number in XRef::fetch(). +Use MacRomanEncoding for TrueType fonts that don't specify an + encoding. +Certain PDF generators apparently don't include FontDescriptors for + Arial, TimesNewRoman, and CourierNew -- set GfxFont flags + appropriately. +Fixed a bug in width guessing in GfxFont -- sans serif and serif were + swapped. +Rewrote XRef::readXRef() to avoid using a parser to read the xref + entries. +Added NO_TEXT_SELECT option. +Ignore APPn/COM/etc. markers in DCT streams. +Replaced select() with XMultiplexInput() in LTKApp.cc for VMS. +Handle WM_DELETE_WINDOW protocol -- if you ask the window manager to + delete the xpdf window, xpdf will exit cleanly; other + windows/dialogs are simply closed. +Optimized DCT decoder; switched to integer arithmetic. +The "/Type /Annots" field in an annotation dictionary is optional. +Check for null nameTree in Catalog::findDest(). +In XOutputDev, search user font map before default font map. +Added "normal" SETWIDTH parameter to all font descriptors in + XOutputDev (some systems have a narrow-width Helvetica font). +Added FOPEN_READ_BIN and FOPEN_WRITE_BIN to support Win32. +Added a hack which allows better font substitution for some Type 3 + fonts. Also allow character names of the form /nn and /nnn. +Added and to LTKApp.cc (needed by AIX and IRIX + for bzero() declaration for FD_ZERO). + +0.80 (98-nov-27) +---------------- +Support for some Japanese fonts (Type 0 fonts using the Adobe-Japan1-2 + character collection, horizontal only). +Added pdfinfo application. +Added pdftopbm application. +Added pdfimages application. +Added -papercolor option and .paperColor resource. +Fixed divide-by-zero problem in XOutputDev Type 3 font matrix kludge. +Font subset char names can be 'Bxx' as well as 'Cxx' and 'Gxx'. +Fixed bug in color space conversion in DCTStream filter (YCC->RGB was + correct, YCCK->CMYK was broken). +Added XRef::getDocInfo() and PDFDoc::getDocInfo() to support pdfinfo. +Optimized GfxImageColorMap. +Lexer::getStream(), getPos(), and setPos() check for null stream. +Decryption code now does strings as well as streams. +ASCII85 decoder rounds short tuples up instead of down. +CropBox and MediaBox can be non-integers. +PostScript output: + - Use a rectangle operator. + - Call setpagedevice with page size. + - Insert %%PageOrientation comments. + - Add paper size flags (-paperw and -paperh) to xpdf and pdftops. + - If HAVE_POPEN is not defined, and user tries to print to '|...', + the PSOutputDev destructor tried to write to the PS file. + - Added support for forms (pdftops -form). +Removed error messages for empty paths in stroke, fill, etc. operators. +Don't allow flatnesses less than 1 in XOutputDev (this speeds up + rendering a little bit when there are lots of tiny curves). +Moved the font subset character name guessing from GfxFont to + XOutputDev and TextOutputDev - now these files print correctly. +Cast argument to XFree() to XPointer; add XPointer definition where + necessary (portability fixes). +Various minor VMS fixes. +Changes to configure script and Makefiles: + - Print a warning if X is missing. + - Use C++ when checking select() argument type (HP-UX). + - Use 0 instead of NULL when checking select(). + - Default to gcc instead of c++. + - Get rid of AC_C_INLINE -- this is meant for C, not C++. + - Changed -USE_GZIP to -DUSE_GZIP. + - Added ability to compile ouside of the source tree. + - Added .cc.o rule to {goo,ltk,xpdf}/Makefile.in. + - Added @LIBS@ to XLIBS in xpdf/Makefile.in. + - In top-level Makefile.in: added '-' to clean commands; added + distclean rule. + - Create install directories. + - Use INSTALL_DATA (instead of INSTALL) for man pages. + - Changed xpdf-ltk.h rule to avoid leaving an empty file when + ltkbuild fails. + - Change things so that by default, ltkbuild is not built and + xpdf-ltk.h is not rebuilt. + - Use AM_PROG_CC_STDC to add compiler flags for ANSI C. + - Modify autoconf's builtin macros to check for xlC. + - Use Steve Robbins' smr_CHECK_LIB to test for pixmap library (Xpm) + -- this should fix the problems on systems that have the library + but not the include file. + - Added better test for sys/select.h, sys/bsdtypes.h, strings.h, + bstring.h. + - New VMS make scripts from Martin P.J. Zinser. + - Moved dependences into Makefile.in -- this gets rid of problems + with 'cc -MM' (which is gcc-specific) and 'include Makefile.dep' + (which isn't supported by all make implementations). Also changed + all non-system include files to '#include "..."' (from '<...>'). +Tweaked the TextOutputDev heuristics slightly. +Modify Gfx to use a stack of resources -- this is necessary for Form + XObjects, which can define their own local resources; also modified + PSOutputDev to dump fonts used by forms. +Look for excessively large MediaBox (compared to CropBox) and shrink + it to CropBox. +Minor fix to scrolling when dragging a selection. +Various patches for pdftex and Win32 support. +Deal with Separation colorspaces by using their alternate colorspace + entry. +Added PBMOutputDev for pdftopbm application. +Added ImageOutputDev for pdfimages application. +Separated XOutputDev into LTKOutputDev + XOutputDev. +Added support for 1-D and mixed 1-D/2-D (Group 3) decoding to + CCITTDecode filter. +Added resetImage(), getImagePixel(), and skipImageLine() to Stream + class; used these in XOutputDev, PSOutputDev, and ImageOutputDev. +Implemented predictor for LZW and Flate filters. +In pdfImM1 in PSOutputDev prolog: div should be idiv. +Changed output from printUsage() function in parseargs to look nicer. + +0.90 (99-aug-02) +---------------- +Added Type 1/1C font rendering, using t1lib. +Added "backward" and "forward" buttons. +Added fit-page and fit-page-width zoom factors; replaced zoom-in and + zoom-out buttons with a zoom popup menu. +Type 1C fonts are converted to Type 1 and embedded in PostScript. +Support vertical Japanese text. +Added Japanese text support (EUC-JP) to pdftotext. +Bumped PDF version to 1.3. Added stub functions for ri and sh + operators. (But there are still some missing 1.3 features.) +Added -raw option to pdftotext. +Minor changes to allow compiling under MS Visual C++ 5.0. +Top-level makefile: changed 'mkdir -p' to '-mkdir -p'. +Configure script: added X_CFLAGS to smr_CHECK_LIB(Xpm). +Added Xpm_CFLAGS to xpdf/Makefile.in (this is needed to get the -I for + the xpm includes). +Rewrote code that handles font encodings; added support for Type 1C + fonts. +In the setpagedevice dictionary in PostScript output - added a + /Policies entry which tells the PS interpreter to scale the page to + fit the available paper. +Changed PageUp behavior slightly: move to bottom (instead of top) of + previous page. +TextPage used character's dx (width + char space) instead of just its + width. +Read base URI from document Catalog (for URI-type links). +Minor change to configure script to avoid using 'unset'. +Fixed bugs in CropBox inheritance. +Fixed a bug in resource stack handling for form objects. +Display forms even if they have a missing/incorrect FormType. +Fixed a bug in stream predictors -- the predictor parameters (width, + comps, bits) don't need to match the actual image parameters. + Completely rearranged the predictor code. +Fixed PostScript output to correctly handle stream predictors. +Don't segfault on empty (zero-page) documents. +Added the xpdf.viKeys feature. +Added the ffi and ffl ligatures to XOutputDev and TextOutputDev. +Pdftotext and pdfimages now check okToCopy(). +Added a '-q' flag to all programs (except pdfinfo) to suppress + messages and errors. +Deal with DeviceN colorspaces by using their alternate colorspace + entry. +Change PostScript output so setpagedevice is only called once, at the + very beginning of the document (to avoid problems on duplex + printers). +Changes to configure script and makefiles for DOS/DJGPP. +FontEncoding::getCharCode() looked for (code>0) instead of (code>=0). +Added keypad arrow keys, etc. to xpdf. +Minor changes to gfile.{h,cpp} () to compile under VC++. +Fixed CCITTFaxStream to correctly handle all parameters. +Modifications to gfile.{h,cc} for Acorn. +Some minor changes for OS/2. +Added 'SHELL = /bin/sh' to Makefiles. +Compare file version to pdfVersionNum+0.0001 to avoid floating point + precision problems. +Added LDFLAGS to Makefiles. +Removed strip entirely from configure and Makefiles. +Fixed a bug in choosing the correct DCTStream color transform. + +0.91 (2000-aug-14) +------------------ +Added TrueType font rendering, using FreeType. +Support for Chinese fonts (Type 0 fonts using the Adobe-GB1-2 + character collection). +Decryption code is included with the main distribution (now that the + US export regulations are a little bit less irrational). +Added (very basic) support for generating PostScript with Japanese + fonts -- only tested with ghostscript so far. +Added support for generating EPS files (pdftops -eps). +Much-improved image filtering in xpdf (for downsampling and for + transforms other than 0/90/180/270-degree rotations). +Implemented a basic full-screen (presentation) mode (xpdf + -fullscreen). (There is currently no way to switch between window + and full-screen modes on the fly -- this will be fixed in a later + release.) +Added "reload" menu item. +Do a better job with anti-aliased Type 1 fonts on non-white + backgrounds. +Handle Lab color spaces. +Handle non-null user passwords. +Avoid security hole with tmpnam()/fopen() -- added openTempFile() in + goo/gfile.cc. [Thanks to Joseph S. Myers for pointing this out.] +Filter out quote marks (' and ") in URLs before running urlCommand to + avoid a potential security hole. [Thanks to Frank Doepper for + pointing this out.] +Fixed TrueColor detection to look at the complete list of available + visuals, not just the default visual. +In gfile.h, changed NAMLEN(dirent) macro to NAMLEN(d). +Removed copyright character from start-up banners. +In the open and save dialogs, if the open/save button is pressed with + no file name, the dialog is not canceled. +Added Xpm_CFLAGS to ltk/Makefile. +XOutputDev::updateLineAttrs was using dashLength before it was + defined. +In top-level Makefile.in, use INSTALL_PROGRAM instead of INSTALL. +In man page, recommend -q instead of -err in .mailcap. +Changes for GNOME / Bonobo support: + - Separated Stream classes into BaseStream and FilterStream trees. + - Got rid of all FileStream-specific stuff. + - Added a PDFDoc constructor that takes a BaseStream* instead of a + file name. +Allow newlines inside strings (Photoshop does this). +Don't require whitespace between tokens in consecutive content + streams (for pages that specify an array of streams). +Look at MissingWidth when constructing font character widths array. +Fixed a bug that caused incorrect PostScript output for images that + use 8-bit indexed color spaces with < 256 colors in the palette. +Handle case where embedded font file is bad (this was seg faulting). +Minor changes for Windows/pdftex. +Work around a bug in PDF files from the IBM patent server. +Fixed bugs in PostScript form generation: use pdfStartPage instead of + pdfSetup; problem with inline images. +Minor bug fix in FlateStream::loadFixedCodes(). +Added %%DocumentMedia and %%PageMedia comments to the PostScript so + that gsview (a Windows frontend for ghostscript) gets the right + paper size. +Draw AcroForm fields that have appearance annotations. +Bounds check gray, CMYK, and RGB values (in GfxColor). +Moved the link border drawing code into Page (from PDFDoc). +Minor modifications for pdftohtml. +PSOutputDev: use the Type 3 font scaling kludge from XOutputDev. +Separation color spaces were handled incorrectly in images. +Fixed a bug with form bounding boxes. +Modified the t1lib support -- replace libt1x code with my own code. + Type 1 and TrueType fonts are now handled similarly, and clipping + works on Type 1 fonts. +Don't print copyright banner (xpdf); add -v switch to get copyright + and version info (all apps); get rid of -err switch (xpdf). +Automatically reload the PDF file if it has been changed, i.e., if the + modification time is different. +Fixed a memory (malloc size) bug in CCITTFaxStream. +Fixed two bugs in FontEncoding::hash() -- handle zero-length character + names (which were found in a (buggy?) PDF file), and handle + character names with high-bit-set characters (use unsigned ints). +Added PDFDoc::isLinearized() and corresponding code in pdfinfo.cc. +Handle files with an incorrect page count in the Pages dictionary + (FOP, from the Apache project produces a page count of 0). +Handle TrueType equivalents to the Base14 fonts (Arial, TimesNewRoman, + CourierNew) -- Adobe's tools use these names without embedding the + fonts. +Tweaked the Type 3 font sizing kludge. +Changed pdfimages (ImageOutputDev) so it doesn't output JPEG files for + 4-component color spaces, since these seem to confuse most image + viewers. +Added support for generating OPI comments (pdftops -opi). +In XOutputDev::drawImage() and drawImageMask(), check for images that + are completely off-page. +Use the provided alternate or a default (DeviceGray/RGB/CMYK) color + space for ICCBased color spaces. +Incorporated MacOS-specific code from Leonard Rosenthol. +Configure script switches to C++ for the strings.h/bstring.h test. +Gfx::opRestore() calls clearPath() to handle (apparently) buggy PDF + files produced by FreeHand. +The /Type field in most dictionaries is optional (PDF 1.3 change). +Move printCommands variable definition into Gfx.cc. +If page is smaller than paper, center the PostScript output. +Fix a minor bug in the SELECT_TAKES_INT detection in the configure + script. +TextOutputDev filters out control characters. +Changed enough occurrences of 'char *' to 'const char *' to keep gcc + 2.95 from barfing. +Support for Latin-2 and Latin-5 in pdftotext (however, this will only + work if the PDF file contains correct font encodings, which seems to + be rare). +TextOutputDev converts "eightoldstyle" to "eight", etc. +Don't use the return value from sprintf() -- most systems return the + length, but some return the string. +Minor fixes for SunOS 4. +Configure script looks for both select() and fd_set in sys/select.h. +Configure script checks for gethostbyname() in -lbsd (for LynxOS). +Fix missing closepath bug in PostScript output. +Change PostScript portrait/landscape mode selection so it only uses + landscape if the page width is greater than the paper width. +Tweaked the VMS code in makePathAbsolute(). + +0.91a (2000-oct-11) +------------------- +Implemented separable CMYK PostScript output (the -level1sep switch to + pdftops). +Implemented Pattern color spaces with tiling patterns (polygon fills + only). +Implemented Stamp annotations. +Implemented Named link actions. +Fixed a really dumb bug in the TrueColor code in SFont (which affects + both Type 1 and TrueType font rendering on 16-bit displays). +Rewrote the GfxColorSpace / GfxColor code. +Switched from djgppcfg to dj_make.bat (from Michael Richmond). +Bug in the Type 1 encoding parser -- couldn't handle lines of the form + 'dup NNN/name put' (with no space between the code and the name). +Fixed the mkstemp() test in configure.in -- switched from + AC_TRY_COMPILE to AC_TRY_LINK and added . +Added DESTDIR to top-level Makefile.in. +Fixed an incorrect OPI comment in PSOutputDev. +Minor tweak to the CCITTFax code to avoid writing past the end of an + array on an invalid data stream. +Xpdf crashed if the user selected 'reload' when no document was + loaded. +Look for character names of the form "xx" (two hex digits with no + leading alphabetic char) and 'cNNN' (decimal digits with a leading + alphabetic char that happens to be a hex digit). +FlateStream didn't correctly handle zero-length streams. +Xref reconstruction didn't handle the case where the opening "<<" + immediately followed "trailer" with no intervening whitespace. +Fix the %%DocumentSuppliedResources comment in EPS output. +Scale annotations to fit their rectangles. +Added Stream::close() to handle cases (e.g., patterns) where a Stream + object is used multiple times before it is deleted. +Added the topLevel arg to Gfx::go() so it doesn't call out->dump() for + every pattern element (and form). +Rearranged the GfxResources class. +Clean up white space handling in Lexer. +Make the dpi parameter to PDFDoc::displayPage etc. a double - this + avoids margin gaps with fit-page and fit-width. +Fix a rounding problem in xpdf.cc that was causing the window to + sometimes be one pixel too small. +Fixed a minor bug in dealing with Base-14 TrueType font names. +Fixed Lab -> RGB color space conversion. +Added support for opacity values (from PDF 1.4) to GfxState and + OutputDev. [Thanks to Leonard Rosenthol.] +Implemented type 2 functions; rearranged the Function class + hierarchy. + +0.91b (2000-oct-29) +------------------- +Print a warning about Type 3 fonts (XOutputDev, PSOutputDev). +Added the scroll lock behavior to 'n' and 'p' keys in xpdf. +Change FileStream buffer size to a #define'd constant. +Renamed Pattern to GfxPattern to avoid clashes with Windows and MacOS + types. +Added CNS (Big5) Chinese font support (CHINESE_CNS_SUPPORT); renamed + CHINESE_SUPPORT to CHINESE_GB_SUPPORT. + +0.91c (2000-nov-19) +------------------- +Fix an endianness problem in the Type 1 font code which resulted in an + incorrect display with "-t1lib plain" on big-endian systems. +CCITTFax stream decoder will skip over extra zero bits at end of line, + even if EncodedByteAlign flag wasn't set. +Added Big5 support to pdftotext (with CHINESE_CNS_SUPPORT enabled). +Fixed a typo in the CNS/Big5 encoding translation table. +Change the form code in PSOutputDev to store images in arrays of + strings. +The xref reconstruction (for damaged files) now also looks for + 'endstream' tags, and the parser uses this information when setting + up stream objects. +In pdfinfo, convert Unicode chars in the 00xx range into 8-bit chars; + print a warning if there are any other Unicode chars. + +0.92 (2000-dec-03) +------------------ +Fixed %%BeginResource comment (for xpdf procset) in PostScript + output. +Added "-title" switch and "xpdf.title" resource to set the window + title. +Check for in addition to . +Upgraded the configure script to smr_macros 0.2.4 - this should fix a + bug where configure wasn't correctly finding t1lib. + +0.92a (2000-dec-17) +------------------- +Added 'extern "C" { ... }' in various places for ANSI C++ compliance. +Tweaked the code that figures out DPI for fit-to-page and fit-to-width + modes. +Fixed the image transformation code in XOutputDev -- no more missing + lines. +Implemented color key image masking in XOutputDev. + +0.92b (2001-jan-07) +------------------- +Fixed a bug in the error-checking code in the Separation/DeviceN color + space parsing functions. [Thanks to Lidia Mirkin.] +Added wheel mouse support (mouse buttons 4 and 5). [Thanks to + Thorsten Schreiner.] +Added preliminary support for FreeType 2 (disabled by default). + +0.92c (2001-jun-04) +------------------- +Fixed a bug in the new image transformation code. +Look for character names of the form "", instead + of looking for names beginning with a few specific letters. +T1FontFile::T1FontFile wasn't initializing vars, and ~T1FontFile + wasn't checking before calling T1_DeleteFont -- this caused crashes + if it tried to open a nonexistent font file. +Catalog::Catalog didn't set baseURI to NULL early enough. +Tweak the check for strings.h in the configure script. +Yet another fix for the image rotation code in XOutputDev -- + off-by-one problem when upsampling. +Handle Type 1/1C encodings when using FreeType 2. +Allow FreeType2 to render user-supplied Type 1 base fonts. +Opening a new file from full-screen mode tried to scroll. +Fixed a bug in GfxFont constructor (missing check for NULL base font + name). +Don't crash if a Type 1 font's FontBBox is non-integer. +Pdfinfo prints page size. +Tweak for the alpha hack in T1Font/TTFont: sample the middle pixel + instead of the top-left pixel. +Automatically activate the text input widget in the find window. +Changed a Japanese char code mapping in XOutputDev and TextOutputDev: + period was being incorrectly mapped to small circle (end-of-sentence + character). +Add the 0/+/-/z/w key bindings to control the zoom setting. +Fixed ImageOutputDev (pdfimages) to correctly handle inline image + masks. +Extract ascent/descent info from font descriptor. + +0.92d (2001-jun-26) +------------------- +Embed TrueType fonts in PostScript output. (Added a "-noembtt" flag + to pdftops.) +Extract encoding from TrueType fonts. +Moved Function classes to a separate file (Function.h/cc). +Implemented multi-dimensional sampled Functions. +Implemented Type 4 (PostScript calculator) Functions. +For Type 0 fonts, FontDescriptor is in descendant font, not parent. + [Thanks to Lidia Mirkin.] +Added the "-htmlmeta" option to pdftotext. +In TextOutputDev, when computing the number of blank lines to insert, + do a sanity check on the result. +If both FlateDecode and some other filter (e.g., DCTDecode) were + applied to an image stream, getPSFilter() crashed instead of just + returning NULL. +Handle the /Identity function. + +0.92e (2001-aug-23) +------------------- +Widths in font dict should override built-in font widths. +Changed "rotate left/right" menu items to "rotate + clockwise/counterclockwise". +The link parsing code choked if the Border array was incorrect (too + short). +Modified PSOutputDev to output CMYK for fill/stroke colors. + +0.93 (2001-oct-25) +------------------ +Implement PDF 1.4 (128-bit) decryption. +Bump supported PDF version number to 1.4. +Text output for Simplified Chinese. [Thanks to Cheung Siu Fai.] +Read an app-defaults file for Xpdf. +Read a system-wide config file (/etc/xpdfrc) if ~/.xpdfrc + doesn't exist. +Accept and verify owner password; if correct, allow all actions. +Added a "-level2sep" option to pdftops to generate Level 2 separable + PostScript. The PostScript separation convention operators are used + to handle custom (spot) colors. [Thanks to Thomas Freitag for help + on this.] +Add support for FreeType 2 to the configure script. Warning: this + requires FT 2.0.5 or newer. +Fixed the bounding rectangle overlap test in the disconnected subpath + fill hack in XOutputDev. +Stupid typo in font name table in PSOutputDev. +Changing the zoom setting with a keyboard shortcut didn't update the + displayed setting. +Modified the mouse wheel support and added the second wheel (mouse + buttons 6 and 7). [Thanks to Michal Pasternak.] +Character and word spacing is affected by horizontal scaling (display + and PS output). [Thanks to Eddy Ng.] +Rotation specified by the text matrix, character spacing, and + horizontal scaling interacted incorrectly (display and PS output). +Some broken Type 1/1C fonts have a zero BBox -- kludge around this by + assuming a largeish BBox. +Handle PDF files with an incorrect (too small) xref table size. +Allow "-?" and "--help" as aliases for "-h" (all apps). +Correctly handle unescaped parens in strings in Lexer. +Fixed a bug in LTK where a menu got posted multiple times if you right + clicked while a page was being rendered. +Removed a comma inside a string in configure.in. +Kludge around broken PDF files that use char 32 but encode it as + .notdef instead of space. +Clean up various compiler warnings: use constructor args like "fooA" + if there is a field named "foo". Everything now compiles cleanly + under gcc 2.91.66, 2.95.2, and 3.0.1. +Page objects now read all of the page rectangles (MediaBox, CropBox, + BleedBox, TrimBox, ArtBox), as requested by the pdfTeX folks. + Added a new PDFRectangle struct to hold these. +Use XOutputDev's Type 3 font size hack in TextOutputDev too, so it + does a little better job of extracting text in Type 3 fonts. +Modify pdfimages to write one-bit images as PBM files. +Work around a bug in cygwin's implementation of fseek. + +0.93a (2001-nov-21) +------------------- +Implemented the sh (shaded fill) operator for the axial shading type. +Minor fixes to avoid compiler warnings. +Cleaned up global variables -- moved many into instance vars and + function args. +Minor fixes for OS/2. +Fix the system config file path for VMS. +Fix an uninitialized var in XOutputDev that caused crashes on Alphas. +Don't incrementally update the display in full-screen mode. +For Type 1/1C fonts, use the FontBBox from the PDF FontDescriptor + (instead of the one in the font file) if present -- this avoids + problems with fonts that have non-standard FontMatrixes. +Add the Euro character to WinAnsiEncoding. +Track the bounding box of the clip region to make rendering patterns + more efficient. +Fix openTempFile() for Win32. + +0.93b (2001-dec-11) +------------------- +Added a duplex option to PSOutputDev and a -duplex switch to pdftops. +Added XRef::PDFgetDocInfoNF() for pdftex project. +Updated the VMS build script. + +0.93c (2001-dec-12) +------------------- +Completely rewrote the code that handles font encodings: + - everything is Unicode-based + - 16-bit fonts are handled much more cleanly + - text output encoding can be set more flexibly +New .xpdfrc config files. + +1.00 (2002-feb-01) +------------------ +More work on the font encoding rewrite: + - use the ToUnicode font dict entry + - pdfinfo and pdftotext (with '-htmlmeta') convert info strings to + the selected text encoding +Added key bindings for forward ('v') and backward ('b'). +Added the pdffonts program which lists the fonts used in a PDF file. +Fixed several problems in the TrueType font embedding code (for + PostScript output). +Accept named destination on command line. +Added several new items to pdfinfo: file size, PDF version, tagged + (yes or no), XML metadata (with the -meta option). +Pdftops didn't get the portrait/landscape setting correct for PDF + files with rotated pages. +The TrueTypeFontFile class (including the Type 42 converter) now + understands cmap format 6. +Improved the "about" window -- mention the GPL, add a list of key + bindings. +Added Zcaron and zcaron characters to WinAnsiEncoding. +The '0' keyboard shortcut didn't update the zoom popup menu. +Handle the complete list of alternate names for the Base14 fonts. +Fixed substitute font scaling in XOutputDev - scale only the width, + not the height. +Implemented stitching (type 3) functions. +Handle the case of moveto/closepath/clip, which defines an empty + clipping region. +Move dependences into separate Makefile.dep files; get rid of the + distdepend target. +Move all of the configure-script-generated -D options out of the + Makefiles and into a top-level .h file (aconf.h). +Cleaned up the FreeType 1/2 detection code in the configure script. +Pdfinfo prints dates in a more readable format. +Fixed a bug in the Paeth image predictor. +Handle annotations with multiple states. +Another workaround for buggy X servers: clip points that are way out + of bounds. +Added libpaper support (for Debian). +Generate PostScript DSC resource comments for PS (not just EPS) + files. +The save and restore (q/Q) operators shouldn't save/restore the path. +Performance optimization: disable pattern drawing in TextOutputDev. + +1.00a (2002-feb-25) +------------------- +Added an optimized special case for one-bit images in XOutputDev. +Implemented CID TrueType font embedding; added a psEmbedCIDTrueType + option. +The initialZoom X resource was broken. +The reverse MacRoman encoding should return 32 for "space" (not 202, + which is an alternate encoding). +Tweaks to the FreeType 2 support: only disable hinting if the bytecode + interpreter is disabled (i.e., disable autohinting but not bytecode + hinting); add some padding to the glyph cache for CJK fonts. +Added level3 and level3Sep options for the psLevel setting and + corresponding -level3 and -level3Sep options to pdftops. +Added a -level2 option to pdftops for consistency. +Avoid a divide by zero in pdftotext. [Thanks to William Bader.] +Added a Greek language support package. [Thanks to Alexandros + Diamantidis and Maria Adaloglou.] +Don't bother trying to extract a "builtin" encoding from a TrueType + font. +Accept either a page number or a page reference in a link + destination. +Update the fontFixedWidth flag in GfxFont after reading the char + widths (used by the Acorn RiscOS port). +Removed yet another (illegal but not caught by gcc) class specified + from a .h file. +Avoid using snprintf - it's not available everywhere. +Improved the CMYK->RGB transform. +Use mkstemps where available. + +1.01 (2002-may-20) +------------------ +Implemented Type 3 fonts. +Implemented PostScript CID font embedding; added a + psEmbedCIDPostScriptFonts option. +Implemented PostScript 16-bit font substitution; added psNamedFont16 + and psFont16 options. +Moved the initialZoom setting from X resources to the xpdfrc file. +Implemented the radial shading type in the sh (shaded fill) operator. + [Thanks to Mike Sweet.] +Added an 'include' command to the xpdfrc format. +Added the displayNamedCIDFontX option so different fonts can be used + within one character collection. +Added a simple reverse video mode (-rv switch, xpdf.reverseVideo + resource). +Implemented stroked text in XOutputDev (with t1lib and FreeType2). + [Thanks to Leonard Rosenthol.] +Implemented stroked text in PSOutputDev. +Added a built-in Unicode map for UCS-2. +New key binding in xpdf: 'g' activates the page number text field. +PSOutputDev will now embed external TrueType fonts in addition to + external Type 1 fonts. +The psEmbedType1Fonts and psEmbedTrueTypeFonts options were missing + the "Fonts" suffix. +Documentation in xpdf.1 for -freetype option was wrong. +Added the Big5ascii Unicode map to the Chinese-traditional support + package (maps 7-bit ASCII straight through). [Thanks to Lawrence + Lai.] +Modified the EUC-CN and EUC-JP encodings to pass 7-bit ASCII straight + through. [Thanks to Lawrence Lai.] +Avoid a divide by zero in XOutputDev. [Thanks to Simon Burge.] +Remove old code in openTempFile that removed an extension from the + name returned by tmpnam. +Tweak the scrolling behavior when switching pages. [Thanks to Case + Jones.] +In the code that guesses character names (for font subsets), also + handle names of the form 'ABnnn'. [Thanks to Colin Granville.] +Fix the transform code for annotations. +Improved the CMap file parser to handle more general PostScript + lexical conventions. +Added '-enc' option to pdfinfo. +Added the small caps and oldstyle numbers from Adobe's Unicode + corporate use area to the Latin1 and ASCII7 Unicode maps. +The code in TextOutputDev that guesses Type 3 font size could generate + a zero size, which resulted in div-by-zero errors. +Various tools (including Adobe's) occasionally embed Type 1 fonts but + label them Type 1C - so check for a '%!' at the start. +Some tools embed Type 1C fonts with an extra whitespace char at the + beginning - just skip over it. +Fixed a typo in the Simplified Chinese add-to-xpdfrc file. +Updates to dj_make.bat and the djgpp build instructions. +Added a Turkish language support package. +Updated VMS build scripts. [Thanks to Martin Zinser.] +Modify the incremental display update code to redraw less often if + most of the commands are vector graphics, as opposed to text and + images. +Tweak the Type 1 font bbox code to look at the bboxes in both the PDF + font object and the embedded font file. +Fixed the ETenms-B5-H CMap file (for traditional Chinese) to map the + Latin characters to their proportional versions. +Added an optional displayCIDFontX entry for one of the Arphic TrueType + fonts in the traditional Chinese 'add-to-xpdfrc' file. +Remove leading '-' on include statements in Makefiles. +Added psASCIIHex parameter. +Added the GBK Unicode map to the simplified Chinese language pack. +Pdftotext now opens the text file in binary mode to avoid Microsoft's + annoying automatic end-of-line translation stuff. +Added an executeCommand function in goo/gfile.cc. [Thanks to Mikhail + Kruk.] +The %ALDImagePosition OPI comment was wrong if the page was scaled to + a different paper size. +The OPI code was saving the default transform matrix before calling + setpagedevice, which can change the matrix. +Fixed a crash when an inline image dictionary contains garbage. +Upgraded to autoconf 2.53. +Use unsigned int file offsets, to allow access to PDF files in the 2-4 + GB size range; use fseek64/ftell64 if available. +Fixed two floating point exception cases that came up with broken PDF + files. +Avoid a crash when printing an error message regarding an unnamed + font. +Default link border width should be 1. [Thanks to Michael Pfeiffer.] +Minor tweak to build with FreeType 2.1.0. +Handle "weird" characters in PostScript font names. +PSOutputDev now handles PostScript XObjects. +Added several more page attributes for the pdftex project. +Transferred the copyright to Glyph & Cog, LLC. + +2.00 (2002-nov-04) +------------------ +Switched to the Motif toolkit. +Support multiple open documents (in separate windows). +Added document outlines to the viewer. +Modified the text extraction (placement) algorithm. +Implemented the JBIG2 decoder. +Added a Latin2 language support package. +Added support for movie annotations. +Switched back to native LZW decompression code. +Text extraction from Type 3 fonts was (partly) broken. +The owner password checking code was missing a step in the case of + 128-bit encryption. +Added the 'printCommands' option to the xpdfrc file. +Added key binding for '?' to bring up the about/help dialog. +In TextOutputDev, ignore any text that's outside the page bounding + box. +Text extraction throws away "tiny" characters after the first 20000 + per page, to avoid really slow runtimes with PDF files that use + special fonts to do shading or cross-hatching; added the + 'textKeepTinyChars' option to disable this behavior. +Text extraction discards duplicated text (fake boldface, shadow + effects). +Added ctrl-F as a key binding for find. +Added a "find next" function, bound to ctrl-G. +Added ctrl-P as a key binding for print. +Modified the DCT decoder to handle progressive and non-interleaved + JPEG streams. +Added key bindings for ctrl-Home and ctrl-End. +Allow the initialZoom setting to be made in either the xpdfrc file or + as an X resource. +Added a Hebrew language support package. [Thanks to Roy Arav.] +The "make distclean" target now creates (empty) Makefile.dep files in + the three subdirectories. +Initialize XRef::ownerPasswordOk. +Correctly handle stroking of Type 3 fonts in PSOutputDev. +Generate correct PostScript for fonts with "weird" character names + (e.g., "("). +Generate correct PostScript for images using Indexed color spaces with + DeviceN base color spaces. +Added lowercase Roman numerals to ISO-2022-CN.unicodeMap (simplified + Chinese support package). +Tweak the image scaling code to better handle flipped (top-bottom + and/or left-right) images. +Generate correct PostScript code for inline images and images in Type + 3 fonts which are too large for a single PS string. +Correctly handle indexed color spaces whose base color spaces have + component ranges other than [0,1]. +Optimized the DCT decoder. +Fixed mistakes in the list of key bindings in the about/help dialog. +Optimized the Flate decoder. +Add literal names for punctuation and digits to the Unicode name + table. +Cygwin's popen wants mode "r", not "rb". +Fixed a bug in the Type 4 function parser (the "if" operator wasn't + parsed correctly). +Fix a bug in PS output for TrueType fonts with no PDF encoding. +Make the bbox size in FTFont more liberal (to avoid problems with + fonts that have incorrect bboxes). +Reverse the colors in PBM files generated by pdfimages, so the common + case (an image mask filled with black) comes out correct. +Add fseeko/ftello support which is basically identical to + fseek64/ftell64. [Thanks to Nassib Nassar.] +Modified column assignment in text extractor to account for characters + that convert to multiple characters in the output encoding. +Fix TrueType fonts which have an incorrect cmap table length. +Work around a pragma bug in the version of gcc that ships with MacOS X + 10.2. [Thanks to Frank Siegert and Andrew Stone.] +Fix a problem that was causing an infinite loop when a damaged content + stream contains an 'ID' command inside a dictionary. +Handle the case where systempapername() returns NULL (libpaper + support). +Handle fonts which are defined directly in the font resource + dictionary rather than as separate objects. +Track process colors in Level 1 separable PostScript. +Pdfinfo now checks the return value from mktime to avoid seg faults in + flakey strftime implementations. +If duplex is not enabled in PostScript output, leave the duplex + setting alone, allowing the spooler to insert its own setting. +Added three missing fclose calls. +Change the default encoding for TrueType fonts (used when the PDF file + doesn't specify an encoding) from MacRomanEncoding to + WinAnsiEncoding. +Move X_CFLAGS to the end of the list in CXXFLAGS (in Makefile.in) to + avoid some of the FreeType2 include path problems. +Fixed an obscure bug in the LZW decoder. [Thanks to Martin + Schroeder.] +Fixed a bug in decryption when using the newer (PDF 1.4) algorithm + with shorter-than-128-bit keys. +Minor optimization for image data streams: the ImageStream class can + return an entire buffered line. + +2.01 (2002-dec-05) +------------------ +Redesigned the text extraction process: + - process the text into "reading order" + - added a "-layout" flag to pdftotext to switch back to the old + style, where physical layout is maintained + - use of the "-raw" flag is no longer recommended +Added the -reload option for xpdf (in remote mode). +Added support for external CID fonts; added the displayCIDFontT1 and + displayNamedCIDFontT1 commands to the xpdfrc file. +Handle the case of moveto/newpath/clip, which defines an empty + clipping region (just like moveto/closepath/clip). +Accept XYZ link destinations with missing array elements. +Fix some problems with state save/restore triggered by Type 3 fonts + that reference other fonts. +Accept bogus font names based on "Symbol": Symbol,{Bold,Italic, + BoldItalic}. +Fixed color and font resource names in the xpdf man page. +Was using delete instead of gfree in OutlineItem::~OutlineItem. +Set the busy cursor in the find dialog while searching. +Map variants of the copyright, trademark, and registered trademark + symbols to the proper Unicode codes, not to Adobe's corporate use + area codes. +Fixed a floating point exception bug in TextOutputDev (check for a + too-small denominator). +Fixed a typo in TextOutputDev, in the code that generating blank lines + to add vertical whitespace. +Config files whose last line didn't end with a LF (or CR+LF) weren't + being handled correctly. +The code that handled CIDToGIDMaps in Type 2 CIDFonts was broken. +Check the per-glyph bounding box in Type 3 fonts, and don't try to + cache glyphs with bogus bboxes. +Allow ToUnicode CMaps to use fewer than four hex digits in the Unicode + char indexes. +Added multithreading protection to the GlobalParams class. +Fixed a bug in end-of-stream detection with the TIFF predictor. +Added some characters to MacRomanEncoding to match up with Apple's + definition. + +2.02 (2003-mar-24) +------------------ +Rewrote the text extractor code that assembles words into lines to + better handle vertically overlapping lines. +Add the "match" option for paper size (in PostScript output). +Added support for external 16-bit TrueType fonts; added the + displayCIDFontTT and displayNamedCIDFontTT commands to the xpdfrc + file. +Added an Arabic language support package. +Added the Windows-1255 encoding to the Hebrew language package. +A missing NULL check was causing a crash when closing the file in a + single window (which clears out the window, but leaves it open). +Deal with TrueType fonts whose glyph data is out of order - this + affected both FreeType rasterization and PostScript generation. +Munge font names in PSOutputDev to avoid names that are problematic + for ghostscript because they start with an out-of-limits number + (e.g., 1e999foo). +Modify the TrueType font encoding deciphering algorithm in yet another + attempt to match up with Acrobat's behavior. +Bounds check the indexHigh value in indexed color spaces. +The text extractor no longer bothers trying to get an average + character width for Type 3 fonts, since it generally doesn't work + very well (because Type 3 metrics are unreliable). +Don't crash if the user hits ctrl-G ("find again") before doing a + find. +Set the button pixmap foreground color correctly. +Handle text drawn backward on 180 degree rotated pages. +Added a magic call to XtUngrabButton after calling XmCreatePopupMenu + which appears to prevent some very odd problems (idea taken from the + DDD source code). +Fix the MacOS X fix (needed to include ). +Fixed a bunch of Motif 1.x / X11R5 incompatibilities. [Thanks to + William Bader and Albert Chin-A-Young.] +Fixed various bugs in previously untested code in the JBIG2 decoder. +Modify the XPDFCore destructor to avoid a bogus warning message from + OpenMotif 2.2. +Modified the Type 1C font parser to do proper bounds checking. +Fixed the bounds checking in the TrueType font parser. +Text extractor shouldn't do block merging in physical layout mode. +Fixed a problem in PSOutputDev in level2sep mode with images in a + Separation color space and with a non-default Decode array. +Text extraction with "-raw" was concatenating lines from the bottom of + one column and the top of the next. +Handle Type 1C subroutines in the font converters. +Correctly handle progressive JPEG images whose scans are slightly + different sizes (e.g., the Y scan rounds up to a multiple of 8 + pixels and the Cb/Cr scans round up to 16 pixels). +Avoid a potential divide-by-zero problem in TextOutputDev. +Modified the T1Font and FTFont modules to correctly handle glyphs that + are larger than the font's claimed bounding box. +Tweak dupMaxDeltaX parameter in TextOutputDev to avoid triggering on + double characters. +Improved detection in pdfinfo for ISO paper sizes. [Thanks to Hartmut + Henkel.] +Xpdf wasn't responding to the TARGETS atom, which prevented pasting + the selection into various applications. [Thanks to Phillip Ezolt.] +Handle XObjects with recursive references in their Resources + dictionaries (in PSOutputDev). +Change PSOutputDev to deal with invalid PDF files that use + non-embedded TrueType fonts with no encoding. +Check for undersized Widths arrays in fonts. +Add bounds checking code to Array class. +Updated VMS build scripts. [Thanks to Martin Zinser.] +Tweak the TrueType font handling code (again): + - char codes in symbolic fonts may or may not be offset by 0xf000 + - discard empty tables because they sometimes confuse FreeType +Fixed bounds checking in the Flate decoder. +Removed a bogus error message for exponential functions without + explicit C0/C1 values. [Thanks to Hartmut Henkel.] +Handle the other Unicode cmap type (platform=0) in TrueType fonts. +Added support for the SGI Motif horizontal paned window widget. + [Thanks to Felix Ritter.] +Ignore extra elements in link destination arrays. +Accept external Type 1 font files with a suffix of ".ps" or no suffix + at all. +Add a bounds check in the DCT decoder. +Added instructions for building xpdf.exe under cygwin/XFree86. +Tweaked the word separation parameter for raw-mode text extraction. + +2.03 (2003-oct-10) +------------------ +Rewrote the text extractor to: + - do a better job with rotated text; + - handle right-to-left scripts; + - be faster. +Changed the zoom setting to use a percentage (relative to 72 dpi) + instead of a zoom "factor". +If the PDF file has an outline, open the outline pane initially. +Added -f and -l options to pdfinfo; print multiple page sizes. +The HAVE_XTAPPSETEXITFLAG test in XPDFApp.cc was backwards. +The BitsPerComponent entry is optional in image mask objects. +Render any annotation with an appearance stream, instead of just + Widget and Stamp annotations. +Fix a bug in the TrueType font checker: the test for an unsorted + 'loca' table was wrong. +Modify the TrueType cmap selection algorithm yet again to try to match + Adobe's behavior. +Changed sqrt(2) to sqrt(2.0) in pdfinfo.cc to make various compilers + happy. +Fixed a deadlock problem (when MULTITHREADING is set); cleaned up some + other problems with the locking code. +Fixed a bug in the interpolation code for type 0 (sampled) functions. +Implemented type 1 (function-based) shaded fills. +Fixed some stupid bugs in the JBIG2 decoder (introduced with the + previous optimization work). +Fixed a typo in the code that parses vertical font metrics for CID + fonts that was causing a seg fault. +Fixed a couple of bugs that were causing seg faults with badly damaged + PDF files. +Limit the number of nested Forms to avoid infinite recursion (in buggy + PDF files). +Add a special case for rectangular clip regions - make sure these + don't drop pixels on the right and bottom edges. +Tell FreeType not to use glyph bitmaps when in anti-aliased mode. +Read all of the border style info for links. +All of the shaded fill types now do at least one bisection to avoid + problems when the colors at the endpoints of the domain are the + same. +If the Length2 parameter for an embedded Type 1 font was incorrect + (too small), pdftops was losing font data. +Deal with (broken) DCT streams that use the same component ID number + for different components. +The MediaBox page attribute was not being inherited correctly. +Fixed a bug in the Type 1C font converter related to local + subroutines. +The Type 1C -> Type 1 font converter was allocating the font dictionary + one slot too small. +Added a missing private dictionary entry to Type 1 fonts generated by + the Type 1C converter. [Thanks to Michael Shell.] +Fixed bugs in the tiling pattern fill code. +Try the TrueType 0xf000 char code offset hack for the MacRoman + encoding too (in addition to MS Symbol). +Update the font metrics info for the Base 14 fonts to include the Euro + character. +SECURITY HOLE: Escape various characters in URLs before running a web + browser (or movie viewer). [Fixed in 2.02p11] +SECURITY HOLE: In the dialog used to verify "launch" links, provide a + scrolling view if the command to be run is excessively long. [Fixed + in 2.02p11] +Added an option to disable insertion of page breaks (form feed + characters) in extracted text (pdftotext -nopgbrk; xpdfrc + "textPageBreaks" option). +Check for 8-bit fonts that specify an out-of-range FirstChar or + LastChar. +Correctly handle an obsolete Type 2 charstring op (in the Type + 1C-to-Type 1 font converter). [Thanks to Helge Blischke.] +Use the font encoding info to fill in holes in the ToUnicode map. +Added character names for Bulgarian (in the Cyrillic support pacakage) + and Greek. +Handle clipping to text in xpdf and pdftops. +Fix color space detection in DCT decoder. [Thanks to Dwight Kelly.] +Added the "unicodeToUnicode" xpdfrc option, intended (initially) for + Arabic support. +Handle the case in PSOutputDev where two font objects refer to the + same embedded TrueType font, but with different encodings. [Thanks + to Frank Siegert.] +Kill any pre-existing path before drawing a form (or annotation). +Save state before rendering page content; restore state afterward. +Fix Stream::reset/close to work correctly with encoder streams; fix + PSOutputDev to use Stream::close consistently. +Fix a seg fault when hitting the 'back' button after closing a file. +GfxState::getStrokeGray was returning the fill gray value (this only + affected Level 1 PS output). +Change PSOutputDev to reuse dictionaries in Level 1 mode (since Level + 1 PS interpreters don't do garbage collection). [Thanks to Frank + Siegert.] +PSOutputDev was generating incorrect translations for landscape-mode + pages. +Implemented shading pattern color spaces. +PSOutputDev wasn't correctly handling Type 3 fonts which used image + resources (as opposed to inline images). [Thanks to Frank Siegert.] +The fix from 1.00 which clipped out-of-bounds points was a bit too + aggressive. +Do proper Floyd-Steinberg dithering in XOutputDev. +Don't automatically check for a null owner password (to match Adobe's + behavior). +Allow the FlateDecode filter in Level 3 PostScript output. +Fixed small bugs in the Type 1C -> Type 1 converter and Type 1C -> + Type 0 converter. [Thanks to Tom Kacvinsky.] +Work around another weird Motif problem with the right button menu + (which was sometimes causing the menu to not be displayed). +Make the code that handles fonts defined directly in the resource dict + more robust. +Add a brief description of the outline pane to the xpdf man page. +Ignore extra operands to content stream operators. +Fixed a bug in the CCITTFax decoder. +Allow the Count entry in a Pages dictionary to be a real number + (because some PDF generators actually do this). +Shading pattern fills weren't being clipped correctly. +Incorrect shallow copies in GfxRadialShading and StitchingFunction. +The StitchingFunction destructor wasn't checking for funcs being + NULL. +Change the TrueType code-to-GID mapping code so it looks at the + TrueType 'post' table. +Set the print command in the print dialog once at startup, don't + change it each time a file is (re)loaded. +Generate the %%BoundingBox comment in regular PostScript files (not + just EPS files). +Fixed a bug in the Unicode CMap parser. + +3.00 (2004-jan-22) +------------------ +New PDF rasterizer ("Splash"). +Added support for PDF 1.5: + - JPX (JPEG 2000) decoder + - XRef streams + - object streams + - DeviceN color spaces with up to 32 components + - Added new CMaps to the CJK language support packages +Replaced pdftopbm with pdftoppm (which can generate PBM, PGM, and PPM + files). +Reorganized the font file parser code into a new library ("Fofi"). +Removed support for FreeType 1.x. +Removed support for X server fonts - Xpdf (and pdftoppm) will now + search for the URW fonts (from ghostscript). +Changed the "-t1lib" and "-freetype" switches; replaced the + "t1libControl" and "freetypeControl" config file options with + "enableT1lib", "enableFreeType", and "antialias". +Added the "-box" option to pdfinfo. +Added imageable area support to PSOutputDev (for CUPS); added the + "psImageableArea" config file option. +Added the "-nocrop", "-expand", "-noshrink", and "-nocenter" switches + to pdftops; added the "psCrop", "psExpandSmaller", "psShrinkLarger", + and "psCenter" config file options. +Dictionary size was in PostScript code generated for Type 3 fonts. +The PS code generated for images in Type 3 characters was broken. +Tweaked the text extractor. +Accept xref entries that are one byte too short (matching Adobe's + behavior). +Change things so "xpdf -h" and "xpdf -v" work if DISPLAY isn't set. +Fix a problem in the damaged file repair code that handles the trailer + dictionary. +Use the "Last" entries in "Outlines" objects - this avoids a problem + with PDF files generated by buggy software that, e.g., sets the last + item's Next pointer to point to itself. +PSOutputDev was not handling DeviceN color spaces correctly in Level 2 + images. +Fixed a stupid little bug that broke PS output for JBIG2 images. +Work around a Lesstif bug: set up an extra callback so hitting + in the find dialog performs a search. [Thanks to Elliott Hughes.] +Pdftops was crashing on zero page PDF files. +Add an AC_PREREQ call to configure.in. +Change the 'find' dialog so the text entry box resizes with the + dialog. +Skip extraneous zero bits at the start of a CCITTFax stream. +The PostScript text clipping operator was missing a 'newpath'. + [Thanks to Frank Siegert.] +Fix a bug in tiling patterns with bboxes that don't start at (0,0). +Fix a bug in Type 3 font handling with rotated text. +The tiled pattern fill code was destroying the current path, which + broke the fill+stroke operators when the fill color space was a + tiled pattern. +ICCBased color spaces don't always set their Ranges values correctly, + so just use the values from the alternate color space. +Modified GHash to accept int or void* - this avoids some conversion + warnings. +Check for missing Type 3 CharProcs - avoid a segfault. +Pdffonts now marks all Type 3 fonts as embedded. +Outline entries with no Title string weren't being handled correctly, + resulting in segfaults. +PSOutputDev now forces the text horizontal scale factor to be non-zero + to avoid singular font matrices in the PS code. +Tweaked the error recovery in the CCITTFax decoder. +The LZW/Flate predictor should treat any Predictor value (in the + stream dictionary) >= 10 identically. +PSOutputDev and pdffonts check for NULL font objects (which can + happen, e.g., because of missing CMap files). +Swap the left and right mouse wheel button numbers. +EPS output ("pdftops -eps") now uses the CropBox instead of the + MediaBox as the EPS bounding box. + +3.01 (2005-aug-17) +------------------ +Added the continuous view mode, including the '-cont' switch and the + 'continuousView' config file option. +At high zoom levels, don't rasterize the entire page - this avoids + problems running out of memory. +Added "search backward" and "match case" options to the find dialog. +Support explicitly masked images and soft masked images. +Add support to DCTStream for 16-bit quant tables. +Don't segfault if the user clicks on an outline entry with a broken + destination. +Changed the makefiles and configure script to skip building pdftoppm + (in addition to xpdf) if X, Motif, or FreeType is not found; changed + the error message in the configure script to match. +Move an inline function in JArithmeticDecoder.cc to avoid compiler + errors. +Fixed a bug in the rasterizer that was sometimes causing infinite + loops with round line caps on vertical lines. +Various rasterizer optimizations. +Look for intermediate resize events - try to avoid lagging when the + user is doing an opaque resize. +The FormType key in Form XObjects is optional. +Handle external 16-bit TrueType fonts correctly, using the Unicode + cmap. +Add class declarations to TextOutputDev.h to work with stricter C++ + compilers. +Support FreeType's weird include file stuff (ft2build.h, etc.). +Fixed a bug handling empty paths. +Fixed a text positioning problem in PostScript output. +Handle TrueType collections in FoFiTrueType.cc. +FoFiTrueType constructor was reporting a failure if the post table was + bad - this should be non-fatal. +Type 1 font parser was missing a NULL test. +Mask chars passed to isdigit in goo/parseargs.c to avoid problems with + signed chars. +Added more error checking to the CCITTFax decoder. +Fixed a bug (computing the MCU size) in the DCT decoder. +Change a test in the Splash stroke code to avoid x86 floating point + weirdness. +Reorganized the decryption code to allow security handler plugins; + removed the NO_DECRYPTION #ifdefs. +Added a plugin interface, initially just for security handlers. +Support color key masked images and explicitly masked images in PS + output (Level 2 only). +When checking for aliases of the Base 14 fonts, ignore spaces in the + specified font name. +Handle encrypted PDF files that are missing the file ID string. +Handle tiling patterns more efficiently in the PostScript output. +Rewrote the code that handles color spaces in PostScript output. +Fixed a bug in the Type 1C font parser - zero-length indexes (and + zero-length names) weren't handled correctly. +Handle shaded fills more efficiently in the PostScript output. +Implement the remaining shading types (4-7). +Rearranged the Splash color modes. +Add the EarlyChange parameter to LZWStream when generating PostScript. +Check for zero values in line dash arrays in PSOutputDev. +Fixed an uninitialized variable in JArithmeticDecoder which was + causing crashes. +Treat unknown CMap names as identity mappings (to match Adobe's + behavior). +Fixed bugs in the XRef parser related to XRef streams in updated + files. +Added a missing call to FT_Done_Glyph which was causing a memory leak. + [Thanks to Dave Formanek.] +Fixed a bug in text copying that was causing the last word to be + dropped on some pages. +Tweaked the image width/height computation in Splash::drawImage and + Splash::fillImageMask to make striped images work better. +Ignore minus signs in the middle of numbers (to match Adobe's + behavior). +Missing '%s' in format strings for dates in pdftotext '-htmlmeta' + mode. +Change the TrueType code-to-GID mapping code so it looks at the + standard name-to-Unicode mapping before the ToUnicode mapping + defined in the font object. +Added a matteColor setting (command line option and X resource). +Tweaked the CMYK->RGB transform. +Fix some problems in tracking the character position (to match up with + Adobe's highlight file format). +Handle moveto/closepath/stroke correctly. +Check for singular text matrices and font size of zero in PSOutputDev. +Clip PS output to the size of the page (avoiding any gibberish that + lies outside the MediaBox, in the case where the MediaBox is smaller + than the paper). +If the line dash element in an annotation's Border array is of an + invalid type (i.e., not an array), don't draw the link at all (this + matches Adobe's behavior). +Don't remap small caps and oldstyle glyphs in the name-to-Unicode + table - it messes up TrueType font encodings. +Pdftoppm wasn't setting the paper color correctly in mono and gray + modes (this only showed up on big-endian machines). +Missing NULL check was causing crashes when attempting to read non-PDF + files that happened to contain the string '%PDF'. +Fixed a problem in the text extractor that was breaking up words. +Handle vertical text (CJK fonts) in PS output with TrueType fonts that + are missing the vertical metrics tables. +Handle the case where a font object and the corresponding embedded + font are different types. +Handle basic crypt filter functionality. +Added more value checking in the XRef parser, to avoid potential + security problems. +Updated the CJK language support packages: replaced the + displayCIDFontX references with displayCIDFontTT; added pointers to + free TrueType fonts. +Added a missing error message when SplashOutputDev can't parse an + embedded TrueType font file. +PDFCore and TextOutputDev now correctly handle searching for Unicode + strings, including real Unicode case-folding. +Throw away tiling pattern fills that are completely outside the clip + region. +The JPEG 2000 inverse reversible multiple component transform code was + wrong. +Fixed some bugs in shading pattern fills: clipping was wrong, and + background color was not implemented. +Added tool tips for the toolbar buttons. +Decrease the max depth of recursive patch mesh filling if the pattern + has a large number of patches. +Highlight the find text whenever the find dialog is mapped. +Handle page boundary boxes with reversed coordinates. +Fixed a bug in the text extractor code that handles duplicated text. +Optimization work on SampledFunction::transform(). +Use the CropBox instead of the MediaBox as the display region. +Dither for PseudoColor (8-bit) displays. +Fix a bug in DCTStream that was causing an infinite loop with + corrupted DCT image data. +Fix a bug in the ToUnicode CMap parser. +Fix a bug in the text extractor - negative font sizes weren't being + handled correctly. +Fix a bug in the text extractor - in certain cases, out-of-bounds text + could cause crashes (generally only in damaged PDF files). +Fix a read-past-end-of-array bug in the JBIG2 decoder. +Fix a case where pdftops was generating lines longer than 255 chars. +Optimize redraws - don't regenerate the XImage every time redrawRect + is called. +The ASCII85 decoder wasn't skipping whitespace properly. +Optimize text extraction: skip (non-inline) image setup entirely. +Added initial transparency support (stroke/fill alpha and blend mode). +Added support for the overprint setting in PostScript output. +Fixed various buffer overflow bugs. +Handle negative font sizes and horizontal scaling correctly - this + affected PSOutputDev for all text operators, as well as the TJ + operator for all OutputDevs. +Fixed a buffer overflow in the CCITTFax decoder. +Fixed an out-of-order entry in the list of font name aliases. +Fixed a backward loop in the PostScriptFunction code. +Treat a zero-length base URI the same way as a nonexistent base URI. +Add a divide-by-zero check in TextOutputDev (the problem was happening + in cases of mixed horizontal and vertical text). +PSOutputDev wasn't rounding the page bounding box coordinates + correctly. +Support the SOF1 marker in DCT (JPEG) image streams. +Minor changes to GlobalParams.h and JPXStream.h because some compilers + don't like anonymous structs inside anonymous unions. +Xpdf now complains about a negative page number. +Changed GString::cmp and GString::cmpN to correctly handle '\0' chars + in the middle of strings. +Fixed the radial shading code; corrected the handling of the 'extend' + parameters. +Added the gmallocn and greallocn functions. +Fixed a bug in the TIFF image component predictor which shows up with + components that are not 1 or 8 bits wide. +Optimized FlateStream::loadFixedCodes(). +For non-embedded Base-14 fonts, don't use the ascent/descent/bbox + values from the FontDescriptor - various PDF generators get them + wrong. +Fixed a bug in the text extractor - words on the same line (especially + in tables) were being split vertically onto multiple lines. +Automatically select the correct radio button ("print with command" + vs. "print to file") in the print dialog. +Don't create the "open" and "save as" dialogs until needed - this + avoids stat-ing every file in the directory at startup. +Changed the Big5 and Big5ascii encodings (in the traditional Chinese + language support package) to include characters from the Unicode + database (which aren't mentioned in the Adobe character collection + documentation). +Added the '-pagecrop' switch to pdftops. +Tweaked the RGB->gray and CMYK->gray conversion functions to match the + PDF spec. +The JPEG 2000 decoder wasn't correctly handling codeblocks split + across multiple packets/layers. +Fixed a typecast that caused compile errors on 64-bit systems. +The CMap parser wasn't handling the 'cidchar' construct. +Handle the case in PSOutputDev where two font objects refer to the + same embedded 16-bit TrueType font, but with different CIDToGIDMaps. +Changed the configure script to report more accurate warnings when + it can't find X / Motif / FreeType. +Encryption with revision=2 always uses a 40-bit key, regardless of the + specified Length value. +Yet another minor change to the TrueType font encoding deciphering + algorithm. +Don't completely invalidate the Catalog if one (or more) of the page + objects are bogus -- just skip over those pages. +Removed the workaround in pdftops for too-small Length2 values in Type + 1 fonts -- it was causing problems on various PostScript printers. +Started adding error checking to the JBIG2 decoder (this is nowhere + near complete yet). +Extended the "unicodeToUnicode" config option to also apply to CID + fonts. +Added the narrow Latin characters to the Adobe-Korea1.cidToUnicode + file in the Korean language support package. +Fixed the code that handles page rotation in PSOutputDev. +When converting a Type 1C glyph to a Type 1 glyph, insert closepath + operators as appropriate. +Check for a sane 'loca' table in TrueType fonts (FoFiTrueType::parse). +Fix PSOutputDev to correctly handle the case of an empty name in a + font encoding. + +3.02 (2007-feb-27) +------------------ +Added anti-aliasing for vector graphics; added the vectorAntialias + xpdfrc option; added the "-aaVector" switch to xpdf and pdftoppm. +Implemented stroke adjustment (always enabled by default, ignoring the + SA parameter, to match Adobe's behavior), and added the strokeAdjust + xpdfrc command. +Support PDF 1.6 and PDF 1.7. +Added support for AES decryption. +Added support for OpenType fonts (only tested with 8-bit CFF data so + far). +Added user-configurable key/mouse bindings - the bind/unbind xpdfrc + commands. +Cleaned up the full-screen mode code and added the ability to toggle + it on the fly (the default key binding is alt-f). +Pdfimages with the -j option now writes JPEG files for 1-component + (grayscale) DCT images, in addition to 3-component (RGB) images. +Fixed bugs in handling sampled (type 0) functions with 32-bit + samples. +Fixed some things to support DeviceN color spaces with up to 32 + colorants. +Pdftops now constructs the %%Creator and %%Title DSC comments from the + relevant information in the PDF Info dictionary. +Tweak the TrueType font encoding deciphering algorithm. +Added the "mapUnkownCharNames" xpdfrc option. +Fix a bug (that only showed up with certain window managers) in the + intermediate resize event optimization. [Thanks to Michael Rogers.] +Check for a broken/missing embedded font (this was causing xpdf to + crash). +Added support for transfer functions in PostScript output. +Be a bit more tolerant of Link destinations that contain null values + for positioning parameters. +Use ordered dot dithering instead of clustered dot dithering at + resolutions below 300 dpi (for monochrome output). +Fixed security holes (bounds checking issues) in several places. +Don't bother creating a SplashFont (allocating memory) for fonts that + are only used for hidden text - this avoids problems with fonts of + unreasonably large sizes. +Clipping in TextOutputDev was off for characters on the left edge of + the page. +The scn and SCN operators weren't correctly handling colors with more + than four components. +FoFiType1::writeEncoded wasn't always correctly finding the end of the + encoding. +Use the ColorTransform parameter in the DCTDecode stream dictionary. +Type 3 fonts are allowed to have a bbox of [0 0 0 0], which means + "unspecified" -- don't issue error messages in that case. +Perform the transform (to device space) in Splash instead of in + SplashOutputDev -- this is needed to correctly handle round joins + and caps on stroked paths. +PSOutputDev now rasterizes any pages that use transparency. +Limit the crop, bleed, trim, and art boxes to the edges of the media + box (per the PDF spec). +Change GString to increase the allocation increment by powers of two. +Handle whitespace in hex strings in CMap files/streams. +Use strings instead of names for separation colorant names in + PSOutputDev. +For explicitly masked images where the mask is higher resolution than + the image, use the soft mask code. +Avoid problems with very large x-steps in the PostScript output for + tiling pattern fills. +Avoid a divide-by-zero in stitching functions which have a subfunction + with empty bounds. +Honor the "Hidden", "NoView", and "Print" flags on annotations. +Rewrote the pixel rendering code in Splash to use a single set of + pixel pipeline functions. +Added support for transparency groups and soft masks. +Fixed the transparency blend functions to match the addendum published + by Adobe. +Changed Splash/SplashBitmap to store alpha in a separate plane. +Setting the color space now selects the correct default color for that + color space. +Remove the mutex lock from GlobalParams::getErrQuiet() to avoid a + deadlock when parseCIDToUnicode() or parseUnicodeToUnicode() calls + it from inside a locked section. +Added error checking (on the argument count) in the sc/SC/scn/SCN + operators. +Skip over notdef glyphs in TrueType fonts (which sometimes get drawn + as little boxes), to match Adobe's behavior. +Painting operations in a Separation color space with the "None" + colorant or a DeviceN color space with all colorants set to "None" + never mark the page. +Fixed an obscure bug in the JPX decoder - it wasn't reading the extra + stuffing byte in the case where the last byte of a packet header was + 0xff. +Change the TrueType font parser (FoFiTrueType) to change the glyph + count rather than report an error if the 'loca' table is too small. +Fixed a couple of bugs in the JBIG2 decoder. +Added stochastic clustered dot dithering. +Added the screenType, screenSize, screenDotRadius, screenGamma, + screenBlackThreshold, and screenWhiteThreshold xpdfrc settings. +PSOutputDev now correctly handles invalid Type 3 charprocs which don't + start with a d0 or d1 operator +FreeType 2.2.x support - get rid of the FT_INTERNAL_OBJECTS_H include, + and add some 'const' declarations. +Handle PDFDocEncoding in Info dictionary strings. +Tweak the xref repair code - ignore whitespace at the start of lines + when looking for objects. +Added the "-exec" switch to xpdf. +Removed the xpdf.viKeys X resource. +Changed the color key / explicit masked image code in PSOutputDev to + generate better PS code, including a Level 3 option. +Tweaked the DEBUG_MEM code for performance. +Move the JBIG2 global stream reading code into reset() instead of the + constructor - this way, pdftotext doesn't end up reading the global + stream. +Added the "-preload" option to pdftops and the psPreload xpdfrc + command. +Added the "zoom to selection" command (on the popup menu). +Fix a bug (in xpdf/pdftoppm/pdftops) with tiling patterns whose bbox + size is different from their xStep/yStep. +Implemented stroke with pattern color spaces. +Following a link to a page whose CropBox was different from the + MediaBox was resulting in an incorrect scroll position. +Parse truncated date strings from the Info dictionary correctly. +Change FoFiType1 to handle Type 1 fonts with two /Encoding keys. +Extend the PSOutputDev shaded fill code to handle DeviceCMYK shaded + fills in level2sep and level3sep modes. +Detect infinite loops in the Page tree. +Optimized the ASCII85Encoder code. +Tweaked the text extractor to do a better job of lining up rows of + text. +Leave images compressed (or re-compress them with RLE) in PostScript + output when setting up images for forms and Type 3 fonts (or with + -preload). +Extend FoFiType1 to handle Type 1 fonts with octal character codes in + their encodings. +Use a custom string formatter to avoid problems with locale-based decimal + formatting (commas instead of periods) in PS output. +Allow comments in PostScript-type functions. +Change the TrueType font parser (FoFiTrueType) to delete glyf table + entries that are too short. diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/CharCodeToUnicode.cc swftools-0.9.1/lib/pdf/xpdf/CharCodeToUnicode.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/CharCodeToUnicode.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/CharCodeToUnicode.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,553 @@ +//======================================================================== +// +// CharCodeToUnicode.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gfile.h" +#include "GString.h" +#include "Error.h" +#include "GlobalParams.h" +#include "PSTokenizer.h" +#include "CharCodeToUnicode.h" + +//------------------------------------------------------------------------ + +#define maxUnicodeString 8 + +struct CharCodeToUnicodeString { + CharCode c; + Unicode u[maxUnicodeString]; + int len; +}; + +//------------------------------------------------------------------------ + +static int getCharFromString(void *data) { + char *p; + int c; + + p = *(char **)data; + if (*p) { + c = *p++; + *(char **)data = p; + } else { + c = EOF; + } + return c; +} + +static int getCharFromFile(void *data) { + return fgetc((FILE *)data); +} + +//------------------------------------------------------------------------ + +CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *fileName, + GString *collection) { + FILE *f; + Unicode *mapA; + CharCode size, mapLenA; + char buf[64]; + Unicode u; + CharCodeToUnicode *ctu; + + if (!(f = fopen(fileName->getCString(), "r"))) { + error(-1, "Couldn't open cidToUnicode file '%s'", + fileName->getCString()); + return NULL; + } + + size = 32768; + mapA = (Unicode *)gmallocn(size, sizeof(Unicode)); + mapLenA = 0; + + while (getLine(buf, sizeof(buf), f)) { + if (mapLenA == size) { + size *= 2; + mapA = (Unicode *)greallocn(mapA, size, sizeof(Unicode)); + } + if (sscanf(buf, "%x", &u) == 1) { + mapA[mapLenA] = u; + } else { + error(-1, "Bad line (%d) in cidToUnicode file '%s'", + (int)(mapLenA + 1), fileName->getCString()); + mapA[mapLenA] = 0; + } + ++mapLenA; + } + fclose(f); + + ctu = new CharCodeToUnicode(collection->copy(), mapA, mapLenA, gTrue, + NULL, 0, 0); + gfree(mapA); + return ctu; +} + +CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode( + GString *fileName) { + FILE *f; + Unicode *mapA; + CharCodeToUnicodeString *sMapA; + CharCode size, oldSize, len, sMapSizeA, sMapLenA; + char buf[256]; + char *tok; + Unicode u0; + Unicode uBuf[maxUnicodeString]; + CharCodeToUnicode *ctu; + int line, n, i; + + if (!(f = fopen(fileName->getCString(), "r"))) { + error(-1, "Couldn't open unicodeToUnicode file '%s'", + fileName->getCString()); + return NULL; + } + + size = 4096; + mapA = (Unicode *)gmallocn(size, sizeof(Unicode)); + memset(mapA, 0, size * sizeof(Unicode)); + len = 0; + sMapA = NULL; + sMapSizeA = sMapLenA = 0; + + line = 0; + while (getLine(buf, sizeof(buf), f)) { + ++line; + if (!(tok = strtok(buf, " \t\r\n")) || + sscanf(tok, "%x", &u0) != 1) { + error(-1, "Bad line (%d) in unicodeToUnicode file '%s'", + line, fileName->getCString()); + continue; + } + n = 0; + while (n < maxUnicodeString) { + if (!(tok = strtok(NULL, " \t\r\n"))) { + break; + } + if (sscanf(tok, "%x", &uBuf[n]) != 1) { + error(-1, "Bad line (%d) in unicodeToUnicode file '%s'", + line, fileName->getCString()); + break; + } + ++n; + } + if (n < 1) { + error(-1, "Bad line (%d) in unicodeToUnicode file '%s'", + line, fileName->getCString()); + continue; + } + if (u0 >= size) { + oldSize = size; + while (u0 >= size) { + size *= 2; + } + mapA = (Unicode *)greallocn(mapA, size, sizeof(Unicode)); + memset(mapA + oldSize, 0, (size - oldSize) * sizeof(Unicode)); + } + if (n == 1) { + mapA[u0] = uBuf[0]; + } else { + mapA[u0] = 0; + if (sMapLenA == sMapSizeA) { + sMapSizeA += 16; + sMapA = (CharCodeToUnicodeString *) + greallocn(sMapA, sMapSizeA, sizeof(CharCodeToUnicodeString)); + } + sMapA[sMapLenA].c = u0; + for (i = 0; i < n; ++i) { + sMapA[sMapLenA].u[i] = uBuf[i]; + } + sMapA[sMapLenA].len = n; + ++sMapLenA; + } + if (u0 >= len) { + len = u0 + 1; + } + } + fclose(f); + + ctu = new CharCodeToUnicode(fileName->copy(), mapA, len, gTrue, + sMapA, sMapLenA, sMapSizeA); + gfree(mapA); + return ctu; +} + +CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) { + return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0, 0); +} + +CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) { + CharCodeToUnicode *ctu; + char *p; + + ctu = new CharCodeToUnicode(NULL); + p = buf->getCString(); + ctu->parseCMap1(&getCharFromString, &p, nBits); + return ctu; +} + +void CharCodeToUnicode::mergeCMap(GString *buf, int nBits) { + char *p; + + p = buf->getCString(); + parseCMap1(&getCharFromString, &p, nBits); +} + +void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, + int nBits) { + PSTokenizer *pst; + char tok1[256], tok2[256], tok3[256]; + int maxCode, n1, n2, n3; + CharCode i; + CharCode code1, code2; + GString *name; + FILE *f; + + maxCode = (nBits == 8) ? 0xff : (nBits == 16) ? 0xffff : 0xffffffff; + pst = new PSTokenizer(getCharFunc, data); + pst->getToken(tok1, sizeof(tok1), &n1); + while (pst->getToken(tok2, sizeof(tok2), &n2)) { + if (!strcmp(tok2, "usecmap")) { + if (tok1[0] == '/') { + name = new GString(tok1 + 1); + if ((f = globalParams->findToUnicodeFile(name))) { + parseCMap1(&getCharFromFile, f, nBits); + fclose(f); + } else { + error(-1, "Couldn't find ToUnicode CMap file for '%s'", + name->getCString()); + } + delete name; + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "beginbfchar")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "endbfchar")) { + break; + } + if (!pst->getToken(tok2, sizeof(tok2), &n2) || + !strcmp(tok2, "endbfchar")) { + error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); + break; + } + if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' && + tok2[0] == '<' && tok2[n2 - 1] == '>')) { + error(-1, "Illegal entry in bfchar block in ToUnicode CMap."); + continue; + } + tok1[n1 - 1] = tok2[n2 - 1] = '\0'; + if (sscanf(tok1 + 1, "%x", &code1) != 1) { + error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); + continue; + } + if (code1 > maxCode) { + error(-1, "Invalid entry in bfchar block in ToUnicode CMap"); + } + addMapping(code1, tok2 + 1, n2 - 2, 0); + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "beginbfrange")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "endbfrange")) { + break; + } + if (!pst->getToken(tok2, sizeof(tok2), &n2) || + !strcmp(tok2, "endbfrange") || + !pst->getToken(tok3, sizeof(tok3), &n3) || + !strcmp(tok3, "endbfrange")) { + error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); + break; + } + if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' && + tok2[0] == '<' && tok2[n2 - 1] == '>')) { + error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); + continue; + } + tok1[n1 - 1] = tok2[n2 - 1] = '\0'; + if (sscanf(tok1 + 1, "%x", &code1) != 1 || + sscanf(tok2 + 1, "%x", &code2) != 1) { + error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); + continue; + } + if (code1 > maxCode || code2 > maxCode) { + error(-1, "Invalid entry in bfrange block in ToUnicode CMap"); + } + + if (!strcmp(tok3, "[")) { + i = 0; + while (pst->getToken(tok1, sizeof(tok1), &n1) && + code1 + i <= code2) { + if (!strcmp(tok1, "]")) { + break; + } + if (tok1[0] == '<' && tok1[n1 - 1] == '>') { + tok1[n1 - 1] = '\0'; + addMapping(code1 + i, tok1 + 1, n1 - 2, 0); + } else { + error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); + } + ++i; + } + } else if (tok3[0] == '<' && tok3[n3 - 1] == '>') { + tok3[n3 - 1] = '\0'; + for (i = 0; code1 <= code2; ++code1, ++i) { + addMapping(code1, tok3 + 1, n3 - 2, i); + } + + } else { + error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); + } + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else { + strcpy(tok1, tok2); + } + } + delete pst; +} + +void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n, + int offset) { + CharCode oldLen, i; + Unicode u; + char uHex[5]; + int j; + + if (code >= mapLen) { + oldLen = mapLen; + mapLen = (code + 256) & ~255; + Unicode *oldmap; + map = (Unicode *)greallocn(map, mapLen, sizeof(Unicode)); + if(!map) { + /* we sometimes get overflows for files trying to use 0xffffffff as charcode */ + map = oldmap; + return; + } + for (i = oldLen; i < mapLen; ++i) { + map[i] = 0; + } + } + if (n <= 4) { + if (sscanf(uStr, "%x", &u) != 1) { + error(-1, "Illegal entry in ToUnicode CMap"); + return; + } + map[code] = u + offset; + } else { + if (sMapLen >= sMapSize) { + sMapSize = sMapSize + 16; + sMap = (CharCodeToUnicodeString *) + greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString)); + } + map[code] = 0; + sMap[sMapLen].c = code; + sMap[sMapLen].len = n / 4; + for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) { + strncpy(uHex, uStr + j*4, 4); + uHex[4] = '\0'; + if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) { + error(-1, "Illegal entry in ToUnicode CMap"); + } + } + sMap[sMapLen].u[sMap[sMapLen].len - 1] += offset; + ++sMapLen; + } +} + +CharCodeToUnicode::CharCodeToUnicode(GString *tagA) { + CharCode i; + + tag = tagA; + mapLen = 256; + map = (Unicode *)gmallocn(mapLen, sizeof(Unicode)); + for (i = 0; i < mapLen; ++i) { + map[i] = 0; + } + sMap = NULL; + sMapLen = sMapSize = 0; + refCnt = 1; +#if MULTITHREADED + gInitMutex(&mutex); +#endif +} + +CharCodeToUnicode::CharCodeToUnicode(GString *tagA, Unicode *mapA, + CharCode mapLenA, GBool copyMap, + CharCodeToUnicodeString *sMapA, + int sMapLenA, int sMapSizeA) { + tag = tagA; + mapLen = mapLenA; + if (copyMap) { + map = (Unicode *)gmallocn(mapLen, sizeof(Unicode)); + memcpy(map, mapA, mapLen * sizeof(Unicode)); + } else { + map = mapA; + } + sMap = sMapA; + sMapLen = sMapLenA; + sMapSize = sMapSizeA; + refCnt = 1; +#if MULTITHREADED + gInitMutex(&mutex); +#endif +} + +CharCodeToUnicode::~CharCodeToUnicode() { + if (tag) { + delete tag; + } + gfree(map); + if (sMap) { + gfree(sMap); + } +#if MULTITHREADED + gDestroyMutex(&mutex); +#endif +} + +void CharCodeToUnicode::incRefCnt() { +#if MULTITHREADED + gLockMutex(&mutex); +#endif + ++refCnt; +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif +} + +void CharCodeToUnicode::decRefCnt() { + GBool done; + +#if MULTITHREADED + gLockMutex(&mutex); +#endif + done = --refCnt == 0; +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif + if (done) { + delete this; + } +} + +GBool CharCodeToUnicode::match(GString *tagA) { + return tag && !tag->cmp(tagA); +} + +void CharCodeToUnicode::setMapping(CharCode c, Unicode *u, int len) { + int i, j; + + if (len == 1) { + map[c] = u[0]; + } else { + for (i = 0; i < sMapLen; ++i) { + if (sMap[i].c == c) { + break; + } + } + if (i == sMapLen) { + if (sMapLen == sMapSize) { + sMapSize += 8; + sMap = (CharCodeToUnicodeString *) + greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString)); + } + ++sMapLen; + } + map[c] = 0; + sMap[i].c = c; + sMap[i].len = len; + for (j = 0; j < len && j < maxUnicodeString; ++j) { + sMap[i].u[j] = u[j]; + } + } +} + +int CharCodeToUnicode::mapToUnicode(CharCode c, Unicode *u, int size) { + int i, j; + + if (c >= mapLen) { + return 0; + } + if (map[c]) { + u[0] = map[c]; + return 1; + } + for (i = 0; i < sMapLen; ++i) { + if (sMap[i].c == c) { + for (j = 0; j < sMap[i].len && j < size; ++j) { + u[j] = sMap[i].u[j]; + } + return j; + } + } + return 0; +} + +//------------------------------------------------------------------------ + +CharCodeToUnicodeCache::CharCodeToUnicodeCache(int sizeA) { + int i; + + size = sizeA; + cache = (CharCodeToUnicode **)gmallocn(size, sizeof(CharCodeToUnicode *)); + for (i = 0; i < size; ++i) { + cache[i] = NULL; + } +} + +CharCodeToUnicodeCache::~CharCodeToUnicodeCache() { + int i; + + for (i = 0; i < size; ++i) { + if (cache[i]) { + cache[i]->decRefCnt(); + } + } + gfree(cache); +} + +CharCodeToUnicode *CharCodeToUnicodeCache::getCharCodeToUnicode(GString *tag) { + CharCodeToUnicode *ctu; + int i, j; + + if (cache[0] && cache[0]->match(tag)) { + cache[0]->incRefCnt(); + return cache[0]; + } + for (i = 1; i < size; ++i) { + if (cache[i] && cache[i]->match(tag)) { + ctu = cache[i]; + for (j = i; j >= 1; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = ctu; + ctu->incRefCnt(); + return ctu; + } + } + return NULL; +} + +void CharCodeToUnicodeCache::add(CharCodeToUnicode *ctu) { + int i; + + if (cache[size - 1]) { + cache[size - 1]->decRefCnt(); + } + for (i = size - 1; i >= 1; --i) { + cache[i] = cache[i - 1]; + } + cache[0] = ctu; + ctu->incRefCnt(); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/CharCodeToUnicode.h swftools-0.9.1/lib/pdf/xpdf/CharCodeToUnicode.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/CharCodeToUnicode.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/CharCodeToUnicode.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,117 @@ +//======================================================================== +// +// CharCodeToUnicode.h +// +// Mapping from character codes to Unicode. +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef CHARCODETOUNICODE_H +#define CHARCODETOUNICODE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "CharTypes.h" + +#if MULTITHREADED +#include "GMutex.h" +#endif + +struct CharCodeToUnicodeString; + +//------------------------------------------------------------------------ + +class CharCodeToUnicode { +public: + + // Read the CID-to-Unicode mapping for from the file + // specified by . Sets the initial reference count to 1. + // Returns NULL on failure. + static CharCodeToUnicode *parseCIDToUnicode(GString *fileName, + GString *collection); + + // Create a Unicode-to-Unicode mapping from the file specified by + // . Sets the initial reference count to 1. Returns NULL + // on failure. + static CharCodeToUnicode *parseUnicodeToUnicode(GString *fileName); + + // Create the CharCode-to-Unicode mapping for an 8-bit font. + // is an array of 256 Unicode indexes. Sets the initial + // reference count to 1. + static CharCodeToUnicode *make8BitToUnicode(Unicode *toUnicode); + + // Parse a ToUnicode CMap for an 8- or 16-bit font. + static CharCodeToUnicode *parseCMap(GString *buf, int nBits); + + // Parse a ToUnicode CMap for an 8- or 16-bit font, merging it into + // . + void mergeCMap(GString *buf, int nBits); + + ~CharCodeToUnicode(); + + void incRefCnt(); + void decRefCnt(); + + // Return true if this mapping matches the specified . + GBool match(GString *tagA); + + // Set the mapping for . + void setMapping(CharCode c, Unicode *u, int len); + + // Map a CharCode to Unicode. + int mapToUnicode(CharCode c, Unicode *u, int size); + + // Return the mapping's length, i.e., one more than the max char + // code supported by the mapping. + CharCode getLength() { return mapLen; } + +private: + + void parseCMap1(int (*getCharFunc)(void *), void *data, int nBits); + void addMapping(CharCode code, char *uStr, int n, int offset); + CharCodeToUnicode(GString *tagA); + CharCodeToUnicode(GString *tagA, Unicode *mapA, + CharCode mapLenA, GBool copyMap, + CharCodeToUnicodeString *sMapA, + int sMapLenA, int sMapSizeA); + + GString *tag; + Unicode *map; + CharCode mapLen; + CharCodeToUnicodeString *sMap; + int sMapLen, sMapSize; + int refCnt; +#if MULTITHREADED + GMutex mutex; +#endif +}; + +//------------------------------------------------------------------------ + +class CharCodeToUnicodeCache { +public: + + CharCodeToUnicodeCache(int sizeA); + ~CharCodeToUnicodeCache(); + + // Get the CharCodeToUnicode object for . Increments its + // reference count; there will be one reference for the cache plus + // one for the caller of this function. Returns NULL on failure. + CharCodeToUnicode *getCharCodeToUnicode(GString *tag); + + // Insert into the cache, in the most-recently-used position. + void add(CharCodeToUnicode *ctu); + +private: + + CharCodeToUnicode **cache; + int size; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/CharTypes.h swftools-0.9.1/lib/pdf/xpdf/CharTypes.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/CharTypes.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/CharTypes.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,24 @@ +//======================================================================== +// +// CharTypes.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef CHARTYPES_H +#define CHARTYPES_H + +// Unicode character. +typedef unsigned int Unicode; + +// Character ID for CID character collections. +typedef unsigned int CID; + +// This is large enough to hold any of the following: +// - 8-bit char code +// - 16-bit CID +// - Unicode +typedef unsigned int CharCode; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/CMap.cc swftools-0.9.1/lib/pdf/xpdf/CMap.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/CMap.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/CMap.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,408 @@ +//======================================================================== +// +// CMap.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gmem.h" +#include "gfile.h" +#include "GString.h" +#include "Error.h" +#include "GlobalParams.h" +#include "PSTokenizer.h" +#include "CMap.h" + +//------------------------------------------------------------------------ + +struct CMapVectorEntry { + GBool isVector; + union { + CMapVectorEntry *vector; + CID cid; + }; +}; + +//------------------------------------------------------------------------ + +static int getCharFromFile(void *data) { + return fgetc((FILE *)data); +} + +//------------------------------------------------------------------------ + +CMap *CMap::parse(CMapCache *cache, GString *collectionA, + GString *cMapNameA) { + FILE *f; + CMap *cmap; + PSTokenizer *pst; + char tok1[256], tok2[256], tok3[256]; + int n1, n2, n3; + Guint start, end, code; + + if (!(f = globalParams->findCMapFile(collectionA, cMapNameA))) { + + // Check for an identity CMap. + if (!cMapNameA->cmp("Identity") || !cMapNameA->cmp("Identity-H")) { + return new CMap(collectionA->copy(), cMapNameA->copy(), 0); + } + if (!cMapNameA->cmp("Identity-V")) { + return new CMap(collectionA->copy(), cMapNameA->copy(), 1); + } + + error(-1, "Couldn't find '%s' CMap file for '%s' collection", + cMapNameA->getCString(), collectionA->getCString()); + return NULL; + } + + cmap = new CMap(collectionA->copy(), cMapNameA->copy()); + + pst = new PSTokenizer(&getCharFromFile, f); + pst->getToken(tok1, sizeof(tok1), &n1); + while (pst->getToken(tok2, sizeof(tok2), &n2)) { + if (!strcmp(tok2, "usecmap")) { + if (tok1[0] == '/') { + cmap->useCMap(cache, tok1 + 1); + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok1, "/WMode")) { + cmap->wMode = atoi(tok2); + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "begincodespacerange")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "endcodespacerange")) { + break; + } + if (!pst->getToken(tok2, sizeof(tok2), &n2) || + !strcmp(tok2, "endcodespacerange")) { + error(-1, "Illegal entry in codespacerange block in CMap"); + break; + } + if (tok1[0] == '<' && tok2[0] == '<' && + n1 == n2 && n1 >= 4 && (n1 & 1) == 0) { + tok1[n1 - 1] = tok2[n1 - 1] = '\0'; + sscanf(tok1 + 1, "%x", &start); + sscanf(tok2 + 1, "%x", &end); + n1 = (n1 - 2) / 2; + cmap->addCodeSpace(cmap->vector, start, end, n1); + } + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "begincidchar")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "endcidchar")) { + break; + } + if (!pst->getToken(tok2, sizeof(tok2), &n2) || + !strcmp(tok2, "endcidchar")) { + error(-1, "Illegal entry in cidchar block in CMap"); + break; + } + if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' && + n1 >= 4 && (n1 & 1) == 0)) { + error(-1, "Illegal entry in cidchar block in CMap"); + continue; + } + tok1[n1 - 1] = '\0'; + if (sscanf(tok1 + 1, "%x", &code) != 1) { + error(-1, "Illegal entry in cidchar block in CMap"); + continue; + } + n1 = (n1 - 2) / 2; + cmap->addCIDs(code, code, n1, (CID)atoi(tok2)); + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else if (!strcmp(tok2, "begincidrange")) { + while (pst->getToken(tok1, sizeof(tok1), &n1)) { + if (!strcmp(tok1, "endcidrange")) { + break; + } + if (!pst->getToken(tok2, sizeof(tok2), &n2) || + !strcmp(tok2, "endcidrange") || + !pst->getToken(tok3, sizeof(tok3), &n3) || + !strcmp(tok3, "endcidrange")) { + error(-1, "Illegal entry in cidrange block in CMap"); + break; + } + if (tok1[0] == '<' && tok2[0] == '<' && + n1 == n2 && n1 >= 4 && (n1 & 1) == 0) { + tok1[n1 - 1] = tok2[n1 - 1] = '\0'; + sscanf(tok1 + 1, "%x", &start); + sscanf(tok2 + 1, "%x", &end); + n1 = (n1 - 2) / 2; + cmap->addCIDs(start, end, n1, (CID)atoi(tok3)); + } + } + pst->getToken(tok1, sizeof(tok1), &n1); + } else { + strcpy(tok1, tok2); + } + } + delete pst; + + fclose(f); + + return cmap; +} + +CMap::CMap(GString *collectionA, GString *cMapNameA) { + int i; + + collection = collectionA; + cMapName = cMapNameA; + wMode = 0; + vector = (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); + for (i = 0; i < 256; ++i) { + vector[i].isVector = gFalse; + vector[i].cid = 0; + } + refCnt = 1; +#if MULTITHREADED + gInitMutex(&mutex); +#endif +} + +CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) { + collection = collectionA; + cMapName = cMapNameA; + wMode = wModeA; + vector = NULL; + refCnt = 1; +#if MULTITHREADED + gInitMutex(&mutex); +#endif +} + +void CMap::useCMap(CMapCache *cache, char *useName) { + GString *useNameStr; + CMap *subCMap; + + useNameStr = new GString(useName); + subCMap = cache->getCMap(collection, useNameStr); + delete useNameStr; + if (!subCMap) { + return; + } + copyVector(vector, subCMap->vector); + subCMap->decRefCnt(); +} + +void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) { + int i, j; + + for (i = 0; i < 256; ++i) { + if (src[i].isVector) { + if (!dest[i].isVector) { + dest[i].isVector = gTrue; + dest[i].vector = + (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); + for (j = 0; j < 256; ++j) { + dest[i].vector[j].isVector = gFalse; + dest[i].vector[j].cid = 0; + } + } + copyVector(dest[i].vector, src[i].vector); + } else { + if (dest[i].isVector) { + error(-1, "Collision in usecmap"); + } else { + dest[i].cid = src[i].cid; + } + } + } +} + +void CMap::addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end, + Guint nBytes) { + Guint start2, end2; + int startByte, endByte, i, j; + + if (nBytes > 1) { + startByte = (start >> (8 * (nBytes - 1))) & 0xff; + endByte = (end >> (8 * (nBytes - 1))) & 0xff; + start2 = start & ((1 << (8 * (nBytes - 1))) - 1); + end2 = end & ((1 << (8 * (nBytes - 1))) - 1); + for (i = startByte; i <= endByte; ++i) { + if (!vec[i].isVector) { + vec[i].isVector = gTrue; + vec[i].vector = + (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); + for (j = 0; j < 256; ++j) { + vec[i].vector[j].isVector = gFalse; + vec[i].vector[j].cid = 0; + } + } + addCodeSpace(vec[i].vector, start2, end2, nBytes - 1); + } + } +} + +void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) { + CMapVectorEntry *vec; + CID cid; + int byte; + Guint i; + + vec = vector; + for (i = nBytes - 1; i >= 1; --i) { + byte = (start >> (8 * i)) & 0xff; + if (!vec[byte].isVector) { + error(-1, "Invalid CID (%0*x - %0*x) in CMap", + 2*nBytes, start, 2*nBytes, end); + return; + } + vec = vec[byte].vector; + } + cid = firstCID; + for (byte = (int)(start & 0xff); byte <= (int)(end & 0xff); ++byte) { + if (vec[byte].isVector) { + error(-1, "Invalid CID (%0*x - %0*x) in CMap", + 2*nBytes, start, 2*nBytes, end); + } else { + vec[byte].cid = cid; + } + ++cid; + } +} + +CMap::~CMap() { + delete collection; + delete cMapName; + if (vector) { + freeCMapVector(vector); + } +#if MULTITHREADED + gDestroyMutex(&mutex); +#endif +} + +void CMap::freeCMapVector(CMapVectorEntry *vec) { + int i; + + for (i = 0; i < 256; ++i) { + if (vec[i].isVector) { + freeCMapVector(vec[i].vector); + } + } + gfree(vec); +} + +void CMap::incRefCnt() { +#if MULTITHREADED + gLockMutex(&mutex); +#endif + ++refCnt; +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif +} + +void CMap::decRefCnt() { + GBool done; + +#if MULTITHREADED + gLockMutex(&mutex); +#endif + done = --refCnt == 0; +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif + if (done) { + delete this; + } +} + +GBool CMap::match(GString *collectionA, GString *cMapNameA) { + return !collection->cmp(collectionA) && !cMapName->cmp(cMapNameA); +} + +CID CMap::getCID(char *s, int len, int *nUsed) { + CMapVectorEntry *vec; + int n, i; + + if (!(vec = vector)) { + // identity CMap + *nUsed = 2; + if (len < 2) { + return 0; + } + return ((s[0] & 0xff) << 8) + (s[1] & 0xff); + } + n = 0; + while (1) { + if (n >= len) { + *nUsed = n; + return 0; + } + i = s[n++] & 0xff; + if (!vec[i].isVector) { + *nUsed = n; + return vec[i].cid; + } + vec = vec[i].vector; + } +} + +//------------------------------------------------------------------------ + +CMapCache::CMapCache() { + int i; + + for (i = 0; i < cMapCacheSize; ++i) { + cache[i] = NULL; + } +} + +CMapCache::~CMapCache() { + int i; + + for (i = 0; i < cMapCacheSize; ++i) { + if (cache[i]) { + cache[i]->decRefCnt(); + } + } +} + +CMap *CMapCache::getCMap(GString *collection, GString *cMapName) { + CMap *cmap; + int i, j; + + if (cache[0] && cache[0]->match(collection, cMapName)) { + cache[0]->incRefCnt(); + return cache[0]; + } + for (i = 1; i < cMapCacheSize; ++i) { + if (cache[i] && cache[i]->match(collection, cMapName)) { + cmap = cache[i]; + for (j = i; j >= 1; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = cmap; + cmap->incRefCnt(); + return cmap; + } + } + if ((cmap = CMap::parse(this, collection, cMapName))) { + if (cache[cMapCacheSize - 1]) { + cache[cMapCacheSize - 1]->decRefCnt(); + } + for (j = cMapCacheSize - 1; j >= 1; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = cmap; + cmap->incRefCnt(); + return cmap; + } + return NULL; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/CMap.h swftools-0.9.1/lib/pdf/xpdf/CMap.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/CMap.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/CMap.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,102 @@ +//======================================================================== +// +// CMap.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef CMAP_H +#define CMAP_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "CharTypes.h" + +#if MULTITHREADED +#include "GMutex.h" +#endif + +class GString; +struct CMapVectorEntry; +class CMapCache; + +//------------------------------------------------------------------------ + +class CMap { +public: + + // Create the CMap specified by and . Sets + // the initial reference count to 1. Returns NULL on failure. + static CMap *parse(CMapCache *cache, GString *collectionA, + GString *cMapNameA); + + ~CMap(); + + void incRefCnt(); + void decRefCnt(); + + // Return collection name (-). + GString *getCollection() { return collection; } + + // Return true if this CMap matches the specified , and + // . + GBool match(GString *collectionA, GString *cMapNameA); + + // Return the CID corresponding to the character code starting at + // , which contains bytes. Sets * to the number of + // bytes used by the char code. + CID getCID(char *s, int len, int *nUsed); + + // Return the writing mode (0=horizontal, 1=vertical). + int getWMode() { return wMode; } + +private: + + CMap(GString *collectionA, GString *cMapNameA); + CMap(GString *collectionA, GString *cMapNameA, int wModeA); + void useCMap(CMapCache *cache, char *useName); + void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src); + void addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end, + Guint nBytes); + void addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID); + void freeCMapVector(CMapVectorEntry *vec); + + GString *collection; + GString *cMapName; + int wMode; // writing mode (0=horizontal, 1=vertical) + CMapVectorEntry *vector; // vector for first byte (NULL for + // identity CMap) + int refCnt; +#if MULTITHREADED + GMutex mutex; +#endif +}; + +//------------------------------------------------------------------------ + +#define cMapCacheSize 4 + +class CMapCache { +public: + + CMapCache(); + ~CMapCache(); + + // Get the CMap for the specified character collection. + // Increments its reference count; there will be one reference for + // the cache plus one for the caller of this function. Returns NULL + // on failure. + CMap *getCMap(GString *collection, GString *cMapName); + +private: + + CMap *cache[cMapCacheSize]; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/CompactFontTables.h swftools-0.9.1/lib/pdf/xpdf/CompactFontTables.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/CompactFontTables.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/CompactFontTables.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,464 @@ +//======================================================================== +// +// CompactFontTables.h +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef COMPACTFONTINFO_H +#define COMPACTFONTINFO_H + +static char *type1CStdStrings[391] = { + ".notdef", + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + "endash", + "dagger", + "daggerdbl", + "periodcentered", + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + "questiondown", + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + "ring", + "cedilla", + "hungarumlaut", + "ogonek", + "caron", + "emdash", + "AE", + "ordfeminine", + "Lslash", + "Oslash", + "OE", + "ordmasculine", + "ae", + "dotlessi", + "lslash", + "oslash", + "oe", + "germandbls", + "onesuperior", + "logicalnot", + "mu", + "trademark", + "Eth", + "onehalf", + "plusminus", + "Thorn", + "onequarter", + "divide", + "brokenbar", + "degree", + "thorn", + "threequarters", + "twosuperior", + "registered", + "minus", + "eth", + "multiply", + "threesuperior", + "copyright", + "Aacute", + "Acircumflex", + "Adieresis", + "Agrave", + "Aring", + "Atilde", + "Ccedilla", + "Eacute", + "Ecircumflex", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Ntilde", + "Oacute", + "Ocircumflex", + "Odieresis", + "Ograve", + "Otilde", + "Scaron", + "Uacute", + "Ucircumflex", + "Udieresis", + "Ugrave", + "Yacute", + "Ydieresis", + "Zcaron", + "aacute", + "acircumflex", + "adieresis", + "agrave", + "aring", + "atilde", + "ccedilla", + "eacute", + "ecircumflex", + "edieresis", + "egrave", + "iacute", + "icircumflex", + "idieresis", + "igrave", + "ntilde", + "oacute", + "ocircumflex", + "odieresis", + "ograve", + "otilde", + "scaron", + "uacute", + "ucircumflex", + "udieresis", + "ugrave", + "yacute", + "ydieresis", + "zcaron", + "exclamsmall", + "Hungarumlautsmall", + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + "isuperior", + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + "rsuperior", + "ssuperior", + "tsuperior", + "ff", + "ffi", + "ffl", + "parenleftinferior", + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + "Dotaccentsmall", + "Macronsmall", + "figuredash", + "hypheninferior", + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + "zerosuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall", + "001.000", + "001.001", + "001.002", + "001.003", + "Black", + "Bold", + "Book", + "Light", + "Medium", + "Regular", + "Roman", + "Semibold" +}; + +static Gushort type1CISOAdobeCharset[229] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228 +}; + +static Gushort type1CExpertCharset[166] = { + 0, 1, 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 13, 14, 15, 99, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, + 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, + 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378 +}; + +static Gushort type1CExpertSubsetCharset[87] = { + 0, 1, 231, 232, 235, 236, 237, 238, 13, 14, + 15, 99, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 109, 110, 267, 268, 269, 270, 272, 300, 301, + 302, 305, 314, 315, 158, 155, 163, 320, 321, 322, + 323, 324, 325, 326, 150, 164, 169, 327, 328, 329, + 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346 +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/config.h swftools-0.9.1/lib/pdf/xpdf/config.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/config.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/config.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,112 @@ +//======================================================================== +// +// config.h +// +// Copyright 1996-2007 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef CONFIG_H +#define CONFIG_H + +//------------------------------------------------------------------------ +// version +//------------------------------------------------------------------------ + +// xpdf version +#define xpdfVersion "3.02" +#define xpdfVersionNum 3.02 +#define xpdfMajorVersion 3 +#define xpdfMinorVersion 2 +#define xpdfUpdateVersion 0 +#define xpdfMajorVersionStr "3" +#define xpdfMinorVersionStr "2" +#define xpdfUpdateVersionStr "0" + +// supported PDF version +#define supportedPDFVersionStr "1.7" +#define supportedPDFVersionNum 1.7 + +// copyright notice +#define xpdfCopyright "Copyright 1996-2007 Glyph & Cog, LLC" + +// Windows resource file stuff +#define winxpdfVersion "WinXpdf 3.02" +#define xpdfCopyrightAmp "Copyright 1996-2007 Glyph && Cog, LLC" + +//------------------------------------------------------------------------ +// paper size +//------------------------------------------------------------------------ + +// default paper size (in points) for PostScript output +#ifdef A4_PAPER +#define defPaperWidth 595 // ISO A4 (210x297 mm) +#define defPaperHeight 842 +#else +#define defPaperWidth 612 // American letter (8.5x11") +#define defPaperHeight 792 +#endif + +//------------------------------------------------------------------------ +// config file (xpdfrc) path +//------------------------------------------------------------------------ + +// user config file name, relative to the user's home directory +#if defined(VMS) || (defined(WIN32) && !defined(__CYGWIN32__)) +#define xpdfUserConfigFile "xpdfrc" +#else +#define xpdfUserConfigFile ".xpdfrc" +#endif + +// system config file name (set via the configure script) +#ifdef SYSTEM_XPDFRC +#define xpdfSysConfigFile SYSTEM_XPDFRC +#else +// under Windows, we get the directory with the executable and then +// append this file name +#define xpdfSysConfigFile "xpdfrc" +#endif + +//------------------------------------------------------------------------ +// X-related constants +//------------------------------------------------------------------------ + +// default maximum size of color cube to allocate +#define defaultRGBCube 5 + +// number of fonts (combined t1lib, FreeType, X server) to cache +#define xOutFontCacheSize 64 + +// number of Type 3 fonts to cache +#define xOutT3FontCacheSize 8 + +//------------------------------------------------------------------------ +// popen +//------------------------------------------------------------------------ + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define popen _popen +#define pclose _pclose +#endif + +#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(MACOS) +#define POPEN_READ_MODE "rb" +#else +#define POPEN_READ_MODE "r" +#endif + +//------------------------------------------------------------------------ +// Win32 stuff +//------------------------------------------------------------------------ + +#ifdef CDECL +#undef CDECL +#endif + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define CDECL __cdecl +#else +#define CDECL +#endif + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/configure swftools-0.9.1/lib/pdf/xpdf/configure --- swftools-0.9.2+ds1/lib/pdf/xpdf/configure 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/configure 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,11805 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59. +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="xpdf/xpdf.cc" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA RANLIB ac_ct_RANLIB EXE LIBPREFIX AR UP_DIR CPP X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS EGREP Xpm_LIBS Xpm_CFLAGS Xext_LIBS Xext_CFLAGS Xp_LIBS Xp_CFLAGS Xt_LIBS Xt_CFLAGS Xm_LIBS Xm_CFLAGS Sgm_LIBS Sgm_CFLAGS t1_LIBS t1_CFLAGS freetype2_LIBS freetype2_CFLAGS libpaper_LIBS libpaper_CFLAGS X XPDF_TARGET LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-a4-paper use A4 paper size instead of Letter for + PostScript output + --enable-no-text-select do not allow text selection + --enable-opi include support for OPI comments + --enable-multithreaded include support for multithreading + --enable-exceptions use C++ exceptions + --enable-wordlist include support for building word lists + --enable-fixedpoint use fixed point (instead of floating point) arithmetic + --enable-cmyk include support for CMYK rasterization + --disable-largefile omit support for large files + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-appdef-dir set app-defaults directory + --with-x use the X Window System + --with-Xpm-library=PATH use Xpm library (pixmap library - used only for icon) + --with-Xpm-includes=DIR set directory for Xpm headers + --with-Xext-library=PATH + use Xext library (Motif library) + --with-Xext-includes=DIR + set directory for Xext headers + --with-Xp-library=PATH use Xp library (Motif library) + --with-Xp-includes=DIR set directory for Xp headers + --with-Xt-library=PATH use Xt library (Motif library) + --with-Xt-includes=DIR set directory for Xt headers + --with-Xm-library=PATH use Xm library (Motif library) + --with-Xm-includes=DIR set directory for Xm headers + --with-Sgm-library=PATH use Sgm library (SGI Motif library) + --with-Sgm-includes=DIR set directory for Sgm headers + --with-t1-library=PATH use t1 library (Type 1 font rasterizer) + --with-t1-includes=DIR set directory for t1 headers + --with-freetype2-library=PATH + use freetype2 library (FreeType2 font rasterizer - version 2.0.5+) + --with-freetype2-includes=DIR + set directory for freetype2 headers + --with-libpaper-library=PATH + use libpaper library (Debian libpaper) + --with-libpaper-includes=DIR + set directory for libpaper headers + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + ac_config_headers="$ac_config_headers aconf.h" + + +# Check whether --enable-a4-paper or --disable-a4-paper was given. +if test "${enable_a4_paper+set}" = set; then + enableval="$enable_a4_paper" + cat >>confdefs.h <<\_ACEOF +#define A4_PAPER 1 +_ACEOF + +fi; +# Check whether --enable-no-text-select or --disable-no-text-select was given. +if test "${enable_no_text_select+set}" = set; then + enableval="$enable_no_text_select" + cat >>confdefs.h <<\_ACEOF +#define NO_TEXT_SELECT 1 +_ACEOF + +fi; +# Check whether --enable-opi or --disable-opi was given. +if test "${enable_opi+set}" = set; then + enableval="$enable_opi" + cat >>confdefs.h <<\_ACEOF +#define OPI_SUPPORT 1 +_ACEOF + +fi; +# Check whether --enable-multithreaded or --disable-multithreaded was given. +if test "${enable_multithreaded+set}" = set; then + enableval="$enable_multithreaded" + cat >>confdefs.h <<\_ACEOF +#define MULTITHREADED 1 +_ACEOF + +fi; +# Check whether --enable-exceptions or --disable-exceptions was given. +if test "${enable_exceptions+set}" = set; then + enableval="$enable_exceptions" + cat >>confdefs.h <<\_ACEOF +#define USE_EXCEPTIONS 1 +_ACEOF + +fi; +# Check whether --enable-wordlist or --disable-wordlist was given. +if test "${enable_wordlist+set}" = set; then + enableval="$enable_wordlist" + cat >>confdefs.h <<\_ACEOF +#define TEXTOUT_WORD_LIST 1 +_ACEOF + +fi; +# Check whether --enable-fixedpoint or --disable-fixedpoint was given. +if test "${enable_fixedpoint+set}" = set; then + enableval="$enable_fixedpoint" + cat >>confdefs.h <<\_ACEOF +#define USE_FIXEDPOINT 1 +_ACEOF + +fi; +# Check whether --enable-cmyk or --disable-cmyk was given. +if test "${enable_cmyk+set}" = set; then + enableval="$enable_cmyk" + cat >>confdefs.h <<\_ACEOF +#define SPLASH_CMYK 1 +_ACEOF + +fi; + +# Check whether --with-appdef-dir or --without-appdef-dir was given. +if test "${with_appdef_dir+set}" = set; then + withval="$with_appdef_dir" + cat >>confdefs.h <<_ACEOF +#define APPDEFDIR "$with_appdef_dir" +_ACEOF + +fi; + +if test "$sysconfdir" = '${prefix}/etc'; then + if test "x$prefix" = xNONE; then + system_xpdfrc="$ac_default_prefix/etc/xpdfrc" + else + system_xpdfrc="$prefix/etc/xpdfrc" + fi +else + system_xpdfrc="$sysconfdir/xpdfrc" +fi +cat >>confdefs.h <<_ACEOF +#define SYSTEM_XPDFRC "$system_xpdfrc" +_ACEOF + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for library containing strerror" >&5 +echo $ECHO_N "checking for library containing strerror... $ECHO_C" >&6 +if test "${ac_cv_search_strerror+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_strerror=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strerror (); +int +main () +{ +strerror (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_strerror="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_strerror" = no; then + for ac_lib in cposix; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strerror (); +int +main () +{ +strerror (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_strerror="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_strerror" >&5 +echo "${ECHO_T}$ac_cv_search_strerror" >&6 +if test "$ac_cv_search_strerror" != no; then + test "$ac_cv_search_strerror" = "none required" || LIBS="$ac_cv_search_strerror $LIBS" + +fi + + +#if test -z "$CXX" -a "$CC" = "gcc"; then +# CXX="gcc" +#fi +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + +EXE="" +LIBPREFIX="lib" +AR="ar rc" +UP_DIR="" + +echo "$as_me:$LINENO: checking for OS/2 (with EMX)" >&5 +echo $ECHO_N "checking for OS/2 (with EMX)... $ECHO_C" >&6 +if test "${xpdf_cv_sys_os2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +__EMX__ + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + xpdf_cv_sys_os2=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +xpdf_cv_sys_os2=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $xpdf_cv_sys_os2" >&5 +echo "${ECHO_T}$xpdf_cv_sys_os2" >&6 +if test "$xpdf_cv_sys_os2" = yes; then + EXE=".exe" + LIBPREFIX="" + AR="ar -rc" +fi + +echo "$as_me:$LINENO: checking for DOS (with DJGPP)" >&5 +echo $ECHO_N "checking for DOS (with DJGPP)... $ECHO_C" >&6 +if test "${xpdf_cv_sys_dos+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +__DJGPP__ + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + xpdf_cv_sys_dos=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +xpdf_cv_sys_dos=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $xpdf_cv_sys_dos" >&5 +echo "${ECHO_T}$xpdf_cv_sys_dos" >&6 +if test "$xpdf_cv_sys_dos" = yes; then + EXE=".exe" + LIBPREFIX="lib" + AR="ar -rc" + UP_DIR="../" +fi + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for X" >&5 +echo $ECHO_N "checking for X... $ECHO_C" >&6 + + +# Check whether --with-x or --without-x was given. +if test "${with_x+set}" = set; then + withval="$with_x" + +fi; +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then + # Both variables are already set. + have_x=yes + else + if test "${ac_cv_have_x+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -fr conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat >Imakefile <<'_ACEOF' +acfindx: + @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' +_ACEOF + if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl; do + if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && + test -f $ac_im_libdir/libX11.$ac_extension; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -fr conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Intrinsic.h. + # First, try using that file with no special directory specified. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # We can compile using X headers with no special include directory. +ac_x_includes= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Intrinsic.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lXt $LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +XtMalloc (0) + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +LIBS=$ac_save_LIBS +for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl; do + if test -r $ac_dir/libXt.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +if test "$ac_x_includes" = no || test "$ac_x_libraries" = no; then + # Didn't find X anywhere. Cache the known absence of X. + ac_cv_have_x="have_x=no" +else + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" +fi +fi + + fi + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + echo "$as_me:$LINENO: result: $have_x" >&5 +echo "${ECHO_T}$have_x" >&6 + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$x_includes ac_x_libraries=$x_libraries" + echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 +echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6 +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + +cat >>confdefs.h <<\_ACEOF +#define X_DISPLAY_MISSING 1 +_ACEOF + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + case `(uname -sr) 2>/dev/null` in + "SunOS 5"*) + echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5 +echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6 + ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_R_nospace=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_R_nospace=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test $ac_R_nospace = yes; then + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + X_LIBS="$X_LIBS -R$x_libraries" + else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_R_space=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_R_space=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test $ac_R_space = yes; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + X_LIBS="$X_LIBS -R $x_libraries" + else + echo "$as_me:$LINENO: result: neither works" >&5 +echo "${ECHO_T}neither works" >&6 + fi + fi + LIBS=$ac_xsave_LIBS + esac + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn Johnson says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And Karl Berry says + # the Alpha needs dnet_stub (dnet does not exist). + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XOpenDisplay (); +int +main () +{ +XOpenDisplay (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5 +echo $ECHO_N "checking for dnet_ntoa in -ldnet... $ECHO_C" >&6 +if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dnet_ntoa (); +int +main () +{ +dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dnet_dnet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dnet_dnet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_dnet_dnet_ntoa" >&6 +if test $ac_cv_lib_dnet_dnet_ntoa = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5 +echo $ECHO_N "checking for dnet_ntoa in -ldnet_stub... $ECHO_C" >&6 +if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet_stub $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dnet_ntoa (); +int +main () +{ +dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dnet_stub_dnet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dnet_stub_dnet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_dnet_stub_dnet_ntoa" >&6 +if test $ac_cv_lib_dnet_stub_dnet_ntoa = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +fi + + fi +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_xsave_LIBS" + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to T.E. Dickey. + # The functions gethostbyname, getservbyname, and inet_addr are + # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. + echo "$as_me:$LINENO: checking for gethostbyname" >&5 +echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6 +if test "${ac_cv_func_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostbyname to an innocuous variant, in case declares gethostbyname. + For example, HP-UX 11i declares gettimeofday. */ +#define gethostbyname innocuous_gethostbyname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef gethostbyname + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +char (*f) () = gethostbyname; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != gethostbyname; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6 + + if test $ac_cv_func_gethostbyname = no; then + echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 +echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6 +if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_nsl_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_nsl_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6 +if test $ac_cv_lib_nsl_gethostbyname = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +fi + + if test $ac_cv_lib_nsl_gethostbyname = no; then + echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 +echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6 +if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_bsd_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_bsd_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6 +if test $ac_cv_lib_bsd_gethostbyname = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" +fi + + fi + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says Simon Leinen: it contains gethostby* + # variants that don't use the name server (or something). -lsocket + # must be given before -lnsl if both are needed. We assume that + # if connect needs -lnsl, so does gethostbyname. + echo "$as_me:$LINENO: checking for connect" >&5 +echo $ECHO_N "checking for connect... $ECHO_C" >&6 +if test "${ac_cv_func_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define connect to an innocuous variant, in case declares connect. + For example, HP-UX 11i declares gettimeofday. */ +#define connect innocuous_connect + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char connect (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef connect + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_connect) || defined (__stub___connect) +choke me +#else +char (*f) () = connect; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != connect; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 +echo "${ECHO_T}$ac_cv_func_connect" >&6 + + if test $ac_cv_func_connect = no; then + echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 +echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6 +if test "${ac_cv_lib_socket_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +int +main () +{ +connect (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_socket_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_socket_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6 +if test $ac_cv_lib_socket_connect = yes; then + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +fi + + fi + + # Guillermo Gomez says -lposix is necessary on A/UX. + echo "$as_me:$LINENO: checking for remove" >&5 +echo $ECHO_N "checking for remove... $ECHO_C" >&6 +if test "${ac_cv_func_remove+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define remove to an innocuous variant, in case declares remove. + For example, HP-UX 11i declares gettimeofday. */ +#define remove innocuous_remove + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char remove (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef remove + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_remove) || defined (__stub___remove) +choke me +#else +char (*f) () = remove; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != remove; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_remove=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_remove=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5 +echo "${ECHO_T}$ac_cv_func_remove" >&6 + + if test $ac_cv_func_remove = no; then + echo "$as_me:$LINENO: checking for remove in -lposix" >&5 +echo $ECHO_N "checking for remove in -lposix... $ECHO_C" >&6 +if test "${ac_cv_lib_posix_remove+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lposix $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove (); +int +main () +{ +remove (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_posix_remove=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_posix_remove=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5 +echo "${ECHO_T}$ac_cv_lib_posix_remove" >&6 +if test $ac_cv_lib_posix_remove = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + echo "$as_me:$LINENO: checking for shmat" >&5 +echo $ECHO_N "checking for shmat... $ECHO_C" >&6 +if test "${ac_cv_func_shmat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shmat to an innocuous variant, in case declares shmat. + For example, HP-UX 11i declares gettimeofday. */ +#define shmat innocuous_shmat + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shmat (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef shmat + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shmat) || defined (__stub___shmat) +choke me +#else +char (*f) () = shmat; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != shmat; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shmat=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_shmat=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5 +echo "${ECHO_T}$ac_cv_func_shmat" >&6 + + if test $ac_cv_func_shmat = no; then + echo "$as_me:$LINENO: checking for shmat in -lipc" >&5 +echo $ECHO_N "checking for shmat in -lipc... $ECHO_C" >&6 +if test "${ac_cv_lib_ipc_shmat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lipc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat (); +int +main () +{ +shmat (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ipc_shmat=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ipc_shmat=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5 +echo "${ECHO_T}$ac_cv_lib_ipc_shmat" >&6 +if test $ac_cv_lib_ipc_shmat = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS=$LDFLAGS + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # John Interrante, Karl Berry + echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5 +echo $ECHO_N "checking for IceConnectionNumber in -lICE... $ECHO_C" >&6 +if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char IceConnectionNumber (); +int +main () +{ +IceConnectionNumber (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ICE_IceConnectionNumber=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ICE_IceConnectionNumber=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 +echo "${ECHO_T}$ac_cv_lib_ICE_IceConnectionNumber" >&6 +if test $ac_cv_lib_ICE_IceConnectionNumber = yes; then + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +fi + + LDFLAGS=$ac_save_LDFLAGS + +fi + + + + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 +echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_opendir=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main () +{ +opendir (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_opendir" = no; then + for ac_lib in dir; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main () +{ +opendir (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6 +if test "$ac_cv_search_opendir" != no; then + test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" + +fi + +else + echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6 +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_opendir=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main () +{ +opendir (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_opendir" = no; then + for ac_lib in x; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main () +{ +opendir (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6 +if test "$ac_cv_search_opendir" != no; then + test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS" + +fi + +fi + + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + +echo "$as_me:$LINENO: checking for gethostbyname" >&5 +echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6 +if test "${ac_cv_func_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostbyname to an innocuous variant, in case declares gethostbyname. + For example, HP-UX 11i declares gettimeofday. */ +#define gethostbyname innocuous_gethostbyname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef gethostbyname + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +char (*f) () = gethostbyname; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != gethostbyname; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6 + +if test $ac_cv_func_gethostbyname = no; then + echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 +echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6 +if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_bsd_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_bsd_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6 +if test $ac_cv_lib_bsd_gethostbyname = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" +fi + +fi + +echo "$as_me:$LINENO: checking select() and fd_set in sys/select.h and sys/bsdtypes.h" >&5 +echo $ECHO_N "checking select() and fd_set in sys/select.h and sys/bsdtypes.h... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +int +main () +{ +fd_set fds; +select(0, NULL, NULL, NULL, NULL); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + xpdf_ok=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +xpdf_ok=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +if test $xpdf_ok = yes; then + echo "$as_me:$LINENO: result: not needed" >&5 +echo "${ECHO_T}not needed" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +#include +int +main () +{ +fd_set fds; +select(0, NULL, NULL, NULL, NULL); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + xpdf_ok=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +xpdf_ok=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + if test $xpdf_ok = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_SELECT_H 1 +_ACEOF + + echo "$as_me:$LINENO: result: need sys/select.h" >&5 +echo "${ECHO_T}need sys/select.h" >&6 + else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +#include +int +main () +{ +fd_set fds; +select(0, NULL, NULL, NULL, NULL); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + xpdf_ok=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +xpdf_ok=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + if test $xpdf_ok = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_BSDTYPES_H 1 +_ACEOF + + echo "$as_me:$LINENO: result: need sys/bsdtypes.h" >&5 +echo "${ECHO_T}need sys/bsdtypes.h" >&6 + else + echo "$as_me:$LINENO: result: problem" >&5 +echo "${ECHO_T}problem" >&6 + fi + fi +fi + +echo "$as_me:$LINENO: checking FD_ZERO and strings.h or bstring.h" >&5 +echo $ECHO_N "checking FD_ZERO and strings.h or bstring.h... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif +int +main () +{ +fd_set fds; FD_ZERO(&fds); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + xpdf_ok=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +xpdf_ok=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +if test $xpdf_ok = yes; then + echo "$as_me:$LINENO: result: not needed" >&5 +echo "${ECHO_T}not needed" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif +int +main () +{ +fd_set fds; FD_ZERO(&fds); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + xpdf_ok=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +xpdf_ok=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + if test $xpdf_ok = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_STRINGS_H 1 +_ACEOF + + echo "$as_me:$LINENO: result: need strings.h" >&5 +echo "${ECHO_T}need strings.h" >&6 + else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif +int +main () +{ +fd_set fds; FD_ZERO(&fds); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + xpdf_ok=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +xpdf_ok=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + if test $xpdf_ok = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_BSTRING_H 1 +_ACEOF + + echo "$as_me:$LINENO: result: need bstring.h" >&5 +echo "${ECHO_T}need bstring.h" >&6 + else + echo "$as_me:$LINENO: result: problem" >&5 +echo "${ECHO_T}problem" >&6 + fi + fi +fi + + +for ac_func in rewinddir +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +if test $ac_cv_func_rewinddir = no; then + +echo "$as_me:$LINENO: checking for rewinddir in -lcposix" >&5 +echo $ECHO_N "checking for rewinddir in -lcposix... $ECHO_C" >&6 +if test "${ac_cv_lib_cposix_rewinddir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcposix $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char rewinddir (); +int +main () +{ +rewinddir (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_cposix_rewinddir=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_cposix_rewinddir=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_cposix_rewinddir" >&5 +echo "${ECHO_T}$ac_cv_lib_cposix_rewinddir" >&6 +if test $ac_cv_lib_cposix_rewinddir = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCPOSIX 1 +_ACEOF + + LIBS="-lcposix $LIBS" + +fi + +fi + + +for ac_func in popen +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +echo "$as_me:$LINENO: checking for mkstemp" >&5 +echo $ECHO_N "checking for mkstemp... $ECHO_C" >&6 +if test "${xpdf_cv_func_mkstemp+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +int +main () +{ +mkstemp("foo"); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + xpdf_cv_func_mkstemp=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +xpdf_cv_func_mkstemp=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $xpdf_cv_func_mkstemp" >&5 +echo "${ECHO_T}$xpdf_cv_func_mkstemp" >&6 +if test "$xpdf_cv_func_mkstemp" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_MKSTEMP 1 +_ACEOF + +fi +echo "$as_me:$LINENO: checking for mkstemps" >&5 +echo $ECHO_N "checking for mkstemps... $ECHO_C" >&6 +if test "${xpdf_cv_func_mkstemps+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +int +main () +{ +mkstemps("foo", 0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + xpdf_cv_func_mkstemps=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +xpdf_cv_func_mkstemps=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $xpdf_cv_func_mkstemps" >&5 +echo "${ECHO_T}$xpdf_cv_func_mkstemps" >&6 +if test "$xpdf_cv_func_mkstemps" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_MKSTEMPS 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking whether select takes fd_set arguments" >&5 +echo $ECHO_N "checking whether select takes fd_set arguments... $ECHO_C" >&6 +if test "${xpdf_cv_func_select_arg+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif +int +main () +{ +fd_set fds; +select(1, &fds, &fds, &fds, 0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + xpdf_cv_func_select_arg=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +xpdf_cv_func_select_arg=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $xpdf_cv_func_select_arg" >&5 +echo "${ECHO_T}$xpdf_cv_func_select_arg" >&6 +if test "$xpdf_cv_func_select_arg" != yes; then + cat >>confdefs.h <<\_ACEOF +#define SELECT_TAKES_INT 1 +_ACEOF + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Check whether --enable-largefile or --disable-largefile was given. +if test "${enable_largefile+set}" = set; then + enableval="$enable_largefile" + +fi; +if test "$enable_largefile" != no; then + + echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5 +echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_largefile_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext + CC="$CC -n32" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_largefile_CC=' -n32'; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5 +echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6 + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi + + echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_file_offset_bits+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + while :; do + ac_cv_sys_file_offset_bits=no + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_file_offset_bits=64; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + break +done +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5 +echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6 +if test "$ac_cv_sys_file_offset_bits" != no; then + +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF + +fi +rm -f conftest* + echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5 +echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_large_files+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + while :; do + ac_cv_sys_large_files=no + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_large_files=1; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + break +done +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5 +echo "${ECHO_T}$ac_cv_sys_large_files" >&6 +if test "$ac_cv_sys_large_files" != no; then + +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF + +fi +rm -f conftest* +fi + +echo "$as_me:$LINENO: checking for _LARGEFILE_SOURCE value needed for large files" >&5 +echo $ECHO_N "checking for _LARGEFILE_SOURCE value needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_largefile_source+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + while :; do + ac_cv_sys_largefile_source=no + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +return !fseeko; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _LARGEFILE_SOURCE 1 +#include +int +main () +{ +return !fseeko; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_largefile_source=1; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + break +done +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_source" >&5 +echo "${ECHO_T}$ac_cv_sys_largefile_source" >&6 +if test "$ac_cv_sys_largefile_source" != no; then + +cat >>confdefs.h <<_ACEOF +#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source +_ACEOF + +fi +rm -f conftest* + +# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug +# in glibc 2.1.3, but that breaks too many other things. +# If you want fseeko and ftello with glibc, upgrade to a fixed glibc. +echo "$as_me:$LINENO: checking for fseeko" >&5 +echo $ECHO_N "checking for fseeko... $ECHO_C" >&6 +if test "${ac_cv_func_fseeko+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +return fseeko && fseeko (stdin, 0, 0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_fseeko=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_fseeko=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_fseeko" >&5 +echo "${ECHO_T}$ac_cv_func_fseeko" >&6 +if test $ac_cv_func_fseeko = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FSEEKO 1 +_ACEOF + +fi + + +for ac_func in fseek64 +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + xpdf_cv_func_fseek64=yes +else + xpdf_cv_func_fseek64=no +fi +done + + +for ac_func in ftell64 +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + xpdf_cv_func_ftell64=yes +else + xpdf_cv_func_ftell64=no +fi +done + +if test "$xpdf_cv_func_fseek64" = yes -a "$xpdf_cv_func_ftell64" = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_FSEEK64 1 +_ACEOF + +fi + +if test -z "$no_x"; then + echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + + + + + + + + + + + + + +# Check whether --with-Xpm-library or --without-Xpm-library was given. +if test "${with_Xpm_library+set}" = set; then + withval="$with_Xpm_library" + smr_cv_with_Xpm_library=$withval +fi; + + echo "$as_me:$LINENO: checking whether to use Xpm library" >&5 +echo $ECHO_N "checking whether to use Xpm library... $ECHO_C" >&6 +if test "${smr_cv_with_Xpm_library+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Xpm_library=maybe +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Xpm_library" >&5 +echo "${ECHO_T}$smr_cv_with_Xpm_library" >&6 + + + case x"$smr_cv_with_Xpm_library" in + xyes | xmaybe) + Xpm_LIBS="-lXpm" + with_Xpm=$smr_cv_with_Xpm_library + ;; + xno) + Xpm_LIBS= + with_Xpm=no + ;; + *) + if test -f "$smr_cv_with_Xpm_library"; then + Xpm_LIBS=$smr_cv_with_Xpm_library + elif test -d "$smr_cv_with_Xpm_library"; then + Xpm_LIBS="-L$smr_cv_with_Xpm_library -lXpm" + else + { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5 +echo "$as_me: error: argument must be boolean, file, or directory" >&2;} + { (exit 1); exit 1; }; } + fi + with_Xpm=yes + ;; + esac + + + + + + + + if test ! x"$with_Xpm" = xno; then + + # If we got this far, then the user didn't explicitly ask not to use + # the library. + + + + + + + + +# Check whether --with-Xpm-includes or --without-Xpm-includes was given. +if test "${with_Xpm_includes+set}" = set; then + withval="$with_Xpm_includes" + smr_cv_with_Xpm_includes=$withval +fi; + + echo "$as_me:$LINENO: checking where to find the Xpm header files" >&5 +echo $ECHO_N "checking where to find the Xpm header files... $ECHO_C" >&6 +if test "${smr_cv_with_Xpm_includes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Xpm_includes= +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Xpm_includes" >&5 +echo "${ECHO_T}$smr_cv_with_Xpm_includes" >&6 + + if test ! x"$smr_cv_with_Xpm_includes" = x; then + if test -d "$smr_cv_with_Xpm_includes"; then + Xpm_CFLAGS="-I$smr_cv_with_Xpm_includes" + else + { { echo "$as_me:$LINENO: error: argument must be a directory" >&5 +echo "$as_me: error: argument must be a directory" >&2;} + { (exit 1); exit 1; }; } + fi + else + Xpm_CFLAGS= + fi + + smr_test_CPPFLAGS="${CPPFLAGS+set}" + smr_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $Xpm_CFLAGS $X_CFLAGS" + + +for ac_header in X11/xpm.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + smr_have_Xpm_header=yes +else + smr_have_Xpm_header=no +fi + +done + + + if test x"$smr_test_CPPFLAGS" = xset; then + CPPFLAGS=$smr_save_CPPFLAGS + else + unset CPPFLAGS + fi + + + + + + + + # We need only look for the library if the header has been found + # (or no header is needed). + if test $smr_have_Xpm_header != no; then + + echo "$as_me:$LINENO: checking for XpmCreatePixmapFromData in -lXpm" >&5 +echo $ECHO_N "checking for XpmCreatePixmapFromData in -lXpm... $ECHO_C" >&6 +if test "${ac_cv_lib_Xpm_XpmCreatePixmapFromData+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXpm $Xpm_CFLAGS $X_CFLAGS $Xpm_LIBS $X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XpmCreatePixmapFromData (); +int +main () +{ +XpmCreatePixmapFromData (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xpm_XpmCreatePixmapFromData=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xpm_XpmCreatePixmapFromData=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xpm_XpmCreatePixmapFromData" >&5 +echo "${ECHO_T}$ac_cv_lib_Xpm_XpmCreatePixmapFromData" >&6 +if test $ac_cv_lib_Xpm_XpmCreatePixmapFromData = yes; then + smr_have_Xpm_library=yes +else + smr_have_Xpm_library=no +fi + + fi + + if test x"$smr_have_Xpm_library" = xyes; then + echo "$as_me:$LINENO: result: using Xpm library" >&5 +echo "${ECHO_T}using Xpm library" >&6 + else + Xpm_LIBS= + Xpm_CFLAGS= + + if test x"$with_Xpm" = xmaybe; then + echo "$as_me:$LINENO: result: not using Xpm library" >&5 +echo "${ECHO_T}not using Xpm library" >&6 + else + { echo "$as_me:$LINENO: WARNING: requested Xpm library not found!" >&5 +echo "$as_me: WARNING: requested Xpm library not found!" >&2;} + fi + fi + fi + + + + + + + + + + + + + +fi + +if test -z "$no_x"; then + + + + + + + + + + + + + + + + + + +# Check whether --with-Xext-library or --without-Xext-library was given. +if test "${with_Xext_library+set}" = set; then + withval="$with_Xext_library" + smr_cv_with_Xext_library=$withval +fi; + + echo "$as_me:$LINENO: checking whether to use Xext library" >&5 +echo $ECHO_N "checking whether to use Xext library... $ECHO_C" >&6 +if test "${smr_cv_with_Xext_library+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Xext_library=maybe +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Xext_library" >&5 +echo "${ECHO_T}$smr_cv_with_Xext_library" >&6 + + + case x"$smr_cv_with_Xext_library" in + xyes | xmaybe) + Xext_LIBS="-lXext" + with_Xext=$smr_cv_with_Xext_library + ;; + xno) + Xext_LIBS= + with_Xext=no + ;; + *) + if test -f "$smr_cv_with_Xext_library"; then + Xext_LIBS=$smr_cv_with_Xext_library + elif test -d "$smr_cv_with_Xext_library"; then + Xext_LIBS="-L$smr_cv_with_Xext_library -lXext" + else + { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5 +echo "$as_me: error: argument must be boolean, file, or directory" >&2;} + { (exit 1); exit 1; }; } + fi + with_Xext=yes + ;; + esac + + + + + + + + if test ! x"$with_Xext" = xno; then + + # If we got this far, then the user didn't explicitly ask not to use + # the library. + + + + + + + + +# Check whether --with-Xext-includes or --without-Xext-includes was given. +if test "${with_Xext_includes+set}" = set; then + withval="$with_Xext_includes" + smr_cv_with_Xext_includes=$withval +fi; + + echo "$as_me:$LINENO: checking where to find the Xext header files" >&5 +echo $ECHO_N "checking where to find the Xext header files... $ECHO_C" >&6 +if test "${smr_cv_with_Xext_includes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Xext_includes= +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Xext_includes" >&5 +echo "${ECHO_T}$smr_cv_with_Xext_includes" >&6 + + if test ! x"$smr_cv_with_Xext_includes" = x; then + if test -d "$smr_cv_with_Xext_includes"; then + Xext_CFLAGS="-I$smr_cv_with_Xext_includes" + else + { { echo "$as_me:$LINENO: error: argument must be a directory" >&5 +echo "$as_me: error: argument must be a directory" >&2;} + { (exit 1); exit 1; }; } + fi + else + Xext_CFLAGS= + fi + + smr_test_CPPFLAGS="${CPPFLAGS+set}" + smr_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $Xext_CFLAGS $X_CFLAGS" + + +for ac_header in X11/Xlib.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + smr_have_Xext_header=yes +else + smr_have_Xext_header=no +fi + +done + + + if test x"$smr_test_CPPFLAGS" = xset; then + CPPFLAGS=$smr_save_CPPFLAGS + else + unset CPPFLAGS + fi + + + + + + + + # We need only look for the library if the header has been found + # (or no header is needed). + if test $smr_have_Xext_header != no; then + + echo "$as_me:$LINENO: checking for XextAddDisplay in -lXext" >&5 +echo $ECHO_N "checking for XextAddDisplay in -lXext... $ECHO_C" >&6 +if test "${ac_cv_lib_Xext_XextAddDisplay+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXext $Xext_CFLAGS $X_CFLAGS $Xext_LIBS $X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XextAddDisplay (); +int +main () +{ +XextAddDisplay (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xext_XextAddDisplay=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xext_XextAddDisplay=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xext_XextAddDisplay" >&5 +echo "${ECHO_T}$ac_cv_lib_Xext_XextAddDisplay" >&6 +if test $ac_cv_lib_Xext_XextAddDisplay = yes; then + smr_have_Xext_library=yes +else + smr_have_Xext_library=no +fi + + fi + + if test x"$smr_have_Xext_library" = xyes; then + echo "$as_me:$LINENO: result: using Xext library" >&5 +echo "${ECHO_T}using Xext library" >&6 + else + Xext_LIBS= + Xext_CFLAGS= + + if test x"$with_Xext" = xmaybe; then + echo "$as_me:$LINENO: result: not using Xext library" >&5 +echo "${ECHO_T}not using Xext library" >&6 + else + { echo "$as_me:$LINENO: WARNING: requested Xext library not found!" >&5 +echo "$as_me: WARNING: requested Xext library not found!" >&2;} + fi + fi + fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Check whether --with-Xp-library or --without-Xp-library was given. +if test "${with_Xp_library+set}" = set; then + withval="$with_Xp_library" + smr_cv_with_Xp_library=$withval +fi; + + echo "$as_me:$LINENO: checking whether to use Xp library" >&5 +echo $ECHO_N "checking whether to use Xp library... $ECHO_C" >&6 +if test "${smr_cv_with_Xp_library+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Xp_library=maybe +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Xp_library" >&5 +echo "${ECHO_T}$smr_cv_with_Xp_library" >&6 + + + case x"$smr_cv_with_Xp_library" in + xyes | xmaybe) + Xp_LIBS="-lXp" + with_Xp=$smr_cv_with_Xp_library + ;; + xno) + Xp_LIBS= + with_Xp=no + ;; + *) + if test -f "$smr_cv_with_Xp_library"; then + Xp_LIBS=$smr_cv_with_Xp_library + elif test -d "$smr_cv_with_Xp_library"; then + Xp_LIBS="-L$smr_cv_with_Xp_library -lXp" + else + { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5 +echo "$as_me: error: argument must be boolean, file, or directory" >&2;} + { (exit 1); exit 1; }; } + fi + with_Xp=yes + ;; + esac + + + + + + + + if test ! x"$with_Xp" = xno; then + + # If we got this far, then the user didn't explicitly ask not to use + # the library. + + + + + + + + +# Check whether --with-Xp-includes or --without-Xp-includes was given. +if test "${with_Xp_includes+set}" = set; then + withval="$with_Xp_includes" + smr_cv_with_Xp_includes=$withval +fi; + + echo "$as_me:$LINENO: checking where to find the Xp header files" >&5 +echo $ECHO_N "checking where to find the Xp header files... $ECHO_C" >&6 +if test "${smr_cv_with_Xp_includes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Xp_includes= +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Xp_includes" >&5 +echo "${ECHO_T}$smr_cv_with_Xp_includes" >&6 + + if test ! x"$smr_cv_with_Xp_includes" = x; then + if test -d "$smr_cv_with_Xp_includes"; then + Xp_CFLAGS="-I$smr_cv_with_Xp_includes" + else + { { echo "$as_me:$LINENO: error: argument must be a directory" >&5 +echo "$as_me: error: argument must be a directory" >&2;} + { (exit 1); exit 1; }; } + fi + else + Xp_CFLAGS= + fi + + smr_test_CPPFLAGS="${CPPFLAGS+set}" + smr_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $Xp_CFLAGS $X_CFLAGS" + + +for ac_header in X11/extensions/Print.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + smr_have_Xp_header=yes +else + smr_have_Xp_header=no +fi + +done + + + if test x"$smr_test_CPPFLAGS" = xset; then + CPPFLAGS=$smr_save_CPPFLAGS + else + unset CPPFLAGS + fi + + + + + + + + # We need only look for the library if the header has been found + # (or no header is needed). + if test $smr_have_Xp_header != no; then + + echo "$as_me:$LINENO: checking for XpStartPage in -lXp" >&5 +echo $ECHO_N "checking for XpStartPage in -lXp... $ECHO_C" >&6 +if test "${ac_cv_lib_Xp_XpStartPage+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXp $Xp_CFLAGS $X_CFLAGS $Xp_LIBS $X_LIBS $X_PRE_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XpStartPage (); +int +main () +{ +XpStartPage (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xp_XpStartPage=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xp_XpStartPage=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xp_XpStartPage" >&5 +echo "${ECHO_T}$ac_cv_lib_Xp_XpStartPage" >&6 +if test $ac_cv_lib_Xp_XpStartPage = yes; then + smr_have_Xp_library=yes +else + smr_have_Xp_library=no +fi + + fi + + if test x"$smr_have_Xp_library" = xyes; then + echo "$as_me:$LINENO: result: using Xp library" >&5 +echo "${ECHO_T}using Xp library" >&6 + else + Xp_LIBS= + Xp_CFLAGS= + + if test x"$with_Xp" = xmaybe; then + echo "$as_me:$LINENO: result: not using Xp library" >&5 +echo "${ECHO_T}not using Xp library" >&6 + else + { echo "$as_me:$LINENO: WARNING: requested Xp library not found!" >&5 +echo "$as_me: WARNING: requested Xp library not found!" >&2;} + fi + fi + fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Check whether --with-Xt-library or --without-Xt-library was given. +if test "${with_Xt_library+set}" = set; then + withval="$with_Xt_library" + smr_cv_with_Xt_library=$withval +fi; + + echo "$as_me:$LINENO: checking whether to use Xt library" >&5 +echo $ECHO_N "checking whether to use Xt library... $ECHO_C" >&6 +if test "${smr_cv_with_Xt_library+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Xt_library=maybe +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Xt_library" >&5 +echo "${ECHO_T}$smr_cv_with_Xt_library" >&6 + + + case x"$smr_cv_with_Xt_library" in + xyes | xmaybe) + Xt_LIBS="-lXt" + with_Xt=$smr_cv_with_Xt_library + ;; + xno) + Xt_LIBS= + with_Xt=no + ;; + *) + if test -f "$smr_cv_with_Xt_library"; then + Xt_LIBS=$smr_cv_with_Xt_library + elif test -d "$smr_cv_with_Xt_library"; then + Xt_LIBS="-L$smr_cv_with_Xt_library -lXt" + else + { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5 +echo "$as_me: error: argument must be boolean, file, or directory" >&2;} + { (exit 1); exit 1; }; } + fi + with_Xt=yes + ;; + esac + + + + + + + + if test ! x"$with_Xt" = xno; then + + # If we got this far, then the user didn't explicitly ask not to use + # the library. + + + + + + + + +# Check whether --with-Xt-includes or --without-Xt-includes was given. +if test "${with_Xt_includes+set}" = set; then + withval="$with_Xt_includes" + smr_cv_with_Xt_includes=$withval +fi; + + echo "$as_me:$LINENO: checking where to find the Xt header files" >&5 +echo $ECHO_N "checking where to find the Xt header files... $ECHO_C" >&6 +if test "${smr_cv_with_Xt_includes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Xt_includes= +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Xt_includes" >&5 +echo "${ECHO_T}$smr_cv_with_Xt_includes" >&6 + + if test ! x"$smr_cv_with_Xt_includes" = x; then + if test -d "$smr_cv_with_Xt_includes"; then + Xt_CFLAGS="-I$smr_cv_with_Xt_includes" + else + { { echo "$as_me:$LINENO: error: argument must be a directory" >&5 +echo "$as_me: error: argument must be a directory" >&2;} + { (exit 1); exit 1; }; } + fi + else + Xt_CFLAGS= + fi + + smr_test_CPPFLAGS="${CPPFLAGS+set}" + smr_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $Xt_CFLAGS $X_CFLAGS" + + +for ac_header in X11/Intrinsic.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + smr_have_Xt_header=yes +else + smr_have_Xt_header=no +fi + +done + + + if test x"$smr_test_CPPFLAGS" = xset; then + CPPFLAGS=$smr_save_CPPFLAGS + else + unset CPPFLAGS + fi + + + + + + + + # We need only look for the library if the header has been found + # (or no header is needed). + if test $smr_have_Xt_header != no; then + + echo "$as_me:$LINENO: checking for XtAppInitialize in -lXt" >&5 +echo $ECHO_N "checking for XtAppInitialize in -lXt... $ECHO_C" >&6 +if test "${ac_cv_lib_Xt_XtAppInitialize+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXt $Xt_CFLAGS $X_CFLAGS $Xt_LIBS $X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XtAppInitialize (); +int +main () +{ +XtAppInitialize (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xt_XtAppInitialize=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xt_XtAppInitialize=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xt_XtAppInitialize" >&5 +echo "${ECHO_T}$ac_cv_lib_Xt_XtAppInitialize" >&6 +if test $ac_cv_lib_Xt_XtAppInitialize = yes; then + smr_have_Xt_library=yes +else + smr_have_Xt_library=no +fi + + fi + + if test x"$smr_have_Xt_library" = xyes; then + echo "$as_me:$LINENO: result: using Xt library" >&5 +echo "${ECHO_T}using Xt library" >&6 + else + Xt_LIBS= + Xt_CFLAGS= + + if test x"$with_Xt" = xmaybe; then + echo "$as_me:$LINENO: result: not using Xt library" >&5 +echo "${ECHO_T}not using Xt library" >&6 + else + { echo "$as_me:$LINENO: WARNING: requested Xt library not found!" >&5 +echo "$as_me: WARNING: requested Xt library not found!" >&2;} + fi + fi + fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Check whether --with-Xm-library or --without-Xm-library was given. +if test "${with_Xm_library+set}" = set; then + withval="$with_Xm_library" + smr_cv_with_Xm_library=$withval +fi; + + echo "$as_me:$LINENO: checking whether to use Xm library" >&5 +echo $ECHO_N "checking whether to use Xm library... $ECHO_C" >&6 +if test "${smr_cv_with_Xm_library+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Xm_library=maybe +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Xm_library" >&5 +echo "${ECHO_T}$smr_cv_with_Xm_library" >&6 + + + case x"$smr_cv_with_Xm_library" in + xyes | xmaybe) + Xm_LIBS="-lXm" + with_Xm=$smr_cv_with_Xm_library + ;; + xno) + Xm_LIBS= + with_Xm=no + ;; + *) + if test -f "$smr_cv_with_Xm_library"; then + Xm_LIBS=$smr_cv_with_Xm_library + elif test -d "$smr_cv_with_Xm_library"; then + Xm_LIBS="-L$smr_cv_with_Xm_library -lXm" + else + { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5 +echo "$as_me: error: argument must be boolean, file, or directory" >&2;} + { (exit 1); exit 1; }; } + fi + with_Xm=yes + ;; + esac + + + + + + + + if test ! x"$with_Xm" = xno; then + + # If we got this far, then the user didn't explicitly ask not to use + # the library. + + + + + + + + +# Check whether --with-Xm-includes or --without-Xm-includes was given. +if test "${with_Xm_includes+set}" = set; then + withval="$with_Xm_includes" + smr_cv_with_Xm_includes=$withval +fi; + + echo "$as_me:$LINENO: checking where to find the Xm header files" >&5 +echo $ECHO_N "checking where to find the Xm header files... $ECHO_C" >&6 +if test "${smr_cv_with_Xm_includes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Xm_includes= +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Xm_includes" >&5 +echo "${ECHO_T}$smr_cv_with_Xm_includes" >&6 + + if test ! x"$smr_cv_with_Xm_includes" = x; then + if test -d "$smr_cv_with_Xm_includes"; then + Xm_CFLAGS="-I$smr_cv_with_Xm_includes" + else + { { echo "$as_me:$LINENO: error: argument must be a directory" >&5 +echo "$as_me: error: argument must be a directory" >&2;} + { (exit 1); exit 1; }; } + fi + else + Xm_CFLAGS= + fi + + smr_test_CPPFLAGS="${CPPFLAGS+set}" + smr_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $Xm_CFLAGS $X_CFLAGS" + + +for ac_header in Xm/XmAll.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + smr_have_Xm_header=yes +else + smr_have_Xm_header=no +fi + +done + + + if test x"$smr_test_CPPFLAGS" = xset; then + CPPFLAGS=$smr_save_CPPFLAGS + else + unset CPPFLAGS + fi + + + + + + + + # We need only look for the library if the header has been found + # (or no header is needed). + if test $smr_have_Xm_header != no; then + + echo "$as_me:$LINENO: checking for XmCreateForm in -lXm" >&5 +echo $ECHO_N "checking for XmCreateForm in -lXm... $ECHO_C" >&6 +if test "${ac_cv_lib_Xm_XmCreateForm+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXm $Xm_CFLAGS $X_CFLAGS $Xm_LIBS $Xt_LIBS $X_LIBS $X_PRE_LIBS $Xp_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XmCreateForm (); +int +main () +{ +XmCreateForm (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xm_XmCreateForm=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xm_XmCreateForm=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xm_XmCreateForm" >&5 +echo "${ECHO_T}$ac_cv_lib_Xm_XmCreateForm" >&6 +if test $ac_cv_lib_Xm_XmCreateForm = yes; then + smr_have_Xm_library=yes +else + smr_have_Xm_library=no +fi + + fi + + if test x"$smr_have_Xm_library" = xyes; then + echo "$as_me:$LINENO: result: using Xm library" >&5 +echo "${ECHO_T}using Xm library" >&6 + else + Xm_LIBS= + Xm_CFLAGS= + + if test x"$with_Xm" = xmaybe; then + echo "$as_me:$LINENO: result: not using Xm library" >&5 +echo "${ECHO_T}not using Xm library" >&6 + else + { echo "$as_me:$LINENO: WARNING: requested Xm library not found!" >&5 +echo "$as_me: WARNING: requested Xm library not found!" >&2;} + fi + fi + fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Check whether --with-Sgm-library or --without-Sgm-library was given. +if test "${with_Sgm_library+set}" = set; then + withval="$with_Sgm_library" + smr_cv_with_Sgm_library=$withval +fi; + + echo "$as_me:$LINENO: checking whether to use Sgm library" >&5 +echo $ECHO_N "checking whether to use Sgm library... $ECHO_C" >&6 +if test "${smr_cv_with_Sgm_library+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Sgm_library=maybe +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Sgm_library" >&5 +echo "${ECHO_T}$smr_cv_with_Sgm_library" >&6 + + + case x"$smr_cv_with_Sgm_library" in + xyes | xmaybe) + Sgm_LIBS="-lSgm" + with_Sgm=$smr_cv_with_Sgm_library + ;; + xno) + Sgm_LIBS= + with_Sgm=no + ;; + *) + if test -f "$smr_cv_with_Sgm_library"; then + Sgm_LIBS=$smr_cv_with_Sgm_library + elif test -d "$smr_cv_with_Sgm_library"; then + Sgm_LIBS="-L$smr_cv_with_Sgm_library -lSgm" + else + { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5 +echo "$as_me: error: argument must be boolean, file, or directory" >&2;} + { (exit 1); exit 1; }; } + fi + with_Sgm=yes + ;; + esac + + + + + + + + if test ! x"$with_Sgm" = xno; then + + # If we got this far, then the user didn't explicitly ask not to use + # the library. + + + + + + + + +# Check whether --with-Sgm-includes or --without-Sgm-includes was given. +if test "${with_Sgm_includes+set}" = set; then + withval="$with_Sgm_includes" + smr_cv_with_Sgm_includes=$withval +fi; + + echo "$as_me:$LINENO: checking where to find the Sgm header files" >&5 +echo $ECHO_N "checking where to find the Sgm header files... $ECHO_C" >&6 +if test "${smr_cv_with_Sgm_includes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_Sgm_includes= +fi +echo "$as_me:$LINENO: result: $smr_cv_with_Sgm_includes" >&5 +echo "${ECHO_T}$smr_cv_with_Sgm_includes" >&6 + + if test ! x"$smr_cv_with_Sgm_includes" = x; then + if test -d "$smr_cv_with_Sgm_includes"; then + Sgm_CFLAGS="-I$smr_cv_with_Sgm_includes" + else + { { echo "$as_me:$LINENO: error: argument must be a directory" >&5 +echo "$as_me: error: argument must be a directory" >&2;} + { (exit 1); exit 1; }; } + fi + else + Sgm_CFLAGS= + fi + + smr_test_CPPFLAGS="${CPPFLAGS+set}" + smr_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $Sgm_CFLAGS $X_CFLAGS" + + +for ac_header in Sgm/HPanedW.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + smr_have_Sgm_header=yes +else + smr_have_Sgm_header=no +fi + +done + + + if test x"$smr_test_CPPFLAGS" = xset; then + CPPFLAGS=$smr_save_CPPFLAGS + else + unset CPPFLAGS + fi + + + + + + + + # We need only look for the library if the header has been found + # (or no header is needed). + if test $smr_have_Sgm_header != no; then + + echo "$as_me:$LINENO: checking for SgCreateHorzPanedWindow in -lSgm" >&5 +echo $ECHO_N "checking for SgCreateHorzPanedWindow in -lSgm... $ECHO_C" >&6 +if test "${ac_cv_lib_Sgm_SgCreateHorzPanedWindow+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lSgm $Sgm_CFLAGS $X_CFLAGS $Sgm_LIBS $Xm_LIBS $Xt_LIBS $X_LIBS $X_PRE_LIBS $Xp_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char SgCreateHorzPanedWindow (); +int +main () +{ +SgCreateHorzPanedWindow (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Sgm_SgCreateHorzPanedWindow=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Sgm_SgCreateHorzPanedWindow=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Sgm_SgCreateHorzPanedWindow" >&5 +echo "${ECHO_T}$ac_cv_lib_Sgm_SgCreateHorzPanedWindow" >&6 +if test $ac_cv_lib_Sgm_SgCreateHorzPanedWindow = yes; then + smr_have_Sgm_library=yes +else + smr_have_Sgm_library=no +fi + + fi + + if test x"$smr_have_Sgm_library" = xyes; then + echo "$as_me:$LINENO: result: using Sgm library" >&5 +echo "${ECHO_T}using Sgm library" >&6 + else + Sgm_LIBS= + Sgm_CFLAGS= + + if test x"$with_Sgm" = xmaybe; then + echo "$as_me:$LINENO: result: not using Sgm library" >&5 +echo "${ECHO_T}not using Sgm library" >&6 + else + { echo "$as_me:$LINENO: WARNING: requested Sgm library not found!" >&5 +echo "$as_me: WARNING: requested Sgm library not found!" >&2;} + fi + fi + fi + + + + + + + + + + + + + + + if test "x$smr_have_Xt_library" = xyes; then + echo "$as_me:$LINENO: checking for XtAppSetExitFlag in -lXt" >&5 +echo $ECHO_N "checking for XtAppSetExitFlag in -lXt... $ECHO_C" >&6 +if test "${ac_cv_lib_Xt_XtAppSetExitFlag+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXt $Xt_LIBS $X_LIBS $X_PRE_LIBS $Xp_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XtAppSetExitFlag (); +int +main () +{ +XtAppSetExitFlag (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xt_XtAppSetExitFlag=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xt_XtAppSetExitFlag=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xt_XtAppSetExitFlag" >&5 +echo "${ECHO_T}$ac_cv_lib_Xt_XtAppSetExitFlag" >&6 +if test $ac_cv_lib_Xt_XtAppSetExitFlag = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_XTAPPSETEXITFLAG 1 +_ACEOF + +fi + + fi +fi + + + + + + + + + + + + + + + + + + + +# Check whether --with-t1-library or --without-t1-library was given. +if test "${with_t1_library+set}" = set; then + withval="$with_t1_library" + smr_cv_with_t1_library=$withval +fi; + + echo "$as_me:$LINENO: checking whether to use t1 library" >&5 +echo $ECHO_N "checking whether to use t1 library... $ECHO_C" >&6 +if test "${smr_cv_with_t1_library+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_t1_library=maybe +fi +echo "$as_me:$LINENO: result: $smr_cv_with_t1_library" >&5 +echo "${ECHO_T}$smr_cv_with_t1_library" >&6 + + + case x"$smr_cv_with_t1_library" in + xyes | xmaybe) + t1_LIBS="-lt1" + with_t1=$smr_cv_with_t1_library + ;; + xno) + t1_LIBS= + with_t1=no + ;; + *) + if test -f "$smr_cv_with_t1_library"; then + t1_LIBS=$smr_cv_with_t1_library + elif test -d "$smr_cv_with_t1_library"; then + t1_LIBS="-L$smr_cv_with_t1_library -lt1" + else + { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5 +echo "$as_me: error: argument must be boolean, file, or directory" >&2;} + { (exit 1); exit 1; }; } + fi + with_t1=yes + ;; + esac + + + + + + + + if test ! x"$with_t1" = xno; then + + # If we got this far, then the user didn't explicitly ask not to use + # the library. + + + + + + + + +# Check whether --with-t1-includes or --without-t1-includes was given. +if test "${with_t1_includes+set}" = set; then + withval="$with_t1_includes" + smr_cv_with_t1_includes=$withval +fi; + + echo "$as_me:$LINENO: checking where to find the t1 header files" >&5 +echo $ECHO_N "checking where to find the t1 header files... $ECHO_C" >&6 +if test "${smr_cv_with_t1_includes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_t1_includes= +fi +echo "$as_me:$LINENO: result: $smr_cv_with_t1_includes" >&5 +echo "${ECHO_T}$smr_cv_with_t1_includes" >&6 + + if test ! x"$smr_cv_with_t1_includes" = x; then + if test -d "$smr_cv_with_t1_includes"; then + t1_CFLAGS="-I$smr_cv_with_t1_includes" + else + { { echo "$as_me:$LINENO: error: argument must be a directory" >&5 +echo "$as_me: error: argument must be a directory" >&2;} + { (exit 1); exit 1; }; } + fi + else + t1_CFLAGS= + fi + + smr_test_CPPFLAGS="${CPPFLAGS+set}" + smr_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $t1_CFLAGS $X_CFLAGS" + + +for ac_header in t1lib.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + smr_have_t1_header=yes +else + smr_have_t1_header=no +fi + +done + + + if test x"$smr_test_CPPFLAGS" = xset; then + CPPFLAGS=$smr_save_CPPFLAGS + else + unset CPPFLAGS + fi + + + + + + + + # We need only look for the library if the header has been found + # (or no header is needed). + if test $smr_have_t1_header != no; then + + echo "$as_me:$LINENO: checking for T1_InitLib in -lt1" >&5 +echo $ECHO_N "checking for T1_InitLib in -lt1... $ECHO_C" >&6 +if test "${ac_cv_lib_t1_T1_InitLib+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lt1 $t1_CFLAGS $X_CFLAGS $t1_LIBS -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char T1_InitLib (); +int +main () +{ +T1_InitLib (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_t1_T1_InitLib=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_t1_T1_InitLib=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_t1_T1_InitLib" >&5 +echo "${ECHO_T}$ac_cv_lib_t1_T1_InitLib" >&6 +if test $ac_cv_lib_t1_T1_InitLib = yes; then + smr_have_t1_library=yes +else + smr_have_t1_library=no +fi + + fi + + if test x"$smr_have_t1_library" = xyes; then + echo "$as_me:$LINENO: result: using t1 library" >&5 +echo "${ECHO_T}using t1 library" >&6 + else + t1_LIBS= + t1_CFLAGS= + + if test x"$with_t1" = xmaybe; then + echo "$as_me:$LINENO: result: not using t1 library" >&5 +echo "${ECHO_T}not using t1 library" >&6 + else + { echo "$as_me:$LINENO: WARNING: requested t1 library not found!" >&5 +echo "$as_me: WARNING: requested t1 library not found!" >&2;} + fi + fi + fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Check whether --with-freetype2-library or --without-freetype2-library was given. +if test "${with_freetype2_library+set}" = set; then + withval="$with_freetype2_library" + smr_cv_with_freetype2_library=$withval +fi; + + echo "$as_me:$LINENO: checking whether to use freetype2 library" >&5 +echo $ECHO_N "checking whether to use freetype2 library... $ECHO_C" >&6 +if test "${smr_cv_with_freetype2_library+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_freetype2_library=maybe +fi +echo "$as_me:$LINENO: result: $smr_cv_with_freetype2_library" >&5 +echo "${ECHO_T}$smr_cv_with_freetype2_library" >&6 + + + case x"$smr_cv_with_freetype2_library" in + xyes | xmaybe) + freetype2_LIBS="-lfreetype" + with_freetype2=$smr_cv_with_freetype2_library + ;; + xno) + freetype2_LIBS= + with_freetype2=no + ;; + *) + if test -f "$smr_cv_with_freetype2_library"; then + freetype2_LIBS=$smr_cv_with_freetype2_library + elif test -d "$smr_cv_with_freetype2_library"; then + freetype2_LIBS="-L$smr_cv_with_freetype2_library -lfreetype" + else + { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5 +echo "$as_me: error: argument must be boolean, file, or directory" >&2;} + { (exit 1); exit 1; }; } + fi + with_freetype2=yes + ;; + esac + + + + + + + + if test ! x"$with_freetype2" = xno; then + + # If we got this far, then the user didn't explicitly ask not to use + # the library. + + + + + + + + +# Check whether --with-freetype2-includes or --without-freetype2-includes was given. +if test "${with_freetype2_includes+set}" = set; then + withval="$with_freetype2_includes" + smr_cv_with_freetype2_includes=$withval +fi; + + echo "$as_me:$LINENO: checking where to find the freetype2 header files" >&5 +echo $ECHO_N "checking where to find the freetype2 header files... $ECHO_C" >&6 +if test "${smr_cv_with_freetype2_includes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_freetype2_includes= +fi +echo "$as_me:$LINENO: result: $smr_cv_with_freetype2_includes" >&5 +echo "${ECHO_T}$smr_cv_with_freetype2_includes" >&6 + + if test ! x"$smr_cv_with_freetype2_includes" = x; then + if test -d "$smr_cv_with_freetype2_includes"; then + freetype2_CFLAGS="-I$smr_cv_with_freetype2_includes" + else + { { echo "$as_me:$LINENO: error: argument must be a directory" >&5 +echo "$as_me: error: argument must be a directory" >&2;} + { (exit 1); exit 1; }; } + fi + else + freetype2_CFLAGS= + fi + + smr_test_CPPFLAGS="${CPPFLAGS+set}" + smr_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $freetype2_CFLAGS " + + +for ac_header in ft2build.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + smr_have_freetype2_header=yes +else + smr_have_freetype2_header=no +fi + +done + + + if test x"$smr_test_CPPFLAGS" = xset; then + CPPFLAGS=$smr_save_CPPFLAGS + else + unset CPPFLAGS + fi + + + + + + + + # We need only look for the library if the header has been found + # (or no header is needed). + if test $smr_have_freetype2_header != no; then + + echo "$as_me:$LINENO: checking for FT_Get_Name_Index in -lfreetype" >&5 +echo $ECHO_N "checking for FT_Get_Name_Index in -lfreetype... $ECHO_C" >&6 +if test "${ac_cv_lib_freetype_FT_Get_Name_Index+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfreetype $freetype2_CFLAGS $freetype2_LIBS -lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char FT_Get_Name_Index (); +int +main () +{ +FT_Get_Name_Index (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_freetype_FT_Get_Name_Index=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_freetype_FT_Get_Name_Index=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_freetype_FT_Get_Name_Index" >&5 +echo "${ECHO_T}$ac_cv_lib_freetype_FT_Get_Name_Index" >&6 +if test $ac_cv_lib_freetype_FT_Get_Name_Index = yes; then + smr_have_freetype2_library=yes +else + smr_have_freetype2_library=no +fi + + fi + + if test x"$smr_have_freetype2_library" = xyes; then + echo "$as_me:$LINENO: result: using freetype2 library" >&5 +echo "${ECHO_T}using freetype2 library" >&6 + else + freetype2_LIBS= + freetype2_CFLAGS= + + if test x"$with_freetype2" = xmaybe; then + echo "$as_me:$LINENO: result: not using freetype2 library" >&5 +echo "${ECHO_T}not using freetype2 library" >&6 + else + { echo "$as_me:$LINENO: WARNING: requested freetype2 library not found!" >&5 +echo "$as_me: WARNING: requested freetype2 library not found!" >&2;} + fi + fi + fi + + + + + + + + + + + + + +if test "x$smr_have_freetype2_library" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_FREETYPE_FREETYPE_H 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_SPLASH 1 +_ACEOF + +fi + + + + + + + + + + + + + + + + + + + +# Check whether --with-libpaper-library or --without-libpaper-library was given. +if test "${with_libpaper_library+set}" = set; then + withval="$with_libpaper_library" + smr_cv_with_libpaper_library=$withval +fi; + + echo "$as_me:$LINENO: checking whether to use libpaper library" >&5 +echo $ECHO_N "checking whether to use libpaper library... $ECHO_C" >&6 +if test "${smr_cv_with_libpaper_library+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_libpaper_library=maybe +fi +echo "$as_me:$LINENO: result: $smr_cv_with_libpaper_library" >&5 +echo "${ECHO_T}$smr_cv_with_libpaper_library" >&6 + + + case x"$smr_cv_with_libpaper_library" in + xyes | xmaybe) + libpaper_LIBS="-lpaper" + with_libpaper=$smr_cv_with_libpaper_library + ;; + xno) + libpaper_LIBS= + with_libpaper=no + ;; + *) + if test -f "$smr_cv_with_libpaper_library"; then + libpaper_LIBS=$smr_cv_with_libpaper_library + elif test -d "$smr_cv_with_libpaper_library"; then + libpaper_LIBS="-L$smr_cv_with_libpaper_library -lpaper" + else + { { echo "$as_me:$LINENO: error: argument must be boolean, file, or directory" >&5 +echo "$as_me: error: argument must be boolean, file, or directory" >&2;} + { (exit 1); exit 1; }; } + fi + with_libpaper=yes + ;; + esac + + + + + + + + if test ! x"$with_libpaper" = xno; then + + # If we got this far, then the user didn't explicitly ask not to use + # the library. + + + + + + + + +# Check whether --with-libpaper-includes or --without-libpaper-includes was given. +if test "${with_libpaper_includes+set}" = set; then + withval="$with_libpaper_includes" + smr_cv_with_libpaper_includes=$withval +fi; + + echo "$as_me:$LINENO: checking where to find the libpaper header files" >&5 +echo $ECHO_N "checking where to find the libpaper header files... $ECHO_C" >&6 +if test "${smr_cv_with_libpaper_includes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + smr_cv_with_libpaper_includes= +fi +echo "$as_me:$LINENO: result: $smr_cv_with_libpaper_includes" >&5 +echo "${ECHO_T}$smr_cv_with_libpaper_includes" >&6 + + if test ! x"$smr_cv_with_libpaper_includes" = x; then + if test -d "$smr_cv_with_libpaper_includes"; then + libpaper_CFLAGS="-I$smr_cv_with_libpaper_includes" + else + { { echo "$as_me:$LINENO: error: argument must be a directory" >&5 +echo "$as_me: error: argument must be a directory" >&2;} + { (exit 1); exit 1; }; } + fi + else + libpaper_CFLAGS= + fi + + smr_test_CPPFLAGS="${CPPFLAGS+set}" + smr_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $libpaper_CFLAGS " + + +for ac_header in paper.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + smr_have_libpaper_header=yes +else + smr_have_libpaper_header=no +fi + +done + + + if test x"$smr_test_CPPFLAGS" = xset; then + CPPFLAGS=$smr_save_CPPFLAGS + else + unset CPPFLAGS + fi + + + + + + + + # We need only look for the library if the header has been found + # (or no header is needed). + if test $smr_have_libpaper_header != no; then + + echo "$as_me:$LINENO: checking for paperinit in -lpaper" >&5 +echo $ECHO_N "checking for paperinit in -lpaper... $ECHO_C" >&6 +if test "${ac_cv_lib_paper_paperinit+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpaper $libpaper_CFLAGS $libpaper_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char paperinit (); +int +main () +{ +paperinit (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_paper_paperinit=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_paper_paperinit=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_paper_paperinit" >&5 +echo "${ECHO_T}$ac_cv_lib_paper_paperinit" >&6 +if test $ac_cv_lib_paper_paperinit = yes; then + smr_have_libpaper_library=yes +else + smr_have_libpaper_library=no +fi + + fi + + if test x"$smr_have_libpaper_library" = xyes; then + echo "$as_me:$LINENO: result: using libpaper library" >&5 +echo "${ECHO_T}using libpaper library" >&6 + else + libpaper_LIBS= + libpaper_CFLAGS= + + if test x"$with_libpaper" = xmaybe; then + echo "$as_me:$LINENO: result: not using libpaper library" >&5 +echo "${ECHO_T}not using libpaper library" >&6 + else + { echo "$as_me:$LINENO: WARNING: requested libpaper library not found!" >&5 +echo "$as_me: WARNING: requested libpaper library not found!" >&2;} + fi + fi + fi + + + + + + + + + + + + + + +if test -n "$no_x" -o "x$smr_have_Xm_library" != xyes -o "x$smr_have_freetype2_library" != xyes; then + X="#" + XPDF_TARGET="all-no-x" +else + X="" + XPDF_TARGET="all" +fi + + + + ac_config_files="$ac_config_files Makefile goo/Makefile fofi/Makefile splash/Makefile xpdf/Makefile" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "goo/Makefile" ) CONFIG_FILES="$CONFIG_FILES goo/Makefile" ;; + "fofi/Makefile" ) CONFIG_FILES="$CONFIG_FILES fofi/Makefile" ;; + "splash/Makefile" ) CONFIG_FILES="$CONFIG_FILES splash/Makefile" ;; + "xpdf/Makefile" ) CONFIG_FILES="$CONFIG_FILES xpdf/Makefile" ;; + "aconf.h" ) CONFIG_HEADERS="$CONFIG_HEADERS aconf.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@EXE@,$EXE,;t t +s,@LIBPREFIX@,$LIBPREFIX,;t t +s,@AR@,$AR,;t t +s,@UP_DIR@,$UP_DIR,;t t +s,@CPP@,$CPP,;t t +s,@X_CFLAGS@,$X_CFLAGS,;t t +s,@X_PRE_LIBS@,$X_PRE_LIBS,;t t +s,@X_LIBS@,$X_LIBS,;t t +s,@X_EXTRA_LIBS@,$X_EXTRA_LIBS,;t t +s,@EGREP@,$EGREP,;t t +s,@Xpm_LIBS@,$Xpm_LIBS,;t t +s,@Xpm_CFLAGS@,$Xpm_CFLAGS,;t t +s,@Xext_LIBS@,$Xext_LIBS,;t t +s,@Xext_CFLAGS@,$Xext_CFLAGS,;t t +s,@Xp_LIBS@,$Xp_LIBS,;t t +s,@Xp_CFLAGS@,$Xp_CFLAGS,;t t +s,@Xt_LIBS@,$Xt_LIBS,;t t +s,@Xt_CFLAGS@,$Xt_CFLAGS,;t t +s,@Xm_LIBS@,$Xm_LIBS,;t t +s,@Xm_CFLAGS@,$Xm_CFLAGS,;t t +s,@Sgm_LIBS@,$Sgm_LIBS,;t t +s,@Sgm_CFLAGS@,$Sgm_CFLAGS,;t t +s,@t1_LIBS@,$t1_LIBS,;t t +s,@t1_CFLAGS@,$t1_CFLAGS,;t t +s,@freetype2_LIBS@,$freetype2_LIBS,;t t +s,@freetype2_CFLAGS@,$freetype2_CFLAGS,;t t +s,@libpaper_LIBS@,$libpaper_LIBS,;t t +s,@libpaper_CFLAGS@,$libpaper_CFLAGS,;t t +s,@X@,$X,;t t +s,@XPDF_TARGET@,$XPDF_TARGET,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + +if test -n "$no_x" -o "x$smr_have_Xm_library" != xyes -o "x$smr_have_freetype2_library" != xyes; then + if test -n "$no_x"; then + { echo "$as_me:$LINENO: WARNING: Couldn't find X" >&5 +echo "$as_me: WARNING: Couldn't find X" >&2;}; + fi + if test "x$smr_have_Xm_library" != xyes; then + { echo "$as_me:$LINENO: WARNING: Couldn't find Motif" >&5 +echo "$as_me: WARNING: Couldn't find Motif" >&2;}; + fi + if test "x$smr_have_freetype2_library" != xyes; then + { echo "$as_me:$LINENO: WARNING: Couldn't find FreeType" >&5 +echo "$as_me: WARNING: Couldn't find FreeType" >&2;}; + fi + { echo "$as_me:$LINENO: WARNING: -- You will be able to compile pdftops, pdftotext, + pdfinfo, pdffonts, and pdfimages, but not xpdf or pdftoppm" >&5 +echo "$as_me: WARNING: -- You will be able to compile pdftops, pdftotext, + pdfinfo, pdffonts, and pdfimages, but not xpdf or pdftoppm" >&2;} +fi diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/configure.in swftools-0.9.1/lib/pdf/xpdf/configure.in --- swftools-0.9.2+ds1/lib/pdf/xpdf/configure.in 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/configure.in 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,353 @@ +dnl Process this file with autoconf to produce a configure script. +dnl Copyright 1998-2005 Glyph & Cog, LLC + +AC_PREREQ(2.57) + +AC_INIT(xpdf/xpdf.cc) +AC_CONFIG_HEADER(aconf.h) + +dnl ##### Optional features. +AC_ARG_ENABLE(a4-paper, +[ --enable-a4-paper use A4 paper size instead of Letter for + PostScript output], +AC_DEFINE(A4_PAPER)) +AC_ARG_ENABLE(no-text-select, +[ --enable-no-text-select do not allow text selection], +AC_DEFINE(NO_TEXT_SELECT)) +AC_ARG_ENABLE(opi, +[ --enable-opi include support for OPI comments], +AC_DEFINE(OPI_SUPPORT)) +AC_ARG_ENABLE(multithreaded, +[ --enable-multithreaded include support for multithreading], +AC_DEFINE(MULTITHREADED)) +AC_ARG_ENABLE(exceptions, +[ --enable-exceptions use C++ exceptions], +AC_DEFINE(USE_EXCEPTIONS)) +AC_ARG_ENABLE(wordlist, +[ --enable-wordlist include support for building word lists], +AC_DEFINE(TEXTOUT_WORD_LIST)) +AC_ARG_ENABLE(fixedpoint, +[ --enable-fixedpoint use fixed point (instead of floating point) arithmetic], +AC_DEFINE(USE_FIXEDPOINT)) +AC_ARG_ENABLE(cmyk, +[ --enable-cmyk include support for CMYK rasterization], +AC_DEFINE(SPLASH_CMYK)) +AC_ARG_WITH(appdef-dir, +[ --with-appdef-dir set app-defaults directory], +AC_DEFINE_UNQUOTED(APPDEFDIR, "$with_appdef_dir")) + +dnl ##### Path to xpdfrc. +dnl This ugly kludge to get the sysconfdir path is needed because +dnl autoconf doesn't actually set the prefix variable until later. +if test "$sysconfdir" = '${prefix}/etc'; then + if test "x$prefix" = xNONE; then + system_xpdfrc="$ac_default_prefix/etc/xpdfrc" + else + system_xpdfrc="$prefix/etc/xpdfrc" + fi +else + system_xpdfrc="$sysconfdir/xpdfrc" +fi +AC_DEFINE_UNQUOTED(SYSTEM_XPDFRC, "$system_xpdfrc") + +dnl ##### Checks for programs. +AC_PROG_CC +AC_ISC_POSIX +AC_PROG_CC_STDC +#if test -z "$CXX" -a "$CC" = "gcc"; then +# CXX="gcc" +#fi +AC_PROG_CXX +AC_PROG_INSTALL +AC_PROG_RANLIB + +dnl ##### Default values for Unix. +EXE="" +LIBPREFIX="lib" +AR="ar rc" +UP_DIR="" + +dnl ##### Check for OS/2. +AC_CACHE_CHECK([for OS/2 (with EMX)], +xpdf_cv_sys_os2, +[AC_TRY_COMPILE([], +[__EMX__], +xpdf_cv_sys_os2=yes, xpdf_cv_sys_os2=no)]) +if test "$xpdf_cv_sys_os2" = yes; then + EXE=".exe" + LIBPREFIX="" + AR="ar -rc" +fi + +dnl ##### Check for DOS (with DJGPP). +AC_CACHE_CHECK([for DOS (with DJGPP)], +xpdf_cv_sys_dos, +[AC_TRY_COMPILE([], +[__DJGPP__], +xpdf_cv_sys_dos=yes, xpdf_cv_sys_dos=no)]) +if test "$xpdf_cv_sys_dos" = yes; then + EXE=".exe" + LIBPREFIX="lib" + AR="ar -rc" + UP_DIR="../" +fi + +dnl ##### Do substitutions. +AC_SUBST(EXE) +AC_SUBST(LIBPREFIX) +AC_SUBST(AR) +AC_SUBST(UP_DIR) + +dnl ##### Checks for header files. +AC_PATH_XTRA +AC_HEADER_DIRENT + +dnl ##### Switch over to C++. This will make the checks below a little +dnl ##### bit stricter (requiring function prototypes in include files). +dnl ##### (99% of xpdf is written in C++.) +AC_LANG_CPLUSPLUS + +dnl ##### Check for extra libraries needed by X. (LynxOS needs this.) +AC_CHECK_FUNC(gethostbyname) +if test $ac_cv_func_gethostbyname = no; then + AC_CHECK_LIB(bsd, gethostbyname, X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd") +fi + +dnl ##### Look for header that defines select() and fd_set. +AC_MSG_CHECKING([select() and fd_set in sys/select.h and sys/bsdtypes.h]) +AC_TRY_COMPILE([#include +#include +#include +#include ], + [fd_set fds; +select(0, NULL, NULL, NULL, NULL);], xpdf_ok=yes, xpdf_ok=no) +if test $xpdf_ok = yes; then + AC_MSG_RESULT([not needed]) +else + AC_TRY_COMPILE([#include +#include +#include +#include +#include ], + [fd_set fds; +select(0, NULL, NULL, NULL, NULL);], xpdf_ok=yes, xpdf_ok=no) + if test $xpdf_ok = yes; then + AC_DEFINE(HAVE_SYS_SELECT_H) + AC_MSG_RESULT([need sys/select.h]) + else + AC_TRY_COMPILE([#include +#include +#include +#include +#include ], + [fd_set fds; +select(0, NULL, NULL, NULL, NULL);], xpdf_ok=yes, xpdf_ok=no) + if test $xpdf_ok = yes; then + AC_DEFINE(HAVE_SYS_BSDTYPES_H) + AC_MSG_RESULT([need sys/bsdtypes.h]) + else + AC_MSG_RESULT([problem]) + fi + fi +fi + +dnl ##### Look for header that defines FD_ZERO. +AC_MSG_CHECKING([FD_ZERO and strings.h or bstring.h]) +AC_TRY_COMPILE([#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif], +[fd_set fds; FD_ZERO(&fds);], xpdf_ok=yes, xpdf_ok=no) +if test $xpdf_ok = yes; then + AC_MSG_RESULT([not needed]) +else + AC_TRY_COMPILE([#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif], + [fd_set fds; FD_ZERO(&fds);], xpdf_ok=yes, xpdf_ok=no) + if test $xpdf_ok = yes; then + AC_DEFINE(HAVE_STRINGS_H) + AC_MSG_RESULT([need strings.h]) + else + AC_TRY_COMPILE([#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif], + [fd_set fds; FD_ZERO(&fds);], xpdf_ok=yes, xpdf_ok=no) + if test $xpdf_ok = yes; then + AC_DEFINE(HAVE_BSTRING_H) + AC_MSG_RESULT([need bstring.h]) + else + AC_MSG_RESULT([problem]) + fi + fi +fi + +dnl ##### Look for rewinddir. +AC_CHECK_FUNCS(rewinddir) +if test $ac_cv_func_rewinddir = no; then + AC_CHECK_LIB(cposix, rewinddir) +fi + +dnl ##### Checks for library functions. +AC_CHECK_FUNCS(popen) +dnl # This should use 'AC_CHECK_FUNCS(mkstemp)' but that fails if +dnl # the mkstemp exists in the library but isn't declared in the +dnl # include file (e.g., in cygwin 1.1.2). +AC_CACHE_CHECK([for mkstemp], +xpdf_cv_func_mkstemp, +[AC_TRY_LINK([#include +#include ], +[mkstemp("foo");], +xpdf_cv_func_mkstemp=yes, xpdf_cv_func_mkstemp=no)]) +if test "$xpdf_cv_func_mkstemp" = yes; then + AC_DEFINE(HAVE_MKSTEMP) +fi +dnl # Check for mkstemps, just like mkstemp. +AC_CACHE_CHECK([for mkstemps], +xpdf_cv_func_mkstemps, +[AC_TRY_LINK([#include +#include ], +[mkstemps("foo", 0);], +xpdf_cv_func_mkstemps=yes, xpdf_cv_func_mkstemps=no)]) +if test "$xpdf_cv_func_mkstemps" = yes; then + AC_DEFINE(HAVE_MKSTEMPS) +fi + +dnl ##### Check select argument type: on HP-UX before version 10, select +dnl ##### takes (int *) instead of (fd_set *). +AC_CACHE_CHECK([whether select takes fd_set arguments], +xpdf_cv_func_select_arg, +[AC_TRY_COMPILE([#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif], +[fd_set fds; +select(1, &fds, &fds, &fds, 0);], +xpdf_cv_func_select_arg=yes, xpdf_cv_func_select_arg=no)]) +if test "$xpdf_cv_func_select_arg" != yes; then + AC_DEFINE(SELECT_TAKES_INT) +fi + +dnl ##### Back to C for the library tests. +AC_LANG_C + +dnl ##### Check for fseeko/ftello or fseek64/ftell64 +dnl The LARGEFILE and FSEEKO macros have to be called in C, not C++, mode. +AC_SYS_LARGEFILE +AC_FUNC_FSEEKO +AC_CHECK_FUNCS(fseek64, xpdf_cv_func_fseek64=yes, xpdf_cv_func_fseek64=no) +AC_CHECK_FUNCS(ftell64, xpdf_cv_func_ftell64=yes, xpdf_cv_func_ftell64=no) +if test "$xpdf_cv_func_fseek64" = yes -a "$xpdf_cv_func_ftell64" = yes; then + AC_DEFINE(HAVE_FSEEK64) +fi + +dnl ##### Check for libXpm. +if test -z "$no_x"; then + smr_CHECK_LIB(Xpm, Xpm, [pixmap library - used only for icon], + XpmCreatePixmapFromData, X11/xpm.h, + $X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS -lX11, $X_CFLAGS) + AC_SUBST(Xpm_LIBS) + AC_SUBST(Xpm_CFLAGS) +fi + +dnl ##### Check for Motif (libXm). +if test -z "$no_x"; then + dnl # XextAddDisplay isn't defined in any header file, so we provide a + dnl # bogus prototype (so the compiler doesn't complain) and a bogus + dnl # header file (so the smr macro doesn't break). + smr_CHECK_LIB(Xext, Xext, [Motif library], + XextAddDisplay, X11/Xlib.h, + $X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS -lX11, $X_CFLAGS, + [int XextAddDisplay();]) + AC_SUBST(Xext_LIBS) + AC_SUBST(Xext_CFLAGS) + smr_CHECK_LIB(Xp, Xp, [Motif library], + XpStartPage, X11/extensions/Print.h, + $X_LIBS $X_PRE_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11, $X_CFLAGS) + AC_SUBST(Xp_LIBS) + AC_SUBST(Xp_CFLAGS) + smr_CHECK_LIB(Xt, Xt, [Motif library], + XtAppInitialize, X11/Intrinsic.h, + $X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS -lX11, $X_CFLAGS) + AC_SUBST(Xt_LIBS) + AC_SUBST(Xt_CFLAGS) + smr_CHECK_LIB(Xm, Xm, [Motif library], + XmCreateForm, Xm/XmAll.h, + $Xt_LIBS $X_LIBS $X_PRE_LIBS $Xp_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11, $X_CFLAGS) + AC_SUBST(Xm_LIBS) + AC_SUBST(Xm_CFLAGS) + smr_CHECK_LIB(Sgm, Sgm, [SGI Motif library], + SgCreateHorzPanedWindow, Sgm/HPanedW.h, + $Xm_LIBS $Xt_LIBS $X_LIBS $X_PRE_LIBS $Xp_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11, $X_CFLAGS) + AC_SUBST(Sgm_LIBS) + AC_SUBST(Sgm_CFLAGS) + + dnl # check for XtAppSetExitFlag, which didn't exist prior to X11R6 (?) + if test "x$smr_have_Xt_library" = xyes; then + AC_CHECK_LIB(Xt, XtAppSetExitFlag, + AC_DEFINE(HAVE_XTAPPSETEXITFLAG), , + [$Xt_LIBS $X_LIBS $X_PRE_LIBS $Xp_LIBS $Xext_LIBS $X_EXTRA_LIBS -lX11]) + fi +fi + +dnl ##### Check for t1lib. +smr_CHECK_LIB(t1, t1, [Type 1 font rasterizer], + T1_InitLib, t1lib.h, + -lm, $X_CFLAGS) +AC_SUBST(t1_LIBS) +AC_SUBST(t1_CFLAGS) + +dnl ##### Check for FreeType 2.x. +dnl ##### (Note: FT_Get_Name_Index was added in FT 2.0.5, and is +dnl ##### the reason that Xpdf requires 2.0.5+.) +smr_CHECK_LIB(freetype2, freetype, [FreeType2 font rasterizer - version 2.0.5+], + FT_Get_Name_Index, ft2build.h, -lm) +AC_SUBST(freetype2_LIBS) +AC_SUBST(freetype2_CFLAGS) +if test "x$smr_have_freetype2_library" = xyes; then + AC_DEFINE(HAVE_FREETYPE_FREETYPE_H) + AC_DEFINE(HAVE_SPLASH) +fi + +dnl ##### Check for libpaper (Debian). +smr_CHECK_LIB(libpaper, paper, [Debian libpaper], paperinit, paper.h) +AC_SUBST(libpaper_LIBS) +AC_SUBST(libpaper_CFLAGS) + +dnl ##### Disable X-specific stuff in top-level Makefile. +if test -n "$no_x" -o "x$smr_have_Xm_library" != xyes -o "x$smr_have_freetype2_library" != xyes; then + X="#" + XPDF_TARGET="all-no-x" +else + X="" + XPDF_TARGET="all" +fi +AC_SUBST(X) +AC_SUBST(XPDF_TARGET) + +dnl ##### Write the makefiles. +AC_OUTPUT(Makefile goo/Makefile fofi/Makefile splash/Makefile xpdf/Makefile) + +dnl ##### Warn user if X is missing. +if test -n "$no_x" -o "x$smr_have_Xm_library" != xyes -o "x$smr_have_freetype2_library" != xyes; then + if test -n "$no_x"; then + AC_MSG_WARN([Couldn't find X]); + fi + if test "x$smr_have_Xm_library" != xyes; then + AC_MSG_WARN([Couldn't find Motif]); + fi + if test "x$smr_have_freetype2_library" != xyes; then + AC_MSG_WARN([Couldn't find FreeType]); + fi + AC_MSG_WARN([-- You will be able to compile pdftops, pdftotext, + pdfinfo, pdffonts, and pdfimages, but not xpdf or pdftoppm]) +fi diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/COPYING swftools-0.9.1/lib/pdf/xpdf/COPYING --- swftools-0.9.2+ds1/lib/pdf/xpdf/COPYING 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/COPYING 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/CoreOutputDev.cc swftools-0.9.1/lib/pdf/xpdf/CoreOutputDev.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/CoreOutputDev.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/CoreOutputDev.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,61 @@ +//======================================================================== +// +// CoreOutputDev.cc +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "Object.h" +#include "TextOutputDev.h" +#include "CoreOutputDev.h" + +//------------------------------------------------------------------------ +// CoreOutputDev +//------------------------------------------------------------------------ + +CoreOutputDev::CoreOutputDev(SplashColorMode colorModeA, int bitmapRowPadA, + GBool reverseVideoA, SplashColorPtr paperColorA, + GBool incrementalUpdateA, + CoreOutRedrawCbk redrawCbkA, + void *redrawCbkDataA): + SplashOutputDev(colorModeA, bitmapRowPadA, reverseVideoA, paperColorA) +{ + incrementalUpdate = incrementalUpdateA; + redrawCbk = redrawCbkA; + redrawCbkData = redrawCbkDataA; +} + +CoreOutputDev::~CoreOutputDev() { +} + +void CoreOutputDev::endPage() { + SplashOutputDev::endPage(); + if (!incrementalUpdate) { + (*redrawCbk)(redrawCbkData, 0, 0, getBitmapWidth(), getBitmapHeight(), + gTrue); + } +} + +void CoreOutputDev::dump() { + int x0, y0, x1, y1; + + if (incrementalUpdate) { + getModRegion(&x0, &y0, &x1, &y1); + clearModRegion(); + if (x1 >= x0 && y1 >= y0) { + (*redrawCbk)(redrawCbkData, x0, y0, x1, y1, gFalse); + } + } +} + +void CoreOutputDev::clear() { + startDoc(NULL); + startPage(0, NULL); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/CoreOutputDev.h swftools-0.9.1/lib/pdf/xpdf/CoreOutputDev.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/CoreOutputDev.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/CoreOutputDev.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,61 @@ +//======================================================================== +// +// CoreOutputDev.h +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef COREOUTPUTDEV_H +#define COREOUTPUTDEV_H + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" +#include "SplashOutputDev.h" + +class TextPage; + +//------------------------------------------------------------------------ + +typedef void (*CoreOutRedrawCbk)(void *data, int x0, int y0, int x1, int y1, + GBool composited); + +//------------------------------------------------------------------------ +// CoreOutputDev +//------------------------------------------------------------------------ + +class CoreOutputDev: public SplashOutputDev { +public: + + CoreOutputDev(SplashColorMode colorModeA, int bitmapRowPadA, + GBool reverseVideoA, SplashColorPtr paperColorA, + GBool incrementalUpdateA, + CoreOutRedrawCbk redrawCbkA, + void *redrawCbkDataA); + + virtual ~CoreOutputDev(); + + //----- initialization and control + + // End a page. + virtual void endPage(); + + // Dump page contents to display. + virtual void dump(); + + //----- special access + + // Clear out the document (used when displaying an empty window). + void clear(); + +private: + + GBool incrementalUpdate; // incrementally update the display? + CoreOutRedrawCbk redrawCbk; + void *redrawCbkData; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/dblLeftArrowDis.xbm swftools-0.9.1/lib/pdf/xpdf/dblLeftArrowDis.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/dblLeftArrowDis.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/dblLeftArrowDis.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define dblLeftArrowDis_width 16 +#define dblLeftArrowDis_height 15 +static unsigned char dblLeftArrowDis_bits[] = { + 0x80, 0x80, 0x40, 0x40, 0xa0, 0xa0, 0x50, 0x50, 0xa8, 0xa8, 0x54, 0x54, + 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x54, 0x54, 0xa8, 0xa8, 0x50, 0x50, + 0xa0, 0xa0, 0x40, 0x40, 0x80, 0x80}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/dblLeftArrow.xbm swftools-0.9.1/lib/pdf/xpdf/dblLeftArrow.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/dblLeftArrow.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/dblLeftArrow.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define dblLeftArrow_width 16 +#define dblLeftArrow_height 15 +static unsigned char dblLeftArrow_bits[] = { + 0x80, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfc, + 0xfe, 0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, + 0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0x80}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/dblRightArrowDis.xbm swftools-0.9.1/lib/pdf/xpdf/dblRightArrowDis.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/dblRightArrowDis.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/dblRightArrowDis.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define dblRightArrowDis_width 16 +#define dblRightArrowDis_height 15 +static unsigned char dblRightArrowDis_bits[] = { + 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x0a, 0x0a, 0x15, 0x15, 0x2a, 0x2a, + 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0x2a, 0x2a, 0x15, 0x15, 0x0a, 0x0a, + 0x05, 0x05, 0x02, 0x02, 0x01, 0x01}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/dblRightArrow.xbm swftools-0.9.1/lib/pdf/xpdf/dblRightArrow.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/dblRightArrow.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/dblRightArrow.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define dblRightArrow_width 16 +#define dblRightArrow_height 15 +static unsigned char dblRightArrow_bits[] = { + 0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x0f, 0x1f, 0x1f, 0x3f, 0x3f, + 0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f, + 0x07, 0x07, 0x03, 0x03, 0x01, 0x01}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Decrypt.cc swftools-0.9.1/lib/pdf/xpdf/Decrypt.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Decrypt.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Decrypt.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,777 @@ +//======================================================================== +// +// Decrypt.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "Decrypt.h" + +static void rc4InitKey(Guchar *key, int keyLen, Guchar *state); +static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c); +static void aesKeyExpansion(DecryptAESState *s, + Guchar *objKey, int objKeyLen); +static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last); +static void md5(Guchar *msg, int msgLen, Guchar *digest); + +static Guchar passwordPad[32] = { + 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, + 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, + 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, + 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a +}; + +//------------------------------------------------------------------------ +// Decrypt +//------------------------------------------------------------------------ + +GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, + GString *ownerKey, GString *userKey, + int permissions, GString *fileID, + GString *ownerPassword, GString *userPassword, + Guchar *fileKey, GBool encryptMetadata, + GBool *ownerPasswordOk) { + Guchar test[32], test2[32]; + GString *userPassword2; + Guchar fState[256]; + Guchar tmpKey[16]; + Guchar fx, fy; + int len, i, j; + + // try using the supplied owner password to generate the user password + *ownerPasswordOk = gFalse; + if (ownerPassword) { + len = ownerPassword->getLength(); + if (len < 32) { + memcpy(test, ownerPassword->getCString(), len); + memcpy(test + len, passwordPad, 32 - len); + } else { + memcpy(test, ownerPassword->getCString(), 32); + } + md5(test, 32, test); + if (encRevision == 3) { + for (i = 0; i < 50; ++i) { + md5(test, 16, test); + } + } + if (encRevision == 2) { + rc4InitKey(test, keyLength, fState); + fx = fy = 0; + for (i = 0; i < 32; ++i) { + test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i)); + } + } else { + memcpy(test2, ownerKey->getCString(), 32); + for (i = 19; i >= 0; --i) { + for (j = 0; j < keyLength; ++j) { + tmpKey[j] = test[j] ^ i; + } + rc4InitKey(tmpKey, keyLength, fState); + fx = fy = 0; + for (j = 0; j < 32; ++j) { + test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]); + } + } + } + userPassword2 = new GString((char *)test2, 32); + if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, + permissions, fileID, userPassword2, fileKey, + encryptMetadata)) { + *ownerPasswordOk = gTrue; + delete userPassword2; + return gTrue; + } + delete userPassword2; + } + + // try using the supplied user password + return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, + permissions, fileID, userPassword, fileKey, + encryptMetadata); +} + +GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength, + GString *ownerKey, GString *userKey, + int permissions, GString *fileID, + GString *userPassword, Guchar *fileKey, + GBool encryptMetadata) { + Guchar *buf; + Guchar test[32]; + Guchar fState[256]; + Guchar tmpKey[16]; + Guchar fx, fy; + int len, i, j; + GBool ok; + + // generate file key + buf = (Guchar *)gmalloc(72 + fileID->getLength()); + if (userPassword) { + len = userPassword->getLength(); + if (len < 32) { + memcpy(buf, userPassword->getCString(), len); + memcpy(buf + len, passwordPad, 32 - len); + } else { + memcpy(buf, userPassword->getCString(), 32); + } + } else { + memcpy(buf, passwordPad, 32); + } + memcpy(buf + 32, ownerKey->getCString(), 32); + buf[64] = permissions & 0xff; + buf[65] = (permissions >> 8) & 0xff; + buf[66] = (permissions >> 16) & 0xff; + buf[67] = (permissions >> 24) & 0xff; + memcpy(buf + 68, fileID->getCString(), fileID->getLength()); + len = 68 + fileID->getLength(); + if (!encryptMetadata) { + buf[len++] = 0xff; + buf[len++] = 0xff; + buf[len++] = 0xff; + buf[len++] = 0xff; + } + md5(buf, len, fileKey); + if (encRevision == 3) { + for (i = 0; i < 50; ++i) { + md5(fileKey, keyLength, fileKey); + } + } + + // test user password + if (encRevision == 2) { + rc4InitKey(fileKey, keyLength, fState); + fx = fy = 0; + for (i = 0; i < 32; ++i) { + test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i)); + } + ok = memcmp(test, passwordPad, 32) == 0; + } else if (encRevision == 3) { + memcpy(test, userKey->getCString(), 32); + for (i = 19; i >= 0; --i) { + for (j = 0; j < keyLength; ++j) { + tmpKey[j] = fileKey[j] ^ i; + } + rc4InitKey(tmpKey, keyLength, fState); + fx = fy = 0; + for (j = 0; j < 32; ++j) { + test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]); + } + } + memcpy(buf, passwordPad, 32); + memcpy(buf + 32, fileID->getCString(), fileID->getLength()); + md5(buf, 32 + fileID->getLength(), buf); + ok = memcmp(test, buf, 16) == 0; + } else { + ok = gFalse; + } + + gfree(buf); + return ok; +} + +//------------------------------------------------------------------------ +// DecryptStream +//------------------------------------------------------------------------ + +DecryptStream::DecryptStream(Stream *strA, Guchar *fileKey, + CryptAlgorithm algoA, int keyLength, + int objNum, int objGen): + FilterStream(strA) +{ + int n, i; + + algo = algoA; + + // construct object key + for (i = 0; i < keyLength; ++i) { + objKey[i] = fileKey[i]; + } + objKey[keyLength] = objNum & 0xff; + objKey[keyLength + 1] = (objNum >> 8) & 0xff; + objKey[keyLength + 2] = (objNum >> 16) & 0xff; + objKey[keyLength + 3] = objGen & 0xff; + objKey[keyLength + 4] = (objGen >> 8) & 0xff; + if (algo == cryptAES) { + objKey[keyLength + 5] = 0x73; // 's' + objKey[keyLength + 6] = 0x41; // 'A' + objKey[keyLength + 7] = 0x6c; // 'l' + objKey[keyLength + 8] = 0x54; // 'T' + n = keyLength + 9; + } else { + n = keyLength + 5; + } + md5(objKey, n, objKey); + if ((objKeyLength = keyLength + 5) > 16) { + objKeyLength = 16; + } +} + +DecryptStream::~DecryptStream() { + delete str; +} + +void DecryptStream::reset() { + int i; + + str->reset(); + switch (algo) { + case cryptRC4: + state.rc4.x = state.rc4.y = 0; + rc4InitKey(objKey, objKeyLength, state.rc4.state); + state.rc4.buf = EOF; + break; + case cryptAES: + aesKeyExpansion(&state.aes, objKey, objKeyLength); + for (i = 0; i < 16; ++i) { + state.aes.cbc[i] = str->getChar(); + } + state.aes.bufIdx = 16; + break; + } +} + +int DecryptStream::getChar() { + Guchar in[16]; + int c, i; + + c = EOF; // make gcc happy + switch (algo) { + case cryptRC4: + if (state.rc4.buf == EOF) { + c = str->getChar(); + if (c != EOF) { + state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x, + &state.rc4.y, (Guchar)c); + } + } + c = state.rc4.buf; + state.rc4.buf = EOF; + break; + case cryptAES: + if (state.aes.bufIdx == 16) { + for (i = 0; i < 16; ++i) { + if ((c = str->getChar()) == EOF) { + return EOF; + } + in[i] = (Guchar)c; + } + aesDecryptBlock(&state.aes, in, str->lookChar() == EOF); + } + if (state.aes.bufIdx == 16) { + c = EOF; + } else { + c = state.aes.buf[state.aes.bufIdx++]; + } + break; + } + return c; +} + +int DecryptStream::lookChar() { + Guchar in[16]; + int c, i; + + c = EOF; // make gcc happy + switch (algo) { + case cryptRC4: + if (state.rc4.buf == EOF) { + c = str->getChar(); + if (c != EOF) { + state.rc4.buf = rc4DecryptByte(state.rc4.state, &state.rc4.x, + &state.rc4.y, (Guchar)c); + } + } + c = state.rc4.buf; + break; + case cryptAES: + if (state.aes.bufIdx == 16) { + for (i = 0; i < 16; ++i) { + if ((c = str->getChar()) == EOF) { + return EOF; + } + in[i] = c; + } + aesDecryptBlock(&state.aes, in, str->lookChar() == EOF); + } + if (state.aes.bufIdx == 16) { + c = EOF; + } else { + c = state.aes.buf[state.aes.bufIdx]; + } + break; + } + return c; +} + +GBool DecryptStream::isBinary(GBool last) { + return str->isBinary(last); +} + +//------------------------------------------------------------------------ +// RC4-compatible decryption +//------------------------------------------------------------------------ + +static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) { + Guchar index1, index2; + Guchar t; + int i; + + for (i = 0; i < 256; ++i) + state[i] = i; + index1 = index2 = 0; + for (i = 0; i < 256; ++i) { + index2 = (key[index1] + state[i] + index2) % 256; + t = state[i]; + state[i] = state[index2]; + state[index2] = t; + index1 = (index1 + 1) % keyLen; + } +} + +static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) { + Guchar x1, y1, tx, ty; + + x1 = *x = (*x + 1) % 256; + y1 = *y = (state[*x] + *y) % 256; + tx = state[x1]; + ty = state[y1]; + state[x1] = ty; + state[y1] = tx; + return c ^ state[(tx + ty) % 256]; +} + +//------------------------------------------------------------------------ +// AES decryption +//------------------------------------------------------------------------ + +static Guchar sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +static Guchar invSbox[256] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +}; + +static Guint rcon[11] = { + 0x00000000, // unused + 0x01000000, + 0x02000000, + 0x04000000, + 0x08000000, + 0x10000000, + 0x20000000, + 0x40000000, + 0x80000000, + 0x1b000000, + 0x36000000 +}; + +static inline Guint subWord(Guint x) { + return (sbox[x >> 24] << 24) + | (sbox[(x >> 16) & 0xff] << 16) + | (sbox[(x >> 8) & 0xff] << 8) + | sbox[x & 0xff]; +} + +static inline Guint rotWord(Guint x) { + return ((x << 8) & 0xffffffff) | (x >> 24); +} + +static inline void invSubBytes(Guchar *state) { + int i; + + for (i = 0; i < 16; ++i) { + state[i] = invSbox[state[i]]; + } +} + +static inline void invShiftRows(Guchar *state) { + Guchar t; + + t = state[7]; + state[7] = state[6]; + state[6] = state[5]; + state[5] = state[4]; + state[4] = t; + + t = state[8]; + state[8] = state[10]; + state[10] = t; + t = state[9]; + state[9] = state[11]; + state[11] = t; + + t = state[12]; + state[12] = state[13]; + state[13] = state[14]; + state[14] = state[15]; + state[15] = t; +} + +// {09} \cdot s +static inline Guchar mul09(Guchar s) { + Guchar s2, s4, s8; + + s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); + s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1); + s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1); + return s ^ s8; +} + +// {0b} \cdot s +static inline Guchar mul0b(Guchar s) { + Guchar s2, s4, s8; + + s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); + s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1); + s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1); + return s ^ s2 ^ s8; +} + +// {0d} \cdot s +static inline Guchar mul0d(Guchar s) { + Guchar s2, s4, s8; + + s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); + s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1); + s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1); + return s ^ s4 ^ s8; +} + +// {0e} \cdot s +static inline Guchar mul0e(Guchar s) { + Guchar s2, s4, s8; + + s2 = (s & 0x80) ? ((s << 1) ^ 0x1b) : (s << 1); + s4 = (s2 & 0x80) ? ((s2 << 1) ^ 0x1b) : (s2 << 1); + s8 = (s4 & 0x80) ? ((s4 << 1) ^ 0x1b) : (s4 << 1); + return s2 ^ s4 ^ s8; +} + +static inline void invMixColumns(Guchar *state) { + int c; + Guchar s0, s1, s2, s3; + + for (c = 0; c < 4; ++c) { + s0 = state[c]; + s1 = state[4+c]; + s2 = state[8+c]; + s3 = state[12+c]; + state[c] = mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3); + state[4+c] = mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3); + state[8+c] = mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3); + state[12+c] = mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3); + } +} + +static inline void invMixColumnsW(Guint *w) { + int c; + Guchar s0, s1, s2, s3; + + for (c = 0; c < 4; ++c) { + s0 = w[c] >> 24; + s1 = w[c] >> 16; + s2 = w[c] >> 8; + s3 = w[c]; + w[c] = ((mul0e(s0) ^ mul0b(s1) ^ mul0d(s2) ^ mul09(s3)) << 24) + | ((mul09(s0) ^ mul0e(s1) ^ mul0b(s2) ^ mul0d(s3)) << 16) + | ((mul0d(s0) ^ mul09(s1) ^ mul0e(s2) ^ mul0b(s3)) << 8) + | (mul0b(s0) ^ mul0d(s1) ^ mul09(s2) ^ mul0e(s3)); + } +} + +static inline void addRoundKey(Guchar *state, Guint *w) { + int c; + + for (c = 0; c < 4; ++c) { + state[c] ^= w[c] >> 24; + state[4+c] ^= w[c] >> 16; + state[8+c] ^= w[c] >> 8; + state[12+c] ^= w[c]; + } +} + +static void aesKeyExpansion(DecryptAESState *s, + Guchar *objKey, int objKeyLen) { + Guint temp; + int i, round; + + //~ this assumes objKeyLen == 16 + + for (i = 0; i < 4; ++i) { + s->w[i] = (objKey[4*i] << 24) + (objKey[4*i+1] << 16) + + (objKey[4*i+2] << 8) + objKey[4*i+3]; + } + for (i = 4; i < 44; ++i) { + temp = s->w[i-1]; + if (!(i & 3)) { + temp = subWord(rotWord(temp)) ^ rcon[i/4]; + } + s->w[i] = s->w[i-4] ^ temp; + } + for (round = 1; round <= 9; ++round) { + invMixColumnsW(&s->w[round * 4]); + } +} + +static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last) { + int c, round, n, i; + + // initial state + for (c = 0; c < 4; ++c) { + s->state[c] = in[4*c]; + s->state[4+c] = in[4*c+1]; + s->state[8+c] = in[4*c+2]; + s->state[12+c] = in[4*c+3]; + } + + // round 0 + addRoundKey(s->state, &s->w[10 * 4]); + + // rounds 1-9 + for (round = 9; round >= 1; --round) { + invSubBytes(s->state); + invShiftRows(s->state); + invMixColumns(s->state); + addRoundKey(s->state, &s->w[round * 4]); + } + + // round 10 + invSubBytes(s->state); + invShiftRows(s->state); + addRoundKey(s->state, &s->w[0]); + + // CBC + for (c = 0; c < 4; ++c) { + s->buf[4*c] = s->state[c] ^ s->cbc[4*c]; + s->buf[4*c+1] = s->state[4+c] ^ s->cbc[4*c+1]; + s->buf[4*c+2] = s->state[8+c] ^ s->cbc[4*c+2]; + s->buf[4*c+3] = s->state[12+c] ^ s->cbc[4*c+3]; + } + + // save the input block for the next CBC + for (i = 0; i < 16; ++i) { + s->cbc[i] = in[i]; + } + + // remove padding + s->bufIdx = 0; + if (last) { + n = s->buf[15]; + if(!n || n>16) n=16; + for (i = 15; i >= n; --i) { + s->buf[i] = s->buf[i-n]; + } + s->bufIdx = n; + } +} + +//------------------------------------------------------------------------ +// MD5 message digest +//------------------------------------------------------------------------ + +// this works around a bug in older Sun compilers +static inline Gulong rotateLeft(Gulong x, int r) { + x &= 0xffffffff; + return ((x << r) | (x >> (32 - r))) & 0xffffffff; +} + +static inline Gulong md5Round1(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, Gulong s, Gulong Ti) { + return b + rotateLeft((a + ((b & c) | (~b & d)) + Xk + Ti), s); +} + +static inline Gulong md5Round2(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, Gulong s, Gulong Ti) { + return b + rotateLeft((a + ((b & d) | (c & ~d)) + Xk + Ti), s); +} + +static inline Gulong md5Round3(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, Gulong s, Gulong Ti) { + return b + rotateLeft((a + (b ^ c ^ d) + Xk + Ti), s); +} + +static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d, + Gulong Xk, Gulong s, Gulong Ti) { + return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s); +} + +static void md5(Guchar *msg, int msgLen, Guchar *digest) { + Gulong x[16]; + Gulong a, b, c, d, aa, bb, cc, dd; + int n64; + int i, j, k; + + // compute number of 64-byte blocks + // (length + pad byte (0x80) + 8 bytes for length) + n64 = (msgLen + 1 + 8 + 63) / 64; + + // initialize a, b, c, d + a = 0x67452301; + b = 0xefcdab89; + c = 0x98badcfe; + d = 0x10325476; + + // loop through blocks + k = 0; + for (i = 0; i < n64; ++i) { + + // grab a 64-byte block + for (j = 0; j < 16 && k < msgLen - 3; ++j, k += 4) + x[j] = (((((msg[k+3] << 8) + msg[k+2]) << 8) + msg[k+1]) << 8) + msg[k]; + if (i == n64 - 1) { + if (k == msgLen - 3) + x[j] = 0x80000000 + (((msg[k+2] << 8) + msg[k+1]) << 8) + msg[k]; + else if (k == msgLen - 2) + x[j] = 0x800000 + (msg[k+1] << 8) + msg[k]; + else if (k == msgLen - 1) + x[j] = 0x8000 + msg[k]; + else + x[j] = 0x80; + ++j; + while (j < 16) + x[j++] = 0; + x[14] = msgLen << 3; + } + + // save a, b, c, d + aa = a; + bb = b; + cc = c; + dd = d; + + // round 1 + a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478); + d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756); + c = md5Round1(c, d, a, b, x[2], 17, 0x242070db); + b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee); + a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf); + d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a); + c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613); + b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501); + a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8); + d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af); + c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1); + b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be); + a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122); + d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193); + c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e); + b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821); + + // round 2 + a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562); + d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340); + c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51); + b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa); + a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d); + d = md5Round2(d, a, b, c, x[10], 9, 0x02441453); + c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681); + b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8); + a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6); + d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6); + c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87); + b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed); + a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905); + d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8); + c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9); + b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a); + + // round 3 + a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942); + d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681); + c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122); + b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c); + a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44); + d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9); + c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60); + b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70); + a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6); + d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa); + c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085); + b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05); + a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039); + d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5); + c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8); + b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665); + + // round 4 + a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244); + d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97); + c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7); + b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039); + a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3); + d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92); + c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d); + b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1); + a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f); + d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0); + c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314); + b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1); + a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82); + d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235); + c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb); + b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391); + + // increment a, b, c, d + a += aa; + b += bb; + c += cc; + d += dd; + } + + // break digest into bytes + digest[0] = (Guchar)(a & 0xff); + digest[1] = (Guchar)((a >>= 8) & 0xff); + digest[2] = (Guchar)((a >>= 8) & 0xff); + digest[3] = (Guchar)((a >>= 8) & 0xff); + digest[4] = (Guchar)(b & 0xff); + digest[5] = (Guchar)((b >>= 8) & 0xff); + digest[6] = (Guchar)((b >>= 8) & 0xff); + digest[7] = (Guchar)((b >>= 8) & 0xff); + digest[8] = (Guchar)(c & 0xff); + digest[9] = (Guchar)((c >>= 8) & 0xff); + digest[10] = (Guchar)((c >>= 8) & 0xff); + digest[11] = (Guchar)((c >>= 8) & 0xff); + digest[12] = (Guchar)(d & 0xff); + digest[13] = (Guchar)((d >>= 8) & 0xff); + digest[14] = (Guchar)((d >>= 8) & 0xff); + digest[15] = (Guchar)((d >>= 8) & 0xff); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Decrypt.h swftools-0.9.1/lib/pdf/xpdf/Decrypt.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Decrypt.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Decrypt.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,95 @@ +//======================================================================== +// +// Decrypt.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef DECRYPT_H +#define DECRYPT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "GString.h" +#include "Object.h" +#include "Stream.h" + +//------------------------------------------------------------------------ +// Decrypt +//------------------------------------------------------------------------ + +class Decrypt { +public: + + // Generate a file key. The buffer must have space for at + // least 16 bytes. Checks and then + // and returns true if either is correct. Sets if + // the owner password was correct. Either or both of the passwords + // may be NULL, which is treated as an empty string. + static GBool makeFileKey(int encVersion, int encRevision, int keyLength, + GString *ownerKey, GString *userKey, + int permissions, GString *fileID, + GString *ownerPassword, GString *userPassword, + Guchar *fileKey, GBool encryptMetadata, + GBool *ownerPasswordOk); + +private: + + static GBool makeFileKey2(int encVersion, int encRevision, int keyLength, + GString *ownerKey, GString *userKey, + int permissions, GString *fileID, + GString *userPassword, Guchar *fileKey, + GBool encryptMetadata); +}; + +//------------------------------------------------------------------------ +// DecryptStream +//------------------------------------------------------------------------ + +struct DecryptRC4State { + Guchar state[256]; + Guchar x, y; + int buf; +}; + +struct DecryptAESState { + Guint w[44]; + Guchar state[16]; + Guchar cbc[16]; + Guchar buf[16]; + int bufIdx; +}; + +class DecryptStream: public FilterStream { +public: + + DecryptStream(Stream *strA, Guchar *fileKey, + CryptAlgorithm algoA, int keyLength, + int objNum, int objGen); + virtual ~DecryptStream(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GBool isBinary(GBool last); + virtual Stream *getUndecodedStream() { return this; } + +private: + + CryptAlgorithm algo; + int objKeyLength; + Guchar objKey[16 + 9]; + + union { + DecryptRC4State rc4; + DecryptAESState aes; + } state; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Dict.cc swftools-0.9.1/lib/pdf/xpdf/Dict.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Dict.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Dict.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,95 @@ +//======================================================================== +// +// Dict.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "Object.h" +#include "XRef.h" +#include "Dict.h" + +//------------------------------------------------------------------------ +// Dict +//------------------------------------------------------------------------ + +Dict::Dict(XRef *xrefA) { + xref = xrefA; + entries = NULL; + size = length = 0; + ref = 1; +} + +Dict::~Dict() { + int i; + + for (i = 0; i < length; ++i) { + gfree(entries[i].key); + entries[i].val.free(); + } + gfree(entries); +} + +void Dict::add(char *key, Object *val) { + if (length == size) { + if (length == 0) { + size = 8; + } else { + size *= 2; + } + entries = (DictEntry *)greallocn(entries, size, sizeof(DictEntry)); + } + entries[length].key = key; + entries[length].val = *val; + ++length; +} + +inline DictEntry *Dict::find(char *key) { + int i; + + for (i = 0; i < length; ++i) { + if (!strcmp(key, entries[i].key)) + return &entries[i]; + } + return NULL; +} + +GBool Dict::is(char *type) { + DictEntry *e; + + return (e = find("Type")) && e->val.isName(type); +} + +Object *Dict::lookup(char *key, Object *obj) { + DictEntry *e; + + return (e = find(key)) ? e->val.fetch(xref, obj) : obj->initNull(); +} + +Object *Dict::lookupNF(char *key, Object *obj) { + DictEntry *e; + + return (e = find(key)) ? e->val.copy(obj) : obj->initNull(); +} + +char *Dict::getKey(int i) { + return entries[i].key; +} + +Object *Dict::getVal(int i, Object *obj) { + return entries[i].val.fetch(xref, obj); +} + +Object *Dict::getValNF(int i, Object *obj) { + return entries[i].val.copy(obj); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Dict.h swftools-0.9.1/lib/pdf/xpdf/Dict.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Dict.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Dict.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,77 @@ +//======================================================================== +// +// Dict.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef DICT_H +#define DICT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Object.h" + +//------------------------------------------------------------------------ +// Dict +//------------------------------------------------------------------------ + +struct DictEntry { + char *key; + Object val; +}; + +class Dict { +public: + + // Constructor. + Dict(XRef *xrefA); + + // Destructor. + ~Dict(); + + // Reference counting. + int incRef() { return ++ref; } + int decRef() { return --ref; } + + // Get number of entries. + int getLength() { return length; } + + // Add an entry. NB: does not copy key. + void add(char *key, Object *val); + + // Check if dictionary is of specified type. + GBool is(char *type); + + // Look up an entry and return the value. Returns a null object + // if is not in the dictionary. + Object *lookup(char *key, Object *obj); + Object *lookupNF(char *key, Object *obj); + + // Iterative accessors. + char *getKey(int i); + Object *getVal(int i, Object *obj); + Object *getValNF(int i, Object *obj); + + // Set the xref pointer. This is only used in one special case: the + // trailer dictionary, which is read before the xref table is + // parsed. + void setXRef(XRef *xrefA) { xref = xrefA; } + +private: + + XRef *xref; // the xref table for this PDF file + DictEntry *entries; // array of entries + int size; // size of array + int length; // number of entries in dictionary + int ref; // reference count + + DictEntry *find(char *key); +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/dj_make.bat swftools-0.9.1/lib/pdf/xpdf/dj_make.bat --- swftools-0.9.2+ds1/lib/pdf/xpdf/dj_make.bat 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/dj_make.bat 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,81 @@ +set CC=gcc +set CFLAGS=-g -O2 -I.. -I..\fofi -I..\goo +set CXX=gpp +set CXXFLAGS=%CFLAGS% +set LIBPROG=ar + +copy aconf-dj.h aconf.h + +cd goo +%CXX% %CXXFLAGS% -c GHash.cc +%CXX% %CXXFLAGS% -c GList.cc +%CXX% %CXXFLAGS% -c GString.cc +%CXX% %CXXFLAGS% -c gmem.cc +%CXX% %CXXFLAGS% -c gmempp.cc +%CXX% %CXXFLAGS% -c gfile.cc +%CC% %CFLAGS% -c parseargs.c +del libGoo.a +%LIBPROG% -rc libGoo.a GHash.o GList.o GString.o gmempp.o gfile.o gmem.o parseargs.o + +cd ..\fofi +%CXX% %CXXFLAGS% -c FoFiBase.cc +%CXX% %CXXFLAGS% -c FoFiEncodings.cc +%CXX% %CXXFLAGS% -c FoFiTrueType.cc +%CXX% %CXXFLAGS% -c FoFiType1.cc +%CXX% %CXXFLAGS% -c FoFiType1C.cc +%LIBPROG% -rc libfofi.a FoFiBase.o FoFiEncodings.o FoFiTrueType.o FoFiType1.o FoFiType1C.o + +cd ..\xpdf +del *.o +%CXX% %CXXFLAGS% -c Annot.cc +%CXX% %CXXFLAGS% -c Array.cc +%CXX% %CXXFLAGS% -c BuiltinFont.cc +%CXX% %CXXFLAGS% -c BuiltinFontTables.cc +%CXX% %CXXFLAGS% -c CMap.cc +%CXX% %CXXFLAGS% -c Catalog.cc +%CXX% %CXXFLAGS% -c CharCodeToUnicode.cc +%CXX% %CXXFLAGS% -c Decrypt.cc +%CXX% %CXXFLAGS% -c Dict.cc +%CXX% %CXXFLAGS% -c Error.cc +%CXX% %CXXFLAGS% -c FontEncodingTables.cc +%CXX% %CXXFLAGS% -c Function.cc +%CXX% %CXXFLAGS% -c Gfx.cc +%CXX% %CXXFLAGS% -c GfxFont.cc +%CXX% %CXXFLAGS% -c GfxState.cc +%CXX% %CXXFLAGS% -c GlobalParams.cc +%CXX% %CXXFLAGS% -c ImageOutputDev.cc +%CXX% %CXXFLAGS% -c JArithmeticDecoder.cc +%CXX% %CXXFLAGS% -c JBIG2Stream.cc +%CXX% %CXXFLAGS% -c JPXStream.cc +%CXX% %CXXFLAGS% -c Lexer.cc +%CXX% %CXXFLAGS% -c Link.cc +%CXX% %CXXFLAGS% -c NameToCharCode.cc +%CXX% %CXXFLAGS% -c Object.cc +%CXX% %CXXFLAGS% -c Outline.cc +%CXX% %CXXFLAGS% -c OutputDev.cc +%CXX% %CXXFLAGS% -c PDFDoc.cc +%CXX% %CXXFLAGS% -c PDFDocEncoding.cc +%CXX% %CXXFLAGS% -c PSOutputDev.cc +%CXX% %CXXFLAGS% -c PSTokenizer.cc +%CXX% %CXXFLAGS% -c Page.cc +%CXX% %CXXFLAGS% -c Parser.cc +%CXX% %CXXFLAGS% -c SecurityHandler.cc +%CXX% %CXXFLAGS% -c Stream.cc +%CXX% %CXXFLAGS% -c TextOutputDev.cc +%CXX% %CXXFLAGS% -c UnicodeMap.cc +%CXX% %CXXFLAGS% -c UnicodeTypeTable.cc +%CXX% %CXXFLAGS% -c XRef.cc +del libxpdf.a +%LIBPROG% -rc libxpdf.a *.o + +%CXX% %CXXFLAGS% -o pdftops.exe pdftops.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a + +%CXX% %CXXFLAGS% -o pdftotext.exe pdftotext.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a + +%CXX% %CXXFLAGS% -o pdfinfo.exe pdfinfo.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a + +%CXX% %CXXFLAGS% -o pdffonts.exe pdffonts.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a + +%CXX% %CXXFLAGS% -o pdfimages.exe pdfimages.cc libxpdf.a ..\fofi\libfofi.a ..\goo\libGoo.a + +cd .. diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Error.cc swftools-0.9.1/lib/pdf/xpdf/Error.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Error.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Error.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,38 @@ +//======================================================================== +// +// Error.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include "GlobalParams.h" +#include "Error.h" + +void CDECL error(int pos, char *msg, ...) { + va_list args; + + // NB: this can be called before the globalParams object is created + if (globalParams && globalParams->getErrQuiet()) { + return; + } + if (pos >= 0) { + fprintf(stderr, "Error (%d): ", pos); + } else { + fprintf(stderr, "Error: "); + } + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + fprintf(stderr, "\n"); + fflush(stderr); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/ErrorCodes.h swftools-0.9.1/lib/pdf/xpdf/ErrorCodes.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/ErrorCodes.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/ErrorCodes.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,36 @@ +//======================================================================== +// +// ErrorCodes.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef ERRORCODES_H +#define ERRORCODES_H + +#define errNone 0 // no error + +#define errOpenFile 1 // couldn't open the PDF file + +#define errBadCatalog 2 // couldn't read the page catalog + +#define errDamaged 3 // PDF file was damaged and couldn't be + // repaired + +#define errEncrypted 4 // file was encrypted and password was + // incorrect or not supplied + +#define errHighlightFile 5 // nonexistent or invalid highlight file + +#define errBadPrinter 6 // invalid printer + +#define errPrinting 7 // error during printing + +#define errPermission 8 // PDF file doesn't allow that operation + +#define errBadPageNum 9 // invalid page number + +#define errFileIO 10 // file I/O error + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Error.h swftools-0.9.1/lib/pdf/xpdf/Error.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Error.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Error.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,23 @@ +//======================================================================== +// +// Error.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef ERROR_H +#define ERROR_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "config.h" + +extern void CDECL error(int pos, char *msg, ...); + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/findDis.xbm swftools-0.9.1/lib/pdf/xpdf/findDis.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/findDis.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/findDis.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define findDis_width 15 +#define findDis_height 15 +static unsigned char findDis_bits[] = { + 0x10, 0x04, 0x28, 0x0a, 0x04, 0x10, 0xaa, 0x2a, 0x55, 0x55, 0x20, 0x02, + 0x41, 0x41, 0x20, 0x02, 0x41, 0x41, 0xa0, 0x02, 0x01, 0x40, 0x20, 0x02, + 0x01, 0x40, 0x20, 0x02, 0x15, 0x54}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/find.xbm swftools-0.9.1/lib/pdf/xpdf/find.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/find.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/find.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define find_width 15 +#define find_height 15 +static unsigned char find_bits[] = { + 0x38, 0x0e, 0x28, 0x0a, 0x2e, 0x3a, 0xfe, 0x3f, 0x7f, 0x7f, 0x61, 0x43, + 0x61, 0x43, 0x61, 0x43, 0x61, 0x43, 0xe1, 0x43, 0x21, 0x42, 0x21, 0x42, + 0x21, 0x42, 0x21, 0x42, 0x3f, 0x7e}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FixedPoint.cc swftools-0.9.1/lib/pdf/xpdf/FixedPoint.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/FixedPoint.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FixedPoint.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,118 @@ +//======================================================================== +// +// FixedPoint.cc +// +// Fixed point type, with C++ operators. +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#if USE_FIXEDPOINT + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "FixedPoint.h" + +#define ln2 ((FixedPoint)0.69314718) + +FixedPoint FixedPoint::sqrt(FixedPoint x) { + FixedPoint y0, y1, z; + + if (x.val <= 0) { + y1.val = 0; + } else { + y1.val = x.val == 1 ? 2 : x.val >> 1; + do { + y0.val = y1.val; + z = x / y0; + y1.val = (y0.val + z.val) >> 1; + } while (::abs(y0.val - y1.val) > 1); + } + return y1; +} + +FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) { + FixedPoint t, t2, lnx0, lnx, z0, z; + int d, n, i; + + if (y.val <= 0) { + z.val = 0; + } else { + // y * ln(x) + t = (x - 1) / (x + 1); + t2 = t * t; + d = 1; + lnx = 0; + do { + lnx0 = lnx; + lnx += t / d; + t *= t2; + d += 2; + } while (::abs(lnx.val - lnx0.val) > 2); + lnx.val <<= 1; + t = y * lnx; + // exp(y * ln(x)) + n = floor(t / ln2); + t -= ln2 * n; + t2 = t; + d = 1; + i = 1; + z = 1; + do { + z0 = z; + z += t2 / d; + t2 *= t; + ++i; + d *= i; + } while (::abs(z.val - z0.val) > 2 && d < (1 << fixptShift)); + if (n >= 0) { + z.val <<= n; + } else if (n < 0) { + z.val >>= -n; + } + } + return z; +} + +int FixedPoint::mul(int x, int y) { +#if 1 //~tmp + return ((FixPtInt64)x * y) >> fixptShift; +#else + int ah0, ah, bh, al, bl; + ah0 = x & fixptMaskH; + ah = x >> fixptShift; + al = x - ah0; + bh = y >> fixptShift; + bl = y - (bh << fixptShift); + return ah0 * bh + ah * bl + al * bh + ((al * bl) >> fixptShift); +#endif +} + +int FixedPoint::div(int x, int y) { +#if 1 //~tmp + return ((FixPtInt64)x << fixptShift) / y; +#else +#endif +} + +GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) { +#if 1 //~tmp + FixPtInt64 z; + + z = ((FixPtInt64)x.val << fixptShift) / y.val; + if ((z == 0 && x != 0) || + z >= ((FixPtInt64)1 << 31) || z < -((FixPtInt64)1 << 31)) { + return gFalse; + } + result->val = z; + return gTrue; +#else +#endif +} + +#endif // USE_FIXEDPOINT diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FixedPoint.h swftools-0.9.1/lib/pdf/xpdf/FixedPoint.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/FixedPoint.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FixedPoint.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,155 @@ +//======================================================================== +// +// FixedPoint.h +// +// Fixed point type, with C++ operators. +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FIXEDPOINT_H +#define FIXEDPOINT_H + +#include + +#if USE_FIXEDPOINT + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include +#include "gtypes.h" + +#define fixptShift 16 +#define fixptMaskL ((1 << fixptShift) - 1) +#define fixptMaskH (~fixptMaskL) + +typedef long long FixPtInt64; + +class FixedPoint { +public: + + FixedPoint() { val = 0; } + FixedPoint(const FixedPoint &x) { val = x.val; } + FixedPoint(double x) { val = (int)(x * (1 << fixptShift) + 0.5); } + FixedPoint(int x) { val = x << fixptShift; } + FixedPoint(long x) { val = x << fixptShift; } + + operator float() + { return (float) val * ((float)1 / (float)(1 << fixptShift)); } + operator double() + { return (double) val * (1.0 / (double)(1 << fixptShift)); } + operator int() + { return val >> fixptShift; } + + int getRaw() { return val; } + + FixedPoint operator =(FixedPoint x) { val = x.val; return *this; } + + int operator ==(FixedPoint x) { return val == x.val; } + int operator ==(double x) { return *this == (FixedPoint)x; } + int operator ==(int x) { return *this == (FixedPoint)x; } + int operator ==(long x) { return *this == (FixedPoint)x; } + + int operator !=(FixedPoint x) { return val != x.val; } + int operator !=(double x) { return *this != (FixedPoint)x; } + int operator !=(int x) { return *this != (FixedPoint)x; } + int operator !=(long x) { return *this != (FixedPoint)x; } + + int operator <(FixedPoint x) { return val < x.val; } + int operator <(double x) { return *this < (FixedPoint)x; } + int operator <(int x) { return *this < (FixedPoint)x; } + int operator <(long x) { return *this < (FixedPoint)x; } + + int operator <=(FixedPoint x) { return val <= x.val; } + int operator <=(double x) { return *this <= (FixedPoint)x; } + int operator <=(int x) { return *this <= (FixedPoint)x; } + int operator <=(long x) { return *this <= (FixedPoint)x; } + + int operator >(FixedPoint x) { return val > x.val; } + int operator >(double x) { return *this > (FixedPoint)x; } + int operator >(int x) { return *this > (FixedPoint)x; } + int operator >(long x) { return *this > (FixedPoint)x; } + + int operator >=(FixedPoint x) { return val >= x.val; } + int operator >=(double x) { return *this >= (FixedPoint)x; } + int operator >=(int x) { return *this >= (FixedPoint)x; } + int operator >=(long x) { return *this >= (FixedPoint)x; } + + FixedPoint operator -() { return make(-val); } + + FixedPoint operator +(FixedPoint x) { return make(val + x.val); } + FixedPoint operator +(double x) { return *this + (FixedPoint)x; } + FixedPoint operator +(int x) { return *this + (FixedPoint)x; } + FixedPoint operator +(long x) { return *this + (FixedPoint)x; } + + FixedPoint operator +=(FixedPoint x) { val = val + x.val; return *this; } + FixedPoint operator +=(double x) { return *this += (FixedPoint)x; } + FixedPoint operator +=(int x) { return *this += (FixedPoint)x; } + FixedPoint operator +=(long x) { return *this += (FixedPoint)x; } + + FixedPoint operator -(FixedPoint x) { return make(val - x.val); } + FixedPoint operator -(double x) { return *this - (FixedPoint)x; } + FixedPoint operator -(int x) { return *this - (FixedPoint)x; } + FixedPoint operator -(long x) { return *this - (FixedPoint)x; } + + FixedPoint operator -=(FixedPoint x) { val = val - x.val; return *this; } + FixedPoint operator -=(double x) { return *this -= (FixedPoint)x; } + FixedPoint operator -=(int x) { return *this -= (FixedPoint)x; } + FixedPoint operator -=(long x) { return *this -= (FixedPoint)x; } + + FixedPoint operator *(FixedPoint x) { return make(mul(val, x.val)); } + FixedPoint operator *(double x) { return *this * (FixedPoint)x; } + FixedPoint operator *(int x) { return *this * (FixedPoint)x; } + FixedPoint operator *(long x) { return *this * (FixedPoint)x; } + + FixedPoint operator *=(FixedPoint x) { val = mul(val, x.val); return *this; } + FixedPoint operator *=(double x) { return *this *= (FixedPoint)x; } + FixedPoint operator *=(int x) { return *this *= (FixedPoint)x; } + FixedPoint operator *=(long x) { return *this *= (FixedPoint)x; } + + FixedPoint operator /(FixedPoint x) { return make(div(val, x.val)); } + FixedPoint operator /(double x) { return *this / (FixedPoint)x; } + FixedPoint operator /(int x) { return *this / (FixedPoint)x; } + FixedPoint operator /(long x) { return *this / (FixedPoint)x; } + + FixedPoint operator /=(FixedPoint x) { val = div(val, x.val); return *this; } + FixedPoint operator /=(double x) { return *this /= (FixedPoint)x; } + FixedPoint operator /=(int x) { return *this /= (FixedPoint)x; } + FixedPoint operator /=(long x) { return *this /= (FixedPoint)x; } + + static FixedPoint abs(FixedPoint x) { return make(::abs(x.val)); } + + static int floor(FixedPoint x) { return x.val >> fixptShift; } + + static int ceil(FixedPoint x) + { return (x.val & fixptMaskL) ? ((x.val >> fixptShift) + 1) + : (x.val >> fixptShift); } + + static int round(FixedPoint x) + { return (x.val + (1 << (fixptShift - 1))) >> fixptShift; } + + static FixedPoint sqrt(FixedPoint x); + + static FixedPoint pow(FixedPoint x, FixedPoint y); + + // Compute *result = x/y; return false if there is an underflow or + // overflow. + static GBool divCheck(FixedPoint x, FixedPoint y, FixedPoint *result); + +private: + + static FixedPoint make(int valA) { FixedPoint x; x.val = valA; return x; } + + static int mul(int x, int y); + static int div(int x, int y); + + int val; // 16.16 fixed point +}; + +#endif // USE_FIXEDPOINT + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiBase.cc swftools-0.9.1/lib/pdf/xpdf/FoFiBase.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiBase.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FoFiBase.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,156 @@ +//======================================================================== +// +// FoFiBase.cc +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "FoFiBase.h" + +//------------------------------------------------------------------------ +// FoFiBase +//------------------------------------------------------------------------ + +FoFiBase::FoFiBase(char *fileA, int lenA, GBool freeFileDataA) { + fileData = file = (Guchar *)fileA; + len = lenA; + freeFileData = freeFileDataA; +} + +FoFiBase::~FoFiBase() { + if (freeFileData) { + gfree(fileData); + } +} + +char *FoFiBase::readFile(char *fileName, int *fileLen) { + FILE *f; + char *buf; + int n; + + if (!(f = fopen(fileName, "rb"))) { + return NULL; + } + fseek(f, 0, SEEK_END); + n = (int)ftell(f); + fseek(f, 0, SEEK_SET); + buf = (char *)gmalloc(n); + if ((int)fread(buf, 1, n, f) != n) { + gfree(buf); + fclose(f); + return NULL; + } + fclose(f); + *fileLen = n; + return buf; +} + +int FoFiBase::getS8(int pos, GBool *ok) { + int x; + + if (pos < 0 || pos >= len) { + *ok = gFalse; + return 0; + } + x = file[pos]; + if (x & 0x80) { + x |= ~0xff; + } + return x; +} + +int FoFiBase::getU8(int pos, GBool *ok) { + if (pos < 0 || pos >= len) { + *ok = gFalse; + return 0; + } + return file[pos]; +} + +int FoFiBase::getS16BE(int pos, GBool *ok) { + int x; + + if (pos < 0 || pos+1 >= len) { + *ok = gFalse; + return 0; + } + x = file[pos]; + x = (x << 8) + file[pos+1]; + if (x & 0x8000) { + x |= ~0xffff; + } + return x; +} + +int FoFiBase::getU16BE(int pos, GBool *ok) { + int x; + + if (pos < 0 || pos+1 >= len) { + *ok = gFalse; + return 0; + } + x = file[pos]; + x = (x << 8) + file[pos+1]; + return x; +} + +int FoFiBase::getS32BE(int pos, GBool *ok) { + int x; + + if (pos < 0 || pos+3 >= len) { + *ok = gFalse; + return 0; + } + x = file[pos]; + x = (x << 8) + file[pos+1]; + x = (x << 8) + file[pos+2]; + x = (x << 8) + file[pos+3]; + if (x & 0x80000000) { + x |= ~0xffffffff; + } + return x; +} + +Guint FoFiBase::getU32BE(int pos, GBool *ok) { + Guint x; + + if (pos < 0 || pos+3 >= len) { + *ok = gFalse; + return 0; + } + x = file[pos]; + x = (x << 8) + file[pos+1]; + x = (x << 8) + file[pos+2]; + x = (x << 8) + file[pos+3]; + return x; +} + +Guint FoFiBase::getUVarBE(int pos, int size, GBool *ok) { + Guint x; + int i; + + if (pos < 0 || pos + size > len) { + *ok = gFalse; + return 0; + } + x = 0; + for (i = 0; i < size; ++i) { + x = (x << 8) + file[pos + i]; + } + return x; +} + +GBool FoFiBase::checkRegion(int pos, int size) { + return pos >= 0 && + pos + size >= pos && + pos + size <= len; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiBase.h swftools-0.9.1/lib/pdf/xpdf/FoFiBase.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiBase.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FoFiBase.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,57 @@ +//======================================================================== +// +// FoFiBase.h +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FOFIBASE_H +#define FOFIBASE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +//------------------------------------------------------------------------ + +typedef void (*FoFiOutputFunc)(void *stream, char *data, int len); + +//------------------------------------------------------------------------ +// FoFiBase +//------------------------------------------------------------------------ + +class FoFiBase { +public: + + virtual ~FoFiBase(); + +protected: + + FoFiBase(char *fileA, int lenA, GBool freeFileDataA); + static char *readFile(char *fileName, int *fileLen); + + // S = signed / U = unsigned + // 8/16/32/Var = word length, in bytes + // BE = big endian + int getS8(int pos, GBool *ok); + int getU8(int pos, GBool *ok); + int getS16BE(int pos, GBool *ok); + int getU16BE(int pos, GBool *ok); + int getS32BE(int pos, GBool *ok); + Guint getU32BE(int pos, GBool *ok); + Guint getUVarBE(int pos, int size, GBool *ok); + + GBool checkRegion(int pos, int size); + + Guchar *fileData; + Guchar *file; + int len; + GBool freeFileData; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiEncodings.cc swftools-0.9.1/lib/pdf/xpdf/FoFiEncodings.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiEncodings.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FoFiEncodings.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,994 @@ +//======================================================================== +// +// FoFiEncodings.cc +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "FoFiEncodings.h" + +//------------------------------------------------------------------------ +// Type 1 and 1C font data +//------------------------------------------------------------------------ + +char *fofiType1StandardEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + NULL, + "endash", + "dagger", + "daggerdbl", + "periodcentered", + NULL, + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + NULL, + "questiondown", + NULL, + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + NULL, + "ring", + "cedilla", + NULL, + "hungarumlaut", + "ogonek", + "caron", + "emdash", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "AE", + NULL, + "ordfeminine", + NULL, + NULL, + NULL, + NULL, + "Lslash", + "Oslash", + "OE", + "ordmasculine", + NULL, + NULL, + NULL, + NULL, + NULL, + "ae", + NULL, + NULL, + NULL, + "dotlessi", + NULL, + NULL, + "lslash", + "oslash", + "oe", + "germandbls", + NULL, + NULL, + NULL, + NULL +}; + +char *fofiType1ExpertEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclamsmall", + "Hungarumlautsmall", + NULL, + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "comma", + "hyphen", + "period", + "fraction", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "colon", + "semicolon", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + NULL, + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + NULL, + NULL, + NULL, + "isuperior", + NULL, + NULL, + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + NULL, + NULL, + "rsuperior", + "ssuperior", + "tsuperior", + NULL, + "ff", + "fi", + "fl", + "ffi", + "ffl", + "parenleftinferior", + NULL, + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + NULL, + NULL, + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + NULL, + "Dotaccentsmall", + NULL, + NULL, + "Macronsmall", + NULL, + NULL, + "figuredash", + "hypheninferior", + NULL, + NULL, + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + NULL, + NULL, + NULL, + "onequarter", + "onehalf", + "threequarters", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + NULL, + NULL, + "zerosuperior", + "onesuperior", + "twosuperior", + "threesuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall" +}; + +//------------------------------------------------------------------------ +// Type 1C font data +//------------------------------------------------------------------------ + +char *fofiType1CStdStrings[391] = { + ".notdef", + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + "endash", + "dagger", + "daggerdbl", + "periodcentered", + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + "questiondown", + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + "ring", + "cedilla", + "hungarumlaut", + "ogonek", + "caron", + "emdash", + "AE", + "ordfeminine", + "Lslash", + "Oslash", + "OE", + "ordmasculine", + "ae", + "dotlessi", + "lslash", + "oslash", + "oe", + "germandbls", + "onesuperior", + "logicalnot", + "mu", + "trademark", + "Eth", + "onehalf", + "plusminus", + "Thorn", + "onequarter", + "divide", + "brokenbar", + "degree", + "thorn", + "threequarters", + "twosuperior", + "registered", + "minus", + "eth", + "multiply", + "threesuperior", + "copyright", + "Aacute", + "Acircumflex", + "Adieresis", + "Agrave", + "Aring", + "Atilde", + "Ccedilla", + "Eacute", + "Ecircumflex", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Ntilde", + "Oacute", + "Ocircumflex", + "Odieresis", + "Ograve", + "Otilde", + "Scaron", + "Uacute", + "Ucircumflex", + "Udieresis", + "Ugrave", + "Yacute", + "Ydieresis", + "Zcaron", + "aacute", + "acircumflex", + "adieresis", + "agrave", + "aring", + "atilde", + "ccedilla", + "eacute", + "ecircumflex", + "edieresis", + "egrave", + "iacute", + "icircumflex", + "idieresis", + "igrave", + "ntilde", + "oacute", + "ocircumflex", + "odieresis", + "ograve", + "otilde", + "scaron", + "uacute", + "ucircumflex", + "udieresis", + "ugrave", + "yacute", + "ydieresis", + "zcaron", + "exclamsmall", + "Hungarumlautsmall", + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + "isuperior", + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + "rsuperior", + "ssuperior", + "tsuperior", + "ff", + "ffi", + "ffl", + "parenleftinferior", + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + "Dotaccentsmall", + "Macronsmall", + "figuredash", + "hypheninferior", + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + "zerosuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall", + "001.000", + "001.001", + "001.002", + "001.003", + "Black", + "Bold", + "Book", + "Light", + "Medium", + "Regular", + "Roman", + "Semibold" +}; + +Gushort fofiType1CISOAdobeCharset[229] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228 +}; + +Gushort fofiType1CExpertCharset[166] = { + 0, 1, 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 13, 14, 15, 99, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, + 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, + 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378 +}; + +Gushort fofiType1CExpertSubsetCharset[87] = { + 0, 1, 231, 232, 235, 236, 237, 238, 13, 14, + 15, 99, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 109, 110, 267, 268, 269, 270, 272, 300, 301, + 302, 305, 314, 315, 158, 155, 163, 320, 321, 322, + 323, 324, 325, 326, 150, 164, 169, 327, 328, 329, + 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346 +}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiEncodings.h swftools-0.9.1/lib/pdf/xpdf/FoFiEncodings.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiEncodings.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FoFiEncodings.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,36 @@ +//======================================================================== +// +// FoFiEncodings.h +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FOFIENCODINGS_H +#define FOFIENCODINGS_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +//------------------------------------------------------------------------ +// Type 1 and 1C font data +//------------------------------------------------------------------------ + +extern char *fofiType1StandardEncoding[256]; +extern char *fofiType1ExpertEncoding[256]; + +//------------------------------------------------------------------------ +// Type 1C font data +//------------------------------------------------------------------------ + +extern char *fofiType1CStdStrings[391]; +extern Gushort fofiType1CISOAdobeCharset[229]; +extern Gushort fofiType1CExpertCharset[166]; +extern Gushort fofiType1CExpertSubsetCharset[87]; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiTrueType.cc swftools-0.9.1/lib/pdf/xpdf/FoFiTrueType.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiTrueType.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FoFiTrueType.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,2031 @@ +//======================================================================== +// +// FoFiTrueType.cc +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gtypes.h" +#include "gmem.h" +#include "GString.h" +#include "GHash.h" +#include "FoFiType1C.h" +#include "FoFiTrueType.h" + +// +// Terminology +// ----------- +// +// character code = number used as an element of a text string +// +// character name = glyph name = name for a particular glyph within a +// font +// +// glyph index = GID = position (within some internal table in the font) +// where the instructions to draw a particular glyph are +// stored +// +// Type 1 fonts +// ------------ +// +// Type 1 fonts contain: +// +// Encoding: array of glyph names, maps char codes to glyph names +// +// Encoding[charCode] = charName +// +// CharStrings: dictionary of instructions, keyed by character names, +// maps character name to glyph data +// +// CharStrings[charName] = glyphData +// +// TrueType fonts +// -------------- +// +// TrueType fonts contain: +// +// 'cmap' table: mapping from character code to glyph index; there may +// be multiple cmaps in a TrueType font +// +// cmap[charCode] = gid +// +// 'post' table: mapping from glyph index to glyph name +// +// post[gid] = glyphName +// +// Type 42 fonts +// ------------- +// +// Type 42 fonts contain: +// +// Encoding: array of glyph names, maps char codes to glyph names +// +// Encoding[charCode] = charName +// +// CharStrings: dictionary of glyph indexes, keyed by character names, +// maps character name to glyph index +// +// CharStrings[charName] = gid +// + +//------------------------------------------------------------------------ + +#define ttcfTag 0x74746366 + +//------------------------------------------------------------------------ + +struct TrueTypeTable { + Guint tag; + Guint checksum; + int offset; + int origOffset; + int len; +}; + +struct TrueTypeCmap { + int platform; + int encoding; + int offset; + int len; + int fmt; +}; + +struct TrueTypeLoca { + int idx; + int origOffset; + int newOffset; + int len; +}; + +#define cmapTag 0x636d6170 +#define glyfTag 0x676c7966 +#define headTag 0x68656164 +#define hheaTag 0x68686561 +#define hmtxTag 0x686d7478 +#define locaTag 0x6c6f6361 +#define nameTag 0x6e616d65 +#define os2Tag 0x4f532f32 +#define postTag 0x706f7374 + +static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) { + TrueTypeLoca *loca1 = (TrueTypeLoca *)p1; + TrueTypeLoca *loca2 = (TrueTypeLoca *)p2; + + if (loca1->origOffset == loca2->origOffset) { + return loca1->idx - loca2->idx; + } + return loca1->origOffset - loca2->origOffset; +} + +static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) { + TrueTypeLoca *loca1 = (TrueTypeLoca *)p1; + TrueTypeLoca *loca2 = (TrueTypeLoca *)p2; + + return loca1->idx - loca2->idx; +} + +static int cmpTrueTypeTableTag(const void *p1, const void *p2) { + TrueTypeTable *tab1 = (TrueTypeTable *)p1; + TrueTypeTable *tab2 = (TrueTypeTable *)p2; + + return (int)tab1->tag - (int)tab2->tag; +} + +//------------------------------------------------------------------------ + +struct T42Table { + char *tag; // 4-byte tag + GBool required; // required by the TrueType spec? +}; + +// TrueType tables to be embedded in Type 42 fonts. +// NB: the table names must be in alphabetical order here. +#define nT42Tables 11 +static T42Table t42Tables[nT42Tables] = { + { "cvt ", gTrue }, + { "fpgm", gTrue }, + { "glyf", gTrue }, + { "head", gTrue }, + { "hhea", gTrue }, + { "hmtx", gTrue }, + { "loca", gTrue }, + { "maxp", gTrue }, + { "prep", gTrue }, + { "vhea", gFalse }, + { "vmtx", gFalse } +}; +#define t42HeadTable 3 +#define t42LocaTable 6 +#define t42GlyfTable 2 +#define t42VheaTable 9 +#define t42VmtxTable 10 + +//------------------------------------------------------------------------ + +// Glyph names in some arbitrary standard order that Apple uses for +// their TrueType fonts. +static char *macGlyphNames[258] = { + ".notdef", "null", "CR", "space", + "exclam", "quotedbl", "numbersign", "dollar", + "percent", "ampersand", "quotesingle", "parenleft", + "parenright", "asterisk", "plus", "comma", + "hyphen", "period", "slash", "zero", + "one", "two", "three", "four", + "five", "six", "seven", "eight", + "nine", "colon", "semicolon", "less", + "equal", "greater", "question", "at", + "A", "B", "C", "D", + "E", "F", "G", "H", + "I", "J", "K", "L", + "M", "N", "O", "P", + "Q", "R", "S", "T", + "U", "V", "W", "X", + "Y", "Z", "bracketleft", "backslash", + "bracketright", "asciicircum", "underscore", "grave", + "a", "b", "c", "d", + "e", "f", "g", "h", + "i", "j", "k", "l", + "m", "n", "o", "p", + "q", "r", "s", "t", + "u", "v", "w", "x", + "y", "z", "braceleft", "bar", + "braceright", "asciitilde", "Adieresis", "Aring", + "Ccedilla", "Eacute", "Ntilde", "Odieresis", + "Udieresis", "aacute", "agrave", "acircumflex", + "adieresis", "atilde", "aring", "ccedilla", + "eacute", "egrave", "ecircumflex", "edieresis", + "iacute", "igrave", "icircumflex", "idieresis", + "ntilde", "oacute", "ograve", "ocircumflex", + "odieresis", "otilde", "uacute", "ugrave", + "ucircumflex", "udieresis", "dagger", "degree", + "cent", "sterling", "section", "bullet", + "paragraph", "germandbls", "registered", "copyright", + "trademark", "acute", "dieresis", "notequal", + "AE", "Oslash", "infinity", "plusminus", + "lessequal", "greaterequal", "yen", "mu1", + "partialdiff", "summation", "product", "pi", + "integral", "ordfeminine", "ordmasculine", "Ohm", + "ae", "oslash", "questiondown", "exclamdown", + "logicalnot", "radical", "florin", "approxequal", + "increment", "guillemotleft", "guillemotright", "ellipsis", + "nbspace", "Agrave", "Atilde", "Otilde", + "OE", "oe", "endash", "emdash", + "quotedblleft", "quotedblright", "quoteleft", "quoteright", + "divide", "lozenge", "ydieresis", "Ydieresis", + "fraction", "currency", "guilsinglleft", "guilsinglright", + "fi", "fl", "daggerdbl", "periodcentered", + "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", + "Ecircumflex", "Aacute", "Edieresis", "Egrave", + "Iacute", "Icircumflex", "Idieresis", "Igrave", + "Oacute", "Ocircumflex", "applelogo", "Ograve", + "Uacute", "Ucircumflex", "Ugrave", "dotlessi", + "circumflex", "tilde", "overscore", "breve", + "dotaccent", "ring", "cedilla", "hungarumlaut", + "ogonek", "caron", "Lslash", "lslash", + "Scaron", "scaron", "Zcaron", "zcaron", + "brokenbar", "Eth", "eth", "Yacute", + "yacute", "Thorn", "thorn", "minus", + "multiply", "onesuperior", "twosuperior", "threesuperior", + "onehalf", "onequarter", "threequarters", "franc", + "Gbreve", "gbreve", "Idot", "Scedilla", + "scedilla", "Cacute", "cacute", "Ccaron", + "ccaron", "dmacron" +}; + +//------------------------------------------------------------------------ +// FoFiTrueType +//------------------------------------------------------------------------ + +FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA) { + FoFiTrueType *ff; + + ff = new FoFiTrueType(fileA, lenA, gFalse); + if (!ff->parsedOk) { + delete ff; + return NULL; + } + return ff; +} + +FoFiTrueType *FoFiTrueType::load(char *fileName) { + FoFiTrueType *ff; + char *fileA; + int lenA; + + if (!(fileA = FoFiBase::readFile(fileName, &lenA))) { + return NULL; + } + ff = new FoFiTrueType(fileA, lenA, gTrue); + if (!ff->parsedOk) { + delete ff; + return NULL; + } + return ff; +} + +FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA): + FoFiBase(fileA, lenA, freeFileDataA) +{ + tables = NULL; + nTables = 0; + cmaps = NULL; + nCmaps = 0; + nameToGID = NULL; + parsedOk = gFalse; + + parse(); +} + +FoFiTrueType::~FoFiTrueType() { + gfree(tables); + gfree(cmaps); + if (nameToGID) { + delete nameToGID; + } +} + +int FoFiTrueType::getNumCmaps() { + return nCmaps; +} + +int FoFiTrueType::getCmapPlatform(int i) { + return cmaps[i].platform; +} + +int FoFiTrueType::getCmapEncoding(int i) { + return cmaps[i].encoding; +} + +int FoFiTrueType::findCmap(int platform, int encoding) { + int i; + + for (i = 0; i < nCmaps; ++i) { + if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) { + return i; + } + } + return -1; +} + +Gushort FoFiTrueType::mapCodeToGID(int i, int c) { + Gushort gid; + int segCnt, segEnd, segStart, segDelta, segOffset; + int cmapFirst, cmapLen; + int pos, a, b, m; + GBool ok; + + if (i < 0 || i >= nCmaps) { + return 0; + } + ok = gTrue; + pos = cmaps[i].offset; + switch (cmaps[i].fmt) { + case 0: + if (c < 0 || c >= cmaps[i].len - 6) { + return 0; + } + gid = getU8(cmaps[i].offset + 6 + c, &ok); + break; + case 4: + segCnt = getU16BE(pos + 6, &ok) / 2; + a = -1; + b = segCnt - 1; + segEnd = getU16BE(pos + 14 + 2*b, &ok); + if (c > segEnd) { + // malformed font -- the TrueType spec requires the last segEnd + // to be 0xffff + return 0; + } + // invariant: seg[a].end < code <= seg[b].end + while (b - a > 1 && ok) { + m = (a + b) / 2; + segEnd = getU16BE(pos + 14 + 2*m, &ok); + if (segEnd < c) { + a = m; + } else { + b = m; + } + } + segStart = getU16BE(pos + 16 + 2*segCnt + 2*b, &ok); + segDelta = getU16BE(pos + 16 + 4*segCnt + 2*b, &ok); + segOffset = getU16BE(pos + 16 + 6*segCnt + 2*b, &ok); + if (c < segStart) { + return 0; + } + if (segOffset == 0) { + gid = (c + segDelta) & 0xffff; + } else { + gid = getU16BE(pos + 16 + 6*segCnt + 2*b + + segOffset + 2 * (c - segStart), &ok); + if (gid != 0) { + gid = (gid + segDelta) & 0xffff; + } + } + break; + case 6: + cmapFirst = getU16BE(pos + 6, &ok); + cmapLen = getU16BE(pos + 8, &ok); + if (c < cmapFirst || c >= cmapFirst + cmapLen) { + return 0; + } + gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok); + break; + default: + return 0; + } + if (!ok) { + return 0; + } + return gid; +} + +int FoFiTrueType::mapNameToGID(char *name) { + if (!nameToGID) { + return 0; + } + return nameToGID->lookupInt(name); +} + +Gushort *FoFiTrueType::getCIDToGIDMap(int *nCIDs) { + FoFiType1C *ff; + Gushort *map; + int i; + + *nCIDs = 0; + if (!openTypeCFF) { + return NULL; + } + i = seekTable("CFF "); + if (!checkRegion(tables[i].offset, tables[i].len)) { + return NULL; + } + if (!(ff = FoFiType1C::make((char *)file + tables[i].offset, + tables[i].len))) { + return NULL; + } + map = ff->getCIDToGIDMap(nCIDs); + delete ff; + return map; +} + +int FoFiTrueType::getEmbeddingRights() { + int i, fsType; + GBool ok; + + if ((i = seekTable("OS/2")) < 0) { + return 4; + } + ok = gTrue; + fsType = getU16BE(tables[i].offset + 8, &ok); + if (!ok) { + return 4; + } + if (fsType & 0x0008) { + return 2; + } + if (fsType & 0x0004) { + return 1; + } + if (fsType & 0x0002) { + return 0; + } + return 3; +} + +void FoFiTrueType::convertToType42(char *psName, char **encoding, + Gushort *codeToGID, + FoFiOutputFunc outputFunc, + void *outputStream) { + GString *buf; + GBool ok; + + if (openTypeCFF) { + return; + } + + // write the header + ok = gTrue; + buf = GString::format("%!PS-TrueTypeFont-{0:2g}\n", + (double)getS32BE(0, &ok) / 65536.0); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + + // begin the font dictionary + (*outputFunc)(outputStream, "10 dict begin\n", 14); + (*outputFunc)(outputStream, "/FontName /", 11); + (*outputFunc)(outputStream, psName, strlen(psName)); + (*outputFunc)(outputStream, " def\n", 5); + (*outputFunc)(outputStream, "/FontType 42 def\n", 17); + (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); + buf = GString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n", + bbox[0], bbox[1], bbox[2], bbox[3]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "/PaintType 0 def\n", 17); + + // write the guts of the dictionary + cvtEncoding(encoding, outputFunc, outputStream); + cvtCharStrings(encoding, codeToGID, outputFunc, outputStream); + cvtSfnts(outputFunc, outputStream, NULL, gFalse); + + // end the dictionary and define the font + (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40); +} + +void FoFiTrueType::convertToType1(char *psName, char **newEncoding, + GBool ascii, FoFiOutputFunc outputFunc, + void *outputStream) { + FoFiType1C *ff; + int i; + + if (!openTypeCFF) { + return; + } + i = seekTable("CFF "); + if (!checkRegion(tables[i].offset, tables[i].len)) { + return; + } + if (!(ff = FoFiType1C::make((char *)file + tables[i].offset, + tables[i].len))) { + return; + } + ff->convertToType1(psName, newEncoding, ascii, outputFunc, outputStream); + delete ff; +} + +void FoFiTrueType::convertToCIDType2(char *psName, + Gushort *cidMap, int nCIDs, + GBool needVerticalMetrics, + FoFiOutputFunc outputFunc, + void *outputStream) { + GString *buf; + Gushort cid; + GBool ok; + int i, j, k; + + if (openTypeCFF) { + return; + } + + // write the header + ok = gTrue; + buf = GString::format("%!PS-TrueTypeFont-{0:2g}\n", + (double)getS32BE(0, &ok) / 65536.0); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + + // begin the font dictionary + (*outputFunc)(outputStream, "20 dict begin\n", 14); + (*outputFunc)(outputStream, "/CIDFontName /", 14); + (*outputFunc)(outputStream, psName, strlen(psName)); + (*outputFunc)(outputStream, " def\n", 5); + (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19); + (*outputFunc)(outputStream, "/FontType 42 def\n", 17); + (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32); + (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24); + (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27); + (*outputFunc)(outputStream, " /Supplement 0 def\n", 20); + (*outputFunc)(outputStream, " end def\n", 10); + (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15); + if (cidMap) { + buf = GString::format("/CIDCount {0:d} def\n", nCIDs); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + if (nCIDs > 32767) { + (*outputFunc)(outputStream, "/CIDMap [", 9); + for (i = 0; i < nCIDs; i += 32768 - 16) { + (*outputFunc)(outputStream, "<\n", 2); + for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) { + (*outputFunc)(outputStream, " ", 2); + for (k = 0; k < 16 && i+j+k < nCIDs; ++k) { + cid = cidMap[i+j+k]; + buf = GString::format("{0:02x}{1:02x}", + (cid >> 8) & 0xff, cid & 0xff); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "\n", 1); + } + (*outputFunc)(outputStream, " >", 3); + } + (*outputFunc)(outputStream, "\n", 1); + (*outputFunc)(outputStream, "] def\n", 6); + } else { + (*outputFunc)(outputStream, "/CIDMap <\n", 10); + for (i = 0; i < nCIDs; i += 16) { + (*outputFunc)(outputStream, " ", 2); + for (j = 0; j < 16 && i+j < nCIDs; ++j) { + cid = cidMap[i+j]; + buf = GString::format("{0:02x}{1:02x}", + (cid >> 8) & 0xff, cid & 0xff); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "\n", 1); + } + (*outputFunc)(outputStream, "> def\n", 6); + } + } else { + // direct mapping - just fill the string(s) with s[i]=i + buf = GString::format("/CIDCount {0:d} def\n", nGlyphs); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + if (nGlyphs > 32767) { + (*outputFunc)(outputStream, "/CIDMap [\n", 10); + for (i = 0; i < nGlyphs; i += 32767) { + j = nGlyphs - i < 32767 ? nGlyphs - i : 32767; + buf = GString::format(" {0:d} string 0 1 {1:d} {{\n", 2 * j, j - 1); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + buf = GString::format(" 2 copy dup 2 mul exch {0:d} add -8 bitshift put\n", + i); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + buf = GString::format(" 1 index exch dup 2 mul 1 add exch {0:d} add" + " 255 and put\n", i); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, " } for\n", 8); + } + (*outputFunc)(outputStream, "] def\n", 6); + } else { + buf = GString::format("/CIDMap {0:d} string\n", 2 * nGlyphs); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + buf = GString::format(" 0 1 {0:d} {{\n", nGlyphs - 1); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, + " 2 copy dup 2 mul exch -8 bitshift put\n", 42); + (*outputFunc)(outputStream, + " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50); + (*outputFunc)(outputStream, " } for\n", 8); + (*outputFunc)(outputStream, "def\n", 4); + } + } + (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); + buf = GString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n", + bbox[0], bbox[1], bbox[2], bbox[3]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "/PaintType 0 def\n", 17); + (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26); + (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30); + (*outputFunc)(outputStream, " /.notdef 0 def\n", 17); + (*outputFunc)(outputStream, " end readonly def\n", 19); + + // write the guts of the dictionary + cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics); + + // end the dictionary and define the font + (*outputFunc)(outputStream, + "CIDFontName currentdict end /CIDFont defineresource pop\n", + 56); +} + +void FoFiTrueType::convertToCIDType0(char *psName, + FoFiOutputFunc outputFunc, + void *outputStream) { + FoFiType1C *ff; + int i; + + if (!openTypeCFF) { + return; + } + i = seekTable("CFF "); + if (!checkRegion(tables[i].offset, tables[i].len)) { + return; + } + if (!(ff = FoFiType1C::make((char *)file + tables[i].offset, + tables[i].len))) { + return; + } + ff->convertToCIDType0(psName, outputFunc, outputStream); + delete ff; +} + +void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs, + GBool needVerticalMetrics, + FoFiOutputFunc outputFunc, + void *outputStream) { + GString *buf; + GString *sfntsName; + int n, i, j; + + if (openTypeCFF) { + return; + } + + // write the Type 42 sfnts array + sfntsName = (new GString(psName))->append("_sfnts"); + cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics); + delete sfntsName; + + // write the descendant Type 42 fonts + n = cidMap ? nCIDs : nGlyphs; + for (i = 0; i < n; i += 256) { + (*outputFunc)(outputStream, "10 dict begin\n", 14); + (*outputFunc)(outputStream, "/FontName /", 11); + (*outputFunc)(outputStream, psName, strlen(psName)); + buf = GString::format("_{0:02x} def\n", i >> 8); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "/FontType 42 def\n", 17); + (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); + buf = GString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n", + bbox[0], bbox[1], bbox[2], bbox[3]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "/PaintType 0 def\n", 17); + (*outputFunc)(outputStream, "/sfnts ", 7); + (*outputFunc)(outputStream, psName, strlen(psName)); + (*outputFunc)(outputStream, "_sfnts def\n", 11); + (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); + for (j = 0; j < 256 && i+j < n; ++j) { + buf = GString::format("dup {0:d} /c{1:02x} put\n", j, j); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "readonly def\n", 13); + (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32); + (*outputFunc)(outputStream, "/.notdef 0 def\n", 15); + for (j = 0; j < 256 && i+j < n; ++j) { + buf = GString::format("/c{0:02x} {1:d} def\n", + j, cidMap ? cidMap[i+j] : i+j); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "end readonly def\n", 17); + (*outputFunc)(outputStream, + "FontName currentdict end definefont pop\n", 40); + } + + // write the Type 0 parent font + (*outputFunc)(outputStream, "16 dict begin\n", 14); + (*outputFunc)(outputStream, "/FontName /", 11); + (*outputFunc)(outputStream, psName, strlen(psName)); + (*outputFunc)(outputStream, " def\n", 5); + (*outputFunc)(outputStream, "/FontType 0 def\n", 16); + (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); + (*outputFunc)(outputStream, "/FMapType 2 def\n", 16); + (*outputFunc)(outputStream, "/Encoding [\n", 12); + for (i = 0; i < n; i += 256) { + buf = GString::format("{0:d}\n", i >> 8); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); + (*outputFunc)(outputStream, "/FDepVector [\n", 14); + for (i = 0; i < n; i += 256) { + (*outputFunc)(outputStream, "/", 1); + (*outputFunc)(outputStream, psName, strlen(psName)); + buf = GString::format("_{0:02x} findfont\n", i >> 8); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); + (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40); +} + +void FoFiTrueType::convertToType0(char *psName, + FoFiOutputFunc outputFunc, + void *outputStream) { + FoFiType1C *ff; + int i; + + if (!openTypeCFF) { + return; + } + i = seekTable("CFF "); + if (!checkRegion(tables[i].offset, tables[i].len)) { + return; + } + if (!(ff = FoFiType1C::make((char *)file + tables[i].offset, + tables[i].len))) { + return; + } + ff->convertToType0(psName, outputFunc, outputStream); + delete ff; +} + +void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, + void *outputStream, char *name, + Gushort *codeToGID) { + // this substitute cmap table maps char codes 0000-ffff directly to + // glyphs 0000-ffff + static char cmapTab[36] = { + 0, 0, // table version number + 0, 1, // number of encoding tables + 0, 1, // platform ID + 0, 0, // encoding ID + 0, 0, 0, 12, // offset of subtable + 0, 4, // subtable format + 0, 24, // subtable length + 0, 0, // subtable version + 0, 2, // segment count * 2 + 0, 2, // 2 * 2 ^ floor(log2(segCount)) + 0, 0, // floor(log2(segCount)) + 0, 0, // 2*segCount - 2*2^floor(log2(segCount)) + (char)0xff, (char)0xff, // endCount[0] + 0, 0, // reserved + 0, 0, // startCount[0] + 0, 0, // idDelta[0] + 0, 0 // pad to a mulitple of four bytes + }; + static char nameTab[8] = { + 0, 0, // format + 0, 0, // number of name records + 0, 6, // offset to start of string storage + 0, 0 // pad to multiple of four bytes + }; + static char postTab[32] = { + 0, 1, 0, 0, // format + 0, 0, 0, 0, // italic angle + 0, 0, // underline position + 0, 0, // underline thickness + 0, 0, 0, 0, // fixed pitch + 0, 0, 0, 0, // min Type 42 memory + 0, 0, 0, 0, // max Type 42 memory + 0, 0, 0, 0, // min Type 1 memory + 0, 0, 0, 0 // max Type 1 memory + }; + static char os2Tab[86] = { + 0, 1, // version + 0, 1, // xAvgCharWidth + 0, 0, // usWeightClass + 0, 0, // usWidthClass + 0, 0, // fsType + 0, 0, // ySubscriptXSize + 0, 0, // ySubscriptYSize + 0, 0, // ySubscriptXOffset + 0, 0, // ySubscriptYOffset + 0, 0, // ySuperscriptXSize + 0, 0, // ySuperscriptYSize + 0, 0, // ySuperscriptXOffset + 0, 0, // ySuperscriptYOffset + 0, 0, // yStrikeoutSize + 0, 0, // yStrikeoutPosition + 0, 0, // sFamilyClass + 0, 0, 0, 0, 0, // panose + 0, 0, 0, 0, 0, + 0, 0, 0, 0, // ulUnicodeRange1 + 0, 0, 0, 0, // ulUnicodeRange2 + 0, 0, 0, 0, // ulUnicodeRange3 + 0, 0, 0, 0, // ulUnicodeRange4 + 0, 0, 0, 0, // achVendID + 0, 0, // fsSelection + 0, 0, // usFirstCharIndex + 0, 0, // usLastCharIndex + 0, 0, // sTypoAscender + 0, 0, // sTypoDescender + 0, 0, // sTypoLineGap + 0, 0, // usWinAscent + 0, 0, // usWinDescent + 0, 0, 0, 0, // ulCodePageRange1 + 0, 0, 0, 0 // ulCodePageRange2 + }; + GBool missingCmap, missingName, missingPost, missingOS2; + GBool unsortedLoca, badCmapLen, abbrevHMTX; + int nZeroLengthTables; + int nHMetrics, advWidth, lsb; + TrueTypeLoca *locaTable; + TrueTypeTable *newTables; + char *newNameTab, *newCmapTab, *newHHEATab, *newHMTXTab; + int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next; + int newHHEALen, newHMTXLen; + Guint locaChecksum, glyfChecksum, fileChecksum; + char *tableDir; + char locaBuf[4], checksumBuf[4]; + GBool ok; + Guint t; + int pos, i, j, k, n; + + if (openTypeCFF) { + return; + } + + // check for missing tables + // (Note: if the OS/2 table is missing, the Microsoft PCL5 driver + // will embed a PCL TrueType font with the pitch field set to zero, + // which apparently causes divide-by-zero errors. As far as I can + // tell, the only important field in the OS/2 table is + // xAvgCharWidth.) + missingCmap = (cmapIdx = seekTable("cmap")) < 0; + missingName = seekTable("name") < 0; + missingPost = seekTable("post") < 0; + missingOS2 = seekTable("OS/2") < 0; + + // read the loca table, check to see if it's sorted + locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca)); + unsortedLoca = gFalse; + i = seekTable("loca"); + pos = tables[i].offset; + ok = gTrue; + for (i = 0; i <= nGlyphs; ++i) { + if (locaFmt) { + locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok); + } else { + locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok); + } + if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) { + unsortedLoca = gTrue; + } + // glyph descriptions must be at least 12 bytes long (nContours, + // xMin, yMin, xMax, yMax, instructionLength - two bytes each); + // invalid glyph descriptions (even if they're never used) make + // Windows choke, so we work around that problem here (ideally, + // this would parse the glyph descriptions in the glyf table and + // remove any that were invalid, but this quick test is a decent + // start) + if (i > 0 && + locaTable[i].origOffset - locaTable[i-1].origOffset > 0 && + locaTable[i].origOffset - locaTable[i-1].origOffset < 12) { + locaTable[i-1].origOffset = locaTable[i].origOffset; + unsortedLoca = gTrue; + } + locaTable[i].idx = i; + } + + // check for zero-length tables + nZeroLengthTables = 0; + for (i = 0; i < nTables; ++i) { + if (tables[i].len == 0) { + ++nZeroLengthTables; + } + } + + // check for an incorrect cmap table length + badCmapLen = gFalse; + cmapLen = 0; // make gcc happy + if (!missingCmap) { + cmapLen = cmaps[0].offset + cmaps[0].len; + for (i = 1; i < nCmaps; ++i) { + if (cmaps[i].offset + cmaps[i].len > cmapLen) { + cmapLen = cmaps[i].offset + cmaps[i].len; + } + } + cmapLen -= tables[cmapIdx].offset; + if (cmapLen > tables[cmapIdx].len) { + badCmapLen = gTrue; + } + } + + // check for an abbreviated hmtx table (this is completely legal, + // but confuses the Microsoft PCL5 printer driver, which generates + // embedded fonts with the pitch field set to zero) + i = seekTable("hhea"); + nHMetrics = getU16BE(tables[i].offset + 34, &ok); + abbrevHMTX = nHMetrics < nGlyphs; + + // if nothing is broken, just write the TTF file as is + if (!missingCmap && !missingName && !missingPost && !missingOS2 && + !unsortedLoca && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 && + !name && !codeToGID) { + (*outputFunc)(outputStream, (char *)file, len); + goto done1; + } + + // sort the 'loca' table: some (non-compliant) fonts have + // out-of-order loca tables; in order to correctly handle the case + // where (compliant) fonts have empty entries in the middle of the + // table, cmpTrueTypeLocaOffset uses offset as its primary sort key, + // and idx as its secondary key (ensuring that adjacent entries with + // the same pos value remain in the same order) + glyfLen = 0; // make gcc happy + if (unsortedLoca) { + qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), + &cmpTrueTypeLocaOffset); + for (i = 0; i < nGlyphs; ++i) { + locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset; + } + locaTable[nGlyphs].len = 0; + qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), + &cmpTrueTypeLocaIdx); + pos = 0; + for (i = 0; i <= nGlyphs; ++i) { + locaTable[i].newOffset = pos; + pos += locaTable[i].len; + if (pos & 3) { + pos += 4 - (pos & 3); + } + } + glyfLen = pos; + } + + // compute checksums for the loca and glyf tables + locaChecksum = glyfChecksum = 0; + if (unsortedLoca) { + if (locaFmt) { + for (j = 0; j <= nGlyphs; ++j) { + locaChecksum += locaTable[j].newOffset; + } + } else { + for (j = 0; j <= nGlyphs; j += 2) { + locaChecksum += locaTable[j].newOffset << 16; + if (j + 1 <= nGlyphs) { + locaChecksum += locaTable[j+1].newOffset; + } + } + } + pos = tables[seekTable("glyf")].offset; + for (j = 0; j < nGlyphs; ++j) { + n = locaTable[j].len; + if (n > 0) { + k = locaTable[j].origOffset; + if (checkRegion(pos + k, n)) { + glyfChecksum += computeTableChecksum(file + pos + k, n); + } + } + } + } + + // construct the new name table + if (name) { + n = strlen(name); + newNameLen = (6 + 4*12 + 2 * (3*n + 7) + 3) & ~3; + newNameTab = (char *)gmalloc(newNameLen); + memset(newNameTab, 0, newNameLen); + newNameTab[0] = 0; // format selector + newNameTab[1] = 0; + newNameTab[2] = 0; // number of name records + newNameTab[3] = 4; + newNameTab[4] = 0; // offset to start of string storage + newNameTab[5] = 6 + 4*12; + next = 0; + for (i = 0; i < 4; ++i) { + newNameTab[6 + i*12 + 0] = 0; // platform ID = Microsoft + newNameTab[6 + i*12 + 1] = 3; + newNameTab[6 + i*12 + 2] = 0; // encoding ID = Unicode + newNameTab[6 + i*12 + 3] = 1; + newNameTab[6 + i*12 + 4] = 0x04; // language ID = American English + newNameTab[6 + i*12 + 5] = 0x09; + newNameTab[6 + i*12 + 6] = 0; // name ID + newNameTab[6 + i*12 + 7] = i + 1; + newNameTab[6 + i*12 + 8] = i+1 == 2 ? 0 : ((2*n) >> 8); // string length + newNameTab[6 + i*12 + 9] = i+1 == 2 ? 14 : ((2*n) & 0xff); + newNameTab[6 + i*12 + 10] = next >> 8; // string offset + newNameTab[6 + i*12 + 11] = next & 0xff; + if (i+1 == 2) { + memcpy(newNameTab + 6 + 4*12 + next, "\0R\0e\0g\0u\0l\0a\0r", 14); + next += 14; + } else { + for (j = 0; j < n; ++j) { + newNameTab[6 + 4*12 + next + 2*j] = 0; + newNameTab[6 + 4*12 + next + 2*j + 1] = name[j]; + } + next += 2*n; + } + } + } else { + newNameLen = 0; + newNameTab = NULL; + } + + // construct the new cmap table + if (codeToGID) { + newCmapLen = 44 + 256 * 2; + newCmapTab = (char *)gmalloc(newCmapLen); + newCmapTab[0] = 0; // table version number = 0 + newCmapTab[1] = 0; + newCmapTab[2] = 0; // number of encoding tables = 1 + newCmapTab[3] = 1; + newCmapTab[4] = 0; // platform ID = Microsoft + newCmapTab[5] = 3; + newCmapTab[6] = 0; // encoding ID = Unicode + newCmapTab[7] = 1; + newCmapTab[8] = 0; // offset of subtable + newCmapTab[9] = 0; + newCmapTab[10] = 0; + newCmapTab[11] = 12; + newCmapTab[12] = 0; // subtable format = 4 + newCmapTab[13] = 4; + newCmapTab[14] = 0x02; // subtable length + newCmapTab[15] = 0x20; + newCmapTab[16] = 0; // subtable version = 0 + newCmapTab[17] = 0; + newCmapTab[18] = 0; // segment count * 2 + newCmapTab[19] = 4; + newCmapTab[20] = 0; // 2 * 2 ^ floor(log2(segCount)) + newCmapTab[21] = 4; + newCmapTab[22] = 0; // floor(log2(segCount)) + newCmapTab[23] = 1; + newCmapTab[24] = 0; // 2*segCount - 2*2^floor(log2(segCount)) + newCmapTab[25] = 0; + newCmapTab[26] = 0x00; // endCount[0] + newCmapTab[27] = (char)0xff; + newCmapTab[28] = (char)0xff; // endCount[1] + newCmapTab[29] = (char)0xff; + newCmapTab[30] = 0; // reserved + newCmapTab[31] = 0; + newCmapTab[32] = 0x00; // startCount[0] + newCmapTab[33] = 0x00; + newCmapTab[34] = (char)0xff; // startCount[1] + newCmapTab[35] = (char)0xff; + newCmapTab[36] = 0; // idDelta[0] + newCmapTab[37] = 0; + newCmapTab[38] = 0; // idDelta[1] + newCmapTab[39] = 1; + newCmapTab[40] = 0; // idRangeOffset[0] + newCmapTab[41] = 4; + newCmapTab[42] = 0; // idRangeOffset[1] + newCmapTab[43] = 0; + for (i = 0; i < 256; ++i) { + newCmapTab[44 + 2*i] = codeToGID[i] >> 8; + newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff; + } + } else { + newCmapLen = 0; + newCmapTab = NULL; + } + + // generate the new hmtx table and the updated hhea table + if (abbrevHMTX) { + i = seekTable("hhea"); + pos = tables[i].offset; + newHHEALen = 36; + newHHEATab = (char *)gmalloc(newHHEALen); + for (i = 0; i < newHHEALen; ++i) { + newHHEATab[i] = getU8(pos++, &ok); + } + newHHEATab[34] = nGlyphs >> 8; + newHHEATab[35] = nGlyphs & 0xff; + i = seekTable("hmtx"); + pos = tables[i].offset; + newHMTXLen = 4 * nGlyphs; + newHMTXTab = (char *)gmalloc(newHMTXLen); + advWidth = 0; + for (i = 0; i < nHMetrics; ++i) { + advWidth = getU16BE(pos, &ok); + lsb = getU16BE(pos + 2, &ok); + pos += 4; + newHMTXTab[4*i ] = advWidth >> 8; + newHMTXTab[4*i + 1] = advWidth & 0xff; + newHMTXTab[4*i + 2] = lsb >> 8; + newHMTXTab[4*i + 3] = lsb & 0xff; + } + for (; i < nGlyphs; ++i) { + lsb = getU16BE(pos, &ok); + pos += 2; + newHMTXTab[4*i ] = advWidth >> 8; + newHMTXTab[4*i + 1] = advWidth & 0xff; + newHMTXTab[4*i + 2] = lsb >> 8; + newHMTXTab[4*i + 3] = lsb & 0xff; + } + } else { + newHHEATab = newHMTXTab = NULL; + newHHEALen = newHMTXLen = 0; // make gcc happy + } + + // construct the new table directory: + // - keep all original tables with non-zero length + // - fix the cmap table's length, if necessary + // - add missing tables + // - sort the table by tag + // - compute new table positions, including 4-byte alignment + // - (re)compute table checksums + nNewTables = nTables - nZeroLengthTables + + (missingCmap ? 1 : 0) + (missingName ? 1 : 0) + + (missingPost ? 1 : 0) + (missingOS2 ? 1 : 0); + newTables = (TrueTypeTable *)gmallocn(nNewTables, sizeof(TrueTypeTable)); + j = 0; + for (i = 0; i < nTables; ++i) { + if (tables[i].len > 0) { + newTables[j] = tables[i]; + newTables[j].origOffset = tables[i].offset; + if (checkRegion(tables[i].offset, newTables[i].len)) { + newTables[j].checksum = + computeTableChecksum(file + tables[i].offset, tables[i].len); + if (tables[i].tag == headTag) { + // don't include the file checksum + newTables[j].checksum -= getU32BE(tables[i].offset + 8, &ok); + } + } + if (newTables[j].tag == cmapTag && codeToGID) { + newTables[j].len = newCmapLen; + newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab, + newCmapLen); + } else if (newTables[j].tag == cmapTag && badCmapLen) { + newTables[j].len = cmapLen; + } else if (newTables[j].tag == locaTag && unsortedLoca) { + newTables[j].len = (nGlyphs + 1) * (locaFmt ? 4 : 2); + newTables[j].checksum = locaChecksum; + } else if (newTables[j].tag == glyfTag && unsortedLoca) { + newTables[j].len = glyfLen; + newTables[j].checksum = glyfChecksum; + } else if (newTables[j].tag == nameTag && name) { + newTables[j].len = newNameLen; + newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab, + newNameLen); + } else if (newTables[j].tag == hheaTag && abbrevHMTX) { + newTables[j].len = newHHEALen; + newTables[j].checksum = computeTableChecksum((Guchar *)newHHEATab, + newHHEALen); + } else if (newTables[j].tag == hmtxTag && abbrevHMTX) { + newTables[j].len = newHMTXLen; + newTables[j].checksum = computeTableChecksum((Guchar *)newHMTXTab, + newHMTXLen); + } + ++j; + } + } + if (missingCmap) { + newTables[j].tag = cmapTag; + if (codeToGID) { + newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab, + newCmapLen); + newTables[j].len = newCmapLen; + } else { + newTables[j].checksum = computeTableChecksum((Guchar *)cmapTab, + sizeof(cmapTab)); + newTables[j].len = sizeof(cmapTab); + } + ++j; + } + if (missingName) { + newTables[j].tag = nameTag; + if (name) { + newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab, + newNameLen); + newTables[j].len = newNameLen; + } else { + newTables[j].checksum = computeTableChecksum((Guchar *)nameTab, + sizeof(nameTab)); + newTables[j].len = sizeof(nameTab); + } + ++j; + } + if (missingPost) { + newTables[j].tag = postTag; + newTables[j].checksum = computeTableChecksum((Guchar *)postTab, + sizeof(postTab)); + newTables[j].len = sizeof(postTab); + ++j; + } + if (missingOS2) { + newTables[j].tag = os2Tag; + newTables[j].checksum = computeTableChecksum((Guchar *)os2Tab, + sizeof(os2Tab)); + newTables[j].len = sizeof(os2Tab); + ++j; + } + qsort(newTables, nNewTables, sizeof(TrueTypeTable), + &cmpTrueTypeTableTag); + pos = 12 + nNewTables * 16; + for (i = 0; i < nNewTables; ++i) { + newTables[i].offset = pos; + pos += newTables[i].len; + if (pos & 3) { + pos += 4 - (pos & 3); + } + } + + // write the table directory + tableDir = (char *)gmalloc(12 + nNewTables * 16); + tableDir[0] = 0x00; // sfnt version + tableDir[1] = 0x01; + tableDir[2] = 0x00; + tableDir[3] = 0x00; + tableDir[4] = (char)((nNewTables >> 8) & 0xff); // numTables + tableDir[5] = (char)(nNewTables & 0xff); + for (i = -1, t = (Guint)nNewTables; t; ++i, t >>= 1) ; + t = 1 << (4 + i); + tableDir[6] = (char)((t >> 8) & 0xff); // searchRange + tableDir[7] = (char)(t & 0xff); + tableDir[8] = (char)((i >> 8) & 0xff); // entrySelector + tableDir[9] = (char)(i & 0xff); + t = nNewTables * 16 - t; + tableDir[10] = (char)((t >> 8) & 0xff); // rangeShift + tableDir[11] = (char)(t & 0xff); + pos = 12; + for (i = 0; i < nNewTables; ++i) { + tableDir[pos ] = (char)(newTables[i].tag >> 24); + tableDir[pos+ 1] = (char)(newTables[i].tag >> 16); + tableDir[pos+ 2] = (char)(newTables[i].tag >> 8); + tableDir[pos+ 3] = (char) newTables[i].tag; + tableDir[pos+ 4] = (char)(newTables[i].checksum >> 24); + tableDir[pos+ 5] = (char)(newTables[i].checksum >> 16); + tableDir[pos+ 6] = (char)(newTables[i].checksum >> 8); + tableDir[pos+ 7] = (char) newTables[i].checksum; + tableDir[pos+ 8] = (char)(newTables[i].offset >> 24); + tableDir[pos+ 9] = (char)(newTables[i].offset >> 16); + tableDir[pos+10] = (char)(newTables[i].offset >> 8); + tableDir[pos+11] = (char) newTables[i].offset; + tableDir[pos+12] = (char)(newTables[i].len >> 24); + tableDir[pos+13] = (char)(newTables[i].len >> 16); + tableDir[pos+14] = (char)(newTables[i].len >> 8); + tableDir[pos+15] = (char) newTables[i].len; + pos += 16; + } + (*outputFunc)(outputStream, tableDir, 12 + nNewTables * 16); + + // compute the file checksum + fileChecksum = computeTableChecksum((Guchar *)tableDir, + 12 + nNewTables * 16); + for (i = 0; i < nNewTables; ++i) { + fileChecksum += newTables[i].checksum; + } + fileChecksum = 0xb1b0afba - fileChecksum; + + // write the tables + for (i = 0; i < nNewTables; ++i) { + if (newTables[i].tag == headTag) { + if (checkRegion(newTables[i].origOffset, newTables[i].len)) { + (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset, 8); + checksumBuf[0] = fileChecksum >> 24; + checksumBuf[1] = fileChecksum >> 16; + checksumBuf[2] = fileChecksum >> 8; + checksumBuf[3] = fileChecksum; + (*outputFunc)(outputStream, checksumBuf, 4); + (*outputFunc)(outputStream, + (char *)file + newTables[i].origOffset + 12, + newTables[i].len - 12); + } else { + for (j = 0; j < newTables[i].len; ++j) { + (*outputFunc)(outputStream, "\0", 1); + } + } + } else if (newTables[i].tag == cmapTag && codeToGID) { + (*outputFunc)(outputStream, newCmapTab, newTables[i].len); + } else if (newTables[i].tag == cmapTag && missingCmap) { + (*outputFunc)(outputStream, cmapTab, newTables[i].len); + } else if (newTables[i].tag == nameTag && name) { + (*outputFunc)(outputStream, newNameTab, newTables[i].len); + } else if (newTables[i].tag == nameTag && missingName) { + (*outputFunc)(outputStream, nameTab, newTables[i].len); + } else if (newTables[i].tag == postTag && missingPost) { + (*outputFunc)(outputStream, postTab, newTables[i].len); + } else if (newTables[i].tag == os2Tag && missingOS2) { + (*outputFunc)(outputStream, os2Tab, newTables[i].len); + } else if (newTables[i].tag == hheaTag && abbrevHMTX) { + (*outputFunc)(outputStream, newHHEATab, newTables[i].len); + } else if (newTables[i].tag == hmtxTag && abbrevHMTX) { + (*outputFunc)(outputStream, newHMTXTab, newTables[i].len); + } else if (newTables[i].tag == locaTag && unsortedLoca) { + for (j = 0; j <= nGlyphs; ++j) { + if (locaFmt) { + locaBuf[0] = (char)(locaTable[j].newOffset >> 24); + locaBuf[1] = (char)(locaTable[j].newOffset >> 16); + locaBuf[2] = (char)(locaTable[j].newOffset >> 8); + locaBuf[3] = (char) locaTable[j].newOffset; + (*outputFunc)(outputStream, locaBuf, 4); + } else { + locaBuf[0] = (char)(locaTable[j].newOffset >> 9); + locaBuf[1] = (char)(locaTable[j].newOffset >> 1); + (*outputFunc)(outputStream, locaBuf, 2); + } + } + } else if (newTables[i].tag == glyfTag && unsortedLoca) { + pos = tables[seekTable("glyf")].offset; + for (j = 0; j < nGlyphs; ++j) { + n = locaTable[j].len; + if (n > 0) { + k = locaTable[j].origOffset; + if (checkRegion(pos + k, n)) { + (*outputFunc)(outputStream, (char *)file + pos + k, n); + } else { + for (k = 0; k < n; ++k) { + (*outputFunc)(outputStream, "\0", 1); + } + } + if ((k = locaTable[j].len & 3)) { + (*outputFunc)(outputStream, "\0\0\0\0", 4 - k); + } + } + } + } else { + if (checkRegion(newTables[i].origOffset, newTables[i].len)) { + (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset, + newTables[i].len); + } else { + for (j = 0; j < newTables[i].len; ++j) { + (*outputFunc)(outputStream, "\0", 1); + } + } + } + if (newTables[i].len & 3) { + (*outputFunc)(outputStream, "\0\0\0", 4 - (newTables[i].len & 3)); + } + } + + gfree(newHMTXTab); + gfree(newHHEATab); + gfree(newCmapTab); + gfree(newNameTab); + gfree(tableDir); + gfree(newTables); + done1: + gfree(locaTable); +} + +void FoFiTrueType::cvtEncoding(char **encoding, + FoFiOutputFunc outputFunc, + void *outputStream) { + char *name; + GString *buf; + int i; + + (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); + if (encoding) { + for (i = 0; i < 256; ++i) { + if (!(name = encoding[i])) { + name = ".notdef"; + } + buf = GString::format("dup {0:d} /", i); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, name, strlen(name)); + (*outputFunc)(outputStream, " put\n", 5); + } + } else { + for (i = 0; i < 256; ++i) { + buf = GString::format("dup {0:d} /c{1:02x} put\n", i, i); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + } + (*outputFunc)(outputStream, "readonly def\n", 13); +} + +void FoFiTrueType::cvtCharStrings(char **encoding, + Gushort *codeToGID, + FoFiOutputFunc outputFunc, + void *outputStream) { + char *name; + GString *buf; + char buf2[16]; + int i, k; + + // always define '.notdef' + (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32); + (*outputFunc)(outputStream, "/.notdef 0 def\n", 15); + + // if there's no 'cmap' table, punt + if (nCmaps == 0) { + goto err; + } + + // map char name to glyph index: + // 1. use encoding to map name to char code + // 2. use codeToGID to map char code to glyph index + // N.B. We do this in reverse order because font subsets can have + // weird encodings that use the same character name twice, and + // the first definition is probably the one we want. + k = 0; // make gcc happy + for (i = 255; i >= 0; --i) { + if (encoding) { + name = encoding[i]; + } else { + sprintf(buf2, "c%02x", i); + name = buf2; + } + if (name && strcmp(name, ".notdef")) { + k = codeToGID[i]; + // note: Distiller (maybe Adobe's PS interpreter in general) + // doesn't like TrueType fonts that have CharStrings entries + // which point to nonexistent glyphs, hence the (k < nGlyphs) + // test + if (k > 0 && k < nGlyphs) { + (*outputFunc)(outputStream, "/", 1); + (*outputFunc)(outputStream, name, strlen(name)); + buf = GString::format(" {0:d} def\n", k); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + } + } + + err: + (*outputFunc)(outputStream, "end readonly def\n", 17); +} + +void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, + void *outputStream, GString *name, + GBool needVerticalMetrics) { + Guchar headData[54]; + TrueTypeLoca *locaTable; + Guchar *locaData; + TrueTypeTable newTables[nT42Tables]; + Guchar tableDir[12 + nT42Tables*16]; + GBool ok; + Guint checksum; + int nNewTables; + int length, pos, glyfPos, i, j, k; + Guchar vheaTab[36] = { + 0, 1, 0, 0, // table version number + 0, 0, // ascent + 0, 0, // descent + 0, 0, // reserved + 0, 0, // max advance height + 0, 0, // min top side bearing + 0, 0, // min bottom side bearing + 0, 0, // y max extent + 0, 0, // caret slope rise + 0, 1, // caret slope run + 0, 0, // caret offset + 0, 0, // reserved + 0, 0, // reserved + 0, 0, // reserved + 0, 0, // reserved + 0, 0, // metric data format + 0, 1 // number of advance heights in vmtx table + }; + Guchar *vmtxTab; + GBool needVhea, needVmtx; + int advance; + + // construct the 'head' table, zero out the font checksum + i = seekTable("head"); + pos = tables[i].offset; + if (!checkRegion(pos, 54)) { + return; + } + memcpy(headData, file + pos, 54); + headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0; + + // read the original 'loca' table, pad entries out to 4 bytes, and + // sort it into proper order -- some (non-compliant) fonts have + // out-of-order loca tables; in order to correctly handle the case + // where (compliant) fonts have empty entries in the middle of the + // table, cmpTrueTypeLocaPos uses offset as its primary sort key, + // and idx as its secondary key (ensuring that adjacent entries with + // the same pos value remain in the same order) + locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca)); + i = seekTable("loca"); + pos = tables[i].offset; + ok = gTrue; + for (i = 0; i <= nGlyphs; ++i) { + locaTable[i].idx = i; + if (locaFmt) { + locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok); + } else { + locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok); + } + } + qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), + &cmpTrueTypeLocaOffset); + for (i = 0; i < nGlyphs; ++i) { + locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset; + } + locaTable[nGlyphs].len = 0; + qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), + &cmpTrueTypeLocaIdx); + pos = 0; + for (i = 0; i <= nGlyphs; ++i) { + locaTable[i].newOffset = pos; + pos += locaTable[i].len; + if (pos & 3) { + pos += 4 - (pos & 3); + } + } + + // construct the new 'loca' table + locaData = (Guchar *)gmallocn(nGlyphs + 1, (locaFmt ? 4 : 2)); + for (i = 0; i <= nGlyphs; ++i) { + pos = locaTable[i].newOffset; + if (locaFmt) { + locaData[4*i ] = (Guchar)(pos >> 24); + locaData[4*i+1] = (Guchar)(pos >> 16); + locaData[4*i+2] = (Guchar)(pos >> 8); + locaData[4*i+3] = (Guchar) pos; + } else { + locaData[2*i ] = (Guchar)(pos >> 9); + locaData[2*i+1] = (Guchar)(pos >> 1); + } + } + + // count the number of tables + nNewTables = 0; + for (i = 0; i < nT42Tables; ++i) { + if (t42Tables[i].required || + seekTable(t42Tables[i].tag) >= 0) { + ++nNewTables; + } + } + vmtxTab = NULL; // make gcc happy + advance = 0; // make gcc happy + if (needVerticalMetrics) { + needVhea = seekTable("vhea") < 0; + needVmtx = seekTable("vmtx") < 0; + if (needVhea || needVmtx) { + i = seekTable("head"); + advance = getU16BE(tables[i].offset + 18, &ok); // units per em + if (needVhea) { + ++nNewTables; + } + if (needVmtx) { + ++nNewTables; + } + } + } + + // construct the new table headers, including table checksums + // (pad each table out to a multiple of 4 bytes) + pos = 12 + nNewTables*16; + k = 0; + for (i = 0; i < nT42Tables; ++i) { + length = -1; + checksum = 0; // make gcc happy + if (i == t42HeadTable) { + length = 54; + checksum = computeTableChecksum(headData, 54); + } else if (i == t42LocaTable) { + length = (nGlyphs + 1) * (locaFmt ? 4 : 2); + checksum = computeTableChecksum(locaData, length); + } else if (i == t42GlyfTable) { + length = 0; + checksum = 0; + glyfPos = tables[seekTable("glyf")].offset; + for (j = 0; j < nGlyphs; ++j) { + length += locaTable[j].len; + if (length & 3) { + length += 4 - (length & 3); + } + if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) { + checksum += + computeTableChecksum(file + glyfPos + locaTable[j].origOffset, + locaTable[j].len); + } + } + } else { + if ((j = seekTable(t42Tables[i].tag)) >= 0) { + length = tables[j].len; + if (checkRegion(tables[j].offset, length)) { + checksum = computeTableChecksum(file + tables[j].offset, length); + } + } else if (needVerticalMetrics && i == t42VheaTable) { + vheaTab[10] = advance / 256; // max advance height + vheaTab[11] = advance % 256; + length = sizeof(vheaTab); + checksum = computeTableChecksum(vheaTab, length); + } else if (needVerticalMetrics && i == t42VmtxTable) { + length = 4 + (nGlyphs - 1) * 4; + vmtxTab = (Guchar *)gmalloc(length); + vmtxTab[0] = advance / 256; + vmtxTab[1] = advance % 256; + for (j = 2; j < length; j += 2) { + vmtxTab[j] = 0; + vmtxTab[j+1] = 0; + } + checksum = computeTableChecksum(vmtxTab, length); + } else if (t42Tables[i].required) { + //~ error(-1, "Embedded TrueType font is missing a required table ('%s')", + //~ t42Tables[i].tag); + length = 0; + checksum = 0; + } + } + if (length >= 0) { + newTables[k].tag = ((t42Tables[i].tag[0] & 0xff) << 24) | + ((t42Tables[i].tag[1] & 0xff) << 16) | + ((t42Tables[i].tag[2] & 0xff) << 8) | + (t42Tables[i].tag[3] & 0xff); + newTables[k].checksum = checksum; + newTables[k].offset = pos; + newTables[k].len = length; + pos += length; + if (pos & 3) { + pos += 4 - (length & 3); + } + ++k; + } + } + + // construct the table directory + tableDir[0] = 0x00; // sfnt version + tableDir[1] = 0x01; + tableDir[2] = 0x00; + tableDir[3] = 0x00; + tableDir[4] = 0; // numTables + tableDir[5] = nNewTables; + tableDir[6] = 0; // searchRange + tableDir[7] = (Guchar)128; + tableDir[8] = 0; // entrySelector + tableDir[9] = 3; + tableDir[10] = 0; // rangeShift + tableDir[11] = (Guchar)(16 * nNewTables - 128); + pos = 12; + for (i = 0; i < nNewTables; ++i) { + tableDir[pos ] = (Guchar)(newTables[i].tag >> 24); + tableDir[pos+ 1] = (Guchar)(newTables[i].tag >> 16); + tableDir[pos+ 2] = (Guchar)(newTables[i].tag >> 8); + tableDir[pos+ 3] = (Guchar) newTables[i].tag; + tableDir[pos+ 4] = (Guchar)(newTables[i].checksum >> 24); + tableDir[pos+ 5] = (Guchar)(newTables[i].checksum >> 16); + tableDir[pos+ 6] = (Guchar)(newTables[i].checksum >> 8); + tableDir[pos+ 7] = (Guchar) newTables[i].checksum; + tableDir[pos+ 8] = (Guchar)(newTables[i].offset >> 24); + tableDir[pos+ 9] = (Guchar)(newTables[i].offset >> 16); + tableDir[pos+10] = (Guchar)(newTables[i].offset >> 8); + tableDir[pos+11] = (Guchar) newTables[i].offset; + tableDir[pos+12] = (Guchar)(newTables[i].len >> 24); + tableDir[pos+13] = (Guchar)(newTables[i].len >> 16); + tableDir[pos+14] = (Guchar)(newTables[i].len >> 8); + tableDir[pos+15] = (Guchar) newTables[i].len; + pos += 16; + } + + // compute the font checksum and store it in the head table + checksum = computeTableChecksum(tableDir, 12 + nNewTables*16); + for (i = 0; i < nNewTables; ++i) { + checksum += newTables[i].checksum; + } + checksum = 0xb1b0afba - checksum; // because the TrueType spec says so + headData[ 8] = (Guchar)(checksum >> 24); + headData[ 9] = (Guchar)(checksum >> 16); + headData[10] = (Guchar)(checksum >> 8); + headData[11] = (Guchar) checksum; + + // start the sfnts array + if (name) { + (*outputFunc)(outputStream, "/", 1); + (*outputFunc)(outputStream, name->getCString(), name->getLength()); + (*outputFunc)(outputStream, " [\n", 3); + } else { + (*outputFunc)(outputStream, "/sfnts [\n", 9); + } + + // write the table directory + dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream); + + // write the tables + for (i = 0; i < nNewTables; ++i) { + if (i == t42HeadTable) { + dumpString(headData, 54, outputFunc, outputStream); + } else if (i == t42LocaTable) { + length = (nGlyphs + 1) * (locaFmt ? 4 : 2); + dumpString(locaData, length, outputFunc, outputStream); + } else if (i == t42GlyfTable) { + glyfPos = tables[seekTable("glyf")].offset; + for (j = 0; j < nGlyphs; ++j) { + if (locaTable[j].len > 0 && + checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) { + dumpString(file + glyfPos + locaTable[j].origOffset, + locaTable[j].len, outputFunc, outputStream); + } + } + } else { + // length == 0 means the table is missing and the error was + // already reported during the construction of the table + // headers + if ((length = newTables[i].len) > 0) { + if ((j = seekTable(t42Tables[i].tag)) >= 0 && + checkRegion(tables[j].offset, tables[j].len)) { + dumpString(file + tables[j].offset, tables[j].len, + outputFunc, outputStream); + } else if (needVerticalMetrics && i == t42VheaTable) { + dumpString(vheaTab, length, outputFunc, outputStream); + } else if (needVerticalMetrics && i == t42VmtxTable) { + dumpString(vmtxTab, length, outputFunc, outputStream); + gfree(vmtxTab); + } + } + } + } + + // end the sfnts array + (*outputFunc)(outputStream, "] def\n", 6); + + gfree(locaData); + gfree(locaTable); +} + +void FoFiTrueType::dumpString(Guchar *s, int length, + FoFiOutputFunc outputFunc, + void *outputStream) { + GString *buf; + int pad, i, j; + + (*outputFunc)(outputStream, "<", 1); + for (i = 0; i < length; i += 32) { + for (j = 0; j < 32 && i+j < length; ++j) { + buf = GString::format("{0:02x}", s[i+j] & 0xff); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + if (i % (65536 - 32) == 65536 - 64) { + (*outputFunc)(outputStream, ">\n<", 3); + } else if (i+32 < length) { + (*outputFunc)(outputStream, "\n", 1); + } + } + if (length & 3) { + pad = 4 - (length & 3); + for (i = 0; i < pad; ++i) { + (*outputFunc)(outputStream, "00", 2); + } + } + // add an extra zero byte because the Adobe Type 42 spec says so + (*outputFunc)(outputStream, "00>\n", 4); +} + +Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) { + Guint checksum, word; + int i; + + checksum = 0; + for (i = 0; i+3 < length; i += 4) { + word = ((data[i ] & 0xff) << 24) + + ((data[i+1] & 0xff) << 16) + + ((data[i+2] & 0xff) << 8) + + (data[i+3] & 0xff); + checksum += word; + } + if (length & 3) { + word = 0; + i = length & ~3; + switch (length & 3) { + case 3: + word |= (data[i+2] & 0xff) << 8; + case 2: + word |= (data[i+1] & 0xff) << 16; + case 1: + word |= (data[i ] & 0xff) << 24; + break; + } + checksum += word; + } + return checksum; +} + +void FoFiTrueType::parse() { + Guint topTag; + int pos, ver, i, j; + + parsedOk = gTrue; + + // look for a collection (TTC) + topTag = getU32BE(0, &parsedOk); + if (!parsedOk) { + return; + } + if (topTag == ttcfTag) { + pos = getU32BE(12, &parsedOk); + if (!parsedOk) { + return; + } + } else { + pos = 0; + } + + // check the sfnt version + ver = getU32BE(pos, &parsedOk); + if (!parsedOk) { + return; + } + openTypeCFF = ver == 0x4f54544f; // 'OTTO' + + // read the table directory + nTables = getU16BE(pos + 4, &parsedOk); + if (!parsedOk) { + return; + } + tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable)); + pos += 12; + for (i = 0; i < nTables; ++i) { + tables[i].tag = getU32BE(pos, &parsedOk); + tables[i].checksum = getU32BE(pos + 4, &parsedOk); + tables[i].offset = (int)getU32BE(pos + 8, &parsedOk); + tables[i].len = (int)getU32BE(pos + 12, &parsedOk); + if (tables[i].offset + tables[i].len < tables[i].offset || + tables[i].offset + tables[i].len > len) { + parsedOk = gFalse; + } + pos += 16; + } + if (!parsedOk) { + return; + } + + // check for tables that are required by both the TrueType spec and + // the Type 42 spec + if (seekTable("head") < 0 || + seekTable("hhea") < 0 || + seekTable("maxp") < 0 || + seekTable("hmtx") < 0 || + (!openTypeCFF && seekTable("loca") < 0) || + (!openTypeCFF && seekTable("glyf") < 0) || + (openTypeCFF && seekTable("CFF ") < 0)) { + parsedOk = gFalse; + return; + } + + // read the cmaps + if ((i = seekTable("cmap")) >= 0) { + pos = tables[i].offset + 2; + nCmaps = getU16BE(pos, &parsedOk); + pos += 2; + if (!parsedOk) { + return; + } + cmaps = (TrueTypeCmap *)gmallocn(nCmaps, sizeof(TrueTypeCmap)); + for (j = 0; j < nCmaps; ++j) { + cmaps[j].platform = getU16BE(pos, &parsedOk); + cmaps[j].encoding = getU16BE(pos + 2, &parsedOk); + cmaps[j].offset = tables[i].offset + getU32BE(pos + 4, &parsedOk); + pos += 8; + cmaps[j].fmt = getU16BE(cmaps[j].offset, &parsedOk); + cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk); + } + if (!parsedOk) { + return; + } + } else { + nCmaps = 0; + } + + // get the number of glyphs from the maxp table + i = seekTable("maxp"); + nGlyphs = getU16BE(tables[i].offset + 4, &parsedOk); + if (!parsedOk) { + return; + } + + // get the bbox and loca table format from the head table + i = seekTable("head"); + bbox[0] = getS16BE(tables[i].offset + 36, &parsedOk); + bbox[1] = getS16BE(tables[i].offset + 38, &parsedOk); + bbox[2] = getS16BE(tables[i].offset + 40, &parsedOk); + bbox[3] = getS16BE(tables[i].offset + 42, &parsedOk); + locaFmt = getS16BE(tables[i].offset + 50, &parsedOk); + if (!parsedOk) { + return; + } + + // make sure the loca table is sane (correct length and entries are + // in bounds) + if (!openTypeCFF) { + i = seekTable("loca"); + if (tables[i].len < 0) { + parsedOk = gFalse; + return; + } + if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) { + nGlyphs = tables[i].len / (locaFmt ? 4 : 2) - 1; + } + for (j = 0; j <= nGlyphs; ++j) { + if (locaFmt) { + pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk); + } else { + pos = getU16BE(tables[i].offset + j*2, &parsedOk); + } + if(pos > len) { + nGlyphs = j; + break; + } + if (pos < 0) { + parsedOk = gFalse; + } + } + if (!parsedOk) { + return; + } + } + + // read the post table + readPostTable(); +} + +void FoFiTrueType::readPostTable() { + GString *name; + int tablePos, postFmt, stringIdx, stringPos; + GBool ok; + int i, j, n, m; + + ok = gTrue; + if ((i = seekTable("post")) < 0) { + return; + } + tablePos = tables[i].offset; + postFmt = getU32BE(tablePos, &ok); + if (!ok) { + goto err; + } + if (postFmt == 0x00010000) { + nameToGID = new GHash(gTrue); + for (i = 0; i < 258; ++i) { + nameToGID->add(new GString(macGlyphNames[i]), i); + } + } else if (postFmt == 0x00020000) { + nameToGID = new GHash(gTrue); + n = getU16BE(tablePos + 32, &ok); + if (!ok) { + goto err; + } + if (n > nGlyphs) { + n = nGlyphs; + } + stringIdx = 0; + stringPos = tablePos + 34 + 2*n; + for (i = 0; i < n; ++i) { + j = getU16BE(tablePos + 34 + 2*i, &ok); + if (j < 258) { + nameToGID->removeInt(macGlyphNames[j]); + nameToGID->add(new GString(macGlyphNames[j]), i); + } else { + j -= 258; + if (j != stringIdx) { + for (stringIdx = 0, stringPos = tablePos + 34 + 2*n; + stringIdx < j; + ++stringIdx, stringPos += 1 + getU8(stringPos, &ok)) ; + if (!ok) { + goto err; + } + } + m = getU8(stringPos, &ok); + if (!ok || !checkRegion(stringPos + 1, m)) { + goto err; + } + name = new GString((char *)&file[stringPos + 1], m); + nameToGID->removeInt(name); + nameToGID->add(name, i); + ++stringIdx; + stringPos += 1 + m; + } + } + } else if (postFmt == 0x00028000) { + nameToGID = new GHash(gTrue); + for (i = 0; i < nGlyphs; ++i) { + j = getU8(tablePos + 32 + i, &ok); + if (!ok) { + goto err; + } + if (j < 258) { + nameToGID->removeInt(macGlyphNames[j]); + nameToGID->add(new GString(macGlyphNames[j]), i); + } + } + } + + return; + + err: + if (nameToGID) { + delete nameToGID; + nameToGID = NULL; + } +} + +int FoFiTrueType::seekTable(char *tag) { + Guint tagI; + int i; + + tagI = ((tag[0] & 0xff) << 24) | + ((tag[1] & 0xff) << 16) | + ((tag[2] & 0xff) << 8) | + (tag[3] & 0xff); + for (i = 0; i < nTables; ++i) { + if (tables[i].tag == tagI) { + return i; + } + } + return -1; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiTrueType.h swftools-0.9.1/lib/pdf/xpdf/FoFiTrueType.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiTrueType.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FoFiTrueType.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,174 @@ +//======================================================================== +// +// FoFiTrueType.h +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FOFITRUETYPE_H +#define FOFITRUETYPE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "FoFiBase.h" + +class GString; +class GHash; +struct TrueTypeTable; +struct TrueTypeCmap; + +//------------------------------------------------------------------------ +// FoFiTrueType +//------------------------------------------------------------------------ + +class FoFiTrueType: public FoFiBase { +public: + + // Create a FoFiTrueType object from a memory buffer. + static FoFiTrueType *make(char *fileA, int lenA); + + // Create a FoFiTrueType object from a file on disk. + static FoFiTrueType *load(char *fileName); + + virtual ~FoFiTrueType(); + + // Returns true if this an OpenType font containing CFF data, false + // if it's a TrueType font (or OpenType font with TrueType data). + GBool isOpenTypeCFF() { return openTypeCFF; } + + // Return the number of cmaps defined by this font. + int getNumCmaps(); + + // Return the platform ID of the th cmap. + int getCmapPlatform(int i); + + // Return the encoding ID of the th cmap. + int getCmapEncoding(int i); + + // Return the index of the cmap for , . Returns + // -1 if there is no corresponding cmap. + int findCmap(int platform, int encoding); + + // Return the GID corresponding to according to the th cmap. + Gushort mapCodeToGID(int i, int c); + + // Returns the GID corresponding to according to the post + // table. Returns 0 if there is no mapping for or if the + // font does not have a post table. + int mapNameToGID(char *name); + + // Return the mapping from CIDs to GIDs, and return the number of + // CIDs in *. This is only useful for CID fonts. (Only + // useful for OpenType CFF fonts.) + Gushort *getCIDToGIDMap(int *nCIDs); + + // Returns the least restrictive embedding licensing right (as + // defined by the TrueType spec): + // * 4: OS/2 table is missing or invalid + // * 3: installable embedding + // * 2: editable embedding + // * 1: preview & print embedding + // * 0: restricted license embedding + int getEmbeddingRights(); + + // Convert to a Type 42 font, suitable for embedding in a PostScript + // file. will be used as the PostScript font name (so we + // don't need to depend on the 'name' table in the font). The + // array specifies the mapping from char codes to names. + // If is NULL, the encoding is unknown or undefined. The + // array specifies the mapping from char codes to GIDs. + // (Not useful for OpenType CFF fonts.) + void convertToType42(char *psName, char **encoding, + Gushort *codeToGID, + FoFiOutputFunc outputFunc, void *outputStream); + + // Convert to a Type 1 font, suitable for embedding in a PostScript + // file. This is only useful with 8-bit fonts. If is + // not NULL, it will be used in place of the encoding in the Type 1C + // font. If is true the eexec section will be hex-encoded, + // otherwise it will be left as binary data. If is + // non-NULL, it will be used as the PostScript font name. (Only + // useful for OpenType CFF fonts.) + void convertToType1(char *psName, char **newEncoding, GBool ascii, + FoFiOutputFunc outputFunc, void *outputStream); + + // Convert to a Type 2 CIDFont, suitable for embedding in a + // PostScript file. will be used as the PostScript font + // name (so we don't need to depend on the 'name' table in the + // font). The array maps CIDs to GIDs; it has + // entries. (Not useful for OpenType CFF fonts.) + void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs, + GBool needVerticalMetrics, + FoFiOutputFunc outputFunc, void *outputStream); + + // Convert to a Type 0 CIDFont, suitable for embedding in a + // PostScript file. will be used as the PostScript font + // name. (Only useful for OpenType CFF fonts.) + void convertToCIDType0(char *psName, + FoFiOutputFunc outputFunc, void *outputStream); + + // Convert to a Type 0 (but non-CID) composite font, suitable for + // embedding in a PostScript file. will be used as the + // PostScript font name (so we don't need to depend on the 'name' + // table in the font). The array maps CIDs to GIDs; it has + // entries. (Not useful for OpenType CFF fonts.) + void convertToType0(char *psName, Gushort *cidMap, int nCIDs, + GBool needVerticalMetrics, + FoFiOutputFunc outputFunc, void *outputStream); + + // Convert to a Type 0 (but non-CID) composite font, suitable for + // embedding in a PostScript file. will be used as the + // PostScript font name. (Only useful for OpenType CFF fonts.) + void convertToType0(char *psName, + FoFiOutputFunc outputFunc, void *outputStream); + + // Write a clean TTF file, filling in missing tables and correcting + // various other errors. If is non-NULL, the font is renamed + // to . If is non-NULL, the font is re-encoded, + // using a Windows Unicode cmap. If is NULL and the font is + // complete and correct, it will be written unmodified. (Not useful + // for OpenType CFF fonts.) + void writeTTF(FoFiOutputFunc outputFunc, void *outputStream, + char *name = NULL, Gushort *codeToGID = NULL); + +private: + + FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA); + void cvtEncoding(char **encoding, + FoFiOutputFunc outputFunc, + void *outputStream); + void cvtCharStrings(char **encoding, + Gushort *codeToGID, + FoFiOutputFunc outputFunc, + void *outputStream); + void cvtSfnts(FoFiOutputFunc outputFunc, + void *outputStream, GString *name, + GBool needVerticalMetrics); + void dumpString(Guchar *s, int length, + FoFiOutputFunc outputFunc, + void *outputStream); + Guint computeTableChecksum(Guchar *data, int length); + void parse(); + void readPostTable(); + int seekTable(char *tag); + + TrueTypeTable *tables; + int nTables; + TrueTypeCmap *cmaps; + int nCmaps; + int nGlyphs; + int locaFmt; + int bbox[4]; + GHash *nameToGID; + GBool openTypeCFF; + + GBool parsedOk; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiType1.cc swftools-0.9.1/lib/pdf/xpdf/FoFiType1.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiType1.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FoFiType1.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,252 @@ +//======================================================================== +// +// FoFiType1.cc +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "FoFiEncodings.h" +#include "FoFiType1.h" + +//------------------------------------------------------------------------ +// FoFiType1 +//------------------------------------------------------------------------ + +FoFiType1 *FoFiType1::make(char *fileA, int lenA) { + return new FoFiType1(fileA, lenA, gFalse); +} + +FoFiType1 *FoFiType1::load(char *fileName) { + char *fileA; + int lenA; + + if (!(fileA = FoFiBase::readFile(fileName, &lenA))) { + return NULL; + } + return new FoFiType1(fileA, lenA, gTrue); +} + +FoFiType1::FoFiType1(char *fileA, int lenA, GBool freeFileDataA): + FoFiBase(fileA, lenA, freeFileDataA) +{ + name = NULL; + encoding = NULL; + parsed = gFalse; +} + +FoFiType1::~FoFiType1() { + int i; + + if (name) { + gfree(name); + } + if (encoding && encoding != fofiType1StandardEncoding) { + for (i = 0; i < 256; ++i) { + gfree(encoding[i]); + } + gfree(encoding); + } +} + +char *FoFiType1::getName() { + if (!parsed) { + parse(); + } + return name; +} + +char **FoFiType1::getEncoding() { + if (!parsed) { + parse(); + } + return encoding; +} + +void FoFiType1::writeEncoded(char **newEncoding, + FoFiOutputFunc outputFunc, void *outputStream) { + char buf[512]; + char *line, *line2, *p; + int i; + + // copy everything up to the encoding + for (line = (char *)file; + line && strncmp(line, "/Encoding", 9); + line = getNextLine(line)) ; + if (!line) { + // no encoding - just copy the whole font file + (*outputFunc)(outputStream, (char *)file, len); + return; + } + (*outputFunc)(outputStream, (char *)file, line - (char *)file); + + // write the new encoding + (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); + (*outputFunc)(outputStream, + "0 1 255 {1 index exch /.notdef put} for\n", 40); + for (i = 0; i < 256; ++i) { + if (newEncoding[i]) { + sprintf(buf, "dup %d /%s put\n", i, newEncoding[i]); + (*outputFunc)(outputStream, buf, strlen(buf)); + } + } + (*outputFunc)(outputStream, "readonly def\n", 13); + + // find the end of the encoding data + //~ this ought to parse PostScript tokens + if (!strncmp(line, "/Encoding StandardEncoding def", 30)) { + line = getNextLine(line); + } else { + // skip "/Encoding" + one whitespace char, + // then look for 'def' preceded by PostScript whitespace + p = line + 10; + line = NULL; + for (; p < (char *)file + len; ++p) { + if ((*p == ' ' || *p == '\t' || *p == '\x0a' || + *p == '\x0d' || *p == '\x0c' || *p == '\0') && + p + 4 <= (char *)file + len && + !strncmp(p + 1, "def", 3)) { + line = p + 4; + break; + } + } + } + + // some fonts have two /Encoding entries in their dictionary, so we + // check for a second one here + if (line) { + for (line2 = line, i = 0; + i < 20 && line2 && strncmp(line2, "/Encoding", 9); + line2 = getNextLine(line2), ++i) ; + if (i < 20 && line2) { + (*outputFunc)(outputStream, line, line2 - line); + if (!strncmp(line2, "/Encoding StandardEncoding def", 30)) { + line = getNextLine(line2); + } else { + // skip "/Encoding" + one whitespace char, + // then look for 'def' preceded by PostScript whitespace + p = line2 + 10; + line = NULL; + for (; p < (char *)file + len; ++p) { + if ((*p == ' ' || *p == '\t' || *p == '\x0a' || + *p == '\x0d' || *p == '\x0c' || *p == '\0') && + p + 4 <= (char *)file + len && + !strncmp(p + 1, "def", 3)) { + line = p + 4; + break; + } + } + } + } + + // copy everything after the encoding + if (line) { + (*outputFunc)(outputStream, line, ((char *)file + len) - line); + } + } +} + +char *FoFiType1::getNextLine(char *line) { + while (line < (char *)file + len && *line != '\x0a' && *line != '\x0d') { + ++line; + } + if (line < (char *)file + len && *line == '\x0d') { + ++line; + } + if (line < (char *)file + len && *line == '\x0a') { + ++line; + } + if (line >= (char *)file + len) { + return NULL; + } + return line; +} + +void FoFiType1::parse() { + char *line, *line1, *p, *p2; + char buf[256]; + char c; + int n, code, i, j; + + for (i = 1, line = (char *)file; + i <= 100 && line && (!name || !encoding); + ++i) { + + // get font name + if (!name && !strncmp(line, "/FontName", 9)) { + strncpy(buf, line, 255); + buf[255] = '\0'; + if ((p = strchr(buf+9, '/')) && + (p = strtok(p+1, " \t\n\r"))) { + name = copyString(p); + } + line = getNextLine(line); + + // get encoding + } else if (!encoding && + !strncmp(line, "/Encoding StandardEncoding def", 30)) { + encoding = fofiType1StandardEncoding; + } else if (!encoding && + !strncmp(line, "/Encoding 256 array", 19)) { + encoding = (char **)gmallocn(256, sizeof(char *)); + for (j = 0; j < 256; ++j) { + encoding[j] = NULL; + } + for (j = 0, line = getNextLine(line); + j < 300 && line && (line1 = getNextLine(line)); + ++j, line = line1) { + if ((n = line1 - line) > 255) { + n = 255; + } + strncpy(buf, line, n); + buf[n] = '\0'; + for (p = buf; *p == ' ' || *p == '\t'; ++p) ; + if (!strncmp(p, "dup", 3)) { + for (p += 3; *p == ' ' || *p == '\t'; ++p) ; + for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ; + if (*p2) { + c = *p2; + *p2 = '\0'; + code = atoi(p); + *p2 = c; + if (code == 8 && *p2 == '#') { + code = 0; + for (++p2; *p2 >= '0' && *p2 <= '7'; ++p2) { + code = code * 8 + (*p2 - '0'); + } + } + if (code < 256) { + for (p = p2; *p == ' ' || *p == '\t'; ++p) ; + if (*p == '/') { + ++p; + for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ; + *p2 = '\0'; + encoding[code] = copyString(p); + } + } + } + } else { + if (strtok(buf, " \t") && + (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) { + break; + } + } + } + //~ check for getinterval/putinterval junk + + } else { + line = getNextLine(line); + } + } + + parsed = gTrue; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiType1C.cc swftools-0.9.1/lib/pdf/xpdf/FoFiType1C.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiType1C.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FoFiType1C.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,2603 @@ +//======================================================================== +// +// FoFiType1C.cc +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include "gmem.h" +#include "GString.h" +#include "FoFiEncodings.h" +#include "FoFiType1C.h" + +//------------------------------------------------------------------------ + +static char hexChars[17] = "0123456789ABCDEF"; + +//------------------------------------------------------------------------ +// FoFiType1C +//------------------------------------------------------------------------ + +FoFiType1C *FoFiType1C::make(char *fileA, int lenA) { + FoFiType1C *ff; + + ff = new FoFiType1C(fileA, lenA, gFalse); + if (!ff->parse()) { + delete ff; + return NULL; + } + return ff; +} + +FoFiType1C *FoFiType1C::load(char *fileName) { + FoFiType1C *ff; + char *fileA; + int lenA; + + if (!(fileA = FoFiBase::readFile(fileName, &lenA))) { + return NULL; + } + ff = new FoFiType1C(fileA, lenA, gTrue); + if (!ff->parse()) { + delete ff; + return NULL; + } + return ff; +} + +FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA): + FoFiBase(fileA, lenA, freeFileDataA) +{ + name = NULL; + encoding = NULL; + privateDicts = NULL; + fdSelect = NULL; + charset = NULL; +} + +FoFiType1C::~FoFiType1C() { + int i; + + if (name) { + delete name; + } + if (encoding && + encoding != fofiType1StandardEncoding && + encoding != fofiType1ExpertEncoding) { + for (i = 0; i < 256; ++i) { + gfree(encoding[i]); + } + gfree(encoding); + } + if (privateDicts) { + gfree(privateDicts); + } + if (fdSelect) { + gfree(fdSelect); + } + if (charset && + charset != fofiType1CISOAdobeCharset && + charset != fofiType1CExpertCharset && + charset != fofiType1CExpertSubsetCharset) { + gfree(charset); + } +} + +char *FoFiType1C::getName() { + return name ? name->getCString() : (char *)NULL; +} + +char **FoFiType1C::getEncoding() { + return encoding; +} + +Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) { + Gushort *map; + int n, i; + + // a CID font's top dict has ROS as the first operator + if (topDict.firstOp != 0x0c1e) { + *nCIDs = 0; + return NULL; + } + + // in a CID font, the charset data is the GID-to-CID mapping, so all + // we have to do is reverse it + n = 0; + for (i = 0; i < nGlyphs; ++i) { + if (charset[i] > n) { + n = charset[i]; + } + } + ++n; + map = (Gushort *)gmallocn(n, sizeof(Gushort)); + memset(map, 0, n * sizeof(Gushort)); + for (i = 0; i < nGlyphs; ++i) { + map[charset[i]] = i; + } + *nCIDs = n; + return map; +} + +void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii, + FoFiOutputFunc outputFunc, + void *outputStream) { + int psNameLen; + Type1CEexecBuf eb; + Type1CIndex subrIdx; + Type1CIndexVal val; + GString *buf; + char buf2[256]; + char **enc; + GBool ok; + int i; + + if (psName) { + psNameLen = strlen(psName); + } else { + psName = name->getCString(); + psNameLen = name->getLength(); + } + + // write header and font dictionary, up to encoding + ok = gTrue; + (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17); + (*outputFunc)(outputStream, psName, psNameLen); + if (topDict.versionSID != 0) { + getString(topDict.versionSID, buf2, &ok); + (*outputFunc)(outputStream, buf2, strlen(buf2)); + } + (*outputFunc)(outputStream, "\n", 1); + // the dictionary needs room for 12 entries: the following 9, plus + // Private and CharStrings (in the eexec section) and FID (which is + // added by definefont) + (*outputFunc)(outputStream, "12 dict begin\n", 14); + (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28); + if (topDict.versionSID != 0) { + (*outputFunc)(outputStream, "/version (", 10); + (*outputFunc)(outputStream, buf2, strlen(buf2)); + (*outputFunc)(outputStream, ") readonly def\n", 15); + } + if (topDict.noticeSID != 0) { + getString(topDict.noticeSID, buf2, &ok); + (*outputFunc)(outputStream, "/Notice (", 9); + (*outputFunc)(outputStream, buf2, strlen(buf2)); + (*outputFunc)(outputStream, ") readonly def\n", 15); + } + if (topDict.copyrightSID != 0) { + getString(topDict.copyrightSID, buf2, &ok); + (*outputFunc)(outputStream, "/Copyright (", 12); + (*outputFunc)(outputStream, buf2, strlen(buf2)); + (*outputFunc)(outputStream, ") readonly def\n", 15); + } + if (topDict.fullNameSID != 0) { + getString(topDict.fullNameSID, buf2, &ok); + (*outputFunc)(outputStream, "/FullName (", 11); + (*outputFunc)(outputStream, buf2, strlen(buf2)); + (*outputFunc)(outputStream, ") readonly def\n", 15); + } + if (topDict.familyNameSID != 0) { + getString(topDict.familyNameSID, buf2, &ok); + (*outputFunc)(outputStream, "/FamilyName (", 13); + (*outputFunc)(outputStream, buf2, strlen(buf2)); + (*outputFunc)(outputStream, ") readonly def\n", 15); + } + if (topDict.weightSID != 0) { + getString(topDict.weightSID, buf2, &ok); + (*outputFunc)(outputStream, "/Weight (", 9); + (*outputFunc)(outputStream, buf2, strlen(buf2)); + (*outputFunc)(outputStream, ") readonly def\n", 15); + } + if (topDict.isFixedPitch) { + (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23); + } else { + (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24); + } + buf = GString::format("/ItalicAngle {0:.4g} def\n", topDict.italicAngle); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + buf = GString::format("/UnderlinePosition {0:.4g} def\n", + topDict.underlinePosition); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + buf = GString::format("/UnderlineThickness {0:.4g} def\n", + topDict.underlineThickness); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "end readonly def\n", 17); + (*outputFunc)(outputStream, "/FontName /", 11); + (*outputFunc)(outputStream, psName, psNameLen); + (*outputFunc)(outputStream, " def\n", 5); + buf = GString::format("/PaintType {0:d} def\n", topDict.paintType); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "/FontType 1 def\n", 16); + buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] readonly def\n", + topDict.fontMatrix[0], topDict.fontMatrix[1], + topDict.fontMatrix[2], topDict.fontMatrix[3], + topDict.fontMatrix[4], topDict.fontMatrix[5]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] readonly def\n", + topDict.fontBBox[0], topDict.fontBBox[1], + topDict.fontBBox[2], topDict.fontBBox[3]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + if (topDict.uniqueID != 0) { + buf = GString::format("/UniqueID {0:d} def\n", topDict.uniqueID); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + + // write the encoding + (*outputFunc)(outputStream, "/Encoding ", 10); + if (!newEncoding && encoding == fofiType1StandardEncoding) { + (*outputFunc)(outputStream, "StandardEncoding def\n", 21); + } else { + (*outputFunc)(outputStream, "256 array\n", 10); + (*outputFunc)(outputStream, + "0 1 255 {1 index exch /.notdef put} for\n", 40); + enc = newEncoding ? newEncoding : encoding; + for (i = 0; i < 256; ++i) { + if (enc[i]) { + buf = GString::format("dup {0:d} /{1:s} put\n", i, enc[i]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + } + (*outputFunc)(outputStream, "readonly def\n", 13); + } + (*outputFunc)(outputStream, "currentdict end\n", 16); + + // start the binary section + (*outputFunc)(outputStream, "currentfile eexec\n", 18); + eb.outputFunc = outputFunc; + eb.outputStream = outputStream; + eb.ascii = ascii; + eb.r1 = 55665; + eb.line = 0; + + // write the private dictionary + eexecWrite(&eb, "\x83\xca\x73\xd5"); + eexecWrite(&eb, "dup /Private 32 dict dup begin\n"); + eexecWrite(&eb, "/RD {string currentfile exch readstring pop}" + " executeonly def\n"); + eexecWrite(&eb, "/ND {noaccess def} executeonly def\n"); + eexecWrite(&eb, "/NP {noaccess put} executeonly def\n"); + eexecWrite(&eb, "/MinFeature {16 16} def\n"); + eexecWrite(&eb, "/password 5839 def\n"); + if (privateDicts[0].nBlueValues) { + eexecWrite(&eb, "/BlueValues ["); + for (i = 0; i < privateDicts[0].nBlueValues; ++i) { + buf = GString::format("{0:s}{1:d}", + i > 0 ? " " : "", privateDicts[0].blueValues[i]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[0].nOtherBlues) { + eexecWrite(&eb, "/OtherBlues ["); + for (i = 0; i < privateDicts[0].nOtherBlues; ++i) { + buf = GString::format("{0:s}{1:d}", + i > 0 ? " " : "", privateDicts[0].otherBlues[i]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[0].nFamilyBlues) { + eexecWrite(&eb, "/FamilyBlues ["); + for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) { + buf = GString::format("{0:s}{1:d}", + i > 0 ? " " : "", privateDicts[0].familyBlues[i]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[0].nFamilyOtherBlues) { + eexecWrite(&eb, "/FamilyOtherBlues ["); + for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) { + buf = GString::format("{0:s}{1:d}", i > 0 ? " " : "", + privateDicts[0].familyOtherBlues[i]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[0].blueScale != 0.039625) { + buf = GString::format("/BlueScale {0:.4g} def\n", + privateDicts[0].blueScale); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[0].blueShift != 7) { + buf = GString::format("/BlueShift {0:d} def\n", privateDicts[0].blueShift); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[0].blueFuzz != 1) { + buf = GString::format("/BlueFuzz {0:d} def\n", privateDicts[0].blueFuzz); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[0].hasStdHW) { + buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[0].stdHW); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[0].hasStdVW) { + buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[0].stdVW); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[0].nStemSnapH) { + eexecWrite(&eb, "/StemSnapH ["); + for (i = 0; i < privateDicts[0].nStemSnapH; ++i) { + buf = GString::format("{0:s}{1:.4g}", + i > 0 ? " " : "", privateDicts[0].stemSnapH[i]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[0].nStemSnapV) { + eexecWrite(&eb, "/StemSnapV ["); + for (i = 0; i < privateDicts[0].nStemSnapV; ++i) { + buf = GString::format("{0:s}{1:.4g}", + i > 0 ? " " : "", privateDicts[0].stemSnapV[i]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[0].hasForceBold) { + buf = GString::format("/ForceBold {0:s} def\n", + privateDicts[0].forceBold ? "true" : "false"); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[0].forceBoldThreshold != 0) { + buf = GString::format("/ForceBoldThreshold {0:.4g} def\n", + privateDicts[0].forceBoldThreshold); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[0].languageGroup != 0) { + buf = GString::format("/LanguageGroup {0:d} def\n", + privateDicts[0].languageGroup); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[0].expansionFactor != 0.06) { + buf = GString::format("/ExpansionFactor {0:.4g} def\n", + privateDicts[0].expansionFactor); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + + // set up subroutines + ok = gTrue; + getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok); + if (!ok) { + subrIdx.pos = -1; + } + + // write the CharStrings + buf = GString::format("2 index /CharStrings {0:d} dict dup begin\n", + nGlyphs); + eexecWrite(&eb, buf->getCString()); + delete buf; + for (i = 0; i < nGlyphs; ++i) { + ok = gTrue; + getIndexVal(&charStringsIdx, i, &val, &ok); + if (ok) { + getString(charset[i], buf2, &ok); + if (ok) { + eexecCvtGlyph(&eb, buf2, val.pos, val.len, &subrIdx, &privateDicts[0]); + } + } + } + eexecWrite(&eb, "end\n"); + eexecWrite(&eb, "end\n"); + eexecWrite(&eb, "readonly put\n"); + eexecWrite(&eb, "noaccess put\n"); + eexecWrite(&eb, "dup /FontName get exch definefont pop\n"); + eexecWrite(&eb, "mark currentfile closefile\n"); + + // trailer + if (ascii && eb.line > 0) { + (*outputFunc)(outputStream, "\n", 1); + } + for (i = 0; i < 8; ++i) { + (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65); + } + (*outputFunc)(outputStream, "cleartomark\n", 12); +} + +void FoFiType1C::convertToCIDType0(char *psName, + FoFiOutputFunc outputFunc, + void *outputStream) { + int *cidMap; + GString *charStrings; + int *charStringOffsets; + Type1CIndex subrIdx; + Type1CIndexVal val; + int nCIDs, gdBytes; + GString *buf; + char buf2[256]; + GBool ok; + int gid, offset, n, i, j, k; + + // compute the CID count and build the CID-to-GID mapping + nCIDs = 0; + for (i = 0; i < nGlyphs; ++i) { + if (charset[i] >= nCIDs) { + nCIDs = charset[i] + 1; + } + } + cidMap = (int *)gmallocn(nCIDs, sizeof(int)); + for (i = 0; i < nCIDs; ++i) { + cidMap[i] = -1; + } + for (i = 0; i < nGlyphs; ++i) { + cidMap[charset[i]] = i; + } + + // build the charstrings + charStrings = new GString(); + charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int)); + for (i = 0; i < nCIDs; ++i) { + charStringOffsets[i] = charStrings->getLength(); + if ((gid = cidMap[i]) >= 0) { + ok = gTrue; + getIndexVal(&charStringsIdx, gid, &val, &ok); + if (ok) { + getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok); + if (!ok) { + subrIdx.pos = -1; + } + cvtGlyph(val.pos, val.len, charStrings, + &subrIdx, &privateDicts[fdSelect[gid]], gTrue); + } + } + } + charStringOffsets[nCIDs] = charStrings->getLength(); + + // compute gdBytes = number of bytes needed for charstring offsets + // (offset size needs to account for the charstring offset table, + // with a worst case of five bytes per entry, plus the charstrings + // themselves) + i = (nCIDs + 1) * 5 + charStrings->getLength(); + if (i < 0x100) { + gdBytes = 1; + } else if (i < 0x10000) { + gdBytes = 2; + } else if (i < 0x1000000) { + gdBytes = 3; + } else { + gdBytes = 4; + } + + // begin the font dictionary + (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37); + (*outputFunc)(outputStream, "20 dict begin\n", 14); + (*outputFunc)(outputStream, "/CIDFontName /", 14); + (*outputFunc)(outputStream, psName, strlen(psName)); + (*outputFunc)(outputStream, " def\n", 5); + (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19); + (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32); + if (topDict.registrySID > 0 && topDict.orderingSID > 0) { + ok = gTrue; + getString(topDict.registrySID, buf2, &ok); + if (ok) { + (*outputFunc)(outputStream, " /Registry (", 13); + (*outputFunc)(outputStream, buf2, strlen(buf2)); + (*outputFunc)(outputStream, ") def\n", 6); + } + ok = gTrue; + getString(topDict.orderingSID, buf2, &ok); + if (ok) { + (*outputFunc)(outputStream, " /Ordering (", 13); + (*outputFunc)(outputStream, buf2, strlen(buf2)); + (*outputFunc)(outputStream, ") def\n", 6); + } + } else { + (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24); + (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27); + } + buf = GString::format(" /Supplement {0:d} def\n", topDict.supplement); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "end def\n", 8); + if (topDict.hasFontMatrix) { + buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n", + topDict.fontMatrix[0], topDict.fontMatrix[1], + topDict.fontMatrix[2], topDict.fontMatrix[3], + topDict.fontMatrix[4], topDict.fontMatrix[5]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } else if (privateDicts[0].hasFontMatrix) { + (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); + } else { + (*outputFunc)(outputStream, + "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38); + } + buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n", + topDict.fontBBox[0], topDict.fontBBox[1], + topDict.fontBBox[2], topDict.fontBBox[3]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27); + (*outputFunc)(outputStream, " /FSType 8 def\n", 16); + (*outputFunc)(outputStream, "end def\n", 8); + + // CIDFont-specific entries + buf = GString::format("/CIDCount {0:d} def\n", nCIDs); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15); + buf = GString::format("/GDBytes {0:d} def\n", gdBytes); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20); + if (topDict.paintType != 0) { + buf = GString::format("/PaintType {0:d} def\n", topDict.paintType); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + + // FDArray entry + buf = GString::format("/FDArray {0:d} array\n", nFDs); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + for (i = 0; i < nFDs; ++i) { + buf = GString::format("dup {0:d} 10 dict begin\n", i); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "/FontType 1 def\n", 16); + if (privateDicts[i].hasFontMatrix) { + buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n", + privateDicts[i].fontMatrix[0], + privateDicts[i].fontMatrix[1], + privateDicts[i].fontMatrix[2], + privateDicts[i].fontMatrix[3], + privateDicts[i].fontMatrix[4], + privateDicts[i].fontMatrix[5]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } else { + (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); + } + buf = GString::format("/PaintType {0:d} def\n", topDict.paintType); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23); + if (privateDicts[i].nBlueValues) { + (*outputFunc)(outputStream, "/BlueValues [", 13); + for (j = 0; j < privateDicts[i].nBlueValues; ++j) { + buf = GString::format("{0:s}{1:d}", + j > 0 ? " " : "", privateDicts[i].blueValues[j]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); + } + if (privateDicts[i].nOtherBlues) { + (*outputFunc)(outputStream, "/OtherBlues [", 13); + for (j = 0; j < privateDicts[i].nOtherBlues; ++j) { + buf = GString::format("{0:s}{1:d}", + j > 0 ? " " : "", privateDicts[i].otherBlues[j]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); + } + if (privateDicts[i].nFamilyBlues) { + (*outputFunc)(outputStream, "/FamilyBlues [", 14); + for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) { + buf = GString::format("{0:s}{1:d}", + j > 0 ? " " : "", + privateDicts[i].familyBlues[j]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); + } + if (privateDicts[i].nFamilyOtherBlues) { + (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19); + for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) { + buf = GString::format("{0:s}{1:d}", j > 0 ? " " : "", + privateDicts[i].familyOtherBlues[j]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); + } + if (privateDicts[i].blueScale != 0.039625) { + buf = GString::format("/BlueScale {0:.4g} def\n", + privateDicts[i].blueScale); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + if (privateDicts[i].blueShift != 7) { + buf = GString::format("/BlueShift {0:d} def\n", + privateDicts[i].blueShift); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + if (privateDicts[i].blueFuzz != 1) { + buf = GString::format("/BlueFuzz {0:d} def\n", privateDicts[i].blueFuzz); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + if (privateDicts[i].hasStdHW) { + buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[i].stdHW); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + if (privateDicts[i].hasStdVW) { + buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[i].stdVW); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + if (privateDicts[i].nStemSnapH) { + (*outputFunc)(outputStream, "/StemSnapH [", 12); + for (j = 0; j < privateDicts[i].nStemSnapH; ++j) { + buf = GString::format("{0:s}{1:.4g}", + j > 0 ? " " : "", privateDicts[i].stemSnapH[j]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); + } + if (privateDicts[i].nStemSnapV) { + (*outputFunc)(outputStream, "/StemSnapV [", 12); + for (j = 0; j < privateDicts[i].nStemSnapV; ++j) { + buf = GString::format("{0:s}{1:.4g}", + j > 0 ? " " : "", privateDicts[i].stemSnapV[j]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); + } + if (privateDicts[i].hasForceBold) { + buf = GString::format("/ForceBold {0:s} def\n", + privateDicts[i].forceBold ? "true" : "false"); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + if (privateDicts[i].forceBoldThreshold != 0) { + buf = GString::format("/ForceBoldThreshold {0:.4g} def\n", + privateDicts[i].forceBoldThreshold); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + if (privateDicts[i].languageGroup != 0) { + buf = GString::format("/LanguageGroup {0:d} def\n", + privateDicts[i].languageGroup); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + if (privateDicts[i].expansionFactor != 0.06) { + buf = GString::format("/ExpansionFactor {0:.4g} def\n", + privateDicts[i].expansionFactor); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "currentdict end def\n", 20); + (*outputFunc)(outputStream, "currentdict end put\n", 20); + } + (*outputFunc)(outputStream, "def\n", 4); + + // start the binary section + offset = (nCIDs + 1) * (1 + gdBytes); + buf = GString::format("(Hex) {0:d} StartData\n", + offset + charStrings->getLength()); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + + // write the charstring offset (CIDMap) table + for (i = 0; i <= nCIDs; i += 6) { + for (j = 0; j < 6 && i+j <= nCIDs; ++j) { + if (i+j < nCIDs && cidMap[i+j] >= 0) { + buf2[0] = (char)fdSelect[cidMap[i+j]]; + } else { + buf2[0] = (char)0; + } + n = offset + charStringOffsets[i+j]; + for (k = gdBytes; k >= 1; --k) { + buf2[k] = (char)(n & 0xff); + n >>= 8; + } + for (k = 0; k <= gdBytes; ++k) { + buf = GString::format("{0:02x}", buf2[k] & 0xff); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + } + (*outputFunc)(outputStream, "\n", 1); + } + + // write the charstring data + n = charStrings->getLength(); + for (i = 0; i < n; i += 32) { + for (j = 0; j < 32 && i+j < n; ++j) { + buf = GString::format("{0:02x}", charStrings->getChar(i+j) & 0xff); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + if (i + 32 >= n) { + (*outputFunc)(outputStream, ">", 1); + } + (*outputFunc)(outputStream, "\n", 1); + } + + gfree(charStringOffsets); + delete charStrings; + gfree(cidMap); +} + +void FoFiType1C::convertToType0(char *psName, + FoFiOutputFunc outputFunc, + void *outputStream) { + int *cidMap; + Type1CIndex subrIdx; + Type1CIndexVal val; + int nCIDs; + GString *buf; + Type1CEexecBuf eb; + GBool ok; + int fd, i, j, k; + + // compute the CID count and build the CID-to-GID mapping + nCIDs = 0; + for (i = 0; i < nGlyphs; ++i) { + if (charset[i] >= nCIDs) { + nCIDs = charset[i] + 1; + } + } + cidMap = (int *)gmallocn(nCIDs, sizeof(int)); + for (i = 0; i < nCIDs; ++i) { + cidMap[i] = -1; + } + for (i = 0; i < nGlyphs; ++i) { + cidMap[charset[i]] = i; + } + + // write the descendant Type 1 fonts + for (i = 0; i < nCIDs; i += 256) { + + //~ this assumes that all CIDs in this block have the same FD -- + //~ to handle multiple FDs correctly, need to somehow divide the + //~ font up by FD; as a kludge we ignore CID 0, which is .notdef + fd = 0; + for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) { + if (cidMap[i+j] >= 0) { + fd = fdSelect[cidMap[i+j]]; + break; + } + } + + // font dictionary (unencrypted section) + (*outputFunc)(outputStream, "16 dict begin\n", 14); + (*outputFunc)(outputStream, "/FontName /", 11); + (*outputFunc)(outputStream, psName, strlen(psName)); + buf = GString::format("_{0:02x} def\n", i >> 8); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, "/FontType 1 def\n", 16); + if (privateDicts[fd].hasFontMatrix) { + buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n", + privateDicts[fd].fontMatrix[0], + privateDicts[fd].fontMatrix[1], + privateDicts[fd].fontMatrix[2], + privateDicts[fd].fontMatrix[3], + privateDicts[fd].fontMatrix[4], + privateDicts[fd].fontMatrix[5]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } else if (topDict.hasFontMatrix) { + (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); + } else { + (*outputFunc)(outputStream, + "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38); + } + buf = GString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n", + topDict.fontBBox[0], topDict.fontBBox[1], + topDict.fontBBox[2], topDict.fontBBox[3]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + buf = GString::format("/PaintType {0:d} def\n", topDict.paintType); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + if (topDict.paintType != 0) { + buf = GString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); + for (j = 0; j < 256 && i+j < nCIDs; ++j) { + buf = GString::format("dup {0:d} /c{1:02x} put\n", j, j); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + if (j < 256) { + buf = GString::format("{0:d} 1 255 {{ 1 index exch /.notdef put }} for\n", + j); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "readonly def\n", 13); + (*outputFunc)(outputStream, "currentdict end\n", 16); + + // start the binary section + (*outputFunc)(outputStream, "currentfile eexec\n", 18); + eb.outputFunc = outputFunc; + eb.outputStream = outputStream; + eb.ascii = gTrue; + eb.r1 = 55665; + eb.line = 0; + + // start the private dictionary + eexecWrite(&eb, "\x83\xca\x73\xd5"); + eexecWrite(&eb, "dup /Private 32 dict dup begin\n"); + eexecWrite(&eb, "/RD {string currentfile exch readstring pop}" + " executeonly def\n"); + eexecWrite(&eb, "/ND {noaccess def} executeonly def\n"); + eexecWrite(&eb, "/NP {noaccess put} executeonly def\n"); + eexecWrite(&eb, "/MinFeature {16 16} def\n"); + eexecWrite(&eb, "/password 5839 def\n"); + if (privateDicts[fd].nBlueValues) { + eexecWrite(&eb, "/BlueValues ["); + for (k = 0; k < privateDicts[fd].nBlueValues; ++k) { + buf = GString::format("{0:s}{1:d}", + k > 0 ? " " : "", + privateDicts[fd].blueValues[k]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[fd].nOtherBlues) { + eexecWrite(&eb, "/OtherBlues ["); + for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) { + buf = GString::format("{0:s}{1:d}", + k > 0 ? " " : "", + privateDicts[fd].otherBlues[k]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[fd].nFamilyBlues) { + eexecWrite(&eb, "/FamilyBlues ["); + for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) { + buf = GString::format("{0:s}{1:d}", k > 0 ? " " : "", + privateDicts[fd].familyBlues[k]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[fd].nFamilyOtherBlues) { + eexecWrite(&eb, "/FamilyOtherBlues ["); + for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) { + buf = GString::format("{0:s}{1:d}", k > 0 ? " " : "", + privateDicts[fd].familyOtherBlues[k]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[fd].blueScale != 0.039625) { + buf = GString::format("/BlueScale {0:.4g} def\n", + privateDicts[fd].blueScale); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[fd].blueShift != 7) { + buf = GString::format("/BlueShift {0:d} def\n", + privateDicts[fd].blueShift); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[fd].blueFuzz != 1) { + buf = GString::format("/BlueFuzz {0:d} def\n", + privateDicts[fd].blueFuzz); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[fd].hasStdHW) { + buf = GString::format("/StdHW [{0:.4g}] def\n", privateDicts[fd].stdHW); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[fd].hasStdVW) { + buf = GString::format("/StdVW [{0:.4g}] def\n", privateDicts[fd].stdVW); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[fd].nStemSnapH) { + eexecWrite(&eb, "/StemSnapH ["); + for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) { + buf = GString::format("{0:s}{1:.4g}", + k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[fd].nStemSnapV) { + eexecWrite(&eb, "/StemSnapV ["); + for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) { + buf = GString::format("{0:s}{1:.4g}", + k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + eexecWrite(&eb, "] def\n"); + } + if (privateDicts[fd].hasForceBold) { + buf = GString::format("/ForceBold {0:s} def\n", + privateDicts[fd].forceBold ? "true" : "false"); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[fd].forceBoldThreshold != 0) { + buf = GString::format("/ForceBoldThreshold {0:.4g} def\n", + privateDicts[fd].forceBoldThreshold); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[fd].languageGroup != 0) { + buf = GString::format("/LanguageGroup {0:d} def\n", + privateDicts[fd].languageGroup); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + if (privateDicts[fd].expansionFactor != 0.06) { + buf = GString::format("/ExpansionFactor {0:.4g} def\n", + privateDicts[fd].expansionFactor); + eexecWrite(&eb, buf->getCString()); + delete buf; + } + + // set up the subroutines + ok = gTrue; + getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok); + if (!ok) { + subrIdx.pos = -1; + } + + // start the CharStrings + eexecWrite(&eb, "2 index /CharStrings 256 dict dup begin\n"); + + // write the .notdef CharString + ok = gTrue; + getIndexVal(&charStringsIdx, 0, &val, &ok); + if (ok) { + eexecCvtGlyph(&eb, ".notdef", val.pos, val.len, + &subrIdx, &privateDicts[fd]); + } + + // write the CharStrings + for (j = 0; j < 256 && i+j < nCIDs; ++j) { + if (cidMap[i+j] >= 0) { + ok = gTrue; + getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok); + if (ok) { + buf = GString::format("c{0:02x}", j); + eexecCvtGlyph(&eb, buf->getCString(), val.pos, val.len, + &subrIdx, &privateDicts[fd]); + delete buf; + } + } + } + eexecWrite(&eb, "end\n"); + eexecWrite(&eb, "end\n"); + eexecWrite(&eb, "readonly put\n"); + eexecWrite(&eb, "noaccess put\n"); + eexecWrite(&eb, "dup /FontName get exch definefont pop\n"); + eexecWrite(&eb, "mark currentfile closefile\n"); + + // trailer + if (eb.line > 0) { + (*outputFunc)(outputStream, "\n", 1); + } + for (j = 0; j < 8; ++j) { + (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65); + } + (*outputFunc)(outputStream, "cleartomark\n", 12); + } + + // write the Type 0 parent font + (*outputFunc)(outputStream, "16 dict begin\n", 14); + (*outputFunc)(outputStream, "/FontName /", 11); + (*outputFunc)(outputStream, psName, strlen(psName)); + (*outputFunc)(outputStream, " def\n", 5); + (*outputFunc)(outputStream, "/FontType 0 def\n", 16); + if (topDict.hasFontMatrix) { + buf = GString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n", + topDict.fontMatrix[0], topDict.fontMatrix[1], + topDict.fontMatrix[2], topDict.fontMatrix[3], + topDict.fontMatrix[4], topDict.fontMatrix[5]); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } else { + (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); + } + (*outputFunc)(outputStream, "/FMapType 2 def\n", 16); + (*outputFunc)(outputStream, "/Encoding [\n", 12); + for (i = 0; i < nCIDs; i += 256) { + buf = GString::format("{0:d}\n", i >> 8); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); + (*outputFunc)(outputStream, "/FDepVector [\n", 14); + for (i = 0; i < nCIDs; i += 256) { + (*outputFunc)(outputStream, "/", 1); + (*outputFunc)(outputStream, psName, strlen(psName)); + buf = GString::format("_{0:02x} findfont\n", i >> 8); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + (*outputFunc)(outputStream, "] def\n", 6); + (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40); + + gfree(cidMap); +} + +void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName, + int offset, int nBytes, + Type1CIndex *subrIdx, + Type1CPrivateDict *pDict) { + GString *buf; + GString *charBuf; + + // generate the charstring + charBuf = new GString(); + cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue); + + buf = GString::format("/{0:s} {1:d} RD ", glyphName, charBuf->getLength()); + eexecWrite(eb, buf->getCString()); + delete buf; + eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(), + charBuf->getLength()); + eexecWrite(eb, " ND\n"); + + delete charBuf; +} + +void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf, + Type1CIndex *subrIdx, Type1CPrivateDict *pDict, + GBool top) { + Type1CIndexVal val; + GBool ok, dFP; + double d, dx, dy; + Gushort r2; + Guchar byte; + int pos, subrBias, start, i, k; + + start = charBuf->getLength(); + if (top) { + charBuf->append((char)73); + charBuf->append((char)58); + charBuf->append((char)147); + charBuf->append((char)134); + nOps = 0; + nHints = 0; + firstOp = gTrue; + openPath = gFalse; + } + + pos = offset; + while (pos < offset + nBytes) { + ok = gTrue; + pos = getOp(pos, gTrue, &ok); + if (!ok) { + break; + } + if (!ops[nOps - 1].isNum) { + --nOps; // drop the operator + switch (ops[nOps].op) { + case 0x0001: // hstem + if (firstOp) { + cvtGlyphWidth(nOps & 1, charBuf, pDict); + firstOp = gFalse; + } + if (nOps & 1) { + //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps); + } + d = 0; + dFP = gFalse; + for (k = 0; k < nOps; k += 2) { + // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints + if (ops[k+1].num < 0) { + d += ops[k].num + ops[k+1].num; + dFP |= ops[k].isFP | ops[k+1].isFP; + cvtNum(d, dFP, charBuf); + cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf); + } else { + d += ops[k].num; + dFP |= ops[k].isFP; + cvtNum(d, dFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + d += ops[k+1].num; + dFP |= ops[k+1].isFP; + } + charBuf->append((char)1); + } + nHints += nOps / 2; + nOps = 0; + break; + case 0x0003: // vstem + if (firstOp) { + cvtGlyphWidth(nOps & 1, charBuf, pDict); + firstOp = gFalse; + } + if (nOps & 1) { + //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps); + } + d = 0; + dFP = gFalse; + for (k = 0; k < nOps; k += 2) { + // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints + if (ops[k+1].num < 0) { + d += ops[k].num + ops[k+1].num; + dFP |= ops[k].isFP | ops[k+1].isFP; + cvtNum(d, dFP, charBuf); + cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf); + } else { + d += ops[k].num; + dFP |= ops[k].isFP; + cvtNum(d, dFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + d += ops[k+1].num; + dFP |= ops[k+1].isFP; + } + charBuf->append((char)3); + } + nHints += nOps / 2; + nOps = 0; + break; + case 0x0004: // vmoveto + if (firstOp) { + cvtGlyphWidth(nOps == 2, charBuf, pDict); + firstOp = gFalse; + } + if (openPath) { + charBuf->append((char)9); + openPath = gFalse; + } + if (nOps != 1) { + //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps); + } + cvtNum(ops[0].num, ops[0].isFP, charBuf); + charBuf->append((char)4); + nOps = 0; + break; + case 0x0005: // rlineto + if (nOps < 2 || nOps % 2 != 0) { + //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps); + } + for (k = 0; k < nOps; k += 2) { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + charBuf->append((char)5); + } + nOps = 0; + openPath = gTrue; + break; + case 0x0006: // hlineto + if (nOps < 1) { + //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps); + } + for (k = 0; k < nOps; ++k) { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + charBuf->append((char)((k & 1) ? 7 : 6)); + } + nOps = 0; + openPath = gTrue; + break; + case 0x0007: // vlineto + if (nOps < 1) { + //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps); + } + for (k = 0; k < nOps; ++k) { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + charBuf->append((char)((k & 1) ? 6 : 7)); + } + nOps = 0; + openPath = gTrue; + break; + case 0x0008: // rrcurveto + if (nOps < 6 || nOps % 6 != 0) { + //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps); + } + for (k = 0; k < nOps; k += 6) { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); + cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf); + charBuf->append((char)8); + } + nOps = 0; + openPath = gTrue; + break; + case 0x000a: // callsubr + if (nOps >= 1) { + subrBias = (subrIdx->len < 1240) + ? 107 : (subrIdx->len < 33900) ? 1131 : 32768; + k = subrBias + (int)ops[nOps - 1].num; + --nOps; + ok = gTrue; + getIndexVal(subrIdx, k, &val, &ok); + if (ok) { + cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse); + } + } else { + //~ error(-1, "Too few args to Type 2 callsubr"); + } + // don't clear the stack + break; + case 0x000b: // return + // don't clear the stack + break; + case 0x000e: // endchar / seac + if (firstOp) { + cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict); + firstOp = gFalse; + } + if (openPath) { + charBuf->append((char)9); + openPath = gFalse; + } + if (nOps == 4) { + cvtNum(0, gFalse, charBuf); + cvtNum(ops[0].num, ops[0].isFP, charBuf); + cvtNum(ops[1].num, ops[1].isFP, charBuf); + cvtNum(ops[2].num, ops[2].isFP, charBuf); + cvtNum(ops[3].num, ops[3].isFP, charBuf); + charBuf->append((char)12)->append((char)6); + } else if (nOps == 0) { + charBuf->append((char)14); + } else { + //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps); + } + nOps = 0; + break; + case 0x000f: // (obsolete) + // this op is ignored, but we need the glyph width + if (firstOp) { + cvtGlyphWidth(nOps > 0, charBuf, pDict); + firstOp = gFalse; + } + nOps = 0; + break; + case 0x0010: // blend + //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]); + nOps = 0; + break; + case 0x0012: // hstemhm + // ignored + if (firstOp) { + cvtGlyphWidth(nOps & 1, charBuf, pDict); + firstOp = gFalse; + } + if (nOps & 1) { + //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps); + } + nHints += nOps / 2; + nOps = 0; + break; + case 0x0013: // hintmask + // ignored + if (firstOp) { + cvtGlyphWidth(nOps & 1, charBuf, pDict); + firstOp = gFalse; + } + if (nOps > 0) { + if (nOps & 1) { + //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm", + //~ nOps); + } + nHints += nOps / 2; + } + pos += (nHints + 7) >> 3; + nOps = 0; + break; + case 0x0014: // cntrmask + // ignored + if (firstOp) { + cvtGlyphWidth(nOps & 1, charBuf, pDict); + firstOp = gFalse; + } + if (nOps > 0) { + if (nOps & 1) { + //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm", + //~ nOps); + } + nHints += nOps / 2; + } + pos += (nHints + 7) >> 3; + nOps = 0; + break; + case 0x0015: // rmoveto + if (firstOp) { + cvtGlyphWidth(nOps == 3, charBuf, pDict); + firstOp = gFalse; + } + if (openPath) { + charBuf->append((char)9); + openPath = gFalse; + } + if (nOps != 2) { + //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps); + } + cvtNum(ops[0].num, ops[0].isFP, charBuf); + cvtNum(ops[1].num, ops[1].isFP, charBuf); + charBuf->append((char)21); + nOps = 0; + break; + case 0x0016: // hmoveto + if (firstOp) { + cvtGlyphWidth(nOps == 2, charBuf, pDict); + firstOp = gFalse; + } + if (openPath) { + charBuf->append((char)9); + openPath = gFalse; + } + if (nOps != 1) { + //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps); + } + cvtNum(ops[0].num, ops[0].isFP, charBuf); + charBuf->append((char)22); + nOps = 0; + break; + case 0x0017: // vstemhm + // ignored + if (firstOp) { + cvtGlyphWidth(nOps & 1, charBuf, pDict); + firstOp = gFalse; + } + if (nOps & 1) { + //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps); + } + nHints += nOps / 2; + nOps = 0; + break; + case 0x0018: // rcurveline + if (nOps < 8 || (nOps - 2) % 6 != 0) { + //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps); + } + for (k = 0; k < nOps - 2; k += 6) { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); + cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf); + charBuf->append((char)8); + } + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k].isFP, charBuf); + charBuf->append((char)5); + nOps = 0; + openPath = gTrue; + break; + case 0x0019: // rlinecurve + if (nOps < 8 || (nOps - 6) % 2 != 0) { + //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps); + } + for (k = 0; k < nOps - 6; k += 2) { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k].isFP, charBuf); + charBuf->append((char)5); + } + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); + cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf); + charBuf->append((char)8); + nOps = 0; + openPath = gTrue; + break; + case 0x001a: // vvcurveto + if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) { + //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps); + } + if (nOps % 2 == 1) { + cvtNum(ops[0].num, ops[0].isFP, charBuf); + cvtNum(ops[1].num, ops[1].isFP, charBuf); + cvtNum(ops[2].num, ops[2].isFP, charBuf); + cvtNum(ops[3].num, ops[3].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + cvtNum(ops[4].num, ops[4].isFP, charBuf); + charBuf->append((char)8); + k = 5; + } else { + k = 0; + } + for (; k < nOps; k += 4) { + cvtNum(0, gFalse, charBuf); + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + charBuf->append((char)8); + } + nOps = 0; + openPath = gTrue; + break; + case 0x001b: // hhcurveto + if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) { + //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps); + } + if (nOps % 2 == 1) { + cvtNum(ops[1].num, ops[1].isFP, charBuf); + cvtNum(ops[0].num, ops[0].isFP, charBuf); + cvtNum(ops[2].num, ops[2].isFP, charBuf); + cvtNum(ops[3].num, ops[3].isFP, charBuf); + cvtNum(ops[4].num, ops[4].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + charBuf->append((char)8); + k = 5; + } else { + k = 0; + } + for (; k < nOps; k += 4) { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + charBuf->append((char)8); + } + nOps = 0; + openPath = gTrue; + break; + case 0x001d: // callgsubr + if (nOps >= 1) { + k = gsubrBias + (int)ops[nOps - 1].num; + --nOps; + ok = gTrue; + getIndexVal(&gsubrIdx, k, &val, &ok); + if (ok) { + cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse); + } + } else { + //~ error(-1, "Too few args to Type 2 callgsubr"); + } + // don't clear the stack + break; + case 0x001e: // vhcurveto + if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) { + //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps); + } + for (k = 0; k < nOps && k != nOps-5; k += 4) { + if (k % 8 == 0) { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + charBuf->append((char)30); + } else { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + charBuf->append((char)31); + } + } + if (k == nOps-5) { + if (k % 8 == 0) { + cvtNum(0, gFalse, charBuf); + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); + } else { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + } + charBuf->append((char)8); + } + nOps = 0; + openPath = gTrue; + break; + case 0x001f: // hvcurveto + if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) { + //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps); + } + for (k = 0; k < nOps && k != nOps-5; k += 4) { + if (k % 8 == 0) { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + charBuf->append((char)31); + } else { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + charBuf->append((char)30); + } + } + if (k == nOps-5) { + if (k % 8 == 0) { + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + } else { + cvtNum(0, gFalse, charBuf); + cvtNum(ops[k].num, ops[k].isFP, charBuf); + cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); + cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); + cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); + cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); + } + charBuf->append((char)8); + } + nOps = 0; + openPath = gTrue; + break; + case 0x0c00: // dotsection (should be Type 1 only?) + // ignored + nOps = 0; + break; + case 0x0c03: // and + case 0x0c04: // or + case 0x0c05: // not + case 0x0c08: // store + case 0x0c09: // abs + case 0x0c0a: // add + case 0x0c0b: // sub + case 0x0c0c: // div + case 0x0c0d: // load + case 0x0c0e: // neg + case 0x0c0f: // eq + case 0x0c12: // drop + case 0x0c14: // put + case 0x0c15: // get + case 0x0c16: // ifelse + case 0x0c17: // random + case 0x0c18: // mul + case 0x0c1a: // sqrt + case 0x0c1b: // dup + case 0x0c1c: // exch + case 0x0c1d: // index + case 0x0c1e: // roll + //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]); + nOps = 0; + break; + case 0x0c22: // hflex + if (nOps != 7) { + //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps); + } + cvtNum(ops[0].num, ops[0].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + cvtNum(ops[1].num, ops[1].isFP, charBuf); + cvtNum(ops[2].num, ops[2].isFP, charBuf); + cvtNum(ops[3].num, ops[3].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + charBuf->append((char)8); + cvtNum(ops[4].num, ops[4].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + cvtNum(ops[5].num, ops[5].isFP, charBuf); + cvtNum(-ops[2].num, ops[2].isFP, charBuf); + cvtNum(ops[6].num, ops[6].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + charBuf->append((char)8); + nOps = 0; + openPath = gTrue; + break; + case 0x0c23: // flex + if (nOps != 13) { + //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps); + } + cvtNum(ops[0].num, ops[0].isFP, charBuf); + cvtNum(ops[1].num, ops[1].isFP, charBuf); + cvtNum(ops[2].num, ops[2].isFP, charBuf); + cvtNum(ops[3].num, ops[3].isFP, charBuf); + cvtNum(ops[4].num, ops[4].isFP, charBuf); + cvtNum(ops[5].num, ops[5].isFP, charBuf); + charBuf->append((char)8); + cvtNum(ops[6].num, ops[6].isFP, charBuf); + cvtNum(ops[7].num, ops[7].isFP, charBuf); + cvtNum(ops[8].num, ops[8].isFP, charBuf); + cvtNum(ops[9].num, ops[9].isFP, charBuf); + cvtNum(ops[10].num, ops[10].isFP, charBuf); + cvtNum(ops[11].num, ops[11].isFP, charBuf); + charBuf->append((char)8); + nOps = 0; + openPath = gTrue; + break; + case 0x0c24: // hflex1 + if (nOps != 9) { + //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps); + } + cvtNum(ops[0].num, ops[0].isFP, charBuf); + cvtNum(ops[1].num, ops[1].isFP, charBuf); + cvtNum(ops[2].num, ops[2].isFP, charBuf); + cvtNum(ops[3].num, ops[3].isFP, charBuf); + cvtNum(ops[4].num, ops[4].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + charBuf->append((char)8); + cvtNum(ops[5].num, ops[5].isFP, charBuf); + cvtNum(0, gFalse, charBuf); + cvtNum(ops[6].num, ops[6].isFP, charBuf); + cvtNum(ops[7].num, ops[7].isFP, charBuf); + cvtNum(ops[8].num, ops[8].isFP, charBuf); + cvtNum(-(ops[1].num + ops[3].num + ops[7].num), + ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf); + charBuf->append((char)8); + nOps = 0; + openPath = gTrue; + break; + case 0x0c25: // flex1 + if (nOps != 11) { + //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps); + } + cvtNum(ops[0].num, ops[0].isFP, charBuf); + cvtNum(ops[1].num, ops[1].isFP, charBuf); + cvtNum(ops[2].num, ops[2].isFP, charBuf); + cvtNum(ops[3].num, ops[3].isFP, charBuf); + cvtNum(ops[4].num, ops[4].isFP, charBuf); + cvtNum(ops[5].num, ops[5].isFP, charBuf); + charBuf->append((char)8); + cvtNum(ops[6].num, ops[6].isFP, charBuf); + cvtNum(ops[7].num, ops[7].isFP, charBuf); + cvtNum(ops[8].num, ops[8].isFP, charBuf); + cvtNum(ops[9].num, ops[9].isFP, charBuf); + dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num; + dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num; + if (fabs(dx) > fabs(dy)) { + cvtNum(ops[10].num, ops[10].isFP, charBuf); + cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP | + ops[7].isFP | ops[9].isFP, charBuf); + } else { + cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP | + ops[6].isFP | ops[8].isFP, charBuf); + cvtNum(ops[10].num, ops[10].isFP, charBuf); + } + charBuf->append((char)8); + nOps = 0; + openPath = gTrue; + break; + default: + //~ error(-1, "Illegal Type 2 charstring op: %04x", + //~ ops[nOps].op); + nOps = 0; + break; + } + } + } + + // charstring encryption + if (top) { + r2 = 4330; + for (i = start; i < charBuf->getLength(); ++i) { + byte = charBuf->getChar(i) ^ (r2 >> 8); + charBuf->setChar(i, byte); + r2 = (byte + r2) * 52845 + 22719; + } + } +} + +void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *charBuf, + Type1CPrivateDict *pDict) { + double w; + GBool wFP; + int i; + + if (useOp) { + w = pDict->nominalWidthX + ops[0].num; + wFP = pDict->nominalWidthXFP | ops[0].isFP; + for (i = 1; i < nOps; ++i) { + ops[i-1] = ops[i]; + } + --nOps; + } else { + w = pDict->defaultWidthX; + wFP = pDict->defaultWidthXFP; + } + cvtNum(0, gFalse, charBuf); + cvtNum(w, wFP, charBuf); + charBuf->append((char)13); +} + +void FoFiType1C::cvtNum(double x, GBool isFP, GString *charBuf) { + Guchar buf[12]; + int y, n; + + n = 0; + if (isFP) { + if (x >= -32768 && x < 32768) { + y = (int)(x * 256.0); + buf[0] = 255; + buf[1] = (Guchar)(y >> 24); + buf[2] = (Guchar)(y >> 16); + buf[3] = (Guchar)(y >> 8); + buf[4] = (Guchar)y; + buf[5] = 255; + buf[6] = 0; + buf[7] = 0; + buf[8] = 1; + buf[9] = 0; + buf[10] = 12; + buf[11] = 12; + n = 12; + } else { + //~ error(-1, "Type 2 fixed point constant out of range"); + } + } else { + y = (int)x; + if (y >= -107 && y <= 107) { + buf[0] = (Guchar)(y + 139); + n = 1; + } else if (y > 107 && y <= 1131) { + y -= 108; + buf[0] = (Guchar)((y >> 8) + 247); + buf[1] = (Guchar)(y & 0xff); + n = 2; + } else if (y < -107 && y >= -1131) { + y = -y - 108; + buf[0] = (Guchar)((y >> 8) + 251); + buf[1] = (Guchar)(y & 0xff); + n = 2; + } else { + buf[0] = 255; + buf[1] = (Guchar)(y >> 24); + buf[2] = (Guchar)(y >> 16); + buf[3] = (Guchar)(y >> 8); + buf[4] = (Guchar)y; + n = 5; + } + } + charBuf->append((char *)buf, n); +} + +void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) { + Guchar *p; + Guchar x; + + for (p = (Guchar *)s; *p; ++p) { + x = *p ^ (eb->r1 >> 8); + eb->r1 = (x + eb->r1) * 52845 + 22719; + if (eb->ascii) { + (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1); + (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1); + eb->line += 2; + if (eb->line == 64) { + (*eb->outputFunc)(eb->outputStream, "\n", 1); + eb->line = 0; + } + } else { + (*eb->outputFunc)(eb->outputStream, (char *)&x, 1); + } + } +} + +void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb, + Guchar *s, int n) { + Guchar x; + int i; + + // eexec encryption + for (i = 0; i < n; ++i) { + x = s[i] ^ (eb->r1 >> 8); + eb->r1 = (x + eb->r1) * 52845 + 22719; + if (eb->ascii) { + (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1); + (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1); + eb->line += 2; + if (eb->line == 64) { + (*eb->outputFunc)(eb->outputStream, "\n", 1); + eb->line = 0; + } + } else { + (*eb->outputFunc)(eb->outputStream, (char *)&x, 1); + } + } +} + +GBool FoFiType1C::parse() { + Type1CIndex fdIdx; + Type1CIndexVal val; + int i; + + parsedOk = gTrue; + + // some tools embed Type 1C fonts with an extra whitespace char at + // the beginning + if (len > 0 && file[0] != '\x01') { + ++file; + --len; + } + + // find the indexes + getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk); + getIndex(nameIdx.endPos, &topDictIdx, &parsedOk); + getIndex(topDictIdx.endPos, &stringIdx, &parsedOk); + getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk); + if (!parsedOk) { + return gFalse; + } + gsubrBias = (gsubrIdx.len < 1240) ? 107 + : (gsubrIdx.len < 33900) ? 1131 : 32768; + + // read the first font name + getIndexVal(&nameIdx, 0, &val, &parsedOk); + if (!parsedOk) { + return gFalse; + } + name = new GString((char *)&file[val.pos], val.len); + + // read the top dict for the first font + readTopDict(); + + // for CID fonts: read the FDArray dicts and private dicts + if (topDict.firstOp == 0x0c1e) { + if (topDict.fdArrayOffset == 0) { + nFDs = 1; + privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict)); + readPrivateDict(0, 0, &privateDicts[0]); + } else { + getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk); + if (!parsedOk) { + return gFalse; + } + nFDs = fdIdx.len; + privateDicts = (Type1CPrivateDict *) + gmallocn(nFDs, sizeof(Type1CPrivateDict)); + for (i = 0; i < nFDs; ++i) { + getIndexVal(&fdIdx, i, &val, &parsedOk); + if (!parsedOk) { + return gFalse; + } + readFD(val.pos, val.len, &privateDicts[i]); + } + } + + // for 8-bit fonts: read the private dict + } else { + privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict)); + readPrivateDict(topDict.privateOffset, topDict.privateSize, + &privateDicts[0]); + } + + // check for parse errors in the private dict(s) + if (!parsedOk) { + return gFalse; + } + + // get the charstrings index + if (topDict.charStringsOffset <= 0) { + parsedOk = gFalse; + return gFalse; + } + getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk); + if (!parsedOk) { + return gFalse; + } + nGlyphs = charStringsIdx.len; + + // for CID fonts: read the FDSelect table + if (topDict.firstOp == 0x0c1e) { + readFDSelect(); + if (!parsedOk) { + return gFalse; + } + } + + // read the charset + if (!readCharset()) { + parsedOk = gFalse; + return gFalse; + } + + // for 8-bit fonts: build the encoding + if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) { + buildEncoding(); + if (!parsedOk) { + return gFalse; + } + } + + return parsedOk; +} + +void FoFiType1C::readTopDict() { + Type1CIndexVal topDictPtr; + int pos; + + topDict.firstOp = -1; + topDict.versionSID = 0; + topDict.noticeSID = 0; + topDict.copyrightSID = 0; + topDict.fullNameSID = 0; + topDict.familyNameSID = 0; + topDict.weightSID = 0; + topDict.isFixedPitch = 0; + topDict.italicAngle = 0; + topDict.underlinePosition = -100; + topDict.underlineThickness = 50; + topDict.paintType = 0; + topDict.charstringType = 2; + topDict.fontMatrix[0] = 0.001; + topDict.fontMatrix[1] = 0; + topDict.fontMatrix[2] = 0; + topDict.fontMatrix[3] = 0.001; + topDict.fontMatrix[4] = 0; + topDict.fontMatrix[5] = 0; + topDict.hasFontMatrix = gFalse; + topDict.uniqueID = 0; + topDict.fontBBox[0] = 0; + topDict.fontBBox[1] = 0; + topDict.fontBBox[2] = 0; + topDict.fontBBox[3] = 0; + topDict.strokeWidth = 0; + topDict.charsetOffset = 0; + topDict.encodingOffset = 0; + topDict.charStringsOffset = 0; + topDict.privateSize = 0; + topDict.privateOffset = 0; + topDict.registrySID = 0; + topDict.orderingSID = 0; + topDict.supplement = 0; + topDict.fdArrayOffset = 0; + topDict.fdSelectOffset = 0; + + getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk); + pos = topDictPtr.pos; + nOps = 0; + while (pos < topDictPtr.pos + topDictPtr.len) { + pos = getOp(pos, gFalse, &parsedOk); + if (!parsedOk) { + break; + } + if (!ops[nOps - 1].isNum) { + --nOps; // drop the operator + if (topDict.firstOp < 0) { + topDict.firstOp = ops[nOps].op; + } + switch (ops[nOps].op) { + case 0x0000: topDict.versionSID = (int)ops[0].num; break; + case 0x0001: topDict.noticeSID = (int)ops[0].num; break; + case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break; + case 0x0002: topDict.fullNameSID = (int)ops[0].num; break; + case 0x0003: topDict.familyNameSID = (int)ops[0].num; break; + case 0x0004: topDict.weightSID = (int)ops[0].num; break; + case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break; + case 0x0c02: topDict.italicAngle = ops[0].num; break; + case 0x0c03: topDict.underlinePosition = ops[0].num; break; + case 0x0c04: topDict.underlineThickness = ops[0].num; break; + case 0x0c05: topDict.paintType = (int)ops[0].num; break; + case 0x0c06: topDict.charstringType = (int)ops[0].num; break; + case 0x0c07: topDict.fontMatrix[0] = ops[0].num; + topDict.fontMatrix[1] = ops[1].num; + topDict.fontMatrix[2] = ops[2].num; + topDict.fontMatrix[3] = ops[3].num; + topDict.fontMatrix[4] = ops[4].num; + topDict.fontMatrix[5] = ops[5].num; + topDict.hasFontMatrix = gTrue; break; + case 0x000d: topDict.uniqueID = (int)ops[0].num; break; + case 0x0005: topDict.fontBBox[0] = ops[0].num; + topDict.fontBBox[1] = ops[1].num; + topDict.fontBBox[2] = ops[2].num; + topDict.fontBBox[3] = ops[3].num; break; + case 0x0c08: topDict.strokeWidth = ops[0].num; break; + case 0x000f: topDict.charsetOffset = (int)ops[0].num; break; + case 0x0010: topDict.encodingOffset = (int)ops[0].num; break; + case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break; + case 0x0012: topDict.privateSize = (int)ops[0].num; + topDict.privateOffset = (int)ops[1].num; break; + case 0x0c1e: topDict.registrySID = (int)ops[0].num; + topDict.orderingSID = (int)ops[1].num; + topDict.supplement = (int)ops[2].num; break; + case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break; + case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; break; + } + nOps = 0; + } + } +} + +// Read a CID font dict (FD) - this pulls out the private dict +// pointer, and reads the private dict. It also pulls the FontMatrix +// (if any) out of the FD. +void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) { + int pos, pSize, pOffset; + double fontMatrix[6]; + GBool hasFontMatrix; + + hasFontMatrix = gFalse; + pSize = pOffset = 0; + pos = offset; + nOps = 0; + while (pos < offset + length) { + pos = getOp(pos, gFalse, &parsedOk); + if (!parsedOk) { + return; + } + if (!ops[nOps - 1].isNum) { + if (ops[nOps - 1].op == 0x0012) { + if (nOps < 3) { + parsedOk = gFalse; + return; + } + pSize = (int)ops[0].num; + pOffset = (int)ops[1].num; + break; + } else if (ops[nOps - 1].op == 0x0c07) { + fontMatrix[0] = ops[0].num; + fontMatrix[1] = ops[1].num; + fontMatrix[2] = ops[2].num; + fontMatrix[3] = ops[3].num; + fontMatrix[4] = ops[4].num; + fontMatrix[5] = ops[5].num; + hasFontMatrix = gTrue; + } + nOps = 0; + } + } + readPrivateDict(pOffset, pSize, pDict); + if (hasFontMatrix) { + pDict->fontMatrix[0] = fontMatrix[0]; + pDict->fontMatrix[1] = fontMatrix[1]; + pDict->fontMatrix[2] = fontMatrix[2]; + pDict->fontMatrix[3] = fontMatrix[3]; + pDict->fontMatrix[4] = fontMatrix[4]; + pDict->fontMatrix[5] = fontMatrix[5]; + pDict->hasFontMatrix = gTrue; + } +} + +void FoFiType1C::readPrivateDict(int offset, int length, + Type1CPrivateDict *pDict) { + int pos; + + pDict->hasFontMatrix = gFalse; + pDict->nBlueValues = 0; + pDict->nOtherBlues = 0; + pDict->nFamilyBlues = 0; + pDict->nFamilyOtherBlues = 0; + pDict->blueScale = 0.039625; + pDict->blueShift = 7; + pDict->blueFuzz = 1; + pDict->hasStdHW = gFalse; + pDict->hasStdVW = gFalse; + pDict->nStemSnapH = 0; + pDict->nStemSnapV = 0; + pDict->hasForceBold = gFalse; + pDict->forceBoldThreshold = 0; + pDict->languageGroup = 0; + pDict->expansionFactor = 0.06; + pDict->initialRandomSeed = 0; + pDict->subrsOffset = 0; + pDict->defaultWidthX = 0; + pDict->defaultWidthXFP = gFalse; + pDict->nominalWidthX = 0; + pDict->nominalWidthXFP = gFalse; + + // no dictionary + if (offset == 0 || length == 0) { + return; + } + + pos = offset; + nOps = 0; + while (pos < offset + length) { + pos = getOp(pos, gFalse, &parsedOk); + if (!parsedOk) { + break; + } + if (!ops[nOps - 1].isNum) { + --nOps; // drop the operator + switch (ops[nOps].op) { + case 0x0006: + pDict->nBlueValues = getDeltaIntArray(pDict->blueValues, + type1CMaxBlueValues); + break; + case 0x0007: + pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues, + type1CMaxOtherBlues); + break; + case 0x0008: + pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues, + type1CMaxBlueValues); + break; + case 0x0009: + pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues, + type1CMaxOtherBlues); + break; + case 0x0c09: + pDict->blueScale = ops[0].num; + break; + case 0x0c0a: + pDict->blueShift = (int)ops[0].num; + break; + case 0x0c0b: + pDict->blueFuzz = (int)ops[0].num; + break; + case 0x000a: + pDict->stdHW = ops[0].num; + pDict->hasStdHW = gTrue; + break; + case 0x000b: + pDict->stdVW = ops[0].num; + pDict->hasStdVW = gTrue; + break; + case 0x0c0c: + pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH, + type1CMaxStemSnap); + break; + case 0x0c0d: + pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV, + type1CMaxStemSnap); + break; + case 0x0c0e: + pDict->forceBold = ops[0].num != 0; + pDict->hasForceBold = gTrue; + break; + case 0x0c0f: + pDict->forceBoldThreshold = ops[0].num; + break; + case 0x0c11: + pDict->languageGroup = (int)ops[0].num; + break; + case 0x0c12: + pDict->expansionFactor = ops[0].num; + break; + case 0x0c13: + pDict->initialRandomSeed = (int)ops[0].num; + break; + case 0x0013: + pDict->subrsOffset = offset + (int)ops[0].num; + break; + case 0x0014: + pDict->defaultWidthX = ops[0].num; + pDict->defaultWidthXFP = ops[0].isFP; + break; + case 0x0015: + pDict->nominalWidthX = ops[0].num; + pDict->nominalWidthXFP = ops[0].isFP; + break; + } + nOps = 0; + } + } +} + +void FoFiType1C::readFDSelect() { + int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j; + + fdSelect = (Guchar *)gmalloc(nGlyphs); + if (topDict.fdSelectOffset == 0) { + for (i = 0; i < nGlyphs; ++i) { + fdSelect[i] = 0; + } + } else { + pos = topDict.fdSelectOffset; + fdSelectFmt = getU8(pos++, &parsedOk); + if (!parsedOk) { + return; + } + if (fdSelectFmt == 0) { + if (!checkRegion(pos, nGlyphs)) { + parsedOk = gFalse; + return; + } + memcpy(fdSelect, file + pos, nGlyphs); + } else if (fdSelectFmt == 3) { + nRanges = getU16BE(pos, &parsedOk); + pos += 2; + gid0 = getU16BE(pos, &parsedOk); + pos += 2; + for (i = 1; i <= nRanges; ++i) { + fd = getU8(pos++, &parsedOk); + gid1 = getU16BE(pos, &parsedOk); + if (!parsedOk) { + return; + } + pos += 2; + if (gid0 > gid1 || gid1 > nGlyphs) { + //~ error(-1, "Bad FDSelect table in CID font"); + parsedOk = gFalse; + return; + } + for (j = gid0; j < gid1; ++j) { + fdSelect[j] = fd; + } + gid0 = gid1; + } + } else { + //~ error(-1, "Unknown FDSelect table format in CID font"); + for (i = 0; i < nGlyphs; ++i) { + fdSelect[i] = 0; + } + } + } +} + +void FoFiType1C::buildEncoding() { + char buf[256]; + int nCodes, nRanges, encFormat; + int pos, c, sid, nLeft, nSups, i, j; + + if (topDict.encodingOffset == 0) { + encoding = fofiType1StandardEncoding; + + } else if (topDict.encodingOffset == 1) { + encoding = fofiType1ExpertEncoding; + + } else { + encoding = (char **)gmallocn(256, sizeof(char *)); + for (i = 0; i < 256; ++i) { + encoding[i] = NULL; + } + pos = topDict.encodingOffset; + encFormat = getU8(pos++, &parsedOk); + if (!parsedOk) { + return; + } + if ((encFormat & 0x7f) == 0) { + nCodes = 1 + getU8(pos++, &parsedOk); + if (!parsedOk) { + return; + } + if (nCodes > nGlyphs) { + nCodes = nGlyphs; + } + for (i = 1; i < nCodes; ++i) { + c = getU8(pos++, &parsedOk); + if (!parsedOk) { + return; + } + if (encoding[c]) { + gfree(encoding[c]); + } + encoding[c] = copyString(getString(charset[i], buf, &parsedOk)); + } + } else if ((encFormat & 0x7f) == 1) { + nRanges = getU8(pos++, &parsedOk); + if (!parsedOk) { + return; + } + nCodes = 1; + for (i = 0; i < nRanges; ++i) { + c = getU8(pos++, &parsedOk); + nLeft = getU8(pos++, &parsedOk); + if (!parsedOk) { + return; + } + for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) { + if (c < 256) { + if (encoding[c]) { + gfree(encoding[c]); + } + encoding[c] = copyString(getString(charset[nCodes], buf, + &parsedOk)); + } + ++nCodes; + ++c; + } + } + } + if (encFormat & 0x80) { + nSups = getU8(pos++, &parsedOk); + if (!parsedOk) { + return; + } + for (i = 0; i < nSups; ++i) { + c = getU8(pos++, &parsedOk);; + if (!parsedOk) { + return;; + } + sid = getU16BE(pos, &parsedOk); + pos += 2; + if (!parsedOk) { + return; + } + if (encoding[c]) { + gfree(encoding[c]); + } + encoding[c] = copyString(getString(sid, buf, &parsedOk)); + } + } + } +} + +GBool FoFiType1C::readCharset() { + int charsetFormat, c, pos; + int nLeft, i, j; + + if (topDict.charsetOffset == 0) { + charset = fofiType1CISOAdobeCharset; + } else if (topDict.charsetOffset == 1) { + charset = fofiType1CExpertCharset; + } else if (topDict.charsetOffset == 2) { + charset = fofiType1CExpertSubsetCharset; + } else { + charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort)); + for (i = 0; i < nGlyphs; ++i) { + charset[i] = 0; + } + pos = topDict.charsetOffset; + charsetFormat = getU8(pos++, &parsedOk); + if (charsetFormat == 0) { + for (i = 1; i < nGlyphs; ++i) { + charset[i] = (Gushort)getU16BE(pos, &parsedOk); + pos += 2; + if (!parsedOk) { + break; + } + } + } else if (charsetFormat == 1) { + i = 1; + while (i < nGlyphs) { + c = getU16BE(pos, &parsedOk); + pos += 2; + nLeft = getU8(pos++, &parsedOk); + if (!parsedOk) { + break; + } + for (j = 0; j <= nLeft && i < nGlyphs; ++j) { + charset[i++] = (Gushort)c++; + } + } + } else if (charsetFormat == 2) { + i = 1; + while (i < nGlyphs) { + c = getU16BE(pos, &parsedOk); + pos += 2; + nLeft = getU16BE(pos, &parsedOk); + pos += 2; + if (!parsedOk) { + break; + } + for (j = 0; j <= nLeft && i < nGlyphs; ++j) { + charset[i++] = (Gushort)c++; + } + } + } + if (!parsedOk) { + gfree(charset); + charset = NULL; + return gFalse; + } + } + return gTrue; +} + +int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) { + static char nybChars[16] = "0123456789.ee -"; + Type1COp op; + char buf[65]; + int b0, b1, nyb0, nyb1, x, i; + + b0 = getU8(pos++, ok); + op.isNum = gTrue; + op.isFP = gFalse; + + if (b0 == 28) { + x = getU8(pos++, ok); + x = (x << 8) | getU8(pos++, ok); + if (x & 0x8000) { + x |= ~0xffff; + } + op.num = x; + + } else if (!charstring && b0 == 29) { + x = getU8(pos++, ok); + x = (x << 8) | getU8(pos++, ok); + x = (x << 8) | getU8(pos++, ok); + x = (x << 8) | getU8(pos++, ok); + if (x & 0x80000000) { + x |= ~0xffffffff; + } + op.num = x; + + } else if (!charstring && b0 == 30) { + i = 0; + do { + b1 = getU8(pos++, ok); + nyb0 = b1 >> 4; + nyb1 = b1 & 0x0f; + if (nyb0 == 0xf) { + break; + } + buf[i++] = nybChars[nyb0]; + if (i == 64) { + break; + } + if (nyb0 == 0xc) { + buf[i++] = '-'; + } + if (i == 64) { + break; + } + if (nyb1 == 0xf) { + break; + } + buf[i++] = nybChars[nyb1]; + if (i == 64) { + break; + } + if (nyb1 == 0xc) { + buf[i++] = '-'; + } + } while (i < 64); + buf[i] = '\0'; + op.num = atof(buf); + op.isFP = gTrue; + + } else if (b0 >= 32 && b0 <= 246) { + op.num = b0 - 139; + + } else if (b0 >= 247 && b0 <= 250) { + op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108; + + } else if (b0 >= 251 && b0 <= 254) { + op.num = -((b0 - 251) << 8) - getU8(pos++, ok) - 108; + + } else if (charstring && b0 == 255) { + x = getU8(pos++, ok); + x = (x << 8) | getU8(pos++, ok); + x = (x << 8) | getU8(pos++, ok); + x = (x << 8) | getU8(pos++, ok); + if (x & 0x80000000) { + x |= ~0xffffffff; + } + op.num = (double)x / 65536.0; + op.isFP = gTrue; + + } else if (b0 == 12) { + op.isNum = gFalse; + op.op = 0x0c00 + getU8(pos++, ok); + + } else { + op.isNum = gFalse; + op.op = b0; + } + + if (nOps < 49) { + ops[nOps++] = op; + } + + return pos; +} + +// Convert the delta-encoded ops array to an array of ints. +int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) { + int x; + int n, i; + + if ((n = nOps) > maxLen) { + n = maxLen; + } + x = 0; + for (i = 0; i < n; ++i) { + x += (int)ops[i].num; + arr[i] = x; + } + return n; +} + +// Convert the delta-encoded ops array to an array of doubles. +int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) { + double x; + int n, i; + + if ((n = nOps) > maxLen) { + n = maxLen; + } + x = 0; + for (i = 0; i < n; ++i) { + x += ops[i].num; + arr[i] = x; + } + return n; +} + +void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) { + idx->pos = pos; + idx->len = getU16BE(pos, ok); + if (idx->len == 0) { + // empty indexes are legal and contain just the length field + idx->offSize = 0; + idx->startPos = idx->endPos = pos + 2; + } else { + idx->offSize = getU8(pos + 2, ok); + if (idx->offSize < 1 || idx->offSize > 4) { + *ok = gFalse; + } + idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1; + if (idx->startPos < 0 || idx->startPos >= len) { + *ok = gFalse; + } + idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize, + idx->offSize, ok); + if (idx->endPos < idx->startPos || idx->endPos > len) { + *ok = gFalse; + } + } +} + +void FoFiType1C::getIndexVal(Type1CIndex *idx, int i, + Type1CIndexVal *val, GBool *ok) { + int pos0, pos1; + + if (i < 0 || i >= idx->len) { + *ok = gFalse; + return; + } + pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize, + idx->offSize, ok); + pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize, + idx->offSize, ok); + if (pos0 < idx->startPos || pos0 > idx->endPos || + pos1 <= idx->startPos || pos1 > idx->endPos || + pos1 < pos0) { + *ok = gFalse; + } + val->pos = pos0; + val->len = pos1 - pos0; +} + +char *FoFiType1C::getString(int sid, char *buf, GBool *ok) { + Type1CIndexVal val; + int n; + + if (sid < 391) { + strcpy(buf, fofiType1CStdStrings[sid]); + } else { + sid -= 391; + getIndexVal(&stringIdx, sid, &val, ok); + if (*ok) { + if ((n = val.len) > 255) { + n = 255; + } + strncpy(buf, (char *)&file[val.pos], n); + buf[n] = '\0'; + } else { + buf[0] = '\0'; + } + } + return buf; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiType1C.h swftools-0.9.1/lib/pdf/xpdf/FoFiType1C.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiType1C.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FoFiType1C.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,233 @@ +//======================================================================== +// +// FoFiType1C.h +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FOFITYPE1C_H +#define FOFITYPE1C_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "FoFiBase.h" + +class GString; + +//------------------------------------------------------------------------ + +struct Type1CIndex { + int pos; // absolute position in file + int len; // length (number of entries) + int offSize; // offset size + int startPos; // position of start of index data - 1 + int endPos; // position one byte past end of the index +}; + +struct Type1CIndexVal { + int pos; // absolute position in file + int len; // length, in bytes +}; + +struct Type1CTopDict { + int firstOp; + + int versionSID; + int noticeSID; + int copyrightSID; + int fullNameSID; + int familyNameSID; + int weightSID; + int isFixedPitch; + double italicAngle; + double underlinePosition; + double underlineThickness; + int paintType; + int charstringType; + double fontMatrix[6]; + GBool hasFontMatrix; // CID fonts are allowed to put their + // FontMatrix in the FD instead of the + // top dict + int uniqueID; + double fontBBox[4]; + double strokeWidth; + int charsetOffset; + int encodingOffset; + int charStringsOffset; + int privateSize; + int privateOffset; + + // CIDFont entries + int registrySID; + int orderingSID; + int supplement; + int fdArrayOffset; + int fdSelectOffset; +}; + +#define type1CMaxBlueValues 14 +#define type1CMaxOtherBlues 10 +#define type1CMaxStemSnap 12 + +struct Type1CPrivateDict { + double fontMatrix[6]; + GBool hasFontMatrix; + int blueValues[type1CMaxBlueValues]; + int nBlueValues; + int otherBlues[type1CMaxOtherBlues]; + int nOtherBlues; + int familyBlues[type1CMaxBlueValues]; + int nFamilyBlues; + int familyOtherBlues[type1CMaxOtherBlues]; + int nFamilyOtherBlues; + double blueScale; + int blueShift; + int blueFuzz; + double stdHW; + GBool hasStdHW; + double stdVW; + GBool hasStdVW; + double stemSnapH[type1CMaxStemSnap]; + int nStemSnapH; + double stemSnapV[type1CMaxStemSnap]; + int nStemSnapV; + GBool forceBold; + GBool hasForceBold; + double forceBoldThreshold; + int languageGroup; + double expansionFactor; + int initialRandomSeed; + int subrsOffset; + double defaultWidthX; + GBool defaultWidthXFP; + double nominalWidthX; + GBool nominalWidthXFP; +}; + +struct Type1COp { + GBool isNum; // true -> number, false -> operator + GBool isFP; // true -> floating point number, false -> int + union { + double num; // if num is true + int op; // if num is false + }; +}; + +struct Type1CEexecBuf { + FoFiOutputFunc outputFunc; + void *outputStream; + GBool ascii; // ASCII encoding? + Gushort r1; // eexec encryption key + int line; // number of eexec chars left on current line +}; + +//------------------------------------------------------------------------ +// FoFiType1C +//------------------------------------------------------------------------ + +class FoFiType1C: public FoFiBase { +public: + + // Create a FoFiType1C object from a memory buffer. + static FoFiType1C *make(char *fileA, int lenA); + + // Create a FoFiType1C object from a file on disk. + static FoFiType1C *load(char *fileName); + + virtual ~FoFiType1C(); + + // Return the font name. + char *getName(); + + // Return the encoding, as an array of 256 names (any of which may + // be NULL). This is only useful with 8-bit fonts. + char **getEncoding(); + + // Return the mapping from CIDs to GIDs, and return the number of + // CIDs in *. This is only useful for CID fonts. + Gushort *getCIDToGIDMap(int *nCIDs); + + // Convert to a Type 1 font, suitable for embedding in a PostScript + // file. This is only useful with 8-bit fonts. If is + // not NULL, it will be used in place of the encoding in the Type 1C + // font. If is true the eexec section will be hex-encoded, + // otherwise it will be left as binary data. If is non-NULL, + // it will be used as the PostScript font name. + void convertToType1(char *psName, char **newEncoding, GBool ascii, + FoFiOutputFunc outputFunc, void *outputStream); + + // Convert to a Type 0 CIDFont, suitable for embedding in a + // PostScript file. will be used as the PostScript font + // name. + void convertToCIDType0(char *psName, + FoFiOutputFunc outputFunc, void *outputStream); + + // Convert to a Type 0 (but non-CID) composite font, suitable for + // embedding in a PostScript file. will be used as the + // PostScript font name. + void convertToType0(char *psName, + FoFiOutputFunc outputFunc, void *outputStream); + +private: + + FoFiType1C(char *fileA, int lenA, GBool freeFileDataA); + void eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName, + int offset, int nBytes, + Type1CIndex *subrIdx, + Type1CPrivateDict *pDict); + void cvtGlyph(int offset, int nBytes, GString *charBuf, + Type1CIndex *subrIdx, Type1CPrivateDict *pDict, + GBool top); + void cvtGlyphWidth(GBool useOp, GString *charBuf, + Type1CPrivateDict *pDict); + void cvtNum(double x, GBool isFP, GString *charBuf); + void eexecWrite(Type1CEexecBuf *eb, char *s); + void eexecWriteCharstring(Type1CEexecBuf *eb, Guchar *s, int n); + GBool parse(); + void readTopDict(); + void readFD(int offset, int length, Type1CPrivateDict *pDict); + void readPrivateDict(int offset, int length, Type1CPrivateDict *pDict); + void readFDSelect(); + void buildEncoding(); + GBool readCharset(); + int getOp(int pos, GBool charstring, GBool *ok); + int getDeltaIntArray(int *arr, int maxLen); + int getDeltaFPArray(double *arr, int maxLen); + void getIndex(int pos, Type1CIndex *idx, GBool *ok); + void getIndexVal(Type1CIndex *idx, int i, Type1CIndexVal *val, GBool *ok); + char *getString(int sid, char *buf, GBool *ok); + + GString *name; + char **encoding; + + Type1CIndex nameIdx; + Type1CIndex topDictIdx; + Type1CIndex stringIdx; + Type1CIndex gsubrIdx; + Type1CIndex charStringsIdx; + + Type1CTopDict topDict; + Type1CPrivateDict *privateDicts; + + int nGlyphs; + int nFDs; + Guchar *fdSelect; + Gushort *charset; + int gsubrBias; + + GBool parsedOk; + + Type1COp ops[49]; // operands and operator + int nOps; // number of operands + int nHints; // number of hints for the current glyph + GBool firstOp; // true if we haven't hit the first op yet + GBool openPath; // true if there is an unclosed path +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiType1.h swftools-0.9.1/lib/pdf/xpdf/FoFiType1.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/FoFiType1.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FoFiType1.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,59 @@ +//======================================================================== +// +// FoFiType1.h +// +// Copyright 1999-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FOFITYPE1_H +#define FOFITYPE1_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "FoFiBase.h" + +//------------------------------------------------------------------------ +// FoFiType1 +//------------------------------------------------------------------------ + +class FoFiType1: public FoFiBase { +public: + + // Create a FoFiType1 object from a memory buffer. + static FoFiType1 *make(char *fileA, int lenA); + + // Create a FoFiType1 object from a file on disk. + static FoFiType1 *load(char *fileName); + + virtual ~FoFiType1(); + + // Return the font name. + char *getName(); + + // Return the encoding, as an array of 256 names (any of which may + // be NULL). + char **getEncoding(); + + // Write a version of the Type 1 font file with a new encoding. + void writeEncoded(char **newEncoding, + FoFiOutputFunc outputFunc, void *outputStream); + +private: + + FoFiType1(char *fileA, int lenA, GBool freeFileDataA); + + char *getNextLine(char *line); + void parse(); + + char *name; + char **encoding; + GBool parsed; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FontEncodingTables.cc swftools-0.9.1/lib/pdf/xpdf/FontEncodingTables.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/FontEncodingTables.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FontEncodingTables.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,1824 @@ +//======================================================================== +// +// FontEncodingTables.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include "FontEncodingTables.h" + +char *macRomanEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quotesingle", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "grave", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + NULL, + "Adieresis", + "Aring", + "Ccedilla", + "Eacute", + "Ntilde", + "Odieresis", + "Udieresis", + "aacute", + "agrave", + "acircumflex", + "adieresis", + "atilde", + "aring", + "ccedilla", + "eacute", + "egrave", + "ecircumflex", + "edieresis", + "iacute", + "igrave", + "icircumflex", + "idieresis", + "ntilde", + "oacute", + "ograve", + "ocircumflex", + "odieresis", + "otilde", + "uacute", + "ugrave", + "ucircumflex", + "udieresis", + "dagger", + "degree", + "cent", + "sterling", + "section", + "bullet", + "paragraph", + "germandbls", + "registered", + "copyright", + "trademark", + "acute", + "dieresis", + "notequal", + "AE", + "Oslash", + "infinity", + "plusminus", + "lessequal", + "greaterequal", + "yen", + "mu", + "partialdiff", + "summation", + "product", + "pi", + "integral", + "ordfeminine", + "ordmasculine", + "Omega", + "ae", + "oslash", + "questiondown", + "exclamdown", + "logicalnot", + "radical", + "florin", + "approxequal", + "Delta", + "guillemotleft", + "guillemotright", + "ellipsis", + "space", + "Agrave", + "Atilde", + "Otilde", + "OE", + "oe", + "endash", + "emdash", + "quotedblleft", + "quotedblright", + "quoteleft", + "quoteright", + "divide", + "lozenge", + "ydieresis", + "Ydieresis", + "fraction", + "currency", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + "daggerdbl", + "periodcentered", + "quotesinglbase", + "quotedblbase", + "perthousand", + "Acircumflex", + "Ecircumflex", + "Aacute", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Oacute", + "Ocircumflex", + "apple", + "Ograve", + "Uacute", + "Ucircumflex", + "Ugrave", + "dotlessi", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "ring", + "cedilla", + "hungarumlaut", + "ogonek", + "caron" +}; + +char *macExpertEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclamsmall", + "Hungarumlautsmall", + "centoldstyle", + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "comma", + "hyphen", + "period", + "fraction", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "colon", + "semicolon", + NULL, + "threequartersemdash", + NULL, + "questionsmall", + NULL, + NULL, + NULL, + NULL, + "Ethsmall", + NULL, + NULL, + "onequarter", + "onehalf", + "threequarters", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "ff", + "fi", + "fl", + "ffi", + "ffl", + "parenleftinferior", + NULL, + "parenrightinferior", + "Circumflexsmall", + "hypheninferior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + NULL, + NULL, + "asuperior", + "centsuperior", + NULL, + NULL, + NULL, + NULL, + "Aacutesmall", + "Agravesmall", + "Acircumflexsmall", + "Adieresissmall", + "Atildesmall", + "Aringsmall", + "Ccedillasmall", + "Eacutesmall", + "Egravesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Iacutesmall", + "Igravesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ntildesmall", + "Oacutesmall", + "Ogravesmall", + "Ocircumflexsmall", + "Odieresissmall", + "Otildesmall", + "Uacutesmall", + "Ugravesmall", + "Ucircumflexsmall", + "Udieresissmall", + NULL, + "eightsuperior", + "fourinferior", + "threeinferior", + "sixinferior", + "eightinferior", + "seveninferior", + "Scaronsmall", + NULL, + "centinferior", + "twoinferior", + NULL, + "Dieresissmall", + NULL, + "Caronsmall", + "osuperior", + "fiveinferior", + NULL, + "commainferior", + "periodinferior", + "Yacutesmall", + NULL, + "dollarinferior", + NULL, + NULL, + "Thornsmall", + NULL, + "nineinferior", + "zeroinferior", + "Zcaronsmall", + "AEsmall", + "Oslashsmall", + "questiondownsmall", + "oneinferior", + "Lslashsmall", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Cedillasmall", + NULL, + NULL, + NULL, + NULL, + NULL, + "OEsmall", + "figuredash", + "hyphensuperior", + NULL, + NULL, + NULL, + NULL, + "exclamdownsmall", + NULL, + "Ydieresissmall", + NULL, + "onesuperior", + "twosuperior", + "threesuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "ninesuperior", + "zerosuperior", + NULL, + "esuperior", + "rsuperior", + "tsuperior", + NULL, + NULL, + "isuperior", + "ssuperior", + "dsuperior", + NULL, + NULL, + NULL, + NULL, + NULL, + "lsuperior", + "Ogoneksmall", + "Brevesmall", + "Macronsmall", + "bsuperior", + "nsuperior", + "msuperior", + "commasuperior", + "periodsuperior", + "Dotaccentsmall", + "Ringsmall", + NULL, + NULL, + NULL, + NULL +}; + +char *winAnsiEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quotesingle", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "grave", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + "bullet", + "Euro", + "bullet", + "quotesinglbase", + "florin", + "quotedblbase", + "ellipsis", + "dagger", + "daggerdbl", + "circumflex", + "perthousand", + "Scaron", + "guilsinglleft", + "OE", + "bullet", + "Zcaron", + "bullet", + "bullet", + "quoteleft", + "quoteright", + "quotedblleft", + "quotedblright", + "bullet", + "endash", + "emdash", + "tilde", + "trademark", + "scaron", + "guilsinglright", + "oe", + "bullet", + "zcaron", + "Ydieresis", + "space", + "exclamdown", + "cent", + "sterling", + "currency", + "yen", + "brokenbar", + "section", + "dieresis", + "copyright", + "ordfeminine", + "guillemotleft", + "logicalnot", + "hyphen", + "registered", + "macron", + "degree", + "plusminus", + "twosuperior", + "threesuperior", + "acute", + "mu", + "paragraph", + "periodcentered", + "cedilla", + "onesuperior", + "ordmasculine", + "guillemotright", + "onequarter", + "onehalf", + "threequarters", + "questiondown", + "Agrave", + "Aacute", + "Acircumflex", + "Atilde", + "Adieresis", + "Aring", + "AE", + "Ccedilla", + "Egrave", + "Eacute", + "Ecircumflex", + "Edieresis", + "Igrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Eth", + "Ntilde", + "Ograve", + "Oacute", + "Ocircumflex", + "Otilde", + "Odieresis", + "multiply", + "Oslash", + "Ugrave", + "Uacute", + "Ucircumflex", + "Udieresis", + "Yacute", + "Thorn", + "germandbls", + "agrave", + "aacute", + "acircumflex", + "atilde", + "adieresis", + "aring", + "ae", + "ccedilla", + "egrave", + "eacute", + "ecircumflex", + "edieresis", + "igrave", + "iacute", + "icircumflex", + "idieresis", + "eth", + "ntilde", + "ograve", + "oacute", + "ocircumflex", + "otilde", + "odieresis", + "divide", + "oslash", + "ugrave", + "uacute", + "ucircumflex", + "udieresis", + "yacute", + "thorn", + "ydieresis" +}; + +char *standardEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + NULL, + "endash", + "dagger", + "daggerdbl", + "periodcentered", + NULL, + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + NULL, + "questiondown", + NULL, + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + NULL, + "ring", + "cedilla", + NULL, + "hungarumlaut", + "ogonek", + "caron", + "emdash", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "AE", + NULL, + "ordfeminine", + NULL, + NULL, + NULL, + NULL, + "Lslash", + "Oslash", + "OE", + "ordmasculine", + NULL, + NULL, + NULL, + NULL, + NULL, + "ae", + NULL, + NULL, + NULL, + "dotlessi", + NULL, + NULL, + "lslash", + "oslash", + "oe", + "germandbls", + NULL, + NULL, + NULL, + NULL +}; + +char *expertEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclamsmall", + "Hungarumlautsmall", + NULL, + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "comma", + "hyphen", + "period", + "fraction", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "colon", + "semicolon", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + NULL, + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + NULL, + NULL, + NULL, + "isuperior", + NULL, + NULL, + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + NULL, + NULL, + "rsuperior", + "ssuperior", + "tsuperior", + NULL, + "ff", + "fi", + "fl", + "ffi", + "ffl", + "parenleftinferior", + NULL, + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + NULL, + NULL, + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + NULL, + "Dotaccentsmall", + NULL, + NULL, + "Macronsmall", + NULL, + NULL, + "figuredash", + "hypheninferior", + NULL, + NULL, + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + NULL, + NULL, + NULL, + "onequarter", + "onehalf", + "threequarters", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + NULL, + NULL, + "zerosuperior", + "onesuperior", + "twosuperior", + "threesuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall" +}; + +char *symbolEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "exclam", + "universal", + "numbersign", + "existential", + "percent", + "ampersand", + "suchthat", + "parenleft", + "parenright", + "asteriskmath", + "plus", + "comma", + "minus", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "congruent", + "Alpha", + "Beta", + "Chi", + "Delta", + "Epsilon", + "Phi", + "Gamma", + "Eta", + "Iota", + "theta1", + "Kappa", + "Lambda", + "Mu", + "Nu", + "Omicron", + "Pi", + "Theta", + "Rho", + "Sigma", + "Tau", + "Upsilon", + "sigma1", + "Omega", + "Xi", + "Psi", + "Zeta", + "bracketleft", + "therefore", + "bracketright", + "perpendicular", + "underscore", + "radicalex", + "alpha", + "beta", + "chi", + "delta", + "epsilon", + "phi", + "gamma", + "eta", + "iota", + "phi1", + "kappa", + "lambda", + "mu", + "nu", + "omicron", + "pi", + "theta", + "rho", + "sigma", + "tau", + "upsilon", + "omega1", + "omega", + "xi", + "psi", + "zeta", + "braceleft", + "bar", + "braceright", + "similar", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Upsilon1", + "minute", + "lessequal", + "fraction", + "infinity", + "florin", + "club", + "diamond", + "heart", + "spade", + "arrowboth", + "arrowleft", + "arrowup", + "arrowright", + "arrowdown", + "degree", + "plusminus", + "second", + "greaterequal", + "multiply", + "proportional", + "partialdiff", + "bullet", + "divide", + "notequal", + "equivalence", + "approxequal", + "ellipsis", + "arrowvertex", + "arrowhorizex", + "carriagereturn", + "aleph", + "Ifraktur", + "Rfraktur", + "weierstrass", + "circlemultiply", + "circleplus", + "emptyset", + "intersection", + "union", + "propersuperset", + "reflexsuperset", + "notsubset", + "propersubset", + "reflexsubset", + "element", + "notelement", + "angle", + "gradient", + "registerserif", + "copyrightserif", + "trademarkserif", + "product", + "radical", + "dotmath", + "logicalnot", + "logicaland", + "logicalor", + "arrowdblboth", + "arrowdblleft", + "arrowdblup", + "arrowdblright", + "arrowdbldown", + "lozenge", + "angleleft", + "registersans", + "copyrightsans", + "trademarksans", + "summation", + "parenlefttp", + "parenleftex", + "parenleftbt", + "bracketlefttp", + "bracketleftex", + "bracketleftbt", + "bracelefttp", + "braceleftmid", + "braceleftbt", + "braceex", + NULL, + "angleright", + "integral", + "integraltp", + "integralex", + "integralbt", + "parenrighttp", + "parenrightex", + "parenrightbt", + "bracketrighttp", + "bracketrightex", + "bracketrightbt", + "bracerighttp", + "bracerightmid", + "bracerightbt", + NULL +}; + +char *zapfDingbatsEncoding[256] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "space", + "a1", + "a2", + "a202", + "a3", + "a4", + "a5", + "a119", + "a118", + "a117", + "a11", + "a12", + "a13", + "a14", + "a15", + "a16", + "a105", + "a17", + "a18", + "a19", + "a20", + "a21", + "a22", + "a23", + "a24", + "a25", + "a26", + "a27", + "a28", + "a6", + "a7", + "a8", + "a9", + "a10", + "a29", + "a30", + "a31", + "a32", + "a33", + "a34", + "a35", + "a36", + "a37", + "a38", + "a39", + "a40", + "a41", + "a42", + "a43", + "a44", + "a45", + "a46", + "a47", + "a48", + "a49", + "a50", + "a51", + "a52", + "a53", + "a54", + "a55", + "a56", + "a57", + "a58", + "a59", + "a60", + "a61", + "a62", + "a63", + "a64", + "a65", + "a66", + "a67", + "a68", + "a69", + "a70", + "a71", + "a72", + "a73", + "a74", + "a203", + "a75", + "a204", + "a76", + "a77", + "a78", + "a79", + "a81", + "a82", + "a83", + "a84", + "a97", + "a98", + "a99", + "a100", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "a101", + "a102", + "a103", + "a104", + "a106", + "a107", + "a108", + "a112", + "a111", + "a110", + "a109", + "a120", + "a121", + "a122", + "a123", + "a124", + "a125", + "a126", + "a127", + "a128", + "a129", + "a130", + "a131", + "a132", + "a133", + "a134", + "a135", + "a136", + "a137", + "a138", + "a139", + "a140", + "a141", + "a142", + "a143", + "a144", + "a145", + "a146", + "a147", + "a148", + "a149", + "a150", + "a151", + "a152", + "a153", + "a154", + "a155", + "a156", + "a157", + "a158", + "a159", + "a160", + "a161", + "a163", + "a164", + "a196", + "a165", + "a192", + "a166", + "a167", + "a168", + "a169", + "a170", + "a171", + "a172", + "a173", + "a162", + "a174", + "a175", + "a176", + "a177", + "a178", + "a179", + "a193", + "a180", + "a199", + "a181", + "a200", + "a182", + NULL, + "a201", + "a183", + "a184", + "a197", + "a185", + "a194", + "a198", + "a186", + "a195", + "a187", + "a188", + "a189", + "a190", + "a191", + NULL +}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/FontEncodingTables.h swftools-0.9.1/lib/pdf/xpdf/FontEncodingTables.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/FontEncodingTables.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/FontEncodingTables.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,20 @@ +//======================================================================== +// +// FontEncodingTables.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FONTENCODINGTABLES_H +#define FONTENCODINGTABLES_H + +extern char *macRomanEncoding[]; +extern char *macExpertEncoding[]; +extern char *winAnsiEncoding[]; +extern char *standardEncoding[]; +extern char *expertEncoding[]; +extern char *symbolEncoding[]; +extern char *zapfDingbatsEncoding[]; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/forwardArrowDis.xbm swftools-0.9.1/lib/pdf/xpdf/forwardArrowDis.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/forwardArrowDis.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/forwardArrowDis.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define forwardArrowDis_width 16 +#define forwardArrowDis_height 15 +static unsigned char forwardArrowDis_bits[] = { + 0x00, 0x01, 0x00, 0x02, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x15, 0x22, 0x2a, + 0x11, 0x55, 0x22, 0xaa, 0x11, 0x55, 0x22, 0x2a, 0x00, 0x15, 0x00, 0x0a, + 0x00, 0x05, 0x00, 0x02, 0x00, 0x01}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/forwardArrow.xbm swftools-0.9.1/lib/pdf/xpdf/forwardArrow.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/forwardArrow.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/forwardArrow.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define forwardArrow_width 16 +#define forwardArrow_height 15 +static unsigned char forwardArrow_bits[] = { + 0x00, 0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x33, 0x3f, + 0x33, 0x7f, 0x33, 0xff, 0x33, 0x7f, 0x33, 0x3f, 0x00, 0x1f, 0x00, 0x0f, + 0x00, 0x07, 0x00, 0x03, 0x00, 0x01}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Function.cc swftools-0.9.1/lib/pdf/xpdf/Function.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Function.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Function.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,1573 @@ +//======================================================================== +// +// Function.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gmem.h" +#include "Object.h" +#include "Dict.h" +#include "Stream.h" +#include "Error.h" +#include "Function.h" + +//------------------------------------------------------------------------ +// Function +//------------------------------------------------------------------------ + +Function::Function() { +} + +Function::~Function() { +} + +Function *Function::parse(Object *funcObj) { + Function *func; + Dict *dict; + int funcType; + Object obj1; + + if (funcObj->isStream()) { + dict = funcObj->streamGetDict(); + } else if (funcObj->isDict()) { + dict = funcObj->getDict(); + } else if (funcObj->isName("Identity")) { + return new IdentityFunction(); + } else { + error(-1, "Expected function dictionary or stream"); + return NULL; + } + + if (!dict->lookup("FunctionType", &obj1)->isInt()) { + error(-1, "Function type is missing or wrong type"); + obj1.free(); + return NULL; + } + funcType = obj1.getInt(); + obj1.free(); + + if (funcType == 0) { + func = new SampledFunction(funcObj, dict); + } else if (funcType == 2) { + func = new ExponentialFunction(funcObj, dict); + } else if (funcType == 3) { + func = new StitchingFunction(funcObj, dict); + } else if (funcType == 4) { + func = new PostScriptFunction(funcObj, dict); + } else { + error(-1, "Unimplemented function type (%d)", funcType); + return NULL; + } + if (!func->isOk()) { + delete func; + return NULL; + } + + return func; +} + +GBool Function::init(Dict *dict) { + Object obj1, obj2; + int i; + + //----- Domain + if (!dict->lookup("Domain", &obj1)->isArray()) { + error(-1, "Function is missing domain"); + goto err2; + } + m = obj1.arrayGetLength() / 2; + if (m > funcMaxInputs) { + error(-1, "Functions with more than %d inputs are unsupported", + funcMaxInputs); + goto err2; + } + for (i = 0; i < m; ++i) { + obj1.arrayGet(2*i, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function domain array"); + goto err1; + } + domain[i][0] = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2*i+1, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function domain array"); + goto err1; + } + domain[i][1] = obj2.getNum(); + obj2.free(); + } + obj1.free(); + + //----- Range + hasRange = gFalse; + n = 0; + if (dict->lookup("Range", &obj1)->isArray()) { + hasRange = gTrue; + n = obj1.arrayGetLength() / 2; + if (n > funcMaxOutputs) { + error(-1, "Functions with more than %d outputs are unsupported", + funcMaxOutputs); + goto err2; + } + for (i = 0; i < n; ++i) { + obj1.arrayGet(2*i, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function range array"); + goto err1; + } + range[i][0] = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2*i+1, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function range array"); + goto err1; + } + range[i][1] = obj2.getNum(); + obj2.free(); + } + } + obj1.free(); + + return gTrue; + + err1: + obj2.free(); + err2: + obj1.free(); + return gFalse; +} + +//------------------------------------------------------------------------ +// IdentityFunction +//------------------------------------------------------------------------ + +IdentityFunction::IdentityFunction() { + int i; + + // fill these in with arbitrary values just in case they get used + // somewhere + m = funcMaxInputs; + n = funcMaxOutputs; + for (i = 0; i < funcMaxInputs; ++i) { + domain[i][0] = 0; + domain[i][1] = 1; + } + hasRange = gFalse; +} + +IdentityFunction::~IdentityFunction() { +} + +void IdentityFunction::transform(double *in, double *out) { + int i; + + for (i = 0; i < funcMaxOutputs; ++i) { + out[i] = in[i]; + } +} + +//------------------------------------------------------------------------ +// SampledFunction +//------------------------------------------------------------------------ + +SampledFunction::SampledFunction(Object *funcObj, Dict *dict) { + Stream *str; + int sampleBits; + double sampleMul; + Object obj1, obj2; + Guint buf, bitMask; + int bits; + Guint s; + int i; + + samples = NULL; + sBuf = NULL; + ok = gFalse; + + //----- initialize the generic stuff + if (!init(dict)) { + goto err1; + } + if (!hasRange) { + error(-1, "Type 0 function is missing range"); + goto err1; + } + if (m > sampledFuncMaxInputs) { + error(-1, "Sampled functions with more than %d inputs are unsupported", + sampledFuncMaxInputs); + goto err1; + } + + //----- buffer + sBuf = (double *)gmallocn(1 << m, sizeof(double)); + + //----- get the stream + if (!funcObj->isStream()) { + error(-1, "Type 0 function isn't a stream"); + goto err1; + } + str = funcObj->getStream(); + + //----- Size + if (!dict->lookup("Size", &obj1)->isArray() || + obj1.arrayGetLength() != m) { + error(-1, "Function has missing or invalid size array"); + goto err2; + } + for (i = 0; i < m; ++i) { + obj1.arrayGet(i, &obj2); + if (!obj2.isInt()) { + error(-1, "Illegal value in function size array"); + goto err3; + } + sampleSize[i] = obj2.getInt(); + obj2.free(); + } + obj1.free(); + idxMul[0] = n; + for (i = 1; i < m; ++i) { + idxMul[i] = idxMul[i-1] * sampleSize[i-1]; + } + + //----- BitsPerSample + if (!dict->lookup("BitsPerSample", &obj1)->isInt()) { + error(-1, "Function has missing or invalid BitsPerSample"); + goto err2; + } + sampleBits = obj1.getInt(); + sampleMul = 1.0 / (pow(2.0, (double)sampleBits) - 1); + obj1.free(); + + //----- Encode + if (dict->lookup("Encode", &obj1)->isArray() && + obj1.arrayGetLength() == 2*m) { + for (i = 0; i < m; ++i) { + obj1.arrayGet(2*i, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function encode array"); + goto err3; + } + encode[i][0] = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2*i+1, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function encode array"); + goto err3; + } + encode[i][1] = obj2.getNum(); + obj2.free(); + } + } else { + for (i = 0; i < m; ++i) { + encode[i][0] = 0; + encode[i][1] = sampleSize[i] - 1; + } + } + obj1.free(); + for (i = 0; i < m; ++i) { + inputMul[i] = (encode[i][1] - encode[i][0]) / + (domain[i][1] - domain[i][0]); + } + + //----- Decode + if (dict->lookup("Decode", &obj1)->isArray() && + obj1.arrayGetLength() == 2*n) { + for (i = 0; i < n; ++i) { + obj1.arrayGet(2*i, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function decode array"); + goto err3; + } + decode[i][0] = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2*i+1, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function decode array"); + goto err3; + } + decode[i][1] = obj2.getNum(); + obj2.free(); + } + } else { + for (i = 0; i < n; ++i) { + decode[i][0] = range[i][0]; + decode[i][1] = range[i][1]; + } + } + obj1.free(); + + //----- samples + nSamples = n; + for (i = 0; i < m; ++i) + nSamples *= sampleSize[i]; + samples = (double *)gmallocn(nSamples, sizeof(double)); + buf = 0; + bits = 0; + bitMask = (1 << sampleBits) - 1; + str->reset(); + for (i = 0; i < nSamples; ++i) { + if (sampleBits == 8) { + s = str->getChar(); + } else if (sampleBits == 16) { + s = str->getChar(); + s = (s << 8) + str->getChar(); + } else if (sampleBits == 32) { + s = str->getChar(); + s = (s << 8) + str->getChar(); + s = (s << 8) + str->getChar(); + s = (s << 8) + str->getChar(); + } else { + while (bits < sampleBits) { + buf = (buf << 8) | (str->getChar() & 0xff); + bits += 8; + } + s = (buf >> (bits - sampleBits)) & bitMask; + bits -= sampleBits; + } + samples[i] = (double)s * sampleMul; + } + str->close(); + + ok = gTrue; + return; + + err3: + obj2.free(); + err2: + obj1.free(); + err1: + return; +} + +SampledFunction::~SampledFunction() { + if (samples) { + gfree(samples); + } + if (sBuf) { + gfree(sBuf); + } +} + +SampledFunction::SampledFunction(SampledFunction *func) { + memcpy(this, func, sizeof(SampledFunction)); + samples = (double *)gmallocn(nSamples, sizeof(double)); + memcpy(samples, func->samples, nSamples * sizeof(double)); + sBuf = (double *)gmallocn(1 << m, sizeof(double)); +} + +void SampledFunction::transform(double *in, double *out) { + double x; + int e[funcMaxInputs][2]; + double efrac0[funcMaxInputs]; + double efrac1[funcMaxInputs]; + int i, j, k, idx, t; + + // map input values into sample array + for (i = 0; i < m; ++i) { + x = (in[i] - domain[i][0]) * inputMul[i] + encode[i][0]; + if (x < 0) { + x = 0; + } else if (x > sampleSize[i] - 1) { + x = sampleSize[i] - 1; + } + e[i][0] = (int)x; + if ((e[i][1] = e[i][0] + 1) >= sampleSize[i]) { + // this happens if in[i] = domain[i][1] + e[i][1] = e[i][0]; + } + efrac1[i] = x - e[i][0]; + efrac0[i] = 1 - efrac1[i]; + } + + // for each output, do m-linear interpolation + for (i = 0; i < n; ++i) { + + // pull 2^m values out of the sample array + for (j = 0; j < (1<>= 1) { + idx += idxMul[k] * (e[k][t & 1]); + } + sBuf[j] = (idx>=0&&idx>= 1) { + for (k = 0; k < t; k += 2) { + sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k+1]; + } + } + + // map output value to range + out[i] = sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0]; + if (out[i] < range[i][0]) { + out[i] = range[i][0]; + } else if (out[i] > range[i][1]) { + out[i] = range[i][1]; + } + } +} + +//------------------------------------------------------------------------ +// ExponentialFunction +//------------------------------------------------------------------------ + +ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) { + Object obj1, obj2; + int i; + + ok = gFalse; + + //----- initialize the generic stuff + if (!init(dict)) { + goto err1; + } + if (m != 1) { + error(-1, "Exponential function with more than one input"); + goto err1; + } + + //----- C0 + if (dict->lookup("C0", &obj1)->isArray()) { + if (hasRange && obj1.arrayGetLength() != n) { + error(-1, "Function's C0 array is wrong length"); + goto err2; + } + n = obj1.arrayGetLength(); + for (i = 0; i < n; ++i) { + obj1.arrayGet(i, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function C0 array"); + goto err3; + } + c0[i] = obj2.getNum(); + obj2.free(); + } + } else { + if (hasRange && n != 1) { + error(-1, "Function's C0 array is wrong length"); + goto err2; + } + n = 1; + c0[0] = 0; + } + obj1.free(); + + //----- C1 + if (dict->lookup("C1", &obj1)->isArray()) { + if (obj1.arrayGetLength() != n) { + error(-1, "Function's C1 array is wrong length"); + goto err2; + } + for (i = 0; i < n; ++i) { + obj1.arrayGet(i, &obj2); + if (!obj2.isNum()) { + error(-1, "Illegal value in function C1 array"); + goto err3; + } + c1[i] = obj2.getNum(); + obj2.free(); + } + } else { + if (n != 1) { + error(-1, "Function's C1 array is wrong length"); + goto err2; + } + c1[0] = 1; + } + obj1.free(); + + //----- N (exponent) + if (!dict->lookup("N", &obj1)->isNum()) { + error(-1, "Function has missing or invalid N"); + goto err2; + } + e = obj1.getNum(); + obj1.free(); + + ok = gTrue; + return; + + err3: + obj2.free(); + err2: + obj1.free(); + err1: + return; +} + +ExponentialFunction::~ExponentialFunction() { +} + +ExponentialFunction::ExponentialFunction(ExponentialFunction *func) { + memcpy(this, func, sizeof(ExponentialFunction)); +} + +void ExponentialFunction::transform(double *in, double *out) { + double x; + int i; + + if (in[0] < domain[0][0]) { + x = domain[0][0]; + } else if (in[0] > domain[0][1]) { + x = domain[0][1]; + } else { + x = in[0]; + } + for (i = 0; i < n; ++i) { + out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]); + if (hasRange) { + if (out[i] < range[i][0]) { + out[i] = range[i][0]; + } else if (out[i] > range[i][1]) { + out[i] = range[i][1]; + } + } + } + return; +} + +//------------------------------------------------------------------------ +// StitchingFunction +//------------------------------------------------------------------------ + +StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) { + Object obj1, obj2; + int i; + + ok = gFalse; + funcs = NULL; + bounds = NULL; + encode = NULL; + scale = NULL; + + //----- initialize the generic stuff + if (!init(dict)) { + goto err1; + } + if (m != 1) { + error(-1, "Stitching function with more than one input"); + goto err1; + } + + //----- Functions + if (!dict->lookup("Functions", &obj1)->isArray()) { + error(-1, "Missing 'Functions' entry in stitching function"); + goto err1; + } + k = obj1.arrayGetLength(); + funcs = (Function **)gmallocn(k, sizeof(Function *)); + bounds = (double *)gmallocn(k + 1, sizeof(double)); + encode = (double *)gmallocn(2 * k, sizeof(double)); + scale = (double *)gmallocn(k, sizeof(double)); + for (i = 0; i < k; ++i) { + funcs[i] = NULL; + } + for (i = 0; i < k; ++i) { + if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2)))) { + goto err2; + } + if (i > 0 && (funcs[i]->getInputSize() != 1 || + funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) { + error(-1, "Incompatible subfunctions in stitching function"); + goto err2; + } + obj2.free(); + } + obj1.free(); + + //----- Bounds + if (!dict->lookup("Bounds", &obj1)->isArray() || + obj1.arrayGetLength() != k - 1) { + error(-1, "Missing or invalid 'Bounds' entry in stitching function"); + goto err1; + } + bounds[0] = domain[0][0]; + for (i = 1; i < k; ++i) { + if (!obj1.arrayGet(i - 1, &obj2)->isNum()) { + error(-1, "Invalid type in 'Bounds' array in stitching function"); + goto err2; + } + bounds[i] = obj2.getNum(); + obj2.free(); + } + bounds[k] = domain[0][1]; + obj1.free(); + + //----- Encode + if (!dict->lookup("Encode", &obj1)->isArray() || + obj1.arrayGetLength() != 2 * k) { + error(-1, "Missing or invalid 'Encode' entry in stitching function"); + goto err1; + } + for (i = 0; i < 2 * k; ++i) { + if (!obj1.arrayGet(i, &obj2)->isNum()) { + error(-1, "Invalid type in 'Encode' array in stitching function"); + goto err2; + } + encode[i] = obj2.getNum(); + obj2.free(); + } + obj1.free(); + + //----- pre-compute the scale factors + for (i = 0; i < k; ++i) { + if (bounds[i] == bounds[i+1]) { + // avoid a divide-by-zero -- in this situation, function i will + // never be used anyway + scale[i] = 0; + } else { + scale[i] = (encode[2*i+1] - encode[2*i]) / (bounds[i+1] - bounds[i]); + } + } + + ok = gTrue; + return; + + err2: + obj2.free(); + err1: + obj1.free(); +} + +StitchingFunction::StitchingFunction(StitchingFunction *func) { + int i; + + k = func->k; + funcs = (Function **)gmallocn(k, sizeof(Function *)); + for (i = 0; i < k; ++i) { + funcs[i] = func->funcs[i]->copy(); + } + bounds = (double *)gmallocn(k + 1, sizeof(double)); + memcpy(bounds, func->bounds, (k + 1) * sizeof(double)); + encode = (double *)gmallocn(2 * k, sizeof(double)); + memcpy(encode, func->encode, 2 * k * sizeof(double)); + scale = (double *)gmallocn(k, sizeof(double)); + memcpy(scale, func->scale, k * sizeof(double)); + ok = gTrue; +} + +StitchingFunction::~StitchingFunction() { + int i; + + if (funcs) { + for (i = 0; i < k; ++i) { + if (funcs[i]) { + delete funcs[i]; + } + } + } + gfree(funcs); + gfree(bounds); + gfree(encode); + gfree(scale); +} + +void StitchingFunction::transform(double *in, double *out) { + double x; + int i; + + if (in[0] < domain[0][0]) { + x = domain[0][0]; + } else if (in[0] > domain[0][1]) { + x = domain[0][1]; + } else { + x = in[0]; + } + for (i = 0; i < k - 1; ++i) { + if (x < bounds[i+1]) { + break; + } + } + x = encode[2*i] + (x - bounds[i]) * scale[i]; + funcs[i]->transform(&x, out); +} + +//------------------------------------------------------------------------ +// PostScriptFunction +//------------------------------------------------------------------------ + +enum PSOp { + psOpAbs, + psOpAdd, + psOpAnd, + psOpAtan, + psOpBitshift, + psOpCeiling, + psOpCopy, + psOpCos, + psOpCvi, + psOpCvr, + psOpDiv, + psOpDup, + psOpEq, + psOpExch, + psOpExp, + psOpFalse, + psOpFloor, + psOpGe, + psOpGt, + psOpIdiv, + psOpIndex, + psOpLe, + psOpLn, + psOpLog, + psOpLt, + psOpMod, + psOpMul, + psOpNe, + psOpNeg, + psOpNot, + psOpOr, + psOpPop, + psOpRoll, + psOpRound, + psOpSin, + psOpSqrt, + psOpSub, + psOpTrue, + psOpTruncate, + psOpXor, + psOpIf, + psOpIfelse, + psOpReturn +}; + +// Note: 'if' and 'ifelse' are parsed separately. +// The rest are listed here in alphabetical order. +// The index in this table is equivalent to the entry in PSOp. +char *psOpNames[] = { + "abs", + "add", + "and", + "atan", + "bitshift", + "ceiling", + "copy", + "cos", + "cvi", + "cvr", + "div", + "dup", + "eq", + "exch", + "exp", + "false", + "floor", + "ge", + "gt", + "idiv", + "index", + "le", + "ln", + "log", + "lt", + "mod", + "mul", + "ne", + "neg", + "not", + "or", + "pop", + "roll", + "round", + "sin", + "sqrt", + "sub", + "true", + "truncate", + "xor" +}; + +#define nPSOps (sizeof(psOpNames) / sizeof(char *)) + +enum PSObjectType { + psBool, + psInt, + psReal, + psOperator, + psBlock +}; + +// In the code array, 'if'/'ifelse' operators take up three slots +// plus space for the code in the subclause(s). +// +// +---------------------------------+ +// | psOperator: psOpIf / psOpIfelse | +// +---------------------------------+ +// | psBlock: ptr= | +// +---------------------------------+ +// | psBlock: ptr= | +// +---------------------------------+ +// | if clause | +// | ... | +// | psOperator: psOpReturn | +// +---------------------------------+ +// | else clause | +// | ... | +// | psOperator: psOpReturn | +// +---------------------------------+ +// | ... | +// +// For 'if', pointer is present in the code stream but unused. + +struct PSObject { + PSObjectType type; + union { + GBool booln; // boolean (stack only) + int intg; // integer (stack and code) + double real; // real (stack and code) + PSOp op; // operator (code only) + int blk; // if/ifelse block pointer (code only) + }; +}; + +#define psStackSize 100 + +class PSStack { +public: + + PSStack() { sp = psStackSize; } + void pushBool(GBool booln); + void pushInt(int intg); + void pushReal(double real); + GBool popBool(); + int popInt(); + double popNum(); + GBool empty() { return sp == psStackSize; } + GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; } + GBool topTwoAreInts() + { return sp < psStackSize - 1 && + stack[sp].type == psInt && + stack[sp+1].type == psInt; } + GBool topIsReal() { return sp < psStackSize && stack[sp].type == psReal; } + GBool topTwoAreNums() + { return sp < psStackSize - 1 && + (stack[sp].type == psInt || stack[sp].type == psReal) && + (stack[sp+1].type == psInt || stack[sp+1].type == psReal); } + void copy(int n); + void roll(int n, int j); + void index(int i); + void pop(); + +private: + + GBool checkOverflow(int n = 1); + GBool checkUnderflow(); + GBool checkType(PSObjectType t1, PSObjectType t2); + + PSObject stack[psStackSize]; + int sp; +}; + +GBool PSStack::checkOverflow(int n) { + if (sp - n < 0) { + error(-1, "Stack overflow in PostScript function"); + return gFalse; + } + return gTrue; +} + +GBool PSStack::checkUnderflow() { + if (sp == psStackSize) { + error(-1, "Stack underflow in PostScript function"); + return gFalse; + } + return gTrue; +} + +GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) { + if (stack[sp].type != t1 && stack[sp].type != t2) { + error(-1, "Type mismatch in PostScript function"); + return gFalse; + } + return gTrue; +} + +void PSStack::pushBool(GBool booln) { + if (checkOverflow()) { + stack[--sp].type = psBool; + stack[sp].booln = booln; + } +} + +void PSStack::pushInt(int intg) { + if (checkOverflow()) { + stack[--sp].type = psInt; + stack[sp].intg = intg; + } +} + +void PSStack::pushReal(double real) { + if (checkOverflow()) { + stack[--sp].type = psReal; + stack[sp].real = real; + } +} + +GBool PSStack::popBool() { + if (checkUnderflow() && checkType(psBool, psBool)) { + return stack[sp++].booln; + } + return gFalse; +} + +int PSStack::popInt() { + if (checkUnderflow() && checkType(psInt, psInt)) { + return stack[sp++].intg; + } + return 0; +} + +double PSStack::popNum() { + double ret; + + if (checkUnderflow() && checkType(psInt, psReal)) { + ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real; + ++sp; + return ret; + } + return 0; +} + +void PSStack::copy(int n) { + int i; + + if (sp + n > psStackSize) { + error(-1, "Stack underflow in PostScript function"); + return; + } + if (!checkOverflow(n)) { + return; + } + for (i = sp + n - 1; i >= sp; --i) { + stack[i - n] = stack[i]; + } + sp -= n; +} + +void PSStack::roll(int n, int j) { + PSObject obj; + int i, k; + + if (j >= 0) { + j %= n; + } else { + j = -j % n; + if (j != 0) { + j = n - j; + } + } + if (n <= 0 || j == 0) { + return; + } + for (i = 0; i < j; ++i) { + obj = stack[sp]; + for (k = sp; k < sp + n - 1; ++k) { + stack[k] = stack[k+1]; + } + stack[sp + n - 1] = obj; + } +} + +void PSStack::index(int i) { + if (!checkOverflow()) { + return; + } + --sp; + stack[sp] = stack[sp + 1 + i]; +} + +void PSStack::pop() { + if (!checkUnderflow()) { + return; + } + ++sp; +} + +PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) { + Stream *str; + int codePtr; + GString *tok; + + code = NULL; + codeSize = 0; + ok = gFalse; + + //----- initialize the generic stuff + if (!init(dict)) { + goto err1; + } + if (!hasRange) { + error(-1, "Type 4 function is missing range"); + goto err1; + } + + //----- get the stream + if (!funcObj->isStream()) { + error(-1, "Type 4 function isn't a stream"); + goto err1; + } + str = funcObj->getStream(); + + //----- parse the function + codeString = new GString(); + str->reset(); + if (!(tok = getToken(str)) || tok->cmp("{")) { + error(-1, "Expected '{' at start of PostScript function"); + if (tok) { + delete tok; + } + goto err1; + } + delete tok; + codePtr = 0; + if (!parseCode(str, &codePtr)) { + goto err2; + } + str->close(); + + ok = gTrue; + + err2: + str->close(); + err1: + return; +} + +PostScriptFunction::PostScriptFunction(PostScriptFunction *func) { + memcpy(this, func, sizeof(PostScriptFunction)); + code = (PSObject *)gmallocn(codeSize, sizeof(PSObject)); + memcpy(code, func->code, codeSize * sizeof(PSObject)); + codeString = func->codeString->copy(); +} + +PostScriptFunction::~PostScriptFunction() { + gfree(code); + delete codeString; +} + +void PostScriptFunction::transform(double *in, double *out) { + PSStack *stack; + int i; + + stack = new PSStack(); + for (i = 0; i < m; ++i) { + //~ may need to check for integers here + stack->pushReal(in[i]); + } + exec(stack, 0); + for (i = n - 1; i >= 0; --i) { + out[i] = stack->popNum(); + if (out[i] < range[i][0]) { + out[i] = range[i][0]; + } else if (out[i] > range[i][1]) { + out[i] = range[i][1]; + } + } + // if (!stack->empty()) { + // error(-1, "Extra values on stack at end of PostScript function"); + // } + delete stack; +} + +GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) { + GString *tok; + char *p; + GBool isReal; + int opPtr, elsePtr; + int a, b, mid, cmp; + + while (1) { + if (!(tok = getToken(str))) { + error(-1, "Unexpected end of PostScript function stream"); + return gFalse; + } + p = tok->getCString(); + if (isdigit(*p) || *p == '.' || *p == '-') { + isReal = gFalse; + for (++p; *p; ++p) { + if (*p == '.') { + isReal = gTrue; + break; + } + } + resizeCode(*codePtr); + if (isReal) { + code[*codePtr].type = psReal; + code[*codePtr].real = atof(tok->getCString()); + } else { + code[*codePtr].type = psInt; + code[*codePtr].intg = atoi(tok->getCString()); + } + ++*codePtr; + delete tok; + } else if (!tok->cmp("{")) { + delete tok; + opPtr = *codePtr; + *codePtr += 3; + resizeCode(opPtr + 2); + if (!parseCode(str, codePtr)) { + return gFalse; + } + if (!(tok = getToken(str))) { + error(-1, "Unexpected end of PostScript function stream"); + return gFalse; + } + if (!tok->cmp("{")) { + elsePtr = *codePtr; + if (!parseCode(str, codePtr)) { + return gFalse; + } + delete tok; + if (!(tok = getToken(str))) { + error(-1, "Unexpected end of PostScript function stream"); + return gFalse; + } + } else { + elsePtr = -1; + } + if (!tok->cmp("if")) { + if (elsePtr >= 0) { + error(-1, "Got 'if' operator with two blocks in PostScript function"); + return gFalse; + } + code[opPtr].type = psOperator; + code[opPtr].op = psOpIf; + code[opPtr+2].type = psBlock; + code[opPtr+2].blk = *codePtr; + } else if (!tok->cmp("ifelse")) { + if (elsePtr < 0) { + error(-1, "Got 'ifelse' operator with one blocks in PostScript function"); + return gFalse; + } + code[opPtr].type = psOperator; + code[opPtr].op = psOpIfelse; + code[opPtr+1].type = psBlock; + code[opPtr+1].blk = elsePtr; + code[opPtr+2].type = psBlock; + code[opPtr+2].blk = *codePtr; + } else { + error(-1, "Expected if/ifelse operator in PostScript function"); + delete tok; + return gFalse; + } + delete tok; + } else if (!tok->cmp("}")) { + delete tok; + resizeCode(*codePtr); + code[*codePtr].type = psOperator; + code[*codePtr].op = psOpReturn; + ++*codePtr; + break; + } else { + a = -1; + b = nPSOps; + // invariant: psOpNames[a] < tok < psOpNames[b] + while (b - a > 1) { + mid = (a + b) / 2; + cmp = tok->cmp(psOpNames[mid]); + if (cmp > 0) { + a = mid; + } else if (cmp < 0) { + b = mid; + } else { + a = b = mid; + } + } + if (cmp != 0) { + error(-1, "Unknown operator '%s' in PostScript function", + tok->getCString()); + delete tok; + return gFalse; + } + delete tok; + resizeCode(*codePtr); + code[*codePtr].type = psOperator; + code[*codePtr].op = (PSOp)a; + ++*codePtr; + } + } + return gTrue; +} + +GString *PostScriptFunction::getToken(Stream *str) { + GString *s; + int c; + GBool comment; + + s = new GString(); + comment = gFalse; + while (1) { + if ((c = str->getChar()) == EOF) { + break; + } + codeString->append(c); + if (comment) { + if (c == '\x0a' || c == '\x0d') { + comment = gFalse; + } + } else if (c == '%') { + comment = gTrue; + } else if (!isspace(c)) { + break; + } + } + if (c == '{' || c == '}') { + s->append((char)c); + } else if (isdigit(c) || c == '.' || c == '-') { + while (1) { + s->append((char)c); + c = str->lookChar(); + if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) { + break; + } + str->getChar(); + codeString->append(c); + } + } else { + while (1) { + s->append((char)c); + c = str->lookChar(); + if (c == EOF || !isalnum(c)) { + break; + } + str->getChar(); + codeString->append(c); + } + } + return s; +} + +void PostScriptFunction::resizeCode(int newSize) { + if (newSize >= codeSize) { + codeSize += 64; + code = (PSObject *)greallocn(code, codeSize, sizeof(PSObject)); + } +} + +void PostScriptFunction::exec(PSStack *stack, int codePtr) { + int i1, i2; + double r1, r2; + GBool b1, b2; + + while (1) { + switch (code[codePtr].type) { + case psInt: + stack->pushInt(code[codePtr++].intg); + break; + case psReal: + stack->pushReal(code[codePtr++].real); + break; + case psOperator: + switch (code[codePtr++].op) { + case psOpAbs: + if (stack->topIsInt()) { + stack->pushInt(abs(stack->popInt())); + } else { + stack->pushReal(fabs(stack->popNum())); + } + break; + case psOpAdd: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushInt(i1 + i2); + } else { + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushReal(r1 + r2); + } + break; + case psOpAnd: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushInt(i1 & i2); + } else { + b2 = stack->popBool(); + b1 = stack->popBool(); + stack->pushBool(b1 && b2); + } + break; + case psOpAtan: + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushReal(atan2(r1, r2)); + break; + case psOpBitshift: + i2 = stack->popInt(); + i1 = stack->popInt(); + if (i2 > 0) { + stack->pushInt(i1 << i2); + } else if (i2 < 0) { + stack->pushInt((int)((Guint)i1 >> i2)); + } else { + stack->pushInt(i1); + } + break; + case psOpCeiling: + if (!stack->topIsInt()) { + stack->pushReal(ceil(stack->popNum())); + } + break; + case psOpCopy: + stack->copy(stack->popInt()); + break; + case psOpCos: + stack->pushReal(cos(stack->popNum())); + break; + case psOpCvi: + if (!stack->topIsInt()) { + stack->pushInt((int)stack->popNum()); + } + break; + case psOpCvr: + if (!stack->topIsReal()) { + stack->pushReal(stack->popNum()); + } + break; + case psOpDiv: + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushReal(r1 / r2); + break; + case psOpDup: + stack->copy(1); + break; + case psOpEq: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushBool(i1 == i2); + } else if (stack->topTwoAreNums()) { + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushBool(r1 == r2); + } else { + b2 = stack->popBool(); + b1 = stack->popBool(); + stack->pushBool(b1 == b2); + } + break; + case psOpExch: + stack->roll(2, 1); + break; + case psOpExp: + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushReal(pow(r1, r2)); + break; + case psOpFalse: + stack->pushBool(gFalse); + break; + case psOpFloor: + if (!stack->topIsInt()) { + stack->pushReal(floor(stack->popNum())); + } + break; + case psOpGe: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushBool(i1 >= i2); + } else { + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushBool(r1 >= r2); + } + break; + case psOpGt: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushBool(i1 > i2); + } else { + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushBool(r1 > r2); + } + break; + case psOpIdiv: + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushInt(i1 / i2); + break; + case psOpIndex: + stack->index(stack->popInt()); + break; + case psOpLe: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushBool(i1 <= i2); + } else { + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushBool(r1 <= r2); + } + break; + case psOpLn: + stack->pushReal(log(stack->popNum())); + break; + case psOpLog: + stack->pushReal(log10(stack->popNum())); + break; + case psOpLt: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushBool(i1 < i2); + } else { + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushBool(r1 < r2); + } + break; + case psOpMod: + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushInt(i1 % i2); + break; + case psOpMul: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + //~ should check for out-of-range, and push a real instead + stack->pushInt(i1 * i2); + } else { + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushReal(r1 * r2); + } + break; + case psOpNe: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushBool(i1 != i2); + } else if (stack->topTwoAreNums()) { + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushBool(r1 != r2); + } else { + b2 = stack->popBool(); + b1 = stack->popBool(); + stack->pushBool(b1 != b2); + } + break; + case psOpNeg: + if (stack->topIsInt()) { + stack->pushInt(-stack->popInt()); + } else { + stack->pushReal(-stack->popNum()); + } + break; + case psOpNot: + if (stack->topIsInt()) { + stack->pushInt(~stack->popInt()); + } else { + stack->pushBool(!stack->popBool()); + } + break; + case psOpOr: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushInt(i1 | i2); + } else { + b2 = stack->popBool(); + b1 = stack->popBool(); + stack->pushBool(b1 || b2); + } + break; + case psOpPop: + stack->pop(); + break; + case psOpRoll: + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->roll(i1, i2); + break; + case psOpRound: + if (!stack->topIsInt()) { + r1 = stack->popNum(); + stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5)); + } + break; + case psOpSin: + stack->pushReal(sin(stack->popNum())); + break; + case psOpSqrt: + stack->pushReal(sqrt(stack->popNum())); + break; + case psOpSub: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushInt(i1 - i2); + } else { + r2 = stack->popNum(); + r1 = stack->popNum(); + stack->pushReal(r1 - r2); + } + break; + case psOpTrue: + stack->pushBool(gTrue); + break; + case psOpTruncate: + if (!stack->topIsInt()) { + r1 = stack->popNum(); + stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1)); + } + break; + case psOpXor: + if (stack->topTwoAreInts()) { + i2 = stack->popInt(); + i1 = stack->popInt(); + stack->pushInt(i1 ^ i2); + } else { + b2 = stack->popBool(); + b1 = stack->popBool(); + stack->pushBool(b1 ^ b2); + } + break; + case psOpIf: + b1 = stack->popBool(); + if (b1) { + exec(stack, codePtr + 2); + } + codePtr = code[codePtr + 1].blk; + break; + case psOpIfelse: + b1 = stack->popBool(); + if (b1) { + exec(stack, codePtr + 2); + } else { + exec(stack, code[codePtr].blk); + } + codePtr = code[codePtr + 1].blk; + break; + case psOpReturn: + return; + } + break; + default: + error(-1, "Internal: bad object in PostScript function code"); + break; + } + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Function.h swftools-0.9.1/lib/pdf/xpdf/Function.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Function.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Function.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,229 @@ +//======================================================================== +// +// Function.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FUNCTION_H +#define FUNCTION_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" + +class Dict; +class Stream; +struct PSObject; +class PSStack; + +//------------------------------------------------------------------------ +// Function +//------------------------------------------------------------------------ + +#define funcMaxInputs 32 +#define funcMaxOutputs 32 +#define sampledFuncMaxInputs 16 + +class Function { +public: + + Function(); + + virtual ~Function(); + + // Construct a function. Returns NULL if unsuccessful. + static Function *parse(Object *funcObj); + + // Initialize the entries common to all function types. + GBool init(Dict *dict); + + virtual Function *copy() = 0; + + // Return the function type: + // -1 : identity + // 0 : sampled + // 2 : exponential + // 3 : stitching + // 4 : PostScript + virtual int getType() = 0; + + // Return size of input and output tuples. + int getInputSize() { return m; } + int getOutputSize() { return n; } + + double getDomainMin(int i) { return domain[i][0]; } + double getDomainMax(int i) { return domain[i][1]; } + double getRangeMin(int i) { return range[i][0]; } + double getRangeMax(int i) { return range[i][1]; } + GBool getHasRange() { return hasRange; } + + // Transform an input tuple into an output tuple. + virtual void transform(double *in, double *out) = 0; + + virtual GBool isOk() = 0; + +protected: + + int m, n; // size of input and output tuples + double // min and max values for function domain + domain[funcMaxInputs][2]; + double // min and max values for function range + range[funcMaxOutputs][2]; + GBool hasRange; // set if range is defined +}; + +//------------------------------------------------------------------------ +// IdentityFunction +//------------------------------------------------------------------------ + +class IdentityFunction: public Function { +public: + + IdentityFunction(); + virtual ~IdentityFunction(); + virtual Function *copy() { return new IdentityFunction(); } + virtual int getType() { return -1; } + virtual void transform(double *in, double *out); + virtual GBool isOk() { return gTrue; } + +private: +}; + +//------------------------------------------------------------------------ +// SampledFunction +//------------------------------------------------------------------------ + +class SampledFunction: public Function { +public: + + SampledFunction(Object *funcObj, Dict *dict); + virtual ~SampledFunction(); + virtual Function *copy() { return new SampledFunction(this); } + virtual int getType() { return 0; } + virtual void transform(double *in, double *out); + virtual GBool isOk() { return ok; } + + int getSampleSize(int i) { return sampleSize[i]; } + double getEncodeMin(int i) { return encode[i][0]; } + double getEncodeMax(int i) { return encode[i][1]; } + double getDecodeMin(int i) { return decode[i][0]; } + double getDecodeMax(int i) { return decode[i][1]; } + double *getSamples() { return samples; } + +private: + + SampledFunction(SampledFunction *func); + + int // number of samples for each domain element + sampleSize[funcMaxInputs]; + double // min and max values for domain encoder + encode[funcMaxInputs][2]; + double // min and max values for range decoder + decode[funcMaxOutputs][2]; + double // input multipliers + inputMul[funcMaxInputs]; + int idxMul[funcMaxInputs]; // sample array index multipliers + double *samples; // the samples + int nSamples; // size of the samples array + double *sBuf; // buffer for the transform function + GBool ok; +}; + +//------------------------------------------------------------------------ +// ExponentialFunction +//------------------------------------------------------------------------ + +class ExponentialFunction: public Function { +public: + + ExponentialFunction(Object *funcObj, Dict *dict); + virtual ~ExponentialFunction(); + virtual Function *copy() { return new ExponentialFunction(this); } + virtual int getType() { return 2; } + virtual void transform(double *in, double *out); + virtual GBool isOk() { return ok; } + + double *getC0() { return c0; } + double *getC1() { return c1; } + double getE() { return e; } + +private: + + ExponentialFunction(ExponentialFunction *func); + + double c0[funcMaxOutputs]; + double c1[funcMaxOutputs]; + double e; + GBool ok; +}; + +//------------------------------------------------------------------------ +// StitchingFunction +//------------------------------------------------------------------------ + +class StitchingFunction: public Function { +public: + + StitchingFunction(Object *funcObj, Dict *dict); + virtual ~StitchingFunction(); + virtual Function *copy() { return new StitchingFunction(this); } + virtual int getType() { return 3; } + virtual void transform(double *in, double *out); + virtual GBool isOk() { return ok; } + + int getNumFuncs() { return k; } + Function *getFunc(int i) { return funcs[i]; } + double *getBounds() { return bounds; } + double *getEncode() { return encode; } + double *getScale() { return scale; } + +private: + + StitchingFunction(StitchingFunction *func); + + int k; + Function **funcs; + double *bounds; + double *encode; + double *scale; + GBool ok; +}; + +//------------------------------------------------------------------------ +// PostScriptFunction +//------------------------------------------------------------------------ + +class PostScriptFunction: public Function { +public: + + PostScriptFunction(Object *funcObj, Dict *dict); + virtual ~PostScriptFunction(); + virtual Function *copy() { return new PostScriptFunction(this); } + virtual int getType() { return 4; } + virtual void transform(double *in, double *out); + virtual GBool isOk() { return ok; } + + GString *getCodeString() { return codeString; } + +private: + + PostScriptFunction(PostScriptFunction *func); + GBool parseCode(Stream *str, int *codePtr); + GString *getToken(Stream *str); + void resizeCode(int newSize); + void exec(PSStack *stack, int codePtr); + + GString *codeString; + PSObject *code; + int codeSize; + GBool ok; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/gfile.cc swftools-0.9.1/lib/pdf/xpdf/gfile.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/gfile.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/gfile.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,778 @@ +//======================================================================== +// +// gfile.cc +// +// Miscellaneous file and directory name manipulation. +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef WIN32 +# include +#else +# if defined(MACOS) +# include +# elif !defined(ACORN) +# include +# include +# include +# endif +# include +# include +# if !defined(VMS) && !defined(ACORN) && !defined(MACOS) +# include +# endif +# if defined(VMS) && (__DECCXX_VER < 50200000) +# include +# endif +#endif // WIN32 +#include "GString.h" +#include "gfile.h" + +// Some systems don't define this, so just make it something reasonably +// large. +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +//------------------------------------------------------------------------ + +GString *getHomeDir() { +#ifdef VMS + //---------- VMS ---------- + return new GString("SYS$LOGIN:"); + +#elif defined(__EMX__) || defined(WIN32) + //---------- OS/2+EMX and Win32 ---------- + char *s; + GString *ret; + + if ((s = getenv("HOME"))) + ret = new GString(s); + else + ret = new GString("."); + return ret; + +#elif defined(ACORN) + //---------- RISCOS ---------- + return new GString("@"); + +#elif defined(MACOS) + //---------- MacOS ---------- + return new GString(":"); + +#else + //---------- Unix ---------- + char *s; + struct passwd *pw; + GString *ret; + + if ((s = getenv("HOME"))) { + ret = new GString(s); + } else { + if ((s = getenv("USER"))) + pw = getpwnam(s); + else + pw = getpwuid(getuid()); + if (pw) + ret = new GString(pw->pw_dir); + else + ret = new GString("."); + } + return ret; +#endif +} + +GString *getCurrentDir() { + char buf[PATH_MAX+1]; + +#if defined(__EMX__) + if (_getcwd2(buf, sizeof(buf))) +#elif defined(WIN32) + if (GetCurrentDirectory(sizeof(buf), buf)) +#elif defined(ACORN) + if (strcpy(buf, "@")) +#elif defined(MACOS) + if (strcpy(buf, ":")) +#else + if (getcwd(buf, sizeof(buf))) +#endif + return new GString(buf); + return new GString(); +} + +GString *appendToPath(GString *path, char *fileName) { +#if defined(VMS) + //---------- VMS ---------- + //~ this should handle everything necessary for file + //~ requesters, but it's certainly not complete + char *p0, *p1, *p2; + char *q1; + + p0 = path->getCString(); + p1 = p0 + path->getLength() - 1; + if (!strcmp(fileName, "-")) { + if (*p1 == ']') { + for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ; + if (*p2 == '[') + ++p2; + path->del(p2 - p0, p1 - p2); + } else if (*p1 == ':') { + path->append("[-]"); + } else { + path->clear(); + path->append("[-]"); + } + } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) { + if (*p1 == ']') { + path->insert(p1 - p0, '.'); + path->insert(p1 - p0 + 1, fileName, q1 - fileName); + } else if (*p1 == ':') { + path->append('['); + path->append(']'); + path->append(fileName, q1 - fileName); + } else { + path->clear(); + path->append(fileName, q1 - fileName); + } + } else { + if (*p1 != ']' && *p1 != ':') + path->clear(); + path->append(fileName); + } + return path; + +#elif defined(WIN32) + //---------- Win32 ---------- + GString *tmp; + char buf[256]; + char *fp; + + tmp = new GString(path); + tmp->append('/'); + tmp->append(fileName); + GetFullPathName(tmp->getCString(), sizeof(buf), buf, &fp); + delete tmp; + path->clear(); + path->append(buf); + return path; + +#elif defined(ACORN) + //---------- RISCOS ---------- + char *p; + int i; + + path->append("."); + i = path->getLength(); + path->append(fileName); + for (p = path->getCString() + i; *p; ++p) { + if (*p == '/') { + *p = '.'; + } else if (*p == '.') { + *p = '/'; + } + } + return path; + +#elif defined(MACOS) + //---------- MacOS ---------- + char *p; + int i; + + path->append(":"); + i = path->getLength(); + path->append(fileName); + for (p = path->getCString() + i; *p; ++p) { + if (*p == '/') { + *p = ':'; + } else if (*p == '.') { + *p = ':'; + } + } + return path; + +#elif defined(__EMX__) + //---------- OS/2+EMX ---------- + int i; + + // appending "." does nothing + if (!strcmp(fileName, ".")) + return path; + + // appending ".." goes up one directory + if (!strcmp(fileName, "..")) { + for (i = path->getLength() - 2; i >= 0; --i) { + if (path->getChar(i) == '/' || path->getChar(i) == '\\' || + path->getChar(i) == ':') + break; + } + if (i <= 0) { + if (path->getChar(0) == '/' || path->getChar(0) == '\\') { + path->del(1, path->getLength() - 1); + } else if (path->getLength() >= 2 && path->getChar(1) == ':') { + path->del(2, path->getLength() - 2); + } else { + path->clear(); + path->append(".."); + } + } else { + if (path->getChar(i-1) == ':') + ++i; + path->del(i, path->getLength() - i); + } + return path; + } + + // otherwise, append "/" and new path component + if (path->getLength() > 0 && + path->getChar(path->getLength() - 1) != '/' && + path->getChar(path->getLength() - 1) != '\\') + path->append('/'); + path->append(fileName); + return path; + +#else + //---------- Unix ---------- + int i; + + // appending "." does nothing + if (!strcmp(fileName, ".")) + return path; + + // appending ".." goes up one directory + if (!strcmp(fileName, "..")) { + for (i = path->getLength() - 2; i >= 0; --i) { + if (path->getChar(i) == '/') + break; + } + if (i <= 0) { + if (path->getChar(0) == '/') { + path->del(1, path->getLength() - 1); + } else { + path->clear(); + path->append(".."); + } + } else { + path->del(i, path->getLength() - i); + } + return path; + } + + // otherwise, append "/" and new path component + if (path->getLength() > 0 && + path->getChar(path->getLength() - 1) != '/') + path->append('/'); + path->append(fileName); + return path; +#endif +} + +GString *grabPath(char *fileName) { +#ifdef VMS + //---------- VMS ---------- + char *p; + + if ((p = strrchr(fileName, ']'))) + return new GString(fileName, p + 1 - fileName); + if ((p = strrchr(fileName, ':'))) + return new GString(fileName, p + 1 - fileName); + return new GString(); + +#elif defined(__EMX__) || defined(WIN32) + //---------- OS/2+EMX and Win32 ---------- + char *p; + + if ((p = strrchr(fileName, '/'))) + return new GString(fileName, p - fileName); + if ((p = strrchr(fileName, '\\'))) + return new GString(fileName, p - fileName); + if ((p = strrchr(fileName, ':'))) + return new GString(fileName, p + 1 - fileName); + return new GString(); + +#elif defined(ACORN) + //---------- RISCOS ---------- + char *p; + + if ((p = strrchr(fileName, '.'))) + return new GString(fileName, p - fileName); + return new GString(); + +#elif defined(MACOS) + //---------- MacOS ---------- + char *p; + + if ((p = strrchr(fileName, ':'))) + return new GString(fileName, p - fileName); + return new GString(); + +#else + //---------- Unix ---------- + char *p; + + if ((p = strrchr(fileName, '/'))) + return new GString(fileName, p - fileName); + return new GString(); +#endif +} + +GBool isAbsolutePath(char *path) { +#ifdef VMS + //---------- VMS ---------- + return strchr(path, ':') || + (path[0] == '[' && path[1] != '.' && path[1] != '-'); + +#elif defined(__EMX__) || defined(WIN32) + //---------- OS/2+EMX and Win32 ---------- + return path[0] == '/' || path[0] == '\\' || path[1] == ':'; + +#elif defined(ACORN) + //---------- RISCOS ---------- + return path[0] == '$'; + +#elif defined(MACOS) + //---------- MacOS ---------- + return path[0] != ':'; + +#else + //---------- Unix ---------- + return path[0] == '/'; +#endif +} + +GString *makePathAbsolute(GString *path) { +#ifdef VMS + //---------- VMS ---------- + char buf[PATH_MAX+1]; + + if (!isAbsolutePath(path->getCString())) { + if (getcwd(buf, sizeof(buf))) { + path->insert(0, buf); + } + } + return path; + +#elif defined(WIN32) + //---------- Win32 ---------- + char buf[_MAX_PATH]; + char *fp; + + buf[0] = '\0'; + if (!GetFullPathName(path->getCString(), _MAX_PATH, buf, &fp)) { + path->clear(); + return path; + } + path->clear(); + path->append(buf); + return path; + +#elif defined(ACORN) + //---------- RISCOS ---------- + path->insert(0, '@'); + return path; + +#elif defined(MACOS) + //---------- MacOS ---------- + path->del(0, 1); + return path; + +#else + //---------- Unix and OS/2+EMX ---------- + struct passwd *pw; + char buf[PATH_MAX+1]; + GString *s; + char *p1, *p2; + int n; + + if (path->getChar(0) == '~') { + if (path->getChar(1) == '/' || +#ifdef __EMX__ + path->getChar(1) == '\\' || +#endif + path->getLength() == 1) { + path->del(0, 1); + s = getHomeDir(); + path->insert(0, s); + delete s; + } else { + p1 = path->getCString() + 1; +#ifdef __EMX__ + for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ; +#else + for (p2 = p1; *p2 && *p2 != '/'; ++p2) ; +#endif + if ((n = p2 - p1) > PATH_MAX) + n = PATH_MAX; + strncpy(buf, p1, n); + buf[n] = '\0'; + if ((pw = getpwnam(buf))) { + path->del(0, p2 - p1 + 1); + path->insert(0, pw->pw_dir); + } + } + } else if (!isAbsolutePath(path->getCString())) { + if (getcwd(buf, sizeof(buf))) { +#ifndef __EMX__ + path->insert(0, '/'); +#endif + path->insert(0, buf); + } + } + return path; +#endif +} + +time_t getModTime(char *fileName) { +#ifdef WIN32 + //~ should implement this, but it's (currently) only used in xpdf + return 0; +#else + struct stat statBuf; + + if (stat(fileName, &statBuf)) { + return 0; + } + return statBuf.st_mtime; +#endif +} + +static char* getTempDir() +{ +#ifdef WIN32 + char*dir = getenv("TMP"); + if(!dir) dir = getenv("TEMP"); + if(!dir) dir = getenv("tmp"); + if(!dir) dir = getenv("temp"); + if(!dir) dir = "C:\\"; +#else + char*dir = getenv("SWFTOOLS_TMP"); + if(!dir) dir = "/tmp/"; +#endif + return dir; +} + +char* mktmpname(char*ptr) { + static char tmpbuf[128]; + char*dir = getTempDir(); + int l = strlen(dir); + char*sep = ""; + if(!ptr) + ptr = tmpbuf; + if(l && dir[l-1]!='/' && dir[l-1]!='\\') { +#ifdef WIN32 + sep = "\\"; +#else + sep = "/"; +#endif + } + + // used to be mktemp. This does remove the warnings, but + // It's not exactly an improvement. +#ifdef HAVE_LRAND48 + sprintf(ptr, "%s%s%08x%08x",dir,sep,(unsigned int)lrand48(),(unsigned int)lrand48()); +#else +# ifdef HAVE_RAND + sprintf(ptr, "%s%s%08x%08x",dir,sep,rand(),rand()); +# else + static int count = 1; + sprintf(ptr, "%s%s%08x%04x%04x",dir,sep,time(0),(unsigned int)tmpbuf^((unsigned int)tmpbuf)>>16,count); + count ++; +# endif +#endif + return ptr; +} + + +GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) { +#if defined(WIN32) + //---------- Win32 ---------- + char *tempDir; + GString *s, *s2; + char buf[32]; + FILE *f2; + int t, i; + + // this has the standard race condition problem, but I haven't found + // a better way to generate temp file names with extensions on + // Windows + if ((tempDir = getenv("SWFTOOLS_TMP"))) { + s = new GString(tempDir); + s->append('\\'); + } else { + s = new GString(); + } + s->append("x"); + t = (int)time(NULL); + for (i = 0; i < 1000; ++i) { + sprintf(buf, "%08x-%08x", t + i, GetCurrentThreadId()); + s2 = s->copy()->append(buf); + if (ext) { + s2->append(ext); + } + if (!(f2 = fopen(s2->getCString(), "r"))) { + if (!(f2 = fopen(s2->getCString(), mode))) { + delete s2; + continue; + } + *name = s2; + *f = f2; + delete s; + return gTrue; + } + fclose(f2); + delete s2; + } + fprintf(stderr, "Couldn't create temporary file\n"); + delete s; + return gFalse; +#elif defined(VMS) || defined(__EMX__) || defined(ACORN) || defined(MACOS) + //---------- non-Unix ---------- + char *s; + + // There is a security hole here: an attacker can create a symlink + // with this file name after the tmpnam call and before the fopen + // call. I will happily accept fixes to this function for non-Unix + // OSs. + if (!(s = mktmpname(NULL))) { + return gFalse; + } + *name = new GString(s); + if (ext) { + (*name)->append(ext); + } + if (!(*f = fopen((*name)->getCString(), mode))) { + delete (*name); + return gFalse; + } + return gTrue; +#else + //---------- Unix ---------- + char *s; + int fd; + + if (ext) { +#if HAVE_MKSTEMPS + if ((s = getenv("SWFTOOLS_TMP"))) { + *name = new GString(s); + } else { + *name = new GString("/tmp"); + } + (*name)->append("/XXXXXX")->append(ext); + fd = mkstemps((*name)->getCString(), strlen(ext)); +#else + if (!(s = mktmpname(NULL))) { + return gFalse; + } + *name = new GString(s); + (*name)->append(ext); + fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600); +#endif + } else { +#if HAVE_MKSTEMP + if ((s = getenv("SWFTOOLS_TMP"))) { + *name = new GString(s); + } else { + *name = new GString("/tmp"); + } + (*name)->append("/XXXXXX"); + fd = mkstemp((*name)->getCString()); +#else // HAVE_MKSTEMP + if (!(s = mktmpname(NULL))) { + return gFalse; + } + *name = new GString(s); + fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600); +#endif // HAVE_MKSTEMP + } + if (fd < 0 || !(*f = fdopen(fd, mode))) { + delete *name; + return gFalse; + } + return gTrue; +#endif +} + +GBool executeCommand(char *cmd) { +#ifdef VMS + return system(cmd) ? gTrue : gFalse; +#else + return system(cmd) ? gFalse : gTrue; +#endif +} + +char *getLine(char *buf, int size, FILE *f) { + int c, i; + + i = 0; + while (i < size - 1) { + if ((c = fgetc(f)) == EOF) { + break; + } + buf[i++] = (char)c; + if (c == '\x0a') { + break; + } + if (c == '\x0d') { + c = fgetc(f); + if (c == '\x0a' && i < size - 1) { + buf[i++] = (char)c; + } else if (c != EOF) { + ungetc(c, f); + } + break; + } + } + buf[i] = '\0'; + if (i == 0) { + return NULL; + } + return buf; +} + +//------------------------------------------------------------------------ +// GDir and GDirEntry +//------------------------------------------------------------------------ + +GDirEntry::GDirEntry(char *dirPath, char *nameA, GBool doStat) { +#ifdef VMS + char *p; +#elif defined(WIN32) + int fa; + GString *s; +#elif defined(ACORN) +#else + struct stat st; + GString *s; +#endif + + name = new GString(nameA); + dir = gFalse; + if (doStat) { +#ifdef VMS + if (!strcmp(nameA, "-") || + ((p = strrchr(nameA, '.')) && !strncmp(p, ".DIR;", 5))) + dir = gTrue; +#elif defined(ACORN) +#else + s = new GString(dirPath); + appendToPath(s, nameA); +#ifdef WIN32 + fa = GetFileAttributes(s->getCString()); + dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY)); +#else + if (stat(s->getCString(), &st) == 0) + dir = S_ISDIR(st.st_mode); +#endif + delete s; +#endif + } +} + +GDirEntry::~GDirEntry() { + delete name; +} + +GDir::GDir(char *name, GBool doStatA) { + path = new GString(name); + doStat = doStatA; +#if defined(WIN32) + GString *tmp; + + tmp = path->copy(); + tmp->append("/*.*"); + hnd = FindFirstFile(tmp->getCString(), &ffd); + delete tmp; +#elif defined(ACORN) +#elif defined(MACOS) +#else + dir = opendir(name); +#ifdef VMS + needParent = strchr(name, '[') != NULL; +#endif +#endif +} + +GDir::~GDir() { + delete path; +#if defined(WIN32) + if (hnd) { + FindClose(hnd); + hnd = NULL; + } +#elif defined(ACORN) +#elif defined(MACOS) +#else + if (dir) + closedir(dir); +#endif +} + +GDirEntry *GDir::getNextEntry() { + GDirEntry *e; + +#if defined(WIN32) + if (hnd) { + e = new GDirEntry(path->getCString(), ffd.cFileName, doStat); + if (hnd && !FindNextFile(hnd, &ffd)) { + FindClose(hnd); + hnd = NULL; + } + } else { + e = NULL; + } +#elif defined(ACORN) +#elif defined(MACOS) +#elif defined(VMS) + struct dirent *ent; + e = NULL; + if (dir) { + if (needParent) { + e = new GDirEntry(path->getCString(), "-", doStat); + needParent = gFalse; + return e; + } + ent = readdir(dir); + if (ent) { + e = new GDirEntry(path->getCString(), ent->d_name, doStat); + } + } +#else + struct dirent *ent; + e = NULL; + if (dir) { + ent = (struct dirent *)readdir(dir); + if (ent && !strcmp(ent->d_name, ".")) { + ent = (struct dirent *)readdir(dir); + } + if (ent) { + e = new GDirEntry(path->getCString(), ent->d_name, doStat); + } + } +#endif + + return e; +} + +void GDir::rewind() { +#ifdef WIN32 + GString *tmp; + + if (hnd) + FindClose(hnd); + tmp = path->copy(); + tmp->append("/*.*"); + hnd = FindFirstFile(tmp->getCString(), &ffd); + delete tmp; +#elif defined(ACORN) +#elif defined(MACOS) +#else + if (dir) + rewinddir(dir); +#ifdef VMS + needParent = strchr(path->getCString(), '[') != NULL; +#endif +#endif +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/gfile.h swftools-0.9.1/lib/pdf/xpdf/gfile.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/gfile.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/gfile.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,141 @@ +//======================================================================== +// +// gfile.h +// +// Miscellaneous file and directory name manipulation. +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GFILE_H +#define GFILE_H + +#include +#include +#include +#if defined(WIN32) +# include +# ifdef FPTEX +# include +# else +# include +# endif +#elif defined(ACORN) +#elif defined(MACOS) +# include +#else +# include +# include +# ifdef VMS +# include "vms_dirent.h" +# elif HAVE_DIRENT_H +# include +# define NAMLEN(d) strlen((d)->d_name) +# else +# define dirent direct +# define NAMLEN(d) (d)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +# endif +#endif +#include "gtypes.h" + +class GString; + +//------------------------------------------------------------------------ + +// Get home directory path. +extern GString *getHomeDir(); + +// Get current directory. +extern GString *getCurrentDir(); + +/* create a temporary filename */ +char* mktmpname(char*ptr); + +// Append a file name to a path string. may be an empty +// string, denoting the current directory). Returns . +extern GString *appendToPath(GString *path, char *fileName); + +// Grab the path from the front of the file name. If there is no +// directory component in , returns an empty string. +extern GString *grabPath(char *fileName); + +// Is this an absolute path or file name? +extern GBool isAbsolutePath(char *path); + +// Make this path absolute by prepending current directory (if path is +// relative) or prepending user's directory (if path starts with '~'). +extern GString *makePathAbsolute(GString *path); + +// Get the modification time for . Returns 0 if there is an +// error. +extern time_t getModTime(char *fileName); + +// Create a temporary file and open it for writing. If is not +// NULL, it will be used as the file name extension. Returns both the +// name and the file pointer. For security reasons, all writing +// should be done to the returned file pointer; the file may be +// reopened later for reading, but not for writing. The string +// should be "w" or "wb". Returns true on success. +extern GBool openTempFile(GString **name, FILE **f, char *mode, char *ext); + +// Execute . Returns true on success. +extern GBool executeCommand(char *cmd); + +// Just like fgets, but handles Unix, Mac, and/or DOS end-of-line +// conventions. +extern char *getLine(char *buf, int size, FILE *f); + +//------------------------------------------------------------------------ +// GDir and GDirEntry +//------------------------------------------------------------------------ + +class GDirEntry { +public: + + GDirEntry(char *dirPath, char *nameA, GBool doStat); + ~GDirEntry(); + GString *getName() { return name; } + GBool isDir() { return dir; } + +private: + + GString *name; // dir/file name + GBool dir; // is it a directory? +}; + +class GDir { +public: + + GDir(char *name, GBool doStatA = gTrue); + ~GDir(); + GDirEntry *getNextEntry(); + void rewind(); + +private: + + GString *path; // directory path + GBool doStat; // call stat() for each entry? +#if defined(WIN32) + WIN32_FIND_DATA ffd; + HANDLE hnd; +#elif defined(ACORN) +#elif defined(MACOS) +#else + DIR *dir; // the DIR structure from opendir() +#ifdef VMS + GBool needParent; // need to return an entry for [-] +#endif +#endif +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Gfx.cc swftools-0.9.1/lib/pdf/xpdf/Gfx.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Gfx.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Gfx.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,4197 @@ +//======================================================================== +// +// Gfx.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include "gmem.h" +#include "GlobalParams.h" +#include "CharTypes.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Stream.h" +#include "Lexer.h" +#include "Parser.h" +#include "GfxFont.h" +#include "GfxState.h" +#include "OutputDev.h" +#include "Page.h" +#include "Annot.h" +#include "Error.h" +#include "Gfx.h" + +// the MSVC math.h doesn't define this +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +//------------------------------------------------------------------------ +// constants +//------------------------------------------------------------------------ + +// Max recursive depth for a function shading fill. +#define functionMaxDepth 6 + +// Max delta allowed in any color component for a function shading fill. +#define functionColorDelta (dblToCol(1 / 256.0)) + +// Max number of splits along the t axis for an axial shading fill. +#define axialMaxSplits 256 + +// Max delta allowed in any color component for an axial shading fill. +#define axialColorDelta (dblToCol(1 / 256.0)) + +// Max number of splits along the t axis for a radial shading fill. +#define radialMaxSplits 256 + +// Max delta allowed in any color component for a radial shading fill. +#define radialColorDelta (dblToCol(1 / 256.0)) + +// Max recursive depth for a Gouraud triangle shading fill. +#define gouraudMaxDepth 6 + +// Max delta allowed in any color component for a Gouraud triangle +// shading fill. +#define gouraudColorDelta (dblToCol(1 / 256.0)) + +// Max recursive depth for a patch mesh shading fill. +#define patchMaxDepth 6 + +// Max delta allowed in any color component for a patch mesh shading +// fill. +#define patchColorDelta (dblToCol(1 / 256.0)) + +//------------------------------------------------------------------------ +// Operator table +//------------------------------------------------------------------------ + +#ifdef WIN32 // this works around a bug in the VC7 compiler +# pragma optimize("",off) +#endif + +Operator Gfx::opTab[] = { + {"\"", 3, {tchkNum, tchkNum, tchkString}, + &Gfx::opMoveSetShowText}, + {"'", 1, {tchkString}, + &Gfx::opMoveShowText}, + {"B", 0, {tchkNone}, + &Gfx::opFillStroke}, + {"B*", 0, {tchkNone}, + &Gfx::opEOFillStroke}, + {"BDC", 2, {tchkName, tchkProps}, + &Gfx::opBeginMarkedContent}, + {"BI", 0, {tchkNone}, + &Gfx::opBeginImage}, + {"BMC", 1, {tchkName}, + &Gfx::opBeginMarkedContent}, + {"BT", 0, {tchkNone}, + &Gfx::opBeginText}, + {"BX", 0, {tchkNone}, + &Gfx::opBeginIgnoreUndef}, + {"CS", 1, {tchkName}, + &Gfx::opSetStrokeColorSpace}, + {"DP", 2, {tchkName, tchkProps}, + &Gfx::opMarkPoint}, + {"Do", 1, {tchkName}, + &Gfx::opXObject}, + {"EI", 0, {tchkNone}, + &Gfx::opEndImage}, + {"EMC", 0, {tchkNone}, + &Gfx::opEndMarkedContent}, + {"ET", 0, {tchkNone}, + &Gfx::opEndText}, + {"EX", 0, {tchkNone}, + &Gfx::opEndIgnoreUndef}, + {"F", 0, {tchkNone}, + &Gfx::opFill}, + {"G", 1, {tchkNum}, + &Gfx::opSetStrokeGray}, + {"ID", 0, {tchkNone}, + &Gfx::opImageData}, + {"J", 1, {tchkInt}, + &Gfx::opSetLineCap}, + {"K", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opSetStrokeCMYKColor}, + {"M", 1, {tchkNum}, + &Gfx::opSetMiterLimit}, + {"MP", 1, {tchkName}, + &Gfx::opMarkPoint}, + {"Q", 0, {tchkNone}, + &Gfx::opRestore}, + {"RG", 3, {tchkNum, tchkNum, tchkNum}, + &Gfx::opSetStrokeRGBColor}, + {"S", 0, {tchkNone}, + &Gfx::opStroke}, + {"SC", -4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opSetStrokeColor}, + {"SCN", -33, {tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN}, + &Gfx::opSetStrokeColorN}, + {"T*", 0, {tchkNone}, + &Gfx::opTextNextLine}, + {"TD", 2, {tchkNum, tchkNum}, + &Gfx::opTextMoveSet}, + {"TJ", 1, {tchkArray}, + &Gfx::opShowSpaceText}, + {"TL", 1, {tchkNum}, + &Gfx::opSetTextLeading}, + {"Tc", 1, {tchkNum}, + &Gfx::opSetCharSpacing}, + {"Td", 2, {tchkNum, tchkNum}, + &Gfx::opTextMove}, + {"Tf", 2, {tchkName, tchkNum}, + &Gfx::opSetFont}, + {"Tj", 1, {tchkString}, + &Gfx::opShowText}, + {"Tm", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opSetTextMatrix}, + {"Tr", 1, {tchkInt}, + &Gfx::opSetTextRender}, + {"Ts", 1, {tchkNum}, + &Gfx::opSetTextRise}, + {"Tw", 1, {tchkNum}, + &Gfx::opSetWordSpacing}, + {"Tz", 1, {tchkNum}, + &Gfx::opSetHorizScaling}, + {"W", 0, {tchkNone}, + &Gfx::opClip}, + {"W*", 0, {tchkNone}, + &Gfx::opEOClip}, + {"b", 0, {tchkNone}, + &Gfx::opCloseFillStroke}, + {"b*", 0, {tchkNone}, + &Gfx::opCloseEOFillStroke}, + {"c", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opCurveTo}, + {"cm", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opConcat}, + {"cs", 1, {tchkName}, + &Gfx::opSetFillColorSpace}, + {"d", 2, {tchkArray, tchkNum}, + &Gfx::opSetDash}, + {"d0", 2, {tchkNum, tchkNum}, + &Gfx::opSetCharWidth}, + {"d1", 6, {tchkNum, tchkNum, tchkNum, tchkNum, + tchkNum, tchkNum}, + &Gfx::opSetCacheDevice}, + {"f", 0, {tchkNone}, + &Gfx::opFill}, + {"f*", 0, {tchkNone}, + &Gfx::opEOFill}, + {"g", 1, {tchkNum}, + &Gfx::opSetFillGray}, + {"gs", 1, {tchkName}, + &Gfx::opSetExtGState}, + {"h", 0, {tchkNone}, + &Gfx::opClosePath}, + {"i", 1, {tchkNum}, + &Gfx::opSetFlat}, + {"j", 1, {tchkInt}, + &Gfx::opSetLineJoin}, + {"k", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opSetFillCMYKColor}, + {"l", 2, {tchkNum, tchkNum}, + &Gfx::opLineTo}, + {"m", 2, {tchkNum, tchkNum}, + &Gfx::opMoveTo}, + {"n", 0, {tchkNone}, + &Gfx::opEndPath}, + {"q", 0, {tchkNone}, + &Gfx::opSave}, + {"re", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opRectangle}, + {"rg", 3, {tchkNum, tchkNum, tchkNum}, + &Gfx::opSetFillRGBColor}, + {"ri", 1, {tchkName}, + &Gfx::opSetRenderingIntent}, + {"s", 0, {tchkNone}, + &Gfx::opCloseStroke}, + {"sc", -4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opSetFillColor}, + {"scn", -33, {tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN, tchkSCN, tchkSCN, tchkSCN, + tchkSCN}, + &Gfx::opSetFillColorN}, + {"sh", 1, {tchkName}, + &Gfx::opShFill}, + {"v", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opCurveTo1}, + {"w", 1, {tchkNum}, + &Gfx::opSetLineWidth}, + {"y", 4, {tchkNum, tchkNum, tchkNum, tchkNum}, + &Gfx::opCurveTo2}, +}; + +#ifdef WIN32 // this works around a bug in the VC7 compiler +# pragma optimize("",on) +#endif + +#define numOps (sizeof(opTab) / sizeof(Operator)) + +//------------------------------------------------------------------------ +// GfxResources +//------------------------------------------------------------------------ + +GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) { + Object obj1, obj2; + Ref r; + + if (resDict) { + + // build font dictionary + fonts = NULL; + resDict->lookupNF("Font", &obj1); + if (obj1.isRef()) { + obj1.fetch(xref, &obj2); + if (obj2.isDict()) { + r = obj1.getRef(); + fonts = new GfxFontDict(xref, &r, obj2.getDict()); + } + obj2.free(); + } else if (obj1.isDict()) { + fonts = new GfxFontDict(xref, NULL, obj1.getDict()); + } + obj1.free(); + + // get XObject dictionary + resDict->lookup("XObject", &xObjDict); + + // get color space dictionary + resDict->lookup("ColorSpace", &colorSpaceDict); + + // get pattern dictionary + resDict->lookup("Pattern", &patternDict); + + // get shading dictionary + resDict->lookup("Shading", &shadingDict); + + // get graphics state parameter dictionary + resDict->lookup("ExtGState", &gStateDict); + + } else { + fonts = NULL; + xObjDict.initNull(); + colorSpaceDict.initNull(); + patternDict.initNull(); + shadingDict.initNull(); + gStateDict.initNull(); + } + + next = nextA; +} + +GfxResources::~GfxResources() { + if (fonts) { + delete fonts; + } + xObjDict.free(); + colorSpaceDict.free(); + patternDict.free(); + shadingDict.free(); + gStateDict.free(); +} + +GfxFont *GfxResources::lookupFont(char *name) { + GfxFont *font; + GfxResources *resPtr; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->fonts) { + if ((font = resPtr->fonts->lookup(name))) + return font; + } + } + error(-1, "Unknown font tag '%s'", name); + return NULL; +} + +GBool GfxResources::lookupXObject(char *name, Object *obj) { + GfxResources *resPtr; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->xObjDict.isDict()) { + if (!resPtr->xObjDict.dictLookup(name, obj)->isNull()) + return gTrue; + obj->free(); + } + } + error(-1, "XObject '%s' is unknown", name); + return gFalse; +} + +GBool GfxResources::lookupXObjectNF(char *name, Object *obj) { + GfxResources *resPtr; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->xObjDict.isDict()) { + if (!resPtr->xObjDict.dictLookupNF(name, obj)->isNull()) + return gTrue; + obj->free(); + } + } + error(-1, "XObject '%s' is unknown", name); + return gFalse; +} + +void GfxResources::lookupColorSpace(char *name, Object *obj) { + GfxResources *resPtr; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->colorSpaceDict.isDict()) { + if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) { + return; + } + obj->free(); + } + } + obj->initNull(); +} + +GfxPattern *GfxResources::lookupPattern(char *name) { + GfxResources *resPtr; + GfxPattern *pattern; + Object obj; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->patternDict.isDict()) { + if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) { + pattern = GfxPattern::parse(&obj); + obj.free(); + return pattern; + } + obj.free(); + } + } + error(-1, "Unknown pattern '%s'", name); + return NULL; +} + +GfxShading *GfxResources::lookupShading(char *name) { + GfxResources *resPtr; + GfxShading *shading; + Object obj; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->shadingDict.isDict()) { + if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) { + shading = GfxShading::parse(&obj); + obj.free(); + return shading; + } + obj.free(); + } + } + error(-1, "Unknown shading '%s'", name); + return NULL; +} + +GBool GfxResources::lookupGState(char *name, Object *obj) { + GfxResources *resPtr; + + for (resPtr = this; resPtr; resPtr = resPtr->next) { + if (resPtr->gStateDict.isDict()) { + if (!resPtr->gStateDict.dictLookup(name, obj)->isNull()) { + return gTrue; + } + obj->free(); + } + } + error(-1, "ExtGState '%s' is unknown", name); + return gFalse; +} + +//------------------------------------------------------------------------ +// Gfx +//------------------------------------------------------------------------ + +Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, + double hDPI, double vDPI, PDFRectangle *box, + PDFRectangle *cropBox, int rotate, + GBool (*abortCheckCbkA)(void *data), + void *abortCheckCbkDataA) { + int i; + + xref = xrefA; + subPage = gFalse; + printCommands = globalParams->getPrintCommands(); + parser = NULL; + + // start the resource stack + res = new GfxResources(xref, resDict, NULL); + + // initialize + out = outA; + state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown()); + fontChanged = gFalse; + clip = clipNone; + ignoreUndef = 0; + out->startPage(pageNum, state); + out->setDefaultCTM(state->getCTM()); + out->updateAll(state); + for (i = 0; i < 6; ++i) { + baseMatrix[i] = state->getCTM()[i]; + } + formDepth = 0; + abortCheckCbk = abortCheckCbkA; + abortCheckCbkData = abortCheckCbkDataA; + + // set crop box +#ifdef XPDFEXE + if (cropBox) { + state->moveTo(cropBox->x1, cropBox->y1); + state->lineTo(cropBox->x2, cropBox->y1); + state->lineTo(cropBox->x2, cropBox->y2); + state->lineTo(cropBox->x1, cropBox->y2); + state->closePath(); + state->clip(); + out->clip(state); + state->clearPath(); + } +#endif +} + +Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict, + PDFRectangle *box, PDFRectangle *cropBox, + GBool (*abortCheckCbkA)(void *data), + void *abortCheckCbkDataA) { + int i; + + xref = xrefA; + subPage = gTrue; + printCommands = globalParams->getPrintCommands(); + + // start the resource stack + res = new GfxResources(xref, resDict, NULL); + + // initialize + out = outA; + state = new GfxState(72, 72, box, 0, gFalse); + fontChanged = gFalse; + clip = clipNone; + ignoreUndef = 0; + for (i = 0; i < 6; ++i) { + baseMatrix[i] = state->getCTM()[i]; + } + formDepth = 0; + abortCheckCbk = abortCheckCbkA; + abortCheckCbkData = abortCheckCbkDataA; + + // set crop box + if (cropBox) { + state->moveTo(cropBox->x1, cropBox->y1); + state->lineTo(cropBox->x2, cropBox->y1); + state->lineTo(cropBox->x2, cropBox->y2); + state->lineTo(cropBox->x1, cropBox->y2); + state->closePath(); + state->clip(); + out->clip(state); + state->clearPath(); + } +} + +Gfx::~Gfx() { + while (state->hasSaves()) { + restoreState(); + } + if (!subPage) { + out->endPage(); + } + while (res) { + popResources(); + } + if (state) { + delete state; + } +} + +void Gfx::display(Object *obj, GBool topLevel) { + Object obj2; + int i; + + if (obj->isArray()) { + for (i = 0; i < obj->arrayGetLength(); ++i) { + obj->arrayGet(i, &obj2); + if (!obj2.isStream()) { + error(-1, "Weird page contents"); + obj2.free(); + return; + } + obj2.free(); + } + } else if (!obj->isStream()) { + error(-1, "Weird page contents"); + return; + } + parser = new Parser(xref, new Lexer(xref, obj), gFalse); + go(topLevel); + delete parser; + parser = NULL; +} + +void Gfx::go(GBool topLevel) { + Object obj; + Object args[maxArgs]; + int numArgs, i; + int lastAbortCheck; + + // scan a sequence of objects + updateLevel = lastAbortCheck = 0; + numArgs = 0; + parser->getObj(&obj); + while (!obj.isEOF()) { + + // got a command - execute it + if (obj.isCmd()) { + if (printCommands) { + obj.print(stdout); + for (i = 0; i < numArgs; ++i) { + printf(" "); + args[i].print(stdout); + } + printf("\n"); + fflush(stdout); + } + execOp(&obj, args, numArgs); + obj.free(); + for (i = 0; i < numArgs; ++i) + args[i].free(); + numArgs = 0; + + // periodically update display + if (++updateLevel >= 20000) { + out->dump(); + updateLevel = 0; + } + + // check for an abort + if (abortCheckCbk) { + if (updateLevel - lastAbortCheck > 10) { + if ((*abortCheckCbk)(abortCheckCbkData)) { + break; + } + lastAbortCheck = updateLevel; + } + } + + // got an argument - save it + } else if (numArgs < maxArgs) { + args[numArgs++] = obj; + + // too many arguments - something is wrong + } else { + error(getPos(), "Too many args in content stream"); + if (printCommands) { + printf("throwing away arg: "); + obj.print(stdout); + printf("\n"); + fflush(stdout); + } + obj.free(); + } + + // grab the next object + parser->getObj(&obj); + } + obj.free(); + + // args at end with no command + if (numArgs > 0) { + error(getPos(), "Leftover args in content stream"); + if (printCommands) { + printf("%d leftovers:", numArgs); + for (i = 0; i < numArgs; ++i) { + printf(" "); + args[i].print(stdout); + } + printf("\n"); + fflush(stdout); + } + for (i = 0; i < numArgs; ++i) + args[i].free(); + } + + // update display + if (topLevel && updateLevel > 0) { + out->dump(); + } +} + +void Gfx::execOp(Object *cmd, Object args[], int numArgs) { + Operator *op; + char *name; + Object *argPtr; + int i; + + // find operator + name = cmd->getCmd(); + if (!(op = findOp(name))) { + if (ignoreUndef == 0) + error(getPos(), "Unknown operator '%s'", name); + return; + } + + // type check args + argPtr = args; + if (op->numArgs >= 0) { + if (numArgs < op->numArgs) { + error(getPos(), "Too few (%d) args to '%s' operator", numArgs, name); + return; + } + if (numArgs > op->numArgs) { +#if 0 + error(getPos(), "Too many (%d) args to '%s' operator", numArgs, name); +#endif + argPtr += numArgs - op->numArgs; + numArgs = op->numArgs; + } + } else { + if (numArgs > -op->numArgs) { + error(getPos(), "Too many (%d) args to '%s' operator", + numArgs, name); + return; + } + } + for (i = 0; i < numArgs; ++i) { + if (!checkArg(&argPtr[i], op->tchk[i])) { + error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)", + i, name, argPtr[i].getTypeName()); + return; + } + } + + // do it + (this->*op->func)(argPtr, numArgs); +} + +Operator *Gfx::findOp(char *name) { + int a, b, m, cmp; + + a = -1; + b = numOps; + // invariant: opTab[a] < name < opTab[b] + while (b - a > 1) { + m = (a + b) / 2; + cmp = strcmp(opTab[m].name, name); + if (cmp < 0) + a = m; + else if (cmp > 0) + b = m; + else + a = b = m; + } + if (cmp != 0) + return NULL; + return &opTab[a]; +} + +GBool Gfx::checkArg(Object *arg, TchkType type) { + switch (type) { + case tchkBool: return arg->isBool(); + case tchkInt: return arg->isInt(); + case tchkNum: return arg->isNum(); + case tchkString: return arg->isString(); + case tchkName: return arg->isName(); + case tchkArray: return arg->isArray(); + case tchkProps: return arg->isDict() || arg->isName(); + case tchkSCN: return arg->isNum() || arg->isName(); + case tchkNone: return gFalse; + } + return gFalse; +} + +int Gfx::getPos() { + return parser ? parser->getPos() : -1; +} + +//------------------------------------------------------------------------ +// graphics state operators +//------------------------------------------------------------------------ + +void Gfx::opSave(Object args[], int numArgs) { + saveState(); +} + +void Gfx::opRestore(Object args[], int numArgs) { + restoreState(); +} + +void Gfx::opConcat(Object args[], int numArgs) { + state->concatCTM(args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum(), + args[4].getNum(), args[5].getNum()); + out->updateCTM(state, args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum(), + args[4].getNum(), args[5].getNum()); + fontChanged = gTrue; +} + +void Gfx::opSetDash(Object args[], int numArgs) { + Array *a; + int length; + Object obj; + double *dash; + int i; + + a = args[0].getArray(); + length = a->getLength(); + if (length == 0) { + dash = NULL; + } else { + dash = (double *)gmallocn(length, sizeof(double)); + for (i = 0; i < length; ++i) { + dash[i] = a->get(i, &obj)->getNum(); + obj.free(); + } + } + state->setLineDash(dash, length, args[1].getNum()); + out->updateLineDash(state); +} + +void Gfx::opSetFlat(Object args[], int numArgs) { + state->setFlatness((int)args[0].getNum()); + out->updateFlatness(state); +} + +void Gfx::opSetLineJoin(Object args[], int numArgs) { + state->setLineJoin(args[0].getInt()); + out->updateLineJoin(state); +} + +void Gfx::opSetLineCap(Object args[], int numArgs) { + state->setLineCap(args[0].getInt()); + out->updateLineCap(state); +} + +void Gfx::opSetMiterLimit(Object args[], int numArgs) { + state->setMiterLimit(args[0].getNum()); + out->updateMiterLimit(state); +} + +void Gfx::opSetLineWidth(Object args[], int numArgs) { + state->setLineWidth(args[0].getNum()); + out->updateLineWidth(state); +} + +void Gfx::opSetExtGState(Object args[], int numArgs) { + Object obj1, obj2, obj3, obj4, obj5; + GfxBlendMode mode; + GBool haveFillOP; + Function *funcs[4]; + GfxColor backdropColor; + GBool haveBackdropColor; + GfxColorSpace *blendingColorSpace; + GBool alpha, isolated, knockout; + int i; + + if (!res->lookupGState(args[0].getName(), &obj1)) { + return; + } + if (!obj1.isDict()) { + error(getPos(), "ExtGState '%s' is wrong type", args[0].getName()); + obj1.free(); + return; + } + if (printCommands) { + printf(" gfx state dict: "); + obj1.print(); + printf("\n"); + } + + // transparency support: blend mode, fill/stroke opacity + if (!obj1.dictLookup("BM", &obj2)->isNull()) { + if (state->parseBlendMode(&obj2, &mode)) { + state->setBlendMode(mode); + out->updateBlendMode(state); + } else { + error(getPos(), "Invalid blend mode in ExtGState"); + } + } + obj2.free(); + if (obj1.dictLookup("ca", &obj2)->isNum()) { + state->setFillOpacity(obj2.getNum()); + out->updateFillOpacity(state); + } + obj2.free(); + if (obj1.dictLookup("CA", &obj2)->isNum()) { + state->setStrokeOpacity(obj2.getNum()); + out->updateStrokeOpacity(state); + } + obj2.free(); + + // fill/stroke overprint + if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) { + state->setFillOverprint(obj2.getBool()); + out->updateFillOverprint(state); + } + obj2.free(); + if (obj1.dictLookup("OP", &obj2)->isBool()) { + state->setStrokeOverprint(obj2.getBool()); + out->updateStrokeOverprint(state); + if (!haveFillOP) { + state->setFillOverprint(obj2.getBool()); + out->updateFillOverprint(state); + } + } + obj2.free(); + + // stroke adjust + if (obj1.dictLookup("SA", &obj2)->isBool()) { + state->setStrokeAdjust(obj2.getBool()); + out->updateStrokeAdjust(state); + } + obj2.free(); + + // transfer function + if (obj1.dictLookup("TR2", &obj2)->isNull()) { + obj2.free(); + obj1.dictLookup("TR", &obj2); + } + if (obj2.isName("Default") || + obj2.isName("Identity")) { + funcs[0] = funcs[1] = funcs[2] = funcs[3] = NULL; + state->setTransfer(funcs); + out->updateTransfer(state); + } else if (obj2.isArray() && obj2.arrayGetLength() == 4) { + for (i = 0; i < 4; ++i) { + obj2.arrayGet(i, &obj3); + funcs[i] = Function::parse(&obj3); + obj3.free(); + if (!funcs[i]) { + break; + } + } + if (i == 4) { + state->setTransfer(funcs); + out->updateTransfer(state); + } + } else if (obj2.isName() || obj2.isDict() || obj2.isStream()) { + if ((funcs[0] = Function::parse(&obj2))) { + funcs[1] = funcs[2] = funcs[3] = NULL; + state->setTransfer(funcs); + out->updateTransfer(state); + } + } else if (!obj2.isNull()) { + error(getPos(), "Invalid transfer function in ExtGState"); + } + obj2.free(); + + // soft mask + if (!obj1.dictLookup("SMask", &obj2)->isNull()) { + if (obj2.isName("None")) { + out->clearSoftMask(state); + } else if (obj2.isDict()) { + if (obj2.dictLookup("S", &obj3)->isName("Alpha")) { + alpha = gTrue; + } else { // "Luminosity" + alpha = gFalse; + } + obj3.free(); + funcs[0] = NULL; + if (!obj2.dictLookup("TR", &obj3)->isNull()) { + funcs[0] = Function::parse(&obj3); + if (funcs[0]->getInputSize() != 1 || + funcs[0]->getOutputSize() != 1) { + error(getPos(), + "Invalid transfer function in soft mask in ExtGState"); + delete funcs[0]; + funcs[0] = NULL; + } + } + obj3.free(); + if ((haveBackdropColor = obj2.dictLookup("BC", &obj3)->isArray())) { + for (i = 0; i < gfxColorMaxComps; ++i) { + backdropColor.c[i] = 0; + } + for (i = 0; i < obj3.arrayGetLength() && i < gfxColorMaxComps; ++i) { + obj3.arrayGet(i, &obj4); + if (obj4.isNum()) { + backdropColor.c[i] = dblToCol(obj4.getNum()); + } + obj4.free(); + } + } + obj3.free(); + if (obj2.dictLookup("G", &obj3)->isStream()) { + if (obj3.streamGetDict()->lookup("Group", &obj4)->isDict()) { + blendingColorSpace = NULL; + isolated = knockout = gFalse; + if (!obj4.dictLookup("CS", &obj5)->isNull()) { + blendingColorSpace = GfxColorSpace::parse(&obj5); + } + obj5.free(); + if (obj4.dictLookup("I", &obj5)->isBool()) { + isolated = obj5.getBool(); + } + obj5.free(); + if (obj4.dictLookup("K", &obj5)->isBool()) { + knockout = obj5.getBool(); + } + obj5.free(); + if (!haveBackdropColor) { + if (blendingColorSpace) { + blendingColorSpace->getDefaultColor(&backdropColor); + } else { + //~ need to get the parent or default color space (?) + for (i = 0; i < gfxColorMaxComps; ++i) { + backdropColor.c[i] = 0; + } + } + } + doSoftMask(&obj3, alpha, blendingColorSpace, + isolated, knockout, funcs[0], &backdropColor); + if (funcs[0]) { + delete funcs[0]; + } + } else { + error(getPos(), "Invalid soft mask in ExtGState - missing group"); + } + obj4.free(); + } else { + error(getPos(), "Invalid soft mask in ExtGState - missing group"); + } + obj3.free(); + } else if (!obj2.isNull()) { + error(getPos(), "Invalid soft mask in ExtGState"); + } + } + obj2.free(); + + obj1.free(); +} + +void Gfx::doSoftMask(Object *str, GBool alpha, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + Function *transferFunc, GfxColor *backdropColor) { + Dict *dict, *resDict; + double m[6], bbox[4]; + Object obj1, obj2; + int i; + + // check for excessive recursion + if (formDepth > 20) { + return; + } + + // get stream dict + dict = str->streamGetDict(); + + // check form type + dict->lookup("FormType", &obj1); + if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) { + error(getPos(), "Unknown form type"); + } + obj1.free(); + + // get bounding box + dict->lookup("BBox", &obj1); + if (!obj1.isArray()) { + obj1.free(); + error(getPos(), "Bad form bounding box"); + return; + } + for (i = 0; i < 4; ++i) { + obj1.arrayGet(i, &obj2); + bbox[i] = obj2.getNum(); + obj2.free(); + } + obj1.free(); + + // get matrix + dict->lookup("Matrix", &obj1); + if (obj1.isArray()) { + for (i = 0; i < 6; ++i) { + obj1.arrayGet(i, &obj2); + m[i] = obj2.getNum(); + obj2.free(); + } + } else { + m[0] = 1; m[1] = 0; + m[2] = 0; m[3] = 1; + m[4] = 0; m[5] = 0; + } + obj1.free(); + + // get resources + dict->lookup("Resources", &obj1); + resDict = obj1.isDict() ? obj1.getDict() : (Dict *)NULL; + + // draw it + ++formDepth; + doForm1(str, resDict, m, bbox, gTrue, gTrue, + blendingColorSpace, isolated, knockout, + alpha, transferFunc, backdropColor); + --formDepth; + + if (blendingColorSpace) { + delete blendingColorSpace; + } + obj1.free(); +} + +void Gfx::opSetRenderingIntent(Object args[], int numArgs) { +} + +//------------------------------------------------------------------------ +// color operators +//------------------------------------------------------------------------ + +void Gfx::opSetFillGray(Object args[], int numArgs) { + GfxColor color; + + state->setFillPattern(NULL); + state->setFillColorSpace(new GfxDeviceGrayColorSpace()); + out->updateFillColorSpace(state); + color.c[0] = dblToCol(args[0].getNum()); + state->setFillColor(&color); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeGray(Object args[], int numArgs) { + GfxColor color; + + state->setStrokePattern(NULL); + state->setStrokeColorSpace(new GfxDeviceGrayColorSpace()); + out->updateStrokeColorSpace(state); + color.c[0] = dblToCol(args[0].getNum()); + state->setStrokeColor(&color); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillCMYKColor(Object args[], int numArgs) { + GfxColor color; + int i; + + state->setFillPattern(NULL); + state->setFillColorSpace(new GfxDeviceCMYKColorSpace()); + out->updateFillColorSpace(state); + for (i = 0; i < 4; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setFillColor(&color); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) { + GfxColor color; + int i; + + state->setStrokePattern(NULL); + state->setStrokeColorSpace(new GfxDeviceCMYKColorSpace()); + out->updateStrokeColorSpace(state); + for (i = 0; i < 4; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setStrokeColor(&color); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillRGBColor(Object args[], int numArgs) { + GfxColor color; + int i; + + state->setFillPattern(NULL); + state->setFillColorSpace(new GfxDeviceRGBColorSpace()); + out->updateFillColorSpace(state); + for (i = 0; i < 3; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setFillColor(&color); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) { + GfxColor color; + int i; + + state->setStrokePattern(NULL); + state->setStrokeColorSpace(new GfxDeviceRGBColorSpace()); + out->updateStrokeColorSpace(state); + for (i = 0; i < 3; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setStrokeColor(&color); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillColorSpace(Object args[], int numArgs) { + Object obj; + GfxColorSpace *colorSpace; + GfxColor color; + + state->setFillPattern(NULL); + res->lookupColorSpace(args[0].getName(), &obj); + if (obj.isNull()) { + colorSpace = GfxColorSpace::parse(&args[0]); + } else { + colorSpace = GfxColorSpace::parse(&obj); + } + obj.free(); + if (colorSpace) { + state->setFillColorSpace(colorSpace); + out->updateFillColorSpace(state); + colorSpace->getDefaultColor(&color); + state->setFillColor(&color); + out->updateFillColor(state); + } else { + error(getPos(), "Bad color space (fill)"); + } +} + +void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) { + Object obj; + GfxColorSpace *colorSpace; + GfxColor color; + + state->setStrokePattern(NULL); + res->lookupColorSpace(args[0].getName(), &obj); + if (obj.isNull()) { + colorSpace = GfxColorSpace::parse(&args[0]); + } else { + colorSpace = GfxColorSpace::parse(&obj); + } + obj.free(); + if (colorSpace) { + state->setStrokeColorSpace(colorSpace); + out->updateStrokeColorSpace(state); + colorSpace->getDefaultColor(&color); + state->setStrokeColor(&color); + out->updateStrokeColor(state); + } else { + error(getPos(), "Bad color space (stroke)"); + } +} + +void Gfx::opSetFillColor(Object args[], int numArgs) { + GfxColor color; + int i; + + if (numArgs != state->getFillColorSpace()->getNComps()) { + error(getPos(), "Incorrect number of arguments in 'sc' command"); + return; + } + state->setFillPattern(NULL); + for (i = 0; i < numArgs; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setFillColor(&color); + out->updateFillColor(state); +} + +void Gfx::opSetStrokeColor(Object args[], int numArgs) { + GfxColor color; + int i; + + if (numArgs != state->getStrokeColorSpace()->getNComps()) { + error(getPos(), "Incorrect number of arguments in 'SC' command"); + return; + } + state->setStrokePattern(NULL); + for (i = 0; i < numArgs; ++i) { + color.c[i] = dblToCol(args[i].getNum()); + } + state->setStrokeColor(&color); + out->updateStrokeColor(state); +} + +void Gfx::opSetFillColorN(Object args[], int numArgs) { + GfxColor color; + GfxPattern *pattern; + int i; + + if (state->getFillColorSpace()->getMode() == csPattern) { + if (numArgs > 1) { + if (!((GfxPatternColorSpace *)state->getFillColorSpace())->getUnder() || + numArgs - 1 != ((GfxPatternColorSpace *)state->getFillColorSpace()) + ->getUnder()->getNComps()) { + error(getPos(), "Incorrect number of arguments in 'scn' command"); + return; + } + for (i = 0; i < numArgs - 1 && i < gfxColorMaxComps; ++i) { + if (args[i].isNum()) { + color.c[i] = dblToCol(args[i].getNum()); + } + } + state->setFillColor(&color); + out->updateFillColor(state); + } + if (args[numArgs-1].isName() && + (pattern = res->lookupPattern(args[numArgs-1].getName()))) { + state->setFillPattern(pattern); + } + + } else { + if (numArgs != state->getFillColorSpace()->getNComps()) { + error(getPos(), "Incorrect number of arguments in 'scn' command"); + return; + } + state->setFillPattern(NULL); + for (i = 0; i < numArgs && i < gfxColorMaxComps; ++i) { + if (args[i].isNum()) { + color.c[i] = dblToCol(args[i].getNum()); + } + } + state->setFillColor(&color); + out->updateFillColor(state); + } +} + +void Gfx::opSetStrokeColorN(Object args[], int numArgs) { + GfxColor color; + GfxPattern *pattern; + int i; + + if (state->getStrokeColorSpace()->getMode() == csPattern) { + if (numArgs > 1) { + if (!((GfxPatternColorSpace *)state->getStrokeColorSpace()) + ->getUnder() || + numArgs - 1 != ((GfxPatternColorSpace *)state->getStrokeColorSpace()) + ->getUnder()->getNComps()) { + error(getPos(), "Incorrect number of arguments in 'SCN' command"); + return; + } + for (i = 0; i < numArgs - 1 && i < gfxColorMaxComps; ++i) { + if (args[i].isNum()) { + color.c[i] = dblToCol(args[i].getNum()); + } + } + state->setStrokeColor(&color); + out->updateStrokeColor(state); + } + if (args[numArgs-1].isName() && + (pattern = res->lookupPattern(args[numArgs-1].getName()))) { + state->setStrokePattern(pattern); + } + + } else { + if (numArgs != state->getStrokeColorSpace()->getNComps()) { + error(getPos(), "Incorrect number of arguments in 'SCN' command"); + return; + } + state->setStrokePattern(NULL); + for (i = 0; i < numArgs && i < gfxColorMaxComps; ++i) { + if (args[i].isNum()) { + color.c[i] = dblToCol(args[i].getNum()); + } + } + state->setStrokeColor(&color); + out->updateStrokeColor(state); + } +} + +//------------------------------------------------------------------------ +// path segment operators +//------------------------------------------------------------------------ + +void Gfx::opMoveTo(Object args[], int numArgs) { + state->moveTo(args[0].getNum(), args[1].getNum()); +} + +void Gfx::opLineTo(Object args[], int numArgs) { + if (!state->isCurPt()) { + error(getPos(), "No current point in lineto"); + return; + } + state->lineTo(args[0].getNum(), args[1].getNum()); +} + +void Gfx::opCurveTo(Object args[], int numArgs) { + double x1, y1, x2, y2, x3, y3; + + if (!state->isCurPt()) { + error(getPos(), "No current point in curveto"); + return; + } + x1 = args[0].getNum(); + y1 = args[1].getNum(); + x2 = args[2].getNum(); + y2 = args[3].getNum(); + x3 = args[4].getNum(); + y3 = args[5].getNum(); + state->curveTo(x1, y1, x2, y2, x3, y3); +} + +void Gfx::opCurveTo1(Object args[], int numArgs) { + double x1, y1, x2, y2, x3, y3; + + if (!state->isCurPt()) { + error(getPos(), "No current point in curveto1"); + return; + } + x1 = state->getCurX(); + y1 = state->getCurY(); + x2 = args[0].getNum(); + y2 = args[1].getNum(); + x3 = args[2].getNum(); + y3 = args[3].getNum(); + state->curveTo(x1, y1, x2, y2, x3, y3); +} + +void Gfx::opCurveTo2(Object args[], int numArgs) { + double x1, y1, x2, y2, x3, y3; + + if (!state->isCurPt()) { + error(getPos(), "No current point in curveto2"); + return; + } + x1 = args[0].getNum(); + y1 = args[1].getNum(); + x2 = args[2].getNum(); + y2 = args[3].getNum(); + x3 = x2; + y3 = y2; + state->curveTo(x1, y1, x2, y2, x3, y3); +} + +void Gfx::opRectangle(Object args[], int numArgs) { + double x, y, w, h; + + x = args[0].getNum(); + y = args[1].getNum(); + w = args[2].getNum(); + h = args[3].getNum(); + state->moveTo(x, y); + state->lineTo(x + w, y); + state->lineTo(x + w, y + h); + state->lineTo(x, y + h); + state->closePath(); +} + +void Gfx::opClosePath(Object args[], int numArgs) { + if (!state->isCurPt()) { + error(getPos(), "No current point in closepath"); + return; + } + state->closePath(); +} + +//------------------------------------------------------------------------ +// path painting operators +//------------------------------------------------------------------------ + +void Gfx::opEndPath(Object args[], int numArgs) { + doEndPath(); +} + +void Gfx::opStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in stroke"); + return; + } + if (state->isPath()) { + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + doEndPath(); +} + +void Gfx::opCloseStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in closepath/stroke"); + return; + } + if (state->isPath()) { + state->closePath(); + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + doEndPath(); +} + +void Gfx::opFill(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in fill"); + return; + } + if (state->isPath()) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + } + doEndPath(); +} + +void Gfx::opEOFill(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in eofill"); + return; + } + if (state->isPath()) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + } + doEndPath(); +} + +void Gfx::opFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in fill/stroke"); + return; + } + if (state->isPath()) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + doEndPath(); +} + +void Gfx::opCloseFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in closepath/fill/stroke"); + return; + } + if (state->isPath()) { + state->closePath(); + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + doEndPath(); +} + +void Gfx::opEOFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in eofill/stroke"); + return; + } + if (state->isPath()) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + doEndPath(); +} + +void Gfx::opCloseEOFillStroke(Object args[], int numArgs) { + if (!state->isCurPt()) { + //error(getPos(), "No path in closepath/eofill/stroke"); + return; + } + if (state->isPath()) { + state->closePath(); + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } + } + doEndPath(); +} + +void Gfx::doPatternFill(GBool eoFill) { + GfxPattern *pattern; + + // this is a bit of a kludge -- patterns can be really slow, so we + // skip them if we're only doing text extraction, since they almost + // certainly don't contain any text + if (!out->needNonText()) { + return; + } + + if (!(pattern = state->getFillPattern())) { + return; + } + switch (pattern->getType()) { + case 1: + doTilingPatternFill((GfxTilingPattern *)pattern, gFalse, eoFill); + break; + case 2: + doShadingPatternFill((GfxShadingPattern *)pattern, gFalse, eoFill); + break; + default: + error(getPos(), "Unimplemented pattern type (%d) in fill", + pattern->getType()); + break; + } +} + +void Gfx::doPatternStroke() { + GfxPattern *pattern; + + // this is a bit of a kludge -- patterns can be really slow, so we + // skip them if we're only doing text extraction, since they almost + // certainly don't contain any text + if (!out->needNonText()) { + return; + } + + if (!(pattern = state->getStrokePattern())) { + return; + } + switch (pattern->getType()) { + case 1: + doTilingPatternFill((GfxTilingPattern *)pattern, gTrue, gFalse); + break; + case 2: + doShadingPatternFill((GfxShadingPattern *)pattern, gTrue, gFalse); + break; + default: + error(getPos(), "Unimplemented pattern type (%d) in stroke", + pattern->getType()); + break; + } +} + +void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, + GBool stroke, GBool eoFill) { + GfxPatternColorSpace *patCS; + GfxColorSpace *cs; + GfxPath *savedPath; + double xMin, yMin, xMax, yMax, x, y, x1, y1; + double cxMin, cyMin, cxMax, cyMax; + int xi0, yi0, xi1, yi1, xi, yi; + double *ctm, *btm, *ptm; + double m[6], ictm[6], m1[6], imb[6]; + double det; + double xstep, ystep; + int i; + + // get color space + patCS = (GfxPatternColorSpace *)(stroke ? state->getStrokeColorSpace() + : state->getFillColorSpace()); + + // construct a (pattern space) -> (current space) transform matrix + ctm = state->getCTM(); + btm = baseMatrix; + ptm = tPat->getMatrix(); + // iCTM = invert CTM + det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); + ictm[0] = ctm[3] * det; + ictm[1] = -ctm[1] * det; + ictm[2] = -ctm[2] * det; + ictm[3] = ctm[0] * det; + ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det; + ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det; + // m1 = PTM * BTM = PTM * base transform matrix + m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2]; + m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3]; + m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2]; + m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3]; + m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4]; + m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5]; + // m = m1 * iCTM = (PTM * BTM) * (iCTM) + m[0] = m1[0] * ictm[0] + m1[1] * ictm[2]; + m[1] = m1[0] * ictm[1] + m1[1] * ictm[3]; + m[2] = m1[2] * ictm[0] + m1[3] * ictm[2]; + m[3] = m1[2] * ictm[1] + m1[3] * ictm[3]; + m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4]; + m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5]; + + // construct a (device space) -> (pattern space) transform matrix + det = 1 / (m1[0] * m1[3] - m1[1] * m1[2]); + imb[0] = m1[3] * det; + imb[1] = -m1[1] * det; + imb[2] = -m1[2] * det; + imb[3] = m1[0] * det; + imb[4] = (m1[2] * m1[5] - m1[3] * m1[4]) * det; + imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det; + + // save current graphics state + savedPath = state->getPath()->copy(); + saveState(); + + // set underlying color space (for uncolored tiling patterns); set + // various other parameters (stroke color, line width) to match + // Adobe's behavior + if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) { + state->setFillColorSpace(cs->copy()); + out->updateFillColorSpace(state); + state->setStrokeColorSpace(cs->copy()); + out->updateStrokeColorSpace(state); + state->setStrokeColor(state->getFillColor()); + } else { + state->setFillColorSpace(new GfxDeviceGrayColorSpace()); + out->updateFillColorSpace(state); + state->setStrokeColorSpace(new GfxDeviceGrayColorSpace()); + out->updateStrokeColorSpace(state); + } + state->setFillPattern(NULL); + out->updateFillColor(state); + state->setStrokePattern(NULL); + out->updateStrokeColor(state); + if (!stroke) { + state->setLineWidth(0); + out->updateLineWidth(state); + } + + // clip to current path + if (stroke) { + state->clipToStrokePath(); + out->clipToStrokePath(state); + } else { + state->clip(); + if (eoFill) { + out->eoClip(state); + } else { + out->clip(state); + } + } + state->clearPath(); + + // get the clip region, check for empty + state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax); + if (cxMin > cxMax || cyMin > cyMax) { + goto err; + } + + // transform clip region bbox to pattern space + xMin = xMax = cxMin * imb[0] + cyMin * imb[2] + imb[4]; + yMin = yMax = cxMin * imb[1] + cyMin * imb[3] + imb[5]; + x1 = cxMin * imb[0] + cyMax * imb[2] + imb[4]; + y1 = cxMin * imb[1] + cyMax * imb[3] + imb[5]; + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + x1 = cxMax * imb[0] + cyMin * imb[2] + imb[4]; + y1 = cxMax * imb[1] + cyMin * imb[3] + imb[5]; + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + x1 = cxMax * imb[0] + cyMax * imb[2] + imb[4]; + y1 = cxMax * imb[1] + cyMax * imb[3] + imb[5]; + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + + // draw the pattern + //~ this should treat negative steps differently -- start at right/top + //~ edge instead of left/bottom (?) + xstep = fabs(tPat->getXStep()); + ystep = fabs(tPat->getYStep()); + xi0 = (int)ceil((xMin - tPat->getBBox()[2]) / xstep); + xi1 = (int)floor((xMax - tPat->getBBox()[0]) / xstep) + 1; + yi0 = (int)ceil((yMin - tPat->getBBox()[3]) / ystep); + yi1 = (int)floor((yMax - tPat->getBBox()[1]) / ystep) + 1; + for (i = 0; i < 4; ++i) { + m1[i] = m[i]; + } + if (out->useTilingPatternFill()) { + m1[4] = m[4]; + m1[5] = m[5]; + out->tilingPatternFill(state, tPat->getContentStream(), + tPat->getPaintType(), tPat->getResDict(), + m1, tPat->getBBox(), + xi0, yi0, xi1, yi1, xstep, ystep); + } else { + for (yi = yi0; yi < yi1; ++yi) { + for (xi = xi0; xi < xi1; ++xi) { + x = xi * xstep; + y = yi * ystep; + m1[4] = x * m[0] + y * m[2] + m[4]; + m1[5] = x * m[1] + y * m[3] + m[5]; + doForm1(tPat->getContentStream(), tPat->getResDict(), + m1, tPat->getBBox()); + } + } + } + + // restore graphics state + err: + restoreState(); + state->setPath(savedPath); +} + +void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, + GBool stroke, GBool eoFill) { + GfxShading *shading; + GfxPath *savedPath; + double *ctm, *btm, *ptm; + double m[6], ictm[6], m1[6]; + double xMin, yMin, xMax, yMax; + double det; + + shading = sPat->getShading(); + + // save current graphics state + savedPath = state->getPath()->copy(); + saveState(); + + // clip to bbox + if (shading->getHasBBox()) { + shading->getBBox(&xMin, &yMin, &xMax, &yMax); + state->moveTo(xMin, yMin); + state->lineTo(xMax, yMin); + state->lineTo(xMax, yMax); + state->lineTo(xMin, yMax); + state->closePath(); + state->clip(); + out->clip(state); + state->setPath(savedPath->copy()); + } + + // clip to current path + if (stroke) { + state->clipToStrokePath(); + out->clipToStrokePath(state); + } else { + state->clip(); + if (eoFill) { + out->eoClip(state); + } else { + out->clip(state); + } + } + + // set the color space + state->setFillColorSpace(shading->getColorSpace()->copy()); + out->updateFillColorSpace(state); + + // background color fill + if (shading->getHasBackground()) { + state->setFillColor(shading->getBackground()); + out->updateFillColor(state); + out->fill(state); + } + state->clearPath(); + + // construct a (pattern space) -> (current space) transform matrix + ctm = state->getCTM(); + btm = baseMatrix; + ptm = sPat->getMatrix(); + // iCTM = invert CTM + det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); + ictm[0] = ctm[3] * det; + ictm[1] = -ctm[1] * det; + ictm[2] = -ctm[2] * det; + ictm[3] = ctm[0] * det; + ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det; + ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det; + // m1 = PTM * BTM = PTM * base transform matrix + m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2]; + m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3]; + m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2]; + m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3]; + m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4]; + m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5]; + // m = m1 * iCTM = (PTM * BTM) * (iCTM) + m[0] = m1[0] * ictm[0] + m1[1] * ictm[2]; + m[1] = m1[0] * ictm[1] + m1[1] * ictm[3]; + m[2] = m1[2] * ictm[0] + m1[3] * ictm[2]; + m[3] = m1[2] * ictm[1] + m1[3] * ictm[3]; + m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4]; + m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5]; + + // set the new matrix + state->concatCTM(m[0], m[1], m[2], m[3], m[4], m[5]); + out->updateCTM(state, m[0], m[1], m[2], m[3], m[4], m[5]); + +#if 1 //~tmp: turn off anti-aliasing temporarily + GBool vaa = out->getVectorAntialias(); + if (vaa) { + out->setVectorAntialias(gFalse); + } +#endif + + // do shading type-specific operations + switch (shading->getType()) { + case 1: + doFunctionShFill((GfxFunctionShading *)shading); + break; + case 2: + doAxialShFill((GfxAxialShading *)shading); + break; + case 3: + doRadialShFill((GfxRadialShading *)shading); + break; + case 4: + case 5: + doGouraudTriangleShFill((GfxGouraudTriangleShading *)shading); + break; + case 6: + case 7: + doPatchMeshShFill((GfxPatchMeshShading *)shading); + break; + } + +#if 1 //~tmp: turn off anti-aliasing temporarily + if (vaa) { + out->setVectorAntialias(gTrue); + } +#endif + + // restore graphics state + restoreState(); + state->setPath(savedPath); +} + +void Gfx::opShFill(Object args[], int numArgs) { + GfxShading *shading; + GfxPath *savedPath; + double xMin, yMin, xMax, yMax; + + if (!(shading = res->lookupShading(args[0].getName()))) { + return; + } + + // save current graphics state + savedPath = state->getPath()->copy(); + saveState(); + + // clip to bbox + if (shading->getHasBBox()) { + shading->getBBox(&xMin, &yMin, &xMax, &yMax); + state->moveTo(xMin, yMin); + state->lineTo(xMax, yMin); + state->lineTo(xMax, yMax); + state->lineTo(xMin, yMax); + state->closePath(); + state->clip(); + out->clip(state); + state->clearPath(); + } + + // set the color space + state->setFillColorSpace(shading->getColorSpace()->copy()); + out->updateFillColorSpace(state); + +#if 1 //~tmp: turn off anti-aliasing temporarily + GBool vaa = out->getVectorAntialias(); + if (vaa) { + out->setVectorAntialias(gFalse); + } +#endif + + // do shading type-specific operations + switch (shading->getType()) { + case 1: + doFunctionShFill((GfxFunctionShading *)shading); + break; + case 2: + doAxialShFill((GfxAxialShading *)shading); + break; + case 3: + doRadialShFill((GfxRadialShading *)shading); + break; + case 4: + case 5: + doGouraudTriangleShFill((GfxGouraudTriangleShading *)shading); + break; + case 6: + case 7: + doPatchMeshShFill((GfxPatchMeshShading *)shading); + break; + } + +#if 1 //~tmp: turn off anti-aliasing temporarily + if (vaa) { + out->setVectorAntialias(gTrue); + } +#endif + + // restore graphics state + restoreState(); + state->setPath(savedPath); + + delete shading; +} + +void Gfx::doFunctionShFill(GfxFunctionShading *shading) { + double x0, y0, x1, y1; + GfxColor colors[4]; + + if (out->useShadedFills() && + out->functionShadedFill(state, shading)) { + return; + } + + shading->getDomain(&x0, &y0, &x1, &y1); + shading->getColor(x0, y0, &colors[0]); + shading->getColor(x0, y1, &colors[1]); + shading->getColor(x1, y0, &colors[2]); + shading->getColor(x1, y1, &colors[3]); + doFunctionShFill1(shading, x0, y0, x1, y1, colors, 0); +} + +void Gfx::doFunctionShFill1(GfxFunctionShading *shading, + double x0, double y0, + double x1, double y1, + GfxColor *colors, int depth) { + GfxColor fillColor; + GfxColor color0M, color1M, colorM0, colorM1, colorMM; + GfxColor colors2[4]; + double *matrix; + double xM, yM; + int nComps, i, j; + + nComps = shading->getColorSpace()->getNComps(); + matrix = shading->getMatrix(); + + // compare the four corner colors + for (i = 0; i < 4; ++i) { + for (j = 0; j < nComps; ++j) { + if (abs(colors[i].c[j] - colors[(i+1)&3].c[j]) > functionColorDelta) { + break; + } + } + if (j < nComps) { + break; + } + } + + // center of the rectangle + xM = 0.5 * (x0 + x1); + yM = 0.5 * (y0 + y1); + + // the four corner colors are close (or we hit the recursive limit) + // -- fill the rectangle; but require at least one subdivision + // (depth==0) to avoid problems when the four outer corners of the + // shaded region are the same color + if ((i == 4 && depth > 0) || depth == functionMaxDepth) { + + // use the center color + shading->getColor(xM, yM, &fillColor); + state->setFillColor(&fillColor); + out->updateFillColor(state); + + // fill the rectangle + state->moveTo(x0 * matrix[0] + y0 * matrix[2] + matrix[4], + x0 * matrix[1] + y0 * matrix[3] + matrix[5]); + state->lineTo(x1 * matrix[0] + y0 * matrix[2] + matrix[4], + x1 * matrix[1] + y0 * matrix[3] + matrix[5]); + state->lineTo(x1 * matrix[0] + y1 * matrix[2] + matrix[4], + x1 * matrix[1] + y1 * matrix[3] + matrix[5]); + state->lineTo(x0 * matrix[0] + y1 * matrix[2] + matrix[4], + x0 * matrix[1] + y1 * matrix[3] + matrix[5]); + state->closePath(); + out->fill(state); + state->clearPath(); + + // the four corner colors are not close enough -- subdivide the + // rectangle + } else { + + // colors[0] colorM0 colors[2] + // (x0,y0) (xM,y0) (x1,y0) + // +----------+----------+ + // | | | + // | UL | UR | + // color0M | colorMM | color1M + // (x0,yM) +----------+----------+ (x1,yM) + // | (xM,yM) | + // | LL | LR | + // | | | + // +----------+----------+ + // colors[1] colorM1 colors[3] + // (x0,y1) (xM,y1) (x1,y1) + + shading->getColor(x0, yM, &color0M); + shading->getColor(x1, yM, &color1M); + shading->getColor(xM, y0, &colorM0); + shading->getColor(xM, y1, &colorM1); + shading->getColor(xM, yM, &colorMM); + + // upper-left sub-rectangle + colors2[0] = colors[0]; + colors2[1] = color0M; + colors2[2] = colorM0; + colors2[3] = colorMM; + doFunctionShFill1(shading, x0, y0, xM, yM, colors2, depth + 1); + + // lower-left sub-rectangle + colors2[0] = color0M; + colors2[1] = colors[1]; + colors2[2] = colorMM; + colors2[3] = colorM1; + doFunctionShFill1(shading, x0, yM, xM, y1, colors2, depth + 1); + + // upper-right sub-rectangle + colors2[0] = colorM0; + colors2[1] = colorMM; + colors2[2] = colors[2]; + colors2[3] = color1M; + doFunctionShFill1(shading, xM, y0, x1, yM, colors2, depth + 1); + + // lower-right sub-rectangle + colors2[0] = colorMM; + colors2[1] = colorM1; + colors2[2] = color1M; + colors2[3] = colors[3]; + doFunctionShFill1(shading, xM, yM, x1, y1, colors2, depth + 1); + } +} + +void Gfx::doAxialShFill(GfxAxialShading *shading) { + double xMin, yMin, xMax, yMax; + double x0, y0, x1, y1; + double dx, dy, mul; + GBool dxZero, dyZero; + double tMin, tMax, t, tx, ty; + double s[4], sMin, sMax, tmp; + double ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1; + double t0, t1, tt; + double ta[axialMaxSplits + 1]; + int next[axialMaxSplits + 1]; + GfxColor color0, color1; + int nComps; + int i, j, k, kk; + + if (out->useShadedFills() && + out->axialShadedFill(state, shading)) { + return; + } + + // get the clip region bbox + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + + // compute min and max t values, based on the four corners of the + // clip region bbox + shading->getCoords(&x0, &y0, &x1, &y1); + dx = x1 - x0; + dy = y1 - y0; + dxZero = fabs(dx) < 0.01; + dyZero = fabs(dy) < 0.01; + if (dxZero && dyZero) { + tMin = tMax = 0; + } else { + mul = 1 / (dx * dx + dy * dy); + tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul; + t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul; + if (t < tMin) { + tMin = t; + } else if (t > tMax) { + tMax = t; + } + t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul; + if (t < tMin) { + tMin = t; + } else if (t > tMax) { + tMax = t; + } + t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul; + if (t < tMin) { + tMin = t; + } else if (t > tMax) { + tMax = t; + } + if (tMin < 0 && !shading->getExtend0()) { + tMin = 0; + } + if (tMax > 1 && !shading->getExtend1()) { + tMax = 1; + } + } + + // get the function domain + t0 = shading->getDomain0(); + t1 = shading->getDomain1(); + + // Traverse the t axis and do the shading. + // + // For each point (tx, ty) on the t axis, consider a line through + // that point perpendicular to the t axis: + // + // x(s) = tx + s * -dy --> s = (x - tx) / -dy + // y(s) = ty + s * dx --> s = (y - ty) / dx + // + // Then look at the intersection of this line with the bounding box + // (xMin, yMin, xMax, yMax). In the general case, there are four + // intersection points: + // + // s0 = (xMin - tx) / -dy + // s1 = (xMax - tx) / -dy + // s2 = (yMin - ty) / dx + // s3 = (yMax - ty) / dx + // + // and we want the middle two s values. + // + // In the case where dx = 0, take s0 and s1; in the case where dy = + // 0, take s2 and s3. + // + // Each filled polygon is bounded by two of these line segments + // perpdendicular to the t axis. + // + // The t axis is bisected into smaller regions until the color + // difference across a region is small enough, and then the region + // is painted with a single color. + + // set up: require at least one split to avoid problems when the two + // ends of the t axis have the same color + nComps = shading->getColorSpace()->getNComps(); + ta[0] = tMin; + next[0] = axialMaxSplits / 2; + ta[axialMaxSplits / 2] = 0.5 * (tMin + tMax); + next[axialMaxSplits / 2] = axialMaxSplits; + ta[axialMaxSplits] = tMax; + + // compute the color at t = tMin + if (tMin < 0) { + tt = t0; + } else if (tMin > 1) { + tt = t1; + } else { + tt = t0 + (t1 - t0) * tMin; + } + shading->getColor(tt, &color0); + + // compute the coordinates of the point on the t axis at t = tMin; + // then compute the intersection of the perpendicular line with the + // bounding box + tx = x0 + tMin * dx; + ty = y0 + tMin * dy; + if (dxZero && dyZero) { + sMin = sMax = 0; + } else if (dxZero) { + sMin = (xMin - tx) / -dy; + sMax = (xMax - tx) / -dy; + if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } + } else if (dyZero) { + sMin = (yMin - ty) / dx; + sMax = (yMax - ty) / dx; + if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } + } else { + s[0] = (yMin - ty) / dx; + s[1] = (yMax - ty) / dx; + s[2] = (xMin - tx) / -dy; + s[3] = (xMax - tx) / -dy; + for (j = 0; j < 3; ++j) { + kk = j; + for (k = j + 1; k < 4; ++k) { + if (s[k] < s[kk]) { + kk = k; + } + } + tmp = s[j]; s[j] = s[kk]; s[kk] = tmp; + } + sMin = s[1]; + sMax = s[2]; + } + ux0 = tx - sMin * dy; + uy0 = ty + sMin * dx; + vx0 = tx - sMax * dy; + vy0 = ty + sMax * dx; + + i = 0; + while (i < axialMaxSplits) { + + // bisect until color difference is small enough or we hit the + // bisection limit + j = next[i]; + while (j > i + 1) { + if (ta[j] < 0) { + tt = t0; + } else if (ta[j] > 1) { + tt = t1; + } else { + tt = t0 + (t1 - t0) * ta[j]; + } + shading->getColor(tt, &color1); + for (k = 0; k < nComps; ++k) { + if (abs(color1.c[k] - color0.c[k]) > axialColorDelta) { + break; + } + } + if (k == nComps) { + break; + } + k = (i + j) / 2; + ta[k] = 0.5 * (ta[i] + ta[j]); + next[i] = k; + next[k] = j; + j = k; + } + + // use the average of the colors of the two sides of the region + for (k = 0; k < nComps; ++k) { + color0.c[k] = (color0.c[k] + color1.c[k]) / 2; + } + + // compute the coordinates of the point on the t axis; then + // compute the intersection of the perpendicular line with the + // bounding box + tx = x0 + ta[j] * dx; + ty = y0 + ta[j] * dy; + if (dxZero && dyZero) { + sMin = sMax = 0; + } else if (dxZero) { + sMin = (xMin - tx) / -dy; + sMax = (xMax - tx) / -dy; + if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } + } else if (dyZero) { + sMin = (yMin - ty) / dx; + sMax = (yMax - ty) / dx; + if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } + } else { + s[0] = (yMin - ty) / dx; + s[1] = (yMax - ty) / dx; + s[2] = (xMin - tx) / -dy; + s[3] = (xMax - tx) / -dy; + for (j = 0; j < 3; ++j) { + kk = j; + for (k = j + 1; k < 4; ++k) { + if (s[k] < s[kk]) { + kk = k; + } + } + tmp = s[j]; s[j] = s[kk]; s[kk] = tmp; + } + sMin = s[1]; + sMax = s[2]; + } + ux1 = tx - sMin * dy; + uy1 = ty + sMin * dx; + vx1 = tx - sMax * dy; + vy1 = ty + sMax * dx; + + // set the color + state->setFillColor(&color0); + out->updateFillColor(state); + + // fill the region + state->moveTo(ux0, uy0); + state->lineTo(vx0, vy0); + state->lineTo(vx1, vy1); + state->lineTo(ux1, uy1); + state->closePath(); + out->fill(state); + state->clearPath(); + + // set up for next region + ux0 = ux1; + uy0 = uy1; + vx0 = vx1; + vy0 = vy1; + color0 = color1; + i = next[i]; + } +} + +void Gfx::doRadialShFill(GfxRadialShading *shading) { + double xMin, yMin, xMax, yMax; + double x0, y0, r0, x1, y1, r1, t0, t1; + int nComps; + GfxColor colorA, colorB; + double xa, ya, xb, yb, ra, rb; + double ta, tb, sa, sb; + double sz, xz, yz, sMin, sMax; + GBool enclosed; + int ia, ib, k, n; + double *ctm; + double theta, alpha, angle, t; + + if (out->useShadedFills() && + out->radialShadedFill(state, shading)) { + return; + } + + // get the shading info + shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); + t0 = shading->getDomain0(); + t1 = shading->getDomain1(); + nComps = shading->getColorSpace()->getNComps(); + + // Compute the point at which r(s) = 0; check for the enclosed + // circles case; and compute the angles for the tangent lines. + if (x0 == x1 && y0 == y1) { + enclosed = gTrue; + theta = 0; // make gcc happy + sz = 0; // make gcc happy + } else if (r0 == r1) { + enclosed = gFalse; + theta = 0; + sz = 0; // make gcc happy + } else { + sz = -r0 / (r1 - r0); + xz = x0 + sz * (x1 - x0); + yz = y0 + sz * (y1 - y0); + enclosed = (xz - x0) * (xz - x0) + (yz - y0) * (yz - y0) <= r0 * r0; + theta = asin(r0 / sqrt((x0 - xz) * (x0 - xz) + (y0 - yz) * (y0 - yz))); + if (r0 > r1) { + theta = -theta; + } + } + if (enclosed) { + alpha = 0; + } else { + alpha = atan2(y1 - y0, x1 - x0); + } + + // compute the (possibly extended) s range + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + if (enclosed) { + sMin = 0; + sMax = 1; + } else { + sMin = 1; + sMax = 0; + // solve for x(s) + r(s) = xMin + if ((x1 + r1) - (x0 + r0) != 0) { + sa = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0)); + if (sa < sMin) { + sMin = sa; + } else if (sa > sMax) { + sMax = sa; + } + } + // solve for x(s) - r(s) = xMax + if ((x1 - r1) - (x0 - r0) != 0) { + sa = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0)); + if (sa < sMin) { + sMin = sa; + } else if (sa > sMax) { + sMax = sa; + } + } + // solve for y(s) + r(s) = yMin + if ((y1 + r1) - (y0 + r0) != 0) { + sa = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0)); + if (sa < sMin) { + sMin = sa; + } else if (sa > sMax) { + sMax = sa; + } + } + // solve for y(s) - r(s) = yMax + if ((y1 - r1) - (y0 - r0) != 0) { + sa = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0)); + if (sa < sMin) { + sMin = sa; + } else if (sa > sMax) { + sMax = sa; + } + } + // check against sz + if (r0 < r1) { + if (sMin < sz) { + sMin = sz; + } + } else if (r0 > r1) { + if (sMax > sz) { + sMax = sz; + } + } + // check the 'extend' flags + if (!shading->getExtend0() && sMin < 0) { + sMin = 0; + } + if (!shading->getExtend1() && sMax > 1) { + sMax = 1; + } + } + + // compute the number of steps into which circles must be divided to + // achieve a curve flatness of 0.1 pixel in device space for the + // largest circle (note that "device space" is 72 dpi when generating + // PostScript, hence the relatively small 0.1 pixel accuracy) + ctm = state->getCTM(); + t = fabs(ctm[0]); + if (fabs(ctm[1]) > t) { + t = fabs(ctm[1]); + } + if (fabs(ctm[2]) > t) { + t = fabs(ctm[2]); + } + if (fabs(ctm[3]) > t) { + t = fabs(ctm[3]); + } + if (r0 > r1) { + t *= r0; + } else { + t *= r1; + } + if (t < 1) { + n = 3; + } else { + n = (int)(M_PI / acos(1 - 0.1 / t)); + if (n < 3) { + n = 3; + } else if (n > 200) { + n = 200; + } + } + + // setup for the start circle + ia = 0; + sa = sMin; + ta = t0 + sa * (t1 - t0); + xa = x0 + sa * (x1 - x0); + ya = y0 + sa * (y1 - y0); + ra = r0 + sa * (r1 - r0); + if (ta < t0) { + shading->getColor(t0, &colorA); + } else if (ta > t1) { + shading->getColor(t1, &colorA); + } else { + shading->getColor(ta, &colorA); + } + + // fill the circles + while (ia < radialMaxSplits) { + + // go as far along the t axis (toward t1) as we can, such that the + // color difference is within the tolerance (radialColorDelta) -- + // this uses bisection (between the current value, t, and t1), + // limited to radialMaxSplits points along the t axis; require at + // least one split to avoid problems when the innermost and + // outermost colors are the same + ib = radialMaxSplits; + sb = sMax; + tb = t0 + sb * (t1 - t0); + if (tb < t0) { + shading->getColor(t0, &colorB); + } else if (tb > t1) { + shading->getColor(t1, &colorB); + } else { + shading->getColor(tb, &colorB); + } + while (ib - ia > 1) { + for (k = 0; k < nComps; ++k) { + if (abs(colorB.c[k] - colorA.c[k]) > radialColorDelta) { + break; + } + } + if (k == nComps && ib < radialMaxSplits) { + break; + } + ib = (ia + ib) / 2; + sb = sMin + ((double)ib / (double)radialMaxSplits) * (sMax - sMin); + tb = t0 + sb * (t1 - t0); + if (tb < t0) { + shading->getColor(t0, &colorB); + } else if (tb > t1) { + shading->getColor(t1, &colorB); + } else { + shading->getColor(tb, &colorB); + } + } + + // compute center and radius of the circle + xb = x0 + sb * (x1 - x0); + yb = y0 + sb * (y1 - y0); + rb = r0 + sb * (r1 - r0); + + // use the average of the colors at the two circles + for (k = 0; k < nComps; ++k) { + colorA.c[k] = (colorA.c[k] + colorB.c[k]) / 2; + } + state->setFillColor(&colorA); + out->updateFillColor(state); + + if (enclosed) { + + // construct path for first circle (counterclockwise) + state->moveTo(xa + ra, ya); + for (k = 1; k < n; ++k) { + angle = ((double)k / (double)n) * 2 * M_PI; + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); + + // construct and append path for second circle (clockwise) + state->moveTo(xb + rb, yb); + for (k = 1; k < n; ++k) { + angle = -((double)k / (double)n) * 2 * M_PI; + state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); + } + state->closePath(); + + } else { + + // construct the first subpath (clockwise) + state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI), + ya + ra * sin(alpha + theta + 0.5 * M_PI)); + for (k = 0; k < n; ++k) { + angle = alpha + theta + 0.5 * M_PI + - ((double)k / (double)n) * (2 * theta + M_PI); + state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); + } + for (k = 0; k < n; ++k) { + angle = alpha - theta - 0.5 * M_PI + + ((double)k / (double)n) * (2 * theta - M_PI); + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); + + // construct the second subpath (counterclockwise) + state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI), + ya + ra * sin(alpha + theta + 0.5 * M_PI)); + for (k = 0; k < n; ++k) { + angle = alpha + theta + 0.5 * M_PI + + ((double)k / (double)n) * (-2 * theta + M_PI); + state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); + } + for (k = 0; k < n; ++k) { + angle = alpha - theta - 0.5 * M_PI + + ((double)k / (double)n) * (2 * theta + M_PI); + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); + } + + // fill the path + out->fill(state); + state->clearPath(); + + // step to the next value of t + ia = ib; + sa = sb; + ta = tb; + xa = xb; + ya = yb; + ra = rb; + colorA = colorB; + } + + if (enclosed) { + // extend the smaller circle + if ((shading->getExtend0() && r0 <= r1) || + (shading->getExtend1() && r1 < r0)) { + if (r0 <= r1) { + ta = t0; + ra = r0; + xa = x0; + ya = y0; + } else { + ta = t1; + ra = r1; + xa = x1; + ya = y1; + } + shading->getColor(ta, &colorA); + state->setFillColor(&colorA); + out->updateFillColor(state); + state->moveTo(xa + ra, ya); + for (k = 1; k < n; ++k) { + angle = ((double)k / (double)n) * 2 * M_PI; + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); + out->fill(state); + state->clearPath(); + } + + // extend the larger circle + if ((shading->getExtend0() && r0 > r1) || + (shading->getExtend1() && r1 >= r0)) { + if (r0 > r1) { + ta = t0; + ra = r0; + xa = x0; + ya = y0; + } else { + ta = t1; + ra = r1; + xa = x1; + ya = y1; + } + shading->getColor(ta, &colorA); + state->setFillColor(&colorA); + out->updateFillColor(state); + state->moveTo(xMin, yMin); + state->lineTo(xMin, yMax); + state->lineTo(xMax, yMax); + state->lineTo(xMax, yMin); + state->closePath(); + state->moveTo(xa + ra, ya); + for (k = 1; k < n; ++k) { + angle = ((double)k / (double)n) * 2 * M_PI; + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); + out->fill(state); + state->clearPath(); + } + } +} + +void Gfx::doGouraudTriangleShFill(GfxGouraudTriangleShading *shading) { + double x0, y0, x1, y1, x2, y2; + GfxColor color0, color1, color2; + int i; + + for (i = 0; i < shading->getNTriangles(); ++i) { + shading->getTriangle(i, &x0, &y0, &color0, + &x1, &y1, &color1, + &x2, &y2, &color2); + gouraudFillTriangle(x0, y0, &color0, x1, y1, &color1, x2, y2, &color2, + shading->getColorSpace()->getNComps(), 0); + } +} + +void Gfx::gouraudFillTriangle(double x0, double y0, GfxColor *color0, + double x1, double y1, GfxColor *color1, + double x2, double y2, GfxColor *color2, + int nComps, int depth) { + double x01, y01, x12, y12, x20, y20; + GfxColor color01, color12, color20; + int i; + + for (i = 0; i < nComps; ++i) { + if (abs(color0->c[i] - color1->c[i]) > gouraudColorDelta || + abs(color1->c[i] - color2->c[i]) > gouraudColorDelta) { + break; + } + } + if (i == nComps || depth == gouraudMaxDepth) { + state->setFillColor(color0); + out->updateFillColor(state); + state->moveTo(x0, y0); + state->lineTo(x1, y1); + state->lineTo(x2, y2); + state->closePath(); + out->fill(state); + state->clearPath(); + } else { + x01 = 0.5 * (x0 + x1); + y01 = 0.5 * (y0 + y1); + x12 = 0.5 * (x1 + x2); + y12 = 0.5 * (y1 + y2); + x20 = 0.5 * (x2 + x0); + y20 = 0.5 * (y2 + y0); + //~ if the shading has a Function, this should interpolate on the + //~ function parameter, not on the color components + for (i = 0; i < nComps; ++i) { + color01.c[i] = (color0->c[i] + color1->c[i]) / 2; + color12.c[i] = (color1->c[i] + color2->c[i]) / 2; + color20.c[i] = (color2->c[i] + color0->c[i]) / 2; + } + gouraudFillTriangle(x0, y0, color0, x01, y01, &color01, + x20, y20, &color20, nComps, depth + 1); + gouraudFillTriangle(x01, y01, &color01, x1, y1, color1, + x12, y12, &color12, nComps, depth + 1); + gouraudFillTriangle(x01, y01, &color01, x12, y12, &color12, + x20, y20, &color20, nComps, depth + 1); + gouraudFillTriangle(x20, y20, &color20, x12, y12, &color12, + x2, y2, color2, nComps, depth + 1); + } +} + +void Gfx::doPatchMeshShFill(GfxPatchMeshShading *shading) { + int start, i; + + if (shading->getNPatches() > 128) { + start = 3; + } else if (shading->getNPatches() > 64) { + start = 2; + } else if (shading->getNPatches() > 16) { + start = 1; + } else { + start = 0; + } + for (i = 0; i < shading->getNPatches(); ++i) { + fillPatch(shading->getPatch(i), shading->getColorSpace()->getNComps(), + start); + } +} + +void Gfx::fillPatch(GfxPatch *patch, int nComps, int depth) { + GfxPatch patch00, patch01, patch10, patch11; + double xx[4][8], yy[4][8]; + double xxm, yym; + int i; + + for (i = 0; i < nComps; ++i) { + if (abs(patch->color[0][0].c[i] - patch->color[0][1].c[i]) + > patchColorDelta || + abs(patch->color[0][1].c[i] - patch->color[1][1].c[i]) + > patchColorDelta || + abs(patch->color[1][1].c[i] - patch->color[1][0].c[i]) + > patchColorDelta || + abs(patch->color[1][0].c[i] - patch->color[0][0].c[i]) + > patchColorDelta) { + break; + } + } + if (i == nComps || depth == patchMaxDepth) { + state->setFillColor(&patch->color[0][0]); + out->updateFillColor(state); + state->moveTo(patch->x[0][0], patch->y[0][0]); + state->curveTo(patch->x[0][1], patch->y[0][1], + patch->x[0][2], patch->y[0][2], + patch->x[0][3], patch->y[0][3]); + state->curveTo(patch->x[1][3], patch->y[1][3], + patch->x[2][3], patch->y[2][3], + patch->x[3][3], patch->y[3][3]); + state->curveTo(patch->x[3][2], patch->y[3][2], + patch->x[3][1], patch->y[3][1], + patch->x[3][0], patch->y[3][0]); + state->curveTo(patch->x[2][0], patch->y[2][0], + patch->x[1][0], patch->y[1][0], + patch->x[0][0], patch->y[0][0]); + state->closePath(); + out->fill(state); + state->clearPath(); + } else { + for (i = 0; i < 4; ++i) { + xx[i][0] = patch->x[i][0]; + yy[i][0] = patch->y[i][0]; + xx[i][1] = 0.5 * (patch->x[i][0] + patch->x[i][1]); + yy[i][1] = 0.5 * (patch->y[i][0] + patch->y[i][1]); + xxm = 0.5 * (patch->x[i][1] + patch->x[i][2]); + yym = 0.5 * (patch->y[i][1] + patch->y[i][2]); + xx[i][6] = 0.5 * (patch->x[i][2] + patch->x[i][3]); + yy[i][6] = 0.5 * (patch->y[i][2] + patch->y[i][3]); + xx[i][2] = 0.5 * (xx[i][1] + xxm); + yy[i][2] = 0.5 * (yy[i][1] + yym); + xx[i][5] = 0.5 * (xxm + xx[i][6]); + yy[i][5] = 0.5 * (yym + yy[i][6]); + xx[i][3] = xx[i][4] = 0.5 * (xx[i][2] + xx[i][5]); + yy[i][3] = yy[i][4] = 0.5 * (yy[i][2] + yy[i][5]); + xx[i][7] = patch->x[i][3]; + yy[i][7] = patch->y[i][3]; + } + for (i = 0; i < 4; ++i) { + patch00.x[0][i] = xx[0][i]; + patch00.y[0][i] = yy[0][i]; + patch00.x[1][i] = 0.5 * (xx[0][i] + xx[1][i]); + patch00.y[1][i] = 0.5 * (yy[0][i] + yy[1][i]); + xxm = 0.5 * (xx[1][i] + xx[2][i]); + yym = 0.5 * (yy[1][i] + yy[2][i]); + patch10.x[2][i] = 0.5 * (xx[2][i] + xx[3][i]); + patch10.y[2][i] = 0.5 * (yy[2][i] + yy[3][i]); + patch00.x[2][i] = 0.5 * (patch00.x[1][i] + xxm); + patch00.y[2][i] = 0.5 * (patch00.y[1][i] + yym); + patch10.x[1][i] = 0.5 * (xxm + patch10.x[2][i]); + patch10.y[1][i] = 0.5 * (yym + patch10.y[2][i]); + patch00.x[3][i] = 0.5 * (patch00.x[2][i] + patch10.x[1][i]); + patch00.y[3][i] = 0.5 * (patch00.y[2][i] + patch10.y[1][i]); + patch10.x[0][i] = patch00.x[3][i]; + patch10.y[0][i] = patch00.y[3][i]; + patch10.x[3][i] = xx[3][i]; + patch10.y[3][i] = yy[3][i]; + } + for (i = 4; i < 8; ++i) { + patch01.x[0][i-4] = xx[0][i]; + patch01.y[0][i-4] = yy[0][i]; + patch01.x[1][i-4] = 0.5 * (xx[0][i] + xx[1][i]); + patch01.y[1][i-4] = 0.5 * (yy[0][i] + yy[1][i]); + xxm = 0.5 * (xx[1][i] + xx[2][i]); + yym = 0.5 * (yy[1][i] + yy[2][i]); + patch11.x[2][i-4] = 0.5 * (xx[2][i] + xx[3][i]); + patch11.y[2][i-4] = 0.5 * (yy[2][i] + yy[3][i]); + patch01.x[2][i-4] = 0.5 * (patch01.x[1][i-4] + xxm); + patch01.y[2][i-4] = 0.5 * (patch01.y[1][i-4] + yym); + patch11.x[1][i-4] = 0.5 * (xxm + patch11.x[2][i-4]); + patch11.y[1][i-4] = 0.5 * (yym + patch11.y[2][i-4]); + patch01.x[3][i-4] = 0.5 * (patch01.x[2][i-4] + patch11.x[1][i-4]); + patch01.y[3][i-4] = 0.5 * (patch01.y[2][i-4] + patch11.y[1][i-4]); + patch11.x[0][i-4] = patch01.x[3][i-4]; + patch11.y[0][i-4] = patch01.y[3][i-4]; + patch11.x[3][i-4] = xx[3][i]; + patch11.y[3][i-4] = yy[3][i]; + } + //~ if the shading has a Function, this should interpolate on the + //~ function parameter, not on the color components + for (i = 0; i < nComps; ++i) { + patch00.color[0][0].c[i] = patch->color[0][0].c[i]; + patch00.color[0][1].c[i] = (patch->color[0][0].c[i] + + patch->color[0][1].c[i]) / 2; + patch01.color[0][0].c[i] = patch00.color[0][1].c[i]; + patch01.color[0][1].c[i] = patch->color[0][1].c[i]; + patch01.color[1][1].c[i] = (patch->color[0][1].c[i] + + patch->color[1][1].c[i]) / 2; + patch11.color[0][1].c[i] = patch01.color[1][1].c[i]; + patch11.color[1][1].c[i] = patch->color[1][1].c[i]; + patch11.color[1][0].c[i] = (patch->color[1][1].c[i] + + patch->color[1][0].c[i]) / 2; + patch10.color[1][1].c[i] = patch11.color[1][0].c[i]; + patch10.color[1][0].c[i] = patch->color[1][0].c[i]; + patch10.color[0][0].c[i] = (patch->color[1][0].c[i] + + patch->color[0][0].c[i]) / 2; + patch00.color[1][0].c[i] = patch10.color[0][0].c[i]; + patch00.color[1][1].c[i] = (patch00.color[1][0].c[i] + + patch01.color[1][1].c[i]) / 2; + patch01.color[1][0].c[i] = patch00.color[1][1].c[i]; + patch11.color[0][0].c[i] = patch00.color[1][1].c[i]; + patch10.color[0][1].c[i] = patch00.color[1][1].c[i]; + } + fillPatch(&patch00, nComps, depth + 1); + fillPatch(&patch10, nComps, depth + 1); + fillPatch(&patch01, nComps, depth + 1); + fillPatch(&patch11, nComps, depth + 1); + } +} + +void Gfx::doEndPath() { + if (state->isCurPt() && clip != clipNone) { + state->clip(); + if (clip == clipNormal) { + out->clip(state); + } else { + out->eoClip(state); + } + } + clip = clipNone; + state->clearPath(); +} + +//------------------------------------------------------------------------ +// path clipping operators +//------------------------------------------------------------------------ + +void Gfx::opClip(Object args[], int numArgs) { + clip = clipNormal; +} + +void Gfx::opEOClip(Object args[], int numArgs) { + clip = clipEO; +} + +//------------------------------------------------------------------------ +// text object operators +//------------------------------------------------------------------------ + +void Gfx::opBeginText(Object args[], int numArgs) { + state->setTextMat(1, 0, 0, 1, 0, 0); + state->textMoveTo(0, 0); + out->updateTextMat(state); + out->updateTextPos(state); + fontChanged = gTrue; +} + +void Gfx::opEndText(Object args[], int numArgs) { + out->endTextObject(state); +} + +//------------------------------------------------------------------------ +// text state operators +//------------------------------------------------------------------------ + +void Gfx::opSetCharSpacing(Object args[], int numArgs) { + state->setCharSpace(args[0].getNum()); + out->updateCharSpace(state); +} + +void Gfx::opSetFont(Object args[], int numArgs) { + GfxFont *font; + + if (!(font = res->lookupFont(args[0].getName()))) { + return; + } + if (printCommands) { + printf(" font: tag=%s name='%s' %g\n", + font->getTag()->getCString(), + font->getName() ? font->getName()->getCString() : "???", + args[1].getNum()); + fflush(stdout); + } + state->setFont(font, args[1].getNum()); + fontChanged = gTrue; +} + +void Gfx::opSetTextLeading(Object args[], int numArgs) { + state->setLeading(args[0].getNum()); +} + +void Gfx::opSetTextRender(Object args[], int numArgs) { + state->setRender(args[0].getInt()); + out->updateRender(state); +} + +void Gfx::opSetTextRise(Object args[], int numArgs) { + state->setRise(args[0].getNum()); + out->updateRise(state); +} + +void Gfx::opSetWordSpacing(Object args[], int numArgs) { + state->setWordSpace(args[0].getNum()); + out->updateWordSpace(state); +} + +void Gfx::opSetHorizScaling(Object args[], int numArgs) { + state->setHorizScaling(args[0].getNum()); + out->updateHorizScaling(state); + fontChanged = gTrue; +} + +//------------------------------------------------------------------------ +// text positioning operators +//------------------------------------------------------------------------ + +void Gfx::opTextMove(Object args[], int numArgs) { + double tx, ty; + + tx = state->getLineX() + args[0].getNum(); + ty = state->getLineY() + args[1].getNum(); + state->textMoveTo(tx, ty); + out->updateTextPos(state); +} + +void Gfx::opTextMoveSet(Object args[], int numArgs) { + double tx, ty; + + tx = state->getLineX() + args[0].getNum(); + ty = args[1].getNum(); + state->setLeading(-ty); + ty += state->getLineY(); + state->textMoveTo(tx, ty); + out->updateTextPos(state); +} + +void Gfx::opSetTextMatrix(Object args[], int numArgs) { + state->setTextMat(args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum(), + args[4].getNum(), args[5].getNum()); + state->textMoveTo(0, 0); + out->updateTextMat(state); + out->updateTextPos(state); + fontChanged = gTrue; +} + +void Gfx::opTextNextLine(Object args[], int numArgs) { + double tx, ty; + + tx = state->getLineX(); + ty = state->getLineY() - state->getLeading(); + state->textMoveTo(tx, ty); + out->updateTextPos(state); +} + +//------------------------------------------------------------------------ +// text string operators +//------------------------------------------------------------------------ + +void Gfx::opShowText(Object args[], int numArgs) { + if (!state->getFont()) { + error(getPos(), "No font in show"); + return; + } + if (fontChanged) { + out->updateFont(state); + fontChanged = gFalse; + } + out->beginStringOp(state); + doShowText(args[0].getString()); + out->endStringOp(state); +} + +void Gfx::opMoveShowText(Object args[], int numArgs) { + double tx, ty; + + if (!state->getFont()) { + error(getPos(), "No font in move/show"); + return; + } + if (fontChanged) { + out->updateFont(state); + fontChanged = gFalse; + } + tx = state->getLineX(); + ty = state->getLineY() - state->getLeading(); + state->textMoveTo(tx, ty); + out->updateTextPos(state); + out->beginStringOp(state); + doShowText(args[0].getString()); + out->endStringOp(state); +} + +void Gfx::opMoveSetShowText(Object args[], int numArgs) { + double tx, ty; + + if (!state->getFont()) { + error(getPos(), "No font in move/set/show"); + return; + } + if (fontChanged) { + out->updateFont(state); + fontChanged = gFalse; + } + state->setWordSpace(args[0].getNum()); + state->setCharSpace(args[1].getNum()); + tx = state->getLineX(); + ty = state->getLineY() - state->getLeading(); + state->textMoveTo(tx, ty); + out->updateWordSpace(state); + out->updateCharSpace(state); + out->updateTextPos(state); + out->beginStringOp(state); + doShowText(args[2].getString()); + out->endStringOp(state); +} + +void Gfx::opShowSpaceText(Object args[], int numArgs) { + Array *a; + Object obj; + int wMode; + int i; + + if (!state->getFont()) { + error(getPos(), "No font in show/space"); + return; + } + if (fontChanged) { + out->updateFont(state); + fontChanged = gFalse; + } + out->beginStringOp(state); + wMode = state->getFont()->getWMode(); + a = args[0].getArray(); + for (i = 0; i < a->getLength(); ++i) { + a->get(i, &obj); + if (obj.isNum()) { + // this uses the absolute value of the font size to match + // Acrobat's behavior + if (wMode) { + state->textShift(0, -obj.getNum() * 0.001 * + fabs(state->getFontSize())); + } else { + state->textShift(-obj.getNum() * 0.001 * + fabs(state->getFontSize()), 0); + } + out->updateTextShift(state, obj.getNum()); + } else if (obj.isString()) { + doShowText(obj.getString()); + } else { + error(getPos(), "Element of show/space array must be number or string"); + } + obj.free(); + } + out->endStringOp(state); +} + +void Gfx::doShowText(GString *s) { + GfxFont *font; + int wMode; + double riseX, riseY; + CharCode code; + Unicode u[8]; + double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, lineX, lineY; + double originX, originY, tOriginX, tOriginY; + double oldCTM[6], newCTM[6]; + double *mat; + Object charProc; + Dict *resDict; + Parser *oldParser; + char *p; + int len, n, uLen, nChars, nSpaces, i; + + font = state->getFont(); + wMode = font->getWMode(); + + if (out->useDrawChar()) { + out->beginString(state, s); + } + + // handle a Type 3 char + if (font->getType() == fontType3 && out->interpretType3Chars()) { + mat = state->getCTM(); + for (i = 0; i < 6; ++i) { + oldCTM[i] = mat[i]; + } + mat = state->getTextMat(); + newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2]; + newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3]; + newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2]; + newCTM[3] = mat[2] * oldCTM[1] + mat[3] * oldCTM[3]; + mat = font->getFontMatrix(); + newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2]; + newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3]; + newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2]; + newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3]; + newCTM[0] *= state->getFontSize(); + newCTM[1] *= state->getFontSize(); + newCTM[2] *= state->getFontSize(); + newCTM[3] *= state->getFontSize(); + newCTM[0] *= state->getHorizScaling(); + newCTM[2] *= state->getHorizScaling(); + state->textTransformDelta(0, state->getRise(), &riseX, &riseY); + curX = state->getCurX(); + curY = state->getCurY(); + lineX = state->getLineX(); + lineY = state->getLineY(); + oldParser = parser; + p = s->getCString(); + len = s->getLength(); + while (len > 0) { + n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); + dx = dx * state->getFontSize() + state->getCharSpace(); + if (n == 1 && (*p == ' ' || *p == 0)) { + double w=state->getWordSpace(); + if (w==0 && dx==0) + w=state->getFontSize()/3; // workaround for zero word space + dx += w; + } + dx *= state->getHorizScaling(); + dy *= state->getFontSize(); + state->textTransformDelta(dx, dy, &tdx, &tdy); + state->transform(curX + riseX, curY + riseY, &x, &y); + saveState(); + state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y); + //~ the CTM concat values here are wrong (but never used) + out->updateCTM(state, 1, 0, 0, 1, 0, 0); + if (!out->beginType3Char(state, curX + riseX, curY + riseY, tdx, tdy, + code, u, uLen)) { + ((Gfx8BitFont *)font)->getCharProc(code, &charProc); + if ((resDict = ((Gfx8BitFont *)font)->getResources())) { + pushResources(resDict); + } + if (charProc.isStream()) { + display(&charProc, gFalse); + } else { + error(getPos(), "Missing or bad Type3 CharProc entry"); + } + out->endType3Char(state); + if (resDict) { + popResources(); + } + charProc.free(); + } + restoreState(); + // GfxState::restore() does *not* restore the current position, + // so we deal with it here using (curX, curY) and (lineX, lineY) + curX += tdx; + curY += tdy; + state->moveTo(curX, curY); + state->textSetPos(lineX, lineY); + p += n; + len -= n; + } + parser = oldParser; + + } else if (out->useDrawChar()) { + state->textTransformDelta(0, state->getRise(), &riseX, &riseY); + p = s->getCString(); + len = s->getLength(); + while (len > 0) { + n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); + if (wMode) { + dx *= state->getFontSize(); + dy = dy * state->getFontSize() + state->getCharSpace(); + if (n == 1 && *p == ' ') { + dy += state->getWordSpace(); + } + } else { + dx = dx * state->getFontSize() + state->getCharSpace(); + if (n == 1 && *p == ' ') { + dx += state->getWordSpace(); + } + dx *= state->getHorizScaling(); + dy *= state->getFontSize(); + } + state->textTransformDelta(dx, dy, &tdx, &tdy); + originX *= state->getFontSize(); + originY *= state->getFontSize(); + state->textTransformDelta(originX, originY, &tOriginX, &tOriginY); + out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY, + tdx, tdy, tOriginX, tOriginY, code, n, u, uLen); + state->shift(tdx, tdy); + p += n; + len -= n; + } + + } else { + dx = dy = 0; + p = s->getCString(); + len = s->getLength(); + nChars = nSpaces = 0; + while (len > 0) { + n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx2, &dy2, &originX, &originY); + dx += dx2; + dy += dy2; + if (n == 1 && *p == ' ') { + ++nSpaces; + } + ++nChars; + p += n; + len -= n; + } + if (wMode) { + dx *= state->getFontSize(); + dy = dy * state->getFontSize() + + nChars * state->getCharSpace() + + nSpaces * state->getWordSpace(); + } else { + dx = dx * state->getFontSize() + + nChars * state->getCharSpace() + + nSpaces * state->getWordSpace(); + dx *= state->getHorizScaling(); + dy *= state->getFontSize(); + } + state->textTransformDelta(dx, dy, &tdx, &tdy); + out->drawString(state, s); + state->shift(tdx, tdy); + } + + if (out->useDrawChar()) { + out->endString(state); + } + + updateLevel += 10 * s->getLength(); +} + +//------------------------------------------------------------------------ +// XObject operators +//------------------------------------------------------------------------ + +void Gfx::opXObject(Object args[], int numArgs) { + char *name; + Object obj1, obj2, obj3, refObj; +#if OPI_SUPPORT + Object opiDict; +#endif + + name = args[0].getName(); + if (!res->lookupXObject(name, &obj1)) { + return; + } + if (!obj1.isStream()) { + error(getPos(), "XObject '%s' is wrong type", name); + obj1.free(); + return; + } +#if OPI_SUPPORT + obj1.streamGetDict()->lookup("OPI", &opiDict); + if (opiDict.isDict()) { + out->opiBegin(state, opiDict.getDict()); + } +#endif + obj1.streamGetDict()->lookup("Subtype", &obj2); + if (obj2.isName("Image")) { + if (out->needNonText()) { + res->lookupXObjectNF(name, &refObj); + doImage(&refObj, obj1.getStream(), gFalse); + refObj.free(); + } + } else if (obj2.isName("Form")) { + res->lookupXObjectNF(name, &refObj); + if (out->useDrawForm() && refObj.isRef()) { + out->drawForm(refObj.getRef()); + } else { + doForm(&obj1); + } + refObj.free(); + } else if (obj2.isName("PS")) { + obj1.streamGetDict()->lookup("Level1", &obj3); + out->psXObject(obj1.getStream(), + obj3.isStream() ? obj3.getStream() : (Stream *)NULL); + } else if (obj2.isName()) { + error(getPos(), "Unknown XObject subtype '%s'", obj2.getName()); + } else { + error(getPos(), "XObject subtype is missing or wrong type"); + } + obj2.free(); +#if OPI_SUPPORT + if (opiDict.isDict()) { + out->opiEnd(state, opiDict.getDict()); + } + opiDict.free(); +#endif + obj1.free(); +} + +void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { + Dict *dict, *maskDict; + int width, height; + int bits, maskBits; + StreamColorSpaceMode csMode; + GBool mask; + GBool invert; + GfxColorSpace *colorSpace, *maskColorSpace; + GfxImageColorMap *colorMap, *maskColorMap; + Object maskObj, smaskObj; + GBool haveColorKeyMask, haveExplicitMask, haveSoftMask; + int maskColors[2*gfxColorMaxComps]; + int maskWidth, maskHeight; + GBool maskInvert; + Stream *maskStr; + Object obj1, obj2; + int i; + + // get info from the stream + bits = 0; + csMode = streamCSNone; + str->getImageParams(&bits, &csMode); + + // get stream dict + dict = str->getDict(); + + // get size + dict->lookup("Width", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("W", &obj1); + } + if (!obj1.isInt()) + goto err2; + width = obj1.getInt(); + obj1.free(); + dict->lookup("Height", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("H", &obj1); + } + if (!obj1.isInt()) + goto err2; + height = obj1.getInt(); + obj1.free(); + + // image or mask? + dict->lookup("ImageMask", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("IM", &obj1); + } + mask = gFalse; + if (obj1.isBool()) + mask = obj1.getBool(); + else if (!obj1.isNull()) + goto err2; + obj1.free(); + + // bit depth + if (bits == 0) { + dict->lookup("BitsPerComponent", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("BPC", &obj1); + } + if (obj1.isInt()) { + bits = obj1.getInt(); + } else if (mask) { + bits = 1; + } else { + goto err2; + } + obj1.free(); + } + + // display a mask + if (mask) { + + // check for inverted mask + if (bits != 1) + goto err1; + invert = gFalse; + dict->lookup("Decode", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("D", &obj1); + } + if (obj1.isArray()) { + obj1.arrayGet(0, &obj2); + if (obj2.isInt() && obj2.getInt() == 1) + invert = gTrue; + obj2.free(); + } else if (!obj1.isNull()) { + goto err2; + } + obj1.free(); + + // draw it + out->drawImageMask(state, ref, str, width, height, invert, inlineImg); + + } else { + + // get color space and color map + dict->lookup("ColorSpace", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("CS", &obj1); + } + if (obj1.isName()) { + res->lookupColorSpace(obj1.getName(), &obj2); + if (!obj2.isNull()) { + obj1.free(); + obj1 = obj2; + } else { + obj2.free(); + } + } + if (!obj1.isNull()) { + colorSpace = GfxColorSpace::parse(&obj1, csMode); + } else if (csMode == streamCSDeviceGray) { + colorSpace = new GfxDeviceGrayColorSpace(); + } else if (csMode == streamCSDeviceRGB) { + colorSpace = new GfxDeviceRGBColorSpace(); + } else if (csMode == streamCSDeviceRGBX) { + colorSpace = new GfxDeviceRGBXColorSpace(); + } else if (csMode == streamCSDeviceCMYK) { + colorSpace = new GfxDeviceCMYKColorSpace(); + } else { + colorSpace = NULL; + } + obj1.free(); + if (!colorSpace) { + goto err1; + } + dict->lookup("Decode", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("D", &obj1); + } + colorMap = new GfxImageColorMap(bits, &obj1, colorSpace); + obj1.free(); + if (!colorMap->isOk()) { + delete colorMap; + goto err1; + } + + // get the mask + haveColorKeyMask = haveExplicitMask = haveSoftMask = gFalse; + maskStr = NULL; // make gcc happy + maskWidth = maskHeight = 0; // make gcc happy + maskInvert = gFalse; // make gcc happy + maskColorMap = NULL; // make gcc happy + dict->lookup("Mask", &maskObj); + dict->lookup("SMask", &smaskObj); + if (smaskObj.isStream()) { + // soft mask + if (inlineImg) { + goto err1; + } + maskStr = smaskObj.getStream(); + maskDict = smaskObj.streamGetDict(); + maskDict->lookup("Width", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("W", &obj1); + } + if (!obj1.isInt()) { + goto err2; + } + maskWidth = obj1.getInt(); + obj1.free(); + maskDict->lookup("Height", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("H", &obj1); + } + if (!obj1.isInt()) { + goto err2; + } + maskHeight = obj1.getInt(); + obj1.free(); + maskDict->lookup("BitsPerComponent", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("BPC", &obj1); + } + if (!obj1.isInt()) { + goto err2; + } + maskBits = obj1.getInt(); + obj1.free(); + maskDict->lookup("ColorSpace", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("CS", &obj1); + } + if (obj1.isName()) { + res->lookupColorSpace(obj1.getName(), &obj2); + if (!obj2.isNull()) { + obj1.free(); + obj1 = obj2; + } else { + obj2.free(); + } + } + maskColorSpace = GfxColorSpace::parse(&obj1); + obj1.free(); + if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) { + goto err1; + } + maskDict->lookup("Decode", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("D", &obj1); + } + maskColorMap = new GfxImageColorMap(maskBits, &obj1, maskColorSpace); + obj1.free(); + if (!maskColorMap->isOk()) { + delete maskColorMap; + goto err1; + } + //~ handle the Matte entry + haveSoftMask = gTrue; + } else if (maskObj.isArray()) { + // color key mask + for (i = 0; + i < maskObj.arrayGetLength() && i < 2*gfxColorMaxComps; + ++i) { + maskObj.arrayGet(i, &obj1); + maskColors[i] = obj1.getInt(); + obj1.free(); + } + haveColorKeyMask = gTrue; + } else if (maskObj.isStream()) { + // explicit mask + if (inlineImg) { + goto err1; + } + maskStr = maskObj.getStream(); + maskDict = maskObj.streamGetDict(); + maskDict->lookup("Width", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("W", &obj1); + } + if (!obj1.isInt()) { + goto err2; + } + maskWidth = obj1.getInt(); + obj1.free(); + maskDict->lookup("Height", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("H", &obj1); + } + if (!obj1.isInt()) { + goto err2; + } + maskHeight = obj1.getInt(); + obj1.free(); + maskDict->lookup("ImageMask", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("IM", &obj1); + } + if (!obj1.isBool() || !obj1.getBool()) { + goto err2; + } + obj1.free(); + maskInvert = gFalse; + maskDict->lookup("Decode", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("D", &obj1); + } + if (obj1.isArray()) { + obj1.arrayGet(0, &obj2); + if (obj2.isInt() && obj2.getInt() == 1) { + maskInvert = gTrue; + } + obj2.free(); + } else if (!obj1.isNull()) { + goto err2; + } + obj1.free(); + haveExplicitMask = gTrue; + } + + // draw it + if (haveSoftMask) { + out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, + maskStr, maskWidth, maskHeight, maskColorMap); + delete maskColorMap; + } else if (haveExplicitMask) { + out->drawMaskedImage(state, ref, str, width, height, colorMap, + maskStr, maskWidth, maskHeight, maskInvert); + } else { + out->drawImage(state, ref, str, width, height, colorMap, + haveColorKeyMask ? maskColors : (int *)NULL, inlineImg); + } + delete colorMap; + + maskObj.free(); + smaskObj.free(); + } + + if ((i = width * height) > 1000) { + i = 1000; + } + updateLevel += i; + + return; + + err2: + obj1.free(); + err1: + error(getPos(), "Bad image parameters"); +} + +void Gfx::doForm(Object *str) { + Dict *dict; + GBool transpGroup, isolated, knockout; + GfxColorSpace *blendingColorSpace; + Object matrixObj, bboxObj; + double m[6], bbox[4]; + Object resObj; + Dict *resDict; + Object obj1, obj2, obj3; + int i; + + // check for excessive recursion + if (formDepth > 20) { + return; + } + + // get stream dict + dict = str->streamGetDict(); + + // check form type + dict->lookup("FormType", &obj1); + if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) { + error(getPos(), "Unknown form type"); + } + obj1.free(); + + // get bounding box + dict->lookup("BBox", &bboxObj); + if (!bboxObj.isArray()) { + bboxObj.free(); + error(getPos(), "Bad form bounding box"); + return; + } + for (i = 0; i < 4; ++i) { + bboxObj.arrayGet(i, &obj1); + bbox[i] = obj1.getNum(); + obj1.free(); + } + bboxObj.free(); + + // get matrix + dict->lookup("Matrix", &matrixObj); + if (matrixObj.isArray()) { + for (i = 0; i < 6; ++i) { + matrixObj.arrayGet(i, &obj1); + m[i] = obj1.getNum(); + obj1.free(); + } + } else { + m[0] = 1; m[1] = 0; + m[2] = 0; m[3] = 1; + m[4] = 0; m[5] = 0; + } + matrixObj.free(); + + // get resources + dict->lookup("Resources", &resObj); + resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; + + // check for a transparency group + transpGroup = isolated = knockout = gFalse; + blendingColorSpace = NULL; + if (dict->lookup("Group", &obj1)->isDict()) { + if (obj1.dictLookup("S", &obj2)->isName("Transparency")) { + transpGroup = gTrue; + if (!obj1.dictLookup("CS", &obj3)->isNull()) { + blendingColorSpace = GfxColorSpace::parse(&obj3); + } + obj3.free(); + if (obj1.dictLookup("I", &obj3)->isBool()) { + isolated = obj3.getBool(); + } + obj3.free(); + if (obj1.dictLookup("K", &obj3)->isBool()) { + knockout = obj3.getBool(); + } + obj3.free(); + } + obj2.free(); + } + obj1.free(); + + // draw it + ++formDepth; + doForm1(str, resDict, m, bbox, + transpGroup, gFalse, blendingColorSpace, isolated, knockout); + --formDepth; + + if (blendingColorSpace) { + delete blendingColorSpace; + } + resObj.free(); +} + +void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox, + GBool transpGroup, GBool softMask, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool alpha, Function *transferFunc, + GfxColor *backdropColor) { + Parser *oldParser; + double oldBaseMatrix[6]; + int i; + + // push new resources on stack + pushResources(resDict); + + // save current graphics state + saveState(); + + // kill any pre-existing path + state->clearPath(); + + // save current parser + oldParser = parser; + + // set form transformation matrix + state->concatCTM(matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5]); + out->updateCTM(state, matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5]); + + // set form bounding box + state->moveTo(bbox[0], bbox[1]); + state->lineTo(bbox[2], bbox[1]); + state->lineTo(bbox[2], bbox[3]); + state->lineTo(bbox[0], bbox[3]); + state->closePath(); + state->clip(); + out->clip(state); + state->clearPath(); + + if (softMask || transpGroup) { + if (state->getBlendMode() != gfxBlendNormal) { + state->setBlendMode(gfxBlendNormal); + out->updateBlendMode(state); + } + if (state->getFillOpacity() != 1) { + state->setFillOpacity(1); + out->updateFillOpacity(state); + } + if (state->getStrokeOpacity() != 1) { + state->setStrokeOpacity(1); + out->updateStrokeOpacity(state); + } + out->clearSoftMask(state); + out->beginTransparencyGroup(state, bbox, blendingColorSpace, + isolated, knockout, softMask); + } + GfxState*old_state = state; + + // set new base matrix + for (i = 0; i < 6; ++i) { + oldBaseMatrix[i] = baseMatrix[i]; + baseMatrix[i] = state->getCTM()[i]; + } + + // draw the form + display(str, gFalse); + + if (softMask || transpGroup) { + // restore graphics state + while(state != old_state) + restoreState(); + out->endTransparencyGroup(state); + } + + // restore base matrix + for (i = 0; i < 6; ++i) { + baseMatrix[i] = oldBaseMatrix[i]; + } + + // restore parser + parser = oldParser; + + // restore graphics state + restoreState(); + + // pop resource stack + popResources(); + + if (softMask) { + out->setSoftMask(state, bbox, alpha, transferFunc, backdropColor); + } else if (transpGroup) { + out->paintTransparencyGroup(state, bbox); + } + + return; +} + +//------------------------------------------------------------------------ +// in-line image operators +//------------------------------------------------------------------------ + +void Gfx::opBeginImage(Object args[], int numArgs) { + Stream *str; + int c1, c2; + + // build dict/stream + str = buildImageStream(); + + // display the image + if (str) { + doImage(NULL, str, gTrue); + + // skip 'EI' tag + c1 = str->getUndecodedStream()->getChar(); + c2 = str->getUndecodedStream()->getChar(); + while (!(c1 == 'E' && c2 == 'I') && c2 != EOF) { + c1 = c2; + c2 = str->getUndecodedStream()->getChar(); + } + delete str; + } +} + +Stream *Gfx::buildImageStream() { + Object dict; + Object obj; + char *key; + Stream *str; + + // build dictionary + dict.initDict(xref); + parser->getObj(&obj); + while (!obj.isCmd("ID") && !obj.isEOF()) { + if (!obj.isName()) { + error(getPos(), "Inline image dictionary key must be a name object"); + obj.free(); + } else { + key = copyString(obj.getName()); + obj.free(); + parser->getObj(&obj); + if (obj.isEOF() || obj.isError()) { + gfree(key); + break; + } + dict.dictAdd(key, &obj); + } + parser->getObj(&obj); + } + if (obj.isEOF()) { + error(getPos(), "End of file in inline image"); + obj.free(); + dict.free(); + return NULL; + } + obj.free(); + + // make stream + if(!parser->getStream()) { + error(getPos(), "Couldn't get stream"); + return NULL; + } + str = new EmbedStream(parser->getStream(), &dict, gFalse, 0); + str = str->addFilters(&dict); + + return str; +} + +void Gfx::opImageData(Object args[], int numArgs) { + error(getPos(), "Internal: got 'ID' operator"); +} + +void Gfx::opEndImage(Object args[], int numArgs) { + error(getPos(), "Internal: got 'EI' operator"); +} + +//------------------------------------------------------------------------ +// type 3 font operators +//------------------------------------------------------------------------ + +void Gfx::opSetCharWidth(Object args[], int numArgs) { + out->type3D0(state, args[0].getNum(), args[1].getNum()); +} + +void Gfx::opSetCacheDevice(Object args[], int numArgs) { + out->type3D1(state, args[0].getNum(), args[1].getNum(), + args[2].getNum(), args[3].getNum(), + args[4].getNum(), args[5].getNum()); +} + +//------------------------------------------------------------------------ +// compatibility operators +//------------------------------------------------------------------------ + +void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) { + ++ignoreUndef; +} + +void Gfx::opEndIgnoreUndef(Object args[], int numArgs) { + if (ignoreUndef > 0) + --ignoreUndef; +} + +//------------------------------------------------------------------------ +// marked content operators +//------------------------------------------------------------------------ + +void Gfx::opBeginMarkedContent(Object args[], int numArgs) { + if (printCommands) { + printf(" marked content: %s ", args[0].getName()); + if (numArgs == 2) + args[2].print(stdout); + printf("\n"); + fflush(stdout); + } +} + +void Gfx::opEndMarkedContent(Object args[], int numArgs) { +} + +void Gfx::opMarkPoint(Object args[], int numArgs) { + if (printCommands) { + printf(" mark point: %s ", args[0].getName()); + if (numArgs == 2) + args[2].print(stdout); + printf("\n"); + fflush(stdout); + } +} + +//------------------------------------------------------------------------ +// misc +//------------------------------------------------------------------------ + +void Gfx::drawAnnot(Object *str, AnnotBorderStyle *borderStyle, + double xMin, double yMin, double xMax, double yMax) { + Dict *dict, *resDict; + Object matrixObj, bboxObj, resObj; + Object obj1; + double m[6], bbox[4], ictm[6]; + double *ctm; + double formX0, formY0, formX1, formY1; + double annotX0, annotY0, annotX1, annotY1; + double det, x, y, sx, sy; + double r, g, b; + GfxColor color; + double *dash, *dash2; + int dashLength; + int i; + + //~ can we assume that we're in default user space? + //~ (i.e., baseMatrix = ctm) + + // transform the annotation bbox from default user space to user + // space: (bbox * baseMatrix) * iCTM + ctm = state->getCTM(); + det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); + ictm[0] = ctm[3] * det; + ictm[1] = -ctm[1] * det; + ictm[2] = -ctm[2] * det; + ictm[3] = ctm[0] * det; + ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det; + ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det; + x = baseMatrix[0] * xMin + baseMatrix[2] * yMin + baseMatrix[4]; + y = baseMatrix[1] * xMin + baseMatrix[3] * yMin + baseMatrix[5]; + annotX0 = ictm[0] * x + ictm[2] * y + ictm[4]; + annotY0 = ictm[1] * x + ictm[3] * y + ictm[5]; + x = baseMatrix[0] * xMax + baseMatrix[2] * yMax + baseMatrix[4]; + y = baseMatrix[1] * xMax + baseMatrix[3] * yMax + baseMatrix[5]; + annotX1 = ictm[0] * x + ictm[2] * y + ictm[4]; + annotY1 = ictm[1] * x + ictm[3] * y + ictm[5]; + if (annotX0 > annotX1) { + x = annotX0; annotX0 = annotX1; annotX1 = x; + } + if (annotY0 > annotY1) { + y = annotY0; annotY0 = annotY1; annotY1 = y; + } + + // draw the appearance stream (if there is one) + if (str->isStream()) { + + // get stream dict + dict = str->streamGetDict(); + + // get the form bounding box + dict->lookup("BBox", &bboxObj); + if (!bboxObj.isArray()) { + bboxObj.free(); + error(getPos(), "Bad form bounding box"); + return; + } + for (i = 0; i < 4; ++i) { + bboxObj.arrayGet(i, &obj1); + bbox[i] = obj1.getNum(); + obj1.free(); + } + bboxObj.free(); + + // get the form matrix + dict->lookup("Matrix", &matrixObj); + if (matrixObj.isArray()) { + for (i = 0; i < 6; ++i) { + matrixObj.arrayGet(i, &obj1); + m[i] = obj1.getNum(); + obj1.free(); + } + } else { + m[0] = 1; m[1] = 0; + m[2] = 0; m[3] = 1; + m[4] = 0; m[5] = 0; + } + matrixObj.free(); + + // transform the form bbox from form space to user space + formX0 = bbox[0] * m[0] + bbox[1] * m[2] + m[4]; + formY0 = bbox[0] * m[1] + bbox[1] * m[3] + m[5]; + formX1 = bbox[2] * m[0] + bbox[3] * m[2] + m[4]; + formY1 = bbox[2] * m[1] + bbox[3] * m[3] + m[5]; + if (formX0 > formX1) { + x = formX0; formX0 = formX1; formX1 = x; + } + if (formY0 > formY1) { + y = formY0; formY0 = formY1; formY1 = y; + } + + // scale the form to fit the annotation bbox + if (formX1 == formX0) { + // this shouldn't happen + sx = 1; + } else { + sx = (annotX1 - annotX0) / (formX1 - formX0); + } + if (formY1 == formY0) { + // this shouldn't happen + sy = 1; + } else { + sy = (annotY1 - annotY0) / (formY1 - formY0); + } + m[0] *= sx; + m[2] *= sx; + m[4] = (m[4] - formX0) * sx + annotX0; + m[1] *= sy; + m[3] *= sy; + m[5] = (m[5] - formY0) * sy + annotY0; + + // get resources + dict->lookup("Resources", &resObj); + resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; + + // draw it + doForm1(str, resDict, m, bbox); + + resObj.free(); + } + + // draw the border + if (borderStyle && borderStyle->getWidth() > 0) { + if (state->getStrokeColorSpace()->getMode() != csDeviceRGB) { + state->setStrokePattern(NULL); + state->setStrokeColorSpace(new GfxDeviceRGBColorSpace()); + out->updateStrokeColorSpace(state); + } + borderStyle->getColor(&r, &g, &b); + color.c[0] = dblToCol(r); + color.c[1] = dblToCol(g); + color.c[2] = dblToCol(b); + state->setStrokeColor(&color); + out->updateStrokeColor(state); + // compute the width scale factor when going from default user + // space to user space + x = (baseMatrix[0] + baseMatrix[2]) * ictm[0] + + (baseMatrix[1] + baseMatrix[3]) * ictm[2]; + y = (baseMatrix[0] + baseMatrix[2]) * ictm[1] + + (baseMatrix[1] + baseMatrix[3]) * ictm[3]; + x = sqrt(0.5 * (x * x + y * y)); + state->setLineWidth(x * borderStyle->getWidth()); + out->updateLineWidth(state); + borderStyle->getDash(&dash, &dashLength); + if (borderStyle->getType() == annotBorderDashed && dashLength > 0) { + dash2 = (double *)gmallocn(dashLength, sizeof(double)); + for (i = 0; i < dashLength; ++i) { + dash2[i] = x * dash[i]; + } + state->setLineDash(dash2, dashLength, 0); + out->updateLineDash(state); + } + //~ this doesn't currently handle the beveled and engraved styles + state->clearPath(); + state->moveTo(annotX0, out->upsideDown() ? annotY1 : annotY0); + state->lineTo(annotX1, out->upsideDown() ? annotY1 : annotY0); + if (borderStyle->getType() != annotBorderUnderlined) { + state->lineTo(annotX1, out->upsideDown() ? annotY0 : annotY1); + state->lineTo(annotX0, out->upsideDown() ? annotY0 : annotY1); + state->closePath(); + } + out->stroke(state); + } +} + +void Gfx::saveState() { + out->saveState(state); + state = state->save(); +} + +void Gfx::restoreState() { + state = state->restore(); + out->restoreState(state); +} + +void Gfx::pushResources(Dict *resDict) { + res = new GfxResources(xref, resDict, res); +} + +void Gfx::popResources() { + GfxResources *resPtr; + + resPtr = res->getNext(); + delete res; + res = resPtr; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GfxFont.cc swftools-0.9.1/lib/pdf/xpdf/GfxFont.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/GfxFont.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GfxFont.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,1576 @@ +//======================================================================== +// +// GfxFont.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gmem.h" +#include "Error.h" +#include "Object.h" +#include "Dict.h" +#include "GlobalParams.h" +#include "CMap.h" +#include "CharCodeToUnicode.h" +#include "FontEncodingTables.h" +#include "BuiltinFontTables.h" +#include "FoFiType1.h" +#include "FoFiType1C.h" +#include "FoFiTrueType.h" +#include "GfxFont.h" + +//------------------------------------------------------------------------ + +struct StdFontMapEntry { + char *altName; + char *properName; +}; + +// Acrobat 4.0 and earlier substituted Base14-compatible fonts without +// providing Widths and a FontDescriptor, so we munge the names into +// the proper Base14 names. This table is from implementation note 44 +// in the PDF 1.4 spec, with some additions based on empirical +// evidence. +static StdFontMapEntry stdFontMap[] = { + { "Arial", "Helvetica" }, + { "Arial,Bold", "Helvetica-Bold" }, + { "Arial,BoldItalic", "Helvetica-BoldOblique" }, + { "Arial,Italic", "Helvetica-Oblique" }, + { "Arial-Bold", "Helvetica-Bold" }, + { "Arial-BoldItalic", "Helvetica-BoldOblique" }, + { "Arial-BoldItalicMT", "Helvetica-BoldOblique" }, + { "Arial-BoldMT", "Helvetica-Bold" }, + { "Arial-Italic", "Helvetica-Oblique" }, + { "Arial-ItalicMT", "Helvetica-Oblique" }, + { "ArialMT", "Helvetica" }, + { "Courier,Bold", "Courier-Bold" }, + { "Courier,BoldItalic", "Courier-BoldOblique" }, + { "Courier,Italic", "Courier-Oblique" }, + { "CourierNew", "Courier" }, + { "CourierNew,Bold", "Courier-Bold" }, + { "CourierNew,BoldItalic", "Courier-BoldOblique" }, + { "CourierNew,Italic", "Courier-Oblique" }, + { "CourierNew-Bold", "Courier-Bold" }, + { "CourierNew-BoldItalic", "Courier-BoldOblique" }, + { "CourierNew-Italic", "Courier-Oblique" }, + { "CourierNewPS-BoldItalicMT", "Courier-BoldOblique" }, + { "CourierNewPS-BoldMT", "Courier-Bold" }, + { "CourierNewPS-ItalicMT", "Courier-Oblique" }, + { "CourierNewPSMT", "Courier" }, + { "Helvetica,Bold", "Helvetica-Bold" }, + { "Helvetica,BoldItalic", "Helvetica-BoldOblique" }, + { "Helvetica,Italic", "Helvetica-Oblique" }, + { "Helvetica-BoldItalic", "Helvetica-BoldOblique" }, + { "Helvetica-Italic", "Helvetica-Oblique" }, + { "Symbol,Bold", "Symbol" }, + { "Symbol,BoldItalic", "Symbol" }, + { "Symbol,Italic", "Symbol" }, + { "TimesNewRoman", "Times-Roman" }, + { "TimesNewRoman,Bold", "Times-Bold" }, + { "TimesNewRoman,BoldItalic", "Times-BoldItalic" }, + { "TimesNewRoman,Italic", "Times-Italic" }, + { "TimesNewRoman-Bold", "Times-Bold" }, + { "TimesNewRoman-BoldItalic", "Times-BoldItalic" }, + { "TimesNewRoman-Italic", "Times-Italic" }, + { "TimesNewRomanPS", "Times-Roman" }, + { "TimesNewRomanPS-Bold", "Times-Bold" }, + { "TimesNewRomanPS-BoldItalic", "Times-BoldItalic" }, + { "TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic" }, + { "TimesNewRomanPS-BoldMT", "Times-Bold" }, + { "TimesNewRomanPS-Italic", "Times-Italic" }, + { "TimesNewRomanPS-ItalicMT", "Times-Italic" }, + { "TimesNewRomanPSMT", "Times-Roman" }, + { "TimesNewRomanPSMT,Bold", "Times-Bold" }, + { "TimesNewRomanPSMT,BoldItalic", "Times-BoldItalic" }, + { "TimesNewRomanPSMT,Italic", "Times-Italic" } +}; + +//------------------------------------------------------------------------ +// GfxFont +//------------------------------------------------------------------------ + +GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) { + GString *nameA; + GfxFont *font; + Object obj1; + + // get base font name + nameA = NULL; + fontDict->lookup("BaseFont", &obj1); + if (obj1.isName()) { + nameA = new GString(obj1.getName()); + } + obj1.free(); + + // get font type + font = NULL; + fontDict->lookup("Subtype", &obj1); + if (obj1.isName("Type1") || obj1.isName("MMType1")) { + font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict); + } else if (obj1.isName("Type1C")) { + font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict); + } else if (obj1.isName("Type3")) { + font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict); + } else if (obj1.isName("TrueType")) { + font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict); + } else if (obj1.isName("Type0")) { + font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict); + } else { + error(-1, "Unknown font type: '%s'", + obj1.isName() ? obj1.getName() : "???"); + font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict); + } + obj1.free(); + + return font; +} + +GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA) { + ok = gFalse; + tag = new GString(tagA); + id = idA; + name = nameA; + origName = nameA; + embFontName = NULL; + extFontFile = NULL; +} + +GfxFont::~GfxFont() { + delete tag; + if (origName && origName != name) { + delete origName; + } + if (name) { + delete name; + } + if (embFontName) { + delete embFontName; + } + if (extFontFile) { + delete extFontFile; + } +} + +void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { + Object obj1, obj2, obj3, obj4; + double t; + int i; + + // assume Times-Roman by default (for substitution purposes) + flags = fontSerif; + + embFontID.num = -1; + embFontID.gen = -1; + missingWidth = 0; + + if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) { + + // get flags + if (obj1.dictLookup("Flags", &obj2)->isInt()) { + flags = obj2.getInt(); + } + obj2.free(); + + // get name + obj1.dictLookup("FontName", &obj2); + if (obj2.isName()) { + embFontName = new GString(obj2.getName()); + } + obj2.free(); + + // look for embedded font file + if (obj1.dictLookupNF("FontFile", &obj2)->isRef()) { + embFontID = obj2.getRef(); + if (type != fontType1) { + error(-1, "Mismatch between font type and embedded font file"); + type = isCIDFont() ? fontCIDType0 : fontType1; + } + } + obj2.free(); + if (embFontID.num == -1 && + obj1.dictLookupNF("FontFile2", &obj2)->isRef()) { + embFontID = obj2.getRef(); + if (type != fontTrueType && type != fontCIDType2) { + error(-1, "Mismatch between font type and embedded font file"); + type = type == fontCIDType0 ? fontCIDType2 : fontTrueType; + } + } + obj2.free(); + if (embFontID.num == -1 && + obj1.dictLookupNF("FontFile3", &obj2)->isRef()) { + if (obj2.fetch(xref, &obj3)->isStream()) { + obj3.streamGetDict()->lookup("Subtype", &obj4); + if (obj4.isName("Type1")) { + embFontID = obj2.getRef(); + if (type != fontType1) { + error(-1, "Mismatch between font type and embedded font file"); + type = fontType1; + } + } else if (obj4.isName("Type1C")) { + embFontID = obj2.getRef(); + if (type != fontType1 && type != fontType1C) { + error(-1, "Mismatch between font type and embedded font file"); + } + type = fontType1C; + } else if (obj4.isName("TrueType")) { + embFontID = obj2.getRef(); + if (type != fontTrueType) { + error(-1, "Mismatch between font type and embedded font file"); + type = fontTrueType; + } + } else if (obj4.isName("CIDFontType0C")) { + embFontID = obj2.getRef(); + if (type != fontCIDType0) { + error(-1, "Mismatch between font type and embedded font file"); + } + type = fontCIDType0C; + } else if (obj4.isName("OpenType")) { + embFontID = obj2.getRef(); + if (type == fontTrueType) { + type = fontTrueTypeOT; + } else if (type == fontType1) { + type = fontType1COT; + } else if (type == fontCIDType0) { + type = fontCIDType0COT; + } else if (type == fontCIDType2) { + type = fontCIDType2OT; + } else { + error(-1, "Mismatch between font type and embedded font file"); + } + } else { + error(-1, "Unknown embedded font type '%s'", + obj4.isName() ? obj4.getName() : "???"); + } + obj4.free(); + } + obj3.free(); + } + obj2.free(); + + // look for MissingWidth + obj1.dictLookup("MissingWidth", &obj2); + if (obj2.isNum()) { + missingWidth = obj2.getNum(); + } + obj2.free(); + + // get Ascent and Descent + obj1.dictLookup("Ascent", &obj2); + if (obj2.isNum()) { + t = 0.001 * obj2.getNum(); + // some broken font descriptors set ascent and descent to 0 + if (t != 0) { + ascent = t; + } + } + obj2.free(); + obj1.dictLookup("Descent", &obj2); + if (obj2.isNum()) { + t = 0.001 * obj2.getNum(); + // some broken font descriptors set ascent and descent to 0 + if (t != 0) { + descent = t; + } + // some broken font descriptors specify a positive descent + if (descent > 0) { + descent = -descent; + } + } + obj2.free(); + + // font FontBBox + if (obj1.dictLookup("FontBBox", &obj2)->isArray()) { + for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) { + if (obj2.arrayGet(i, &obj3)->isNum()) { + fontBBox[i] = 0.001 * obj3.getNum(); + } + obj3.free(); + } + } + obj2.free(); + + } + obj1.free(); +} + +CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits, + CharCodeToUnicode *ctu) { + GString *buf; + Object obj1; + int c; + + if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) { + obj1.free(); + return NULL; + } + buf = new GString(); + obj1.streamReset(); + while ((c = obj1.streamGetChar()) != EOF) { + buf->append(c); + } + obj1.streamClose(); + obj1.free(); + if (ctu) { + ctu->mergeCMap(buf, nBits); + } else { + ctu = CharCodeToUnicode::parseCMap(buf, nBits); + } + delete buf; + return ctu; +} + +void GfxFont::findExtFontFile() { + static char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL }; + static char *ttExts[] = { ".ttf", NULL }; + + if (name) { + if (type == fontType1) { + extFontFile = globalParams->findFontFile(name, type1Exts); + } else if (type == fontTrueType) { + extFontFile = globalParams->findFontFile(name, ttExts); + } + } +} + +char *GfxFont::readExtFontFile(int *len) { + FILE *f; + char *buf; + + if (!(f = fopen(extFontFile->getCString(), "rb"))) { + error(-1, "External font file '%s' vanished", extFontFile->getCString()); + return NULL; + } + fseek(f, 0, SEEK_END); + *len = (int)ftell(f); + fseek(f, 0, SEEK_SET); + buf = (char *)gmalloc(*len); + if ((int)fread(buf, 1, *len, f) != *len) { + error(-1, "Error reading external font file '%s'", + extFontFile->getCString()); + } + fclose(f); + return buf; +} + +char *GfxFont::readEmbFontFile(XRef *xref, int *len) { + char *buf; + Object obj1, obj2; + Stream *str; + int c; + int size, i; + + obj1.initRef(embFontID.num, embFontID.gen); + obj1.fetch(xref, &obj2); + if (!obj2.isStream()) { + error(-1, "Embedded font file is not a stream"); + obj2.free(); + obj1.free(); + embFontID.num = -1; + return NULL; + } + str = obj2.getStream(); + + buf = NULL; + i = size = 0; + str->reset(); + while ((c = str->getChar()) != EOF) { + if (i == size) { + size += 4096; + buf = (char *)grealloc(buf, size); + } + buf[i++] = c; + } + *len = i; + str->close(); + + obj2.free(); + obj1.free(); + + return buf; +} + +//------------------------------------------------------------------------ +// Gfx8BitFont +//------------------------------------------------------------------------ + +Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, + GfxFontType typeA, Dict *fontDict): + GfxFont(tagA, idA, nameA) +{ + GString *name2; + BuiltinFont *builtinFont; + char **baseEnc; + GBool baseEncFromFontFile; + char *buf; + int len; + FoFiType1 *ffT1; + FoFiType1C *ffT1C; + int code, code2; + char *charName; + GBool missing, hex; + Unicode toUnicode[256]; + CharCodeToUnicode *utu, *ctu2; + Unicode uBuf[8]; + double mul; + int firstChar, lastChar; + Gushort w; + Object obj1, obj2, obj3; + int n, i, a, b, m; + + type = typeA; + ctu = NULL; + + // do font name substitution for various aliases of the Base 14 font + // names + if (name) { + name2 = name->copy(); + i = 0; + while (i < name2->getLength()) { + if (name2->getChar(i) == ' ') { + name2->del(i); + } else { + ++i; + } + } + a = 0; + b = sizeof(stdFontMap) / sizeof(StdFontMapEntry); + // invariant: stdFontMap[a].altName <= name2 < stdFontMap[b].altName + while (b - a > 1) { + m = (a + b) / 2; + if (name2->cmp(stdFontMap[m].altName) >= 0) { + a = m; + } else { + b = m; + } + } + if (!name2->cmp(stdFontMap[a].altName)) { + name = new GString(stdFontMap[a].properName); + } + delete name2; + } + + // is it a built-in font? + builtinFont = NULL; + if (name) { + for (i = 0; i < nBuiltinFonts; ++i) { + if (!name->cmp(builtinFonts[i].name)) { + builtinFont = &builtinFonts[i]; + break; + } + } + } + + // default ascent/descent values + if (builtinFont) { + ascent = 0.001 * builtinFont->ascent; + descent = 0.001 * builtinFont->descent; + fontBBox[0] = 0.001 * builtinFont->bbox[0]; + fontBBox[1] = 0.001 * builtinFont->bbox[1]; + fontBBox[2] = 0.001 * builtinFont->bbox[2]; + fontBBox[3] = 0.001 * builtinFont->bbox[3]; + } else { + ascent = 0.95; + descent = -0.35; + fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0; + } + + // get info from font descriptor + readFontDescriptor(xref, fontDict); + + // for non-embedded fonts, don't trust the ascent/descent/bbox + // values from the font descriptor + if (builtinFont && embFontID.num < 0) { + ascent = 0.001 * builtinFont->ascent; + descent = 0.001 * builtinFont->descent; + fontBBox[0] = 0.001 * builtinFont->bbox[0]; + fontBBox[1] = 0.001 * builtinFont->bbox[1]; + fontBBox[2] = 0.001 * builtinFont->bbox[2]; + fontBBox[3] = 0.001 * builtinFont->bbox[3]; + } + + // look for an external font file + findExtFontFile(); + + // get font matrix + fontMat[0] = fontMat[3] = 1; + fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0; + if (fontDict->lookup("FontMatrix", &obj1)->isArray()) { + for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + fontMat[i] = obj2.getNum(); + } + obj2.free(); + } + } + obj1.free(); + + // get Type 3 bounding box, font definition, and resources + if (type == fontType3) { + if (fontDict->lookup("FontBBox", &obj1)->isArray()) { + for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + fontBBox[i] = obj2.getNum(); + } + obj2.free(); + } + } + obj1.free(); + if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) { + error(-1, "Missing or invalid CharProcs dictionary in Type 3 font"); + charProcs.free(); + } + if (!fontDict->lookup("Resources", &resources)->isDict()) { + resources.free(); + } + } + + //----- build the font encoding ----- + + // Encodings start with a base encoding, which can come from + // (in order of priority): + // 1. FontDict.Encoding or FontDict.Encoding.BaseEncoding + // - MacRoman / MacExpert / WinAnsi / Standard + // 2. embedded or external font file + // 3. default: + // - builtin --> builtin encoding + // - TrueType --> WinAnsiEncoding + // - others --> StandardEncoding + // and then add a list of differences (if any) from + // FontDict.Encoding.Differences. + + // check FontDict for base encoding + hasEncoding = gFalse; + usesMacRomanEnc = gFalse; + baseEnc = NULL; + baseEncFromFontFile = gFalse; + fontDict->lookup("Encoding", &obj1); + if (obj1.isDict()) { + obj1.dictLookup("BaseEncoding", &obj2); + if (obj2.isName("MacRomanEncoding")) { + hasEncoding = gTrue; + usesMacRomanEnc = gTrue; + baseEnc = macRomanEncoding; + } else if (obj2.isName("MacExpertEncoding")) { + hasEncoding = gTrue; + baseEnc = macExpertEncoding; + } else if (obj2.isName("WinAnsiEncoding")) { + hasEncoding = gTrue; + baseEnc = winAnsiEncoding; + } + obj2.free(); + } else if (obj1.isName("MacRomanEncoding")) { + hasEncoding = gTrue; + usesMacRomanEnc = gTrue; + baseEnc = macRomanEncoding; + } else if (obj1.isName("MacExpertEncoding")) { + hasEncoding = gTrue; + baseEnc = macExpertEncoding; + } else if (obj1.isName("WinAnsiEncoding")) { + hasEncoding = gTrue; + baseEnc = winAnsiEncoding; + } + + // check embedded or external font file for base encoding + // (only for Type 1 fonts - trying to get an encoding out of a + // TrueType font is a losing proposition) + ffT1 = NULL; + ffT1C = NULL; + buf = NULL; + if (type == fontType1 && (extFontFile || embFontID.num >= 0)) { + if (extFontFile) { + ffT1 = FoFiType1::load(extFontFile->getCString()); + } else { + buf = readEmbFontFile(xref, &len); + ffT1 = FoFiType1::make(buf, len); + } + if (ffT1) { + if (ffT1->getName()) { + if (embFontName) { + delete embFontName; + } + embFontName = new GString(ffT1->getName()); + } + if (!baseEnc) { + baseEnc = ffT1->getEncoding(); + baseEncFromFontFile = gTrue; + } + } + } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) { + if (extFontFile) { + ffT1C = FoFiType1C::load(extFontFile->getCString()); + } else { + buf = readEmbFontFile(xref, &len); + ffT1C = FoFiType1C::make(buf, len); + } + if (ffT1C) { + if (ffT1C->getName()) { + if (embFontName) { + delete embFontName; + } + embFontName = new GString(ffT1C->getName()); + } + if (!baseEnc) { + baseEnc = ffT1C->getEncoding(); + baseEncFromFontFile = gTrue; + } + } + } + if (buf) { + gfree(buf); + } + + // get default base encoding + if (!baseEnc) { + if (builtinFont && embFontID.num < 0) { + baseEnc = builtinFont->defaultBaseEnc; + hasEncoding = gTrue; + } else if (type == fontTrueType) { + baseEnc = winAnsiEncoding; + } else { + baseEnc = standardEncoding; + } + } + + // copy the base encoding + for (i = 0; i < 256; ++i) { + enc[i] = baseEnc[i]; + if ((encFree[i] = baseEncFromFontFile) && enc[i]) { + enc[i] = copyString(baseEnc[i]); + } + } + + // some Type 1C font files have empty encodings, which can break the + // T1C->T1 conversion (since the 'seac' operator depends on having + // the accents in the encoding), so we fill in any gaps from + // StandardEncoding + if (type == fontType1C && (extFontFile || embFontID.num >= 0) && + baseEncFromFontFile) { + for (i = 0; i < 256; ++i) { + if (!enc[i] && standardEncoding[i]) { + enc[i] = standardEncoding[i]; + encFree[i] = gFalse; + } + } + } + + // merge differences into encoding + if (obj1.isDict()) { + obj1.dictLookup("Differences", &obj2); + if (obj2.isArray()) { + hasEncoding = gTrue; + code = 0; + for (i = 0; i < obj2.arrayGetLength(); ++i) { + obj2.arrayGet(i, &obj3); + if (obj3.isInt()) { + code = obj3.getInt(); + } else if (obj3.isName()) { + if (code >= 0 && code < 256) { + if (encFree[code]) { + gfree(enc[code]); + } + enc[code] = copyString(obj3.getName()); + encFree[code] = gTrue; + } + ++code; + } else { + error(-1, "Wrong type in font encoding resource differences (%s)", + obj3.getTypeName()); + } + obj3.free(); + } + } + obj2.free(); + } + obj1.free(); + if (ffT1) { + delete ffT1; + } + if (ffT1C) { + delete ffT1C; + } + + //----- build the mapping to Unicode ----- + + // pass 1: use the name-to-Unicode mapping table + missing = hex = gFalse; + for (code = 0; code < 256; ++code) { + if ((charName = enc[code])) { + if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) && + strcmp(charName, ".notdef")) { + // if it wasn't in the name-to-Unicode table, check for a + // name that looks like 'Axx' or 'xx', where 'A' is any letter + // and 'xx' is two hex digits + if ((strlen(charName) == 3 && + isalpha(charName[0]) && + isxdigit(charName[1]) && isxdigit(charName[2]) && + ((charName[1] >= 'a' && charName[1] <= 'f') || + (charName[1] >= 'A' && charName[1] <= 'F') || + (charName[2] >= 'a' && charName[2] <= 'f') || + (charName[2] >= 'A' && charName[2] <= 'F'))) || + (strlen(charName) == 2 && + isxdigit(charName[0]) && isxdigit(charName[1]) && + ((charName[0] >= 'a' && charName[0] <= 'f') || + (charName[0] >= 'A' && charName[0] <= 'F') || + (charName[1] >= 'a' && charName[1] <= 'f') || + (charName[1] >= 'A' && charName[1] <= 'F')))) { + hex = gTrue; + } + missing = gTrue; + } + } else { + toUnicode[code] = 0; + } + } + + // pass 2: try to fill in the missing chars, looking for names of + // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B' + // are any letters, 'xx' is two hex digits, and 'nn' is 2-4 + // decimal digits + if (missing && globalParams->getMapNumericCharNames()) { + for (code = 0; code < 256; ++code) { + if ((charName = enc[code]) && !toUnicode[code] && + strcmp(charName, ".notdef")) { + n = strlen(charName); + code2 = -1; + if (hex && n == 3 && isalpha(charName[0]) && + isxdigit(charName[1]) && isxdigit(charName[2])) { + sscanf(charName+1, "%x", &code2); + } else if (hex && n == 2 && + isxdigit(charName[0]) && isxdigit(charName[1])) { + sscanf(charName, "%x", &code2); + } else if (!hex && n >= 2 && n <= 4 && + isdigit(charName[0]) && isdigit(charName[1])) { + code2 = atoi(charName); + } else if (n >= 3 && n <= 5 && + isdigit(charName[1]) && isdigit(charName[2])) { + code2 = atoi(charName+1); + } else if (n >= 4 && n <= 6 && + isdigit(charName[2]) && isdigit(charName[3])) { + code2 = atoi(charName+2); + } + if (code2 >= 0 && code2 <= 0xff) { + toUnicode[code] = (Unicode)code2; + } + } + } + + // if the 'mapUnknownCharNames' flag is set, do a simple pass-through + // mapping for unknown character names + } else if (missing && globalParams->getMapUnknownCharNames()) { + for (code = 0; code < 256; ++code) { + if (!toUnicode[code]) { + toUnicode[code] = code; + } + } + } + + // construct the char code -> Unicode mapping object + ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode); + + // merge in a ToUnicode CMap, if there is one -- this overwrites + // existing entries in ctu, i.e., the ToUnicode CMap takes + // precedence, but the other encoding info is allowed to fill in any + // holes + readToUnicodeCMap(fontDict, 8, ctu); + + // look for a Unicode-to-Unicode mapping + if (name && (utu = globalParams->getUnicodeToUnicode(name))) { + for (i = 0; i < 256; ++i) { + toUnicode[i] = 0; + } + ctu2 = CharCodeToUnicode::make8BitToUnicode(toUnicode); + for (i = 0; i < 256; ++i) { + n = ctu->mapToUnicode((CharCode)i, uBuf, 8); + if (n >= 1) { + n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8); + if (n >= 1) { + ctu2->setMapping((CharCode)i, uBuf, n); + } + } + } + utu->decRefCnt(); + delete ctu; + ctu = ctu2; + } + + //----- get the character widths ----- + + // initialize all widths + for (code = 0; code < 256; ++code) { + widths[code] = missingWidth * 0.001; + } + + // use widths from font dict, if present + fontDict->lookup("FirstChar", &obj1); + firstChar = obj1.isInt() ? obj1.getInt() : 0; + obj1.free(); + if (firstChar < 0 || firstChar > 255) { + firstChar = 0; + } + fontDict->lookup("LastChar", &obj1); + lastChar = obj1.isInt() ? obj1.getInt() : 255; + obj1.free(); + if (lastChar < 0 || lastChar > 255) { + lastChar = 255; + } + mul = (type == fontType3) ? fontMat[0] : 0.001; + fontDict->lookup("Widths", &obj1); + if (obj1.isArray()) { + flags |= fontFixedWidth; + if (obj1.arrayGetLength() < lastChar - firstChar + 1) { + lastChar = firstChar + obj1.arrayGetLength() - 1; + } + for (code = firstChar; code <= lastChar; ++code) { + obj1.arrayGet(code - firstChar, &obj2); + if (obj2.isNum()) { + widths[code] = obj2.getNum() * mul; + if (widths[code] != widths[firstChar]) { + flags &= ~fontFixedWidth; + } + } + obj2.free(); + } + + // use widths from built-in font + } else if (builtinFont) { + // this is a kludge for broken PDF files that encode char 32 + // as .notdef + if (builtinFont->widths->getWidth("space", &w)) { + widths[32] = 0.001 * w; + } + for (code = 0; code < 256; ++code) { + if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) { + widths[code] = 0.001 * w; + } + } + + // couldn't find widths -- use defaults + } else { + // this is technically an error -- the Widths entry is required + // for all but the Base-14 fonts -- but certain PDF generators + // apparently don't include widths for Arial and TimesNewRoman + if (isFixedWidth()) { + i = 0; + } else if (isSerif()) { + i = 8; + } else { + i = 4; + } + if (isBold()) { + i += 2; + } + if (isItalic()) { + i += 1; + } + builtinFont = builtinFontSubst[i]; + // this is a kludge for broken PDF files that encode char 32 + // as .notdef + if (builtinFont->widths->getWidth("space", &w)) { + widths[32] = 0.001 * w; + } + for (code = 0; code < 256; ++code) { + if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) { + widths[code] = 0.001 * w; + } + } + } + obj1.free(); + + ok = gTrue; +} + +Gfx8BitFont::~Gfx8BitFont() { + int i; + + for (i = 0; i < 256; ++i) { + if (encFree[i] && enc[i]) { + gfree(enc[i]); + } + } + ctu->decRefCnt(); + if (charProcs.isDict()) { + charProcs.free(); + } + if (resources.isDict()) { + resources.free(); + } +} + +int Gfx8BitFont::getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy) { + CharCode c; + + *code = c = (CharCode)(*s & 0xff); + *uLen = ctu->mapToUnicode(c, u, uSize); + *dx = widths[c]; + *dy = *ox = *oy = 0; + return 1; +} + +CharCodeToUnicode* Gfx8BitFont::getCTU() { + return ctu; +} + +CharCodeToUnicode *Gfx8BitFont::getToUnicode() { + ctu->incRefCnt(); + return ctu; +} + +Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { + Gushort *map; + int cmapPlatform, cmapEncoding; + int unicodeCmap, macRomanCmap, msSymbolCmap, cmap; + GBool useMacRoman, useUnicode; + char *charName; + Unicode u; + int code, i, n; + + map = (Gushort *)gmallocn(256, sizeof(Gushort)); + for (i = 0; i < 256; ++i) { + map[i] = 0; + } + + // To match up with the Adobe-defined behaviour, we choose a cmap + // like this: + // 1. If the PDF font has an encoding: + // 1a. If the PDF font specified MacRomanEncoding and the + // TrueType font has a Macintosh Roman cmap, use it, and + // reverse map the char names through MacRomanEncoding to + // get char codes. + // 1b. If the TrueType font has a Microsoft Unicode cmap or a + // non-Microsoft Unicode cmap, use it, and use the Unicode + // indexes, not the char codes. + // 1c. If the PDF font is symbolic and the TrueType font has a + // Microsoft Symbol cmap, use it, and use char codes + // directly (possibly with an offset of 0xf000). + // 1d. If the TrueType font has a Macintosh Roman cmap, use it, + // as in case 1a. + // 2. If the PDF font does not have an encoding or the PDF font is + // symbolic: + // 2a. If the TrueType font has a Macintosh Roman cmap, use it, + // and use char codes directly (possibly with an offset of + // 0xf000). + // 2b. If the TrueType font has a Microsoft Symbol cmap, use it, + // and use char codes directly (possible with an offset of + // 0xf000). + // 3. If none of these rules apply, use the first cmap and hope for + // the best (this shouldn't happen). + unicodeCmap = macRomanCmap = msSymbolCmap = -1; + for (i = 0; i < ff->getNumCmaps(); ++i) { + cmapPlatform = ff->getCmapPlatform(i); + cmapEncoding = ff->getCmapEncoding(i); + if ((cmapPlatform == 3 && cmapEncoding == 1) || + cmapPlatform == 0) { + unicodeCmap = i; + } else if (cmapPlatform == 1 && cmapEncoding == 0) { + macRomanCmap = i; + } else if (cmapPlatform == 3 && cmapEncoding == 0) { + msSymbolCmap = i; + } + } + cmap = 0; + useMacRoman = gFalse; + useUnicode = gFalse; + if (hasEncoding) { + if (usesMacRomanEnc && macRomanCmap >= 0) { + cmap = macRomanCmap; + useMacRoman = gTrue; + } else if (unicodeCmap >= 0) { + cmap = unicodeCmap; + useUnicode = gTrue; + } else if ((flags & fontSymbolic) && msSymbolCmap >= 0) { + cmap = msSymbolCmap; + } else if ((flags & fontSymbolic) && macRomanCmap >= 0) { + cmap = macRomanCmap; + } else if (macRomanCmap >= 0) { + cmap = macRomanCmap; + useMacRoman = gTrue; + } + } else { + if (msSymbolCmap >= 0) { + cmap = msSymbolCmap; + } else if (macRomanCmap >= 0) { + cmap = macRomanCmap; + } + } + + // reverse map the char names through MacRomanEncoding, then map the + // char codes through the cmap + if (useMacRoman) { + for (i = 0; i < 256; ++i) { + if ((charName = enc[i])) { + if ((code = globalParams->getMacRomanCharCode(charName))) { + map[i] = ff->mapCodeToGID(cmap, code); + } + } + } + + // map Unicode through the cmap + } else if (useUnicode) { + for (i = 0; i < 256; ++i) { + if (((charName = enc[i]) && + (u = globalParams->mapNameToUnicode(charName))) || + (n = ctu->mapToUnicode((CharCode)i, &u, 1))) { + map[i] = ff->mapCodeToGID(cmap, u); + } + } + + // map the char codes through the cmap, possibly with an offset of + // 0xf000 + } else { + for (i = 0; i < 256; ++i) { + if (!(map[i] = ff->mapCodeToGID(cmap, i))) { + map[i] = ff->mapCodeToGID(cmap, 0xf000 + i); + } + } + } + + // try the TrueType 'post' table to handle any unmapped characters + for (i = 0; i < 256; ++i) { + if (!map[i] && (charName = enc[i])) { + map[i] = (Gushort)(int)ff->mapNameToGID(charName); + } + } + + return map; +} + +Dict *Gfx8BitFont::getCharProcs() { + return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL; +} + +Object *Gfx8BitFont::getCharProc(int code, Object *proc) { + if (enc[code] && charProcs.isDict()) { + charProcs.dictLookup(enc[code], proc); + } else { + proc->initNull(); + } + return proc; +} + +Dict *Gfx8BitFont::getResources() { + return resources.isDict() ? resources.getDict() : (Dict *)NULL; +} + +//------------------------------------------------------------------------ +// GfxCIDFont +//------------------------------------------------------------------------ + +static int CDECL cmpWidthExcep(const void *w1, const void *w2) { + return ((GfxFontCIDWidthExcep *)w1)->first - + ((GfxFontCIDWidthExcep *)w2)->first; +} + +static int CDECL cmpWidthExcepV(const void *w1, const void *w2) { + return ((GfxFontCIDWidthExcepV *)w1)->first - + ((GfxFontCIDWidthExcepV *)w2)->first; +} + +GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, + Dict *fontDict): + GfxFont(tagA, idA, nameA) +{ + Dict *desFontDict; + GString *collection, *cMapName; + Object desFontDictObj; + Object obj1, obj2, obj3, obj4, obj5, obj6; + CharCodeToUnicode *utu; + CharCode c; + Unicode uBuf[8]; + int c1, c2; + int excepsSize, i, j, k, n; + + ascent = 0.95; + descent = -0.35; + fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0; + cMap = NULL; + ctu = NULL; + widths.defWidth = 1.0; + widths.defHeight = -1.0; + widths.defVY = 0.880; + widths.exceps = NULL; + widths.nExceps = 0; + widths.excepsV = NULL; + widths.nExcepsV = 0; + cidToGID = NULL; + cidToGIDLen = 0; + + // get the descendant font + if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) { + error(-1, "Missing DescendantFonts entry in Type 0 font"); + obj1.free(); + goto err1; + } + if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) { + error(-1, "Bad descendant font in Type 0 font"); + goto err3; + } + obj1.free(); + desFontDict = desFontDictObj.getDict(); + + // font type + if (!desFontDict->lookup("Subtype", &obj1)) { + error(-1, "Missing Subtype entry in Type 0 descendant font"); + goto err3; + } + if (obj1.isName("CIDFontType0")) { + type = fontCIDType0; + } else if (obj1.isName("CIDFontType2")) { + type = fontCIDType2; + } else { + error(-1, "Unknown Type 0 descendant font type '%s'", + obj1.isName() ? obj1.getName() : "???"); + goto err3; + } + obj1.free(); + + // get info from font descriptor + readFontDescriptor(xref, desFontDict); + + // look for an external font file + findExtFontFile(); + + //----- encoding info ----- + + // char collection + if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) { + error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font"); + goto err3; + } + obj1.dictLookup("Registry", &obj2); + obj1.dictLookup("Ordering", &obj3); + if (!obj2.isString() || !obj3.isString()) { + error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font"); + goto err4; + } + collection = obj2.getString()->copy()->append('-')->append(obj3.getString()); + obj3.free(); + obj2.free(); + obj1.free(); + + // look for a ToUnicode CMap + if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) { + + // the "Adobe-Identity" and "Adobe-UCS" collections don't have + // cidToUnicode files + if (collection->cmp("Adobe-Identity") && + collection->cmp("Adobe-UCS")) { + + // look for a user-supplied .cidToUnicode file + if (!(ctu = globalParams->getCIDToUnicode(collection))) { + error(-1, "Unknown character collection '%s'", + collection->getCString()); + // fall-through, assuming the Identity mapping -- this appears + // to match Adobe's behavior + } + } + } + + // look for a Unicode-to-Unicode mapping + if (name && (utu = globalParams->getUnicodeToUnicode(name))) { + if (ctu) { + for (c = 0; c < ctu->getLength(); ++c) { + n = ctu->mapToUnicode(c, uBuf, 8); + if (n >= 1) { + n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8); + if (n >= 1) { + ctu->setMapping(c, uBuf, n); + } + } + } + utu->decRefCnt(); + } else { + ctu = utu; + } + } + + // encoding (i.e., CMap) + //~ need to handle a CMap stream here + //~ also need to deal with the UseCMap entry in the stream dict + if (!fontDict->lookup("Encoding", &obj1)->isName()) { + error(-1, "Missing or invalid Encoding entry in Type 0 font"); + delete collection; + goto err3; + } + cMapName = new GString(obj1.getName()); + obj1.free(); + if (!(cMap = globalParams->getCMap(collection, cMapName))) { + error(-1, "Unknown CMap '%s' for character collection '%s'", + cMapName->getCString(), collection->getCString()); + delete collection; + delete cMapName; + goto err2; + } + delete collection; + delete cMapName; + + // CIDToGIDMap (for embedded TrueType fonts) + if (type == fontCIDType2) { + desFontDict->lookup("CIDToGIDMap", &obj1); + if (obj1.isStream()) { + cidToGIDLen = 0; + i = 64; + cidToGID = (Gushort *)gmallocn(i, sizeof(Gushort)); + obj1.streamReset(); + while ((c1 = obj1.streamGetChar()) != EOF && + (c2 = obj1.streamGetChar()) != EOF) { + if (cidToGIDLen == i) { + i *= 2; + cidToGID = (Gushort *)greallocn(cidToGID, i, sizeof(Gushort)); + } + cidToGID[cidToGIDLen++] = (Gushort)((c1 << 8) + c2); + } + } else if (!obj1.isName("Identity") && !obj1.isNull()) { + error(-1, "Invalid CIDToGIDMap entry in CID font"); + } + obj1.free(); + } + + //----- character metrics ----- + + // default char width + if (desFontDict->lookup("DW", &obj1)->isInt()) { + widths.defWidth = obj1.getInt() * 0.001; + } + obj1.free(); + + // char width exceptions + if (desFontDict->lookup("W", &obj1)->isArray()) { + excepsSize = 0; + i = 0; + while (i + 1 < obj1.arrayGetLength()) { + obj1.arrayGet(i, &obj2); + obj1.arrayGet(i + 1, &obj3); + if (obj2.isInt() && obj3.isInt() && i + 2 < obj1.arrayGetLength()) { + if (obj1.arrayGet(i + 2, &obj4)->isNum()) { + if (widths.nExceps == excepsSize) { + excepsSize += 16; + widths.exceps = (GfxFontCIDWidthExcep *) + greallocn(widths.exceps, + excepsSize, sizeof(GfxFontCIDWidthExcep)); + } + widths.exceps[widths.nExceps].first = obj2.getInt(); + widths.exceps[widths.nExceps].last = obj3.getInt(); + widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001; + ++widths.nExceps; + } else { + error(-1, "Bad widths array in Type 0 font"); + } + obj4.free(); + i += 3; + } else if (obj2.isInt() && obj3.isArray()) { + if (widths.nExceps + obj3.arrayGetLength() > excepsSize) { + excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15; + widths.exceps = (GfxFontCIDWidthExcep *) + greallocn(widths.exceps, + excepsSize, sizeof(GfxFontCIDWidthExcep)); + } + j = obj2.getInt(); + for (k = 0; k < obj3.arrayGetLength(); ++k) { + if (obj3.arrayGet(k, &obj4)->isNum()) { + widths.exceps[widths.nExceps].first = j; + widths.exceps[widths.nExceps].last = j; + widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001; + ++j; + ++widths.nExceps; + } else { + error(-1, "Bad widths array in Type 0 font"); + } + obj4.free(); + } + i += 2; + } else { + error(-1, "Bad widths array in Type 0 font"); + ++i; + } + obj3.free(); + obj2.free(); + } + qsort(widths.exceps, widths.nExceps, sizeof(GfxFontCIDWidthExcep), + &cmpWidthExcep); + } + obj1.free(); + + // default metrics for vertical font + if (desFontDict->lookup("DW2", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + if (obj1.arrayGet(0, &obj2)->isNum()) { + widths.defVY = obj2.getNum() * 0.001; + } + obj2.free(); + if (obj1.arrayGet(1, &obj2)->isNum()) { + widths.defHeight = obj2.getNum() * 0.001; + } + obj2.free(); + } + obj1.free(); + + // char metric exceptions for vertical font + if (desFontDict->lookup("W2", &obj1)->isArray()) { + excepsSize = 0; + i = 0; + while (i + 1 < obj1.arrayGetLength()) { + obj1.arrayGet(i, &obj2); + obj1.arrayGet(i+ 1, &obj3); + if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) { + if (obj1.arrayGet(i + 2, &obj4)->isNum() && + obj1.arrayGet(i + 3, &obj5)->isNum() && + obj1.arrayGet(i + 4, &obj6)->isNum()) { + if (widths.nExcepsV == excepsSize) { + excepsSize += 16; + widths.excepsV = (GfxFontCIDWidthExcepV *) + greallocn(widths.excepsV, + excepsSize, sizeof(GfxFontCIDWidthExcepV)); + } + widths.excepsV[widths.nExcepsV].first = obj2.getInt(); + widths.excepsV[widths.nExcepsV].last = obj3.getInt(); + widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001; + widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001; + widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001; + ++widths.nExcepsV; + } else { + error(-1, "Bad widths (W2) array in Type 0 font"); + } + obj6.free(); + obj5.free(); + obj4.free(); + i += 5; + } else if (obj2.isInt() && obj3.isArray()) { + if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) { + excepsSize = + (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15; + widths.excepsV = (GfxFontCIDWidthExcepV *) + greallocn(widths.excepsV, + excepsSize, sizeof(GfxFontCIDWidthExcepV)); + } + j = obj2.getInt(); + for (k = 0; k < obj3.arrayGetLength(); k += 3) { + if (obj3.arrayGet(k, &obj4)->isNum() && + obj3.arrayGet(k+1, &obj5)->isNum() && + obj3.arrayGet(k+2, &obj6)->isNum()) { + widths.excepsV[widths.nExceps].first = j; + widths.excepsV[widths.nExceps].last = j; + widths.excepsV[widths.nExceps].height = obj4.getNum() * 0.001; + widths.excepsV[widths.nExceps].vx = obj5.getNum() * 0.001; + widths.excepsV[widths.nExceps].vy = obj6.getNum() * 0.001; + ++j; + ++widths.nExcepsV; + } else { + error(-1, "Bad widths (W2) array in Type 0 font"); + } + obj6.free(); + obj5.free(); + obj4.free(); + } + i += 2; + } else { + error(-1, "Bad widths (W2) array in Type 0 font"); + ++i; + } + obj3.free(); + obj2.free(); + } + qsort(widths.excepsV, widths.nExcepsV, sizeof(GfxFontCIDWidthExcepV), + &cmpWidthExcepV); + } + obj1.free(); + + desFontDictObj.free(); + ok = gTrue; + return; + + err4: + obj3.free(); + obj2.free(); + err3: + obj1.free(); + err2: + desFontDictObj.free(); + err1:; +} + +GfxCIDFont::~GfxCIDFont() { + if (cMap) { + cMap->decRefCnt(); + } + if (ctu) { + ctu->decRefCnt(); + } + gfree(widths.exceps); + gfree(widths.excepsV); + if (cidToGID) { + gfree(cidToGID); + } +} + +CharCodeToUnicode* GfxCIDFont::getCTU() { + return ctu; +} + +int GfxCIDFont::getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy) { + CID cid; + double w, h, vx, vy; + int n, a, b, m; + + if (!cMap) { + *code = 0; + *uLen = 0; + *dx = *dy = 0; + return 1; + } + + *code = (CharCode)(cid = cMap->getCID(s, len, &n)); + if (ctu) { + *uLen = ctu->mapToUnicode(cid, u, uSize); + } else { + *uLen = 0; + } + + // horizontal + if (cMap->getWMode() == 0) { + w = widths.defWidth; + h = vx = vy = 0; + if (widths.nExceps > 0 && cid >= widths.exceps[0].first) { + a = 0; + b = widths.nExceps; + // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first + while (b - a > 1) { + m = (a + b) / 2; + if (widths.exceps[m].first <= cid) { + a = m; + } else { + b = m; + } + } + if (cid <= widths.exceps[a].last) { + w = widths.exceps[a].width; + } + } + + // vertical + } else { + w = 0; + h = widths.defHeight; + vx = widths.defWidth / 2; + vy = widths.defVY; + if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) { + a = 0; + b = widths.nExcepsV; + // invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first + while (b - a > 1) { + m = (a + b) / 2; + if (widths.excepsV[m].last <= cid) { + a = m; + } else { + b = m; + } + } + if (cid <= widths.excepsV[a].last) { + h = widths.excepsV[a].height; + vx = widths.excepsV[a].vx; + vy = widths.excepsV[a].vy; + } + } + } + + *dx = w; + *dy = h; + *ox = vx; + *oy = vy; + + return n; +} + +int GfxCIDFont::getWMode() { + return cMap ? cMap->getWMode() : 0; +} + +CharCodeToUnicode *GfxCIDFont::getToUnicode() { + if (ctu) { + ctu->incRefCnt(); + } + return ctu; +} + +GString *GfxCIDFont::getCollection() { + return cMap ? cMap->getCollection() : (GString *)NULL; +} + +//------------------------------------------------------------------------ +// GfxFontDict +//------------------------------------------------------------------------ + +GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) { + int i; + Object obj1, obj2; + Ref r; + + numFonts = fontDict->getLength(); + fonts = (GfxFont **)gmallocn(numFonts, sizeof(GfxFont *)); + for (i = 0; i < numFonts; ++i) { + fontDict->getValNF(i, &obj1); + obj1.fetch(xref, &obj2); + if (obj2.isDict()) { + if (obj1.isRef()) { + r = obj1.getRef(); + } else { + // no indirect reference for this font, so invent a unique one + // (legal generation numbers are five digits, so any 6-digit + // number would be safe) + r.num = i; + if (fontDictRef) { + r.gen = 100000 + fontDictRef->num; + } else { + r.gen = 999999; + } + } + fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i), + r, obj2.getDict()); + if (fonts[i] && !fonts[i]->isOk()) { + delete fonts[i]; + fonts[i] = NULL; + } + } else { + error(-1, "font resource is not a dictionary"); + fonts[i] = NULL; + } + obj1.free(); + obj2.free(); + } +} + +GfxFontDict::~GfxFontDict() { + int i; + + for (i = 0; i < numFonts; ++i) { + if (fonts[i]) { + delete fonts[i]; + } + } + gfree(fonts); +} + +GfxFont *GfxFontDict::lookup(char *tag) { + int i; + + for (i = 0; i < numFonts; ++i) { + if (fonts[i] && fonts[i]->matches(tag)) { + return fonts[i]; + } + } + return NULL; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GfxFont.h swftools-0.9.1/lib/pdf/xpdf/GfxFont.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/GfxFont.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GfxFont.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,323 @@ +//======================================================================== +// +// GfxFont.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GFXFONT_H +#define GFXFONT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "GString.h" +#include "Object.h" +#include "CharTypes.h" + +class Dict; +class CMap; +class CharCodeToUnicode; +class FoFiTrueType; +struct GfxFontCIDWidths; + +//------------------------------------------------------------------------ +// GfxFontType +//------------------------------------------------------------------------ + +enum GfxFontType { + //----- Gfx8BitFont + fontUnknownType, + fontType1, + fontType1C, + fontType1COT, + fontType3, + fontTrueType, + fontTrueTypeOT, + //----- GfxCIDFont + fontCIDType0, + fontCIDType0C, + fontCIDType0COT, + fontCIDType2, + fontCIDType2OT +}; + +//------------------------------------------------------------------------ +// GfxFontCIDWidths +//------------------------------------------------------------------------ + +struct GfxFontCIDWidthExcep { + CID first; // this record applies to + CID last; // CIDs .. + double width; // char width +}; + +struct GfxFontCIDWidthExcepV { + CID first; // this record applies to + CID last; // CIDs .. + double height; // char height + double vx, vy; // origin position +}; + +struct GfxFontCIDWidths { + double defWidth; // default char width + double defHeight; // default char height + double defVY; // default origin position + GfxFontCIDWidthExcep *exceps; // exceptions + int nExceps; // number of valid entries in exceps + GfxFontCIDWidthExcepV * // exceptions for vertical font + excepsV; + int nExcepsV; // number of valid entries in excepsV +}; + +//------------------------------------------------------------------------ +// GfxFont +//------------------------------------------------------------------------ + +#define fontFixedWidth (1 << 0) +#define fontSerif (1 << 1) +#define fontSymbolic (1 << 2) +#define fontItalic (1 << 6) +#define fontBold (1 << 18) + +class GfxFont { +public: + + // Build a GfxFont object. + static GfxFont *makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict); + + GfxFont(char *tagA, Ref idA, GString *nameA); + + virtual ~GfxFont(); + + GBool isOk() { return ok; } + + // Get font tag. + GString *getTag() { return tag; } + + // Get font dictionary ID. + Ref *getID() { return &id; } + + // Does this font match the tag? + GBool matches(char *tagA) { return !tag->cmp(tagA); } + + // Get base font name. + GString *getName() { return name; } + + // Get the original font name (ignornig any munging that might have + // been done to map to a canonical Base-14 font name). + GString *getOrigName() { return origName; } + + // Get font type. + GfxFontType getType() { return type; } + virtual GBool isCIDFont() { return gFalse; } + + // Get embedded font ID, i.e., a ref for the font file stream. + // Returns false if there is no embedded font. + GBool getEmbeddedFontID(Ref *embID) + { *embID = embFontID; return embFontID.num >= 0; } + + // Get the PostScript font name for the embedded font. Returns + // NULL if there is no embedded font. + GString *getEmbeddedFontName() { return embFontName; } + + // Get the name of the external font file. Returns NULL if there + // is no external font file. + GString *getExtFontFile() { return extFontFile; } + + // Get font descriptor flags. + int getFlags() { return flags; } + GBool isFixedWidth() { return flags & fontFixedWidth; } + GBool isSerif() { return flags & fontSerif; } + GBool isSymbolic() { return flags & fontSymbolic; } + GBool isItalic() { return flags & fontItalic; } + GBool isBold() { return flags & fontBold; } + + // Return the font matrix. + double *getFontMatrix() { return fontMat; } + + // Return the font bounding box. + double *getFontBBox() { return fontBBox; } + + // Return the ascent and descent values. + double getAscent() { return ascent; } + double getDescent() { return descent; } + + // Return the writing mode (0=horizontal, 1=vertical). + virtual int getWMode() { return 0; } + + // Read an external or embedded font file into a buffer. + char *readExtFontFile(int *len); + char *readEmbFontFile(XRef *xref, int *len); + + // Get the next char from a string of bytes, returning the + // char , its Unicode mapping , its displacement vector + // (, ), and its origin offset vector (, ). + // is the number of entries available in , and is set to + // the number actually used. Returns the number of bytes used by + // the char code. + virtual int getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy) = 0; + virtual CharCodeToUnicode* getCTU() = 0; + +protected: + + void readFontDescriptor(XRef *xref, Dict *fontDict); + CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits, + CharCodeToUnicode *ctu); + void findExtFontFile(); + + GString *tag; // PDF font tag + Ref id; // reference (used as unique ID) + GString *name; // font name + GString *origName; // original font name + GfxFontType type; // type of font + int flags; // font descriptor flags + GString *embFontName; // name of embedded font + Ref embFontID; // ref to embedded font file stream + GString *extFontFile; // external font file name + double fontMat[6]; // font matrix (Type 3 only) + double fontBBox[4]; // font bounding box (Type 3 only) + double missingWidth; // "default" width + double ascent; // max height above baseline + double descent; // max depth below baseline + GBool ok; +}; + +//------------------------------------------------------------------------ +// Gfx8BitFont +//------------------------------------------------------------------------ + +class Gfx8BitFont: public GfxFont { +public: + + Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, + GfxFontType typeA, Dict *fontDict); + + virtual ~Gfx8BitFont(); + + virtual int getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy); + virtual CharCodeToUnicode* getCTU(); + + // Return the encoding. + char **getEncoding() { return enc; } + + // Return the Unicode map. + CharCodeToUnicode *getToUnicode(); + + // Return the character name associated with . + char *getCharName(int code) { return code>=256?0:enc[code]; } + + // Returns true if the PDF font specified an encoding. + GBool getHasEncoding() { return hasEncoding; } + + // Returns true if the PDF font specified MacRomanEncoding. + GBool getUsesMacRomanEnc() { return usesMacRomanEnc; } + + // Get width of a character. + double getWidth(Guchar c) { return widths[c]; } + + // Return a char code-to-GID mapping for the provided font file. + // (This is only useful for TrueType fonts.) + Gushort *getCodeToGIDMap(FoFiTrueType *ff); + + // Return the Type 3 CharProc dictionary, or NULL if none. + Dict *getCharProcs(); + + // Return the Type 3 CharProc for the character associated with . + Object *getCharProc(int code, Object *proc); + + // Return the Type 3 Resources dictionary, or NULL if none. + Dict *getResources(); + +private: + + char *enc[256]; // char code --> char name + char encFree[256]; // boolean for each char name: if set, + // the string is malloc'ed + CharCodeToUnicode *ctu; // char code --> Unicode + GBool hasEncoding; + GBool usesMacRomanEnc; + double widths[256]; // character widths + Object charProcs; // Type 3 CharProcs dictionary + Object resources; // Type 3 Resources dictionary +}; + +//------------------------------------------------------------------------ +// GfxCIDFont +//------------------------------------------------------------------------ + +class GfxCIDFont: public GfxFont { +public: + + GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, + Dict *fontDict); + + virtual ~GfxCIDFont(); + + virtual GBool isCIDFont() { return gTrue; } + + virtual int getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy); + virtual CharCodeToUnicode* getCTU(); + + // Return the writing mode (0=horizontal, 1=vertical). + virtual int getWMode(); + + // Return the Unicode map. + CharCodeToUnicode *getToUnicode(); + + // Get the collection name (-). + GString *getCollection(); + + // Return the CID-to-GID mapping table. These should only be called + // if type is fontCIDType2. + Gushort *getCIDToGID() { return cidToGID; } + int getCIDToGIDLen() { return cidToGIDLen; } + +private: + + CMap *cMap; // char code --> CID + CharCodeToUnicode *ctu; // CID --> Unicode + GfxFontCIDWidths widths; // character widths + Gushort *cidToGID; // CID --> GID mapping (for embedded + // TrueType fonts) + int cidToGIDLen; +}; + +//------------------------------------------------------------------------ +// GfxFontDict +//------------------------------------------------------------------------ + +class GfxFontDict { +public: + + // Build the font dictionary, given the PDF font dictionary. + GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict); + + // Destructor. + ~GfxFontDict(); + + // Get the specified font. + GfxFont *lookup(char *tag); + + // Iterative access. + int getNumFonts() { return numFonts; } + GfxFont *getFont(int i) { return fonts[i]; } + +private: + + GfxFont **fonts; // list of fonts + int numFonts; // number of fonts +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Gfx.h swftools-0.9.1/lib/pdf/xpdf/Gfx.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Gfx.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Gfx.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,312 @@ +//======================================================================== +// +// Gfx.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GFX_H +#define GFX_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +class GString; +class XRef; +class Array; +class Stream; +class Parser; +class Dict; +class Function; +class OutputDev; +class GfxFontDict; +class GfxFont; +class GfxPattern; +class GfxTilingPattern; +class GfxShadingPattern; +class GfxShading; +class GfxFunctionShading; +class GfxAxialShading; +class GfxRadialShading; +class GfxGouraudTriangleShading; +class GfxPatchMeshShading; +struct GfxPatch; +class GfxState; +struct GfxColor; +class GfxColorSpace; +class Gfx; +class PDFRectangle; +class AnnotBorderStyle; + +//------------------------------------------------------------------------ + +enum GfxClipType { + clipNone, + clipNormal, + clipEO +}; + +enum TchkType { + tchkBool, // boolean + tchkInt, // integer + tchkNum, // number (integer or real) + tchkString, // string + tchkName, // name + tchkArray, // array + tchkProps, // properties (dictionary or name) + tchkSCN, // scn/SCN args (number of name) + tchkNone // used to avoid empty initializer lists +}; + +#define maxArgs 33 + +struct Operator { + char name[4]; + int numArgs; + TchkType tchk[maxArgs]; + void (Gfx::*func)(Object args[], int numArgs); +}; + +//------------------------------------------------------------------------ + +class GfxResources { +public: + + GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA); + ~GfxResources(); + + GfxFont *lookupFont(char *name); + GBool lookupXObject(char *name, Object *obj); + GBool lookupXObjectNF(char *name, Object *obj); + void lookupColorSpace(char *name, Object *obj); + GfxPattern *lookupPattern(char *name); + GfxShading *lookupShading(char *name); + GBool lookupGState(char *name, Object *obj); + + GfxResources *getNext() { return next; } + +private: + + GfxFontDict *fonts; + Object xObjDict; + Object colorSpaceDict; + Object patternDict; + Object shadingDict; + Object gStateDict; + GfxResources *next; +}; + +//------------------------------------------------------------------------ +// Gfx +//------------------------------------------------------------------------ + +class Gfx { +public: + + // Constructor for regular output. + Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, + double hDPI, double vDPI, PDFRectangle *box, + PDFRectangle *cropBox, int rotate, + GBool (*abortCheckCbkA)(void *data) = NULL, + void *abortCheckCbkDataA = NULL); + + // Constructor for a sub-page object. + Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict, + PDFRectangle *box, PDFRectangle *cropBox, + GBool (*abortCheckCbkA)(void *data) = NULL, + void *abortCheckCbkDataA = NULL); + + ~Gfx(); + + // Interpret a stream or array of streams. + void display(Object *obj, GBool topLevel = gTrue); + + // Display an annotation, given its appearance (a Form XObject), + // border style, and bounding box (in default user space). + void drawAnnot(Object *str, AnnotBorderStyle *borderStyle, + double xMin, double yMin, double xMax, double yMax); + + // Save graphics state. + void saveState(); + + // Restore graphics state. + void restoreState(); + + // Get the current graphics state object. + GfxState *getState() { return state; } + +private: + + XRef *xref; // the xref table for this PDF file + OutputDev *out; // output device + GBool subPage; // is this a sub-page object? + GBool printCommands; // print the drawing commands (for debugging) + GfxResources *res; // resource stack + int updateLevel; + + GfxState *state; // current graphics state + GBool fontChanged; // set if font or text matrix has changed + GfxClipType clip; // do a clip? + int ignoreUndef; // current BX/EX nesting level + double baseMatrix[6]; // default matrix for most recent + // page/form/pattern + int formDepth; + + Parser *parser; // parser for page content stream(s) + + GBool // callback to check for an abort + (*abortCheckCbk)(void *data); + void *abortCheckCbkData; + + static Operator opTab[]; // table of operators + + void go(GBool topLevel); + void execOp(Object *cmd, Object args[], int numArgs); + Operator *findOp(char *name); + GBool checkArg(Object *arg, TchkType type); + int getPos(); + + // graphics state operators + void opSave(Object args[], int numArgs); + void opRestore(Object args[], int numArgs); + void opConcat(Object args[], int numArgs); + void opSetDash(Object args[], int numArgs); + void opSetFlat(Object args[], int numArgs); + void opSetLineJoin(Object args[], int numArgs); + void opSetLineCap(Object args[], int numArgs); + void opSetMiterLimit(Object args[], int numArgs); + void opSetLineWidth(Object args[], int numArgs); + void opSetExtGState(Object args[], int numArgs); + void doSoftMask(Object *str, GBool alpha, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + Function *transferFunc, GfxColor *backdropColor); + void opSetRenderingIntent(Object args[], int numArgs); + + // color operators + void opSetFillGray(Object args[], int numArgs); + void opSetStrokeGray(Object args[], int numArgs); + void opSetFillCMYKColor(Object args[], int numArgs); + void opSetStrokeCMYKColor(Object args[], int numArgs); + void opSetFillRGBColor(Object args[], int numArgs); + void opSetStrokeRGBColor(Object args[], int numArgs); + void opSetFillColorSpace(Object args[], int numArgs); + void opSetStrokeColorSpace(Object args[], int numArgs); + void opSetFillColor(Object args[], int numArgs); + void opSetStrokeColor(Object args[], int numArgs); + void opSetFillColorN(Object args[], int numArgs); + void opSetStrokeColorN(Object args[], int numArgs); + + // path segment operators + void opMoveTo(Object args[], int numArgs); + void opLineTo(Object args[], int numArgs); + void opCurveTo(Object args[], int numArgs); + void opCurveTo1(Object args[], int numArgs); + void opCurveTo2(Object args[], int numArgs); + void opRectangle(Object args[], int numArgs); + void opClosePath(Object args[], int numArgs); + + // path painting operators + void opEndPath(Object args[], int numArgs); + void opStroke(Object args[], int numArgs); + void opCloseStroke(Object args[], int numArgs); + void opFill(Object args[], int numArgs); + void opEOFill(Object args[], int numArgs); + void opFillStroke(Object args[], int numArgs); + void opCloseFillStroke(Object args[], int numArgs); + void opEOFillStroke(Object args[], int numArgs); + void opCloseEOFillStroke(Object args[], int numArgs); + void doPatternFill(GBool eoFill); + void doPatternStroke(); + void doTilingPatternFill(GfxTilingPattern *tPat, + GBool stroke, GBool eoFill); + void doShadingPatternFill(GfxShadingPattern *sPat, + GBool stroke, GBool eoFill); + void opShFill(Object args[], int numArgs); + void doFunctionShFill(GfxFunctionShading *shading); + void doFunctionShFill1(GfxFunctionShading *shading, + double x0, double y0, + double x1, double y1, + GfxColor *colors, int depth); + void doAxialShFill(GfxAxialShading *shading); + void doRadialShFill(GfxRadialShading *shading); + void doGouraudTriangleShFill(GfxGouraudTriangleShading *shading); + void gouraudFillTriangle(double x0, double y0, GfxColor *color0, + double x1, double y1, GfxColor *color1, + double x2, double y2, GfxColor *color2, + int nComps, int depth); + void doPatchMeshShFill(GfxPatchMeshShading *shading); + void fillPatch(GfxPatch *patch, int nComps, int depth); + void doEndPath(); + + // path clipping operators + void opClip(Object args[], int numArgs); + void opEOClip(Object args[], int numArgs); + + // text object operators + void opBeginText(Object args[], int numArgs); + void opEndText(Object args[], int numArgs); + + // text state operators + void opSetCharSpacing(Object args[], int numArgs); + void opSetFont(Object args[], int numArgs); + void opSetTextLeading(Object args[], int numArgs); + void opSetTextRender(Object args[], int numArgs); + void opSetTextRise(Object args[], int numArgs); + void opSetWordSpacing(Object args[], int numArgs); + void opSetHorizScaling(Object args[], int numArgs); + + // text positioning operators + void opTextMove(Object args[], int numArgs); + void opTextMoveSet(Object args[], int numArgs); + void opSetTextMatrix(Object args[], int numArgs); + void opTextNextLine(Object args[], int numArgs); + + // text string operators + void opShowText(Object args[], int numArgs); + void opMoveShowText(Object args[], int numArgs); + void opMoveSetShowText(Object args[], int numArgs); + void opShowSpaceText(Object args[], int numArgs); + void doShowText(GString *s); + + // XObject operators + void opXObject(Object args[], int numArgs); + void doImage(Object *ref, Stream *str, GBool inlineImg); + void doForm(Object *str); + void doForm1(Object *str, Dict *resDict, double *matrix, double *bbox, + GBool transpGroup = gFalse, GBool softMask = gFalse, + GfxColorSpace *blendingColorSpace = NULL, + GBool isolated = gFalse, GBool knockout = gFalse, + GBool alpha = gFalse, Function *transferFunc = NULL, + GfxColor *backdropColor = NULL); + + // in-line image operators + void opBeginImage(Object args[], int numArgs); + Stream *buildImageStream(); + void opImageData(Object args[], int numArgs); + void opEndImage(Object args[], int numArgs); + + // type 3 font operators + void opSetCharWidth(Object args[], int numArgs); + void opSetCacheDevice(Object args[], int numArgs); + + // compatibility operators + void opBeginIgnoreUndef(Object args[], int numArgs); + void opEndIgnoreUndef(Object args[], int numArgs); + + // marked content operators + void opBeginMarkedContent(Object args[], int numArgs); + void opEndMarkedContent(Object args[], int numArgs); + void opMarkPoint(Object args[], int numArgs); + + void pushResources(Dict *resDict); + void popResources(); +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GfxState.cc swftools-0.9.1/lib/pdf/xpdf/GfxState.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/GfxState.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GfxState.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,4172 @@ +//======================================================================== +// +// GfxState.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include "gmem.h" +#include "Error.h" +#include "Object.h" +#include "Array.h" +#include "Page.h" +#include "GfxState.h" +#include "cmyk.h" + +//------------------------------------------------------------------------ + +static inline GfxColorComp clip01(GfxColorComp x) { + return (x < 0) ? 0 : (x > gfxColorComp1) ? gfxColorComp1 : x; +} + +static inline double clip01(double x) { + return (x < 0) ? 0 : (x > 1) ? 1 : x; +} + +//------------------------------------------------------------------------ + +struct GfxBlendModeInfo { + char *name; + GfxBlendMode mode; +}; + +static GfxBlendModeInfo gfxBlendModeNames[] = { + { "Normal", gfxBlendNormal }, + { "Compatible", gfxBlendNormal }, + { "Multiply", gfxBlendMultiply }, + { "Screen", gfxBlendScreen }, + { "Overlay", gfxBlendOverlay }, + { "Darken", gfxBlendDarken }, + { "Lighten", gfxBlendLighten }, + { "ColorDodge", gfxBlendColorDodge }, + { "ColorBurn", gfxBlendColorBurn }, + { "HardLight", gfxBlendHardLight }, + { "SoftLight", gfxBlendSoftLight }, + { "Difference", gfxBlendDifference }, + { "Exclusion", gfxBlendExclusion }, + { "Hue", gfxBlendHue }, + { "Saturation", gfxBlendSaturation }, + { "Color", gfxBlendColor }, + { "Luminosity", gfxBlendLuminosity } +}; + +#define nGfxBlendModeNames \ + ((int)((sizeof(gfxBlendModeNames) / sizeof(GfxBlendModeInfo)))) + +//------------------------------------------------------------------------ + +// NB: This must match the GfxColorSpaceMode enum defined in +// GfxState.h +static char *gfxColorSpaceModeNames[] = { + "DeviceGray", + "CalGray", + "DeviceRGB", + "CalRGB", + "DeviceCMYK", + "Lab", + "ICCBased", + "Indexed", + "Separation", + "DeviceN", + "Pattern" +}; + +#define nGfxColorSpaceModes ((sizeof(gfxColorSpaceModeNames) / sizeof(char *))) + +//------------------------------------------------------------------------ +// GfxColorSpace +//------------------------------------------------------------------------ + +GfxColorSpace::GfxColorSpace() { +} + +GfxColorSpace::~GfxColorSpace() { +} + +GfxColorSpace *GfxColorSpace::parse(Object *csObj, StreamColorSpaceMode csMode) { + GfxColorSpace *cs; + Object obj1; + + cs = NULL; + if (csObj->isName()) { + if (csObj->isName("DeviceGray") || csObj->isName("G")) { + cs = new GfxDeviceGrayColorSpace(); + } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) { + if(csMode == streamCSDeviceRGBX) + cs = new GfxDeviceRGBXColorSpace(); + else + cs = new GfxDeviceRGBColorSpace(); + } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) { + cs = new GfxDeviceCMYKColorSpace(); + } else if (csObj->isName("Pattern")) { + cs = new GfxPatternColorSpace(NULL); + } else { + error(-1, "Bad color space '%s'", csObj->getName()); + } + } else if (csObj->isArray()) { + csObj->arrayGet(0, &obj1); + if (obj1.isName("DeviceGray") || obj1.isName("G")) { + cs = new GfxDeviceGrayColorSpace(); + } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) { + if(csMode == streamCSDeviceRGBX) + cs = new GfxDeviceRGBColorSpace(); + else + cs = new GfxDeviceRGBColorSpace(); + } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) { + cs = new GfxDeviceCMYKColorSpace(); + } else if (obj1.isName("CalGray")) { + cs = GfxCalGrayColorSpace::parse(csObj->getArray()); + } else if (obj1.isName("CalRGB")) { + cs = GfxCalRGBColorSpace::parse(csObj->getArray()); + } else if (obj1.isName("Lab")) { + cs = GfxLabColorSpace::parse(csObj->getArray()); + } else if (obj1.isName("ICCBased")) { + cs = GfxICCBasedColorSpace::parse(csObj->getArray()); + } else if (obj1.isName("Indexed") || obj1.isName("I")) { + cs = GfxIndexedColorSpace::parse(csObj->getArray()); + } else if (obj1.isName("Separation")) { + cs = GfxSeparationColorSpace::parse(csObj->getArray()); + } else if (obj1.isName("DeviceN")) { + cs = GfxDeviceNColorSpace::parse(csObj->getArray()); + } else if (obj1.isName("Pattern")) { + cs = GfxPatternColorSpace::parse(csObj->getArray()); + } else { + error(-1, "Bad color space"); + } + obj1.free(); + } else { + error(-1, "Bad color space - expected name or array"); + } + return cs; +} + +void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel) { + int i; + + for (i = 0; i < getNComps(); ++i) { + decodeLow[i] = 0; + decodeRange[i] = 1; + } +} + +int GfxColorSpace::getNumColorSpaceModes() { + return nGfxColorSpaceModes; +} + +char *GfxColorSpace::getColorSpaceModeName(int idx) { + return gfxColorSpaceModeNames[idx]; +} + +//------------------------------------------------------------------------ +// GfxDeviceGrayColorSpace +//------------------------------------------------------------------------ + +GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() { +} + +GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() { +} + +GfxColorSpace *GfxDeviceGrayColorSpace::copy() { + return new GfxDeviceGrayColorSpace(); +} + +void GfxDeviceGrayColorSpace::getGray(GfxColor *color, GfxGray *gray) { + *gray = clip01(color->c[0]); +} + +void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + rgb->r = rgb->g = rgb->b = clip01(color->c[0]); +} + +void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { + cmyk->c = cmyk->m = cmyk->y = 0; + cmyk->k = clip01(gfxColorComp1 - color->c[0]); +} + +void GfxDeviceGrayColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; +} + +//------------------------------------------------------------------------ +// GfxCalGrayColorSpace +//------------------------------------------------------------------------ + +GfxCalGrayColorSpace::GfxCalGrayColorSpace() { + whiteX = whiteY = whiteZ = 1; + blackX = blackY = blackZ = 0; + gamma = 1; +} + +GfxCalGrayColorSpace::~GfxCalGrayColorSpace() { +} + +GfxColorSpace *GfxCalGrayColorSpace::copy() { + GfxCalGrayColorSpace *cs; + + cs = new GfxCalGrayColorSpace(); + cs->whiteX = whiteX; + cs->whiteY = whiteY; + cs->whiteZ = whiteZ; + cs->blackX = blackX; + cs->blackY = blackY; + cs->blackZ = blackZ; + cs->gamma = gamma; + return cs; +} + +GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) { + GfxCalGrayColorSpace *cs; + Object obj1, obj2, obj3; + + arr->get(1, &obj1); + if (!obj1.isDict()) { + error(-1, "Bad CalGray color space"); + obj1.free(); + return NULL; + } + cs = new GfxCalGrayColorSpace(); + if (obj1.dictLookup("WhitePoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->whiteX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->whiteY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->whiteZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("BlackPoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->blackX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->blackY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->blackZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("Gamma", &obj2)->isNum()) { + cs->gamma = obj2.getNum(); + } + obj2.free(); + obj1.free(); + return cs; +} + +void GfxCalGrayColorSpace::getGray(GfxColor *color, GfxGray *gray) { + *gray = clip01(color->c[0]); +} + +void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + rgb->r = rgb->g = rgb->b = clip01(color->c[0]); +} + +void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { + cmyk->c = cmyk->m = cmyk->y = 0; + cmyk->k = clip01(gfxColorComp1 - color->c[0]); +} + +void GfxCalGrayColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; +} + +//------------------------------------------------------------------------ +// GfxDeviceRGBColorSpace +//------------------------------------------------------------------------ + +GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() { +} + +GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() { +} + +GfxColorSpace *GfxDeviceRGBColorSpace::copy() { + return new GfxDeviceRGBColorSpace(); +} + +void GfxDeviceRGBColorSpace::getGray(GfxColor *color, GfxGray *gray) { + *gray = clip01((GfxColorComp)(0.3 * color->c[0] + + 0.59 * color->c[1] + + 0.11 * color->c[2] + 0.5)); +} + +void GfxDeviceRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + rgb->r = clip01(color->c[0]); + rgb->g = clip01(color->c[1]); + rgb->b = clip01(color->c[2]); +} + +void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { + GfxColorComp c, m, y, k; + + c = clip01(gfxColorComp1 - color->c[0]); + m = clip01(gfxColorComp1 - color->c[1]); + y = clip01(gfxColorComp1 - color->c[2]); + k = c; + if (m < k) { + k = m; + } + if (y < k) { + k = y; + } + cmyk->c = c - k; + cmyk->m = m - k; + cmyk->y = y - k; + cmyk->k = k; +} + +void GfxDeviceRGBColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; + color->c[1] = 0; + color->c[2] = 0; +} + +//------------------------------------------------------------------------ +// GfxDeviceRGBXColorSpace +//------------------------------------------------------------------------ + +GfxDeviceRGBXColorSpace::GfxDeviceRGBXColorSpace() { +} + +GfxColorSpace *GfxDeviceRGBXColorSpace::copy() { + return new GfxDeviceRGBXColorSpace(); +} + +//------------------------------------------------------------------------ +// GfxCalRGBColorSpace +//------------------------------------------------------------------------ + +GfxCalRGBColorSpace::GfxCalRGBColorSpace() { + whiteX = whiteY = whiteZ = 1; + blackX = blackY = blackZ = 0; + gammaR = gammaG = gammaB = 1; + mat[0] = 1; mat[1] = 0; mat[2] = 0; + mat[3] = 0; mat[4] = 1; mat[5] = 0; + mat[6] = 0; mat[7] = 0; mat[8] = 1; +} + +GfxCalRGBColorSpace::~GfxCalRGBColorSpace() { +} + +GfxColorSpace *GfxCalRGBColorSpace::copy() { + GfxCalRGBColorSpace *cs; + int i; + + cs = new GfxCalRGBColorSpace(); + cs->whiteX = whiteX; + cs->whiteY = whiteY; + cs->whiteZ = whiteZ; + cs->blackX = blackX; + cs->blackY = blackY; + cs->blackZ = blackZ; + cs->gammaR = gammaR; + cs->gammaG = gammaG; + cs->gammaB = gammaB; + for (i = 0; i < 9; ++i) { + cs->mat[i] = mat[i]; + } + return cs; +} + +GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) { + GfxCalRGBColorSpace *cs; + Object obj1, obj2, obj3; + int i; + + arr->get(1, &obj1); + if (!obj1.isDict()) { + error(-1, "Bad CalRGB color space"); + obj1.free(); + return NULL; + } + cs = new GfxCalRGBColorSpace(); + if (obj1.dictLookup("WhitePoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->whiteX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->whiteY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->whiteZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("BlackPoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->blackX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->blackY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->blackZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("Gamma", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->gammaR = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->gammaG = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->gammaB = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("Matrix", &obj2)->isArray() && + obj2.arrayGetLength() == 9) { + for (i = 0; i < 9; ++i) { + obj2.arrayGet(i, &obj3); + cs->mat[i] = obj3.getNum(); + obj3.free(); + } + } + obj2.free(); + obj1.free(); + return cs; +} + +void GfxCalRGBColorSpace::getGray(GfxColor *color, GfxGray *gray) { + *gray = clip01((GfxColorComp)(0.299 * color->c[0] + + 0.587 * color->c[1] + + 0.114 * color->c[2] + 0.5)); +} + +void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + rgb->r = clip01(color->c[0]); + rgb->g = clip01(color->c[1]); + rgb->b = clip01(color->c[2]); +} + +void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { + GfxColorComp c, m, y, k; + + c = clip01(gfxColorComp1 - color->c[0]); + m = clip01(gfxColorComp1 - color->c[1]); + y = clip01(gfxColorComp1 - color->c[2]); + k = c; + if (m < k) { + k = m; + } + if (y < k) { + k = y; + } + cmyk->c = c - k; + cmyk->m = m - k; + cmyk->y = y - k; + cmyk->k = k; +} + +void GfxCalRGBColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; + color->c[1] = 0; + color->c[2] = 0; +} + +//------------------------------------------------------------------------ +// GfxDeviceCMYKColorSpace +//------------------------------------------------------------------------ + +GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() { +} + +GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() { +} + +GfxColorSpace *GfxDeviceCMYKColorSpace::copy() { + return new GfxDeviceCMYKColorSpace(); +} + +void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, GfxGray *gray) { + *gray = clip01((GfxColorComp)(gfxColorComp1 - color->c[3] + - 0.3 * color->c[0] + - 0.59 * color->c[1] + - 0.11 * color->c[2] + 0.5)); +} + +/*void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + unsigned char r,g,b; + float c = color->c[0]; + float m = color->c[1]; + float y = color->c[2]; + float k = color->c[3]; + convert_cmyk2rgb(c,m,y,k, &r,&g,&b); + rgb->r = r/255.0; + rgb->g = g/255.0; + rgb->b = b/255.0; +}*/ + +void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + double c, m, y, k, c1, m1, y1, k1, r, g, b, x; + + c = colToDbl(color->c[0]); + m = colToDbl(color->c[1]); + y = colToDbl(color->c[2]); + k = colToDbl(color->c[3]); + c1 = 1 - c; + m1 = 1 - m; + y1 = 1 - y; + k1 = 1 - k; + // this is a matrix multiplication, unrolled for performance + // C M Y K + x = c1 * m1 * y1 * k1; // 0 0 0 0 + r = g = b = x; + x = c1 * m1 * y1 * k; // 0 0 0 1 + r += 0.1373 * x; + g += 0.1216 * x; + b += 0.1255 * x; + x = c1 * m1 * y * k1; // 0 0 1 0 + r += x; + g += 0.9490 * x; + x = c1 * m1 * y * k; // 0 0 1 1 + r += 0.1098 * x; + g += 0.1020 * x; + x = c1 * m * y1 * k1; // 0 1 0 0 + r += 0.9255 * x; + b += 0.5490 * x; + x = c1 * m * y1 * k; // 0 1 0 1 + r += 0.1412 * x; + x = c1 * m * y * k1; // 0 1 1 0 + r += 0.9294 * x; + g += 0.1098 * x; + b += 0.1412 * x; + x = c1 * m * y * k; // 0 1 1 1 + r += 0.1333 * x; + x = c * m1 * y1 * k1; // 1 0 0 0 + g += 0.6784 * x; + b += 0.9373 * x; + x = c * m1 * y1 * k; // 1 0 0 1 + g += 0.0588 * x; + b += 0.1412 * x; + x = c * m1 * y * k1; // 1 0 1 0 + g += 0.6510 * x; + b += 0.3137 * x; + x = c * m1 * y * k; // 1 0 1 1 + g += 0.0745 * x; + x = c * m * y1 * k1; // 1 1 0 0 + r += 0.1804 * x; + g += 0.1922 * x; + b += 0.5725 * x; + x = c * m * y1 * k; // 1 1 0 1 + b += 0.0078 * x; + x = c * m * y * k1; // 1 1 1 0 + r += 0.2118 * x; + g += 0.2119 * x; + b += 0.2235 * x; + rgb->r = clip01(dblToCol(r)); + rgb->g = clip01(dblToCol(g)); + rgb->b = clip01(dblToCol(b)); +} + +void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { + cmyk->c = clip01(color->c[0]); + cmyk->m = clip01(color->c[1]); + cmyk->y = clip01(color->c[2]); + cmyk->k = clip01(color->c[3]); +} + +void GfxDeviceCMYKColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; + color->c[1] = 0; + color->c[2] = 0; + color->c[3] = gfxColorComp1; +} + +//------------------------------------------------------------------------ +// GfxLabColorSpace +//------------------------------------------------------------------------ + +// This is the inverse of MatrixLMN in Example 4.10 from the PostScript +// Language Reference, Third Edition. +static double xyzrgb[3][3] = { + { 3.240449, -1.537136, -0.498531 }, + { -0.969265, 1.876011, 0.041556 }, + { 0.055643, -0.204026, 1.057229 } +}; + +GfxLabColorSpace::GfxLabColorSpace() { + whiteX = whiteY = whiteZ = 1; + blackX = blackY = blackZ = 0; + aMin = bMin = -100; + aMax = bMax = 100; +} + +GfxLabColorSpace::~GfxLabColorSpace() { +} + +GfxColorSpace *GfxLabColorSpace::copy() { + GfxLabColorSpace *cs; + + cs = new GfxLabColorSpace(); + cs->whiteX = whiteX; + cs->whiteY = whiteY; + cs->whiteZ = whiteZ; + cs->blackX = blackX; + cs->blackY = blackY; + cs->blackZ = blackZ; + cs->aMin = aMin; + cs->aMax = aMax; + cs->bMin = bMin; + cs->bMax = bMax; + cs->kr = kr; + cs->kg = kg; + cs->kb = kb; + return cs; +} + +GfxColorSpace *GfxLabColorSpace::parse(Array *arr) { + GfxLabColorSpace *cs; + Object obj1, obj2, obj3; + + arr->get(1, &obj1); + if (!obj1.isDict()) { + error(-1, "Bad Lab color space"); + obj1.free(); + return NULL; + } + cs = new GfxLabColorSpace(); + if (obj1.dictLookup("WhitePoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->whiteX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->whiteY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->whiteZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("BlackPoint", &obj2)->isArray() && + obj2.arrayGetLength() == 3) { + obj2.arrayGet(0, &obj3); + cs->blackX = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->blackY = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->blackZ = obj3.getNum(); + obj3.free(); + } + obj2.free(); + if (obj1.dictLookup("Range", &obj2)->isArray() && + obj2.arrayGetLength() == 4) { + obj2.arrayGet(0, &obj3); + cs->aMin = obj3.getNum(); + obj3.free(); + obj2.arrayGet(1, &obj3); + cs->aMax = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2, &obj3); + cs->bMin = obj3.getNum(); + obj3.free(); + obj2.arrayGet(3, &obj3); + cs->bMax = obj3.getNum(); + obj3.free(); + } + obj2.free(); + obj1.free(); + + cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX + + xyzrgb[0][1] * cs->whiteY + + xyzrgb[0][2] * cs->whiteZ); + cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX + + xyzrgb[1][1] * cs->whiteY + + xyzrgb[1][2] * cs->whiteZ); + cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX + + xyzrgb[2][1] * cs->whiteY + + xyzrgb[2][2] * cs->whiteZ); + + return cs; +} + +void GfxLabColorSpace::getGray(GfxColor *color, GfxGray *gray) { + GfxRGB rgb; + + getRGB(color, &rgb); + *gray = clip01((GfxColorComp)(0.299 * rgb.r + + 0.587 * rgb.g + + 0.114 * rgb.b + 0.5)); +} + +void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + double X, Y, Z; + double t1, t2; + double r, g, b; + + // convert L*a*b* to CIE 1931 XYZ color space + t1 = (colToDbl(color->c[0]) + 16) / 116; + t2 = t1 + colToDbl(color->c[1]) / 500; + if (t2 >= (6.0 / 29.0)) { + X = t2 * t2 * t2; + } else { + X = (108.0 / 841.0) * (t2 - (4.0 / 29.0)); + } + X *= whiteX; + if (t1 >= (6.0 / 29.0)) { + Y = t1 * t1 * t1; + } else { + Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0)); + } + Y *= whiteY; + t2 = t1 - colToDbl(color->c[2]) / 200; + if (t2 >= (6.0 / 29.0)) { + Z = t2 * t2 * t2; + } else { + Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0)); + } + Z *= whiteZ; + + // convert XYZ to RGB, including gamut mapping and gamma correction + r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z; + g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z; + b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z; + rgb->r = dblToCol(pow(clip01(r * kr), 0.5)); + rgb->g = dblToCol(pow(clip01(g * kg), 0.5)); + rgb->b = dblToCol(pow(clip01(b * kb), 0.5)); +} + +void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { + GfxRGB rgb; + GfxColorComp c, m, y, k; + + getRGB(color, &rgb); + c = clip01(gfxColorComp1 - rgb.r); + m = clip01(gfxColorComp1 - rgb.g); + y = clip01(gfxColorComp1 - rgb.b); + k = c; + if (m < k) { + k = m; + } + if (y < k) { + k = y; + } + cmyk->c = c - k; + cmyk->m = m - k; + cmyk->y = y - k; + cmyk->k = k; +} + +void GfxLabColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; + if (aMin > 0) { + color->c[1] = dblToCol(aMin); + } else if (aMax < 0) { + color->c[1] = dblToCol(aMax); + } else { + color->c[1] = 0; + } + if (bMin > 0) { + color->c[2] = dblToCol(bMin); + } else if (bMax < 0) { + color->c[2] = dblToCol(bMax); + } else { + color->c[2] = 0; + } +} + +void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel) { + decodeLow[0] = 0; + decodeRange[0] = 100; + decodeLow[1] = aMin; + decodeRange[1] = aMax - aMin; + decodeLow[2] = bMin; + decodeRange[2] = bMax - bMin; +} + +//------------------------------------------------------------------------ +// GfxICCBasedColorSpace +//------------------------------------------------------------------------ + +GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA, + Ref *iccProfileStreamA) { + nComps = nCompsA; + alt = altA; + iccProfileStream = *iccProfileStreamA; + rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0; + rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1; +} + +GfxICCBasedColorSpace::~GfxICCBasedColorSpace() { + delete alt; +} + +GfxColorSpace *GfxICCBasedColorSpace::copy() { + GfxICCBasedColorSpace *cs; + int i; + + cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream); + for (i = 0; i < 4; ++i) { + cs->rangeMin[i] = rangeMin[i]; + cs->rangeMax[i] = rangeMax[i]; + } + return cs; +} + +GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) { + GfxICCBasedColorSpace *cs; + Ref iccProfileStreamA; + int nCompsA; + GfxColorSpace *altA; + Dict *dict; + Object obj1, obj2, obj3; + int i; + + arr->getNF(1, &obj1); + if (obj1.isRef()) { + iccProfileStreamA = obj1.getRef(); + } else { + iccProfileStreamA.num = 0; + iccProfileStreamA.gen = 0; + } + obj1.free(); + arr->get(1, &obj1); + if (!obj1.isStream()) { + error(-1, "Bad ICCBased color space (stream)"); + obj1.free(); + return NULL; + } + dict = obj1.streamGetDict(); + if (!dict->lookup("N", &obj2)->isInt()) { + error(-1, "Bad ICCBased color space (N)"); + obj2.free(); + obj1.free(); + return NULL; + } + nCompsA = obj2.getInt(); + obj2.free(); + if (nCompsA > gfxColorMaxComps) { + error(-1, "ICCBased color space with too many (%d > %d) components", + nCompsA, gfxColorMaxComps); + nCompsA = gfxColorMaxComps; + } + if (dict->lookup("Alternate", &obj2)->isNull() || + !(altA = GfxColorSpace::parse(&obj2))) { + switch (nCompsA) { + case 1: + altA = new GfxDeviceGrayColorSpace(); + break; + case 3: + altA = new GfxDeviceRGBColorSpace(); + break; + case 4: + altA = new GfxDeviceCMYKColorSpace(); + break; + default: + error(-1, "Bad ICCBased color space - invalid N"); + obj2.free(); + obj1.free(); + return NULL; + } + } + obj2.free(); + cs = new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA); + if (dict->lookup("Range", &obj2)->isArray() && + obj2.arrayGetLength() == 2 * nCompsA) { + for (i = 0; i < nCompsA; ++i) { + obj2.arrayGet(2*i, &obj3); + cs->rangeMin[i] = obj3.getNum(); + obj3.free(); + obj2.arrayGet(2*i+1, &obj3); + cs->rangeMax[i] = obj3.getNum(); + obj3.free(); + } + } + obj2.free(); + obj1.free(); + return cs; +} + +void GfxICCBasedColorSpace::getGray(GfxColor *color, GfxGray *gray) { + alt->getGray(color, gray); +} + +void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + alt->getRGB(color, rgb); +} + +void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { + alt->getCMYK(color, cmyk); +} + +void GfxICCBasedColorSpace::getDefaultColor(GfxColor *color) { + int i; + + for (i = 0; i < nComps; ++i) { + if (rangeMin[i] > 0) { + color->c[i] = dblToCol(rangeMin[i]); + } else if (rangeMax[i] < 0) { + color->c[i] = dblToCol(rangeMax[i]); + } else { + color->c[i] = 0; + } + } +} + +void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow, + double *decodeRange, + int maxImgPixel) { + alt->getDefaultRanges(decodeLow, decodeRange, maxImgPixel); + +#if 0 + // this is nominally correct, but some PDF files don't set the + // correct ranges in the ICCBased dict + int i; + + for (i = 0; i < nComps; ++i) { + decodeLow[i] = rangeMin[i]; + decodeRange[i] = rangeMax[i] - rangeMin[i]; + } +#endif +} + +//------------------------------------------------------------------------ +// GfxIndexedColorSpace +//------------------------------------------------------------------------ + +GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA, + int indexHighA) { + base = baseA; + indexHigh = indexHighA; + lookup = (Guchar *)gmallocn((indexHigh + 1) * base->getNComps(), + sizeof(Guchar)); +} + +GfxIndexedColorSpace::~GfxIndexedColorSpace() { + delete base; + gfree(lookup); +} + +GfxColorSpace *GfxIndexedColorSpace::copy() { + GfxIndexedColorSpace *cs; + + cs = new GfxIndexedColorSpace(base->copy(), indexHigh); + memcpy(cs->lookup, lookup, + (indexHigh + 1) * base->getNComps() * sizeof(Guchar)); + return cs; +} + +GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) { + GfxIndexedColorSpace *cs; + GfxColorSpace *baseA; + int indexHighA; + Object obj1; + int x; + char *s; + int n, i, j; + + if (arr->getLength() != 4) { + error(-1, "Bad Indexed color space"); + goto err1; + } + arr->get(1, &obj1); + if (!(baseA = GfxColorSpace::parse(&obj1))) { + error(-1, "Bad Indexed color space (base color space)"); + goto err2; + } + obj1.free(); + if (!arr->get(2, &obj1)->isInt()) { + error(-1, "Bad Indexed color space (hival)"); + delete baseA; + goto err2; + } + indexHighA = obj1.getInt(); + if (indexHighA < 0 || indexHighA > 255) { + // the PDF spec requires indexHigh to be in [0,255] -- allowing + // values larger than 255 creates a security hole: if nComps * + // indexHigh is greater than 2^31, the loop below may overwrite + // past the end of the array + error(-1, "Bad Indexed color space (invalid indexHigh value)"); + delete baseA; + goto err2; + } + obj1.free(); + cs = new GfxIndexedColorSpace(baseA, indexHighA); + arr->get(3, &obj1); + n = baseA->getNComps(); + if (obj1.isStream()) { + obj1.streamReset(); + for (i = 0; i <= indexHighA; ++i) { + for (j = 0; j < n; ++j) { + if ((x = obj1.streamGetChar()) == EOF) { + error(-1, "Bad Indexed color space (lookup table stream too short)"); + goto err3; + } + cs->lookup[i*n + j] = (Guchar)x; + } + } + obj1.streamClose(); + } else if (obj1.isString()) { + if (obj1.getString()->getLength() < (indexHighA + 1) * n) { + error(-1, "Bad Indexed color space (lookup table string too short)"); + goto err3; + } + s = obj1.getString()->getCString(); + for (i = 0; i <= indexHighA; ++i) { + for (j = 0; j < n; ++j) { + cs->lookup[i*n + j] = (Guchar)*s++; + } + } + } else { + error(-1, "Bad Indexed color space (lookup table)"); + goto err3; + } + obj1.free(); + return cs; + + err3: + delete cs; + err2: + obj1.free(); + err1: + return NULL; +} + +GfxColor *GfxIndexedColorSpace::mapColorToBase(GfxColor *color, + GfxColor *baseColor) { + Guchar *p; + double low[gfxColorMaxComps], range[gfxColorMaxComps]; + int n, i; + + n = base->getNComps(); + base->getDefaultRanges(low, range, indexHigh); + p = &lookup[(int)(colToDbl(color->c[0]) + 0.5) * n]; + for (i = 0; i < n; ++i) { + baseColor->c[i] = dblToCol(low[i] + (p[i] / 255.0) * range[i]); + } + return baseColor; +} + +void GfxIndexedColorSpace::getGray(GfxColor *color, GfxGray *gray) { + GfxColor color2; + + base->getGray(mapColorToBase(color, &color2), gray); +} + +void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + GfxColor color2; + + base->getRGB(mapColorToBase(color, &color2), rgb); +} + +void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { + GfxColor color2; + + base->getCMYK(mapColorToBase(color, &color2), cmyk); +} + +void GfxIndexedColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = 0; +} + +void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow, + double *decodeRange, + int maxImgPixel) { + decodeLow[0] = 0; + decodeRange[0] = maxImgPixel; +} + +//------------------------------------------------------------------------ +// GfxSeparationColorSpace +//------------------------------------------------------------------------ + +GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA, + GfxColorSpace *altA, + Function *funcA) { + name = nameA; + alt = altA; + func = funcA; + nonMarking = !name->cmp("None"); +} + +GfxSeparationColorSpace::~GfxSeparationColorSpace() { + delete name; + delete alt; + delete func; +} + +GfxColorSpace *GfxSeparationColorSpace::copy() { + return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy()); +} + +//~ handle the 'All' and 'None' colorants +GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) { + GfxSeparationColorSpace *cs; + GString *nameA; + GfxColorSpace *altA; + Function *funcA; + Object obj1; + + if (arr->getLength() != 4) { + error(-1, "Bad Separation color space"); + goto err1; + } + if (!arr->get(1, &obj1)->isName()) { + error(-1, "Bad Separation color space (name)"); + goto err2; + } + nameA = new GString(obj1.getName()); + obj1.free(); + arr->get(2, &obj1); + if (!(altA = GfxColorSpace::parse(&obj1))) { + error(-1, "Bad Separation color space (alternate color space)"); + goto err3; + } + obj1.free(); + arr->get(3, &obj1); + if (!(funcA = Function::parse(&obj1))) { + goto err4; + } + obj1.free(); + cs = new GfxSeparationColorSpace(nameA, altA, funcA); + return cs; + + err4: + delete altA; + err3: + delete nameA; + err2: + obj1.free(); + err1: + return NULL; +} + +void GfxSeparationColorSpace::getGray(GfxColor *color, GfxGray *gray) { + double x; + double c[gfxColorMaxComps]; + GfxColor color2; + int i; + + x = colToDbl(color->c[0]); + func->transform(&x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getGray(&color2, gray); +} + +void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + double x; + double c[gfxColorMaxComps]; + GfxColor color2; + int i; + + x = colToDbl(color->c[0]); + func->transform(&x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getRGB(&color2, rgb); +} + +void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { + double x; + double c[gfxColorMaxComps]; + GfxColor color2; + int i; + + x = colToDbl(color->c[0]); + func->transform(&x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getCMYK(&color2, cmyk); +} + +void GfxSeparationColorSpace::getDefaultColor(GfxColor *color) { + color->c[0] = gfxColorComp1; +} + +//------------------------------------------------------------------------ +// GfxDeviceNColorSpace +//------------------------------------------------------------------------ + +GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA, + GfxColorSpace *altA, + Function *funcA) { + nComps = nCompsA; + alt = altA; + func = funcA; + nonMarking = gFalse; +} + +GfxDeviceNColorSpace::~GfxDeviceNColorSpace() { + int i; + + for (i = 0; i < nComps; ++i) { + delete names[i]; + } + delete alt; + delete func; +} + +GfxColorSpace *GfxDeviceNColorSpace::copy() { + GfxDeviceNColorSpace *cs; + int i; + + cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy()); + for (i = 0; i < nComps; ++i) { + cs->names[i] = names[i]->copy(); + } + cs->nonMarking = nonMarking; + return cs; +} + +//~ handle the 'None' colorant +GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) { + GfxDeviceNColorSpace *cs; + int nCompsA; + GString *namesA[gfxColorMaxComps]; + GfxColorSpace *altA; + Function *funcA; + Object obj1, obj2; + int i; + + if (arr->getLength() != 4 && arr->getLength() != 5) { + error(-1, "Bad DeviceN color space"); + goto err1; + } + if (!arr->get(1, &obj1)->isArray()) { + error(-1, "Bad DeviceN color space (names)"); + goto err2; + } + nCompsA = obj1.arrayGetLength(); + if (nCompsA > gfxColorMaxComps) { + error(-1, "DeviceN color space with too many (%d > %d) components", + nCompsA, gfxColorMaxComps); + nCompsA = gfxColorMaxComps; + } + for (i = 0; i < nCompsA; ++i) { + if (!obj1.arrayGet(i, &obj2)->isName()) { + error(-1, "Bad DeviceN color space (names)"); + obj2.free(); + goto err2; + } + namesA[i] = new GString(obj2.getName()); + obj2.free(); + } + obj1.free(); + arr->get(2, &obj1); + if (!(altA = GfxColorSpace::parse(&obj1))) { + error(-1, "Bad DeviceN color space (alternate color space)"); + goto err3; + } + obj1.free(); + arr->get(3, &obj1); + if (!(funcA = Function::parse(&obj1))) { + goto err4; + } + obj1.free(); + cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA); + cs->nonMarking = gTrue; + for (i = 0; i < nCompsA; ++i) { + cs->names[i] = namesA[i]; + if (namesA[i]->cmp("None")) { + cs->nonMarking = gFalse; + } + } + return cs; + + err4: + delete altA; + err3: + for (i = 0; i < nCompsA; ++i) { + delete namesA[i]; + } + err2: + obj1.free(); + err1: + return NULL; +} + +void GfxDeviceNColorSpace::getGray(GfxColor *color, GfxGray *gray) { + double x[gfxColorMaxComps], c[gfxColorMaxComps]; + GfxColor color2; + int i; + + for (i = 0; i < nComps; ++i) { + x[i] = colToDbl(color->c[i]); + } + func->transform(x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getGray(&color2, gray); +} + +void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + double x[gfxColorMaxComps], c[gfxColorMaxComps]; + GfxColor color2; + int i; + + for (i = 0; i < nComps; ++i) { + x[i] = colToDbl(color->c[i]); + } + func->transform(x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getRGB(&color2, rgb); +} + +void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { + double x[gfxColorMaxComps], c[gfxColorMaxComps]; + GfxColor color2; + int i; + + for (i = 0; i < nComps; ++i) { + x[i] = colToDbl(color->c[i]); + } + func->transform(x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getCMYK(&color2, cmyk); +} + +void GfxDeviceNColorSpace::getDefaultColor(GfxColor *color) { + int i; + + for (i = 0; i < nComps; ++i) { + color->c[i] = gfxColorComp1; + } +} + +//------------------------------------------------------------------------ +// GfxPatternColorSpace +//------------------------------------------------------------------------ + +GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) { + under = underA; +} + +GfxPatternColorSpace::~GfxPatternColorSpace() { + if (under) { + delete under; + } +} + +GfxColorSpace *GfxPatternColorSpace::copy() { + return new GfxPatternColorSpace(under ? under->copy() : + (GfxColorSpace *)NULL); +} + +GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) { + GfxPatternColorSpace *cs; + GfxColorSpace *underA; + Object obj1; + + if (arr->getLength() != 1 && arr->getLength() != 2) { + error(-1, "Bad Pattern color space"); + return NULL; + } + underA = NULL; + if (arr->getLength() == 2) { + arr->get(1, &obj1); + if (!(underA = GfxColorSpace::parse(&obj1))) { + error(-1, "Bad Pattern color space (underlying color space)"); + obj1.free(); + return NULL; + } + obj1.free(); + } + cs = new GfxPatternColorSpace(underA); + return cs; +} + +void GfxPatternColorSpace::getGray(GfxColor *color, GfxGray *gray) { + *gray = 0; +} + +void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + rgb->r = rgb->g = rgb->b = 0; +} + +void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { + cmyk->c = cmyk->m = cmyk->y = 0; + cmyk->k = 1; +} + +void GfxPatternColorSpace::getDefaultColor(GfxColor *color) { + // not used +} + +//------------------------------------------------------------------------ +// Pattern +//------------------------------------------------------------------------ + +GfxPattern::GfxPattern(int typeA) { + type = typeA; +} + +GfxPattern::~GfxPattern() { +} + +GfxPattern *GfxPattern::parse(Object *obj) { + GfxPattern *pattern; + Object obj1; + + if (obj->isDict()) { + obj->dictLookup("PatternType", &obj1); + } else if (obj->isStream()) { + obj->streamGetDict()->lookup("PatternType", &obj1); + } else { + return NULL; + } + pattern = NULL; + if (obj1.isInt() && obj1.getInt() == 1) { + pattern = GfxTilingPattern::parse(obj); + } else if (obj1.isInt() && obj1.getInt() == 2) { + pattern = GfxShadingPattern::parse(obj); + } + obj1.free(); + return pattern; +} + +//------------------------------------------------------------------------ +// GfxTilingPattern +//------------------------------------------------------------------------ + +GfxTilingPattern *GfxTilingPattern::parse(Object *patObj) { + GfxTilingPattern *pat; + Dict *dict; + int paintTypeA, tilingTypeA; + double bboxA[4], matrixA[6]; + double xStepA, yStepA; + Object resDictA; + Object obj1, obj2; + int i; + + if (!patObj->isStream()) { + return NULL; + } + dict = patObj->streamGetDict(); + + if (dict->lookup("PaintType", &obj1)->isInt()) { + paintTypeA = obj1.getInt(); + } else { + paintTypeA = 1; + error(-1, "Invalid or missing PaintType in pattern"); + } + obj1.free(); + if (dict->lookup("TilingType", &obj1)->isInt()) { + tilingTypeA = obj1.getInt(); + } else { + tilingTypeA = 1; + error(-1, "Invalid or missing TilingType in pattern"); + } + obj1.free(); + bboxA[0] = bboxA[1] = 0; + bboxA[2] = bboxA[3] = 1; + if (dict->lookup("BBox", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + for (i = 0; i < 4; ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + bboxA[i] = obj2.getNum(); + } + obj2.free(); + } + } else { + error(-1, "Invalid or missing BBox in pattern"); + } + obj1.free(); + if (dict->lookup("XStep", &obj1)->isNum()) { + xStepA = obj1.getNum(); + } else { + xStepA = 1; + error(-1, "Invalid or missing XStep in pattern"); + } + obj1.free(); + if (dict->lookup("YStep", &obj1)->isNum()) { + yStepA = obj1.getNum(); + } else { + yStepA = 1; + error(-1, "Invalid or missing YStep in pattern"); + } + obj1.free(); + if (!dict->lookup("Resources", &resDictA)->isDict()) { + resDictA.free(); + resDictA.initNull(); + error(-1, "Invalid or missing Resources in pattern"); + } + matrixA[0] = 1; matrixA[1] = 0; + matrixA[2] = 0; matrixA[3] = 1; + matrixA[4] = 0; matrixA[5] = 0; + if (dict->lookup("Matrix", &obj1)->isArray() && + obj1.arrayGetLength() == 6) { + for (i = 0; i < 6; ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + matrixA[i] = obj2.getNum(); + } + obj2.free(); + } + } + obj1.free(); + + pat = new GfxTilingPattern(paintTypeA, tilingTypeA, bboxA, xStepA, yStepA, + &resDictA, matrixA, patObj); + resDictA.free(); + return pat; +} + +GfxTilingPattern::GfxTilingPattern(int paintTypeA, int tilingTypeA, + double *bboxA, double xStepA, double yStepA, + Object *resDictA, double *matrixA, + Object *contentStreamA): + GfxPattern(1) +{ + int i; + + paintType = paintTypeA; + tilingType = tilingTypeA; + for (i = 0; i < 4; ++i) { + bbox[i] = bboxA[i]; + } + xStep = xStepA; + yStep = yStepA; + resDictA->copy(&resDict); + for (i = 0; i < 6; ++i) { + matrix[i] = matrixA[i]; + } + contentStreamA->copy(&contentStream); +} + +GfxTilingPattern::~GfxTilingPattern() { + resDict.free(); + contentStream.free(); +} + +GfxPattern *GfxTilingPattern::copy() { + return new GfxTilingPattern(paintType, tilingType, bbox, xStep, yStep, + &resDict, matrix, &contentStream); +} + +//------------------------------------------------------------------------ +// GfxShadingPattern +//------------------------------------------------------------------------ + +GfxShadingPattern *GfxShadingPattern::parse(Object *patObj) { + Dict *dict; + GfxShading *shadingA; + double matrixA[6]; + Object obj1, obj2; + int i; + + if (!patObj->isDict()) { + return NULL; + } + dict = patObj->getDict(); + + dict->lookup("Shading", &obj1); + shadingA = GfxShading::parse(&obj1); + obj1.free(); + if (!shadingA) { + return NULL; + } + + matrixA[0] = 1; matrixA[1] = 0; + matrixA[2] = 0; matrixA[3] = 1; + matrixA[4] = 0; matrixA[5] = 0; + if (dict->lookup("Matrix", &obj1)->isArray() && + obj1.arrayGetLength() == 6) { + for (i = 0; i < 6; ++i) { + if (obj1.arrayGet(i, &obj2)->isNum()) { + matrixA[i] = obj2.getNum(); + } + obj2.free(); + } + } + obj1.free(); + + return new GfxShadingPattern(shadingA, matrixA); +} + +GfxShadingPattern::GfxShadingPattern(GfxShading *shadingA, double *matrixA): + GfxPattern(2) +{ + int i; + + shading = shadingA; + for (i = 0; i < 6; ++i) { + matrix[i] = matrixA[i]; + } +} + +GfxShadingPattern::~GfxShadingPattern() { + delete shading; +} + +GfxPattern *GfxShadingPattern::copy() { + return new GfxShadingPattern(shading->copy(), matrix); +} + +//------------------------------------------------------------------------ +// GfxShading +//------------------------------------------------------------------------ + +GfxShading::GfxShading(int typeA) { + type = typeA; + colorSpace = NULL; +} + +GfxShading::GfxShading(GfxShading *shading) { + int i; + + type = shading->type; + colorSpace = shading->colorSpace->copy(); + for (i = 0; i < gfxColorMaxComps; ++i) { + background.c[i] = shading->background.c[i]; + } + hasBackground = shading->hasBackground; + xMin = shading->xMin; + yMin = shading->yMin; + xMax = shading->xMax; + yMax = shading->yMax; + hasBBox = shading->hasBBox; +} + +GfxShading::~GfxShading() { + if (colorSpace) { + delete colorSpace; + } +} + +GfxShading *GfxShading::parse(Object *obj) { + GfxShading *shading; + Dict *dict; + int typeA; + Object obj1; + + if (obj->isDict()) { + dict = obj->getDict(); + } else if (obj->isStream()) { + dict = obj->streamGetDict(); + } else { + return NULL; + } + + if (!dict->lookup("ShadingType", &obj1)->isInt()) { + error(-1, "Invalid ShadingType in shading dictionary"); + obj1.free(); + return NULL; + } + typeA = obj1.getInt(); + obj1.free(); + + switch (typeA) { + case 1: + shading = GfxFunctionShading::parse(dict); + break; + case 2: + shading = GfxAxialShading::parse(dict); + break; + case 3: + shading = GfxRadialShading::parse(dict); + break; + case 4: + if (obj->isStream()) { + shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream()); + } else { + error(-1, "Invalid Type 4 shading object"); + goto err1; + } + break; + case 5: + if (obj->isStream()) { + shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream()); + } else { + error(-1, "Invalid Type 5 shading object"); + goto err1; + } + break; + case 6: + if (obj->isStream()) { + shading = GfxPatchMeshShading::parse(6, dict, obj->getStream()); + } else { + error(-1, "Invalid Type 6 shading object"); + goto err1; + } + break; + case 7: + if (obj->isStream()) { + shading = GfxPatchMeshShading::parse(7, dict, obj->getStream()); + } else { + error(-1, "Invalid Type 7 shading object"); + goto err1; + } + break; + default: + error(-1, "Unimplemented shading type %d", typeA); + goto err1; + } + + return shading; + + err1: + return NULL; +} + +GBool GfxShading::init(Dict *dict) { + Object obj1, obj2; + int i; + + dict->lookup("ColorSpace", &obj1); + if (!(colorSpace = GfxColorSpace::parse(&obj1))) { + error(-1, "Bad color space in shading dictionary"); + obj1.free(); + return gFalse; + } + obj1.free(); + + for (i = 0; i < gfxColorMaxComps; ++i) { + background.c[i] = 0; + } + hasBackground = gFalse; + if (dict->lookup("Background", &obj1)->isArray()) { + if (obj1.arrayGetLength() == colorSpace->getNComps()) { + hasBackground = gTrue; + for (i = 0; i < colorSpace->getNComps(); ++i) { + background.c[i] = dblToCol(obj1.arrayGet(i, &obj2)->getNum()); + obj2.free(); + } + } else { + error(-1, "Bad Background in shading dictionary"); + } + } + obj1.free(); + + xMin = yMin = xMax = yMax = 0; + hasBBox = gFalse; + if (dict->lookup("BBox", &obj1)->isArray()) { + if (obj1.arrayGetLength() == 4) { + hasBBox = gTrue; + xMin = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + yMin = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + xMax = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + yMax = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + } else { + error(-1, "Bad BBox in shading dictionary"); + } + } + obj1.free(); + + return gTrue; +} + +//------------------------------------------------------------------------ +// GfxFunctionShading +//------------------------------------------------------------------------ + +GfxFunctionShading::GfxFunctionShading(double x0A, double y0A, + double x1A, double y1A, + double *matrixA, + Function **funcsA, int nFuncsA): + GfxShading(1) +{ + int i; + + x0 = x0A; + y0 = y0A; + x1 = x1A; + y1 = y1A; + for (i = 0; i < 6; ++i) { + matrix[i] = matrixA[i]; + } + nFuncs = nFuncsA; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = funcsA[i]; + } +} + +GfxFunctionShading::GfxFunctionShading(GfxFunctionShading *shading): + GfxShading(shading) +{ + int i; + + x0 = shading->x0; + y0 = shading->y0; + x1 = shading->x1; + y1 = shading->y1; + for (i = 0; i < 6; ++i) { + matrix[i] = shading->matrix[i]; + } + nFuncs = shading->nFuncs; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = shading->funcs[i]->copy(); + } +} + +GfxFunctionShading::~GfxFunctionShading() { + int i; + + for (i = 0; i < nFuncs; ++i) { + delete funcs[i]; + } +} + +GfxFunctionShading *GfxFunctionShading::parse(Dict *dict) { + GfxFunctionShading *shading; + double x0A, y0A, x1A, y1A; + double matrixA[6]; + Function *funcsA[gfxColorMaxComps]; + int nFuncsA; + Object obj1, obj2; + int i; + + x0A = y0A = 0; + x1A = y1A = 1; + if (dict->lookup("Domain", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + x0A = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + y0A = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + x1A = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + y1A = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + } + obj1.free(); + + matrixA[0] = 1; matrixA[1] = 0; + matrixA[2] = 0; matrixA[3] = 1; + matrixA[4] = 0; matrixA[5] = 0; + if (dict->lookup("Matrix", &obj1)->isArray() && + obj1.arrayGetLength() == 6) { + matrixA[0] = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + matrixA[1] = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + matrixA[2] = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + matrixA[3] = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + matrixA[4] = obj1.arrayGet(4, &obj2)->getNum(); + obj2.free(); + matrixA[5] = obj1.arrayGet(5, &obj2)->getNum(); + obj2.free(); + } + obj1.free(); + + dict->lookup("Function", &obj1); + if (obj1.isArray()) { + nFuncsA = obj1.arrayGetLength(); + if (nFuncsA > gfxColorMaxComps) { + error(-1, "Invalid Function array in shading dictionary"); + goto err1; + } + for (i = 0; i < nFuncsA; ++i) { + obj1.arrayGet(i, &obj2); + if (!(funcsA[i] = Function::parse(&obj2))) { + goto err2; + } + obj2.free(); + } + } else { + nFuncsA = 1; + if (!(funcsA[0] = Function::parse(&obj1))) { + goto err1; + } + } + obj1.free(); + + shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA, + funcsA, nFuncsA); + if (!shading->init(dict)) { + delete shading; + return NULL; + } + return shading; + + err2: + obj2.free(); + err1: + obj1.free(); + return NULL; +} + +GfxShading *GfxFunctionShading::copy() { + return new GfxFunctionShading(this); +} + +void GfxFunctionShading::getColor(double x, double y, GfxColor *color) { + double in[2], out[gfxColorMaxComps]; + int i; + + // NB: there can be one function with n outputs or n functions with + // one output each (where n = number of color components) + for (i = 0; i < gfxColorMaxComps; ++i) { + out[i] = 0; + } + in[0] = x; + in[1] = y; + for (i = 0; i < nFuncs; ++i) { + funcs[i]->transform(in, &out[i]); + } + for (i = 0; i < gfxColorMaxComps; ++i) { + color->c[i] = dblToCol(out[i]); + } +} + +//------------------------------------------------------------------------ +// GfxAxialShading +//------------------------------------------------------------------------ + +GfxAxialShading::GfxAxialShading(double x0A, double y0A, + double x1A, double y1A, + double t0A, double t1A, + Function **funcsA, int nFuncsA, + GBool extend0A, GBool extend1A): + GfxShading(2) +{ + int i; + + x0 = x0A; + y0 = y0A; + x1 = x1A; + y1 = y1A; + t0 = t0A; + t1 = t1A; + nFuncs = nFuncsA; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = funcsA[i]; + } + extend0 = extend0A; + extend1 = extend1A; +} + +GfxAxialShading::GfxAxialShading(GfxAxialShading *shading): + GfxShading(shading) +{ + int i; + + x0 = shading->x0; + y0 = shading->y0; + x1 = shading->x1; + y1 = shading->y1; + t0 = shading->t0; + y1 = shading->t1; + nFuncs = shading->nFuncs; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = shading->funcs[i]->copy(); + } + extend0 = shading->extend0; + extend1 = shading->extend1; +} + +GfxAxialShading::~GfxAxialShading() { + int i; + + for (i = 0; i < nFuncs; ++i) { + delete funcs[i]; + } +} + +GfxAxialShading *GfxAxialShading::parse(Dict *dict) { + GfxAxialShading *shading; + double x0A, y0A, x1A, y1A; + double t0A, t1A; + Function *funcsA[gfxColorMaxComps]; + int nFuncsA; + GBool extend0A, extend1A; + Object obj1, obj2; + int i; + + x0A = y0A = x1A = y1A = 0; + if (dict->lookup("Coords", &obj1)->isArray() && + obj1.arrayGetLength() == 4) { + x0A = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + y0A = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + x1A = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + y1A = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + } else { + error(-1, "Missing or invalid Coords in shading dictionary"); + goto err1; + } + obj1.free(); + + t0A = 0; + t1A = 1; + if (dict->lookup("Domain", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + t0A = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + t1A = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + } + obj1.free(); + + dict->lookup("Function", &obj1); + if (obj1.isArray()) { + nFuncsA = obj1.arrayGetLength(); + if (nFuncsA > gfxColorMaxComps) { + error(-1, "Invalid Function array in shading dictionary"); + goto err1; + } + for (i = 0; i < nFuncsA; ++i) { + obj1.arrayGet(i, &obj2); + if (!(funcsA[i] = Function::parse(&obj2))) { + obj1.free(); + obj2.free(); + goto err1; + } + obj2.free(); + } + } else { + nFuncsA = 1; + if (!(funcsA[0] = Function::parse(&obj1))) { + obj1.free(); + goto err1; + } + } + obj1.free(); + + extend0A = extend1A = gFalse; + if (dict->lookup("Extend", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + extend0A = obj1.arrayGet(0, &obj2)->getBool(); + obj2.free(); + extend1A = obj1.arrayGet(1, &obj2)->getBool(); + obj2.free(); + } + obj1.free(); + + shading = new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A, + funcsA, nFuncsA, extend0A, extend1A); + if (!shading->init(dict)) { + delete shading; + return NULL; + } + return shading; + + err1: + return NULL; +} + +GfxShading *GfxAxialShading::copy() { + return new GfxAxialShading(this); +} + +void GfxAxialShading::getColor(double t, GfxColor *color) { + double out[gfxColorMaxComps]; + int i; + + // NB: there can be one function with n outputs or n functions with + // one output each (where n = number of color components) + for (i = 0; i < gfxColorMaxComps; ++i) { + out[i] = 0; + } + for (i = 0; i < nFuncs; ++i) { + funcs[i]->transform(&t, &out[i]); + } + for (i = 0; i < gfxColorMaxComps; ++i) { + color->c[i] = dblToCol(out[i]); + } +} + +//------------------------------------------------------------------------ +// GfxRadialShading +//------------------------------------------------------------------------ + +GfxRadialShading::GfxRadialShading(double x0A, double y0A, double r0A, + double x1A, double y1A, double r1A, + double t0A, double t1A, + Function **funcsA, int nFuncsA, + GBool extend0A, GBool extend1A): + GfxShading(3) +{ + int i; + + x0 = x0A; + y0 = y0A; + r0 = r0A; + x1 = x1A; + y1 = y1A; + r1 = r1A; + t0 = t0A; + t1 = t1A; + nFuncs = nFuncsA; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = funcsA[i]; + } + extend0 = extend0A; + extend1 = extend1A; +} + +GfxRadialShading::GfxRadialShading(GfxRadialShading *shading): + GfxShading(shading) +{ + int i; + + x0 = shading->x0; + y0 = shading->y0; + r0 = shading->r0; + x1 = shading->x1; + y1 = shading->y1; + r1 = shading->r1; + t0 = shading->t0; + y1 = shading->t1; + nFuncs = shading->nFuncs; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = shading->funcs[i]->copy(); + } + extend0 = shading->extend0; + extend1 = shading->extend1; +} + +GfxRadialShading::~GfxRadialShading() { + int i; + + for (i = 0; i < nFuncs; ++i) { + delete funcs[i]; + } +} + +GfxRadialShading *GfxRadialShading::parse(Dict *dict) { + GfxRadialShading *shading; + double x0A, y0A, r0A, x1A, y1A, r1A; + double t0A, t1A; + Function *funcsA[gfxColorMaxComps]; + int nFuncsA; + GBool extend0A, extend1A; + Object obj1, obj2; + int i; + + x0A = y0A = r0A = x1A = y1A = r1A = 0; + if (dict->lookup("Coords", &obj1)->isArray() && + obj1.arrayGetLength() == 6) { + x0A = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + y0A = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + r0A = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + x1A = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + y1A = obj1.arrayGet(4, &obj2)->getNum(); + obj2.free(); + r1A = obj1.arrayGet(5, &obj2)->getNum(); + obj2.free(); + } else { + error(-1, "Missing or invalid Coords in shading dictionary"); + goto err1; + } + obj1.free(); + + t0A = 0; + t1A = 1; + if (dict->lookup("Domain", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + t0A = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + t1A = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + } + obj1.free(); + + dict->lookup("Function", &obj1); + if (obj1.isArray()) { + nFuncsA = obj1.arrayGetLength(); + if (nFuncsA > gfxColorMaxComps) { + error(-1, "Invalid Function array in shading dictionary"); + goto err1; + } + for (i = 0; i < nFuncsA; ++i) { + obj1.arrayGet(i, &obj2); + if (!(funcsA[i] = Function::parse(&obj2))) { + obj1.free(); + obj2.free(); + goto err1; + } + obj2.free(); + } + } else { + nFuncsA = 1; + if (!(funcsA[0] = Function::parse(&obj1))) { + obj1.free(); + goto err1; + } + } + obj1.free(); + + extend0A = extend1A = gFalse; + if (dict->lookup("Extend", &obj1)->isArray() && + obj1.arrayGetLength() == 2) { + extend0A = obj1.arrayGet(0, &obj2)->getBool(); + obj2.free(); + extend1A = obj1.arrayGet(1, &obj2)->getBool(); + obj2.free(); + } + obj1.free(); + + shading = new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A, + funcsA, nFuncsA, extend0A, extend1A); + if (!shading->init(dict)) { + delete shading; + return NULL; + } + return shading; + + err1: + return NULL; +} + +GfxShading *GfxRadialShading::copy() { + return new GfxRadialShading(this); +} + +void GfxRadialShading::getColor(double t, GfxColor *color) { + double out[gfxColorMaxComps]; + int i; + + // NB: there can be one function with n outputs or n functions with + // one output each (where n = number of color components) + for (i = 0; i < gfxColorMaxComps; ++i) { + out[i] = 0; + } + for (i = 0; i < nFuncs; ++i) { + funcs[i]->transform(&t, &out[i]); + } + for (i = 0; i < gfxColorMaxComps; ++i) { + color->c[i] = dblToCol(out[i]); + } +} + +//------------------------------------------------------------------------ +// GfxShadingBitBuf +//------------------------------------------------------------------------ + +class GfxShadingBitBuf { +public: + + GfxShadingBitBuf(Stream *strA); + ~GfxShadingBitBuf(); + GBool getBits(int n, Guint *val); + void flushBits(); + +private: + + Stream *str; + int bitBuf; + int nBits; +}; + +GfxShadingBitBuf::GfxShadingBitBuf(Stream *strA) { + str = strA; + str->reset(); + bitBuf = 0; + nBits = 0; +} + +GfxShadingBitBuf::~GfxShadingBitBuf() { + str->close(); +} + +GBool GfxShadingBitBuf::getBits(int n, Guint *val) { + int x; + + if (nBits >= n) { + x = (bitBuf >> (nBits - n)) & ((1 << n) - 1); + nBits -= n; + } else { + x = 0; + if (nBits > 0) { + x = bitBuf & ((1 << nBits) - 1); + n -= nBits; + nBits = 0; + } + while (n > 0) { + if ((bitBuf = str->getChar()) == EOF) { + nBits = 0; + return gFalse; + } + if (n >= 8) { + x = (x << 8) | bitBuf; + n -= 8; + } else { + x = (x << n) | (bitBuf >> (8 - n)); + nBits = 8 - n; + n = 0; + } + } + } + *val = x; + return gTrue; +} + +void GfxShadingBitBuf::flushBits() { + bitBuf = 0; + nBits = 0; +} + +//------------------------------------------------------------------------ +// GfxGouraudTriangleShading +//------------------------------------------------------------------------ + +GfxGouraudTriangleShading::GfxGouraudTriangleShading( + int typeA, + GfxGouraudVertex *verticesA, int nVerticesA, + int (*trianglesA)[3], int nTrianglesA, + Function **funcsA, int nFuncsA): + GfxShading(typeA) +{ + int i; + + vertices = verticesA; + nVertices = nVerticesA; + triangles = trianglesA; + nTriangles = nTrianglesA; + nFuncs = nFuncsA; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = funcsA[i]; + } +} + +GfxGouraudTriangleShading::GfxGouraudTriangleShading( + GfxGouraudTriangleShading *shading): + GfxShading(shading) +{ + int i; + + nVertices = shading->nVertices; + vertices = (GfxGouraudVertex *)gmallocn(nVertices, sizeof(GfxGouraudVertex)); + memcpy(vertices, shading->vertices, nVertices * sizeof(GfxGouraudVertex)); + nTriangles = shading->nTriangles; + triangles = (int (*)[3])gmallocn(nTriangles * 3, sizeof(int)); + memcpy(triangles, shading->triangles, nTriangles * 3 * sizeof(int)); + nFuncs = shading->nFuncs; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = shading->funcs[i]->copy(); + } +} + +GfxGouraudTriangleShading::~GfxGouraudTriangleShading() { + int i; + + gfree(vertices); + gfree(triangles); + for (i = 0; i < nFuncs; ++i) { + delete funcs[i]; + } +} + +GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA, + Dict *dict, + Stream *str) { + GfxGouraudTriangleShading *shading; + Function *funcsA[gfxColorMaxComps]; + int nFuncsA; + int coordBits, compBits, flagBits, vertsPerRow, nRows; + double xMin, xMax, yMin, yMax; + double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps]; + double xMul, yMul; + double cMul[gfxColorMaxComps]; + GfxGouraudVertex *verticesA; + int (*trianglesA)[3]; + int nComps, nVerticesA, nTrianglesA, vertSize, triSize; + Guint x, y, flag; + Guint c[gfxColorMaxComps]; + GfxShadingBitBuf *bitBuf; + Object obj1, obj2; + int i, j, k, state; + + if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) { + coordBits = obj1.getInt(); + } else { + error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary"); + goto err2; + } + obj1.free(); + if (dict->lookup("BitsPerComponent", &obj1)->isInt()) { + compBits = obj1.getInt(); + } else { + error(-1, "Missing or invalid BitsPerComponent in shading dictionary"); + goto err2; + } + obj1.free(); + flagBits = vertsPerRow = 0; // make gcc happy + if (typeA == 4) { + if (dict->lookup("BitsPerFlag", &obj1)->isInt()) { + flagBits = obj1.getInt(); + } else { + error(-1, "Missing or invalid BitsPerFlag in shading dictionary"); + goto err2; + } + obj1.free(); + } else { + if (dict->lookup("VerticesPerRow", &obj1)->isInt()) { + vertsPerRow = obj1.getInt(); + } else { + error(-1, "Missing or invalid VerticesPerRow in shading dictionary"); + goto err2; + } + obj1.free(); + } + if (dict->lookup("Decode", &obj1)->isArray() && + obj1.arrayGetLength() >= 6) { + xMin = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + xMax = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1); + yMin = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + yMax = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1); + for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) { + cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum(); + obj2.free(); + cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum(); + obj2.free(); + cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1); + } + nComps = i; + } else { + error(-1, "Missing or invalid Decode array in shading dictionary"); + goto err2; + } + obj1.free(); + + if (!dict->lookup("Function", &obj1)->isNull()) { + if (obj1.isArray()) { + nFuncsA = obj1.arrayGetLength(); + if (nFuncsA > gfxColorMaxComps) { + error(-1, "Invalid Function array in shading dictionary"); + goto err1; + } + for (i = 0; i < nFuncsA; ++i) { + obj1.arrayGet(i, &obj2); + if (!(funcsA[i] = Function::parse(&obj2))) { + obj1.free(); + obj2.free(); + goto err1; + } + obj2.free(); + } + } else { + nFuncsA = 1; + if (!(funcsA[0] = Function::parse(&obj1))) { + obj1.free(); + goto err1; + } + } + } else { + nFuncsA = 0; + } + obj1.free(); + + nVerticesA = nTrianglesA = 0; + verticesA = NULL; + trianglesA = NULL; + vertSize = triSize = 0; + state = 0; + flag = 0; // make gcc happy + bitBuf = new GfxShadingBitBuf(str); + while (1) { + if (typeA == 4) { + if (!bitBuf->getBits(flagBits, &flag)) { + break; + } + } + if (!bitBuf->getBits(coordBits, &x) || + !bitBuf->getBits(coordBits, &y)) { + break; + } + for (i = 0; i < nComps; ++i) { + if (!bitBuf->getBits(compBits, &c[i])) { + break; + } + } + if (i < nComps) { + break; + } + if (nVerticesA == vertSize) { + vertSize = (vertSize == 0) ? 16 : 2 * vertSize; + verticesA = (GfxGouraudVertex *) + greallocn(verticesA, vertSize, sizeof(GfxGouraudVertex)); + } + verticesA[nVerticesA].x = xMin + xMul * (double)x; + verticesA[nVerticesA].y = yMin + yMul * (double)y; + for (i = 0; i < nComps; ++i) { + verticesA[nVerticesA].color.c[i] = + dblToCol(cMin[i] + cMul[i] * (double)c[i]); + } + ++nVerticesA; + bitBuf->flushBits(); + if (typeA == 4) { + if (state == 0 || state == 1) { + ++state; + } else if (state == 2 || flag > 0) { + if (nTrianglesA == triSize) { + triSize = (triSize == 0) ? 16 : 2 * triSize; + trianglesA = (int (*)[3]) + greallocn(trianglesA, triSize * 3, sizeof(int)); + } + if (state == 2) { + trianglesA[nTrianglesA][0] = nVerticesA - 3; + trianglesA[nTrianglesA][1] = nVerticesA - 2; + trianglesA[nTrianglesA][2] = nVerticesA - 1; + ++state; + } else if (flag == 1) { + trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][1]; + trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2]; + trianglesA[nTrianglesA][2] = nVerticesA - 1; + } else { // flag == 2 + trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][0]; + trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2]; + trianglesA[nTrianglesA][2] = nVerticesA - 1; + } + ++nTrianglesA; + } else { // state == 3 && flag == 0 + state = 1; + } + } + } + delete bitBuf; + if (typeA == 5) { + nRows = nVerticesA / vertsPerRow; + nTrianglesA = (nRows - 1) * 2 * (vertsPerRow - 1); + trianglesA = (int (*)[3])gmallocn(nTrianglesA * 3, sizeof(int)); + k = 0; + for (i = 0; i < nRows - 1; ++i) { + for (j = 0; j < vertsPerRow - 1; ++j) { + trianglesA[k][0] = i * vertsPerRow + j; + trianglesA[k][1] = i * vertsPerRow + j+1; + trianglesA[k][2] = (i+1) * vertsPerRow + j; + ++k; + trianglesA[k][0] = i * vertsPerRow + j+1; + trianglesA[k][1] = (i+1) * vertsPerRow + j; + trianglesA[k][2] = (i+1) * vertsPerRow + j+1; + ++k; + } + } + } + + shading = new GfxGouraudTriangleShading(typeA, verticesA, nVerticesA, + trianglesA, nTrianglesA, + funcsA, nFuncsA); + if (!shading->init(dict)) { + delete shading; + return NULL; + } + return shading; + + err2: + obj1.free(); + err1: + return NULL; +} + +GfxShading *GfxGouraudTriangleShading::copy() { + return new GfxGouraudTriangleShading(this); +} + +void GfxGouraudTriangleShading::getTriangle( + int i, + double *x0, double *y0, GfxColor *color0, + double *x1, double *y1, GfxColor *color1, + double *x2, double *y2, GfxColor *color2) { + double in; + double out[gfxColorMaxComps]; + int v, j; + + v = triangles[i][0]; + *x0 = vertices[v].x; + *y0 = vertices[v].y; + if (nFuncs > 0) { + in = colToDbl(vertices[v].color.c[0]); + for (j = 0; j < nFuncs; ++j) { + funcs[j]->transform(&in, &out[j]); + } + for (j = 0; j < gfxColorMaxComps; ++j) { + color0->c[j] = dblToCol(out[j]); + } + } else { + *color0 = vertices[v].color; + } + v = triangles[i][1]; + *x1 = vertices[v].x; + *y1 = vertices[v].y; + if (nFuncs > 0) { + in = colToDbl(vertices[v].color.c[0]); + for (j = 0; j < nFuncs; ++j) { + funcs[j]->transform(&in, &out[j]); + } + for (j = 0; j < gfxColorMaxComps; ++j) { + color1->c[j] = dblToCol(out[j]); + } + } else { + *color1 = vertices[v].color; + } + v = triangles[i][2]; + *x2 = vertices[v].x; + *y2 = vertices[v].y; + if (nFuncs > 0) { + in = colToDbl(vertices[v].color.c[0]); + for (j = 0; j < nFuncs; ++j) { + funcs[j]->transform(&in, &out[j]); + } + for (j = 0; j < gfxColorMaxComps; ++j) { + color2->c[j] = dblToCol(out[j]); + } + } else { + *color2 = vertices[v].color; + } +} + +//------------------------------------------------------------------------ +// GfxPatchMeshShading +//------------------------------------------------------------------------ + +GfxPatchMeshShading::GfxPatchMeshShading(int typeA, + GfxPatch *patchesA, int nPatchesA, + Function **funcsA, int nFuncsA): + GfxShading(typeA) +{ + int i; + + patches = patchesA; + nPatches = nPatchesA; + nFuncs = nFuncsA; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = funcsA[i]; + } +} + +GfxPatchMeshShading::GfxPatchMeshShading(GfxPatchMeshShading *shading): + GfxShading(shading) +{ + int i; + + nPatches = shading->nPatches; + patches = (GfxPatch *)gmallocn(nPatches, sizeof(GfxPatch)); + memcpy(patches, shading->patches, nPatches * sizeof(GfxPatch)); + nFuncs = shading->nFuncs; + for (i = 0; i < nFuncs; ++i) { + funcs[i] = shading->funcs[i]->copy(); + } +} + +GfxPatchMeshShading::~GfxPatchMeshShading() { + int i; + + gfree(patches); + for (i = 0; i < nFuncs; ++i) { + delete funcs[i]; + } +} + +GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, + Stream *str) { + GfxPatchMeshShading *shading; + Function *funcsA[gfxColorMaxComps]; + int nFuncsA; + int coordBits, compBits, flagBits; + double xMin, xMax, yMin, yMax; + double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps]; + double xMul, yMul; + double cMul[gfxColorMaxComps]; + GfxPatch *patchesA, *p; + int nComps, nPatchesA, patchesSize, nPts, nColors; + Guint flag; + double x[16], y[16]; + Guint xi, yi; + GfxColorComp c[4][gfxColorMaxComps]; + Guint ci[4]; + GfxShadingBitBuf *bitBuf; + Object obj1, obj2; + int i, j; + + if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) { + coordBits = obj1.getInt(); + } else { + error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary"); + goto err2; + } + obj1.free(); + if (dict->lookup("BitsPerComponent", &obj1)->isInt()) { + compBits = obj1.getInt(); + } else { + error(-1, "Missing or invalid BitsPerComponent in shading dictionary"); + goto err2; + } + obj1.free(); + if (dict->lookup("BitsPerFlag", &obj1)->isInt()) { + flagBits = obj1.getInt(); + } else { + error(-1, "Missing or invalid BitsPerFlag in shading dictionary"); + goto err2; + } + obj1.free(); + if (dict->lookup("Decode", &obj1)->isArray() && + obj1.arrayGetLength() >= 6) { + xMin = obj1.arrayGet(0, &obj2)->getNum(); + obj2.free(); + xMax = obj1.arrayGet(1, &obj2)->getNum(); + obj2.free(); + xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1); + yMin = obj1.arrayGet(2, &obj2)->getNum(); + obj2.free(); + yMax = obj1.arrayGet(3, &obj2)->getNum(); + obj2.free(); + yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1); + for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) { + cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum(); + obj2.free(); + cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum(); + obj2.free(); + cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1); + } + nComps = i; + } else { + error(-1, "Missing or invalid Decode array in shading dictionary"); + goto err2; + } + obj1.free(); + + if (!dict->lookup("Function", &obj1)->isNull()) { + if (obj1.isArray()) { + nFuncsA = obj1.arrayGetLength(); + if (nFuncsA > gfxColorMaxComps) { + error(-1, "Invalid Function array in shading dictionary"); + goto err1; + } + for (i = 0; i < nFuncsA; ++i) { + obj1.arrayGet(i, &obj2); + if (!(funcsA[i] = Function::parse(&obj2))) { + obj1.free(); + obj2.free(); + goto err1; + } + obj2.free(); + } + } else { + nFuncsA = 1; + if (!(funcsA[0] = Function::parse(&obj1))) { + obj1.free(); + goto err1; + } + } + } else { + nFuncsA = 0; + } + obj1.free(); + + nPatchesA = 0; + patchesA = NULL; + patchesSize = 0; + bitBuf = new GfxShadingBitBuf(str); + while (1) { + if (!bitBuf->getBits(flagBits, &flag)) { + break; + } + if (typeA == 6) { + switch (flag) { + case 0: nPts = 12; nColors = 4; break; + case 1: + case 2: + case 3: + default: nPts = 8; nColors = 2; break; + } + } else { + switch (flag) { + case 0: nPts = 16; nColors = 4; break; + case 1: + case 2: + case 3: + default: nPts = 12; nColors = 2; break; + } + } + for (i = 0; i < nPts; ++i) { + if (!bitBuf->getBits(coordBits, &xi) || + !bitBuf->getBits(coordBits, &yi)) { + break; + } + x[i] = xMin + xMul * (double)xi; + y[i] = yMin + yMul * (double)yi; + } + if (i < nPts) { + break; + } + for (i = 0; i < nColors; ++i) { + for (j = 0; j < nComps; ++j) { + if (!bitBuf->getBits(compBits, &ci[j])) { + break; + } + c[i][j] = dblToCol(cMin[j] + cMul[j] * (double)ci[j]); + } + if (j < nComps) { + break; + } + } + if (i < nColors) { + break; + } + if (nPatchesA == patchesSize) { + patchesSize = (patchesSize == 0) ? 16 : 2 * patchesSize; + patchesA = (GfxPatch *)greallocn(patchesA, + patchesSize, sizeof(GfxPatch)); + } + p = &patchesA[nPatchesA]; + if (typeA == 6) { + switch (flag) { + case 0: + p->x[0][0] = x[0]; + p->y[0][0] = y[0]; + p->x[0][1] = x[1]; + p->y[0][1] = y[1]; + p->x[0][2] = x[2]; + p->y[0][2] = y[2]; + p->x[0][3] = x[3]; + p->y[0][3] = y[3]; + p->x[1][3] = x[4]; + p->y[1][3] = y[4]; + p->x[2][3] = x[5]; + p->y[2][3] = y[5]; + p->x[3][3] = x[6]; + p->y[3][3] = y[6]; + p->x[3][2] = x[7]; + p->y[3][2] = y[7]; + p->x[3][1] = x[8]; + p->y[3][1] = y[8]; + p->x[3][0] = x[9]; + p->y[3][0] = y[9]; + p->x[2][0] = x[10]; + p->y[2][0] = y[10]; + p->x[1][0] = x[11]; + p->y[1][0] = y[11]; + for (j = 0; j < nComps; ++j) { + p->color[0][0].c[j] = c[0][j]; + p->color[0][1].c[j] = c[1][j]; + p->color[1][1].c[j] = c[2][j]; + p->color[1][0].c[j] = c[3][j]; + } + break; + case 1: + p->x[0][0] = patchesA[nPatchesA-1].x[0][3]; + p->y[0][0] = patchesA[nPatchesA-1].y[0][3]; + p->x[0][1] = patchesA[nPatchesA-1].x[1][3]; + p->y[0][1] = patchesA[nPatchesA-1].y[1][3]; + p->x[0][2] = patchesA[nPatchesA-1].x[2][3]; + p->y[0][2] = patchesA[nPatchesA-1].y[2][3]; + p->x[0][3] = patchesA[nPatchesA-1].x[3][3]; + p->y[0][3] = patchesA[nPatchesA-1].y[3][3]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + for (j = 0; j < nComps; ++j) { + p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j]; + p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; + p->color[1][1].c[j] = c[0][j]; + p->color[1][0].c[j] = c[1][j]; + } + break; + case 2: + p->x[0][0] = patchesA[nPatchesA-1].x[3][3]; + p->y[0][0] = patchesA[nPatchesA-1].y[3][3]; + p->x[0][1] = patchesA[nPatchesA-1].x[3][2]; + p->y[0][1] = patchesA[nPatchesA-1].y[3][2]; + p->x[0][2] = patchesA[nPatchesA-1].x[3][1]; + p->y[0][2] = patchesA[nPatchesA-1].y[3][1]; + p->x[0][3] = patchesA[nPatchesA-1].x[3][0]; + p->y[0][3] = patchesA[nPatchesA-1].y[3][0]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + for (j = 0; j < nComps; ++j) { + p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; + p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; + p->color[1][1].c[j] = c[0][j]; + p->color[1][0].c[j] = c[1][j]; + } + break; + case 3: + p->x[0][0] = patchesA[nPatchesA-1].x[3][0]; + p->y[0][0] = patchesA[nPatchesA-1].y[3][0]; + p->x[0][1] = patchesA[nPatchesA-1].x[2][0]; + p->y[0][1] = patchesA[nPatchesA-1].y[2][0]; + p->x[0][2] = patchesA[nPatchesA-1].x[1][0]; + p->y[0][2] = patchesA[nPatchesA-1].y[1][0]; + p->x[0][3] = patchesA[nPatchesA-1].x[0][0]; + p->y[0][3] = patchesA[nPatchesA-1].y[0][0]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + for (j = 0; j < nComps; ++j) { + p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; + p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j]; + p->color[1][1].c[j] = c[0][j]; + p->color[1][0].c[j] = c[1][j]; + } + break; + } + } else { + switch (flag) { + case 0: + p->x[0][0] = x[0]; + p->y[0][0] = y[0]; + p->x[0][1] = x[1]; + p->y[0][1] = y[1]; + p->x[0][2] = x[2]; + p->y[0][2] = y[2]; + p->x[0][3] = x[3]; + p->y[0][3] = y[3]; + p->x[1][3] = x[4]; + p->y[1][3] = y[4]; + p->x[2][3] = x[5]; + p->y[2][3] = y[5]; + p->x[3][3] = x[6]; + p->y[3][3] = y[6]; + p->x[3][2] = x[7]; + p->y[3][2] = y[7]; + p->x[3][1] = x[8]; + p->y[3][1] = y[8]; + p->x[3][0] = x[9]; + p->y[3][0] = y[9]; + p->x[2][0] = x[10]; + p->y[2][0] = y[10]; + p->x[1][0] = x[11]; + p->y[1][0] = y[11]; + p->x[1][1] = x[12]; + p->y[1][1] = y[12]; + p->x[1][2] = x[13]; + p->y[1][2] = y[13]; + p->x[2][2] = x[14]; + p->y[2][2] = y[14]; + p->x[2][1] = x[15]; + p->y[2][1] = y[15]; + for (j = 0; j < nComps; ++j) { + p->color[0][0].c[j] = c[0][j]; + p->color[0][1].c[j] = c[1][j]; + p->color[1][1].c[j] = c[2][j]; + p->color[1][0].c[j] = c[3][j]; + } + break; + case 1: + p->x[0][0] = patchesA[nPatchesA-1].x[0][3]; + p->y[0][0] = patchesA[nPatchesA-1].y[0][3]; + p->x[0][1] = patchesA[nPatchesA-1].x[1][3]; + p->y[0][1] = patchesA[nPatchesA-1].y[1][3]; + p->x[0][2] = patchesA[nPatchesA-1].x[2][3]; + p->y[0][2] = patchesA[nPatchesA-1].y[2][3]; + p->x[0][3] = patchesA[nPatchesA-1].x[3][3]; + p->y[0][3] = patchesA[nPatchesA-1].y[3][3]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + p->x[1][1] = x[8]; + p->y[1][1] = y[8]; + p->x[1][2] = x[9]; + p->y[1][2] = y[9]; + p->x[2][2] = x[10]; + p->y[2][2] = y[10]; + p->x[2][1] = x[11]; + p->y[2][1] = y[11]; + for (j = 0; j < nComps; ++j) { + p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j]; + p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; + p->color[1][1].c[j] = c[0][j]; + p->color[1][0].c[j] = c[1][j]; + } + break; + case 2: + p->x[0][0] = patchesA[nPatchesA-1].x[3][3]; + p->y[0][0] = patchesA[nPatchesA-1].y[3][3]; + p->x[0][1] = patchesA[nPatchesA-1].x[3][2]; + p->y[0][1] = patchesA[nPatchesA-1].y[3][2]; + p->x[0][2] = patchesA[nPatchesA-1].x[3][1]; + p->y[0][2] = patchesA[nPatchesA-1].y[3][1]; + p->x[0][3] = patchesA[nPatchesA-1].x[3][0]; + p->y[0][3] = patchesA[nPatchesA-1].y[3][0]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + p->x[1][1] = x[8]; + p->y[1][1] = y[8]; + p->x[1][2] = x[9]; + p->y[1][2] = y[9]; + p->x[2][2] = x[10]; + p->y[2][2] = y[10]; + p->x[2][1] = x[11]; + p->y[2][1] = y[11]; + for (j = 0; j < nComps; ++j) { + p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; + p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; + p->color[1][1].c[j] = c[0][j]; + p->color[1][0].c[j] = c[1][j]; + } + break; + case 3: + p->x[0][0] = patchesA[nPatchesA-1].x[3][0]; + p->y[0][0] = patchesA[nPatchesA-1].y[3][0]; + p->x[0][1] = patchesA[nPatchesA-1].x[2][0]; + p->y[0][1] = patchesA[nPatchesA-1].y[2][0]; + p->x[0][2] = patchesA[nPatchesA-1].x[1][0]; + p->y[0][2] = patchesA[nPatchesA-1].y[1][0]; + p->x[0][3] = patchesA[nPatchesA-1].x[0][0]; + p->y[0][3] = patchesA[nPatchesA-1].y[0][0]; + p->x[1][3] = x[0]; + p->y[1][3] = y[0]; + p->x[2][3] = x[1]; + p->y[2][3] = y[1]; + p->x[3][3] = x[2]; + p->y[3][3] = y[2]; + p->x[3][2] = x[3]; + p->y[3][2] = y[3]; + p->x[3][1] = x[4]; + p->y[3][1] = y[4]; + p->x[3][0] = x[5]; + p->y[3][0] = y[5]; + p->x[2][0] = x[6]; + p->y[2][0] = y[6]; + p->x[1][0] = x[7]; + p->y[1][0] = y[7]; + p->x[1][1] = x[8]; + p->y[1][1] = y[8]; + p->x[1][2] = x[9]; + p->y[1][2] = y[9]; + p->x[2][2] = x[10]; + p->y[2][2] = y[10]; + p->x[2][1] = x[11]; + p->y[2][1] = y[11]; + for (j = 0; j < nComps; ++j) { + p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; + p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j]; + p->color[1][1].c[j] = c[0][j]; + p->color[1][0].c[j] = c[1][j]; + } + break; + } + } + ++nPatchesA; + bitBuf->flushBits(); + } + delete bitBuf; + + if (typeA == 6) { + for (i = 0; i < nPatchesA; ++i) { + p = &patchesA[i]; + p->x[1][1] = (-4 * p->x[0][0] + +6 * (p->x[0][1] + p->x[1][0]) + -2 * (p->x[0][3] + p->x[3][0]) + +3 * (p->x[3][1] + p->x[1][3]) + - p->x[3][3]) / 9; + p->y[1][1] = (-4 * p->y[0][0] + +6 * (p->y[0][1] + p->y[1][0]) + -2 * (p->y[0][3] + p->y[3][0]) + +3 * (p->y[3][1] + p->y[1][3]) + - p->y[3][3]) / 9; + p->x[1][2] = (-4 * p->x[0][3] + +6 * (p->x[0][2] + p->x[1][3]) + -2 * (p->x[0][0] + p->x[3][3]) + +3 * (p->x[3][2] + p->x[1][0]) + - p->x[3][0]) / 9; + p->y[1][2] = (-4 * p->y[0][3] + +6 * (p->y[0][2] + p->y[1][3]) + -2 * (p->y[0][0] + p->y[3][3]) + +3 * (p->y[3][2] + p->y[1][0]) + - p->y[3][0]) / 9; + p->x[2][1] = (-4 * p->x[3][0] + +6 * (p->x[3][1] + p->x[2][0]) + -2 * (p->x[3][3] + p->x[0][0]) + +3 * (p->x[0][1] + p->x[2][3]) + - p->x[0][3]) / 9; + p->y[2][1] = (-4 * p->y[3][0] + +6 * (p->y[3][1] + p->y[2][0]) + -2 * (p->y[3][3] + p->y[0][0]) + +3 * (p->y[0][1] + p->y[2][3]) + - p->y[0][3]) / 9; + p->x[2][2] = (-4 * p->x[3][3] + +6 * (p->x[3][2] + p->x[2][3]) + -2 * (p->x[3][0] + p->x[0][3]) + +3 * (p->x[0][2] + p->x[2][0]) + - p->x[0][0]) / 9; + p->y[2][2] = (-4 * p->y[3][3] + +6 * (p->y[3][2] + p->y[2][3]) + -2 * (p->y[3][0] + p->y[0][3]) + +3 * (p->y[0][2] + p->y[2][0]) + - p->y[0][0]) / 9; + } + } + + shading = new GfxPatchMeshShading(typeA, patchesA, nPatchesA, + funcsA, nFuncsA); + if (!shading->init(dict)) { + delete shading; + return NULL; + } + return shading; + + err2: + obj1.free(); + err1: + return NULL; +} + +GfxShading *GfxPatchMeshShading::copy() { + return new GfxPatchMeshShading(this); +} + +//------------------------------------------------------------------------ +// GfxImageColorMap +//------------------------------------------------------------------------ + +GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, + GfxColorSpace *colorSpaceA) { + GfxIndexedColorSpace *indexedCS; + GfxSeparationColorSpace *sepCS; + int maxPixel, indexHigh; + int maxPixelForAlloc; + Guchar *lookup2; + Function *sepFunc; + Object obj; + double x[gfxColorMaxComps]; + double y[gfxColorMaxComps]; + int i, j, k; + + ok = gTrue; + + // bits per component and color space + bits = bitsA; + maxPixel = (1 << bits) - 1; + maxPixelForAlloc = (1 << (bits>8?bits:8)); + colorSpace = colorSpaceA; + + // initialize + for (k = 0; k < gfxColorMaxComps; ++k) { + lookup[k] = NULL; + } + + // get decode map + if (decode->isNull()) { + nComps = colorSpace->getNComps(); + colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel); + } else if (decode->isArray()) { + nComps = decode->arrayGetLength() / 2; + if (nComps != colorSpace->getNComps()) { + goto err1; + } + for (i = 0; i < nComps; ++i) { + decode->arrayGet(2*i, &obj); + if (!obj.isNum()) { + goto err2; + } + decodeLow[i] = obj.getNum(); + obj.free(); + decode->arrayGet(2*i+1, &obj); + if (!obj.isNum()) { + goto err2; + } + decodeRange[i] = obj.getNum() - decodeLow[i]; + obj.free(); + } + } else { + goto err1; + } + + // Construct a lookup table -- this stores pre-computed decoded + // values for each component, i.e., the result of applying the + // decode mapping to each possible image pixel component value. + // + // Optimization: for Indexed and Separation color spaces (which have + // only one component), we store color values in the lookup table + // rather than component values. + colorSpace2 = NULL; + nComps2 = 0; + if (colorSpace->getMode() == csIndexed) { + // Note that indexHigh may not be the same as maxPixel -- + // Distiller will remove unused palette entries, resulting in + // indexHigh < maxPixel. + indexedCS = (GfxIndexedColorSpace *)colorSpace; + colorSpace2 = indexedCS->getBase(); + indexHigh = indexedCS->getIndexHigh(); + nComps2 = colorSpace2->getNComps(); + lookup2 = indexedCS->getLookup(); + colorSpace2->getDefaultRanges(x, y, indexHigh); + for (k = 0; k < nComps2; ++k) { + lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1, + sizeof(GfxColorComp)); + for (i = 0; i <= maxPixel; ++i) { + j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5); + if (j < 0) { + j = 0; + } else if (j > indexHigh) { + j = indexHigh; + } + lookup[k][i] = + dblToCol(x[k] + (lookup2[j*nComps2 + k] / 255.0) * y[k]); + } + } + } else if (colorSpace->getMode() == csSeparation) { + sepCS = (GfxSeparationColorSpace *)colorSpace; + colorSpace2 = sepCS->getAlt(); + nComps2 = colorSpace2->getNComps(); + sepFunc = sepCS->getFunc(); + for (k = 0; k < nComps2; ++k) { + lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1, + sizeof(GfxColorComp)); + for (i = 0; i <= maxPixel; ++i) { + x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel; + sepFunc->transform(x, y); + lookup[k][i] = dblToCol(y[k]); + } + } + } else { + for (k = 0; k < nComps; ++k) { + lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1, + sizeof(GfxColorComp)); + for (i = 0; i <= maxPixel; ++i) { + lookup[k][i] = dblToCol(decodeLow[k] + + (i * decodeRange[k]) / maxPixel); + } + } + } + + return; + + err2: + obj.free(); + err1: + ok = gFalse; +} + +GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) { + int n, i, k; + + colorSpace = colorMap->colorSpace->copy(); + bits = colorMap->bits; + nComps = colorMap->nComps; + nComps2 = colorMap->nComps2; + colorSpace2 = NULL; + for (k = 0; k < gfxColorMaxComps; ++k) { + lookup[k] = NULL; + } + n = 1 << bits; + if (colorSpace->getMode() == csIndexed) { + colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase(); + for (k = 0; k < nComps2; ++k) { + lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); + memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); + } + } else if (colorSpace->getMode() == csSeparation) { + colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt(); + for (k = 0; k < nComps2; ++k) { + lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); + memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); + } + } else { + for (k = 0; k < nComps; ++k) { + lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); + memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); + } + } + for (i = 0; i < nComps; ++i) { + decodeLow[i] = colorMap->decodeLow[i]; + decodeRange[i] = colorMap->decodeRange[i]; + } + ok = gTrue; +} + +GfxImageColorMap::~GfxImageColorMap() { + int i; + + delete colorSpace; + for (i = 0; i < gfxColorMaxComps; ++i) { + gfree(lookup[i]); + } +} + +void GfxImageColorMap::getGray(Guchar *x, GfxGray *gray) { + GfxColor color; + int i; + + if (colorSpace2) { + for (i = 0; i < nComps2; ++i) { + color.c[i] = lookup[i][x[0]]; + } + colorSpace2->getGray(&color, gray); + } else { + for (i = 0; i < nComps; ++i) { + color.c[i] = lookup[i][x[i]]; + } + colorSpace->getGray(&color, gray); + } +} + +void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) { + GfxColor color; + int i; + + if (colorSpace2) { + for (i = 0; i < nComps2; ++i) { + color.c[i] = lookup[i][x[0]]; + } + colorSpace2->getRGB(&color, rgb); + } else { + for (i = 0; i < nComps; ++i) { + color.c[i] = lookup[i][x[i]]; + } + colorSpace->getRGB(&color, rgb); + } +} + +void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) { + GfxColor color; + int i; + + if (colorSpace2) { + for (i = 0; i < nComps2; ++i) { + color.c[i] = lookup[i][x[0]]; + } + colorSpace2->getCMYK(&color, cmyk); + } else { + for (i = 0; i < nComps; ++i) { + color.c[i] = lookup[i][x[i]]; + } + colorSpace->getCMYK(&color, cmyk); + } +} + +void GfxImageColorMap::getColor(Guchar *x, GfxColor *color) { + int maxPixel, i; + + maxPixel = (1 << bits) - 1; + for (i = 0; i < nComps; ++i) { + color->c[i] = dblToCol(decodeLow[i] + (x[i] * decodeRange[i]) / maxPixel); + } +} + +//------------------------------------------------------------------------ +// GfxSubpath and GfxPath +//------------------------------------------------------------------------ + +GfxSubpath::GfxSubpath(double x1, double y1) { + size = 16; + x = (double *)gmallocn(size, sizeof(double)); + y = (double *)gmallocn(size, sizeof(double)); + curve = (GBool *)gmallocn(size, sizeof(GBool)); + n = 1; + x[0] = x1; + y[0] = y1; + curve[0] = gFalse; + closed = gFalse; +} + +GfxSubpath::~GfxSubpath() { + gfree(x); + gfree(y); + gfree(curve); +} + +// Used for copy(). +GfxSubpath::GfxSubpath(GfxSubpath *subpath) { + size = subpath->size; + n = subpath->n; + x = (double *)gmallocn(size, sizeof(double)); + y = (double *)gmallocn(size, sizeof(double)); + curve = (GBool *)gmallocn(size, sizeof(GBool)); + memcpy(x, subpath->x, n * sizeof(double)); + memcpy(y, subpath->y, n * sizeof(double)); + memcpy(curve, subpath->curve, n * sizeof(GBool)); + closed = subpath->closed; +} + +void GfxSubpath::lineTo(double x1, double y1) { + if (n >= size) { + size += 16; + x = (double *)greallocn(x, size, sizeof(double)); + y = (double *)greallocn(y, size, sizeof(double)); + curve = (GBool *)greallocn(curve, size, sizeof(GBool)); + } + x[n] = x1; + y[n] = y1; + curve[n] = gFalse; + ++n; +} + +void GfxSubpath::curveTo(double x1, double y1, double x2, double y2, + double x3, double y3) { + if (n+3 > size) { + size += 16; + x = (double *)greallocn(x, size, sizeof(double)); + y = (double *)greallocn(y, size, sizeof(double)); + curve = (GBool *)greallocn(curve, size, sizeof(GBool)); + } + x[n] = x1; + y[n] = y1; + x[n+1] = x2; + y[n+1] = y2; + x[n+2] = x3; + y[n+2] = y3; + curve[n] = curve[n+1] = gTrue; + curve[n+2] = gFalse; + n += 3; +} + +void GfxSubpath::close() { + if (x[n-1] != x[0] || y[n-1] != y[0]) { + lineTo(x[0], y[0]); + } + closed = gTrue; +} + +void GfxSubpath::offset(double dx, double dy) { + int i; + + for (i = 0; i < n; ++i) { + x[i] += dx; + y[i] += dy; + } +} + +GfxPath::GfxPath() { + justMoved = gFalse; + size = 16; + n = 0; + firstX = firstY = 0; + subpaths = (GfxSubpath **)gmallocn(size, sizeof(GfxSubpath *)); +} + +GfxPath::~GfxPath() { + int i; + + for (i = 0; i < n; ++i) + delete subpaths[i]; + gfree(subpaths); +} + +// Used for copy(). +GfxPath::GfxPath(GBool justMoved1, double firstX1, double firstY1, + GfxSubpath **subpaths1, int n1, int size1) { + int i; + + justMoved = justMoved1; + firstX = firstX1; + firstY = firstY1; + size = size1; + n = n1; + subpaths = (GfxSubpath **)gmallocn(size, sizeof(GfxSubpath *)); + for (i = 0; i < n; ++i) + subpaths[i] = subpaths1[i]->copy(); +} + +void GfxPath::moveTo(double x, double y) { + justMoved = gTrue; + firstX = x; + firstY = y; +} + +void GfxPath::lineTo(double x, double y) { + if (justMoved) { + if (n >= size) { + size += 16; + subpaths = (GfxSubpath **) + greallocn(subpaths, size, sizeof(GfxSubpath *)); + } + subpaths[n] = new GfxSubpath(firstX, firstY); + ++n; + justMoved = gFalse; + } + subpaths[n-1]->lineTo(x, y); +} + +void GfxPath::curveTo(double x1, double y1, double x2, double y2, + double x3, double y3) { + if (justMoved) { + if (n >= size) { + size += 16; + subpaths = (GfxSubpath **) + greallocn(subpaths, size, sizeof(GfxSubpath *)); + } + subpaths[n] = new GfxSubpath(firstX, firstY); + ++n; + justMoved = gFalse; + } + subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3); +} + +void GfxPath::close() { + // this is necessary to handle the pathological case of + // moveto/closepath/clip, which defines an empty clipping region + if (justMoved) { + if (n >= size) { + size += 16; + subpaths = (GfxSubpath **) + greallocn(subpaths, size, sizeof(GfxSubpath *)); + } + subpaths[n] = new GfxSubpath(firstX, firstY); + ++n; + justMoved = gFalse; + } + subpaths[n-1]->close(); +} + +void GfxPath::append(GfxPath *path) { + int i; + + if (n + path->n > size) { + size = n + path->n; + subpaths = (GfxSubpath **) + greallocn(subpaths, size, sizeof(GfxSubpath *)); + } + for (i = 0; i < path->n; ++i) { + subpaths[n++] = path->subpaths[i]->copy(); + } + justMoved = gFalse; +} + +void GfxPath::offset(double dx, double dy) { + int i; + + for (i = 0; i < n; ++i) { + subpaths[i]->offset(dx, dy); + } +} + +//------------------------------------------------------------------------ +// GfxState +//------------------------------------------------------------------------ + +GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, + int rotateA, GBool upsideDown) { + double kx, ky; + + hDPI = hDPIA; + vDPI = vDPIA; + rotate = rotateA; + px1 = pageBox->x1; + py1 = pageBox->y1; + px2 = pageBox->x2; + py2 = pageBox->y2; + kx = hDPI / 72.0; + ky = vDPI / 72.0; + if (rotate == 90) { + ctm[0] = 0; + ctm[1] = upsideDown ? ky : -ky; + ctm[2] = kx; + ctm[3] = 0; + ctm[4] = -kx * py1; + ctm[5] = ky * (upsideDown ? -px1 : px2); + pageWidth = kx * (py2 - py1); + pageHeight = ky * (px2 - px1); + } else if (rotate == 180) { + ctm[0] = -kx; + ctm[1] = 0; + ctm[2] = 0; + ctm[3] = upsideDown ? ky : -ky; + ctm[4] = kx * px2; + ctm[5] = ky * (upsideDown ? -py1 : py2); + pageWidth = kx * (px2 - px1); + pageHeight = ky * (py2 - py1); + } else if (rotate == 270) { + ctm[0] = 0; + ctm[1] = upsideDown ? -ky : ky; + ctm[2] = -kx; + ctm[3] = 0; + ctm[4] = kx * py2; + ctm[5] = ky * (upsideDown ? px2 : -px1); + pageWidth = kx * (py2 - py1); + pageHeight = ky * (px2 - px1); + } else { + ctm[0] = kx; + ctm[1] = 0; + ctm[2] = 0; + ctm[3] = upsideDown ? -ky : ky; + ctm[4] = -kx * px1; + ctm[5] = ky * (upsideDown ? py2 : -py1); + pageWidth = kx * (px2 - px1); + pageHeight = ky * (py2 - py1); + } + + fillColorSpace = new GfxDeviceGrayColorSpace(); + strokeColorSpace = new GfxDeviceGrayColorSpace(); + fillColor.c[0] = 0; + strokeColor.c[0] = 0; + fillPattern = NULL; + strokePattern = NULL; + blendMode = gfxBlendNormal; + fillOpacity = 1; + strokeOpacity = 1; + fillOverprint = gFalse; + strokeOverprint = gFalse; + transfer[0] = transfer[1] = transfer[2] = transfer[3] = NULL; + + lineWidth = 1; + lineDash = NULL; + lineDashLength = 0; + lineDashStart = 0; + flatness = 1; + lineJoin = 0; + lineCap = 0; + miterLimit = 10; + strokeAdjust = gFalse; + + font = NULL; + fontSize = 0; + textMat[0] = 1; textMat[1] = 0; + textMat[2] = 0; textMat[3] = 1; + textMat[4] = 0; textMat[5] = 0; + charSpace = 0; + wordSpace = 0; + horizScaling = 1; + leading = 0; + rise = 0; + render = 0; + + path = new GfxPath(); + curX = curY = 0; + lineX = lineY = 0; + + clipXMin = 0; + clipYMin = 0; + clipXMax = pageWidth; + clipYMax = pageHeight; + + saved = NULL; +} + +GfxState::~GfxState() { + int i; + + if (fillColorSpace) { + delete fillColorSpace; + } + if (strokeColorSpace) { + delete strokeColorSpace; + } + if (fillPattern) { + delete fillPattern; + } + if (strokePattern) { + delete strokePattern; + } + for (i = 0; i < 4; ++i) { + if (transfer[i]) { + delete transfer[i]; + } + } + gfree(lineDash); + if (path) { + // this gets set to NULL by restore() + delete path; + } + if (saved) { + delete saved; + } +} + +// Used for copy(); +GfxState::GfxState(GfxState *state) { + int i; + + memcpy(this, state, sizeof(GfxState)); + if (fillColorSpace) { + fillColorSpace = state->fillColorSpace->copy(); + } + if (strokeColorSpace) { + strokeColorSpace = state->strokeColorSpace->copy(); + } + if (fillPattern) { + fillPattern = state->fillPattern->copy(); + } + if (strokePattern) { + strokePattern = state->strokePattern->copy(); + } + for (i = 0; i < 4; ++i) { + if (transfer[i]) { + transfer[i] = state->transfer[i]->copy(); + } + } + if (lineDashLength > 0) { + lineDash = (double *)gmallocn(lineDashLength, sizeof(double)); + memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double)); + } + saved = NULL; +} + +void GfxState::setPath(GfxPath *pathA) { + if(pathA) { + if(path) + delete path; + } + path = pathA; +} + +void GfxState::getUserClipBBox(double *xMin, double *yMin, + double *xMax, double *yMax) { + double ictm[6]; + double xMin1, yMin1, xMax1, yMax1, det, tx, ty; + + // invert the CTM + det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); + ictm[0] = ctm[3] * det; + ictm[1] = -ctm[1] * det; + ictm[2] = -ctm[2] * det; + ictm[3] = ctm[0] * det; + ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det; + ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det; + + // transform all four corners of the clip bbox; find the min and max + // x and y values + xMin1 = xMax1 = clipXMin * ictm[0] + clipYMin * ictm[2] + ictm[4]; + yMin1 = yMax1 = clipXMin * ictm[1] + clipYMin * ictm[3] + ictm[5]; + tx = clipXMin * ictm[0] + clipYMax * ictm[2] + ictm[4]; + ty = clipXMin * ictm[1] + clipYMax * ictm[3] + ictm[5]; + if (tx < xMin1) { + xMin1 = tx; + } else if (tx > xMax1) { + xMax1 = tx; + } + if (ty < yMin1) { + yMin1 = ty; + } else if (ty > yMax1) { + yMax1 = ty; + } + tx = clipXMax * ictm[0] + clipYMin * ictm[2] + ictm[4]; + ty = clipXMax * ictm[1] + clipYMin * ictm[3] + ictm[5]; + if (tx < xMin1) { + xMin1 = tx; + } else if (tx > xMax1) { + xMax1 = tx; + } + if (ty < yMin1) { + yMin1 = ty; + } else if (ty > yMax1) { + yMax1 = ty; + } + tx = clipXMax * ictm[0] + clipYMax * ictm[2] + ictm[4]; + ty = clipXMax * ictm[1] + clipYMax * ictm[3] + ictm[5]; + if (tx < xMin1) { + xMin1 = tx; + } else if (tx > xMax1) { + xMax1 = tx; + } + if (ty < yMin1) { + yMin1 = ty; + } else if (ty > yMax1) { + yMax1 = ty; + } + + *xMin = xMin1; + *yMin = yMin1; + *xMax = xMax1; + *yMax = yMax1; +} + +double GfxState::transformWidth(double w) { + double x, y; + + x = ctm[0] + ctm[2]; + y = ctm[1] + ctm[3]; + return w * sqrt(0.5 * (x * x + y * y)); +} + +double GfxState::getTransformedFontSize() { + double x1, y1, x2, y2; + + x1 = textMat[2] * fontSize; + y1 = textMat[3] * fontSize; + x2 = ctm[0] * x1 + ctm[2] * y1; + y2 = ctm[1] * x1 + ctm[3] * y1; + return sqrt(x2 * x2 + y2 * y2); +} + +void GfxState::getFontTransMat(double *m11, double *m12, + double *m21, double *m22) { + *m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize; + *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize; + *m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize; + *m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize; +} + +void GfxState::setCTM(double a, double b, double c, + double d, double e, double f) { + int i; + + ctm[0] = a; + ctm[1] = b; + ctm[2] = c; + ctm[3] = d; + ctm[4] = e; + ctm[5] = f; + + // avoid FP exceptions on badly messed up PDF files + for (i = 0; i < 6; ++i) { + if (ctm[i] > 1e10) { + ctm[i] = 1e10; + } else if (ctm[i] < -1e10) { + ctm[i] = -1e10; + } + } +} + +void GfxState::concatCTM(double a, double b, double c, + double d, double e, double f) { + double a1 = ctm[0]; + double b1 = ctm[1]; + double c1 = ctm[2]; + double d1 = ctm[3]; + int i; + + ctm[0] = a * a1 + b * c1; + ctm[1] = a * b1 + b * d1; + ctm[2] = c * a1 + d * c1; + ctm[3] = c * b1 + d * d1; + ctm[4] = e * a1 + f * c1 + ctm[4]; + ctm[5] = e * b1 + f * d1 + ctm[5]; + + // avoid FP exceptions on badly messed up PDF files + for (i = 0; i < 6; ++i) { + if (ctm[i] > 1e10) { + ctm[i] = 1e10; + } else if (ctm[i] < -1e10) { + ctm[i] = -1e10; + } + } +} + +void GfxState::shiftCTM(double tx, double ty) { + ctm[4] += tx; + ctm[5] += ty; + clipXMin += tx; + clipYMin += ty; + clipXMax += tx; + clipYMax += ty; +} + +void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) { + if (fillColorSpace) { + delete fillColorSpace; + } + fillColorSpace = colorSpace; +} + +void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) { + if (strokeColorSpace) { + delete strokeColorSpace; + } + strokeColorSpace = colorSpace; +} + +void GfxState::setFillPattern(GfxPattern *pattern) { + if (fillPattern) { + delete fillPattern; + } + fillPattern = pattern; +} + +void GfxState::setStrokePattern(GfxPattern *pattern) { + if (strokePattern) { + delete strokePattern; + } + strokePattern = pattern; +} + +void GfxState::setTransfer(Function **funcs) { + int i; + + for (i = 0; i < 4; ++i) { + if (transfer[i]) { + delete transfer[i]; + } + transfer[i] = funcs[i]; + } +} + +void GfxState::setLineDash(double *dash, int length, double start) { + if (lineDash) + gfree(lineDash); + lineDash = dash; + lineDashLength = length; + lineDashStart = start; +} + +void GfxState::clearPath() { + delete path; + path = new GfxPath(); +} + +void GfxState::clip() { + double xMin, yMin, xMax, yMax, x, y; + GfxSubpath *subpath; + int i, j; + + xMin = xMax = yMin = yMax = 0; // make gcc happy + for (i = 0; i < path->getNumSubpaths(); ++i) { + subpath = path->getSubpath(i); + for (j = 0; j < subpath->getNumPoints(); ++j) { + transform(subpath->getX(j), subpath->getY(j), &x, &y); + if (i == 0 && j == 0) { + xMin = xMax = x; + yMin = yMax = y; + } else { + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + } + } + } + if (xMin > clipXMin) { + clipXMin = xMin; + } + if (yMin > clipYMin) { + clipYMin = yMin; + } + if (xMax < clipXMax) { + clipXMax = xMax; + } + if (yMax < clipYMax) { + clipYMax = yMax; + } +} + +void GfxState::clipToStrokePath() { + double xMin, yMin, xMax, yMax, x, y, t0, t1; + GfxSubpath *subpath; + int i, j; + + xMin = xMax = yMin = yMax = 0; // make gcc happy + for (i = 0; i < path->getNumSubpaths(); ++i) { + subpath = path->getSubpath(i); + for (j = 0; j < subpath->getNumPoints(); ++j) { + transform(subpath->getX(j), subpath->getY(j), &x, &y); + if (i == 0 && j == 0) { + xMin = xMax = x; + yMin = yMax = y; + } else { + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + } + } + } + + // allow for the line width + //~ miter joins can extend farther than this + t0 = fabs(ctm[0]); + t1 = fabs(ctm[2]); + if (t0 > t1) { + xMin -= 0.5 * lineWidth * t0; + xMax += 0.5 * lineWidth * t0; + } else { + xMin -= 0.5 * lineWidth * t1; + xMax += 0.5 * lineWidth * t1; + } + t0 = fabs(ctm[0]); + t1 = fabs(ctm[3]); + if (t0 > t1) { + yMin -= 0.5 * lineWidth * t0; + yMax += 0.5 * lineWidth * t0; + } else { + yMin -= 0.5 * lineWidth * t1; + yMax += 0.5 * lineWidth * t1; + } + + if (xMin > clipXMin) { + clipXMin = xMin; + } + if (yMin > clipYMin) { + clipYMin = yMin; + } + if (xMax < clipXMax) { + clipXMax = xMax; + } + if (yMax < clipYMax) { + clipYMax = yMax; + } +} + +void GfxState::textShift(double tx, double ty) { + double dx, dy; + + textTransformDelta(tx, ty, &dx, &dy); + curX += dx; + curY += dy; +} + +void GfxState::shift(double dx, double dy) { + curX += dx; + curY += dy; +} + +GfxState *GfxState::save() { + GfxState *newState; + + newState = copy(); + newState->saved = this; + return newState; +} + +GfxState *GfxState::restore() { + GfxState *oldState; + + if (saved) { + oldState = saved; + + // these attributes aren't saved/restored by the q/Q operators + oldState->path = path; + oldState->curX = curX; + oldState->curY = curY; + oldState->lineX = lineX; + oldState->lineY = lineY; + + path = NULL; + saved = NULL; + delete this; + + } else { + oldState = this; + } + + return oldState; +} + +GBool GfxState::parseBlendMode(Object *obj, GfxBlendMode *mode) { + Object obj2; + int i, j; + + if (obj->isName()) { + for (i = 0; i < nGfxBlendModeNames; ++i) { + if (!strcmp(obj->getName(), gfxBlendModeNames[i].name)) { + *mode = gfxBlendModeNames[i].mode; + return gTrue; + } + } + return gFalse; + } else if (obj->isArray()) { + for (i = 0; i < obj->arrayGetLength(); ++i) { + obj->arrayGet(i, &obj2); + if (!obj2.isName()) { + obj2.free(); + return gFalse; + } + for (j = 0; j < nGfxBlendModeNames; ++j) { + if (!strcmp(obj2.getName(), gfxBlendModeNames[j].name)) { + obj2.free(); + *mode = gfxBlendModeNames[j].mode; + return gTrue; + } + } + obj2.free(); + } + *mode = gfxBlendNormal; + return gTrue; + } else { + return gFalse; + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GfxState.h swftools-0.9.1/lib/pdf/xpdf/GfxState.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/GfxState.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GfxState.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,1257 @@ +//======================================================================== +// +// GfxState.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GFXSTATE_H +#define GFXSTATE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" +#include "Function.h" + +class Array; +class GfxFont; +class PDFRectangle; +class GfxShading; + +//------------------------------------------------------------------------ +// GfxBlendMode +//------------------------------------------------------------------------ + +enum GfxBlendMode { + gfxBlendNormal, + gfxBlendMultiply, + gfxBlendScreen, + gfxBlendOverlay, + gfxBlendDarken, + gfxBlendLighten, + gfxBlendColorDodge, + gfxBlendColorBurn, + gfxBlendHardLight, + gfxBlendSoftLight, + gfxBlendDifference, + gfxBlendExclusion, + gfxBlendHue, + gfxBlendSaturation, + gfxBlendColor, + gfxBlendLuminosity +}; + +//------------------------------------------------------------------------ +// GfxColorComp +//------------------------------------------------------------------------ + +// 16.16 fixed point color component +typedef int GfxColorComp; + +#define gfxColorComp1 0x10000 + +static inline GfxColorComp dblToCol(double x) { + return (GfxColorComp)(x * gfxColorComp1); +} + +static inline double colToDbl(GfxColorComp x) { + return (double)x / (double)gfxColorComp1; +} + +static inline GfxColorComp byteToCol(Guchar x) { + // (x / 255) << 16 = (0.0000000100000001... * x) << 16 + // = ((x << 8) + (x) + (x >> 8) + ...) << 16 + // = (x << 8) + (x) + (x >> 7) + // [for rounding] + return (GfxColorComp)((x << 8) + x + (x >> 7)); +} + +static inline Guchar colToByte(GfxColorComp x) { + // 255 * x + 0.5 = 256 * x - x + 0x8000 + return (Guchar)(((x << 8) - x + 0x8000) >> 16); +} + +//------------------------------------------------------------------------ +// GfxColor +//------------------------------------------------------------------------ + +#define gfxColorMaxComps funcMaxOutputs + +struct GfxColor { + GfxColorComp c[gfxColorMaxComps]; +}; + +//------------------------------------------------------------------------ +// GfxGray +//------------------------------------------------------------------------ + +typedef GfxColorComp GfxGray; + +//------------------------------------------------------------------------ +// GfxRGB +//------------------------------------------------------------------------ + +struct GfxRGB { + GfxColorComp r, g, b; +}; + +//------------------------------------------------------------------------ +// GfxCMYK +//------------------------------------------------------------------------ + +struct GfxCMYK { + GfxColorComp c, m, y, k; +}; + +//------------------------------------------------------------------------ +// GfxColorSpace +//------------------------------------------------------------------------ + +// NB: The nGfxColorSpaceModes constant and the gfxColorSpaceModeNames +// array defined in GfxState.cc must match this enum. +enum GfxColorSpaceMode { + csDeviceGray, + csCalGray, + csDeviceRGB, + csCalRGB, + csDeviceCMYK, + csLab, + csICCBased, + csIndexed, + csSeparation, + csDeviceN, + csPattern +}; + +class GfxColorSpace { +public: + + GfxColorSpace(); + virtual ~GfxColorSpace(); + virtual GfxColorSpace *copy() = 0; + virtual GfxColorSpaceMode getMode() = 0; + + // Construct a color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Object *csObj, StreamColorSpaceMode csMode = streamCSNone); + + // Convert to gray, RGB, or CMYK. + virtual void getGray(GfxColor *color, GfxGray *gray) = 0; + virtual void getRGB(GfxColor *color, GfxRGB *rgb) = 0; + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk) = 0; + + // Return the number of color components. + virtual int getNComps() = 0; + + // Get this color space's default color. + virtual void getDefaultColor(GfxColor *color) = 0; + + // Return the default ranges for each component, assuming an image + // with a max pixel value of . + virtual void getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel); + + // Returns true if painting operations in this color space never + // mark the page (e.g., the "None" colorant). + virtual GBool isNonMarking() { return gFalse; } + + // Return the number of color space modes + static int getNumColorSpaceModes(); + + // Return the name of the th color space mode. + static char *getColorSpaceModeName(int idx); + +private: +}; + +//------------------------------------------------------------------------ +// GfxDeviceGrayColorSpace +//------------------------------------------------------------------------ + +class GfxDeviceGrayColorSpace: public GfxColorSpace { +public: + + GfxDeviceGrayColorSpace(); + virtual ~GfxDeviceGrayColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csDeviceGray; } + + virtual void getGray(GfxColor *color, GfxGray *gray); + virtual void getRGB(GfxColor *color, GfxRGB *rgb); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); + + virtual int getNComps() { return 1; } + virtual void getDefaultColor(GfxColor *color); + +private: +}; + +//------------------------------------------------------------------------ +// GfxCalGrayColorSpace +//------------------------------------------------------------------------ + +class GfxCalGrayColorSpace: public GfxColorSpace { +public: + + GfxCalGrayColorSpace(); + virtual ~GfxCalGrayColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csCalGray; } + + // Construct a CalGray color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr); + + virtual void getGray(GfxColor *color, GfxGray *gray); + virtual void getRGB(GfxColor *color, GfxRGB *rgb); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); + + virtual int getNComps() { return 1; } + virtual void getDefaultColor(GfxColor *color); + + // CalGray-specific access. + double getWhiteX() { return whiteX; } + double getWhiteY() { return whiteY; } + double getWhiteZ() { return whiteZ; } + double getBlackX() { return blackX; } + double getBlackY() { return blackY; } + double getBlackZ() { return blackZ; } + double getGamma() { return gamma; } + +private: + + double whiteX, whiteY, whiteZ; // white point + double blackX, blackY, blackZ; // black point + double gamma; // gamma value +}; + +//------------------------------------------------------------------------ +// GfxDeviceRGBColorSpace +//------------------------------------------------------------------------ + +class GfxDeviceRGBColorSpace: public GfxColorSpace { +public: + + GfxDeviceRGBColorSpace(); + virtual ~GfxDeviceRGBColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csDeviceRGB; } + + virtual void getGray(GfxColor *color, GfxGray *gray); + virtual void getRGB(GfxColor *color, GfxRGB *rgb); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); + + virtual int getNComps() { return 3; } + virtual void getDefaultColor(GfxColor *color); + +private: +}; + +//------------------------------------------------------------------------ +// GfxDeviceRGBXColorSpace +//------------------------------------------------------------------------ + +class GfxDeviceRGBXColorSpace: public GfxDeviceRGBColorSpace { +public: + + GfxDeviceRGBXColorSpace(); + virtual GfxColorSpace *copy(); + virtual int getNComps() { return 4; } +private: +}; + +//------------------------------------------------------------------------ +// GfxCalRGBColorSpace +//------------------------------------------------------------------------ + +class GfxCalRGBColorSpace: public GfxColorSpace { +public: + + GfxCalRGBColorSpace(); + virtual ~GfxCalRGBColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csCalRGB; } + + // Construct a CalRGB color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr); + + virtual void getGray(GfxColor *color, GfxGray *gray); + virtual void getRGB(GfxColor *color, GfxRGB *rgb); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); + + virtual int getNComps() { return 3; } + virtual void getDefaultColor(GfxColor *color); + + // CalRGB-specific access. + double getWhiteX() { return whiteX; } + double getWhiteY() { return whiteY; } + double getWhiteZ() { return whiteZ; } + double getBlackX() { return blackX; } + double getBlackY() { return blackY; } + double getBlackZ() { return blackZ; } + double getGammaR() { return gammaR; } + double getGammaG() { return gammaG; } + double getGammaB() { return gammaB; } + double *getMatrix() { return mat; } + +private: + + double whiteX, whiteY, whiteZ; // white point + double blackX, blackY, blackZ; // black point + double gammaR, gammaG, gammaB; // gamma values + double mat[9]; // ABC -> XYZ transform matrix +}; + +//------------------------------------------------------------------------ +// GfxDeviceCMYKColorSpace +//------------------------------------------------------------------------ + +class GfxDeviceCMYKColorSpace: public GfxColorSpace { +public: + + GfxDeviceCMYKColorSpace(); + virtual ~GfxDeviceCMYKColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csDeviceCMYK; } + + virtual void getGray(GfxColor *color, GfxGray *gray); + virtual void getRGB(GfxColor *color, GfxRGB *rgb); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); + + virtual int getNComps() { return 4; } + virtual void getDefaultColor(GfxColor *color); + +private: +}; + +//------------------------------------------------------------------------ +// GfxLabColorSpace +//------------------------------------------------------------------------ + +class GfxLabColorSpace: public GfxColorSpace { +public: + + GfxLabColorSpace(); + virtual ~GfxLabColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csLab; } + + // Construct a Lab color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr); + + virtual void getGray(GfxColor *color, GfxGray *gray); + virtual void getRGB(GfxColor *color, GfxRGB *rgb); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); + + virtual int getNComps() { return 3; } + virtual void getDefaultColor(GfxColor *color); + + virtual void getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel); + + // Lab-specific access. + double getWhiteX() { return whiteX; } + double getWhiteY() { return whiteY; } + double getWhiteZ() { return whiteZ; } + double getBlackX() { return blackX; } + double getBlackY() { return blackY; } + double getBlackZ() { return blackZ; } + double getAMin() { return aMin; } + double getAMax() { return aMax; } + double getBMin() { return bMin; } + double getBMax() { return bMax; } + +private: + + double whiteX, whiteY, whiteZ; // white point + double blackX, blackY, blackZ; // black point + double aMin, aMax, bMin, bMax; // range for the a and b components + double kr, kg, kb; // gamut mapping mulitpliers +}; + +//------------------------------------------------------------------------ +// GfxICCBasedColorSpace +//------------------------------------------------------------------------ + +class GfxICCBasedColorSpace: public GfxColorSpace { +public: + + GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA, + Ref *iccProfileStreamA); + virtual ~GfxICCBasedColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csICCBased; } + + // Construct an ICCBased color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr); + + virtual void getGray(GfxColor *color, GfxGray *gray); + virtual void getRGB(GfxColor *color, GfxRGB *rgb); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); + + virtual int getNComps() { return nComps; } + virtual void getDefaultColor(GfxColor *color); + + virtual void getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel); + + // ICCBased-specific access. + GfxColorSpace *getAlt() { return alt; } + +private: + + int nComps; // number of color components (1, 3, or 4) + GfxColorSpace *alt; // alternate color space + double rangeMin[4]; // min values for each component + double rangeMax[4]; // max values for each component + Ref iccProfileStream; // the ICC profile +}; + +//------------------------------------------------------------------------ +// GfxIndexedColorSpace +//------------------------------------------------------------------------ + +class GfxIndexedColorSpace: public GfxColorSpace { +public: + + GfxIndexedColorSpace(GfxColorSpace *baseA, int indexHighA); + virtual ~GfxIndexedColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csIndexed; } + + // Construct a Lab color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr); + + virtual void getGray(GfxColor *color, GfxGray *gray); + virtual void getRGB(GfxColor *color, GfxRGB *rgb); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); + + virtual int getNComps() { return 1; } + virtual void getDefaultColor(GfxColor *color); + + virtual void getDefaultRanges(double *decodeLow, double *decodeRange, + int maxImgPixel); + + // Indexed-specific access. + GfxColorSpace *getBase() { return base; } + int getIndexHigh() { return indexHigh; } + Guchar *getLookup() { return lookup; } + GfxColor *mapColorToBase(GfxColor *color, GfxColor *baseColor); + +private: + + GfxColorSpace *base; // base color space + int indexHigh; // max pixel value + Guchar *lookup; // lookup table +}; + +//------------------------------------------------------------------------ +// GfxSeparationColorSpace +//------------------------------------------------------------------------ + +class GfxSeparationColorSpace: public GfxColorSpace { +public: + + GfxSeparationColorSpace(GString *nameA, GfxColorSpace *altA, + Function *funcA); + virtual ~GfxSeparationColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csSeparation; } + + // Construct a Separation color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr); + + virtual void getGray(GfxColor *color, GfxGray *gray); + virtual void getRGB(GfxColor *color, GfxRGB *rgb); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); + + virtual int getNComps() { return 1; } + virtual void getDefaultColor(GfxColor *color); + + virtual GBool isNonMarking() { return nonMarking; } + + // Separation-specific access. + GString *getName() { return name; } + GfxColorSpace *getAlt() { return alt; } + Function *getFunc() { return func; } + +private: + + GString *name; // colorant name + GfxColorSpace *alt; // alternate color space + Function *func; // tint transform (into alternate color space) + GBool nonMarking; +}; + +//------------------------------------------------------------------------ +// GfxDeviceNColorSpace +//------------------------------------------------------------------------ + +class GfxDeviceNColorSpace: public GfxColorSpace { +public: + + GfxDeviceNColorSpace(int nCompsA, GfxColorSpace *alt, Function *func); + virtual ~GfxDeviceNColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csDeviceN; } + + // Construct a DeviceN color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr); + + virtual void getGray(GfxColor *color, GfxGray *gray); + virtual void getRGB(GfxColor *color, GfxRGB *rgb); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); + + virtual int getNComps() { return nComps; } + virtual void getDefaultColor(GfxColor *color); + + virtual GBool isNonMarking() { return nonMarking; } + + // DeviceN-specific access. + GString *getColorantName(int i) { return names[i]; } + GfxColorSpace *getAlt() { return alt; } + Function *getTintTransformFunc() { return func; } + +private: + + int nComps; // number of components + GString // colorant names + *names[gfxColorMaxComps]; + GfxColorSpace *alt; // alternate color space + Function *func; // tint transform (into alternate color space) + GBool nonMarking; +}; + +//------------------------------------------------------------------------ +// GfxPatternColorSpace +//------------------------------------------------------------------------ + +class GfxPatternColorSpace: public GfxColorSpace { +public: + + GfxPatternColorSpace(GfxColorSpace *underA); + virtual ~GfxPatternColorSpace(); + virtual GfxColorSpace *copy(); + virtual GfxColorSpaceMode getMode() { return csPattern; } + + // Construct a Pattern color space. Returns NULL if unsuccessful. + static GfxColorSpace *parse(Array *arr); + + virtual void getGray(GfxColor *color, GfxGray *gray); + virtual void getRGB(GfxColor *color, GfxRGB *rgb); + virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); + + virtual int getNComps() { return 0; } + virtual void getDefaultColor(GfxColor *color); + + // Pattern-specific access. + GfxColorSpace *getUnder() { return under; } + +private: + + GfxColorSpace *under; // underlying color space (for uncolored + // patterns) +}; + +//------------------------------------------------------------------------ +// GfxPattern +//------------------------------------------------------------------------ + +class GfxPattern { +public: + + GfxPattern(int typeA); + virtual ~GfxPattern(); + + static GfxPattern *parse(Object *obj); + + virtual GfxPattern *copy() = 0; + + int getType() { return type; } + +private: + + int type; +}; + +//------------------------------------------------------------------------ +// GfxTilingPattern +//------------------------------------------------------------------------ + +class GfxTilingPattern: public GfxPattern { +public: + + static GfxTilingPattern *parse(Object *patObj); + virtual ~GfxTilingPattern(); + + virtual GfxPattern *copy(); + + int getPaintType() { return paintType; } + int getTilingType() { return tilingType; } + double *getBBox() { return bbox; } + double getXStep() { return xStep; } + double getYStep() { return yStep; } + Dict *getResDict() + { return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; } + double *getMatrix() { return matrix; } + Object *getContentStream() { return &contentStream; } + +private: + + GfxTilingPattern(int paintTypeA, int tilingTypeA, + double *bboxA, double xStepA, double yStepA, + Object *resDictA, double *matrixA, + Object *contentStreamA); + + int paintType; + int tilingType; + double bbox[4]; + double xStep, yStep; + Object resDict; + double matrix[6]; + Object contentStream; +}; + +//------------------------------------------------------------------------ +// GfxShadingPattern +//------------------------------------------------------------------------ + +class GfxShadingPattern: public GfxPattern { +public: + + static GfxShadingPattern *parse(Object *patObj); + virtual ~GfxShadingPattern(); + + virtual GfxPattern *copy(); + + GfxShading *getShading() { return shading; } + double *getMatrix() { return matrix; } + +private: + + GfxShadingPattern(GfxShading *shadingA, double *matrixA); + + GfxShading *shading; + double matrix[6]; +}; + +//------------------------------------------------------------------------ +// GfxShading +//------------------------------------------------------------------------ + +class GfxShading { +public: + + GfxShading(int typeA); + GfxShading(GfxShading *shading); + virtual ~GfxShading(); + + static GfxShading *parse(Object *obj); + + virtual GfxShading *copy() = 0; + + int getType() { return type; } + GfxColorSpace *getColorSpace() { return colorSpace; } + GfxColor *getBackground() { return &background; } + GBool getHasBackground() { return hasBackground; } + void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA) + { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; } + GBool getHasBBox() { return hasBBox; } + +protected: + + GBool init(Dict *dict); + + int type; + GfxColorSpace *colorSpace; + GfxColor background; + GBool hasBackground; + double xMin, yMin, xMax, yMax; + GBool hasBBox; +}; + +//------------------------------------------------------------------------ +// GfxFunctionShading +//------------------------------------------------------------------------ + +class GfxFunctionShading: public GfxShading { +public: + + GfxFunctionShading(double x0A, double y0A, + double x1A, double y1A, + double *matrixA, + Function **funcsA, int nFuncsA); + GfxFunctionShading(GfxFunctionShading *shading); + virtual ~GfxFunctionShading(); + + static GfxFunctionShading *parse(Dict *dict); + + virtual GfxShading *copy(); + + void getDomain(double *x0A, double *y0A, double *x1A, double *y1A) + { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; } + double *getMatrix() { return matrix; } + int getNFuncs() { return nFuncs; } + Function *getFunc(int i) { return funcs[i]; } + void getColor(double x, double y, GfxColor *color); + +private: + + double x0, y0, x1, y1; + double matrix[6]; + Function *funcs[gfxColorMaxComps]; + int nFuncs; +}; + +//------------------------------------------------------------------------ +// GfxAxialShading +//------------------------------------------------------------------------ + +class GfxAxialShading: public GfxShading { +public: + + GfxAxialShading(double x0A, double y0A, + double x1A, double y1A, + double t0A, double t1A, + Function **funcsA, int nFuncsA, + GBool extend0A, GBool extend1A); + GfxAxialShading(GfxAxialShading *shading); + virtual ~GfxAxialShading(); + + static GfxAxialShading *parse(Dict *dict); + + virtual GfxShading *copy(); + + void getCoords(double *x0A, double *y0A, double *x1A, double *y1A) + { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; } + double getDomain0() { return t0; } + double getDomain1() { return t1; } + GBool getExtend0() { return extend0; } + GBool getExtend1() { return extend1; } + int getNFuncs() { return nFuncs; } + Function *getFunc(int i) { return funcs[i]; } + void getColor(double t, GfxColor *color); + +private: + + double x0, y0, x1, y1; + double t0, t1; + Function *funcs[gfxColorMaxComps]; + int nFuncs; + GBool extend0, extend1; +}; + +//------------------------------------------------------------------------ +// GfxRadialShading +//------------------------------------------------------------------------ + +class GfxRadialShading: public GfxShading { +public: + + GfxRadialShading(double x0A, double y0A, double r0A, + double x1A, double y1A, double r1A, + double t0A, double t1A, + Function **funcsA, int nFuncsA, + GBool extend0A, GBool extend1A); + GfxRadialShading(GfxRadialShading *shading); + virtual ~GfxRadialShading(); + + static GfxRadialShading *parse(Dict *dict); + + virtual GfxShading *copy(); + + void getCoords(double *x0A, double *y0A, double *r0A, + double *x1A, double *y1A, double *r1A) + { *x0A = x0; *y0A = y0; *r0A = r0; *x1A = x1; *y1A = y1; *r1A = r1; } + double getDomain0() { return t0; } + double getDomain1() { return t1; } + GBool getExtend0() { return extend0; } + GBool getExtend1() { return extend1; } + int getNFuncs() { return nFuncs; } + Function *getFunc(int i) { return funcs[i]; } + void getColor(double t, GfxColor *color); + +private: + + double x0, y0, r0, x1, y1, r1; + double t0, t1; + Function *funcs[gfxColorMaxComps]; + int nFuncs; + GBool extend0, extend1; +}; + +//------------------------------------------------------------------------ +// GfxGouraudTriangleShading +//------------------------------------------------------------------------ + +struct GfxGouraudVertex { + double x, y; + GfxColor color; +}; + +class GfxGouraudTriangleShading: public GfxShading { +public: + + GfxGouraudTriangleShading(int typeA, + GfxGouraudVertex *verticesA, int nVerticesA, + int (*trianglesA)[3], int nTrianglesA, + Function **funcsA, int nFuncsA); + GfxGouraudTriangleShading(GfxGouraudTriangleShading *shading); + virtual ~GfxGouraudTriangleShading(); + + static GfxGouraudTriangleShading *parse(int typeA, Dict *dict, Stream *str); + + virtual GfxShading *copy(); + + int getNTriangles() { return nTriangles; } + void getTriangle(int i, double *x0, double *y0, GfxColor *color0, + double *x1, double *y1, GfxColor *color1, + double *x2, double *y2, GfxColor *color2); + +private: + + GfxGouraudVertex *vertices; + int nVertices; + int (*triangles)[3]; + int nTriangles; + Function *funcs[gfxColorMaxComps]; + int nFuncs; +}; + +//------------------------------------------------------------------------ +// GfxPatchMeshShading +//------------------------------------------------------------------------ + +struct GfxPatch { + double x[4][4]; + double y[4][4]; + GfxColor color[2][2]; +}; + +class GfxPatchMeshShading: public GfxShading { +public: + + GfxPatchMeshShading(int typeA, GfxPatch *patchesA, int nPatchesA, + Function **funcsA, int nFuncsA); + GfxPatchMeshShading(GfxPatchMeshShading *shading); + virtual ~GfxPatchMeshShading(); + + static GfxPatchMeshShading *parse(int typeA, Dict *dict, Stream *str); + + virtual GfxShading *copy(); + + int getNPatches() { return nPatches; } + GfxPatch *getPatch(int i) { return &patches[i]; } + +private: + + GfxPatch *patches; + int nPatches; + Function *funcs[gfxColorMaxComps]; + int nFuncs; +}; + +//------------------------------------------------------------------------ +// GfxImageColorMap +//------------------------------------------------------------------------ + +class GfxImageColorMap { +public: + + // Constructor. + GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA); + + // Destructor. + ~GfxImageColorMap(); + + // Return a copy of this color map. + GfxImageColorMap *copy() { return new GfxImageColorMap(this); } + + // Is color map valid? + GBool isOk() { return ok; } + + // Get the color space. + GfxColorSpace *getColorSpace() { return colorSpace; } + + // Get stream decoding info. + int getNumPixelComps() { return nComps; } + int getBits() { return bits; } + + // Get decode table. + double getDecodeLow(int i) { return decodeLow[i]; } + double getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; } + + // Convert an image pixel to a color. + void getGray(Guchar *x, GfxGray *gray); + void getRGB(Guchar *x, GfxRGB *rgb); + void getCMYK(Guchar *x, GfxCMYK *cmyk); + void getColor(Guchar *x, GfxColor *color); + +private: + + GfxImageColorMap(GfxImageColorMap *colorMap); + + GfxColorSpace *colorSpace; // the image color space + int bits; // bits per component + int nComps; // number of components in a pixel + GfxColorSpace *colorSpace2; // secondary color space + int nComps2; // number of components in colorSpace2 + GfxColorComp * // lookup table + lookup[gfxColorMaxComps]; + double // minimum values for each component + decodeLow[gfxColorMaxComps]; + double // max - min value for each component + decodeRange[gfxColorMaxComps]; + GBool ok; +}; + +//------------------------------------------------------------------------ +// GfxSubpath and GfxPath +//------------------------------------------------------------------------ + +class GfxSubpath { +public: + + // Constructor. + GfxSubpath(double x1, double y1); + + // Destructor. + ~GfxSubpath(); + + // Copy. + GfxSubpath *copy() { return new GfxSubpath(this); } + + // Get points. + int getNumPoints() { return n; } + double getX(int i) { return x[i]; } + double getY(int i) { return y[i]; } + GBool getCurve(int i) { return curve[i]; } + + // Get last point. + double getLastX() { return x[n-1]; } + double getLastY() { return y[n-1]; } + + // Add a line segment. + void lineTo(double x1, double y1); + + // Add a Bezier curve. + void curveTo(double x1, double y1, double x2, double y2, + double x3, double y3); + + // Close the subpath. + void close(); + GBool isClosed() { return closed; } + + // Add (, ) to each point in the subpath. + void offset(double dx, double dy); + +private: + + double *x, *y; // points + GBool *curve; // curve[i] => point i is a control point + // for a Bezier curve + int n; // number of points + int size; // size of x/y arrays + GBool closed; // set if path is closed + + GfxSubpath(GfxSubpath *subpath); +}; + +class GfxPath { +public: + + // Constructor. + GfxPath(); + + // Destructor. + ~GfxPath(); + + // Copy. + GfxPath *copy() + { return new GfxPath(justMoved, firstX, firstY, subpaths, n, size); } + + // Is there a current point? + GBool isCurPt() { return n > 0 || justMoved; } + + // Is the path non-empty, i.e., is there at least one segment? + GBool isPath() { return n > 0; } + + // Get subpaths. + int getNumSubpaths() { return n; } + GfxSubpath *getSubpath(int i) { return subpaths[i]; } + + // Get last point on last subpath. + double getLastX() { return subpaths[n-1]->getLastX(); } + double getLastY() { return subpaths[n-1]->getLastY(); } + + // Move the current point. + void moveTo(double x, double y); + + // Add a segment to the last subpath. + void lineTo(double x, double y); + + // Add a Bezier curve to the last subpath + void curveTo(double x1, double y1, double x2, double y2, + double x3, double y3); + + // Close the last subpath. + void close(); + + // Append to . + void append(GfxPath *path); + + // Add (, ) to each point in the path. + void offset(double dx, double dy); + +private: + + GBool justMoved; // set if a new subpath was just started + double firstX, firstY; // first point in new subpath + GfxSubpath **subpaths; // subpaths + int n; // number of subpaths + int size; // size of subpaths array + + GfxPath(GBool justMoved1, double firstX1, double firstY1, + GfxSubpath **subpaths1, int n1, int size1); +}; + +//------------------------------------------------------------------------ +// GfxState +//------------------------------------------------------------------------ + +class GfxState { +public: + + // Construct a default GfxState, for a device with resolution + // x , page box , page rotation , and + // coordinate system specified by . + GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, + int rotateA, GBool upsideDown); + + // Destructor. + ~GfxState(); + + // Copy. + GfxState *copy() { return new GfxState(this); } + + // Accessors. + double getHDPI() { return hDPI; } + double getVDPI() { return vDPI; } + double *getCTM() { return ctm; } + double getX1() { return px1; } + double getY1() { return py1; } + double getX2() { return px2; } + double getY2() { return py2; } + double getPageWidth() { return pageWidth; } + double getPageHeight() { return pageHeight; } + int getRotate() { return rotate; } + GfxColor *getFillColor() { return &fillColor; } + GfxColor *getStrokeColor() { return &strokeColor; } + void getFillGray(GfxGray *gray) + { fillColorSpace->getGray(&fillColor, gray); } + void getStrokeGray(GfxGray *gray) + { strokeColorSpace->getGray(&strokeColor, gray); } + void getFillRGB(GfxRGB *rgb) + { fillColorSpace->getRGB(&fillColor, rgb); } + void getStrokeRGB(GfxRGB *rgb) + { strokeColorSpace->getRGB(&strokeColor, rgb); } + void getFillCMYK(GfxCMYK *cmyk) + { fillColorSpace->getCMYK(&fillColor, cmyk); } + void getStrokeCMYK(GfxCMYK *cmyk) + { strokeColorSpace->getCMYK(&strokeColor, cmyk); } + GfxColorSpace *getFillColorSpace() { return fillColorSpace; } + GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; } + GfxPattern *getFillPattern() { return fillPattern; } + GfxPattern *getStrokePattern() { return strokePattern; } + GfxBlendMode getBlendMode() { return blendMode; } + double getFillOpacity() { return fillOpacity; } + double getStrokeOpacity() { return strokeOpacity; } + GBool getFillOverprint() { return fillOverprint; } + GBool getStrokeOverprint() { return strokeOverprint; } + Function **getTransfer() { return transfer; } + double getLineWidth() { return lineWidth; } + void getLineDash(double **dash, int *length, double *start) + { *dash = lineDash; *length = lineDashLength; *start = lineDashStart; } + int getFlatness() { return flatness; } + int getLineJoin() { return lineJoin; } + int getLineCap() { return lineCap; } + double getMiterLimit() { return miterLimit; } + GBool getStrokeAdjust() { return strokeAdjust; } + GfxFont *getFont() { return font; } + double getFontSize() { return fontSize; } + double *getTextMat() { return textMat; } + double getCharSpace() { return charSpace; } + double getWordSpace() { return wordSpace; } + double getHorizScaling() { return horizScaling; } + double getLeading() { return leading; } + double getRise() { return rise; } + int getRender() { return render; } + GfxPath *getPath() { return path; } + void setPath(GfxPath *pathA); + double getCurX() { return curX; } + double getCurY() { return curY; } + void getClipBBox(double *xMin, double *yMin, double *xMax, double *yMax) + { *xMin = clipXMin; *yMin = clipYMin; *xMax = clipXMax; *yMax = clipYMax; } + void getUserClipBBox(double *xMin, double *yMin, double *xMax, double *yMax); + double getLineX() { return lineX; } + double getLineY() { return lineY; } + + // Is there a current point/path? + GBool isCurPt() { return path->isCurPt(); } + GBool isPath() { return path->isPath(); } + + // Transforms. + void transform(double x1, double y1, double *x2, double *y2) + { *x2 = ctm[0] * x1 + ctm[2] * y1 + ctm[4]; + *y2 = ctm[1] * x1 + ctm[3] * y1 + ctm[5]; } + void transformDelta(double x1, double y1, double *x2, double *y2) + { *x2 = ctm[0] * x1 + ctm[2] * y1; + *y2 = ctm[1] * x1 + ctm[3] * y1; } + void textTransform(double x1, double y1, double *x2, double *y2) + { *x2 = textMat[0] * x1 + textMat[2] * y1 + textMat[4]; + *y2 = textMat[1] * x1 + textMat[3] * y1 + textMat[5]; } + void textTransformDelta(double x1, double y1, double *x2, double *y2) + { *x2 = textMat[0] * x1 + textMat[2] * y1; + *y2 = textMat[1] * x1 + textMat[3] * y1; } + double transformWidth(double w); + double getTransformedLineWidth() + { return transformWidth(lineWidth); } + double getTransformedFontSize(); + void getFontTransMat(double *m11, double *m12, double *m21, double *m22); + + // Change state parameters. + void setCTM(double a, double b, double c, + double d, double e, double f); + void concatCTM(double a, double b, double c, + double d, double e, double f); + void shiftCTM(double tx, double ty); + void setFillColorSpace(GfxColorSpace *colorSpace); + void setStrokeColorSpace(GfxColorSpace *colorSpace); + void setFillColor(GfxColor *color) { fillColor = *color; } + void setStrokeColor(GfxColor *color) { strokeColor = *color; } + void setFillPattern(GfxPattern *pattern); + void setStrokePattern(GfxPattern *pattern); + void setBlendMode(GfxBlendMode mode) { blendMode = mode; } + void setFillOpacity(double opac) { fillOpacity = opac; } + void setStrokeOpacity(double opac) { strokeOpacity = opac; } + void setFillOverprint(GBool op) { fillOverprint = op; } + void setStrokeOverprint(GBool op) { strokeOverprint = op; } + void setTransfer(Function **funcs); + void setLineWidth(double width) { lineWidth = width; } + void setLineDash(double *dash, int length, double start); + void setFlatness(int flatness1) { flatness = flatness1; } + void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; } + void setLineCap(int lineCap1) { lineCap = lineCap1; } + void setMiterLimit(double limit) { miterLimit = limit; } + void setStrokeAdjust(GBool sa) { strokeAdjust = sa; } + void setFont(GfxFont *fontA, double fontSizeA) + { font = fontA; fontSize = fontSizeA; } + void setTextMat(double a, double b, double c, + double d, double e, double f) + { textMat[0] = a; textMat[1] = b; textMat[2] = c; + textMat[3] = d; textMat[4] = e; textMat[5] = f; } + void setCharSpace(double space) + { charSpace = space; } + void setWordSpace(double space) + { wordSpace = space; } + void setHorizScaling(double scale) + { horizScaling = 0.01 * scale; } + void setLeading(double leadingA) + { leading = leadingA; } + void setRise(double riseA) + { rise = riseA; } + void setRender(int renderA) + { render = renderA; } + + // Add to path. + void moveTo(double x, double y) + { path->moveTo(curX = x, curY = y); } + void lineTo(double x, double y) + { path->lineTo(curX = x, curY = y); } + void curveTo(double x1, double y1, double x2, double y2, + double x3, double y3) + { path->curveTo(x1, y1, x2, y2, curX = x3, curY = y3); } + void closePath() + { path->close(); curX = path->getLastX(); curY = path->getLastY(); } + void clearPath(); + + // Update clip region. + void clip(); + void clipToStrokePath(); + + // Text position. + void textSetPos(double tx, double ty) { lineX = tx; lineY = ty; } + void textMoveTo(double tx, double ty) + { lineX = tx; lineY = ty; textTransform(tx, ty, &curX, &curY); } + void textShift(double tx, double ty); + void shift(double dx, double dy); + + // Push/pop GfxState on/off stack. + GfxState *save(); + GfxState *restore(); + GBool hasSaves() { return saved != NULL; } + + // Misc + GBool parseBlendMode(Object *obj, GfxBlendMode *mode); + +private: + + double hDPI, vDPI; // resolution + double ctm[6]; // coord transform matrix + double px1, py1, px2, py2; // page corners (user coords) + double pageWidth, pageHeight; // page size (pixels) + int rotate; // page rotation angle + + GfxColorSpace *fillColorSpace; // fill color space + GfxColorSpace *strokeColorSpace; // stroke color space + GfxColor fillColor; // fill color + GfxColor strokeColor; // stroke color + GfxPattern *fillPattern; // fill pattern + GfxPattern *strokePattern; // stroke pattern + GfxBlendMode blendMode; // transparency blend mode + double fillOpacity; // fill opacity + double strokeOpacity; // stroke opacity + GBool fillOverprint; // fill overprint + GBool strokeOverprint; // stroke overprint + Function *transfer[4]; // transfer function (entries may be: all + // NULL = identity; last three NULL = + // single function; all four non-NULL = + // R,G,B,gray functions) + + double lineWidth; // line width + double *lineDash; // line dash + int lineDashLength; + double lineDashStart; + int flatness; // curve flatness + int lineJoin; // line join style + int lineCap; // line cap style + double miterLimit; // line miter limit + GBool strokeAdjust; // stroke adjustment + + GfxFont *font; // font + double fontSize; // font size + double textMat[6]; // text matrix + double charSpace; // character spacing + double wordSpace; // word spacing + double horizScaling; // horizontal scaling + double leading; // text leading + double rise; // text rise + int render; // text rendering mode + + GfxPath *path; // array of path elements + double curX, curY; // current point (user coords) + double lineX, lineY; // start of current text line (text coords) + + double clipXMin, clipYMin, // bounding box for clip region + clipXMax, clipYMax; + + GfxState *saved; // next GfxState on stack + + GfxState(GfxState *state); +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GHash.cc swftools-0.9.1/lib/pdf/xpdf/GHash.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/GHash.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GHash.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,380 @@ +//======================================================================== +// +// GHash.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "gmem.h" +#include "GString.h" +#include "GHash.h" + +//------------------------------------------------------------------------ + +struct GHashBucket { + GString *key; + union { + void *p; + int i; + } val; + GHashBucket *next; +}; + +struct GHashIter { + int h; + GHashBucket *p; +}; + +//------------------------------------------------------------------------ + +GHash::GHash(GBool deleteKeysA) { + int h; + + deleteKeys = deleteKeysA; + size = 7; + tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *)); + for (h = 0; h < size; ++h) { + tab[h] = NULL; + } + len = 0; +} + +GHash::~GHash() { + GHashBucket *p; + int h; + + for (h = 0; h < size; ++h) { + while (tab[h]) { + p = tab[h]; + tab[h] = p->next; + if (deleteKeys) { + delete p->key; + } + delete p; + } + } + gfree(tab); +} + +void GHash::add(GString *key, void *val) { + GHashBucket *p; + int h; + + // expand the table if necessary + if (len >= size) { + expand(); + } + + // add the new symbol + p = new GHashBucket; + p->key = key; + p->val.p = val; + h = hash(key); + p->next = tab[h]; + tab[h] = p; + ++len; +} + +void GHash::add(GString *key, int val) { + GHashBucket *p; + int h; + + // expand the table if necessary + if (len >= size) { + expand(); + } + + // add the new symbol + p = new GHashBucket; + p->key = key; + p->val.i = val; + h = hash(key); + p->next = tab[h]; + tab[h] = p; + ++len; +} + +void GHash::replace(GString *key, void *val) { + GHashBucket *p; + int h; + + if ((p = find(key, &h))) { + p->val.p = val; + delete key; + } else { + add(key, val); + } +} + +void GHash::replace(GString *key, int val) { + GHashBucket *p; + int h; + + if ((p = find(key, &h))) { + p->val.i = val; + delete key; + } else { + add(key, val); + } +} + +void *GHash::lookup(GString *key) { + GHashBucket *p; + int h; + + if (!(p = find(key, &h))) { + return NULL; + } + return p->val.p; +} + +int GHash::lookupInt(GString *key) { + GHashBucket *p; + int h; + + if (!(p = find(key, &h))) { + return 0; + } + return p->val.i; +} + +void *GHash::lookup(char *key) { + GHashBucket *p; + int h; + + if (!(p = find(key, &h))) { + return NULL; + } + return p->val.p; +} + +int GHash::lookupInt(char *key) { + GHashBucket *p; + int h; + + if (!(p = find(key, &h))) { + return 0; + } + return p->val.i; +} + +void *GHash::remove(GString *key) { + GHashBucket *p; + GHashBucket **q; + void *val; + int h; + + if (!(p = find(key, &h))) { + return NULL; + } + q = &tab[h]; + while (*q != p) { + q = &((*q)->next); + } + *q = p->next; + if (deleteKeys) { + delete p->key; + } + val = p->val.p; + delete p; + --len; + return val; +} + +int GHash::removeInt(GString *key) { + GHashBucket *p; + GHashBucket **q; + int val; + int h; + + if (!(p = find(key, &h))) { + return 0; + } + q = &tab[h]; + while (*q != p) { + q = &((*q)->next); + } + *q = p->next; + if (deleteKeys) { + delete p->key; + } + val = p->val.i; + delete p; + --len; + return val; +} + +void *GHash::remove(char *key) { + GHashBucket *p; + GHashBucket **q; + void *val; + int h; + + if (!(p = find(key, &h))) { + return NULL; + } + q = &tab[h]; + while (*q != p) { + q = &((*q)->next); + } + *q = p->next; + if (deleteKeys) { + delete p->key; + } + val = p->val.p; + delete p; + --len; + return val; +} + +int GHash::removeInt(char *key) { + GHashBucket *p; + GHashBucket **q; + int val; + int h; + + if (!(p = find(key, &h))) { + return 0; + } + q = &tab[h]; + while (*q != p) { + q = &((*q)->next); + } + *q = p->next; + if (deleteKeys) { + delete p->key; + } + val = p->val.i; + delete p; + --len; + return val; +} + +void GHash::startIter(GHashIter **iter) { + *iter = new GHashIter; + (*iter)->h = -1; + (*iter)->p = NULL; +} + +GBool GHash::getNext(GHashIter **iter, GString **key, void **val) { + if (!*iter) { + return gFalse; + } + if ((*iter)->p) { + (*iter)->p = (*iter)->p->next; + } + while (!(*iter)->p) { + if (++(*iter)->h == size) { + delete *iter; + *iter = NULL; + return gFalse; + } + (*iter)->p = tab[(*iter)->h]; + } + *key = (*iter)->p->key; + *val = (*iter)->p->val.p; + return gTrue; +} + +GBool GHash::getNext(GHashIter **iter, GString **key, int *val) { + if (!*iter) { + return gFalse; + } + if ((*iter)->p) { + (*iter)->p = (*iter)->p->next; + } + while (!(*iter)->p) { + if (++(*iter)->h == size) { + delete *iter; + *iter = NULL; + return gFalse; + } + (*iter)->p = tab[(*iter)->h]; + } + *key = (*iter)->p->key; + *val = (*iter)->p->val.i; + return gTrue; +} + +void GHash::killIter(GHashIter **iter) { + delete *iter; + *iter = NULL; +} + +void GHash::expand() { + GHashBucket **oldTab; + GHashBucket *p; + int oldSize, h, i; + + oldSize = size; + oldTab = tab; + size = 2*size + 1; + tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *)); + for (h = 0; h < size; ++h) { + tab[h] = NULL; + } + for (i = 0; i < oldSize; ++i) { + while (oldTab[i]) { + p = oldTab[i]; + oldTab[i] = oldTab[i]->next; + h = hash(p->key); + p->next = tab[h]; + tab[h] = p; + } + } + gfree(oldTab); +} + +GHashBucket *GHash::find(GString *key, int *h) { + GHashBucket *p; + + *h = hash(key); + for (p = tab[*h]; p; p = p->next) { + if (!p->key->cmp(key)) { + return p; + } + } + return NULL; +} + +GHashBucket *GHash::find(char *key, int *h) { + GHashBucket *p; + + *h = hash(key); + for (p = tab[*h]; p; p = p->next) { + if (!p->key->cmp(key)) { + return p; + } + } + return NULL; +} + +int GHash::hash(GString *key) { + char *p; + unsigned int h; + int i; + + h = 0; + for (p = key->getCString(), i = 0; i < key->getLength(); ++p, ++i) { + h = 17 * h + (int)(*p & 0xff); + } + return (int)(h % size); +} + +int GHash::hash(char *key) { + char *p; + unsigned int h; + + h = 0; + for (p = key; *p; ++p) { + h = 17 * h + (int)(*p & 0xff); + } + return (int)(h % size); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GHash.h swftools-0.9.1/lib/pdf/xpdf/GHash.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/GHash.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GHash.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,78 @@ +//======================================================================== +// +// GHash.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GHASH_H +#define GHASH_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +class GString; +struct GHashBucket; +struct GHashIter; + +//------------------------------------------------------------------------ + +class GHash { +public: + + GHash(GBool deleteKeysA = gFalse); + ~GHash(); + void add(GString *key, void *val); + void add(GString *key, int val); + void replace(GString *key, void *val); + void replace(GString *key, int val); + void *lookup(GString *key); + int lookupInt(GString *key); + void *lookup(char *key); + int lookupInt(char *key); + void *remove(GString *key); + int removeInt(GString *key); + void *remove(char *key); + int removeInt(char *key); + int getLength() { return len; } + void startIter(GHashIter **iter); + GBool getNext(GHashIter **iter, GString **key, void **val); + GBool getNext(GHashIter **iter, GString **key, int *val); + void killIter(GHashIter **iter); + +private: + + void expand(); + GHashBucket *find(GString *key, int *h); + GHashBucket *find(char *key, int *h); + int hash(GString *key); + int hash(char *key); + + GBool deleteKeys; // set if key strings should be deleted + int size; // number of buckets + int len; // number of entries + GHashBucket **tab; +}; + +#define deleteGHash(hash, T) \ + do { \ + GHash *_hash = (hash); \ + { \ + GHashIter *_iter; \ + GString *_key; \ + void *_p; \ + _hash->startIter(&_iter); \ + while (_hash->getNext(&_iter, &_key, &_p)) { \ + delete (T*)_p; \ + } \ + delete _hash; \ + } \ + } while(0) + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GList.cc swftools-0.9.1/lib/pdf/xpdf/GList.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/GList.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GList.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,97 @@ +//======================================================================== +// +// GList.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "GList.h" + +//------------------------------------------------------------------------ +// GList +//------------------------------------------------------------------------ + +GList::GList() { + size = 8; + data = (void **)gmallocn(size, sizeof(void*)); + length = 0; + inc = 0; +} + +GList::GList(int sizeA) { + size = sizeA; + data = (void **)gmallocn(size, sizeof(void*)); + length = 0; + inc = 0; +} + +GList::~GList() { + gfree(data); +} + +void GList::append(void *p) { + if (length >= size) { + expand(); + } + data[length++] = p; +} + +void GList::append(GList *list) { + int i; + + while (length + list->length > size) { + expand(); + } + for (i = 0; i < list->length; ++i) { + data[length++] = list->data[i]; + } +} + +void GList::insert(int i, void *p) { + if (length >= size) { + expand(); + } + if (i < length) { + memmove(data+i+1, data+i, (length - i) * sizeof(void *)); + } + data[i] = p; + ++length; +} + +void *GList::del(int i) { + void *p; + + p = data[i]; + if (i < length - 1) { + memmove(data+i, data+i+1, (length - i - 1) * sizeof(void *)); + } + --length; + if (size - length >= ((inc > 0) ? inc : size/2)) { + shrink(); + } + return p; +} + +void GList::sort(int (*cmp)(const void *obj1, const void *obj2)) { + qsort(data, length, sizeof(void *), cmp); +} + +void GList::expand() { + size += (inc > 0) ? inc : size; + data = (void **)greallocn(data, size, sizeof(void*)); +} + +void GList::shrink() { + size -= (inc > 0) ? inc : size/2; + data = (void **)greallocn(data, size, sizeof(void*)); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GList.h swftools-0.9.1/lib/pdf/xpdf/GList.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/GList.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GList.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,96 @@ +//======================================================================== +// +// GList.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GLIST_H +#define GLIST_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +//------------------------------------------------------------------------ +// GList +//------------------------------------------------------------------------ + +class GList { +public: + + // Create an empty list. + GList(); + + // Create an empty list with space for elements. + GList(int sizeA); + + // Destructor - does not free pointed-to objects. + ~GList(); + + //----- general + + // Get the number of elements. + int getLength() { return length; } + + //----- ordered list support + + // Return the th element. + // Assumes 0 <= i < length. + void *get(int i) { return data[i]; } + + // Append an element to the end of the list. + void append(void *p); + + // Append another list to the end of this one. + void append(GList *list); + + // Insert an element at index . + // Assumes 0 <= i <= length. + void insert(int i, void *p); + + // Deletes and returns the element at index . + // Assumes 0 <= i < length. + void *del(int i); + + // Sort the list accoring to the given comparison function. + // NB: this sorts an array of pointers, so the pointer args need to + // be double-dereferenced. + void sort(int (*cmp)(const void *ptr1, const void *ptr2)); + + //----- control + + // Set allocation increment to . If inc > 0, that many + // elements will be allocated every time the list is expanded. + // If inc <= 0, the list will be doubled in size. + void setAllocIncr(int incA) { inc = incA; } + +private: + + void expand(); + void shrink(); + + void **data; // the list elements + int size; // size of data array + int length; // number of elements on list + int inc; // allocation increment +}; + +#define deleteGList(list, T) \ + do { \ + GList *_list = (list); \ + { \ + int _i; \ + for (_i = 0; _i < _list->getLength(); ++_i) { \ + delete (T*)_list->get(_i); \ + } \ + delete _list; \ + } \ + } while (0) + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GlobalParams.cc swftools-0.9.1/lib/pdf/xpdf/GlobalParams.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/GlobalParams.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GlobalParams.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,2980 @@ +//======================================================================== +// +// GlobalParams.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#ifdef ENABLE_PLUGINS +# ifndef WIN32 +# include +# endif +#endif +#ifdef WIN32 +# include +#endif +#if HAVE_PAPER_H +#include +#endif +#include "gmem.h" +#include "GString.h" +#include "GList.h" +#include "GHash.h" +#include "gfile.h" +#include "Error.h" +#include "NameToCharCode.h" +#include "CharCodeToUnicode.h" +#include "UnicodeMap.h" +#include "CMap.h" +#include "BuiltinFontTables.h" +#include "FontEncodingTables.h" +#ifdef ENABLE_PLUGINS +# include "XpdfPluginAPI.h" +#endif +#include "GlobalParams.h" + +#ifdef WIN32 +# define strcasecmp stricmp +#endif + +#if MULTITHREADED +# define lockGlobalParams gLockMutex(&mutex) +# define lockUnicodeMapCache gLockMutex(&unicodeMapCacheMutex) +# define lockCMapCache gLockMutex(&cMapCacheMutex) +# define unlockGlobalParams gUnlockMutex(&mutex) +# define unlockUnicodeMapCache gUnlockMutex(&unicodeMapCacheMutex) +# define unlockCMapCache gUnlockMutex(&cMapCacheMutex) +#else +# define lockGlobalParams +# define lockUnicodeMapCache +# define lockCMapCache +# define unlockGlobalParams +# define unlockUnicodeMapCache +# define unlockCMapCache +#endif + +#include "NameToUnicodeTable.h" +#include "UnicodeMapTables.h" +#include "UTF8.h" + +#ifdef ENABLE_PLUGINS +# ifdef WIN32 +extern XpdfPluginVecTable xpdfPluginVecTable; +# endif +#endif + +//------------------------------------------------------------------------ + +#define cidToUnicodeCacheSize 4 +#define unicodeToUnicodeCacheSize 4 + +//------------------------------------------------------------------------ + +static struct { + char *name; + char *t1FileName; + char *ttFileName; +} displayFontTab[] = { + {"Courier", "n022003l.pfb", "cour.ttf"}, + {"Courier-Bold", "n022004l.pfb", "courbd.ttf"}, + {"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf"}, + {"Courier-Oblique", "n022023l.pfb", "couri.ttf"}, + {"Helvetica", "n019003l.pfb", "arial.ttf"}, + {"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf"}, + {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf"}, + {"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf"}, + {"Symbol", "s050000l.pfb", NULL}, + {"Times-Bold", "n021004l.pfb", "timesbd.ttf"}, + {"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf"}, + {"Times-Italic", "n021023l.pfb", "timesi.ttf"}, + {"Times-Roman", "n021003l.pfb", "times.ttf"}, + {"ZapfDingbats", "d050000l.pfb", NULL}, + {NULL} +}; + +#ifdef WIN32 +static char *displayFontDirs[] = { + "c:/windows/fonts", + "c:/winnt/fonts", + NULL +}; +#else +static char *displayFontDirs[] = { + "/usr/share/ghostscript/fonts", + "/usr/local/share/ghostscript/fonts", + "/usr/share/fonts/default/Type1", + "/usr/share/fonts/default/ghostscript", + "/usr/share/fonts/type1/gsfonts", + NULL +}; +#endif + +//------------------------------------------------------------------------ + +GlobalParams *globalParams = NULL; + +//------------------------------------------------------------------------ +// DisplayFontParam +//------------------------------------------------------------------------ + +DisplayFontParam::DisplayFontParam(GString *nameA, + DisplayFontParamKind kindA) { + name = nameA; + kind = kindA; + switch (kind) { + case displayFontT1: + t1.fileName = NULL; + break; + case displayFontTT: + tt.fileName = NULL; + break; + } +} + +DisplayFontParam::~DisplayFontParam() { + delete name; + switch (kind) { + case displayFontT1: + if (t1.fileName) { + delete t1.fileName; + } + break; + case displayFontTT: + if (tt.fileName) { + delete tt.fileName; + } + break; + } +} + +#ifdef WIN32 + +//------------------------------------------------------------------------ +// WinFontInfo +//------------------------------------------------------------------------ + +class WinFontInfo: public DisplayFontParam { +public: + + GBool bold, italic; + + static WinFontInfo *make(GString *nameA, GBool boldA, GBool italicA, + HKEY regKey, char *winFontDir); + WinFontInfo(GString *nameA, GBool boldA, GBool italicA, + GString *fileNameA); + virtual ~WinFontInfo(); + GBool equals(WinFontInfo *fi); +}; + +WinFontInfo *WinFontInfo::make(GString *nameA, GBool boldA, GBool italicA, + HKEY regKey, char *winFontDir) { + GString *regName; + GString *fileNameA; + char buf[MAX_PATH]; + DWORD n; + char c; + int i; + + //----- find the font file + fileNameA = NULL; + regName = nameA->copy(); + if (boldA) { + regName->append(" Bold"); + } + if (italicA) { + regName->append(" Italic"); + } + regName->append(" (TrueType)"); + n = sizeof(buf); + if (RegQueryValueEx(regKey, regName->getCString(), NULL, NULL, + (LPBYTE)buf, &n) == ERROR_SUCCESS) { + fileNameA = new GString(winFontDir); + fileNameA->append('\\')->append(buf); + } + delete regName; + if (!fileNameA) { + delete nameA; + return NULL; + } + + //----- normalize the font name + i = 0; + while (i < nameA->getLength()) { + c = nameA->getChar(i); + if (c == ' ' || c == ',' || c == '-') { + nameA->del(i); + } else { + ++i; + } + } + + return new WinFontInfo(nameA, boldA, italicA, fileNameA); +} + +WinFontInfo::WinFontInfo(GString *nameA, GBool boldA, GBool italicA, + GString *fileNameA): + DisplayFontParam(nameA, displayFontTT) +{ + bold = boldA; + italic = italicA; + tt.fileName = fileNameA; +} + +WinFontInfo::~WinFontInfo() { +} + +GBool WinFontInfo::equals(WinFontInfo *fi) { + return !name->cmp(fi->name) && bold == fi->bold && italic == fi->italic; +} + +//------------------------------------------------------------------------ +// WinFontList +//------------------------------------------------------------------------ + +class WinFontList { +public: + + WinFontList(char *winFontDirA); + ~WinFontList(); + WinFontInfo *find(GString *font); + +private: + + void add(WinFontInfo *fi); + static int CALLBACK enumFunc1(CONST LOGFONT *font, + CONST TEXTMETRIC *metrics, + DWORD type, LPARAM data); + static int CALLBACK enumFunc2(CONST LOGFONT *font, + CONST TEXTMETRIC *metrics, + DWORD type, LPARAM data); + + GList *fonts; // [WinFontInfo] + HDC dc; // (only used during enumeration) + HKEY regKey; // (only used during enumeration) + char *winFontDir; // (only used during enumeration) +}; + +WinFontList::WinFontList(char *winFontDirA) { + OSVERSIONINFO version; + char *path; + + fonts = new GList(); + dc = GetDC(NULL); + winFontDir = winFontDirA; + version.dwOSVersionInfoSize = sizeof(version); + GetVersionEx(&version); + if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) { + path = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\"; + } else { + path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\"; + } + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, + KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, + ®Key) == ERROR_SUCCESS) { + EnumFonts(dc, NULL, &WinFontList::enumFunc1, (LPARAM)this); + RegCloseKey(regKey); + } + ReleaseDC(NULL, dc); +} + +WinFontList::~WinFontList() { + deleteGList(fonts, WinFontInfo); +} + +void WinFontList::add(WinFontInfo *fi) { + int i; + + for (i = 0; i < fonts->getLength(); ++i) { + if (((WinFontInfo *)fonts->get(i))->equals(fi)) { + delete fi; + return; + } + } + fonts->append(fi); +} + +WinFontInfo *WinFontList::find(GString *font) { + GString *name; + GBool bold, italic; + WinFontInfo *fi; + char c; + int n, i; + + name = font->copy(); + + // remove space, comma, dash chars + i = 0; + while (i < name->getLength()) { + c = name->getChar(i); + if (c == ' ' || c == ',' || c == '-') { + name->del(i); + } else { + ++i; + } + } + n = name->getLength(); + + // remove trailing "MT" (Foo-MT, Foo-BoldMT, etc.) + if (!strcmp(name->getCString() + n - 2, "MT")) { + name->del(n - 2, 2); + n -= 2; + } + + // look for "Italic" + if (!strcmp(name->getCString() + n - 6, "Italic")) { + name->del(n - 6, 6); + italic = gTrue; + n -= 6; + } else { + italic = gFalse; + } + + // look for "Bold" + if (!strcmp(name->getCString() + n - 4, "Bold")) { + name->del(n - 4, 4); + bold = gTrue; + n -= 4; + } else { + bold = gFalse; + } + + // remove trailing "MT" (FooMT-Bold, etc.) + if (!strcmp(name->getCString() + n - 2, "MT")) { + name->del(n - 2, 2); + n -= 2; + } + + // remove trailing "PS" + if (!strcmp(name->getCString() + n - 2, "PS")) { + name->del(n - 2, 2); + n -= 2; + } + + // search for the font + fi = NULL; + for (i = 0; i < fonts->getLength(); ++i) { + fi = (WinFontInfo *)fonts->get(i); + if (!fi->name->cmp(name) && fi->bold == bold && fi->italic == italic) { + break; + } + fi = NULL; + } + + delete name; + return fi; +} + +int CALLBACK WinFontList::enumFunc1(CONST LOGFONT *font, + CONST TEXTMETRIC *metrics, + DWORD type, LPARAM data) { + WinFontList *fl = (WinFontList *)data; + + EnumFonts(fl->dc, font->lfFaceName, &WinFontList::enumFunc2, (LPARAM)fl); + return 1; +} + +int CALLBACK WinFontList::enumFunc2(CONST LOGFONT *font, + CONST TEXTMETRIC *metrics, + DWORD type, LPARAM data) { + WinFontList *fl = (WinFontList *)data; + WinFontInfo *fi; + + if (type & TRUETYPE_FONTTYPE) { + if ((fi = WinFontInfo::make(new GString(font->lfFaceName), + font->lfWeight >= 600, + font->lfItalic ? gTrue : gFalse, + fl->regKey, fl->winFontDir))) { + fl->add(fi); + } + } + return 1; +} + +#endif // WIN32 + +//------------------------------------------------------------------------ +// PSFontParam +//------------------------------------------------------------------------ + +PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA, + GString *psFontNameA, GString *encodingA) { + pdfFontName = pdfFontNameA; + wMode = wModeA; + psFontName = psFontNameA; + encoding = encodingA; +} + +PSFontParam::~PSFontParam() { + delete pdfFontName; + delete psFontName; + if (encoding) { + delete encoding; + } +} + +//------------------------------------------------------------------------ +// KeyBinding +//------------------------------------------------------------------------ + +KeyBinding::KeyBinding(int codeA, int modsA, int contextA, char *cmd0) { + code = codeA; + mods = modsA; + context = contextA; + cmds = new GList(); + cmds->append(new GString(cmd0)); +} + +KeyBinding::KeyBinding(int codeA, int modsA, int contextA, + char *cmd0, char *cmd1) { + code = codeA; + mods = modsA; + context = contextA; + cmds = new GList(); + cmds->append(new GString(cmd0)); + cmds->append(new GString(cmd1)); +} + +KeyBinding::KeyBinding(int codeA, int modsA, int contextA, GList *cmdsA) { + code = codeA; + mods = modsA; + context = contextA; + cmds = cmdsA; +} + +KeyBinding::~KeyBinding() { + deleteGList(cmds, GString); +} + +#ifdef ENABLE_PLUGINS +//------------------------------------------------------------------------ +// Plugin +//------------------------------------------------------------------------ + +class Plugin { +public: + + static Plugin *load(char *type, char *name); + ~Plugin(); + +private: + +#ifdef WIN32 + Plugin(HMODULE libA); + HMODULE lib; +#else + Plugin(void *dlA); + void *dl; +#endif +}; + +Plugin *Plugin::load(char *type, char *name) { + GString *path; + Plugin *plugin; + XpdfPluginVecTable *vt; + XpdfBool (*xpdfInitPlugin)(void); +#ifdef WIN32 + HMODULE libA; +#else + void *dlA; +#endif + + path = globalParams->getBaseDir(); + appendToPath(path, "plugins"); + appendToPath(path, type); + appendToPath(path, name); + +#ifdef WIN32 + path->append(".dll"); + if (!(libA = LoadLibrary(path->getCString()))) { + error(-1, "Failed to load plugin '%s'", + path->getCString()); + goto err1; + } + if (!(vt = (XpdfPluginVecTable *) + GetProcAddress(libA, "xpdfPluginVecTable"))) { + error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'", + path->getCString()); + goto err2; + } +#else + //~ need to deal with other extensions here + path->append(".so"); + if (!(dlA = dlopen(path->getCString(), RTLD_NOW))) { + error(-1, "Failed to load plugin '%s': %s", + path->getCString(), dlerror()); + goto err1; + } + if (!(vt = (XpdfPluginVecTable *)dlsym(dlA, "xpdfPluginVecTable"))) { + error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'", + path->getCString()); + goto err2; + } +#endif + + if (vt->version != xpdfPluginVecTable.version) { + error(-1, "Plugin '%s' is wrong version", path->getCString()); + goto err2; + } + memcpy(vt, &xpdfPluginVecTable, sizeof(xpdfPluginVecTable)); + +#ifdef WIN32 + if (!(xpdfInitPlugin = (XpdfBool (*)(void)) + GetProcAddress(libA, "xpdfInitPlugin"))) { + error(-1, "Failed to find xpdfInitPlugin in plugin '%s'", + path->getCString()); + goto err2; + } +#else + if (!(xpdfInitPlugin = (XpdfBool (*)(void))dlsym(dlA, "xpdfInitPlugin"))) { + error(-1, "Failed to find xpdfInitPlugin in plugin '%s'", + path->getCString()); + goto err2; + } +#endif + + if (!(*xpdfInitPlugin)()) { + error(-1, "Initialization of plugin '%s' failed", + path->getCString()); + goto err2; + } + +#ifdef WIN32 + plugin = new Plugin(libA); +#else + plugin = new Plugin(dlA); +#endif + + delete path; + return plugin; + + err2: +#ifdef WIN32 + FreeLibrary(libA); +#else + dlclose(dlA); +#endif + err1: + delete path; + return NULL; +} + +#ifdef WIN32 +Plugin::Plugin(HMODULE libA) { + lib = libA; +} +#else +Plugin::Plugin(void *dlA) { + dl = dlA; +} +#endif + +Plugin::~Plugin() { + void (*xpdfFreePlugin)(void); + +#ifdef WIN32 + if ((xpdfFreePlugin = (void (*)(void)) + GetProcAddress(lib, "xpdfFreePlugin"))) { + (*xpdfFreePlugin)(); + } + FreeLibrary(lib); +#else + if ((xpdfFreePlugin = (void (*)(void))dlsym(dl, "xpdfFreePlugin"))) { + (*xpdfFreePlugin)(); + } + dlclose(dl); +#endif +} + +#endif // ENABLE_PLUGINS + +//------------------------------------------------------------------------ +// parsing +//------------------------------------------------------------------------ + +GlobalParams::GlobalParams(char *cfgFileName) { + UnicodeMap *map; + GString *fileName; + FILE *f; + int i; + +#if MULTITHREADED + gInitMutex(&mutex); + gInitMutex(&unicodeMapCacheMutex); + gInitMutex(&cMapCacheMutex); +#endif + + initBuiltinFontTables(); + + // scan the encoding in reverse because we want the lowest-numbered + // index for each char name ('space' is encoded twice) + macRomanReverseMap = new NameToCharCode(); + for (i = 255; i >= 0; --i) { + if (macRomanEncoding[i]) { + macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i); + } + } + +#ifdef WIN32 + // baseDir will be set by a call to setBaseDir + baseDir = new GString(); +#else + baseDir = appendToPath(getHomeDir(), ".xpdf"); +#endif + nameToUnicode = new NameToCharCode(); + cidToUnicodes = new GHash(gTrue); + unicodeToUnicodes = new GHash(gTrue); + residentUnicodeMaps = new GHash(); + unicodeMaps = new GHash(gTrue); + cMapDirs = new GHash(gTrue); + toUnicodeDirs = new GList(); + displayFonts = new GHash(); + displayCIDFonts = new GHash(); + displayNamedCIDFonts = new GHash(); +#if HAVE_PAPER_H + char *paperName; + const struct paper *paperType; + paperinit(); + if ((paperName = systempapername())) { + paperType = paperinfo(paperName); + psPaperWidth = (int)paperpswidth(paperType); + psPaperHeight = (int)paperpsheight(paperType); + } else { + error(-1, "No paper information available - using defaults"); + psPaperWidth = defPaperWidth; + psPaperHeight = defPaperHeight; + } + paperdone(); +#else + psPaperWidth = defPaperWidth; + psPaperHeight = defPaperHeight; +#endif + psImageableLLX = psImageableLLY = 0; + psImageableURX = psPaperWidth; + psImageableURY = psPaperHeight; + psCrop = gTrue; + psExpandSmaller = gFalse; + psShrinkLarger = gTrue; + psCenter = gTrue; + psDuplex = gFalse; + psLevel = psLevel2; + psFile = NULL; + psFonts = new GHash(); + psNamedFonts16 = new GList(); + psFonts16 = new GList(); + psEmbedType1 = gTrue; + psEmbedTrueType = gTrue; + psEmbedCIDPostScript = gTrue; + psEmbedCIDTrueType = gTrue; + psPreload = gFalse; + psOPI = gFalse; + psASCIIHex = gFalse; + textEncoding = new GString("Latin1"); +#if defined(WIN32) + textEOL = eolDOS; +#elif defined(MACOS) + textEOL = eolMac; +#else + textEOL = eolUnix; +#endif + textPageBreaks = gTrue; + textKeepTinyChars = gFalse; + fontDirs = new GList(); + initialZoom = new GString("125"); + continuousView = gFalse; + enableT1lib = gTrue; + enableFreeType = gTrue; + antialias = gTrue; + vectorAntialias = gTrue; + strokeAdjust = gTrue; + screenType = screenUnset; + screenSize = -1; + screenDotRadius = -1; + screenGamma = 1.0; + screenBlackThreshold = 0.0; + screenWhiteThreshold = 1.0; + urlCommand = NULL; + movieCommand = NULL; + mapNumericCharNames = gTrue; + mapUnknownCharNames = gFalse; + createDefaultKeyBindings(); + printCommands = gFalse; + errQuiet = gFalse; + + cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize); + unicodeToUnicodeCache = + new CharCodeToUnicodeCache(unicodeToUnicodeCacheSize); + unicodeMapCache = new UnicodeMapCache(); + cMapCache = new CMapCache(); + +#ifdef WIN32 + winFontList = NULL; +#endif + +#ifdef ENABLE_PLUGINS + plugins = new GList(); + securityHandlers = new GList(); +#endif + + // set up the initial nameToUnicode table + for (i = 0; nameToUnicodeTab[i].name; ++i) { + nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u); + } + + // set up the residentUnicodeMaps table + map = new UnicodeMap("Latin1", gFalse, + latin1UnicodeMapRanges, latin1UnicodeMapLen); + residentUnicodeMaps->add(map->getEncodingName(), map); + map = new UnicodeMap("ASCII7", gFalse, + ascii7UnicodeMapRanges, ascii7UnicodeMapLen); + residentUnicodeMaps->add(map->getEncodingName(), map); + map = new UnicodeMap("Symbol", gFalse, + symbolUnicodeMapRanges, symbolUnicodeMapLen); + residentUnicodeMaps->add(map->getEncodingName(), map); + map = new UnicodeMap("ZapfDingbats", gFalse, zapfDingbatsUnicodeMapRanges, + zapfDingbatsUnicodeMapLen); + residentUnicodeMaps->add(map->getEncodingName(), map); + map = new UnicodeMap("UTF-8", gTrue, &mapUTF8); + residentUnicodeMaps->add(map->getEncodingName(), map); + map = new UnicodeMap("UCS-2", gTrue, &mapUCS2); + residentUnicodeMaps->add(map->getEncodingName(), map); + + // look for a user config file, then a system-wide config file + f = NULL; + fileName = NULL; + if (cfgFileName && cfgFileName[0]) { + fileName = new GString(cfgFileName); + if (!(f = fopen(fileName->getCString(), "r"))) { + delete fileName; + } + } + if (!f) { + fileName = appendToPath(getHomeDir(), xpdfUserConfigFile); + if (!(f = fopen(fileName->getCString(), "r"))) { + delete fileName; + } + } + if (!f) { +#if defined(WIN32) && !defined(__CYGWIN32__) + char buf[512]; + i = GetModuleFileName(NULL, buf, sizeof(buf)); + if (i <= 0 || i >= sizeof(buf)) { + // error or path too long for buffer - just use the current dir + buf[0] = '\0'; + } + fileName = grabPath(buf); + appendToPath(fileName, xpdfSysConfigFile); +#else + fileName = new GString(xpdfSysConfigFile); +#endif + if (!(f = fopen(fileName->getCString(), "r"))) { + delete fileName; + } + } + if (f) { + parseFile(fileName, f); + delete fileName; + fclose(f); + } +} + +void GlobalParams::createDefaultKeyBindings() { + keyBindings = new GList(); + + //----- mouse buttons + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress1, xpdfKeyModNone, + xpdfKeyContextAny, "startSelection")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease1, xpdfKeyModNone, + xpdfKeyContextAny, "endSelection", + "followLinkNoSel")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress2, xpdfKeyModNone, + xpdfKeyContextAny, "startPan")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease2, xpdfKeyModNone, + xpdfKeyContextAny, "endPan")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress3, xpdfKeyModNone, + xpdfKeyContextAny, "postPopupMenu")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress4, xpdfKeyModNone, + xpdfKeyContextAny, + "scrollUpPrevPage(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress5, xpdfKeyModNone, + xpdfKeyContextAny, + "scrollDownNextPage(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress6, xpdfKeyModNone, + xpdfKeyContextAny, "scrollLeft(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress7, xpdfKeyModNone, + xpdfKeyContextAny, "scrollRight(16)")); + + //----- keys + keyBindings->append(new KeyBinding(xpdfKeyCodeHome, xpdfKeyModCtrl, + xpdfKeyContextAny, "gotoPage(1)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeHome, xpdfKeyModNone, + xpdfKeyContextAny, "scrollToTopLeft")); + keyBindings->append(new KeyBinding(xpdfKeyCodeEnd, xpdfKeyModCtrl, + xpdfKeyContextAny, "gotoLastPage")); + keyBindings->append(new KeyBinding(xpdfKeyCodeEnd, xpdfKeyModNone, + xpdfKeyContextAny, + "scrollToBottomRight")); + keyBindings->append(new KeyBinding(xpdfKeyCodePgUp, xpdfKeyModNone, + xpdfKeyContextAny, "pageUp")); + keyBindings->append(new KeyBinding(xpdfKeyCodeBackspace, xpdfKeyModNone, + xpdfKeyContextAny, "pageUp")); + keyBindings->append(new KeyBinding(xpdfKeyCodeDelete, xpdfKeyModNone, + xpdfKeyContextAny, "pageUp")); + keyBindings->append(new KeyBinding(xpdfKeyCodePgDn, xpdfKeyModNone, + xpdfKeyContextAny, "pageDown")); + keyBindings->append(new KeyBinding(' ', xpdfKeyModNone, + xpdfKeyContextAny, "pageDown")); + keyBindings->append(new KeyBinding(xpdfKeyCodeLeft, xpdfKeyModNone, + xpdfKeyContextAny, "scrollLeft(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeRight, xpdfKeyModNone, + xpdfKeyContextAny, "scrollRight(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeUp, xpdfKeyModNone, + xpdfKeyContextAny, "scrollUp(16)")); + keyBindings->append(new KeyBinding(xpdfKeyCodeDown, xpdfKeyModNone, + xpdfKeyContextAny, "scrollDown(16)")); + keyBindings->append(new KeyBinding('o', xpdfKeyModNone, + xpdfKeyContextAny, "open")); + keyBindings->append(new KeyBinding('O', xpdfKeyModNone, + xpdfKeyContextAny, "open")); + keyBindings->append(new KeyBinding('r', xpdfKeyModNone, + xpdfKeyContextAny, "reload")); + keyBindings->append(new KeyBinding('R', xpdfKeyModNone, + xpdfKeyContextAny, "reload")); + keyBindings->append(new KeyBinding('f', xpdfKeyModNone, + xpdfKeyContextAny, "find")); + keyBindings->append(new KeyBinding('F', xpdfKeyModNone, + xpdfKeyContextAny, "find")); + keyBindings->append(new KeyBinding('f', xpdfKeyModCtrl, + xpdfKeyContextAny, "find")); + keyBindings->append(new KeyBinding('g', xpdfKeyModCtrl, + xpdfKeyContextAny, "findNext")); + keyBindings->append(new KeyBinding('p', xpdfKeyModCtrl, + xpdfKeyContextAny, "print")); + keyBindings->append(new KeyBinding('n', xpdfKeyModNone, + xpdfKeyContextScrLockOff, "nextPage")); + keyBindings->append(new KeyBinding('N', xpdfKeyModNone, + xpdfKeyContextScrLockOff, "nextPage")); + keyBindings->append(new KeyBinding('n', xpdfKeyModNone, + xpdfKeyContextScrLockOn, + "nextPageNoScroll")); + keyBindings->append(new KeyBinding('N', xpdfKeyModNone, + xpdfKeyContextScrLockOn, + "nextPageNoScroll")); + keyBindings->append(new KeyBinding('p', xpdfKeyModNone, + xpdfKeyContextScrLockOff, "prevPage")); + keyBindings->append(new KeyBinding('P', xpdfKeyModNone, + xpdfKeyContextScrLockOff, "prevPage")); + keyBindings->append(new KeyBinding('p', xpdfKeyModNone, + xpdfKeyContextScrLockOn, + "prevPageNoScroll")); + keyBindings->append(new KeyBinding('P', xpdfKeyModNone, + xpdfKeyContextScrLockOn, + "prevPageNoScroll")); + keyBindings->append(new KeyBinding('v', xpdfKeyModNone, + xpdfKeyContextAny, "goForward")); + keyBindings->append(new KeyBinding('b', xpdfKeyModNone, + xpdfKeyContextAny, "goBackward")); + keyBindings->append(new KeyBinding('g', xpdfKeyModNone, + xpdfKeyContextAny, "focusToPageNum")); + keyBindings->append(new KeyBinding('0', xpdfKeyModNone, + xpdfKeyContextAny, "zoomPercent(125)")); + keyBindings->append(new KeyBinding('+', xpdfKeyModNone, + xpdfKeyContextAny, "zoomIn")); + keyBindings->append(new KeyBinding('-', xpdfKeyModNone, + xpdfKeyContextAny, "zoomOut")); + keyBindings->append(new KeyBinding('z', xpdfKeyModNone, + xpdfKeyContextAny, "zoomFitPage")); + keyBindings->append(new KeyBinding('w', xpdfKeyModNone, + xpdfKeyContextAny, "zoomFitWidth")); + keyBindings->append(new KeyBinding('f', xpdfKeyModAlt, + xpdfKeyContextAny, + "toggleFullScreenMode")); + keyBindings->append(new KeyBinding('l', xpdfKeyModCtrl, + xpdfKeyContextAny, "redraw")); + keyBindings->append(new KeyBinding('w', xpdfKeyModCtrl, + xpdfKeyContextAny, "closeWindow")); + keyBindings->append(new KeyBinding('?', xpdfKeyModNone, + xpdfKeyContextAny, "about")); + keyBindings->append(new KeyBinding('q', xpdfKeyModNone, + xpdfKeyContextAny, "quit")); + keyBindings->append(new KeyBinding('Q', xpdfKeyModNone, + xpdfKeyContextAny, "quit")); +} + +void GlobalParams::parseFile(GString *fileName, FILE *f) { + int line; + char buf[512]; + + /* extract path */ + if(fileName) { + char* cfgFileName = fileName->getCString(); + char* pos1 = strrchr(cfgFileName, '/'); + char* pos2 = strrchr(cfgFileName, '\\'); + char* p = pos1>pos2?pos1:pos2; + int pos = p ? p-cfgFileName : -1; + GString*path = new GString(new GString(cfgFileName), 0, (pos < 0 ? strlen(cfgFileName): pos)); + if(pos1>=0) + path->append('/'); + else if(pos2>=0) + path->append('\\'); + else +#ifdef WIN32 + path->append('\\'); +#else + path->append('/'); +#endif + this->path = path; + } else { + this->path = new GString(); + } + + line = 1; + while (getLine(buf, sizeof(buf) - 1, f)) { + parseLine(buf, fileName, line); + ++line; + } +} + +void GlobalParams::parseLine(char *buf, GString *fileName, int line) { + GList *tokens; + GString *cmd, *incFile; + char *p1, *p2; + FILE *f2; + + // break the line into tokens + tokens = new GList(); + p1 = buf; + while (*p1) { + for (; *p1 && isspace(*p1); ++p1) ; + if (!*p1) { + break; + } + if (*p1 == '"' || *p1 == '\'') { + for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ; + ++p1; + } else { + for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ; + } + tokens->append(new GString(p1, p2 - p1)); + p1 = *p2 ? p2 + 1 : p2; + } + + // parse the line + if (tokens->getLength() > 0 && + ((GString *)tokens->get(0))->getChar(0) != '#') { + cmd = (GString *)tokens->get(0); + if (!cmd->cmp("include")) { + if (tokens->getLength() == 2) { + incFile = (GString *)tokens->get(1); + if ((f2 = fopen(incFile->getCString(), "r"))) { + parseFile(incFile, f2); + fclose(f2); + } else { + error(-1, "Couldn't find included config file: '%s' (%s:%d)", + incFile->getCString(), fileName->getCString(), line); + } + } else { + error(-1, "Bad 'include' config file command (%s:%d)", + fileName->getCString(), line); + } + } else if (!cmd->cmp("nameToUnicode")) { + parseNameToUnicode(tokens, fileName, line); + } else if (!cmd->cmp("cidToUnicode")) { + parseCIDToUnicode(tokens, fileName, line); + } else if (!cmd->cmp("unicodeToUnicode")) { + parseUnicodeToUnicode(tokens, fileName, line); + } else if (!cmd->cmp("unicodeMap")) { + parseUnicodeMap(tokens, fileName, line); + } else if (!cmd->cmp("cMapDir")) { + parseCMapDir(tokens, fileName, line); + } else if (!cmd->cmp("toUnicodeDir")) { + parseToUnicodeDir(tokens, fileName, line); + } else if (!cmd->cmp("displayFontT1")) { + parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line); + } else if (!cmd->cmp("displayFontTT")) { + parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line); + } else if (!cmd->cmp("displayNamedCIDFontT1")) { + parseDisplayFont(tokens, displayNamedCIDFonts, + displayFontT1, fileName, line); + } else if (!cmd->cmp("displayCIDFontT1")) { + parseDisplayFont(tokens, displayCIDFonts, + displayFontT1, fileName, line); + } else if (!cmd->cmp("displayNamedCIDFontTT")) { + parseDisplayFont(tokens, displayNamedCIDFonts, + displayFontTT, fileName, line); + } else if (!cmd->cmp("displayCIDFontTT")) { + parseDisplayFont(tokens, displayCIDFonts, + displayFontTT, fileName, line); + } else if (!cmd->cmp("psFile")) { + parsePSFile(tokens, fileName, line); + } else if (!cmd->cmp("psFont")) { + parsePSFont(tokens, fileName, line); + } else if (!cmd->cmp("psNamedFont16")) { + parsePSFont16("psNamedFont16", psNamedFonts16, + tokens, fileName, line); + } else if (!cmd->cmp("psFont16")) { + parsePSFont16("psFont16", psFonts16, tokens, fileName, line); + } else if (!cmd->cmp("psPaperSize")) { + parsePSPaperSize(tokens, fileName, line); + } else if (!cmd->cmp("psImageableArea")) { + parsePSImageableArea(tokens, fileName, line); + } else if (!cmd->cmp("psCrop")) { + parseYesNo("psCrop", &psCrop, tokens, fileName, line); + } else if (!cmd->cmp("psExpandSmaller")) { + parseYesNo("psExpandSmaller", &psExpandSmaller, + tokens, fileName, line); + } else if (!cmd->cmp("psShrinkLarger")) { + parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line); + } else if (!cmd->cmp("psCenter")) { + parseYesNo("psCenter", &psCenter, tokens, fileName, line); + } else if (!cmd->cmp("psDuplex")) { + parseYesNo("psDuplex", &psDuplex, tokens, fileName, line); + } else if (!cmd->cmp("psLevel")) { + parsePSLevel(tokens, fileName, line); + } else if (!cmd->cmp("psEmbedType1Fonts")) { + parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line); + } else if (!cmd->cmp("psEmbedTrueTypeFonts")) { + parseYesNo("psEmbedTrueType", &psEmbedTrueType, + tokens, fileName, line); + } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) { + parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript, + tokens, fileName, line); + } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) { + parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType, + tokens, fileName, line); + } else if (!cmd->cmp("psPreload")) { + parseYesNo("psPreload", &psPreload, tokens, fileName, line); + } else if (!cmd->cmp("psOPI")) { + parseYesNo("psOPI", &psOPI, tokens, fileName, line); + } else if (!cmd->cmp("psASCIIHex")) { + parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line); + } else if (!cmd->cmp("textEncoding")) { + parseTextEncoding(tokens, fileName, line); + } else if (!cmd->cmp("textEOL")) { + parseTextEOL(tokens, fileName, line); + } else if (!cmd->cmp("textPageBreaks")) { + parseYesNo("textPageBreaks", &textPageBreaks, + tokens, fileName, line); + } else if (!cmd->cmp("textKeepTinyChars")) { + parseYesNo("textKeepTinyChars", &textKeepTinyChars, + tokens, fileName, line); + } else if (!cmd->cmp("fontDir")) { + parseFontDir(tokens, fileName, line); + } else if (!cmd->cmp("initialZoom")) { + parseInitialZoom(tokens, fileName, line); + } else if (!cmd->cmp("continuousView")) { + parseYesNo("continuousView", &continuousView, tokens, fileName, line); + } else if (!cmd->cmp("enableT1lib")) { + parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line); + } else if (!cmd->cmp("enableFreeType")) { + parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line); + } else if (!cmd->cmp("antialias")) { + parseYesNo("antialias", &antialias, tokens, fileName, line); + } else if (!cmd->cmp("vectorAntialias")) { + parseYesNo("vectorAntialias", &vectorAntialias, + tokens, fileName, line); + } else if (!cmd->cmp("strokeAdjust")) { + parseYesNo("strokeAdjust", &strokeAdjust, tokens, fileName, line); + } else if (!cmd->cmp("screenType")) { + parseScreenType(tokens, fileName, line); + } else if (!cmd->cmp("screenSize")) { + parseInteger("screenSize", &screenSize, tokens, fileName, line); + } else if (!cmd->cmp("screenDotRadius")) { + parseInteger("screenDotRadius", &screenDotRadius, + tokens, fileName, line); + } else if (!cmd->cmp("screenGamma")) { + parseFloat("screenGamma", &screenGamma, + tokens, fileName, line); + } else if (!cmd->cmp("screenBlackThreshold")) { + parseFloat("screenBlackThreshold", &screenBlackThreshold, + tokens, fileName, line); + } else if (!cmd->cmp("screenWhiteThreshold")) { + parseFloat("screenWhiteThreshold", &screenWhiteThreshold, + tokens, fileName, line); + } else if (!cmd->cmp("urlCommand")) { + parseCommand("urlCommand", &urlCommand, tokens, fileName, line); + } else if (!cmd->cmp("movieCommand")) { + parseCommand("movieCommand", &movieCommand, tokens, fileName, line); + } else if (!cmd->cmp("mapNumericCharNames")) { + parseYesNo("mapNumericCharNames", &mapNumericCharNames, + tokens, fileName, line); + } else if (!cmd->cmp("mapUnknownCharNames")) { + parseYesNo("mapUnknownCharNames", &mapUnknownCharNames, + tokens, fileName, line); + } else if (!cmd->cmp("bind")) { + parseBind(tokens, fileName, line); + } else if (!cmd->cmp("unbind")) { + parseUnbind(tokens, fileName, line); + } else if (!cmd->cmp("printCommands")) { + parseYesNo("printCommands", &printCommands, tokens, fileName, line); + } else if (!cmd->cmp("errQuiet")) { + parseYesNo("errQuiet", &errQuiet, tokens, fileName, line); + } else { + error(-1, "Unknown config file command '%s' (%s:%d)", + cmd->getCString(), fileName->getCString(), line); + if (!cmd->cmp("displayFontX") || + !cmd->cmp("displayNamedCIDFontX") || + !cmd->cmp("displayCIDFontX")) { + error(-1, "-- Xpdf no longer supports X fonts"); + } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) { + error(-1, "-- The t1libControl and freetypeControl options have been replaced"); + error(-1, " by the enableT1lib, enableFreeType, and antialias options"); + } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) { + error(-1, "-- the config file format has changed since Xpdf 0.9x"); + } + } + } + + deleteGList(tokens, GString); +} + +static char is_absolute(char*filename) +{ + int l = strlen(filename); + if(filename[0] == '/' || filename[0] == '\\') + return 1; + if(l>2 && filename[1]==':' && (filename[2]=='\\' || filename[2]=='/')) + return 1; + return 0; +} + +static GString* qualify_filename(GString*path, GString*filename) +{ + GString*fullpath = 0; + char*prefix = "/usr/local/share/xpdf/"; + + if (!is_absolute(filename->getCString())) { + /* relative path */ + fullpath = path->copy(); + fullpath->append(filename); + } else if (!strncmp(filename->getCString(), prefix, strlen(prefix))) { + /* xpdf default path */ + char*s = strchr(filename->getCString()+strlen(prefix), '/'); + if(s) { + fullpath = path->copy(); + fullpath->append(s+1); + } else { + fullpath = filename->copy(); + } + } else { + /* absolute path */ + fullpath = filename->copy(); + } + //printf("%s -%s-> %s\n", filename->getCString(), path->getCString(), fullpath->getCString()); + return fullpath; +} + +void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName, + int line) { + GString *name; + char *tok1, *tok2; + FILE *f; + char buf[256]; + int line2; + Unicode u; + + if (tokens->getLength() != 2) { + error(-1, "Bad 'nameToUnicode' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + name = qualify_filename(this->path, (GString *)tokens->get(1)); + if (!(f = fopen(name->getCString(), "r"))) { + error(-1, "Couldn't open 'nameToUnicode' file '%s' using path '%s'", + name->getCString(), path->getCString()); + return; + } + line2 = 1; + while (getLine(buf, sizeof(buf), f)) { + tok1 = strtok(buf, " \t\r\n"); + tok2 = strtok(NULL, " \t\r\n"); + if (tok1 && tok2) { + sscanf(tok1, "%x", &u); + nameToUnicode->add(tok2, u); + } else { + error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2); + } + ++line2; + } + fclose(f); +} + +void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName, + int line) { + GString *collection, *name, *old; + + if (tokens->getLength() != 3) { + error(-1, "Bad 'cidToUnicode' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + collection = (GString *)tokens->get(1); + name = (GString *)tokens->get(2); + + if ((old = (GString *)cidToUnicodes->remove(collection))) { + delete old; + } + + cidToUnicodes->add(collection->copy(), qualify_filename(this->path, name)); +} + +void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName, + int line) { + GString *font, *file, *old; + + if (tokens->getLength() != 3) { + error(-1, "Bad 'unicodeToUnicode' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + font = (GString *)tokens->get(1); + file = (GString *)tokens->get(2); + if ((old = (GString *)unicodeToUnicodes->remove(font))) { + delete old; + } + + unicodeToUnicodes->add(font->copy(), qualify_filename(this->path, file)); +} + +void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName, + int line) { + GString *encodingName, *name, *old; + + if (tokens->getLength() != 3) { + error(-1, "Bad 'unicodeMap' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + encodingName = (GString *)tokens->get(1); + name = (GString *)tokens->get(2); + if ((old = (GString *)unicodeMaps->remove(encodingName))) { + delete old; + } + + unicodeMaps->add(encodingName->copy(), qualify_filename(this->path, name)); +} + +void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) { + GString *collection, *dir; + GList *list; + + if (tokens->getLength() != 3) { + error(-1, "Bad 'cMapDir' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + collection = (GString *)tokens->get(1); + dir = (GString *)tokens->get(2); + if (!(list = (GList *)cMapDirs->lookup(collection))) { + list = new GList(); + cMapDirs->add(collection->copy(), list); + } + + list->append(qualify_filename(this->path, dir)); +} + +void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName, + int line) { + GString *dir; + + if (tokens->getLength() != 2) { + error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + + dir = (GString *)tokens->get(1); + + toUnicodeDirs->append(qualify_filename(this->path, dir)); +} + +void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash, + DisplayFontParamKind kind, + GString *fileName, int line) { + DisplayFontParam *param, *old; + GString *file; + + if (tokens->getLength() < 2) { + goto err1; + } + param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind); + + switch (kind) { + case displayFontT1: + if (tokens->getLength() != 3) { + goto err2; + } + file = (GString *)tokens->get(2); + param->t1.fileName = qualify_filename(this->path, file); + break; + case displayFontTT: + if (tokens->getLength() != 3) { + goto err2; + } + file = (GString *)tokens->get(2); + param->tt.fileName = qualify_filename(this->path, file); + break; + } + + if ((old = (DisplayFontParam *)fontHash->remove(param->name))) { + delete old; + } + fontHash->add(param->name, param); + return; + + err2: + delete param; + err1: + error(-1, "Bad 'display*Font*' config file command (%s:%d)", + fileName->getCString(), line); +} + +void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName, + int line) { + GString *tok; + + if (tokens->getLength() == 2) { + tok = (GString *)tokens->get(1); + if (!setPSPaperSize(tok->getCString())) { + error(-1, "Bad 'psPaperSize' config file command (%s:%d)", + fileName->getCString(), line); + } + } else if (tokens->getLength() == 3) { + tok = (GString *)tokens->get(1); + psPaperWidth = atoi(tok->getCString()); + tok = (GString *)tokens->get(2); + psPaperHeight = atoi(tok->getCString()); + psImageableLLX = psImageableLLY = 0; + psImageableURX = psPaperWidth; + psImageableURY = psPaperHeight; + } else { + error(-1, "Bad 'psPaperSize' config file command (%s:%d)", + fileName->getCString(), line); + } +} + +void GlobalParams::parsePSImageableArea(GList *tokens, GString *fileName, + int line) { + if (tokens->getLength() != 5) { + error(-1, "Bad 'psImageableArea' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + psImageableLLX = atoi(((GString *)tokens->get(1))->getCString()); + psImageableLLY = atoi(((GString *)tokens->get(2))->getCString()); + psImageableURX = atoi(((GString *)tokens->get(3))->getCString()); + psImageableURY = atoi(((GString *)tokens->get(4))->getCString()); +} + +void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) { + GString *tok; + + if (tokens->getLength() != 2) { + error(-1, "Bad 'psLevel' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + tok = (GString *)tokens->get(1); + if (!tok->cmp("level1")) { + psLevel = psLevel1; + } else if (!tok->cmp("level1sep")) { + psLevel = psLevel1Sep; + } else if (!tok->cmp("level2")) { + psLevel = psLevel2; + } else if (!tok->cmp("level2sep")) { + psLevel = psLevel2Sep; + } else if (!tok->cmp("level3")) { + psLevel = psLevel3; + } else if (!tok->cmp("level3Sep")) { + psLevel = psLevel3Sep; + } else { + error(-1, "Bad 'psLevel' config file command (%s:%d)", + fileName->getCString(), line); + } +} + +void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) { + if (tokens->getLength() != 2) { + error(-1, "Bad 'psFile' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + if (psFile) { + delete psFile; + } + psFile = ((GString *)tokens->get(1))->copy(); +} + +void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) { + PSFontParam *param; + + if (tokens->getLength() != 3) { + error(-1, "Bad 'psFont' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0, + ((GString *)tokens->get(2))->copy(), NULL); + psFonts->add(param->pdfFontName, param); +} + +void GlobalParams::parsePSFont16(char *cmdName, GList *fontList, + GList *tokens, GString *fileName, int line) { + PSFontParam *param; + int wMode; + GString *tok; + + if (tokens->getLength() != 5) { + error(-1, "Bad '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return; + } + tok = (GString *)tokens->get(2); + if (!tok->cmp("H")) { + wMode = 0; + } else if (!tok->cmp("V")) { + wMode = 1; + } else { + error(-1, "Bad '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return; + } + param = new PSFontParam(((GString *)tokens->get(1))->copy(), + wMode, + ((GString *)tokens->get(3))->copy(), + ((GString *)tokens->get(4))->copy()); + fontList->append(param); +} + +void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName, + int line) { + if (tokens->getLength() != 2) { + error(-1, "Bad 'textEncoding' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + delete textEncoding; + textEncoding = ((GString *)tokens->get(1))->copy(); +} + +void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) { + GString *tok; + + if (tokens->getLength() != 2) { + error(-1, "Bad 'textEOL' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + tok = (GString *)tokens->get(1); + if (!tok->cmp("unix")) { + textEOL = eolUnix; + } else if (!tok->cmp("dos")) { + textEOL = eolDOS; + } else if (!tok->cmp("mac")) { + textEOL = eolMac; + } else { + error(-1, "Bad 'textEOL' config file command (%s:%d)", + fileName->getCString(), line); + } +} + +void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) { + if (tokens->getLength() != 2) { + error(-1, "Bad 'fontDir' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + fontDirs->append(((GString *)tokens->get(1))->copy()); +} + +void GlobalParams::parseInitialZoom(GList *tokens, + GString *fileName, int line) { + if (tokens->getLength() != 2) { + error(-1, "Bad 'initialZoom' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + delete initialZoom; + initialZoom = ((GString *)tokens->get(1))->copy(); +} + +void GlobalParams::parseScreenType(GList *tokens, GString *fileName, + int line) { + GString *tok; + + if (tokens->getLength() != 2) { + error(-1, "Bad 'screenType' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + tok = (GString *)tokens->get(1); + if (!tok->cmp("dispersed")) { + screenType = screenDispersed; + } else if (!tok->cmp("clustered")) { + screenType = screenClustered; + } else if (!tok->cmp("stochasticClustered")) { + screenType = screenStochasticClustered; + } else { + error(-1, "Bad 'screenType' config file command (%s:%d)", + fileName->getCString(), line); + } +} + +void GlobalParams::parseBind(GList *tokens, GString *fileName, int line) { + KeyBinding *binding; + GList *cmds; + int code, mods, context, i; + + if (tokens->getLength() < 4) { + error(-1, "Bad 'bind' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + if (!parseKey((GString *)tokens->get(1), (GString *)tokens->get(2), + &code, &mods, &context, + "bind", tokens, fileName, line)) { + return; + } + for (i = 0; i < keyBindings->getLength(); ++i) { + binding = (KeyBinding *)keyBindings->get(i); + if (binding->code == code && + binding->mods == mods && + binding->context == context) { + delete (KeyBinding *)keyBindings->del(i); + break; + } + } + cmds = new GList(); + for (i = 3; i < tokens->getLength(); ++i) { + cmds->append(((GString *)tokens->get(i))->copy()); + } + keyBindings->append(new KeyBinding(code, mods, context, cmds)); +} + +void GlobalParams::parseUnbind(GList *tokens, GString *fileName, int line) { + KeyBinding *binding; + int code, mods, context, i; + + if (tokens->getLength() != 3) { + error(-1, "Bad 'unbind' config file command (%s:%d)", + fileName->getCString(), line); + return; + } + if (!parseKey((GString *)tokens->get(1), (GString *)tokens->get(2), + &code, &mods, &context, + "unbind", tokens, fileName, line)) { + return; + } + for (i = 0; i < keyBindings->getLength(); ++i) { + binding = (KeyBinding *)keyBindings->get(i); + if (binding->code == code && + binding->mods == mods && + binding->context == context) { + delete (KeyBinding *)keyBindings->del(i); + break; + } + } +} + +GBool GlobalParams::parseKey(GString *modKeyStr, GString *contextStr, + int *code, int *mods, int *context, + char *cmdName, + GList *tokens, GString *fileName, int line) { + char *p0; + + *mods = xpdfKeyModNone; + p0 = modKeyStr->getCString(); + while (1) { + if (!strncmp(p0, "shift-", 6)) { + *mods |= xpdfKeyModShift; + p0 += 6; + } else if (!strncmp(p0, "ctrl-", 5)) { + *mods |= xpdfKeyModCtrl; + p0 += 5; + } else if (!strncmp(p0, "alt-", 4)) { + *mods |= xpdfKeyModAlt; + p0 += 4; + } else { + break; + } + } + + if (!strcmp(p0, "space")) { + *code = ' '; + } else if (!strcmp(p0, "tab")) { + *code = xpdfKeyCodeTab; + } else if (!strcmp(p0, "return")) { + *code = xpdfKeyCodeReturn; + } else if (!strcmp(p0, "enter")) { + *code = xpdfKeyCodeEnter; + } else if (!strcmp(p0, "backspace")) { + *code = xpdfKeyCodeBackspace; + } else if (!strcmp(p0, "insert")) { + *code = xpdfKeyCodeInsert; + } else if (!strcmp(p0, "delete")) { + *code = xpdfKeyCodeDelete; + } else if (!strcmp(p0, "home")) { + *code = xpdfKeyCodeHome; + } else if (!strcmp(p0, "end")) { + *code = xpdfKeyCodeEnd; + } else if (!strcmp(p0, "pgup")) { + *code = xpdfKeyCodePgUp; + } else if (!strcmp(p0, "pgdn")) { + *code = xpdfKeyCodePgDn; + } else if (!strcmp(p0, "left")) { + *code = xpdfKeyCodeLeft; + } else if (!strcmp(p0, "right")) { + *code = xpdfKeyCodeRight; + } else if (!strcmp(p0, "up")) { + *code = xpdfKeyCodeUp; + } else if (!strcmp(p0, "down")) { + *code = xpdfKeyCodeDown; + } else if (p0[0] == 'f' && p0[1] >= '1' && p0[1] <= '9' && !p0[2]) { + *code = xpdfKeyCodeF1 + (p0[1] - '1'); + } else if (p0[0] == 'f' && + ((p0[1] >= '1' && p0[1] <= '2' && p0[2] >= '0' && p0[2] <= '9') || + (p0[1] == '3' && p0[2] >= '0' && p0[2] <= '5')) && + !p0[3]) { + *code = xpdfKeyCodeF1 + 10 * (p0[1] - '0') + (p0[2] - '0') - 1; + } else if (!strncmp(p0, "mousePress", 10) && + p0[10] >= '1' && p0[10] <= '7' && !p0[11]) { + *code = xpdfKeyCodeMousePress1 + (p0[10] - '1'); + } else if (!strncmp(p0, "mouseRelease", 12) && + p0[12] >= '1' && p0[12] <= '7' && !p0[13]) { + *code = xpdfKeyCodeMouseRelease1 + (p0[12] - '1'); + } else if (*p0 >= 0x20 && *p0 <= 0x7e && !p0[1]) { + *code = (int)*p0; + } else { + error(-1, "Bad key/modifier in '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return gFalse; + } + + p0 = contextStr->getCString(); + if (!strcmp(p0, "any")) { + *context = xpdfKeyContextAny; + } else { + *context = xpdfKeyContextAny; + while (1) { + if (!strncmp(p0, "fullScreen", 10)) { + *context |= xpdfKeyContextFullScreen; + p0 += 10; + } else if (!strncmp(p0, "window", 6)) { + *context |= xpdfKeyContextWindow; + p0 += 6; + } else if (!strncmp(p0, "continuous", 10)) { + *context |= xpdfKeyContextContinuous; + p0 += 10; + } else if (!strncmp(p0, "singlePage", 10)) { + *context |= xpdfKeyContextSinglePage; + p0 += 10; + } else if (!strncmp(p0, "overLink", 8)) { + *context |= xpdfKeyContextOverLink; + p0 += 8; + } else if (!strncmp(p0, "offLink", 7)) { + *context |= xpdfKeyContextOffLink; + p0 += 7; + } else if (!strncmp(p0, "outline", 7)) { + *context |= xpdfKeyContextOutline; + p0 += 7; + } else if (!strncmp(p0, "mainWin", 7)) { + *context |= xpdfKeyContextMainWin; + p0 += 7; + } else if (!strncmp(p0, "scrLockOn", 9)) { + *context |= xpdfKeyContextScrLockOn; + p0 += 9; + } else if (!strncmp(p0, "scrLockOff", 10)) { + *context |= xpdfKeyContextScrLockOff; + p0 += 10; + } else { + error(-1, "Bad context in '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return gFalse; + } + if (!*p0) { + break; + } + if (*p0 != ',') { + error(-1, "Bad context in '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return gFalse; + } + ++p0; + } + } + + return gTrue; +} + +void GlobalParams::parseCommand(char *cmdName, GString **val, + GList *tokens, GString *fileName, int line) { + if (tokens->getLength() != 2) { + error(-1, "Bad '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return; + } + if (*val) { + delete *val; + } + *val = ((GString *)tokens->get(1))->copy(); +} + +void GlobalParams::parseYesNo(char *cmdName, GBool *flag, + GList *tokens, GString *fileName, int line) { + GString *tok; + + if (tokens->getLength() != 2) { + error(-1, "Bad '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return; + } + tok = (GString *)tokens->get(1); + if (!parseYesNo2(tok->getCString(), flag)) { + error(-1, "Bad '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + } +} + +GBool GlobalParams::parseYesNo2(char *token, GBool *flag) { + if (!strcmp(token, "yes")) { + *flag = gTrue; + } else if (!strcmp(token, "no")) { + *flag = gFalse; + } else { + return gFalse; + } + return gTrue; +} + +void GlobalParams::parseInteger(char *cmdName, int *val, + GList *tokens, GString *fileName, int line) { + GString *tok; + int i; + + if (tokens->getLength() != 2) { + error(-1, "Bad '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return; + } + tok = (GString *)tokens->get(1); + if (tok->getLength() == 0) { + error(-1, "Bad '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return; + } + if (tok->getChar(0) == '-') { + i = 1; + } else { + i = 0; + } + for (; i < tok->getLength(); ++i) { + if (tok->getChar(i) < '0' || tok->getChar(i) > '9') { + error(-1, "Bad '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return; + } + } + *val = atoi(tok->getCString()); +} + +void GlobalParams::parseFloat(char *cmdName, double *val, + GList *tokens, GString *fileName, int line) { + GString *tok; + int i; + + if (tokens->getLength() != 2) { + error(-1, "Bad '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return; + } + tok = (GString *)tokens->get(1); + if (tok->getLength() == 0) { + error(-1, "Bad '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return; + } + if (tok->getChar(0) == '-') { + i = 1; + } else { + i = 0; + } + for (; i < tok->getLength(); ++i) { + if (!((tok->getChar(i) >= '0' && tok->getChar(i) <= '9') || + tok->getChar(i) == '.')) { + error(-1, "Bad '%s' config file command (%s:%d)", + cmdName, fileName->getCString(), line); + return; + } + } + *val = atof(tok->getCString()); +} + +GlobalParams::~GlobalParams() { + GHashIter *iter; + GString *key; + GList *list; + + freeBuiltinFontTables(); + + delete macRomanReverseMap; + + delete baseDir; + delete nameToUnicode; + deleteGHash(cidToUnicodes, GString); + deleteGHash(unicodeToUnicodes, GString); + deleteGHash(residentUnicodeMaps, UnicodeMap); + deleteGHash(unicodeMaps, GString); + deleteGList(toUnicodeDirs, GString); + deleteGHash(displayFonts, DisplayFontParam); + deleteGHash(displayCIDFonts, DisplayFontParam); + deleteGHash(displayNamedCIDFonts, DisplayFontParam); +#ifdef WIN32 + if (winFontList) { + delete winFontList; + } +#endif + if (psFile) { + delete psFile; + } + deleteGHash(psFonts, PSFontParam); + deleteGList(psNamedFonts16, PSFontParam); + deleteGList(psFonts16, PSFontParam); + delete textEncoding; + deleteGList(fontDirs, GString); + delete initialZoom; + if (urlCommand) { + delete urlCommand; + } + if (movieCommand) { + delete movieCommand; + } + deleteGList(keyBindings, KeyBinding); + + cMapDirs->startIter(&iter); + while (cMapDirs->getNext(&iter, &key, (void **)&list)) { + deleteGList(list, GString); + } + delete cMapDirs; + + delete cidToUnicodeCache; + delete unicodeToUnicodeCache; + delete unicodeMapCache; + delete cMapCache; + +#ifdef ENABLE_PLUGINS + delete securityHandlers; + deleteGList(plugins, Plugin); +#endif + +#if MULTITHREADED + gDestroyMutex(&mutex); + gDestroyMutex(&unicodeMapCacheMutex); + gDestroyMutex(&cMapCacheMutex); +#endif +} + +//------------------------------------------------------------------------ + +void GlobalParams::setBaseDir(char *dir) { + delete baseDir; + baseDir = new GString(dir); +} + +void GlobalParams::setupBaseFonts(char *dir) { + GString *fontName; + GString *fileName; +#ifdef WIN32 + HMODULE shell32Lib; + BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner, + LPTSTR lpszPath, + int nFolder, + BOOL fCreate); + char winFontDir[MAX_PATH]; +#endif + FILE *f; + DisplayFontParamKind kind; + DisplayFontParam *dfp; + int i, j; + +#ifdef WIN32 + // SHGetSpecialFolderPath isn't available in older versions of + // shell32.dll (Win95 and WinNT4), so do a dynamic load + winFontDir[0] = '\0'; + if ((shell32Lib = LoadLibrary("shell32.dll"))) { + if ((SHGetSpecialFolderPathFunc = + (BOOL (__stdcall *)(HWND hwndOwner, LPTSTR lpszPath, + int nFolder, BOOL fCreate)) + GetProcAddress(shell32Lib, "SHGetSpecialFolderPathA"))) { + if (!(*SHGetSpecialFolderPathFunc)(NULL, winFontDir, + CSIDL_FONTS, FALSE)) { + winFontDir[0] = '\0'; + } + } + } +#endif + for (i = 0; displayFontTab[i].name; ++i) { + fontName = new GString(displayFontTab[i].name); + if (getDisplayFont(fontName)) { + delete fontName; + continue; + } + fileName = NULL; + kind = displayFontT1; // make gcc happy + if (dir) { + fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName); + kind = displayFontT1; + if ((f = fopen(fileName->getCString(), "rb"))) { + fclose(f); + } else { + delete fileName; + fileName = NULL; + } + } +#ifdef WIN32 + if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) { + fileName = appendToPath(new GString(winFontDir), + displayFontTab[i].ttFileName); + kind = displayFontTT; + if ((f = fopen(fileName->getCString(), "rb"))) { + fclose(f); + } else { + delete fileName; + fileName = NULL; + } + } + // SHGetSpecialFolderPath(CSIDL_FONTS) doesn't work on Win 2k Server + // or Win2003 Server, or with older versions of shell32.dll, so check + // the "standard" directories + if (displayFontTab[i].ttFileName) { + for (j = 0; !fileName && displayFontDirs[j]; ++j) { + fileName = appendToPath(new GString(displayFontDirs[j]), + displayFontTab[i].ttFileName); + kind = displayFontTT; + if ((f = fopen(fileName->getCString(), "rb"))) { + fclose(f); + } else { + delete fileName; + fileName = NULL; + } + } + } +#else + for (j = 0; !fileName && displayFontDirs[j]; ++j) { + fileName = appendToPath(new GString(displayFontDirs[j]), + displayFontTab[i].t1FileName); + kind = displayFontT1; + if ((f = fopen(fileName->getCString(), "rb"))) { + fclose(f); + } else { + delete fileName; + fileName = NULL; + } + } +#endif + if (!fileName) { + error(-1, "No display font for '%s'", displayFontTab[i].name); + delete fontName; + continue; + } + dfp = new DisplayFontParam(fontName, kind); + dfp->t1.fileName = fileName; + globalParams->addDisplayFont(dfp); + } + +#ifdef WIN32 + if (winFontDir[0]) { + winFontList = new WinFontList(winFontDir); + } +#endif +} + +//------------------------------------------------------------------------ +// accessors +//------------------------------------------------------------------------ + +CharCode GlobalParams::getMacRomanCharCode(char *charName) { + // no need to lock - macRomanReverseMap is constant + return macRomanReverseMap->lookup(charName); +} + +GString *GlobalParams::getBaseDir() { + GString *s; + + lockGlobalParams; + s = baseDir->copy(); + unlockGlobalParams; + return s; +} + +Unicode GlobalParams::mapNameToUnicode(char *charName) { + // no need to lock - nameToUnicode is constant + return nameToUnicode->lookup(charName); +} + +UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) { + UnicodeMap *map; + + lockGlobalParams; + map = (UnicodeMap *)residentUnicodeMaps->lookup(encodingName); + unlockGlobalParams; + if (map) { + map->incRefCnt(); + } + return map; +} + +FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) { + GString *fileName; + FILE *f; + + lockGlobalParams; + if ((fileName = (GString *)unicodeMaps->lookup(encodingName))) { + f = fopen(fileName->getCString(), "r"); + } else { + f = NULL; + } + unlockGlobalParams; + return f; +} + +FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) { + GList *list; + GString *dir; + GString *fileName; + FILE *f; + int i; + + lockGlobalParams; + if (!(list = (GList *)cMapDirs->lookup(collection))) { + unlockGlobalParams; + return NULL; + } + for (i = 0; i < list->getLength(); ++i) { + dir = (GString *)list->get(i); + fileName = appendToPath(dir->copy(), cMapName->getCString()); + f = fopen(fileName->getCString(), "r"); + delete fileName; + if (f) { + unlockGlobalParams; + return f; + } + } + unlockGlobalParams; + return NULL; +} + +FILE *GlobalParams::findToUnicodeFile(GString *name) { + GString *dir, *fileName; + FILE *f; + int i; + + lockGlobalParams; + for (i = 0; i < toUnicodeDirs->getLength(); ++i) { + dir = (GString *)toUnicodeDirs->get(i); + fileName = appendToPath(dir->copy(), name->getCString()); + f = fopen(fileName->getCString(), "r"); + delete fileName; + if (f) { + unlockGlobalParams; + return f; + } + } + unlockGlobalParams; + return NULL; +} + +DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) { + DisplayFontParam *dfp; + + lockGlobalParams; + dfp = (DisplayFontParam *)displayFonts->lookup(fontName); +#ifdef WIN32 + if (!dfp && winFontList) { + dfp = winFontList->find(fontName); + } +#endif + unlockGlobalParams; + return dfp; +} + +DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName, + GString *collection) { + DisplayFontParam *dfp; + + lockGlobalParams; + if (!fontName || + !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) { + dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection); + } + unlockGlobalParams; + return dfp; +} + +GString *GlobalParams::getPSFile() { + GString *s; + + lockGlobalParams; + s = psFile ? psFile->copy() : (GString *)NULL; + unlockGlobalParams; + return s; +} + +int GlobalParams::getPSPaperWidth() { + int w; + + lockGlobalParams; + w = psPaperWidth; + unlockGlobalParams; + return w; +} + +int GlobalParams::getPSPaperHeight() { + int h; + + lockGlobalParams; + h = psPaperHeight; + unlockGlobalParams; + return h; +} + +void GlobalParams::getPSImageableArea(int *llx, int *lly, int *urx, int *ury) { + lockGlobalParams; + *llx = psImageableLLX; + *lly = psImageableLLY; + *urx = psImageableURX; + *ury = psImageableURY; + unlockGlobalParams; +} + +GBool GlobalParams::getPSCrop() { + GBool f; + + lockGlobalParams; + f = psCrop; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getPSExpandSmaller() { + GBool f; + + lockGlobalParams; + f = psExpandSmaller; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getPSShrinkLarger() { + GBool f; + + lockGlobalParams; + f = psShrinkLarger; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getPSCenter() { + GBool f; + + lockGlobalParams; + f = psCenter; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getPSDuplex() { + GBool d; + + lockGlobalParams; + d = psDuplex; + unlockGlobalParams; + return d; +} + +PSLevel GlobalParams::getPSLevel() { + PSLevel level; + + lockGlobalParams; + level = psLevel; + unlockGlobalParams; + return level; +} + +PSFontParam *GlobalParams::getPSFont(GString *fontName) { + PSFontParam *p; + + lockGlobalParams; + p = (PSFontParam *)psFonts->lookup(fontName); + unlockGlobalParams; + return p; +} + +PSFontParam *GlobalParams::getPSFont16(GString *fontName, + GString *collection, int wMode) { + PSFontParam *p; + int i; + + lockGlobalParams; + p = NULL; + if (fontName) { + for (i = 0; i < psNamedFonts16->getLength(); ++i) { + p = (PSFontParam *)psNamedFonts16->get(i); + if (!p->pdfFontName->cmp(fontName) && + p->wMode == wMode) { + break; + } + p = NULL; + } + } + if (!p && collection) { + for (i = 0; i < psFonts16->getLength(); ++i) { + p = (PSFontParam *)psFonts16->get(i); + if (!p->pdfFontName->cmp(collection) && + p->wMode == wMode) { + break; + } + p = NULL; + } + } + unlockGlobalParams; + return p; +} + +GBool GlobalParams::getPSEmbedType1() { + GBool e; + + lockGlobalParams; + e = psEmbedType1; + unlockGlobalParams; + return e; +} + +GBool GlobalParams::getPSEmbedTrueType() { + GBool e; + + lockGlobalParams; + e = psEmbedTrueType; + unlockGlobalParams; + return e; +} + +GBool GlobalParams::getPSEmbedCIDPostScript() { + GBool e; + + lockGlobalParams; + e = psEmbedCIDPostScript; + unlockGlobalParams; + return e; +} + +GBool GlobalParams::getPSEmbedCIDTrueType() { + GBool e; + + lockGlobalParams; + e = psEmbedCIDTrueType; + unlockGlobalParams; + return e; +} + +GBool GlobalParams::getPSPreload() { + GBool preload; + + lockGlobalParams; + preload = psPreload; + unlockGlobalParams; + return preload; +} + +GBool GlobalParams::getPSOPI() { + GBool opi; + + lockGlobalParams; + opi = psOPI; + unlockGlobalParams; + return opi; +} + +GBool GlobalParams::getPSASCIIHex() { + GBool ah; + + lockGlobalParams; + ah = psASCIIHex; + unlockGlobalParams; + return ah; +} + +GString *GlobalParams::getTextEncodingName() { + GString *s; + + lockGlobalParams; + s = textEncoding->copy(); + unlockGlobalParams; + return s; +} + +EndOfLineKind GlobalParams::getTextEOL() { + EndOfLineKind eol; + + lockGlobalParams; + eol = textEOL; + unlockGlobalParams; + return eol; +} + +GBool GlobalParams::getTextPageBreaks() { + GBool pageBreaks; + + lockGlobalParams; + pageBreaks = textPageBreaks; + unlockGlobalParams; + return pageBreaks; +} + +GBool GlobalParams::getTextKeepTinyChars() { + GBool tiny; + + lockGlobalParams; + tiny = textKeepTinyChars; + unlockGlobalParams; + return tiny; +} + +GString *GlobalParams::findFontFile(GString *fontName, char **exts) { + GString *dir, *fileName; + char **ext; + FILE *f; + int i; + + lockGlobalParams; + for (i = 0; i < fontDirs->getLength(); ++i) { + dir = (GString *)fontDirs->get(i); + for (ext = exts; *ext; ++ext) { + fileName = appendToPath(dir->copy(), fontName->getCString()); + fileName->append(*ext); + if ((f = fopen(fileName->getCString(), "rb"))) { + fclose(f); + unlockGlobalParams; + return fileName; + } + delete fileName; + } + } + unlockGlobalParams; + return NULL; +} + +GString *GlobalParams::getInitialZoom() { + GString *s; + + lockGlobalParams; + s = initialZoom->copy(); + unlockGlobalParams; + return s; +} + +GBool GlobalParams::getContinuousView() { + GBool f; + + lockGlobalParams; + f = continuousView; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getEnableT1lib() { + GBool f; + + lockGlobalParams; + f = enableT1lib; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getEnableFreeType() { + GBool f; + + lockGlobalParams; + f = enableFreeType; + unlockGlobalParams; + return f; +} + + +GBool GlobalParams::getAntialias() { + GBool f; + + lockGlobalParams; + f = antialias; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getVectorAntialias() { + GBool f; + + lockGlobalParams; + f = vectorAntialias; + unlockGlobalParams; + return f; +} + +GBool GlobalParams::getStrokeAdjust() { + GBool f; + + lockGlobalParams; + f = strokeAdjust; + unlockGlobalParams; + return f; +} + +ScreenType GlobalParams::getScreenType() { + ScreenType t; + + lockGlobalParams; + t = screenType; + unlockGlobalParams; + return t; +} + +int GlobalParams::getScreenSize() { + int size; + + lockGlobalParams; + size = screenSize; + unlockGlobalParams; + return size; +} + +int GlobalParams::getScreenDotRadius() { + int r; + + lockGlobalParams; + r = screenDotRadius; + unlockGlobalParams; + return r; +} + +double GlobalParams::getScreenGamma() { + double gamma; + + lockGlobalParams; + gamma = screenGamma; + unlockGlobalParams; + return gamma; +} + +double GlobalParams::getScreenBlackThreshold() { + double thresh; + + lockGlobalParams; + thresh = screenBlackThreshold; + unlockGlobalParams; + return thresh; +} + +double GlobalParams::getScreenWhiteThreshold() { + double thresh; + + lockGlobalParams; + thresh = screenWhiteThreshold; + unlockGlobalParams; + return thresh; +} + +GBool GlobalParams::getMapNumericCharNames() { + GBool map; + + lockGlobalParams; + map = mapNumericCharNames; + unlockGlobalParams; + return map; +} + +GBool GlobalParams::getMapUnknownCharNames() { + GBool map; + + lockGlobalParams; + map = mapUnknownCharNames; + unlockGlobalParams; + return map; +} + +GList *GlobalParams::getKeyBinding(int code, int mods, int context) { + KeyBinding *binding; + GList *cmds; + int modMask; + int i, j; + + lockGlobalParams; + cmds = NULL; + // for ASCII chars, ignore the shift modifier + modMask = code <= 0xff ? ~xpdfKeyModShift : ~0; + for (i = 0; i < keyBindings->getLength(); ++i) { + binding = (KeyBinding *)keyBindings->get(i); + if (binding->code == code && + (binding->mods & modMask) == (mods & modMask) && + (~binding->context | context) == ~0) { + cmds = new GList(); + for (j = 0; j < binding->cmds->getLength(); ++j) { + cmds->append(((GString *)binding->cmds->get(j))->copy()); + } + break; + } + } + unlockGlobalParams; + return cmds; +} + +GBool GlobalParams::getPrintCommands() { + GBool p; + + lockGlobalParams; + p = printCommands; + unlockGlobalParams; + return p; +} + +GBool GlobalParams::getErrQuiet() { + // no locking -- this function may get called from inside a locked + // section + return errQuiet; +} + +CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) { + GString *fileName; + CharCodeToUnicode *ctu; + + lockGlobalParams; + if (!(ctu = cidToUnicodeCache->getCharCodeToUnicode(collection))) { + if ((fileName = (GString *)cidToUnicodes->lookup(collection)) && + (ctu = CharCodeToUnicode::parseCIDToUnicode(fileName, collection))) { + cidToUnicodeCache->add(ctu); + } + } + unlockGlobalParams; + return ctu; +} + +CharCodeToUnicode *GlobalParams::getUnicodeToUnicode(GString *fontName) { + CharCodeToUnicode *ctu; + GHashIter *iter; + GString *fontPattern, *fileName; + + lockGlobalParams; + fileName = NULL; + unicodeToUnicodes->startIter(&iter); + while (unicodeToUnicodes->getNext(&iter, &fontPattern, (void **)&fileName)) { + if (strstr(fontName->getCString(), fontPattern->getCString())) { + unicodeToUnicodes->killIter(&iter); + break; + } + fileName = NULL; + } + if (fileName) { + if (!(ctu = unicodeToUnicodeCache->getCharCodeToUnicode(fileName))) { + if ((ctu = CharCodeToUnicode::parseUnicodeToUnicode(fileName))) { + unicodeToUnicodeCache->add(ctu); + } + } + } else { + ctu = NULL; + } + unlockGlobalParams; + return ctu; +} + +UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) { + return getUnicodeMap2(encodingName); +} + +UnicodeMap *GlobalParams::getUnicodeMap2(GString *encodingName) { + UnicodeMap *map; + + if (!(map = getResidentUnicodeMap(encodingName))) { + lockUnicodeMapCache; + map = unicodeMapCache->getUnicodeMap(encodingName); + unlockUnicodeMapCache; + } + return map; +} + +CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) { + CMap *cMap; + + lockCMapCache; + cMap = cMapCache->getCMap(collection, cMapName); + unlockCMapCache; + return cMap; +} + +UnicodeMap *GlobalParams::getTextEncoding() { + return getUnicodeMap2(textEncoding); +} + +//------------------------------------------------------------------------ +// functions to set parameters +//------------------------------------------------------------------------ + +void GlobalParams::addDisplayFont(DisplayFontParam *param) { + DisplayFontParam *old; + + lockGlobalParams; + if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) { + delete old; + } + displayFonts->add(param->name, param); + unlockGlobalParams; +} + +void GlobalParams::setPSFile(char *file) { + lockGlobalParams; + if (psFile) { + delete psFile; + } + psFile = new GString(file); + unlockGlobalParams; +} + +GBool GlobalParams::setPSPaperSize(char *size) { + lockGlobalParams; + if (!strcmp(size, "match")) { + psPaperWidth = psPaperHeight = -1; + } else if (!strcmp(size, "letter")) { + psPaperWidth = 612; + psPaperHeight = 792; + } else if (!strcmp(size, "legal")) { + psPaperWidth = 612; + psPaperHeight = 1008; + } else if (!strcmp(size, "A4")) { + psPaperWidth = 595; + psPaperHeight = 842; + } else if (!strcmp(size, "A3")) { + psPaperWidth = 842; + psPaperHeight = 1190; + } else { + unlockGlobalParams; + return gFalse; + } + psImageableLLX = psImageableLLY = 0; + psImageableURX = psPaperWidth; + psImageableURY = psPaperHeight; + unlockGlobalParams; + return gTrue; +} + +void GlobalParams::setPSPaperWidth(int width) { + lockGlobalParams; + psPaperWidth = width; + psImageableLLX = 0; + psImageableURX = psPaperWidth; + unlockGlobalParams; +} + +void GlobalParams::setPSPaperHeight(int height) { + lockGlobalParams; + psPaperHeight = height; + psImageableLLY = 0; + psImageableURY = psPaperHeight; + unlockGlobalParams; +} + +void GlobalParams::setPSImageableArea(int llx, int lly, int urx, int ury) { + lockGlobalParams; + psImageableLLX = llx; + psImageableLLY = lly; + psImageableURX = urx; + psImageableURY = ury; + unlockGlobalParams; +} + +void GlobalParams::setPSCrop(GBool crop) { + lockGlobalParams; + psCrop = crop; + unlockGlobalParams; +} + +void GlobalParams::setPSExpandSmaller(GBool expand) { + lockGlobalParams; + psExpandSmaller = expand; + unlockGlobalParams; +} + +void GlobalParams::setPSShrinkLarger(GBool shrink) { + lockGlobalParams; + psShrinkLarger = shrink; + unlockGlobalParams; +} + +void GlobalParams::setPSCenter(GBool center) { + lockGlobalParams; + psCenter = center; + unlockGlobalParams; +} + +void GlobalParams::setPSDuplex(GBool duplex) { + lockGlobalParams; + psDuplex = duplex; + unlockGlobalParams; +} + +void GlobalParams::setPSLevel(PSLevel level) { + lockGlobalParams; + psLevel = level; + unlockGlobalParams; +} + +void GlobalParams::setPSEmbedType1(GBool embed) { + lockGlobalParams; + psEmbedType1 = embed; + unlockGlobalParams; +} + +void GlobalParams::setPSEmbedTrueType(GBool embed) { + lockGlobalParams; + psEmbedTrueType = embed; + unlockGlobalParams; +} + +void GlobalParams::setPSEmbedCIDPostScript(GBool embed) { + lockGlobalParams; + psEmbedCIDPostScript = embed; + unlockGlobalParams; +} + +void GlobalParams::setPSEmbedCIDTrueType(GBool embed) { + lockGlobalParams; + psEmbedCIDTrueType = embed; + unlockGlobalParams; +} + +void GlobalParams::setPSPreload(GBool preload) { + lockGlobalParams; + psPreload = preload; + unlockGlobalParams; +} + +void GlobalParams::setPSOPI(GBool opi) { + lockGlobalParams; + psOPI = opi; + unlockGlobalParams; +} + +void GlobalParams::setPSASCIIHex(GBool hex) { + lockGlobalParams; + psASCIIHex = hex; + unlockGlobalParams; +} + +void GlobalParams::setTextEncoding(char *encodingName) { + lockGlobalParams; + delete textEncoding; + textEncoding = new GString(encodingName); + unlockGlobalParams; +} + +GBool GlobalParams::setTextEOL(char *s) { + lockGlobalParams; + if (!strcmp(s, "unix")) { + textEOL = eolUnix; + } else if (!strcmp(s, "dos")) { + textEOL = eolDOS; + } else if (!strcmp(s, "mac")) { + textEOL = eolMac; + } else { + unlockGlobalParams; + return gFalse; + } + unlockGlobalParams; + return gTrue; +} + +void GlobalParams::setTextPageBreaks(GBool pageBreaks) { + lockGlobalParams; + textPageBreaks = pageBreaks; + unlockGlobalParams; +} + +void GlobalParams::setTextKeepTinyChars(GBool keep) { + lockGlobalParams; + textKeepTinyChars = keep; + unlockGlobalParams; +} + +void GlobalParams::setInitialZoom(char *s) { + lockGlobalParams; + delete initialZoom; + initialZoom = new GString(s); + unlockGlobalParams; +} + +void GlobalParams::setContinuousView(GBool cont) { + lockGlobalParams; + continuousView = cont; + unlockGlobalParams; +} + +GBool GlobalParams::setEnableT1lib(char *s) { + GBool ok; + + lockGlobalParams; + ok = parseYesNo2(s, &enableT1lib); + unlockGlobalParams; + return ok; +} + +GBool GlobalParams::setEnableFreeType(char *s) { + GBool ok; + + lockGlobalParams; + ok = parseYesNo2(s, &enableFreeType); + unlockGlobalParams; + return ok; +} + + +GBool GlobalParams::setAntialias(char *s) { + GBool ok; + + lockGlobalParams; + ok = parseYesNo2(s, &antialias); + unlockGlobalParams; + return ok; +} + +GBool GlobalParams::setVectorAntialias(char *s) { + GBool ok; + + lockGlobalParams; + ok = parseYesNo2(s, &vectorAntialias); + unlockGlobalParams; + return ok; +} + +void GlobalParams::setScreenType(ScreenType t) { + lockGlobalParams; + screenType = t; + unlockGlobalParams; +} + +void GlobalParams::setScreenSize(int size) { + lockGlobalParams; + screenSize = size; + unlockGlobalParams; +} + +void GlobalParams::setScreenDotRadius(int r) { + lockGlobalParams; + screenDotRadius = r; + unlockGlobalParams; +} + +void GlobalParams::setScreenGamma(double gamma) { + lockGlobalParams; + screenGamma = gamma; + unlockGlobalParams; +} + +void GlobalParams::setScreenBlackThreshold(double thresh) { + lockGlobalParams; + screenBlackThreshold = thresh; + unlockGlobalParams; +} + +void GlobalParams::setScreenWhiteThreshold(double thresh) { + lockGlobalParams; + screenWhiteThreshold = thresh; + unlockGlobalParams; +} + +void GlobalParams::setMapNumericCharNames(GBool map) { + lockGlobalParams; + mapNumericCharNames = map; + unlockGlobalParams; +} + +void GlobalParams::setMapUnknownCharNames(GBool map) { + lockGlobalParams; + mapUnknownCharNames = map; + unlockGlobalParams; +} + +void GlobalParams::setPrintCommands(GBool printCommandsA) { + lockGlobalParams; + printCommands = printCommandsA; + unlockGlobalParams; +} + +void GlobalParams::setErrQuiet(GBool errQuietA) { + lockGlobalParams; + errQuiet = errQuietA; + unlockGlobalParams; +} + +void GlobalParams::addSecurityHandler(XpdfSecurityHandler *handler) { +#ifdef ENABLE_PLUGINS + lockGlobalParams; + securityHandlers->append(handler); + unlockGlobalParams; +#endif +} + +XpdfSecurityHandler *GlobalParams::getSecurityHandler(char *name) { +#ifdef ENABLE_PLUGINS + XpdfSecurityHandler *hdlr; + int i; + + lockGlobalParams; + for (i = 0; i < securityHandlers->getLength(); ++i) { + hdlr = (XpdfSecurityHandler *)securityHandlers->get(i); + if (!strcasecmp(hdlr->name, name)) { + unlockGlobalParams; + return hdlr; + } + } + unlockGlobalParams; + + if (!loadPlugin("security", name)) { + return NULL; + } + + lockGlobalParams; + for (i = 0; i < securityHandlers->getLength(); ++i) { + hdlr = (XpdfSecurityHandler *)securityHandlers->get(i); + if (!strcmp(hdlr->name, name)) { + unlockGlobalParams; + return hdlr; + } + } + unlockGlobalParams; +#endif + + return NULL; +} + +#ifdef ENABLE_PLUGINS +//------------------------------------------------------------------------ +// plugins +//------------------------------------------------------------------------ + +GBool GlobalParams::loadPlugin(char *type, char *name) { + Plugin *plugin; + + if (!(plugin = Plugin::load(type, name))) { + return gFalse; + } + lockGlobalParams; + plugins->append(plugin); + unlockGlobalParams; + return gTrue; +} + +#endif // ENABLE_PLUGINS diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GlobalParams.h swftools-0.9.1/lib/pdf/xpdf/GlobalParams.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/GlobalParams.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GlobalParams.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,467 @@ +//======================================================================== +// +// GlobalParams.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GLOBALPARAMS_H +#define GLOBALPARAMS_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "gtypes.h" +#include "CharTypes.h" + +#if MULTITHREADED +#include "GMutex.h" +#endif + +class GString; +class GList; +class GHash; +class NameToCharCode; +class CharCodeToUnicode; +class CharCodeToUnicodeCache; +class UnicodeMap; +class UnicodeMapCache; +class CMap; +class CMapCache; +struct XpdfSecurityHandler; +class GlobalParams; +#ifdef WIN32 +class WinFontList; +#endif + +//------------------------------------------------------------------------ + +// The global parameters object. +extern GlobalParams *globalParams; + +//------------------------------------------------------------------------ + +enum DisplayFontParamKind { + displayFontT1, + displayFontTT +}; + +struct DisplayFontParamT1 { + GString *fileName; +}; + +struct DisplayFontParamTT { + GString *fileName; +}; + +class DisplayFontParam { +public: + + GString *name; // font name for 8-bit fonts and named + // CID fonts; collection name for + // generic CID fonts + DisplayFontParamKind kind; + union { + DisplayFontParamT1 t1; + DisplayFontParamTT tt; + }; + + DisplayFontParam(GString *nameA, DisplayFontParamKind kindA); + virtual ~DisplayFontParam(); +}; + +//------------------------------------------------------------------------ + +class PSFontParam { +public: + + GString *pdfFontName; // PDF font name for 8-bit fonts and + // named 16-bit fonts; char collection + // name for generic 16-bit fonts + int wMode; // writing mode (0=horiz, 1=vert) for + // 16-bit fonts + GString *psFontName; // PostScript font name + GString *encoding; // encoding, for 16-bit fonts only + + PSFontParam(GString *pdfFontNameA, int wModeA, + GString *psFontNameA, GString *encodingA); + ~PSFontParam(); +}; + +//------------------------------------------------------------------------ + +enum PSLevel { + psLevel1, + psLevel1Sep, + psLevel2, + psLevel2Sep, + psLevel3, + psLevel3Sep +}; + +//------------------------------------------------------------------------ + +enum EndOfLineKind { + eolUnix, // LF + eolDOS, // CR+LF + eolMac // CR +}; + +//------------------------------------------------------------------------ + +enum ScreenType { + screenUnset, + screenDispersed, + screenClustered, + screenStochasticClustered +}; + +//------------------------------------------------------------------------ + +class KeyBinding { +public: + + int code; // 0x20 .. 0xfe = ASCII, + // >=0x10000 = special keys, mouse buttons, + // etc. (xpdfKeyCode* symbols) + int mods; // modifiers (xpdfKeyMod* symbols, or-ed + // together) + int context; // context (xpdfKeyContext* symbols, or-ed + // together) + GList *cmds; // list of commands [GString] + + KeyBinding(int codeA, int modsA, int contextA, char *cmd0); + KeyBinding(int codeA, int modsA, int contextA, char *cmd0, char *cmd1); + KeyBinding(int codeA, int modsA, int contextA, GList *cmdsA); + ~KeyBinding(); +}; + +#define xpdfKeyCodeTab 0x1000 +#define xpdfKeyCodeReturn 0x1001 +#define xpdfKeyCodeEnter 0x1002 +#define xpdfKeyCodeBackspace 0x1003 +#define xpdfKeyCodeInsert 0x1004 +#define xpdfKeyCodeDelete 0x1005 +#define xpdfKeyCodeHome 0x1006 +#define xpdfKeyCodeEnd 0x1007 +#define xpdfKeyCodePgUp 0x1008 +#define xpdfKeyCodePgDn 0x1009 +#define xpdfKeyCodeLeft 0x100a +#define xpdfKeyCodeRight 0x100b +#define xpdfKeyCodeUp 0x100c +#define xpdfKeyCodeDown 0x100d +#define xpdfKeyCodeF1 0x1100 +#define xpdfKeyCodeF35 0x1122 +#define xpdfKeyCodeMousePress1 0x2001 +#define xpdfKeyCodeMousePress2 0x2002 +#define xpdfKeyCodeMousePress3 0x2003 +#define xpdfKeyCodeMousePress4 0x2004 +#define xpdfKeyCodeMousePress5 0x2005 +#define xpdfKeyCodeMousePress6 0x2006 +#define xpdfKeyCodeMousePress7 0x2007 +#define xpdfKeyCodeMouseRelease1 0x2101 +#define xpdfKeyCodeMouseRelease2 0x2102 +#define xpdfKeyCodeMouseRelease3 0x2103 +#define xpdfKeyCodeMouseRelease4 0x2104 +#define xpdfKeyCodeMouseRelease5 0x2105 +#define xpdfKeyCodeMouseRelease6 0x2106 +#define xpdfKeyCodeMouseRelease7 0x2107 +#define xpdfKeyModNone 0 +#define xpdfKeyModShift (1 << 0) +#define xpdfKeyModCtrl (1 << 1) +#define xpdfKeyModAlt (1 << 2) +#define xpdfKeyContextAny 0 +#define xpdfKeyContextFullScreen (1 << 0) +#define xpdfKeyContextWindow (2 << 0) +#define xpdfKeyContextContinuous (1 << 2) +#define xpdfKeyContextSinglePage (2 << 2) +#define xpdfKeyContextOverLink (1 << 4) +#define xpdfKeyContextOffLink (2 << 4) +#define xpdfKeyContextOutline (1 << 6) +#define xpdfKeyContextMainWin (2 << 6) +#define xpdfKeyContextScrLockOn (1 << 8) +#define xpdfKeyContextScrLockOff (2 << 8) + +//------------------------------------------------------------------------ + +class GlobalParams { +public: + + // Initialize the global parameters by attempting to read a config + // file. + GlobalParams(char *cfgFileName); + + virtual ~GlobalParams(); + + void setBaseDir(char *dir); + void setupBaseFonts(char *dir); + + void parseLine(char *buf, GString *fileName, int line); + + //----- accessors + + CharCode getMacRomanCharCode(char *charName); + + GString *getBaseDir(); + Unicode mapNameToUnicode(char *charName); + UnicodeMap *getResidentUnicodeMap(GString *encodingName); + FILE *getUnicodeMapFile(GString *encodingName); + FILE *findCMapFile(GString *collection, GString *cMapName); + FILE *findToUnicodeFile(GString *name); + virtual DisplayFontParam *getDisplayFont(GString *fontName); + virtual DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection); + GString *getPSFile(); + int getPSPaperWidth(); + int getPSPaperHeight(); + void getPSImageableArea(int *llx, int *lly, int *urx, int *ury); + GBool getPSDuplex(); + GBool getPSCrop(); + GBool getPSExpandSmaller(); + GBool getPSShrinkLarger(); + GBool getPSCenter(); + PSLevel getPSLevel(); + PSFontParam *getPSFont(GString *fontName); + PSFontParam *getPSFont16(GString *fontName, GString *collection, int wMode); + GBool getPSEmbedType1(); + GBool getPSEmbedTrueType(); + GBool getPSEmbedCIDPostScript(); + GBool getPSEmbedCIDTrueType(); + GBool getPSPreload(); + GBool getPSOPI(); + GBool getPSASCIIHex(); + GString *getTextEncodingName(); + EndOfLineKind getTextEOL(); + GBool getTextPageBreaks(); + GBool getTextKeepTinyChars(); + GString *findFontFile(GString *fontName, char **exts); + GString *getInitialZoom(); + GBool getContinuousView(); + GBool getEnableT1lib(); + GBool getEnableFreeType(); + GBool getAntialias(); + GBool getVectorAntialias(); + GBool getStrokeAdjust(); + ScreenType getScreenType(); + int getScreenSize(); + int getScreenDotRadius(); + double getScreenGamma(); + double getScreenBlackThreshold(); + double getScreenWhiteThreshold(); + GString *getURLCommand() { return urlCommand; } + GString *getMovieCommand() { return movieCommand; } + GBool getMapNumericCharNames(); + GBool getMapUnknownCharNames(); + GList *getKeyBinding(int code, int mods, int context); + GBool getPrintCommands(); + GBool getErrQuiet(); + + CharCodeToUnicode *getCIDToUnicode(GString *collection); + CharCodeToUnicode *getUnicodeToUnicode(GString *fontName); + UnicodeMap *getUnicodeMap(GString *encodingName); + CMap *getCMap(GString *collection, GString *cMapName); + UnicodeMap *getTextEncoding(); + + //----- functions to set parameters + + void addDisplayFont(DisplayFontParam *param); + void setPSFile(char *file); + GBool setPSPaperSize(char *size); + void setPSPaperWidth(int width); + void setPSPaperHeight(int height); + void setPSImageableArea(int llx, int lly, int urx, int ury); + void setPSDuplex(GBool duplex); + void setPSCrop(GBool crop); + void setPSExpandSmaller(GBool expand); + void setPSShrinkLarger(GBool shrink); + void setPSCenter(GBool center); + void setPSLevel(PSLevel level); + void setPSEmbedType1(GBool embed); + void setPSEmbedTrueType(GBool embed); + void setPSEmbedCIDPostScript(GBool embed); + void setPSEmbedCIDTrueType(GBool embed); + void setPSPreload(GBool preload); + void setPSOPI(GBool opi); + void setPSASCIIHex(GBool hex); + void setTextEncoding(char *encodingName); + GBool setTextEOL(char *s); + void setTextPageBreaks(GBool pageBreaks); + void setTextKeepTinyChars(GBool keep); + void setInitialZoom(char *s); + void setContinuousView(GBool cont); + GBool setEnableT1lib(char *s); + GBool setEnableFreeType(char *s); + GBool setAntialias(char *s); + GBool setVectorAntialias(char *s); + void setScreenType(ScreenType t); + void setScreenSize(int size); + void setScreenDotRadius(int r); + void setScreenGamma(double gamma); + void setScreenBlackThreshold(double thresh); + void setScreenWhiteThreshold(double thresh); + void setMapNumericCharNames(GBool map); + void setMapUnknownCharNames(GBool map); + void setPrintCommands(GBool printCommandsA); + void setErrQuiet(GBool errQuietA); + + //----- security handlers + + void addSecurityHandler(XpdfSecurityHandler *handler); + XpdfSecurityHandler *getSecurityHandler(char *name); + +private: + + void createDefaultKeyBindings(); +public: void parseFile(GString *fileName, FILE *f); private: + void parseNameToUnicode(GList *tokens, GString *fileName, int line); + void parseCIDToUnicode(GList *tokens, GString *fileName, int line); + void parseUnicodeToUnicode(GList *tokens, GString *fileName, int line); + void parseUnicodeMap(GList *tokens, GString *fileName, int line); + void parseCMapDir(GList *tokens, GString *fileName, int line); + void parseToUnicodeDir(GList *tokens, GString *fileName, int line); + void parseDisplayFont(GList *tokens, GHash *fontHash, + DisplayFontParamKind kind, + GString *fileName, int line); + void parsePSFile(GList *tokens, GString *fileName, int line); + void parsePSPaperSize(GList *tokens, GString *fileName, int line); + void parsePSImageableArea(GList *tokens, GString *fileName, int line); + void parsePSLevel(GList *tokens, GString *fileName, int line); + void parsePSFont(GList *tokens, GString *fileName, int line); + void parsePSFont16(char *cmdName, GList *fontList, + GList *tokens, GString *fileName, int line); + void parseTextEncoding(GList *tokens, GString *fileName, int line); + void parseTextEOL(GList *tokens, GString *fileName, int line); + void parseFontDir(GList *tokens, GString *fileName, int line); + void parseInitialZoom(GList *tokens, GString *fileName, int line); + void parseScreenType(GList *tokens, GString *fileName, int line); + void parseBind(GList *tokens, GString *fileName, int line); + void parseUnbind(GList *tokens, GString *fileName, int line); + GBool parseKey(GString *modKeyStr, GString *contextStr, + int *code, int *mods, int *context, + char *cmdName, + GList *tokens, GString *fileName, int line); + void parseCommand(char *cmdName, GString **val, + GList *tokens, GString *fileName, int line); + void parseYesNo(char *cmdName, GBool *flag, + GList *tokens, GString *fileName, int line); + GBool parseYesNo2(char *token, GBool *flag); + void parseInteger(char *cmdName, int *val, + GList *tokens, GString *fileName, int line); + void parseFloat(char *cmdName, double *val, + GList *tokens, GString *fileName, int line); + UnicodeMap *getUnicodeMap2(GString *encodingName); +#ifdef ENABLE_PLUGINS + GBool loadPlugin(char *type, char *name); +#endif + + //----- config file base path + + GString*path; + + //----- static tables + + NameToCharCode * // mapping from char name to + macRomanReverseMap; // MacRomanEncoding index + + //----- user-modifiable settings + + GString *baseDir; // base directory - for plugins, etc. + NameToCharCode * // mapping from char name to Unicode + nameToUnicode; + GHash *cidToUnicodes; // files for mappings from char collections + // to Unicode, indexed by collection name + // [GString] + GHash *unicodeToUnicodes; // files for Unicode-to-Unicode mappings, + // indexed by font name pattern [GString] + GHash *residentUnicodeMaps; // mappings from Unicode to char codes, + // indexed by encoding name [UnicodeMap] + GHash *unicodeMaps; // files for mappings from Unicode to char + // codes, indexed by encoding name [GString] + GHash *cMapDirs; // list of CMap dirs, indexed by collection + // name [GList[GString]] + GList *toUnicodeDirs; // list of ToUnicode CMap dirs [GString] + GHash *displayFonts; // display font info, indexed by font name + // [DisplayFontParam] +#ifdef WIN32 + WinFontList *winFontList; // system TrueType fonts +#endif + GHash *displayCIDFonts; // display CID font info, indexed by + // collection [DisplayFontParam] + GHash *displayNamedCIDFonts; // display CID font info, indexed by + // font name [DisplayFontParam] + GString *psFile; // PostScript file or command (for xpdf) + int psPaperWidth; // paper size, in PostScript points, for + int psPaperHeight; // PostScript output + int psImageableLLX, // imageable area, in PostScript points, + psImageableLLY, // for PostScript output + psImageableURX, + psImageableURY; + GBool psCrop; // crop PS output to CropBox + GBool psExpandSmaller; // expand smaller pages to fill paper + GBool psShrinkLarger; // shrink larger pages to fit paper + GBool psCenter; // center pages on the paper + GBool psDuplex; // enable duplexing in PostScript? + PSLevel psLevel; // PostScript level to generate + GHash *psFonts; // PostScript font info, indexed by PDF + // font name [PSFontParam] + GList *psNamedFonts16; // named 16-bit fonts [PSFontParam] + GList *psFonts16; // generic 16-bit fonts [PSFontParam] + GBool psEmbedType1; // embed Type 1 fonts? + GBool psEmbedTrueType; // embed TrueType fonts? + GBool psEmbedCIDPostScript; // embed CID PostScript fonts? + GBool psEmbedCIDTrueType; // embed CID TrueType fonts? + GBool psPreload; // preload PostScript images and forms into + // memory + GBool psOPI; // generate PostScript OPI comments? + GBool psASCIIHex; // use ASCIIHex instead of ASCII85? + GString *textEncoding; // encoding (unicodeMap) to use for text + // output + EndOfLineKind textEOL; // type of EOL marker to use for text + // output + GBool textPageBreaks; // insert end-of-page markers? + GBool textKeepTinyChars; // keep all characters in text output + GList *fontDirs; // list of font dirs [GString] + GString *initialZoom; // initial zoom level + GBool continuousView; // continuous view mode + GBool enableT1lib; // t1lib enable flag + GBool enableFreeType; // FreeType enable flag + GBool antialias; // font anti-aliasing enable flag + GBool vectorAntialias; // vector anti-aliasing enable flag + GBool strokeAdjust; // stroke adjustment enable flag + ScreenType screenType; // halftone screen type + int screenSize; // screen matrix size + int screenDotRadius; // screen dot radius + double screenGamma; // screen gamma correction + double screenBlackThreshold; // screen black clamping threshold + double screenWhiteThreshold; // screen white clamping threshold + GString *urlCommand; // command executed for URL links + GString *movieCommand; // command executed for movie annotations + GBool mapNumericCharNames; // map numeric char names (from font subsets)? + GBool mapUnknownCharNames; // map unknown char names? + GList *keyBindings; // key & mouse button bindings [KeyBinding] + GBool printCommands; // print the drawing commands + GBool errQuiet; // suppress error messages? + + CharCodeToUnicodeCache *cidToUnicodeCache; + CharCodeToUnicodeCache *unicodeToUnicodeCache; + UnicodeMapCache *unicodeMapCache; + CMapCache *cMapCache; + +#ifdef ENABLE_PLUGINS + GList *plugins; // list of plugins [Plugin] + GList *securityHandlers; // list of loaded security handlers + // [XpdfSecurityHandler] +#endif + +#if MULTITHREADED + GMutex mutex; + GMutex unicodeMapCacheMutex; + GMutex cMapCacheMutex; +#endif +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/gmem.cc swftools-0.9.1/lib/pdf/xpdf/gmem.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/gmem.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/gmem.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,304 @@ +/* + * gmem.c + * + * Memory routines with out-of-memory checking. + * + * Copyright 1996-2003 Glyph & Cog, LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include "gmem.h" + +#ifdef DEBUG_MEM + +typedef struct _GMemHdr { + unsigned int magic; + int size; + int index; + struct _GMemHdr *next, *prev; +} GMemHdr; + +#define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7) +#define gMemTrlSize (sizeof(long)) + +#define gMemMagic 0xabcd9999 + +#if gmemTrlSize==8 +#define gMemDeadVal 0xdeadbeefdeadbeefUL +#else +#define gMemDeadVal 0xdeadbeefUL +#endif + +/* round data size so trailer will be aligned */ +#define gMemDataSize(size) \ + ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize) + +static GMemHdr *gMemHead = NULL; +static GMemHdr *gMemTail = NULL; + +static int gMemIndex = 0; +static int gMemAlloc = 0; +static int gMemInUse = 0; + +#endif /* DEBUG_MEM */ + +void *gmalloc(int size, bool exit_on_error) GMEM_EXCEP { +#ifdef DEBUG_MEM + int size1; + char *mem; + GMemHdr *hdr; + void *data; + unsigned long *trl, *p; + + if (size <= 0) { + return NULL; + } + size1 = gMemDataSize(size); + if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) { +#if USE_EXCEPTIONS + throw GMemException(); +#else + fprintf(stderr, "Out of memory\n"); + if(exit_on_error) + exit(1); + else + return NULL; +#endif + } + hdr = (GMemHdr *)mem; + data = (void *)(mem + gMemHdrSize); + trl = (unsigned long *)(mem + gMemHdrSize + size1); + hdr->magic = gMemMagic; + hdr->size = size; + hdr->index = gMemIndex++; + if (gMemTail) { + gMemTail->next = hdr; + hdr->prev = gMemTail; + gMemTail = hdr; + } else { + hdr->prev = NULL; + gMemHead = gMemTail = hdr; + } + hdr->next = NULL; + ++gMemAlloc; + gMemInUse += size; + for (p = (unsigned long *)data; p <= trl; ++p) { + *p = gMemDeadVal; + } + return data; +#else + void *p; + + if (size <= 0) { + return NULL; + } + if (!(p = malloc(size))) { +#if USE_EXCEPTIONS + throw GMemException(); +#else + fprintf(stderr, "Out of memory\n"); + if(exit_on_error) + exit(1); + else + return NULL; +#endif + } + return p; +#endif +} +void *gmalloc(int size) GMEM_EXCEP { + return gmalloc(size, true); +} +void *gmalloc_noexit(int size) GMEM_EXCEP { + return gmalloc(size, false); +} + +void *grealloc(void *p, int size, bool exit_on_error) GMEM_EXCEP { +#ifdef DEBUG_MEM + GMemHdr *hdr; + void *q; + int oldSize; + + if (size <= 0) { + if (p) { + gfree(p); + } + return NULL; + } + if (p) { + hdr = (GMemHdr *)((char *)p - gMemHdrSize); + oldSize = hdr->size; + q = gmalloc(size); + memcpy(q, p, size < oldSize ? size : oldSize); + gfree(p); + } else { + q = gmalloc(size); + } + return q; +#else + void *q; + + if (size <= 0) { + if (p) { + free(p); + } + return NULL; + } + if (p) { + q = realloc(p, size); + } else { + q = malloc(size); + } + if (!q) { +#if USE_EXCEPTIONS + throw GMemException(); +#else + fprintf(stderr, "Out of memory\n"); + if(exit_on_error) + exit(1); + else + return NULL; +#endif + } + return q; +#endif +} +void *grealloc(void *p, int size) GMEM_EXCEP { + return grealloc(p, size, true); +} +void *grealloc_noexit(void *p, int size) GMEM_EXCEP { + return grealloc(p, size, false); +} + +void *gmallocn(int nObjs, int objSize, bool exit_on_error) GMEM_EXCEP { + int n; + + if (nObjs == 0) { + return NULL; + } + n = nObjs * objSize; + if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) { +#if USE_EXCEPTIONS + throw GMemException(); +#else + fprintf(stderr, "Bogus memory allocation size\n"); + if(exit_on_error) + exit(1); + else + return NULL; +#endif + } + return gmalloc(n); +} +void *gmallocn(int nObjs, int objSize) GMEM_EXCEP { + return gmallocn(nObjs, objSize, true); +} +void *gmallocn_noexit(int nObjs, int objSize) GMEM_EXCEP { + return gmallocn(nObjs, objSize, false); +} + +void *greallocn(void *p, int nObjs, int objSize, bool exit_on_error) GMEM_EXCEP { + int n; + + if (nObjs == 0) { + if (p) { + gfree(p); + } + return NULL; + } + n = nObjs * objSize; + if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) { +#if USE_EXCEPTIONS + throw GMemException(); +#else + fprintf(stderr, "Bogus memory allocation size\n"); + if(exit_on_error) + exit(1); + else + return NULL; +#endif + } + return grealloc(p, n); +} +void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP { + return greallocn(p, nObjs, objSize, true); +} +void *greallocn_noexit(void *p, int nObjs, int objSize) GMEM_EXCEP { + return greallocn(p, nObjs, objSize, false); +} + +void gfree(void *p) { +#ifdef DEBUG_MEM + int size; + GMemHdr *hdr; + unsigned long *trl, *clr; + + if (p) { + hdr = (GMemHdr *)((char *)p - gMemHdrSize); + if (hdr->magic == gMemMagic && + ((hdr->prev == NULL) == (hdr == gMemHead)) && + ((hdr->next == NULL) == (hdr == gMemTail))) { + if (hdr->prev) { + hdr->prev->next = hdr->next; + } else { + gMemHead = hdr->next; + } + if (hdr->next) { + hdr->next->prev = hdr->prev; + } else { + gMemTail = hdr->prev; + } + --gMemAlloc; + gMemInUse -= hdr->size; + size = gMemDataSize(hdr->size); + trl = (unsigned long *)((char *)hdr + gMemHdrSize + size); + if (*trl != gMemDeadVal) { + fprintf(stderr, "Overwrite past end of block %d at address %p\n", + hdr->index, p); + } + for (clr = (unsigned long *)hdr; clr <= trl; ++clr) { + *clr = gMemDeadVal; + } + free(hdr); + } else { + fprintf(stderr, "Attempted to free bad address %p\n", p); + } + } +#else + if (p) { + free(p); + } +#endif +} + +#ifdef DEBUG_MEM +void gMemReport(FILE *f) { + GMemHdr *p; + + fprintf(f, "%d memory allocations in all\n", gMemIndex); + if (gMemAlloc > 0) { + fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc); + fprintf(f, " index size\n"); + fprintf(f, "-------- --------\n"); + for (p = gMemHead; p; p = p->next) { + fprintf(f, "%8d %8d\n", p->index, p->size); + } + } else { + fprintf(f, "No memory blocks left allocated\n"); + } +} +#endif + +char *copyString(char *s) { + char *s1; + + s1 = (char *)gmalloc(strlen(s) + 1); + strcpy(s1, s); + return s1; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/gmem.h swftools-0.9.1/lib/pdf/xpdf/gmem.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/gmem.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/gmem.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,83 @@ +/* + * gmem.h + * + * Memory routines with out-of-memory checking. + * + * Copyright 1996-2003 Glyph & Cog, LLC + */ + +#ifndef GMEM_H +#define GMEM_H + +#include +#include + +#if USE_EXCEPTIONS + +class GMemException { +public: + GMemException() {} + ~GMemException() {} +}; + +#define GMEM_EXCEP throw(GMemException) + +#else // USE_EXCEPTIONS + +#define GMEM_EXCEP + +#endif // USE_EXCEPTIONS + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Same as malloc, but prints error message and exits if malloc() + * returns NULL. + */ +extern void *gmalloc(int size) GMEM_EXCEP; +extern void *gmalloc_noexit(int size) GMEM_EXCEP; + +/* + * Same as realloc, but prints error message and exits if realloc() + * returns NULL. If

    is NULL, calls malloc instead of realloc(). + */ +extern void *grealloc(void *p, int size) GMEM_EXCEP; +extern void *grealloc_noexit(void *p, int size) GMEM_EXCEP; + +/* + * These are similar to gmalloc and grealloc, but take an object count + * and size. The result is similar to allocating nObjs * objSize + * bytes, but there is an additional error check that the total size + * doesn't overflow an int. + */ +extern void *gmallocn(int nObjs, int objSize) GMEM_EXCEP; +extern void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP; +extern void *gmallocn_noexit(int nObjs, int objSize) GMEM_EXCEP; +extern void *greallocn_noexit(void *p, int nObjs, int objSize) GMEM_EXCEP; + +/* + * Same as free, but checks for and ignores NULL pointers. + */ +extern void gfree(void *p); + +#ifdef DEBUG_MEM +/* + * Report on unfreed memory. + */ +extern void gMemReport(FILE *f); +#else +#define gMemReport(f) +#endif + +/* + * Allocate memory and copy a string into it. + */ +extern char *copyString(char *s); + +#ifdef __cplusplus +} +#endif + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/gmempp.cc swftools-0.9.1/lib/pdf/xpdf/gmempp.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/gmempp.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/gmempp.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,32 @@ +//======================================================================== +// +// gmempp.cc +// +// Use gmalloc/gfree for C++ new/delete operators. +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include "gmem.h" + +#ifdef DEBUG_MEM + +void *operator new(size_t size) { + return gmalloc((int)size); +} + +void *operator new[](size_t size) { + return gmalloc((int)size); +} + +void operator delete(void *p) { + gfree(p); +} + +void operator delete[](void *p) { + gfree(p); +} + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GMutex.h swftools-0.9.1/lib/pdf/xpdf/GMutex.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/GMutex.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GMutex.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,49 @@ +//======================================================================== +// +// GMutex.h +// +// Portable mutex macros. +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GMUTEX_H +#define GMUTEX_H + +// Usage: +// +// GMutex m; +// gInitMutex(&m); +// ... +// gLockMutex(&m); +// ... critical section ... +// gUnlockMutex(&m); +// ... +// gDestroyMutex(&m); + +#ifdef WIN32 + +#include + +typedef CRITICAL_SECTION GMutex; + +#define gInitMutex(m) InitializeCriticalSection(m) +#define gDestroyMutex(m) DeleteCriticalSection(m) +#define gLockMutex(m) EnterCriticalSection(m) +#define gUnlockMutex(m) LeaveCriticalSection(m) + +#else // assume pthreads + +#include + +typedef pthread_mutex_t GMutex; + +#define gInitMutex(m) pthread_mutex_init(m, NULL) +#define gDestroyMutex(m) pthread_mutex_destroy(m) +#define gLockMutex(m) pthread_mutex_lock(m) +#define gUnlockMutex(m) pthread_mutex_unlock(m) + +#endif + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GString.cc swftools-0.9.1/lib/pdf/xpdf/GString.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/GString.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GString.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,718 @@ +//======================================================================== +// +// GString.cc +// +// Simple variable-length string type. +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include "gmem.h" +#include "GString.h" + +//------------------------------------------------------------------------ + +union GStringFormatArg { + int i; + Guint ui; + long l; + Gulong ul; + double f; + char c; + char *s; + GString *gs; +}; + +enum GStringFormatType { + fmtIntDecimal, + fmtIntHex, + fmtIntOctal, + fmtIntBinary, + fmtUIntDecimal, + fmtUIntHex, + fmtUIntOctal, + fmtUIntBinary, + fmtLongDecimal, + fmtLongHex, + fmtLongOctal, + fmtLongBinary, + fmtULongDecimal, + fmtULongHex, + fmtULongOctal, + fmtULongBinary, + fmtDouble, + fmtDoubleTrim, + fmtChar, + fmtString, + fmtGString, + fmtSpace +}; + +static char *formatStrings[] = { + "d", "x", "o", "b", "ud", "ux", "uo", "ub", + "ld", "lx", "lo", "lb", "uld", "ulx", "ulo", "ulb", + "f", "g", + "c", + "s", + "t", + "w", + NULL +}; + +//------------------------------------------------------------------------ + +static inline int size(int len) { + int delta; + for (delta = 8; delta < len && delta < 0x100000; delta <<= 1) ; + // this is ((len + 1) + (delta - 1)) & ~(delta - 1) + return (len + delta) & ~(delta - 1); +} + +inline void GString::resize(int length1) { + char *s1; + + if (!s) { + s = new char[size(length1)]; + } else if (size(length1) != size(length)) { + s1 = new char[size(length1)]; + if (length1 < length) { + memcpy(s1, s, length1); + s1[length1] = '\0'; + } else { + memcpy(s1, s, length + 1); + } + delete[] s; + s = s1; + } +} + +GString::GString() { + s = NULL; + resize(length = 0); + s[0] = '\0'; +} + +GString::GString(const char *sA) { + int n = strlen(sA); + + s = NULL; + resize(length = n); + memcpy(s, sA, n + 1); +} + +GString::GString(const char *sA, int lengthA) { + s = NULL; + resize(length = lengthA); + memcpy(s, sA, length * sizeof(char)); + s[length] = '\0'; +} + +GString::GString(GString *str, int idx, int lengthA) { + s = NULL; + resize(length = lengthA); + memcpy(s, str->getCString() + idx, length); + s[length] = '\0'; +} + +GString::GString(GString *str) { + s = NULL; + resize(length = str->getLength()); + memcpy(s, str->getCString(), length + 1); +} + +GString::GString(GString *str1, GString *str2) { + int n1 = str1->getLength(); + int n2 = str2->getLength(); + + s = NULL; + resize(length = n1 + n2); + memcpy(s, str1->getCString(), n1); + memcpy(s + n1, str2->getCString(), n2 + 1); +} + +GString *GString::fromInt(int x) { + char buf[24]; // enough space for 64-bit ints plus a little extra + char *p; + int len; + + formatInt(x, buf, sizeof(buf), gFalse, 0, 10, &p, &len); + return new GString(p, len); +} + +GString *GString::format(char *fmt, ...) { + va_list argList; + GString *s; + + s = new GString(); + va_start(argList, fmt); + s->appendfv(fmt, argList); + va_end(argList); + return s; +} + +GString *GString::formatv(char *fmt, va_list argList) { + GString *s; + + s = new GString(); + s->appendfv(fmt, argList); + return s; +} + +GString::~GString() { + delete[] s; +} + +GString *GString::clear() { + s[length = 0] = '\0'; + resize(0); + return this; +} + +GString *GString::append(char c) { + resize(length + 1); + s[length++] = c; + s[length] = '\0'; + return this; +} + +GString *GString::append(GString *str) { + int n = str->getLength(); + + resize(length + n); + memcpy(s + length, str->getCString(), n + 1); + length += n; + return this; +} + +GString *GString::append(const char *str) { + int n = strlen(str); + + resize(length + n); + memcpy(s + length, str, n + 1); + length += n; + return this; +} + +GString *GString::append(const char *str, int lengthA) { + resize(length + lengthA); + memcpy(s + length, str, lengthA); + length += lengthA; + s[length] = '\0'; + return this; +} + +GString *GString::appendf(char *fmt, ...) { + va_list argList; + + va_start(argList, fmt); + appendfv(fmt, argList); + va_end(argList); + return this; +} + +GString *GString::appendfv(char *fmt, va_list argList) { + GStringFormatArg *args; + int argsLen, argsSize; + GStringFormatArg arg; + int idx, width, prec; + GBool reverseAlign, zeroFill; + GStringFormatType ft; + char buf[65]; + int len, i; + char *p0, *p1, *str; + + argsLen = 0; + argsSize = 8; + args = (GStringFormatArg *)gmallocn(argsSize, sizeof(GStringFormatArg)); + + p0 = fmt; + while (*p0) { + if (*p0 == '{') { + ++p0; + if (*p0 == '{') { + ++p0; + append('{'); + } else { + + // parse the format string + if (!(*p0 >= '0' && *p0 <= '9')) { + break; + } + idx = *p0 - '0'; + for (++p0; *p0 >= '0' && *p0 <= '9'; ++p0) { + idx = 10 * idx + (*p0 - '0'); + } + if (*p0 != ':') { + break; + } + ++p0; + if (*p0 == '-') { + reverseAlign = gTrue; + ++p0; + } else { + reverseAlign = gFalse; + } + width = 0; + zeroFill = *p0 == '0'; + for (; *p0 >= '0' && *p0 <= '9'; ++p0) { + width = 10 * width + (*p0 - '0'); + } + if (*p0 == '.') { + ++p0; + prec = 0; + for (; *p0 >= '0' && *p0 <= '9'; ++p0) { + prec = 10 * prec + (*p0 - '0'); + } + } else { + prec = 0; + } + for (ft = (GStringFormatType)0; + formatStrings[ft]; + ft = (GStringFormatType)(ft + 1)) { + if (!strncmp(p0, formatStrings[ft], strlen(formatStrings[ft]))) { + break; + } + } + if (!formatStrings[ft]) { + break; + } + p0 += strlen(formatStrings[ft]); + if (*p0 != '}') { + break; + } + ++p0; + + // fetch the argument + if (idx > argsLen) { + break; + } + if (idx == argsLen) { + if (argsLen == argsSize) { + argsSize *= 2; + args = (GStringFormatArg *)greallocn(args, argsSize, + sizeof(GStringFormatArg)); + } + switch (ft) { + case fmtIntDecimal: + case fmtIntHex: + case fmtIntOctal: + case fmtIntBinary: + case fmtSpace: + args[argsLen].i = va_arg(argList, int); + break; + case fmtUIntDecimal: + case fmtUIntHex: + case fmtUIntOctal: + case fmtUIntBinary: + args[argsLen].ui = va_arg(argList, Guint); + break; + case fmtLongDecimal: + case fmtLongHex: + case fmtLongOctal: + case fmtLongBinary: + args[argsLen].l = va_arg(argList, long); + break; + case fmtULongDecimal: + case fmtULongHex: + case fmtULongOctal: + case fmtULongBinary: + args[argsLen].ul = va_arg(argList, Gulong); + break; + case fmtDouble: + case fmtDoubleTrim: + args[argsLen].f = va_arg(argList, double); + break; + case fmtChar: + args[argsLen].c = (char)va_arg(argList, int); + break; + case fmtString: + args[argsLen].s = va_arg(argList, char *); + break; + case fmtGString: + args[argsLen].gs = va_arg(argList, GString *); + break; + } + ++argsLen; + } + + // format the argument + arg = args[idx]; + switch (ft) { + case fmtIntDecimal: + formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 10, &str, &len); + break; + case fmtIntHex: + formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 16, &str, &len); + break; + case fmtIntOctal: + formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 8, &str, &len); + break; + case fmtIntBinary: + formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 2, &str, &len); + break; + case fmtUIntDecimal: + formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 10, + &str, &len); + break; + case fmtUIntHex: + formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 16, + &str, &len); + break; + case fmtUIntOctal: + formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 8, &str, &len); + break; + case fmtUIntBinary: + formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 2, &str, &len); + break; + case fmtLongDecimal: + formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 10, &str, &len); + break; + case fmtLongHex: + formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 16, &str, &len); + break; + case fmtLongOctal: + formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 8, &str, &len); + break; + case fmtLongBinary: + formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 2, &str, &len); + break; + case fmtULongDecimal: + formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 10, + &str, &len); + break; + case fmtULongHex: + formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 16, + &str, &len); + break; + case fmtULongOctal: + formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 8, &str, &len); + break; + case fmtULongBinary: + formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 2, &str, &len); + break; + case fmtDouble: + formatDouble(arg.f, buf, sizeof(buf), prec, gFalse, &str, &len); + break; + case fmtDoubleTrim: + formatDouble(arg.f, buf, sizeof(buf), prec, gTrue, &str, &len); + break; + case fmtChar: + buf[0] = arg.c; + str = buf; + len = 1; + reverseAlign = !reverseAlign; + break; + case fmtString: + str = arg.s; + len = strlen(str); + reverseAlign = !reverseAlign; + break; + case fmtGString: + str = arg.gs->getCString(); + len = arg.gs->getLength(); + reverseAlign = !reverseAlign; + break; + case fmtSpace: + str = buf; + len = 0; + width = arg.i; + break; + } + + // append the formatted arg, handling width and alignment + if (!reverseAlign && len < width) { + for (i = len; i < width; ++i) { + append(' '); + } + } + append(str, len); + if (reverseAlign && len < width) { + for (i = len; i < width; ++i) { + append(' '); + } + } + } + + } else if (*p0 == '}') { + ++p0; + if (*p0 == '}') { + ++p0; + } + append('}'); + + } else { + for (p1 = p0 + 1; *p1 && *p1 != '{' && *p1 != '}'; ++p1) ; + append(p0, p1 - p0); + p0 = p1; + } + } + + gfree(args); + return this; +} + +void GString::formatInt(long x, char *buf, int bufSize, + GBool zeroFill, int width, int base, + char **p, int *len) { + static char vals[17] = "0123456789abcdef"; + GBool neg; + int start, i, j; + + i = bufSize; + if ((neg = x < 0)) { + x = -x; + } + start = neg ? 1 : 0; + if (x == 0) { + buf[--i] = '0'; + } else { + while (i > start && x) { + buf[--i] = vals[x % base]; + x /= base; + } + } + if (zeroFill) { + for (j = bufSize - i; i > start && j < width - start; ++j) { + buf[--i] = '0'; + } + } + if (neg) { + buf[--i] = '-'; + } + *p = buf + i; + *len = bufSize - i; +} + +void GString::formatUInt(Gulong x, char *buf, int bufSize, + GBool zeroFill, int width, int base, + char **p, int *len) { + static char vals[17] = "0123456789abcdef"; + int i, j; + + i = bufSize; + if (x == 0) { + buf[--i] = '0'; + } else { + while (i > 0 && x) { + buf[--i] = vals[x % base]; + x /= base; + } + } + if (zeroFill) { + for (j = bufSize - i; i > 0 && j < width; ++j) { + buf[--i] = '0'; + } + } + *p = buf + i; + *len = bufSize - i; +} + +void GString::formatDouble(double x, char *buf, int bufSize, int prec, + GBool trim, char **p, int *len) { + GBool neg, started; + double x2; + int d, i, j; + + if ((neg = x < 0)) { + x = -x; + } + x = floor(x * pow(10, prec) + 0.5); + i = bufSize; + started = !trim; + for (j = 0; j < prec && i > 1; ++j) { + x2 = floor(0.1 * (x + 0.5)); + d = (int)floor(x - 10 * x2 + 0.5); + if (started || d != 0) { + buf[--i] = '0' + d; + started = gTrue; + } + x = x2; + } + if (i > 1 && started) { + buf[--i] = '.'; + } + if (i > 1) { + do { + x2 = floor(0.1 * (x + 0.5)); + d = (int)floor(x - 10 * x2 + 0.5); + buf[--i] = '0' + d; + x = x2; + } while (i > 1 && x); + } + if (neg) { + buf[--i] = '-'; + } + *p = buf + i; + *len = bufSize - i; +} + +GString *GString::insert(int i, char c) { + int j; + + resize(length + 1); + for (j = length + 1; j > i; --j) + s[j] = s[j-1]; + s[i] = c; + ++length; + return this; +} + +GString *GString::insert(int i, GString *str) { + int n = str->getLength(); + int j; + + resize(length + n); + for (j = length; j >= i; --j) + s[j+n] = s[j]; + memcpy(s+i, str->getCString(), n); + length += n; + return this; +} + +GString *GString::insert(int i, const char *str) { + int n = strlen(str); + int j; + + resize(length + n); + for (j = length; j >= i; --j) + s[j+n] = s[j]; + memcpy(s+i, str, n); + length += n; + return this; +} + +GString *GString::insert(int i, const char *str, int lengthA) { + int j; + + resize(length + lengthA); + for (j = length; j >= i; --j) + s[j+lengthA] = s[j]; + memcpy(s+i, str, lengthA); + length += lengthA; + return this; +} + +GString *GString::del(int i, int n) { + int j; + + if (n > 0) { + if (i + n > length) { + n = length - i; + } + for (j = i; j <= length - n; ++j) { + s[j] = s[j + n]; + } + resize(length -= n); + } + return this; +} + +GString *GString::upperCase() { + int i; + + for (i = 0; i < length; ++i) { + if (islower(s[i])) + s[i] = toupper(s[i]); + } + return this; +} + +GString *GString::lowerCase() { + int i; + + for (i = 0; i < length; ++i) { + if (isupper(s[i])) + s[i] = tolower(s[i]); + } + return this; +} + +int GString::cmp(GString *str) { + int n1, n2, i, x; + char *p1, *p2; + + n1 = length; + n2 = str->length; + for (i = 0, p1 = s, p2 = str->s; i < n1 && i < n2; ++i, ++p1, ++p2) { + x = *p1 - *p2; + if (x != 0) { + return x; + } + } + return n1 - n2; +} + +int GString::cmpN(GString *str, int n) { + int n1, n2, i, x; + char *p1, *p2; + + n1 = length; + n2 = str->length; + for (i = 0, p1 = s, p2 = str->s; + i < n1 && i < n2 && i < n; + ++i, ++p1, ++p2) { + x = *p1 - *p2; + if (x != 0) { + return x; + } + } + if (i == n) { + return 0; + } + return n1 - n2; +} + +int GString::cmp(const char *sA) { + int n1, i, x; + const char *p1, *p2; + + n1 = length; + for (i = 0, p1 = s, p2 = sA; i < n1 && *p2; ++i, ++p1, ++p2) { + x = *p1 - *p2; + if (x != 0) { + return x; + } + } + if (i < n1) { + return 1; + } + if (*p2) { + return -1; + } + return 0; +} + +int GString::cmpN(const char *sA, int n) { + int n1, i, x; + const char *p1, *p2; + + n1 = length; + for (i = 0, p1 = s, p2 = sA; i < n1 && *p2 && i < n; ++i, ++p1, ++p2) { + x = *p1 - *p2; + if (x != 0) { + return x; + } + } + if (i == n) { + return 0; + } + if (i < n1) { + return 1; + } + if (*p2) { + return -1; + } + return 0; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/GString.h swftools-0.9.1/lib/pdf/xpdf/GString.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/GString.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/GString.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,136 @@ +//======================================================================== +// +// GString.h +// +// Simple variable-length string type. +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef GSTRING_H +#define GSTRING_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "gtypes.h" + +class GString { +public: + + // Create an empty string. + GString(); + + // Create a string from a C string. + GString(const char *sA); + + // Create a string from chars at . This string + // can contain null characters. + GString(const char *sA, int lengthA); + + // Create a string from chars at in . + GString(GString *str, int idx, int lengthA); + + // Copy a string. + GString(GString *str); + GString *copy() { return new GString(this); } + + // Concatenate two strings. + GString(GString *str1, GString *str2); + + // Convert an integer to a string. + static GString *fromInt(int x); + + // Create a formatted string. Similar to printf, but without the + // string overflow issues. Formatting elements consist of: + // {:[][.]} + // where: + // - is the argument number (arg 0 is the first argument + // following the format string) -- NB: args must be first used in + // order; they can be reused in any order + // - is the field width -- negative to reverse the alignment; + // starting with a leading zero to zero-fill (for integers) + // - is the number of digits to the right of the decimal + // point (for floating point numbers) + // - is one of: + // d, x, o, b -- int in decimal, hex, octal, binary + // ud, ux, uo, ub -- unsigned int + // ld, lx, lo, lb, uld, ulx, ulo, ulb -- long, unsigned long + // f, g -- double + // c -- char + // s -- string (char *) + // t -- GString * + // w -- blank space; arg determines width + // To get literal curly braces, use {{ or }}. + static GString *format(char *fmt, ...); + static GString *formatv(char *fmt, va_list argList); + + // Destructor. + ~GString(); + + // Get length. + int getLength() { return length; } + + // Get C string. + char *getCString() { return s; } + + // Get th character. + char getChar(int i) { return s[i]; } + + // Change th character. + void setChar(int i, char c) { s[i] = c; } + + // Clear string to zero length. + GString *clear(); + + // Append a character or string. + GString *append(char c); + GString *append(GString *str); + GString *append(const char *str); + GString *append(const char *str, int lengthA); + + // Append a formatted string. + GString *appendf(char *fmt, ...); + GString *appendfv(char *fmt, va_list argList); + + // Insert a character or string. + GString *insert(int i, char c); + GString *insert(int i, GString *str); + GString *insert(int i, const char *str); + GString *insert(int i, const char *str, int lengthA); + + // Delete a character or range of characters. + GString *del(int i, int n = 1); + + // Convert string to all-upper/all-lower case. + GString *upperCase(); + GString *lowerCase(); + + // Compare two strings: -1:< 0:= +1:> + int cmp(GString *str); + int cmpN(GString *str, int n); + int cmp(const char *sA); + int cmpN(const char *sA, int n); + +private: + + int length; + char *s; + + void resize(int length1); + static void formatInt(long x, char *buf, int bufSize, + GBool zeroFill, int width, int base, + char **p, int *len); + static void formatUInt(Gulong x, char *buf, int bufSize, + GBool zeroFill, int width, int base, + char **p, int *len); + static void formatDouble(double x, char *buf, int bufSize, int prec, + GBool trim, char **p, int *len); +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/gtypes.h swftools-0.9.1/lib/pdf/xpdf/gtypes.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/gtypes.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/gtypes.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,29 @@ +/* + * gtypes.h + * + * Some useful simple types. + * + * Copyright 1996-2003 Glyph & Cog, LLC + */ + +#ifndef GTYPES_H +#define GTYPES_H + +/* + * These have stupid names to avoid conflicts with some (but not all) + * C++ compilers which define them. + */ +typedef int GBool; +#define gTrue 1 +#define gFalse 0 + +/* + * These have stupid names to avoid conflicts with , + * which on various systems defines some random subset of these. + */ +typedef unsigned char Guchar; +typedef unsigned short Gushort; +typedef unsigned int Guint; +typedef unsigned long Gulong; + +#endif Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/lib/pdf/xpdf/hello.pdf and /tmp/M5qDI_SGQH/swftools-0.9.1/lib/pdf/xpdf/hello.pdf differ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/ImageOutputDev.cc swftools-0.9.1/lib/pdf/xpdf/ImageOutputDev.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/ImageOutputDev.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/ImageOutputDev.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,195 @@ +//======================================================================== +// +// ImageOutputDev.cc +// +// Copyright 1998-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gmem.h" +#include "config.h" +#include "Error.h" +#include "GfxState.h" +#include "Object.h" +#include "Stream.h" +#include "ImageOutputDev.h" + +ImageOutputDev::ImageOutputDev(char *fileRootA, GBool dumpJPEGA) { + fileRoot = copyString(fileRootA); + fileName = (char *)gmalloc(strlen(fileRoot) + 20); + dumpJPEG = dumpJPEGA; + imgNum = 0; + ok = gTrue; +} + +ImageOutputDev::~ImageOutputDev() { + gfree(fileName); + gfree(fileRoot); +} + +void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg) { + FILE *f; + int c; + int size, i; + + // dump JPEG file + if (dumpJPEG && str->getKind() == strDCT && !inlineImg) { + + // open the image file + sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum); + ++imgNum; + if (!(f = fopen(fileName, "wb"))) { + error(-1, "Couldn't open image file '%s'", fileName); + return; + } + + // initialize stream + str = ((DCTStream *)str)->getRawStream(); + str->reset(); + + // copy the stream + while ((c = str->getChar()) != EOF) + fputc(c, f); + + str->close(); + fclose(f); + + // dump PBM file + } else { + + // open the image file and write the PBM header + sprintf(fileName, "%s-%03d.pbm", fileRoot, imgNum); + ++imgNum; + if (!(f = fopen(fileName, "wb"))) { + error(-1, "Couldn't open image file '%s'", fileName); + return; + } + fprintf(f, "P4\n"); + fprintf(f, "%d %d\n", width, height); + + // initialize stream + str->reset(); + + // copy the stream + size = height * ((width + 7) / 8); + for (i = 0; i < size; ++i) { + fputc(str->getChar(), f); + } + + str->close(); + fclose(f); + } +} + +void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg) { + FILE *f; + ImageStream *imgStr; + Guchar *p; + GfxRGB rgb; + int x, y; + int c; + int size, i; + + // dump JPEG file + if (dumpJPEG && str->getKind() == strDCT && + (colorMap->getNumPixelComps() == 1 || + colorMap->getNumPixelComps() == 3) && + !inlineImg) { + + // open the image file + sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum); + ++imgNum; + if (!(f = fopen(fileName, "wb"))) { + error(-1, "Couldn't open image file '%s'", fileName); + return; + } + + // initialize stream + str = ((DCTStream *)str)->getRawStream(); + str->reset(); + + // copy the stream + while ((c = str->getChar()) != EOF) + fputc(c, f); + + str->close(); + fclose(f); + + // dump PBM file + } else if (colorMap->getNumPixelComps() == 1 && + colorMap->getBits() == 1) { + + // open the image file and write the PBM header + sprintf(fileName, "%s-%03d.pbm", fileRoot, imgNum); + ++imgNum; + if (!(f = fopen(fileName, "wb"))) { + error(-1, "Couldn't open image file '%s'", fileName); + return; + } + fprintf(f, "P4\n"); + fprintf(f, "%d %d\n", width, height); + + // initialize stream + str->reset(); + + // copy the stream + size = height * ((width + 7) / 8); + for (i = 0; i < size; ++i) { + fputc(str->getChar() ^ 0xff, f); + } + + str->close(); + fclose(f); + + // dump PPM file + } else { + + // open the image file and write the PPM header + sprintf(fileName, "%s-%03d.ppm", fileRoot, imgNum); + ++imgNum; + if (!(f = fopen(fileName, "wb"))) { + error(-1, "Couldn't open image file '%s'", fileName); + return; + } + fprintf(f, "P6\n"); + fprintf(f, "%d %d\n", width, height); + fprintf(f, "255\n"); + + // initialize stream + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); + + // for each line... + for (y = 0; y < height; ++y) { + + // write the line + p = imgStr->getLine(); + for (x = 0; x < width; ++x) { + colorMap->getRGB(p, &rgb); + fputc(colToByte(rgb.r), f); + fputc(colToByte(rgb.g), f); + fputc(colToByte(rgb.b), f); + p += colorMap->getNumPixelComps(); + } + } + delete imgStr; + + fclose(f); + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/ImageOutputDev.h swftools-0.9.1/lib/pdf/xpdf/ImageOutputDev.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/ImageOutputDev.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/ImageOutputDev.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,76 @@ +//======================================================================== +// +// ImageOutputDev.h +// +// Copyright 1998-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef IMAGEOUTPUTDEV_H +#define IMAGEOUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "gtypes.h" +#include "OutputDev.h" + +class GfxState; + +//------------------------------------------------------------------------ +// ImageOutputDev +//------------------------------------------------------------------------ + +class ImageOutputDev: public OutputDev { +public: + + // Create an OutputDev which will write images to files named + // -NNN.. Normally, all images are written as PBM + // (.pbm) or PPM (.ppm) files. If is set, JPEG images are + // written as JPEG (.jpg) files. + ImageOutputDev(char *fileRootA, GBool dumpJPEGA); + + // Destructor. + virtual ~ImageOutputDev(); + + // Check if file was successfully created. + virtual GBool isOk() { return ok; } + + // Does this device use beginType3Char/endType3Char? Otherwise, + // text in Type 3 fonts will be drawn with drawChar/drawString. + virtual GBool interpretType3Chars() { return gFalse; } + + // Does this device need non-text content? + virtual GBool needNonText() { return gTrue; } + + //---- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() { return gTrue; } + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() { return gFalse; } + + //----- image drawing + virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg); + +private: + + char *fileRoot; // root of output file names + char *fileName; // buffer for output file names + GBool dumpJPEG; // set to dump native JPEG files + int imgNum; // current image number + GBool ok; // set up ok? +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/INSTALL swftools-0.9.1/lib/pdf/xpdf/INSTALL --- swftools-0.9.2+ds1/lib/pdf/xpdf/INSTALL 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/INSTALL 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,248 @@ +Xpdf +==== + +version 3.02 +2007-feb-27 + +The Xpdf software and documentation are +copyright 1996-2007 Glyph & Cog, LLC. + +Email: derekn@foolabs.com +WWW: http://www.foolabs.com/xpdf/ + + +Compiling xpdf +-------------- + +Xpdf is written in C++ (with a little bit of C). It should work with +any ANSI-compliant C++ and C compilers. The systems and compilers +it's been tested with are listed on the xpdf web page. + +Xpdf requires the Motif (or Lesstif) toolkit. + +The following notes give specific instructions for compiling on +different systems. + + +************** +*** UNIX *** +************** + +* Install t1lib (if desired). The resulting library (libt1) and + include files (t1lib.h and t1libx.h) should be placed somewhere on + the standard search paths. Alternatively, when you configure xpdf, + you can use the following options to tell configure where to find + the t1lib files: + + --with-t1-library=PATH + --with-t1-includes=PATH + +* Install FreeType 2 (this is required). WARNING: You must have + version 2.0.5 or newer. Some older versions of XFree86 ship with an + older version of FreeType, which means you'll need to explicitly set + include and library paths to get the correct version: + + --with-freetype2-library=PATH + --with-freetype2-includes=PATH + + (The include path is the directory which contains the freetype2 + directory, i.e., do NOT include "freetype2" in the + --with-freetype2-includes path. For example, with the default + installation, the library path is /usr/local/lib and the include + path is /usr/local/include/freetype2.) + +* If you have Motif (or Lesstif) installed in a non-standard place, + you can use the following options to tell configure where to find + it: + + --with-Xm-library=PATH + --with-Xm-includes=PATH + +* Run the configure script: + + ./configure + + This should produce a set of makefiles customized for your system. + The configure script accepts the following options (in addition to + the usual things accepted by autoconf configure scripts): + + --prefix=PREFIX + Changes the directory where xpdf is installed. The default is + /usr/local. + + --enable-a4-paper + Switches the default paper size for PostScript output (xpdf + and pdftops) to A4. The default is Letter size. + + --enable-no-text-select + With this option, xpdf will not copy text. (This is only + useful on closed systems where the user can't get at the PDF + file directly.) + + --enable-opi + Enables support for generation of OPI (Open Prepress + Interface) comments with pdftops. + + --sysconfdir=DIR + Look for the system-wide xpdfrc config file in this directory. + The default is PREFIX/etc. + + --with-appdef-dir=DIR + Use the specified app-defaults directory. The default is + /usr/lib/X11/app-defaults. + + If you need to pass specific options to the C and/or C++ compiler, + you can set the CFLAGS and/or CXXFLAGS environment variables before + running the configure script. Any options given that way will be + added to the CFLAGS/CXXFLAGS used by all of the Xpdf makefiles. + +* Type 'make'. This should build the executables: + + xpdf/xpdf + xpdf/pdftops + xpdf/pdftotext + xpdf/pdfinfo + xpdf/pdffonts + xpdf/pdftoppm + xpdf/pdfimages + +* If desired, type 'make install' to install the binaries and man + pages. + +The old Makefile.config and Makefiles are no longer provided or +supported. If you really want to manually configure Xpdf (which is +not recommended), the files that need to be created are aconf.h, +Makefile, goo/Makefile, fofi/Makefile, splash/Makefile, and +xpdf/Makefile, all of which are generated from the corresponding '.in' +files. + +If you want to run a quick test, there is a tiny PDF file included +with xpdf, as misc/hello.pdf . + + +************* +*** VMS *** +************* + +* The 'stddef.h' include file which comes with older versions of gcc + may be missing a definition for wchar_t. In this case, add the + following lines: + ----- + File GNU_CC:[INCLUDE]STDDEF.H;2 + 44 /* Wide characters, not yet supported by VAXCRTL [match VAXC's + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "Object.h" +#include "Stream.h" +#include "JArithmeticDecoder.h" + +//------------------------------------------------------------------------ +// JArithmeticDecoderStates +//------------------------------------------------------------------------ + +JArithmeticDecoderStats::JArithmeticDecoderStats(int contextSizeA) { + contextSize = contextSizeA; + cxTab = (Guchar *)gmallocn(contextSize, sizeof(Guchar)); + reset(); +} + +JArithmeticDecoderStats::~JArithmeticDecoderStats() { + gfree(cxTab); +} + +JArithmeticDecoderStats *JArithmeticDecoderStats::copy() { + JArithmeticDecoderStats *stats; + + stats = new JArithmeticDecoderStats(contextSize); + memcpy(stats->cxTab, cxTab, contextSize); + return stats; +} + +void JArithmeticDecoderStats::reset() { + memset(cxTab, 0, contextSize); +} + +void JArithmeticDecoderStats::copyFrom(JArithmeticDecoderStats *stats) { + memcpy(cxTab, stats->cxTab, contextSize); +} + +void JArithmeticDecoderStats::setEntry(Guint cx, int i, int mps) { + cxTab[cx] = (i << 1) + mps; +} + +//------------------------------------------------------------------------ +// JArithmeticDecoder +//------------------------------------------------------------------------ + +Guint JArithmeticDecoder::qeTab[47] = { + 0x56010000, 0x34010000, 0x18010000, 0x0AC10000, + 0x05210000, 0x02210000, 0x56010000, 0x54010000, + 0x48010000, 0x38010000, 0x30010000, 0x24010000, + 0x1C010000, 0x16010000, 0x56010000, 0x54010000, + 0x51010000, 0x48010000, 0x38010000, 0x34010000, + 0x30010000, 0x28010000, 0x24010000, 0x22010000, + 0x1C010000, 0x18010000, 0x16010000, 0x14010000, + 0x12010000, 0x11010000, 0x0AC10000, 0x09C10000, + 0x08A10000, 0x05210000, 0x04410000, 0x02A10000, + 0x02210000, 0x01410000, 0x01110000, 0x00850000, + 0x00490000, 0x00250000, 0x00150000, 0x00090000, + 0x00050000, 0x00010000, 0x56010000 +}; + +int JArithmeticDecoder::nmpsTab[47] = { + 1, 2, 3, 4, 5, 38, 7, 8, 9, 10, 11, 12, 13, 29, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46 +}; + +int JArithmeticDecoder::nlpsTab[47] = { + 1, 6, 9, 12, 29, 33, 6, 14, 14, 14, 17, 18, 20, 21, 14, 14, + 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 46 +}; + +int JArithmeticDecoder::switchTab[47] = { + 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +JArithmeticDecoder::JArithmeticDecoder() { + str = NULL; + dataLen = 0; + limitStream = gFalse; +} + +inline Guint JArithmeticDecoder::readByte() { + if (limitStream) { + --dataLen; + if (dataLen < 0) { + return 0xff; + } + } + return (Guint)str->getChar() & 0xff; +} + +JArithmeticDecoder::~JArithmeticDecoder() { + cleanup(); +} + +void JArithmeticDecoder::start() { + buf0 = readByte(); + buf1 = readByte(); + + // INITDEC + c = (buf0 ^ 0xff) << 16; + byteIn(); + c <<= 7; + ct -= 7; + a = 0x80000000; +} + +void JArithmeticDecoder::restart(int dataLenA) { + int oldDataLen; + + oldDataLen = dataLen; + dataLen = dataLenA; + if (oldDataLen == -1) { + buf1 = readByte(); + } else if (oldDataLen <= -2) { + buf0 = readByte(); + buf1 = readByte(); + } +} + +void JArithmeticDecoder::cleanup() { + if (limitStream) { + while (dataLen > 0) { + buf0 = buf1; + buf1 = readByte(); + } + } +} + +int JArithmeticDecoder::decodeBit(Guint context, + JArithmeticDecoderStats *stats) { + int bit; + Guint qe; + int iCX, mpsCX; + + iCX = stats->cxTab[context] >> 1; + mpsCX = stats->cxTab[context] & 1; + qe = qeTab[iCX]; + a -= qe; + if (c < a) { + if (a & 0x80000000) { + bit = mpsCX; + } else { + // MPS_EXCHANGE + if (a < qe) { + bit = 1 - mpsCX; + if (switchTab[iCX]) { + stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX); + } else { + stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX; + } + } else { + bit = mpsCX; + stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX; + } + // RENORMD + do { + if (ct == 0) { + byteIn(); + } + a <<= 1; + c <<= 1; + --ct; + } while (!(a & 0x80000000)); + } + } else { + c -= a; + // LPS_EXCHANGE + if (a < qe) { + bit = mpsCX; + stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX; + } else { + bit = 1 - mpsCX; + if (switchTab[iCX]) { + stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX); + } else { + stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX; + } + } + a = qe; + // RENORMD + do { + if (ct == 0) { + byteIn(); + } + a <<= 1; + c <<= 1; + --ct; + } while (!(a & 0x80000000)); + } + return bit; +} + +int JArithmeticDecoder::decodeByte(Guint context, + JArithmeticDecoderStats *stats) { + int byte; + int i; + + byte = 0; + for (i = 0; i < 8; ++i) { + byte = (byte << 1) | decodeBit(context, stats); + } + return byte; +} + +GBool JArithmeticDecoder::decodeInt(int *x, JArithmeticDecoderStats *stats) { + int s; + Guint v; + int i; + + prev = 1; + s = decodeIntBit(stats); + if (decodeIntBit(stats)) { + if (decodeIntBit(stats)) { + if (decodeIntBit(stats)) { + if (decodeIntBit(stats)) { + if (decodeIntBit(stats)) { + v = 0; + for (i = 0; i < 32; ++i) { + v = (v << 1) | decodeIntBit(stats); + } + v += 4436; + } else { + v = 0; + for (i = 0; i < 12; ++i) { + v = (v << 1) | decodeIntBit(stats); + } + v += 340; + } + } else { + v = 0; + for (i = 0; i < 8; ++i) { + v = (v << 1) | decodeIntBit(stats); + } + v += 84; + } + } else { + v = 0; + for (i = 0; i < 6; ++i) { + v = (v << 1) | decodeIntBit(stats); + } + v += 20; + } + } else { + v = decodeIntBit(stats); + v = (v << 1) | decodeIntBit(stats); + v = (v << 1) | decodeIntBit(stats); + v = (v << 1) | decodeIntBit(stats); + v += 4; + } + } else { + v = decodeIntBit(stats); + v = (v << 1) | decodeIntBit(stats); + } + + if (s) { + if (v == 0) { + return gFalse; + } + *x = -(int)v; + } else { + *x = (int)v; + } + return gTrue; +} + +int JArithmeticDecoder::decodeIntBit(JArithmeticDecoderStats *stats) { + int bit; + + bit = decodeBit(prev, stats); + if (prev < 0x100) { + prev = (prev << 1) | bit; + } else { + prev = (((prev << 1) | bit) & 0x1ff) | 0x100; + } + return bit; +} + +Guint JArithmeticDecoder::decodeIAID(Guint codeLen, + JArithmeticDecoderStats *stats) { + Guint i; + int bit; + + prev = 1; + for (i = 0; i < codeLen; ++i) { + bit = decodeBit(prev, stats); + prev = (prev << 1) | bit; + } + return prev - (1 << codeLen); +} + +void JArithmeticDecoder::byteIn() { + if (buf0 == 0xff) { + if (buf1 > 0x8f) { + ct = 8; + } else { + buf0 = buf1; + buf1 = readByte(); + c = c + 0xfe00 - (buf0 << 9); + ct = 7; + } + } else { + buf0 = buf1; + buf1 = readByte(); + c = c + 0xff00 - (buf0 << 8); + ct = 8; + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/JArithmeticDecoder.h swftools-0.9.1/lib/pdf/xpdf/JArithmeticDecoder.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/JArithmeticDecoder.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/JArithmeticDecoder.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,109 @@ +//======================================================================== +// +// JArithmeticDecoder.h +// +// Arithmetic decoder used by the JBIG2 and JPEG2000 decoders. +// +// Copyright 2002-2004 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef JARITHMETICDECODER_H +#define JARITHMETICDECODER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +class Stream; + +//------------------------------------------------------------------------ +// JArithmeticDecoderStats +//------------------------------------------------------------------------ + +class JArithmeticDecoderStats { +public: + + JArithmeticDecoderStats(int contextSizeA); + ~JArithmeticDecoderStats(); + JArithmeticDecoderStats *copy(); + void reset(); + int getContextSize() { return contextSize; } + void copyFrom(JArithmeticDecoderStats *stats); + void setEntry(Guint cx, int i, int mps); + +private: + + Guchar *cxTab; // cxTab[cx] = (i[cx] << 1) + mps[cx] + int contextSize; + + friend class JArithmeticDecoder; +}; + +//------------------------------------------------------------------------ +// JArithmeticDecoder +//------------------------------------------------------------------------ + +class JArithmeticDecoder { +public: + + JArithmeticDecoder(); + ~JArithmeticDecoder(); + + void setStream(Stream *strA) + { str = strA; dataLen = 0; limitStream = gFalse; } + void setStream(Stream *strA, int dataLenA) + { str = strA; dataLen = dataLenA; limitStream = gTrue; } + + // Start decoding on a new stream. This fills the byte buffers and + // runs INITDEC. + void start(); + + // Restart decoding on an interrupted stream. This refills the + // buffers if needed, but does not run INITDEC. (This is used in + // JPEG 2000 streams when codeblock data is split across multiple + // packets/layers.) + void restart(int dataLenA); + + // Read any leftover data in the stream. + void cleanup(); + + // Decode one bit. + int decodeBit(Guint context, JArithmeticDecoderStats *stats); + + // Decode eight bits. + int decodeByte(Guint context, JArithmeticDecoderStats *stats); + + // Returns false for OOB, otherwise sets * and returns true. + GBool decodeInt(int *x, JArithmeticDecoderStats *stats); + + Guint decodeIAID(Guint codeLen, + JArithmeticDecoderStats *stats); + +private: + + Guint readByte(); + int decodeIntBit(JArithmeticDecoderStats *stats); + void byteIn(); + + static Guint qeTab[47]; + static int nmpsTab[47]; + static int nlpsTab[47]; + static int switchTab[47]; + + Guint buf0, buf1; + Guint c, a; + int ct; + + Guint prev; // for the integer decoder + + Stream *str; + int dataLen; + GBool limitStream; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/JBIG2Stream.cc swftools-0.9.1/lib/pdf/xpdf/JBIG2Stream.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/JBIG2Stream.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/JBIG2Stream.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,3517 @@ +//======================================================================== +// +// JBIG2Stream.cc +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +//======================================================================== +// +// Modified under the Poppler project - http://poppler.freedesktop.org +// +// All changes made under the Poppler project to this file are licensed +// under GPL version 2 or later +// +// Copyright (C) 2006 Raj Kumar +// Copyright (C) 2006 Paul Walmsley +// Copyright (C) 2006-2009 Albert Astals Cid +// Copyright (C) 2009 David Benjamin +// +// To see a description of the changes please see the Changelog file that +// came with your tarball or type make ChangeLog if you are building from git +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "GList.h" +#include "Error.h" +#include "JArithmeticDecoder.h" +#include "JBIG2Stream.h" + +//~ share these tables +#include "Stream-CCITT.h" + +//------------------------------------------------------------------------ + +static const int contextSize[4] = { 16, 13, 10, 10 }; +static const int refContextSize[2] = { 13, 10 }; + +//------------------------------------------------------------------------ +// JBIG2HuffmanTable +//------------------------------------------------------------------------ + +#define jbig2HuffmanLOW 0xfffffffd +#define jbig2HuffmanOOB 0xfffffffe +#define jbig2HuffmanEOT 0xffffffff + +struct JBIG2HuffmanTable { + int val; + Guint prefixLen; + Guint rangeLen; // can also be LOW, OOB, or EOT + Guint prefix; +}; + +static JBIG2HuffmanTable huffTableA[] = { + { 0, 1, 4, 0x000 }, + { 16, 2, 8, 0x002 }, + { 272, 3, 16, 0x006 }, + { 65808, 3, 32, 0x007 }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableB[] = { + { 0, 1, 0, 0x000 }, + { 1, 2, 0, 0x002 }, + { 2, 3, 0, 0x006 }, + { 3, 4, 3, 0x00e }, + { 11, 5, 6, 0x01e }, + { 75, 6, 32, 0x03e }, + { 0, 6, jbig2HuffmanOOB, 0x03f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableC[] = { + { 0, 1, 0, 0x000 }, + { 1, 2, 0, 0x002 }, + { 2, 3, 0, 0x006 }, + { 3, 4, 3, 0x00e }, + { 11, 5, 6, 0x01e }, + { 0, 6, jbig2HuffmanOOB, 0x03e }, + { 75, 7, 32, 0x0fe }, + { -256, 8, 8, 0x0fe }, + { -257, 8, jbig2HuffmanLOW, 0x0ff }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableD[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 0, 0x006 }, + { 4, 4, 3, 0x00e }, + { 12, 5, 6, 0x01e }, + { 76, 5, 32, 0x01f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableE[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 0, 0x006 }, + { 4, 4, 3, 0x00e }, + { 12, 5, 6, 0x01e }, + { 76, 6, 32, 0x03e }, + { -255, 7, 8, 0x07e }, + { -256, 7, jbig2HuffmanLOW, 0x07f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableF[] = { + { 0, 2, 7, 0x000 }, + { 128, 3, 7, 0x002 }, + { 256, 3, 8, 0x003 }, + { -1024, 4, 9, 0x008 }, + { -512, 4, 8, 0x009 }, + { -256, 4, 7, 0x00a }, + { -32, 4, 5, 0x00b }, + { 512, 4, 9, 0x00c }, + { 1024, 4, 10, 0x00d }, + { -2048, 5, 10, 0x01c }, + { -128, 5, 6, 0x01d }, + { -64, 5, 5, 0x01e }, + { -2049, 6, jbig2HuffmanLOW, 0x03e }, + { 2048, 6, 32, 0x03f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableG[] = { + { -512, 3, 8, 0x000 }, + { 256, 3, 8, 0x001 }, + { 512, 3, 9, 0x002 }, + { 1024, 3, 10, 0x003 }, + { -1024, 4, 9, 0x008 }, + { -256, 4, 7, 0x009 }, + { -32, 4, 5, 0x00a }, + { 0, 4, 5, 0x00b }, + { 128, 4, 7, 0x00c }, + { -128, 5, 6, 0x01a }, + { -64, 5, 5, 0x01b }, + { 32, 5, 5, 0x01c }, + { 64, 5, 6, 0x01d }, + { -1025, 5, jbig2HuffmanLOW, 0x01e }, + { 2048, 5, 32, 0x01f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableH[] = { + { 0, 2, 1, 0x000 }, + { 0, 2, jbig2HuffmanOOB, 0x001 }, + { 4, 3, 4, 0x004 }, + { -1, 4, 0, 0x00a }, + { 22, 4, 4, 0x00b }, + { 38, 4, 5, 0x00c }, + { 2, 5, 0, 0x01a }, + { 70, 5, 6, 0x01b }, + { 134, 5, 7, 0x01c }, + { 3, 6, 0, 0x03a }, + { 20, 6, 1, 0x03b }, + { 262, 6, 7, 0x03c }, + { 646, 6, 10, 0x03d }, + { -2, 7, 0, 0x07c }, + { 390, 7, 8, 0x07d }, + { -15, 8, 3, 0x0fc }, + { -5, 8, 1, 0x0fd }, + { -7, 9, 1, 0x1fc }, + { -3, 9, 0, 0x1fd }, + { -16, 9, jbig2HuffmanLOW, 0x1fe }, + { 1670, 9, 32, 0x1ff }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableI[] = { + { 0, 2, jbig2HuffmanOOB, 0x000 }, + { -1, 3, 1, 0x002 }, + { 1, 3, 1, 0x003 }, + { 7, 3, 5, 0x004 }, + { -3, 4, 1, 0x00a }, + { 43, 4, 5, 0x00b }, + { 75, 4, 6, 0x00c }, + { 3, 5, 1, 0x01a }, + { 139, 5, 7, 0x01b }, + { 267, 5, 8, 0x01c }, + { 5, 6, 1, 0x03a }, + { 39, 6, 2, 0x03b }, + { 523, 6, 8, 0x03c }, + { 1291, 6, 11, 0x03d }, + { -5, 7, 1, 0x07c }, + { 779, 7, 9, 0x07d }, + { -31, 8, 4, 0x0fc }, + { -11, 8, 2, 0x0fd }, + { -15, 9, 2, 0x1fc }, + { -7, 9, 1, 0x1fd }, + { -32, 9, jbig2HuffmanLOW, 0x1fe }, + { 3339, 9, 32, 0x1ff }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableJ[] = { + { -2, 2, 2, 0x000 }, + { 6, 2, 6, 0x001 }, + { 0, 2, jbig2HuffmanOOB, 0x002 }, + { -3, 5, 0, 0x018 }, + { 2, 5, 0, 0x019 }, + { 70, 5, 5, 0x01a }, + { 3, 6, 0, 0x036 }, + { 102, 6, 5, 0x037 }, + { 134, 6, 6, 0x038 }, + { 198, 6, 7, 0x039 }, + { 326, 6, 8, 0x03a }, + { 582, 6, 9, 0x03b }, + { 1094, 6, 10, 0x03c }, + { -21, 7, 4, 0x07a }, + { -4, 7, 0, 0x07b }, + { 4, 7, 0, 0x07c }, + { 2118, 7, 11, 0x07d }, + { -5, 8, 0, 0x0fc }, + { 5, 8, 0, 0x0fd }, + { -22, 8, jbig2HuffmanLOW, 0x0fe }, + { 4166, 8, 32, 0x0ff }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableK[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 1, 0x002 }, + { 4, 4, 0, 0x00c }, + { 5, 4, 1, 0x00d }, + { 7, 5, 1, 0x01c }, + { 9, 5, 2, 0x01d }, + { 13, 6, 2, 0x03c }, + { 17, 7, 2, 0x07a }, + { 21, 7, 3, 0x07b }, + { 29, 7, 4, 0x07c }, + { 45, 7, 5, 0x07d }, + { 77, 7, 6, 0x07e }, + { 141, 7, 32, 0x07f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableL[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 1, 0x006 }, + { 5, 5, 0, 0x01c }, + { 6, 5, 1, 0x01d }, + { 8, 6, 1, 0x03c }, + { 10, 7, 0, 0x07a }, + { 11, 7, 1, 0x07b }, + { 13, 7, 2, 0x07c }, + { 17, 7, 3, 0x07d }, + { 25, 7, 4, 0x07e }, + { 41, 8, 5, 0x0fe }, + { 73, 8, 32, 0x0ff }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableM[] = { + { 1, 1, 0, 0x000 }, + { 2, 3, 0, 0x004 }, + { 7, 3, 3, 0x005 }, + { 3, 4, 0, 0x00c }, + { 5, 4, 1, 0x00d }, + { 4, 5, 0, 0x01c }, + { 15, 6, 1, 0x03a }, + { 17, 6, 2, 0x03b }, + { 21, 6, 3, 0x03c }, + { 29, 6, 4, 0x03d }, + { 45, 6, 5, 0x03e }, + { 77, 7, 6, 0x07e }, + { 141, 7, 32, 0x07f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableN[] = { + { 0, 1, 0, 0x000 }, + { -2, 3, 0, 0x004 }, + { -1, 3, 0, 0x005 }, + { 1, 3, 0, 0x006 }, + { 2, 3, 0, 0x007 }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +static JBIG2HuffmanTable huffTableO[] = { + { 0, 1, 0, 0x000 }, + { -1, 3, 0, 0x004 }, + { 1, 3, 0, 0x005 }, + { -2, 4, 0, 0x00c }, + { 2, 4, 0, 0x00d }, + { -4, 5, 1, 0x01c }, + { 3, 5, 1, 0x01d }, + { -8, 6, 2, 0x03c }, + { 5, 6, 2, 0x03d }, + { -24, 7, 4, 0x07c }, + { 9, 7, 4, 0x07d }, + { -25, 7, jbig2HuffmanLOW, 0x07e }, + { 25, 7, 32, 0x07f }, + { 0, 0, jbig2HuffmanEOT, 0 } +}; + +//------------------------------------------------------------------------ +// JBIG2HuffmanDecoder +//------------------------------------------------------------------------ + +class JBIG2HuffmanDecoder { +public: + + JBIG2HuffmanDecoder(); + ~JBIG2HuffmanDecoder(); + void setStream(Stream *strA) { str = strA; } + + void reset(); + + // Returns false for OOB, otherwise sets * and returns true. + GBool decodeInt(int *x, JBIG2HuffmanTable *table); + + Guint readBits(Guint n); + Guint readBit(); + + // Sort the table by prefix length and assign prefix values. + void buildTable(JBIG2HuffmanTable *table, Guint len); + +private: + + Stream *str; + Guint buf; + Guint bufLen; +}; + +JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() { + str = NULL; + reset(); +} + +JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() { +} + +void JBIG2HuffmanDecoder::reset() { + buf = 0; + bufLen = 0; +} + +//~ optimize this +GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) { + Guint i, len, prefix; + + i = 0; + len = 0; + prefix = 0; + while (table[i].rangeLen != jbig2HuffmanEOT) { + while (len < table[i].prefixLen) { + prefix = (prefix << 1) | readBit(); + ++len; + } + if (prefix == table[i].prefix) { + if (table[i].rangeLen == jbig2HuffmanOOB) { + return gFalse; + } + if (table[i].rangeLen == jbig2HuffmanLOW) { + *x = table[i].val - readBits(32); + } else if (table[i].rangeLen > 0) { + *x = table[i].val + readBits(table[i].rangeLen); + } else { + *x = table[i].val; + } + return gTrue; + } + ++i; + } + return gFalse; +} + +Guint JBIG2HuffmanDecoder::readBits(Guint n) { + Guint x, mask, nLeft; + + mask = (n == 32) ? 0xffffffff : ((1 << n) - 1); + if (bufLen >= n) { + x = (buf >> (bufLen - n)) & mask; + bufLen -= n; + } else { + x = buf & ((1 << bufLen) - 1); + nLeft = n - bufLen; + bufLen = 0; + while (nLeft >= 8) { + x = (x << 8) | (str->getChar() & 0xff); + nLeft -= 8; + } + if (nLeft > 0) { + buf = str->getChar(); + bufLen = 8 - nLeft; + x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1)); + } + } + return x; +} + +Guint JBIG2HuffmanDecoder::readBit() { + if (bufLen == 0) { + buf = str->getChar(); + bufLen = 8; + } + --bufLen; + return (buf >> bufLen) & 1; +} + +void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) { + Guint i, j, k, prefix; + JBIG2HuffmanTable tab; + + // stable selection sort: + // - entries with prefixLen > 0, in ascending prefixLen order + // - entry with prefixLen = 0, rangeLen = EOT + // - all other entries with prefixLen = 0 + // (on entry, table[len] has prefixLen = 0, rangeLen = EOT) + for (i = 0; i < len; ++i) { + for (j = i; j < len && table[j].prefixLen == 0; ++j) ; + if (j == len) { + break; + } + for (k = j + 1; k < len; ++k) { + if (table[k].prefixLen > 0 && + table[k].prefixLen < table[j].prefixLen) { + j = k; + } + } + if (j != i) { + tab = table[j]; + for (k = j; k > i; --k) { + table[k] = table[k - 1]; + } + table[i] = tab; + } + } + table[i] = table[len]; + + // assign prefixes + i = 0; + prefix = 0; + table[i++].prefix = prefix++; + for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) { + prefix <<= table[i].prefixLen - table[i-1].prefixLen; + table[i].prefix = prefix++; + } +} + +//------------------------------------------------------------------------ +// JBIG2MMRDecoder +//------------------------------------------------------------------------ + +class JBIG2MMRDecoder { +public: + + JBIG2MMRDecoder(); + ~JBIG2MMRDecoder(); + void setStream(Stream *strA) { str = strA; } + void reset(); + int get2DCode(); + int getBlackCode(); + int getWhiteCode(); + Guint get24Bits(); + void skipTo(Guint length); + +private: + + Stream *str; + Guint buf; + Guint bufLen; + Guint nBytesRead; +}; + +JBIG2MMRDecoder::JBIG2MMRDecoder() { + str = NULL; + reset(); +} + +JBIG2MMRDecoder::~JBIG2MMRDecoder() { +} + +void JBIG2MMRDecoder::reset() { + buf = 0; + bufLen = 0; + nBytesRead = 0; +} + +int JBIG2MMRDecoder::get2DCode() { + const CCITTCode *p; + + if (bufLen == 0) { + buf = str->getChar() & 0xff; + bufLen = 8; + ++nBytesRead; + p = &twoDimTab1[(buf >> 1) & 0x7f]; + } else if (bufLen == 8) { + p = &twoDimTab1[(buf >> 1) & 0x7f]; + } else { + p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f]; + if (p->bits < 0 || p->bits > (int)bufLen) { + buf = (buf << 8) | (str->getChar() & 0xff); + bufLen += 8; + ++nBytesRead; + p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f]; + } + } + if (p->bits < 0) { + error(str->getPos(), "Bad two dim code in JBIG2 MMR stream"); + return 0; + } + bufLen -= p->bits; + return p->n; +} + +int JBIG2MMRDecoder::getWhiteCode() { + const CCITTCode *p; + Guint code; + + if (bufLen == 0) { + buf = str->getChar() & 0xff; + bufLen = 8; + ++nBytesRead; + } + while (1) { + if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) { + if (bufLen <= 12) { + code = buf << (12 - bufLen); + } else { + code = buf >> (bufLen - 12); + } + p = &whiteTab1[code & 0x1f]; + } else { + if (bufLen <= 9) { + code = buf << (9 - bufLen); + } else { + code = buf >> (bufLen - 9); + } + p = &whiteTab2[code & 0x1ff]; + } + if (p->bits > 0 && p->bits <= (int)bufLen) { + bufLen -= p->bits; + return p->n; + } + if (bufLen >= 12) { + break; + } + buf = (buf << 8) | (str->getChar() & 0xff); + bufLen += 8; + ++nBytesRead; + } + error(str->getPos(), "Bad white code in JBIG2 MMR stream"); + // eat a bit and return a positive number so that the caller doesn't + // go into an infinite loop + --bufLen; + return 1; +} + +int JBIG2MMRDecoder::getBlackCode() { + const CCITTCode *p; + Guint code; + + if (bufLen == 0) { + buf = str->getChar() & 0xff; + bufLen = 8; + ++nBytesRead; + } + while (1) { + if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) { + if (bufLen <= 13) { + code = buf << (13 - bufLen); + } else { + code = buf >> (bufLen - 13); + } + p = &blackTab1[code & 0x7f]; + } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) { + if (bufLen <= 12) { + code = buf << (12 - bufLen); + } else { + code = buf >> (bufLen - 12); + } + p = &blackTab2[(code & 0xff) - 64]; + } else { + if (bufLen <= 6) { + code = buf << (6 - bufLen); + } else { + code = buf >> (bufLen - 6); + } + p = &blackTab3[code & 0x3f]; + } + if (p->bits > 0 && p->bits <= (int)bufLen) { + bufLen -= p->bits; + return p->n; + } + if (bufLen >= 13) { + break; + } + buf = (buf << 8) | (str->getChar() & 0xff); + bufLen += 8; + ++nBytesRead; + } + error(str->getPos(), "Bad black code in JBIG2 MMR stream"); + // eat a bit and return a positive number so that the caller doesn't + // go into an infinite loop + --bufLen; + return 1; +} + +Guint JBIG2MMRDecoder::get24Bits() { + while (bufLen < 24) { + buf = (buf << 8) | (str->getChar() & 0xff); + bufLen += 8; + ++nBytesRead; + } + return (buf >> (bufLen - 24)) & 0xffffff; +} + +void JBIG2MMRDecoder::skipTo(Guint length) { + while (nBytesRead < length) { + str->getChar(); + ++nBytesRead; + } +} + +//------------------------------------------------------------------------ +// JBIG2Segment +//------------------------------------------------------------------------ + +enum JBIG2SegmentType { + jbig2SegBitmap, + jbig2SegSymbolDict, + jbig2SegPatternDict, + jbig2SegCodeTable +}; + +class JBIG2Segment { +public: + + JBIG2Segment(Guint segNumA) { segNum = segNumA; } + virtual ~JBIG2Segment() {} + void setSegNum(Guint segNumA) { segNum = segNumA; } + Guint getSegNum() { return segNum; } + virtual JBIG2SegmentType getType() = 0; + +private: + + Guint segNum; +}; + +//------------------------------------------------------------------------ +// JBIG2Bitmap +//------------------------------------------------------------------------ + +struct JBIG2BitmapPtr { + Guchar *p; + int shift; + int x; +}; + +class JBIG2Bitmap: public JBIG2Segment { +public: + + JBIG2Bitmap(Guint segNumA, int wA, int hA); + virtual ~JBIG2Bitmap(); + virtual JBIG2SegmentType getType() { return jbig2SegBitmap; } + JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); } + JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA); + void expand(int newH, Guint pixel); + void clearToZero(); + void clearToOne(); + int getWidth() { return w; } + int getHeight() { return h; } + int getPixel(int x, int y) + { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 : + (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; } + void setPixel(int x, int y) + { data[y * line + (x >> 3)] |= 1 << (7 - (x & 7)); } + void clearPixel(int x, int y) + { data[y * line + (x >> 3)] &= 0x7f7f >> (x & 7); } + void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr); + int nextPixel(JBIG2BitmapPtr *ptr); + void duplicateRow(int yDest, int ySrc); + void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp); + Guchar *getDataPtr() { return data; } + int getDataSize() { return h * line; } + GBool isOk() { return data != NULL; } + +private: + + JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap); + + int w, h, line; + Guchar *data; +}; + +JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA): + JBIG2Segment(segNumA) +{ + w = wA; + h = hA; + line = (wA + 7) >> 3; + if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { + data = NULL; + return; + } + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)gmalloc(h * line + 1); + data[h * line] = 0; +} + +JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap): + JBIG2Segment(segNumA) +{ + w = bitmap->w; + h = bitmap->h; + line = bitmap->line; + if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { + data = NULL; + return; + } + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)gmalloc(h * line + 1); + memcpy(data, bitmap->data, h * line); + data[h * line] = 0; +} + +JBIG2Bitmap::~JBIG2Bitmap() { + gfree(data); +} + +//~ optimize this +JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) { + JBIG2Bitmap *slice; + Guint xx, yy; + + slice = new JBIG2Bitmap(0, wA, hA); + slice->clearToZero(); + for (yy = 0; yy < hA; ++yy) { + for (xx = 0; xx < wA; ++xx) { + if (getPixel(x + xx, y + yy)) { + slice->setPixel(xx, yy); + } + } + } + return slice; +} + +void JBIG2Bitmap::expand(int newH, Guint pixel) { + if (newH <= h || line <= 0 || newH >= (INT_MAX - 1) / line) { + error(-1, "invalid width/height"); + gfree(data); + data = NULL; + return; + } + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)grealloc(data, newH * line + 1); + if (pixel) { + memset(data + h * line, 0xff, (newH - h) * line); + } else { + memset(data + h * line, 0x00, (newH - h) * line); + } + h = newH; + data[h * line] = 0; +} + +void JBIG2Bitmap::clearToZero() { + memset(data, 0, h * line); +} + +void JBIG2Bitmap::clearToOne() { + memset(data, 0xff, h * line); +} + +inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) { + if (y < 0 || y >= h || x >= w) { + ptr->p = NULL; + } else if (x < 0) { + ptr->p = &data[y * line]; + ptr->shift = 7; + ptr->x = x; + } else { + ptr->p = &data[y * line + (x >> 3)]; + ptr->shift = 7 - (x & 7); + ptr->x = x; + } +} + +inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) { + int pix; + + if (!ptr->p) { + pix = 0; + } else if (ptr->x < 0) { + ++ptr->x; + pix = 0; + } else { + pix = (*ptr->p >> ptr->shift) & 1; + if (++ptr->x == w) { + ptr->p = NULL; + } else if (ptr->shift == 0) { + ++ptr->p; + ptr->shift = 7; + } else { + --ptr->shift; + } + } + return pix; +} + +void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) { + memcpy(data + yDest * line, data + ySrc * line, line); +} + +void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y, + Guint combOp) { + int x0, x1, y0, y1, xx, yy; + Guchar *srcPtr, *destPtr; + Guint src0, src1, src, dest, s1, s2, m1, m2, m3; + GBool oneByte; + + if (y < 0) { + y0 = -y; + } else { + y0 = 0; + } + if (y + bitmap->h > h) { + y1 = h - y; + } else { + y1 = bitmap->h; + } + if (y0 >= y1) { + return; + } + + if (x >= 0) { + x0 = x & ~7; + } else { + x0 = 0; + } + x1 = x + bitmap->w; + if (x1 > w) { + x1 = w; + } + if (x0 >= x1) { + return; + } + + s1 = x & 7; + s2 = 8 - s1; + m1 = 0xff >> (x1 & 7); + m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7)); + m3 = (0xff >> s1) & m2; + + oneByte = x0 == ((x1 - 1) & ~7); + + for (yy = y0; yy < y1; ++yy) { + + // one byte per line -- need to mask both left and right side + if (oneByte) { + if (x >= 0) { + destPtr = data + (y + yy) * line + (x >> 3); + srcPtr = bitmap->data + yy * bitmap->line; + dest = *destPtr; + src1 = *srcPtr; + switch (combOp) { + case 0: // or + dest |= (src1 >> s1) & m2; + break; + case 1: // and + dest &= ((0xff00 | src1) >> s1) | m1; + break; + case 2: // xor + dest ^= (src1 >> s1) & m2; + break; + case 3: // xnor + dest ^= ((src1 ^ 0xff) >> s1) & m2; + break; + case 4: // replace + dest = (dest & ~m3) | ((src1 >> s1) & m3); + break; + } + *destPtr = dest; + } else { + destPtr = data + (y + yy) * line; + srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3); + dest = *destPtr; + src1 = *srcPtr; + switch (combOp) { + case 0: // or + dest |= src1 & m2; + break; + case 1: // and + dest &= src1 | m1; + break; + case 2: // xor + dest ^= src1 & m2; + break; + case 3: // xnor + dest ^= (src1 ^ 0xff) & m2; + break; + case 4: // replace + dest = (src1 & m2) | (dest & m1); + break; + } + *destPtr = dest; + } + + // multiple bytes per line -- need to mask left side of left-most + // byte and right side of right-most byte + } else { + + // left-most byte + if (x >= 0) { + destPtr = data + (y + yy) * line + (x >> 3); + srcPtr = bitmap->data + yy * bitmap->line; + src1 = *srcPtr++; + dest = *destPtr; + switch (combOp) { + case 0: // or + dest |= src1 >> s1; + break; + case 1: // and + dest &= (0xff00 | src1) >> s1; + break; + case 2: // xor + dest ^= src1 >> s1; + break; + case 3: // xnor + dest ^= (src1 ^ 0xff) >> s1; + break; + case 4: // replace + dest = (dest & (0xff << s2)) | (src1 >> s1); + break; + } + *destPtr++ = dest; + xx = x0 + 8; + } else { + destPtr = data + (y + yy) * line; + srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3); + src1 = *srcPtr++; + xx = x0; + } + + // middle bytes + for (; xx < x1 - 8; xx += 8) { + dest = *destPtr; + src0 = src1; + src1 = *srcPtr++; + src = (((src0 << 8) | src1) >> s1) & 0xff; + switch (combOp) { + case 0: // or + dest |= src; + break; + case 1: // and + dest &= src; + break; + case 2: // xor + dest ^= src; + break; + case 3: // xnor + dest ^= src ^ 0xff; + break; + case 4: // replace + dest = src; + break; + } + *destPtr++ = dest; + } + + // right-most byte + // note: this last byte (src1) may not actually be used, depending + // on the values of s1, m1, and m2 - and in fact, it may be off + // the edge of the source bitmap, which means we need to allocate + // one extra guard byte at the end of each bitmap + dest = *destPtr; + src0 = src1; + src1 = *srcPtr++; + src = (((src0 << 8) | src1) >> s1) & 0xff; + switch (combOp) { + case 0: // or + dest |= src & m2; + break; + case 1: // and + dest &= src | m1; + break; + case 2: // xor + dest ^= src & m2; + break; + case 3: // xnor + dest ^= (src ^ 0xff) & m2; + break; + case 4: // replace + dest = (src & m2) | (dest & m1); + break; + } + *destPtr = dest; + } + } +} + +//------------------------------------------------------------------------ +// JBIG2SymbolDict +//------------------------------------------------------------------------ + +class JBIG2SymbolDict: public JBIG2Segment { +public: + + JBIG2SymbolDict(Guint segNumA, Guint sizeA); + virtual ~JBIG2SymbolDict(); + virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; } + Guint getSize() { return size; } + void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; } + JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; } + GBool isOk() { return bitmaps != NULL; } + void setGenericRegionStats(JArithmeticDecoderStats *stats) + { genericRegionStats = stats; } + void setRefinementRegionStats(JArithmeticDecoderStats *stats) + { refinementRegionStats = stats; } + JArithmeticDecoderStats *getGenericRegionStats() + { return genericRegionStats; } + JArithmeticDecoderStats *getRefinementRegionStats() + { return refinementRegionStats; } + +private: + + Guint size; + JBIG2Bitmap **bitmaps; + JArithmeticDecoderStats *genericRegionStats; + JArithmeticDecoderStats *refinementRegionStats; +}; + +JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA): + JBIG2Segment(segNumA) +{ + size = sizeA; + bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); + genericRegionStats = NULL; + refinementRegionStats = NULL; +} + +JBIG2SymbolDict::~JBIG2SymbolDict() { + Guint i; + + for (i = 0; i < size; ++i) { + delete bitmaps[i]; + } + gfree(bitmaps); + if (genericRegionStats) { + delete genericRegionStats; + } + if (refinementRegionStats) { + delete refinementRegionStats; + } +} + +//------------------------------------------------------------------------ +// JBIG2PatternDict +//------------------------------------------------------------------------ + +class JBIG2PatternDict: public JBIG2Segment { +public: + + JBIG2PatternDict(Guint segNumA, Guint sizeA); + virtual ~JBIG2PatternDict(); + virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; } + Guint getSize() { return size; } + void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; } + JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; } + +private: + + Guint size; + JBIG2Bitmap **bitmaps; +}; + +JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA): + JBIG2Segment(segNumA) +{ + size = sizeA; + bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); +} + +JBIG2PatternDict::~JBIG2PatternDict() { + Guint i; + + for (i = 0; i < size; ++i) { + delete bitmaps[i]; + } + gfree(bitmaps); +} + +//------------------------------------------------------------------------ +// JBIG2CodeTable +//------------------------------------------------------------------------ + +class JBIG2CodeTable: public JBIG2Segment { +public: + + JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA); + virtual ~JBIG2CodeTable(); + virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; } + JBIG2HuffmanTable *getHuffTable() { return table; } + +private: + + JBIG2HuffmanTable *table; +}; + +JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA): + JBIG2Segment(segNumA) +{ + table = tableA; +} + +JBIG2CodeTable::~JBIG2CodeTable() { + gfree(table); +} + +//------------------------------------------------------------------------ +// JBIG2Stream +//------------------------------------------------------------------------ + +JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA): + FilterStream(strA) +{ + pageBitmap = NULL; + + arithDecoder = new JArithmeticDecoder(); + genericRegionStats = new JArithmeticDecoderStats(1 << 1); + refinementRegionStats = new JArithmeticDecoderStats(1 << 1); + iadhStats = new JArithmeticDecoderStats(1 << 9); + iadwStats = new JArithmeticDecoderStats(1 << 9); + iaexStats = new JArithmeticDecoderStats(1 << 9); + iaaiStats = new JArithmeticDecoderStats(1 << 9); + iadtStats = new JArithmeticDecoderStats(1 << 9); + iaitStats = new JArithmeticDecoderStats(1 << 9); + iafsStats = new JArithmeticDecoderStats(1 << 9); + iadsStats = new JArithmeticDecoderStats(1 << 9); + iardxStats = new JArithmeticDecoderStats(1 << 9); + iardyStats = new JArithmeticDecoderStats(1 << 9); + iardwStats = new JArithmeticDecoderStats(1 << 9); + iardhStats = new JArithmeticDecoderStats(1 << 9); + iariStats = new JArithmeticDecoderStats(1 << 9); + iaidStats = new JArithmeticDecoderStats(1 << 1); + huffDecoder = new JBIG2HuffmanDecoder(); + mmrDecoder = new JBIG2MMRDecoder(); + + globalsStreamA->copy(&globalsStream); + segments = globalSegments = NULL; + curStr = NULL; + dataPtr = dataEnd = NULL; +} + +JBIG2Stream::~JBIG2Stream() { + close(); + globalsStream.free(); + delete arithDecoder; + delete genericRegionStats; + delete refinementRegionStats; + delete iadhStats; + delete iadwStats; + delete iaexStats; + delete iaaiStats; + delete iadtStats; + delete iaitStats; + delete iafsStats; + delete iadsStats; + delete iardxStats; + delete iardyStats; + delete iardwStats; + delete iardhStats; + delete iariStats; + delete iaidStats; + delete huffDecoder; + delete mmrDecoder; + delete str; +} + +void JBIG2Stream::reset() { + // read the globals stream + globalSegments = new GList(); + if (globalsStream.isStream()) { + segments = globalSegments; + curStr = globalsStream.getStream(); + curStr->reset(); + arithDecoder->setStream(curStr); + huffDecoder->setStream(curStr); + mmrDecoder->setStream(curStr); + readSegments(); + curStr->close(); + } + + // read the main stream + segments = new GList(); + curStr = str; + curStr->reset(); + arithDecoder->setStream(curStr); + huffDecoder->setStream(curStr); + mmrDecoder->setStream(curStr); + readSegments(); + + if (pageBitmap) { + dataPtr = pageBitmap->getDataPtr(); + dataEnd = dataPtr + pageBitmap->getDataSize(); + } else { + dataPtr = dataEnd = NULL; + } +} + +void JBIG2Stream::close() { + if (pageBitmap) { + delete pageBitmap; + pageBitmap = NULL; + } + if (segments) { + deleteGList(segments, JBIG2Segment); + segments = NULL; + } + if (globalSegments) { + deleteGList(globalSegments, JBIG2Segment); + globalSegments = NULL; + } + dataPtr = dataEnd = NULL; + FilterStream::close(); +} + +int JBIG2Stream::getChar() { + if (dataPtr && dataPtr < dataEnd) { + return (*dataPtr++ ^ 0xff) & 0xff; + } + return EOF; +} + +int JBIG2Stream::lookChar() { + if (dataPtr && dataPtr < dataEnd) { + return (*dataPtr ^ 0xff) & 0xff; + } + return EOF; +} + +GString *JBIG2Stream::getPSFilter(int psLevel, char *indent) { + return NULL; +} + +GBool JBIG2Stream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +void JBIG2Stream::readSegments() { + Guint segNum, segFlags, segType, page, segLength; + Guint refFlags, nRefSegs; + Guint *refSegs; + int segDataPos; + int c1, c2, c3; + Guint i; + + while (readULong(&segNum)) { + + // segment header flags + if (!readUByte(&segFlags)) { + goto eofError1; + } + segType = segFlags & 0x3f; + + // referred-to segment count and retention flags + if (!readUByte(&refFlags)) { + goto eofError1; + } + nRefSegs = refFlags >> 5; + if (nRefSegs == 7) { + if ((c1 = curStr->getChar()) == EOF || + (c2 = curStr->getChar()) == EOF || + (c3 = curStr->getChar()) == EOF) { + goto eofError1; + } + refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3; + nRefSegs = refFlags & 0x1fffffff; + for (i = 0; i < (nRefSegs + 9) >> 3; ++i) { + c1 = curStr->getChar(); + } + } + + // referred-to segment numbers + refSegs = (Guint *)gmallocn(nRefSegs, sizeof(Guint)); + if (segNum <= 256) { + for (i = 0; i < nRefSegs; ++i) { + if (!readUByte(&refSegs[i])) { + goto eofError2; + } + } + } else if (segNum <= 65536) { + for (i = 0; i < nRefSegs; ++i) { + if (!readUWord(&refSegs[i])) { + goto eofError2; + } + } + } else { + for (i = 0; i < nRefSegs; ++i) { + if (!readULong(&refSegs[i])) { + goto eofError2; + } + } + } + + // segment page association + if (segFlags & 0x40) { + if (!readULong(&page)) { + goto eofError2; + } + } else { + if (!readUByte(&page)) { + goto eofError2; + } + } + + // segment data length + if (!readULong(&segLength)) { + goto eofError2; + } + + // read the segment data + switch (segType) { + case 0: + if (!readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs)) { + goto syntaxError; + } + break; + case 4: + readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs); + break; + case 6: + readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs); + break; + case 7: + readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs); + break; + case 16: + readPatternDictSeg(segNum, segLength); + break; + case 20: + readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength, + refSegs, nRefSegs); + break; + case 22: + readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength, + refSegs, nRefSegs); + break; + case 23: + readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength, + refSegs, nRefSegs); + break; + case 36: + readGenericRegionSeg(segNum, gFalse, gFalse, segLength); + break; + case 38: + readGenericRegionSeg(segNum, gTrue, gFalse, segLength); + break; + case 39: + readGenericRegionSeg(segNum, gTrue, gTrue, segLength); + break; + case 40: + readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength, + refSegs, nRefSegs); + break; + case 42: + readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength, + refSegs, nRefSegs); + break; + case 43: + readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength, + refSegs, nRefSegs); + break; + case 48: + readPageInfoSeg(segLength); + break; + case 50: + readEndOfStripeSeg(segLength); + break; + case 52: + readProfilesSeg(segLength); + break; + case 53: + readCodeTableSeg(segNum, segLength); + break; + case 62: + readExtensionSeg(segLength); + break; + default: + error(getPos(), "Unknown segment type in JBIG2 stream"); + for (i = 0; i < segLength; ++i) { + if ((c1 = curStr->getChar()) == EOF) { + goto eofError2; + } + } + break; + } + + // Make sure the segment handler read all of the bytes in the + // segment data, unless this segment is marked as having an + // unknown length (section 7.2.7 of the JBIG2 Final Committee Draft) + + if (segLength != 0xffffffff) { + + int segExtraBytes = segDataPos + segLength - getPos(); + if (segExtraBytes > 0) { + + // If we didn't read all of the bytes in the segment data, + // indicate an error, and throw away the rest of the data. + + // v.3.1.01.13 of the LuraTech PDF Compressor Server will + // sometimes generate an extraneous NULL byte at the end of + // arithmetic-coded symbol dictionary segments when numNewSyms + // == 0. Segments like this often occur for blank pages. + + error(getPos(), "%d extraneous byte%s after segment", + segExtraBytes, (segExtraBytes > 1) ? "s" : ""); + + // Burn through the remaining bytes -- inefficient, but + // hopefully we're not doing this much + + int trash; + for (int i = segExtraBytes; i > 0; i--) { + readByte(&trash); + } + + } else if (segExtraBytes < 0) { + + // If we read more bytes than we should have, according to the + // segment length field, note an error. + + error(getPos(), "Previous segment handler read too many bytes"); + + } + + } + + gfree(refSegs); + } + + return; + + syntaxError: + gfree(refSegs); + return; + + eofError2: + gfree(refSegs); + eofError1: + error(getPos(), "Unexpected EOF in JBIG2 stream"); +} + +GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length, + Guint *refSegs, Guint nRefSegs) { + JBIG2SymbolDict *symbolDict; + JBIG2HuffmanTable *huffDHTable, *huffDWTable; + JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable; + JBIG2Segment *seg; + GList *codeTables; + JBIG2SymbolDict *inputSymbolDict; + Guint flags, sdTemplate, sdrTemplate, huff, refAgg; + Guint huffDH, huffDW, huffBMSize, huffAggInst; + Guint contextUsed, contextRetained; + int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2]; + Guint numExSyms, numNewSyms, numInputSyms, symCodeLen; + JBIG2Bitmap **bitmaps; + JBIG2Bitmap *collBitmap, *refBitmap; + Guint *symWidths; + Guint symHeight, symWidth, totalWidth, x, symID; + int dh, dw, refAggNum, refDX, refDY, bmSize; + GBool ex; + int run, cnt; + Guint i, j, k; + Guchar *p; + + // symbol dictionary flags + if (!readUWord(&flags)) { + goto eofError; + } + sdTemplate = (flags >> 10) & 3; + sdrTemplate = (flags >> 12) & 1; + huff = flags & 1; + refAgg = (flags >> 1) & 1; + huffDH = (flags >> 2) & 3; + huffDW = (flags >> 4) & 3; + huffBMSize = (flags >> 6) & 1; + huffAggInst = (flags >> 7) & 1; + contextUsed = (flags >> 8) & 1; + contextRetained = (flags >> 9) & 1; + + // symbol dictionary AT flags + if (!huff) { + if (sdTemplate == 0) { + if (!readByte(&sdATX[0]) || + !readByte(&sdATY[0]) || + !readByte(&sdATX[1]) || + !readByte(&sdATY[1]) || + !readByte(&sdATX[2]) || + !readByte(&sdATY[2]) || + !readByte(&sdATX[3]) || + !readByte(&sdATY[3])) { + goto eofError; + } + } else { + if (!readByte(&sdATX[0]) || + !readByte(&sdATY[0])) { + goto eofError; + } + } + } + + // symbol dictionary refinement AT flags + if (refAgg && !sdrTemplate) { + if (!readByte(&sdrATX[0]) || + !readByte(&sdrATY[0]) || + !readByte(&sdrATX[1]) || + !readByte(&sdrATY[1])) { + goto eofError; + } + } + + // SDNUMEXSYMS and SDNUMNEWSYMS + if (!readULong(&numExSyms) || !readULong(&numNewSyms)) { + goto eofError; + } + + // get referenced segments: input symbol dictionaries and code tables + codeTables = new GList(); + numInputSyms = 0; + for (i = 0; i < nRefSegs; ++i) { + seg = findSegment(refSegs[i]); + if (seg->getType() == jbig2SegSymbolDict) { + numInputSyms += ((JBIG2SymbolDict *)seg)->getSize(); + } else if (seg->getType() == jbig2SegCodeTable) { + codeTables->append(seg); + } + } + + // compute symbol code length + symCodeLen = 0; + i = 1; + while (i < numInputSyms + numNewSyms) { + ++symCodeLen; + i <<= 1; + } + + // get the input symbol bitmaps + bitmaps = (JBIG2Bitmap **)gmallocn(numInputSyms + numNewSyms, + sizeof(JBIG2Bitmap *)); + for (i = 0; i < numInputSyms + numNewSyms; ++i) { + bitmaps[i] = NULL; + } + k = 0; + inputSymbolDict = NULL; + for (i = 0; i < nRefSegs; ++i) { + seg = findSegment(refSegs[i]); + if (seg->getType() == jbig2SegSymbolDict) { + inputSymbolDict = (JBIG2SymbolDict *)seg; + for (j = 0; j < inputSymbolDict->getSize(); ++j) { + bitmaps[k++] = inputSymbolDict->getBitmap(j); + } + } + } + + // get the Huffman tables + huffDHTable = huffDWTable = NULL; // make gcc happy + huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy + i = 0; + if (huff) { + if (huffDH == 0) { + huffDHTable = huffTableD; + } else if (huffDH == 1) { + huffDHTable = huffTableE; + } else { + huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDW == 0) { + huffDWTable = huffTableB; + } else if (huffDW == 1) { + huffDWTable = huffTableC; + } else { + huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffBMSize == 0) { + huffBMSizeTable = huffTableA; + } else { + huffBMSizeTable = + ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffAggInst == 0) { + huffAggInstTable = huffTableA; + } else { + huffAggInstTable = + ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + } + delete codeTables; + + // set up the Huffman decoder + if (huff) { + huffDecoder->reset(); + + // set up the arithmetic decoder + } else { + if (contextUsed && inputSymbolDict) { + resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats()); + } else { + resetGenericStats(sdTemplate, NULL); + } + resetIntStats(symCodeLen); + arithDecoder->start(); + } + + // set up the arithmetic decoder for refinement/aggregation + if (refAgg) { + if (contextUsed && inputSymbolDict) { + resetRefinementStats(sdrTemplate, + inputSymbolDict->getRefinementRegionStats()); + } else { + resetRefinementStats(sdrTemplate, NULL); + } + } + + // allocate symbol widths storage + symWidths = NULL; + if (huff && !refAgg) { + symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint)); + } + + symHeight = 0; + i = 0; + while (i < numNewSyms) { + + // read the height class delta height + if (huff) { + huffDecoder->decodeInt(&dh, huffDHTable); + } else { + arithDecoder->decodeInt(&dh, iadhStats); + } + if (dh < 0 && (Guint)-dh >= symHeight) { + error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary"); + goto syntaxError; + } + symHeight += dh; + symWidth = 0; + totalWidth = 0; + j = i; + + // read the symbols in this height class + while (1) { + + // read the delta width + if (huff) { + if (!huffDecoder->decodeInt(&dw, huffDWTable)) { + break; + } + } else { + if (!arithDecoder->decodeInt(&dw, iadwStats)) { + break; + } + } + if (dw < 0 && (Guint)-dw >= symWidth) { + error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary"); + goto syntaxError; + } + symWidth += dw; + + // using a collective bitmap, so don't read a bitmap here + if (huff && !refAgg) { + symWidths[i] = symWidth; + totalWidth += symWidth; + + // refinement/aggregate coding + } else if (refAgg) { + if (huff) { + if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) { + break; + } + } else { + if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) { + break; + } + } +#if 0 //~ This special case was added about a year before the final draft + //~ of the JBIG2 spec was released. I have encountered some old + //~ JBIG2 images that predate it. + if (0) { +#else + if (refAggNum == 1) { +#endif + if (huff) { + symID = huffDecoder->readBits(symCodeLen); + huffDecoder->decodeInt(&refDX, huffTableO); + huffDecoder->decodeInt(&refDY, huffTableO); + huffDecoder->decodeInt(&bmSize, huffTableA); + huffDecoder->reset(); + arithDecoder->start(); + } else { + symID = arithDecoder->decodeIAID(symCodeLen, iaidStats); + arithDecoder->decodeInt(&refDX, iardxStats); + arithDecoder->decodeInt(&refDY, iardyStats); + } + refBitmap = bitmaps[symID]; + bitmaps[numInputSyms + i] = + readGenericRefinementRegion(symWidth, symHeight, + sdrTemplate, gFalse, + refBitmap, refDX, refDY, + sdrATX, sdrATY); + //~ do we need to use the bmSize value here (in Huffman mode)? + } else { + bitmaps[numInputSyms + i] = + readTextRegion(huff, gTrue, symWidth, symHeight, + refAggNum, 0, numInputSyms + i, NULL, + symCodeLen, bitmaps, 0, 0, 0, 1, 0, + huffTableF, huffTableH, huffTableK, huffTableO, + huffTableO, huffTableO, huffTableO, huffTableA, + sdrTemplate, sdrATX, sdrATY); + } + + // non-ref/agg coding + } else { + bitmaps[numInputSyms + i] = + readGenericBitmap(gFalse, symWidth, symHeight, + sdTemplate, gFalse, gFalse, NULL, + sdATX, sdATY, 0); + } + + ++i; + } + + // read the collective bitmap + if (huff && !refAgg) { + huffDecoder->decodeInt(&bmSize, huffBMSizeTable); + huffDecoder->reset(); + if (bmSize == 0) { + collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight); + bmSize = symHeight * ((totalWidth + 7) >> 3); + p = collBitmap->getDataPtr(); + for (k = 0; k < (Guint)bmSize; ++k) { + *p++ = curStr->getChar(); + } + } else { + collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight, + 0, gFalse, gFalse, NULL, NULL, NULL, + bmSize); + } + x = 0; + for (; j < i; ++j) { + bitmaps[numInputSyms + j] = + collBitmap->getSlice(x, 0, symWidths[j], symHeight); + x += symWidths[j]; + } + delete collBitmap; + } + } + + // create the symbol dict object + symbolDict = new JBIG2SymbolDict(segNum, numExSyms); + + // exported symbol list + i = j = 0; + ex = gFalse; + while (i < numInputSyms + numNewSyms) { + if (huff) { + huffDecoder->decodeInt(&run, huffTableA); + } else { + arithDecoder->decodeInt(&run, iaexStats); + } + if (ex) { + for (cnt = 0; cnt < run; ++cnt) { + symbolDict->setBitmap(j++, bitmaps[i++]->copy()); + } + } else { + i += run; + } + ex = !ex; + } + + for (i = 0; i < numNewSyms; ++i) { + delete bitmaps[numInputSyms + i]; + } + gfree(bitmaps); + if (symWidths) { + gfree(symWidths); + } + + // save the arithmetic decoder stats + if (!huff && contextRetained) { + symbolDict->setGenericRegionStats(genericRegionStats->copy()); + if (refAgg) { + symbolDict->setRefinementRegionStats(refinementRegionStats->copy()); + } + } + + // store the new symbol dict + segments->append(symbolDict); + + return gTrue; + + syntaxError: + for (i = 0; i < numNewSyms; ++i) { + if (bitmaps[numInputSyms + i]) { + delete bitmaps[numInputSyms + i]; + } + } + gfree(bitmaps); + if (symWidths) { + gfree(symWidths); + } + return gFalse; + + eofError: + error(getPos(), "Unexpected EOF in JBIG2 stream"); + return gFalse; +} + +void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + Guint *refSegs, Guint nRefSegs) { + JBIG2Bitmap *bitmap; + JBIG2HuffmanTable runLengthTab[36]; + JBIG2HuffmanTable *symCodeTab; + JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable; + JBIG2HuffmanTable *huffRDWTable, *huffRDHTable; + JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable; + JBIG2Segment *seg; + GList *codeTables; + JBIG2SymbolDict *symbolDict; + JBIG2Bitmap **syms; + Guint w, h, x, y, segInfoFlags, extCombOp; + Guint flags, huff, refine, logStrips, refCorner, transposed; + Guint combOp, defPixel, templ; + int sOffset; + Guint huffFlags, huffFS, huffDS, huffDT; + Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize; + Guint numInstances, numSyms, symCodeLen; + int atx[2], aty[2]; + Guint i, k, kk; + int j; + + // region segment info field + if (!readULong(&w) || !readULong(&h) || + !readULong(&x) || !readULong(&y) || + !readUByte(&segInfoFlags)) { + goto eofError; + } + extCombOp = segInfoFlags & 7; + + // rest of the text region header + if (!readUWord(&flags)) { + goto eofError; + } + huff = flags & 1; + refine = (flags >> 1) & 1; + logStrips = (flags >> 2) & 3; + refCorner = (flags >> 4) & 3; + transposed = (flags >> 6) & 1; + combOp = (flags >> 7) & 3; + defPixel = (flags >> 9) & 1; + sOffset = (flags >> 10) & 0x1f; + if (sOffset & 0x10) { + sOffset |= -1 - 0x0f; + } + templ = (flags >> 15) & 1; + huffFS = huffDS = huffDT = 0; // make gcc happy + huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy + if (huff) { + if (!readUWord(&huffFlags)) { + goto eofError; + } + huffFS = huffFlags & 3; + huffDS = (huffFlags >> 2) & 3; + huffDT = (huffFlags >> 4) & 3; + huffRDW = (huffFlags >> 6) & 3; + huffRDH = (huffFlags >> 8) & 3; + huffRDX = (huffFlags >> 10) & 3; + huffRDY = (huffFlags >> 12) & 3; + huffRSize = (huffFlags >> 14) & 1; + } + if (refine && templ == 0) { + if (!readByte(&atx[0]) || !readByte(&aty[0]) || + !readByte(&atx[1]) || !readByte(&aty[1])) { + goto eofError; + } + } + if (!readULong(&numInstances)) { + goto eofError; + } + + // get symbol dictionaries and tables + codeTables = new GList(); + numSyms = 0; + for (i = 0; i < nRefSegs; ++i) { + // This is need by bug 12014, returning gFalse makes it not crash + // but we end up with a empty page while acroread is able to render + // part of it + if ((seg = findSegment(refSegs[i]))) { + if (seg->getType() == jbig2SegSymbolDict) { + numSyms += ((JBIG2SymbolDict *)seg)->getSize(); + } else if (seg->getType() == jbig2SegCodeTable) { + codeTables->append(seg); + } + } else { + error(getPos(), "Invalid segment reference in JBIG2 text region"); + } + } + symCodeLen = 0; + i = 1; + while (i < numSyms) { + ++symCodeLen; + i <<= 1; + } + if (huff && symCodeLen == 0) { + symCodeLen = 1; + } + + // get the symbol bitmaps + syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *)); + kk = 0; + for (i = 0; i < nRefSegs; ++i) { + if ((seg = findSegment(refSegs[i]))) { + if (seg->getType() == jbig2SegSymbolDict) { + symbolDict = (JBIG2SymbolDict *)seg; + for (k = 0; k < symbolDict->getSize(); ++k) { + syms[kk++] = symbolDict->getBitmap(k); + } + } + } + } + + // get the Huffman tables + huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy + huffRDWTable = huffRDHTable = NULL; // make gcc happy + huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy + i = 0; + if (huff) { + if (huffFS == 0) { + huffFSTable = huffTableF; + } else if (huffFS == 1) { + huffFSTable = huffTableG; + } else { + huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDS == 0) { + huffDSTable = huffTableH; + } else if (huffDS == 1) { + huffDSTable = huffTableI; + } else if (huffDS == 2) { + huffDSTable = huffTableJ; + } else { + huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDT == 0) { + huffDTTable = huffTableK; + } else if (huffDT == 1) { + huffDTTable = huffTableL; + } else if (huffDT == 2) { + huffDTTable = huffTableM; + } else { + huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDW == 0) { + huffRDWTable = huffTableN; + } else if (huffRDW == 1) { + huffRDWTable = huffTableO; + } else { + huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDH == 0) { + huffRDHTable = huffTableN; + } else if (huffRDH == 1) { + huffRDHTable = huffTableO; + } else { + huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDX == 0) { + huffRDXTable = huffTableN; + } else if (huffRDX == 1) { + huffRDXTable = huffTableO; + } else { + huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDY == 0) { + huffRDYTable = huffTableN; + } else if (huffRDY == 1) { + huffRDYTable = huffTableO; + } else { + huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRSize == 0) { + huffRSizeTable = huffTableA; + } else { + huffRSizeTable = + ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + } + delete codeTables; + + // symbol ID Huffman decoding table + if (huff) { + huffDecoder->reset(); + for (i = 0; i < 32; ++i) { + runLengthTab[i].val = i; + runLengthTab[i].prefixLen = huffDecoder->readBits(4); + runLengthTab[i].rangeLen = 0; + } + runLengthTab[32].val = 0x103; + runLengthTab[32].prefixLen = huffDecoder->readBits(4); + runLengthTab[32].rangeLen = 2; + runLengthTab[33].val = 0x203; + runLengthTab[33].prefixLen = huffDecoder->readBits(4); + runLengthTab[33].rangeLen = 3; + runLengthTab[34].val = 0x20b; + runLengthTab[34].prefixLen = huffDecoder->readBits(4); + runLengthTab[34].rangeLen = 7; + runLengthTab[35].prefixLen = 0; + runLengthTab[35].rangeLen = jbig2HuffmanEOT; + huffDecoder->buildTable(runLengthTab, 35); + symCodeTab = (JBIG2HuffmanTable *)gmallocn(numSyms + 1, + sizeof(JBIG2HuffmanTable)); + for (i = 0; i < numSyms; ++i) { + symCodeTab[i].val = i; + symCodeTab[i].rangeLen = 0; + } + i = 0; + while (i < numSyms) { + huffDecoder->decodeInt(&j, runLengthTab); + if (j > 0x200) { + for (j -= 0x200; j && i < numSyms; --j) { + symCodeTab[i++].prefixLen = 0; + } + } else if (j > 0x100) { + for (j -= 0x100; j && i < numSyms; --j) { + symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen; + ++i; + } + } else { + symCodeTab[i++].prefixLen = j; + } + } + symCodeTab[numSyms].prefixLen = 0; + symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT; + huffDecoder->buildTable(symCodeTab, numSyms); + huffDecoder->reset(); + + // set up the arithmetic decoder + } else { + symCodeTab = NULL; + resetIntStats(symCodeLen); + arithDecoder->start(); + } + if (refine) { + resetRefinementStats(templ, NULL); + } + + bitmap = readTextRegion(huff, refine, w, h, numInstances, + logStrips, numSyms, symCodeTab, symCodeLen, syms, + defPixel, combOp, transposed, refCorner, sOffset, + huffFSTable, huffDSTable, huffDTTable, + huffRDWTable, huffRDHTable, + huffRDXTable, huffRDYTable, huffRSizeTable, + templ, atx, aty); + + gfree(syms); + + if (bitmap) { + // combine the region bitmap into the page bitmap + if (imm) { + if (pageH == 0xffffffff && y + h > curPageH) { + pageBitmap->expand(y + h, pageDefPixel); + } + pageBitmap->combine(bitmap, x, y, extCombOp); + delete bitmap; + + // store the region bitmap + } else { + bitmap->setSegNum(segNum); + segments->append(bitmap); + } + } + + // clean up the Huffman decoder + if (huff) { + gfree(symCodeTab); + } + + return; + + eofError: + error(getPos(), "Unexpected EOF in JBIG2 stream"); +} + +JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine, + int w, int h, + Guint numInstances, + Guint logStrips, + int numSyms, + JBIG2HuffmanTable *symCodeTab, + Guint symCodeLen, + JBIG2Bitmap **syms, + Guint defPixel, Guint combOp, + Guint transposed, Guint refCorner, + int sOffset, + JBIG2HuffmanTable *huffFSTable, + JBIG2HuffmanTable *huffDSTable, + JBIG2HuffmanTable *huffDTTable, + JBIG2HuffmanTable *huffRDWTable, + JBIG2HuffmanTable *huffRDHTable, + JBIG2HuffmanTable *huffRDXTable, + JBIG2HuffmanTable *huffRDYTable, + JBIG2HuffmanTable *huffRSizeTable, + Guint templ, + int *atx, int *aty) { + JBIG2Bitmap *bitmap; + JBIG2Bitmap *symbolBitmap; + Guint strips; + int t, dt, tt, s, ds, sFirst, j; + int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize; + Guint symID, inst, bw, bh; + + strips = 1 << logStrips; + + // allocate the bitmap + bitmap = new JBIG2Bitmap(0, w, h); + if (!bitmap->isOk()) { + delete bitmap; + return NULL; + } + if (defPixel) { + bitmap->clearToOne(); + } else { + bitmap->clearToZero(); + } + + // decode initial T value + if (huff) { + huffDecoder->decodeInt(&t, huffDTTable); + } else { + arithDecoder->decodeInt(&t, iadtStats); + } + t *= -(int)strips; + + inst = 0; + sFirst = 0; + while (inst < numInstances) { + + // decode delta-T + if (huff) { + huffDecoder->decodeInt(&dt, huffDTTable); + } else { + arithDecoder->decodeInt(&dt, iadtStats); + } + t += dt * strips; + + // first S value + if (huff) { + huffDecoder->decodeInt(&ds, huffFSTable); + } else { + arithDecoder->decodeInt(&ds, iafsStats); + } + sFirst += ds; + s = sFirst; + + // read the instances + while (1) { + + // T value + if (strips == 1) { + dt = 0; + } else if (huff) { + dt = huffDecoder->readBits(logStrips); + } else { + arithDecoder->decodeInt(&dt, iaitStats); + } + tt = t + dt; + + // symbol ID + if (huff) { + if (symCodeTab) { + huffDecoder->decodeInt(&j, symCodeTab); + symID = (Guint)j; + } else { + symID = huffDecoder->readBits(symCodeLen); + } + } else { + symID = arithDecoder->decodeIAID(symCodeLen, iaidStats); + } + + if (symID >= (Guint)numSyms) { + error(getPos(), "Invalid symbol number in JBIG2 text region"); + } else { + + // get the symbol bitmap + symbolBitmap = NULL; + if (refine) { + if (huff) { + ri = (int)huffDecoder->readBit(); + } else { + arithDecoder->decodeInt(&ri, iariStats); + } + } else { + ri = 0; + } + if (ri) { + GBool decodeSuccess; + if (huff) { + decodeSuccess = huffDecoder->decodeInt(&rdw, huffRDWTable); + decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdh, huffRDHTable); + decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdx, huffRDXTable); + decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdy, huffRDYTable); + decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&bmSize, huffRSizeTable); + huffDecoder->reset(); + arithDecoder->start(); + } else { + decodeSuccess = arithDecoder->decodeInt(&rdw, iardwStats); + decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdh, iardhStats); + decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdx, iardxStats); + decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdy, iardyStats); + } + + if (decodeSuccess && syms[symID]) + { + refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx; + refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy; + + symbolBitmap = + readGenericRefinementRegion(rdw + syms[symID]->getWidth(), + rdh + syms[symID]->getHeight(), + templ, gFalse, syms[symID], + refDX, refDY, atx, aty); + } + //~ do we need to use the bmSize value here (in Huffman mode)? + } else { + symbolBitmap = syms[symID]; + } + + if (symbolBitmap) { + // combine the symbol bitmap into the region bitmap + //~ something is wrong here - refCorner shouldn't degenerate into + //~ two cases + bw = symbolBitmap->getWidth() - 1; + bh = symbolBitmap->getHeight() - 1; + if (transposed) { + switch (refCorner) { + case 0: // bottom left + bitmap->combine(symbolBitmap, tt, s, combOp); + break; + case 1: // top left + bitmap->combine(symbolBitmap, tt, s, combOp); + break; + case 2: // bottom right + bitmap->combine(symbolBitmap, tt - bw, s, combOp); + break; + case 3: // top right + bitmap->combine(symbolBitmap, tt - bw, s, combOp); + break; + } + s += bh; + } else { + switch (refCorner) { + case 0: // bottom left + bitmap->combine(symbolBitmap, s, tt - bh, combOp); + break; + case 1: // top left + bitmap->combine(symbolBitmap, s, tt, combOp); + break; + case 2: // bottom right + bitmap->combine(symbolBitmap, s, tt - bh, combOp); + break; + case 3: // top right + bitmap->combine(symbolBitmap, s, tt, combOp); + break; + } + s += bw; + } + if (ri) { + delete symbolBitmap; + } + } else { + // NULL symbolBitmap only happens on error + delete bitmap; + return NULL; + } + } + + // next instance + ++inst; + + // next S value + if (huff) { + if (!huffDecoder->decodeInt(&ds, huffDSTable)) { + break; + } + } else { + if (!arithDecoder->decodeInt(&ds, iadsStats)) { + break; + } + } + s += sOffset + ds; + } + } + + return bitmap; +} + +void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) { + JBIG2PatternDict *patternDict; + JBIG2Bitmap *bitmap; + Guint flags, patternW, patternH, grayMax, templ, mmr; + int atx[4], aty[4]; + Guint i, x; + + // halftone dictionary flags, pattern width and height, max gray value + if (!readUByte(&flags) || + !readUByte(&patternW) || + !readUByte(&patternH) || + !readULong(&grayMax)) { + goto eofError; + } + templ = (flags >> 1) & 3; + mmr = flags & 1; + + // set up the arithmetic decoder + if (!mmr) { + resetGenericStats(templ, NULL); + arithDecoder->start(); + } + + // read the bitmap + atx[0] = -(int)patternW; aty[0] = 0; + atx[1] = -3; aty[1] = -1; + atx[2] = 2; aty[2] = -2; + atx[3] = -2; aty[3] = -2; + bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH, + templ, gFalse, gFalse, NULL, + atx, aty, length - 7); + + // create the pattern dict object + patternDict = new JBIG2PatternDict(segNum, grayMax + 1); + + // split up the bitmap + x = 0; + for (i = 0; i <= grayMax; ++i) { + patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH)); + x += patternW; + } + + // free memory + delete bitmap; + + // store the new pattern dict + segments->append(patternDict); + + return; + + eofError: + error(getPos(), "Unexpected EOF in JBIG2 stream"); +} + +void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + Guint *refSegs, Guint nRefSegs) { + JBIG2Bitmap *bitmap; + JBIG2Segment *seg; + JBIG2PatternDict *patternDict; + JBIG2Bitmap *skipBitmap; + Guint *grayImg; + JBIG2Bitmap *grayBitmap; + JBIG2Bitmap *patternBitmap; + Guint w, h, x, y, segInfoFlags, extCombOp; + Guint flags, mmr, templ, enableSkip, combOp; + Guint gridW, gridH, stepX, stepY, patW, patH; + int atx[4], aty[4]; + int gridX, gridY, xx, yy, bit, j; + Guint bpp, m, n, i; + + // region segment info field + if (!readULong(&w) || !readULong(&h) || + !readULong(&x) || !readULong(&y) || + !readUByte(&segInfoFlags)) { + goto eofError; + } + extCombOp = segInfoFlags & 7; + + // rest of the halftone region header + if (!readUByte(&flags)) { + goto eofError; + } + mmr = flags & 1; + templ = (flags >> 1) & 3; + enableSkip = (flags >> 3) & 1; + combOp = (flags >> 4) & 7; + if (!readULong(&gridW) || !readULong(&gridH) || + !readLong(&gridX) || !readLong(&gridY) || + !readUWord(&stepX) || !readUWord(&stepY)) { + goto eofError; + } + if (w == 0 || h == 0 || w >= INT_MAX / h) { + error(getPos(), "Bad bitmap size in JBIG2 halftone segment"); + return; + } + if (gridH == 0 || gridW >= INT_MAX / gridH) { + error(getPos(), "Bad grid size in JBIG2 halftone segment"); + return; + } + + // get pattern dictionary + if (nRefSegs != 1) { + error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); + return; + } + seg = findSegment(refSegs[0]); + if (seg->getType() != jbig2SegPatternDict) { + error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); + return; + } + patternDict = (JBIG2PatternDict *)seg; + bpp = 0; + i = 1; + while (i < patternDict->getSize()) { + ++bpp; + i <<= 1; + } + patW = patternDict->getBitmap(0)->getWidth(); + patH = patternDict->getBitmap(0)->getHeight(); + + // set up the arithmetic decoder + if (!mmr) { + resetGenericStats(templ, NULL); + arithDecoder->start(); + } + + // allocate the bitmap + bitmap = new JBIG2Bitmap(segNum, w, h); + if (flags & 0x80) { // HDEFPIXEL + bitmap->clearToOne(); + } else { + bitmap->clearToZero(); + } + + // compute the skip bitmap + skipBitmap = NULL; + if (enableSkip) { + skipBitmap = new JBIG2Bitmap(0, gridW, gridH); + skipBitmap->clearToZero(); + for (m = 0; m < gridH; ++m) { + for (n = 0; n < gridW; ++n) { + xx = gridX + m * stepY + n * stepX; + yy = gridY + m * stepX - n * stepY; + if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w || + ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) { + skipBitmap->setPixel(n, m); + } + } + } + } + + // read the gray-scale image + grayImg = (Guint *)gmallocn(gridW * gridH, sizeof(Guint)); + memset(grayImg, 0, gridW * gridH * sizeof(Guint)); + atx[0] = templ <= 1 ? 3 : 2; aty[0] = -1; + atx[1] = -3; aty[1] = -1; + atx[2] = 2; aty[2] = -2; + atx[3] = -2; aty[3] = -2; + for (j = bpp - 1; j >= 0; --j) { + grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse, + enableSkip, skipBitmap, atx, aty, -1); + i = 0; + for (m = 0; m < gridH; ++m) { + for (n = 0; n < gridW; ++n) { + bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1); + grayImg[i] = (grayImg[i] << 1) | bit; + ++i; + } + } + delete grayBitmap; + } + + // decode the image + i = 0; + for (m = 0; m < gridH; ++m) { + xx = gridX + m * stepY; + yy = gridY + m * stepX; + for (n = 0; n < gridW; ++n) { + if (!(enableSkip && skipBitmap->getPixel(n, m))) { + patternBitmap = patternDict->getBitmap(grayImg[i]); + bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp); + } + xx += stepX; + yy -= stepY; + ++i; + } + } + + gfree(grayImg); + if (skipBitmap) { + delete skipBitmap; + } + + // combine the region bitmap into the page bitmap + if (imm) { + if (pageH == 0xffffffff && y + h > curPageH) { + pageBitmap->expand(y + h, pageDefPixel); + } + pageBitmap->combine(bitmap, x, y, extCombOp); + delete bitmap; + + // store the region bitmap + } else { + segments->append(bitmap); + } + + return; + + eofError: + error(getPos(), "Unexpected EOF in JBIG2 stream"); +} + +void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length) { + JBIG2Bitmap *bitmap; + Guint w, h, x, y, segInfoFlags, extCombOp; + Guint flags, mmr, templ, tpgdOn; + int atx[4], aty[4]; + + // region segment info field + if (!readULong(&w) || !readULong(&h) || + !readULong(&x) || !readULong(&y) || + !readUByte(&segInfoFlags)) { + goto eofError; + } + extCombOp = segInfoFlags & 7; + + // rest of the generic region segment header + if (!readUByte(&flags)) { + goto eofError; + } + mmr = flags & 1; + templ = (flags >> 1) & 3; + tpgdOn = (flags >> 3) & 1; + + // AT flags + if (!mmr) { + if (templ == 0) { + if (!readByte(&atx[0]) || + !readByte(&aty[0]) || + !readByte(&atx[1]) || + !readByte(&aty[1]) || + !readByte(&atx[2]) || + !readByte(&aty[2]) || + !readByte(&atx[3]) || + !readByte(&aty[3])) { + goto eofError; + } + } else { + if (!readByte(&atx[0]) || + !readByte(&aty[0])) { + goto eofError; + } + } + } + + // set up the arithmetic decoder + if (!mmr) { + resetGenericStats(templ, NULL); + arithDecoder->start(); + } + + // read the bitmap + bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse, + NULL, atx, aty, mmr ? 0 : length - 18); + + // combine the region bitmap into the page bitmap + if (imm) { + if (pageH == 0xffffffff && y + h > curPageH) { + pageBitmap->expand(y + h, pageDefPixel); + } + pageBitmap->combine(bitmap, x, y, extCombOp); + delete bitmap; + + // store the region bitmap + } else { + bitmap->setSegNum(segNum); + segments->append(bitmap); + } + + return; + + eofError: + error(getPos(), "Unexpected EOF in JBIG2 stream"); +} + +JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h, + int templ, GBool tpgdOn, + GBool useSkip, JBIG2Bitmap *skip, + int *atx, int *aty, + int mmrDataLength) { + JBIG2Bitmap *bitmap; + GBool ltp; + Guint ltpCX, cx, cx0, cx1, cx2; + JBIG2BitmapPtr cxPtr0, cxPtr1; + JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3; + int *refLine, *codingLine; + int code1, code2, code3; + int x, y, a0, pix, i, refI, codingI; + + bitmap = new JBIG2Bitmap(0, w, h); + bitmap->clearToZero(); + + //----- MMR decode + + if (mmr) { + + mmrDecoder->reset(); + refLine = (int *)gmallocn(w + 2, sizeof(int)); + codingLine = (int *)gmallocn(w + 2, sizeof(int)); + codingLine[0] = codingLine[1] = w; + + for (y = 0; y < h; ++y) { + + // copy coding line to ref line + for (i = 0; codingLine[i] < w; ++i) { + refLine[i] = codingLine[i]; + } + refLine[i] = refLine[i + 1] = w; + + // decode a line + refI = 0; // b1 = refLine[refI] + codingI = 0; // a1 = codingLine[codingI] + a0 = 0; + do { + code1 = mmrDecoder->get2DCode(); + switch (code1) { + case twoDimPass: + if (refLine[refI] < w) { + a0 = refLine[refI + 1]; + refI += 2; + } + break; + case twoDimHoriz: + if (codingI & 1) { + code1 = 0; + do { + code1 += code3 = mmrDecoder->getBlackCode(); + } while (code3 >= 64); + code2 = 0; + do { + code2 += code3 = mmrDecoder->getWhiteCode(); + } while (code3 >= 64); + } else { + code1 = 0; + do { + code1 += code3 = mmrDecoder->getWhiteCode(); + } while (code3 >= 64); + code2 = 0; + do { + code2 += code3 = mmrDecoder->getBlackCode(); + } while (code3 >= 64); + } + if (code1 > 0 || code2 > 0) { + a0 = codingLine[codingI++] = a0 + code1; + a0 = codingLine[codingI++] = a0 + code2; + while (refLine[refI] <= a0 && refLine[refI] < w) { + refI += 2; + } + } + break; + case twoDimVert0: + a0 = codingLine[codingI++] = refLine[refI]; + if (refLine[refI] < w) { + ++refI; + } + break; + case twoDimVertR1: + a0 = codingLine[codingI++] = refLine[refI] + 1; + if (refLine[refI] < w) { + ++refI; + while (refLine[refI] <= a0 && refLine[refI] < w) { + refI += 2; + } + } + break; + case twoDimVertR2: + a0 = codingLine[codingI++] = refLine[refI] + 2; + if (refLine[refI] < w) { + ++refI; + while (refLine[refI] <= a0 && refLine[refI] < w) { + refI += 2; + } + } + break; + case twoDimVertR3: + a0 = codingLine[codingI++] = refLine[refI] + 3; + if (refLine[refI] < w) { + ++refI; + while (refLine[refI] <= a0 && refLine[refI] < w) { + refI += 2; + } + } + break; + case twoDimVertL1: + a0 = codingLine[codingI++] = refLine[refI] - 1; + if (refI > 0) { + --refI; + } else { + ++refI; + } + while (refLine[refI] <= a0 && refLine[refI] < w) { + refI += 2; + } + break; + case twoDimVertL2: + a0 = codingLine[codingI++] = refLine[refI] - 2; + if (refI > 0) { + --refI; + } else { + ++refI; + } + while (refLine[refI] <= a0 && refLine[refI] < w) { + refI += 2; + } + break; + case twoDimVertL3: + a0 = codingLine[codingI++] = refLine[refI] - 3; + if (refI > 0) { + --refI; + } else { + ++refI; + } + while (refLine[refI] <= a0 && refLine[refI] < w) { + refI += 2; + } + break; + default: + error(getPos(), "Illegal code in JBIG2 MMR bitmap data"); + break; + } + } while (a0 < w); + codingLine[codingI++] = w; + + // convert the run lengths to a bitmap line + i = 0; + while (codingLine[i] < w) { + for (x = codingLine[i]; x < codingLine[i+1]; ++x) { + bitmap->setPixel(x, y); + } + i += 2; + } + } + + if (mmrDataLength >= 0) { + mmrDecoder->skipTo(mmrDataLength); + } else { + if (mmrDecoder->get24Bits() != 0x001001) { + error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data"); + } + } + + gfree(refLine); + gfree(codingLine); + + //----- arithmetic decode + + } else { + // set up the typical row context + ltpCX = 0; // make gcc happy + if (tpgdOn) { + switch (templ) { + case 0: + ltpCX = 0x3953; // 001 11001 0101 0011 + break; + case 1: + ltpCX = 0x079a; // 0011 11001 101 0 + break; + case 2: + ltpCX = 0x0e3; // 001 1100 01 1 + break; + case 3: + ltpCX = 0x18a; // 01100 0101 1 + break; + } + } + + ltp = 0; + cx = cx0 = cx1 = cx2 = 0; // make gcc happy + for (y = 0; y < h; ++y) { + + // check for a "typical" (duplicate) row + if (tpgdOn) { + if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) { + ltp = !ltp; + } + if (ltp) { + bitmap->duplicateRow(y, y-1); + continue; + } + } + + switch (templ) { + case 0: + + // set up the context + bitmap->getPixelPtr(0, y-2, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(0, y-1, &cxPtr1); + cx1 = bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); + cx2 = 0; + bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); + bitmap->getPixelPtr(atx[1], y + aty[1], &atPtr1); + bitmap->getPixelPtr(atx[2], y + aty[2], &atPtr2); + bitmap->getPixelPtr(atx[3], y + aty[3], &atPtr3); + + // decode the row + for (x = 0; x < w; ++x) { + + // build the context + cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) | + (bitmap->nextPixel(&atPtr0) << 3) | + (bitmap->nextPixel(&atPtr1) << 2) | + (bitmap->nextPixel(&atPtr2) << 1) | + bitmap->nextPixel(&atPtr3); + + // check for a skipped pixel + if (useSkip && skip->getPixel(x, y)) { + pix = 0; + + // decode the pixel + } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { + bitmap->setPixel(x, y); + } + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07; + cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; + cx2 = ((cx2 << 1) | pix) & 0x0f; + } + break; + + case 1: + + // set up the context + bitmap->getPixelPtr(0, y-2, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); + cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(0, y-1, &cxPtr1); + cx1 = bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); + cx2 = 0; + bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); + + // decode the row + for (x = 0; x < w; ++x) { + + // build the context + cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) | + bitmap->nextPixel(&atPtr0); + + // check for a skipped pixel + if (useSkip && skip->getPixel(x, y)) { + pix = 0; + + // decode the pixel + } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { + bitmap->setPixel(x, y); + } + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x0f; + cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; + cx2 = ((cx2 << 1) | pix) & 0x07; + } + break; + + case 2: + + // set up the context + bitmap->getPixelPtr(0, y-2, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(0, y-1, &cxPtr1); + cx1 = bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); + cx2 = 0; + bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); + + // decode the row + for (x = 0; x < w; ++x) { + + // build the context + cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) | + bitmap->nextPixel(&atPtr0); + + // check for a skipped pixel + if (useSkip && skip->getPixel(x, y)) { + pix = 0; + + // decode the pixel + } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { + bitmap->setPixel(x, y); + } + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07; + cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x0f; + cx2 = ((cx2 << 1) | pix) & 0x03; + } + break; + + case 3: + + // set up the context + bitmap->getPixelPtr(0, y-1, &cxPtr1); + cx1 = bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); + cx2 = 0; + bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); + + // decode the row + for (x = 0; x < w; ++x) { + + // build the context + cx = (cx1 << 5) | (cx2 << 1) | + bitmap->nextPixel(&atPtr0); + + // check for a skipped pixel + if (useSkip && skip->getPixel(x, y)) { + pix = 0; + + // decode the pixel + } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { + bitmap->setPixel(x, y); + } + + // update the context + cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; + cx2 = ((cx2 << 1) | pix) & 0x0f; + } + break; + } + } + } + + return bitmap; +} + +void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + Guint *refSegs, + Guint nRefSegs) { + JBIG2Bitmap *bitmap, *refBitmap; + Guint w, h, x, y, segInfoFlags, extCombOp; + Guint flags, templ, tpgrOn; + int atx[2], aty[2]; + JBIG2Segment *seg; + + // region segment info field + if (!readULong(&w) || !readULong(&h) || + !readULong(&x) || !readULong(&y) || + !readUByte(&segInfoFlags)) { + goto eofError; + } + extCombOp = segInfoFlags & 7; + + // rest of the generic refinement region segment header + if (!readUByte(&flags)) { + goto eofError; + } + templ = flags & 1; + tpgrOn = (flags >> 1) & 1; + + // AT flags + if (!templ) { + if (!readByte(&atx[0]) || !readByte(&aty[0]) || + !readByte(&atx[1]) || !readByte(&aty[1])) { + goto eofError; + } + } + + // resize the page bitmap if needed + if (nRefSegs == 0 || imm) { + if (pageH == 0xffffffff && y + h > curPageH) { + pageBitmap->expand(y + h, pageDefPixel); + } + } + + // get referenced bitmap + if (nRefSegs > 1) { + error(getPos(), "Bad reference in JBIG2 generic refinement segment"); + return; + } + if (nRefSegs == 1) { + seg = findSegment(refSegs[0]); + if (seg->getType() != jbig2SegBitmap) { + error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment"); + return; + } + refBitmap = (JBIG2Bitmap *)seg; + } else { + refBitmap = pageBitmap->getSlice(x, y, w, h); + } + + // set up the arithmetic decoder + resetRefinementStats(templ, NULL); + arithDecoder->start(); + + // read + bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn, + refBitmap, 0, 0, atx, aty); + + // combine the region bitmap into the page bitmap + if (imm) { + pageBitmap->combine(bitmap, x, y, extCombOp); + delete bitmap; + + // store the region bitmap + } else { + bitmap->setSegNum(segNum); + segments->append(bitmap); + } + + // delete the referenced bitmap + if (nRefSegs == 1) { + discardSegment(refSegs[0]); + } else { + delete refBitmap; + } + + return; + + eofError: + error(getPos(), "Unexpected EOF in JBIG2 stream"); +} + +JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h, + int templ, GBool tpgrOn, + JBIG2Bitmap *refBitmap, + int refDX, int refDY, + int *atx, int *aty) { + JBIG2Bitmap *bitmap; + GBool ltp; + Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2; + JBIG2BitmapPtr cxPtr0 = {0}; + JBIG2BitmapPtr cxPtr1 = {0}; + JBIG2BitmapPtr cxPtr2 = {0}; + JBIG2BitmapPtr cxPtr3 = {0}; + JBIG2BitmapPtr cxPtr4 = {0}; + JBIG2BitmapPtr cxPtr5 = {0}; + JBIG2BitmapPtr cxPtr6 = {0}; + JBIG2BitmapPtr tpgrCXPtr0 = {0}; + JBIG2BitmapPtr tpgrCXPtr1 = {0}; + JBIG2BitmapPtr tpgrCXPtr2 = {0}; + int x, y, pix; + + bitmap = new JBIG2Bitmap(0, w, h); + if (!bitmap->isOk()) + { + delete bitmap; + return NULL; + } + bitmap->clearToZero(); + + // set up the typical row context + if (templ) { + ltpCX = 0x008; + } else { + ltpCX = 0x0010; + } + + ltp = 0; + for (y = 0; y < h; ++y) { + + if (templ) { + + // set up the context + bitmap->getPixelPtr(0, y-1, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(-1, y, &cxPtr1); + refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3); + cx3 = refBitmap->nextPixel(&cxPtr3); + cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3); + refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4); + cx4 = refBitmap->nextPixel(&cxPtr4); + + // set up the typical prediction context + tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy + if (tpgrOn) { + refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0); + tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1); + tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2); + tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); + } + + for (x = 0; x < w; ++x) { + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7; + cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7; + cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3; + + if (tpgrOn) { + // update the typical predictor context + tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7; + tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7; + tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7; + + // check for a "typical" pixel + if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) { + ltp = !ltp; + } + if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) { + bitmap->clearPixel(x, y); + continue; + } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) { + bitmap->setPixel(x, y); + continue; + } + } + + // build the context + cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) | + (refBitmap->nextPixel(&cxPtr2) << 5) | + (cx3 << 2) | cx4; + + // decode the pixel + if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) { + bitmap->setPixel(x, y); + } + } + + } else { + + // set up the context + bitmap->getPixelPtr(0, y-1, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(-1, y, &cxPtr1); + refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2); + cx2 = refBitmap->nextPixel(&cxPtr2); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3); + cx3 = refBitmap->nextPixel(&cxPtr3); + cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3); + refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4); + cx4 = refBitmap->nextPixel(&cxPtr4); + cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4); + bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5); + refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6); + + // set up the typical prediction context + tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy + if (tpgrOn) { + refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0); + tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1); + tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2); + tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); + } + + for (x = 0; x < w; ++x) { + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3; + cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3; + cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7; + cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7; + + if (tpgrOn) { + // update the typical predictor context + tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7; + tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7; + tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7; + + // check for a "typical" pixel + if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) { + ltp = !ltp; + } + if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) { + bitmap->clearPixel(x, y); + continue; + } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) { + bitmap->setPixel(x, y); + continue; + } + } + + // build the context + cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) | + (cx2 << 8) | (cx3 << 5) | (cx4 << 2) | + (bitmap->nextPixel(&cxPtr5) << 1) | + refBitmap->nextPixel(&cxPtr6); + + // decode the pixel + if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) { + bitmap->setPixel(x, y); + } + } + } + } + + return bitmap; +} + +void JBIG2Stream::readPageInfoSeg(Guint length) { + Guint xRes, yRes, flags, striping; + + if (!readULong(&pageW) || !readULong(&pageH) || + !readULong(&xRes) || !readULong(&yRes) || + !readUByte(&flags) || !readUWord(&striping)) { + goto eofError; + } + pageDefPixel = (flags >> 2) & 1; + defCombOp = (flags >> 3) & 3; + + // allocate the page bitmap + if (pageH == 0xffffffff) { + curPageH = striping & 0x7fff; + } else { + curPageH = pageH; + } + pageBitmap = new JBIG2Bitmap(0, pageW, curPageH); + + if (!pageBitmap->isOk()) { + delete pageBitmap; + pageBitmap = NULL; + return; + } + + // default pixel value + if (pageDefPixel) { + pageBitmap->clearToOne(); + } else { + pageBitmap->clearToZero(); + } + + return; + + eofError: + error(getPos(), "Unexpected EOF in JBIG2 stream"); +} + +void JBIG2Stream::readEndOfStripeSeg(Guint length) { + Guint i; + + // skip the segment + for (i = 0; i < length; ++i) { + curStr->getChar(); + } +} + +void JBIG2Stream::readProfilesSeg(Guint length) { + Guint i; + + // skip the segment + for (i = 0; i < length; ++i) { + curStr->getChar(); + } +} + +void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) { + JBIG2HuffmanTable *huffTab; + Guint flags, oob, prefixBits, rangeBits; + int lowVal, highVal, val; + Guint huffTabSize, i; + + if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) { + goto eofError; + } + oob = flags & 1; + prefixBits = ((flags >> 1) & 7) + 1; + rangeBits = ((flags >> 4) & 7) + 1; + + huffDecoder->reset(); + huffTabSize = 8; + huffTab = (JBIG2HuffmanTable *) + gmallocn(huffTabSize, sizeof(JBIG2HuffmanTable)); + i = 0; + val = lowVal; + while (val < highVal) { + if (i == huffTabSize) { + huffTabSize *= 2; + huffTab = (JBIG2HuffmanTable *) + greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable)); + } + huffTab[i].val = val; + huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); + huffTab[i].rangeLen = huffDecoder->readBits(rangeBits); + val += 1 << huffTab[i].rangeLen; + ++i; + } + if (i + oob + 3 > huffTabSize) { + huffTabSize = i + oob + 3; + huffTab = (JBIG2HuffmanTable *) + greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable)); + } + huffTab[i].val = lowVal - 1; + huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); + huffTab[i].rangeLen = jbig2HuffmanLOW; + ++i; + huffTab[i].val = highVal; + huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); + huffTab[i].rangeLen = 32; + ++i; + if (oob) { + huffTab[i].val = 0; + huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); + huffTab[i].rangeLen = jbig2HuffmanOOB; + ++i; + } + huffTab[i].val = 0; + huffTab[i].prefixLen = 0; + huffTab[i].rangeLen = jbig2HuffmanEOT; + huffDecoder->buildTable(huffTab, i); + + // create and store the new table segment + segments->append(new JBIG2CodeTable(segNum, huffTab)); + + return; + + eofError: + error(getPos(), "Unexpected EOF in JBIG2 stream"); +} + +void JBIG2Stream::readExtensionSeg(Guint length) { + Guint i; + + // skip the segment + for (i = 0; i < length; ++i) { + curStr->getChar(); + } +} + +JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) { + JBIG2Segment *seg; + int i; + + for (i = 0; i < globalSegments->getLength(); ++i) { + seg = (JBIG2Segment *)globalSegments->get(i); + if (seg->getSegNum() == segNum) { + return seg; + } + } + for (i = 0; i < segments->getLength(); ++i) { + seg = (JBIG2Segment *)segments->get(i); + if (seg->getSegNum() == segNum) { + return seg; + } + } + return NULL; +} + +void JBIG2Stream::discardSegment(Guint segNum) { + JBIG2Segment *seg; + int i; + + for (i = 0; i < globalSegments->getLength(); ++i) { + seg = (JBIG2Segment *)globalSegments->get(i); + if (seg->getSegNum() == segNum) { + globalSegments->del(i); + return; + } + } + for (i = 0; i < segments->getLength(); ++i) { + seg = (JBIG2Segment *)segments->get(i); + if (seg->getSegNum() == segNum) { + segments->del(i); + return; + } + } +} + +void JBIG2Stream::resetGenericStats(Guint templ, + JArithmeticDecoderStats *prevStats) { + int size; + + size = contextSize[templ]; + if (prevStats && prevStats->getContextSize() == size) { + if (genericRegionStats->getContextSize() == size) { + genericRegionStats->copyFrom(prevStats); + } else { + delete genericRegionStats; + genericRegionStats = prevStats->copy(); + } + } else { + if (genericRegionStats->getContextSize() == size) { + genericRegionStats->reset(); + } else { + delete genericRegionStats; + genericRegionStats = new JArithmeticDecoderStats(1 << size); + } + } +} + +void JBIG2Stream::resetRefinementStats(Guint templ, + JArithmeticDecoderStats *prevStats) { + int size; + + size = refContextSize[templ]; + if (prevStats && prevStats->getContextSize() == size) { + if (refinementRegionStats->getContextSize() == size) { + refinementRegionStats->copyFrom(prevStats); + } else { + delete refinementRegionStats; + refinementRegionStats = prevStats->copy(); + } + } else { + if (refinementRegionStats->getContextSize() == size) { + refinementRegionStats->reset(); + } else { + delete refinementRegionStats; + refinementRegionStats = new JArithmeticDecoderStats(1 << size); + } + } +} + +void JBIG2Stream::resetIntStats(int symCodeLen) { + iadhStats->reset(); + iadwStats->reset(); + iaexStats->reset(); + iaaiStats->reset(); + iadtStats->reset(); + iaitStats->reset(); + iafsStats->reset(); + iadsStats->reset(); + iardxStats->reset(); + iardyStats->reset(); + iardwStats->reset(); + iardhStats->reset(); + iariStats->reset(); + if (iaidStats->getContextSize() == 1 << (symCodeLen + 1)) { + iaidStats->reset(); + } else { + delete iaidStats; + iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1)); + } +} + +GBool JBIG2Stream::readUByte(Guint *x) { + int c0; + + if ((c0 = curStr->getChar()) == EOF) { + return gFalse; + } + *x = (Guint)c0; + return gTrue; +} + +GBool JBIG2Stream::readByte(int *x) { + int c0; + + if ((c0 = curStr->getChar()) == EOF) { + return gFalse; + } + *x = c0; + if (c0 & 0x80) { + *x |= -1 - 0xff; + } + return gTrue; +} + +GBool JBIG2Stream::readUWord(Guint *x) { + int c0, c1; + + if ((c0 = curStr->getChar()) == EOF || + (c1 = curStr->getChar()) == EOF) { + return gFalse; + } + *x = (Guint)((c0 << 8) | c1); + return gTrue; +} + +GBool JBIG2Stream::readULong(Guint *x) { + int c0, c1, c2, c3; + + if ((c0 = curStr->getChar()) == EOF || + (c1 = curStr->getChar()) == EOF || + (c2 = curStr->getChar()) == EOF || + (c3 = curStr->getChar()) == EOF) { + return gFalse; + } + *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); + return gTrue; +} + +GBool JBIG2Stream::readLong(int *x) { + int c0, c1, c2, c3; + + if ((c0 = curStr->getChar()) == EOF || + (c1 = curStr->getChar()) == EOF || + (c2 = curStr->getChar()) == EOF || + (c3 = curStr->getChar()) == EOF) { + return gFalse; + } + *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); + if (c0 & 0x80) { + *x |= -1 - (int)0xffffffff; + } + return gTrue; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/JBIG2Stream.h swftools-0.9.1/lib/pdf/xpdf/JBIG2Stream.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/JBIG2Stream.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/JBIG2Stream.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,145 @@ +//======================================================================== +// +// JBIG2Stream.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef JBIG2STREAM_H +#define JBIG2STREAM_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" +#include "Stream.h" + +class GList; +class JBIG2Segment; +class JBIG2Bitmap; +class JArithmeticDecoder; +class JArithmeticDecoderStats; +class JBIG2HuffmanDecoder; +struct JBIG2HuffmanTable; +class JBIG2MMRDecoder; + +//------------------------------------------------------------------------ + +class JBIG2Stream: public FilterStream { +public: + + JBIG2Stream(Stream *strA, Object *globalsStreamA); + virtual ~JBIG2Stream(); + virtual StreamKind getKind() { return strJBIG2; } + virtual void reset(); + virtual void close(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + void readSegments(); + GBool readSymbolDictSeg(Guint segNum, Guint length, + Guint *refSegs, Guint nRefSegs); + void readTextRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + Guint *refSegs, Guint nRefSegs); + JBIG2Bitmap *readTextRegion(GBool huff, GBool refine, + int w, int h, + Guint numInstances, + Guint logStrips, + int numSyms, + JBIG2HuffmanTable *symCodeTab, + Guint symCodeLen, + JBIG2Bitmap **syms, + Guint defPixel, Guint combOp, + Guint transposed, Guint refCorner, + int sOffset, + JBIG2HuffmanTable *huffFSTable, + JBIG2HuffmanTable *huffDSTable, + JBIG2HuffmanTable *huffDTTable, + JBIG2HuffmanTable *huffRDWTable, + JBIG2HuffmanTable *huffRDHTable, + JBIG2HuffmanTable *huffRDXTable, + JBIG2HuffmanTable *huffRDYTable, + JBIG2HuffmanTable *huffRSizeTable, + Guint templ, + int *atx, int *aty); + void readPatternDictSeg(Guint segNum, Guint length); + void readHalftoneRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + Guint *refSegs, Guint nRefSegs); + void readGenericRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length); + JBIG2Bitmap *readGenericBitmap(GBool mmr, int w, int h, + int templ, GBool tpgdOn, + GBool useSkip, JBIG2Bitmap *skip, + int *atx, int *aty, + int mmrDataLength); + void readGenericRefinementRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length, + Guint *refSegs, + Guint nRefSegs); + JBIG2Bitmap *readGenericRefinementRegion(int w, int h, + int templ, GBool tpgrOn, + JBIG2Bitmap *refBitmap, + int refDX, int refDY, + int *atx, int *aty); + void readPageInfoSeg(Guint length); + void readEndOfStripeSeg(Guint length); + void readProfilesSeg(Guint length); + void readCodeTableSeg(Guint segNum, Guint length); + void readExtensionSeg(Guint length); + JBIG2Segment *findSegment(Guint segNum); + void discardSegment(Guint segNum); + void resetGenericStats(Guint templ, + JArithmeticDecoderStats *prevStats); + void resetRefinementStats(Guint templ, + JArithmeticDecoderStats *prevStats); + void resetIntStats(int symCodeLen); + GBool readUByte(Guint *x); + GBool readByte(int *x); + GBool readUWord(Guint *x); + GBool readULong(Guint *x); + GBool readLong(int *x); + + Object globalsStream; + Guint pageW, pageH, curPageH; + Guint pageDefPixel; + JBIG2Bitmap *pageBitmap; + Guint defCombOp; + GList *segments; // [JBIG2Segment] + GList *globalSegments; // [JBIG2Segment] + Stream *curStr; + Guchar *dataPtr; + Guchar *dataEnd; + + JArithmeticDecoder *arithDecoder; + JArithmeticDecoderStats *genericRegionStats; + JArithmeticDecoderStats *refinementRegionStats; + JArithmeticDecoderStats *iadhStats; + JArithmeticDecoderStats *iadwStats; + JArithmeticDecoderStats *iaexStats; + JArithmeticDecoderStats *iaaiStats; + JArithmeticDecoderStats *iadtStats; + JArithmeticDecoderStats *iaitStats; + JArithmeticDecoderStats *iafsStats; + JArithmeticDecoderStats *iadsStats; + JArithmeticDecoderStats *iardxStats; + JArithmeticDecoderStats *iardyStats; + JArithmeticDecoderStats *iardwStats; + JArithmeticDecoderStats *iardhStats; + JArithmeticDecoderStats *iariStats; + JArithmeticDecoderStats *iaidStats; + JBIG2HuffmanDecoder *huffDecoder; + JBIG2MMRDecoder *mmrDecoder; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/JPXStream.cc swftools-0.9.1/lib/pdf/xpdf/JPXStream.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/JPXStream.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/JPXStream.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,3154 @@ +//======================================================================== +// +// JPXStream.cc +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "Error.h" +#include "JArithmeticDecoder.h" +#include "JPXStream.h" + +//~ to do: +// - precincts +// - ROI +// - progression order changes +// - packed packet headers +// - support for palettes, channel maps, etc. +// - make sure all needed JP2/JPX subboxes are parsed (readBoxes) +// - can we assume that QCC segments must come after the QCD segment? +// - skip EPH markers (readTilePartData) +// - handle tilePartToEOC in readTilePartData +// - deal with multiple codeword segments (readTilePartData, +// readCodeBlockData) +// - progression orders 2, 3, and 4 +// - in coefficient decoding (readCodeBlockData): +// - termination pattern: terminate after every coding pass +// - error resilience segmentation symbol +// - selective arithmetic coding bypass +// - vertically causal context formation +// - coeffs longer than 31 bits (should just ignore the extra bits?) +// - handle boxes larger than 2^32 bytes +// - the fixed-point arithmetic won't handle 16-bit pixels + +//------------------------------------------------------------------------ + +// number of contexts for the arithmetic decoder +#define jpxNContexts 19 + +#define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup +#define jpxContextSign 9 // 9 - 13: sign +#define jpxContextMagRef 14 // 14 -16: magnitude refinement +#define jpxContextRunLength 17 // cleanup: run length +#define jpxContextUniform 18 // cleanup: first signif coeff + +//------------------------------------------------------------------------ + +#define jpxPassSigProp 0 +#define jpxPassMagRef 1 +#define jpxPassCleanup 2 + +//------------------------------------------------------------------------ + +// arithmetic decoder context for the significance propagation and +// cleanup passes: +// [horiz][vert][diag][subband] +// where subband = 0 for HL +// = 1 for LH and LL +// = 2 for HH +static Guint sigPropContext[3][3][5][3] = { + {{{ 0, 0, 0 }, // horiz=0, vert=0, diag=0 + { 1, 1, 3 }, // horiz=0, vert=0, diag=1 + { 2, 2, 6 }, // horiz=0, vert=0, diag=2 + { 2, 2, 8 }, // horiz=0, vert=0, diag=3 + { 2, 2, 8 }}, // horiz=0, vert=0, diag=4 + {{ 5, 3, 1 }, // horiz=0, vert=1, diag=0 + { 6, 3, 4 }, // horiz=0, vert=1, diag=1 + { 6, 3, 7 }, // horiz=0, vert=1, diag=2 + { 6, 3, 8 }, // horiz=0, vert=1, diag=3 + { 6, 3, 8 }}, // horiz=0, vert=1, diag=4 + {{ 8, 4, 2 }, // horiz=0, vert=2, diag=0 + { 8, 4, 5 }, // horiz=0, vert=2, diag=1 + { 8, 4, 7 }, // horiz=0, vert=2, diag=2 + { 8, 4, 8 }, // horiz=0, vert=2, diag=3 + { 8, 4, 8 }}}, // horiz=0, vert=2, diag=4 + {{{ 3, 5, 1 }, // horiz=1, vert=0, diag=0 + { 3, 6, 4 }, // horiz=1, vert=0, diag=1 + { 3, 6, 7 }, // horiz=1, vert=0, diag=2 + { 3, 6, 8 }, // horiz=1, vert=0, diag=3 + { 3, 6, 8 }}, // horiz=1, vert=0, diag=4 + {{ 7, 7, 2 }, // horiz=1, vert=1, diag=0 + { 7, 7, 5 }, // horiz=1, vert=1, diag=1 + { 7, 7, 7 }, // horiz=1, vert=1, diag=2 + { 7, 7, 8 }, // horiz=1, vert=1, diag=3 + { 7, 7, 8 }}, // horiz=1, vert=1, diag=4 + {{ 8, 7, 2 }, // horiz=1, vert=2, diag=0 + { 8, 7, 5 }, // horiz=1, vert=2, diag=1 + { 8, 7, 7 }, // horiz=1, vert=2, diag=2 + { 8, 7, 8 }, // horiz=1, vert=2, diag=3 + { 8, 7, 8 }}}, // horiz=1, vert=2, diag=4 + {{{ 4, 8, 2 }, // horiz=2, vert=0, diag=0 + { 4, 8, 5 }, // horiz=2, vert=0, diag=1 + { 4, 8, 7 }, // horiz=2, vert=0, diag=2 + { 4, 8, 8 }, // horiz=2, vert=0, diag=3 + { 4, 8, 8 }}, // horiz=2, vert=0, diag=4 + {{ 7, 8, 2 }, // horiz=2, vert=1, diag=0 + { 7, 8, 5 }, // horiz=2, vert=1, diag=1 + { 7, 8, 7 }, // horiz=2, vert=1, diag=2 + { 7, 8, 8 }, // horiz=2, vert=1, diag=3 + { 7, 8, 8 }}, // horiz=2, vert=1, diag=4 + {{ 8, 8, 2 }, // horiz=2, vert=2, diag=0 + { 8, 8, 5 }, // horiz=2, vert=2, diag=1 + { 8, 8, 7 }, // horiz=2, vert=2, diag=2 + { 8, 8, 8 }, // horiz=2, vert=2, diag=3 + { 8, 8, 8 }}} // horiz=2, vert=2, diag=4 +}; + +// arithmetic decoder context and xor bit for the sign bit in the +// significance propagation pass: +// [horiz][vert][k] +// where horiz/vert are offset by 2 (i.e., range is -2 .. 2) +// and k = 0 for the context +// = 1 for the xor bit +static Guint signContext[5][5][2] = { + {{ 13, 1 }, // horiz=-2, vert=-2 + { 13, 1 }, // horiz=-2, vert=-1 + { 12, 1 }, // horiz=-2, vert= 0 + { 11, 1 }, // horiz=-2, vert=+1 + { 11, 1 }}, // horiz=-2, vert=+2 + {{ 13, 1 }, // horiz=-1, vert=-2 + { 13, 1 }, // horiz=-1, vert=-1 + { 12, 1 }, // horiz=-1, vert= 0 + { 11, 1 }, // horiz=-1, vert=+1 + { 11, 1 }}, // horiz=-1, vert=+2 + {{ 10, 1 }, // horiz= 0, vert=-2 + { 10, 1 }, // horiz= 0, vert=-1 + { 9, 0 }, // horiz= 0, vert= 0 + { 10, 0 }, // horiz= 0, vert=+1 + { 10, 0 }}, // horiz= 0, vert=+2 + {{ 11, 0 }, // horiz=+1, vert=-2 + { 11, 0 }, // horiz=+1, vert=-1 + { 12, 0 }, // horiz=+1, vert= 0 + { 13, 0 }, // horiz=+1, vert=+1 + { 13, 0 }}, // horiz=+1, vert=+2 + {{ 11, 0 }, // horiz=+2, vert=-2 + { 11, 0 }, // horiz=+2, vert=-1 + { 12, 0 }, // horiz=+2, vert= 0 + { 13, 0 }, // horiz=+2, vert=+1 + { 13, 0 }}, // horiz=+2, vert=+2 +}; + +//------------------------------------------------------------------------ + +// constants used in the IDWT +#define idwtAlpha -1.586134342059924 +#define idwtBeta -0.052980118572961 +#define idwtGamma 0.882911075530934 +#define idwtDelta 0.443506852043971 +#define idwtKappa 1.230174104914001 +#define idwtIKappa (1.0 / idwtKappa) + +// number of bits to the right of the decimal point for the fixed +// point arithmetic used in the IDWT +#define fracBits 16 + +//------------------------------------------------------------------------ + +// floor(x / y) +#define jpxFloorDiv(x, y) ((x) / (y)) + +// floor(x / 2^y) +#define jpxFloorDivPow2(x, y) ((x) >> (y)) + +// ceil(x / y) +#define jpxCeilDiv(x, y) (((x) + (y) - 1) / (y)) + +// ceil(x / 2^y) +#define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y)) + +//------------------------------------------------------------------------ + +#if 1 //----- disable coverage tracking + +#define cover(idx) + +#else //----- enable coverage tracking + +class JPXCover { +public: + + JPXCover(int sizeA); + ~JPXCover(); + void incr(int idx); + +private: + + int size, used; + int *data; +}; + +JPXCover::JPXCover(int sizeA) { + size = sizeA; + used = -1; + data = (int *)gmallocn(size, sizeof(int)); + memset(data, 0, size * sizeof(int)); +} + +JPXCover::~JPXCover() { + int i; + + printf("JPX coverage:\n"); + for (i = 0; i <= used; ++i) { + printf(" %4d: %8d\n", i, data[i]); + } + gfree(data); +} + +void JPXCover::incr(int idx) { + if (idx < size) { + ++data[idx]; + if (idx > used) { + used = idx; + } + } +} + +JPXCover jpxCover(150); + +#define cover(idx) jpxCover.incr(idx) + +#endif //----- coverage tracking + +//------------------------------------------------------------------------ + +JPXStream::JPXStream(Stream *strA): + FilterStream(strA) +{ + nComps = 0; + bpc = NULL; + width = height = 0; + haveCS = gFalse; + havePalette = gFalse; + haveCompMap = gFalse; + haveChannelDefn = gFalse; + + img.xSize = 0; + img.ySize = 0; + img.xOffset = 0; + img.yOffset = 0; + curX = 0; + curY = 0; + img.tiles = NULL; + bitBuf = 0; + bitBufLen = 0; + bitBufSkip = gFalse; + byteCount = 0; +} + +JPXStream::~JPXStream() { + close(); + delete str; +} + +void JPXStream::reset() { + str->reset(); + if (readBoxes()) { + curY = img.yOffset; + } else { + // readBoxes reported an error, so we go immediately to EOF + curY = img.ySize; + } + curX = img.xOffset; + curComp = 0; + readBufLen = 0; +} + +void JPXStream::close() { + JPXTile *tile; + JPXTileComp *tileComp; + JPXResLevel *resLevel; + JPXPrecinct *precinct; + JPXSubband *subband; + JPXCodeBlock *cb; + Guint comp, i, k, r, pre, sb; + + gfree(bpc); + bpc = NULL; + if (havePalette) { + gfree(palette.bpc); + gfree(palette.c); + havePalette = gFalse; + } + if (haveCompMap) { + gfree(compMap.comp); + gfree(compMap.type); + gfree(compMap.pComp); + haveCompMap = gFalse; + } + if (haveChannelDefn) { + gfree(channelDefn.idx); + gfree(channelDefn.type); + gfree(channelDefn.assoc); + haveChannelDefn = gFalse; + } + + if (img.tiles) { + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + tile = &img.tiles[i]; + if (tile->tileComps) { + for (comp = 0; comp < img.nComps; ++comp) { + tileComp = &tile->tileComps[comp]; + gfree(tileComp->quantSteps); + gfree(tileComp->data); + gfree(tileComp->buf); + if (tileComp->resLevels) { + for (r = 0; r <= tileComp->nDecompLevels; ++r) { + resLevel = &tileComp->resLevels[r]; + if (resLevel->precincts) { + for (pre = 0; pre < 1; ++pre) { + precinct = &resLevel->precincts[pre]; + if (precinct->subbands) { + for (sb = 0; sb < (Guint)(r == 0 ? 1 : 3); ++sb) { + subband = &precinct->subbands[sb]; + gfree(subband->inclusion); + gfree(subband->zeroBitPlane); + if (subband->cbs) { + for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) { + cb = &subband->cbs[k]; + gfree(cb->coeffs); + if (cb->arithDecoder) { + delete cb->arithDecoder; + } + if (cb->stats) { + delete cb->stats; + } + } + gfree(subband->cbs); + } + } + gfree(precinct->subbands); + } + } + gfree(img.tiles[i].tileComps[comp].resLevels[r].precincts); + } + } + gfree(img.tiles[i].tileComps[comp].resLevels); + } + } + gfree(img.tiles[i].tileComps); + } + } + gfree(img.tiles); + img.tiles = NULL; + } + FilterStream::close(); +} + +int JPXStream::getChar() { + int c; + + if (readBufLen < 8) { + fillReadBuf(); + } + if (readBufLen == 8) { + c = readBuf & 0xff; + readBufLen = 0; + } else if (readBufLen > 8) { + c = (readBuf >> (readBufLen - 8)) & 0xff; + readBufLen -= 8; + } else if (readBufLen == 0) { + c = EOF; + } else { + c = (readBuf << (8 - readBufLen)) & 0xff; + readBufLen = 0; + } + return c; +} + +int JPXStream::lookChar() { + int c; + + if (readBufLen < 8) { + fillReadBuf(); + } + if (readBufLen == 8) { + c = readBuf & 0xff; + } else if (readBufLen > 8) { + c = (readBuf >> (readBufLen - 8)) & 0xff; + } else if (readBufLen == 0) { + c = EOF; + } else { + c = (readBuf << (8 - readBufLen)) & 0xff; + } + return c; +} + +void JPXStream::fillReadBuf() { + JPXTileComp *tileComp; + Guint tileIdx, tx, ty; + int pix, pixBits; + + do { + if (curY >= img.ySize) { + return; + } + tileIdx = ((curY - img.yTileOffset) / img.yTileSize) * img.nXTiles + + (curX - img.xTileOffset) / img.xTileSize; +#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid + tileComp = &img.tiles[tileIdx].tileComps[curComp]; +#else + tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp]; +#endif + tx = jpxCeilDiv((curX - img.xTileOffset) % img.xTileSize, tileComp->hSep); + ty = jpxCeilDiv((curY - img.yTileOffset) % img.yTileSize, tileComp->vSep); + pix = (int)tileComp->data[ty * (tileComp->x1 - tileComp->x0) + tx]; + pixBits = tileComp->prec; +#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid + if (++curComp == img.nComps) { +#else + if (havePalette) { + if (pix >= 0 && pix < palette.nEntries) { + pix = palette.c[pix * palette.nComps + curComp]; + } else { + pix = + pixBits = palette.bpc[curComp]; + } + if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) { +#endif + curComp = 0; + if (++curX == img.xSize) { + curX = img.xOffset; + ++curY; + } + } + if (pixBits == 8) { + readBuf = (readBuf << 8) | (pix & 0xff); + } else { + readBuf = (readBuf << pixBits) | (pix & ((1 << pixBits) - 1)); + } + readBufLen += pixBits; + } while (readBufLen < 8); +} + +GString *JPXStream::getPSFilter(int psLevel, char *indent) { + return NULL; +} + +GBool JPXStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +void JPXStream::getImageParams(int *bitsPerComponent, + StreamColorSpaceMode *csMode) { + Guint boxType, boxLen, dataLen, csEnum; + Guint bpc1, dummy, i; + int csMeth, csPrec, csPrec1, dummy2; + StreamColorSpaceMode csMode1; + GBool haveBPC, haveCSMode; + + csPrec = 0; // make gcc happy + Guint num_components = 0; + haveBPC = haveCSMode = gFalse; + str->reset(); + if (str->lookChar() == 0xff) { + getImageParams2(bitsPerComponent, csMode); + } else { + while (readBoxHdr(&boxType, &boxLen, &dataLen)) { + if (boxType == 0x6a703268) { // JP2 header + cover(0); + // skip the superbox + } else if (boxType == 0x69686472) { // image header + cover(1); + if (readULong(&dummy) && + readULong(&dummy) && + readUWord(&num_components) && + readUByte(&bpc1) && + readUByte(&dummy) && + readUByte(&dummy) && + readUByte(&dummy)) { + *bitsPerComponent = bpc1 + 1; + haveBPC = gTrue; + } + } else if (boxType == 0x636F6C72) { // color specification + cover(2); + if (readByte(&csMeth) && + readByte(&csPrec1) && + readByte(&dummy2)) { + if (csMeth == 1) { + if (readULong(&csEnum)) { + csMode1 = streamCSNone; + if (csEnum == jpxCSBiLevel || + csEnum == jpxCSGrayscale) { + csMode1 = streamCSDeviceGray; + } else if (csEnum == jpxCSCMYK) { + csMode1 = streamCSDeviceCMYK; + } else if (csEnum == jpxCSsRGB || + csEnum == jpxCSCISesRGB || + csEnum == jpxCSROMMRGB) { + csMode1 = streamCSDeviceRGB; + } + if (csMode1 != streamCSNone && + (!haveCSMode || csPrec1 > csPrec)) { + *csMode = csMode1; + csPrec = csPrec1; + haveCSMode = gTrue; + } + for (i = 0; i < dataLen - 7; ++i) { + str->getChar(); + } + } + } else { + for (i = 0; i < dataLen - 3; ++i) { + str->getChar(); + } + } + } + } else if (boxType == 0x6A703263) { // codestream + cover(3); + if (!(haveBPC && haveCSMode)) { + getImageParams2(bitsPerComponent, csMode); + } + break; + } else { + cover(4); + for (i = 0; i < dataLen; ++i) { + str->getChar(); + } + } + } + } + if(*csMode == streamCSDeviceRGB && num_components == 4) { + *csMode = streamCSDeviceRGBX; + } + str->close(); +} + +// Get image parameters from the codestream. +void JPXStream::getImageParams2(int *bitsPerComponent, + StreamColorSpaceMode *csMode) { + int segType; + Guint segLen, nComps1, bpc1, dummy, i; + + while (readMarkerHdr(&segType, &segLen)) { + if (segType == 0x51) { // SIZ - image and tile size + cover(5); + if (readUWord(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readULong(&dummy) && + readUWord(&nComps1) && + readUByte(&bpc1)) { + *bitsPerComponent = (bpc1 & 0x7f) + 1; + // if there's no color space info, take a guess + if (nComps1 == 1) { + *csMode = streamCSDeviceGray; + } else if (nComps1 == 3) { + *csMode = streamCSDeviceRGB; + } else if (nComps1 == 4) { + *csMode = streamCSDeviceCMYK; + } + } + break; + } else { + cover(6); + if (segLen > 2) { + for (i = 0; i < segLen - 2; ++i) { + str->getChar(); + } + } + } + } +} + +GBool JPXStream::readBoxes() { + Guint boxType, boxLen, dataLen; + Guint bpc1, compression, unknownColorspace, ipr; + Guint i, j; + + haveImgHdr = gFalse; + + // check for a naked JPEG 2000 codestream (without the JP2/JPX + // wrapper) -- this appears to be a violation of the PDF spec, but + // Acrobat allows it + if (str->lookChar() == 0xff) { + cover(7); + error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper"); + readCodestream(0); + nComps = img.nComps; + bpc = (Guint *)gmallocn(nComps, sizeof(Guint)); + for (i = 0; i < nComps; ++i) { + bpc[i] = img.tiles[0].tileComps[i].prec; + } + width = img.xSize - img.xOffset; + height = img.ySize - img.yOffset; + return gTrue; + } + + while (readBoxHdr(&boxType, &boxLen, &dataLen)) { + switch (boxType) { + case 0x6a703268: // JP2 header + // this is a grouping box ('superbox') which has no real + // contents and doesn't appear to be used consistently, i.e., + // some things which should be subboxes of the JP2 header box + // show up outside of it - so we simply ignore the JP2 header + // box + cover(8); + break; + case 0x69686472: // image header + cover(9); + if (!readULong(&height) || + !readULong(&width) || + !readUWord(&nComps) || + !readUByte(&bpc1) || + !readUByte(&compression) || + !readUByte(&unknownColorspace) || + !readUByte(&ipr)) { + error(getPos(), "Unexpected EOF in JPX stream"); + return gFalse; + } + if (compression != 7) { + error(getPos(), "Unknown compression type in JPX stream"); + return gFalse; + } + bpc = (Guint *)gmallocn(nComps, sizeof(Guint)); + for (i = 0; i < nComps; ++i) { + bpc[i] = bpc1; + } + haveImgHdr = gTrue; + break; + case 0x62706363: // bits per component + cover(10); + if (!haveImgHdr) { + error(getPos(), "Found bits per component box before image header box in JPX stream"); + return gFalse; + } + if (dataLen != nComps) { + error(getPos(), "Invalid bits per component box in JPX stream"); + return gFalse; + } + for (i = 0; i < nComps; ++i) { + if (!readUByte(&bpc[i])) { + error(getPos(), "Unexpected EOF in JPX stream"); + return gFalse; + } + } + break; + case 0x636F6C72: // color specification + cover(11); + if (!readColorSpecBox(dataLen)) { + return gFalse; + } + break; + case 0x70636c72: // palette + cover(12); + if (!readUWord(&palette.nEntries) || + !readUByte(&palette.nComps)) { + error(getPos(), "Unexpected EOF in JPX stream"); + return gFalse; + } + palette.bpc = (Guint *)gmallocn(palette.nComps, sizeof(Guint)); + palette.c = + (int *)gmallocn(palette.nEntries * palette.nComps, sizeof(int)); + for (i = 0; i < palette.nComps; ++i) { + if (!readUByte(&palette.bpc[i])) { + error(getPos(), "Unexpected EOF in JPX stream"); + return gFalse; + } + ++palette.bpc[i]; + } + for (i = 0; i < palette.nEntries; ++i) { + for (j = 0; j < palette.nComps; ++j) { + if (!readNBytes(((palette.bpc[j] & 0x7f) + 7) >> 3, + (palette.bpc[j] & 0x80) ? gTrue : gFalse, + &palette.c[i * palette.nComps + j])) { + error(getPos(), "Unexpected EOF in JPX stream"); + return gFalse; + } + } + } + havePalette = gTrue; + break; + case 0x636d6170: // component mapping + cover(13); + compMap.nChannels = dataLen / 4; + compMap.comp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); + compMap.type = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); + compMap.pComp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); + for (i = 0; i < compMap.nChannels; ++i) { + if (!readUWord(&compMap.comp[i]) || + !readUByte(&compMap.type[i]) || + !readUByte(&compMap.pComp[i])) { + error(getPos(), "Unexpected EOF in JPX stream"); + return gFalse; + } + } + haveCompMap = gTrue; + break; + case 0x63646566: // channel definition + cover(14); + if (!readUWord(&channelDefn.nChannels)) { + error(getPos(), "Unexpected EOF in JPX stream"); + return gFalse; + } + channelDefn.idx = + (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); + channelDefn.type = + (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); + channelDefn.assoc = + (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); + for (i = 0; i < channelDefn.nChannels; ++i) { + if (!readUWord(&channelDefn.idx[i]) || + !readUWord(&channelDefn.type[i]) || + !readUWord(&channelDefn.assoc[i])) { + error(getPos(), "Unexpected EOF in JPX stream"); + return gFalse; + } + } + haveChannelDefn = gTrue; + break; + case 0x6A703263: // contiguous codestream + cover(15); + if (!bpc) { + error(getPos(), "JPX stream is missing the image header box"); + } + if (!haveCS) { + error(getPos(), "JPX stream has no supported color spec"); + } + if (!readCodestream(dataLen)) { + return gFalse; + } + break; + default: + cover(16); + for (i = 0; i < dataLen; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Unexpected EOF in JPX stream"); + return gFalse; + } + } + break; + } + } + return gTrue; +} + +GBool JPXStream::readColorSpecBox(Guint dataLen) { + JPXColorSpec newCS; + Guint csApprox, csEnum; + Guint i; + GBool ok; + + ok = gFalse; + if (!readUByte(&newCS.meth) || + !readByte(&newCS.prec) || + !readUByte(&csApprox)) { + goto err; + } + switch (newCS.meth) { + case 1: // enumerated colorspace + cover(17); + if (!readULong(&csEnum)) { + goto err; + } + newCS.enumerated.type = (JPXColorSpaceType)csEnum; + switch (newCS.enumerated.type) { + case jpxCSBiLevel: + ok = gTrue; + break; + case jpxCSYCbCr1: + ok = gTrue; + break; + case jpxCSYCbCr2: + ok = gTrue; + break; + case jpxCSYCBCr3: + ok = gTrue; + break; + case jpxCSPhotoYCC: + ok = gTrue; + break; + case jpxCSCMY: + ok = gTrue; + break; + case jpxCSCMYK: + ok = gTrue; + break; + case jpxCSYCCK: + ok = gTrue; + break; + case jpxCSCIELab: + if (dataLen == 7 + 7*4) { + if (!readULong(&newCS.enumerated.cieLab.rl) || + !readULong(&newCS.enumerated.cieLab.ol) || + !readULong(&newCS.enumerated.cieLab.ra) || + !readULong(&newCS.enumerated.cieLab.oa) || + !readULong(&newCS.enumerated.cieLab.rb) || + !readULong(&newCS.enumerated.cieLab.ob) || + !readULong(&newCS.enumerated.cieLab.il)) { + goto err; + } + } else if (dataLen == 7) { + //~ this assumes the 8-bit case + cover(92); + newCS.enumerated.cieLab.rl = 100; + newCS.enumerated.cieLab.ol = 0; + newCS.enumerated.cieLab.ra = 255; + newCS.enumerated.cieLab.oa = 128; + newCS.enumerated.cieLab.rb = 255; + newCS.enumerated.cieLab.ob = 96; + newCS.enumerated.cieLab.il = 0x00443530; + } else { + goto err; + } + ok = gTrue; + break; + case jpxCSsRGB: + ok = gTrue; + break; + case jpxCSGrayscale: + ok = gTrue; + break; + case jpxCSBiLevel2: + ok = gTrue; + break; + case jpxCSCIEJab: + // not allowed in PDF + goto err; + case jpxCSCISesRGB: + ok = gTrue; + break; + case jpxCSROMMRGB: + ok = gTrue; + break; + case jpxCSsRGBYCbCr: + ok = gTrue; + break; + case jpxCSYPbPr1125: + ok = gTrue; + break; + case jpxCSYPbPr1250: + ok = gTrue; + break; + default: + goto err; + } + break; + case 2: // restricted ICC profile + case 3: // any ICC profile (JPX) + case 4: // vendor color (JPX) + cover(18); + for (i = 0; i < dataLen - 3; ++i) { + if (str->getChar() == EOF) { + goto err; + } + } + break; + } + + if (ok && (!haveCS || newCS.prec > cs.prec)) { + cs = newCS; + haveCS = gTrue; + } + + return gTrue; + + err: + error(getPos(), "Error in JPX color spec"); + return gFalse; +} + +GBool JPXStream::readCodestream(Guint len) { + JPXTile *tile; + JPXTileComp *tileComp; + int segType; + GBool haveSIZ, haveCOD, haveQCD, haveSOT; + Guint precinctSize, style; + Guint segLen, capabilities, comp, i, j, r; + + //----- main header + haveSIZ = haveCOD = haveQCD = haveSOT = gFalse; + do { + if (!readMarkerHdr(&segType, &segLen)) { + error(getPos(), "Error in JPX codestream"); + return gFalse; + } + switch (segType) { + case 0x4f: // SOC - start of codestream + // marker only + cover(19); + break; + case 0x51: // SIZ - image and tile size + cover(20); + if (!readUWord(&capabilities) || + !readULong(&img.xSize) || + !readULong(&img.ySize) || + !readULong(&img.xOffset) || + !readULong(&img.yOffset) || + !readULong(&img.xTileSize) || + !readULong(&img.yTileSize) || + !readULong(&img.xTileOffset) || + !readULong(&img.yTileOffset) || + !readUWord(&img.nComps)) { + error(getPos(), "Error in JPX SIZ marker segment"); + return gFalse; + } + if (haveImgHdr && img.nComps != nComps) { + error(getPos(), "Different number of components in JPX SIZ marker segment"); + return gFalse; + } + img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1) + / img.xTileSize; + img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1) + / img.yTileSize; + // check for overflow before allocating memory + if (img.nXTiles <= 0 || img.nYTiles <= 0 || + img.nXTiles >= INT_MAX / img.nYTiles) { + error(getPos(), "Bad tile count in JPX SIZ marker segment"); + return gFalse; + } + img.tiles = (JPXTile *)gmallocn(img.nXTiles * img.nYTiles, + sizeof(JPXTile)); + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps, + sizeof(JPXTileComp)); + for (comp = 0; comp < img.nComps; ++comp) { + img.tiles[i].tileComps[comp].quantSteps = NULL; + img.tiles[i].tileComps[comp].data = NULL; + img.tiles[i].tileComps[comp].buf = NULL; + img.tiles[i].tileComps[comp].resLevels = NULL; + } + } + for (comp = 0; comp < img.nComps; ++comp) { + if (!readUByte(&img.tiles[0].tileComps[comp].prec) || + !readUByte(&img.tiles[0].tileComps[comp].hSep) || + !readUByte(&img.tiles[0].tileComps[comp].vSep)) { + error(getPos(), "Error in JPX SIZ marker segment"); + return gFalse; + } + img.tiles[0].tileComps[comp].sgned = + (img.tiles[0].tileComps[comp].prec & 0x80) ? gTrue : gFalse; + img.tiles[0].tileComps[comp].prec = + (img.tiles[0].tileComps[comp].prec & 0x7f) + 1; + for (i = 1; i < img.nXTiles * img.nYTiles; ++i) { + img.tiles[i].tileComps[comp] = img.tiles[0].tileComps[comp]; + } + } + haveSIZ = gTrue; + break; + case 0x52: // COD - coding style default + cover(21); + if (!readUByte(&img.tiles[0].tileComps[0].style) || + !readUByte(&img.tiles[0].progOrder) || + !readUWord(&img.tiles[0].nLayers) || + !readUByte(&img.tiles[0].multiComp) || + !readUByte(&img.tiles[0].tileComps[0].nDecompLevels) || + !readUByte(&img.tiles[0].tileComps[0].codeBlockW) || + !readUByte(&img.tiles[0].tileComps[0].codeBlockH) || + !readUByte(&img.tiles[0].tileComps[0].codeBlockStyle) || + !readUByte(&img.tiles[0].tileComps[0].transform)) { + error(getPos(), "Error in JPX COD marker segment"); + return gFalse; + } + img.tiles[0].tileComps[0].codeBlockW += 2; + img.tiles[0].tileComps[0].codeBlockH += 2; + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + if (i != 0) { + img.tiles[i].progOrder = img.tiles[0].progOrder; + img.tiles[i].nLayers = img.tiles[0].nLayers; + img.tiles[i].multiComp = img.tiles[0].multiComp; + } + for (comp = 0; comp < img.nComps; ++comp) { + if (!(i == 0 && comp == 0)) { + img.tiles[i].tileComps[comp].style = + img.tiles[0].tileComps[0].style; + img.tiles[i].tileComps[comp].nDecompLevels = + img.tiles[0].tileComps[0].nDecompLevels; + img.tiles[i].tileComps[comp].codeBlockW = + img.tiles[0].tileComps[0].codeBlockW; + img.tiles[i].tileComps[comp].codeBlockH = + img.tiles[0].tileComps[0].codeBlockH; + img.tiles[i].tileComps[comp].codeBlockStyle = + img.tiles[0].tileComps[0].codeBlockStyle; + img.tiles[i].tileComps[comp].transform = + img.tiles[0].tileComps[0].transform; + } + img.tiles[i].tileComps[comp].resLevels = + (JPXResLevel *)gmallocn( + (img.tiles[i].tileComps[comp].nDecompLevels + 1), + sizeof(JPXResLevel)); + for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) { + img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL; + } + } + } + for (r = 0; r <= img.tiles[0].tileComps[0].nDecompLevels; ++r) { + if (img.tiles[0].tileComps[0].style & 0x01) { + cover(91); + if (!readUByte(&precinctSize)) { + error(getPos(), "Error in JPX COD marker segment"); + return gFalse; + } + img.tiles[0].tileComps[0].resLevels[r].precinctWidth = + precinctSize & 0x0f; + img.tiles[0].tileComps[0].resLevels[r].precinctHeight = + (precinctSize >> 4) & 0x0f; + } else { + img.tiles[0].tileComps[0].resLevels[r].precinctWidth = 15; + img.tiles[0].tileComps[0].resLevels[r].precinctHeight = 15; + } + } + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + for (comp = 0; comp < img.nComps; ++comp) { + if (!(i == 0 && comp == 0)) { + for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) { + img.tiles[i].tileComps[comp].resLevels[r].precinctWidth = + img.tiles[0].tileComps[0].resLevels[r].precinctWidth; + img.tiles[i].tileComps[comp].resLevels[r].precinctHeight = + img.tiles[0].tileComps[0].resLevels[r].precinctHeight; + } + } + } + } + haveCOD = gTrue; + break; + case 0x53: // COC - coding style component + cover(22); + if (!haveCOD) { + error(getPos(), "JPX COC marker segment before COD segment"); + return gFalse; + } + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&style) || + !readUByte(&img.tiles[0].tileComps[comp].nDecompLevels) || + !readUByte(&img.tiles[0].tileComps[comp].codeBlockW) || + !readUByte(&img.tiles[0].tileComps[comp].codeBlockH) || + !readUByte(&img.tiles[0].tileComps[comp].codeBlockStyle) || + !readUByte(&img.tiles[0].tileComps[comp].transform)) { + error(getPos(), "Error in JPX COC marker segment"); + return gFalse; + } + img.tiles[0].tileComps[comp].style = + (img.tiles[0].tileComps[comp].style & ~1) | (style & 1); + img.tiles[0].tileComps[comp].codeBlockW += 2; + img.tiles[0].tileComps[comp].codeBlockH += 2; + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + if (i != 0) { + img.tiles[i].tileComps[comp].style = + img.tiles[0].tileComps[comp].style; + img.tiles[i].tileComps[comp].nDecompLevels = + img.tiles[0].tileComps[comp].nDecompLevels; + img.tiles[i].tileComps[comp].codeBlockW = + img.tiles[0].tileComps[comp].codeBlockW; + img.tiles[i].tileComps[comp].codeBlockH = + img.tiles[0].tileComps[comp].codeBlockH; + img.tiles[i].tileComps[comp].codeBlockStyle = + img.tiles[0].tileComps[comp].codeBlockStyle; + img.tiles[i].tileComps[comp].transform = + img.tiles[0].tileComps[comp].transform; + } + img.tiles[i].tileComps[comp].resLevels = + (JPXResLevel *)greallocn( + img.tiles[i].tileComps[comp].resLevels, + (img.tiles[i].tileComps[comp].nDecompLevels + 1), + sizeof(JPXResLevel)); + for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) { + img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL; + } + } + for (r = 0; r <= img.tiles[0].tileComps[comp].nDecompLevels; ++r) { + if (img.tiles[0].tileComps[comp].style & 0x01) { + if (!readUByte(&precinctSize)) { + error(getPos(), "Error in JPX COD marker segment"); + return gFalse; + } + img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = + precinctSize & 0x0f; + img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = + (precinctSize >> 4) & 0x0f; + } else { + img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = 15; + img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = 15; + } + } + for (i = 1; i < img.nXTiles * img.nYTiles; ++i) { + for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) { + img.tiles[i].tileComps[comp].resLevels[r].precinctWidth = + img.tiles[0].tileComps[comp].resLevels[r].precinctWidth; + img.tiles[i].tileComps[comp].resLevels[r].precinctHeight = + img.tiles[0].tileComps[comp].resLevels[r].precinctHeight; + } + } + break; + case 0x5c: // QCD - quantization default + cover(23); + if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) { + img.tiles[0].tileComps[0].nQuantSteps = segLen - 3; + img.tiles[0].tileComps[0].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps, + img.tiles[0].tileComps[0].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) { + if (!readUByte(&img.tiles[0].tileComps[0].quantSteps[i])) { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + } + } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x01) { + img.tiles[0].tileComps[0].nQuantSteps = 1; + img.tiles[0].tileComps[0].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps, + img.tiles[0].tileComps[0].nQuantSteps, + sizeof(Guint)); + if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[0])) { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) { + img.tiles[0].tileComps[0].nQuantSteps = (segLen - 3) / 2; + img.tiles[0].tileComps[0].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps, + img.tiles[0].tileComps[0].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) { + if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[i])) { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + } + } else { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + for (comp = 0; comp < img.nComps; ++comp) { + if (!(i == 0 && comp == 0)) { + img.tiles[i].tileComps[comp].quantStyle = + img.tiles[0].tileComps[0].quantStyle; + img.tiles[i].tileComps[comp].nQuantSteps = + img.tiles[0].tileComps[0].nQuantSteps; + img.tiles[i].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps, + img.tiles[0].tileComps[0].nQuantSteps, + sizeof(Guint)); + for (j = 0; j < img.tiles[0].tileComps[0].nQuantSteps; ++j) { + img.tiles[i].tileComps[comp].quantSteps[j] = + img.tiles[0].tileComps[0].quantSteps[j]; + } + } + } + } + haveQCD = gTrue; + break; + case 0x5d: // QCC - quantization component + cover(24); + if (!haveQCD) { + error(getPos(), "JPX QCC marker segment before QCD segment"); + return gFalse; + } + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&img.tiles[0].tileComps[comp].quantStyle)) { + error(getPos(), "Error in JPX QCC marker segment"); + return gFalse; + } + if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) { + img.tiles[0].tileComps[comp].nQuantSteps = + segLen - (img.nComps > 256 ? 5 : 4); + img.tiles[0].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps, + img.tiles[0].tileComps[comp].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) { + if (!readUByte(&img.tiles[0].tileComps[comp].quantSteps[i])) { + error(getPos(), "Error in JPX QCC marker segment"); + return gFalse; + } + } + } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x01) { + img.tiles[0].tileComps[comp].nQuantSteps = 1; + img.tiles[0].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps, + img.tiles[0].tileComps[comp].nQuantSteps, + sizeof(Guint)); + if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[0])) { + error(getPos(), "Error in JPX QCC marker segment"); + return gFalse; + } + } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) { + img.tiles[0].tileComps[comp].nQuantSteps = + (segLen - (img.nComps > 256 ? 5 : 4)) / 2; + img.tiles[0].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps, + img.tiles[0].tileComps[comp].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) { + if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[i])) { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + } + } else { + error(getPos(), "Error in JPX QCC marker segment"); + return gFalse; + } + for (i = 1; i < img.nXTiles * img.nYTiles; ++i) { + img.tiles[i].tileComps[comp].quantStyle = + img.tiles[0].tileComps[comp].quantStyle; + img.tiles[i].tileComps[comp].nQuantSteps = + img.tiles[0].tileComps[comp].nQuantSteps; + img.tiles[i].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps, + img.tiles[0].tileComps[comp].nQuantSteps, + sizeof(Guint)); + for (j = 0; j < img.tiles[0].tileComps[comp].nQuantSteps; ++j) { + img.tiles[i].tileComps[comp].quantSteps[j] = + img.tiles[0].tileComps[comp].quantSteps[j]; + } + } + break; + case 0x5e: // RGN - region of interest + cover(25); +#if 1 //~ ROI is unimplemented + fprintf(stderr, "RGN\n"); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX PPM marker segment"); + return gFalse; + } + } +#else + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&compInfo[comp].defROI.style) || + !readUByte(&compInfo[comp].defROI.shift)) { + error(getPos(), "Error in JPX RGN marker segment"); + return gFalse; + } +#endif + break; + case 0x5f: // POC - progression order change + cover(26); +#if 1 //~ progression order changes are unimplemented + fprintf(stderr, "POC\n"); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX PPM marker segment"); + return gFalse; + } + } +#else + nProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7); + progs = (JPXProgOrder *)gmallocn(nProgs, sizeof(JPXProgOrder)); + for (i = 0; i < nProgs; ++i) { + if (!readUByte(&progs[i].startRes) || + !(img.nComps > 256 && readUWord(&progs[i].startComp)) || + !(img.nComps <= 256 && readUByte(&progs[i].startComp)) || + !readUWord(&progs[i].endLayer) || + !readUByte(&progs[i].endRes) || + !(img.nComps > 256 && readUWord(&progs[i].endComp)) || + !(img.nComps <= 256 && readUByte(&progs[i].endComp)) || + !readUByte(&progs[i].progOrder)) { + error(getPos(), "Error in JPX POC marker segment"); + return gFalse; + } + } +#endif + break; + case 0x60: // PPM - packed packet headers, main header + cover(27); +#if 1 //~ packed packet headers are unimplemented + fprintf(stderr, "PPM\n"); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX PPM marker segment"); + return gFalse; + } + } +#endif + break; + case 0x55: // TLM - tile-part lengths + // skipped + cover(28); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX TLM marker segment"); + return gFalse; + } + } + break; + case 0x57: // PLM - packet length, main header + // skipped + cover(29); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX PLM marker segment"); + return gFalse; + } + } + break; + case 0x63: // CRG - component registration + // skipped + cover(30); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX CRG marker segment"); + return gFalse; + } + } + break; + case 0x64: // COM - comment + // skipped + cover(31); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX COM marker segment"); + return gFalse; + } + } + break; + case 0x90: // SOT - start of tile + cover(32); + haveSOT = gTrue; + break; + default: + cover(33); + error(getPos(), "Unknown marker segment %02x in JPX stream", segType); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + break; + } + } + break; + } + } while (!haveSOT); + + if (!haveSIZ) { + error(getPos(), "Missing SIZ marker segment in JPX stream"); + return gFalse; + } + if (!haveCOD) { + error(getPos(), "Missing COD marker segment in JPX stream"); + return gFalse; + } + if (!haveQCD) { + error(getPos(), "Missing QCD marker segment in JPX stream"); + return gFalse; + } + + //----- read the tile-parts + while (1) { + if (!readTilePart()) { + return gFalse; + } + if (!readMarkerHdr(&segType, &segLen)) { + error(getPos(), "Error in JPX codestream"); + return gFalse; + } + if (segType != 0x90) { // SOT - start of tile + break; + } + } + + if (segType != 0xd9) { // EOC - end of codestream + error(getPos(), "Missing EOC marker in JPX codestream"); + return gFalse; + } + + //----- finish decoding the image + for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { + tile = &img.tiles[i]; + for (comp = 0; comp < img.nComps; ++comp) { + tileComp = &tile->tileComps[comp]; + inverseTransform(tileComp); + } + if (!inverseMultiCompAndDC(tile)) { + return gFalse; + } + } + + //~ can free memory below tileComps here, and also tileComp.buf + + return gTrue; +} + +GBool JPXStream::readTilePart() { + JPXTile *tile; + JPXTileComp *tileComp; + JPXResLevel *resLevel; + JPXPrecinct *precinct; + JPXSubband *subband; + JPXCodeBlock *cb; + GBool haveSOD; + Guint tileIdx, tilePartLen, tilePartIdx, nTileParts; + GBool tilePartToEOC; + Guint precinctSize, style; + Guint n, nSBs, nx, ny, sbx0, sby0, comp, segLen; + Guint i, j, k, cbX, cbY, r, pre, sb, cbi; + int segType, level; + + // process the SOT marker segment + if (!readUWord(&tileIdx) || + !readULong(&tilePartLen) || + !readUByte(&tilePartIdx) || + !readUByte(&nTileParts)) { + error(getPos(), "Error in JPX SOT marker segment"); + return gFalse; + } + + if (tileIdx >= img.nXTiles * img.nYTiles) { + error(getPos(), "Weird tile index in JPX stream"); + return gFalse; + } + + tilePartToEOC = tilePartLen == 0; + tilePartLen -= 12; // subtract size of SOT segment + + haveSOD = gFalse; + do { + if (!readMarkerHdr(&segType, &segLen)) { + error(getPos(), "Error in JPX tile-part codestream"); + return gFalse; + } + tilePartLen -= 2 + segLen; + switch (segType) { + case 0x52: // COD - coding style default + cover(34); + if (!readUByte(&img.tiles[tileIdx].tileComps[0].style) || + !readUByte(&img.tiles[tileIdx].progOrder) || + !readUWord(&img.tiles[tileIdx].nLayers) || + !readUByte(&img.tiles[tileIdx].multiComp) || + !readUByte(&img.tiles[tileIdx].tileComps[0].nDecompLevels) || + !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockW) || + !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockH) || + !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockStyle) || + !readUByte(&img.tiles[tileIdx].tileComps[0].transform)) { + error(getPos(), "Error in JPX COD marker segment"); + return gFalse; + } + img.tiles[tileIdx].tileComps[0].codeBlockW += 2; + img.tiles[tileIdx].tileComps[0].codeBlockH += 2; + for (comp = 0; comp < img.nComps; ++comp) { + if (comp != 0) { + img.tiles[tileIdx].tileComps[comp].style = + img.tiles[tileIdx].tileComps[0].style; + img.tiles[tileIdx].tileComps[comp].nDecompLevels = + img.tiles[tileIdx].tileComps[0].nDecompLevels; + img.tiles[tileIdx].tileComps[comp].codeBlockW = + img.tiles[tileIdx].tileComps[0].codeBlockW; + img.tiles[tileIdx].tileComps[comp].codeBlockH = + img.tiles[tileIdx].tileComps[0].codeBlockH; + img.tiles[tileIdx].tileComps[comp].codeBlockStyle = + img.tiles[tileIdx].tileComps[0].codeBlockStyle; + img.tiles[tileIdx].tileComps[comp].transform = + img.tiles[tileIdx].tileComps[0].transform; + } + img.tiles[tileIdx].tileComps[comp].resLevels = + (JPXResLevel *)greallocn( + img.tiles[tileIdx].tileComps[comp].resLevels, + (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1), + sizeof(JPXResLevel)); + for (r = 0; + r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; + ++r) { + img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL; + } + } + for (r = 0; r <= img.tiles[tileIdx].tileComps[0].nDecompLevels; ++r) { + if (img.tiles[tileIdx].tileComps[0].style & 0x01) { + if (!readUByte(&precinctSize)) { + error(getPos(), "Error in JPX COD marker segment"); + return gFalse; + } + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = + precinctSize & 0x0f; + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = + (precinctSize >> 4) & 0x0f; + } else { + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = 15; + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = 15; + } + } + for (comp = 1; comp < img.nComps; ++comp) { + for (r = 0; + r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; + ++r) { + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth; + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = + img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight; + } + } + break; + case 0x53: // COC - coding style component + cover(35); + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&style) || + !readUByte(&img.tiles[tileIdx].tileComps[comp].nDecompLevels) || + !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockW) || + !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockH) || + !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockStyle) || + !readUByte(&img.tiles[tileIdx].tileComps[comp].transform)) { + error(getPos(), "Error in JPX COC marker segment"); + return gFalse; + } + img.tiles[tileIdx].tileComps[comp].style = + (img.tiles[tileIdx].tileComps[comp].style & ~1) | (style & 1); + img.tiles[tileIdx].tileComps[comp].codeBlockW += 2; + img.tiles[tileIdx].tileComps[comp].codeBlockH += 2; + img.tiles[tileIdx].tileComps[comp].resLevels = + (JPXResLevel *)greallocn( + img.tiles[tileIdx].tileComps[comp].resLevels, + (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1), + sizeof(JPXResLevel)); + for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) { + img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL; + } + for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) { + if (img.tiles[tileIdx].tileComps[comp].style & 0x01) { + if (!readUByte(&precinctSize)) { + error(getPos(), "Error in JPX COD marker segment"); + return gFalse; + } + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = + precinctSize & 0x0f; + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = + (precinctSize >> 4) & 0x0f; + } else { + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = 15; + img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = 15; + } + } + break; + case 0x5c: // QCD - quantization default + cover(36); + if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x00) { + img.tiles[tileIdx].tileComps[0].nQuantSteps = + segLen - 3; + img.tiles[tileIdx].tileComps[0].quantSteps = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps, + img.tiles[tileIdx].tileComps[0].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) { + if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + } + } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x01) { + img.tiles[tileIdx].tileComps[0].nQuantSteps = 1; + img.tiles[tileIdx].tileComps[0].quantSteps = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps, + img.tiles[tileIdx].tileComps[0].nQuantSteps, + sizeof(Guint)); + if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[0])) { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x02) { + img.tiles[tileIdx].tileComps[0].nQuantSteps = (segLen - 3) / 2; + img.tiles[tileIdx].tileComps[0].quantSteps = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps, + img.tiles[tileIdx].tileComps[0].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) { + if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + } + } else { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + for (comp = 1; comp < img.nComps; ++comp) { + img.tiles[tileIdx].tileComps[comp].quantStyle = + img.tiles[tileIdx].tileComps[0].quantStyle; + img.tiles[tileIdx].tileComps[comp].nQuantSteps = + img.tiles[tileIdx].tileComps[0].nQuantSteps; + img.tiles[tileIdx].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, + img.tiles[tileIdx].tileComps[0].nQuantSteps, + sizeof(Guint)); + for (j = 0; j < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++j) { + img.tiles[tileIdx].tileComps[comp].quantSteps[j] = + img.tiles[tileIdx].tileComps[0].quantSteps[j]; + } + } + break; + case 0x5d: // QCC - quantization component + cover(37); + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&img.tiles[tileIdx].tileComps[comp].quantStyle)) { + error(getPos(), "Error in JPX QCC marker segment"); + return gFalse; + } + if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x00) { + img.tiles[tileIdx].tileComps[comp].nQuantSteps = + segLen - (img.nComps > 256 ? 5 : 4); + img.tiles[tileIdx].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, + img.tiles[tileIdx].tileComps[comp].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) { + if (!readUByte(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) { + error(getPos(), "Error in JPX QCC marker segment"); + return gFalse; + } + } + } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) + == 0x01) { + img.tiles[tileIdx].tileComps[comp].nQuantSteps = 1; + img.tiles[tileIdx].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, + img.tiles[tileIdx].tileComps[comp].nQuantSteps, + sizeof(Guint)); + if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[0])) { + error(getPos(), "Error in JPX QCC marker segment"); + return gFalse; + } + } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) + == 0x02) { + img.tiles[tileIdx].tileComps[comp].nQuantSteps = + (segLen - (img.nComps > 256 ? 5 : 4)) / 2; + img.tiles[tileIdx].tileComps[comp].quantSteps = + (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, + img.tiles[tileIdx].tileComps[comp].nQuantSteps, + sizeof(Guint)); + for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) { + if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) { + error(getPos(), "Error in JPX QCD marker segment"); + return gFalse; + } + } + } else { + error(getPos(), "Error in JPX QCC marker segment"); + return gFalse; + } + break; + case 0x5e: // RGN - region of interest + cover(38); +#if 1 //~ ROI is unimplemented + fprintf(stderr, "RGN\n"); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX PPM marker segment"); + return gFalse; + } + } +#else + if ((img.nComps > 256 && !readUWord(&comp)) || + (img.nComps <= 256 && !readUByte(&comp)) || + comp >= img.nComps || + !readUByte(&compInfo[comp].roi.style) || + !readUByte(&compInfo[comp].roi.shift)) { + error(getPos(), "Error in JPX RGN marker segment"); + return gFalse; + } +#endif + break; + case 0x5f: // POC - progression order change + cover(39); +#if 1 //~ progression order changes are unimplemented + fprintf(stderr, "POC\n"); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX PPM marker segment"); + return gFalse; + } + } +#else + nTileProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7); + tileProgs = (JPXProgOrder *)gmallocn(nTileProgs, sizeof(JPXProgOrder)); + for (i = 0; i < nTileProgs; ++i) { + if (!readUByte(&tileProgs[i].startRes) || + !(img.nComps > 256 && readUWord(&tileProgs[i].startComp)) || + !(img.nComps <= 256 && readUByte(&tileProgs[i].startComp)) || + !readUWord(&tileProgs[i].endLayer) || + !readUByte(&tileProgs[i].endRes) || + !(img.nComps > 256 && readUWord(&tileProgs[i].endComp)) || + !(img.nComps <= 256 && readUByte(&tileProgs[i].endComp)) || + !readUByte(&tileProgs[i].progOrder)) { + error(getPos(), "Error in JPX POC marker segment"); + return gFalse; + } + } +#endif + break; + case 0x61: // PPT - packed packet headers, tile-part hdr + cover(40); +#if 1 //~ packed packet headers are unimplemented + fprintf(stderr, "PPT\n"); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX PPT marker segment"); + return gFalse; + } + } +#endif + case 0x58: // PLT - packet length, tile-part header + // skipped + cover(41); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX PLT marker segment"); + return gFalse; + } + } + break; + case 0x64: // COM - comment + // skipped + cover(42); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + error(getPos(), "Error in JPX COM marker segment"); + return gFalse; + } + } + break; + case 0x93: // SOD - start of data + cover(43); + haveSOD = gTrue; + break; + default: + cover(44); + error(getPos(), "Unknown marker segment %02x in JPX tile-part stream", + segType); + for (i = 0; i < segLen - 2; ++i) { + if (str->getChar() == EOF) { + break; + } + } + break; + } + } while (!haveSOD); + + //----- initialize the tile, precincts, and code-blocks + if (tilePartIdx == 0) { + tile = &img.tiles[tileIdx]; + i = tileIdx / img.nXTiles; + j = tileIdx % img.nXTiles; + if ((tile->x0 = img.xTileOffset + j * img.xTileSize) < img.xOffset) { + tile->x0 = img.xOffset; + } + if ((tile->y0 = img.yTileOffset + i * img.yTileSize) < img.yOffset) { + tile->y0 = img.yOffset; + } + if ((tile->x1 = img.xTileOffset + (j + 1) * img.xTileSize) > img.xSize) { + tile->x1 = img.xSize; + } + if ((tile->y1 = img.yTileOffset + (i + 1) * img.yTileSize) > img.ySize) { + tile->y1 = img.ySize; + } + tile->comp = 0; + tile->res = 0; + tile->precinct = 0; + tile->layer = 0; + tile->maxNDecompLevels = 0; + for (comp = 0; comp < img.nComps; ++comp) { + tileComp = &tile->tileComps[comp]; + if (tileComp->nDecompLevels > tile->maxNDecompLevels) { + tile->maxNDecompLevels = tileComp->nDecompLevels; + } + tileComp->x0 = jpxCeilDiv(tile->x0, tileComp->hSep); + tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->hSep); + tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep); + tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->hSep); + tileComp->cbW = 1 << tileComp->codeBlockW; + tileComp->cbH = 1 << tileComp->codeBlockH; + tileComp->data = (int *)gmallocn((tileComp->x1 - tileComp->x0) * + (tileComp->y1 - tileComp->y0), + sizeof(int)); + if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) { + n = tileComp->x1 - tileComp->x0; + } else { + n = tileComp->y1 - tileComp->y0; + } + tileComp->buf = (int *)gmallocn(n + 8, sizeof(int)); + for (r = 0; r <= tileComp->nDecompLevels; ++r) { + resLevel = &tileComp->resLevels[r]; + k = r == 0 ? tileComp->nDecompLevels + : tileComp->nDecompLevels - r + 1; + resLevel->x0 = jpxCeilDivPow2(tileComp->x0, k); + resLevel->y0 = jpxCeilDivPow2(tileComp->y0, k); + resLevel->x1 = jpxCeilDivPow2(tileComp->x1, k); + resLevel->y1 = jpxCeilDivPow2(tileComp->y1, k); + if (r == 0) { + resLevel->bx0[0] = resLevel->x0; + resLevel->by0[0] = resLevel->y0; + resLevel->bx1[0] = resLevel->x1; + resLevel->by1[0] = resLevel->y1; + } else { + resLevel->bx0[0] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k); + resLevel->by0[0] = resLevel->y0; + resLevel->bx1[0] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k); + resLevel->by1[0] = resLevel->y1; + resLevel->bx0[1] = resLevel->x0; + resLevel->by0[1] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k); + resLevel->bx1[1] = resLevel->x1; + resLevel->by1[1] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k); + resLevel->bx0[2] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k); + resLevel->by0[2] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k); + resLevel->bx1[2] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k); + resLevel->by1[2] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k); + } + resLevel->precincts = (JPXPrecinct *)gmallocn(1, sizeof(JPXPrecinct)); + for (pre = 0; pre < 1; ++pre) { + precinct = &resLevel->precincts[pre]; + precinct->x0 = resLevel->x0; + precinct->y0 = resLevel->y0; + precinct->x1 = resLevel->x1; + precinct->y1 = resLevel->y1; + nSBs = r == 0 ? 1 : 3; + precinct->subbands = + (JPXSubband *)gmallocn(nSBs, sizeof(JPXSubband)); + for (sb = 0; sb < nSBs; ++sb) { + subband = &precinct->subbands[sb]; + subband->x0 = resLevel->bx0[sb]; + subband->y0 = resLevel->by0[sb]; + subband->x1 = resLevel->bx1[sb]; + subband->y1 = resLevel->by1[sb]; + subband->nXCBs = jpxCeilDivPow2(subband->x1, + tileComp->codeBlockW) + - jpxFloorDivPow2(subband->x0, + tileComp->codeBlockW); + subband->nYCBs = jpxCeilDivPow2(subband->y1, + tileComp->codeBlockH) + - jpxFloorDivPow2(subband->y0, + tileComp->codeBlockH); + n = subband->nXCBs > subband->nYCBs ? subband->nXCBs + : subband->nYCBs; + for (subband->maxTTLevel = 0, --n; + n; + ++subband->maxTTLevel, n >>= 1) ; + n = 0; + for (level = subband->maxTTLevel; level >= 0; --level) { + nx = jpxCeilDivPow2(subband->nXCBs, level); + ny = jpxCeilDivPow2(subband->nYCBs, level); + n += nx * ny; + } + subband->inclusion = + (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode)); + subband->zeroBitPlane = + (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode)); + for (k = 0; k < n; ++k) { + subband->inclusion[k].finished = gFalse; + subband->inclusion[k].val = 0; + subband->zeroBitPlane[k].finished = gFalse; + subband->zeroBitPlane[k].val = 0; + } + subband->cbs = (JPXCodeBlock *)gmallocn(subband->nXCBs * + subband->nYCBs, + sizeof(JPXCodeBlock)); + sbx0 = jpxFloorDivPow2(subband->x0, tileComp->codeBlockW); + sby0 = jpxFloorDivPow2(subband->y0, tileComp->codeBlockH); + cb = subband->cbs; + for (cbY = 0; cbY < subband->nYCBs; ++cbY) { + for (cbX = 0; cbX < subband->nXCBs; ++cbX) { + cb->x0 = (sbx0 + cbX) << tileComp->codeBlockW; + cb->x1 = cb->x0 + tileComp->cbW; + if (subband->x0 > cb->x0) { + cb->x0 = subband->x0; + } + if (subband->x1 < cb->x1) { + cb->x1 = subband->x1; + } + cb->y0 = (sby0 + cbY) << tileComp->codeBlockH; + cb->y1 = cb->y0 + tileComp->cbH; + if (subband->y0 > cb->y0) { + cb->y0 = subband->y0; + } + if (subband->y1 < cb->y1) { + cb->y1 = subband->y1; + } + cb->seen = gFalse; + cb->lBlock = 3; + cb->nextPass = jpxPassCleanup; + cb->nZeroBitPlanes = 0; + cb->coeffs = + (JPXCoeff *)gmallocn((1 << (tileComp->codeBlockW + + tileComp->codeBlockH)), + sizeof(JPXCoeff)); + for (cbi = 0; + cbi < (Guint)(1 << (tileComp->codeBlockW + + tileComp->codeBlockH)); + ++cbi) { + cb->coeffs[cbi].flags = 0; + cb->coeffs[cbi].len = 0; + cb->coeffs[cbi].mag = 0; + } + cb->arithDecoder = NULL; + cb->stats = NULL; + ++cb; + } + } + } + } + } + } + } + + return readTilePartData(tileIdx, tilePartLen, tilePartToEOC); +} + +GBool JPXStream::readTilePartData(Guint tileIdx, + Guint tilePartLen, GBool tilePartToEOC) { + JPXTile *tile; + JPXTileComp *tileComp; + JPXResLevel *resLevel; + JPXPrecinct *precinct; + JPXSubband *subband; + JPXCodeBlock *cb; + Guint ttVal; + Guint bits, cbX, cbY, nx, ny, i, j, n, sb; + int level; + + tile = &img.tiles[tileIdx]; + + // read all packets from this tile-part + while (1) { + if (tilePartToEOC) { + //~ peek for an EOC marker + cover(93); + } else if (tilePartLen == 0) { + break; + } + + tileComp = &tile->tileComps[tile->comp]; + resLevel = &tileComp->resLevels[tile->res]; + precinct = &resLevel->precincts[tile->precinct]; + + //----- packet header + + // setup + startBitBuf(tilePartLen); + + // zero-length flag + if (!readBits(1, &bits)) { + goto err; + } + if (!bits) { + // packet is empty -- clear all code-block inclusion flags + cover(45); + for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) { + subband = &precinct->subbands[sb]; + for (cbY = 0; cbY < subband->nYCBs; ++cbY) { + for (cbX = 0; cbX < subband->nXCBs; ++cbX) { + cb = &subband->cbs[cbY * subband->nXCBs + cbX]; + cb->included = gFalse; + } + } + } + } else { + + for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) { + subband = &precinct->subbands[sb]; + for (cbY = 0; cbY < subband->nYCBs; ++cbY) { + for (cbX = 0; cbX < subband->nXCBs; ++cbX) { + cb = &subband->cbs[cbY * subband->nXCBs + cbX]; + + // skip code-blocks with no coefficients + if (cb->x0 >= cb->x1 || cb->y0 >= cb->y1) { + cover(46); + cb->included = gFalse; + continue; + } + + // code-block inclusion + if (cb->seen) { + cover(47); + if (!readBits(1, &cb->included)) { + goto err; + } + } else { + cover(48); + ttVal = 0; + i = 0; + for (level = subband->maxTTLevel; level >= 0; --level) { + nx = jpxCeilDivPow2(subband->nXCBs, level); + ny = jpxCeilDivPow2(subband->nYCBs, level); + j = i + (cbY >> level) * nx + (cbX >> level); + if (!subband->inclusion[j].finished && + !subband->inclusion[j].val) { + subband->inclusion[j].val = ttVal; + } else { + ttVal = subband->inclusion[j].val; + } + while (!subband->inclusion[j].finished && + ttVal <= tile->layer) { + if (!readBits(1, &bits)) { + goto err; + } + if (bits == 1) { + subband->inclusion[j].finished = gTrue; + } else { + ++ttVal; + } + } + subband->inclusion[j].val = ttVal; + if (ttVal > tile->layer) { + break; + } + i += nx * ny; + } + cb->included = level < 0; + } + + if (cb->included) { + cover(49); + + // zero bit-plane count + if (!cb->seen) { + cover(50); + ttVal = 0; + i = 0; + for (level = subband->maxTTLevel; level >= 0; --level) { + nx = jpxCeilDivPow2(subband->nXCBs, level); + ny = jpxCeilDivPow2(subband->nYCBs, level); + j = i + (cbY >> level) * nx + (cbX >> level); + if (!subband->zeroBitPlane[j].finished && + !subband->zeroBitPlane[j].val) { + subband->zeroBitPlane[j].val = ttVal; + } else { + ttVal = subband->zeroBitPlane[j].val; + } + while (!subband->zeroBitPlane[j].finished) { + if (!readBits(1, &bits)) { + goto err; + } + if (bits == 1) { + subband->zeroBitPlane[j].finished = gTrue; + } else { + ++ttVal; + } + } + subband->zeroBitPlane[j].val = ttVal; + i += nx * ny; + } + cb->nZeroBitPlanes = ttVal; + } + + // number of coding passes + if (!readBits(1, &bits)) { + goto err; + } + if (bits == 0) { + cover(51); + cb->nCodingPasses = 1; + } else { + if (!readBits(1, &bits)) { + goto err; + } + if (bits == 0) { + cover(52); + cb->nCodingPasses = 2; + } else { + cover(53); + if (!readBits(2, &bits)) { + goto err; + } + if (bits < 3) { + cover(54); + cb->nCodingPasses = 3 + bits; + } else { + cover(55); + if (!readBits(5, &bits)) { + goto err; + } + if (bits < 31) { + cover(56); + cb->nCodingPasses = 6 + bits; + } else { + cover(57); + if (!readBits(7, &bits)) { + goto err; + } + cb->nCodingPasses = 37 + bits; + } + } + } + } + + // update Lblock + while (1) { + if (!readBits(1, &bits)) { + goto err; + } + if (!bits) { + break; + } + ++cb->lBlock; + } + + // length of compressed data + //~ deal with multiple codeword segments + for (n = cb->lBlock, i = cb->nCodingPasses >> 1; + i; + ++n, i >>= 1) ; + if (!readBits(n, &cb->dataLen)) { + goto err; + } + } + } + } + } + } + tilePartLen = finishBitBuf(); + + //----- packet data + + for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) { + subband = &precinct->subbands[sb]; + for (cbY = 0; cbY < subband->nYCBs; ++cbY) { + for (cbX = 0; cbX < subband->nXCBs; ++cbX) { + cb = &subband->cbs[cbY * subband->nXCBs + cbX]; + if (cb->included) { + if (!readCodeBlockData(tileComp, resLevel, precinct, subband, + tile->res, sb, cb)) { + return gFalse; + } + tilePartLen -= cb->dataLen; + cb->seen = gTrue; + } + } + } + } + + //----- next packet + + switch (tile->progOrder) { + case 0: // layer, resolution level, component, precinct + cover(58); + if (++tile->comp == img.nComps) { + tile->comp = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + } + } + } + break; + case 1: // resolution level, layer, component, precinct + cover(59); + if (++tile->comp == img.nComps) { + tile->comp = 0; + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + } + } + } + break; + case 2: // resolution level, precinct, component, layer + //~ this isn't correct -- see B.12.1.3 + cover(60); + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + } + } + } + break; + case 3: // precinct, component, resolution level, layer + //~ this isn't correct -- see B.12.1.4 + cover(61); + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + } + } + } + break; + case 4: // component, precinct, resolution level, layer + //~ this isn't correct -- see B.12.1.5 + cover(62); + if (++tile->layer == tile->nLayers) { + tile->layer = 0; + if (++tile->res == tile->maxNDecompLevels + 1) { + tile->res = 0; + if (++tile->comp == img.nComps) { + tile->comp = 0; + } + } + } + break; + } + } + + return gTrue; + + err: + error(getPos(), "Error in JPX stream"); + return gFalse; +} + +GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp, + JPXResLevel *resLevel, + JPXPrecinct *precinct, + JPXSubband *subband, + Guint res, Guint sb, + JPXCodeBlock *cb) { + JPXCoeff *coeff0, *coeff1, *coeff; + Guint horiz, vert, diag, all, cx, xorBit; + int horizSign, vertSign; + Guint i, x, y0, y1, y2; + + if (cb->arithDecoder) { + cover(63); + cb->arithDecoder->restart(cb->dataLen); + } else { + cover(64); + cb->arithDecoder = new JArithmeticDecoder(); + cb->arithDecoder->setStream(str, cb->dataLen); + cb->arithDecoder->start(); + cb->stats = new JArithmeticDecoderStats(jpxNContexts); + cb->stats->setEntry(jpxContextSigProp, 4, 0); + cb->stats->setEntry(jpxContextRunLength, 3, 0); + cb->stats->setEntry(jpxContextUniform, 46, 0); + } + + for (i = 0; i < cb->nCodingPasses; ++i) { + switch (cb->nextPass) { + + //----- significance propagation pass + case jpxPassSigProp: + cover(65); + for (y0 = cb->y0, coeff0 = cb->coeffs; + y0 < cb->y1; + y0 += 4, coeff0 += 4 << tileComp->codeBlockW) { + for (x = cb->x0, coeff1 = coeff0; + x < cb->x1; + ++x, ++coeff1) { + for (y1 = 0, coeff = coeff1; + y1 < 4 && y0+y1 < cb->y1; + ++y1, coeff += tileComp->cbW) { + if (!(coeff->flags & jpxCoeffSignificant)) { + horiz = vert = diag = 0; + horizSign = vertSign = 2; + if (x > cb->x0) { + if (coeff[-1].flags & jpxCoeffSignificant) { + ++horiz; + horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1; + } + if (y0+y1 > cb->y0) { + diag += (coeff[-(int)tileComp->cbW - 1].flags + >> jpxCoeffSignificantB) & 1; + } + if (y0+y1 < cb->y1 - 1) { + diag += (coeff[tileComp->cbW - 1].flags + >> jpxCoeffSignificantB) & 1; + } + } + if (x < cb->x1 - 1) { + if (coeff[1].flags & jpxCoeffSignificant) { + ++horiz; + horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1; + } + if (y0+y1 > cb->y0) { + diag += (coeff[-(int)tileComp->cbW + 1].flags + >> jpxCoeffSignificantB) & 1; + } + if (y0+y1 < cb->y1 - 1) { + diag += (coeff[tileComp->cbW + 1].flags + >> jpxCoeffSignificantB) & 1; + } + } + if (y0+y1 > cb->y0) { + if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) { + ++vert; + vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign) + ? -1 : 1; + } + } + if (y0+y1 < cb->y1 - 1) { + if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) { + ++vert; + vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign) + ? -1 : 1; + } + } + cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb]; + if (cx != 0) { + if (cb->arithDecoder->decodeBit(cx, cb->stats)) { + coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef; + coeff->mag = (coeff->mag << 1) | 1; + cx = signContext[horizSign][vertSign][0]; + xorBit = signContext[horizSign][vertSign][1]; + if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { + coeff->flags |= jpxCoeffSign; + } + } + ++coeff->len; + coeff->flags |= jpxCoeffTouched; + } + } + } + } + } + ++cb->nextPass; + break; + + //----- magnitude refinement pass + case jpxPassMagRef: + cover(66); + for (y0 = cb->y0, coeff0 = cb->coeffs; + y0 < cb->y1; + y0 += 4, coeff0 += 4 << tileComp->codeBlockW) { + for (x = cb->x0, coeff1 = coeff0; + x < cb->x1; + ++x, ++coeff1) { + for (y1 = 0, coeff = coeff1; + y1 < 4 && y0+y1 < cb->y1; + ++y1, coeff += tileComp->cbW) { + if ((coeff->flags & jpxCoeffSignificant) && + !(coeff->flags & jpxCoeffTouched)) { + if (coeff->flags & jpxCoeffFirstMagRef) { + all = 0; + if (x > cb->x0) { + all += (coeff[-1].flags >> jpxCoeffSignificantB) & 1; + if (y0+y1 > cb->y0) { + all += (coeff[-(int)tileComp->cbW - 1].flags + >> jpxCoeffSignificantB) & 1; + } + if (y0+y1 < cb->y1 - 1) { + all += (coeff[tileComp->cbW - 1].flags + >> jpxCoeffSignificantB) & 1; + } + } + if (x < cb->x1 - 1) { + all += (coeff[1].flags >> jpxCoeffSignificantB) & 1; + if (y0+y1 > cb->y0) { + all += (coeff[-(int)tileComp->cbW + 1].flags + >> jpxCoeffSignificantB) & 1; + } + if (y0+y1 < cb->y1 - 1) { + all += (coeff[tileComp->cbW + 1].flags + >> jpxCoeffSignificantB) & 1; + } + } + if (y0+y1 > cb->y0) { + all += (coeff[-(int)tileComp->cbW].flags + >> jpxCoeffSignificantB) & 1; + } + if (y0+y1 < cb->y1 - 1) { + all += (coeff[tileComp->cbW].flags + >> jpxCoeffSignificantB) & 1; + } + cx = all ? 15 : 14; + } else { + cx = 16; + } + coeff->mag = (coeff->mag << 1) | + cb->arithDecoder->decodeBit(cx, cb->stats); + ++coeff->len; + coeff->flags |= jpxCoeffTouched; + coeff->flags &= ~jpxCoeffFirstMagRef; + } + } + } + } + ++cb->nextPass; + break; + + //----- cleanup pass + case jpxPassCleanup: + cover(67); + for (y0 = cb->y0, coeff0 = cb->coeffs; + y0 < cb->y1; + y0 += 4, coeff0 += 4 << tileComp->codeBlockW) { + for (x = cb->x0, coeff1 = coeff0; + x < cb->x1; + ++x, ++coeff1) { + y1 = 0; + if (y0 + 3 < cb->y1 && + !(coeff1->flags & jpxCoeffTouched) && + !(coeff1[tileComp->cbW].flags & jpxCoeffTouched) && + !(coeff1[2 * tileComp->cbW].flags & jpxCoeffTouched) && + !(coeff1[3 * tileComp->cbW].flags & jpxCoeffTouched) && + (x == cb->x0 || y0 == cb->y0 || + !(coeff1[-(int)tileComp->cbW - 1].flags + & jpxCoeffSignificant)) && + (y0 == cb->y0 || + !(coeff1[-(int)tileComp->cbW].flags + & jpxCoeffSignificant)) && + (x == cb->x1 - 1 || y0 == cb->y0 || + !(coeff1[-(int)tileComp->cbW + 1].flags + & jpxCoeffSignificant)) && + (x == cb->x0 || + (!(coeff1[-1].flags & jpxCoeffSignificant) && + !(coeff1[tileComp->cbW - 1].flags + & jpxCoeffSignificant) && + !(coeff1[2 * tileComp->cbW - 1].flags + & jpxCoeffSignificant) && + !(coeff1[3 * tileComp->cbW - 1].flags + & jpxCoeffSignificant))) && + (x == cb->x1 - 1 || + (!(coeff1[1].flags & jpxCoeffSignificant) && + !(coeff1[tileComp->cbW + 1].flags + & jpxCoeffSignificant) && + !(coeff1[2 * tileComp->cbW + 1].flags + & jpxCoeffSignificant) && + !(coeff1[3 * tileComp->cbW + 1].flags + & jpxCoeffSignificant))) && + (x == cb->x0 || y0+4 == cb->y1 || + !(coeff1[4 * tileComp->cbW - 1].flags & jpxCoeffSignificant)) && + (y0+4 == cb->y1 || + !(coeff1[4 * tileComp->cbW].flags & jpxCoeffSignificant)) && + (x == cb->x1 - 1 || y0+4 == cb->y1 || + !(coeff1[4 * tileComp->cbW + 1].flags + & jpxCoeffSignificant))) { + if (cb->arithDecoder->decodeBit(jpxContextRunLength, cb->stats)) { + y1 = cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats); + y1 = (y1 << 1) | + cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats); + for (y2 = 0, coeff = coeff1; + y2 < y1; + ++y2, coeff += tileComp->cbW) { + ++coeff->len; + } + coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef; + coeff->mag = (coeff->mag << 1) | 1; + ++coeff->len; + cx = signContext[2][2][0]; + xorBit = signContext[2][2][1]; + if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { + coeff->flags |= jpxCoeffSign; + } + ++y1; + } else { + for (y1 = 0, coeff = coeff1; + y1 < 4; + ++y1, coeff += tileComp->cbW) { + ++coeff->len; + } + y1 = 4; + } + } + for (coeff = &coeff1[y1 << tileComp->codeBlockW]; + y1 < 4 && y0 + y1 < cb->y1; + ++y1, coeff += tileComp->cbW) { + if (!(coeff->flags & jpxCoeffTouched)) { + horiz = vert = diag = 0; + horizSign = vertSign = 2; + if (x > cb->x0) { + if (coeff[-1].flags & jpxCoeffSignificant) { + ++horiz; + horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1; + } + if (y0+y1 > cb->y0) { + diag += (coeff[-(int)tileComp->cbW - 1].flags + >> jpxCoeffSignificantB) & 1; + } + if (y0+y1 < cb->y1 - 1) { + diag += (coeff[tileComp->cbW - 1].flags + >> jpxCoeffSignificantB) & 1; + } + } + if (x < cb->x1 - 1) { + if (coeff[1].flags & jpxCoeffSignificant) { + ++horiz; + horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1; + } + if (y0+y1 > cb->y0) { + diag += (coeff[-(int)tileComp->cbW + 1].flags + >> jpxCoeffSignificantB) & 1; + } + if (y0+y1 < cb->y1 - 1) { + diag += (coeff[tileComp->cbW + 1].flags + >> jpxCoeffSignificantB) & 1; + } + } + if (y0+y1 > cb->y0) { + if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) { + ++vert; + vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign) + ? -1 : 1; + } + } + if (y0+y1 < cb->y1 - 1) { + if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) { + ++vert; + vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign) + ? -1 : 1; + } + } + cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb]; + if (cb->arithDecoder->decodeBit(cx, cb->stats)) { + coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef; + coeff->mag = (coeff->mag << 1) | 1; + cx = signContext[horizSign][vertSign][0]; + xorBit = signContext[horizSign][vertSign][1]; + if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { + coeff->flags |= jpxCoeffSign; + } + } + ++coeff->len; + } else { + coeff->flags &= ~jpxCoeffTouched; + } + } + } + } + cb->nextPass = jpxPassSigProp; + break; + } + } + + cb->arithDecoder->cleanup(); + return gTrue; +} + +// Inverse quantization, and wavelet transform (IDWT). This also does +// the initial shift to convert to fixed point format. +void JPXStream::inverseTransform(JPXTileComp *tileComp) { + JPXResLevel *resLevel; + JPXPrecinct *precinct; + JPXSubband *subband; + JPXCodeBlock *cb; + JPXCoeff *coeff0, *coeff; + Guint qStyle, guard, eps, shift; + int shift2; + double mu; + int val; + int *dataPtr; + Guint nx0, ny0, nx1, ny1; + Guint r, cbX, cbY, x, y; + + cover(68); + + //----- (NL)LL subband (resolution level 0) + + resLevel = &tileComp->resLevels[0]; + precinct = &resLevel->precincts[0]; + subband = &precinct->subbands[0]; + + // i-quant parameters + qStyle = tileComp->quantStyle & 0x1f; + guard = (tileComp->quantStyle >> 5) & 7; + if (qStyle == 0) { + cover(69); + eps = (tileComp->quantSteps[0] >> 3) & 0x1f; + shift = guard + eps - 1; + mu = 0; // make gcc happy + } else { + cover(70); + shift = guard - 1 + tileComp->prec; + mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0; + } + if (tileComp->transform == 0) { + cover(71); + shift += fracBits; + } + + // copy (NL)LL into the upper-left corner of the data array, doing + // the fixed point adjustment and dequantization along the way + cb = subband->cbs; + for (cbY = 0; cbY < subband->nYCBs; ++cbY) { + for (cbX = 0; cbX < subband->nXCBs; ++cbX) { + for (y = cb->y0, coeff0 = cb->coeffs; + y < cb->y1; + ++y, coeff0 += tileComp->cbW) { + dataPtr = &tileComp->data[(y - subband->y0) + * (tileComp->x1 - tileComp->x0) + + (cb->x0 - subband->x0)]; + for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) { + val = (int)coeff->mag; + if (val != 0) { + shift2 = shift - (cb->nZeroBitPlanes + coeff->len); + if (shift2 > 0) { + cover(94); + val = (val << shift2) + (1 << (shift2 - 1)); + } else { + cover(95); + val >>= -shift2; + } + if (qStyle == 0) { + cover(96); + if (tileComp->transform == 0) { + cover(97); + val &= -1 << fracBits; + } + } else { + cover(98); + val = (int)((double)val * mu); + } + if (coeff->flags & jpxCoeffSign) { + cover(99); + val = -val; + } + } + *dataPtr++ = val; + } + } + ++cb; + } + } + + //----- IDWT for each level + + for (r = 1; r <= tileComp->nDecompLevels; ++r) { + resLevel = &tileComp->resLevels[r]; + + // (n)LL is already in the upper-left corner of the + // tile-component data array -- interleave with (n)HL/LH/HH + // and inverse transform to get (n-1)LL, which will be stored + // in the upper-left corner of the tile-component data array + if (r == tileComp->nDecompLevels) { + cover(72); + nx0 = tileComp->x0; + ny0 = tileComp->y0; + nx1 = tileComp->x1; + ny1 = tileComp->y1; + } else { + cover(73); + nx0 = tileComp->resLevels[r+1].x0; + ny0 = tileComp->resLevels[r+1].y0; + nx1 = tileComp->resLevels[r+1].x1; + ny1 = tileComp->resLevels[r+1].y1; + } + inverseTransformLevel(tileComp, r, resLevel, nx0, ny0, nx1, ny1); + } +} + +// Do one level of the inverse transform: +// - take (n)LL from the tile-component data array +// - take (n)HL/LH/HH from +// - leave the resulting (n-1)LL in the tile-component data array +void JPXStream::inverseTransformLevel(JPXTileComp *tileComp, + Guint r, JPXResLevel *resLevel, + Guint nx0, Guint ny0, + Guint nx1, Guint ny1) { + JPXPrecinct *precinct; + JPXSubband *subband; + JPXCodeBlock *cb; + JPXCoeff *coeff0, *coeff; + Guint qStyle, guard, eps, shift, t; + int shift2; + double mu; + int val; + int *dataPtr; + Guint xo, yo; + Guint x, y, sb, cbX, cbY; + int xx, yy; + + //----- interleave + + // spread out LL + for (yy = resLevel->y1 - 1; yy >= (int)resLevel->y0; --yy) { + for (xx = resLevel->x1 - 1; xx >= (int)resLevel->x0; --xx) { + tileComp->data[(2 * yy - ny0) * (tileComp->x1 - tileComp->x0) + + (2 * xx - nx0)] = + tileComp->data[(yy - resLevel->y0) * (tileComp->x1 - tileComp->x0) + + (xx - resLevel->x0)]; + } + } + + // i-quant parameters + qStyle = tileComp->quantStyle & 0x1f; + guard = (tileComp->quantStyle >> 5) & 7; + + // interleave HL/LH/HH + precinct = &resLevel->precincts[0]; + for (sb = 0; sb < 3; ++sb) { + + // i-quant parameters + if (qStyle == 0) { + cover(100); + eps = (tileComp->quantSteps[3*r - 2 + sb] >> 3) & 0x1f; + shift = guard + eps - 1; + mu = 0; // make gcc happy + } else { + cover(101); + shift = guard + tileComp->prec; + if (sb == 2) { + cover(102); + ++shift; + } + t = tileComp->quantSteps[qStyle == 1 ? 0 : (3*r - 2 + sb)]; + mu = (double)(0x800 + (t & 0x7ff)) / 2048.0; + } + if (tileComp->transform == 0) { + cover(103); + shift += fracBits; + } + + // copy the subband coefficients into the data array, doing the + // fixed point adjustment and dequantization along the way + xo = (sb & 1) ? 0 : 1; + yo = (sb > 0) ? 1 : 0; + subband = &precinct->subbands[sb]; + cb = subband->cbs; + for (cbY = 0; cbY < subband->nYCBs; ++cbY) { + for (cbX = 0; cbX < subband->nXCBs; ++cbX) { + for (y = cb->y0, coeff0 = cb->coeffs; + y < cb->y1; + ++y, coeff0 += tileComp->cbW) { + dataPtr = &tileComp->data[(2 * y + yo - ny0) + * (tileComp->x1 - tileComp->x0) + + (2 * cb->x0 + xo - nx0)]; + for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) { + val = (int)coeff->mag; + if (val != 0) { + shift2 = shift - (cb->nZeroBitPlanes + coeff->len); + if (shift2 > 0) { + cover(74); + val = (val << shift2) + (1 << (shift2 - 1)); + } else { + cover(75); + val >>= -shift2; + } + if (qStyle == 0) { + cover(76); + if (tileComp->transform == 0) { + val &= -1 << fracBits; + } + } else { + cover(77); + val = (int)((double)val * mu); + } + if (coeff->flags & jpxCoeffSign) { + cover(78); + val = -val; + } + } + *dataPtr = val; + dataPtr += 2; + } + } + ++cb; + } + } + } + + //----- horizontal (row) transforms + dataPtr = tileComp->data; + for (y = 0; y < ny1 - ny0; ++y) { + inverseTransform1D(tileComp, dataPtr, 1, nx0, nx1); + dataPtr += tileComp->x1 - tileComp->x0; + } + + //----- vertical (column) transforms + dataPtr = tileComp->data; + for (x = 0; x < nx1 - nx0; ++x) { + inverseTransform1D(tileComp, dataPtr, + tileComp->x1 - tileComp->x0, ny0, ny1); + ++dataPtr; + } +} + +void JPXStream::inverseTransform1D(JPXTileComp *tileComp, + int *data, Guint stride, + Guint i0, Guint i1) { + int *buf; + Guint offset, end, i; + + //----- special case for length = 1 + if (i1 - i0 == 1) { + cover(79); + if (i0 & 1) { + cover(104); + *data >>= 1; + } + + } else { + cover(80); + + // choose an offset: this makes even buf[] indexes correspond to + // odd values of i, and vice versa + offset = 3 + (i0 & 1); + end = offset + i1 - i0; + + //----- gather + buf = tileComp->buf; + for (i = 0; i < i1 - i0; ++i) { + buf[offset + i] = data[i * stride]; + } + + //----- extend right + buf[end] = buf[end - 2]; + if (i1 - i0 == 2) { + cover(81); + buf[end+1] = buf[offset + 1]; + buf[end+2] = buf[offset]; + buf[end+3] = buf[offset + 1]; + } else { + cover(82); + buf[end+1] = buf[end - 3]; + if (i1 - i0 == 3) { + cover(105); + buf[end+2] = buf[offset + 1]; + buf[end+3] = buf[offset + 2]; + } else { + cover(106); + buf[end+2] = buf[end - 4]; + if (i1 - i0 == 4) { + cover(107); + buf[end+3] = buf[offset + 1]; + } else { + cover(108); + buf[end+3] = buf[end - 5]; + } + } + } + + //----- extend left + buf[offset - 1] = buf[offset + 1]; + buf[offset - 2] = buf[offset + 2]; + buf[offset - 3] = buf[offset + 3]; + if (offset == 4) { + cover(83); + buf[0] = buf[offset + 4]; + } + + //----- 9-7 irreversible filter + + if (tileComp->transform == 0) { + cover(84); + // step 1 (even) + for (i = 1; i <= end + 2; i += 2) { + buf[i] = (int)(idwtKappa * buf[i]); + } + // step 2 (odd) + for (i = 0; i <= end + 3; i += 2) { + buf[i] = (int)(idwtIKappa * buf[i]); + } + // step 3 (even) + for (i = 1; i <= end + 2; i += 2) { + buf[i] = (int)(buf[i] - idwtDelta * (buf[i-1] + buf[i+1])); + } + // step 4 (odd) + for (i = 2; i <= end + 1; i += 2) { + buf[i] = (int)(buf[i] - idwtGamma * (buf[i-1] + buf[i+1])); + } + // step 5 (even) + for (i = 3; i <= end; i += 2) { + buf[i] = (int)(buf[i] - idwtBeta * (buf[i-1] + buf[i+1])); + } + // step 6 (odd) + for (i = 4; i <= end - 1; i += 2) { + buf[i] = (int)(buf[i] - idwtAlpha * (buf[i-1] + buf[i+1])); + } + + //----- 5-3 reversible filter + + } else { + cover(85); + // step 1 (even) + for (i = 3; i <= end; i += 2) { + buf[i] -= (buf[i-1] + buf[i+1] + 2) >> 2; + } + // step 2 (odd) + for (i = 4; i < end; i += 2) { + buf[i] += (buf[i-1] + buf[i+1]) >> 1; + } + } + + //----- scatter + for (i = 0; i < i1 - i0; ++i) { + data[i * stride] = buf[offset + i]; + } + } +} + +// Inverse multi-component transform and DC level shift. This also +// converts fixed point samples back to integers. +GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) { + JPXTileComp *tileComp; + int coeff, d0, d1, d2, t, minVal, maxVal, zeroVal; + int *dataPtr; + Guint j, comp, x, y; + + //----- inverse multi-component transform + + if (tile->multiComp == 1) { + cover(86); + if (img.nComps < 3 || + tile->tileComps[0].hSep != tile->tileComps[1].hSep || + tile->tileComps[0].vSep != tile->tileComps[1].vSep || + tile->tileComps[1].hSep != tile->tileComps[2].hSep || + tile->tileComps[1].vSep != tile->tileComps[2].vSep) { + return gFalse; + } + + // inverse irreversible multiple component transform + if (tile->tileComps[0].transform == 0) { + cover(87); + j = 0; + for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) { + for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) { + d0 = tile->tileComps[0].data[j]; + d1 = tile->tileComps[1].data[j]; + d2 = tile->tileComps[2].data[j]; + tile->tileComps[0].data[j] = (int)(d0 + 1.402 * d2 + 0.5); + tile->tileComps[1].data[j] = + (int)(d0 - 0.34413 * d1 - 0.71414 * d2 + 0.5); + tile->tileComps[2].data[j] = (int)(d0 + 1.772 * d1 + 0.5); + ++j; + } + } + + // inverse reversible multiple component transform + } else { + cover(88); + j = 0; + for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) { + for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) { + d0 = tile->tileComps[0].data[j]; + d1 = tile->tileComps[1].data[j]; + d2 = tile->tileComps[2].data[j]; + tile->tileComps[1].data[j] = t = d0 - ((d2 + d1) >> 2); + tile->tileComps[0].data[j] = d2 + t; + tile->tileComps[2].data[j] = d1 + t; + ++j; + } + } + } + } + + //----- DC level shift + for (comp = 0; comp < img.nComps; ++comp) { + tileComp = &tile->tileComps[comp]; + + // signed: clip + if (tileComp->sgned) { + cover(89); + minVal = -(1 << (tileComp->prec - 1)); + maxVal = (1 << (tileComp->prec - 1)) - 1; + dataPtr = tileComp->data; + for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) { + for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) { + coeff = *dataPtr; + if (tileComp->transform == 0) { + cover(109); + coeff >>= fracBits; + } + if (coeff < minVal) { + cover(110); + coeff = minVal; + } else if (coeff > maxVal) { + cover(111); + coeff = maxVal; + } + *dataPtr++ = coeff; + } + } + + // unsigned: inverse DC level shift and clip + } else { + cover(90); + maxVal = (1 << tileComp->prec) - 1; + zeroVal = 1 << (tileComp->prec - 1); + dataPtr = tileComp->data; + for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) { + for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) { + coeff = *dataPtr; + if (tileComp->transform == 0) { + cover(112); + coeff >>= fracBits; + } + coeff += zeroVal; + if (coeff < 0) { + cover(113); + coeff = 0; + } else if (coeff > maxVal) { + cover(114); + coeff = maxVal; + } + *dataPtr++ = coeff; + } + } + } + } + + return gTrue; +} + +GBool JPXStream::readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen) { + Guint len, lenH; + + if (!readULong(&len) || + !readULong(boxType)) { + return gFalse; + } + if (len == 1) { + if (!readULong(&lenH) || !readULong(&len)) { + return gFalse; + } + if (lenH) { + error(getPos(), "JPX stream contains a box larger than 2^32 bytes"); + return gFalse; + } + *boxLen = len; + *dataLen = len - 16; + } else if (len == 0) { + *boxLen = 0; + *dataLen = 0; + } else { + *boxLen = len; + *dataLen = len - 8; + } + return gTrue; +} + +int JPXStream::readMarkerHdr(int *segType, Guint *segLen) { + int c; + + do { + do { + if ((c = str->getChar()) == EOF) { + return gFalse; + } + } while (c != 0xff); + do { + if ((c = str->getChar()) == EOF) { + return gFalse; + } + } while (c == 0xff); + } while (c == 0x00); + *segType = c; + if ((c >= 0x30 && c <= 0x3f) || + c == 0x4f || c == 0x92 || c == 0x93 || c == 0xd9) { + *segLen = 0; + return gTrue; + } + return readUWord(segLen); +} + +GBool JPXStream::readUByte(Guint *x) { + int c0; + + if ((c0 = str->getChar()) == EOF) { + return gFalse; + } + *x = (Guint)c0; + return gTrue; +} + +GBool JPXStream::readByte(int *x) { + int c0; + + if ((c0 = str->getChar()) == EOF) { + return gFalse; + } + *x = c0; + if (c0 & 0x80) { + *x |= -1 - 0xff; + } + return gTrue; +} + +GBool JPXStream::readUWord(Guint *x) { + int c0, c1; + + if ((c0 = str->getChar()) == EOF || + (c1 = str->getChar()) == EOF) { + return gFalse; + } + *x = (Guint)((c0 << 8) | c1); + return gTrue; +} + +GBool JPXStream::readULong(Guint *x) { + int c0, c1, c2, c3; + + if ((c0 = str->getChar()) == EOF || + (c1 = str->getChar()) == EOF || + (c2 = str->getChar()) == EOF || + (c3 = str->getChar()) == EOF) { + return gFalse; + } + *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); + return gTrue; +} + +GBool JPXStream::readNBytes(int nBytes, GBool signd, int *x) { + int y, c, i; + + y = 0; + for (i = 0; i < nBytes; ++i) { + if ((c = str->getChar()) == EOF) { + return gFalse; + } + y = (y << 8) + c; + } + if (signd) { + if (y & (1 << (8 * nBytes - 1))) { + y |= -1 << (8 * nBytes); + } + } + *x = y; + return gTrue; +} + +GBool JPXStream::readBits(int nBits, Guint *x) { + int c; + + while (bitBufLen < nBits) { + if (byteCount == 0 || (c = str->getChar()) == EOF) { + return gFalse; + } + --byteCount; + if (bitBufSkip) { + bitBuf = (bitBuf << 7) | (c & 0x7f); + bitBufLen += 7; + } else { + bitBuf = (bitBuf << 8) | (c & 0xff); + bitBufLen += 8; + } + bitBufSkip = c == 0xff; + } + *x = (bitBuf >> (bitBufLen - nBits)) & ((1 << nBits) - 1); + bitBufLen -= nBits; + return gTrue; +} + +void JPXStream::startBitBuf(Guint byteCountA) { + bitBufLen = 0; + bitBufSkip = gFalse; + byteCount = byteCountA; +} + +Guint JPXStream::finishBitBuf() { + if (bitBufSkip) { + str->getChar(); + --byteCount; + } + return byteCount; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/JPXStream.h swftools-0.9.1/lib/pdf/xpdf/JPXStream.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/JPXStream.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/JPXStream.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,351 @@ +//======================================================================== +// +// JPXStream.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef JPXSTREAM_H +#define JPXSTREAM_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" +#include "Stream.h" + +class JArithmeticDecoder; +class JArithmeticDecoderStats; + +//------------------------------------------------------------------------ + +enum JPXColorSpaceType { + jpxCSBiLevel = 0, + jpxCSYCbCr1 = 1, + jpxCSYCbCr2 = 3, + jpxCSYCBCr3 = 4, + jpxCSPhotoYCC = 9, + jpxCSCMY = 11, + jpxCSCMYK = 12, + jpxCSYCCK = 13, + jpxCSCIELab = 14, + jpxCSsRGB = 16, + jpxCSGrayscale = 17, + jpxCSBiLevel2 = 18, + jpxCSCIEJab = 19, + jpxCSCISesRGB = 20, + jpxCSROMMRGB = 21, + jpxCSsRGBYCbCr = 22, + jpxCSYPbPr1125 = 23, + jpxCSYPbPr1250 = 24 +}; + +struct JPXColorSpecCIELab { + Guint rl, ol, ra, oa, rb, ob, il; +}; + +struct JPXColorSpecEnumerated { + JPXColorSpaceType type; // color space type + union { + JPXColorSpecCIELab cieLab; + }; +}; + +struct JPXColorSpec { + Guint meth; // method + int prec; // precedence + union { + JPXColorSpecEnumerated enumerated; + }; +}; + +//------------------------------------------------------------------------ + +struct JPXPalette { + Guint nEntries; // number of entries in the palette + Guint nComps; // number of components in each entry + Guint *bpc; // bits per component, for each component + int *c; // color data: + // c[i*nComps+j] = entry i, component j +}; + +//------------------------------------------------------------------------ + +struct JPXCompMap { + Guint nChannels; // number of channels + Guint *comp; // codestream components mapped to each channel + Guint *type; // 0 for direct use, 1 for palette mapping + Guint *pComp; // palette components to use +}; + +//------------------------------------------------------------------------ + +struct JPXChannelDefn { + Guint nChannels; // number of channels + Guint *idx; // channel indexes + Guint *type; // channel types + Guint *assoc; // channel associations +}; + +//------------------------------------------------------------------------ + +struct JPXTagTreeNode { + GBool finished; // true if this node is finished + Guint val; // current value +}; + +//------------------------------------------------------------------------ + +struct JPXCoeff { + Gushort flags; // flag bits + Gushort len; // number of significant bits in mag + Guint mag; // magnitude value +}; + +// coefficient flags +#define jpxCoeffSignificantB 0 +#define jpxCoeffTouchedB 1 +#define jpxCoeffFirstMagRefB 2 +#define jpxCoeffSignB 7 +#define jpxCoeffSignificant (1 << jpxCoeffSignificantB) +#define jpxCoeffTouched (1 << jpxCoeffTouchedB) +#define jpxCoeffFirstMagRef (1 << jpxCoeffFirstMagRefB) +#define jpxCoeffSign (1 << jpxCoeffSignB) + +//------------------------------------------------------------------------ + +struct JPXCodeBlock { + //----- size + Guint x0, y0, x1, y1; // bounds + + //----- persistent state + GBool seen; // true if this code-block has already + // been seen + Guint lBlock; // base number of bits used for pkt data length + Guint nextPass; // next coding pass + + //---- info from first packet + Guint nZeroBitPlanes; // number of zero bit planes + + //----- info for the current packet + Guint included; // code-block inclusion in this packet: + // 0=not included, 1=included + Guint nCodingPasses; // number of coding passes in this pkt + Guint dataLen; // pkt data length + + //----- coefficient data + JPXCoeff *coeffs; // the coefficients + JArithmeticDecoder // arithmetic decoder + *arithDecoder; + JArithmeticDecoderStats // arithmetic decoder stats + *stats; +}; + +//------------------------------------------------------------------------ + +struct JPXSubband { + //----- computed + Guint x0, y0, x1, y1; // bounds + Guint nXCBs, nYCBs; // number of code-blocks in the x and y + // directions + + //----- tag trees + Guint maxTTLevel; // max tag tree level + JPXTagTreeNode *inclusion; // inclusion tag tree for each subband + JPXTagTreeNode *zeroBitPlane; // zero-bit plane tag tree for each + // subband + + //----- children + JPXCodeBlock *cbs; // the code-blocks (len = nXCBs * nYCBs) +}; + +//------------------------------------------------------------------------ + +struct JPXPrecinct { + //----- computed + Guint x0, y0, x1, y1; // bounds of the precinct + + //----- children + JPXSubband *subbands; // the subbands +}; + +//------------------------------------------------------------------------ + +struct JPXResLevel { + //----- from the COD and COC segments (main and tile) + Guint precinctWidth; // log2(precinct width) + Guint precinctHeight; // log2(precinct height) + + //----- computed + Guint x0, y0, x1, y1; // bounds of the tile-comp (for this res level) + Guint bx0[3], by0[3], // subband bounds + bx1[3], by1[3]; + + //---- children + JPXPrecinct *precincts; // the precincts +}; + +//------------------------------------------------------------------------ + +struct JPXTileComp { + //----- from the SIZ segment + GBool sgned; // 1 for signed, 0 for unsigned + Guint prec; // precision, in bits + Guint hSep; // horizontal separation of samples + Guint vSep; // vertical separation of samples + + //----- from the COD and COC segments (main and tile) + Guint style; // coding style parameter (Scod / Scoc) + Guint nDecompLevels; // number of decomposition levels + Guint codeBlockW; // log2(code-block width) + Guint codeBlockH; // log2(code-block height) + Guint codeBlockStyle; // code-block style + Guint transform; // wavelet transformation + + //----- from the QCD and QCC segments (main and tile) + Guint quantStyle; // quantization style + Guint *quantSteps; // quantization step size for each subband + Guint nQuantSteps; // number of entries in quantSteps + + //----- computed + Guint x0, y0, x1, y1; // bounds of the tile-comp, in ref coords + Guint cbW; // code-block width + Guint cbH; // code-block height + + //----- image data + int *data; // the decoded image data + int *buf; // intermediate buffer for the inverse + // transform + + //----- children + JPXResLevel *resLevels; // the resolution levels + // (len = nDecompLevels + 1) +}; + +//------------------------------------------------------------------------ + +struct JPXTile { + //----- from the COD segments (main and tile) + Guint progOrder; // progression order + Guint nLayers; // number of layers + Guint multiComp; // multiple component transformation + + //----- computed + Guint x0, y0, x1, y1; // bounds of the tile, in ref coords + Guint maxNDecompLevels; // max number of decomposition levels used + // in any component in this tile + + //----- progression order loop counters + Guint comp; // component + Guint res; // resolution level + Guint precinct; // precinct + Guint layer; // layer + + //----- children + JPXTileComp *tileComps; // the tile-components (len = JPXImage.nComps) +}; + +//------------------------------------------------------------------------ + +struct JPXImage { + //----- from the SIZ segment + Guint xSize, ySize; // size of reference grid + Guint xOffset, yOffset; // image offset + Guint xTileSize, yTileSize; // size of tiles + Guint xTileOffset, // offset of first tile + yTileOffset; + Guint nComps; // number of components + + //----- computed + Guint nXTiles; // number of tiles in x direction + Guint nYTiles; // number of tiles in y direction + + //----- children + JPXTile *tiles; // the tiles (len = nXTiles * nYTiles) +}; + +//------------------------------------------------------------------------ + +class JPXStream: public FilterStream { +public: + + JPXStream(Stream *strA); + virtual ~JPXStream(); + virtual StreamKind getKind() { return strJPX; } + virtual void reset(); + virtual void close(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, char *indent); + virtual GBool isBinary(GBool last = gTrue); + virtual void getImageParams(int *bitsPerComponent, + StreamColorSpaceMode *csMode); + +private: + + void fillReadBuf(); + void getImageParams2(int *bitsPerComponent, StreamColorSpaceMode *csMode); + GBool readBoxes(); + GBool readColorSpecBox(Guint dataLen); + GBool readCodestream(Guint len); + GBool readTilePart(); + GBool readTilePartData(Guint tileIdx, + Guint tilePartLen, GBool tilePartToEOC); + GBool readCodeBlockData(JPXTileComp *tileComp, + JPXResLevel *resLevel, + JPXPrecinct *precinct, + JPXSubband *subband, + Guint res, Guint sb, + JPXCodeBlock *cb); + void inverseTransform(JPXTileComp *tileComp); + void inverseTransformLevel(JPXTileComp *tileComp, + Guint r, JPXResLevel *resLevel, + Guint nx0, Guint ny0, + Guint nx1, Guint ny1); + void inverseTransform1D(JPXTileComp *tileComp, + int *data, Guint stride, + Guint i0, Guint i1); + GBool inverseMultiCompAndDC(JPXTile *tile); + GBool readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen); + int readMarkerHdr(int *segType, Guint *segLen); + GBool readUByte(Guint *x); + GBool readByte(int *x); + GBool readUWord(Guint *x); + GBool readULong(Guint *x); + GBool readNBytes(int nBytes, GBool signd, int *x); + GBool readBits(int nBits, Guint *x); + void startBitBuf(Guint byteCountA); + Guint finishBitBuf(); + + Guint nComps; // number of components + Guint *bpc; // bits per component, for each component + Guint width, height; // image size + GBool haveImgHdr; // set if a JP2/JPX image header has been + // found + JPXColorSpec cs; // color specification + GBool haveCS; // set if a color spec has been found + JPXPalette palette; // the palette + GBool havePalette; // set if a palette has been found + JPXCompMap compMap; // the component mapping + GBool haveCompMap; // set if a component mapping has been found + JPXChannelDefn channelDefn; // channel definition + GBool haveChannelDefn; // set if a channel defn has been found + + JPXImage img; // JPEG2000 decoder data + Guint bitBuf; // buffer for bit reads + int bitBufLen; // number of bits in bitBuf + GBool bitBufSkip; // true if next bit should be skipped + // (for bit stuffing) + Guint byteCount; // number of available bytes left + + Guint curX, curY, curComp; // current position for lookChar/getChar + Guint readBuf; // read buffer + Guint readBufLen; // number of valid bits in readBuf +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/leftArrowDis.xbm swftools-0.9.1/lib/pdf/xpdf/leftArrowDis.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/leftArrowDis.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/leftArrowDis.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,5 @@ +#define leftArrowDis_width 8 +#define leftArrowDis_height 15 +static unsigned char leftArrowDis_bits[] = { + 0x80, 0x40, 0xa0, 0x50, 0xa8, 0x54, 0xaa, 0x55, 0xaa, 0x54, 0xa8, 0x50, + 0xa0, 0x40, 0x80}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/leftArrow.xbm swftools-0.9.1/lib/pdf/xpdf/leftArrow.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/leftArrow.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/leftArrow.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,5 @@ +#define leftArrow_width 8 +#define leftArrow_height 15 +static unsigned char leftArrow_bits[] = { + 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xfe, 0xfc, 0xf8, 0xf0, + 0xe0, 0xc0, 0x80}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Lexer.cc swftools-0.9.1/lib/pdf/xpdf/Lexer.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Lexer.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Lexer.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,493 @@ +//======================================================================== +// +// Lexer.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include "Lexer.h" +#include "Error.h" + +//------------------------------------------------------------------------ + +// A '1' in this array means the character is white space. A '1' or +// '2' means the character ends a name or command. +static char specialChars[256] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx +}; + +//------------------------------------------------------------------------ +// Lexer +//------------------------------------------------------------------------ + +Lexer::Lexer(XRef *xref, Stream *str) { + Object obj; + + curStr.initStream(str); + streams = new Array(xref); + streams->add(curStr.copy(&obj)); + strPtr = 0; + freeArray = gTrue; + curStr.streamReset(); +} + +Lexer::Lexer(XRef *xref, Object *obj) { + Object obj2; + + if (obj->isStream()) { + streams = new Array(xref); + freeArray = gTrue; + streams->add(obj->copy(&obj2)); + } else { + streams = obj->getArray(); + freeArray = gFalse; + } + strPtr = 0; + if (streams->getLength() > 0) { + streams->get(strPtr, &curStr); + curStr.streamReset(); + } +} +static int illegalChars = 0; + +Lexer::~Lexer() { + if (!curStr.isNone()) { + curStr.streamClose(); + curStr.free(); + } + if (freeArray) { + delete streams; + } + if(illegalChars) + error(0, "Illegal characters in hex string (%d)", illegalChars); + illegalChars = 0; +} + +int Lexer::getChar() { + int c; + + c = EOF; + while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) { + curStr.streamClose(); + curStr.free(); + ++strPtr; + if (strPtr < streams->getLength()) { + streams->get(strPtr, &curStr); + curStr.streamReset(); + } + } + return c; +} + +int Lexer::lookChar() { + if (curStr.isNone()) { + return EOF; + } + return curStr.streamLookChar(); +} + +Object *Lexer::getObj(Object *obj) { + char *p; + int c, c2; + GBool comment, neg, done; + int numParen; + int xi; + double xf, scale; + GString *s; + int n, m; + + // skip whitespace and comments + comment = gFalse; + while (1) { + if ((c = getChar()) == EOF) { + return obj->initEOF(); + } + if (comment) { + if (c == '\r' || c == '\n') + comment = gFalse; + } else if (c == '%') { + comment = gTrue; + } else if (specialChars[c] != 1) { + break; + } + } + + // start reading token + switch (c) { + + // number + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '-': case '.': + neg = gFalse; + xi = 0; + if (c == '-') { + neg = gTrue; + } else if (c == '.') { + goto doReal; + } else { + xi = c - '0'; + } + while (1) { + c = lookChar(); + if (isdigit(c)) { + getChar(); + xi = xi * 10 + (c - '0'); + } else if (c == '.') { + getChar(); + goto doReal; + } else { + break; + } + } + if (neg) + xi = -xi; + obj->initInt(xi); + break; + doReal: + xf = xi; + scale = 0.1; + while (1) { + c = lookChar(); + if (c == '-') { + // ignore minus signs in the middle of numbers to match + // Adobe's behavior + error(getPos(), "Badly formatted number"); + getChar(); + continue; + } + if (!isdigit(c)) { + break; + } + getChar(); + xf = xf + scale * (c - '0'); + scale *= 0.1; + } + if (neg) + xf = -xf; + obj->initReal(xf); + break; + + // string + case '(': + p = tokBuf; + n = 0; + numParen = 1; + done = gFalse; + s = NULL; + do { + c2 = EOF; + switch (c = getChar()) { + + case EOF: +#if 0 + // This breaks some PDF files, e.g., ones from Photoshop. + case '\r': + case '\n': +#endif + error(getPos(), "Unterminated string"); + done = gTrue; + break; + + case '(': + ++numParen; + c2 = c; + break; + + case ')': + if (--numParen == 0) { + done = gTrue; + } else { + c2 = c; + } + break; + + case '\\': + switch (c = getChar()) { + case 'n': + c2 = '\n'; + break; + case 'r': + c2 = '\r'; + break; + case 't': + c2 = '\t'; + break; + case 'b': + c2 = '\b'; + break; + case 'f': + c2 = '\f'; + break; + case '\\': + case '(': + case ')': + c2 = c; + break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c2 = c - '0'; + c = lookChar(); + if (c >= '0' && c <= '7') { + getChar(); + c2 = (c2 << 3) + (c - '0'); + c = lookChar(); + if (c >= '0' && c <= '7') { + getChar(); + c2 = (c2 << 3) + (c - '0'); + } + } + break; + case '\r': + c = lookChar(); + if (c == '\n') { + getChar(); + } + break; + case '\n': + break; + case EOF: + error(getPos(), "Unterminated string"); + done = gTrue; + break; + default: + c2 = c; + break; + } + break; + + default: + c2 = c; + break; + } + + if (c2 != EOF) { + if (n == tokBufSize) { + if (!s) + s = new GString(tokBuf, tokBufSize); + else + s->append(tokBuf, tokBufSize); + p = tokBuf; + n = 0; + } + *p++ = (char)c2; + ++n; + } + } while (!done); + if (!s) + s = new GString(tokBuf, n); + else + s->append(tokBuf, n); + obj->initString(s); + break; + + // name + case '/': + p = tokBuf; + n = 0; + while ((c = lookChar()) != EOF && !specialChars[c]) { + getChar(); + if (c == '#') { + c2 = lookChar(); + if (c2 >= '0' && c2 <= '9') { + c = c2 - '0'; + } else if (c2 >= 'A' && c2 <= 'F') { + c = c2 - 'A' + 10; + } else if (c2 >= 'a' && c2 <= 'f') { + c = c2 - 'a' + 10; + } else { + goto notEscChar; + } + getChar(); + c <<= 4; + c2 = getChar(); + if (c2 >= '0' && c2 <= '9') { + c += c2 - '0'; + } else if (c2 >= 'A' && c2 <= 'F') { + c += c2 - 'A' + 10; + } else if (c2 >= 'a' && c2 <= 'f') { + c += c2 - 'a' + 10; + } else { + illegalChars++; + //error(getPos(), "Illegal digit in hex char in name"); + } + } + notEscChar: + if (++n == tokBufSize) { + error(getPos(), "Name token too long"); + break; + } + *p++ = c; + } + *p = '\0'; + obj->initName(tokBuf); + break; + + // array punctuation + case '[': + case ']': + tokBuf[0] = c; + tokBuf[1] = '\0'; + obj->initCmd(tokBuf); + break; + + // hex string or dict punctuation + case '<': + c = lookChar(); + + // dict punctuation + if (c == '<') { + getChar(); + tokBuf[0] = tokBuf[1] = '<'; + tokBuf[2] = '\0'; + obj->initCmd(tokBuf); + + // hex string + } else { + p = tokBuf; + m = n = 0; + c2 = 0; + s = NULL; + while (1) { + c = getChar(); + if (c == '>') { + break; + } else if (c == EOF) { + error(getPos(), "Unterminated hex string"); + break; + } else if (specialChars[c] != 1) { + c2 = c2 << 4; + if (c >= '0' && c <= '9') + c2 += c - '0'; + else if (c >= 'A' && c <= 'F') + c2 += c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + c2 += c - 'a' + 10; + else { + illegalChars++; + //error(getPos(), "Illegal character <%02x> in hex string", c); + } + if (++m == 2) { + if (n == tokBufSize) { + if (!s) + s = new GString(tokBuf, tokBufSize); + else + s->append(tokBuf, tokBufSize); + p = tokBuf; + n = 0; + } + *p++ = (char)c2; + ++n; + c2 = 0; + m = 0; + } + } + } + if (!s) + s = new GString(tokBuf, n); + else + s->append(tokBuf, n); + if (m == 1) + s->append((char)(c2 << 4)); + obj->initString(s); + } + break; + + // dict punctuation + case '>': + c = lookChar(); + if (c == '>') { + getChar(); + tokBuf[0] = tokBuf[1] = '>'; + tokBuf[2] = '\0'; + obj->initCmd(tokBuf); + } else { + illegalChars++; + //error(getPos(), "Illegal character '>'"); + obj->initError(); + } + break; + + // error + case ')': + case '{': + case '}': + //error(getPos(), "Illegal character '%c'", c); + illegalChars++; + obj->initError(); + break; + + // command + default: + p = tokBuf; + *p++ = c; + n = 1; + while ((c = lookChar()) != EOF && !specialChars[c]) { + getChar(); + if (++n == tokBufSize) { + error(getPos(), "Command token too long"); + break; + } + *p++ = c; + } + *p = '\0'; + if (tokBuf[0] == 't' && !strcmp(tokBuf, "true")) { + obj->initBool(gTrue); + } else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false")) { + obj->initBool(gFalse); + } else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null")) { + obj->initNull(); + } else { + obj->initCmd(tokBuf); + } + break; + } + return obj; +} + +void Lexer::skipToNextLine() { + int c; + + while (1) { + c = getChar(); + if (c == EOF || c == '\n') { + return; + } + if (c == '\r') { + if ((c = lookChar()) == '\n') { + getChar(); + } + return; + } + } +} + +GBool Lexer::isSpace(int c) { + return c >= 0 && c <= 0xff && specialChars[c] == 1; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Lexer.h swftools-0.9.1/lib/pdf/xpdf/Lexer.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Lexer.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Lexer.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,80 @@ +//======================================================================== +// +// Lexer.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef LEXER_H +#define LEXER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Object.h" +#include "Stream.h" + +class XRef; + +#define tokBufSize 128 // size of token buffer + +//------------------------------------------------------------------------ +// Lexer +//------------------------------------------------------------------------ + +class Lexer { +public: + + // Construct a lexer for a single stream. Deletes the stream when + // lexer is deleted. + Lexer(XRef *xref, Stream *str); + + // Construct a lexer for a stream or array of streams (assumes obj + // is either a stream or array of streams). + Lexer(XRef *xref, Object *obj); + + // Destructor. + ~Lexer(); + + // Get the next object from the input stream. + Object *getObj(Object *obj); + + // Skip to the beginning of the next line in the input stream. + void skipToNextLine(); + + // Skip over one character. + void skipChar() { getChar(); } + + // Get stream. + Stream *getStream() + { return curStr.isNone() ? (Stream *)NULL : curStr.getStream(); } + + // Get current position in file. This is only used for error + // messages, so it returns an int instead of a Guint. + int getPos() + { return curStr.isNone() ? -1 : (int)curStr.streamGetPos(); } + + // Set position in file. + void setPos(Guint pos, int dir = 0) + { if (!curStr.isNone()) curStr.streamSetPos(pos, dir); } + + // Returns true if is a whitespace character. + static GBool isSpace(int c); + +private: + + int getChar(); + int lookChar(); + + Array *streams; // array of input streams + int strPtr; // index of current stream + Object curStr; // current stream + GBool freeArray; // should lexer free the streams array? + char tokBuf[tokBufSize]; // temporary token buffer +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Link.cc swftools-0.9.1/lib/pdf/xpdf/Link.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Link.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Link.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,782 @@ +//======================================================================== +// +// Link.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "GString.h" +#include "Error.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Link.h" + +//------------------------------------------------------------------------ +// LinkAction +//------------------------------------------------------------------------ + +LinkAction *LinkAction::parseDest(Object *obj) { + LinkAction *action; + + action = new LinkGoTo(obj); + if (!action->isOk()) { + delete action; + return NULL; + } + return action; +} + +LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) { + LinkAction *action; + Object obj2, obj3, obj4; + + if (!obj->isDict()) { + error(-1, "Bad annotation action"); + return NULL; + } + + obj->dictLookup("S", &obj2); + + // GoTo action + if (obj2.isName("GoTo")) { + obj->dictLookup("D", &obj3); + action = new LinkGoTo(&obj3); + obj3.free(); + + // GoToR action + } else if (obj2.isName("GoToR")) { + obj->dictLookup("F", &obj3); + obj->dictLookup("D", &obj4); + action = new LinkGoToR(&obj3, &obj4); + obj3.free(); + obj4.free(); + + // Launch action + } else if (obj2.isName("Launch")) { + action = new LinkLaunch(obj); + + // URI action + } else if (obj2.isName("URI")) { + obj->dictLookup("URI", &obj3); + action = new LinkURI(&obj3, baseURI); + obj3.free(); + + // Named action + } else if (obj2.isName("Named")) { + obj->dictLookup("N", &obj3); + action = new LinkNamed(&obj3); + obj3.free(); + + // Movie action + } else if (obj2.isName("Movie")) { + obj->dictLookupNF("Annot", &obj3); + obj->dictLookup("T", &obj4); + action = new LinkMovie(&obj3, &obj4); + obj3.free(); + obj4.free(); + + // unknown action + } else if (obj2.isName()) { + action = new LinkUnknown(obj2.getName()); + + // action is missing or wrong type + } else { + error(-1, "Bad annotation action"); + action = NULL; + } + + obj2.free(); + + if (action && !action->isOk()) { + delete action; + return NULL; + } + return action; +} + +GString *LinkAction::getFileSpecName(Object *fileSpecObj) { + GString *name; + Object obj1; + + name = NULL; + + // string + if (fileSpecObj->isString()) { + name = fileSpecObj->getString()->copy(); + + // dictionary + } else if (fileSpecObj->isDict()) { +#ifdef WIN32 + if (!fileSpecObj->dictLookup("DOS", &obj1)->isString()) { +#else + if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) { +#endif + obj1.free(); + fileSpecObj->dictLookup("F", &obj1); + } + if (obj1.isString()) { + name = obj1.getString()->copy(); + } else { + error(-1, "Illegal file spec in link"); + } + obj1.free(); + + // error + } else { + error(-1, "Illegal file spec in link"); + } + + // system-dependent path manipulation + if (name) { +#ifdef WIN32 + int i, j; + + // "//...." --> "\...." + // "/x/...." --> "x:\...." + // "/server/share/...." --> "\\server\share\...." + // convert escaped slashes to slashes and unescaped slashes to backslashes + i = 0; + if (name->getChar(0) == '/') { + if (name->getLength() >= 2 && name->getChar(1) == '/') { + name->del(0); + i = 0; + } else if (name->getLength() >= 2 && + ((name->getChar(1) >= 'a' && name->getChar(1) <= 'z') || + (name->getChar(1) >= 'A' && name->getChar(1) <= 'Z')) && + (name->getLength() == 2 || name->getChar(2) == '/')) { + name->setChar(0, name->getChar(1)); + name->setChar(1, ':'); + i = 2; + } else { + for (j = 2; j < name->getLength(); ++j) { + if (name->getChar(j-1) != '\\' && + name->getChar(j) == '/') { + break; + } + } + if (j < name->getLength()) { + name->setChar(0, '\\'); + name->insert(0, '\\'); + i = 2; + } + } + } + for (; i < name->getLength(); ++i) { + if (name->getChar(i) == '/') { + name->setChar(i, '\\'); + } else if (name->getChar(i) == '\\' && + i+1 < name->getLength() && + name->getChar(i+1) == '/') { + name->del(i); + } + } +#else + // no manipulation needed for Unix +#endif + } + + return name; +} + +//------------------------------------------------------------------------ +// LinkDest +//------------------------------------------------------------------------ + +LinkDest::LinkDest(Array *a) { + Object obj1, obj2; + + // initialize fields + left = bottom = right = top = zoom = 0; + ok = gFalse; + + // get page + if (a->getLength() < 2) { + error(-1, "Annotation destination array is too short"); + return; + } + a->getNF(0, &obj1); + if (obj1.isInt()) { + pageNum = obj1.getInt() + 1; + pageIsRef = gFalse; + } else if (obj1.isRef()) { + pageRef.num = obj1.getRefNum(); + pageRef.gen = obj1.getRefGen(); + pageIsRef = gTrue; + } else { + error(-1, "Bad annotation destination"); + goto err2; + } + obj1.free(); + + // get destination type + a->get(1, &obj1); + + // XYZ link + if (obj1.isName("XYZ")) { + kind = destXYZ; + if (a->getLength() < 3) { + changeLeft = gFalse; + } else { + a->get(2, &obj2); + if (obj2.isNull()) { + changeLeft = gFalse; + } else if (obj2.isNum()) { + changeLeft = gTrue; + left = obj2.getNum(); + } else { + error(-1, "Bad annotation destination position"); + goto err1; + } + obj2.free(); + } + if (a->getLength() < 4) { + changeTop = gFalse; + } else { + a->get(3, &obj2); + if (obj2.isNull()) { + changeTop = gFalse; + } else if (obj2.isNum()) { + changeTop = gTrue; + top = obj2.getNum(); + } else { + error(-1, "Bad annotation destination position"); + goto err1; + } + obj2.free(); + } + if (a->getLength() < 5) { + changeZoom = gFalse; + } else { + a->get(4, &obj2); + if (obj2.isNull()) { + changeZoom = gFalse; + } else if (obj2.isNum()) { + changeZoom = gTrue; + zoom = obj2.getNum(); + } else { + error(-1, "Bad annotation destination position"); + goto err1; + } + obj2.free(); + } + + // Fit link + } else if (obj1.isName("Fit")) { + if (a->getLength() < 2) { + error(-1, "Annotation destination array is too short"); + goto err2; + } + kind = destFit; + + // FitH link + } else if (obj1.isName("FitH")) { + if (a->getLength() < 3) { + error(-1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitH; + if (!a->get(2, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + kind = destFit; + } + top = obj2.getNum(); + obj2.free(); + + // FitV link + } else if (obj1.isName("FitV")) { + if (a->getLength() < 3) { + error(-1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitV; + if (!a->get(2, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + kind = destFit; + } + left = obj2.getNum(); + obj2.free(); + + // FitR link + } else if (obj1.isName("FitR")) { + if (a->getLength() < 6) { + error(-1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitR; + if (!a->get(2, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + kind = destFit; + } + left = obj2.getNum(); + obj2.free(); + if (!a->get(3, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + kind = destFit; + } + bottom = obj2.getNum(); + obj2.free(); + if (!a->get(4, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + kind = destFit; + } + right = obj2.getNum(); + obj2.free(); + if (!a->get(5, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + kind = destFit; + } + top = obj2.getNum(); + obj2.free(); + + // FitB link + } else if (obj1.isName("FitB")) { + if (a->getLength() < 2) { + error(-1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitB; + + // FitBH link + } else if (obj1.isName("FitBH")) { + if (a->getLength() < 3) { + error(-1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitBH; + if (!a->get(2, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + kind = destFit; + } + top = obj2.getNum(); + obj2.free(); + + // FitBV link + } else if (obj1.isName("FitBV")) { + if (a->getLength() < 3) { + error(-1, "Annotation destination array is too short"); + goto err2; + } + kind = destFitBV; + if (!a->get(2, &obj2)->isNum()) { + error(-1, "Bad annotation destination position"); + kind = destFit; + } + left = obj2.getNum(); + obj2.free(); + + // unknown link kind + } else { + error(-1, "Unknown annotation destination type"); + goto err2; + } + + obj1.free(); + ok = gTrue; + return; + + err1: + obj2.free(); + err2: + obj1.free(); +} + +LinkDest::LinkDest(LinkDest *dest) { + kind = dest->kind; + pageIsRef = dest->pageIsRef; + if (pageIsRef) + pageRef = dest->pageRef; + else + pageNum = dest->pageNum; + left = dest->left; + bottom = dest->bottom; + right = dest->right; + top = dest->top; + zoom = dest->zoom; + changeLeft = dest->changeLeft; + changeTop = dest->changeTop; + changeZoom = dest->changeZoom; + ok = gTrue; +} + +//------------------------------------------------------------------------ +// LinkGoTo +//------------------------------------------------------------------------ + +LinkGoTo::LinkGoTo(Object *destObj) { + dest = NULL; + namedDest = NULL; + + // named destination + if (destObj->isName()) { + namedDest = new GString(destObj->getName()); + } else if (destObj->isString()) { + namedDest = destObj->getString()->copy(); + + // destination dictionary + } else if (destObj->isArray()) { + dest = new LinkDest(destObj->getArray()); + if (!dest->isOk()) { + delete dest; + dest = NULL; + } + // error + } else { + error(-1, "Illegal annotation destination %d", destObj->getType()); + } +} + +LinkGoTo::~LinkGoTo() { + if (dest) + delete dest; + if (namedDest) + delete namedDest; +} + +//------------------------------------------------------------------------ +// LinkGoToR +//------------------------------------------------------------------------ + +LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) { + dest = NULL; + namedDest = NULL; + + // get file name + fileName = getFileSpecName(fileSpecObj); + + // named destination + if (destObj->isName()) { + namedDest = new GString(destObj->getName()); + } else if (destObj->isString()) { + namedDest = destObj->getString()->copy(); + + // destination dictionary + } else if (destObj->isArray()) { + dest = new LinkDest(destObj->getArray()); + if (!dest->isOk()) { + delete dest; + dest = NULL; + } + // error + } else { + error(-1, "Illegal annotation destination %d", destObj->getType()); + } +} + +LinkGoToR::~LinkGoToR() { + if (fileName) + delete fileName; + if (dest) + delete dest; + if (namedDest) + delete namedDest; +} + + +//------------------------------------------------------------------------ +// LinkLaunch +//------------------------------------------------------------------------ + +LinkLaunch::LinkLaunch(Object *actionObj) { + Object obj1, obj2; + + fileName = NULL; + params = NULL; + + if (actionObj->isDict()) { + if (!actionObj->dictLookup("F", &obj1)->isNull()) { + fileName = getFileSpecName(&obj1); + } else { + obj1.free(); +#ifdef WIN32 + if (actionObj->dictLookup("Win", &obj1)->isDict()) { + obj1.dictLookup("F", &obj2); + fileName = getFileSpecName(&obj2); + obj2.free(); + if (obj1.dictLookup("P", &obj2)->isString()) { + params = obj2.getString()->copy(); + } + obj2.free(); + } else { + error(-1, "Bad launch-type link action"); + } +#else + //~ This hasn't been defined by Adobe yet, so assume it looks + //~ just like the Win dictionary until they say otherwise. + if (actionObj->dictLookup("Unix", &obj1)->isDict()) { + obj1.dictLookup("F", &obj2); + fileName = getFileSpecName(&obj2); + obj2.free(); + if (obj1.dictLookup("P", &obj2)->isString()) { + params = obj2.getString()->copy(); + } + obj2.free(); + } else { + error(-1, "Bad launch-type link action"); + } +#endif + } + obj1.free(); + } +} + +LinkLaunch::~LinkLaunch() { + if (fileName) + delete fileName; + if (params) + delete params; +} + +//------------------------------------------------------------------------ +// LinkURI +//------------------------------------------------------------------------ + +LinkURI::LinkURI(Object *uriObj, GString *baseURI) { + GString *uri2; + int n; + char c; + + uri = NULL; + if (uriObj->isString()) { + uri2 = uriObj->getString()->copy(); + if (baseURI && baseURI->getLength() > 0) { + n = strcspn(uri2->getCString(), "/:"); + if (n == uri2->getLength() || uri2->getChar(n) == '/') { + uri = baseURI->copy(); + c = uri->getChar(uri->getLength() - 1); + if (c == '/' || c == '?') { + if (uri2->getChar(0) == '/') { + uri2->del(0); + } + } else { + if (uri2->getChar(0) != '/') { + uri->append('/'); + } + } + uri->append(uri2); + delete uri2; + } else { + uri = uri2; + } + } else { + uri = uri2; + } + } else { + error(-1, "Illegal URI-type link"); + } +} + +LinkURI::~LinkURI() { + if (uri) + delete uri; +} + +//------------------------------------------------------------------------ +// LinkNamed +//------------------------------------------------------------------------ + +LinkNamed::LinkNamed(Object *nameObj) { + name = NULL; + if (nameObj->isName()) { + name = new GString(nameObj->getName()); + } +} + +LinkNamed::~LinkNamed() { + if (name) { + delete name; + } +} + +//------------------------------------------------------------------------ +// LinkMovie +//------------------------------------------------------------------------ + +LinkMovie::LinkMovie(Object *annotObj, Object *titleObj) { + annotRef.num = -1; + title = NULL; + if (annotObj->isRef()) { + annotRef = annotObj->getRef(); + } else if (titleObj->isString()) { + title = titleObj->getString()->copy(); + } else { + error(-1, "Movie action is missing both the Annot and T keys"); + } +} + +LinkMovie::~LinkMovie() { + if (title) { + delete title; + } +} + +//------------------------------------------------------------------------ +// LinkUnknown +//------------------------------------------------------------------------ + +LinkUnknown::LinkUnknown(char *actionA) { + action = new GString(actionA); +} + +LinkUnknown::~LinkUnknown() { + delete action; +} + +//------------------------------------------------------------------------ +// Link +//------------------------------------------------------------------------ + +Link::Link(Dict *dict, GString *baseURI) { + Object obj1, obj2; + double t; + + action = NULL; + ok = gFalse; + + // get rectangle + if (!dict->lookup("Rect", &obj1)->isArray()) { + error(-1, "Annotation rectangle is wrong type"); + goto err2; + } + if (!obj1.arrayGet(0, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + x1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(1, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + y1 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(2, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + x2 = obj2.getNum(); + obj2.free(); + if (!obj1.arrayGet(3, &obj2)->isNum()) { + error(-1, "Bad annotation rectangle"); + goto err1; + } + y2 = obj2.getNum(); + obj2.free(); + obj1.free(); + if (x1 > x2) { + t = x1; + x1 = x2; + x2 = t; + } + if (y1 > y2) { + t = y1; + y1 = y2; + y2 = t; + } + + // look for destination + if (!dict->lookup("Dest", &obj1)->isNull()) { + action = LinkAction::parseDest(&obj1); + + // look for action + } else { + obj1.free(); + if (dict->lookup("A", &obj1)->isDict()) { + action = LinkAction::parseAction(&obj1, baseURI); + } + } + obj1.free(); + + // check for bad action + if (action) { + ok = gTrue; + } + + return; + + err1: + obj2.free(); + err2: + obj1.free(); +} + +Link::~Link() { + if (action) { + delete action; + } +} + +//------------------------------------------------------------------------ +// Links +//------------------------------------------------------------------------ + +Links::Links(Object *annots, GString *baseURI) { + Link *link; + Object obj1, obj2; + int size; + int i; + + links = NULL; + size = 0; + numLinks = 0; + + if (annots->isArray()) { + for (i = 0; i < annots->arrayGetLength(); ++i) { + if (annots->arrayGet(i, &obj1)->isDict()) { + if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) { + link = new Link(obj1.getDict(), baseURI); + if (link->isOk()) { + if (numLinks >= size) { + size += 16; + links = (Link **)greallocn(links, size, sizeof(Link *)); + } + links[numLinks++] = link; + } else { + delete link; + } + } + obj2.free(); + } + obj1.free(); + } + } +} + +Links::~Links() { + int i; + + for (i = 0; i < numLinks; ++i) + delete links[i]; + gfree(links); +} + +LinkAction *Links::find(double x, double y) { + int i; + + for (i = numLinks - 1; i >= 0; --i) { + if (links[i]->inRect(x, y)) { + return links[i]->getAction(); + } + } + return NULL; +} + +GBool Links::onLink(double x, double y) { + int i; + + for (i = 0; i < numLinks; ++i) { + if (links[i]->inRect(x, y)) + return gTrue; + } + return gFalse; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Link.h swftools-0.9.1/lib/pdf/xpdf/Link.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Link.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Link.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,369 @@ +//======================================================================== +// +// Link.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef LINK_H +#define LINK_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Object.h" + +class GString; +class Array; +class Dict; + +//------------------------------------------------------------------------ +// LinkAction +//------------------------------------------------------------------------ + +enum LinkActionKind { + actionGoTo, // go to destination + actionGoToR, // go to destination in new file + actionLaunch, // launch app (or open document) + actionURI, // URI + actionNamed, // named action + actionMovie, // movie action + actionUnknown // anything else +}; + +class LinkAction { +public: + + // Destructor. + virtual ~LinkAction() {} + + // Was the LinkAction created successfully? + virtual GBool isOk() = 0; + + // Check link action type. + virtual LinkActionKind getKind() = 0; + + // Parse a destination (old-style action) name, string, or array. + static LinkAction *parseDest(Object *obj); + + // Parse an action dictionary. + static LinkAction *parseAction(Object *obj, GString *baseURI = NULL); + + // Extract a file name from a file specification (string or + // dictionary). + static GString *getFileSpecName(Object *fileSpecObj); +}; + +//------------------------------------------------------------------------ +// LinkDest +//------------------------------------------------------------------------ + +enum LinkDestKind { + destXYZ, + destFit, + destFitH, + destFitV, + destFitR, + destFitB, + destFitBH, + destFitBV +}; + +class LinkDest { +public: + + // Build a LinkDest from the array. + LinkDest(Array *a); + + // Copy a LinkDest. + LinkDest *copy() { return new LinkDest(this); } + + // Was the LinkDest created successfully? + GBool isOk() { return ok; } + + // Accessors. + LinkDestKind getKind() { return kind; } + GBool isPageRef() { return pageIsRef; } + int getPageNum() { return pageNum; } + Ref getPageRef() { return pageRef; } + double getLeft() { return left; } + double getBottom() { return bottom; } + double getRight() { return right; } + double getTop() { return top; } + double getZoom() { return zoom; } + GBool getChangeLeft() { return changeLeft; } + GBool getChangeTop() { return changeTop; } + GBool getChangeZoom() { return changeZoom; } + +private: + + LinkDestKind kind; // destination type + GBool pageIsRef; // is the page a reference or number? + union { + Ref pageRef; // reference to page + int pageNum; // one-relative page number + }; + double left, bottom; // position + double right, top; + double zoom; // zoom factor + GBool changeLeft, changeTop; // for destXYZ links, which position + GBool changeZoom; // components to change + GBool ok; // set if created successfully + + LinkDest(LinkDest *dest); +}; + +//------------------------------------------------------------------------ +// LinkGoTo +//------------------------------------------------------------------------ + +class LinkGoTo: public LinkAction { +public: + + // Build a LinkGoTo from a destination (dictionary, name, or string). + LinkGoTo(Object *destObj); + + // Destructor. + virtual ~LinkGoTo(); + + // Was the LinkGoTo created successfully? + virtual GBool isOk() { return dest || namedDest; } + + // Accessors. + virtual LinkActionKind getKind() { return actionGoTo; } + LinkDest *getDest() { return dest; } + GString *getNamedDest() { return namedDest; } + +private: + + LinkDest *dest; // regular destination (NULL for remote + // link with bad destination) + GString *namedDest; // named destination (only one of dest and + // and namedDest may be non-NULL) +}; + +//------------------------------------------------------------------------ +// LinkGoToR +//------------------------------------------------------------------------ + +class LinkGoToR: public LinkAction { +public: + + // Build a LinkGoToR from a file spec (dictionary) and destination + // (dictionary, name, or string). + LinkGoToR(Object *fileSpecObj, Object *destObj); + + // Destructor. + virtual ~LinkGoToR(); + + // Was the LinkGoToR created successfully? + virtual GBool isOk() { return fileName && (dest || namedDest); } + + // Accessors. + virtual LinkActionKind getKind() { return actionGoToR; } + GString *getFileName() { return fileName; } + LinkDest *getDest() { return dest; } + GString *getNamedDest() { return namedDest; } + +private: + + GString *fileName; // file name + LinkDest *dest; // regular destination (NULL for remote + // link with bad destination) + GString *namedDest; // named destination (only one of dest and + // and namedDest may be non-NULL) +}; + +//------------------------------------------------------------------------ +// LinkLaunch +//------------------------------------------------------------------------ + +class LinkLaunch: public LinkAction { +public: + + // Build a LinkLaunch from an action dictionary. + LinkLaunch(Object *actionObj); + + // Destructor. + virtual ~LinkLaunch(); + + // Was the LinkLaunch created successfully? + virtual GBool isOk() { return fileName != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionLaunch; } + GString *getFileName() { return fileName; } + GString *getParams() { return params; } + +private: + + GString *fileName; // file name + GString *params; // parameters +}; + +//------------------------------------------------------------------------ +// LinkURI +//------------------------------------------------------------------------ + +class LinkURI: public LinkAction { +public: + + // Build a LinkURI given the URI (string) and base URI. + LinkURI(Object *uriObj, GString *baseURI); + + // Destructor. + virtual ~LinkURI(); + + // Was the LinkURI created successfully? + virtual GBool isOk() { return uri != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionURI; } + GString *getURI() { return uri; } + +private: + + GString *uri; // the URI +}; + +//------------------------------------------------------------------------ +// LinkNamed +//------------------------------------------------------------------------ + +class LinkNamed: public LinkAction { +public: + + // Build a LinkNamed given the action name. + LinkNamed(Object *nameObj); + + virtual ~LinkNamed(); + + virtual GBool isOk() { return name != NULL; } + + virtual LinkActionKind getKind() { return actionNamed; } + GString *getName() { return name; } + +private: + + GString *name; +}; + +//------------------------------------------------------------------------ +// LinkMovie +//------------------------------------------------------------------------ + +class LinkMovie: public LinkAction { +public: + + LinkMovie(Object *annotObj, Object *titleObj); + + virtual ~LinkMovie(); + + virtual GBool isOk() { return annotRef.num >= 0 || title != NULL; } + + virtual LinkActionKind getKind() { return actionMovie; } + GBool hasAnnotRef() { return annotRef.num >= 0; } + Ref *getAnnotRef() { return &annotRef; } + GString *getTitle() { return title; } + +private: + + Ref annotRef; + GString *title; +}; + +//------------------------------------------------------------------------ +// LinkUnknown +//------------------------------------------------------------------------ + +class LinkUnknown: public LinkAction { +public: + + // Build a LinkUnknown with the specified action type. + LinkUnknown(char *actionA); + + // Destructor. + virtual ~LinkUnknown(); + + // Was the LinkUnknown create successfully? + virtual GBool isOk() { return action != NULL; } + + // Accessors. + virtual LinkActionKind getKind() { return actionUnknown; } + GString *getAction() { return action; } + +private: + + GString *action; // action subtype +}; + +//------------------------------------------------------------------------ +// Link +//------------------------------------------------------------------------ + +class Link { +public: + + // Construct a link, given its dictionary. + Link(Dict *dict, GString *baseURI); + + // Destructor. + ~Link(); + + // Was the link created successfully? + GBool isOk() { return ok; } + + // Check if point is inside the link rectangle. + GBool inRect(double x, double y) + { return x1 <= x && x <= x2 && y1 <= y && y <= y2; } + + // Get action. + LinkAction *getAction() { return action; } + + // Get the link rectangle. + void getRect(double *xa1, double *ya1, double *xa2, double *ya2) + { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; } + +private: + + double x1, y1; // lower left corner + double x2, y2; // upper right corner + LinkAction *action; // action + GBool ok; // is link valid? +}; + +//------------------------------------------------------------------------ +// Links +//------------------------------------------------------------------------ + +class Links { +public: + + // Extract links from array of annotations. + Links(Object *annots, GString *baseURI); + + // Destructor. + ~Links(); + + // Iterate through list of links. + int getNumLinks() { return numLinks; } + Link *getLink(int i) { return links[i]; } + + // If point , is in a link, return the associated action; + // else return NULL. + LinkAction *find(double x, double y); + + // Return true if , is in a link. + GBool onLink(double x, double y); + +private: + + Link **links; + int numLinks; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Makefile.in swftools-0.9.1/lib/pdf/xpdf/Makefile.in --- swftools-0.9.2+ds1/lib/pdf/xpdf/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Makefile.in 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,71 @@ +#======================================================================== +# +# Goo library Makefile +# +# Copyright 1996-2003 Glyph & Cog, LLC +# +#======================================================================== + +SHELL = /bin/sh + +srcdir = @srcdir@ +VPATH = @srcdir@ + +CFLAGS = @CFLAGS@ @DEFS@ -I.. -I$(srcdir) +CXXFLAGS = @CXXFLAGS@ @DEFS@ -I.. -I$(srcdir) + +CC = @CC@ +CXX = @CXX@ +AR = @AR@ +RANLIB = @RANLIB@ + +LIBPREFIX = @LIBPREFIX@ + +#------------------------------------------------------------------------ + +.SUFFIXES: .cc + +.cc.o: + $(CXX) $(CXXFLAGS) -c $< + +#------------------------------------------------------------------------ + +CXX_SRC = \ + $(srcdir)/GHash.cc \ + $(srcdir)/GList.cc \ + $(srcdir)/GString.cc \ + $(srcdir)/gmem.cc \ + $(srcdir)/gmempp.cc \ + $(srcdir)/gfile.cc \ + $(srcdir)/FixedPoint.cc + +C_SRC = \ + $(srcdir)/parseargs.c + +#------------------------------------------------------------------------ + +all: $(LIBPREFIX)Goo.a + +#------------------------------------------------------------------------ + +GOO_CXX_OBJS = GHash.o GList.o GString.o gmem.o gmempp.o gfile.o FixedPoint.o +GOO_C_OBJS = parseargs.o +GOO_OBJS = $(GOO_CXX_OBJS) $(GOO_C_OBJS) + +$(LIBPREFIX)Goo.a: $(GOO_OBJS) + rm -f $(LIBPREFIX)Goo.a + $(AR) $(LIBPREFIX)Goo.a $(GOO_OBJS) + $(RANLIB) $(LIBPREFIX)Goo.a + +#------------------------------------------------------------------------ + +clean: + rm -f $(GOO_OBJS) $(LIBPREFIX)Goo.a + +#------------------------------------------------------------------------ + +depend: + $(CXX) $(CXXFLAGS) -MM $(CXX_SRC) >Makefile.dep + $(CC) $(CFLAGS) -MM $(C_SRC) >>Makefile.dep + +include Makefile.dep diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/ms_make.bat swftools-0.9.1/lib/pdf/xpdf/ms_make.bat --- swftools-0.9.2+ds1/lib/pdf/xpdf/ms_make.bat 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/ms_make.bat 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,118 @@ +set CC=cl +set CFLAGS=/DWIN32 /I.. /I..\goo /I..\fofi /O2 /nologo +set CXX=cl +set CXXFLAGS=%CFLAGS% /TP +set LIBPROG=lib +set LINKFLAGS=/MT /nologo + +copy aconf-win32.h aconf.h + +cd goo +%CXX% %CXXFLAGS% /c GHash.cc +%CXX% %CXXFLAGS% /c GList.cc +%CXX% %CXXFLAGS% /c GString.cc +%CXX% %CXXFLAGS% /c gmem.cc +%CXX% %CXXFLAGS% /c gmempp.cc +%CXX% %CXXFLAGS% /c gfile.cc +%CC% %CFLAGS% /c parseargs.c +%LIBPROG% /nologo /out:Goo.lib GHash.obj GList.obj GString.obj gmempp.obj gfile.obj gmem.obj parseargs.obj + +cd ..\fofi +%CXX% %CXXFLAGS% /c FoFiBase.cc +%CXX% %CXXFLAGS% /c FoFiEncodings.cc +%CXX% %CXXFLAGS% /c FoFiTrueType.cc +%CXX% %CXXFLAGS% /c FoFiType1.cc +%CXX% %CXXFLAGS% /c FoFiType1C.cc +%LIBPROG% /nologo /out:fofi.lib FoFiBase.obj FoFiEncodings.obj FoFiTrueType.obj FoFiType1.obj FoFiType1C.obj + +cd ..\xpdf +%CXX% %CXXFLAGS% /c Annot.cc +%CXX% %CXXFLAGS% /c Array.cc +%CXX% %CXXFLAGS% /c BuiltinFont.cc +%CXX% %CXXFLAGS% /c BuiltinFontTables.cc +%CXX% %CXXFLAGS% /c CMap.cc +%CXX% %CXXFLAGS% /c Catalog.cc +%CXX% %CXXFLAGS% /c CharCodeToUnicode.cc +%CXX% %CXXFLAGS% /c Decrypt.cc +%CXX% %CXXFLAGS% /c Dict.cc +%CXX% %CXXFLAGS% /c Error.cc +%CXX% %CXXFLAGS% /c FontEncodingTables.cc +%CXX% %CXXFLAGS% /c Function.cc +%CXX% %CXXFLAGS% /c Gfx.cc +%CXX% %CXXFLAGS% /c GfxFont.cc +%CXX% %CXXFLAGS% /c GfxState.cc +%CXX% %CXXFLAGS% /c GlobalParams.cc +%CXX% %CXXFLAGS% /c ImageOutputDev.cc +%CXX% %CXXFLAGS% /c JArithmeticDecoder.cc +%CXX% %CXXFLAGS% /c JBIG2Stream.cc +%CXX% %CXXFLAGS% /c JPXStream.cc +%CXX% %CXXFLAGS% /c Lexer.cc +%CXX% %CXXFLAGS% /c Link.cc +%CXX% %CXXFLAGS% /c NameToCharCode.cc +%CXX% %CXXFLAGS% /c Object.cc +%CXX% %CXXFLAGS% /c Outline.cc +%CXX% %CXXFLAGS% /c OutputDev.cc +%CXX% %CXXFLAGS% /c PDFDoc.cc +%CXX% %CXXFLAGS% /c PDFDocEncoding.cc +%CXX% %CXXFLAGS% /c PSOutputDev.cc +%CXX% %CXXFLAGS% /c PSTokenizer.cc +%CXX% %CXXFLAGS% /c Page.cc +%CXX% %CXXFLAGS% /c Parser.cc +%CXX% %CXXFLAGS% /c SecurityHandler.cc +%CXX% %CXXFLAGS% /c Stream.cc +%CXX% %CXXFLAGS% /c TextOutputDev.cc +%CXX% %CXXFLAGS% /c UnicodeMap.cc +%CXX% %CXXFLAGS% /c UnicodeTypeTable.cc +%CXX% %CXXFLAGS% /c XRef.cc +%CXX% %CXXFLAGS% /c pdftops.cc +%CXX% %CXXFLAGS% /c pdftotext.cc +%CXX% %CXXFLAGS% /c pdfinfo.cc +%CXX% %CXXFLAGS% /c pdffonts.cc +%CXX% %CXXFLAGS% /c pdfimages.cc + +%CXX% %LINKFLAGS% /Fepdftops.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSOutputDev.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdftops.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib + +%CXX% %LINKFLAGS% /Fepdftotext.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj TextOutputDev.obj UnicodeMap.obj UnicodeTypeTable.obj XRef.obj pdftotext.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib + +%CXX% %LINKFLAGS% /Fepdfinfo.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdfinfo.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib + +%CXX% %LINKFLAGS% /Fepdffonts.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdffonts.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib + +%CXX% %LINKFLAGS% /Fepdfimages.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj ImageOutputDev.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj Stream.obj UnicodeMap.obj XRef.obj pdfimages.obj ..\fofi\fofi.lib ..\goo\Goo.lib shell32.lib user32.lib gdi32.lib advapi32.lib + +cd .. + +rem --- This part will only work if you have FreeType installed --- + +set FT2DIR=..\freetype-2.3.1 +set CXXFLAGS=%CXXFLAGS% /I..\splash /I%FT2DIR%\include + +cd splash +%CXX% %CXXFLAGS% /c Splash.cc +%CXX% %CXXFLAGS% /c SplashBitmap.cc +%CXX% %CXXFLAGS% /c SplashClip.cc +%CXX% %CXXFLAGS% /c SplashFTFont.cc +%CXX% %CXXFLAGS% /c SplashFTFontEngine.cc +%CXX% %CXXFLAGS% /c SplashFTFontFile.cc +%CXX% %CXXFLAGS% /c SplashFont.cc +%CXX% %CXXFLAGS% /c SplashFontEngine.cc +%CXX% %CXXFLAGS% /c SplashFontFile.cc +%CXX% %CXXFLAGS% /c SplashFontFileID.cc +%CXX% %CXXFLAGS% /c SplashPath.cc +%CXX% %CXXFLAGS% /c SplashPattern.cc +%CXX% %CXXFLAGS% /c SplashScreen.cc +%CXX% %CXXFLAGS% /c SplashState.cc +%CXX% %CXXFLAGS% /c SplashT1Font.cc +%CXX% %CXXFLAGS% /c SplashT1FontEngine.cc +%CXX% %CXXFLAGS% /c SplashT1FontFile.cc +%CXX% %CXXFLAGS% /c SplashXPath.cc +%CXX% %CXXFLAGS% /c SplashXPathScanner.cc +%LIBPROG% /nologo /out:splash.lib Splash.obj SplashBitmap.obj SplashClip.obj SplashFTFont.obj SplashFTFontEngine.obj SplashFTFontFile.obj SplashFont.obj SplashFontEngine.obj SplashFontFile.obj SplashFontFileID.obj SplashPath.obj SplashPattern.obj SplashScreen.obj SplashState.obj SplashT1Font.obj SplashT1FontEngine.obj SplashT1FontFile.obj SplashXPath.obj SplashXPathScanner.obj + +cd ..\xpdf +%CXX% %CXXFLAGS% /c SplashOutputDev.cc +%CXX% %CXXFLAGS% /c pdftoppm.cc + +%CXX% %LINKFLAGS% /Fepdftoppm.exe Annot.obj Array.obj BuiltinFont.obj BuiltinFontTables.obj Catalog.obj CharCodeToUnicode.obj CMap.obj Decrypt.obj Dict.obj Error.obj FontEncodingTables.obj Function.obj Gfx.obj GfxFont.obj GfxState.obj GlobalParams.obj JArithmeticDecoder.obj JBIG2Stream.obj JPXStream.obj Lexer.obj Link.obj NameToCharCode.obj Object.obj Outline.obj OutputDev.obj Page.obj Parser.obj PDFDoc.obj PDFDocEncoding.obj PSTokenizer.obj SecurityHandler.obj SplashOutputDev.obj Stream.obj UnicodeMap.obj UnicodeTypeTable.obj XRef.obj pdftoppm.obj ..\splash\splash.lib ..\fofi\fofi.lib ..\goo\Goo.lib %FT2DIR%\freetype2.lib shell32.lib user32.lib gdi32.lib advapi32.lib + +cd .. diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/NameToCharCode.cc swftools-0.9.1/lib/pdf/xpdf/NameToCharCode.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/NameToCharCode.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/NameToCharCode.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,116 @@ +//======================================================================== +// +// NameToCharCode.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "NameToCharCode.h" + +//------------------------------------------------------------------------ + +struct NameToCharCodeEntry { + char *name; + CharCode c; +}; + +//------------------------------------------------------------------------ + +NameToCharCode::NameToCharCode() { + int i; + + size = 31; + len = 0; + tab = (NameToCharCodeEntry *)gmallocn(size, sizeof(NameToCharCodeEntry)); + for (i = 0; i < size; ++i) { + tab[i].name = NULL; + } +} + +NameToCharCode::~NameToCharCode() { + int i; + + for (i = 0; i < size; ++i) { + if (tab[i].name) { + gfree(tab[i].name); + } + } + gfree(tab); +} + +void NameToCharCode::add(char *name, CharCode c) { + NameToCharCodeEntry *oldTab; + int h, i, oldSize; + + // expand the table if necessary + if (len >= size / 2) { + oldSize = size; + oldTab = tab; + size = 2*size + 1; + tab = (NameToCharCodeEntry *)gmallocn(size, sizeof(NameToCharCodeEntry)); + for (h = 0; h < size; ++h) { + tab[h].name = NULL; + } + for (i = 0; i < oldSize; ++i) { + if (oldTab[i].name) { + h = hash(oldTab[i].name); + while (tab[h].name) { + if (++h == size) { + h = 0; + } + } + tab[h] = oldTab[i]; + } + } + gfree(oldTab); + } + + // add the new name + h = hash(name); + while (tab[h].name && strcmp(tab[h].name, name)) { + if (++h == size) { + h = 0; + } + } + if (!tab[h].name) { + tab[h].name = copyString(name); + } + tab[h].c = c; + + ++len; +} + +CharCode NameToCharCode::lookup(char *name) { + int h; + + h = hash(name); + while (tab[h].name) { + if (!strcmp(tab[h].name, name)) { + return tab[h].c; + } + if (++h == size) { + h = 0; + } + } + return 0; +} + +int NameToCharCode::hash(char *name) { + char *p; + unsigned int h; + + h = 0; + for (p = name; *p; ++p) { + h = 17 * h + (int)(*p & 0xff); + } + return (int)(h % size); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/NameToCharCode.h swftools-0.9.1/lib/pdf/xpdf/NameToCharCode.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/NameToCharCode.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/NameToCharCode.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,42 @@ +//======================================================================== +// +// NameToCharCode.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef NAMETOCHARCODE_H +#define NAMETOCHARCODE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "CharTypes.h" + +struct NameToCharCodeEntry; + +//------------------------------------------------------------------------ + +class NameToCharCode { +public: + + NameToCharCode(); + ~NameToCharCode(); + + void add(char *name, CharCode c); + CharCode lookup(char *name); + +private: + + int hash(char *name); + + NameToCharCodeEntry *tab; + int size; + int len; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/NameToUnicodeTable.h swftools-0.9.1/lib/pdf/xpdf/NameToUnicodeTable.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/NameToUnicodeTable.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/NameToUnicodeTable.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,1097 @@ +//======================================================================== +// +// NameToUnicodeTable.h +// +// Copyright 2001-2004 Glyph & Cog, LLC +// +//======================================================================== + +static struct { + Unicode u; + char *name; +} nameToUnicodeTab[] = { + {0x0021, "!"}, + {0x0023, "#"}, + {0x0024, "$"}, + {0x0025, "%"}, + {0x0026, "&"}, + {0x0027, "'"}, + {0x0028, "("}, + {0x0029, ")"}, + {0x002a, "*"}, + {0x002b, "+"}, + {0x002c, ","}, + {0x002d, "-"}, + {0x002e, "."}, + {0x002f, "/"}, + {0x0030, "0"}, + {0x0031, "1"}, + {0x0032, "2"}, + {0x0033, "3"}, + {0x0034, "4"}, + {0x0035, "5"}, + {0x0036, "6"}, + {0x0037, "7"}, + {0x0038, "8"}, + {0x0039, "9"}, + {0x003a, ":"}, + {0x003b, ";"}, + {0x003c, "<"}, + {0x003d, "="}, + {0x003e, ">"}, + {0x003f, "?"}, + {0x0040, "@"}, + {0x0041, "A"}, + {0x00c6, "AE"}, + {0x01fc, "AEacute"}, + {0xf7e6, "AEsmall"}, + {0x00c1, "Aacute"}, + {0xf7e1, "Aacutesmall"}, + {0x0102, "Abreve"}, + {0x00c2, "Acircumflex"}, + {0xf7e2, "Acircumflexsmall"}, + {0xf6c9, "Acute"}, + {0xf7b4, "Acutesmall"}, + {0x00c4, "Adieresis"}, + {0xf7e4, "Adieresissmall"}, + {0x00c0, "Agrave"}, + {0xf7e0, "Agravesmall"}, + {0x0391, "Alpha"}, + {0x0386, "Alphatonos"}, + {0x0100, "Amacron"}, + {0x0104, "Aogonek"}, + {0x00c5, "Aring"}, + {0x01fa, "Aringacute"}, + {0xf7e5, "Aringsmall"}, + {0xf761, "Asmall"}, + {0x00c3, "Atilde"}, + {0xf7e3, "Atildesmall"}, + {0x0042, "B"}, + {0x0392, "Beta"}, + {0xf6f4, "Brevesmall"}, + {0xf762, "Bsmall"}, + {0x0043, "C"}, + {0x0106, "Cacute"}, + {0xf6ca, "Caron"}, + {0xf6f5, "Caronsmall"}, + {0x010c, "Ccaron"}, + {0x00c7, "Ccedilla"}, + {0xf7e7, "Ccedillasmall"}, + {0x0108, "Ccircumflex"}, + {0x010a, "Cdotaccent"}, + {0xf7b8, "Cedillasmall"}, + {0x03a7, "Chi"}, + {0xf6f6, "Circumflexsmall"}, + {0xf763, "Csmall"}, + {0x0044, "D"}, + {0x010e, "Dcaron"}, + {0x0110, "Dcroat"}, + {0x2206, "Delta"}, + {0xf6cb, "Dieresis"}, + {0xf6cc, "DieresisAcute"}, + {0xf6cd, "DieresisGrave"}, + {0xf7a8, "Dieresissmall"}, + {0xf6f7, "Dotaccentsmall"}, + {0xf764, "Dsmall"}, + {0x0045, "E"}, + {0x00c9, "Eacute"}, + {0xf7e9, "Eacutesmall"}, + {0x0114, "Ebreve"}, + {0x011a, "Ecaron"}, + {0x00ca, "Ecircumflex"}, + {0xf7ea, "Ecircumflexsmall"}, + {0x00cb, "Edieresis"}, + {0xf7eb, "Edieresissmall"}, + {0x0116, "Edotaccent"}, + {0x00c8, "Egrave"}, + {0xf7e8, "Egravesmall"}, + {0x0112, "Emacron"}, + {0x014a, "Eng"}, + {0x0118, "Eogonek"}, + {0x0395, "Epsilon"}, + {0x0388, "Epsilontonos"}, + {0xf765, "Esmall"}, + {0x0397, "Eta"}, + {0x0389, "Etatonos"}, + {0x00d0, "Eth"}, + {0xf7f0, "Ethsmall"}, + {0x20ac, "Euro"}, + {0x0046, "F"}, + {0xf766, "Fsmall"}, + {0x0047, "G"}, + {0x0393, "Gamma"}, + {0x011e, "Gbreve"}, + {0x01e6, "Gcaron"}, + {0x011c, "Gcircumflex"}, + {0x0122, "Gcommaaccent"}, + {0x0120, "Gdotaccent"}, + {0xf6ce, "Grave"}, + {0xf760, "Gravesmall"}, + {0xf767, "Gsmall"}, + {0x0048, "H"}, + {0x25cf, "H18533"}, + {0x25aa, "H18543"}, + {0x25ab, "H18551"}, + {0x25a1, "H22073"}, + {0x0126, "Hbar"}, + {0x0124, "Hcircumflex"}, + {0xf768, "Hsmall"}, + {0xf6cf, "Hungarumlaut"}, + {0xf6f8, "Hungarumlautsmall"}, + {0x0049, "I"}, + {0x0132, "IJ"}, + {0x00cd, "Iacute"}, + {0xf7ed, "Iacutesmall"}, + {0x012c, "Ibreve"}, + {0x00ce, "Icircumflex"}, + {0xf7ee, "Icircumflexsmall"}, + {0x00cf, "Idieresis"}, + {0xf7ef, "Idieresissmall"}, + {0x0130, "Idotaccent"}, + {0x2111, "Ifraktur"}, + {0x00cc, "Igrave"}, + {0xf7ec, "Igravesmall"}, + {0x012a, "Imacron"}, + {0x012e, "Iogonek"}, + {0x0399, "Iota"}, + {0x03aa, "Iotadieresis"}, + {0x038a, "Iotatonos"}, + {0xf769, "Ismall"}, + {0x0128, "Itilde"}, + {0x004a, "J"}, + {0x0134, "Jcircumflex"}, + {0xf76a, "Jsmall"}, + {0x004b, "K"}, + {0x039a, "Kappa"}, + {0x0136, "Kcommaaccent"}, + {0xf76b, "Ksmall"}, + {0x004c, "L"}, + {0xf6bf, "LL"}, + {0x0139, "Lacute"}, + {0x039b, "Lambda"}, + {0x013d, "Lcaron"}, + {0x013b, "Lcommaaccent"}, + {0x013f, "Ldot"}, + {0x0141, "Lslash"}, + {0xf6f9, "Lslashsmall"}, + {0xf76c, "Lsmall"}, + {0x004d, "M"}, + {0xf6d0, "Macron"}, + {0xf7af, "Macronsmall"}, + {0xf76d, "Msmall"}, + {0x039c, "Mu"}, + {0x004e, "N"}, + {0x0143, "Nacute"}, + {0x0147, "Ncaron"}, + {0x0145, "Ncommaaccent"}, + {0xf76e, "Nsmall"}, + {0x00d1, "Ntilde"}, + {0xf7f1, "Ntildesmall"}, + {0x039d, "Nu"}, + {0x004f, "O"}, + {0x0152, "OE"}, + {0xf6fa, "OEsmall"}, + {0x00d3, "Oacute"}, + {0xf7f3, "Oacutesmall"}, + {0x014e, "Obreve"}, + {0x00d4, "Ocircumflex"}, + {0xf7f4, "Ocircumflexsmall"}, + {0x00d6, "Odieresis"}, + {0xf7f6, "Odieresissmall"}, + {0xf6fb, "Ogoneksmall"}, + {0x00d2, "Ograve"}, + {0xf7f2, "Ogravesmall"}, + {0x01a0, "Ohorn"}, + {0x0150, "Ohungarumlaut"}, + {0x014c, "Omacron"}, + {0x2126, "Omega"}, + {0x038f, "Omegatonos"}, + {0x039f, "Omicron"}, + {0x038c, "Omicrontonos"}, + {0x00d8, "Oslash"}, + {0x01fe, "Oslashacute"}, + {0xf7f8, "Oslashsmall"}, + {0xf76f, "Osmall"}, + {0x00d5, "Otilde"}, + {0xf7f5, "Otildesmall"}, + {0x0050, "P"}, + {0x03a6, "Phi"}, + {0x03a0, "Pi"}, + {0x03a8, "Psi"}, + {0xf770, "Psmall"}, + {0x0051, "Q"}, + {0xf771, "Qsmall"}, + {0x0052, "R"}, + {0x0154, "Racute"}, + {0x0158, "Rcaron"}, + {0x0156, "Rcommaaccent"}, + {0x211c, "Rfraktur"}, + {0x03a1, "Rho"}, + {0xf6fc, "Ringsmall"}, + {0xf772, "Rsmall"}, + {0x0053, "S"}, + {0x250c, "SF010000"}, + {0x2514, "SF020000"}, + {0x2510, "SF030000"}, + {0x2518, "SF040000"}, + {0x253c, "SF050000"}, + {0x252c, "SF060000"}, + {0x2534, "SF070000"}, + {0x251c, "SF080000"}, + {0x2524, "SF090000"}, + {0x2500, "SF100000"}, + {0x2502, "SF110000"}, + {0x2561, "SF190000"}, + {0x2562, "SF200000"}, + {0x2556, "SF210000"}, + {0x2555, "SF220000"}, + {0x2563, "SF230000"}, + {0x2551, "SF240000"}, + {0x2557, "SF250000"}, + {0x255d, "SF260000"}, + {0x255c, "SF270000"}, + {0x255b, "SF280000"}, + {0x255e, "SF360000"}, + {0x255f, "SF370000"}, + {0x255a, "SF380000"}, + {0x2554, "SF390000"}, + {0x2569, "SF400000"}, + {0x2566, "SF410000"}, + {0x2560, "SF420000"}, + {0x2550, "SF430000"}, + {0x256c, "SF440000"}, + {0x2567, "SF450000"}, + {0x2568, "SF460000"}, + {0x2564, "SF470000"}, + {0x2565, "SF480000"}, + {0x2559, "SF490000"}, + {0x2558, "SF500000"}, + {0x2552, "SF510000"}, + {0x2553, "SF520000"}, + {0x256b, "SF530000"}, + {0x256a, "SF540000"}, + {0x015a, "Sacute"}, + {0x0160, "Scaron"}, + {0xf6fd, "Scaronsmall"}, + {0x015e, "Scedilla"}, + {0x015c, "Scircumflex"}, + {0x0218, "Scommaaccent"}, + {0x03a3, "Sigma"}, + {0xf773, "Ssmall"}, + {0x0054, "T"}, + {0x03a4, "Tau"}, + {0x0166, "Tbar"}, + {0x0164, "Tcaron"}, + {0x0162, "Tcommaaccent"}, + {0x0398, "Theta"}, + {0x00de, "Thorn"}, + {0xf7fe, "Thornsmall"}, + {0xf6fe, "Tildesmall"}, + {0xf774, "Tsmall"}, + {0x0055, "U"}, + {0x00da, "Uacute"}, + {0xf7fa, "Uacutesmall"}, + {0x016c, "Ubreve"}, + {0x00db, "Ucircumflex"}, + {0xf7fb, "Ucircumflexsmall"}, + {0x00dc, "Udieresis"}, + {0xf7fc, "Udieresissmall"}, + {0x00d9, "Ugrave"}, + {0xf7f9, "Ugravesmall"}, + {0x01af, "Uhorn"}, + {0x0170, "Uhungarumlaut"}, + {0x016a, "Umacron"}, + {0x0172, "Uogonek"}, + {0x03a5, "Upsilon"}, + {0x03d2, "Upsilon1"}, + {0x03ab, "Upsilondieresis"}, + {0x038e, "Upsilontonos"}, + {0x016e, "Uring"}, + {0xf775, "Usmall"}, + {0x0168, "Utilde"}, + {0x0056, "V"}, + {0xf776, "Vsmall"}, + {0x0057, "W"}, + {0x1e82, "Wacute"}, + {0x0174, "Wcircumflex"}, + {0x1e84, "Wdieresis"}, + {0x1e80, "Wgrave"}, + {0xf777, "Wsmall"}, + {0x0058, "X"}, + {0x039e, "Xi"}, + {0xf778, "Xsmall"}, + {0x0059, "Y"}, + {0x00dd, "Yacute"}, + {0xf7fd, "Yacutesmall"}, + {0x0176, "Ycircumflex"}, + {0x0178, "Ydieresis"}, + {0xf7ff, "Ydieresissmall"}, + {0x1ef2, "Ygrave"}, + {0xf779, "Ysmall"}, + {0x005a, "Z"}, + {0x0179, "Zacute"}, + {0x017d, "Zcaron"}, + {0xf6ff, "Zcaronsmall"}, + {0x017b, "Zdotaccent"}, + {0x0396, "Zeta"}, + {0xf77a, "Zsmall"}, + {0x0022, "\""}, + {0x005c, "\\"}, + {0x005d, "]"}, + {0x005e, "^"}, + {0x005f, "_"}, + {0x0060, "`"}, + {0x0061, "a"}, + {0x00e1, "aacute"}, + {0x0103, "abreve"}, + {0x00e2, "acircumflex"}, + {0x00b4, "acute"}, + {0x0301, "acutecomb"}, + {0x00e4, "adieresis"}, + {0x00e6, "ae"}, + {0x01fd, "aeacute"}, + {0x2015, "afii00208"}, + {0x0410, "afii10017"}, + {0x0411, "afii10018"}, + {0x0412, "afii10019"}, + {0x0413, "afii10020"}, + {0x0414, "afii10021"}, + {0x0415, "afii10022"}, + {0x0401, "afii10023"}, + {0x0416, "afii10024"}, + {0x0417, "afii10025"}, + {0x0418, "afii10026"}, + {0x0419, "afii10027"}, + {0x041a, "afii10028"}, + {0x041b, "afii10029"}, + {0x041c, "afii10030"}, + {0x041d, "afii10031"}, + {0x041e, "afii10032"}, + {0x041f, "afii10033"}, + {0x0420, "afii10034"}, + {0x0421, "afii10035"}, + {0x0422, "afii10036"}, + {0x0423, "afii10037"}, + {0x0424, "afii10038"}, + {0x0425, "afii10039"}, + {0x0426, "afii10040"}, + {0x0427, "afii10041"}, + {0x0428, "afii10042"}, + {0x0429, "afii10043"}, + {0x042a, "afii10044"}, + {0x042b, "afii10045"}, + {0x042c, "afii10046"}, + {0x042d, "afii10047"}, + {0x042e, "afii10048"}, + {0x042f, "afii10049"}, + {0x0490, "afii10050"}, + {0x0402, "afii10051"}, + {0x0403, "afii10052"}, + {0x0404, "afii10053"}, + {0x0405, "afii10054"}, + {0x0406, "afii10055"}, + {0x0407, "afii10056"}, + {0x0408, "afii10057"}, + {0x0409, "afii10058"}, + {0x040a, "afii10059"}, + {0x040b, "afii10060"}, + {0x040c, "afii10061"}, + {0x040e, "afii10062"}, + {0xf6c4, "afii10063"}, + {0xf6c5, "afii10064"}, + {0x0430, "afii10065"}, + {0x0431, "afii10066"}, + {0x0432, "afii10067"}, + {0x0433, "afii10068"}, + {0x0434, "afii10069"}, + {0x0435, "afii10070"}, + {0x0451, "afii10071"}, + {0x0436, "afii10072"}, + {0x0437, "afii10073"}, + {0x0438, "afii10074"}, + {0x0439, "afii10075"}, + {0x043a, "afii10076"}, + {0x043b, "afii10077"}, + {0x043c, "afii10078"}, + {0x043d, "afii10079"}, + {0x043e, "afii10080"}, + {0x043f, "afii10081"}, + {0x0440, "afii10082"}, + {0x0441, "afii10083"}, + {0x0442, "afii10084"}, + {0x0443, "afii10085"}, + {0x0444, "afii10086"}, + {0x0445, "afii10087"}, + {0x0446, "afii10088"}, + {0x0447, "afii10089"}, + {0x0448, "afii10090"}, + {0x0449, "afii10091"}, + {0x044a, "afii10092"}, + {0x044b, "afii10093"}, + {0x044c, "afii10094"}, + {0x044d, "afii10095"}, + {0x044e, "afii10096"}, + {0x044f, "afii10097"}, + {0x0491, "afii10098"}, + {0x0452, "afii10099"}, + {0x0453, "afii10100"}, + {0x0454, "afii10101"}, + {0x0455, "afii10102"}, + {0x0456, "afii10103"}, + {0x0457, "afii10104"}, + {0x0458, "afii10105"}, + {0x0459, "afii10106"}, + {0x045a, "afii10107"}, + {0x045b, "afii10108"}, + {0x045c, "afii10109"}, + {0x045e, "afii10110"}, + {0x040f, "afii10145"}, + {0x0462, "afii10146"}, + {0x0472, "afii10147"}, + {0x0474, "afii10148"}, + {0xf6c6, "afii10192"}, + {0x045f, "afii10193"}, + {0x0463, "afii10194"}, + {0x0473, "afii10195"}, + {0x0475, "afii10196"}, + {0xf6c7, "afii10831"}, + {0xf6c8, "afii10832"}, + {0x04d9, "afii10846"}, + {0x200e, "afii299"}, + {0x200f, "afii300"}, + {0x200d, "afii301"}, + {0x066a, "afii57381"}, + {0x060c, "afii57388"}, + {0x0660, "afii57392"}, + {0x0661, "afii57393"}, + {0x0662, "afii57394"}, + {0x0663, "afii57395"}, + {0x0664, "afii57396"}, + {0x0665, "afii57397"}, + {0x0666, "afii57398"}, + {0x0667, "afii57399"}, + {0x0668, "afii57400"}, + {0x0669, "afii57401"}, + {0x061b, "afii57403"}, + {0x061f, "afii57407"}, + {0x0621, "afii57409"}, + {0x0622, "afii57410"}, + {0x0623, "afii57411"}, + {0x0624, "afii57412"}, + {0x0625, "afii57413"}, + {0x0626, "afii57414"}, + {0x0627, "afii57415"}, + {0x0628, "afii57416"}, + {0x0629, "afii57417"}, + {0x062a, "afii57418"}, + {0x062b, "afii57419"}, + {0x062c, "afii57420"}, + {0x062d, "afii57421"}, + {0x062e, "afii57422"}, + {0x062f, "afii57423"}, + {0x0630, "afii57424"}, + {0x0631, "afii57425"}, + {0x0632, "afii57426"}, + {0x0633, "afii57427"}, + {0x0634, "afii57428"}, + {0x0635, "afii57429"}, + {0x0636, "afii57430"}, + {0x0637, "afii57431"}, + {0x0638, "afii57432"}, + {0x0639, "afii57433"}, + {0x063a, "afii57434"}, + {0x0640, "afii57440"}, + {0x0641, "afii57441"}, + {0x0642, "afii57442"}, + {0x0643, "afii57443"}, + {0x0644, "afii57444"}, + {0x0645, "afii57445"}, + {0x0646, "afii57446"}, + {0x0648, "afii57448"}, + {0x0649, "afii57449"}, + {0x064a, "afii57450"}, + {0x064b, "afii57451"}, + {0x064c, "afii57452"}, + {0x064d, "afii57453"}, + {0x064e, "afii57454"}, + {0x064f, "afii57455"}, + {0x0650, "afii57456"}, + {0x0651, "afii57457"}, + {0x0652, "afii57458"}, + {0x0647, "afii57470"}, + {0x06a4, "afii57505"}, + {0x067e, "afii57506"}, + {0x0686, "afii57507"}, + {0x0698, "afii57508"}, + {0x06af, "afii57509"}, + {0x0679, "afii57511"}, + {0x0688, "afii57512"}, + {0x0691, "afii57513"}, + {0x06ba, "afii57514"}, + {0x06d2, "afii57519"}, + {0x06d5, "afii57534"}, + {0x20aa, "afii57636"}, + {0x05be, "afii57645"}, + {0x05c3, "afii57658"}, + {0x05d0, "afii57664"}, + {0x05d1, "afii57665"}, + {0x05d2, "afii57666"}, + {0x05d3, "afii57667"}, + {0x05d4, "afii57668"}, + {0x05d5, "afii57669"}, + {0x05d6, "afii57670"}, + {0x05d7, "afii57671"}, + {0x05d8, "afii57672"}, + {0x05d9, "afii57673"}, + {0x05da, "afii57674"}, + {0x05db, "afii57675"}, + {0x05dc, "afii57676"}, + {0x05dd, "afii57677"}, + {0x05de, "afii57678"}, + {0x05df, "afii57679"}, + {0x05e0, "afii57680"}, + {0x05e1, "afii57681"}, + {0x05e2, "afii57682"}, + {0x05e3, "afii57683"}, + {0x05e4, "afii57684"}, + {0x05e5, "afii57685"}, + {0x05e6, "afii57686"}, + {0x05e7, "afii57687"}, + {0x05e8, "afii57688"}, + {0x05e9, "afii57689"}, + {0x05ea, "afii57690"}, + {0xfb2a, "afii57694"}, + {0xfb2b, "afii57695"}, + {0xfb4b, "afii57700"}, + {0xfb1f, "afii57705"}, + {0x05f0, "afii57716"}, + {0x05f1, "afii57717"}, + {0x05f2, "afii57718"}, + {0xfb35, "afii57723"}, + {0x05b4, "afii57793"}, + {0x05b5, "afii57794"}, + {0x05b6, "afii57795"}, + {0x05bb, "afii57796"}, + {0x05b8, "afii57797"}, + {0x05b7, "afii57798"}, + {0x05b0, "afii57799"}, + {0x05b2, "afii57800"}, + {0x05b1, "afii57801"}, + {0x05b3, "afii57802"}, + {0x05c2, "afii57803"}, + {0x05c1, "afii57804"}, + {0x05b9, "afii57806"}, + {0x05bc, "afii57807"}, + {0x05bd, "afii57839"}, + {0x05bf, "afii57841"}, + {0x05c0, "afii57842"}, + {0x02bc, "afii57929"}, + {0x2105, "afii61248"}, + {0x2113, "afii61289"}, + {0x2116, "afii61352"}, + {0x202c, "afii61573"}, + {0x202d, "afii61574"}, + {0x202e, "afii61575"}, + {0x200c, "afii61664"}, + {0x066d, "afii63167"}, + {0x02bd, "afii64937"}, + {0x00e0, "agrave"}, + {0x2135, "aleph"}, + {0x03b1, "alpha"}, + {0x03ac, "alphatonos"}, + {0x0101, "amacron"}, + {0x0026, "ampersand"}, + {0xf726, "ampersandsmall"}, + {0x2220, "angle"}, + {0x2329, "angleleft"}, + {0x232a, "angleright"}, + {0x0387, "anoteleia"}, + {0x0105, "aogonek"}, + {0x2248, "approxequal"}, + {0x00e5, "aring"}, + {0x01fb, "aringacute"}, + {0x2194, "arrowboth"}, + {0x21d4, "arrowdblboth"}, + {0x21d3, "arrowdbldown"}, + {0x21d0, "arrowdblleft"}, + {0x21d2, "arrowdblright"}, + {0x21d1, "arrowdblup"}, + {0x2193, "arrowdown"}, + {0xf8e7, "arrowhorizex"}, + {0x2190, "arrowleft"}, + {0x2192, "arrowright"}, + {0x2191, "arrowup"}, + {0x2195, "arrowupdn"}, + {0x21a8, "arrowupdnbse"}, + {0xf8e6, "arrowvertex"}, + {0x005e, "asciicircum"}, + {0x007e, "asciitilde"}, + {0x002a, "asterisk"}, + {0x2217, "asteriskmath"}, + {0xf6e9, "asuperior"}, + {0x0040, "at"}, + {0x00e3, "atilde"}, + {0x0062, "b"}, + {0x005c, "backslash"}, + {0x007c, "bar"}, + {0x03b2, "beta"}, + {0x2588, "block"}, + {0xf8f4, "braceex"}, + {0x007b, "braceleft"}, + {0xf8f3, "braceleftbt"}, + {0xf8f2, "braceleftmid"}, + {0xf8f1, "bracelefttp"}, + {0x007d, "braceright"}, + {0xf8fe, "bracerightbt"}, + {0xf8fd, "bracerightmid"}, + {0xf8fc, "bracerighttp"}, + {0x005b, "bracketleft"}, + {0xf8f0, "bracketleftbt"}, + {0xf8ef, "bracketleftex"}, + {0xf8ee, "bracketlefttp"}, + {0x005d, "bracketright"}, + {0xf8fb, "bracketrightbt"}, + {0xf8fa, "bracketrightex"}, + {0xf8f9, "bracketrighttp"}, + {0x02d8, "breve"}, + {0x00a6, "brokenbar"}, + {0xf6ea, "bsuperior"}, + {0x2022, "bullet"}, + {0x0063, "c"}, + {0x0107, "cacute"}, + {0x02c7, "caron"}, + {0x21b5, "carriagereturn"}, + {0x010d, "ccaron"}, + {0x00e7, "ccedilla"}, + {0x0109, "ccircumflex"}, + {0x010b, "cdotaccent"}, + {0x00b8, "cedilla"}, + {0x00a2, "cent"}, + {0xf6df, "centinferior"}, + {0xf7a2, "centoldstyle"}, + {0xf6e0, "centsuperior"}, + {0x03c7, "chi"}, + {0x25cb, "circle"}, + {0x2297, "circlemultiply"}, + {0x2295, "circleplus"}, + {0x02c6, "circumflex"}, + {0x2663, "club"}, + {0x003a, "colon"}, + {0x20a1, "colonmonetary"}, + {0x002c, "comma"}, + {0xf6c3, "commaaccent"}, + {0xf6e1, "commainferior"}, + {0xf6e2, "commasuperior"}, + {0x2245, "congruent"}, + {0x00a9, "copyright"}, + {0x00a9, "copyrightsans"}, + {0x00a9, "copyrightserif"}, + {0x00a4, "currency"}, + {0xf6d1, "cyrBreve"}, + {0xf6d2, "cyrFlex"}, + {0xf6d4, "cyrbreve"}, + {0xf6d5, "cyrflex"}, + {0x0064, "d"}, + {0x2020, "dagger"}, + {0x2021, "daggerdbl"}, + {0xf6d3, "dblGrave"}, + {0xf6d6, "dblgrave"}, + {0x010f, "dcaron"}, + {0x0111, "dcroat"}, + {0x00b0, "degree"}, + {0x03b4, "delta"}, + {0x2666, "diamond"}, + {0x00a8, "dieresis"}, + {0xf6d7, "dieresisacute"}, + {0xf6d8, "dieresisgrave"}, + {0x0385, "dieresistonos"}, + {0x00f7, "divide"}, + {0x2593, "dkshade"}, + {0x2584, "dnblock"}, + {0x0024, "dollar"}, + {0xf6e3, "dollarinferior"}, + {0xf724, "dollaroldstyle"}, + {0xf6e4, "dollarsuperior"}, + {0x20ab, "dong"}, + {0x02d9, "dotaccent"}, + {0x0323, "dotbelowcomb"}, + {0x0131, "dotlessi"}, + {0xf6be, "dotlessj"}, + {0x22c5, "dotmath"}, + {0xf6eb, "dsuperior"}, + {0x0065, "e"}, + {0x00e9, "eacute"}, + {0x0115, "ebreve"}, + {0x011b, "ecaron"}, + {0x00ea, "ecircumflex"}, + {0x00eb, "edieresis"}, + {0x0117, "edotaccent"}, + {0x00e8, "egrave"}, + {0x0038, "eight"}, + {0x2088, "eightinferior"}, + {0xf738, "eightoldstyle"}, + {0x2078, "eightsuperior"}, + {0x2208, "element"}, + {0x2026, "ellipsis"}, + {0x0113, "emacron"}, + {0x2014, "emdash"}, + {0x2205, "emptyset"}, + {0x2013, "endash"}, + {0x014b, "eng"}, + {0x0119, "eogonek"}, + {0x03b5, "epsilon"}, + {0x03ad, "epsilontonos"}, + {0x003d, "equal"}, + {0x2261, "equivalence"}, + {0x212e, "estimated"}, + {0xf6ec, "esuperior"}, + {0x03b7, "eta"}, + {0x03ae, "etatonos"}, + {0x00f0, "eth"}, + {0x0021, "exclam"}, + {0x203c, "exclamdbl"}, + {0x00a1, "exclamdown"}, + {0xf7a1, "exclamdownsmall"}, + {0x0021, "exclamleft"}, + {0xf721, "exclamsmall"}, + {0x2203, "existential"}, + {0x0066, "f"}, + {0x2640, "female"}, + {0xfb00, "ff"}, + {0xfb03, "ffi"}, + {0xfb04, "ffl"}, + {0xfb01, "fi"}, + {0x2012, "figuredash"}, + {0x25a0, "filledbox"}, + {0x25ac, "filledrect"}, + {0x0035, "five"}, + {0x215d, "fiveeighths"}, + {0x2085, "fiveinferior"}, + {0xf735, "fiveoldstyle"}, + {0x2075, "fivesuperior"}, + {0xfb02, "fl"}, + {0x0192, "florin"}, + {0x0034, "four"}, + {0x2084, "fourinferior"}, + {0xf734, "fouroldstyle"}, + {0x2074, "foursuperior"}, + {0x2044, "fraction"}, + {0x20a3, "franc"}, + {0x0067, "g"}, + {0x03b3, "gamma"}, + {0x011f, "gbreve"}, + {0x01e7, "gcaron"}, + {0x011d, "gcircumflex"}, + {0x0123, "gcommaaccent"}, + {0x0121, "gdotaccent"}, + {0x00df, "germandbls"}, + {0x2207, "gradient"}, + {0x0060, "grave"}, + {0x0300, "gravecomb"}, + {0x003e, "greater"}, + {0x2265, "greaterequal"}, + {0x00ab, "guillemotleft"}, + {0x00bb, "guillemotright"}, + {0x2039, "guilsinglleft"}, + {0x203a, "guilsinglright"}, + {0x0068, "h"}, + {0x0127, "hbar"}, + {0x0125, "hcircumflex"}, + {0x2665, "heart"}, + {0x0309, "hookabovecomb"}, + {0x2302, "house"}, + {0x02dd, "hungarumlaut"}, + {0x002d, "hyphen"}, + {0xf6e5, "hypheninferior"}, + {0xf6e6, "hyphensuperior"}, + {0x0069, "i"}, + {0x00ed, "iacute"}, + {0x012d, "ibreve"}, + {0x00ee, "icircumflex"}, + {0x00ef, "idieresis"}, + {0x00ec, "igrave"}, + {0x0133, "ij"}, + {0x012b, "imacron"}, + {0x221e, "infinity"}, + {0x222b, "integral"}, + {0x2321, "integralbt"}, + {0xf8f5, "integralex"}, + {0x2320, "integraltp"}, + {0x2229, "intersection"}, + {0x25d8, "invbullet"}, + {0x25d9, "invcircle"}, + {0x263b, "invsmileface"}, + {0x012f, "iogonek"}, + {0x03b9, "iota"}, + {0x03ca, "iotadieresis"}, + {0x0390, "iotadieresistonos"}, + {0x03af, "iotatonos"}, + {0xf6ed, "isuperior"}, + {0x0129, "itilde"}, + {0x006a, "j"}, + {0x0135, "jcircumflex"}, + {0x006b, "k"}, + {0x03ba, "kappa"}, + {0x0137, "kcommaaccent"}, + {0x0138, "kgreenlandic"}, + {0x006c, "l"}, + {0x013a, "lacute"}, + {0x03bb, "lambda"}, + {0x013e, "lcaron"}, + {0x013c, "lcommaaccent"}, + {0x0140, "ldot"}, + {0x003c, "less"}, + {0x2264, "lessequal"}, + {0x258c, "lfblock"}, + {0x20a4, "lira"}, + {0xf6c0, "ll"}, + {0x2227, "logicaland"}, + {0x00ac, "logicalnot"}, + {0x2228, "logicalor"}, + {0x017f, "longs"}, + {0x25ca, "lozenge"}, + {0x0142, "lslash"}, + {0xf6ee, "lsuperior"}, + {0x2591, "ltshade"}, + {0x006d, "m"}, + {0x00af, "macron"}, + {0x2642, "male"}, + {0x2212, "minus"}, + {0x2032, "minute"}, + {0xf6ef, "msuperior"}, + {0x00b5, "mu"}, + {0x00d7, "multiply"}, + {0x266a, "musicalnote"}, + {0x266b, "musicalnotedbl"}, + {0x006e, "n"}, + {0x0144, "nacute"}, + {0x0149, "napostrophe"}, + {0x00a0, "nbspace"}, + {0x0148, "ncaron"}, + {0x0146, "ncommaaccent"}, + {0x0039, "nine"}, + {0x2089, "nineinferior"}, + {0xf739, "nineoldstyle"}, + {0x2079, "ninesuperior"}, + {0x00a0, "nonbreakingspace"}, + {0x2209, "notelement"}, + {0x2260, "notequal"}, + {0x2284, "notsubset"}, + {0x207f, "nsuperior"}, + {0x00f1, "ntilde"}, + {0x03bd, "nu"}, + {0x0023, "numbersign"}, + {0x006f, "o"}, + {0x00f3, "oacute"}, + {0x014f, "obreve"}, + {0x00f4, "ocircumflex"}, + {0x00f6, "odieresis"}, + {0x0153, "oe"}, + {0x02db, "ogonek"}, + {0x00f2, "ograve"}, + {0x01a1, "ohorn"}, + {0x0151, "ohungarumlaut"}, + {0x014d, "omacron"}, + {0x03c9, "omega"}, + {0x03d6, "omega1"}, + {0x03ce, "omegatonos"}, + {0x03bf, "omicron"}, + {0x03cc, "omicrontonos"}, + {0x0031, "one"}, + {0x2024, "onedotenleader"}, + {0x215b, "oneeighth"}, + {0xf6dc, "onefitted"}, + {0x00bd, "onehalf"}, + {0x2081, "oneinferior"}, + {0xf731, "oneoldstyle"}, + {0x00bc, "onequarter"}, + {0x00b9, "onesuperior"}, + {0x2153, "onethird"}, + {0x25e6, "openbullet"}, + {0x00aa, "ordfeminine"}, + {0x00ba, "ordmasculine"}, + {0x221f, "orthogonal"}, + {0x00f8, "oslash"}, + {0x01ff, "oslashacute"}, + {0xf6f0, "osuperior"}, + {0x00f5, "otilde"}, + {0x0070, "p"}, + {0x00b6, "paragraph"}, + {0x0028, "parenleft"}, + {0xf8ed, "parenleftbt"}, + {0xf8ec, "parenleftex"}, + {0x208d, "parenleftinferior"}, + {0x207d, "parenleftsuperior"}, + {0xf8eb, "parenlefttp"}, + {0x0029, "parenright"}, + {0xf8f8, "parenrightbt"}, + {0xf8f7, "parenrightex"}, + {0x208e, "parenrightinferior"}, + {0x207e, "parenrightsuperior"}, + {0xf8f6, "parenrighttp"}, + {0x2202, "partialdiff"}, + {0x0025, "percent"}, + {0x002e, "period"}, + {0x00b7, "periodcentered"}, + {0xf6e7, "periodinferior"}, + {0xf6e8, "periodsuperior"}, + {0x22a5, "perpendicular"}, + {0x2030, "perthousand"}, + {0x20a7, "peseta"}, + {0x03c6, "phi"}, + {0x03d5, "phi1"}, + {0x03c0, "pi"}, + {0x002b, "plus"}, + {0x00b1, "plusminus"}, + {0x211e, "prescription"}, + {0x220f, "product"}, + {0x2282, "propersubset"}, + {0x2283, "propersuperset"}, + {0x221d, "proportional"}, + {0x03c8, "psi"}, + {0x0071, "q"}, + {0x003f, "question"}, + {0x00bf, "questiondown"}, + {0xf7bf, "questiondownsmall"}, + {0xf73f, "questionsmall"}, + {0x0022, "quotedbl"}, + {0x201e, "quotedblbase"}, + {0x201c, "quotedblleft"}, + {0x201d, "quotedblright"}, + {0x2018, "quoteleft"}, + {0x201b, "quotereversed"}, + {0x2019, "quoteright"}, + {0x201a, "quotesinglbase"}, + {0x0027, "quotesingle"}, + {0x0072, "r"}, + {0x0155, "racute"}, + {0x221a, "radical"}, + {0xf8e5, "radicalex"}, + {0x0159, "rcaron"}, + {0x0157, "rcommaaccent"}, + {0x2286, "reflexsubset"}, + {0x2287, "reflexsuperset"}, + {0x00ae, "registered"}, + {0x00ae, "registersans"}, + {0x00ae, "registerserif"}, + {0x2310, "revlogicalnot"}, + {0x03c1, "rho"}, + {0x02da, "ring"}, + {0xf6f1, "rsuperior"}, + {0x2590, "rtblock"}, + {0xf6dd, "rupiah"}, + {0x0073, "s"}, + {0x015b, "sacute"}, + {0x0161, "scaron"}, + {0x015f, "scedilla"}, + {0x015d, "scircumflex"}, + {0x0219, "scommaaccent"}, + {0x2033, "second"}, + {0x00a7, "section"}, + {0x003b, "semicolon"}, + {0x0037, "seven"}, + {0x215e, "seveneighths"}, + {0x2087, "seveninferior"}, + {0xf737, "sevenoldstyle"}, + {0x2077, "sevensuperior"}, + {0x2592, "shade"}, + {0x03c3, "sigma"}, + {0x03c2, "sigma1"}, + {0x223c, "similar"}, + {0x0036, "six"}, + {0x2086, "sixinferior"}, + {0xf736, "sixoldstyle"}, + {0x2076, "sixsuperior"}, + {0x002f, "slash"}, + {0x263a, "smileface"}, + {0x0020, "space"}, + {0x2660, "spade"}, + {0xf6f2, "ssuperior"}, + {0x00a3, "sterling"}, + {0x220b, "suchthat"}, + {0x2211, "summation"}, + {0x263c, "sun"}, + {0x0074, "t"}, + {0x03c4, "tau"}, + {0x0167, "tbar"}, + {0x0165, "tcaron"}, + {0x0163, "tcommaaccent"}, + {0x2234, "therefore"}, + {0x03b8, "theta"}, + {0x03d1, "theta1"}, + {0x00fe, "thorn"}, + {0x0033, "three"}, + {0x215c, "threeeighths"}, + {0x2083, "threeinferior"}, + {0xf733, "threeoldstyle"}, + {0x00be, "threequarters"}, + {0xf6de, "threequartersemdash"}, + {0x00b3, "threesuperior"}, + {0x02dc, "tilde"}, + {0x0303, "tildecomb"}, + {0x0384, "tonos"}, + {0x2122, "trademark"}, + {0x2122, "trademarksans"}, + {0x2122, "trademarkserif"}, + {0x25bc, "triagdn"}, + {0x25c4, "triaglf"}, + {0x25ba, "triagrt"}, + {0x25b2, "triagup"}, + {0xf6f3, "tsuperior"}, + {0x0032, "two"}, + {0x2025, "twodotenleader"}, + {0x2082, "twoinferior"}, + {0xf732, "twooldstyle"}, + {0x00b2, "twosuperior"}, + {0x2154, "twothirds"}, + {0x0075, "u"}, + {0x00fa, "uacute"}, + {0x016d, "ubreve"}, + {0x00fb, "ucircumflex"}, + {0x00fc, "udieresis"}, + {0x00f9, "ugrave"}, + {0x01b0, "uhorn"}, + {0x0171, "uhungarumlaut"}, + {0x016b, "umacron"}, + {0x005f, "underscore"}, + {0x2017, "underscoredbl"}, + {0x222a, "union"}, + {0x2200, "universal"}, + {0x0173, "uogonek"}, + {0x2580, "upblock"}, + {0x03c5, "upsilon"}, + {0x03cb, "upsilondieresis"}, + {0x03b0, "upsilondieresistonos"}, + {0x03cd, "upsilontonos"}, + {0x016f, "uring"}, + {0x0169, "utilde"}, + {0x0076, "v"}, + {0x0077, "w"}, + {0x1e83, "wacute"}, + {0x0175, "wcircumflex"}, + {0x1e85, "wdieresis"}, + {0x2118, "weierstrass"}, + {0x1e81, "wgrave"}, + {0x0078, "x"}, + {0x03be, "xi"}, + {0x0079, "y"}, + {0x00fd, "yacute"}, + {0x0177, "ycircumflex"}, + {0x00ff, "ydieresis"}, + {0x00a5, "yen"}, + {0x1ef3, "ygrave"}, + {0x007a, "z"}, + {0x017a, "zacute"}, + {0x017e, "zcaron"}, + {0x017c, "zdotaccent"}, + {0x0030, "zero"}, + {0x2080, "zeroinferior"}, + {0xf730, "zerooldstyle"}, + {0x2070, "zerosuperior"}, + {0x03b6, "zeta"}, + {0x007b, "{"}, + {0x007c, "|"}, + {0x007d, "}"}, + {0x007e, "~"}, + { 0, NULL } +}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Object.cc swftools-0.9.1/lib/pdf/xpdf/Object.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Object.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Object.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,231 @@ +//======================================================================== +// +// Object.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Error.h" +#include "Stream.h" +#include "XRef.h" + +//------------------------------------------------------------------------ +// Object +//------------------------------------------------------------------------ + +char *objTypeNames[numObjTypes] = { + "boolean", + "integer", + "real", + "string", + "name", + "null", + "array", + "dictionary", + "stream", + "ref", + "cmd", + "error", + "eof", + "none" +}; + +#ifdef DEBUG_MEM +int Object::numAlloc[numObjTypes] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +#endif + +Object *Object::initArray(XRef *xref) { + initObj(objArray); + array = new Array(xref); + return this; +} + +Object *Object::initDict(XRef *xref) { + initObj(objDict); + dict = new Dict(xref); + return this; +} + +Object *Object::initDict(Dict *dictA) { + initObj(objDict); + dict = dictA; + dict->incRef(); + return this; +} + +Object *Object::initStream(Stream *streamA) { + initObj(objStream); + stream = streamA; + return this; +} + +Object *Object::copy(Object *obj) { + *obj = *this; + switch (type) { + case objString: + obj->string = string->copy(); + break; + case objName: + obj->name = copyString(name); + break; + case objArray: + array->incRef(); + break; + case objDict: + dict->incRef(); + break; + case objStream: + stream->incRef(); + break; + case objCmd: + obj->cmd = copyString(cmd); + break; + default: + break; + } +#ifdef DEBUG_MEM + ++numAlloc[type]; +#endif + return obj; +} + +Object *Object::fetch(XRef *xref, Object *obj) { + return (type == objRef && xref) ? + xref->fetch(ref.num, ref.gen, obj) : copy(obj); +} + +void Object::free() { + switch (type) { + case objString: + delete string; + break; + case objName: + gfree(name); + break; + case objArray: + if (!array->decRef()) { + delete array; + } + break; + case objDict: + if (!dict->decRef()) { + delete dict; + } + break; + case objStream: + if (!stream->decRef()) { + delete stream; + } + break; + case objCmd: + gfree(cmd); + break; + default: + break; + } +#ifdef DEBUG_MEM + --numAlloc[type]; +#endif + type = objNone; +} + +char *Object::getTypeName() { + return objTypeNames[type]; +} + +void Object::print(FILE *f) { + Object obj; + int i; + + switch (type) { + case objBool: + fprintf(f, "%s", booln ? "true" : "false"); + break; + case objInt: + fprintf(f, "%d", intg); + break; + case objReal: + fprintf(f, "%g", real); + break; + case objString: + fprintf(f, "("); + fwrite(string->getCString(), 1, string->getLength(), f); + fprintf(f, ")"); + break; + case objName: + fprintf(f, "/%s", name); + break; + case objNull: + fprintf(f, "null"); + break; + case objArray: + fprintf(f, "["); + for (i = 0; i < arrayGetLength(); ++i) { + if (i > 0) + fprintf(f, " "); + arrayGetNF(i, &obj); + obj.print(f); + obj.free(); + } + fprintf(f, "]"); + break; + case objDict: + fprintf(f, "<<"); + for (i = 0; i < dictGetLength(); ++i) { + fprintf(f, " /%s ", dictGetKey(i)); + dictGetValNF(i, &obj); + obj.print(f); + obj.free(); + } + fprintf(f, " >>"); + break; + case objStream: + fprintf(f, ""); + break; + case objRef: + fprintf(f, "%d %d R", ref.num, ref.gen); + break; + case objCmd: + fprintf(f, "%s", cmd); + break; + case objError: + fprintf(f, ""); + break; + case objEOF: + fprintf(f, ""); + break; + case objNone: + fprintf(f, ""); + break; + } +} + +void Object::memCheck(FILE *f) { +#ifdef DEBUG_MEM + int i; + int t; + + t = 0; + for (i = 0; i < numObjTypes; ++i) + t += numAlloc[i]; + if (t > 0) { + fprintf(f, "Allocated objects:\n"); + for (i = 0; i < numObjTypes; ++i) { + if (numAlloc[i] > 0) + fprintf(f, " %-20s: %6d\n", objTypeNames[i], numAlloc[i]); + } + } +#endif +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Object.h swftools-0.9.1/lib/pdf/xpdf/Object.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Object.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Object.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,303 @@ +//======================================================================== +// +// Object.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef OBJECT_H +#define OBJECT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include +#include "gtypes.h" +#include "gmem.h" +#include "GString.h" + +class XRef; +class Array; +class Dict; +class Stream; + +//------------------------------------------------------------------------ +// Ref +//------------------------------------------------------------------------ + +struct Ref { + int num; // object number + int gen; // generation number +}; + +//------------------------------------------------------------------------ +// object types +//------------------------------------------------------------------------ + +enum ObjType { + // simple objects + objBool, // boolean + objInt, // integer + objReal, // real + objString, // string + objName, // name + objNull, // null + + // complex objects + objArray, // array + objDict, // dictionary + objStream, // stream + objRef, // indirect reference + + // special objects + objCmd, // command name + objError, // error return from Lexer + objEOF, // end of file return from Lexer + objNone // uninitialized object +}; + +#define numObjTypes 14 // total number of object types + +//------------------------------------------------------------------------ +// Object +//------------------------------------------------------------------------ + +#ifdef DEBUG_MEM +#define initObj(t) ++numAlloc[type = t] +#else +#define initObj(t) type = t +#endif + +class Object { +public: + + // Default constructor. + Object(): + type(objNone) {} + + // Initialize an object. + Object *initBool(GBool boolnA) + { initObj(objBool); booln = boolnA; return this; } + Object *initInt(int intgA) + { initObj(objInt); intg = intgA; return this; } + Object *initReal(double realA) + { initObj(objReal); real = realA; return this; } + Object *initString(GString *stringA) + { initObj(objString); string = stringA; return this; } + Object *initName(char *nameA) + { initObj(objName); name = copyString(nameA); return this; } + Object *initNull() + { initObj(objNull); return this; } + Object *initArray(XRef *xref); + Object *initDict(XRef *xref); + Object *initDict(Dict *dictA); + Object *initStream(Stream *streamA); + Object *initRef(int numA, int genA) + { initObj(objRef); ref.num = numA; ref.gen = genA; return this; } + Object *initCmd(char *cmdA) + { initObj(objCmd); cmd = copyString(cmdA); return this; } + Object *initError() + { initObj(objError); return this; } + Object *initEOF() + { initObj(objEOF); return this; } + + // Copy an object. + Object *copy(Object *obj); + + // If object is a Ref, fetch and return the referenced object. + // Otherwise, return a copy of the object. + Object *fetch(XRef *xref, Object *obj); + + // Free object contents. + void free(); + + // Type checking. + ObjType getType() { return type; } + GBool isBool() { return type == objBool; } + GBool isInt() { return type == objInt; } + GBool isReal() { return type == objReal; } + GBool isNum() { return type == objInt || type == objReal; } + GBool isString() { return type == objString; } + GBool isName() { return type == objName; } + GBool isNull() { return type == objNull; } + GBool isArray() { return type == objArray; } + GBool isDict() { return type == objDict; } + GBool isStream() { return type == objStream; } + GBool isRef() { return type == objRef; } + GBool isCmd() { return type == objCmd; } + GBool isError() { return type == objError; } + GBool isEOF() { return type == objEOF; } + GBool isNone() { return type == objNone; } + + // Special type checking. + GBool isName(char *nameA) + { return type == objName && !strcmp(name, nameA); } + GBool isDict(char *dictType); + GBool isStream(char *dictType); + GBool isCmd(char *cmdA) + { return type == objCmd && !strcmp(cmd, cmdA); } + + // Accessors. NB: these assume object is of correct type. + GBool getBool() { return booln; } + int getInt() { return intg; } + double getReal() { return real; } + double getNum() { return type == objInt ? (double)intg : real; } + GString *getString() { return string; } + char *getName() { return name; } + Array *getArray() { return array; } + Dict *getDict() { return dict; } + Stream *getStream() { return stream; } + Ref getRef() { return ref; } + int getRefNum() { return ref.num; } + int getRefGen() { return ref.gen; } + char *getCmd() { return cmd; } + + // Array accessors. + int arrayGetLength(); + void arrayAdd(Object *elem); + Object *arrayGet(int i, Object *obj); + Object *arrayGetNF(int i, Object *obj); + + // Dict accessors. + int dictGetLength(); + void dictAdd(char *key, Object *val); + GBool dictIs(char *dictType); + Object *dictLookup(char *key, Object *obj); + Object *dictLookupNF(char *key, Object *obj); + char *dictGetKey(int i); + Object *dictGetVal(int i, Object *obj); + Object *dictGetValNF(int i, Object *obj); + + // Stream accessors. + GBool streamIs(char *dictType); + void streamReset(); + void streamClose(); + int streamGetChar(); + int streamLookChar(); + char *streamGetLine(char *buf, int size); + Guint streamGetPos(); + void streamSetPos(Guint pos, int dir = 0); + Dict *streamGetDict(); + + // Output. + char *getTypeName(); + void print(FILE *f = stdout); + + // Memory testing. + static void memCheck(FILE *f); + +private: + + ObjType type; // object type + union { // value for each type: + GBool booln; // boolean + int intg; // integer + double real; // real + GString *string; // string + char *name; // name + Array *array; // array + Dict *dict; // dictionary + Stream *stream; // stream + Ref ref; // indirect reference + char *cmd; // command + }; + +#ifdef DEBUG_MEM + static int // number of each type of object + numAlloc[numObjTypes]; // currently allocated +#endif +}; + +//------------------------------------------------------------------------ +// Array accessors. +//------------------------------------------------------------------------ + +#include "Array.h" + +inline int Object::arrayGetLength() + { return array->getLength(); } + +inline void Object::arrayAdd(Object *elem) + { array->add(elem); } + +inline Object *Object::arrayGet(int i, Object *obj) + { return array->get(i, obj); } + +inline Object *Object::arrayGetNF(int i, Object *obj) + { return array->getNF(i, obj); } + +//------------------------------------------------------------------------ +// Dict accessors. +//------------------------------------------------------------------------ + +#include "Dict.h" + +inline int Object::dictGetLength() + { return dict->getLength(); } + +inline void Object::dictAdd(char *key, Object *val) + { dict->add(key, val); } + +inline GBool Object::dictIs(char *dictType) + { return dict->is(dictType); } + +inline GBool Object::isDict(char *dictType) + { return type == objDict && dictIs(dictType); } + +inline Object *Object::dictLookup(char *key, Object *obj) + { return dict->lookup(key, obj); } + +inline Object *Object::dictLookupNF(char *key, Object *obj) + { return dict->lookupNF(key, obj); } + +inline char *Object::dictGetKey(int i) + { return dict->getKey(i); } + +inline Object *Object::dictGetVal(int i, Object *obj) + { return dict->getVal(i, obj); } + +inline Object *Object::dictGetValNF(int i, Object *obj) + { return dict->getValNF(i, obj); } + +//------------------------------------------------------------------------ +// Stream accessors. +//------------------------------------------------------------------------ + +#include "Stream.h" + +inline GBool Object::streamIs(char *dictType) + { return stream->getDict()->is(dictType); } + +inline GBool Object::isStream(char *dictType) + { return type == objStream && streamIs(dictType); } + +inline void Object::streamReset() + { stream->reset(); } + +inline void Object::streamClose() + { stream->close(); } + +inline int Object::streamGetChar() + { return stream->getChar(); } + +inline int Object::streamLookChar() + { return stream->lookChar(); } + +inline char *Object::streamGetLine(char *buf, int size) + { return stream->getLine(buf, size); } + +inline Guint Object::streamGetPos() + { return stream->getPos(); } + +inline void Object::streamSetPos(Guint pos, int dir) + { stream->setPos(pos, dir); } + +inline Dict *Object::streamGetDict() + { return stream->getDict(); } + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Outline.cc swftools-0.9.1/lib/pdf/xpdf/Outline.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Outline.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Outline.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,151 @@ +//======================================================================== +// +// Outline.cc +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "gmem.h" +#include "GString.h" +#include "GList.h" +#include "Link.h" +#include "PDFDocEncoding.h" +#include "Outline.h" + +//------------------------------------------------------------------------ + +Outline::Outline(Object *outlineObj, XRef *xref) { + Object first, last; + + items = NULL; + if (!outlineObj->isDict()) { + return; + } + items = OutlineItem::readItemList(outlineObj->dictLookupNF("First", &first), + outlineObj->dictLookupNF("Last", &last), + xref); + first.free(); + last.free(); +} + +Outline::~Outline() { + if (items) { + deleteGList(items, OutlineItem); + } +} + +//------------------------------------------------------------------------ + +OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) { + Object obj1; + GString *s; + int i; + + xref = xrefA; + title = NULL; + action = NULL; + kids = NULL; + + if (dict->lookup("Title", &obj1)->isString()) { + s = obj1.getString(); + if ((s->getChar(0) & 0xff) == 0xfe && + (s->getChar(1) & 0xff) == 0xff) { + titleLen = (s->getLength() - 2) / 2; + title = (Unicode *)gmallocn(titleLen, sizeof(Unicode)); + for (i = 0; i < titleLen; ++i) { + title[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) | + (s->getChar(3 + 2*i) & 0xff); + } + } else { + titleLen = s->getLength(); + title = (Unicode *)gmallocn(titleLen, sizeof(Unicode)); + for (i = 0; i < titleLen; ++i) { + title[i] = pdfDocEncoding[s->getChar(i) & 0xff]; + } + } + } else { + titleLen = 0; + } + obj1.free(); + + if (!dict->lookup("Dest", &obj1)->isNull()) { + action = LinkAction::parseDest(&obj1); + } else { + obj1.free(); + if (!dict->lookup("A", &obj1)->isNull()) { + action = LinkAction::parseAction(&obj1); + } + } + obj1.free(); + + dict->lookupNF("First", &firstRef); + dict->lookupNF("Last", &lastRef); + dict->lookupNF("Next", &nextRef); + + startsOpen = gFalse; + if (dict->lookup("Count", &obj1)->isInt()) { + if (obj1.getInt() > 0) { + startsOpen = gTrue; + } + } + obj1.free(); +} + +OutlineItem::~OutlineItem() { + close(); + if (title) { + gfree(title); + } + if (action) { + delete action; + } + firstRef.free(); + lastRef.free(); + nextRef.free(); +} + +GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef, + XRef *xrefA) { + GList *items; + OutlineItem *item; + Object obj; + Object *p; + + items = new GList(); + p = firstItemRef; + while (p->isRef()) { + if (!p->fetch(xrefA, &obj)->isDict()) { + obj.free(); + break; + } + item = new OutlineItem(obj.getDict(), xrefA); + obj.free(); + items->append(item); + if (p->getRef().num == lastItemRef->getRef().num && + p->getRef().gen == lastItemRef->getRef().gen) { + break; + } + p = &item->nextRef; + } + return items; +} + +void OutlineItem::open() { + if (!kids) { + kids = readItemList(&firstRef, &lastRef, xref); + } +} + +void OutlineItem::close() { + if (kids) { + deleteGList(kids, OutlineItem); + kids = NULL; + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Outline.h swftools-0.9.1/lib/pdf/xpdf/Outline.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Outline.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Outline.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,76 @@ +//======================================================================== +// +// Outline.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef OUTLINE_H +#define OUTLINE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Object.h" +#include "CharTypes.h" + +class GString; +class GList; +class XRef; +class LinkAction; + +//------------------------------------------------------------------------ + +class Outline { +public: + + Outline(Object *outlineObj, XRef *xref); + ~Outline(); + + GList *getItems() { return items; } + +private: + + GList *items; // NULL if document has no outline + // [OutlineItem] +}; + +//------------------------------------------------------------------------ + +class OutlineItem { +public: + + OutlineItem(Dict *dict, XRef *xrefA); + ~OutlineItem(); + + static GList *readItemList(Object *firstItemRef, Object *lastItemRef, + XRef *xrefA); + + void open(); + void close(); + + Unicode *getTitle() { return title; } + int getTitleLength() { return titleLen; } + LinkAction *getAction() { return action; } + GBool isOpen() { return startsOpen; } + GBool hasKids() { return firstRef.isRef(); } + GList *getKids() { return kids; } + +private: + + XRef *xref; + Unicode *title; + int titleLen; + LinkAction *action; + Object firstRef; + Object lastRef; + Object nextRef; + GBool startsOpen; + GList *kids; // NULL unless this item is open [OutlineItem] +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/OutputDev.cc swftools-0.9.1/lib/pdf/xpdf/OutputDev.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/OutputDev.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/OutputDev.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,131 @@ +//======================================================================== +// +// OutputDev.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "Object.h" +#include "Stream.h" +#include "GfxState.h" +#include "OutputDev.h" + +//------------------------------------------------------------------------ +// OutputDev +//------------------------------------------------------------------------ + +void OutputDev::setDefaultCTM(double *ctm) { + int i; + double det; + + for (i = 0; i < 6; ++i) { + defCTM[i] = ctm[i]; + } + det = 1 / (defCTM[0] * defCTM[3] - defCTM[1] * defCTM[2]); + defICTM[0] = defCTM[3] * det; + defICTM[1] = -defCTM[1] * det; + defICTM[2] = -defCTM[2] * det; + defICTM[3] = defCTM[0] * det; + defICTM[4] = (defCTM[2] * defCTM[5] - defCTM[3] * defCTM[4]) * det; + defICTM[5] = (defCTM[1] * defCTM[4] - defCTM[0] * defCTM[5]) * det; +} + +void OutputDev::cvtDevToUser(double dx, double dy, double *ux, double *uy) { + *ux = defICTM[0] * dx + defICTM[2] * dy + defICTM[4]; + *uy = defICTM[1] * dx + defICTM[3] * dy + defICTM[5]; +} + +void OutputDev::cvtUserToDev(double ux, double uy, int *dx, int *dy) { + *dx = (int)(defCTM[0] * ux + defCTM[2] * uy + defCTM[4] + 0.5); + *dy = (int)(defCTM[1] * ux + defCTM[3] * uy + defCTM[5] + 0.5); +} + +void OutputDev::updateAll(GfxState *state) { + updateLineDash(state); + updateFlatness(state); + updateLineJoin(state); + updateLineCap(state); + updateMiterLimit(state); + updateLineWidth(state); + updateStrokeAdjust(state); + updateFillColorSpace(state); + updateFillColor(state); + updateStrokeColorSpace(state); + updateStrokeColor(state); + updateBlendMode(state); + updateFillOpacity(state); + updateStrokeOpacity(state); + updateFillOverprint(state); + updateStrokeOverprint(state); + updateTransfer(state); + updateFont(state); +} + +GBool OutputDev::beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen) { + return gFalse; +} + +void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg) { + int i, j; + + if (inlineImg) { + str->reset(); + j = height * ((width + 7) / 8); + for (i = 0; i < j; ++i) + str->getChar(); + str->close(); + } +} + +void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg) { + int i, j; + + if (inlineImg) { + str->reset(); + j = height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8); + for (i = 0; i < j; ++i) + str->getChar(); + str->close(); + } +} + +void OutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert) { + drawImage(state, ref, str, width, height, colorMap, NULL, gFalse); +} + +void OutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap) { + drawImage(state, ref, str, width, height, colorMap, NULL, gFalse); +} + +#if OPI_SUPPORT +void OutputDev::opiBegin(GfxState *state, Dict *opiDict) { +} + +void OutputDev::opiEnd(GfxState *state, Dict *opiDict) { +} +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/OutputDev.h swftools-0.9.1/lib/pdf/xpdf/OutputDev.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/OutputDev.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/OutputDev.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,251 @@ +//======================================================================== +// +// OutputDev.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef OUTPUTDEV_H +#define OUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "CharTypes.h" +#include "Object.h" + +class GString; +class GfxState; +struct GfxColor; +class GfxColorSpace; +class GfxImageColorMap; +class GfxFunctionShading; +class GfxAxialShading; +class GfxRadialShading; +class Stream; +class Links; +class Link; +class Catalog; +class Page; +class Function; + +//------------------------------------------------------------------------ +// OutputDev +//------------------------------------------------------------------------ + +class OutputDev { +public: + + // Constructor. + OutputDev() {} + + // Destructor. + virtual ~OutputDev() {} + + //----- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() = 0; + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() = 0; + + // Does this device use tilingPatternFill()? If this returns false, + // tiling pattern fills will be reduced to a series of other drawing + // operations. + virtual GBool useTilingPatternFill() { return gFalse; } + + // Does this device use functionShadedFill(), axialShadedFill(), and + // radialShadedFill()? If this returns false, these shaded fills + // will be reduced to a series of other drawing operations. + virtual GBool useShadedFills() { return gFalse; } + + // Does this device use drawForm()? If this returns false, + // form-type XObjects will be interpreted (i.e., unrolled). + virtual GBool useDrawForm() { return gFalse; } + + // Does this device use beginType3Char/endType3Char? Otherwise, + // text in Type 3 fonts will be drawn with drawChar/drawString. + virtual GBool interpretType3Chars() = 0; + + // Does this device need non-text content? + virtual GBool needNonText() { return gTrue; } + + //----- initialization and control + + // Set default transform matrix. + virtual void setDefaultCTM(double *ctm); + + // Check to see if a page slice should be displayed. If this + // returns false, the page display is aborted. Typically, an + // OutputDev will use some alternate means to display the page + // before returning false. + virtual GBool checkPageSlice(Page *page, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool printing, Catalog *catalog, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL) + { return gTrue; } + + // Start a page. + virtual void startPage(int pageNum, GfxState *state) {} + + // End a page. + virtual void endPage() {} + + // Dump page contents to display. + virtual void dump() {} + + //----- coordinate conversion + + // Convert between device and user coordinates. + virtual void cvtDevToUser(double dx, double dy, double *ux, double *uy); + virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy); + + double *getDefCTM() { return defCTM; } + double *getDefICTM() { return defICTM; } + + //----- save/restore graphics state + virtual void saveState(GfxState *state) {} + virtual void restoreState(GfxState *state) {} + + //----- update graphics state + virtual void updateAll(GfxState *state); + virtual void updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32) {} + virtual void updateLineDash(GfxState *state) {} + virtual void updateFlatness(GfxState *state) {} + virtual void updateLineJoin(GfxState *state) {} + virtual void updateLineCap(GfxState *state) {} + virtual void updateMiterLimit(GfxState *state) {} + virtual void updateLineWidth(GfxState *state) {} + virtual void updateStrokeAdjust(GfxState *state) {} + virtual void updateFillColorSpace(GfxState *state) {} + virtual void updateStrokeColorSpace(GfxState *state) {} + virtual void updateFillColor(GfxState *state) {} + virtual void updateStrokeColor(GfxState *state) {} + virtual void updateBlendMode(GfxState *state) {} + virtual void updateFillOpacity(GfxState *state) {} + virtual void updateStrokeOpacity(GfxState *state) {} + virtual void updateFillOverprint(GfxState *state) {} + virtual void updateStrokeOverprint(GfxState *state) {} + virtual void updateTransfer(GfxState *state) {} + + //----- update text state + virtual void updateFont(GfxState *state) {} + virtual void updateTextMat(GfxState *state) {} + virtual void updateCharSpace(GfxState *state) {} + virtual void updateRender(GfxState *state) {} + virtual void updateRise(GfxState *state) {} + virtual void updateWordSpace(GfxState *state) {} + virtual void updateHorizScaling(GfxState *state) {} + virtual void updateTextPos(GfxState *state) {} + virtual void updateTextShift(GfxState *state, double shift) {} + + //----- path painting + virtual void stroke(GfxState *state) {} + virtual void fill(GfxState *state) {} + virtual void eoFill(GfxState *state) {} + virtual void tilingPatternFill(GfxState *state, Object *str, + int paintType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep) {} + virtual GBool functionShadedFill(GfxState *state, + GfxFunctionShading *shading) + { return gFalse; } + virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading) + { return gFalse; } + virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading) + { return gFalse; } + + //----- path clipping + virtual void clip(GfxState *state) {} + virtual void eoClip(GfxState *state) {} + virtual void clipToStrokePath(GfxState *state) {} + + //----- text drawing + virtual void beginStringOp(GfxState *state) {} + virtual void endStringOp(GfxState *state) {} + virtual void beginString(GfxState *state, GString *s) {} + virtual void endString(GfxState *state) {} + virtual void drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, Unicode *u, int uLen) {} + virtual void drawString(GfxState *state, GString *s) {} + virtual GBool beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen); + virtual void endType3Char(GfxState *state) {} + virtual void endTextObject(GfxState *state) {} + + //----- image drawing + virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, int maskWidth, int maskHeight, + GBool maskInvert); + virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap); + +#if OPI_SUPPORT + //----- OPI functions + virtual void opiBegin(GfxState *state, Dict *opiDict); + virtual void opiEnd(GfxState *state, Dict *opiDict); +#endif + + //----- Type 3 font operators + virtual void type3D0(GfxState *state, double wx, double wy) {} + virtual void type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury) {} + + //----- form XObjects + virtual void drawForm(Ref id) {} + + //----- PostScript XObjects + virtual void psXObject(Stream *psStream, Stream *level1Stream) {} + + //----- transparency groups and soft masks + virtual void beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask) {} + virtual void endTransparencyGroup(GfxState *state) {} + virtual void paintTransparencyGroup(GfxState *state, double *bbox) {} + virtual void setSoftMask(GfxState *state, double *bbox, GBool alpha, + Function *transferFunc, GfxColor *backdropColor) {} + virtual void clearSoftMask(GfxState *state) {} + + //----- links + virtual void processLink(Link *link, Catalog *catalog) {} + +#if 1 //~tmp: turn off anti-aliasing temporarily + virtual GBool getVectorAntialias() { return gFalse; } + virtual void setVectorAntialias(GBool vaa) {} +#endif + +private: + + double defCTM[6]; // default coordinate transform matrix + double defICTM[6]; // inverse of default CTM +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Page.cc swftools-0.9.1/lib/pdf/xpdf/Page.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Page.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Page.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,441 @@ +//======================================================================== +// +// Page.cc +// +// Copyright 1996-2007 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "GlobalParams.h" +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "XRef.h" +#include "Link.h" +#include "OutputDev.h" +#ifndef PDF_PARSER_ONLY +#include "Gfx.h" +#include "GfxState.h" +#include "Annot.h" +#endif +#include "Error.h" +#include "Catalog.h" +#include "Page.h" + +//------------------------------------------------------------------------ +// PDFRectangle +//------------------------------------------------------------------------ + +void PDFRectangle::clipTo(PDFRectangle *rect) { + if (x1 < rect->x1) { + x1 = rect->x1; + } else if (x1 > rect->x2) { + x1 = rect->x2; + } + if (x2 < rect->x1) { + x2 = rect->x1; + } else if (x2 > rect->x2) { + x2 = rect->x2; + } + if (y1 < rect->y1) { + y1 = rect->y1; + } else if (y1 > rect->y2) { + y1 = rect->y2; + } + if (y2 < rect->y1) { + y2 = rect->y1; + } else if (y2 > rect->y2) { + y2 = rect->y2; + } +} + +//------------------------------------------------------------------------ +// PageAttrs +//------------------------------------------------------------------------ + +PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { + Object obj1; + + // get old/default values + if (attrs) { + mediaBox = attrs->mediaBox; + cropBox = attrs->cropBox; + haveCropBox = attrs->haveCropBox; + rotate = attrs->rotate; + attrs->resources.copy(&resources); + } else { + // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary + // but some (non-compliant) PDF files don't specify a MediaBox + mediaBox.x1 = 0; + mediaBox.y1 = 0; + mediaBox.x2 = 612; + mediaBox.y2 = 792; + cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0; + haveCropBox = gFalse; + rotate = 0; + resources.initNull(); + } + + // media box + readBox(dict, "MediaBox", &mediaBox); + + // crop box + if (readBox(dict, "CropBox", &cropBox)) { + haveCropBox = gTrue; + } + if (!haveCropBox) { + cropBox = mediaBox; + } + + // other boxes + bleedBox = cropBox; + readBox(dict, "BleedBox", &bleedBox); + trimBox = cropBox; + readBox(dict, "TrimBox", &trimBox); + artBox = cropBox; + readBox(dict, "ArtBox", &artBox); + + // clip all other boxes to the media box + cropBox.clipTo(&mediaBox); + bleedBox.clipTo(&mediaBox); + trimBox.clipTo(&mediaBox); + artBox.clipTo(&mediaBox); + + // rotate + dict->lookup("Rotate", &obj1); + if (obj1.isInt()) { + rotate = obj1.getInt(); + } + obj1.free(); + while (rotate < 0) { + rotate += 360; + } + while (rotate >= 360) { + rotate -= 360; + } + + // misc attributes + dict->lookup("LastModified", &lastModified); + dict->lookup("BoxColorInfo", &boxColorInfo); + dict->lookup("Group", &group); + dict->lookup("Metadata", &metadata); + dict->lookup("PieceInfo", &pieceInfo); + dict->lookup("SeparationInfo", &separationInfo); + + // resource dictionary + dict->lookup("Resources", &obj1); + if (obj1.isDict()) { + resources.free(); + obj1.copy(&resources); + } + obj1.free(); +} + +PageAttrs::~PageAttrs() { + lastModified.free(); + boxColorInfo.free(); + group.free(); + metadata.free(); + pieceInfo.free(); + separationInfo.free(); + resources.free(); +} + +GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) { + PDFRectangle tmp; + double t; + Object obj1, obj2; + GBool ok; + + dict->lookup(key, &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 4) { + ok = gTrue; + obj1.arrayGet(0, &obj2); + if (obj2.isNum()) { + tmp.x1 = obj2.getNum(); + } else { + ok = gFalse; + } + obj2.free(); + obj1.arrayGet(1, &obj2); + if (obj2.isNum()) { + tmp.y1 = obj2.getNum(); + } else { + ok = gFalse; + } + obj2.free(); + obj1.arrayGet(2, &obj2); + if (obj2.isNum()) { + tmp.x2 = obj2.getNum(); + } else { + ok = gFalse; + } + obj2.free(); + obj1.arrayGet(3, &obj2); + if (obj2.isNum()) { + tmp.y2 = obj2.getNum(); + } else { + ok = gFalse; + } + obj2.free(); + if (ok) { + if (tmp.x1 > tmp.x2) { + t = tmp.x1; tmp.x1 = tmp.x2; tmp.x2 = t; + } + if (tmp.y1 > tmp.y2) { + t = tmp.y1; tmp.y1 = tmp.y2; tmp.y2 = t; + } + *box = tmp; + } + } else { + ok = gFalse; + } + obj1.free(); + return ok; +} + +//------------------------------------------------------------------------ +// Page +//------------------------------------------------------------------------ + +Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) { + ok = gTrue; + xref = xrefA; + num = numA; + + // get attributes + attrs = attrsA; + + // annotations + pageDict->lookupNF("Annots", &annots); + if (!(annots.isRef() || annots.isArray() || annots.isNull())) { + error(-1, "Page annotations object (page %d) is wrong type (%s)", + num, annots.getTypeName()); + annots.free(); + goto err2; + } + + // contents + pageDict->lookupNF("Contents", &contents); + if (!(contents.isRef() || contents.isArray() || + contents.isNull())) { + error(-1, "Page contents object (page %d) is wrong type (%s)", + num, contents.getTypeName()); + contents.free(); + goto err1; + } + + return; + + err2: + annots.initNull(); + err1: + contents.initNull(); + ok = gFalse; +} + +Page::~Page() { + delete attrs; + annots.free(); + contents.free(); +} + +Links *Page::getLinks(Catalog *catalog) { + Links *links; + Object obj; + + links = new Links(getAnnots(&obj), catalog->getBaseURI()); + obj.free(); + return links; +} + +void Page::display(OutputDev *out, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + GBool printing, Catalog *catalog, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { + displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, + -1, -1, -1, -1, printing, catalog, + abortCheckCbk, abortCheckCbkData); +} + +void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool printing, Catalog *catalog, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { +#ifndef PDF_PARSER_ONLY + PDFRectangle *mediaBox, *cropBox; + PDFRectangle box; + Gfx *gfx; + Object obj; + Annots *annotList; + Dict *acroForm; + int i; + + if (!out->checkPageSlice(this, hDPI, vDPI, rotate, useMediaBox, crop, + sliceX, sliceY, sliceW, sliceH, + printing, catalog, + abortCheckCbk, abortCheckCbkData)) { + return; + } + + rotate += getRotate(); + if (rotate >= 360) { + rotate -= 360; + } else if (rotate < 0) { + rotate += 360; + } + + makeBox(hDPI, vDPI, rotate, useMediaBox, out->upsideDown(), + sliceX, sliceY, sliceW, sliceH, &box, &crop); + cropBox = getCropBox(); + + if (globalParams->getPrintCommands()) { + mediaBox = getMediaBox(); + printf("***** MediaBox = ll:%g,%g ur:%g,%g\n", + mediaBox->x1, mediaBox->y1, mediaBox->x2, mediaBox->y2); + printf("***** CropBox = ll:%g,%g ur:%g,%g\n", + cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2); + printf("***** Rotate = %d\n", attrs->getRotate()); + } + + gfx = new Gfx(xref, out, num, attrs->getResourceDict(), + hDPI, vDPI, &box, crop ? cropBox : (PDFRectangle *)NULL, + rotate, abortCheckCbk, abortCheckCbkData); + contents.fetch(xref, &obj); + if (!obj.isNull()) { + gfx->saveState(); + gfx->display(&obj); + gfx->restoreState(); + } + obj.free(); + + // draw annotations + annotList = new Annots(xref, catalog, getAnnots(&obj)); + obj.free(); + acroForm = catalog->getAcroForm()->isDict() ? + catalog->getAcroForm()->getDict() : NULL; + if (acroForm) { + if (acroForm->lookup("NeedAppearances", &obj)) { + if (obj.isBool() && obj.getBool()) { + annotList->generateAppearances(acroForm); + } + } + obj.free(); + } + if (annotList->getNumAnnots() > 0) { + if (globalParams->getPrintCommands()) { + printf("***** Annotations\n"); + } + for (i = 0; i < annotList->getNumAnnots(); ++i) { + annotList->getAnnot(i)->draw(gfx, printing); + } + out->dump(); + } + delete annotList; + + delete gfx; +#endif +} + +void Page::makeBox(double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool upsideDown, + double sliceX, double sliceY, double sliceW, double sliceH, + PDFRectangle *box, GBool *crop) { + PDFRectangle *mediaBox, *cropBox, *baseBox; + double kx, ky; + + mediaBox = getMediaBox(); + cropBox = getCropBox(); + if (sliceW >= 0 && sliceH >= 0) { + baseBox = useMediaBox ? mediaBox : cropBox; + kx = 72.0 / hDPI; + ky = 72.0 / vDPI; + if (rotate == 90) { + if (upsideDown) { + box->x1 = baseBox->x1 + ky * sliceY; + box->x2 = baseBox->x1 + ky * (sliceY + sliceH); + } else { + box->x1 = baseBox->x2 - ky * (sliceY + sliceH); + box->x2 = baseBox->x2 - ky * sliceY; + } + box->y1 = baseBox->y1 + kx * sliceX; + box->y2 = baseBox->y1 + kx * (sliceX + sliceW); + } else if (rotate == 180) { + box->x1 = baseBox->x2 - kx * (sliceX + sliceW); + box->x2 = baseBox->x2 - kx * sliceX; + if (upsideDown) { + box->y1 = baseBox->y1 + ky * sliceY; + box->y2 = baseBox->y1 + ky * (sliceY + sliceH); + } else { + box->y1 = baseBox->y2 - ky * (sliceY + sliceH); + box->y2 = baseBox->y2 - ky * sliceY; + } + } else if (rotate == 270) { + if (upsideDown) { + box->x1 = baseBox->x2 - ky * (sliceY + sliceH); + box->x2 = baseBox->x2 - ky * sliceY; + } else { + box->x1 = baseBox->x1 + ky * sliceY; + box->x2 = baseBox->x1 + ky * (sliceY + sliceH); + } + box->y1 = baseBox->y2 - kx * (sliceX + sliceW); + box->y2 = baseBox->y2 - kx * sliceX; + } else { + box->x1 = baseBox->x1 + kx * sliceX; + box->x2 = baseBox->x1 + kx * (sliceX + sliceW); + if (upsideDown) { + box->y1 = baseBox->y2 - ky * (sliceY + sliceH); + box->y2 = baseBox->y2 - ky * sliceY; + } else { + box->y1 = baseBox->y1 + ky * sliceY; + box->y2 = baseBox->y1 + ky * (sliceY + sliceH); + } + } + } else if (useMediaBox) { + *box = *mediaBox; + } else { + *box = *cropBox; + *crop = gFalse; + } +} + +void Page::processLinks(OutputDev *out, Catalog *catalog) { + Links *links; + int i; + + links = getLinks(catalog); + for (i = 0; i < links->getNumLinks(); ++i) { + out->processLink(links->getLink(i), catalog); + } + delete links; +} + +void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool upsideDown) { + GfxState *state; + int i; + + rotate += getRotate(); + if (rotate >= 360) { + rotate -= 360; + } else if (rotate < 0) { + rotate += 360; + } + state = new GfxState(hDPI, vDPI, + useMediaBox ? getMediaBox() : getCropBox(), + rotate, upsideDown); + for (i = 0; i < 6; ++i) { + ctm[i] = state->getCTM()[i]; + } + delete state; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Page.h swftools-0.9.1/lib/pdf/xpdf/Page.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Page.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Page.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,187 @@ +//======================================================================== +// +// Page.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PAGE_H +#define PAGE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Object.h" + +class Dict; +class XRef; +class OutputDev; +class Links; +class Catalog; + +//------------------------------------------------------------------------ + +class PDFRectangle { +public: + double x1, y1, x2, y2; + + PDFRectangle() { x1 = y1 = x2 = y2 = 0; } + PDFRectangle(double x1A, double y1A, double x2A, double y2A) + { x1 = x1A; y1 = y1A; x2 = x2A; y2 = y2A; } + GBool isValid() { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; } + void clipTo(PDFRectangle *rect); +}; + +//------------------------------------------------------------------------ +// PageAttrs +//------------------------------------------------------------------------ + +class PageAttrs { +public: + + // Construct a new PageAttrs object by merging a dictionary + // (of type Pages or Page) into another PageAttrs object. If + // is NULL, uses defaults. + PageAttrs(PageAttrs *attrs, Dict *dict); + + // Destructor. + ~PageAttrs(); + + // Accessors. + PDFRectangle *getMediaBox() { return &mediaBox; } + PDFRectangle *getCropBox() { return &cropBox; } + GBool isCropped() { return haveCropBox; } + PDFRectangle *getBleedBox() { return &bleedBox; } + PDFRectangle *getTrimBox() { return &trimBox; } + PDFRectangle *getArtBox() { return &artBox; } + int getRotate() { return rotate; } + GString *getLastModified() + { return lastModified.isString() + ? lastModified.getString() : (GString *)NULL; } + Dict *getBoxColorInfo() + { return boxColorInfo.isDict() ? boxColorInfo.getDict() : (Dict *)NULL; } + Dict *getGroup() + { return group.isDict() ? group.getDict() : (Dict *)NULL; } + Stream *getMetadata() + { return metadata.isStream() ? metadata.getStream() : (Stream *)NULL; } + Dict *getPieceInfo() + { return pieceInfo.isDict() ? pieceInfo.getDict() : (Dict *)NULL; } + Dict *getSeparationInfo() + { return separationInfo.isDict() + ? separationInfo.getDict() : (Dict *)NULL; } + Dict *getResourceDict() + { return resources.isDict() ? resources.getDict() : (Dict *)NULL; } + +private: + + GBool readBox(Dict *dict, char *key, PDFRectangle *box); + + PDFRectangle mediaBox; + PDFRectangle cropBox; + GBool haveCropBox; + PDFRectangle bleedBox; + PDFRectangle trimBox; + PDFRectangle artBox; + int rotate; + Object lastModified; + Object boxColorInfo; + Object group; + Object metadata; + Object pieceInfo; + Object separationInfo; + Object resources; +}; + +//------------------------------------------------------------------------ +// Page +//------------------------------------------------------------------------ + +class Page { +public: + + // Constructor. + Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA); + + // Destructor. + ~Page(); + + // Is page valid? + GBool isOk() { return ok; } + + // Get page parameters. + int getNum() { return num; } + PDFRectangle *getMediaBox() { return attrs->getMediaBox(); } + PDFRectangle *getCropBox() { return attrs->getCropBox(); } + GBool isCropped() { return attrs->isCropped(); } + double getMediaWidth() + { return attrs->getMediaBox()->x2 - attrs->getMediaBox()->x1; } + double getMediaHeight() + { return attrs->getMediaBox()->y2 - attrs->getMediaBox()->y1; } + double getCropWidth() + { return attrs->getCropBox()->x2 - attrs->getCropBox()->x1; } + double getCropHeight() + { return attrs->getCropBox()->y2 - attrs->getCropBox()->y1; } + PDFRectangle *getBleedBox() { return attrs->getBleedBox(); } + PDFRectangle *getTrimBox() { return attrs->getTrimBox(); } + PDFRectangle *getArtBox() { return attrs->getArtBox(); } + int getRotate() { return attrs->getRotate(); } + GString *getLastModified() { return attrs->getLastModified(); } + Dict *getBoxColorInfo() { return attrs->getBoxColorInfo(); } + Dict *getGroup() { return attrs->getGroup(); } + Stream *getMetadata() { return attrs->getMetadata(); } + Dict *getPieceInfo() { return attrs->getPieceInfo(); } + Dict *getSeparationInfo() { return attrs->getSeparationInfo(); } + + // Get resource dictionary. + Dict *getResourceDict() { return attrs->getResourceDict(); } + + // Get annotations array. + Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); } + + // Return a list of links. + Links *getLinks(Catalog *catalog); + + // Get contents. + Object *getContents(Object *obj) { return contents.fetch(xref, obj); } + + // Display a page. + void display(OutputDev *out, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + GBool printing, Catalog *catalog, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + // Display part of a page. + void displaySlice(OutputDev *out, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool printing, Catalog *catalog, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + void makeBox(double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool upsideDown, + double sliceX, double sliceY, double sliceW, double sliceH, + PDFRectangle *box, GBool *crop); + + void processLinks(OutputDev *out, Catalog *catalog); + + // Get the page's default CTM. + void getDefaultCTM(double *ctm, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool upsideDown); + +private: + + XRef *xref; // the xref table for this PDF file + int num; // page number + PageAttrs *attrs; // page attributes + Object annots; // annotations array + Object contents; // page contents + GBool ok; // true if page is valid +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/parseargs.c swftools-0.9.1/lib/pdf/xpdf/parseargs.c --- swftools-0.9.2+ds1/lib/pdf/xpdf/parseargs.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/parseargs.c 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,190 @@ +/* + * parseargs.h + * + * Command line argument parser. + * + * Copyright 1996-2003 Glyph & Cog, LLC + */ + +#include +#include +#include +#include +#include +#include "parseargs.h" + +static ArgDesc *findArg(ArgDesc *args, char *arg); +static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]); + +GBool parseArgs(ArgDesc *args, int *argc, char *argv[]) { + ArgDesc *arg; + int i, j; + GBool ok; + + ok = gTrue; + i = 1; + while (i < *argc) { + if (!strcmp(argv[i], "--")) { + --*argc; + for (j = i; j < *argc; ++j) + argv[j] = argv[j+1]; + break; + } else if ((arg = findArg(args, argv[i]))) { + if (!grabArg(arg, i, argc, argv)) + ok = gFalse; + } else { + ++i; + } + } + return ok; +} + +void printUsage(char *program, char *otherArgs, ArgDesc *args) { + ArgDesc *arg; + char *typ; + int w, w1; + + w = 0; + for (arg = args; arg->arg; ++arg) { + if ((w1 = strlen(arg->arg)) > w) + w = w1; + } + + fprintf(stderr, "Usage: %s [options]", program); + if (otherArgs) + fprintf(stderr, " %s", otherArgs); + fprintf(stderr, "\n"); + + for (arg = args; arg->arg; ++arg) { + fprintf(stderr, " %s", arg->arg); + w1 = 9 + w - strlen(arg->arg); + switch (arg->kind) { + case argInt: + case argIntDummy: + typ = " "; + break; + case argFP: + case argFPDummy: + typ = " "; + break; + case argString: + case argStringDummy: + typ = " "; + break; + case argFlag: + case argFlagDummy: + default: + typ = ""; + break; + } + fprintf(stderr, "%-*s", w1, typ); + if (arg->usage) + fprintf(stderr, ": %s", arg->usage); + fprintf(stderr, "\n"); + } +} + +static ArgDesc *findArg(ArgDesc *args, char *arg) { + ArgDesc *p; + + for (p = args; p->arg; ++p) { + if (p->kind < argFlagDummy && !strcmp(p->arg, arg)) + return p; + } + return NULL; +} + +static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]) { + int n; + int j; + GBool ok; + + ok = gTrue; + n = 0; + switch (arg->kind) { + case argFlag: + *(GBool *)arg->val = gTrue; + n = 1; + break; + case argInt: + if (i + 1 < *argc && isInt(argv[i+1])) { + *(int *)arg->val = atoi(argv[i+1]); + n = 2; + } else { + ok = gFalse; + n = 1; + } + break; + case argFP: + if (i + 1 < *argc && isFP(argv[i+1])) { + *(double *)arg->val = atof(argv[i+1]); + n = 2; + } else { + ok = gFalse; + n = 1; + } + break; + case argString: + if (i + 1 < *argc) { + strncpy((char *)arg->val, argv[i+1], arg->size - 1); + ((char *)arg->val)[arg->size - 1] = '\0'; + n = 2; + } else { + ok = gFalse; + n = 1; + } + break; + default: + fprintf(stderr, "Internal error in arg table\n"); + n = 1; + break; + } + if (n > 0) { + *argc -= n; + for (j = i; j < *argc; ++j) + argv[j] = argv[j+n]; + } + return ok; +} + +GBool isInt(char *s) { + if (*s == '-' || *s == '+') + ++s; + while (isdigit(*s & 0xff)) + ++s; + if (*s) + return gFalse; + return gTrue; +} + +GBool isFP(char *s) { + int n; + + if (*s == '-' || *s == '+') + ++s; + n = 0; + while (isdigit(*s & 0xff)) { + ++s; + ++n; + } + if (*s == '.') + ++s; + while (isdigit(*s & 0xff)) { + ++s; + ++n; + } + if (n > 0 && (*s == 'e' || *s == 'E')) { + ++s; + if (*s == '-' || *s == '+') + ++s; + n = 0; + if (!isdigit(*s & 0xff)) + return gFalse; + do { + ++s; + } while (isdigit(*s & 0xff)); + } + if (*s) + return gFalse; + return gTrue; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/parseargs.h swftools-0.9.1/lib/pdf/xpdf/parseargs.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/parseargs.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/parseargs.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * parseargs.h + * + * Command line argument parser. + * + * Copyright 1996-2003 Glyph & Cog, LLC + */ + +#ifndef PARSEARGS_H +#define PARSEARGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gtypes.h" + +/* + * Argument kinds. + */ +typedef enum { + argFlag, /* flag (present / not-present) */ + /* [val: GBool *] */ + argInt, /* integer arg */ + /* [val: int *] */ + argFP, /* floating point arg */ + /* [val: double *] */ + argString, /* string arg */ + /* [val: char *] */ + /* dummy entries -- these show up in the usage listing only; */ + /* useful for X args, for example */ + argFlagDummy, + argIntDummy, + argFPDummy, + argStringDummy +} ArgKind; + +/* + * Argument descriptor. + */ +typedef struct { + char *arg; /* the command line switch */ + ArgKind kind; /* kind of arg */ + void *val; /* place to store value */ + int size; /* for argString: size of string */ + char *usage; /* usage string */ +} ArgDesc; + +/* + * Parse command line. Removes all args which are found in the arg + * descriptor list . Stops parsing if "--" is found (and removes + * it). Returns gFalse if there was an error. + */ +extern GBool parseArgs(ArgDesc *args, int *argc, char *argv[]); + +/* + * Print usage message, based on arg descriptor list. + */ +extern void printUsage(char *program, char *otherArgs, ArgDesc *args); + +/* + * Check if a string is a valid integer or floating point number. + */ +extern GBool isInt(char *s); +extern GBool isFP(char *s); + +#ifdef __cplusplus +} +#endif + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Parser.cc swftools-0.9.1/lib/pdf/xpdf/Parser.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Parser.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Parser.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,227 @@ +//======================================================================== +// +// Parser.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "Object.h" +#include "Array.h" +#include "Dict.h" +#include "Decrypt.h" +#include "Parser.h" +#include "XRef.h" +#include "Error.h" + +Parser::Parser(XRef *xrefA, Lexer *lexerA, GBool allowStreamsA) { + xref = xrefA; + lexer = lexerA; + inlineImg = 0; + allowStreams = allowStreamsA; + lexer->getObj(&buf1); + lexer->getObj(&buf2); +} + +Parser::~Parser() { + buf1.free(); + buf2.free(); + delete lexer; +} + +Object *Parser::getObj(Object *obj, Guchar *fileKey, + CryptAlgorithm encAlgorithm, int keyLength, + int objNum, int objGen) { + char *key; + Stream *str; + Object obj2; + int num; + DecryptStream *decrypt; + GString *s, *s2; + int c; + + // refill buffer after inline image data + if (inlineImg == 2) { + buf1.free(); + buf2.free(); + lexer->getObj(&buf1); + lexer->getObj(&buf2); + inlineImg = 0; + } + + // array + if (buf1.isCmd("[")) { + shift(); + obj->initArray(xref); + while (!buf1.isCmd("]") && !buf1.isEOF()) + obj->arrayAdd(getObj(&obj2, fileKey, encAlgorithm, keyLength, + objNum, objGen)); + if (buf1.isEOF()) + error(getPos(), "End of file inside array"); + shift(); + + // dictionary or stream + } else if (buf1.isCmd("<<")) { + shift(); + obj->initDict(xref); + while (!buf1.isCmd(">>") && !buf1.isEOF()) { + if (!buf1.isName()) { + error(getPos(), "Dictionary key must be a name object"); + shift(); + } else { + key = copyString(buf1.getName()); + shift(); + if (buf1.isEOF() || buf1.isError()) { + gfree(key); + break; + } + obj->dictAdd(key, getObj(&obj2, fileKey, encAlgorithm, keyLength, + objNum, objGen)); + } + } + if (buf1.isEOF()) + error(getPos(), "End of file inside dictionary"); + // stream objects are not allowed inside content streams or + // object streams + if (allowStreams && buf2.isCmd("stream")) { + if ((str = makeStream(obj, fileKey, encAlgorithm, keyLength, + objNum, objGen))) { + obj->initStream(str); + } else { + obj->free(); + obj->initError(); + } + } else { + shift(); + } + + // indirect reference or integer + } else if (buf1.isInt()) { + num = buf1.getInt(); + shift(); + if (buf1.isInt() && buf2.isCmd("R")) { + obj->initRef(num, buf1.getInt()); + shift(); + shift(); + } else { + obj->initInt(num); + } + + // string + } else if (buf1.isString() && fileKey) { + s = buf1.getString(); + s2 = new GString(); + obj2.initNull(); + decrypt = new DecryptStream(new MemStream(s->getCString(), 0, + s->getLength(), &obj2), + fileKey, encAlgorithm, keyLength, + objNum, objGen); + decrypt->reset(); + while ((c = decrypt->getChar()) != EOF) { + s2->append((char)c); + } + delete decrypt; + obj->initString(s2); + shift(); + + // simple object + } else { + buf1.copy(obj); + shift(); + } + + return obj; +} + +Stream *Parser::makeStream(Object *dict, Guchar *fileKey, + CryptAlgorithm encAlgorithm, int keyLength, + int objNum, int objGen) { + Object obj; + BaseStream *baseStr; + Stream *str; + Guint pos, endPos, length; + + // get stream start position + lexer->skipToNextLine(); + pos = lexer->getPos(); + + // get length + dict->dictLookup("Length", &obj); + if (obj.isInt()) { + length = (Guint)obj.getInt(); + obj.free(); + } else { + error(getPos(), "Bad 'Length' attribute in stream"); + obj.free(); + return NULL; + } + + // check for length in damaged file + if (xref && xref->getStreamEnd(pos, &endPos)) { + length = endPos - pos; + } + + // in badly damaged PDF files, we can run off the end of the input + // stream immediately after the "stream" token + if (!lexer->getStream()) { + return NULL; + } + baseStr = lexer->getStream()->getBaseStream(); + + // skip over stream data + lexer->setPos(pos + length); + + // refill token buffers and check for 'endstream' + shift(); // kill '>>' + shift(); // kill 'stream' + if (buf1.isCmd("endstream")) { + shift(); + } else { + error(getPos(), "Missing 'endstream'"); + // kludge for broken PDF files: just add 5k to the length, and + // hope its enough + length += 5000; + } + + // make base stream + str = baseStr->makeSubStream(pos, gTrue, length, dict); + + // handle decryption + if (fileKey) { + str = new DecryptStream(str, fileKey, encAlgorithm, keyLength, + objNum, objGen); + } + + // get filters + str = str->addFilters(dict); + + return str; +} + +void Parser::shift() { + if (inlineImg > 0) { + if (inlineImg < 2) { + ++inlineImg; + } else { + // in a damaged content stream, if 'ID' shows up in the middle + // of a dictionary, we need to reset + inlineImg = 0; + } + } else if (buf2.isCmd("ID")) { + lexer->skipChar(); // skip char after 'ID' command + inlineImg = 1; + } + buf1.free(); + buf1 = buf2; + if (inlineImg > 0) // don't buffer inline image data + buf2.initNull(); + else + lexer->getObj(&buf2); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Parser.h swftools-0.9.1/lib/pdf/xpdf/Parser.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Parser.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Parser.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,59 @@ +//======================================================================== +// +// Parser.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PARSER_H +#define PARSER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "Lexer.h" + +//------------------------------------------------------------------------ +// Parser +//------------------------------------------------------------------------ + +class Parser { +public: + + // Constructor. + Parser(XRef *xrefA, Lexer *lexerA, GBool allowStreamsA); + + // Destructor. + ~Parser(); + + // Get the next object from the input stream. + Object *getObj(Object *obj, Guchar *fileKey = NULL, + CryptAlgorithm encAlgorithm = cryptRC4, int keyLength = 0, + int objNum = 0, int objGen = 0); + + // Get stream. + Stream *getStream() { return lexer->getStream(); } + + // Get current position in file. + int getPos() { return lexer->getPos(); } + +private: + + XRef *xref; // the xref table for this PDF file + Lexer *lexer; // input stream + GBool allowStreams; // parse stream objects? + Object buf1, buf2; // next two tokens + int inlineImg; // set when inline image data is encountered + + Stream *makeStream(Object *dict, Guchar *fileKey, + CryptAlgorithm encAlgorithm, int keyLength, + int objNum, int objGen); + void shift(); +}; + +#endif + diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PDFCore.cc swftools-0.9.1/lib/pdf/xpdf/PDFCore.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/PDFCore.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PDFCore.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,2044 @@ +//======================================================================== +// +// PDFCore.cc +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "GString.h" +#include "GList.h" +#include "GlobalParams.h" +#include "Splash.h" +#include "SplashBitmap.h" +#include "SplashPattern.h" +#include "SplashPath.h" +#include "Error.h" +#include "ErrorCodes.h" +#include "PDFDoc.h" +#include "Link.h" +#include "TextOutputDev.h" +#include "CoreOutputDev.h" +#include "PDFCore.h" + +//------------------------------------------------------------------------ +// PDFCorePage +//------------------------------------------------------------------------ + +PDFCorePage::PDFCorePage(int pageA, int wA, int hA, int tileWA, int tileHA) { + page = pageA; + tiles = new GList(); + w = wA; + h = hA; + tileW = tileWA; + tileH = tileHA; + links = NULL; + text = NULL; +} + +PDFCorePage::~PDFCorePage() { + deleteGList(tiles, PDFCoreTile); + if (links) { + delete links; + } + if (text) { + delete text; + } +} + +//------------------------------------------------------------------------ +// PDFCoreTile +//------------------------------------------------------------------------ + +PDFCoreTile::PDFCoreTile(int xDestA, int yDestA) { + xMin = 0; + yMin = 0; + xMax = 0; + yMax = 0; + xDest = xDestA; + yDest = yDestA; + bitmap = NULL; +} + +PDFCoreTile::~PDFCoreTile() { + if (bitmap) { + delete bitmap; + } +} + + +//------------------------------------------------------------------------ +// PDFCore +//------------------------------------------------------------------------ + +PDFCore::PDFCore(SplashColorMode colorModeA, int bitmapRowPadA, + GBool reverseVideoA, SplashColorPtr paperColorA, + GBool incrementalUpdate) { + int i; + + doc = NULL; + continuousMode = globalParams->getContinuousView(); + drawAreaWidth = drawAreaHeight = 0; + maxPageW = totalDocH = 0; + pageY = NULL; + topPage = 0; + scrollX = scrollY = 0; + zoom = defZoom; + dpi = 0; + rotate = 0; + + selectPage = 0; + selectULX = selectLRX = 0; + selectULY = selectLRY = 0; + dragging = gFalse; + lastDragLeft = lastDragTop = gTrue; + + historyCur = pdfHistorySize - 1; + historyBLen = historyFLen = 0; + for (i = 0; i < pdfHistorySize; ++i) { + history[i].fileName = NULL; + } + + + pages = new GList(); + curTile = NULL; + + splashColorCopy(paperColor, paperColorA); + out = new CoreOutputDev(colorModeA, bitmapRowPadA, + reverseVideoA, paperColorA, incrementalUpdate, + &redrawCbk, this); + out->startDoc(NULL); +} + +PDFCore::~PDFCore() { + int i; + + if (doc) { + delete doc; + } + for (i = 0; i < pdfHistorySize; ++i) { + if (history[i].fileName) { + delete history[i].fileName; + } + } + gfree(pageY); + deleteGList(pages, PDFCorePage); + delete out; +} + +int PDFCore::loadFile(GString *fileName, GString *ownerPassword, + GString *userPassword) { + int err; + + setBusyCursor(gTrue); + err = loadFile2(new PDFDoc(fileName->copy(), ownerPassword, userPassword, + this)); + setBusyCursor(gFalse); + return err; +} + +#ifdef WIN32 +int PDFCore::loadFile(wchar_t *fileName, int fileNameLen, + GString *ownerPassword, GString *userPassword) { + int err; + + setBusyCursor(gTrue); + err = loadFile2(new PDFDoc(fileName, fileNameLen, + ownerPassword, userPassword, this)); + setBusyCursor(gFalse); + return err; +} +#endif + +int PDFCore::loadFile(BaseStream *stream, GString *ownerPassword, + GString *userPassword) { + int err; + + setBusyCursor(gTrue); + err = loadFile2(new PDFDoc(stream, ownerPassword, userPassword, this)); + setBusyCursor(gFalse); + return err; +} + +void PDFCore::loadDoc(PDFDoc *docA) { + setBusyCursor(gTrue); + loadFile2(docA); + setBusyCursor(gFalse); +} + +int PDFCore::loadFile2(PDFDoc *newDoc) { + int err; + double w, h, t; + int i; + + // open the PDF file + if (!newDoc->isOk()) { + err = newDoc->getErrorCode(); + delete newDoc; + return err; + } + + // replace old document + if (doc) { + delete doc; + } + doc = newDoc; + if (out) { + out->startDoc(doc->getXRef()); + } + + // nothing displayed yet + topPage = -99; + while (pages->getLength() > 0) { + delete (PDFCorePage *)pages->del(0); + } + + // compute the max unscaled page size + maxUnscaledPageW = maxUnscaledPageH = 0; + for (i = 1; i <= doc->getNumPages(); ++i) { + w = doc->getPageCropWidth(i); + h = doc->getPageCropHeight(i); + if (doc->getPageRotate(i) == 90 || doc->getPageRotate(i) == 270) { + t = w; w = h; h = t; + } + if (w > maxUnscaledPageW) { + maxUnscaledPageW = w; + } + if (h > maxUnscaledPageH) { + maxUnscaledPageH = h; + } + } + + return errNone; +} + +void PDFCore::clear() { + if (!doc) { + return; + } + + // no document + delete doc; + doc = NULL; + out->clear(); + + // no page displayed + topPage = -99; + while (pages->getLength() > 0) { + delete (PDFCorePage *)pages->del(0); + } + + // redraw + scrollX = scrollY = 0; + redrawWindow(0, 0, drawAreaWidth, drawAreaHeight, gTrue); + updateScrollbars(); +} + +PDFDoc *PDFCore::takeDoc(GBool redraw) { + PDFDoc *docA; + + if (!doc) { + return NULL; + } + + // no document + docA = doc; + doc = NULL; + out->clear(); + + // no page displayed + topPage = -99; + while (pages->getLength() > 0) { + delete (PDFCorePage *)pages->del(0); + } + + // redraw + scrollX = scrollY = 0; + if (redraw) { + redrawWindow(0, 0, drawAreaWidth, drawAreaHeight, gTrue); + updateScrollbars(); + } + + return docA; +} + +void PDFCore::displayPage(int topPageA, double zoomA, int rotateA, + GBool scrollToTop, GBool addToHist) { + int scrollXA, scrollYA; + + scrollXA = scrollX; + if (continuousMode) { + scrollYA = -1; + } else if (scrollToTop) { + scrollYA = 0; + } else { + scrollYA = scrollY; + } + if (zoomA != zoom) { + scrollXA = 0; + scrollYA = continuousMode ? -1 : 0; + } + + dragging = gFalse; + lastDragLeft = lastDragTop = gTrue; + + update(topPageA, scrollXA, scrollYA, zoomA, rotateA, gTrue, addToHist); +} + +void PDFCore::displayDest(LinkDest *dest, double zoomA, int rotateA, + GBool addToHist) { + Ref pageRef; + int topPageA; + int dx, dy, scrollXA, scrollYA; + + if (dest->isPageRef()) { + pageRef = dest->getPageRef(); + topPageA = doc->findPage(pageRef.num, pageRef.gen); + } else { + topPageA = dest->getPageNum(); + } + if (topPageA <= 0 || topPageA > doc->getNumPages()) { + topPageA = 1; + } + scrollXA = scrollX; + scrollYA = continuousMode ? -1 : scrollY; + switch (dest->getKind()) { + case destXYZ: + cvtUserToDev(topPageA, dest->getLeft(), dest->getTop(), &dx, &dy); + scrollXA = dest->getChangeLeft() ? dx : scrollX; + if (dest->getChangeTop()) { + scrollYA = dy; + } else { + if (topPage <= 0) { + scrollYA = 0; + } else if (continuousMode) { + scrollYA = scrollY - pageY[topPage - 1]; + } else { + scrollYA = scrollY; + } + } + if (continuousMode && topPage > 0) { + scrollYA += pageY[topPageA - 1]; + } + //~ what is the zoom parameter? + break; + case destFit: + case destFitB: + //~ do fit + scrollXA = 0; + scrollYA = continuousMode ? -1 : 0; + break; + case destFitH: + case destFitBH: + //~ do fit + cvtUserToDev(topPageA, 0, dest->getTop(), &dx, &dy); + if (continuousMode && topPage > 0) { + dy += pageY[topPageA - 1]; + } + scrollXA = 0; + scrollYA = dy; + break; + case destFitV: + case destFitBV: + //~ do fit + cvtUserToDev(topPageA, dest->getLeft(), 0, &dx, &dy); + scrollXA = dx; + scrollYA = continuousMode ? -1 : 0; + break; + case destFitR: + //~ do fit + cvtUserToDev(topPageA, dest->getLeft(), dest->getTop(), &dx, &dy); + if (continuousMode && topPage > 0) { + dy += pageY[topPageA - 1]; + } + scrollXA = dx; + scrollYA = dy; + break; + } + update(topPageA, scrollXA, scrollYA, zoom, rotate, gFalse, + addToHist && topPageA != topPage); +} + +void PDFCore::update(int topPageA, int scrollXA, int scrollYA, + double zoomA, int rotateA, GBool force, GBool addToHist) { + double hDPI, vDPI, dpiA, uw, uh, ut; + int w, h, t, x0, x1, y0, y1, x, y; + int rot; + int pg0, pg1; + PDFCoreTile *tile; + PDFCorePage *page; + PDFHistory *hist; + SplashColor xorColor; + GBool needUpdate; + int i, j; + + // check for document and valid page number + if (!doc) { + // save the new settings + zoom = zoomA; + rotate = rotateA; + return; + } + if (topPageA <= 0 || topPageA > doc->getNumPages()) { + return; + } + + needUpdate = gFalse; + + // check for changes to the PDF file + if ((force || (!continuousMode && topPage != topPageA)) && + checkForNewFile()) { + if (loadFile(doc->getFileName()) == errNone) { + if (topPageA > doc->getNumPages()) { + topPageA = doc->getNumPages(); + } + needUpdate = gTrue; + } + } + + // compute the DPI + if (continuousMode) { + uw = maxUnscaledPageW; + uh = maxUnscaledPageH; + rot = rotateA; + } else { + uw = doc->getPageCropWidth(topPageA); + uh = doc->getPageCropHeight(topPageA); + rot = rotateA + doc->getPageRotate(topPageA); + if (rot >= 360) { + rot -= 360; + } else if (rot < 0) { + rot += 360; + } + } + if (rot == 90 || rot == 270) { + ut = uw; uw = uh; uh = ut; + } + if (zoomA == zoomPage) { + hDPI = (drawAreaWidth / uw) * 72; + if (continuousMode) { + vDPI = ((drawAreaHeight - continuousModePageSpacing) / uh) * 72; + } else { + vDPI = (drawAreaHeight / uh) * 72; + } + dpiA = (hDPI < vDPI) ? hDPI : vDPI; + } else if (zoomA == zoomWidth) { + dpiA = (drawAreaWidth / uw) * 72; + } else { + dpiA = 0.01 * zoomA * 72; + } + // this can happen if the window hasn't been sized yet + if (dpiA <= 0) { + dpiA = 1; + } + + // if the display properties have changed, create a new PDFCorePage + // object + if (force || pages->getLength() == 0 || + (!continuousMode && topPageA != topPage) || + zoomA != zoom || dpiA != dpi || rotateA != rotate) { + needUpdate = gTrue; + setSelection(0, 0, 0, 0, 0); + while (pages->getLength() > 0) { + delete (PDFCorePage *)pages->del(0); + } + zoom = zoomA; + rotate = rotateA; + dpi = dpiA; + if (continuousMode) { + maxPageW = totalDocH = 0; + pageY = (int *)greallocn(pageY, doc->getNumPages(), sizeof(int)); + for (i = 1; i <= doc->getNumPages(); ++i) { + pageY[i-1] = totalDocH; + w = (int)((doc->getPageCropWidth(i) * dpi) / 72 + 0.5); + h = (int)((doc->getPageCropHeight(i) * dpi) / 72 + 0.5); + rot = rotate + doc->getPageRotate(i); + if (rot >= 360) { + rot -= 360; + } else if (rot < 0) { + rot += 360; + } + if (rot == 90 || rot == 270) { + t = w; w = h; h = t; + } + if (w > maxPageW) { + maxPageW = w; + } + totalDocH += h; + if (i < doc->getNumPages()) { + totalDocH += continuousModePageSpacing; + } + } + } else { + rot = rotate + doc->getPageRotate(topPageA); + if (rot >= 360) { + rot -= 360; + } else if (rot < 0) { + rot += 360; + } + addPage(topPageA, rot); + } + } else { + // erase the selection + if (selectULX != selectLRX && selectULY != selectLRY) { + xorColor[0] = xorColor[1] = xorColor[2] = 0xff; + xorRectangle(selectPage, selectULX, selectULY, selectLRX, selectLRY, + new SplashSolidColor(xorColor)); + } + } + if (continuousMode) { + page = NULL; // make gcc happy + } else { + page = (PDFCorePage *)pages->get(0); + } + topPage = topPageA; + + // adjust the scroll position + scrollX = scrollXA; + if (continuousMode && scrollYA < 0) { + scrollY = pageY[topPage - 1]; + } else { + scrollY = scrollYA; + } + w = continuousMode ? maxPageW : page->w; + if (scrollX > w - drawAreaWidth) { + scrollX = w - drawAreaWidth; + } + if (scrollX < 0) { + scrollX = 0; + } + h = continuousMode ? totalDocH : page->h; + if (scrollY > h - drawAreaHeight) { + scrollY = h - drawAreaHeight; + } + if (scrollY < 0) { + scrollY = 0; + } + + // find topPage, and the first and last pages to be rasterized + if (continuousMode) { + //~ should use a binary search + for (i = 2; i <= doc->getNumPages(); ++i) { + if (pageY[i-1] > scrollY - drawAreaHeight / 2) { + break; + } + } + pg0 = i - 1; + for (i = pg0 + 1; i <= doc->getNumPages(); ++i) { + if (pageY[i-1] > scrollY) { + break; + } + } + topPage = i - 1; + for (i = topPage + 1; i <= doc->getNumPages(); ++i) { + if (pageY[i-1] > scrollY + drawAreaHeight + drawAreaHeight / 2) { + break; + } + } + pg1 = i - 1; + + // delete pages that are no longer needed and insert new pages + // objects that are needed + while (pages->getLength() > 0 && + ((PDFCorePage *)pages->get(0))->page < pg0) { + delete (PDFCorePage *)pages->del(0); + } + i = pages->getLength() - 1; + while (i > 0 && ((PDFCorePage *)pages->get(i))->page > pg1) { + delete (PDFCorePage *)pages->del(i--); + } + j = pages->getLength() > 0 ? ((PDFCorePage *)pages->get(0))->page - 1 + : pg1; + for (i = pg0; i <= j; ++i) { + rot = rotate + doc->getPageRotate(i); + if (rot >= 360) { + rot -= 360; + } else if (rot < 0) { + rot += 360; + } + addPage(i, rot); + } + j = ((PDFCorePage *)pages->get(pages->getLength() - 1))->page; + for (i = j + 1; i <= pg1; ++i) { + rot = rotate + doc->getPageRotate(i); + if (rot >= 360) { + rot -= 360; + } else if (rot < 0) { + rot += 360; + } + addPage(i, rot); + } + + } else { + pg0 = pg1 = topPage; + } + + // delete tiles that are no longer needed + for (i = 0; i < pages->getLength(); ++i) { + page = (PDFCorePage *)pages->get(i); + j = 0; + while (j < page->tiles->getLength()) { + tile = (PDFCoreTile *)page->tiles->get(j); + if (continuousMode) { + y0 = pageY[page->page - 1] + tile->yMin; + y1 = pageY[page->page - 1] + tile->yMax; + } else { + y0 = tile->yMin; + y1 = tile->yMax; + } + if (tile->xMax < scrollX - drawAreaWidth / 2 || + tile->xMin > scrollX + drawAreaWidth + drawAreaWidth / 2 || + y1 < scrollY - drawAreaHeight / 2 || + y0 > scrollY + drawAreaHeight + drawAreaHeight / 2) { + delete (PDFCoreTile *)page->tiles->del(j); + } else { + ++j; + } + } + } + + // update page positions + for (i = 0; i < pages->getLength(); ++i) { + page = (PDFCorePage *)pages->get(i); + page->xDest = -scrollX; + if (continuousMode) { + page->yDest = pageY[page->page - 1] - scrollY; + } else { + page->yDest = -scrollY; + } + if (continuousMode) { + if (page->w < maxPageW) { + page->xDest += (maxPageW - page->w) / 2; + } + if (maxPageW < drawAreaWidth) { + page->xDest += (drawAreaWidth - maxPageW) / 2; + } + } else if (page->w < drawAreaWidth) { + page->xDest += (drawAreaWidth - page->w) / 2; + } + if (continuousMode && totalDocH < drawAreaHeight) { + page->yDest += (drawAreaHeight - totalDocH) / 2; + } else if (!continuousMode && page->h < drawAreaHeight) { + page->yDest += (drawAreaHeight - page->h) / 2; + } + } + + // rasterize any new tiles + for (i = 0; i < pages->getLength(); ++i) { + page = (PDFCorePage *)pages->get(i); + x0 = page->xDest; + x1 = x0 + page->w - 1; + if (x0 < -drawAreaWidth / 2) { + x0 = -drawAreaWidth / 2; + } + if (x1 > drawAreaWidth + drawAreaWidth / 2) { + x1 = drawAreaWidth + drawAreaWidth / 2; + } + x0 = ((x0 - page->xDest) / page->tileW) * page->tileW; + x1 = ((x1 - page->xDest) / page->tileW) * page->tileW; + y0 = page->yDest; + y1 = y0 + page->h - 1; + if (y0 < -drawAreaHeight / 2) { + y0 = -drawAreaHeight / 2; + } + if (y1 > drawAreaHeight + drawAreaHeight / 2) { + y1 = drawAreaHeight + drawAreaHeight / 2; + } + y0 = ((y0 - page->yDest) / page->tileH) * page->tileH; + y1 = ((y1 - page->yDest) / page->tileH) * page->tileH; + for (y = y0; y <= y1; y += page->tileH) { + for (x = x0; x <= x1; x += page->tileW) { + needTile(page, x, y); + } + } + } + + // update tile positions + for (i = 0; i < pages->getLength(); ++i) { + page = (PDFCorePage *)pages->get(i); + for (j = 0; j < page->tiles->getLength(); ++j) { + tile = (PDFCoreTile *)page->tiles->get(j); + tile->xDest = tile->xMin - scrollX; + if (continuousMode) { + tile->yDest = tile->yMin + pageY[page->page - 1] - scrollY; + } else { + tile->yDest = tile->yMin - scrollY; + } + if (continuousMode) { + if (page->w < maxPageW) { + tile->xDest += (maxPageW - page->w) / 2; + } + if (maxPageW < drawAreaWidth) { + tile->xDest += (drawAreaWidth - maxPageW) / 2; + } + } else if (page->w < drawAreaWidth) { + tile->xDest += (drawAreaWidth - page->w) / 2; + } + if (continuousMode && totalDocH < drawAreaHeight) { + tile->yDest += (drawAreaHeight - totalDocH) / 2; + } else if (!continuousMode && page->h < drawAreaHeight) { + tile->yDest += (drawAreaHeight - page->h) / 2; + } + } + } + + // redraw the selection + if (selectULX != selectLRX && selectULY != selectLRY) { + xorColor[0] = xorColor[1] = xorColor[2] = 0xff; + xorRectangle(selectPage, selectULX, selectULY, selectLRX, selectLRY, + new SplashSolidColor(xorColor)); + } + + // redraw the window + redrawWindow(0, 0, drawAreaWidth, drawAreaHeight, needUpdate); + updateScrollbars(); + + // add to history + if (addToHist) { + if (++historyCur == pdfHistorySize) { + historyCur = 0; + } + hist = &history[historyCur]; + if (hist->fileName) { + delete hist->fileName; + } + if (doc->getFileName()) { + hist->fileName = doc->getFileName()->copy(); + } else { + hist->fileName = NULL; + } + hist->page = topPage; + if (historyBLen < pdfHistorySize) { + ++historyBLen; + } + historyFLen = 0; + } +} + +void PDFCore::addPage(int pg, int rot) { + PDFCorePage *page; + int w, h, t, tileW, tileH, i; + + w = (int)((doc->getPageCropWidth(pg) * dpi) / 72 + 0.5); + h = (int)((doc->getPageCropHeight(pg) * dpi) / 72 + 0.5); + if (rot == 90 || rot == 270) { + t = w; w = h; h = t; + } + tileW = 2 * drawAreaWidth; + if (tileW < 1500) { + tileW = 1500; + } + if (tileW > w) { + tileW = w; + } + tileH = 2 * drawAreaHeight; + if (tileH < 1500) { + tileH = 1500; + } + if (tileH > h) { + tileH = h; + } + page = new PDFCorePage(pg, w, h, tileW, tileH); + for (i = 0; + i < pages->getLength() && pg > ((PDFCorePage *)pages->get(i))->page; + ++i) ; + pages->insert(i, page); +} + +void PDFCore::needTile(PDFCorePage *page, int x, int y) { + PDFCoreTile *tile; + TextOutputDev *textOut; + int xDest, yDest, sliceW, sliceH; + int i; + + for (i = 0; i < page->tiles->getLength(); ++i) { + tile = (PDFCoreTile *)page->tiles->get(i); + if (x == tile->xMin && y == tile->yMin) { + return; + } + } + + setBusyCursor(gTrue); + + sliceW = page->tileW; + if (x + sliceW > page->w) { + sliceW = page->w - x; + } + sliceH = page->tileH; + if (y + sliceH > page->h) { + sliceH = page->h - y; + } + + xDest = x - scrollX; + if (continuousMode) { + yDest = y + pageY[page->page - 1] - scrollY; + } else { + yDest = y - scrollY; + } + if (continuousMode) { + if (page->w < maxPageW) { + xDest += (maxPageW - page->w) / 2; + } + if (maxPageW < drawAreaWidth) { + xDest += (drawAreaWidth - maxPageW) / 2; + } + } else if (page->w < drawAreaWidth) { + xDest += (drawAreaWidth - page->w) / 2; + } + if (continuousMode && totalDocH < drawAreaHeight) { + yDest += (drawAreaHeight - totalDocH) / 2; + } else if (!continuousMode && page->h < drawAreaHeight) { + yDest += (drawAreaHeight - page->h) / 2; + } + curTile = tile = newTile(xDest, yDest); + curPage = page; + tile->xMin = x; + tile->yMin = y; + tile->xMax = x + sliceW; + tile->yMax = y + sliceH; + tile->edges = 0; + if (tile->xMin == 0) { + tile->edges |= pdfCoreTileLeftEdge; + } + if (tile->xMax == page->w) { + tile->edges |= pdfCoreTileRightEdge; + } + if (continuousMode) { + if (tile->yMin == 0) { + tile->edges |= pdfCoreTileTopSpace; + if (page->page == 1) { + tile->edges |= pdfCoreTileTopEdge; + } + } + if (tile->yMax == page->h) { + tile->edges |= pdfCoreTileBottomSpace; + if (page->page == doc->getNumPages()) { + tile->edges |= pdfCoreTileBottomEdge; + } + } + } else { + if (tile->yMin == 0) { + tile->edges |= pdfCoreTileTopEdge; + } + if (tile->yMax == page->h) { + tile->edges |= pdfCoreTileBottomEdge; + } + } + doc->displayPageSlice(out, page->page, dpi, dpi, rotate, + gFalse, gTrue, gFalse, x, y, sliceW, sliceH); + tile->bitmap = out->takeBitmap(); + memcpy(tile->ctm, out->getDefCTM(), 6 * sizeof(double)); + memcpy(tile->ictm, out->getDefICTM(), 6 * sizeof(double)); + if (!page->links) { + page->links = doc->getLinks(page->page); + } + if (!page->text) { + if ((textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse))) { + doc->displayPage(textOut, page->page, dpi, dpi, rotate, + gFalse, gTrue, gFalse); + page->text = textOut->takeText(); + delete textOut; + } + } + page->tiles->append(tile); + curTile = NULL; + curPage = NULL; + + setBusyCursor(gFalse); +} + +GBool PDFCore::gotoNextPage(int inc, GBool top) { + int pg, scrollYA; + + if (!doc || doc->getNumPages() == 0 || topPage >= doc->getNumPages()) { + return gFalse; + } + if ((pg = topPage + inc) > doc->getNumPages()) { + pg = doc->getNumPages(); + } + if (continuousMode) { + scrollYA = -1; + } else if (top) { + scrollYA = 0; + } else { + scrollYA = scrollY; + } + update(pg, scrollX, scrollYA, zoom, rotate, gFalse, gTrue); + return gTrue; +} + +GBool PDFCore::gotoPrevPage(int dec, GBool top, GBool bottom) { + int pg, scrollYA; + + if (!doc || doc->getNumPages() == 0 || topPage <= 1) { + return gFalse; + } + if ((pg = topPage - dec) < 1) { + pg = 1; + } + if (continuousMode) { + scrollYA = -1; + } else if (top) { + scrollYA = 0; + } else if (bottom) { + scrollYA = ((PDFCorePage *)pages->get(0))->h - drawAreaHeight; + if (scrollYA < 0) { + scrollYA = 0; + } + } else { + scrollYA = scrollY; + } + update(pg, scrollX, scrollYA, zoom, rotate, gFalse, gTrue); + return gTrue; +} + +GBool PDFCore::gotoNamedDestination(GString *dest) { + LinkDest *d; + + if (!doc) { + return gFalse; + } + if (!(d = doc->findDest(dest))) { + return gFalse; + } + displayDest(d, zoom, rotate, gTrue); + delete d; + return gTrue; +} + +GBool PDFCore::goForward() { + int pg; + + if (historyFLen == 0) { + return gFalse; + } + if (++historyCur == pdfHistorySize) { + historyCur = 0; + } + --historyFLen; + ++historyBLen; + if (!doc || history[historyCur].fileName->cmp(doc->getFileName()) != 0) { + if (loadFile(history[historyCur].fileName) != errNone) { + return gFalse; + } + } + pg = history[historyCur].page; + update(pg, scrollX, continuousMode ? -1 : scrollY, + zoom, rotate, gFalse, gFalse); + return gTrue; +} + +GBool PDFCore::goBackward() { + int pg; + + if (historyBLen <= 1) { + return gFalse; + } + if (--historyCur < 0) { + historyCur = pdfHistorySize - 1; + } + --historyBLen; + ++historyFLen; + if (!doc || history[historyCur].fileName->cmp(doc->getFileName()) != 0) { + if (loadFile(history[historyCur].fileName) != errNone) { + return gFalse; + } + } + pg = history[historyCur].page; + update(pg, scrollX, continuousMode ? -1 : scrollY, + zoom, rotate, gFalse, gFalse); + return gTrue; +} + +void PDFCore::scrollLeft(int nCols) { + scrollTo(scrollX - nCols, scrollY); +} + +void PDFCore::scrollRight(int nCols) { + scrollTo(scrollX + nCols, scrollY); +} + +void PDFCore::scrollUp(int nLines) { + scrollTo(scrollX, scrollY - nLines); +} + +void PDFCore::scrollUpPrevPage(int nLines) { + if (!continuousMode && scrollY == 0) { + gotoPrevPage(1, gFalse, gTrue); + } else { + scrollTo(scrollX, scrollY - nLines); + } +} + +void PDFCore::scrollDown(int nLines) { + scrollTo(scrollX, scrollY + nLines); +} + +void PDFCore::scrollDownNextPage(int nLines) { + if (!continuousMode && + scrollY >= ((PDFCorePage *)pages->get(0))->h - drawAreaHeight) { + gotoNextPage(1, gTrue); + } else { + scrollTo(scrollX, scrollY + nLines); + } +} + +void PDFCore::scrollPageUp() { + if (!continuousMode && scrollY == 0) { + gotoPrevPage(1, gFalse, gTrue); + } else { + scrollTo(scrollX, scrollY - drawAreaHeight); + } +} + +void PDFCore::scrollPageDown() { + if (!continuousMode && + scrollY >= ((PDFCorePage *)pages->get(0))->h - drawAreaHeight) { + gotoNextPage(1, gTrue); + } else { + scrollTo(scrollX, scrollY + drawAreaHeight); + } +} + +void PDFCore::scrollTo(int x, int y) { + update(topPage, x, y < 0 ? 0 : y, zoom, rotate, gFalse, gFalse); +} + +void PDFCore::scrollToLeftEdge() { + update(topPage, 0, scrollY, zoom, rotate, gFalse, gFalse); +} + +void PDFCore::scrollToRightEdge() { + PDFCorePage *page; + + page = (PDFCorePage *)pages->get(0); + update(topPage, page->w - drawAreaWidth, scrollY, + zoom, rotate, gFalse, gFalse); +} + +void PDFCore::scrollToTopEdge() { + int y; + + y = continuousMode ? pageY[topPage - 1] : 0; + update(topPage, scrollX, y, zoom, rotate, gFalse, gFalse); +} + +void PDFCore::scrollToBottomEdge() { + PDFCorePage *page; + int y, i; + + for (i = pages->getLength() - 1; i > 0; --i) { + page = (PDFCorePage *)pages->get(i); + if (page->yDest < drawAreaHeight) { + break; + } + } + page = (PDFCorePage *)pages->get(i); + if (continuousMode) { + y = pageY[page->page - 1] + page->h - drawAreaHeight; + } else { + y = page->h - drawAreaHeight; + } + update(topPage, scrollX, y, zoom, rotate, gFalse, gFalse); +} + +void PDFCore::scrollToTopLeft() { + int y; + + y = continuousMode ? pageY[topPage - 1] : 0; + update(topPage, 0, y, zoom, rotate, gFalse, gFalse); +} + +void PDFCore::scrollToBottomRight() { + PDFCorePage *page; + int x, y, i; + + for (i = pages->getLength() - 1; i > 0; --i) { + page = (PDFCorePage *)pages->get(i); + if (page->yDest < drawAreaHeight) { + break; + } + } + page = (PDFCorePage *)pages->get(i); + x = page->w - drawAreaWidth; + if (continuousMode) { + y = pageY[page->page - 1] + page->h - drawAreaHeight; + } else { + y = page->h - drawAreaHeight; + } + update(topPage, x, y, zoom, rotate, gFalse, gFalse); +} + +void PDFCore::zoomToRect(int pg, double ulx, double uly, + double lrx, double lry) { + int x0, y0, x1, y1, u, sx, sy; + double rx, ry, newZoom, t; + PDFCorePage *p; + + cvtUserToDev(pg, ulx, uly, &x0, &y0); + cvtUserToDev(pg, lrx, lry, &x1, &y1); + if (x0 > x1) { + u = x0; x0 = x1; x1 = u; + } + if (y0 > y1) { + u = y0; y0 = y1; y1 = u; + } + rx = (double)drawAreaWidth / (double)(x1 - x0); + ry = (double)drawAreaHeight / (double)(y1 - y0); + if (rx < ry) { + newZoom = rx * (dpi / (0.01 * 72)); + sx = (int)(rx * x0); + t = (drawAreaHeight * (x1 - x0)) / drawAreaWidth; + sy = (int)(rx * (y0 + y1 - t) / 2); + if (continuousMode) { + if ((p = findPage(pg)) && p->w < maxPageW) { + sx += (int)(0.5 * rx * (maxPageW - p->w)); + } + u = (pg - 1) * continuousModePageSpacing; + sy += (int)(rx * (pageY[pg - 1] - u)) + u; + } + } else { + newZoom = ry * (dpi / (0.01 * 72)); + t = (drawAreaWidth * (y1 - y0)) / drawAreaHeight; + sx = (int)(ry * (x0 + x1 - t) / 2); + sy = (int)(ry * y0); + if (continuousMode) { + if ((p = findPage(pg)) && p->w < maxPageW) { + sx += (int)(0.5 * rx * (maxPageW - p->w)); + } + u = (pg - 1) * continuousModePageSpacing; + sy += (int)(ry * (pageY[pg - 1] - u)) + u; + } + } + update(pg, sx, sy, newZoom, rotate, gFalse, gFalse); +} + +void PDFCore::zoomCentered(double zoomA) { + int sx, sy, rot, hAdjust, vAdjust, i; + double dpi1, dpi2, pageW, pageH; + PDFCorePage *page; + + if (zoomA == zoomPage) { + if (continuousMode) { + pageW = (rotate == 90 || rotate == 270) ? maxUnscaledPageH + : maxUnscaledPageW; + pageH = (rotate == 90 || rotate == 270) ? maxUnscaledPageW + : maxUnscaledPageH; + dpi1 = 72.0 * (double)drawAreaWidth / pageW; + dpi2 = 72.0 * (double)(drawAreaHeight - continuousModePageSpacing) / + pageH; + if (dpi2 < dpi1) { + dpi1 = dpi2; + } + } else { + // in single-page mode, sx=sy=0 -- so dpi1 is irrelevant + dpi1 = dpi; + } + sx = 0; + + } else if (zoomA == zoomWidth) { + if (continuousMode) { + pageW = (rotate == 90 || rotate == 270) ? maxUnscaledPageH + : maxUnscaledPageW; + } else { + rot = rotate + doc->getPageRotate(topPage); + if (rot >= 360) { + rot -= 360; + } else if (rot < 0) { + rot += 360; + } + pageW = (rot == 90 || rot == 270) ? doc->getPageCropHeight(topPage) + : doc->getPageCropWidth(topPage); + } + dpi1 = 72.0 * (double)drawAreaWidth / pageW; + sx = 0; + + } else if (zoomA <= 0) { + return; + + } else { + dpi1 = 72.0 * zoomA / 100.0; + if ((page = (PDFCorePage *)pages->get(0)) && page->xDest > 0) { + hAdjust = page->xDest; + } else { + hAdjust = 0; + } + sx = (int)((scrollX - hAdjust + drawAreaWidth / 2) * (dpi1 / dpi)) - + drawAreaWidth / 2; + if (sx < 0) { + sx = 0; + } + } + + if (continuousMode) { + // we can't just multiply scrollY by dpi1/dpi -- the rounding + // errors add up (because the pageY values are integers) -- so + // we compute the pageY values at the new zoom level instead + sy = 0; + for (i = 1; i < topPage; ++i) { + rot = rotate + doc->getPageRotate(i); + if (rot >= 360) { + rot -= 360; + } else if (rot < 0) { + rot += 360; + } + if (rot == 90 || rot == 270) { + sy += (int)((doc->getPageCropWidth(i) * dpi1) / 72 + 0.5); + } else { + sy += (int)((doc->getPageCropHeight(i) * dpi1) / 72 + 0.5); + } + } + vAdjust = (topPage - 1) * continuousModePageSpacing; + sy = sy + (int)((scrollY - pageY[topPage - 1] + drawAreaHeight / 2) + * (dpi1 / dpi)) + + vAdjust - drawAreaHeight / 2; + } else { + sy = (int)((scrollY + drawAreaHeight / 2) * (dpi1 / dpi)) + - drawAreaHeight / 2; + } + + update(topPage, sx, sy, zoomA, rotate, gFalse, gFalse); +} + +// Zoom so that the current page(s) fill the window width. Maintain +// the vertical center. +void PDFCore::zoomToCurrentWidth() { + double w, maxW, dpi1; + int sx, sy, vAdjust, rot, i; + + // compute the maximum page width of visible pages + rot = rotate + doc->getPageRotate(topPage); + if (rot >= 360) { + rot -= 360; + } else if (rot < 0) { + rot += 360; + } + if (rot == 90 || rot == 270) { + maxW = doc->getPageCropHeight(topPage); + } else { + maxW = doc->getPageCropWidth(topPage); + } + if (continuousMode) { + for (i = topPage + 1; + i < doc->getNumPages() && pageY[i-1] < scrollY + drawAreaHeight; + ++i) { + rot = rotate + doc->getPageRotate(i); + if (rot >= 360) { + rot -= 360; + } else if (rot < 0) { + rot += 360; + } + if (rot == 90 || rot == 270) { + w = doc->getPageCropHeight(i); + } else { + w = doc->getPageCropWidth(i); + } + if (w > maxW) { + maxW = w; + } + } + } + + // compute the resolution + dpi1 = (drawAreaWidth / maxW) * 72; + + // compute the horizontal scroll position + if (continuousMode) { + sx = ((int)(maxPageW * dpi1 / dpi) - drawAreaWidth) / 2; + } else { + sx = 0; + } + + // compute the vertical scroll position + if (continuousMode) { + // we can't just multiply scrollY by dpi1/dpi -- the rounding + // errors add up (because the pageY values are integers) -- so + // we compute the pageY values at the new zoom level instead + sy = 0; + for (i = 1; i < topPage; ++i) { + rot = rotate + doc->getPageRotate(i); + if (rot >= 360) { + rot -= 360; + } else if (rot < 0) { + rot += 360; + } + if (rot == 90 || rot == 270) { + sy += (int)((doc->getPageCropWidth(i) * dpi1) / 72 + 0.5); + } else { + sy += (int)((doc->getPageCropHeight(i) * dpi1) / 72 + 0.5); + } + } + vAdjust = (topPage - 1) * continuousModePageSpacing; + sy = sy + (int)((scrollY - pageY[topPage - 1] + drawAreaHeight / 2) + * (dpi1 / dpi)) + + vAdjust - drawAreaHeight / 2; + } else { + sy = (int)((scrollY + drawAreaHeight / 2) * (dpi1 / dpi)) + - drawAreaHeight / 2; + } + + update(topPage, sx, sy, (dpi1 * 100) / 72, rotate, gFalse, gFalse); +} + +void PDFCore::setContinuousMode(GBool cm) { + if (continuousMode != cm) { + continuousMode = cm; + update(topPage, scrollX, -1, zoom, rotate, gTrue, gFalse); + } +} + +void PDFCore::setSelection(int newSelectPage, + int newSelectULX, int newSelectULY, + int newSelectLRX, int newSelectLRY) { + int x0, y0, x1, y1, py; + GBool haveSel, newHaveSel; + GBool needRedraw, needScroll; + GBool moveLeft, moveRight, moveTop, moveBottom; + SplashColor xorColor; + PDFCorePage *page; + + + haveSel = selectULX != selectLRX && selectULY != selectLRY; + newHaveSel = newSelectULX != newSelectLRX && newSelectULY != newSelectLRY; + + // erase old selection on off-screen bitmap + needRedraw = gFalse; + if (haveSel) { + xorColor[0] = xorColor[1] = xorColor[2] = 0xff; + xorRectangle(selectPage, selectULX, selectULY, selectLRX, selectLRY, + new SplashSolidColor(xorColor)); + needRedraw = gTrue; + } + + // draw new selection on off-screen bitmap + if (newHaveSel) { + xorColor[0] = xorColor[1] = xorColor[2] = 0xff; + xorRectangle(newSelectPage, newSelectULX, newSelectULY, + newSelectLRX, newSelectLRY, + new SplashSolidColor(xorColor)); + needRedraw = gTrue; + } + + // check which edges moved + if (!haveSel || newSelectPage != selectPage) { + moveLeft = moveTop = moveRight = moveBottom = gTrue; + } else { + moveLeft = newSelectULX != selectULX; + moveTop = newSelectULY != selectULY; + moveRight = newSelectLRX != selectLRX; + moveBottom = newSelectLRY != selectLRY; + } + + // redraw currently visible part of bitmap + if (needRedraw) { + if (!haveSel) { + page = findPage(newSelectPage); + x0 = newSelectULX; + y0 = newSelectULY; + x1 = newSelectLRX; + y1 = newSelectLRY; + redrawWindow(page->xDest + x0, page->yDest + y0, + x1 - x0 + 1, y1 - y0 + 1, gFalse); + } else if (!newHaveSel) { + if ((page = findPage(selectPage))) { + x0 = selectULX; + y0 = selectULY; + x1 = selectLRX; + y1 = selectLRY; + redrawWindow(page->xDest + x0, page->yDest + y0, + x1 - x0 + 1, y1 - y0 + 1, gFalse); + } + } else { + page = findPage(newSelectPage); + if (moveLeft) { + x0 = newSelectULX < selectULX ? newSelectULX : selectULX; + y0 = newSelectULY < selectULY ? newSelectULY : selectULY; + x1 = newSelectULX > selectULX ? newSelectULX : selectULX; + y1 = newSelectLRY > selectLRY ? newSelectLRY : selectLRY; + redrawWindow(page->xDest + x0, page->yDest + y0, + x1 - x0 + 1, y1 - y0 + 1, gFalse); + } + if (moveRight) { + x0 = newSelectLRX < selectLRX ? newSelectLRX : selectLRX; + y0 = newSelectULY < selectULY ? newSelectULY : selectULY; + x1 = newSelectLRX > selectLRX ? newSelectLRX : selectLRX; + y1 = newSelectLRY > selectLRY ? newSelectLRY : selectLRY; + redrawWindow(page->xDest + x0, page->yDest + y0, + x1 - x0 + 1, y1 - y0 + 1, gFalse); + } + if (moveTop) { + x0 = newSelectULX < selectULX ? newSelectULX : selectULX; + y0 = newSelectULY < selectULY ? newSelectULY : selectULY; + x1 = newSelectLRX > selectLRX ? newSelectLRX : selectLRX; + y1 = newSelectULY > selectULY ? newSelectULY : selectULY; + redrawWindow(page->xDest + x0, page->yDest + y0, + x1 - x0 + 1, y1 - y0 + 1, gFalse); + } + if (moveBottom) { + x0 = newSelectULX < selectULX ? newSelectULX : selectULX; + y0 = newSelectLRY < selectLRY ? newSelectLRY : selectLRY; + x1 = newSelectLRX > selectLRX ? newSelectLRX : selectLRX; + y1 = newSelectLRY > selectLRY ? newSelectLRY : selectLRY; + redrawWindow(page->xDest + x0, page->yDest + y0, + x1 - x0 + 1, y1 - y0 + 1, gFalse); + } + } + } + + // switch to new selection coords + selectPage = newSelectPage; + selectULX = newSelectULX; + selectULY = newSelectULY; + selectLRX = newSelectLRX; + selectLRY = newSelectLRY; + + // scroll if necessary + if (newHaveSel) { + page = findPage(selectPage); + needScroll = gFalse; + x0 = scrollX; + y0 = scrollY; + if (moveLeft && page->xDest + selectULX < 0) { + x0 += page->xDest + selectULX; + needScroll = gTrue; + } else if (moveRight && page->xDest + selectLRX >= drawAreaWidth) { + x0 += page->xDest + selectLRX - drawAreaWidth; + needScroll = gTrue; + } else if (moveLeft && page->xDest + selectULX >= drawAreaWidth) { + x0 += page->xDest + selectULX - drawAreaWidth; + needScroll = gTrue; + } else if (moveRight && page->xDest + selectLRX < 0) { + x0 += page->xDest + selectLRX; + needScroll = gTrue; + } + py = continuousMode ? pageY[selectPage - 1] : 0; + if (moveTop && py + selectULY < y0) { + y0 = py + selectULY; + needScroll = gTrue; + } else if (moveBottom && py + selectLRY >= y0 + drawAreaHeight) { + y0 = py + selectLRY - drawAreaHeight; + needScroll = gTrue; + } else if (moveTop && py + selectULY >= y0 + drawAreaHeight) { + y0 = py + selectULY - drawAreaHeight; + needScroll = gTrue; + } else if (moveBottom && py + selectLRY < y0) { + y0 = py + selectLRY; + needScroll = gTrue; + } + if (needScroll) { + scrollTo(x0, y0); + } + } +} + +void PDFCore::moveSelection(int pg, int x, int y) { + int newSelectULX, newSelectULY, newSelectLRX, newSelectLRY; + + // don't allow selections to span multiple pages + if (pg != selectPage) { + return; + } + + // move appropriate edges of selection + if (lastDragLeft) { + if (x < selectLRX) { + newSelectULX = x; + newSelectLRX = selectLRX; + } else { + newSelectULX = selectLRX; + newSelectLRX = x; + lastDragLeft = gFalse; + } + } else { + if (x > selectULX) { + newSelectULX = selectULX; + newSelectLRX = x; + } else { + newSelectULX = x; + newSelectLRX = selectULX; + lastDragLeft = gTrue; + } + } + if (lastDragTop) { + if (y < selectLRY) { + newSelectULY = y; + newSelectLRY = selectLRY; + } else { + newSelectULY = selectLRY; + newSelectLRY = y; + lastDragTop = gFalse; + } + } else { + if (y > selectULY) { + newSelectULY = selectULY; + newSelectLRY = y; + } else { + newSelectULY = y; + newSelectLRY = selectULY; + lastDragTop = gTrue; + } + } + + // redraw the selection + setSelection(selectPage, newSelectULX, newSelectULY, + newSelectLRX, newSelectLRY); +} + +void PDFCore::xorRectangle(int pg, int x0, int y0, int x1, int y1, + SplashPattern *pattern, PDFCoreTile *oneTile) { + Splash *splash; + SplashPath *path; + PDFCorePage *page; + PDFCoreTile *tile; + SplashCoord xx0, yy0, xx1, yy1; + int xi, yi, wi, hi; + int i; + + if ((page = findPage(pg))) { + for (i = 0; i < page->tiles->getLength(); ++i) { + tile = (PDFCoreTile *)page->tiles->get(i); + if (!oneTile || tile == oneTile) { + splash = new Splash(tile->bitmap, gFalse); + splash->setFillPattern(pattern->copy()); + xx0 = (SplashCoord)(x0 - tile->xMin); + yy0 = (SplashCoord)(y0 - tile->yMin); + xx1 = (SplashCoord)(x1 - tile->xMin); + yy1 = (SplashCoord)(y1 - tile->yMin); + path = new SplashPath(); + path->moveTo(xx0, yy0); + path->lineTo(xx1, yy0); + path->lineTo(xx1, yy1); + path->lineTo(xx0, yy1); + path->close(); + splash->xorFill(path, gTrue); + delete path; + delete splash; + xi = x0 - tile->xMin; + wi = x1 - x0; + if (xi < 0) { + wi += xi; + xi = 0; + } + if (xi + wi > tile->bitmap->getWidth()) { + wi = tile->bitmap->getWidth() - xi; + } + yi = y0 - tile->yMin; + hi = y1 - y0; + if (yi < 0) { + hi += yi; + yi = 0; + } + if (yi + hi > tile->bitmap->getHeight()) { + hi = tile->bitmap->getHeight() - yi; + } + updateTileData(tile, xi, yi, wi, hi, gTrue); + } + } + } + delete pattern; +} + +GBool PDFCore::getSelection(int *pg, double *ulx, double *uly, + double *lrx, double *lry) { + if (selectULX == selectLRX || selectULY == selectLRY) { + return gFalse; + } + *pg = selectPage; + cvtDevToUser(selectPage, selectULX, selectULY, ulx, uly); + cvtDevToUser(selectPage, selectLRX, selectLRY, lrx, lry); + return gTrue; +} + +GString *PDFCore::extractText(int pg, double xMin, double yMin, + double xMax, double yMax) { + PDFCorePage *page; + TextOutputDev *textOut; + int x0, y0, x1, y1, t; + GString *s; + + if (!doc->okToCopy()) { + return NULL; + } + if ((page = findPage(pg))) { + cvtUserToDev(pg, xMin, yMin, &x0, &y0); + cvtUserToDev(pg, xMax, yMax, &x1, &y1); + if (x0 > x1) { + t = x0; x0 = x1; x1 = t; + } + if (y0 > y1) { + t = y0; y0 = y1; y1 = t; + } + s = page->text->getText(x0, y0, x1, y1); + } else { + textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse); + if (textOut->isOk()) { + doc->displayPage(textOut, pg, dpi, dpi, rotate, gFalse, gTrue, gFalse); + textOut->cvtUserToDev(xMin, yMin, &x0, &y0); + textOut->cvtUserToDev(xMax, yMax, &x1, &y1); + if (x0 > x1) { + t = x0; x0 = x1; x1 = t; + } + if (y0 > y1) { + t = y0; y0 = y1; y1 = t; + } + s = textOut->getText(x0, y0, x1, y1); + } else { + s = new GString(); + } + delete textOut; + } + return s; +} + +GBool PDFCore::find(char *s, GBool caseSensitive, GBool next, GBool backward, + GBool onePageOnly) { + Unicode *u; + int len, i; + GBool ret; + + // convert to Unicode + len = strlen(s); + u = (Unicode *)gmallocn(len, sizeof(Unicode)); + for (i = 0; i < len; ++i) { + u[i] = (Unicode)(s[i] & 0xff); + } + + ret = findU(u, len, caseSensitive, next, backward, onePageOnly); + + gfree(u); + return ret; +} + +GBool PDFCore::findU(Unicode *u, int len, GBool caseSensitive, + GBool next, GBool backward, GBool onePageOnly) { + TextOutputDev *textOut; + double xMin, yMin, xMax, yMax; + PDFCorePage *page; + PDFCoreTile *tile; + int pg; + GBool startAtTop, startAtLast, stopAtLast; + + // check for zero-length string + if (len == 0) { + return gFalse; + } + + setBusyCursor(gTrue); + + // search current page starting at previous result, current + // selection, or top/bottom of page + startAtTop = startAtLast = gFalse; + xMin = yMin = xMax = yMax = 0; + pg = topPage; + if (next) { + startAtLast = gTrue; + } else if (selectULX != selectLRX && selectULY != selectLRY) { + pg = selectPage; + if (backward) { + xMin = selectULX - 1; + yMin = selectULY - 1; + } else { + xMin = selectULX + 1; + yMin = selectULY + 1; + } + } else { + startAtTop = gTrue; + } + if (!(page = findPage(pg))) { + displayPage(pg, zoom, rotate, gTrue, gFalse); + page = findPage(pg); + } + if (page->text->findText(u, len, startAtTop, gTrue, startAtLast, gFalse, + caseSensitive, backward, + &xMin, &yMin, &xMax, &yMax)) { + goto found; + } + + if (!onePageOnly) { + + // search following/previous pages + textOut = new TextOutputDev(NULL, gTrue, gFalse, gFalse); + if (!textOut->isOk()) { + delete textOut; + goto notFound; + } + for (pg = backward ? pg - 1 : pg + 1; + backward ? pg >= 1 : pg <= doc->getNumPages(); + pg += backward ? -1 : 1) { + doc->displayPage(textOut, pg, 72, 72, 0, gFalse, gTrue, gFalse); + if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse, + caseSensitive, backward, + &xMin, &yMin, &xMax, &yMax)) { + delete textOut; + goto foundPage; + } + } + + // search previous/following pages + for (pg = backward ? doc->getNumPages() : 1; + backward ? pg > topPage : pg < topPage; + pg += backward ? -1 : 1) { + doc->displayPage(textOut, pg, 72, 72, 0, gFalse, gTrue, gFalse); + if (textOut->findText(u, len, gTrue, gTrue, gFalse, gFalse, + caseSensitive, backward, + &xMin, &yMin, &xMax, &yMax)) { + delete textOut; + goto foundPage; + } + } + delete textOut; + + } + + // search current page ending at previous result, current selection, + // or bottom/top of page + if (!startAtTop) { + xMin = yMin = xMax = yMax = 0; + if (next) { + stopAtLast = gTrue; + } else { + stopAtLast = gFalse; + xMax = selectLRX; + yMax = selectLRY; + } + if (page->text->findText(u, len, gTrue, gFalse, gFalse, stopAtLast, + caseSensitive, backward, + &xMin, &yMin, &xMax, &yMax)) { + goto found; + } + } + + // not found + notFound: + setBusyCursor(gFalse); + return gFalse; + + // found on a different page + foundPage: + update(pg, scrollX, continuousMode ? -1 : 0, zoom, rotate, gFalse, gTrue); + page = findPage(pg); + if (!page->text->findText(u, len, gTrue, gTrue, gFalse, gFalse, + caseSensitive, backward, + &xMin, &yMin, &xMax, &yMax)) { + // this can happen if coalescing is bad + goto notFound; + } + + // found: change the selection + found: + tile = (PDFCoreTile *)page->tiles->get(0); + setSelection(pg, (int)floor(xMin), (int)floor(yMin), + (int)ceil(xMax), (int)ceil(yMax)); + + setBusyCursor(gFalse); + return gTrue; +} + + +GBool PDFCore::cvtWindowToUser(int xw, int yw, + int *pg, double *xu, double *yu) { + PDFCorePage *page; + PDFCoreTile *tile; + int i; + + for (i = 0; i < pages->getLength(); ++i) { + page = (PDFCorePage *)pages->get(i); + if (xw >= page->xDest && xw < page->xDest + page->w && + yw >= page->yDest && yw < page->yDest + page->h) { + tile = (PDFCoreTile *)page->tiles->get(0); + *pg = page->page; + xw -= tile->xDest; + yw -= tile->yDest; + *xu = tile->ictm[0] * xw + tile->ictm[2] * yw + tile->ictm[4]; + *yu = tile->ictm[1] * xw + tile->ictm[3] * yw + tile->ictm[5]; + return gTrue; + } + } + *pg = 0; + *xu = *yu = 0; + return gFalse; +} + +GBool PDFCore::cvtWindowToDev(int xw, int yw, int *pg, int *xd, int *yd) { + PDFCorePage *page; + int i; + + for (i = 0; i < pages->getLength(); ++i) { + page = (PDFCorePage *)pages->get(i); + if (xw >= page->xDest && xw < page->xDest + page->w && + yw >= page->yDest && yw < page->yDest + page->h) { + *pg = page->page; + *xd = xw - page->xDest; + *yd = yw - page->yDest; + return gTrue; + } + } + *pg = 0; + *xd = *yd = 0; + return gFalse; +} + +void PDFCore::cvtUserToWindow(int pg, double xu, double yu, int *xw, int *yw) { + PDFCorePage *page; + PDFCoreTile *tile; + + if ((page = findPage(pg)) && + page->tiles->getLength() > 0) { + tile = (PDFCoreTile *)page->tiles->get(0); + } else if (curTile && curPage->page == pg) { + tile = curTile; + } else { + tile = NULL; + } + if (tile) { + *xw = tile->xDest + (int)(tile->ctm[0] * xu + tile->ctm[2] * yu + + tile->ctm[4] + 0.5); + *yw = tile->yDest + (int)(tile->ctm[1] * xu + tile->ctm[3] * yu + + tile->ctm[5] + 0.5); + } else { + // this should never happen + *xw = *yw = 0; + } +} + +void PDFCore::cvtUserToDev(int pg, double xu, double yu, int *xd, int *yd) { + PDFCorePage *page; + PDFCoreTile *tile; + double ctm[6]; + + if ((page = findPage(pg)) && + page->tiles->getLength() > 0) { + tile = (PDFCoreTile *)page->tiles->get(0); + } else if (curTile && curPage->page == pg) { + tile = curTile; + } else { + tile = NULL; + } + if (tile) { + *xd = (int)(tile->xMin + tile->ctm[0] * xu + + tile->ctm[2] * yu + tile->ctm[4] + 0.5); + *yd = (int)(tile->yMin + tile->ctm[1] * xu + + tile->ctm[3] * yu + tile->ctm[5] + 0.5); + } else { + doc->getCatalog()->getPage(pg)->getDefaultCTM(ctm, dpi, dpi, rotate, + gFalse, out->upsideDown()); + *xd = (int)(ctm[0] * xu + ctm[2] * yu + ctm[4] + 0.5); + *yd = (int)(ctm[1] * xu + ctm[3] * yu + ctm[5] + 0.5); + } +} + +void PDFCore::cvtDevToWindow(int pg, int xd, int yd, int *xw, int *yw) { + PDFCorePage *page; + + if ((page = findPage(pg))) { + *xw = page->xDest + xd; + *yw = page->yDest + yd; + } else { + // this should never happen + *xw = *yw = 0; + } +} + +void PDFCore::cvtDevToUser(int pg, int xd, int yd, double *xu, double *yu) { + PDFCorePage *page; + PDFCoreTile *tile; + + if ((page = findPage(pg)) && + page->tiles->getLength() > 0) { + tile = (PDFCoreTile *)page->tiles->get(0); + } else if (curTile && curPage->page == pg) { + tile = curTile; + } else { + tile = NULL; + } + if (tile) { + xd -= tile->xMin; + yd -= tile->yMin; + *xu = tile->ictm[0] * xd + tile->ictm[2] * yd + tile->ictm[4]; + *yu = tile->ictm[1] * xd + tile->ictm[3] * yd + tile->ictm[5]; + } else { + // this should never happen + *xu = *yu = 0; + } +} + +void PDFCore::setReverseVideo(GBool reverseVideoA) { + out->setReverseVideo(reverseVideoA); + update(topPage, scrollX, scrollY, zoom, rotate, gTrue, gFalse); +} + +LinkAction *PDFCore::findLink(int pg, double x, double y) { + PDFCorePage *page; + + if ((page = findPage(pg))) { + return page->links ? page->links->find(x, y) : (LinkAction *)NULL; + } + return NULL; +} + +PDFCorePage *PDFCore::findPage(int pg) { + PDFCorePage *page; + int i; + + for (i = 0; i < pages->getLength(); ++i) { + page = (PDFCorePage *)pages->get(i); + if (page->page == pg) { + return page; + } + } + return NULL; +} + +void PDFCore::redrawCbk(void *data, int x0, int y0, int x1, int y1, + GBool composited) { + PDFCore *core = (PDFCore *)data; + + core->curTile->bitmap = core->out->getBitmap(); + + // the default CTM is set by the Gfx constructor; tile->ctm is + // needed by the coordinate conversion functions (which may be + // called during redraw) + memcpy(core->curTile->ctm, core->out->getDefCTM(), 6 * sizeof(double)); + memcpy(core->curTile->ictm, core->out->getDefICTM(), 6 * sizeof(double)); + + // the bitmap created by Gfx and SplashOutputDev can be a slightly + // different size due to rounding errors + if (x1 >= core->curTile->xMax) { + x1 = core->curTile->xMax - 1; + } + if (y1 >= core->curTile->yMax) { + y1 = core->curTile->yMax - 1; + } + + core->clippedRedrawRect(core->curTile, x0, y0, + core->curTile->xDest + x0, core->curTile->yDest + y0, + x1 - x0 + 1, y1 - y0 + 1, + 0, 0, core->drawAreaWidth, core->drawAreaHeight, + gTrue, composited); +} + +void PDFCore::redrawWindow(int x, int y, int width, int height, + GBool needUpdate) { + PDFCorePage *page; + PDFCoreTile *tile; + int xDest, yDest, w, i, j; + + if (pages->getLength() == 0) { + redrawRect(NULL, 0, 0, x, y, width, height, gTrue); + return; + } + + for (i = 0; i < pages->getLength(); ++i) { + page = (PDFCorePage *)pages->get(i); + for (j = 0; j < page->tiles->getLength(); ++j) { + tile = (PDFCoreTile *)page->tiles->get(j); + if (tile->edges & pdfCoreTileTopEdge) { + if (tile->edges & pdfCoreTileLeftEdge) { + xDest = 0; + } else { + xDest = tile->xDest; + } + if (tile->edges & pdfCoreTileRightEdge) { + w = drawAreaWidth - xDest; + } else { + w = tile->xDest + (tile->xMax - tile->xMin) - xDest; + } + clippedRedrawRect(NULL, 0, 0, + xDest, 0, w, tile->yDest, + x, y, width, height, gFalse); + } + if (tile->edges & pdfCoreTileBottomEdge) { + if (tile->edges & pdfCoreTileLeftEdge) { + xDest = 0; + } else { + xDest = tile->xDest; + } + if (tile->edges & pdfCoreTileRightEdge) { + w = drawAreaWidth - xDest; + } else { + w = tile->xDest + (tile->xMax - tile->xMin) - xDest; + } + yDest = tile->yDest + (tile->yMax - tile->yMin); + clippedRedrawRect(NULL, 0, 0, + xDest, yDest, w, drawAreaHeight - yDest, + x, y, width, height, gFalse); + } else if ((tile->edges & pdfCoreTileBottomSpace) && + i+1 < pages->getLength()) { + if (tile->edges & pdfCoreTileLeftEdge) { + xDest = 0; + } else { + xDest = tile->xDest; + } + if (tile->edges & pdfCoreTileRightEdge) { + w = drawAreaWidth - xDest; + } else { + w = tile->xDest + (tile->xMax - tile->xMin) - xDest; + } + yDest = tile->yDest + (tile->yMax - tile->yMin); + clippedRedrawRect(NULL, 0, 0, + xDest, yDest, + w, ((PDFCorePage *)pages->get(i+1))->yDest - yDest, + x, y, width, height, gFalse); + } + if (tile->edges & pdfCoreTileLeftEdge) { + clippedRedrawRect(NULL, 0, 0, + 0, tile->yDest, + tile->xDest, tile->yMax - tile->yMin, + x, y, width, height, gFalse); + } + if (tile->edges & pdfCoreTileRightEdge) { + xDest = tile->xDest + (tile->xMax - tile->xMin); + clippedRedrawRect(NULL, 0, 0, + xDest, tile->yDest, + drawAreaWidth - xDest, tile->yMax - tile->yMin, + x, y, width, height, gFalse); + } + clippedRedrawRect(tile, 0, 0, tile->xDest, tile->yDest, + tile->bitmap->getWidth(), tile->bitmap->getHeight(), + x, y, width, height, needUpdate); + } + } +} + +PDFCoreTile *PDFCore::newTile(int xDestA, int yDestA) { + return new PDFCoreTile(xDestA, yDestA); +} + +void PDFCore::updateTileData(PDFCoreTile *tileA, int xSrc, int ySrc, + int width, int height, GBool composited) { +} + +void PDFCore::clippedRedrawRect(PDFCoreTile *tile, int xSrc, int ySrc, + int xDest, int yDest, int width, int height, + int xClip, int yClip, int wClip, int hClip, + GBool needUpdate, GBool composited) { + if (tile && needUpdate) { + updateTileData(tile, xSrc, ySrc, width, height, composited); + } + if (xDest < xClip) { + xSrc += xClip - xDest; + width -= xClip - xDest; + xDest = xClip; + } + if (xDest + width > xClip + wClip) { + width = xClip + wClip - xDest; + } + if (yDest < yClip) { + ySrc += yClip - yDest; + height -= yClip - yDest; + yDest = yClip; + } + if (yDest + height > yClip + hClip) { + height = yClip + hClip - yDest; + } + if (width > 0 && height > 0) { + redrawRect(tile, xSrc, ySrc, xDest, yDest, width, height, composited); + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PDFCore.h swftools-0.9.1/lib/pdf/xpdf/PDFCore.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/PDFCore.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PDFCore.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,321 @@ +//======================================================================== +// +// PDFCore.h +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PDFCORE_H +#define PDFCORE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "SplashTypes.h" +#include "CharTypes.h" + +class GString; +class GList; +class SplashBitmap; +class SplashPattern; +class BaseStream; +class PDFDoc; +class Links; +class LinkDest; +class LinkAction; +class TextPage; +class HighlightFile; +class CoreOutputDev; +class PDFCore; + +//------------------------------------------------------------------------ +// zoom factor +//------------------------------------------------------------------------ + +#define zoomPage -1 +#define zoomWidth -2 +#define defZoom 125 + +//------------------------------------------------------------------------ + + +//------------------------------------------------------------------------ + +// Number of pixels of matte color between pages in continuous mode. +#define continuousModePageSpacing 3 + +//------------------------------------------------------------------------ +// PDFCorePage +//------------------------------------------------------------------------ + +class PDFCorePage { +public: + + PDFCorePage(int pageA, int wA, int hA, int tileWA, int tileHA); + ~PDFCorePage(); + + int page; + GList *tiles; // cached tiles [PDFCoreTile] + int xDest, yDest; // position of upper-left corner + // in the drawing area + int w, h; // size of whole page bitmap + int tileW, tileH; // size of tiles + Links *links; // hyperlinks for this page + TextPage *text; // extracted text +}; + +//------------------------------------------------------------------------ +// PDFCoreTile +//------------------------------------------------------------------------ + +class PDFCoreTile { +public: + + PDFCoreTile(int xDestA, int yDestA); + virtual ~PDFCoreTile(); + + int xMin, yMin, xMax, yMax; + int xDest, yDest; + Guint edges; + SplashBitmap *bitmap; + double ctm[6]; // coordinate transform matrix: + // default user space -> device space + double ictm[6]; // inverse CTM +}; + +#define pdfCoreTileTopEdge 0x01 +#define pdfCoreTileBottomEdge 0x02 +#define pdfCoreTileLeftEdge 0x04 +#define pdfCoreTileRightEdge 0x08 +#define pdfCoreTileTopSpace 0x10 +#define pdfCoreTileBottomSpace 0x20 + +//------------------------------------------------------------------------ +// PDFHistory +//------------------------------------------------------------------------ + +struct PDFHistory { + GString *fileName; + int page; +}; + +#define pdfHistorySize 50 + + +//------------------------------------------------------------------------ +// PDFCore +//------------------------------------------------------------------------ + +class PDFCore { +public: + + PDFCore(SplashColorMode colorModeA, int bitmapRowPadA, + GBool reverseVideoA, SplashColorPtr paperColorA, + GBool incrementalUpdate); + virtual ~PDFCore(); + + //----- loadFile / displayPage / displayDest + + // Load a new file. Returns pdfOk or error code. + virtual int loadFile(GString *fileName, GString *ownerPassword = NULL, + GString *userPassword = NULL); + +#ifdef WIN32 + // Load a new file. Returns pdfOk or error code. + virtual int loadFile(wchar_t *fileName, int fileNameLen, + GString *ownerPassword = NULL, + GString *userPassword = NULL); +#endif + + // Load a new file, via a Stream instead of a file name. Returns + // pdfOk or error code. + virtual int loadFile(BaseStream *stream, GString *ownerPassword = NULL, + GString *userPassword = NULL); + + // Load an already-created PDFDoc object. + virtual void loadDoc(PDFDoc *docA); + + // Clear out the current document, if any. + virtual void clear(); + + // Same as clear(), but returns the PDFDoc object instead of + // deleting it. + virtual PDFDoc *takeDoc(GBool redraw); + + // Display (or redisplay) the specified page. If is + // set, the window is vertically scrolled to the top; otherwise, no + // scrolling is done. If is set, this page change is + // added to the history list. + virtual void displayPage(int topPageA, double zoomA, int rotateA, + GBool scrollToTop, GBool addToHist); + + // Display a link destination. + virtual void displayDest(LinkDest *dest, double zoomA, int rotateA, + GBool addToHist); + + // Update the display, given the specified parameters. + virtual void update(int topPageA, int scrollXA, int scrollYA, + double zoomA, int rotateA, GBool force, GBool addToHist); + + //----- page/position changes + + virtual GBool gotoNextPage(int inc, GBool top); + virtual GBool gotoPrevPage(int dec, GBool top, GBool bottom); + virtual GBool gotoNamedDestination(GString *dest); + virtual GBool goForward(); + virtual GBool goBackward(); + virtual void scrollLeft(int nCols = 16); + virtual void scrollRight(int nCols = 16); + virtual void scrollUp(int nLines = 16); + virtual void scrollUpPrevPage(int nLines = 16); + virtual void scrollDown(int nLines = 16); + virtual void scrollDownNextPage(int nLines = 16); + virtual void scrollPageUp(); + virtual void scrollPageDown(); + virtual void scrollTo(int x, int y); + virtual void scrollToLeftEdge(); + virtual void scrollToRightEdge(); + virtual void scrollToTopEdge(); + virtual void scrollToBottomEdge(); + virtual void scrollToTopLeft(); + virtual void scrollToBottomRight(); + virtual void zoomToRect(int pg, double ulx, double uly, + double lrx, double lry); + virtual void zoomCentered(double zoomA); + virtual void zoomToCurrentWidth(); + virtual void setContinuousMode(GBool cm); + + //----- selection + + // Current selected region. + void setSelection(int newSelectPage, + int newSelectULX, int newSelectULY, + int newSelectLRX, int newSelectLRY); + void moveSelection(int pg, int x, int y); + GBool getSelection(int *pg, double *ulx, double *uly, + double *lrx, double *lry); + + // Text extraction. + GString *extractText(int pg, double xMin, double yMin, + double xMax, double yMax); + + //----- find + + virtual GBool find(char *s, GBool caseSensitive, GBool next, GBool backward, + GBool onePageOnly); + virtual GBool findU(Unicode *u, int len, GBool caseSensitive, + GBool next, GBool backward, GBool onePageOnly); + + + //----- coordinate conversion + + // user space: per-pace, as defined by PDF file; unit = point + // device space: (0,0) is upper-left corner of a page; unit = pixel + // window space: (0,0) is upper-left corner of drawing area; unit = pixel + + GBool cvtWindowToUser(int xw, int yw, int *pg, double *xu, double *yu); + GBool cvtWindowToDev(int xw, int yw, int *pg, int *xd, int *yd); + void cvtUserToWindow(int pg, double xy, double yu, int *xw, int *yw); + void cvtUserToDev(int pg, double xu, double yu, int *xd, int *yd); + void cvtDevToWindow(int pg, int xd, int yd, int *xw, int *yw); + void cvtDevToUser(int pg, int xd, int yd, double *xu, double *yu); + + //----- misc access + + PDFDoc *getDoc() { return doc; } + int getPageNum() { return topPage; } + double getZoom() { return zoom; } + double getZoomDPI() { return dpi; } + int getRotate() { return rotate; } + GBool getContinuousMode() { return continuousMode; } + virtual void setReverseVideo(GBool reverseVideoA); + GBool canGoBack() { return historyBLen > 1; } + GBool canGoForward() { return historyFLen > 0; } + int getScrollX() { return scrollX; } + int getScrollY() { return scrollY; } + int getDrawAreaWidth() { return drawAreaWidth; } + int getDrawAreaHeight() { return drawAreaHeight; } + virtual void setBusyCursor(GBool busy) = 0; + LinkAction *findLink(int pg, double x, double y); + +protected: + + int loadFile2(PDFDoc *newDoc); + void addPage(int pg, int rot); + void needTile(PDFCorePage *page, int x, int y); + void xorRectangle(int pg, int x0, int y0, int x1, int y1, + SplashPattern *pattern, PDFCoreTile *oneTile = NULL); + int loadHighlightFile(HighlightFile *hf, SplashColorPtr color, + SplashColorPtr selectColor, GBool selectable); + PDFCorePage *findPage(int pg); + static void redrawCbk(void *data, int x0, int y0, int x1, int y1, + GBool composited); + void redrawWindow(int x, int y, int width, int height, + GBool needUpdate); + virtual PDFCoreTile *newTile(int xDestA, int yDestA); + virtual void updateTileData(PDFCoreTile *tileA, int xSrc, int ySrc, + int width, int height, GBool composited); + virtual void redrawRect(PDFCoreTile *tileA, int xSrc, int ySrc, + int xDest, int yDest, int width, int height, + GBool composited) = 0; + void clippedRedrawRect(PDFCoreTile *tile, int xSrc, int ySrc, + int xDest, int yDest, int width, int height, + int xClip, int yClip, int wClip, int hClip, + GBool needUpdate, GBool composited = gTrue); + virtual void updateScrollbars() = 0; + virtual GBool checkForNewFile() { return gFalse; } + + PDFDoc *doc; // current PDF file + GBool continuousMode; // false for single-page mode, true for + // continuous mode + int drawAreaWidth, // size of the PDF display area + drawAreaHeight; + double maxUnscaledPageW, // maximum unscaled page size + maxUnscaledPageH; + int maxPageW; // maximum page width (only used in + // continuous mode) + int totalDocH; // total document height (only used in + // continuous mode) + int *pageY; // top coordinates for each page (only used + // in continuous mode) + int topPage; // page at top of window + int scrollX, scrollY; // offset from top left corner of topPage + // to top left corner of window + double zoom; // current zoom level, in percent of 72 dpi + double dpi; // current zoom level, in DPI + int rotate; // current page rotation + + int selectPage; // page number of current selection + int selectULX, // coordinates of current selection, + selectULY, // in device space -- (ULX==LRX || ULY==LRY) + selectLRX, // means there is no selection + selectLRY; + GBool dragging; // set while selection is being dragged + GBool lastDragLeft; // last dragged selection edge was left/right + GBool lastDragTop; // last dragged selection edge was top/bottom + + PDFHistory // page history queue + history[pdfHistorySize]; + int historyCur; // currently displayed page + int historyBLen; // number of valid entries backward from + // current entry + int historyFLen; // number of valid entries forward from + // current entry + + + GList *pages; // cached pages [PDFCorePage] + PDFCoreTile *curTile; // tile currently being rasterized + PDFCorePage *curPage; // page to which curTile belongs + + SplashColor paperColor; + CoreOutputDev *out; + + friend class PDFCoreTile; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PDFDoc.cc swftools-0.9.1/lib/pdf/xpdf/PDFDoc.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/PDFDoc.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PDFDoc.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,402 @@ +//======================================================================== +// +// PDFDoc.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#ifdef WIN32 +# include +#endif +#include "GString.h" +#include "config.h" +#include "GlobalParams.h" +#include "Page.h" +#include "Catalog.h" +#include "Stream.h" +#include "XRef.h" +#include "Link.h" +#include "OutputDev.h" +#include "Error.h" +#include "ErrorCodes.h" +#include "Lexer.h" +#include "Parser.h" +#include "SecurityHandler.h" +#ifndef DISABLE_OUTLINE +#include "Outline.h" +#endif +#include "PDFDoc.h" + +//------------------------------------------------------------------------ + +#define headerSearchSize 1024 // read this many bytes at beginning of + // file to look for '%PDF' + +//------------------------------------------------------------------------ +// PDFDoc +//------------------------------------------------------------------------ + +PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, + GString *userPassword, void *guiDataA) { + Object obj; + GString *fileName1, *fileName2; + + ok = gFalse; + errCode = errNone; + + guiData = guiDataA; + + file = NULL; + str = NULL; + xref = NULL; + catalog = NULL; +#ifndef DISABLE_OUTLINE + outline = NULL; +#endif + + fileName = fileNameA; + fileName1 = fileName; + + + // try to open file + fileName2 = NULL; +#ifdef VMS + if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) { + error(-1, "Couldn't open file '%s'", fileName1->getCString()); + errCode = errOpenFile; + return; + } +#else + if (!(file = fopen(fileName1->getCString(), "rb"))) { + fileName2 = fileName->copy(); + fileName2->lowerCase(); + if (!(file = fopen(fileName2->getCString(), "rb"))) { + fileName2->upperCase(); + if (!(file = fopen(fileName2->getCString(), "rb"))) { + error(-1, "Couldn't open file '%s'", fileName->getCString()); + delete fileName2; + errCode = errOpenFile; + return; + } + } + delete fileName2; + } +#endif + + // create stream + obj.initNull(); + str = new FileStream(file, 0, gFalse, 0, &obj); + + ok = setup(ownerPassword, userPassword); +} + +#ifdef WIN32 +PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword, + GString *userPassword, void *guiDataA) { + OSVERSIONINFO version; + wchar_t fileName2[_MAX_PATH + 1]; + Object obj; + int i; + + ok = gFalse; + errCode = errNone; + + guiData = guiDataA; + + file = NULL; + str = NULL; + xref = NULL; + catalog = NULL; +#ifndef DISABLE_OUTLINE + outline = NULL; +#endif + + //~ file name should be stored in Unicode (?) + fileName = new GString(); + for (i = 0; i < fileNameLen; ++i) { + fileName->append((char)fileNameA[i]); + } + + // zero-terminate the file name string + for (i = 0; i < fileNameLen && i < _MAX_PATH; ++i) { + fileName2[i] = fileNameA[i]; + } + fileName2[i] = 0; + + // try to open file + // NB: _wfopen is only available in NT + version.dwOSVersionInfoSize = sizeof(version); + GetVersionEx(&version); + if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) { + file = _wfopen(fileName2, L"rb"); + } else { + file = fopen(fileName->getCString(), "rb"); + } + if (!file) { + error(-1, "Couldn't open file '%s'", fileName->getCString()); + errCode = errOpenFile; + return; + } + + // create stream + obj.initNull(); + str = new FileStream(file, 0, gFalse, 0, &obj); + + ok = setup(ownerPassword, userPassword); +} +#endif + +PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword, + GString *userPassword, void *guiDataA) { + ok = gFalse; + errCode = errNone; + guiData = guiDataA; + if (strA->getFileName()) { + fileName = strA->getFileName()->copy(); + } else { + fileName = NULL; + } + file = NULL; + str = strA; + xref = NULL; + catalog = NULL; +#ifndef DISABLE_OUTLINE + outline = NULL; +#endif + ok = setup(ownerPassword, userPassword); +} + +GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) { + str->reset(); + + // check header + checkHeader(); + + // read xref table + xref = new XRef(str); + if (!xref->isOk()) { + error(-1, "Couldn't read xref table"); + errCode = xref->getErrorCode(); + return gFalse; + } + + // check for encryption + if (!checkEncryption(ownerPassword, userPassword)) { + errCode = errEncrypted; + return gFalse; + } + + // read catalog + catalog = new Catalog(xref); + if (!catalog->isOk()) { + error(-1, "Couldn't read page catalog"); + errCode = errBadCatalog; + return gFalse; + } + +#ifndef DISABLE_OUTLINE + // read outline + outline = new Outline(catalog->getOutline(), xref); +#endif + + // done + return gTrue; +} + +PDFDoc::~PDFDoc() { +#ifndef DISABLE_OUTLINE + if (outline) { + delete outline; + } +#endif + if (catalog) { + delete catalog; + } + if (xref) { + delete xref; + } + if (str) { + delete str; + } + if (file) { + fclose(file); + } + if (fileName) { + delete fileName; + } +} + +// Check for a PDF header on this stream. Skip past some garbage +// if necessary. +void PDFDoc::checkHeader() { + char hdrBuf[headerSearchSize+1]; + char *p; + int i; + + pdfVersion = 0; + for (i = 0; i < headerSearchSize; ++i) { + hdrBuf[i] = str->getChar(); + } + hdrBuf[headerSearchSize] = '\0'; + for (i = 0; i < headerSearchSize - 5; ++i) { + if (!strncmp(&hdrBuf[i], "%PDF-", 5)) { + break; + } + } + if (i >= headerSearchSize - 5) { + error(-1, "May not be a PDF file (continuing anyway)"); + return; + } + str->moveStart(i); + if (!(p = strtok(&hdrBuf[i+5], " \t\n\r"))) { + error(-1, "May not be a PDF file (continuing anyway)"); + return; + } + pdfVersion = atof(p); + if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') || + pdfVersion > supportedPDFVersionNum + 0.0001) { + error(-1, "PDF version %s -- xpdf supports version %s" + " (continuing anyway)", p, supportedPDFVersionStr); + } +} + +GBool PDFDoc::checkEncryption(GString *ownerPassword, GString *userPassword) { + Object encrypt; + GBool encrypted; + SecurityHandler *secHdlr; + GBool ret; + + xref->getTrailerDict()->dictLookup("Encrypt", &encrypt); + if ((encrypted = encrypt.isDict())) { + if ((secHdlr = SecurityHandler::make(this, &encrypt))) { + if (secHdlr->checkEncryption(ownerPassword, userPassword)) { + // authorization succeeded + xref->setEncryption(secHdlr->getPermissionFlags(), + secHdlr->getOwnerPasswordOk(), + secHdlr->getFileKey(), + secHdlr->getFileKeyLength(), + secHdlr->getEncVersion(), + secHdlr->getEncAlgorithm()); + ret = gTrue; + } else { + // authorization failed + ret = gFalse; + } + delete secHdlr; + } else { + // couldn't find the matching security handler + ret = gFalse; + } + } else { + // document is not encrypted + ret = gTrue; + } + encrypt.free(); + return ret; +} + +void PDFDoc::displayPage(OutputDev *out, int page, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { + if (globalParams->getPrintCommands()) { + printf("***** page %d *****\n", page); + } + catalog->getPage(page)->display(out, hDPI, vDPI, + rotate, useMediaBox, crop, printing, catalog, + abortCheckCbk, abortCheckCbkData); +} + +void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { + int page; + + for (page = firstPage; page <= lastPage; ++page) { + displayPage(out, page, hDPI, vDPI, rotate, useMediaBox, crop, printing, + abortCheckCbk, abortCheckCbkData); + } +} + +void PDFDoc::displayPageSlice(OutputDev *out, int page, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { + catalog->getPage(page)->displaySlice(out, hDPI, vDPI, + rotate, useMediaBox, crop, + sliceX, sliceY, sliceW, sliceH, + printing, catalog, + abortCheckCbk, abortCheckCbkData); +} + +Links *PDFDoc::getLinks(int page) { + return catalog->getPage(page)->getLinks(catalog); +} + +void PDFDoc::processLinks(OutputDev *out, int page) { + catalog->getPage(page)->processLinks(out, catalog); +} + +GBool PDFDoc::isLinearized() { + Parser *parser; + Object obj1, obj2, obj3, obj4, obj5; + GBool lin; + + lin = gFalse; + obj1.initNull(); + parser = new Parser(xref, + new Lexer(xref, + str->makeSubStream(str->getStart(), gFalse, 0, &obj1)), + gTrue); + parser->getObj(&obj1); + parser->getObj(&obj2); + parser->getObj(&obj3); + parser->getObj(&obj4); + if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") && + obj4.isDict()) { + obj4.dictLookup("Linearized", &obj5); + if (obj5.isNum() && obj5.getNum() > 0) { + lin = gTrue; + } + obj5.free(); + } + obj4.free(); + obj3.free(); + obj2.free(); + obj1.free(); + delete parser; + return lin; +} + +GBool PDFDoc::saveAs(GString *name) { + FILE *f; + int c; + + if (!(f = fopen(name->getCString(), "wb"))) { + error(-1, "Couldn't open file '%s'", name->getCString()); + return gFalse; + } + str->reset(); + while ((c = str->getChar()) != EOF) { + fputc(c, f); + } + str->close(); + fclose(f); + return gTrue; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PDFDocEncoding.cc swftools-0.9.1/lib/pdf/xpdf/PDFDocEncoding.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/PDFDocEncoding.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PDFDocEncoding.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,44 @@ +//======================================================================== +// +// PDFDocEncoding.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include "PDFDocEncoding.h" + +Unicode pdfDocEncoding[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 00 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 10 + 0x02d8, 0x02c7, 0x02c6, 0x02d9, 0x02dd, 0x02db, 0x02da, 0x02dc, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, // 20 + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, // 30 + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, // 40 + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, // 50 + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, // 60 + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, // 70 + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000, + 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, // 80 + 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, + 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, // 90 + 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 0x0000, + 0x20ac, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, // a0 + 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x0000, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, // b0 + 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, // c0 + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, // d0 + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, // e0 + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, // f0 + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff +}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PDFDocEncoding.h swftools-0.9.1/lib/pdf/xpdf/PDFDocEncoding.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/PDFDocEncoding.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PDFDocEncoding.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,16 @@ +//======================================================================== +// +// PDFDocEncoding.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PDFDOCENCODING_H +#define PDFDOCENCODING_H + +#include "CharTypes.h" + +extern Unicode pdfDocEncoding[256]; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PDFDoc.h swftools-0.9.1/lib/pdf/xpdf/PDFDoc.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/PDFDoc.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PDFDoc.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,183 @@ +//======================================================================== +// +// PDFDoc.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PDFDOC_H +#define PDFDOC_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "XRef.h" +#include "Catalog.h" +#include "Page.h" + +class GString; +class BaseStream; +class OutputDev; +class Links; +class LinkAction; +class LinkDest; +class Outline; + +//------------------------------------------------------------------------ +// PDFDoc +//------------------------------------------------------------------------ + +class PDFDoc { +public: + + PDFDoc(GString *fileNameA, GString *ownerPassword = NULL, + GString *userPassword = NULL, void *guiDataA = NULL); +#ifdef WIN32 + PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword = NULL, + GString *userPassword = NULL, void *guiDataA = NULL); +#endif + PDFDoc(BaseStream *strA, GString *ownerPassword = NULL, + GString *userPassword = NULL, void *guiDataA = NULL); + ~PDFDoc(); + + // Was PDF document successfully opened? + GBool isOk() { return ok; } + + // Get the error code (if isOk() returns false). + int getErrorCode() { return errCode; } + + // Get file name. + GString *getFileName() { return fileName; } + + // Get the xref table. + XRef *getXRef() { return xref; } + + // Get catalog. + Catalog *getCatalog() { return catalog; } + + // Get base stream. + BaseStream *getBaseStream() { return str; } + + // Get page parameters. + double getPageMediaWidth(int page) + { return catalog->getPage(page)->getMediaWidth(); } + double getPageMediaHeight(int page) + { return catalog->getPage(page)->getMediaHeight(); } + double getPageCropWidth(int page) + { return catalog->getPage(page)->getCropWidth(); } + double getPageCropHeight(int page) + { return catalog->getPage(page)->getCropHeight(); } + int getPageRotate(int page) + { return catalog->getPage(page)->getRotate(); } + + // Get number of pages. + int getNumPages() { return catalog->getNumPages(); } + + // Return the contents of the metadata stream, or NULL if there is + // no metadata. + GString *readMetadata() { return catalog->readMetadata(); } + + // Return the structure tree root object. + Object *getStructTreeRoot() { return catalog->getStructTreeRoot(); } + + // Display a page. + void displayPage(OutputDev *out, int page, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + // Display a range of pages. + void displayPages(OutputDev *out, int firstPage, int lastPage, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + // Display part of a page. + void displayPageSlice(OutputDev *out, int page, + double hDPI, double vDPI, int rotate, + GBool useMediaBox, GBool crop, GBool printing, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + // Find a page, given its object ID. Returns page number, or 0 if + // not found. + int findPage(int num, int gen) { return catalog->findPage(num, gen); } + + // Returns the links for the current page, transferring ownership to + // the caller. + Links *getLinks(int page); + + // Find a named destination. Returns the link destination, or + // NULL if is not a destination. + LinkDest *findDest(GString *name) + { return catalog->findDest(name); } + + // Process the links for a page. + void processLinks(OutputDev *out, int page); + +#ifndef DISABLE_OUTLINE + // Return the outline object. + Outline *getOutline() { return outline; } +#endif + + // Is the file encrypted? + GBool isEncrypted() { return xref->isEncrypted(); } + + // Check various permissions. + GBool okToPrint(GBool ignoreOwnerPW = gFalse) + { return xref->okToPrint(ignoreOwnerPW); } + GBool okToChange(GBool ignoreOwnerPW = gFalse) + { return xref->okToChange(ignoreOwnerPW); } + GBool okToCopy(GBool ignoreOwnerPW = gFalse) + { return xref->okToCopy(ignoreOwnerPW); } + GBool okToAddNotes(GBool ignoreOwnerPW = gFalse) + { return xref->okToAddNotes(ignoreOwnerPW); } + + // Is this document linearized? + GBool isLinearized(); + + // Return the document's Info dictionary (if any). + Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); } + Object *getDocInfoNF(Object *obj) { return xref->getDocInfoNF(obj); } + + // Return the PDF version specified by the file. + double getPDFVersion() { return pdfVersion; } + + // Save this file with another name. + GBool saveAs(GString *name); + + // Return a pointer to the GUI (XPDFCore or WinPDFCore object). + void *getGUIData() { return guiData; } + + +private: + + GBool setup(GString *ownerPassword, GString *userPassword); + void checkHeader(); + GBool checkEncryption(GString *ownerPassword, GString *userPassword); + + GString *fileName; + FILE *file; + BaseStream *str; + void *guiData; + double pdfVersion; + XRef *xref; + Catalog *catalog; +#ifndef DISABLE_OUTLINE + Outline *outline; +#endif + + + GBool ok; + int errCode; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdffonts.1 swftools-0.9.1/lib/pdf/xpdf/pdffonts.1 --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdffonts.1 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdffonts.1 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,142 @@ +.\" Copyright 1999-2007 Glyph & Cog, LLC +.TH pdffonts 1 "27 February 2007" +.SH NAME +pdffonts \- Portable Document Format (PDF) font analyzer (version +3.02) +.SH SYNOPSIS +.B pdffonts +[options] +.RI [ PDF-file ] +.SH DESCRIPTION +.B Pdffonts +lists the fonts used in a Portable Document Format (PDF) file along +with various information for each font. +.PP +The following information is listed for each font: +.TP +.B name +the font name, exactly as given in the PDF file (potentially including +a subset prefix) +.TP +.B type +the font type -- see below for details +.TP +.B emb +"yes" if the font is embedded in the PDF file +.TP +.B sub +"yes" if the font is a subset +.TP +.B uni +"yes" if there is an explicit "ToUnicode" map in the PDF file (the +absence of a ToUnicode map doesn't necessarily mean that the text +can't be converted to Unicode) +.TP +.B object ID +the font dictionary object ID (number and generation) +.PP +PDF files can contain the following types of fonts: +.PP +.RS +Type 1 +.RE +.RS +Type 1C -- aka Compact Font Format (CFF) +.RE +.RS +Type 1C (OT) -- OpenType with 8-bit CFF data +.RE +.RS +Type 3 +.RE +.RS +TrueType +.RE +.RS +TrueType (OT) -- OpenType with 8-bit TrueType data +.RE +.RS +CID Type 0 -- 16-bit font with no specified type +.RE +.RS +CID Type 0C -- 16-bit PostScript CFF font +.RE +.RS +CID Type 0C (OT) -- OpenType with CID CFF data +.RE +.RS +CID TrueType -- 16-bit TrueType font +.RE +.RS +CID TrueType (OT) -- OpenType with CID TrueType data +.RE +.SH CONFIGURATION FILE +Pdffonts reads a configuration file at startup. It first tries to +find the user's private config file, ~/.xpdfrc. If that doesn't +exist, it looks for a system-wide config file, typically +/usr/local/etc/xpdfrc (but this location can be changed when pdffonts +is built). See the +.BR xpdfrc (5) +man page for details. +.SH OPTIONS +Many of the following options can be set with configuration file +commands. These are listed in square brackets with the description of +the corresponding command line option. +.TP +.BI \-f " number" +Specifies the first page to analyze. +.TP +.BI \-l " number" +Specifies the last page to analyze. +.TP +.BI \-opw " password" +Specify the owner password for the PDF file. Providing this will +bypass all security restrictions. +.TP +.BI \-upw " password" +Specify the user password for the PDF file. +.TP +.BI \-cfg " config-file" +Read +.I config-file +in place of ~/.xpdfrc or the system-wide config file. +.TP +.B \-v +Print copyright and version information. +.TP +.B \-h +Print usage information. +.RB ( \-help +and +.B \-\-help +are equivalent.) +.SH EXIT CODES +The Xpdf tools use the following exit codes: +.TP +0 +No error. +.TP +1 +Error opening a PDF file. +.TP +2 +Error opening an output file. +.TP +3 +Error related to PDF permissions. +.TP +99 +Other error. +.SH AUTHOR +The pdffonts software and documentation are copyright 1996-2007 Glyph +& Cog, LLC. +.SH "SEE ALSO" +.BR xpdf (1), +.BR pdftops (1), +.BR pdftotext (1), +.BR pdfinfo (1), +.BR pdftoppm (1), +.BR pdfimages (1), +.BR xpdfrc (5) +.br +.B http://www.foolabs.com/xpdf/ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdffonts.cat swftools-0.9.1/lib/pdf/xpdf/pdffonts.cat --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdffonts.cat 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdffonts.cat 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,112 @@ +pdffonts(1) pdffonts(1) + + + +NAME + pdffonts - Portable Document Format (PDF) font analyzer + (version 3.02) + +SYNOPSIS + pdffonts [options] [PDF-file] + +DESCRIPTION + Pdffonts lists the fonts used in a Portable Document For- + mat (PDF) file along with various information for each + font. + + The following information is listed for each font: + + name the font name, exactly as given in the PDF file + (potentially including a subset prefix) + + type the font type -- see below for details + + emb "yes" if the font is embedded in the PDF file + + sub "yes" if the font is a subset + + uni "yes" if there is an explicit "ToUnicode" map in + the PDF file (the absence of a ToUnicode map + doesn't necessarily mean that the text can't be + converted to Unicode) + + object ID + the font dictionary object ID (number and genera- + tion) + + PDF files can contain the following types of fonts: + + Type 1 + Type 1C -- aka Compact Font Format (CFF) + Type 1C (OT) -- OpenType with 8-bit CFF data + Type 3 + TrueType + TrueType (OT) -- OpenType with 8-bit TrueType data + CID Type 0 -- 16-bit font with no specified type + CID Type 0C -- 16-bit PostScript CFF font + CID Type 0C (OT) -- OpenType with CID CFF data + CID TrueType -- 16-bit TrueType font + CID TrueType (OT) -- OpenType with CID TrueType + data + +CONFIGURATION FILE + Pdffonts reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdffonts is built). See the xpdfrc(5) + man page for details. + +OPTIONS + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to analyze. + + -l number + Specifies the last page to analyze. + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the sys- + tem-wide config file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + +EXIT CODES + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + +AUTHOR + The pdffonts software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + +SEE ALSO + xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), + pdftoppm(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + + + 27 February 2007 pdffonts(1) diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdffonts.cc swftools-0.9.1/lib/pdf/xpdf/pdffonts.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdffonts.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdffonts.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,298 @@ +//======================================================================== +// +// pdffonts.cc +// +// Copyright 2001-2007 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#include +#include +#include "parseargs.h" +#include "GString.h" +#include "gmem.h" +#include "GlobalParams.h" +#include "Error.h" +#include "Object.h" +#include "Dict.h" +#include "GfxFont.h" +#include "Annot.h" +#include "PDFDoc.h" +#include "config.h" + +// NB: this must match the definition of GfxFontType in GfxFont.h. +static char *fontTypeNames[] = { + "unknown", + "Type 1", + "Type 1C", + "Type 1C (OT)", + "Type 3", + "TrueType", + "TrueType (OT)", + "CID Type 0", + "CID Type 0C", + "CID Type 0C (OT)", + "CID TrueType", + "CID TrueType (OT)" +}; + +static void scanFonts(Dict *resDict, PDFDoc *doc); +static void scanFont(GfxFont *font, PDFDoc *doc); + +static int firstPage = 1; +static int lastPage = 0; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to examine"}, + {"-l", argInt, &lastPage, 0, + "last page to examine"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, + {"-h", argFlag, &printHelp, 0, + "print usage information"}, + {"-help", argFlag, &printHelp, 0, + "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +static Ref *fonts; +static int fontsLen; +static int fontsSize; + +int main(int argc, char *argv[]) { + PDFDoc *doc; + GString *fileName; + GString *ownerPW, *userPW; + GBool ok; + Page *page; + Dict *resDict; + Annots *annots; + Object obj1, obj2; + int pg, i; + int exitCode; + + exitCode = 99; + + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc != 2 || printVersion || printHelp) { + fprintf(stderr, "pdffonts version %s\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdffonts", "", argDesc); + } + goto err0; + } + fileName = new GString(argv[1]); + + // read config file + globalParams = new GlobalParams(cfgFileName); + + // open PDF file + if (ownerPassword[0] != '\001') { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0] != '\001') { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // get page range + if (firstPage < 1) { + firstPage = 1; + } + if (lastPage < 1 || lastPage > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + + // scan the fonts + printf("name type emb sub uni object ID\n"); + printf("------------------------------------ ----------------- --- --- --- ---------\n"); + fonts = NULL; + fontsLen = fontsSize = 0; + for (pg = firstPage; pg <= lastPage; ++pg) { + page = doc->getCatalog()->getPage(pg); + if ((resDict = page->getResourceDict())) { + scanFonts(resDict, doc); + } + annots = new Annots(doc->getXRef(), doc->getCatalog(), + page->getAnnots(&obj1)); + obj1.free(); + for (i = 0; i < annots->getNumAnnots(); ++i) { + if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) { + obj1.streamGetDict()->lookup("Resources", &obj2); + if (obj2.isDict()) { + scanFonts(obj2.getDict(), doc); + } + obj2.free(); + } + obj1.free(); + } + delete annots; + } + + exitCode = 0; + + // clean up + gfree(fonts); + err1: + delete doc; + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} + +static void scanFonts(Dict *resDict, PDFDoc *doc) { + Object obj1, obj2, xObjDict, xObj, resObj; + Ref r; + GfxFontDict *gfxFontDict; + GfxFont *font; + int i; + + // scan the fonts in this resource dictionary + gfxFontDict = NULL; + resDict->lookupNF("Font", &obj1); + if (obj1.isRef()) { + obj1.fetch(doc->getXRef(), &obj2); + if (obj2.isDict()) { + r = obj1.getRef(); + gfxFontDict = new GfxFontDict(doc->getXRef(), &r, obj2.getDict()); + } + obj2.free(); + } else if (obj1.isDict()) { + gfxFontDict = new GfxFontDict(doc->getXRef(), NULL, obj1.getDict()); + } + if (gfxFontDict) { + for (i = 0; i < gfxFontDict->getNumFonts(); ++i) { + if ((font = gfxFontDict->getFont(i))) { + scanFont(font, doc); + } + } + delete gfxFontDict; + } + obj1.free(); + + // recursively scan any resource dictionaries in objects in this + // resource dictionary + resDict->lookup("XObject", &xObjDict); + if (xObjDict.isDict()) { + for (i = 0; i < xObjDict.dictGetLength(); ++i) { + xObjDict.dictGetVal(i, &xObj); + if (xObj.isStream()) { + xObj.streamGetDict()->lookup("Resources", &resObj); + if (resObj.isDict()) { + scanFonts(resObj.getDict(), doc); + } + resObj.free(); + } + xObj.free(); + } + } + xObjDict.free(); +} + +static void scanFont(GfxFont *font, PDFDoc *doc) { + Ref fontRef, embRef; + Object fontObj, toUnicodeObj; + GString *name; + GBool emb, subset, hasToUnicode; + int i; + + fontRef = *font->getID(); + + // check for an already-seen font + for (i = 0; i < fontsLen; ++i) { + if (fontRef.num == fonts[i].num && fontRef.gen == fonts[i].gen) { + return; + } + } + + // font name + name = font->getOrigName(); + + // check for an embedded font + if (font->getType() == fontType3) { + emb = gTrue; + } else { + emb = font->getEmbeddedFontID(&embRef); + } + + // look for a ToUnicode map + hasToUnicode = gFalse; + if (doc->getXRef()->fetch(fontRef.num, fontRef.gen, &fontObj)->isDict()) { + hasToUnicode = fontObj.dictLookup("ToUnicode", &toUnicodeObj)->isStream(); + toUnicodeObj.free(); + } + fontObj.free(); + + // check for a font subset name: capital letters followed by a '+' + // sign + subset = gFalse; + if (name) { + for (i = 0; i < name->getLength(); ++i) { + if (name->getChar(i) < 'A' || name->getChar(i) > 'Z') { + break; + } + } + subset = i > 0 && i < name->getLength() && name->getChar(i) == '+'; + } + + // print the font info + printf("%-36s %-17s %-3s %-3s %-3s", + name ? name->getCString() : "[none]", + fontTypeNames[font->getType()], + emb ? "yes" : "no", + subset ? "yes" : "no", + hasToUnicode ? "yes" : "no"); + if (fontRef.gen >= 100000) { + printf(" [none]\n"); + } else { + printf(" %6d %2d\n", fontRef.num, fontRef.gen); + } + + // add this font to the list + if (fontsLen == fontsSize) { + fontsSize += 32; + fonts = (Ref *)greallocn(fonts, fontsSize, sizeof(Ref)); + } + fonts[fontsLen++] = *font->getID(); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdffonts.hlp swftools-0.9.1/lib/pdf/xpdf/pdffonts.hlp --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdffonts.hlp 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdffonts.hlp 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,122 @@ +! Generated automatically by mantohlp +1 pdffonts + + pdffonts - Portable Document Format (PDF) font analyzer + (version + + pdffonts [options] [PDF-file] + + Pdffonts lists the fonts used in a Portable Document For- + mat (PDF) file along with various information for each + font. + + The following information is listed for each font: + + name the font name, exactly as given in the PDF file + (potentially including a subset prefix) + + type the font type -- see below for details + + emb "yes" if the font is embedded in the PDF file + + sub "yes" if the font is a subset + + uni "yes" if there is an explicit "ToUnicode" map in + the PDF file (the absence of a ToUnicode map + doesn't necessarily mean that the text can't be + converted to Unicode) + + object ID + the font dictionary object ID (number and genera- + tion) + + PDF files can contain the following types of fonts: + + Type 1 + Type 1C -- aka Compact Font Format (CFF) + Type 1C (OT) -- OpenType with 8-bit CFF data + Type 3 + TrueType + TrueType (OT) -- OpenType with 8-bit TrueType data + CID Type 0 -- 16-bit font with no specified type + CID Type 0C -- 16-bit PostScript CFF font + CID Type 0C (OT) -- OpenType with CID CFF data + CID TrueType -- 16-bit TrueType font + CID TrueType (OT) -- OpenType with CID TrueType + data + + () + +2 ONFIGURATION_FIL + + Pdffonts reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdffonts is built). See the xpdfrc(5) + man page for details. + + () + +2 OPTIONS + + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to analyze. + + -l number + Specifies the last page to analyze. + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the sys- + tem-wide config file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + + () + +2 XIT_CODE + + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + + () + +2 AUTHOR + + The pdffonts software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + + () + +2 SEE_ALSO + + xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), + pdftoppm(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + () + diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdfimages.1 swftools-0.9.1/lib/pdf/xpdf/pdfimages.1 --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdfimages.1 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdfimages.1 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,102 @@ +.\" Copyright 1998-2007 Glyph & Cog, LLC +.TH pdfimages 1 "27 February 2007" +.SH NAME +pdfimages \- Portable Document Format (PDF) image extractor +(version 3.02) +.SH SYNOPSIS +.B pdfimages +[options] +.I PDF-file image-root +.SH DESCRIPTION +.B Pdfimages +saves images from a Portable Document Format (PDF) file as Portable +Pixmap (PPM), Portable Bitmap (PBM), or JPEG files. +.PP +Pdfimages reads the PDF file, scans one or more pages, +.IR PDF-file , +and writes one PPM, PBM, or JPEG file for each image, +.IR image-root - nnn . xxx , +where +.I nnn +is the image number and +.I xxx +is the image type (.ppm, .pbm, .jpg). +.PP +NB: pdfimages extracts the raw image data from the PDF file, without +performing any additional transforms. Any rotation, clipping, +color inversion, etc. done by the PDF content stream is ignored. +.SH CONFIGURATION FILE +Pdfimages reads a configuration file at startup. It first tries to +find the user's private config file, ~/.xpdfrc. If that doesn't +exist, it looks for a system-wide config file, typically +/usr/local/etc/xpdfrc (but this location can be changed when pdfimages +is built). See the +.BR xpdfrc (5) +man page for details. +.SH OPTIONS +Many of the following options can be set with configuration file +commands. These are listed in square brackets with the description of +the corresponding command line option. +.TP +.BI \-f " number" +Specifies the first page to scan. +.TP +.BI \-l " number" +Specifies the last page to scan. +.TP +.B \-j +Normally, all images are written as PBM (for monochrome images) or PPM +(for non-monochrome images) files. With this option, images in DCT +format are saved as JPEG files. All non-DCT images are saved in +PBM/PPM format as usual. +.TP +.BI \-opw " password" +Specify the owner password for the PDF file. Providing this will +bypass all security restrictions. +.TP +.BI \-upw " password" +Specify the user password for the PDF file. +.TP +.B \-q +Don't print any messages or errors. +.RB "[config file: " errQuiet ] +.TP +.B \-v +Print copyright and version information. +.TP +.B \-h +Print usage information. +.RB ( \-help +and +.B \-\-help +are equivalent.) +.SH EXIT CODES +The Xpdf tools use the following exit codes: +.TP +0 +No error. +.TP +1 +Error opening a PDF file. +.TP +2 +Error opening an output file. +.TP +3 +Error related to PDF permissions. +.TP +99 +Other error. +.SH AUTHOR +The pdfimages software and documentation are copyright 1998-2007 Glyph +& Cog, LLC. +.SH "SEE ALSO" +.BR xpdf (1), +.BR pdftops (1), +.BR pdftotext (1), +.BR pdfinfo (1), +.BR pdffonts (1), +.BR pdftoppm (1), +.BR xpdfrc (5) +.br +.B http://www.foolabs.com/xpdf/ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdfimages.cat swftools-0.9.1/lib/pdf/xpdf/pdfimages.cat --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdfimages.cat 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdfimages.cat 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,92 @@ +pdfimages(1) pdfimages(1) + + + +NAME + pdfimages - Portable Document Format (PDF) image extractor + (version 3.02) + +SYNOPSIS + pdfimages [options] PDF-file image-root + +DESCRIPTION + Pdfimages saves images from a Portable Document Format + (PDF) file as Portable Pixmap (PPM), Portable Bitmap + (PBM), or JPEG files. + + Pdfimages reads the PDF file, scans one or more pages, + PDF-file, and writes one PPM, PBM, or JPEG file for each + image, image-root-nnn.xxx, where nnn is the image number + and xxx is the image type (.ppm, .pbm, .jpg). + + NB: pdfimages extracts the raw image data from the PDF + file, without performing any additional transforms. Any + rotation, clipping, color inversion, etc. done by the PDF + content stream is ignored. + +CONFIGURATION FILE + Pdfimages reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdfimages is built). See the + xpdfrc(5) man page for details. + +OPTIONS + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to scan. + + -l number + Specifies the last page to scan. + + -j Normally, all images are written as PBM (for + monochrome images) or PPM (for non-monochrome + images) files. With this option, images in DCT + format are saved as JPEG files. All non-DCT images + are saved in PBM/PPM format as usual. + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -q Don't print any messages or errors. [config file: + errQuiet] + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + +EXIT CODES + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + +AUTHOR + The pdfimages software and documentation are copyright + 1998-2007 Glyph & Cog, LLC. + +SEE ALSO + xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdf- + fonts(1), pdftoppm(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + + + 27 February 2007 pdfimages(1) diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdfimages.cc swftools-0.9.1/lib/pdf/xpdf/pdfimages.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdfimages.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdfimages.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,155 @@ +//======================================================================== +// +// pdfimages.cc +// +// Copyright 1998-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#include +#include "parseargs.h" +#include "GString.h" +#include "gmem.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Stream.h" +#include "Array.h" +#include "Dict.h" +#include "XRef.h" +#include "Catalog.h" +#include "Page.h" +#include "PDFDoc.h" +#include "ImageOutputDev.h" +#include "Error.h" +#include "config.h" + +static int firstPage = 1; +static int lastPage = 0; +static GBool dumpJPEG = gFalse; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to convert"}, + {"-l", argInt, &lastPage, 0, + "last page to convert"}, + {"-j", argFlag, &dumpJPEG, 0, + "write JPEG images as JPEG files"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, + {"-h", argFlag, &printHelp, 0, + "print usage information"}, + {"-help", argFlag, &printHelp, 0, + "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +int main(int argc, char *argv[]) { + PDFDoc *doc; + GString *fileName; + char *imgRoot; + GString *ownerPW, *userPW; + ImageOutputDev *imgOut; + GBool ok; + int exitCode; + + exitCode = 99; + + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc != 3 || printVersion || printHelp) { + fprintf(stderr, "pdfimages version %s\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdfimages", " ", argDesc); + } + goto err0; + } + fileName = new GString(argv[1]); + imgRoot = argv[2]; + + // read config file + globalParams = new GlobalParams(cfgFileName); + if (quiet) { + globalParams->setErrQuiet(quiet); + } + + // open PDF file + if (ownerPassword[0] != '\001') { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0] != '\001') { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // check for copy permission + if (!doc->okToCopy()) { + error(-1, "Copying of images from this document is not allowed."); + exitCode = 3; + goto err1; + } + + // get page range + if (firstPage < 1) + firstPage = 1; + if (lastPage < 1 || lastPage > doc->getNumPages()) + lastPage = doc->getNumPages(); + + // write image files + imgOut = new ImageOutputDev(imgRoot, dumpJPEG); + if (imgOut->isOk()) { + doc->displayPages(imgOut, firstPage, lastPage, 72, 72, 0, + gFalse, gTrue, gFalse); + } + delete imgOut; + + exitCode = 0; + + // clean up + err1: + delete doc; + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdfimages.hlp swftools-0.9.1/lib/pdf/xpdf/pdfimages.hlp --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdfimages.hlp 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdfimages.hlp 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,101 @@ +! Generated automatically by mantohlp +1 pdfimages + + pdfimages - Portable Document Format (PDF) image extractor + + pdfimages [options] PDF-file image-root + + Pdfimages saves images from a Portable Document Format + (PDF) file as Portable Pixmap (PPM), Portable Bitmap + (PBM), or JPEG files. + + Pdfimages reads the PDF file, scans one or more pages, + PDF-file, and writes one PPM, PBM, or JPEG file for each + image, image-root-nnn.xxx, where nnn is the image number + and xxx is the image type (.ppm, .pbm, .jpg). + + NB: pdfimages extracts the raw image data from the PDF + file, without performing any additional transforms. Any + rotation, clipping, color inversion, etc. done by the PDF + content stream is ignored. + + () + +2 ONFIGURATION_FIL + + Pdfimages reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdfimages is built). See the + xpdfrc(5) man page for details. + + () + +2 OPTIONS + + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to scan. + + -l number + Specifies the last page to scan. + + -j Normally, all images are written as PBM (for + monochrome images) or PPM (for non-monochrome + images) files. With this option, images in DCT + format are saved as JPEG files. All non-DCT images + are saved in PBM/PPM format as usual. + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -q Don't print any messages or errors. [config file: + errQuiet] + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + + () + +2 XIT_CODE + + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + + () + +2 AUTHOR + + The pdfimages software and documentation are copyright + 1998-2007 Glyph & Cog, LLC. + + () + +2 SEE_ALSO + + xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdf- + fonts(1), pdftoppm(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + () + diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdfinfo.1 swftools-0.9.1/lib/pdf/xpdf/pdfinfo.1 --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdfinfo.1 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdfinfo.1 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,158 @@ +.\" Copyright 1999-2007 Glyph & Cog, LLC +.TH pdfinfo 1 "27 February 2007" +.SH NAME +pdfinfo \- Portable Document Format (PDF) document information +extractor (version 3.02) +.SH SYNOPSIS +.B pdfinfo +[options] +.RI [ PDF-file ] +.SH DESCRIPTION +.B Pdfinfo +prints the contents of the \'Info' dictionary (plus some other useful +information) from a Portable Document Format (PDF) file. +.PP +The \'Info' dictionary contains the following values: +.PP +.RS +title +.RE +.RS +subject +.RE +.RS +keywords +.RE +.RS +author +.RE +.RS +creator +.RE +.RS +producer +.RE +.RS +creation date +.RE +.RS +modification date +.RE +.PP +In addition, the following information is printed: +.PP +.RS +tagged (yes/no) +.RE +.RS +page count +.RE +.RS +encrypted flag (yes/no) +.RE +.RS +print and copy permissions (if encrypted) +.RE +.RS +page size +.RE +.RS +file size +.RE +.RS +linearized (yes/no) +.RE +.RS +PDF version +.RE +.RS +metadata (only if requested) +.RE +.SH CONFIGURATION FILE +Pdfinfo reads a configuration file at startup. It first tries to find +the user's private config file, ~/.xpdfrc. If that doesn't exist, it +looks for a system-wide config file, typically /usr/local/etc/xpdfrc +(but this location can be changed when pdfinfo is built). See the +.BR xpdfrc (5) +man page for details. +.SH OPTIONS +Many of the following options can be set with configuration file +commands. These are listed in square brackets with the description of +the corresponding command line option. +.TP +.BI \-f " number" +Specifies the first page to examine. If multiple pages are requested +using the "-f" and "-l" options, the size of each requested page (and, +optionally, the bounding boxes for each requested page) are printed. +Otherwise, only page one is examined. +.TP +.BI \-l " number" +Specifies the last page to examine. +.TP +.B \-box +Prints the page box bounding boxes: MediaBox, CropBox, BleedBox, +TrimBox, and ArtBox. +.TP +.B \-meta +Prints document-level metadata. (This is the "Metadata" stream from +the PDF file's Catalog object.) +.TP +.BI \-enc " encoding-name" +Sets the encoding to use for text output. The +.I encoding\-name +must be defined with the unicodeMap command (see +.BR xpdfrc (5)). +This defaults to "Latin1" (which is a built-in encoding). +.RB "[config file: " textEncoding ] +.TP +.BI \-opw " password" +Specify the owner password for the PDF file. Providing this will +bypass all security restrictions. +.TP +.BI \-upw " password" +Specify the user password for the PDF file. +.TP +.BI \-cfg " config-file" +Read +.I config-file +in place of ~/.xpdfrc or the system-wide config file. +.TP +.B \-v +Print copyright and version information. +.TP +.B \-h +Print usage information. +.RB ( \-help +and +.B \-\-help +are equivalent.) +.SH EXIT CODES +The Xpdf tools use the following exit codes: +.TP +0 +No error. +.TP +1 +Error opening a PDF file. +.TP +2 +Error opening an output file. +.TP +3 +Error related to PDF permissions. +.TP +99 +Other error. +.SH AUTHOR +The pdfinfo software and documentation are copyright 1996-2007 Glyph & +Cog, LLC. +.SH "SEE ALSO" +.BR xpdf (1), +.BR pdftops (1), +.BR pdftotext (1), +.BR pdffonts (1), +.BR pdftoppm (1), +.BR pdfimages (1), +.BR xpdfrc (5) +.br +.B http://www.foolabs.com/xpdf/ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdfinfo.cat swftools-0.9.1/lib/pdf/xpdf/pdfinfo.cat --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdfinfo.cat 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdfinfo.cat 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,119 @@ +pdfinfo(1) pdfinfo(1) + + + +NAME + pdfinfo - Portable Document Format (PDF) document informa- + tion extractor (version 3.02) + +SYNOPSIS + pdfinfo [options] [PDF-file] + +DESCRIPTION + Pdfinfo prints the contents of the 'Info' dictionary (plus + some other useful information) from a Portable Document + Format (PDF) file. + + The 'Info' dictionary contains the following values: + + title + subject + keywords + author + creator + producer + creation date + modification date + + In addition, the following information is printed: + + tagged (yes/no) + page count + encrypted flag (yes/no) + print and copy permissions (if encrypted) + page size + file size + linearized (yes/no) + PDF version + metadata (only if requested) + +CONFIGURATION FILE + Pdfinfo reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdfinfo is built). See the xpdfrc(5) + man page for details. + +OPTIONS + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to examine. If multiple + pages are requested using the "-f" and "-l" + options, the size of each requested page (and, + optionally, the bounding boxes for each requested + page) are printed. Otherwise, only page one is + examined. + + -l number + Specifies the last page to examine. + + -box Prints the page box bounding boxes: MediaBox, Crop- + Box, BleedBox, TrimBox, and ArtBox. + + -meta Prints document-level metadata. (This is the + "Metadata" stream from the PDF file's Catalog + object.) + + -enc encoding-name + Sets the encoding to use for text output. The + encoding-name must be defined with the unicodeMap + command (see xpdfrc(5)). This defaults to "Latin1" + (which is a built-in encoding). [config file: tex- + tEncoding] + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the sys- + tem-wide config file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + +EXIT CODES + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + +AUTHOR + The pdfinfo software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + +SEE ALSO + xpdf(1), pdftops(1), pdftotext(1), pdffonts(1), + pdftoppm(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + + + 27 February 2007 pdfinfo(1) diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdfinfo.cc swftools-0.9.1/lib/pdf/xpdf/pdfinfo.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdfinfo.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdfinfo.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,397 @@ +//======================================================================== +// +// pdfinfo.cc +// +// Copyright 1998-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "parseargs.h" +#include "GString.h" +#include "gmem.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Stream.h" +#include "Array.h" +#include "Dict.h" +#include "XRef.h" +#include "Catalog.h" +#include "Page.h" +#include "PDFDoc.h" +#include "CharTypes.h" +#include "UnicodeMap.h" +#include "PDFDocEncoding.h" +#include "Error.h" +#include "config.h" + +static void printInfoString(Dict *infoDict, char *key, char *text, + UnicodeMap *uMap); +static void printInfoDate(Dict *infoDict, char *key, char *text); +static void printBox(char *text, PDFRectangle *box); + +static int firstPage = 1; +static int lastPage = 0; +static GBool printBoxes = gFalse; +static GBool printMetadata = gFalse; +static char textEncName[128] = ""; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to convert"}, + {"-l", argInt, &lastPage, 0, + "last page to convert"}, + {"-box", argFlag, &printBoxes, 0, + "print the page bounding boxes"}, + {"-meta", argFlag, &printMetadata, 0, + "print the document metadata (XML)"}, + {"-enc", argString, textEncName, sizeof(textEncName), + "output text encoding name"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, + {"-h", argFlag, &printHelp, 0, + "print usage information"}, + {"-help", argFlag, &printHelp, 0, + "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +int main(int argc, char *argv[]) { + PDFDoc *doc; + GString *fileName; + GString *ownerPW, *userPW; + UnicodeMap *uMap; + Page *page; + Object info; + char buf[256]; + double w, h, wISO, hISO; + FILE *f; + GString *metadata; + GBool ok; + int exitCode; + int pg, i; + GBool multiPage; + + exitCode = 99; + +#ifdef HAVE_LRAND48 + srand48(time(0)*getpid()); +#endif +#ifdef HAVE_RAND + srand(time(0)*getpid()); +#endif + + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc != 2 || printVersion || printHelp) { + fprintf(stderr, "pdfinfo version %s\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdfinfo", "", argDesc); + } + goto err0; + } + fileName = new GString(argv[1]); + + // read config file + globalParams = new GlobalParams(cfgFileName); + if (textEncName[0]) { + globalParams->setTextEncoding(textEncName); + } + + // get mapping to output encoding + if (!(uMap = globalParams->getTextEncoding())) { + error(-1, "Couldn't get text encoding"); + delete fileName; + goto err1; + } + + // open PDF file + if (ownerPassword[0] != '\001') { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0] != '\001') { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err2; + } + + // get page range + if (firstPage < 1) { + firstPage = 1; + } + if (lastPage == 0) { + multiPage = gFalse; + lastPage = 1; + } else { + multiPage = gTrue; + } + if (lastPage < 1 || lastPage > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + + // print doc info + doc->getDocInfo(&info); + if (info.isDict()) { + printInfoString(info.getDict(), "Title", "Title: ", uMap); + printInfoString(info.getDict(), "Subject", "Subject: ", uMap); + printInfoString(info.getDict(), "Keywords", "Keywords: ", uMap); + printInfoString(info.getDict(), "Author", "Author: ", uMap); + printInfoString(info.getDict(), "Creator", "Creator: ", uMap); + printInfoString(info.getDict(), "Producer", "Producer: ", uMap); + printInfoDate(info.getDict(), "CreationDate", "CreationDate: "); + printInfoDate(info.getDict(), "ModDate", "ModDate: "); + } + info.free(); + + // print tagging info + printf("Tagged: %s\n", + doc->getStructTreeRoot()->isDict() ? "yes" : "no"); + + // print page count + printf("Pages: %d\n", doc->getNumPages()); + + // print encryption info + printf("Encrypted: "); + if (doc->isEncrypted()) { + printf("yes (print:%s copy:%s change:%s addNotes:%s)\n", + doc->okToPrint(gTrue) ? "yes" : "no", + doc->okToCopy(gTrue) ? "yes" : "no", + doc->okToChange(gTrue) ? "yes" : "no", + doc->okToAddNotes(gTrue) ? "yes" : "no"); + } else { + printf("no\n"); + } + + // print page size + for (pg = firstPage; pg <= lastPage; ++pg) { + w = doc->getPageCropWidth(pg); + h = doc->getPageCropHeight(pg); + if (multiPage) { + printf("Page %4d size: %g x %g pts", pg, w, h); + } else { + printf("Page size: %g x %g pts", w, h); + } + if ((fabs(w - 612) < 0.1 && fabs(h - 792) < 0.1) || + (fabs(w - 792) < 0.1 && fabs(h - 612) < 0.1)) { + printf(" (letter)"); + } else { + hISO = sqrt(sqrt(2.0)) * 7200 / 2.54; + wISO = hISO / sqrt(2.0); + for (i = 0; i <= 6; ++i) { + if ((fabs(w - wISO) < 1 && fabs(h - hISO) < 1) || + (fabs(w - hISO) < 1 && fabs(h - wISO) < 1)) { + printf(" (A%d)", i); + break; + } + hISO = wISO; + wISO /= sqrt(2.0); + } + } + printf("\n"); + } + + // print the boxes + if (printBoxes) { + if (multiPage) { + for (pg = firstPage; pg <= lastPage; ++pg) { + page = doc->getCatalog()->getPage(pg); + sprintf(buf, "Page %4d MediaBox: ", pg); + printBox(buf, page->getMediaBox()); + sprintf(buf, "Page %4d CropBox: ", pg); + printBox(buf, page->getCropBox()); + sprintf(buf, "Page %4d BleedBox: ", pg); + printBox(buf, page->getBleedBox()); + sprintf(buf, "Page %4d TrimBox: ", pg); + printBox(buf, page->getTrimBox()); + sprintf(buf, "Page %4d ArtBox: ", pg); + printBox(buf, page->getArtBox()); + } + } else { + page = doc->getCatalog()->getPage(firstPage); + printBox("MediaBox: ", page->getMediaBox()); + printBox("CropBox: ", page->getCropBox()); + printBox("BleedBox: ", page->getBleedBox()); + printBox("TrimBox: ", page->getTrimBox()); + printBox("ArtBox: ", page->getArtBox()); + } + } + + // print file size +#ifdef VMS + f = fopen(fileName->getCString(), "rb", "ctx=stm"); +#else + f = fopen(fileName->getCString(), "rb"); +#endif + if (f) { +#if HAVE_FSEEKO + fseeko(f, 0, SEEK_END); + printf("File size: %u bytes\n", (Guint)ftello(f)); +#elif HAVE_FSEEK64 + fseek64(f, 0, SEEK_END); + printf("File size: %u bytes\n", (Guint)ftell64(f)); +#else + fseek(f, 0, SEEK_END); + printf("File size: %d bytes\n", (int)ftell(f)); +#endif + fclose(f); + } + + // print linearization info + printf("Optimized: %s\n", doc->isLinearized() ? "yes" : "no"); + + // print PDF version + printf("PDF version: %.1f\n", doc->getPDFVersion()); + + // print the metadata + if (printMetadata && (metadata = doc->readMetadata())) { + fputs("Metadata:\n", stdout); + fputs(metadata->getCString(), stdout); + fputc('\n', stdout); + delete metadata; + } + + exitCode = 0; + + // clean up + err2: + uMap->decRefCnt(); + delete doc; + err1: + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} + +static void printInfoString(Dict *infoDict, char *key, char *text, + UnicodeMap *uMap) { + Object obj; + GString *s1; + GBool isUnicode; + Unicode u; + char buf[8]; + int i, n; + + if (infoDict->lookup(key, &obj)->isString()) { + fputs(text, stdout); + s1 = obj.getString(); + if ((s1->getChar(0) & 0xff) == 0xfe && + (s1->getChar(1) & 0xff) == 0xff) { + isUnicode = gTrue; + i = 2; + } else { + isUnicode = gFalse; + i = 0; + } + while (i < obj.getString()->getLength()) { + if (isUnicode) { + u = ((s1->getChar(i) & 0xff) << 8) | + (s1->getChar(i+1) & 0xff); + i += 2; + } else { + u = pdfDocEncoding[s1->getChar(i) & 0xff]; + ++i; + } + n = uMap->mapUnicode(u, buf, sizeof(buf)); + fwrite(buf, 1, n, stdout); + } + fputc('\n', stdout); + } + obj.free(); +} + +static void printInfoDate(Dict *infoDict, char *key, char *text) { + Object obj; + char *s; + int year, mon, day, hour, min, sec, n; + struct tm tmStruct; + char buf[256]; + + if (infoDict->lookup(key, &obj)->isString()) { + fputs(text, stdout); + s = obj.getString()->getCString(); + if (s[0] == 'D' && s[1] == ':') { + s += 2; + } + if ((n = sscanf(s, "%4d%2d%2d%2d%2d%2d", + &year, &mon, &day, &hour, &min, &sec)) >= 1) { + switch (n) { + case 1: mon = 1; + case 2: day = 1; + case 3: hour = 0; + case 4: min = 0; + case 5: sec = 0; + } + tmStruct.tm_year = year - 1900; + tmStruct.tm_mon = mon - 1; + tmStruct.tm_mday = day; + tmStruct.tm_hour = hour; + tmStruct.tm_min = min; + tmStruct.tm_sec = sec; + tmStruct.tm_wday = -1; + tmStruct.tm_yday = -1; + tmStruct.tm_isdst = -1; + // compute the tm_wday and tm_yday fields + if (mktime(&tmStruct) != (time_t)-1 && + strftime(buf, sizeof(buf), "%c", &tmStruct)) { + fputs(buf, stdout); + } else { + fputs(s, stdout); + } + } else { + fputs(s, stdout); + } + + + + fputc('\n', stdout); + } + obj.free(); +} + +static void printBox(char *text, PDFRectangle *box) { + printf("%s%8.2f %8.2f %8.2f %8.2f\n", + text, box->x1, box->y1, box->x2, box->y2); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdfinfo.hlp swftools-0.9.1/lib/pdf/xpdf/pdfinfo.hlp --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdfinfo.hlp 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdfinfo.hlp 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,129 @@ +! Generated automatically by mantohlp +1 pdfinfo + + pdfinfo - Portable Document Format (PDF) document informa- + tion + + pdfinfo [options] [PDF-file] + + Pdfinfo prints the contents of the 'Info' dictionary (plus + some other useful information) from a Portable Document + Format (PDF) file. + + The 'Info' dictionary contains the following values: + + title + subject + keywords + author + creator + producer + creation date + modification date + + In addition, the following information is printed: + + tagged (yes/no) + page count + encrypted flag (yes/no) + print and copy permissions (if encrypted) + page size + file size + linearized (yes/no) + PDF version + metadata (only if requested) + + () + +2 ONFIGURATION_FIL + + Pdfinfo reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdfinfo is built). See the xpdfrc(5) + man page for details. + + () + +2 OPTIONS + + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to examine. If multiple + pages are requested using the "-f" and "-l" + options, the size of each requested page (and, + optionally, the bounding boxes for each requested + page) are printed. Otherwise, only page one is + examined. + + -l number + Specifies the last page to examine. + + -box Prints the page box bounding boxes: MediaBox, Crop- + Box, BleedBox, TrimBox, and ArtBox. + + -meta Prints document-level metadata. (This is the + "Metadata" stream from the PDF file's Catalog + object.) + + -enc encoding-name + Sets the encoding to use for text output. The + encoding-name must be defined with the unicodeMap + command (see xpdfrc(5)). This defaults to "Latin1" + (which is a built-in encoding). [config file: tex- + tEncoding] + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the sys- + tem-wide config file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + + () + +2 XIT_CODE + + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + + () + +2 AUTHOR + + The pdfinfo software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + + () + +2 SEE_ALSO + + xpdf(1), pdftops(1), pdftotext(1), pdffonts(1), + pdftoppm(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + () + diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftoppm.1 swftools-0.9.1/lib/pdf/xpdf/pdftoppm.1 --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftoppm.1 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftoppm.1 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,119 @@ +.\" Copyright 2005-2007 Glyph & Cog, LLC +.TH pdftoppm 1 "27 February 2007" +.SH NAME +pdftoppm \- Portable Document Format (PDF) to Portable Pixmap (PPM) +converter (version 3.02) +.SH SYNOPSIS +.B pdftoppm +[options] +.I PDF-file PPM-root +.SH DESCRIPTION +.B Pdftoppm +converts Portable Document Format (PDF) files to color image files in +Portable Pixmap (PPM) format, grayscale image files in Portable +Graymap (PGM) format, or monochrome image files in Portable Bitmap +(PBM) format. +.PP +Pdftoppm reads the PDF file, +.IR PDF-file , +and writes one PPM file for each page, +.IR PPM-root - nnnnnn .ppm, +where +.I nnnnnn +is the page number. +.SH CONFIGURATION FILE +Pdftoppm reads a configuration file at startup. It first tries to +find the user's private config file, ~/.xpdfrc. If that doesn't +exist, it looks for a system-wide config file, typically +/usr/local/etc/xpdfrc (but this location can be changed when pdftoppm +is built). See the +.BR xpdfrc (5) +man page for details. +.SH OPTIONS +Many of the following options can be set with configuration file +commands. These are listed in square brackets with the description of +the corresponding command line option. +.TP +.BI \-f " number" +Specifies the first page to convert. +.TP +.BI \-l " number" +Specifies the last page to convert. +.TP +.BI \-r " number" +Specifies the resolution, in DPI. The default is 150 DPI. +.TP +.B \-mono +Generate a monochrome PBM file (instead of a color PPM file). +.TP +.B \-gray +Generate a grayscale PGM file (instead of a color PPM file). +.TP +.BI \-t1lib " yes | no" +Enable or disable t1lib (a Type 1 font rasterizer). This defaults to +"yes". +.RB "[config file: " enableT1lib ] +.TP +.BI \-freetype " yes | no" +Enable or disable FreeType (a TrueType / Type 1 font rasterizer). +This defaults to "yes". +.RB "[config file: " enableFreeType ] +.TP +.BI \-aa " yes | no" +Enable or disable font anti-aliasing. This defaults to "yes". +.RB "[config file: " antialias ] +.TP +.BI \-aaVector " yes | no" +Enable or disable vector anti-aliasing. This defaults to "yes". +.RB "[config file: " vectorAntialias ] +.TP +.BI \-opw " password" +Specify the owner password for the PDF file. Providing this will +bypass all security restrictions. +.TP +.BI \-upw " password" +Specify the user password for the PDF file. +.TP +.B \-q +Don't print any messages or errors. +.RB "[config file: " errQuiet ] +.TP +.B \-v +Print copyright and version information. +.TP +.B \-h +Print usage information. +.RB ( \-help +and +.B \-\-help +are equivalent.) +.SH EXIT CODES +The Xpdf tools use the following exit codes: +.TP +0 +No error. +.TP +1 +Error opening a PDF file. +.TP +2 +Error opening an output file. +.TP +3 +Error related to PDF permissions. +.TP +99 +Other error. +.SH AUTHOR +The pdftoppm software and documentation are copyright 1996-2007 Glyph +& Cog, LLC. +.SH "SEE ALSO" +.BR xpdf (1), +.BR pdftops (1), +.BR pdftotext (1), +.BR pdfinfo (1), +.BR pdffonts (1), +.BR pdfimages (1), +.BR xpdfrc (5) +.br +.B http://www.foolabs.com/xpdf/ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftoppm.cat swftools-0.9.1/lib/pdf/xpdf/pdftoppm.cat --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftoppm.cat 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftoppm.cat 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,108 @@ +pdftoppm(1) pdftoppm(1) + + + +NAME + pdftoppm - Portable Document Format (PDF) to Portable + Pixmap (PPM) converter (version 3.02) + +SYNOPSIS + pdftoppm [options] PDF-file PPM-root + +DESCRIPTION + Pdftoppm converts Portable Document Format (PDF) files to + color image files in Portable Pixmap (PPM) format, + grayscale image files in Portable Graymap (PGM) format, or + monochrome image files in Portable Bitmap (PBM) format. + + Pdftoppm reads the PDF file, PDF-file, and writes one PPM + file for each page, PPM-root-nnnnnn.ppm, where nnnnnn is + the page number. + +CONFIGURATION FILE + Pdftoppm reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdftoppm is built). See the xpdfrc(5) + man page for details. + +OPTIONS + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to convert. + + -l number + Specifies the last page to convert. + + -r number + Specifies the resolution, in DPI. The default is + 150 DPI. + + -mono Generate a monochrome PBM file (instead of a color + PPM file). + + -gray Generate a grayscale PGM file (instead of a color + PPM file). + + -t1lib yes | no + Enable or disable t1lib (a Type 1 font rasterizer). + This defaults to "yes". [config file: enableT1lib] + + -freetype yes | no + Enable or disable FreeType (a TrueType / Type 1 + font rasterizer). This defaults to "yes". [config + file: enableFreeType] + + -aa yes | no + Enable or disable font anti-aliasing. This + defaults to "yes". [config file: antialias] + + -aaVector yes | no + Enable or disable vector anti-aliasing. This + defaults to "yes". [config file: vectorAntialias] + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -q Don't print any messages or errors. [config file: + errQuiet] + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + +EXIT CODES + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + +AUTHOR + The pdftoppm software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + +SEE ALSO + xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdf- + fonts(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + + + 27 February 2007 pdftoppm(1) diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftoppm.cc swftools-0.9.1/lib/pdf/xpdf/pdftoppm.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftoppm.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftoppm.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,214 @@ +//======================================================================== +// +// pdftoppm.cc +// +// Copyright 2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#include +#include +#include "parseargs.h" +#include "gmem.h" +#include "GString.h" +#include "GlobalParams.h" +#include "Object.h" +#include "PDFDoc.h" +#include "SplashBitmap.h" +#include "Splash.h" +#include "SplashOutputDev.h" +#include "config.h" + +static int firstPage = 1; +static int lastPage = 0; +static int resolution = 150; +static GBool mono = gFalse; +static GBool gray = gFalse; +static char enableT1libStr[16] = ""; +static char enableFreeTypeStr[16] = ""; +static char antialiasStr[16] = ""; +static char vectorAntialiasStr[16] = ""; +static char ownerPassword[33] = ""; +static char userPassword[33] = ""; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to print"}, + {"-l", argInt, &lastPage, 0, + "last page to print"}, + {"-r", argInt, &resolution, 0, + "resolution, in DPI (default is 150)"}, + {"-mono", argFlag, &mono, 0, + "generate a monochrome PBM file"}, + {"-gray", argFlag, &gray, 0, + "generate a grayscale PGM file"}, +#if HAVE_T1LIB_H + {"-t1lib", argString, enableT1libStr, sizeof(enableT1libStr), + "enable t1lib font rasterizer: yes, no"}, +#endif +#if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H + {"-freetype", argString, enableFreeTypeStr, sizeof(enableFreeTypeStr), + "enable FreeType font rasterizer: yes, no"}, +#endif + {"-aa", argString, antialiasStr, sizeof(antialiasStr), + "enable font anti-aliasing: yes, no"}, + {"-aaVector", argString, vectorAntialiasStr, sizeof(vectorAntialiasStr), + "enable vector anti-aliasing: yes, no"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, + {"-h", argFlag, &printHelp, 0, + "print usage information"}, + {"-help", argFlag, &printHelp, 0, + "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +int main(int argc, char *argv[]) { + PDFDoc *doc; + GString *fileName; + char *ppmRoot; + char ppmFile[512]; + GString *ownerPW, *userPW; + SplashColor paperColor; + SplashOutputDev *splashOut; + GBool ok; + int exitCode; + int pg; + + exitCode = 99; + +#ifdef HAVE_LRAND48 + srand48(time(0)*getpid()); +#endif +#ifdef HAVE_RAND + srand(time(0)*getpid()); +#endif + + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (mono && gray) { + ok = gFalse; + } + if (!ok || argc != 3 || printVersion || printHelp) { + fprintf(stderr, "pdftoppm version %s\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdftoppm", " ", argDesc); + } + goto err0; + } + fileName = new GString(argv[1]); + ppmRoot = argv[2]; + + // read config file + globalParams = new GlobalParams(cfgFileName); + globalParams->setupBaseFonts(NULL); + if (enableT1libStr[0]) { + if (!globalParams->setEnableT1lib(enableT1libStr)) { + fprintf(stderr, "Bad '-t1lib' value on command line\n"); + } + } + if (enableFreeTypeStr[0]) { + if (!globalParams->setEnableFreeType(enableFreeTypeStr)) { + fprintf(stderr, "Bad '-freetype' value on command line\n"); + } + } + if (antialiasStr[0]) { + if (!globalParams->setAntialias(antialiasStr)) { + fprintf(stderr, "Bad '-aa' value on command line\n"); + } + } + if (vectorAntialiasStr[0]) { + if (!globalParams->setVectorAntialias(vectorAntialiasStr)) { + fprintf(stderr, "Bad '-aaVector' value on command line\n"); + } + } + if (quiet) { + globalParams->setErrQuiet(quiet); + } + + // open PDF file + if (ownerPassword[0]) { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0]) { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // get page range + if (firstPage < 1) + firstPage = 1; + if (lastPage < 1 || lastPage > doc->getNumPages()) + lastPage = doc->getNumPages(); + + // write PPM files + if (mono) { + paperColor[0] = 0xff; + splashOut = new SplashOutputDev(splashModeMono1, 1, gFalse, paperColor); + } else if (gray) { + paperColor[0] = 0xff; + splashOut = new SplashOutputDev(splashModeMono8, 1, gFalse, paperColor); + } else { + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor); + } + splashOut->startDoc(doc->getXRef()); + for (pg = firstPage; pg <= lastPage; ++pg) { + doc->displayPage(splashOut, pg, resolution, resolution, 0, + gFalse, gTrue, gFalse); + sprintf(ppmFile, "%.*s-%06d.%s", + (int)sizeof(ppmFile) - 32, ppmRoot, pg, + mono ? "pbm" : gray ? "pgm" : "ppm"); + splashOut->getBitmap()->writePNMFile(ppmFile); + } + delete splashOut; + + exitCode = 0; + + // clean up + err1: + delete doc; + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftoppm.hlp swftools-0.9.1/lib/pdf/xpdf/pdftoppm.hlp --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftoppm.hlp 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftoppm.hlp 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,118 @@ +! Generated automatically by mantohlp +1 pdftoppm + + pdftoppm - Portable Document Format (PDF) to Portable + Pixmap (PPM) + + pdftoppm [options] PDF-file PPM-root + + Pdftoppm converts Portable Document Format (PDF) files to + color image files in Portable Pixmap (PPM) format, + grayscale image files in Portable Graymap (PGM) format, or + monochrome image files in Portable Bitmap (PBM) format. + + Pdftoppm reads the PDF file, PDF-file, and writes one PPM + file for each page, PPM-root-nnnnnn.ppm, where nnnnnn is + the page number. + + () + +2 ONFIGURATION_FIL + + Pdftoppm reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdftoppm is built). See the xpdfrc(5) + man page for details. + + () + +2 OPTIONS + + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to convert. + + -l number + Specifies the last page to convert. + + -r number + Specifies the resolution, in DPI. The default is + 150 DPI. + + -mono Generate a monochrome PBM file (instead of a color + PPM file). + + -gray Generate a grayscale PGM file (instead of a color + PPM file). + + -t1lib yes | no + Enable or disable t1lib (a Type 1 font rasterizer). + This defaults to "yes". [config file: enableT1lib] + + -freetype yes | no + Enable or disable FreeType (a TrueType / Type 1 + font rasterizer). This defaults to "yes". [config + file: enableFreeType] + + -aa yes | no + Enable or disable font anti-aliasing. This + defaults to "yes". [config file: antialias] + + -aaVector yes | no + Enable or disable vector anti-aliasing. This + defaults to "yes". [config file: vectorAntialias] + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -q Don't print any messages or errors. [config file: + errQuiet] + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + + () + +2 XIT_CODE + + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + + () + +2 AUTHOR + + The pdftoppm software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + + () + +2 SEE_ALSO + + xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), pdf- + fonts(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + () + diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftops.1 swftools-0.9.1/lib/pdf/xpdf/pdftops.1 --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftops.1 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftops.1 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,235 @@ +.\" Copyright 1996-2007 Glyph & Cog, LLC +.TH pdftops 1 "27 February 2007" +.SH NAME +pdftops \- Portable Document Format (PDF) to PostScript converter +(version 3.02) +.SH SYNOPSIS +.B pdftops +[options] +.RI [ PDF-file +.RI [ PS-file ]] +.SH DESCRIPTION +.B Pdftops +converts Portable Document Format (PDF) files to PostScript so they +can be printed. +.PP +Pdftops reads the PDF file, +.IR PDF-file , +and writes a PostScript file, +.IR PS-file . +If +.I PS-file +is not specified, pdftops converts +.I file.pdf +to +.I file.ps +(or +.I file.eps +with the -eps option). If +.I PS-file +is \'-', the PostScript is sent to stdout. +.SH CONFIGURATION FILE +Pdftops reads a configuration file at startup. It first tries to find +the user's private config file, ~/.xpdfrc. If that doesn't exist, it +looks for a system-wide config file, typically /usr/local/etc/xpdfrc +(but this location can be changed when pdftops is built). See the +.BR xpdfrc (5) +man page for details. +.SH OPTIONS +Many of the following options can be set with configuration file +commands. These are listed in square brackets with the description of +the corresponding command line option. +.TP +.BI \-f " number" +Specifies the first page to print. +.TP +.BI \-l " number" +Specifies the last page to print. +.TP +.B \-level1 +Generate Level 1 PostScript. The resulting PostScript files will be +significantly larger (if they contain images), but will print on Level +1 printers. This also converts all images to black and white. No +more than one of the PostScript level options (-level1, -level1sep, +-level2, -level2sep, -level3, -level3Sep) may be given. +.RB "[config file: " psLevel ] +.TP +.B \-level1sep +Generate Level 1 separable PostScript. All colors are converted to +CMYK. Images are written with separate stream data for the four +components. +.RB "[config file: " psLevel ] +.TP +.B \-level2 +Generate Level 2 PostScript. Level 2 supports color images and image +compression. This is the default setting. +.RB "[config file: " psLevel ] +.TP +.B \-level2sep +Generate Level 2 separable PostScript. All colors are converted to +CMYK. The PostScript separation convention operators are used to +handle custom (spot) colors. +.RB "[config file: " psLevel ] +.TP +.B \-level3 +Generate Level 3 PostScript. This enables all Level 2 features plus +CID font embedding and masked image generation. +.RB "[config file: " psLevel ] +.TP +.B \-level3Sep +Generate Level 3 separable PostScript. The separation handling is the +same as for -level2Sep. +.RB "[config file: " psLevel ] +.TP +.B \-eps +Generate an Encapsulated PostScript (EPS) file. An EPS file contains +a single image, so if you use this option with a multi-page PDF file, +you must use -f and -l to specify a single page. No more than one of +the mode options (-eps, -form) may be given. +.TP +.B \-form +Generate a PostScript form which can be imported by software that +understands forms. A form contains a single page, so if you use this +option with a multi-page PDF file, you must use -f and -l to specify a +single page. The -level1 option cannot be used with -form. +.TP +.B \-opi +Generate OPI comments for all images and forms which have OPI +information. (This option is only available if pdftops was compiled +with OPI support.) +.RB "[config file: " psOPI ] +.TP +.B \-noembt1 +By default, any Type 1 fonts which are embedded in the PDF file are +copied into the PostScript file. This option causes pdftops to +substitute base fonts instead. Embedded fonts make PostScript files +larger, but may be necessary for readable output. +.RB "[config file: " psEmbedType1Fonts ] +.TP +.B \-noembtt +By default, any TrueType fonts which are embedded in the PDF file are +copied into the PostScript file. This option causes pdftops to +substitute base fonts instead. Embedded fonts make PostScript files +larger, but may be necessary for readable output. Also, some +PostScript interpreters do not have TrueType rasterizers. +.RB "[config file: " psEmbedTrueTypeFonts ] +.TP +.B \-noembcidps +By default, any CID PostScript fonts which are embedded in the PDF +file are copied into the PostScript file. This option disables that +embedding. No attempt is made to substitute for non-embedded CID +PostScript fonts. +.RB "[config file: " psEmbedCIDPostScriptFonts ] +.TP +.B \-noembcidtt +By default, any CID TrueType fonts which are embedded in the PDF file +are copied into the PostScript file. This option disables that +embedding. No attempt is made to substitute for non-embedded CID +TrueType fonts. +.RB "[config file: " psEmbedCIDTrueTypeFonts ] +.TP +.B \-preload +Convert PDF forms to PS procedures, and preload image data. This uses +more memory in the PostScript interpreter, but generates significantly +smaller PS files in situations where, e.g., the same image is drawn on +every page of a long document. +.TP +.BI \-paper " size" +Set the paper size to one of "letter", "legal", "A4", or "A3". This +can also be set to "match", which will set the paper size to match the +size specified in the PDF file. +.RB "[config file: " psPaperSize ] +.TP +.BI \-paperw " size" +Set the paper width, in points. +.RB "[config file: " psPaperSize ] +.TP +.BI \-paperh " size" +Set the paper height, in points. +.RB "[config file: " psPaperSize ] +.TP +.B \-nocrop +By default, output is cropped to the CropBox specified in the PDF +file. This option disables cropping. +.RB "[config file: " psCrop ] +.TP +.B \-expand +Expand PDF pages smaller than the paper to fill the paper. By +default, these pages are not scaled. +.RB "[config file: " psExpandSmaller ] +.TP +.B \-noshrink +Don't scale PDF pages which are larger than the paper. By default, +pages larger than the paper are shrunk to fit. +.RB "[config file: " psShrinkLarger ] +.TP +.B \-nocenter +By default, PDF pages smaller than the paper (after any scaling) are +centered on the paper. This option causes them to be aligned to the +lower-left corner of the paper instead. +.RB "[config file: " psCenter ] +.TP +.B \-pagecrop +Treat the CropBox as the PDF page size. By default, the MediaBox is +used as the page size. +.TP +.B \-duplex +Set the Duplex pagedevice entry in the PostScript file. This tells +duplex-capable printers to enable duplexing. +.RB "[config file: " psDuplex ] +.TP +.BI \-opw " password" +Specify the owner password for the PDF file. Providing this will +bypass all security restrictions. +.TP +.BI \-upw " password" +Specify the user password for the PDF file. +.TP +.B \-q +Don't print any messages or errors. +.RB "[config file: " errQuiet ] +.TP +.BI \-cfg " config-file" +Read +.I config-file +in place of ~/.xpdfrc or the system-wide config file. +.TP +.B \-v +Print copyright and version information. +.TP +.B \-h +Print usage information. +.RB ( \-help +and +.B \-\-help +are equivalent.) +.SH EXIT CODES +The Xpdf tools use the following exit codes: +.TP +0 +No error. +.TP +1 +Error opening a PDF file. +.TP +2 +Error opening an output file. +.TP +3 +Error related to PDF permissions. +.TP +99 +Other error. +.SH AUTHOR +The pdftops software and documentation are copyright 1996-2007 Glyph & +Cog, LLC. +.SH "SEE ALSO" +.BR xpdf (1), +.BR pdftotext (1), +.BR pdfinfo (1), +.BR pdffonts (1), +.BR pdftoppm (1), +.BR pdfimages (1), +.BR xpdfrc (5) +.br +.B http://www.foolabs.com/xpdf/ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftops.cat swftools-0.9.1/lib/pdf/xpdf/pdftops.cat --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftops.cat 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftops.cat 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,229 @@ +pdftops(1) pdftops(1) + + + +NAME + pdftops - Portable Document Format (PDF) to PostScript + converter (version 3.02) + +SYNOPSIS + pdftops [options] [PDF-file [PS-file]] + +DESCRIPTION + Pdftops converts Portable Document Format (PDF) files to + PostScript so they can be printed. + + Pdftops reads the PDF file, PDF-file, and writes a + PostScript file, PS-file. If PS-file is not specified, + pdftops converts file.pdf to file.ps (or file.eps with the + -eps option). If PS-file is '-', the PostScript is sent + to stdout. + +CONFIGURATION FILE + Pdftops reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdftops is built). See the xpdfrc(5) + man page for details. + +OPTIONS + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to print. + + -l number + Specifies the last page to print. + + -level1 + Generate Level 1 PostScript. The resulting + PostScript files will be significantly larger (if + they contain images), but will print on Level 1 + printers. This also converts all images to black + and white. No more than one of the PostScript + level options (-level1, -level1sep, -level2, + -level2sep, -level3, -level3Sep) may be given. + [config file: psLevel] + + -level1sep + Generate Level 1 separable PostScript. All colors + are converted to CMYK. Images are written with + separate stream data for the four components. + [config file: psLevel] + + -level2 + Generate Level 2 PostScript. Level 2 supports + color images and image compression. This is the + default setting. [config file: psLevel] + + -level2sep + Generate Level 2 separable PostScript. All colors + are converted to CMYK. The PostScript separation + convention operators are used to handle custom + (spot) colors. [config file: psLevel] + + -level3 + Generate Level 3 PostScript. This enables all + Level 2 features plus CID font embedding and masked + image generation. [config file: psLevel] + + -level3Sep + Generate Level 3 separable PostScript. The separa- + tion handling is the same as for -level2Sep. [con- + fig file: psLevel] + + -eps Generate an Encapsulated PostScript (EPS) file. An + EPS file contains a single image, so if you use + this option with a multi-page PDF file, you must + use -f and -l to specify a single page. No more + than one of the mode options (-eps, -form) may be + given. + + -form Generate a PostScript form which can be imported by + software that understands forms. A form contains a + single page, so if you use this option with a + multi-page PDF file, you must use -f and -l to + specify a single page. The -level1 option cannot + be used with -form. + + -opi Generate OPI comments for all images and forms + which have OPI information. (This option is only + available if pdftops was compiled with OPI sup- + port.) [config file: psOPI] + + -noembt1 + By default, any Type 1 fonts which are embedded in + the PDF file are copied into the PostScript file. + This option causes pdftops to substitute base fonts + instead. Embedded fonts make PostScript files + larger, but may be necessary for readable output. + [config file: psEmbedType1Fonts] + + -noembtt + By default, any TrueType fonts which are embedded + in the PDF file are copied into the PostScript + file. This option causes pdftops to substitute + base fonts instead. Embedded fonts make PostScript + files larger, but may be necessary for readable + output. Also, some PostScript interpreters do not + have TrueType rasterizers. [config file: psEm- + bedTrueTypeFonts] + + -noembcidps + By default, any CID PostScript fonts which are + embedded in the PDF file are copied into the + PostScript file. This option disables that embed- + ding. No attempt is made to substitute for non- + embedded CID PostScript fonts. [config file: psEm- + bedCIDPostScriptFonts] + + -noembcidtt + By default, any CID TrueType fonts which are embed- + ded in the PDF file are copied into the PostScript + file. This option disables that embedding. No + attempt is made to substitute for non-embedded CID + TrueType fonts. [config file: psEmbedCIDTrueType- + Fonts] + + -preload + Convert PDF forms to PS procedures, and preload + image data. This uses more memory in the + PostScript interpreter, but generates significantly + smaller PS files in situations where, e.g., the + same image is drawn on every page of a long docu- + ment. + + -paper size + Set the paper size to one of "letter", "legal", + "A4", or "A3". This can also be set to "match", + which will set the paper size to match the size + specified in the PDF file. [config file: psPaper- + Size] + + -paperw size + Set the paper width, in points. [config file: + psPaperSize] + + -paperh size + Set the paper height, in points. [config file: + psPaperSize] + + -nocrop + By default, output is cropped to the CropBox speci- + fied in the PDF file. This option disables crop- + ping. [config file: psCrop] + + -expand + Expand PDF pages smaller than the paper to fill the + paper. By default, these pages are not scaled. + [config file: psExpandSmaller] + + -noshrink + Don't scale PDF pages which are larger than the + paper. By default, pages larger than the paper are + shrunk to fit. [config file: psShrinkLarger] + + -nocenter + By default, PDF pages smaller than the paper (after + any scaling) are centered on the paper. This + option causes them to be aligned to the lower-left + corner of the paper instead. [config file: psCen- + ter] + + -pagecrop + Treat the CropBox as the PDF page size. By + default, the MediaBox is used as the page size. + + -duplex + Set the Duplex pagedevice entry in the PostScript + file. This tells duplex-capable printers to enable + duplexing. [config file: psDuplex] + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -q Don't print any messages or errors. [config file: + errQuiet] + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the sys- + tem-wide config file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + +EXIT CODES + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + +AUTHOR + The pdftops software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + +SEE ALSO + xpdf(1), pdftotext(1), pdfinfo(1), pdffonts(1), + pdftoppm(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + + + 27 February 2007 pdftops(1) diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftops.cc swftools-0.9.1/lib/pdf/xpdf/pdftops.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftops.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftops.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,344 @@ +//======================================================================== +// +// pdftops.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#include +#include "parseargs.h" +#include "GString.h" +#include "gmem.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Stream.h" +#include "Array.h" +#include "Dict.h" +#include "XRef.h" +#include "Catalog.h" +#include "Page.h" +#include "PDFDoc.h" +#include "PSOutputDev.h" +#include "Error.h" +#include "config.h" + +static int firstPage = 1; +static int lastPage = 0; +static GBool level1 = gFalse; +static GBool level1Sep = gFalse; +static GBool level2 = gFalse; +static GBool level2Sep = gFalse; +static GBool level3 = gFalse; +static GBool level3Sep = gFalse; +static GBool doEPS = gFalse; +static GBool doForm = gFalse; +#if OPI_SUPPORT +static GBool doOPI = gFalse; +#endif +static GBool noEmbedT1Fonts = gFalse; +static GBool noEmbedTTFonts = gFalse; +static GBool noEmbedCIDPSFonts = gFalse; +static GBool noEmbedCIDTTFonts = gFalse; +static GBool preload = gFalse; +static char paperSize[15] = ""; +static int paperWidth = 0; +static int paperHeight = 0; +static GBool noCrop = gFalse; +static GBool expand = gFalse; +static GBool noShrink = gFalse; +static GBool noCenter = gFalse; +static GBool pageCrop = gFalse; +static GBool duplex = gFalse; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to print"}, + {"-l", argInt, &lastPage, 0, + "last page to print"}, + {"-level1", argFlag, &level1, 0, + "generate Level 1 PostScript"}, + {"-level1sep", argFlag, &level1Sep, 0, + "generate Level 1 separable PostScript"}, + {"-level2", argFlag, &level2, 0, + "generate Level 2 PostScript"}, + {"-level2sep", argFlag, &level2Sep, 0, + "generate Level 2 separable PostScript"}, + {"-level3", argFlag, &level3, 0, + "generate Level 3 PostScript"}, + {"-level3sep", argFlag, &level3Sep, 0, + "generate Level 3 separable PostScript"}, + {"-eps", argFlag, &doEPS, 0, + "generate Encapsulated PostScript (EPS)"}, + {"-form", argFlag, &doForm, 0, + "generate a PostScript form"}, +#if OPI_SUPPORT + {"-opi", argFlag, &doOPI, 0, + "generate OPI comments"}, +#endif + {"-noembt1", argFlag, &noEmbedT1Fonts, 0, + "don't embed Type 1 fonts"}, + {"-noembtt", argFlag, &noEmbedTTFonts, 0, + "don't embed TrueType fonts"}, + {"-noembcidps", argFlag, &noEmbedCIDPSFonts, 0, + "don't embed CID PostScript fonts"}, + {"-noembcidtt", argFlag, &noEmbedCIDTTFonts, 0, + "don't embed CID TrueType fonts"}, + {"-preload", argFlag, &preload, 0, + "preload images and forms"}, + {"-paper", argString, paperSize, sizeof(paperSize), + "paper size (letter, legal, A4, A3, match)"}, + {"-paperw", argInt, &paperWidth, 0, + "paper width, in points"}, + {"-paperh", argInt, &paperHeight, 0, + "paper height, in points"}, + {"-nocrop", argFlag, &noCrop, 0, + "don't crop pages to CropBox"}, + {"-expand", argFlag, &expand, 0, + "expand pages smaller than the paper size"}, + {"-noshrink", argFlag, &noShrink, 0, + "don't shrink pages larger than the paper size"}, + {"-nocenter", argFlag, &noCenter, 0, + "don't center pages smaller than the paper size"}, + {"-pagecrop", argFlag, &pageCrop, 0, + "treat the CropBox as the page size"}, + {"-duplex", argFlag, &duplex, 0, + "enable duplex printing"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, + {"-h", argFlag, &printHelp, 0, + "print usage information"}, + {"-help", argFlag, &printHelp, 0, + "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +int main(int argc, char *argv[]) { + PDFDoc *doc; + GString *fileName; + GString *psFileName; + PSLevel level; + PSOutMode mode; + GString *ownerPW, *userPW; + PSOutputDev *psOut; + GBool ok; + char *p; + int exitCode; + + exitCode = 99; + + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) { + fprintf(stderr, "pdftops version %s\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdftops", " []", argDesc); + } + exit(1); + } + if ((level1 ? 1 : 0) + + (level1Sep ? 1 : 0) + + (level2 ? 1 : 0) + + (level2Sep ? 1 : 0) + + (level3 ? 1 : 0) + + (level3Sep ? 1 : 0) > 1) { + fprintf(stderr, "Error: use only one of the 'level' options.\n"); + exit(1); + } + if (doEPS && doForm) { + fprintf(stderr, "Error: use only one of -eps and -form\n"); + exit(1); + } + if (level1) { + level = psLevel1; + } else if (level1Sep) { + level = psLevel1Sep; + } else if (level2Sep) { + level = psLevel2Sep; + } else if (level3) { + level = psLevel3; + } else if (level3Sep) { + level = psLevel3Sep; + } else { + level = psLevel2; + } + if (doForm && level < psLevel2) { + fprintf(stderr, "Error: forms are only available with Level 2 output.\n"); + exit(1); + } + mode = doEPS ? psModeEPS + : doForm ? psModeForm + : psModePS; + fileName = new GString(argv[1]); + + // read config file + globalParams = new GlobalParams(cfgFileName); +#if HAVE_SPLASH + globalParams->setupBaseFonts(NULL); +#endif + if (paperSize[0]) { + if (!globalParams->setPSPaperSize(paperSize)) { + fprintf(stderr, "Invalid paper size\n"); + delete fileName; + goto err0; + } + } else { + if (paperWidth) { + globalParams->setPSPaperWidth(paperWidth); + } + if (paperHeight) { + globalParams->setPSPaperHeight(paperHeight); + } + } + if (noCrop) { + globalParams->setPSCrop(gFalse); + } + if (expand) { + globalParams->setPSExpandSmaller(gTrue); + } + if (noShrink) { + globalParams->setPSShrinkLarger(gFalse); + } + if (noCenter) { + globalParams->setPSCenter(gFalse); + } + if (duplex) { + globalParams->setPSDuplex(duplex); + } + if (level1 || level1Sep || level2 || level2Sep || level3 || level3Sep) { + globalParams->setPSLevel(level); + } + if (noEmbedT1Fonts) { + globalParams->setPSEmbedType1(!noEmbedT1Fonts); + } + if (noEmbedTTFonts) { + globalParams->setPSEmbedTrueType(!noEmbedTTFonts); + } + if (noEmbedCIDPSFonts) { + globalParams->setPSEmbedCIDPostScript(!noEmbedCIDPSFonts); + } + if (noEmbedCIDTTFonts) { + globalParams->setPSEmbedCIDTrueType(!noEmbedCIDTTFonts); + } + if (preload) { + globalParams->setPSPreload(preload); + } +#if OPI_SUPPORT + if (doOPI) { + globalParams->setPSOPI(doOPI); + } +#endif + if (quiet) { + globalParams->setErrQuiet(quiet); + } + + // open PDF file + if (ownerPassword[0] != '\001') { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0] != '\001') { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err1; + } + + // check for print permission + if (!doc->okToPrint()) { + error(-1, "Printing this document is not allowed."); + exitCode = 3; + goto err1; + } + + // construct PostScript file name + if (argc == 3) { + psFileName = new GString(argv[2]); + } else { + p = fileName->getCString() + fileName->getLength() - 4; + if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) { + psFileName = new GString(fileName->getCString(), + fileName->getLength() - 4); + } else { + psFileName = fileName->copy(); + } + psFileName->append(doEPS ? ".eps" : ".ps"); + } + + // get page range + if (firstPage < 1) { + firstPage = 1; + } + if (lastPage < 1 || lastPage > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + + // check for multi-page EPS or form + if ((doEPS || doForm) && firstPage != lastPage) { + error(-1, "EPS and form files can only contain one page."); + goto err2; + } + + // write PostScript file + psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(), + doc->getCatalog(), firstPage, lastPage, mode); + if (psOut->isOk()) { + doc->displayPages(psOut, firstPage, lastPage, 72, 72, + 0, !pageCrop, globalParams->getPSCrop(), gTrue); + } else { + delete psOut; + exitCode = 2; + goto err2; + } + delete psOut; + + exitCode = 0; + + // clean up + err2: + delete psFileName; + err1: + delete doc; + err0: + delete globalParams; + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftops.hlp swftools-0.9.1/lib/pdf/xpdf/pdftops.hlp --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftops.hlp 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftops.hlp 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,239 @@ +! Generated automatically by mantohlp +1 pdftops + + pdftops - Portable Document Format (PDF) to PostScript + converter + + pdftops [options] [PDF-file [PS-file]] + + Pdftops converts Portable Document Format (PDF) files to + PostScript so they can be printed. + + Pdftops reads the PDF file, PDF-file, and writes a + PostScript file, PS-file. If PS-file is not specified, + pdftops converts file.pdf to file.ps (or file.eps with the + -eps option). If PS-file is '-', the PostScript is sent + to stdout. + + () + +2 ONFIGURATION_FIL + + Pdftops reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdftops is built). See the xpdfrc(5) + man page for details. + + () + +2 OPTIONS + + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to print. + + -l number + Specifies the last page to print. + + -level1 + Generate Level 1 PostScript. The resulting + PostScript files will be significantly larger (if + they contain images), but will print on Level 1 + printers. This also converts all images to black + and white. No more than one of the PostScript + level options (-level1, -level1sep, -level2, + -level2sep, -level3, -level3Sep) may be given. + [config file: psLevel] + + -level1sep + Generate Level 1 separable PostScript. All colors + are converted to CMYK. Images are written with + separate stream data for the four components. + [config file: psLevel] + + -level2 + Generate Level 2 PostScript. Level 2 supports + color images and image compression. This is the + default setting. [config file: psLevel] + + -level2sep + Generate Level 2 separable PostScript. All colors + are converted to CMYK. The PostScript separation + convention operators are used to handle custom + (spot) colors. [config file: psLevel] + + -level3 + Generate Level 3 PostScript. This enables all + Level 2 features plus CID font embedding and masked + image generation. [config file: psLevel] + + -level3Sep + Generate Level 3 separable PostScript. The separa- + tion handling is the same as for -level2Sep. [con- + fig file: psLevel] + + -eps Generate an Encapsulated PostScript (EPS) file. An + EPS file contains a single image, so if you use + this option with a multi-page PDF file, you must + use -f and -l to specify a single page. No more + than one of the mode options (-eps, -form) may be + given. + + -form Generate a PostScript form which can be imported by + software that understands forms. A form contains a + single page, so if you use this option with a + multi-page PDF file, you must use -f and -l to + specify a single page. The -level1 option cannot + be used with -form. + + -opi Generate OPI comments for all images and forms + which have OPI information. (This option is only + available if pdftops was compiled with OPI sup- + port.) [config file: psOPI] + + -noembt1 + By default, any Type 1 fonts which are embedded in + the PDF file are copied into the PostScript file. + This option causes pdftops to substitute base fonts + instead. Embedded fonts make PostScript files + larger, but may be necessary for readable output. + [config file: psEmbedType1Fonts] + + -noembtt + By default, any TrueType fonts which are embedded + in the PDF file are copied into the PostScript + file. This option causes pdftops to substitute + base fonts instead. Embedded fonts make PostScript + files larger, but may be necessary for readable + output. Also, some PostScript interpreters do not + have TrueType rasterizers. [config file: psEm- + bedTrueTypeFonts] + + -noembcidps + By default, any CID PostScript fonts which are + embedded in the PDF file are copied into the + PostScript file. This option disables that embed- + ding. No attempt is made to substitute for non- + embedded CID PostScript fonts. [config file: psEm- + bedCIDPostScriptFonts] + + -noembcidtt + By default, any CID TrueType fonts which are embed- + ded in the PDF file are copied into the PostScript + file. This option disables that embedding. No + attempt is made to substitute for non-embedded CID + TrueType fonts. [config file: psEmbedCIDTrueType- + Fonts] + + -preload + Convert PDF forms to PS procedures, and preload + image data. This uses more memory in the + PostScript interpreter, but generates significantly + smaller PS files in situations where, e.g., the + same image is drawn on every page of a long docu- + ment. + + -paper size + Set the paper size to one of "letter", "legal", + "A4", or "A3". This can also be set to "match", + which will set the paper size to match the size + specified in the PDF file. [config file: psPaper- + Size] + + -paperw size + Set the paper width, in points. [config file: + psPaperSize] + + -paperh size + Set the paper height, in points. [config file: + psPaperSize] + + -nocrop + By default, output is cropped to the CropBox speci- + fied in the PDF file. This option disables + cropping. [config file: psCrop] + + -expand + Expand PDF pages smaller than the paper to fill the + paper. By default, these pages are not scaled. + [config file: psExpandSmaller] + + -noshrink + Don't scale PDF pages which are larger than the + paper. By default, pages larger than the paper are + shrunk to fit. [config file: psShrinkLarger] + + -nocenter + By default, PDF pages smaller than the paper (after + any scaling) are centered on the paper. This + option causes them to be aligned to the lower-left + corner of the paper instead. [config file: psCen- + ter] + + -pagecrop + Treat the CropBox as the PDF page size. By + default, the MediaBox is used as the page size. + + -duplex + Set the Duplex pagedevice entry in the PostScript + file. This tells duplex-capable printers to enable + duplexing. [config file: psDuplex] + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -q Don't print any messages or errors. [config file: + errQuiet] + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the sys- + tem-wide config file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + + () + +2 XIT_CODE + + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + + () + +2 AUTHOR + + The pdftops software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + + () + +2 SEE_ALSO + + xpdf(1), pdftotext(1), pdfinfo(1), pdffonts(1), + pdftoppm(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + () + diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftotext.1 swftools-0.9.1/lib/pdf/xpdf/pdftotext.1 --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftotext.1 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftotext.1 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,137 @@ +.\" Copyright 1997-2007 Glyph & Cog, LLC +.TH pdftotext 1 "27 Febuary 2007" +.SH NAME +pdftotext \- Portable Document Format (PDF) to text converter +(version 3.02) +.SH SYNOPSIS +.B pdftotext +[options] +.RI [ PDF-file +.RI [ text-file ]] +.SH DESCRIPTION +.B Pdftotext +converts Portable Document Format (PDF) files to plain text. +.PP +Pdftotext reads the PDF file, +.IR PDF-file , +and writes a text file, +.IR text-file . +If +.I text-file +is not specified, pdftotext converts +.I file.pdf +to +.IR file.txt . +If +.I text-file +is \'-', the text is sent to stdout. +.SH CONFIGURATION FILE +Pdftotext reads a configuration file at startup. It first tries to +find the user's private config file, ~/.xpdfrc. If that doesn't +exist, it looks for a system-wide config file, typically +/usr/local/etc/xpdfrc (but this location can be changed when pdftotext +is built). See the +.BR xpdfrc (5) +man page for details. +.SH OPTIONS +Many of the following options can be set with configuration file +commands. These are listed in square brackets with the description of +the corresponding command line option. +.TP +.BI \-f " number" +Specifies the first page to convert. +.TP +.BI \-l " number" +Specifies the last page to convert. +.TP +.B \-layout +Maintain (as best as possible) the original physical layout of the +text. The default is to \'undo' physical layout (columns, +hyphenation, etc.) and output the text in reading order. +.TP +.B \-raw +Keep the text in content stream order. This is a hack which often +"undoes" column formatting, etc. Use of raw mode is no longer +recommended. +.TP +.B \-htmlmeta +Generate a simple HTML file, including the meta information. This +simply wraps the text in

     and 
    and prepends the meta +headers. +.TP +.BI \-enc " encoding-name" +Sets the encoding to use for text output. The +.I encoding\-name +must be defined with the unicodeMap command (see +.BR xpdfrc (5)). +The encoding name is case-sensitive. This defaults to "Latin1" (which +is a built-in encoding). +.RB "[config file: " textEncoding ] +.TP +.BI \-eol " unix | dos | mac" +Sets the end-of-line convention to use for text output. +.RB "[config file: " textEOL ] +.TP +.B \-nopgbrk +Don't insert page breaks (form feed characters) between pages. +.RB "[config file: " textPageBreaks ] +.TP +.BI \-opw " password" +Specify the owner password for the PDF file. Providing this will +bypass all security restrictions. +.TP +.BI \-upw " password" +Specify the user password for the PDF file. +.TP +.B \-q +Don't print any messages or errors. +.RB "[config file: " errQuiet ] +.TP +.BI \-cfg " config-file" +Read +.I config-file +in place of ~/.xpdfrc or the system-wide config file. +.TP +.B \-v +Print copyright and version information. +.TP +.B \-h +Print usage information. +.RB ( \-help +and +.B \-\-help +are equivalent.) +.SH BUGS +Some PDF files contain fonts whose encodings have been mangled beyond +recognition. There is no way (short of OCR) to extract text from +these files. +.SH EXIT CODES +The Xpdf tools use the following exit codes: +.TP +0 +No error. +.TP +1 +Error opening a PDF file. +.TP +2 +Error opening an output file. +.TP +3 +Error related to PDF permissions. +.TP +99 +Other error. +.SH AUTHOR +The pdftotext software and documentation are copyright 1996-2007 Glyph +& Cog, LLC. +.SH "SEE ALSO" +.BR xpdf (1), +.BR pdftops (1), +.BR pdfinfo (1), +.BR pdffonts (1), +.BR pdftoppm (1), +.BR pdfimages (1), +.BR xpdfrc (5) +.br +.B http://www.foolabs.com/xpdf/ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftotext.cat swftools-0.9.1/lib/pdf/xpdf/pdftotext.cat --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftotext.cat 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftotext.cat 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,120 @@ +pdftotext(1) pdftotext(1) + + + +NAME + pdftotext - Portable Document Format (PDF) to text con- + verter (version 3.02) + +SYNOPSIS + pdftotext [options] [PDF-file [text-file]] + +DESCRIPTION + Pdftotext converts Portable Document Format (PDF) files to + plain text. + + Pdftotext reads the PDF file, PDF-file, and writes a text + file, text-file. If text-file is not specified, pdftotext + converts file.pdf to file.txt. If text-file is '-', the + text is sent to stdout. + +CONFIGURATION FILE + Pdftotext reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdftotext is built). See the + xpdfrc(5) man page for details. + +OPTIONS + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to convert. + + -l number + Specifies the last page to convert. + + -layout + Maintain (as best as possible) the original physi- + cal layout of the text. The default is to 'undo' + physical layout (columns, hyphenation, etc.) and + output the text in reading order. + + -raw Keep the text in content stream order. This is a + hack which often "undoes" column formatting, etc. + Use of raw mode is no longer recommended. + + -htmlmeta + Generate a simple HTML file, including the meta + information. This simply wraps the text in
    +              and 
    and prepends the meta headers. + + -enc encoding-name + Sets the encoding to use for text output. The + encoding-name must be defined with the unicodeMap + command (see xpdfrc(5)). The encoding name is + case-sensitive. This defaults to "Latin1" (which + is a built-in encoding). [config file: textEncod- + ing] + + -eol unix | dos | mac + Sets the end-of-line convention to use for text + output. [config file: textEOL] + + -nopgbrk + Don't insert page breaks (form feed characters) + between pages. [config file: textPageBreaks] + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -q Don't print any messages or errors. [config file: + errQuiet] + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the sys- + tem-wide config file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + +BUGS + Some PDF files contain fonts whose encodings have been + mangled beyond recognition. There is no way (short of + OCR) to extract text from these files. + +EXIT CODES + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + +AUTHOR + The pdftotext software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + +SEE ALSO + xpdf(1), pdftops(1), pdfinfo(1), pdffonts(1), pdftoppm(1), + pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + + + 27 Febuary 2007 pdftotext(1) diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftotext.cc swftools-0.9.1/lib/pdf/xpdf/pdftotext.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftotext.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftotext.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,343 @@ +//======================================================================== +// +// pdftotext.cc +// +// Copyright 1997-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include "parseargs.h" +#include "GString.h" +#include "gmem.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Stream.h" +#include "Array.h" +#include "Dict.h" +#include "XRef.h" +#include "Catalog.h" +#include "Page.h" +#include "PDFDoc.h" +#include "TextOutputDev.h" +#include "CharTypes.h" +#include "UnicodeMap.h" +#include "Error.h" +#include "config.h" + +static void printInfoString(FILE *f, Dict *infoDict, char *key, + char *text1, char *text2, UnicodeMap *uMap); +static void printInfoDate(FILE *f, Dict *infoDict, char *key, char *fmt); + +static int firstPage = 1; +static int lastPage = 0; +static GBool physLayout = gFalse; +static GBool rawOrder = gFalse; +static GBool htmlMeta = gFalse; +static char textEncName[128] = ""; +static char textEOL[16] = ""; +static GBool noPageBreaks = gFalse; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-f", argInt, &firstPage, 0, + "first page to convert"}, + {"-l", argInt, &lastPage, 0, + "last page to convert"}, + {"-layout", argFlag, &physLayout, 0, + "maintain original physical layout"}, + {"-raw", argFlag, &rawOrder, 0, + "keep strings in content stream order"}, + {"-htmlmeta", argFlag, &htmlMeta, 0, + "generate a simple HTML file, including the meta information"}, + {"-enc", argString, textEncName, sizeof(textEncName), + "output text encoding name"}, + {"-eol", argString, textEOL, sizeof(textEOL), + "output end-of-line convention (unix, dos, or mac)"}, + {"-nopgbrk", argFlag, &noPageBreaks, 0, + "don't insert page breaks between pages"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, + {"-h", argFlag, &printHelp, 0, + "print usage information"}, + {"-help", argFlag, &printHelp, 0, + "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +int main(int argc, char *argv[]) { + PDFDoc *doc; + GString *fileName; + GString *textFileName; + GString *ownerPW, *userPW; + TextOutputDev *textOut; + FILE *f; + UnicodeMap *uMap; + Object info; + GBool ok; + char *p; + int exitCode; + + exitCode = 99; + +#ifdef HAVE_LRAND48 + srand48(time(0)*getpid()); +#endif +#ifdef HAVE_RAND + srand(time(0)*getpid()); +#endif + + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) { + fprintf(stderr, "pdftotext version %s\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("pdftotext", " []", argDesc); + } + goto err0; + } + fileName = new GString(argv[1]); + + // read config file + globalParams = new GlobalParams(cfgFileName); + if (textEncName[0]) { + globalParams->setTextEncoding(textEncName); + } + if (textEOL[0]) { + if (!globalParams->setTextEOL(textEOL)) { + fprintf(stderr, "Bad '-eol' value on command line\n"); + } + } + if (noPageBreaks) { + globalParams->setTextPageBreaks(gFalse); + } + if (quiet) { + globalParams->setErrQuiet(quiet); + } + + // get mapping to output encoding + if (!(uMap = globalParams->getTextEncoding())) { + error(-1, "Couldn't get text encoding"); + delete fileName; + goto err1; + } + + // open PDF file + if (ownerPassword[0] != '\001') { + ownerPW = new GString(ownerPassword); + } else { + ownerPW = NULL; + } + if (userPassword[0] != '\001') { + userPW = new GString(userPassword); + } else { + userPW = NULL; + } + doc = new PDFDoc(fileName, ownerPW, userPW); + if (userPW) { + delete userPW; + } + if (ownerPW) { + delete ownerPW; + } + if (!doc->isOk()) { + exitCode = 1; + goto err2; + } + + // check for copy permission + if (!doc->okToCopy()) { + error(-1, "Copying of text from this document is not allowed."); + exitCode = 3; + goto err2; + } + + // construct text file name + if (argc == 3) { + textFileName = new GString(argv[2]); + } else { + p = fileName->getCString() + fileName->getLength() - 4; + if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) { + textFileName = new GString(fileName->getCString(), + fileName->getLength() - 4); + } else { + textFileName = fileName->copy(); + } + textFileName->append(htmlMeta ? ".html" : ".txt"); + } + + // get page range + if (firstPage < 1) { + firstPage = 1; + } + if (lastPage < 1 || lastPage > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + + // write HTML header + if (htmlMeta) { + if (!textFileName->cmp("-")) { + f = stdout; + } else { + if (!(f = fopen(textFileName->getCString(), "wb"))) { + error(-1, "Couldn't open text file '%s'", textFileName->getCString()); + exitCode = 2; + goto err3; + } + } + fputs("\n", f); + fputs("\n", f); + doc->getDocInfo(&info); + if (info.isDict()) { + printInfoString(f, info.getDict(), "Title", "", "\n", + uMap); + printInfoString(f, info.getDict(), "Subject", + "\n", uMap); + printInfoString(f, info.getDict(), "Keywords", + "\n", uMap); + printInfoString(f, info.getDict(), "Author", + "\n", uMap); + printInfoString(f, info.getDict(), "Creator", + "\n", uMap); + printInfoString(f, info.getDict(), "Producer", + "\n", uMap); + printInfoDate(f, info.getDict(), "CreationDate", + "\n"); + printInfoDate(f, info.getDict(), "LastModifiedDate", + "\n"); + } + info.free(); + fputs("\n", f); + fputs("\n", f); + fputs("
    \n", f);
    +    if (f != stdout) {
    +      fclose(f);
    +    }
    +  }
    +
    +  // write text file
    +  textOut = new TextOutputDev(textFileName->getCString(),
    +			      physLayout, rawOrder, htmlMeta);
    +  if (textOut->isOk()) {
    +    doc->displayPages(textOut, firstPage, lastPage, 72, 72, 0,
    +		      gFalse, gTrue, gFalse);
    +  } else {
    +    delete textOut;
    +    exitCode = 2;
    +    goto err3;
    +  }
    +  delete textOut;
    +
    +  // write end of HTML file
    +  if (htmlMeta) {
    +    if (!textFileName->cmp("-")) {
    +      f = stdout;
    +    } else {
    +      if (!(f = fopen(textFileName->getCString(), "ab"))) {
    +	error(-1, "Couldn't open text file '%s'", textFileName->getCString());
    +	exitCode = 2;
    +	goto err3;
    +      }
    +    }
    +    fputs("
    \n", f); + fputs("\n", f); + fputs("\n", f); + if (f != stdout) { + fclose(f); + } + } + + exitCode = 0; + + // clean up + err3: + delete textFileName; + err2: + delete doc; + uMap->decRefCnt(); + err1: + delete globalParams; + err0: + + // check for memory leaks + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} + +static void printInfoString(FILE *f, Dict *infoDict, char *key, + char *text1, char *text2, UnicodeMap *uMap) { + Object obj; + GString *s1; + GBool isUnicode; + Unicode u; + char buf[8]; + int i, n; + + if (infoDict->lookup(key, &obj)->isString()) { + fputs(text1, f); + s1 = obj.getString(); + if ((s1->getChar(0) & 0xff) == 0xfe && + (s1->getChar(1) & 0xff) == 0xff) { + isUnicode = gTrue; + i = 2; + } else { + isUnicode = gFalse; + i = 0; + } + while (i < obj.getString()->getLength()) { + if (isUnicode) { + u = ((s1->getChar(i) & 0xff) << 8) | + (s1->getChar(i+1) & 0xff); + i += 2; + } else { + u = s1->getChar(i) & 0xff; + ++i; + } + n = uMap->mapUnicode(u, buf, sizeof(buf)); + fwrite(buf, 1, n, f); + } + fputs(text2, f); + } + obj.free(); +} + +static void printInfoDate(FILE *f, Dict *infoDict, char *key, char *fmt) { + Object obj; + char *s; + + if (infoDict->lookup(key, &obj)->isString()) { + s = obj.getString()->getCString(); + if (s[0] == 'D' && s[1] == ':') { + s += 2; + } + fprintf(f, fmt, s); + } + obj.free(); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/pdftotext.hlp swftools-0.9.1/lib/pdf/xpdf/pdftotext.hlp --- swftools-0.9.2+ds1/lib/pdf/xpdf/pdftotext.hlp 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/pdftotext.hlp 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,133 @@ +! Generated automatically by mantohlp +1 pdftotext + + pdftotext - Portable Document Format (PDF) to text con- + verter + + pdftotext [options] [PDF-file [text-file]] + + Pdftotext converts Portable Document Format (PDF) files to + plain text. + + Pdftotext reads the PDF file, PDF-file, and writes a text + file, text-file. If text-file is not specified, pdftotext + converts file.pdf to file.txt. If text-file is '-', the + text is sent to stdout. + + () + +2 ONFIGURATION_FIL + + Pdftotext reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when pdftotext is built). See the + xpdfrc(5) man page for details. + + () + +2 OPTIONS + + Many of the following options can be set with configura- + tion file commands. These are listed in square brackets + with the description of the corresponding command line + option. + + -f number + Specifies the first page to convert. + + -l number + Specifies the last page to convert. + + -layout + Maintain (as best as possible) the original physi- + cal layout of the text. The default is to 'undo' + physical layout (columns, hyphenation, etc.) and + output the text in reading order. + + -raw Keep the text in content stream order. This is a + hack which often "undoes" column formatting, etc. + Use of raw mode is no longer recommended. + + -htmlmeta + Generate a simple HTML file, including the meta + information. This simply wraps the text in
    +              and 
    and prepends the meta headers. + + -enc encoding-name + Sets the encoding to use for text output. The + encoding-name must be defined with the unicodeMap + command (see xpdfrc(5)). The encoding name is + case-sensitive. This defaults to "Latin1" (which + is a built-in encoding). [config file: textEncod- + ing] + + -eol unix | dos | mac + Sets the end-of-line convention to use for text + output. [config file: textEOL] + + -nopgbrk + Don't insert page breaks (form feed characters) + between pages. [config file: textPageBreaks] + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -q Don't print any messages or errors. [config file: + errQuiet] + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the sys- + tem-wide config file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + + () + +2 BUGS + + Some PDF files contain fonts whose encodings have been + mangled beyond recognition. There is no way (short of + OCR) to extract text from these files. + + () + +2 XIT_CODE + + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + + () + +2 AUTHOR + + The pdftotext software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + + () + +2 SEE_ALSO + + xpdf(1), pdftops(1), pdfinfo(1), pdffonts(1), pdftoppm(1), + pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + () + diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PreScanOutputDev.cc swftools-0.9.1/lib/pdf/xpdf/PreScanOutputDev.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/PreScanOutputDev.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PreScanOutputDev.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,257 @@ +//======================================================================== +// +// PreScanOutputDev.cc +// +// Copyright 2005 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "GlobalParams.h" +#include "GfxFont.h" +#include "Link.h" +#include "PreScanOutputDev.h" + +//------------------------------------------------------------------------ +// PreScanOutputDev +//------------------------------------------------------------------------ + +PreScanOutputDev::PreScanOutputDev() { + clearStats(); +} + +PreScanOutputDev::~PreScanOutputDev() { +} + +void PreScanOutputDev::startPage(int pageNum, GfxState *state) { +} + +void PreScanOutputDev::endPage() { +} + +void PreScanOutputDev::stroke(GfxState *state) { + double *dash; + int dashLen; + double dashStart; + + check(state->getStrokeColorSpace(), state->getStrokeColor(), + state->getStrokeOpacity(), state->getBlendMode()); + state->getLineDash(&dash, &dashLen, &dashStart); + if (dashLen != 0) { + gdi = gFalse; + } +} + +void PreScanOutputDev::fill(GfxState *state) { + check(state->getFillColorSpace(), state->getFillColor(), + state->getFillOpacity(), state->getBlendMode()); +} + +void PreScanOutputDev::eoFill(GfxState *state) { + check(state->getFillColorSpace(), state->getFillColor(), + state->getFillOpacity(), state->getBlendMode()); +} + +void PreScanOutputDev::clip(GfxState *state) { + //~ check for a rectangle "near" the edge of the page; + //~ else set gdi to false +} + +void PreScanOutputDev::eoClip(GfxState *state) { + //~ see clip() +} + +void PreScanOutputDev::beginStringOp(GfxState *state) { + int render; + GfxFont *font; + double m11, m12, m21, m22; + Ref embRef; + DisplayFontParam *dfp; + GBool simpleTTF; + + render = state->getRender(); + if (!(render & 1)) { + check(state->getFillColorSpace(), state->getFillColor(), + state->getFillOpacity(), state->getBlendMode()); + } + if ((render & 3) == 1 || (render & 3) == 2) { + check(state->getStrokeColorSpace(), state->getStrokeColor(), + state->getStrokeOpacity(), state->getBlendMode()); + } + + font = state->getFont(); + state->getFontTransMat(&m11, &m12, &m21, &m22); + simpleTTF = fabs(m11 + m22) < 0.01 && + m11 > 0 && + fabs(m12) < 0.01 && + fabs(m21) < 0.01 && + fabs(state->getHorizScaling() - 1) < 0.001 && + (font->getType() == fontTrueType || + font->getType() == fontTrueTypeOT) && + (font->getEmbeddedFontID(&embRef) || + font->getExtFontFile() || + (font->getName() && + (dfp = globalParams->getDisplayFont(font->getName())) && + dfp->kind == displayFontTT)); + if (simpleTTF) { + //~ need to create a FoFiTrueType object, and check for a Unicode cmap + } + if (state->getRender() != 0 || !simpleTTF) { + gdi = gFalse; + } +} + +void PreScanOutputDev::endStringOp(GfxState *state) { +} + +GBool PreScanOutputDev::beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen) { + // return false so all Type 3 chars get rendered (no caching) + return gFalse; +} + +void PreScanOutputDev::endType3Char(GfxState *state) { +} + +void PreScanOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg) { + int i, j; + + check(state->getFillColorSpace(), state->getFillColor(), + state->getFillOpacity(), state->getBlendMode()); + gdi = gFalse; + + if (inlineImg) { + str->reset(); + j = height * ((width + 7) / 8); + for (i = 0; i < j; ++i) + str->getChar(); + str->close(); + } +} + +void PreScanOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg) { + GfxColorSpace *colorSpace; + int i, j; + + colorSpace = colorMap->getColorSpace(); + if (colorSpace->getMode() == csIndexed) { + colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase(); + } + if (colorSpace->getMode() != csDeviceGray && + colorSpace->getMode() != csCalGray) { + gray = gFalse; + } + mono = gFalse; + if (state->getBlendMode() != gfxBlendNormal) { + transparency = gTrue; + } + gdi = gFalse; + + if (inlineImg) { + str->reset(); + j = height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8); + for (i = 0; i < j; ++i) + str->getChar(); + str->close(); + } +} + +void PreScanOutputDev::drawMaskedImage(GfxState *state, Object *ref, + Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert) { + GfxColorSpace *colorSpace; + + colorSpace = colorMap->getColorSpace(); + if (colorSpace->getMode() == csIndexed) { + colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase(); + } + if (colorSpace->getMode() != csDeviceGray && + colorSpace->getMode() != csCalGray) { + gray = gFalse; + } + mono = gFalse; + if (state->getBlendMode() != gfxBlendNormal) { + transparency = gTrue; + } + gdi = gFalse; +} + +void PreScanOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, + Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap) { + GfxColorSpace *colorSpace; + + colorSpace = colorMap->getColorSpace(); + if (colorSpace->getMode() == csIndexed) { + colorSpace = ((GfxIndexedColorSpace *)colorSpace)->getBase(); + } + if (colorSpace->getMode() != csDeviceGray && + colorSpace->getMode() != csCalGray) { + gray = gFalse; + } + mono = gFalse; + transparency = gTrue; + gdi = gFalse; +} + +void PreScanOutputDev::beginTransparencyGroup( + GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask) { + transparency = gTrue; + gdi = gFalse; +} + +void PreScanOutputDev::check(GfxColorSpace *colorSpace, GfxColor *color, + double opacity, GfxBlendMode blendMode) { + GfxRGB rgb; + + if (colorSpace->getMode() == csPattern) { + mono = gFalse; + gray = gFalse; + gdi = gFalse; + } else { + colorSpace->getRGB(color, &rgb); + if (rgb.r != rgb.g || rgb.g != rgb.b || rgb.b != rgb.r) { + mono = gFalse; + gray = gFalse; + } else if (!((rgb.r == 0 && rgb.g == 0 && rgb.b == 0) || + (rgb.r == gfxColorComp1 && + rgb.g == gfxColorComp1 && + rgb.b == gfxColorComp1))) { + mono = gFalse; + } + } + if (opacity != 1 || blendMode != gfxBlendNormal) { + transparency = gTrue; + } +} + +void PreScanOutputDev::clearStats() { + mono = gTrue; + gray = gTrue; + transparency = gFalse; + gdi = gTrue; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PreScanOutputDev.h swftools-0.9.1/lib/pdf/xpdf/PreScanOutputDev.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/PreScanOutputDev.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PreScanOutputDev.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,130 @@ +//======================================================================== +// +// PreScanOutputDev.h +// +// Copyright 2005 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PRESCANOUTPUTDEV_H +#define PRESCANOUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "GfxState.h" +#include "OutputDev.h" + +//------------------------------------------------------------------------ +// PreScanOutputDev +//------------------------------------------------------------------------ + +class PreScanOutputDev: public OutputDev { +public: + + // Constructor. + PreScanOutputDev(); + + // Destructor. + virtual ~PreScanOutputDev(); + + //----- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() { return gTrue; } + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() { return gTrue; } + + // Does this device use beginType3Char/endType3Char? Otherwise, + // text in Type 3 fonts will be drawn with drawChar/drawString. + virtual GBool interpretType3Chars() { return gTrue; } + + //----- initialization and control + + // Start a page. + virtual void startPage(int pageNum, GfxState *state); + + // End a page. + virtual void endPage(); + + //----- path painting + virtual void stroke(GfxState *state); + virtual void fill(GfxState *state); + virtual void eoFill(GfxState *state); + + //----- path clipping + virtual void clip(GfxState *state); + virtual void eoClip(GfxState *state); + + //----- text drawing + virtual void beginStringOp(GfxState *state); + virtual void endStringOp(GfxState *state); + virtual GBool beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen); + virtual void endType3Char(GfxState *state); + + //----- image drawing + virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, int maskWidth, int maskHeight, + GBool maskInvert); + virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap); + + //----- transparency groups and soft masks + virtual void beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask); + + //----- special access + + // Returns true if the operations performed since the last call to + // clearStats() are all monochrome (black or white). + GBool isMonochrome() { return mono; } + + // Returns true if the operations performed since the last call to + // clearStats() are all gray. + GBool isGray() { return gray; } + + // Returns true if the operations performed since the last call to + // clearStats() included any transparency. + GBool usesTransparency() { return transparency; } + + // Returns true if the operations performed since the last call to + // clearStats() are all rasterizable by GDI calls in GDIOutputDev. + GBool isAllGDI() { return gdi; } + + // Clear the stats used by the above functions. + void clearStats(); + +private: + + void check(GfxColorSpace *colorSpace, GfxColor *color, + double opacity, GfxBlendMode blendMode); + + GBool mono; + GBool gray; + GBool transparency; + GBool gdi; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/printDis.xbm swftools-0.9.1/lib/pdf/xpdf/printDis.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/printDis.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/printDis.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define printDis_width 15 +#define printDis_height 15 +static unsigned char printDis_bits[] = { + 0xa0, 0x2a, 0x10, 0x40, 0x00, 0x00, 0x40, 0x01, 0x08, 0x20, 0x40, 0x01, + 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x01, 0x40, + 0x00, 0x00, 0x01, 0x40, 0xaa, 0x2a}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/print.xbm swftools-0.9.1/lib/pdf/xpdf/print.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/print.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/print.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6 @@ +#define print_width 15 +#define print_height 15 +static unsigned char print_bits[] = { + 0xf0, 0x7f, 0x10, 0x40, 0x10, 0x40, 0xc8, 0x23, 0x08, 0x20, 0x68, 0x23, + 0x04, 0x10, 0x34, 0x10, 0x04, 0x10, 0xff, 0x7f, 0x55, 0x55, 0xab, 0x6a, + 0x55, 0x55, 0xab, 0x6a, 0xfe, 0x3f}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PSOutputDev.cc swftools-0.9.1/lib/pdf/xpdf/PSOutputDev.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/PSOutputDev.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PSOutputDev.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,6222 @@ +//======================================================================== +// +// PSOutputDev.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#include "GString.h" +#include "GList.h" +#include "config.h" +#include "GlobalParams.h" +#include "Object.h" +#include "Error.h" +#include "Function.h" +#include "Gfx.h" +#include "GfxState.h" +#include "GfxFont.h" +#include "UnicodeMap.h" +#include "FoFiType1C.h" +#include "FoFiTrueType.h" +#include "Catalog.h" +#include "Page.h" +#include "Stream.h" +#include "Annot.h" +#include "XRef.h" +#include "PreScanOutputDev.h" +#if HAVE_SPLASH +# include "Splash.h" +# include "SplashBitmap.h" +# include "SplashOutputDev.h" +#endif +#include "PSOutputDev.h" + +#ifdef MACOS +// needed for setting type/creator of MacOS files +#include "ICSupport.h" +#endif + +// the MSVC math.h doesn't define this +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +//------------------------------------------------------------------------ + +// Resolution at which pages with transparency will be rasterized. +#define splashDPI 300 + +//------------------------------------------------------------------------ +// PostScript prolog and setup +//------------------------------------------------------------------------ + +// The '~' escapes mark prolog code that is emitted only in certain +// levels: +// +// ~[123][sn] +// ^ ^----- s=psLevel*Sep, n=psLevel* +// +----- 1=psLevel1*, 2=psLevel2*, 3=psLevel3* + +static char *prolog[] = { + "/xpdf 75 dict def xpdf begin", + "% PDF special state", + "/pdfDictSize 15 def", + "~1sn", + "/pdfStates 64 array def", + " 0 1 63 {", + " pdfStates exch pdfDictSize dict", + " dup /pdfStateIdx 3 index put", + " put", + " } for", + "~123sn", + "/pdfSetup {", + " 3 1 roll 2 array astore", + " /setpagedevice where {", + " pop 3 dict begin", + " /PageSize exch def", + " /ImagingBBox null def", + " /Policies 1 dict dup begin /PageSize 3 def end def", + " { /Duplex true def } if", + " currentdict end setpagedevice", + " } {", + " pop pop", + " } ifelse", + "} def", + "~1sn", + "/pdfOpNames [", + " /pdfFill /pdfStroke /pdfLastFill /pdfLastStroke", + " /pdfTextMat /pdfFontSize /pdfCharSpacing /pdfTextRender", + " /pdfTextRise /pdfWordSpacing /pdfHorizScaling /pdfTextClipPath", + "] def", + "~123sn", + "/pdfStartPage {", + "~1sn", + " pdfStates 0 get begin", + "~23sn", + " pdfDictSize dict begin", + "~23n", + " /pdfFillCS [] def", + " /pdfFillXform {} def", + " /pdfStrokeCS [] def", + " /pdfStrokeXform {} def", + "~1n", + " /pdfFill 0 def", + " /pdfStroke 0 def", + "~1s", + " /pdfFill [0 0 0 1] def", + " /pdfStroke [0 0 0 1] def", + "~23sn", + " /pdfFill [0] def", + " /pdfStroke [0] def", + " /pdfFillOP false def", + " /pdfStrokeOP false def", + "~123sn", + " /pdfLastFill false def", + " /pdfLastStroke false def", + " /pdfTextMat [1 0 0 1 0 0] def", + " /pdfFontSize 0 def", + " /pdfCharSpacing 0 def", + " /pdfTextRender 0 def", + " /pdfTextRise 0 def", + " /pdfWordSpacing 0 def", + " /pdfHorizScaling 1 def", + " /pdfTextClipPath [] def", + "} def", + "/pdfEndPage { end } def", + "~23s", + "% separation convention operators", + "/findcmykcustomcolor where {", + " pop", + "}{", + " /findcmykcustomcolor { 5 array astore } def", + "} ifelse", + "/setcustomcolor where {", + " pop", + "}{", + " /setcustomcolor {", + " exch", + " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch", + " 0 4 getinterval cvx", + " [ exch /dup load exch { mul exch dup } /forall load", + " /pop load dup ] cvx", + " ] setcolorspace setcolor", + " } def", + "} ifelse", + "/customcolorimage where {", + " pop", + "}{", + " /customcolorimage {", + " gsave", + " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch", + " 0 4 getinterval", + " [ exch /dup load exch { mul exch dup } /forall load", + " /pop load dup ] cvx", + " ] setcolorspace", + " 10 dict begin", + " /ImageType 1 def", + " /DataSource exch def", + " /ImageMatrix exch def", + " /BitsPerComponent exch def", + " /Height exch def", + " /Width exch def", + " /Decode [1 0] def", + " currentdict end", + " image", + " grestore", + " } def", + "} ifelse", + "~123sn", + "% PDF color state", + "~1n", + "/g { dup /pdfFill exch def setgray", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/G { dup /pdfStroke exch def setgray", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/fCol {", + " pdfLastFill not {", + " pdfFill setgray", + " /pdfLastFill true def /pdfLastStroke false def", + " } if", + "} def", + "/sCol {", + " pdfLastStroke not {", + " pdfStroke setgray", + " /pdfLastStroke true def /pdfLastFill false def", + " } if", + "} def", + "~1s", + "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/fCol {", + " pdfLastFill not {", + " pdfFill aload pop setcmykcolor", + " /pdfLastFill true def /pdfLastStroke false def", + " } if", + "} def", + "/sCol {", + " pdfLastStroke not {", + " pdfStroke aload pop setcmykcolor", + " /pdfLastStroke true def /pdfLastFill false def", + " } if", + "} def", + "~23n", + "/cs { /pdfFillXform exch def dup /pdfFillCS exch def", + " setcolorspace } def", + "/CS { /pdfStrokeXform exch def dup /pdfStrokeCS exch def", + " setcolorspace } def", + "/sc { pdfLastFill not { pdfFillCS setcolorspace } if", + " dup /pdfFill exch def aload pop pdfFillXform setcolor", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/SC { pdfLastStroke not { pdfStrokeCS setcolorspace } if", + " dup /pdfStroke exch def aload pop pdfStrokeXform setcolor", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/op { /pdfFillOP exch def", + " pdfLastFill { pdfFillOP setoverprint } if } def", + "/OP { /pdfStrokeOP exch def", + " pdfLastStroke { pdfStrokeOP setoverprint } if } def", + "/fCol {", + " pdfLastFill not {", + " pdfFillCS setcolorspace", + " pdfFill aload pop pdfFillXform setcolor", + " pdfFillOP setoverprint", + " /pdfLastFill true def /pdfLastStroke false def", + " } if", + "} def", + "/sCol {", + " pdfLastStroke not {", + " pdfStrokeCS setcolorspace", + " pdfStroke aload pop pdfStrokeXform setcolor", + " pdfStrokeOP setoverprint", + " /pdfLastStroke true def /pdfLastFill false def", + " } if", + "} def", + "~23s", + "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/ck { 6 copy 6 array astore /pdfFill exch def", + " findcmykcustomcolor exch setcustomcolor", + " /pdfLastFill true def /pdfLastStroke false def } def", + "/CK { 6 copy 6 array astore /pdfStroke exch def", + " findcmykcustomcolor exch setcustomcolor", + " /pdfLastStroke true def /pdfLastFill false def } def", + "/op { /pdfFillOP exch def", + " pdfLastFill { pdfFillOP setoverprint } if } def", + "/OP { /pdfStrokeOP exch def", + " pdfLastStroke { pdfStrokeOP setoverprint } if } def", + "/fCol {", + " pdfLastFill not {", + " pdfFill aload length 4 eq {", + " setcmykcolor", + " }{", + " findcmykcustomcolor exch setcustomcolor", + " } ifelse", + " pdfFillOP setoverprint", + " /pdfLastFill true def /pdfLastStroke false def", + " } if", + "} def", + "/sCol {", + " pdfLastStroke not {", + " pdfStroke aload length 4 eq {", + " setcmykcolor", + " }{", + " findcmykcustomcolor exch setcustomcolor", + " } ifelse", + " pdfStrokeOP setoverprint", + " /pdfLastStroke true def /pdfLastFill false def", + " } if", + "} def", + "~123sn", + "% build a font", + "/pdfMakeFont {", + " 4 3 roll findfont", + " 4 2 roll matrix scale makefont", + " dup length dict begin", + " { 1 index /FID ne { def } { pop pop } ifelse } forall", + " /Encoding exch def", + " currentdict", + " end", + " definefont pop", + "} def", + "/pdfMakeFont16 {", + " exch findfont", + " dup length dict begin", + " { 1 index /FID ne { def } { pop pop } ifelse } forall", + " /WMode exch def", + " currentdict", + " end", + " definefont pop", + "} def", + "~3sn", + "/pdfMakeFont16L3 {", + " 1 index /CIDFont resourcestatus {", + " pop pop 1 index /CIDFont findresource /CIDFontType known", + " } {", + " false", + " } ifelse", + " {", + " 0 eq { /Identity-H } { /Identity-V } ifelse", + " exch 1 array astore composefont pop", + " } {", + " pdfMakeFont16", + " } ifelse", + "} def", + "~123sn", + "% graphics state operators", + "~1sn", + "/q {", + " gsave", + " pdfOpNames length 1 sub -1 0 { pdfOpNames exch get load } for", + " pdfStates pdfStateIdx 1 add get begin", + " pdfOpNames { exch def } forall", + "} def", + "/Q { end grestore } def", + "~23sn", + "/q { gsave pdfDictSize dict begin } def", + "/Q {", + " end grestore", + " /pdfLastFill where {", + " pop", + " pdfLastFill {", + " pdfFillOP setoverprint", + " } {", + " pdfStrokeOP setoverprint", + " } ifelse", + " } if", + "} def", + "~123sn", + "/cm { concat } def", + "/d { setdash } def", + "/i { setflat } def", + "/j { setlinejoin } def", + "/J { setlinecap } def", + "/M { setmiterlimit } def", + "/w { setlinewidth } def", + "% path segment operators", + "/m { moveto } def", + "/l { lineto } def", + "/c { curveto } def", + "/re { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto", + " neg 0 rlineto closepath } def", + "/h { closepath } def", + "% path painting operators", + "/S { sCol stroke } def", + "/Sf { fCol stroke } def", + "/f { fCol fill } def", + "/f* { fCol eofill } def", + "% clipping operators", + "/W { clip newpath } def", + "/W* { eoclip newpath } def", + "/Ws { strokepath clip newpath } def", + "% text state operators", + "/Tc { /pdfCharSpacing exch def } def", + "/Tf { dup /pdfFontSize exch def", + " dup pdfHorizScaling mul exch matrix scale", + " pdfTextMat matrix concatmatrix dup 4 0 put dup 5 0 put", + " exch findfont exch makefont setfont } def", + "/Tr { /pdfTextRender exch def } def", + "/Ts { /pdfTextRise exch def } def", + "/Tw { /pdfWordSpacing exch def } def", + "/Tz { /pdfHorizScaling exch def } def", + "% text positioning operators", + "/Td { pdfTextMat transform moveto } def", + "/Tm { /pdfTextMat exch def } def", + "% text string operators", + "/cshow where {", + " pop", + " /cshow2 {", + " dup {", + " pop pop", + " 1 string dup 0 3 index put 3 index exec", + " } exch cshow", + " pop pop", + " } def", + "}{", + " /cshow2 {", + " currentfont /FontType get 0 eq {", + " 0 2 2 index length 1 sub {", + " 2 copy get exch 1 add 2 index exch get", + " 2 copy exch 256 mul add", + " 2 string dup 0 6 5 roll put dup 1 5 4 roll put", + " 3 index exec", + " } for", + " } {", + " dup {", + " 1 string dup 0 3 index put 3 index exec", + " } forall", + " } ifelse", + " pop pop", + " } def", + "} ifelse", + "/awcp {", // awidthcharpath + " exch {", + " false charpath", + " 5 index 5 index rmoveto", + " 6 index eq { 7 index 7 index rmoveto } if", + " } exch cshow2", + " 6 {pop} repeat", + "} def", + "/Tj {", + " fCol", // because stringwidth has to draw Type 3 chars + " 1 index stringwidth pdfTextMat idtransform pop", + " sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse", + " pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32", + " 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0", + " pdfTextMat dtransform", + " 6 5 roll Tj1", + "} def", + "/Tj16 {", + " fCol", // because stringwidth has to draw Type 3 chars + " 2 index stringwidth pdfTextMat idtransform pop", + " sub exch div", + " pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32", + " 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0", + " pdfTextMat dtransform", + " 6 5 roll Tj1", + "} def", + "/Tj16V {", + " fCol", // because stringwidth has to draw Type 3 chars + " 2 index stringwidth pdfTextMat idtransform exch pop", + " sub exch div", + " 0 pdfWordSpacing pdfTextMat dtransform 32", + " 4 3 roll pdfCharSpacing add 0 exch", + " pdfTextMat dtransform", + " 6 5 roll Tj1", + "} def", + "/Tj1 {", + " 0 pdfTextRise pdfTextMat dtransform rmoveto", + " currentpoint 8 2 roll", + " pdfTextRender 1 and 0 eq {", + " 6 copy awidthshow", + " } if", + " pdfTextRender 3 and dup 1 eq exch 2 eq or {", + " 7 index 7 index moveto", + " 6 copy", + " currentfont /FontType get 3 eq { fCol } { sCol } ifelse", + " false awcp currentpoint stroke moveto", + " } if", + " pdfTextRender 4 and 0 ne {", + " 8 6 roll moveto", + " false awcp", + " /pdfTextClipPath [ pdfTextClipPath aload pop", + " {/moveto cvx}", + " {/lineto cvx}", + " {/curveto cvx}", + " {/closepath cvx}", + " pathforall ] def", + " currentpoint newpath moveto", + " } {", + " 8 {pop} repeat", + " } ifelse", + " 0 pdfTextRise neg pdfTextMat dtransform rmoveto", + "} def", + "/TJm { pdfFontSize 0.001 mul mul neg 0", + " pdfTextMat dtransform rmoveto } def", + "/TJmV { pdfFontSize 0.001 mul mul neg 0 exch", + " pdfTextMat dtransform rmoveto } def", + "/Tclip { pdfTextClipPath cvx exec clip newpath", + " /pdfTextClipPath [] def } def", + "~1ns", + "% Level 1 image operators", + "~1n", + "/pdfIm1 {", + " /pdfImBuf1 4 index string def", + " { currentfile pdfImBuf1 readhexstring pop } image", + "} def", + "~1s", + "/pdfIm1Sep {", + " /pdfImBuf1 4 index string def", + " /pdfImBuf2 4 index string def", + " /pdfImBuf3 4 index string def", + " /pdfImBuf4 4 index string def", + " { currentfile pdfImBuf1 readhexstring pop }", + " { currentfile pdfImBuf2 readhexstring pop }", + " { currentfile pdfImBuf3 readhexstring pop }", + " { currentfile pdfImBuf4 readhexstring pop }", + " true 4 colorimage", + "} def", + "~1ns", + "/pdfImM1 {", + " fCol /pdfImBuf1 4 index 7 add 8 idiv string def", + " { currentfile pdfImBuf1 readhexstring pop } imagemask", + "} def", + "/pdfImM1a {", + " { 2 copy get exch 1 add exch } imagemask", + " pop pop", + "} def", + "~23sn", + "% Level 2 image operators", + "/pdfImBuf 100 string def", + "/pdfIm {", + " image", + " { currentfile pdfImBuf readline", + " not { pop exit } if", + " (%-EOD-) eq { exit } if } loop", + "} def", + "~23s", + "/pdfImSep {", + " findcmykcustomcolor exch", + " dup /Width get /pdfImBuf1 exch string def", + " dup /Decode get aload pop 1 index sub /pdfImDecodeRange exch def", + " /pdfImDecodeLow exch def", + " begin Width Height BitsPerComponent ImageMatrix DataSource end", + " /pdfImData exch def", + " { pdfImData pdfImBuf1 readstring pop", + " 0 1 2 index length 1 sub {", + " 1 index exch 2 copy get", + " pdfImDecodeRange mul 255 div pdfImDecodeLow add round cvi", + " 255 exch sub put", + " } for }", + " 6 5 roll customcolorimage", + " { currentfile pdfImBuf readline", + " not { pop exit } if", + " (%-EOD-) eq { exit } if } loop", + "} def", + "~23sn", + "/pdfImM {", + " fCol imagemask", + " { currentfile pdfImBuf readline", + " not { pop exit } if", + " (%-EOD-) eq { exit } if } loop", + "} def", + "/pr { 2 index 2 index 3 2 roll putinterval 4 add } def", + "/pdfImClip {", + " gsave", + " 0 2 4 index length 1 sub {", + " dup 4 index exch 2 copy", + " get 5 index div put", + " 1 add 3 index exch 2 copy", + " get 3 index div put", + " } for", + " pop pop rectclip", + "} def", + "/pdfImClipEnd { grestore } def", + "~23sn", + "% shading operators", + "/colordelta {", + " false 0 1 3 index length 1 sub {", + " dup 4 index exch get 3 index 3 2 roll get sub abs 0.004 gt {", + " pop true", + " } if", + " } for", + " exch pop exch pop", + "} def", + "/funcCol { func n array astore } def", + "/funcSH {", + " dup 0 eq {", + " true", + " } {", + " dup 6 eq {", + " false", + " } {", + " 4 index 4 index funcCol dup", + " 6 index 4 index funcCol dup", + " 3 1 roll colordelta 3 1 roll", + " 5 index 5 index funcCol dup", + " 3 1 roll colordelta 3 1 roll", + " 6 index 8 index funcCol dup", + " 3 1 roll colordelta 3 1 roll", + " colordelta or or or", + " } ifelse", + " } ifelse", + " {", + " 1 add", + " 4 index 3 index add 0.5 mul exch 4 index 3 index add 0.5 mul exch", + " 6 index 6 index 4 index 4 index 4 index funcSH", + " 2 index 6 index 6 index 4 index 4 index funcSH", + " 6 index 2 index 4 index 6 index 4 index funcSH", + " 5 3 roll 3 2 roll funcSH pop pop", + " } {", + " pop 3 index 2 index add 0.5 mul 3 index 2 index add 0.5 mul", + "~23n", + " funcCol sc", + "~23s", + " funcCol aload pop k", + "~23sn", + " dup 4 index exch mat transform m", + " 3 index 3 index mat transform l", + " 1 index 3 index mat transform l", + " mat transform l pop pop h f*", + " } ifelse", + "} def", + "/axialCol {", + " dup 0 lt {", + " pop t0", + " } {", + " dup 1 gt {", + " pop t1", + " } {", + " dt mul t0 add", + " } ifelse", + " } ifelse", + " func n array astore", + "} def", + "/axialSH {", + " dup 0 eq {", + " true", + " } {", + " dup 8 eq {", + " false", + " } {", + " 2 index axialCol 2 index axialCol colordelta", + " } ifelse", + " } ifelse", + " {", + " 1 add 3 1 roll 2 copy add 0.5 mul", + " dup 4 3 roll exch 4 index axialSH", + " exch 3 2 roll axialSH", + " } {", + " pop 2 copy add 0.5 mul", + "~23n", + " axialCol sc", + "~23s", + " axialCol aload pop k", + "~23sn", + " exch dup dx mul x0 add exch dy mul y0 add", + " 3 2 roll dup dx mul x0 add exch dy mul y0 add", + " dx abs dy abs ge {", + " 2 copy yMin sub dy mul dx div add yMin m", + " yMax sub dy mul dx div add yMax l", + " 2 copy yMax sub dy mul dx div add yMax l", + " yMin sub dy mul dx div add yMin l", + " h f*", + " } {", + " exch 2 copy xMin sub dx mul dy div add xMin exch m", + " xMax sub dx mul dy div add xMax exch l", + " exch 2 copy xMax sub dx mul dy div add xMax exch l", + " xMin sub dx mul dy div add xMin exch l", + " h f*", + " } ifelse", + " } ifelse", + "} def", + "/radialCol {", + " dup t0 lt {", + " pop t0", + " } {", + " dup t1 gt {", + " pop t1", + " } if", + " } ifelse", + " func n array astore", + "} def", + "/radialSH {", + " dup 0 eq {", + " true", + " } {", + " dup 8 eq {", + " false", + " } {", + " 2 index dt mul t0 add radialCol", + " 2 index dt mul t0 add radialCol colordelta", + " } ifelse", + " } ifelse", + " {", + " 1 add 3 1 roll 2 copy add 0.5 mul", + " dup 4 3 roll exch 4 index radialSH", + " exch 3 2 roll radialSH", + " } {", + " pop 2 copy add 0.5 mul dt mul t0 add", + "~23n", + " radialCol sc", + "~23s", + " radialCol aload pop k", + "~23sn", + " encl {", + " exch dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " 0 360 arc h", + " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " 360 0 arcn h f", + " } {", + " 2 copy", + " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " a1 a2 arcn", + " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " a2 a1 arcn h", + " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " a1 a2 arc", + " dup dx mul x0 add exch dup dy mul y0 add exch dr mul r0 add", + " a2 a1 arc h f", + " } ifelse", + " } ifelse", + "} def", + "~123sn", + "end", + NULL +}; + +static char *cmapProlog[] = { + "/CIDInit /ProcSet findresource begin", + "10 dict begin", + " begincmap", + " /CMapType 1 def", + " /CMapName /Identity-H def", + " /CIDSystemInfo 3 dict dup begin", + " /Registry (Adobe) def", + " /Ordering (Identity) def", + " /Supplement 0 def", + " end def", + " 1 begincodespacerange", + " <0000> ", + " endcodespacerange", + " 0 usefont", + " 1 begincidrange", + " <0000> 0", + " endcidrange", + " endcmap", + " currentdict CMapName exch /CMap defineresource pop", + "end", + "10 dict begin", + " begincmap", + " /CMapType 1 def", + " /CMapName /Identity-V def", + " /CIDSystemInfo 3 dict dup begin", + " /Registry (Adobe) def", + " /Ordering (Identity) def", + " /Supplement 0 def", + " end def", + " /WMode 1 def", + " 1 begincodespacerange", + " <0000> ", + " endcodespacerange", + " 0 usefont", + " 1 begincidrange", + " <0000> 0", + " endcidrange", + " endcmap", + " currentdict CMapName exch /CMap defineresource pop", + "end", + "end", + NULL +}; + +//------------------------------------------------------------------------ +// Fonts +//------------------------------------------------------------------------ + +struct PSSubstFont { + char *psName; // PostScript name + double mWidth; // width of 'm' character +}; + +static char *psFonts[] = { + "Courier", + "Courier-Bold", + "Courier-Oblique", + "Courier-BoldOblique", + "Helvetica", + "Helvetica-Bold", + "Helvetica-Oblique", + "Helvetica-BoldOblique", + "Symbol", + "Times-Roman", + "Times-Bold", + "Times-Italic", + "Times-BoldItalic", + "ZapfDingbats", + NULL +}; + +static PSSubstFont psSubstFonts[] = { + {"Helvetica", 0.833}, + {"Helvetica-Oblique", 0.833}, + {"Helvetica-Bold", 0.889}, + {"Helvetica-BoldOblique", 0.889}, + {"Times-Roman", 0.788}, + {"Times-Italic", 0.722}, + {"Times-Bold", 0.833}, + {"Times-BoldItalic", 0.778}, + {"Courier", 0.600}, + {"Courier-Oblique", 0.600}, + {"Courier-Bold", 0.600}, + {"Courier-BoldOblique", 0.600} +}; + +// Info for 8-bit fonts +struct PSFont8Info { + Ref fontID; + Gushort *codeToGID; // code-to-GID mapping for TrueType fonts +}; + +// Encoding info for substitute 16-bit font +struct PSFont16Enc { + Ref fontID; + GString *enc; +}; + +//------------------------------------------------------------------------ +// process colors +//------------------------------------------------------------------------ + +#define psProcessCyan 1 +#define psProcessMagenta 2 +#define psProcessYellow 4 +#define psProcessBlack 8 +#define psProcessCMYK 15 + +//------------------------------------------------------------------------ +// PSOutCustomColor +//------------------------------------------------------------------------ + +class PSOutCustomColor { +public: + + PSOutCustomColor(double cA, double mA, + double yA, double kA, GString *nameA); + ~PSOutCustomColor(); + + double c, m, y, k; + GString *name; + PSOutCustomColor *next; +}; + +PSOutCustomColor::PSOutCustomColor(double cA, double mA, + double yA, double kA, GString *nameA) { + c = cA; + m = mA; + y = yA; + k = kA; + name = nameA; + next = NULL; +} + +PSOutCustomColor::~PSOutCustomColor() { + delete name; +} + +//------------------------------------------------------------------------ + +struct PSOutImgClipRect { + int x0, x1, y0, y1; +}; + +//------------------------------------------------------------------------ +// DeviceNRecoder +//------------------------------------------------------------------------ + +class DeviceNRecoder: public FilterStream { +public: + + DeviceNRecoder(Stream *strA, int widthA, int heightA, + GfxImageColorMap *colorMapA); + virtual ~DeviceNRecoder(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar() + { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx++]; } + virtual int lookChar() + { return (bufIdx >= bufSize && !fillBuf()) ? EOF : buf[bufIdx]; } + virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gTrue; } + virtual GBool isEncoder() { return gTrue; } + +private: + + GBool fillBuf(); + + int width, height; + GfxImageColorMap *colorMap; + Function *func; + ImageStream *imgStr; + int buf[gfxColorMaxComps]; + int pixelIdx; + int bufIdx; + int bufSize; +}; + +DeviceNRecoder::DeviceNRecoder(Stream *strA, int widthA, int heightA, + GfxImageColorMap *colorMapA): + FilterStream(strA) { + width = widthA; + height = heightA; + colorMap = colorMapA; + imgStr = NULL; + pixelIdx = 0; + bufIdx = gfxColorMaxComps; + bufSize = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())-> + getAlt()->getNComps(); + func = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())-> + getTintTransformFunc(); +} + +DeviceNRecoder::~DeviceNRecoder() { + if (imgStr) { + delete imgStr; + } +} + +void DeviceNRecoder::reset() { + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); +} + +GBool DeviceNRecoder::fillBuf() { + Guchar pixBuf[gfxColorMaxComps]; + GfxColor color; + double x[gfxColorMaxComps], y[gfxColorMaxComps]; + int i; + + if (pixelIdx >= width * height) { + return gFalse; + } + imgStr->getPixel(pixBuf); + colorMap->getColor(pixBuf, &color); + for (i = 0; + i < ((GfxDeviceNColorSpace *)colorMap->getColorSpace())->getNComps(); + ++i) { + x[i] = colToDbl(color.c[i]); + } + func->transform(x, y); + for (i = 0; i < bufSize; ++i) { + buf[i] = (int)(y[i] * 255 + 0.5); + } + bufIdx = 0; + ++pixelIdx; + return gTrue; +} + +//------------------------------------------------------------------------ +// PSOutputDev +//------------------------------------------------------------------------ + +extern "C" { +typedef void (*SignalFunc)(int); +} + +static void outputToFile(void *stream, char *data, int len) { + fwrite(data, 1, len, (FILE *)stream); +} + +PSOutputDev::PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog, + int firstPage, int lastPage, PSOutMode modeA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool manualCtrlA) { + FILE *f; + PSFileType fileTypeA; + + underlayCbk = NULL; + underlayCbkData = NULL; + overlayCbk = NULL; + overlayCbkData = NULL; + + fontIDs = NULL; + fontFileIDs = NULL; + fontFileNames = NULL; + font8Info = NULL; + font16Enc = NULL; + imgIDs = NULL; + formIDs = NULL; + xobjStack = NULL; + embFontList = NULL; + customColors = NULL; + haveTextClip = gFalse; + t3String = NULL; + + // open file or pipe + if (!strcmp(fileName, "-")) { + fileTypeA = psStdout; + f = stdout; + } else if (fileName[0] == '|') { + fileTypeA = psPipe; +#ifdef HAVE_POPEN +#ifndef WIN32 + signal(SIGPIPE, (SignalFunc)SIG_IGN); +#endif + if (!(f = popen(fileName + 1, "w"))) { + error(-1, "Couldn't run print command '%s'", fileName); + ok = gFalse; + return; + } +#else + error(-1, "Print commands are not supported ('%s')", fileName); + ok = gFalse; + return; +#endif + } else { + fileTypeA = psFile; + if (!(f = fopen(fileName, "w"))) { + error(-1, "Couldn't open PostScript file '%s'", fileName); + ok = gFalse; + return; + } + } + + init(outputToFile, f, fileTypeA, + xrefA, catalog, firstPage, lastPage, modeA, + imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA); +} + +PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, + XRef *xrefA, Catalog *catalog, + int firstPage, int lastPage, PSOutMode modeA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool manualCtrlA) { + underlayCbk = NULL; + underlayCbkData = NULL; + overlayCbk = NULL; + overlayCbkData = NULL; + + fontIDs = NULL; + fontFileIDs = NULL; + fontFileNames = NULL; + font8Info = NULL; + font16Enc = NULL; + imgIDs = NULL; + formIDs = NULL; + xobjStack = NULL; + embFontList = NULL; + customColors = NULL; + haveTextClip = gFalse; + t3String = NULL; + + init(outputFuncA, outputStreamA, psGeneric, + xrefA, catalog, firstPage, lastPage, modeA, + imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA); +} + +void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA, + PSFileType fileTypeA, XRef *xrefA, Catalog *catalog, + int firstPage, int lastPage, PSOutMode modeA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool manualCtrlA) { + Page *page; + PDFRectangle *box; + + // initialize + ok = gTrue; + outputFunc = outputFuncA; + outputStream = outputStreamA; + fileType = fileTypeA; + xref = xrefA; + level = globalParams->getPSLevel(); + mode = modeA; + paperWidth = globalParams->getPSPaperWidth(); + paperHeight = globalParams->getPSPaperHeight(); + imgLLX = imgLLXA; + imgLLY = imgLLYA; + imgURX = imgURXA; + imgURY = imgURYA; + if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) { + globalParams->getPSImageableArea(&imgLLX, &imgLLY, &imgURX, &imgURY); + } + if (paperWidth < 0 || paperHeight < 0) { + // this check is needed in case the document has zero pages + if (firstPage > 0 && firstPage <= catalog->getNumPages()) { + page = catalog->getPage(firstPage); + paperWidth = (int)ceil(page->getMediaWidth()); + paperHeight = (int)ceil(page->getMediaHeight()); + } else { + paperWidth = 1; + paperHeight = 1; + } + imgLLX = imgLLY = 0; + imgURX = paperWidth; + imgURY = paperHeight; + } + preload = globalParams->getPSPreload(); + manualCtrl = manualCtrlA; + if (mode == psModeForm) { + lastPage = firstPage; + } + processColors = 0; + inType3Char = gFalse; + +#if OPI_SUPPORT + // initialize OPI nesting levels + opi13Nest = 0; + opi20Nest = 0; +#endif + + tx0 = ty0 = -1; + xScale0 = yScale0 = 0; + rotate0 = -1; + clipLLX0 = clipLLY0 = 0; + clipURX0 = clipURY0 = -1; + + // initialize fontIDs, fontFileIDs, and fontFileNames lists + fontIDSize = 64; + fontIDLen = 0; + fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref)); + fontFileIDSize = 64; + fontFileIDLen = 0; + fontFileIDs = (Ref *)gmallocn(fontFileIDSize, sizeof(Ref)); + fontFileNameSize = 64; + fontFileNameLen = 0; + fontFileNames = (GString **)gmallocn(fontFileNameSize, sizeof(GString *)); + nextTrueTypeNum = 0; + font8InfoLen = 0; + font8InfoSize = 0; + font16EncLen = 0; + font16EncSize = 0; + imgIDLen = 0; + imgIDSize = 0; + formIDLen = 0; + formIDSize = 0; + + xobjStack = new GList(); + numSaves = 0; + numTilingPatterns = 0; + nextFunc = 0; + + // initialize embedded font resource comment list + embFontList = new GString(); + + if (!manualCtrl) { + // this check is needed in case the document has zero pages + if (firstPage > 0 && firstPage <= catalog->getNumPages()) { + writeHeader(firstPage, lastPage, + catalog->getPage(firstPage)->getMediaBox(), + catalog->getPage(firstPage)->getCropBox(), + catalog->getPage(firstPage)->getRotate()); + } else { + box = new PDFRectangle(0, 0, 1, 1); + writeHeader(firstPage, lastPage, box, box, 0); + delete box; + } + if (mode != psModeForm) { + writePS("%%BeginProlog\n"); + } + writeXpdfProcset(); + if (mode != psModeForm) { + writePS("%%EndProlog\n"); + writePS("%%BeginSetup\n"); + } + writeDocSetup(catalog, firstPage, lastPage); + if (mode != psModeForm) { + writePS("%%EndSetup\n"); + } + } + + // initialize sequential page number + seqPage = 1; +} + +PSOutputDev::~PSOutputDev() { + PSOutCustomColor *cc; + int i; + + if (ok) { + if (!manualCtrl) { + writePS("%%Trailer\n"); + writeTrailer(); + if (mode != psModeForm) { + writePS("%%EOF\n"); + } + } + if (fileType == psFile) { +#ifdef MACOS + ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle); +#endif + fclose((FILE *)outputStream); + } +#ifdef HAVE_POPEN + else if (fileType == psPipe) { + pclose((FILE *)outputStream); +#ifndef WIN32 + signal(SIGPIPE, (SignalFunc)SIG_DFL); +#endif + } +#endif + } + if (embFontList) { + delete embFontList; + } + if (fontIDs) { + gfree(fontIDs); + } + if (fontFileIDs) { + gfree(fontFileIDs); + } + if (fontFileNames) { + for (i = 0; i < fontFileNameLen; ++i) { + delete fontFileNames[i]; + } + gfree(fontFileNames); + } + if (font8Info) { + for (i = 0; i < font8InfoLen; ++i) { + gfree(font8Info[i].codeToGID); + } + gfree(font8Info); + } + if (font16Enc) { + for (i = 0; i < font16EncLen; ++i) { + delete font16Enc[i].enc; + } + gfree(font16Enc); + } + gfree(imgIDs); + gfree(formIDs); + if (xobjStack) { + delete xobjStack; + } + while (customColors) { + cc = customColors; + customColors = cc->next; + delete cc; + } +} + +void PSOutputDev::writeHeader(int firstPage, int lastPage, + PDFRectangle *mediaBox, PDFRectangle *cropBox, + int pageRotate) { + Object info, obj1; + double x1, y1, x2, y2; + + switch (mode) { + case psModePS: + writePS("%!PS-Adobe-3.0\n"); + break; + case psModeEPS: + writePS("%!PS-Adobe-3.0 EPSF-3.0\n"); + break; + case psModeForm: + writePS("%!PS-Adobe-3.0 Resource-Form\n"); + break; + } + + writePSFmt("% Produced by xpdf/pdftops {0:s}\n", xpdfVersion); + xref->getDocInfo(&info); + if (info.isDict() && info.dictLookup("Creator", &obj1)->isString()) { + writePS("%%Creator: "); + writePSTextLine(obj1.getString()); + } + obj1.free(); + if (info.isDict() && info.dictLookup("Title", &obj1)->isString()) { + writePS("%%Title: "); + writePSTextLine(obj1.getString()); + } + obj1.free(); + info.free(); + writePSFmt("%%LanguageLevel: {0:d}\n", + (level == psLevel1 || level == psLevel1Sep) ? 1 : + (level == psLevel2 || level == psLevel2Sep) ? 2 : 3); + if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) { + writePS("%%DocumentProcessColors: (atend)\n"); + writePS("%%DocumentCustomColors: (atend)\n"); + } + writePS("%%DocumentSuppliedResources: (atend)\n"); + + switch (mode) { + case psModePS: + writePSFmt("%%DocumentMedia: plain {0:d} {1:d} 0 () ()\n", + paperWidth, paperHeight); + writePSFmt("%%BoundingBox: 0 0 {0:d} {1:d}\n", paperWidth, paperHeight); + writePSFmt("%%Pages: {0:d}\n", lastPage - firstPage + 1); + writePS("%%EndComments\n"); + writePS("%%BeginDefaults\n"); + writePS("%%PageMedia: plain\n"); + writePS("%%EndDefaults\n"); + break; + case psModeEPS: + epsX1 = cropBox->x1; + epsY1 = cropBox->y1; + epsX2 = cropBox->x2; + epsY2 = cropBox->y2; + if (pageRotate == 0 || pageRotate == 180) { + x1 = epsX1; + y1 = epsY1; + x2 = epsX2; + y2 = epsY2; + } else { // pageRotate == 90 || pageRotate == 270 + x1 = 0; + y1 = 0; + x2 = epsY2 - epsY1; + y2 = epsX2 - epsX1; + } + writePSFmt("%%BoundingBox: {0:d} {1:d} {2:d} {3:d}\n", + (int)floor(x1), (int)floor(y1), (int)ceil(x2), (int)ceil(y2)); + if (floor(x1) != ceil(x1) || floor(y1) != ceil(y1) || + floor(x2) != ceil(x2) || floor(y2) != ceil(y2)) { + writePSFmt("%%HiResBoundingBox: {0:.4g} {1:.4g} {2:.4g} {3:.4g}\n", + x1, y1, x2, y2); + } + writePS("%%EndComments\n"); + break; + case psModeForm: + writePS("%%EndComments\n"); + writePS("32 dict dup begin\n"); + writePSFmt("/BBox [{0:d} {1:d} {2:d} {3:d}] def\n", + (int)floor(mediaBox->x1), (int)floor(mediaBox->y1), + (int)ceil(mediaBox->x2), (int)ceil(mediaBox->y2)); + writePS("/FormType 1 def\n"); + writePS("/Matrix [1 0 0 1 0 0] def\n"); + break; + } +} + +void PSOutputDev::writeXpdfProcset() { + GBool lev1, lev2, lev3, sep, nonSep; + char **p; + char *q; + + writePSFmt("%%BeginResource: procset xpdf {0:s} 0\n", xpdfVersion); + writePSFmt("%%Copyright: {0:s}\n", xpdfCopyright); + lev1 = lev2 = lev3 = sep = nonSep = gTrue; + for (p = prolog; *p; ++p) { + if ((*p)[0] == '~') { + lev1 = lev2 = lev3 = sep = nonSep = gFalse; + for (q = *p + 1; *q; ++q) { + switch (*q) { + case '1': lev1 = gTrue; break; + case '2': lev2 = gTrue; break; + case '3': lev3 = gTrue; break; + case 's': sep = gTrue; break; + case 'n': nonSep = gTrue; break; + } + } + } else if ((level == psLevel1 && lev1 && nonSep) || + (level == psLevel1Sep && lev1 && sep) || + (level == psLevel2 && lev2 && nonSep) || + (level == psLevel2Sep && lev2 && sep) || + (level == psLevel3 && lev3 && nonSep) || + (level == psLevel3Sep && lev3 && sep)) { + writePSFmt("{0:s}\n", *p); + } + } + writePS("%%EndResource\n"); + + if (level >= psLevel3) { + for (p = cmapProlog; *p; ++p) { + writePSFmt("{0:s}\n", *p); + } + } +} + +void PSOutputDev::writeDocSetup(Catalog *catalog, + int firstPage, int lastPage) { + Page *page; + Dict *resDict; + Annots *annots; + Object obj1, obj2; + int pg, i; + + if (mode == psModeForm) { + // swap the form and xpdf dicts + writePS("xpdf end begin dup begin\n"); + } else { + writePS("xpdf begin\n"); + } + for (pg = firstPage; pg <= lastPage; ++pg) { + page = catalog->getPage(pg); + if ((resDict = page->getResourceDict())) { + setupResources(resDict); + } + annots = new Annots(xref, catalog, page->getAnnots(&obj1)); + obj1.free(); + for (i = 0; i < annots->getNumAnnots(); ++i) { + if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) { + obj1.streamGetDict()->lookup("Resources", &obj2); + if (obj2.isDict()) { + setupResources(obj2.getDict()); + } + obj2.free(); + } + obj1.free(); + } + delete annots; + } + if (mode != psModeForm) { + if (mode != psModeEPS && !manualCtrl) { + writePSFmt("{0:d} {1:d} {2:s} pdfSetup\n", + paperWidth, paperHeight, + globalParams->getPSDuplex() ? "true" : "false"); + } +#if OPI_SUPPORT + if (globalParams->getPSOPI()) { + writePS("/opiMatrix matrix currentmatrix def\n"); + } +#endif + } +} + +void PSOutputDev::writePageTrailer() { + if (mode != psModeForm) { + writePS("pdfEndPage\n"); + } +} + +void PSOutputDev::writeTrailer() { + PSOutCustomColor *cc; + + if (mode == psModeForm) { + writePS("/Foo exch /Form defineresource pop\n"); + } else { + writePS("end\n"); + writePS("%%DocumentSuppliedResources:\n"); + writePS(embFontList->getCString()); + if (level == psLevel1Sep || level == psLevel2Sep || + level == psLevel3Sep) { + writePS("%%DocumentProcessColors:"); + if (processColors & psProcessCyan) { + writePS(" Cyan"); + } + if (processColors & psProcessMagenta) { + writePS(" Magenta"); + } + if (processColors & psProcessYellow) { + writePS(" Yellow"); + } + if (processColors & psProcessBlack) { + writePS(" Black"); + } + writePS("\n"); + writePS("%%DocumentCustomColors:"); + for (cc = customColors; cc; cc = cc->next) { + writePSFmt(" ({0:s})", cc->name->getCString()); + } + writePS("\n"); + writePS("%%CMYKCustomColor:\n"); + for (cc = customColors; cc; cc = cc->next) { + writePSFmt("%%+ {0:.4g} {1:.4g} {2:.4g} {3:.4g} ({4:t})\n", + cc->c, cc->m, cc->y, cc->k, cc->name); + } + } + } +} + +void PSOutputDev::setupResources(Dict *resDict) { + Object xObjDict, xObjRef, xObj, patDict, patRef, pat, resObj; + Ref ref0, ref1; + GBool skip; + int i, j; + + setupFonts(resDict); + setupImages(resDict); + setupForms(resDict); + + //----- recursively scan XObjects + resDict->lookup("XObject", &xObjDict); + if (xObjDict.isDict()) { + for (i = 0; i < xObjDict.dictGetLength(); ++i) { + + // avoid infinite recursion on XObjects + skip = gFalse; + if ((xObjDict.dictGetValNF(i, &xObjRef)->isRef())) { + ref0 = xObjRef.getRef(); + for (j = 0; j < xobjStack->getLength(); ++j) { + ref1 = *(Ref *)xobjStack->get(j); + if (ref1.num == ref0.num && ref1.gen == ref0.gen) { + skip = gTrue; + break; + } + } + if (!skip) { + xobjStack->append(&ref0); + } + } + if (!skip) { + + // process the XObject's resource dictionary + xObjDict.dictGetVal(i, &xObj); + if (xObj.isStream()) { + xObj.streamGetDict()->lookup("Resources", &resObj); + if (resObj.isDict()) { + setupResources(resObj.getDict()); + } + resObj.free(); + } + xObj.free(); + } + + if (xObjRef.isRef() && !skip) { + xobjStack->del(xobjStack->getLength() - 1); + } + xObjRef.free(); + } + } + xObjDict.free(); + + //----- recursively scan Patterns + resDict->lookup("Pattern", &patDict); + if (patDict.isDict()) { + inType3Char = gTrue; + for (i = 0; i < patDict.dictGetLength(); ++i) { + + // avoid infinite recursion on Patterns + skip = gFalse; + if ((patDict.dictGetValNF(i, &patRef)->isRef())) { + ref0 = patRef.getRef(); + for (j = 0; j < xobjStack->getLength(); ++j) { + ref1 = *(Ref *)xobjStack->get(j); + if (ref1.num == ref0.num && ref1.gen == ref0.gen) { + skip = gTrue; + break; + } + } + if (!skip) { + xobjStack->append(&ref0); + } + } + if (!skip) { + + // process the Pattern's resource dictionary + patDict.dictGetVal(i, &pat); + if (pat.isStream()) { + pat.streamGetDict()->lookup("Resources", &resObj); + if (resObj.isDict()) { + setupResources(resObj.getDict()); + } + resObj.free(); + } + pat.free(); + } + + if (patRef.isRef() && !skip) { + xobjStack->del(xobjStack->getLength() - 1); + } + patRef.free(); + } + inType3Char = gFalse; + } + patDict.free(); +} + +void PSOutputDev::setupFonts(Dict *resDict) { + Object obj1, obj2; + Ref r; + GfxFontDict *gfxFontDict; + GfxFont *font; + int i; + + gfxFontDict = NULL; + resDict->lookupNF("Font", &obj1); + if (obj1.isRef()) { + obj1.fetch(xref, &obj2); + if (obj2.isDict()) { + r = obj1.getRef(); + gfxFontDict = new GfxFontDict(xref, &r, obj2.getDict()); + } + obj2.free(); + } else if (obj1.isDict()) { + gfxFontDict = new GfxFontDict(xref, NULL, obj1.getDict()); + } + if (gfxFontDict) { + for (i = 0; i < gfxFontDict->getNumFonts(); ++i) { + if ((font = gfxFontDict->getFont(i))) { + setupFont(font, resDict); + } + } + delete gfxFontDict; + } + obj1.free(); +} + +void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { + Ref fontFileID; + GString *name; + PSFontParam *fontParam; + GString *psName; + char buf[16]; + GBool subst; + UnicodeMap *uMap; + char *charName; + double xs, ys; + int code; + double w1, w2; + double *fm; + int i, j; + + // check if font is already set up + for (i = 0; i < fontIDLen; ++i) { + if (fontIDs[i].num == font->getID()->num && + fontIDs[i].gen == font->getID()->gen) { + return; + } + } + + // add entry to fontIDs list + if (fontIDLen >= fontIDSize) { + fontIDSize += 64; + fontIDs = (Ref *)greallocn(fontIDs, fontIDSize, sizeof(Ref)); + } + fontIDs[fontIDLen++] = *font->getID(); + + xs = ys = 1; + subst = gFalse; + + // check for resident 8-bit font + if (font->getName() && + (fontParam = globalParams->getPSFont(font->getName()))) { + psName = new GString(fontParam->psFontName->getCString()); + + // check for embedded Type 1 font + } else if (globalParams->getPSEmbedType1() && + font->getType() == fontType1 && + font->getEmbeddedFontID(&fontFileID)) { + psName = filterPSName(font->getEmbeddedFontName()); + setupEmbeddedType1Font(&fontFileID, psName); + + // check for embedded Type 1C font + } else if (globalParams->getPSEmbedType1() && + font->getType() == fontType1C && + font->getEmbeddedFontID(&fontFileID)) { + // use the PDF font name because the embedded font name might + // not include the subset prefix + psName = filterPSName(font->getOrigName()); + setupEmbeddedType1CFont(font, &fontFileID, psName); + + // check for embedded OpenType - Type 1C font + } else if (globalParams->getPSEmbedType1() && + font->getType() == fontType1COT && + font->getEmbeddedFontID(&fontFileID)) { + // use the PDF font name because the embedded font name might + // not include the subset prefix + psName = filterPSName(font->getOrigName()); + setupEmbeddedOpenTypeT1CFont(font, &fontFileID, psName); + + // check for external Type 1 font file + } else if (globalParams->getPSEmbedType1() && + font->getType() == fontType1 && + font->getExtFontFile()) { + // this assumes that the PS font name matches the PDF font name + psName = font->getName()->copy(); + setupExternalType1Font(font->getExtFontFile(), psName); + + // check for embedded TrueType font + } else if (globalParams->getPSEmbedTrueType() && + (font->getType() == fontTrueType || + font->getType() == fontTrueTypeOT) && + font->getEmbeddedFontID(&fontFileID)) { + psName = filterPSName(font->getEmbeddedFontName()); + setupEmbeddedTrueTypeFont(font, &fontFileID, psName); + + // check for external TrueType font file + } else if (globalParams->getPSEmbedTrueType() && + font->getType() == fontTrueType && + font->getExtFontFile()) { + psName = filterPSName(font->getName()); + setupExternalTrueTypeFont(font, psName); + + // check for embedded CID PostScript font + } else if (globalParams->getPSEmbedCIDPostScript() && + font->getType() == fontCIDType0C && + font->getEmbeddedFontID(&fontFileID)) { + psName = filterPSName(font->getEmbeddedFontName()); + setupEmbeddedCIDType0Font(font, &fontFileID, psName); + + // check for embedded CID TrueType font + } else if (globalParams->getPSEmbedCIDTrueType() && + (font->getType() == fontCIDType2 || + font->getType() == fontCIDType2OT) && + font->getEmbeddedFontID(&fontFileID)) { + psName = filterPSName(font->getEmbeddedFontName()); + //~ should check to see if font actually uses vertical mode + setupEmbeddedCIDTrueTypeFont(font, &fontFileID, psName, gTrue); + + // check for embedded OpenType - CID CFF font + } else if (globalParams->getPSEmbedCIDPostScript() && + font->getType() == fontCIDType0COT && + font->getEmbeddedFontID(&fontFileID)) { + psName = filterPSName(font->getEmbeddedFontName()); + setupEmbeddedOpenTypeCFFFont(font, &fontFileID, psName); + + // check for Type 3 font + } else if (font->getType() == fontType3) { + psName = GString::format("T3_{0:d}_{1:d}", + font->getID()->num, font->getID()->gen); + setupType3Font(font, psName, parentResDict); + + // do 8-bit font substitution + } else if (!font->isCIDFont()) { + subst = gTrue; + name = font->getName(); + psName = NULL; + if (name) { + for (i = 0; psFonts[i]; ++i) { + if (name->cmp(psFonts[i]) == 0) { + psName = new GString(psFonts[i]); + break; + } + } + } + if (!psName) { + if (font->isFixedWidth()) { + i = 8; + } else if (font->isSerif()) { + i = 4; + } else { + i = 0; + } + if (font->isBold()) { + i += 2; + } + if (font->isItalic()) { + i += 1; + } + psName = new GString(psSubstFonts[i].psName); + for (code = 0; code < 256; ++code) { + if ((charName = ((Gfx8BitFont *)font)->getCharName(code)) && + charName[0] == 'm' && charName[1] == '\0') { + break; + } + } + if (code < 256) { + w1 = ((Gfx8BitFont *)font)->getWidth(code); + } else { + w1 = 0; + } + w2 = psSubstFonts[i].mWidth; + xs = w1 / w2; + if (xs < 0.1) { + xs = 1; + } + if (font->getType() == fontType3) { + // This is a hack which makes it possible to substitute for some + // Type 3 fonts. The problem is that it's impossible to know what + // the base coordinate system used in the font is without actually + // rendering the font. + ys = xs; + fm = font->getFontMatrix(); + if (fm[0] != 0) { + ys *= fm[3] / fm[0]; + } + } else { + ys = 1; + } + } + + // do 16-bit font substitution + } else if ((fontParam = globalParams-> + getPSFont16(font->getName(), + ((GfxCIDFont *)font)->getCollection(), + font->getWMode()))) { + subst = gTrue; + psName = fontParam->psFontName->copy(); + if (font16EncLen >= font16EncSize) { + font16EncSize += 16; + font16Enc = (PSFont16Enc *)greallocn(font16Enc, + font16EncSize, sizeof(PSFont16Enc)); + } + font16Enc[font16EncLen].fontID = *font->getID(); + font16Enc[font16EncLen].enc = fontParam->encoding->copy(); + if ((uMap = globalParams->getUnicodeMap(font16Enc[font16EncLen].enc))) { + uMap->decRefCnt(); + ++font16EncLen; + } else { + error(-1, "Couldn't find Unicode map for 16-bit font encoding '%s'", + font16Enc[font16EncLen].enc->getCString()); + } + + // give up - can't do anything with this font + } else { + error(-1, "Couldn't find a font to substitute for '%s' ('%s' character collection)", + font->getName() ? font->getName()->getCString() : "(unnamed)", + ((GfxCIDFont *)font)->getCollection() + ? ((GfxCIDFont *)font)->getCollection()->getCString() + : "(unknown)"); + return; + } + + // generate PostScript code to set up the font + if (font->isCIDFont()) { + if (level == psLevel3 || level == psLevel3Sep) { + writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16L3\n", + font->getID()->num, font->getID()->gen, psName, + font->getWMode()); + } else { + writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16\n", + font->getID()->num, font->getID()->gen, psName, + font->getWMode()); + } + } else { + writePSFmt("/F{0:d}_{1:d} /{2:t} {3:.4g} {4:.4g}\n", + font->getID()->num, font->getID()->gen, psName, xs, ys); + for (i = 0; i < 256; i += 8) { + writePS((char *)((i == 0) ? "[ " : " ")); + for (j = 0; j < 8; ++j) { + if (font->getType() == fontTrueType && + !subst && + !((Gfx8BitFont *)font)->getHasEncoding()) { + sprintf(buf, "c%02x", i+j); + charName = buf; + } else { + charName = ((Gfx8BitFont *)font)->getCharName(i+j); + // this is a kludge for broken PDF files that encode char 32 + // as .notdef + if (i+j == 32 && charName && !strcmp(charName, ".notdef")) { + charName = "space"; + } + } + writePS("/"); + writePSName(charName ? charName : (char *)".notdef"); + // the empty name is legal in PDF and PostScript, but PostScript + // uses a double-slash (//...) for "immediately evaluated names", + // so we need to add a space character here + if (charName && !charName[0]) { + writePS(" "); + } + } + writePS((i == 256-8) ? (char *)"]\n" : (char *)"\n"); + } + writePS("pdfMakeFont\n"); + } + + delete psName; +} + +void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) { + static char hexChar[17] = "0123456789abcdef"; + Object refObj, strObj, obj1, obj2, obj3; + Dict *dict; + int length1, length2, length3; + int c; + int start[4]; + GBool binMode; + int i; + + // check if font is already embedded + for (i = 0; i < fontFileIDLen; ++i) { + if (fontFileIDs[i].num == id->num && + fontFileIDs[i].gen == id->gen) + return; + } + + // add entry to fontFileIDs list + if (fontFileIDLen >= fontFileIDSize) { + fontFileIDSize += 64; + fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); + } + fontFileIDs[fontFileIDLen++] = *id; + + // get the font stream and info + refObj.initRef(id->num, id->gen); + refObj.fetch(xref, &strObj); + refObj.free(); + if (!strObj.isStream()) { + error(-1, "Embedded font file object is not a stream"); + goto err1; + } + if (!(dict = strObj.streamGetDict())) { + error(-1, "Embedded font stream is missing its dictionary"); + goto err1; + } + dict->lookup("Length1", &obj1); + dict->lookup("Length2", &obj2); + dict->lookup("Length3", &obj3); + if (!obj1.isInt() || !obj2.isInt() || !obj3.isInt()) { + error(-1, "Missing length fields in embedded font stream dictionary"); + obj1.free(); + obj2.free(); + obj3.free(); + goto err1; + } + length1 = obj1.getInt(); + length2 = obj2.getInt(); + length3 = obj3.getInt(); + obj1.free(); + obj2.free(); + obj3.free(); + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // copy ASCII portion of font + strObj.streamReset(); + for (i = 0; i < length1 && (c = strObj.streamGetChar()) != EOF; ++i) { + writePSChar(c); + } + + // figure out if encrypted portion is binary or ASCII + binMode = gFalse; + for (i = 0; i < 4; ++i) { + start[i] = strObj.streamGetChar(); + if (start[i] == EOF) { + error(-1, "Unexpected end of file in embedded font stream"); + goto err1; + } + if (!((start[i] >= '0' && start[i] <= '9') || + (start[i] >= 'A' && start[i] <= 'F') || + (start[i] >= 'a' && start[i] <= 'f'))) + binMode = gTrue; + } + + // convert binary data to ASCII + if (binMode) { + for (i = 0; i < 4; ++i) { + writePSChar(hexChar[(start[i] >> 4) & 0x0f]); + writePSChar(hexChar[start[i] & 0x0f]); + } +#if 0 // this causes trouble for various PostScript printers + // if Length2 is incorrect (too small), font data gets chopped, so + // we take a few extra characters from the trailer just in case + length2 += length3 >= 8 ? 8 : length3; +#endif + while (i < length2) { + if ((c = strObj.streamGetChar()) == EOF) { + break; + } + writePSChar(hexChar[(c >> 4) & 0x0f]); + writePSChar(hexChar[c & 0x0f]); + if (++i % 32 == 0) { + writePSChar('\n'); + } + } + if (i % 32 > 0) { + writePSChar('\n'); + } + + // already in ASCII format -- just copy it + } else { + for (i = 0; i < 4; ++i) { + writePSChar(start[i]); + } + for (i = 4; i < length2; ++i) { + if ((c = strObj.streamGetChar()) == EOF) { + break; + } + writePSChar(c); + } + } + + // write padding and "cleartomark" + for (i = 0; i < 8; ++i) { + writePS("00000000000000000000000000000000" + "00000000000000000000000000000000\n"); + } + writePS("cleartomark\n"); + + // ending comment + writePS("%%EndResource\n"); + + err1: + strObj.streamClose(); + strObj.free(); +} + +//~ This doesn't handle .pfb files or binary eexec data (which only +//~ happens in pfb files?). +void PSOutputDev::setupExternalType1Font(GString *fileName, GString *psName) { + FILE *fontFile; + int c; + int i; + + // check if font is already embedded + for (i = 0; i < fontFileNameLen; ++i) { + if (!fontFileNames[i]->cmp(fileName)) { + return; + } + } + + // add entry to fontFileNames list + if (fontFileNameLen >= fontFileNameSize) { + fontFileNameSize += 64; + fontFileNames = (GString **)greallocn(fontFileNames, + fontFileNameSize, sizeof(GString *)); + } + fontFileNames[fontFileNameLen++] = fileName->copy(); + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // copy the font file + if (!(fontFile = fopen(fileName->getCString(), "rb"))) { + error(-1, "Couldn't open external font file"); + return; + } + while ((c = fgetc(fontFile)) != EOF) { + writePSChar(c); + } + fclose(fontFile); + + // ending comment + writePS("%%EndResource\n"); +} + +void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id, + GString *psName) { + char *fontBuf; + int fontLen; + FoFiType1C *ffT1C; + int i; + + // check if font is already embedded + for (i = 0; i < fontFileIDLen; ++i) { + if (fontFileIDs[i].num == id->num && + fontFileIDs[i].gen == id->gen) + return; + } + + // add entry to fontFileIDs list + if (fontFileIDLen >= fontFileIDSize) { + fontFileIDSize += 64; + fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); + } + fontFileIDs[fontFileIDLen++] = *id; + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 1 font + fontBuf = font->readEmbFontFile(xref, &fontLen); + if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) { + ffT1C->convertToType1(psName->getCString(), NULL, gTrue, + outputFunc, outputStream); + delete ffT1C; + } + gfree(fontBuf); + + // ending comment + writePS("%%EndResource\n"); +} + +void PSOutputDev::setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id, + GString *psName) { + char *fontBuf; + int fontLen; + FoFiTrueType *ffTT; + int i; + + // check if font is already embedded + for (i = 0; i < fontFileIDLen; ++i) { + if (fontFileIDs[i].num == id->num && + fontFileIDs[i].gen == id->gen) + return; + } + + // add entry to fontFileIDs list + if (fontFileIDLen >= fontFileIDSize) { + fontFileIDSize += 64; + fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); + } + fontFileIDs[fontFileIDLen++] = *id; + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 1 font + fontBuf = font->readEmbFontFile(xref, &fontLen); + if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { + if (ffTT->isOpenTypeCFF()) { + ffTT->convertToType1(psName->getCString(), NULL, gTrue, + outputFunc, outputStream); + } + delete ffTT; + } + gfree(fontBuf); + + // ending comment + writePS("%%EndResource\n"); +} + +void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, + GString *psName) { + char *fontBuf; + int fontLen; + FoFiTrueType *ffTT; + Gushort *codeToGID; + int i; + + // check if font is already embedded + for (i = 0; i < fontFileIDLen; ++i) { + if (fontFileIDs[i].num == id->num && + fontFileIDs[i].gen == id->gen) { + psName->appendf("_{0:d}", nextTrueTypeNum++); + break; + } + } + + // add entry to fontFileIDs list + if (i == fontFileIDLen) { + if (fontFileIDLen >= fontFileIDSize) { + fontFileIDSize += 64; + fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); + } + fontFileIDs[fontFileIDLen++] = *id; + } + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 42 font + fontBuf = font->readEmbFontFile(xref, &fontLen); + if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { + codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT); + ffTT->convertToType42(psName->getCString(), + ((Gfx8BitFont *)font)->getHasEncoding() + ? ((Gfx8BitFont *)font)->getEncoding() + : (char **)NULL, + codeToGID, outputFunc, outputStream); + if (codeToGID) { + if (font8InfoLen >= font8InfoSize) { + font8InfoSize += 16; + font8Info = (PSFont8Info *)greallocn(font8Info, + font8InfoSize, + sizeof(PSFont8Info)); + } + font8Info[font8InfoLen].fontID = *font->getID(); + font8Info[font8InfoLen].codeToGID = codeToGID; + ++font8InfoLen; + } + delete ffTT; + } + gfree(fontBuf); + + // ending comment + writePS("%%EndResource\n"); +} + +void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) { + GString *fileName; + char *fontBuf; + int fontLen; + FoFiTrueType *ffTT; + Gushort *codeToGID; + int i; + + // check if font is already embedded + fileName = font->getExtFontFile(); + for (i = 0; i < fontFileNameLen; ++i) { + if (!fontFileNames[i]->cmp(fileName)) { + psName->appendf("_{0:d}", nextTrueTypeNum++); + break; + } + } + + // add entry to fontFileNames list + if (i == fontFileNameLen) { + if (fontFileNameLen >= fontFileNameSize) { + fontFileNameSize += 64; + fontFileNames = + (GString **)greallocn(fontFileNames, + fontFileNameSize, sizeof(GString *)); + } + fontFileNames[fontFileNameLen++] = fileName->copy(); + } + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 42 font + fontBuf = font->readExtFontFile(&fontLen); + if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { + codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT); + ffTT->convertToType42(psName->getCString(), + ((Gfx8BitFont *)font)->getHasEncoding() + ? ((Gfx8BitFont *)font)->getEncoding() + : (char **)NULL, + codeToGID, outputFunc, outputStream); + if (codeToGID) { + if (font8InfoLen >= font8InfoSize) { + font8InfoSize += 16; + font8Info = (PSFont8Info *)greallocn(font8Info, + font8InfoSize, + sizeof(PSFont8Info)); + } + font8Info[font8InfoLen].fontID = *font->getID(); + font8Info[font8InfoLen].codeToGID = codeToGID; + ++font8InfoLen; + } + delete ffTT; + } + gfree(fontBuf); + + // ending comment + writePS("%%EndResource\n"); +} + +void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, + GString *psName) { + char *fontBuf; + int fontLen; + FoFiType1C *ffT1C; + int i; + + // check if font is already embedded + for (i = 0; i < fontFileIDLen; ++i) { + if (fontFileIDs[i].num == id->num && + fontFileIDs[i].gen == id->gen) + return; + } + + // add entry to fontFileIDs list + if (fontFileIDLen >= fontFileIDSize) { + fontFileIDSize += 64; + fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); + } + fontFileIDs[fontFileIDLen++] = *id; + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 0 font + fontBuf = font->readEmbFontFile(xref, &fontLen); + if ((ffT1C = FoFiType1C::make(fontBuf, fontLen))) { + if (globalParams->getPSLevel() >= psLevel3) { + // Level 3: use a CID font + ffT1C->convertToCIDType0(psName->getCString(), outputFunc, outputStream); + } else { + // otherwise: use a non-CID composite font + ffT1C->convertToType0(psName->getCString(), outputFunc, outputStream); + } + delete ffT1C; + } + gfree(fontBuf); + + // ending comment + writePS("%%EndResource\n"); +} + +void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, + GString *psName, + GBool needVerticalMetrics) { + char *fontBuf; + int fontLen; + FoFiTrueType *ffTT; + int i; + + // check if font is already embedded + for (i = 0; i < fontFileIDLen; ++i) { + if (fontFileIDs[i].num == id->num && + fontFileIDs[i].gen == id->gen) { + psName->appendf("_{0:d}", nextTrueTypeNum++); + break; + } + } + + // add entry to fontFileIDs list + if (fontFileIDLen >= fontFileIDSize) { + fontFileIDSize += 64; + fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); + } + fontFileIDs[fontFileIDLen++] = *id; + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 0 font + fontBuf = font->readEmbFontFile(xref, &fontLen); + if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { + if (globalParams->getPSLevel() >= psLevel3) { + // Level 3: use a CID font + ffTT->convertToCIDType2(psName->getCString(), + ((GfxCIDFont *)font)->getCIDToGID(), + ((GfxCIDFont *)font)->getCIDToGIDLen(), + needVerticalMetrics, + outputFunc, outputStream); + } else { + // otherwise: use a non-CID composite font + ffTT->convertToType0(psName->getCString(), + ((GfxCIDFont *)font)->getCIDToGID(), + ((GfxCIDFont *)font)->getCIDToGIDLen(), + needVerticalMetrics, + outputFunc, outputStream); + } + delete ffTT; + } + gfree(fontBuf); + + // ending comment + writePS("%%EndResource\n"); +} + +void PSOutputDev::setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id, + GString *psName) { + char *fontBuf; + int fontLen; + FoFiTrueType *ffTT; + int i; + + // check if font is already embedded + for (i = 0; i < fontFileIDLen; ++i) { + if (fontFileIDs[i].num == id->num && + fontFileIDs[i].gen == id->gen) + return; + } + + // add entry to fontFileIDs list + if (fontFileIDLen >= fontFileIDSize) { + fontFileIDSize += 64; + fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); + } + fontFileIDs[fontFileIDLen++] = *id; + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // convert it to a Type 0 font + fontBuf = font->readEmbFontFile(xref, &fontLen); + if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) { + if (ffTT->isOpenTypeCFF()) { + if (globalParams->getPSLevel() >= psLevel3) { + // Level 3: use a CID font + ffTT->convertToCIDType0(psName->getCString(), + outputFunc, outputStream); + } else { + // otherwise: use a non-CID composite font + ffTT->convertToType0(psName->getCString(), outputFunc, outputStream); + } + } + delete ffTT; + } + gfree(fontBuf); + + // ending comment + writePS("%%EndResource\n"); +} + +void PSOutputDev::setupType3Font(GfxFont *font, GString *psName, + Dict *parentResDict) { + Dict *resDict; + Dict *charProcs; + Object charProc; + Gfx *gfx; + PDFRectangle box; + double *m; + GString *buf; + int i; + + // set up resources used by font + if ((resDict = ((Gfx8BitFont *)font)->getResources())) { + inType3Char = gTrue; + setupResources(resDict); + inType3Char = gFalse; + } else { + resDict = parentResDict; + } + + // beginning comment + writePSFmt("%%BeginResource: font {0:t}\n", psName); + embFontList->append("%%+ font "); + embFontList->append(psName->getCString()); + embFontList->append("\n"); + + // font dictionary + writePS("8 dict begin\n"); + writePS("/FontType 3 def\n"); + m = font->getFontMatrix(); + writePSFmt("/FontMatrix [{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] def\n", + m[0], m[1], m[2], m[3], m[4], m[5]); + m = font->getFontBBox(); + writePSFmt("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n", + m[0], m[1], m[2], m[3]); + writePS("/Encoding 256 array def\n"); + writePS(" 0 1 255 { Encoding exch /.notdef put } for\n"); + writePS("/BuildGlyph {\n"); + writePS(" exch /CharProcs get exch\n"); + writePS(" 2 copy known not { pop /.notdef } if\n"); + writePS(" get exec\n"); + writePS("} bind def\n"); + writePS("/BuildChar {\n"); + writePS(" 1 index /Encoding get exch get\n"); + writePS(" 1 index /BuildGlyph get exec\n"); + writePS("} bind def\n"); + if ((charProcs = ((Gfx8BitFont *)font)->getCharProcs())) { + writePSFmt("/CharProcs {0:d} dict def\n", charProcs->getLength()); + writePS("CharProcs begin\n"); + box.x1 = m[0]; + box.y1 = m[1]; + box.x2 = m[2]; + box.y2 = m[3]; + gfx = new Gfx(xref, this, resDict, &box, NULL); + inType3Char = gTrue; + for (i = 0; i < charProcs->getLength(); ++i) { + t3Cacheable = gFalse; + t3NeedsRestore = gFalse; + writePS("/"); + writePSName(charProcs->getKey(i)); + writePS(" {\n"); + gfx->display(charProcs->getVal(i, &charProc)); + charProc.free(); + if (t3String) { + if (t3Cacheable) { + buf = GString::format("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g} setcachedevice\n", + t3WX, t3WY, t3LLX, t3LLY, t3URX, t3URY); + } else { + buf = GString::format("{0:.4g} {1:.4g} setcharwidth\n", t3WX, t3WY); + } + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + (*outputFunc)(outputStream, t3String->getCString(), + t3String->getLength()); + delete t3String; + t3String = NULL; + } + if (t3NeedsRestore) { + (*outputFunc)(outputStream, "Q\n", 2); + } + writePS("} def\n"); + } + inType3Char = gFalse; + delete gfx; + writePS("end\n"); + } + writePS("currentdict end\n"); + writePSFmt("/{0:t} exch definefont pop\n", psName); + + // ending comment + writePS("%%EndResource\n"); +} + +void PSOutputDev::setupImages(Dict *resDict) { + Object xObjDict, xObj, xObjRef, subtypeObj; + int i; + + if (!(mode == psModeForm || inType3Char || preload)) { + return; + } + + resDict->lookup("XObject", &xObjDict); + if (xObjDict.isDict()) { + for (i = 0; i < xObjDict.dictGetLength(); ++i) { + xObjDict.dictGetValNF(i, &xObjRef); + xObjDict.dictGetVal(i, &xObj); + if (xObj.isStream()) { + xObj.streamGetDict()->lookup("Subtype", &subtypeObj); + if (subtypeObj.isName("Image")) { + if (xObjRef.isRef()) { + setupImage(xObjRef.getRef(), xObj.getStream()); + } else { + error(-1, "Image in resource dict is not an indirect reference"); + } + } + subtypeObj.free(); + } + xObj.free(); + xObjRef.free(); + } + } + xObjDict.free(); +} + +void PSOutputDev::setupImage(Ref id, Stream *str) { + GBool useRLE, useCompressed, useASCIIHex; + GString *s; + int c; + int size, line, col, i; + + // check if image is already setup + for (i = 0; i < imgIDLen; ++i) { + if (imgIDs[i].num == id.num && imgIDs[i].gen == id.gen) { + return; + } + } + + // add entry to imgIDs list + if (imgIDLen >= imgIDSize) { + if (imgIDSize == 0) { + imgIDSize = 64; + } else { + imgIDSize *= 2; + } + imgIDs = (Ref *)greallocn(imgIDs, imgIDSize, sizeof(Ref)); + } + imgIDs[imgIDLen++] = id; + + // filters + //~ this does not correctly handle the DeviceN color space + //~ -- need to use DeviceNRecoder + if (level < psLevel2) { + useRLE = gFalse; + useCompressed = gFalse; + useASCIIHex = gTrue; + } else { + s = str->getPSFilter(level < psLevel3 ? 2 : 3, ""); + if (s) { + useRLE = gFalse; + useCompressed = gTrue; + delete s; + } else { + useRLE = gTrue; + useCompressed = gFalse; + } + useASCIIHex = level == psLevel1 || level == psLevel1Sep || + globalParams->getPSASCIIHex(); + } + if (useCompressed) { + str = str->getUndecodedStream(); + } + if (useRLE) { + str = new RunLengthEncoder(str); + } + if (useASCIIHex) { + str = new ASCIIHexEncoder(str); + } else { + str = new ASCII85Encoder(str); + } + + // compute image data size + str->reset(); + col = size = 0; + do { + do { + c = str->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + if (c == 'z') { + ++col; + } else { + ++col; + for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) { + do { + c = str->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + ++col; + } + } + if (col > 225) { + ++size; + col = 0; + } + } while (c != (useASCIIHex ? '>' : '~') && c != EOF); + // add one entry for the final line of data; add another entry + // because the RunLengthDecode filter may read past the end + ++size; + if (useRLE) { + ++size; + } + writePSFmt("{0:d} array dup /ImData_{1:d}_{2:d} exch def\n", + size, id.num, id.gen); + str->close(); + + // write the data into the array + str->reset(); + line = col = 0; + writePS((char *)(useASCIIHex ? "dup 0 <" : "dup 0 <~")); + do { + do { + c = str->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + if (c == 'z') { + writePSChar(c); + ++col; + } else { + writePSChar(c); + ++col; + for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) { + do { + c = str->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + writePSChar(c); + ++col; + } + } + // each line is: "dup nnnnn <~...data...~> put" + // so max data length = 255 - 20 = 235 + // chunks are 1 or 4 bytes each, so we have to stop at 232 + // but make it 225 just to be safe + if (col > 225) { + writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n")); + ++line; + writePSFmt((char *)(useASCIIHex ? "dup {0:d} <" : "dup {0:d} <~"), line); + col = 0; + } + } while (c != (useASCIIHex ? '>' : '~') && c != EOF); + writePS((char *)(useASCIIHex ? "> put\n" : "~> put\n")); + if (useRLE) { + ++line; + writePSFmt("{0:d} <> put\n", line); + } else { + writePS("pop\n"); + } + str->close(); + + delete str; +} + +void PSOutputDev::setupForms(Dict *resDict) { + Object xObjDict, xObj, xObjRef, subtypeObj; + int i; + + if (!preload) { + return; + } + + resDict->lookup("XObject", &xObjDict); + if (xObjDict.isDict()) { + for (i = 0; i < xObjDict.dictGetLength(); ++i) { + xObjDict.dictGetValNF(i, &xObjRef); + xObjDict.dictGetVal(i, &xObj); + if (xObj.isStream()) { + xObj.streamGetDict()->lookup("Subtype", &subtypeObj); + if (subtypeObj.isName("Form")) { + if (xObjRef.isRef()) { + setupForm(xObjRef.getRef(), &xObj); + } else { + error(-1, "Form in resource dict is not an indirect reference"); + } + } + subtypeObj.free(); + } + xObj.free(); + xObjRef.free(); + } + } + xObjDict.free(); +} + +void PSOutputDev::setupForm(Ref id, Object *strObj) { + Dict *dict, *resDict; + Object matrixObj, bboxObj, resObj, obj1; + double m[6], bbox[4]; + PDFRectangle box; + Gfx *gfx; + int i; + + // check if form is already defined + for (i = 0; i < formIDLen; ++i) { + if (formIDs[i].num == id.num && formIDs[i].gen == id.gen) { + return; + } + } + + // add entry to formIDs list + if (formIDLen >= formIDSize) { + if (formIDSize == 0) { + formIDSize = 64; + } else { + formIDSize *= 2; + } + formIDs = (Ref *)greallocn(formIDs, formIDSize, sizeof(Ref)); + } + formIDs[formIDLen++] = id; + + dict = strObj->streamGetDict(); + + // get bounding box + dict->lookup("BBox", &bboxObj); + if (!bboxObj.isArray()) { + bboxObj.free(); + error(-1, "Bad form bounding box"); + return; + } + for (i = 0; i < 4; ++i) { + bboxObj.arrayGet(i, &obj1); + bbox[i] = obj1.getNum(); + obj1.free(); + } + bboxObj.free(); + + // get matrix + dict->lookup("Matrix", &matrixObj); + if (matrixObj.isArray()) { + for (i = 0; i < 6; ++i) { + matrixObj.arrayGet(i, &obj1); + m[i] = obj1.getNum(); + obj1.free(); + } + } else { + m[0] = 1; m[1] = 0; + m[2] = 0; m[3] = 1; + m[4] = 0; m[5] = 0; + } + matrixObj.free(); + + // get resources + dict->lookup("Resources", &resObj); + resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; + + writePSFmt("/f_{0:d}_{1:d} {{\n", id.num, id.gen); + writePS("q\n"); + writePSFmt("[{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] cm\n", + m[0], m[1], m[2], m[3], m[4], m[5]); + + box.x1 = bbox[0]; + box.y1 = bbox[1]; + box.x2 = bbox[2]; + box.y2 = bbox[3]; + gfx = new Gfx(xref, this, resDict, &box, &box); + gfx->display(strObj); + delete gfx; + + writePS("Q\n"); + writePS("} def\n"); + + resObj.free(); +} + +GBool PSOutputDev::checkPageSlice(Page *page, double hDPI, double vDPI, + int rotateA, GBool useMediaBox, GBool crop, + int sliceX, int sliceY, + int sliceW, int sliceH, + GBool printing, Catalog *catalog, + GBool (*abortCheckCbk)(void *data), + void *abortCheckCbkData) { +#if HAVE_SPLASH + PreScanOutputDev *scan; + GBool rasterize; + SplashOutputDev *splashOut; + SplashColor paperColor; + PDFRectangle box; + GfxState *state; + SplashBitmap *bitmap; + Stream *str0, *str; + Object obj; + Guchar *p; + Guchar col[4]; + double m0, m1, m2, m3, m4, m5; + int c, w, h, x, y, comp, i; + + scan = new PreScanOutputDev(); + page->displaySlice(scan, 72, 72, rotateA, useMediaBox, crop, + sliceX, sliceY, sliceW, sliceH, + printing, catalog, abortCheckCbk, abortCheckCbkData); + rasterize = scan->usesTransparency(); + delete scan; + if (!rasterize) { + return gTrue; + } + + // rasterize the page + if (level == psLevel1) { + paperColor[0] = 0xff; + splashOut = new SplashOutputDev(splashModeMono8, 1, gFalse, + paperColor, gTrue, gFalse); +#if SPLASH_CMYK + } else if (level == psLevel1Sep) { + paperColor[0] = paperColor[1] = paperColor[2] = paperColor[3] = 0; + splashOut = new SplashOutputDev(splashModeCMYK8, 1, gFalse, + paperColor, gTrue, gFalse); +#endif + } else { + paperColor[0] = paperColor[1] = paperColor[2] = 0xff; + splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, + paperColor, gTrue, gFalse); + } + splashOut->startDoc(xref); + page->displaySlice(splashOut, splashDPI, splashDPI, rotateA, + useMediaBox, crop, + sliceX, sliceY, sliceW, sliceH, + printing, catalog, abortCheckCbk, abortCheckCbkData); + + // start the PS page + page->makeBox(splashDPI, splashDPI, rotateA, useMediaBox, gFalse, + sliceX, sliceY, sliceW, sliceH, &box, &crop); + rotateA += page->getRotate(); + if (rotateA >= 360) { + rotateA -= 360; + } else if (rotateA < 0) { + rotateA += 360; + } + state = new GfxState(splashDPI, splashDPI, &box, rotateA, gFalse); + startPage(page->getNum(), state); + delete state; + switch (rotateA) { + case 0: + default: // this should never happen + m0 = box.x2 - box.x1; + m1 = 0; + m2 = 0; + m3 = box.y2 - box.y1; + m4 = box.x1; + m5 = box.y1; + break; + case 90: + m0 = 0; + m1 = box.y2 - box.y1; + m2 = -(box.x2 - box.x1); + m3 = 0; + m4 = box.x2; + m5 = box.y1; + break; + case 180: + m0 = -(box.x2 - box.x1); + m1 = 0; + m2 = 0; + m3 = -(box.y2 - box.y1); + m4 = box.x2; + m5 = box.y2; + break; + case 270: + m0 = 0; + m1 = -(box.y2 - box.y1); + m2 = box.x2 - box.x1; + m3 = 0; + m4 = box.x1; + m5 = box.y2; + break; + } + + //~ need to add the process colors + + // draw the rasterized image + bitmap = splashOut->getBitmap(); + w = bitmap->getWidth(); + h = bitmap->getHeight(); + writePS("gsave\n"); + writePSFmt("[{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] concat\n", + m0, m1, m2, m3, m4, m5); + switch (level) { + case psLevel1: + writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1\n", + w, h, w, -h, h); + p = bitmap->getDataPtr(); + i = 0; + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + writePSFmt("{0:02x}", *p++); + if (++i == 32) { + writePSChar('\n'); + i = 0; + } + } + } + if (i != 0) { + writePSChar('\n'); + } + break; + case psLevel1Sep: + writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1Sep\n", + w, h, w, -h, h); + p = bitmap->getDataPtr(); + i = 0; + col[0] = col[1] = col[2] = col[3] = 0; + for (y = 0; y < h; ++y) { + for (comp = 0; comp < 4; ++comp) { + for (x = 0; x < w; ++x) { + writePSFmt("{0:02x}", p[4*x + comp]); + col[comp] |= p[4*x + comp]; + if (++i == 32) { + writePSChar('\n'); + i = 0; + } + } + } + p += bitmap->getRowSize(); + } + if (i != 0) { + writePSChar('\n'); + } + if (col[0]) { + processColors |= psProcessCyan; + } + if (col[1]) { + processColors |= psProcessMagenta; + } + if (col[2]) { + processColors |= psProcessYellow; + } + if (col[3]) { + processColors |= psProcessBlack; + } + break; + case psLevel2: + case psLevel2Sep: + case psLevel3: + case psLevel3Sep: + writePS("/DeviceRGB setcolorspace\n"); + writePS("<<\n /ImageType 1\n"); + writePSFmt(" /Width {0:d}\n", bitmap->getWidth()); + writePSFmt(" /Height {0:d}\n", bitmap->getHeight()); + writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", w, -h, h); + writePS(" /BitsPerComponent 8\n"); + writePS(" /Decode [0 1 0 1 0 1]\n"); + writePS(" /DataSource currentfile\n"); + if (globalParams->getPSASCIIHex()) { + writePS(" /ASCIIHexDecode filter\n"); + } else { + writePS(" /ASCII85Decode filter\n"); + } + writePS(" /RunLengthDecode filter\n"); + writePS(">>\n"); + writePS("image\n"); + obj.initNull(); + str0 = new MemStream((char *)bitmap->getDataPtr(), 0, w * h * 3, &obj); + str = new RunLengthEncoder(str0); + if (globalParams->getPSASCIIHex()) { + str = new ASCIIHexEncoder(str); + } else { + str = new ASCII85Encoder(str); + } + str->reset(); + while ((c = str->getChar()) != EOF) { + writePSChar(c); + } + str->close(); + delete str; + delete str0; + processColors |= psProcessCMYK; + break; + } + delete splashOut; + writePS("grestore\n"); + + // finish the PS page + endPage(); + + return gFalse; +#else + return gTrue; +#endif +} + +void PSOutputDev::startPage(int pageNum, GfxState *state) { + int x1, y1, x2, y2, width, height; + int imgWidth, imgHeight, imgWidth2, imgHeight2; + GBool landscape; + + + if (mode == psModePS) { + writePSFmt("%%Page: {0:d} {1:d}\n", pageNum, seqPage); + writePS("%%BeginPageSetup\n"); + } + + // underlays + if (underlayCbk) { + (*underlayCbk)(this, underlayCbkData); + } + if (overlayCbk) { + saveState(NULL); + } + + switch (mode) { + + case psModePS: + // rotate, translate, and scale page + imgWidth = imgURX - imgLLX; + imgHeight = imgURY - imgLLY; + x1 = (int)floor(state->getX1()); + y1 = (int)floor(state->getY1()); + x2 = (int)ceil(state->getX2()); + y2 = (int)ceil(state->getY2()); + width = x2 - x1; + height = y2 - y1; + tx = ty = 0; + // rotation and portrait/landscape mode + if (rotate0 >= 0) { + rotate = (360 - rotate0) % 360; + landscape = gFalse; + } else { + rotate = (360 - state->getRotate()) % 360; + if (rotate == 0 || rotate == 180) { + if (width > height && width > imgWidth) { + rotate += 90; + landscape = gTrue; + } else { + landscape = gFalse; + } + } else { // rotate == 90 || rotate == 270 + if (height > width && height > imgWidth) { + rotate = 270 - rotate; + landscape = gTrue; + } else { + landscape = gFalse; + } + } + } + writePSFmt("%%PageOrientation: {0:s}\n", + landscape ? "Landscape" : "Portrait"); + writePS("pdfStartPage\n"); + if (rotate == 0) { + imgWidth2 = imgWidth; + imgHeight2 = imgHeight; + } else if (rotate == 90) { + writePS("90 rotate\n"); + ty = -imgWidth; + imgWidth2 = imgHeight; + imgHeight2 = imgWidth; + } else if (rotate == 180) { + writePS("180 rotate\n"); + imgWidth2 = imgWidth; + imgHeight2 = imgHeight; + tx = -imgWidth; + ty = -imgHeight; + } else { // rotate == 270 + writePS("270 rotate\n"); + tx = -imgHeight; + imgWidth2 = imgHeight; + imgHeight2 = imgWidth; + } + // shrink or expand + if (xScale0 > 0 && yScale0 > 0) { + xScale = xScale0; + yScale = yScale0; + } else if ((globalParams->getPSShrinkLarger() && + (width > imgWidth2 || height > imgHeight2)) || + (globalParams->getPSExpandSmaller() && + (width < imgWidth2 && height < imgHeight2))) { + xScale = (double)imgWidth2 / (double)width; + yScale = (double)imgHeight2 / (double)height; + if (yScale < xScale) { + xScale = yScale; + } else { + yScale = xScale; + } + } else { + xScale = yScale = 1; + } + // deal with odd bounding boxes or clipping + if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) { + tx -= xScale * clipLLX0; + ty -= yScale * clipLLY0; + } else { + tx -= xScale * x1; + ty -= yScale * y1; + } + // center + if (tx0 >= 0 && ty0 >= 0) { + tx += rotate == 0 ? tx0 : ty0; + ty += rotate == 0 ? ty0 : -tx0; + } else if (globalParams->getPSCenter()) { + if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) { + tx += (imgWidth2 - xScale * (clipURX0 - clipLLX0)) / 2; + ty += (imgHeight2 - yScale * (clipURY0 - clipLLY0)) / 2; + } else { + tx += (imgWidth2 - xScale * width) / 2; + ty += (imgHeight2 - yScale * height) / 2; + } + } + tx += rotate == 0 ? imgLLX : imgLLY; + ty += rotate == 0 ? imgLLY : -imgLLX; + if (tx != 0 || ty != 0) { + writePSFmt("{0:.4g} {1:.4g} translate\n", tx, ty); + } + if (xScale != 1 || yScale != 1) { + writePSFmt("{0:.4f} {0:.4f} scale\n", xScale); + } + if (clipLLX0 < clipURX0 && clipLLY0 < clipURY0) { + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} re W\n", + clipLLX0, clipLLY0, clipURX0 - clipLLX0, clipURY0 - clipLLY0); + } else { + writePSFmt("{0:d} {1:d} {2:d} {3:d} re W\n", x1, y1, x2 - x1, y2 - y1); + } + + writePS("%%EndPageSetup\n"); + ++seqPage; + break; + + case psModeEPS: + writePS("pdfStartPage\n"); + tx = ty = 0; + rotate = (360 - state->getRotate()) % 360; + if (rotate == 0) { + } else if (rotate == 90) { + writePS("90 rotate\n"); + tx = -epsX1; + ty = -epsY2; + } else if (rotate == 180) { + writePS("180 rotate\n"); + tx = -(epsX1 + epsX2); + ty = -(epsY1 + epsY2); + } else { // rotate == 270 + writePS("270 rotate\n"); + tx = -epsX2; + ty = -epsY1; + } + if (tx != 0 || ty != 0) { + writePSFmt("{0:.4g} {1:.4g} translate\n", tx, ty); + } + xScale = yScale = 1; + break; + + case psModeForm: + writePS("/PaintProc {\n"); + writePS("begin xpdf begin\n"); + writePS("pdfStartPage\n"); + tx = ty = 0; + xScale = yScale = 1; + rotate = 0; + break; + } +} + +void PSOutputDev::endPage() { + if (overlayCbk) { + restoreState(NULL); + (*overlayCbk)(this, overlayCbkData); + } + + + if (mode == psModeForm) { + writePS("pdfEndPage\n"); + writePS("end end\n"); + writePS("} def\n"); + writePS("end end\n"); + } else { + if (!manualCtrl) { + writePS("showpage\n"); + } + writePS("%%PageTrailer\n"); + writePageTrailer(); + } +} + +void PSOutputDev::saveState(GfxState *state) { + writePS("q\n"); + ++numSaves; +} + +void PSOutputDev::restoreState(GfxState *state) { + writePS("Q\n"); + --numSaves; +} + +void PSOutputDev::updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32) { + writePSFmt("[{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] cm\n", + m11, m12, m21, m22, m31, m32); +} + +void PSOutputDev::updateLineDash(GfxState *state) { + double *dash; + double start; + int length, i; + + state->getLineDash(&dash, &length, &start); + writePS("["); + for (i = 0; i < length; ++i) { + writePSFmt("{0:.4g}{1:w}", + dash[i] < 0 ? 0 : dash[i], + (i == length-1) ? 0 : 1); + } + writePSFmt("] {0:.4g} d\n", start); +} + +void PSOutputDev::updateFlatness(GfxState *state) { + writePSFmt("{0:d} i\n", state->getFlatness()); +} + +void PSOutputDev::updateLineJoin(GfxState *state) { + writePSFmt("{0:d} j\n", state->getLineJoin()); +} + +void PSOutputDev::updateLineCap(GfxState *state) { + writePSFmt("{0:d} J\n", state->getLineCap()); +} + +void PSOutputDev::updateMiterLimit(GfxState *state) { + writePSFmt("{0:.4g} M\n", state->getMiterLimit()); +} + +void PSOutputDev::updateLineWidth(GfxState *state) { + writePSFmt("{0:.4g} w\n", state->getLineWidth()); +} + +void PSOutputDev::updateFillColorSpace(GfxState *state) { + switch (level) { + case psLevel1: + case psLevel1Sep: + break; + case psLevel2: + case psLevel3: + if (state->getFillColorSpace()->getMode() != csPattern) { + dumpColorSpaceL2(state->getFillColorSpace(), gTrue, gFalse, gFalse); + writePS(" cs\n"); + } + break; + case psLevel2Sep: + case psLevel3Sep: + break; + } +} + +void PSOutputDev::updateStrokeColorSpace(GfxState *state) { + switch (level) { + case psLevel1: + case psLevel1Sep: + break; + case psLevel2: + case psLevel3: + if (state->getStrokeColorSpace()->getMode() != csPattern) { + dumpColorSpaceL2(state->getStrokeColorSpace(), gTrue, gFalse, gFalse); + writePS(" CS\n"); + } + break; + case psLevel2Sep: + case psLevel3Sep: + break; + } +} + +void PSOutputDev::updateFillColor(GfxState *state) { + GfxColor color; + GfxColor *colorPtr; + GfxGray gray; + GfxCMYK cmyk; + GfxSeparationColorSpace *sepCS; + double c, m, y, k; + int i; + + switch (level) { + case psLevel1: + state->getFillGray(&gray); + writePSFmt("{0:.4g} g\n", colToDbl(gray)); + break; + case psLevel1Sep: + state->getFillCMYK(&cmyk); + c = colToDbl(cmyk.c); + m = colToDbl(cmyk.m); + y = colToDbl(cmyk.y); + k = colToDbl(cmyk.k); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} k\n", c, m, y, k); + addProcessColor(c, m, y, k); + break; + case psLevel2: + case psLevel3: + if (state->getFillColorSpace()->getMode() != csPattern) { + colorPtr = state->getFillColor(); + writePS("["); + for (i = 0; i < state->getFillColorSpace()->getNComps(); ++i) { + if (i > 0) { + writePS(" "); + } + writePSFmt("{0:.4g}", colToDbl(colorPtr->c[i])); + } + writePS("] sc\n"); + } + break; + case psLevel2Sep: + case psLevel3Sep: + if (state->getFillColorSpace()->getMode() == csSeparation) { + sepCS = (GfxSeparationColorSpace *)state->getFillColorSpace(); + color.c[0] = gfxColorComp1; + sepCS->getCMYK(&color, &cmyk); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} ({5:t}) ck\n", + colToDbl(state->getFillColor()->c[0]), + colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k), + sepCS->getName()); + addCustomColor(sepCS); + } else { + state->getFillCMYK(&cmyk); + c = colToDbl(cmyk.c); + m = colToDbl(cmyk.m); + y = colToDbl(cmyk.y); + k = colToDbl(cmyk.k); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} k\n", c, m, y, k); + addProcessColor(c, m, y, k); + } + break; + } + t3Cacheable = gFalse; +} + +void PSOutputDev::updateStrokeColor(GfxState *state) { + GfxColor color; + GfxColor *colorPtr; + GfxGray gray; + GfxCMYK cmyk; + GfxSeparationColorSpace *sepCS; + double c, m, y, k; + int i; + + switch (level) { + case psLevel1: + state->getStrokeGray(&gray); + writePSFmt("{0:.4g} G\n", colToDbl(gray)); + break; + case psLevel1Sep: + state->getStrokeCMYK(&cmyk); + c = colToDbl(cmyk.c); + m = colToDbl(cmyk.m); + y = colToDbl(cmyk.y); + k = colToDbl(cmyk.k); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} K\n", c, m, y, k); + addProcessColor(c, m, y, k); + break; + case psLevel2: + case psLevel3: + if (state->getStrokeColorSpace()->getMode() != csPattern) { + colorPtr = state->getStrokeColor(); + writePS("["); + for (i = 0; i < state->getStrokeColorSpace()->getNComps(); ++i) { + if (i > 0) { + writePS(" "); + } + writePSFmt("{0:.4g}", colToDbl(colorPtr->c[i])); + } + writePS("] SC\n"); + } + break; + case psLevel2Sep: + case psLevel3Sep: + if (state->getStrokeColorSpace()->getMode() == csSeparation) { + sepCS = (GfxSeparationColorSpace *)state->getStrokeColorSpace(); + color.c[0] = gfxColorComp1; + sepCS->getCMYK(&color, &cmyk); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} ({5:t}) CK\n", + colToDbl(state->getStrokeColor()->c[0]), + colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k), + sepCS->getName()); + addCustomColor(sepCS); + } else { + state->getStrokeCMYK(&cmyk); + c = colToDbl(cmyk.c); + m = colToDbl(cmyk.m); + y = colToDbl(cmyk.y); + k = colToDbl(cmyk.k); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} K\n", c, m, y, k); + addProcessColor(c, m, y, k); + } + break; + } + t3Cacheable = gFalse; +} + +void PSOutputDev::addProcessColor(double c, double m, double y, double k) { + if (c > 0) { + processColors |= psProcessCyan; + } + if (m > 0) { + processColors |= psProcessMagenta; + } + if (y > 0) { + processColors |= psProcessYellow; + } + if (k > 0) { + processColors |= psProcessBlack; + } +} + +void PSOutputDev::addCustomColor(GfxSeparationColorSpace *sepCS) { + PSOutCustomColor *cc; + GfxColor color; + GfxCMYK cmyk; + + for (cc = customColors; cc; cc = cc->next) { + if (!cc->name->cmp(sepCS->getName())) { + return; + } + } + color.c[0] = gfxColorComp1; + sepCS->getCMYK(&color, &cmyk); + cc = new PSOutCustomColor(colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k), + sepCS->getName()->copy()); + cc->next = customColors; + customColors = cc; +} + +void PSOutputDev::updateFillOverprint(GfxState *state) { + if (level >= psLevel2) { + writePSFmt("{0:s} op\n", state->getFillOverprint() ? "true" : "false"); + } +} + +void PSOutputDev::updateStrokeOverprint(GfxState *state) { + if (level >= psLevel2) { + writePSFmt("{0:s} OP\n", state->getStrokeOverprint() ? "true" : "false"); + } +} + +void PSOutputDev::updateTransfer(GfxState *state) { + Function **funcs; + int i; + + funcs = state->getTransfer(); + if (funcs[0] && funcs[1] && funcs[2] && funcs[3]) { + if (level >= psLevel2) { + for (i = 0; i < 4; ++i) { + cvtFunction(funcs[i]); + } + writePS("setcolortransfer\n"); + } else { + cvtFunction(funcs[3]); + writePS("settransfer\n"); + } + } else if (funcs[0]) { + cvtFunction(funcs[0]); + writePS("settransfer\n"); + } else { + writePS("{} settransfer\n"); + } +} + +void PSOutputDev::updateFont(GfxState *state) { + if (state->getFont()) { + writePSFmt("/F{0:d}_{1:d} {2:.4g} Tf\n", + state->getFont()->getID()->num, state->getFont()->getID()->gen, + fabs(state->getFontSize()) < 0.00001 ? 0.00001 + : state->getFontSize()); + } +} + +void PSOutputDev::updateTextMat(GfxState *state) { + double *mat; + + mat = state->getTextMat(); + if (fabs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.00001) { + // avoid a singular (or close-to-singular) matrix + writePSFmt("[0.00001 0 0 0.00001 {0:.4g} {1:.4g}] Tm\n", mat[4], mat[5]); + } else { + writePSFmt("[{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] Tm\n", + mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); + } +} + +void PSOutputDev::updateCharSpace(GfxState *state) { + writePSFmt("{0:.4g} Tc\n", state->getCharSpace()); +} + +void PSOutputDev::updateRender(GfxState *state) { + int rm; + + rm = state->getRender(); + writePSFmt("{0:d} Tr\n", rm); + rm &= 3; + if (rm != 0 && rm != 3) { + t3Cacheable = gFalse; + } +} + +void PSOutputDev::updateRise(GfxState *state) { + writePSFmt("{0:.4g} Ts\n", state->getRise()); +} + +void PSOutputDev::updateWordSpace(GfxState *state) { + writePSFmt("{0:.4g} Tw\n", state->getWordSpace()); +} + +void PSOutputDev::updateHorizScaling(GfxState *state) { + double h; + + h = state->getHorizScaling(); + if (fabs(h) < 0.01) { + h = 0.01; + } + writePSFmt("{0:.4g} Tz\n", h); +} + +void PSOutputDev::updateTextPos(GfxState *state) { + writePSFmt("{0:.4g} {1:.4g} Td\n", state->getLineX(), state->getLineY()); +} + +void PSOutputDev::updateTextShift(GfxState *state, double shift) { + if (state->getFont()->getWMode()) { + writePSFmt("{0:.4g} TJmV\n", shift); + } else { + writePSFmt("{0:.4g} TJm\n", shift); + } +} + +void PSOutputDev::stroke(GfxState *state) { + doPath(state->getPath()); + if (t3String) { + // if we're construct a cacheable Type 3 glyph, we need to do + // everything in the fill color + writePS("Sf\n"); + } else { + writePS("S\n"); + } +} + +void PSOutputDev::fill(GfxState *state) { + doPath(state->getPath()); + writePS("f\n"); +} + +void PSOutputDev::eoFill(GfxState *state) { + doPath(state->getPath()); + writePS("f*\n"); +} + +void PSOutputDev::tilingPatternFill(GfxState *state, Object *str, + int paintType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep) { + PDFRectangle box; + Gfx *gfx; + + // define a Type 3 font + writePS("8 dict begin\n"); + writePS("/FontType 3 def\n"); + writePS("/FontMatrix [1 0 0 1 0 0] def\n"); + writePSFmt("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n", + bbox[0], bbox[1], bbox[2], bbox[3]); + writePS("/Encoding 256 array def\n"); + writePS(" 0 1 255 { Encoding exch /.notdef put } for\n"); + writePS(" Encoding 120 /x put\n"); + writePS("/BuildGlyph {\n"); + writePS(" exch /CharProcs get exch\n"); + writePS(" 2 copy known not { pop /.notdef } if\n"); + writePS(" get exec\n"); + writePS("} bind def\n"); + writePS("/BuildChar {\n"); + writePS(" 1 index /Encoding get exch get\n"); + writePS(" 1 index /BuildGlyph get exec\n"); + writePS("} bind def\n"); + writePS("/CharProcs 1 dict def\n"); + writePS("CharProcs begin\n"); + box.x1 = bbox[0]; + box.y1 = bbox[1]; + box.x2 = bbox[2]; + box.y2 = bbox[3]; + gfx = new Gfx(xref, this, resDict, &box, NULL); + writePS("/x {\n"); + if (paintType == 2) { + writePSFmt("{0:.4g} 0 {1:.4g} {2:.4g} {3:.4g} {4:.4g} setcachedevice\n", + xStep, bbox[0], bbox[1], bbox[2], bbox[3]); + } else { + if (x1 - 1 <= x0) { + writePS("1 0 setcharwidth\n"); + } else { + writePSFmt("{0:.4g} 0 setcharwidth\n", xStep); + } + } + inType3Char = gTrue; + ++numTilingPatterns; + gfx->display(str); + --numTilingPatterns; + inType3Char = gFalse; + writePS("} def\n"); + delete gfx; + writePS("end\n"); + writePS("currentdict end\n"); + writePSFmt("/xpdfTile{0:d} exch definefont pop\n", numTilingPatterns); + + // draw the tiles + writePSFmt("/xpdfTile{0:d} findfont setfont\n", numTilingPatterns); + writePSFmt("gsave [{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] concat\n", + mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); + writePSFmt("{0:d} 1 {1:d} {{ {2:.4g} exch {3:.4g} mul m {4:d} 1 {5:d} {{ pop (x) show }} for }} for\n", + y0, y1 - 1, x0 * xStep, yStep, x0, x1 - 1); + writePS("grestore\n"); +} + +GBool PSOutputDev::functionShadedFill(GfxState *state, + GfxFunctionShading *shading) { + double x0, y0, x1, y1; + double *mat; + int i; + + if (level == psLevel2Sep || level == psLevel3Sep) { + if (shading->getColorSpace()->getMode() != csDeviceCMYK) { + return gFalse; + } + processColors |= psProcessCMYK; + } + + shading->getDomain(&x0, &y0, &x1, &y1); + mat = shading->getMatrix(); + writePSFmt("/mat [{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g}] def\n", + mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); + writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps()); + if (shading->getNFuncs() == 1) { + writePS("/func "); + cvtFunction(shading->getFunc(0)); + writePS("def\n"); + } else { + writePS("/func {\n"); + for (i = 0; i < shading->getNFuncs(); ++i) { + if (i < shading->getNFuncs() - 1) { + writePS("2 copy\n"); + } + cvtFunction(shading->getFunc(i)); + writePS("exec\n"); + if (i < shading->getNFuncs() - 1) { + writePS("3 1 roll\n"); + } + } + writePS("} def\n"); + } + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} 0 funcSH\n", x0, y0, x1, y1); + + return gTrue; +} + +GBool PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading) { + double xMin, yMin, xMax, yMax; + double x0, y0, x1, y1, dx, dy, mul; + double tMin, tMax, t, t0, t1; + int i; + + if (level == psLevel2Sep || level == psLevel3Sep) { + if (shading->getColorSpace()->getMode() != csDeviceCMYK) { + return gFalse; + } + processColors |= psProcessCMYK; + } + + // get the clip region bbox + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + + // compute min and max t values, based on the four corners of the + // clip region bbox + shading->getCoords(&x0, &y0, &x1, &y1); + dx = x1 - x0; + dy = y1 - y0; + if (fabs(dx) < 0.01 && fabs(dy) < 0.01) { + return gTrue; + } else { + mul = 1 / (dx * dx + dy * dy); + tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul; + t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul; + if (t < tMin) { + tMin = t; + } else if (t > tMax) { + tMax = t; + } + t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul; + if (t < tMin) { + tMin = t; + } else if (t > tMax) { + tMax = t; + } + t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul; + if (t < tMin) { + tMin = t; + } else if (t > tMax) { + tMax = t; + } + if (tMin < 0 && !shading->getExtend0()) { + tMin = 0; + } + if (tMax > 1 && !shading->getExtend1()) { + tMax = 1; + } + } + + // get the function domain + t0 = shading->getDomain0(); + t1 = shading->getDomain1(); + + // generate the PS code + writePSFmt("/t0 {0:.4g} def\n", t0); + writePSFmt("/t1 {0:.4g} def\n", t1); + writePSFmt("/dt {0:.4g} def\n", t1 - t0); + writePSFmt("/x0 {0:.4g} def\n", x0); + writePSFmt("/y0 {0:.4g} def\n", y0); + writePSFmt("/dx {0:.4g} def\n", x1 - x0); + writePSFmt("/x1 {0:.4g} def\n", x1); + writePSFmt("/y1 {0:.4g} def\n", y1); + writePSFmt("/dy {0:.4g} def\n", y1 - y0); + writePSFmt("/xMin {0:.4g} def\n", xMin); + writePSFmt("/yMin {0:.4g} def\n", yMin); + writePSFmt("/xMax {0:.4g} def\n", xMax); + writePSFmt("/yMax {0:.4g} def\n", yMax); + writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps()); + if (shading->getNFuncs() == 1) { + writePS("/func "); + cvtFunction(shading->getFunc(0)); + writePS("def\n"); + } else { + writePS("/func {\n"); + for (i = 0; i < shading->getNFuncs(); ++i) { + if (i < shading->getNFuncs() - 1) { + writePS("dup\n"); + } + cvtFunction(shading->getFunc(i)); + writePS("exec\n"); + if (i < shading->getNFuncs() - 1) { + writePS("exch\n"); + } + } + writePS("} def\n"); + } + writePSFmt("{0:.4g} {1:.4g} 0 axialSH\n", tMin, tMax); + + return gTrue; +} + +GBool PSOutputDev::radialShadedFill(GfxState *state, + GfxRadialShading *shading) { + double xMin, yMin, xMax, yMax; + double x0, y0, r0, x1, y1, r1, t0, t1; + double xa, ya, ra; + double sz, xz, yz, sMin, sMax, sa, ta; + double theta, alpha, a1, a2; + GBool enclosed; + int i; + + if (level == psLevel2Sep || level == psLevel3Sep) { + if (shading->getColorSpace()->getMode() != csDeviceCMYK) { + return gFalse; + } + processColors |= psProcessCMYK; + } + + // get the shading info + shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); + t0 = shading->getDomain0(); + t1 = shading->getDomain1(); + + // Compute the point at which r(s) = 0; check for the enclosed + // circles case; and compute the angles for the tangent lines. + if (r0 == r1) { + enclosed = x0 == x1 && y0 == y1; + theta = 0; + sz = 0; // make gcc happy + } else { + sz = -r0 / (r1 - r0); + xz = x0 + sz * (x1 - x0); + yz = y0 + sz * (y1 - y0); + enclosed = (xz - x0) * (xz - x0) + (yz - y0) * (yz - y0) <= r0 * r0; + theta = asin(r0 / sqrt((x0 - xz) * (x0 - xz) + (y0 - yz) * (y0 - yz))); + if (r0 > r1) { + theta = -theta; + } + } + if (enclosed) { + a1 = 0; + a2 = 360; + } else { + alpha = atan2(y1 - y0, x1 - x0); + a1 = (180 / M_PI) * (alpha + theta) + 90; + a2 = (180 / M_PI) * (alpha - theta) - 90; + while (a2 < a1) { + a2 += 360; + } + } + + // compute the (possibly extended) s range + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + if (enclosed) { + sMin = 0; + sMax = 1; + } else { + sMin = 1; + sMax = 0; + // solve for x(s) + r(s) = xMin + if ((x1 + r1) - (x0 + r0) != 0) { + sa = (xMin - (x0 + r0)) / ((x1 + r1) - (x0 + r0)); + if (sa < sMin) { + sMin = sa; + } else if (sa > sMax) { + sMax = sa; + } + } + // solve for x(s) - r(s) = xMax + if ((x1 - r1) - (x0 - r0) != 0) { + sa = (xMax - (x0 - r0)) / ((x1 - r1) - (x0 - r0)); + if (sa < sMin) { + sMin = sa; + } else if (sa > sMax) { + sMax = sa; + } + } + // solve for y(s) + r(s) = yMin + if ((y1 + r1) - (y0 + r0) != 0) { + sa = (yMin - (y0 + r0)) / ((y1 + r1) - (y0 + r0)); + if (sa < sMin) { + sMin = sa; + } else if (sa > sMax) { + sMax = sa; + } + } + // solve for y(s) - r(s) = yMax + if ((y1 - r1) - (y0 - r0) != 0) { + sa = (yMax - (y0 - r0)) / ((y1 - r1) - (y0 - r0)); + if (sa < sMin) { + sMin = sa; + } else if (sa > sMax) { + sMax = sa; + } + } + // check against sz + if (r0 < r1) { + if (sMin < sz) { + sMin = sz; + } + } else if (r0 > r1) { + if (sMax > sz) { + sMax = sz; + } + } + // check the 'extend' flags + if (!shading->getExtend0() && sMin < 0) { + sMin = 0; + } + if (!shading->getExtend1() && sMax > 1) { + sMax = 1; + } + } + + // generate the PS code + writePSFmt("/x0 {0:.4g} def\n", x0); + writePSFmt("/x1 {0:.4g} def\n", x1); + writePSFmt("/dx {0:.4g} def\n", x1 - x0); + writePSFmt("/y0 {0:.4g} def\n", y0); + writePSFmt("/y1 {0:.4g} def\n", y1); + writePSFmt("/dy {0:.4g} def\n", y1 - y0); + writePSFmt("/r0 {0:.4g} def\n", r0); + writePSFmt("/r1 {0:.4g} def\n", r1); + writePSFmt("/dr {0:.4g} def\n", r1 - r0); + writePSFmt("/t0 {0:.4g} def\n", t0); + writePSFmt("/t1 {0:.4g} def\n", t1); + writePSFmt("/dt {0:.4g} def\n", t1 - t0); + writePSFmt("/n {0:d} def\n", shading->getColorSpace()->getNComps()); + writePSFmt("/encl {0:s} def\n", enclosed ? "true" : "false"); + writePSFmt("/a1 {0:.4g} def\n", a1); + writePSFmt("/a2 {0:.4g} def\n", a2); + if (shading->getNFuncs() == 1) { + writePS("/func "); + cvtFunction(shading->getFunc(0)); + writePS("def\n"); + } else { + writePS("/func {\n"); + for (i = 0; i < shading->getNFuncs(); ++i) { + if (i < shading->getNFuncs() - 1) { + writePS("dup\n"); + } + cvtFunction(shading->getFunc(i)); + writePS("exec\n"); + if (i < shading->getNFuncs() - 1) { + writePS("exch\n"); + } + } + writePS("} def\n"); + } + writePSFmt("{0:.4g} {1:.4g} 0 radialSH\n", sMin, sMax); + + // extend the 'enclosed' case + if (enclosed) { + // extend the smaller circle + if ((shading->getExtend0() && r0 <= r1) || + (shading->getExtend1() && r1 < r0)) { + if (r0 <= r1) { + ta = t0; + ra = r0; + xa = x0; + ya = y0; + } else { + ta = t1; + ra = r1; + xa = x1; + ya = y1; + } + if (level == psLevel2Sep || level == psLevel3Sep) { + writePSFmt("{0:.4g} radialCol aload pop k\n", ta); + } else { + writePSFmt("{0:.4g} radialCol sc\n", ta); + } + writePSFmt("{0:.4g} {1:.4g} {2:.4g} 0 360 arc h f*\n", xa, ya, ra); + } + + // extend the larger circle + if ((shading->getExtend0() && r0 > r1) || + (shading->getExtend1() && r1 >= r0)) { + if (r0 > r1) { + ta = t0; + ra = r0; + xa = x0; + ya = y0; + } else { + ta = t1; + ra = r1; + xa = x1; + ya = y1; + } + if (level == psLevel2Sep || level == psLevel3Sep) { + writePSFmt("{0:.4g} radialCol aload pop k\n", ta); + } else { + writePSFmt("{0:.4g} radialCol sc\n", ta); + } + writePSFmt("{0:.4g} {1:.4g} {2:.4g} 0 360 arc h\n", xa, ya, ra); + writePSFmt("{0:.4g} {1:.4g} m {2:.4g} {3:.4g} l {4:.4g} {5:.4g} l {6:.4g} {7:.4g} l h f*\n", + xMin, yMin, xMin, yMax, xMax, yMax, xMax, yMin); + } + } + + return gTrue; +} + +void PSOutputDev::clip(GfxState *state) { + doPath(state->getPath()); + writePS("W\n"); +} + +void PSOutputDev::eoClip(GfxState *state) { + doPath(state->getPath()); + writePS("W*\n"); +} + +void PSOutputDev::clipToStrokePath(GfxState *state) { + doPath(state->getPath()); + writePS("Ws\n"); +} + +void PSOutputDev::doPath(GfxPath *path) { + GfxSubpath *subpath; + double x0, y0, x1, y1, x2, y2, x3, y3, x4, y4; + int n, m, i, j; + + n = path->getNumSubpaths(); + + if (n == 1 && path->getSubpath(0)->getNumPoints() == 5) { + subpath = path->getSubpath(0); + x0 = subpath->getX(0); + y0 = subpath->getY(0); + x4 = subpath->getX(4); + y4 = subpath->getY(4); + if (x4 == x0 && y4 == y0) { + x1 = subpath->getX(1); + y1 = subpath->getY(1); + x2 = subpath->getX(2); + y2 = subpath->getY(2); + x3 = subpath->getX(3); + y3 = subpath->getY(3); + if (x0 == x1 && x2 == x3 && y0 == y3 && y1 == y2) { + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} re\n", + x0 < x2 ? x0 : x2, y0 < y1 ? y0 : y1, + fabs(x2 - x0), fabs(y1 - y0)); + return; + } else if (x0 == x3 && x1 == x2 && y0 == y1 && y2 == y3) { + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} re\n", + x0 < x1 ? x0 : x1, y0 < y2 ? y0 : y2, + fabs(x1 - x0), fabs(y2 - y0)); + return; + } + } + } + + for (i = 0; i < n; ++i) { + subpath = path->getSubpath(i); + m = subpath->getNumPoints(); + writePSFmt("{0:.4g} {1:.4g} m\n", subpath->getX(0), subpath->getY(0)); + j = 1; + while (j < m) { + if (subpath->getCurve(j)) { + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g} c\n", + subpath->getX(j), subpath->getY(j), + subpath->getX(j+1), subpath->getY(j+1), + subpath->getX(j+2), subpath->getY(j+2)); + j += 3; + } else { + writePSFmt("{0:.4g} {1:.4g} l\n", subpath->getX(j), subpath->getY(j)); + ++j; + } + } + if (subpath->isClosed()) { + writePS("h\n"); + } + } +} + +void PSOutputDev::drawString(GfxState *state, GString *s) { + GfxFont *font; + int wMode; + Gushort *codeToGID; + GString *s2; + double dx, dy, dx2, dy2, originX, originY; + char *p; + UnicodeMap *uMap; + CharCode code; + Unicode u[8]; + char buf[8]; + int len, nChars, uLen, n, m, i, j; + + // check for invisible text -- this is used by Acrobat Capture + if (state->getRender() == 3) { + return; + } + + // ignore empty strings + if (s->getLength() == 0) { + return; + } + + // get the font + if (!(font = state->getFont())) { + return; + } + wMode = font->getWMode(); + + // check for a subtitute 16-bit font + uMap = NULL; + codeToGID = NULL; + if (font->isCIDFont()) { + for (i = 0; i < font16EncLen; ++i) { + if (font->getID()->num == font16Enc[i].fontID.num && + font->getID()->gen == font16Enc[i].fontID.gen) { + uMap = globalParams->getUnicodeMap(font16Enc[i].enc); + break; + } + } + + // check for a code-to-GID map + } else { + for (i = 0; i < font8InfoLen; ++i) { + if (font->getID()->num == font8Info[i].fontID.num && + font->getID()->gen == font8Info[i].fontID.gen) { + codeToGID = font8Info[i].codeToGID; + break; + } + } + } + + // compute width of chars in string, ignoring char spacing and word + // spacing -- the Tj operator will adjust for the metrics of the + // font that's actually used + dx = dy = 0; + nChars = 0; + p = s->getCString(); + len = s->getLength(); + s2 = new GString(); + while (len > 0) { + n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx2, &dy2, &originX, &originY); + if (font->isCIDFont()) { + if (uMap) { + for (i = 0; i < uLen; ++i) { + m = uMap->mapUnicode(u[i], buf, (int)sizeof(buf)); + for (j = 0; j < m; ++j) { + s2->append(buf[j]); + } + } + //~ this really needs to get the number of chars in the target + //~ encoding - which may be more than the number of Unicode + //~ chars + nChars += uLen; + } else { + s2->append((char)((code >> 8) & 0xff)); + s2->append((char)(code & 0xff)); + ++nChars; + } + } else { + if (!codeToGID || codeToGID[code]) { + s2->append((char)code); + } + } + dx += dx2; + dy += dy2; + p += n; + len -= n; + } + dx *= state->getFontSize() * state->getHorizScaling(); + dy *= state->getFontSize(); + if (uMap) { + uMap->decRefCnt(); + } + + if (s2->getLength() > 0) { + writePSString(s2); + if (font->isCIDFont()) { + if (wMode) { + writePSFmt(" {0:d} {1:.4g} Tj16V\n", nChars, dy); + } else { + writePSFmt(" {0:d} {1:.4g} Tj16\n", nChars, dx); + } + } else { + writePSFmt(" {0:.4g} Tj\n", dx); + } + } + delete s2; + + if (state->getRender() & 4) { + haveTextClip = gTrue; + } +} + +void PSOutputDev::endTextObject(GfxState *state) { + if (haveTextClip) { + writePS("Tclip\n"); + haveTextClip = gFalse; + } +} + +void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg) { + int len; + + len = height * ((width + 7) / 8); + switch (level) { + case psLevel1: + case psLevel1Sep: + doImageL1(ref, NULL, invert, inlineImg, str, width, height, len); + break; + case psLevel2: + case psLevel2Sep: + doImageL2(ref, NULL, invert, inlineImg, str, width, height, len, + NULL, NULL, 0, 0, gFalse); + break; + case psLevel3: + case psLevel3Sep: + doImageL3(ref, NULL, invert, inlineImg, str, width, height, len, + NULL, NULL, 0, 0, gFalse); + break; + } +} + +void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg) { + int len; + + len = height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8); + switch (level) { + case psLevel1: + doImageL1(ref, colorMap, gFalse, inlineImg, str, width, height, len); + break; + case psLevel1Sep: + //~ handle indexed, separation, ... color spaces + doImageL1Sep(colorMap, gFalse, inlineImg, str, width, height, len); + break; + case psLevel2: + case psLevel2Sep: + doImageL2(ref, colorMap, gFalse, inlineImg, str, + width, height, len, maskColors, NULL, 0, 0, gFalse); + break; + case psLevel3: + case psLevel3Sep: + doImageL3(ref, colorMap, gFalse, inlineImg, str, + width, height, len, maskColors, NULL, 0, 0, gFalse); + break; + } + t3Cacheable = gFalse; +} + +void PSOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert) { + int len; + + len = height * ((width * colorMap->getNumPixelComps() * + colorMap->getBits() + 7) / 8); + switch (level) { + case psLevel1: + doImageL1(ref, colorMap, gFalse, gFalse, str, width, height, len); + break; + case psLevel1Sep: + //~ handle indexed, separation, ... color spaces + doImageL1Sep(colorMap, gFalse, gFalse, str, width, height, len); + break; + case psLevel2: + case psLevel2Sep: + doImageL2(ref, colorMap, gFalse, gFalse, str, width, height, len, + NULL, maskStr, maskWidth, maskHeight, maskInvert); + break; + case psLevel3: + case psLevel3Sep: + doImageL3(ref, colorMap, gFalse, gFalse, str, width, height, len, + NULL, maskStr, maskWidth, maskHeight, maskInvert); + break; + } + t3Cacheable = gFalse; +} + +void PSOutputDev::doImageL1(Object *ref, GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len) { + ImageStream *imgStr; + Guchar pixBuf[gfxColorMaxComps]; + GfxGray gray; + int col, x, y, c, i; + + if ((inType3Char || preload) && !colorMap) { + if (inlineImg) { + // create an array + str = new FixedLengthEncoder(str, len); + str = new ASCIIHexEncoder(str); + str->reset(); + col = 0; + writePS("[<"); + do { + do { + c = str->getChar(); + } while (c == '\n' || c == '\r'); + if (c == '>' || c == EOF) { + break; + } + writePSChar(c); + ++col; + // each line is: "<...data...>" + // so max data length = 255 - 4 = 251 + // but make it 240 just to be safe + // chunks are 2 bytes each, so we need to stop on an even col number + if (col == 240) { + writePS(">\n<"); + col = 0; + } + } while (c != '>' && c != EOF); + writePS(">]\n"); + writePS("0\n"); + str->close(); + delete str; + } else { + // set up to use the array already created by setupImages() + writePSFmt("ImData_{0:d}_{1:d} 0\n", ref->getRefNum(), ref->getRefGen()); + } + } + + // image/imagemask command + if ((inType3Char || preload) && !colorMap) { + writePSFmt("{0:d} {1:d} {2:s} [{3:d} 0 0 {4:d} 0 {5:d}] pdfImM1a\n", + width, height, invert ? "true" : "false", + width, -height, height); + } else if (colorMap) { + writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1\n", + width, height, + width, -height, height); + } else { + writePSFmt("{0:d} {1:d} {2:s} [{3:d} 0 0 {4:d} 0 {5:d}] pdfImM1\n", + width, height, invert ? "true" : "false", + width, -height, height); + } + + // image data + if (!((inType3Char || preload) && !colorMap)) { + + if (colorMap) { + + // set up to process the data stream + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); + + // process the data stream + i = 0; + for (y = 0; y < height; ++y) { + + // write the line + for (x = 0; x < width; ++x) { + imgStr->getPixel(pixBuf); + colorMap->getGray(pixBuf, &gray); + writePSFmt("{0:02x}", colToByte(gray)); + if (++i == 32) { + writePSChar('\n'); + i = 0; + } + } + } + if (i != 0) { + writePSChar('\n'); + } + str->close(); + delete imgStr; + + // imagemask + } else { + str->reset(); + i = 0; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; x += 8) { + writePSFmt("{0:02x}", str->getChar() & 0xff); + if (++i == 32) { + writePSChar('\n'); + i = 0; + } + } + } + if (i != 0) { + writePSChar('\n'); + } + str->close(); + } + } +} + +void PSOutputDev::doImageL1Sep(GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len) { + ImageStream *imgStr; + Guchar *lineBuf; + Guchar pixBuf[gfxColorMaxComps]; + GfxCMYK cmyk; + int x, y, i, comp; + + // width, height, matrix, bits per component + writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1Sep\n", + width, height, + width, -height, height); + + // allocate a line buffer + lineBuf = (Guchar *)gmalloc(4 * width); + + // set up to process the data stream + imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), + colorMap->getBits()); + imgStr->reset(); + + // process the data stream + i = 0; + for (y = 0; y < height; ++y) { + + // read the line + for (x = 0; x < width; ++x) { + imgStr->getPixel(pixBuf); + colorMap->getCMYK(pixBuf, &cmyk); + lineBuf[4*x+0] = colToByte(cmyk.c); + lineBuf[4*x+1] = colToByte(cmyk.m); + lineBuf[4*x+2] = colToByte(cmyk.y); + lineBuf[4*x+3] = colToByte(cmyk.k); + addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k)); + } + + // write one line of each color component + for (comp = 0; comp < 4; ++comp) { + for (x = 0; x < width; ++x) { + writePSFmt("{0:02x}", lineBuf[4*x + comp]); + if (++i == 32) { + writePSChar('\n'); + i = 0; + } + } + } + } + + if (i != 0) { + writePSChar('\n'); + } + + str->close(); + delete imgStr; + gfree(lineBuf); +} + +void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len, + int *maskColors, Stream *maskStr, + int maskWidth, int maskHeight, GBool maskInvert) { + Stream *str2; + ImageStream *imgStr; + Guchar *line; + PSOutImgClipRect *rects0, *rects1, *rectsTmp, *rectsOut; + int rects0Len, rects1Len, rectsSize, rectsOutLen, rectsOutSize; + GBool emitRect, addRect, extendRect; + GString *s; + int n, numComps; + GBool useRLE, useASCII, useASCIIHex, useCompressed; + GfxSeparationColorSpace *sepCS; + GfxColor color; + GfxCMYK cmyk; + int c; + int col, i, j, x0, x1, y, maskXor; + + // color key masking + if (maskColors && colorMap && !inlineImg) { + // can't read the stream twice for inline images -- but masking + // isn't allowed with inline images anyway + numComps = colorMap->getNumPixelComps(); + imgStr = new ImageStream(str, width, numComps, colorMap->getBits()); + imgStr->reset(); + rects0Len = rects1Len = rectsOutLen = 0; + rectsSize = rectsOutSize = 64; + rects0 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect)); + rects1 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect)); + rectsOut = (PSOutImgClipRect *)gmallocn(rectsOutSize, + sizeof(PSOutImgClipRect)); + for (y = 0; y < height; ++y) { + if (!(line = imgStr->getLine())) { + break; + } + i = 0; + rects1Len = 0; + for (x0 = 0; x0 < width; ++x0) { + for (j = 0; j < numComps; ++j) { + if (line[x0*numComps+j] < maskColors[2*j] || + line[x0*numComps+j] > maskColors[2*j+1]) { + break; + } + } + if (j < numComps) { + break; + } + } + for (x1 = x0; x1 < width; ++x1) { + for (j = 0; j < numComps; ++j) { + if (line[x1*numComps+j] < maskColors[2*j] || + line[x1*numComps+j] > maskColors[2*j+1]) { + break; + } + } + if (j == numComps) { + break; + } + } + while (x0 < width || i < rects0Len) { + emitRect = addRect = extendRect = gFalse; + if (x0 >= width) { + emitRect = gTrue; + } else if (i >= rects0Len) { + addRect = gTrue; + } else if (rects0[i].x0 < x0) { + emitRect = gTrue; + } else if (x0 < rects0[i].x0) { + addRect = gTrue; + } else if (rects0[i].x1 == x1) { + extendRect = gTrue; + } else { + emitRect = addRect = gTrue; + } + if (emitRect) { + if (rectsOutLen == rectsOutSize) { + rectsOutSize *= 2; + rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, + sizeof(PSOutImgClipRect)); + } + rectsOut[rectsOutLen].x0 = rects0[i].x0; + rectsOut[rectsOutLen].x1 = rects0[i].x1; + rectsOut[rectsOutLen].y0 = height - y - 1; + rectsOut[rectsOutLen].y1 = height - rects0[i].y0 - 1; + ++rectsOutLen; + ++i; + } + if (addRect || extendRect) { + if (rects1Len == rectsSize) { + rectsSize *= 2; + rects0 = (PSOutImgClipRect *)greallocn(rects0, rectsSize, + sizeof(PSOutImgClipRect)); + rects1 = (PSOutImgClipRect *)greallocn(rects1, rectsSize, + sizeof(PSOutImgClipRect)); + } + rects1[rects1Len].x0 = x0; + rects1[rects1Len].x1 = x1; + if (addRect) { + rects1[rects1Len].y0 = y; + } + if (extendRect) { + rects1[rects1Len].y0 = rects0[i].y0; + ++i; + } + ++rects1Len; + for (x0 = x1; x0 < width; ++x0) { + for (j = 0; j < numComps; ++j) { + if (line[x0*numComps+j] < maskColors[2*j] || + line[x0*numComps+j] > maskColors[2*j+1]) { + break; + } + } + if (j < numComps) { + break; + } + } + for (x1 = x0; x1 < width; ++x1) { + for (j = 0; j < numComps; ++j) { + if (line[x1*numComps+j] < maskColors[2*j] || + line[x1*numComps+j] > maskColors[2*j+1]) { + break; + } + } + if (j == numComps) { + break; + } + } + } + } + rectsTmp = rects0; + rects0 = rects1; + rects1 = rectsTmp; + i = rects0Len; + rects0Len = rects1Len; + rects1Len = i; + } + for (i = 0; i < rects0Len; ++i) { + if (rectsOutLen == rectsOutSize) { + rectsOutSize *= 2; + rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, + sizeof(PSOutImgClipRect)); + } + rectsOut[rectsOutLen].x0 = rects0[i].x0; + rectsOut[rectsOutLen].x1 = rects0[i].x1; + rectsOut[rectsOutLen].y0 = height - y - 1; + rectsOut[rectsOutLen].y1 = height - rects0[i].y0 - 1; + ++rectsOutLen; + } + writePSFmt("{0:d} array 0\n", rectsOutLen * 4); + for (i = 0; i < rectsOutLen; ++i) { + writePSFmt("[{0:d} {1:d} {2:d} {3:d}] pr\n", + rectsOut[i].x0, rectsOut[i].y0, + rectsOut[i].x1 - rectsOut[i].x0, + rectsOut[i].y1 - rectsOut[i].y0); + } + writePSFmt("pop {0:d} {1:d} pdfImClip\n", width, height); + gfree(rectsOut); + gfree(rects0); + gfree(rects1); + delete imgStr; + str->close(); + + // explicit masking + } else if (maskStr) { + imgStr = new ImageStream(maskStr, maskWidth, 1, 1); + imgStr->reset(); + rects0Len = rects1Len = rectsOutLen = 0; + rectsSize = rectsOutSize = 64; + rects0 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect)); + rects1 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect)); + rectsOut = (PSOutImgClipRect *)gmallocn(rectsOutSize, + sizeof(PSOutImgClipRect)); + maskXor = maskInvert ? 1 : 0; + for (y = 0; y < maskHeight; ++y) { + if (!(line = imgStr->getLine())) { + break; + } + i = 0; + rects1Len = 0; + for (x0 = 0; x0 < maskWidth && (line[x0] ^ maskXor); ++x0) ; + for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1) ; + while (x0 < maskWidth || i < rects0Len) { + emitRect = addRect = extendRect = gFalse; + if (x0 >= maskWidth) { + emitRect = gTrue; + } else if (i >= rects0Len) { + addRect = gTrue; + } else if (rects0[i].x0 < x0) { + emitRect = gTrue; + } else if (x0 < rects0[i].x0) { + addRect = gTrue; + } else if (rects0[i].x1 == x1) { + extendRect = gTrue; + } else { + emitRect = addRect = gTrue; + } + if (emitRect) { + if (rectsOutLen == rectsOutSize) { + rectsOutSize *= 2; + rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, + sizeof(PSOutImgClipRect)); + } + rectsOut[rectsOutLen].x0 = rects0[i].x0; + rectsOut[rectsOutLen].x1 = rects0[i].x1; + rectsOut[rectsOutLen].y0 = maskHeight - y - 1; + rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1; + ++rectsOutLen; + ++i; + } + if (addRect || extendRect) { + if (rects1Len == rectsSize) { + rectsSize *= 2; + rects0 = (PSOutImgClipRect *)greallocn(rects0, rectsSize, + sizeof(PSOutImgClipRect)); + rects1 = (PSOutImgClipRect *)greallocn(rects1, rectsSize, + sizeof(PSOutImgClipRect)); + } + rects1[rects1Len].x0 = x0; + rects1[rects1Len].x1 = x1; + if (addRect) { + rects1[rects1Len].y0 = y; + } + if (extendRect) { + rects1[rects1Len].y0 = rects0[i].y0; + ++i; + } + ++rects1Len; + for (x0 = x1; x0 < maskWidth && (line[x0] ^ maskXor); ++x0) ; + for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1) ; + } + } + rectsTmp = rects0; + rects0 = rects1; + rects1 = rectsTmp; + i = rects0Len; + rects0Len = rects1Len; + rects1Len = i; + } + for (i = 0; i < rects0Len; ++i) { + if (rectsOutLen == rectsOutSize) { + rectsOutSize *= 2; + rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, + sizeof(PSOutImgClipRect)); + } + rectsOut[rectsOutLen].x0 = rects0[i].x0; + rectsOut[rectsOutLen].x1 = rects0[i].x1; + rectsOut[rectsOutLen].y0 = maskHeight - y - 1; + rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1; + ++rectsOutLen; + } + writePSFmt("{0:d} array 0\n", rectsOutLen * 4); + for (i = 0; i < rectsOutLen; ++i) { + writePSFmt("[{0:d} {1:d} {2:d} {3:d}] pr\n", + rectsOut[i].x0, rectsOut[i].y0, + rectsOut[i].x1 - rectsOut[i].x0, + rectsOut[i].y1 - rectsOut[i].y0); + } + writePSFmt("pop {0:d} {1:d} pdfImClip\n", maskWidth, maskHeight); + gfree(rectsOut); + gfree(rects0); + gfree(rects1); + delete imgStr; + maskStr->close(); + } + + // color space + if (colorMap) { + dumpColorSpaceL2(colorMap->getColorSpace(), gFalse, gTrue, gFalse); + writePS(" setcolorspace\n"); + } + + useASCIIHex = globalParams->getPSASCIIHex(); + + // set up the image data + if (mode == psModeForm || inType3Char || preload) { + if (inlineImg) { + // create an array + str2 = new FixedLengthEncoder(str, len); + str2 = new RunLengthEncoder(str2); + if (useASCIIHex) { + str2 = new ASCIIHexEncoder(str2); + } else { + str2 = new ASCII85Encoder(str2); + } + str2->reset(); + col = 0; + writePS((char *)(useASCIIHex ? "[<" : "[<~")); + do { + do { + c = str2->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + if (c == 'z') { + writePSChar(c); + ++col; + } else { + writePSChar(c); + ++col; + for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) { + do { + c = str2->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + writePSChar(c); + ++col; + } + } + // each line is: "<~...data...~>" + // so max data length = 255 - 6 = 249 + // chunks are 1 or 5 bytes each, so we have to stop at 245 + // but make it 240 just to be safe + if (col > 240) { + writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~")); + col = 0; + } + } while (c != (useASCIIHex ? '>' : '~') && c != EOF); + writePS((char *)(useASCIIHex ? ">\n" : "~>\n")); + // add an extra entry because the RunLengthDecode filter may + // read past the end + writePS("<>]\n"); + writePS("0\n"); + str2->close(); + delete str2; + } else { + // set up to use the array already created by setupImages() + writePSFmt("ImData_{0:d}_{1:d} 0\n", ref->getRefNum(), ref->getRefGen()); + } + } + + // image dictionary + writePS("<<\n /ImageType 1\n"); + + // width, height, matrix, bits per component + writePSFmt(" /Width {0:d}\n", width); + writePSFmt(" /Height {0:d}\n", height); + writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", + width, -height, height); + if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) { + writePS(" /BitsPerComponent 8\n"); + } else { + writePSFmt(" /BitsPerComponent {0:d}\n", + colorMap ? colorMap->getBits() : 1); + } + + // decode + if (colorMap) { + writePS(" /Decode ["); + if ((level == psLevel2Sep || level == psLevel3Sep) && + colorMap->getColorSpace()->getMode() == csSeparation) { + // this matches up with the code in the pdfImSep operator + n = (1 << colorMap->getBits()) - 1; + writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(0) * n, + colorMap->getDecodeHigh(0) * n); + } else if (colorMap->getColorSpace()->getMode() == csDeviceN) { + numComps = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())-> + getAlt()->getNComps(); + for (i = 0; i < numComps; ++i) { + if (i > 0) { + writePS(" "); + } + writePS("0 1"); + } + } else { + numComps = colorMap->getNumPixelComps(); + for (i = 0; i < numComps; ++i) { + if (i > 0) { + writePS(" "); + } + writePSFmt("{0:.4g} {1:.4g}", + colorMap->getDecodeLow(i), colorMap->getDecodeHigh(i)); + } + } + writePS("]\n"); + } else { + writePSFmt(" /Decode [{0:d} {1:d}]\n", invert ? 1 : 0, invert ? 0 : 1); + } + + // data source + if (mode == psModeForm || inType3Char || preload) { + writePS(" /DataSource { 2 copy get exch 1 add exch }\n"); + } else { + writePS(" /DataSource currentfile\n"); + } + + // filters + s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3, + " "); + if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) || + inlineImg || !s) { + useRLE = gTrue; + useASCII = !(mode == psModeForm || inType3Char || preload); + useCompressed = gFalse; + } else { + useRLE = gFalse; + useASCII = str->isBinary() && + !(mode == psModeForm || inType3Char || preload); + useCompressed = gTrue; + } + if (useASCII) { + writePSFmt(" /ASCII{0:s}Decode filter\n", + useASCIIHex ? "Hex" : "85"); + } + if (useRLE) { + writePS(" /RunLengthDecode filter\n"); + } + if (useCompressed) { + writePS(s->getCString()); + } + if (s) { + delete s; + } + + if (mode == psModeForm || inType3Char || preload) { + + // end of image dictionary + writePSFmt(">>\n{0:s}\n", colorMap ? "image" : "imagemask"); + + // get rid of the array and index + writePS("pop pop\n"); + + } else { + + // cut off inline image streams at appropriate length + if (inlineImg) { + str = new FixedLengthEncoder(str, len); + } else if (useCompressed) { + str = str->getUndecodedStream(); + } + + // recode DeviceN data + if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) { + str = new DeviceNRecoder(str, width, height, colorMap); + } + + // add RunLengthEncode and ASCIIHex/85 encode filters + if (useRLE) { + str = new RunLengthEncoder(str); + } + if (useASCII) { + if (useASCIIHex) { + str = new ASCIIHexEncoder(str); + } else { + str = new ASCII85Encoder(str); + } + } + + // end of image dictionary + writePS(">>\n"); +#if OPI_SUPPORT + if (opi13Nest) { + if (inlineImg) { + // this can't happen -- OPI dictionaries are in XObjects + error(-1, "Internal: OPI in inline image"); + n = 0; + } else { + // need to read the stream to count characters -- the length + // is data-dependent (because of ASCII and RLE filters) + str->reset(); + n = 0; + while ((c = str->getChar()) != EOF) { + ++n; + } + str->close(); + } + // +6/7 for "pdfIm\n" / "pdfImM\n" + // +8 for newline + trailer + n += colorMap ? 14 : 15; + writePSFmt("%%BeginData: {0:d} Hex Bytes\n", n); + } +#endif + if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap && + colorMap->getColorSpace()->getMode() == csSeparation) { + color.c[0] = gfxColorComp1; + sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace(); + sepCS->getCMYK(&color, &cmyk); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} ({4:t}) pdfImSep\n", + colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k), + sepCS->getName()); + } else { + writePSFmt("{0:s}\n", colorMap ? "pdfIm" : "pdfImM"); + } + + // copy the stream data + str->reset(); + while ((c = str->getChar()) != EOF) { + writePSChar(c); + } + str->close(); + + // add newline and trailer to the end + writePSChar('\n'); + writePS("%-EOD-\n"); +#if OPI_SUPPORT + if (opi13Nest) { + writePS("%%EndData\n"); + } +#endif + + // delete encoders + if (useRLE || useASCII || inlineImg) { + delete str; + } + } + + if ((maskColors && colorMap && !inlineImg) || maskStr) { + writePS("pdfImClipEnd\n"); + } +} + +//~ this doesn't currently support OPI +void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len, + int *maskColors, Stream *maskStr, + int maskWidth, int maskHeight, GBool maskInvert) { + Stream *str2; + GString *s; + int n, numComps; + GBool useRLE, useASCII, useASCIIHex, useCompressed; + GBool maskUseRLE, maskUseASCII, maskUseCompressed; + GfxSeparationColorSpace *sepCS; + GfxColor color; + GfxCMYK cmyk; + int c; + int col, i; + + useASCIIHex = globalParams->getPSASCIIHex(); + useRLE = useASCII = useCompressed = gFalse; // make gcc happy + maskUseRLE = maskUseASCII = maskUseCompressed = gFalse; // make gcc happy + + // color space + if (colorMap) { + dumpColorSpaceL2(colorMap->getColorSpace(), gFalse, gTrue, gFalse); + writePS(" setcolorspace\n"); + } + + // set up the image data + if (mode == psModeForm || inType3Char || preload) { + if (inlineImg) { + // create an array + str2 = new FixedLengthEncoder(str, len); + str2 = new RunLengthEncoder(str2); + if (useASCIIHex) { + str2 = new ASCIIHexEncoder(str2); + } else { + str2 = new ASCII85Encoder(str2); + } + str2->reset(); + col = 0; + writePS((char *)(useASCIIHex ? "[<" : "[<~")); + do { + do { + c = str2->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + if (c == 'z') { + writePSChar(c); + ++col; + } else { + writePSChar(c); + ++col; + for (i = 1; i <= (useASCIIHex ? 1 : 4); ++i) { + do { + c = str2->getChar(); + } while (c == '\n' || c == '\r'); + if (c == (useASCIIHex ? '>' : '~') || c == EOF) { + break; + } + writePSChar(c); + ++col; + } + } + // each line is: "<~...data...~>" + // so max data length = 255 - 6 = 249 + // chunks are 1 or 5 bytes each, so we have to stop at 245 + // but make it 240 just to be safe + if (col > 240) { + writePS((char *)(useASCIIHex ? ">\n<" : "~>\n<~")); + col = 0; + } + } while (c != (useASCIIHex ? '>' : '~') && c != EOF); + writePS((char *)(useASCIIHex ? ">\n" : "~>\n")); + // add an extra entry because the RunLengthDecode filter may + // read past the end + writePS("<>]\n"); + writePS("0\n"); + str2->close(); + delete str2; + } else { + // set up to use the array already created by setupImages() + writePSFmt("ImData_{0:d}_{1:d} 0\n", ref->getRefNum(), ref->getRefGen()); + } + } + + // explicit masking + if (maskStr) { + writePS("<<\n /ImageType 3\n"); + writePS(" /InterleaveType 3\n"); + writePS(" /DataDict\n"); + } + + // image (data) dictionary + writePSFmt("<<\n /ImageType {0:d}\n", (maskColors && colorMap) ? 4 : 1); + + // color key masking + if (maskColors && colorMap) { + writePS(" /MaskColor [\n"); + numComps = colorMap->getNumPixelComps(); + for (i = 0; i < 2 * numComps; i += 2) { + writePSFmt(" {0:d} {1:d}\n", maskColors[i], maskColors[i+1]); + } + writePS(" ]\n"); + } + + // width, height, matrix, bits per component + writePSFmt(" /Width {0:d}\n", width); + writePSFmt(" /Height {0:d}\n", height); + writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", + width, -height, height); + if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) { + writePS(" /BitsPerComponent 8\n"); + } else { + writePSFmt(" /BitsPerComponent {0:d}\n", + colorMap ? colorMap->getBits() : 1); + } + + // decode + if (colorMap) { + writePS(" /Decode ["); + if ((level == psLevel2Sep || level == psLevel3Sep) && + colorMap->getColorSpace()->getMode() == csSeparation) { + // this matches up with the code in the pdfImSep operator + n = (1 << colorMap->getBits()) - 1; + writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(0) * n, + colorMap->getDecodeHigh(0) * n); + } else if (colorMap->getColorSpace()->getMode() == csDeviceN) { + numComps = ((GfxDeviceNColorSpace *)colorMap->getColorSpace())-> + getAlt()->getNComps(); + for (i = 0; i < numComps; ++i) { + if (i > 0) { + writePS(" "); + } + writePS("0 1"); + } + } else { + numComps = colorMap->getNumPixelComps(); + for (i = 0; i < numComps; ++i) { + if (i > 0) { + writePS(" "); + } + writePSFmt("{0:.4g} {1:.4g}", colorMap->getDecodeLow(i), + colorMap->getDecodeHigh(i)); + } + } + writePS("]\n"); + } else { + writePSFmt(" /Decode [{0:d} {1:d}]\n", invert ? 1 : 0, invert ? 0 : 1); + } + + // data source + if (mode == psModeForm || inType3Char || preload) { + writePS(" /DataSource { 2 copy get exch 1 add exch }\n"); + } else { + writePS(" /DataSource currentfile\n"); + } + + // filters + s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3, + " "); + if ((colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) || + inlineImg || !s) { + useRLE = gTrue; + useASCII = !(mode == psModeForm || inType3Char || preload); + useCompressed = gFalse; + } else { + useRLE = gFalse; + useASCII = str->isBinary() && + !(mode == psModeForm || inType3Char || preload); + useCompressed = gTrue; + } + if (useASCII) { + writePSFmt(" /ASCII{0:s}Decode filter\n", + useASCIIHex ? "Hex" : "85"); + } + if (useRLE) { + writePS(" /RunLengthDecode filter\n"); + } + if (useCompressed) { + writePS(s->getCString()); + } + if (s) { + delete s; + } + + // end of image (data) dictionary + writePS(">>\n"); + + // explicit masking + if (maskStr) { + writePS(" /MaskDict\n"); + writePS("<<\n"); + writePS(" /ImageType 1\n"); + writePSFmt(" /Width {0:d}\n", maskWidth); + writePSFmt(" /Height {0:d}\n", maskHeight); + writePSFmt(" /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", + maskWidth, -maskHeight, maskHeight); + writePS(" /BitsPerComponent 1\n"); + writePSFmt(" /Decode [{0:d} {1:d}]\n", + maskInvert ? 1 : 0, maskInvert ? 0 : 1); + + // mask data source + writePS(" /DataSource currentfile\n"); + s = maskStr->getPSFilter(3, " "); + if (!s) { + maskUseRLE = gTrue; + maskUseASCII = gTrue; + maskUseCompressed = gFalse; + } else { + maskUseRLE = gFalse; + maskUseASCII = maskStr->isBinary(); + maskUseCompressed = gTrue; + } + if (maskUseASCII) { + writePSFmt(" /ASCII{0:s}Decode filter\n", + useASCIIHex ? "Hex" : "85"); + } + if (maskUseRLE) { + writePS(" /RunLengthDecode filter\n"); + } + if (maskUseCompressed) { + writePS(s->getCString()); + } + if (s) { + delete s; + } + + writePS(">>\n"); + writePS(">>\n"); + } + + if (mode == psModeForm || inType3Char || preload) { + + // image command + writePSFmt("{0:s}\n", colorMap ? "image" : "imagemask"); + + } else { + + if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap && + colorMap->getColorSpace()->getMode() == csSeparation) { + color.c[0] = gfxColorComp1; + sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace(); + sepCS->getCMYK(&color, &cmyk); + writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} ({4:t}) pdfImSep\n", + colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k), + sepCS->getName()); + } else { + writePSFmt("{0:s}\n", colorMap ? "pdfIm" : "pdfImM"); + } + + } + + // explicit masking + if (maskStr) { + + if (maskUseCompressed) { + maskStr = maskStr->getUndecodedStream(); + } + + // add RunLengthEncode and ASCIIHex/85 encode filters + if (maskUseRLE) { + maskStr = new RunLengthEncoder(maskStr); + } + if (maskUseASCII) { + if (useASCIIHex) { + maskStr = new ASCIIHexEncoder(maskStr); + } else { + maskStr = new ASCII85Encoder(maskStr); + } + } + + // copy the stream data + maskStr->reset(); + while ((c = maskStr->getChar()) != EOF) { + writePSChar(c); + } + maskStr->close(); + writePSChar('\n'); + + // delete encoders + if (maskUseRLE || maskUseASCII) { + delete maskStr; + } + } + + // get rid of the array and index + if (mode == psModeForm || inType3Char || preload) { + writePS("pop pop\n"); + + // image data + } else { + + // cut off inline image streams at appropriate length + if (inlineImg) { + str = new FixedLengthEncoder(str, len); + } else if (useCompressed) { + str = str->getUndecodedStream(); + } + + // recode DeviceN data + if (colorMap && colorMap->getColorSpace()->getMode() == csDeviceN) { + str = new DeviceNRecoder(str, width, height, colorMap); + } + + // add RunLengthEncode and ASCIIHex/85 encode filters + if (useRLE) { + str = new RunLengthEncoder(str); + } + if (useASCII) { + if (useASCIIHex) { + str = new ASCIIHexEncoder(str); + } else { + str = new ASCII85Encoder(str); + } + } + + // copy the stream data + str->reset(); + while ((c = str->getChar()) != EOF) { + writePSChar(c); + } + str->close(); + + // add newline and trailer to the end + writePSChar('\n'); + writePS("%-EOD-\n"); + + // delete encoders + if (useRLE || useASCII || inlineImg) { + delete str; + } + } +} + +void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace, + GBool genXform, GBool updateColors, + GBool map01) { + GfxCalGrayColorSpace *calGrayCS; + GfxCalRGBColorSpace *calRGBCS; + GfxLabColorSpace *labCS; + GfxIndexedColorSpace *indexedCS; + GfxSeparationColorSpace *separationCS; + GfxDeviceNColorSpace *deviceNCS; + GfxColorSpace *baseCS; + Guchar *lookup, *p; + double x[gfxColorMaxComps], y[gfxColorMaxComps]; + double low[gfxColorMaxComps], range[gfxColorMaxComps]; + GfxColor color; + GfxCMYK cmyk; + Function *func; + int n, numComps, numAltComps; + int byte; + int i, j, k; + + switch (colorSpace->getMode()) { + + case csDeviceGray: + writePS("/DeviceGray"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessBlack; + } + break; + + case csCalGray: + calGrayCS = (GfxCalGrayColorSpace *)colorSpace; + writePS("[/CIEBasedA <<\n"); + writePSFmt(" /DecodeA {{{0:.4g} exp}} bind\n", calGrayCS->getGamma()); + writePSFmt(" /MatrixA [{0:.4g} {1:.4g} {2:.4g}]\n", + calGrayCS->getWhiteX(), calGrayCS->getWhiteY(), + calGrayCS->getWhiteZ()); + writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n", + calGrayCS->getWhiteX(), calGrayCS->getWhiteY(), + calGrayCS->getWhiteZ()); + writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n", + calGrayCS->getBlackX(), calGrayCS->getBlackY(), + calGrayCS->getBlackZ()); + writePS(">>]"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessBlack; + } + break; + + case csDeviceRGB: + writePS("/DeviceRGB"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessCMYK; + } + break; + + case csCalRGB: + calRGBCS = (GfxCalRGBColorSpace *)colorSpace; + writePS("[/CIEBasedABC <<\n"); + writePSFmt(" /DecodeABC [{{{0:.4g} exp}} bind {{{1:.4g} exp}} bind {{{2:.4g} exp}} bind]\n", + calRGBCS->getGammaR(), calRGBCS->getGammaG(), + calRGBCS->getGammaB()); + writePSFmt(" /MatrixABC [{0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g} {6:.4g} {7:.4g} {8:.4g}]\n", + calRGBCS->getMatrix()[0], calRGBCS->getMatrix()[1], + calRGBCS->getMatrix()[2], calRGBCS->getMatrix()[3], + calRGBCS->getMatrix()[4], calRGBCS->getMatrix()[5], + calRGBCS->getMatrix()[6], calRGBCS->getMatrix()[7], + calRGBCS->getMatrix()[8]); + writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n", + calRGBCS->getWhiteX(), calRGBCS->getWhiteY(), + calRGBCS->getWhiteZ()); + writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n", + calRGBCS->getBlackX(), calRGBCS->getBlackY(), + calRGBCS->getBlackZ()); + writePS(">>]"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessCMYK; + } + break; + + case csDeviceCMYK: + writePS("/DeviceCMYK"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessCMYK; + } + break; + + case csLab: + labCS = (GfxLabColorSpace *)colorSpace; + writePS("[/CIEBasedABC <<\n"); + if (map01) { + writePS(" /RangeABC [0 1 0 1 0 1]\n"); + writePSFmt(" /DecodeABC [{{100 mul 16 add 116 div}} bind {{{0:.4g} mul {1:.4g} add}} bind {{{2:.4g} mul {3:.4g} add}} bind]\n", + (labCS->getAMax() - labCS->getAMin()) / 500.0, + labCS->getAMin() / 500.0, + (labCS->getBMax() - labCS->getBMin()) / 200.0, + labCS->getBMin() / 200.0); + } else { + writePSFmt(" /RangeABC [0 100 {0:.4g} {1:.4g} {2:.4g} {3:.4g}]\n", + labCS->getAMin(), labCS->getAMax(), + labCS->getBMin(), labCS->getBMax()); + writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n"); + } + writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n"); + writePS(" /DecodeLMN\n"); + writePS(" [{dup 6 29 div ge {dup dup mul mul}\n"); + writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind\n", + labCS->getWhiteX()); + writePS(" {dup 6 29 div ge {dup dup mul mul}\n"); + writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind\n", + labCS->getWhiteY()); + writePS(" {dup 6 29 div ge {dup dup mul mul}\n"); + writePSFmt(" {{4 29 div sub 108 841 div mul }} ifelse {0:.4g} mul}} bind]\n", + labCS->getWhiteZ()); + writePSFmt(" /WhitePoint [{0:.4g} {1:.4g} {2:.4g}]\n", + labCS->getWhiteX(), labCS->getWhiteY(), labCS->getWhiteZ()); + writePSFmt(" /BlackPoint [{0:.4g} {1:.4g} {2:.4g}]\n", + labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ()); + writePS(">>]"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + processColors |= psProcessCMYK; + } + break; + + case csICCBased: + // there is no transform function to the alternate color space, so + // we can use it directly + dumpColorSpaceL2(((GfxICCBasedColorSpace *)colorSpace)->getAlt(), + genXform, updateColors, gFalse); + break; + + case csIndexed: + indexedCS = (GfxIndexedColorSpace *)colorSpace; + baseCS = indexedCS->getBase(); + writePS("[/Indexed "); + dumpColorSpaceL2(baseCS, gFalse, gFalse, gTrue); + n = indexedCS->getIndexHigh(); + numComps = baseCS->getNComps(); + lookup = indexedCS->getLookup(); + writePSFmt(" {0:d} <\n", n); + if (baseCS->getMode() == csDeviceN) { + func = ((GfxDeviceNColorSpace *)baseCS)->getTintTransformFunc(); + baseCS->getDefaultRanges(low, range, indexedCS->getIndexHigh()); + if (((GfxDeviceNColorSpace *)baseCS)->getAlt()->getMode() == csLab) { + labCS = (GfxLabColorSpace *)((GfxDeviceNColorSpace *)baseCS)->getAlt(); + } else { + labCS = NULL; + } + numAltComps = ((GfxDeviceNColorSpace *)baseCS)->getAlt()->getNComps(); + p = lookup; + for (i = 0; i <= n; i += 8) { + writePS(" "); + for (j = i; j < i+8 && j <= n; ++j) { + for (k = 0; k < numComps; ++k) { + x[k] = low[k] + (*p++ / 255.0) * range[k]; + } + func->transform(x, y); + if (labCS) { + y[0] /= 100.0; + y[1] = (y[1] - labCS->getAMin()) / + (labCS->getAMax() - labCS->getAMin()); + y[2] = (y[2] - labCS->getBMin()) / + (labCS->getBMax() - labCS->getBMin()); + } + for (k = 0; k < numAltComps; ++k) { + byte = (int)(y[k] * 255 + 0.5); + if (byte < 0) { + byte = 0; + } else if (byte > 255) { + byte = 255; + } + writePSFmt("{0:02x}", byte); + } + if (updateColors) { + color.c[0] = dblToCol(j); + indexedCS->getCMYK(&color, &cmyk); + addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k)); + } + } + writePS("\n"); + } + } else { + for (i = 0; i <= n; i += 8) { + writePS(" "); + for (j = i; j < i+8 && j <= n; ++j) { + for (k = 0; k < numComps; ++k) { + writePSFmt("{0:02x}", lookup[j * numComps + k]); + } + if (updateColors) { + color.c[0] = dblToCol(j); + indexedCS->getCMYK(&color, &cmyk); + addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m), + colToDbl(cmyk.y), colToDbl(cmyk.k)); + } + } + writePS("\n"); + } + } + writePS(">]"); + if (genXform) { + writePS(" {}"); + } + break; + + case csSeparation: + separationCS = (GfxSeparationColorSpace *)colorSpace; + writePS("[/Separation "); + writePSString(separationCS->getName()); + writePS(" "); + dumpColorSpaceL2(separationCS->getAlt(), gFalse, gFalse, gFalse); + writePS("\n"); + cvtFunction(separationCS->getFunc()); + writePS("]"); + if (genXform) { + writePS(" {}"); + } + if (updateColors) { + addCustomColor(separationCS); + } + break; + + case csDeviceN: + // DeviceN color spaces are a Level 3 PostScript feature. + deviceNCS = (GfxDeviceNColorSpace *)colorSpace; + dumpColorSpaceL2(deviceNCS->getAlt(), gFalse, updateColors, map01); + if (genXform) { + writePS(" "); + cvtFunction(deviceNCS->getTintTransformFunc()); + } + break; + + case csPattern: + //~ unimplemented + break; + } +} + +#if OPI_SUPPORT +void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict) { + Object dict; + + if (globalParams->getPSOPI()) { + opiDict->lookup("2.0", &dict); + if (dict.isDict()) { + opiBegin20(state, dict.getDict()); + dict.free(); + } else { + dict.free(); + opiDict->lookup("1.3", &dict); + if (dict.isDict()) { + opiBegin13(state, dict.getDict()); + } + dict.free(); + } + } +} + +void PSOutputDev::opiBegin20(GfxState *state, Dict *dict) { + Object obj1, obj2, obj3, obj4; + double width, height, left, right, top, bottom; + int w, h; + int i; + + writePS("%%BeginOPI: 2.0\n"); + writePS("%%Distilled\n"); + + dict->lookup("F", &obj1); + if (getFileSpec(&obj1, &obj2)) { + writePSFmt("%%ImageFileName: {0:t}\n", obj2.getString()); + obj2.free(); + } + obj1.free(); + + dict->lookup("MainImage", &obj1); + if (obj1.isString()) { + writePSFmt("%%MainImage: {0:t}\n", obj1.getString()); + } + obj1.free(); + + //~ ignoring 'Tags' entry + //~ need to use writePSString() and deal with >255-char lines + + dict->lookup("Size", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + width = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + height = obj2.getNum(); + obj2.free(); + writePSFmt("%%ImageDimensions: {0:.4g} {1:.4g}\n", width, height); + } + obj1.free(); + + dict->lookup("CropRect", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 4) { + obj1.arrayGet(0, &obj2); + left = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + top = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + right = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + bottom = obj2.getNum(); + obj2.free(); + writePSFmt("%%ImageCropRect: {0:.4g} {1:.4g} {2:.4g} {3:.4g}\n", + left, top, right, bottom); + } + obj1.free(); + + dict->lookup("Overprint", &obj1); + if (obj1.isBool()) { + writePSFmt("%%ImageOverprint: {0:s}\n", obj1.getBool() ? "true" : "false"); + } + obj1.free(); + + dict->lookup("Inks", &obj1); + if (obj1.isName()) { + writePSFmt("%%ImageInks: {0:s}\n", obj1.getName()); + } else if (obj1.isArray() && obj1.arrayGetLength() >= 1) { + obj1.arrayGet(0, &obj2); + if (obj2.isName()) { + writePSFmt("%%ImageInks: {0:s} {1:d}", + obj2.getName(), (obj1.arrayGetLength() - 1) / 2); + for (i = 1; i+1 < obj1.arrayGetLength(); i += 2) { + obj1.arrayGet(i, &obj3); + obj1.arrayGet(i+1, &obj4); + if (obj3.isString() && obj4.isNum()) { + writePS(" "); + writePSString(obj3.getString()); + writePSFmt(" {0:.4g}", obj4.getNum()); + } + obj3.free(); + obj4.free(); + } + writePS("\n"); + } + obj2.free(); + } + obj1.free(); + + writePS("gsave\n"); + + writePS("%%BeginIncludedImage\n"); + + dict->lookup("IncludedImageDimensions", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + w = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + h = obj2.getInt(); + obj2.free(); + writePSFmt("%%IncludedImageDimensions: {0:d} {1:d}\n", w, h); + } + obj1.free(); + + dict->lookup("IncludedImageQuality", &obj1); + if (obj1.isNum()) { + writePSFmt("%%IncludedImageQuality: {0:.4g}\n", obj1.getNum()); + } + obj1.free(); + + ++opi20Nest; +} + +void PSOutputDev::opiBegin13(GfxState *state, Dict *dict) { + Object obj1, obj2; + int left, right, top, bottom, samples, bits, width, height; + double c, m, y, k; + double llx, lly, ulx, uly, urx, ury, lrx, lry; + double tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry; + double horiz, vert; + int i, j; + + writePS("save\n"); + writePS("/opiMatrix2 matrix currentmatrix def\n"); + writePS("opiMatrix setmatrix\n"); + + dict->lookup("F", &obj1); + if (getFileSpec(&obj1, &obj2)) { + writePSFmt("%ALDImageFileName: {0:t}\n", obj2.getString()); + obj2.free(); + } + obj1.free(); + + dict->lookup("CropRect", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 4) { + obj1.arrayGet(0, &obj2); + left = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + top = obj2.getInt(); + obj2.free(); + obj1.arrayGet(2, &obj2); + right = obj2.getInt(); + obj2.free(); + obj1.arrayGet(3, &obj2); + bottom = obj2.getInt(); + obj2.free(); + writePSFmt("%ALDImageCropRect: {0:d} {1:d} {2:d} {3:d}\n", + left, top, right, bottom); + } + obj1.free(); + + dict->lookup("Color", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 5) { + obj1.arrayGet(0, &obj2); + c = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + m = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + y = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + k = obj2.getNum(); + obj2.free(); + obj1.arrayGet(4, &obj2); + if (obj2.isString()) { + writePSFmt("%ALDImageColor: {0:.4g} {1:.4g} {2:.4g} {3:.4g} ", + c, m, y, k); + writePSString(obj2.getString()); + writePS("\n"); + } + obj2.free(); + } + obj1.free(); + + dict->lookup("ColorType", &obj1); + if (obj1.isName()) { + writePSFmt("%ALDImageColorType: {0:s}\n", obj1.getName()); + } + obj1.free(); + + //~ ignores 'Comments' entry + //~ need to handle multiple lines + + dict->lookup("CropFixed", &obj1); + if (obj1.isArray()) { + obj1.arrayGet(0, &obj2); + ulx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + uly = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + lrx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + lry = obj2.getNum(); + obj2.free(); + writePSFmt("%ALDImageCropFixed: {0:.4g} {1:.4g} {2:.4g} {3:.4g}\n", + ulx, uly, lrx, lry); + } + obj1.free(); + + dict->lookup("GrayMap", &obj1); + if (obj1.isArray()) { + writePS("%ALDImageGrayMap:"); + for (i = 0; i < obj1.arrayGetLength(); i += 16) { + if (i > 0) { + writePS("\n%%+"); + } + for (j = 0; j < 16 && i+j < obj1.arrayGetLength(); ++j) { + obj1.arrayGet(i+j, &obj2); + writePSFmt(" {0:d}", obj2.getInt()); + obj2.free(); + } + } + writePS("\n"); + } + obj1.free(); + + dict->lookup("ID", &obj1); + if (obj1.isString()) { + writePSFmt("%ALDImageID: {0:t}\n", obj1.getString()); + } + obj1.free(); + + dict->lookup("ImageType", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + samples = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + bits = obj2.getInt(); + obj2.free(); + writePSFmt("%ALDImageType: {0:d} {1:d}\n", samples, bits); + } + obj1.free(); + + dict->lookup("Overprint", &obj1); + if (obj1.isBool()) { + writePSFmt("%ALDImageOverprint: {0:s}\n", + obj1.getBool() ? "true" : "false"); + } + obj1.free(); + + dict->lookup("Position", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 8) { + obj1.arrayGet(0, &obj2); + llx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + lly = obj2.getNum(); + obj2.free(); + obj1.arrayGet(2, &obj2); + ulx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(3, &obj2); + uly = obj2.getNum(); + obj2.free(); + obj1.arrayGet(4, &obj2); + urx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(5, &obj2); + ury = obj2.getNum(); + obj2.free(); + obj1.arrayGet(6, &obj2); + lrx = obj2.getNum(); + obj2.free(); + obj1.arrayGet(7, &obj2); + lry = obj2.getNum(); + obj2.free(); + opiTransform(state, llx, lly, &tllx, &tlly); + opiTransform(state, ulx, uly, &tulx, &tuly); + opiTransform(state, urx, ury, &turx, &tury); + opiTransform(state, lrx, lry, &tlrx, &tlry); + writePSFmt("%ALDImagePosition: {0:.4g} {1:.4g} {2:.4g} {3:.4g} {4:.4g} {5:.4g} {6:.4g} {7:.4g}\n", + tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry); + obj2.free(); + } + obj1.free(); + + dict->lookup("Resolution", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + horiz = obj2.getNum(); + obj2.free(); + obj1.arrayGet(1, &obj2); + vert = obj2.getNum(); + obj2.free(); + writePSFmt("%ALDImageResoution: {0:.4g} {1:.4g}\n", horiz, vert); + obj2.free(); + } + obj1.free(); + + dict->lookup("Size", &obj1); + if (obj1.isArray() && obj1.arrayGetLength() == 2) { + obj1.arrayGet(0, &obj2); + width = obj2.getInt(); + obj2.free(); + obj1.arrayGet(1, &obj2); + height = obj2.getInt(); + obj2.free(); + writePSFmt("%ALDImageDimensions: {0:d} {1:d}\n", width, height); + } + obj1.free(); + + //~ ignoring 'Tags' entry + //~ need to use writePSString() and deal with >255-char lines + + dict->lookup("Tint", &obj1); + if (obj1.isNum()) { + writePSFmt("%ALDImageTint: {0:.4g}\n", obj1.getNum()); + } + obj1.free(); + + dict->lookup("Transparency", &obj1); + if (obj1.isBool()) { + writePSFmt("%ALDImageTransparency: {0:s}\n", + obj1.getBool() ? "true" : "false"); + } + obj1.free(); + + writePS("%%BeginObject: image\n"); + writePS("opiMatrix2 setmatrix\n"); + ++opi13Nest; +} + +// Convert PDF user space coordinates to PostScript default user space +// coordinates. This has to account for both the PDF CTM and the +// PSOutputDev page-fitting transform. +void PSOutputDev::opiTransform(GfxState *state, double x0, double y0, + double *x1, double *y1) { + double t; + + state->transform(x0, y0, x1, y1); + *x1 += tx; + *y1 += ty; + if (rotate == 90) { + t = *x1; + *x1 = -*y1; + *y1 = t; + } else if (rotate == 180) { + *x1 = -*x1; + *y1 = -*y1; + } else if (rotate == 270) { + t = *x1; + *x1 = *y1; + *y1 = -t; + } + *x1 *= xScale; + *y1 *= yScale; +} + +void PSOutputDev::opiEnd(GfxState *state, Dict *opiDict) { + Object dict; + + if (globalParams->getPSOPI()) { + opiDict->lookup("2.0", &dict); + if (dict.isDict()) { + writePS("%%EndIncludedImage\n"); + writePS("%%EndOPI\n"); + writePS("grestore\n"); + --opi20Nest; + dict.free(); + } else { + dict.free(); + opiDict->lookup("1.3", &dict); + if (dict.isDict()) { + writePS("%%EndObject\n"); + writePS("restore\n"); + --opi13Nest; + } + dict.free(); + } + } +} + +GBool PSOutputDev::getFileSpec(Object *fileSpec, Object *fileName) { + if (fileSpec->isString()) { + fileSpec->copy(fileName); + return gTrue; + } + if (fileSpec->isDict()) { + fileSpec->dictLookup("DOS", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + fileSpec->dictLookup("Mac", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + fileSpec->dictLookup("Unix", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + fileSpec->dictLookup("F", fileName); + if (fileName->isString()) { + return gTrue; + } + fileName->free(); + } + return gFalse; +} +#endif // OPI_SUPPORT + +void PSOutputDev::type3D0(GfxState *state, double wx, double wy) { + writePSFmt("{0:.4g} {1:.4g} setcharwidth\n", wx, wy); + writePS("q\n"); + t3NeedsRestore = gTrue; +} + +void PSOutputDev::type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury) { + t3WX = wx; + t3WY = wy; + t3LLX = llx; + t3LLY = lly; + t3URX = urx; + t3URY = ury; + t3String = new GString(); + writePS("q\n"); + t3Cacheable = gTrue; + t3NeedsRestore = gTrue; +} + +void PSOutputDev::drawForm(Ref id) { + writePSFmt("f_{0:d}_{1:d}\n", id.num, id.gen); +} + +void PSOutputDev::psXObject(Stream *psStream, Stream *level1Stream) { + Stream *str; + int c; + + if ((level == psLevel1 || level == psLevel1Sep) && level1Stream) { + str = level1Stream; + } else { + str = psStream; + } + str->reset(); + while ((c = str->getChar()) != EOF) { + writePSChar(c); + } + str->close(); +} + +//~ can nextFunc be reset to 0 -- maybe at the start of each page? +//~ or maybe at the start of each color space / pattern? +void PSOutputDev::cvtFunction(Function *func) { + SampledFunction *func0; + ExponentialFunction *func2; + StitchingFunction *func3; + PostScriptFunction *func4; + int thisFunc, m, n, nSamples, i, j, k; + + switch (func->getType()) { + + case -1: // identity + writePS("{}\n"); + break; + + case 0: // sampled + func0 = (SampledFunction *)func; + thisFunc = nextFunc++; + m = func0->getInputSize(); + n = func0->getOutputSize(); + nSamples = n; + for (i = 0; i < m; ++i) { + nSamples *= func0->getSampleSize(i); + } + writePSFmt("/xpdfSamples{0:d} [\n", thisFunc); + for (i = 0; i < nSamples; ++i) { + writePSFmt("{0:.4g}\n", func0->getSamples()[i]); + } + writePS("] def\n"); + writePSFmt("{{ {0:d} array {1:d} array {2:d} 2 roll\n", 2*m, m, m+2); + // [e01] [efrac] x0 x1 ... xm-1 + for (i = m-1; i >= 0; --i) { + // [e01] [efrac] x0 x1 ... xi + writePSFmt("{0:.4g} sub {1:.4g} mul {2:.4g} add\n", + func0->getDomainMin(i), + (func0->getEncodeMax(i) - func0->getEncodeMin(i)) / + (func0->getDomainMax(i) - func0->getDomainMin(i)), + func0->getEncodeMin(i)); + // [e01] [efrac] x0 x1 ... xi-1 xi' + writePSFmt("dup 0 lt {{ pop 0 }} {{ dup {0:d} gt {{ pop {1:d} }} if }} ifelse\n", + func0->getSampleSize(i) - 1, func0->getSampleSize(i) - 1); + // [e01] [efrac] x0 x1 ... xi-1 xi' + writePS("dup floor cvi exch dup ceiling cvi exch 2 index sub\n"); + // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi') xi'-floor(xi') + writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i+3, i); + // [e01] [efrac] x0 x1 ... xi-1 floor(xi') ceiling(xi') + writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i+3, 2*i+1); + // [e01] [efrac] x0 x1 ... xi-1 floor(xi') + writePSFmt("{0:d} index {1:d} 3 2 roll put\n", i+2, 2*i); + // [e01] [efrac] x0 x1 ... xi-1 + } + // [e01] [efrac] + for (i = 0; i < n; ++i) { + // [e01] [efrac] y(0) ... y(i-1) + for (j = 0; j < (1<> k) & 1)); + for (k = m - 2; k >= 0; --k) { + writePSFmt("{0:d} mul {1:d} index {2:d} get add\n", + func0->getSampleSize(k), + i + j + 3, + 2 * k + ((j >> k) & 1)); + } + if (n > 1) { + writePSFmt("{0:d} mul {1:d} add ", n, i); + } + writePS("get\n"); + } + // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^m-1) + for (j = 0; j < m; ++j) { + // [e01] [efrac] y(0) ... y(i-1) s(0) s(1) ... s(2^(m-j)-1) + for (k = 0; k < (1 << (m - j)); k += 2) { + // [e01] [efrac] y(0) ... y(i-1) <2^(m-j)-k s values> + writePSFmt("{0:d} index {1:d} get dup\n", + i + k/2 + (1 << (m-j)) - k, j); + writePS("3 2 roll mul exch 1 exch sub 3 2 roll mul add\n"); + writePSFmt("{0:d} 1 roll\n", k/2 + (1 << m-j) - k - 1); + } + // [e01] [efrac] s'(0) s'(1) ... s(2^(m-j-1)-1) + } + // [e01] [efrac] y(0) ... y(i-1) s + writePSFmt("{0:.4g} mul {1:.4g} add\n", + func0->getDecodeMax(i) - func0->getDecodeMin(i), + func0->getDecodeMin(i)); + writePSFmt("dup {0:.4g} lt {{ pop {1:.4g} }} {{ dup {2:.4g} gt {{ pop {3:.4g} }} if }} ifelse\n", + func0->getRangeMin(i), func0->getRangeMin(i), + func0->getRangeMax(i), func0->getRangeMax(i)); + // [e01] [efrac] y(0) ... y(i-1) y(i) + } + // [e01] [efrac] y(0) ... y(n-1) + writePSFmt("{0:d} {1:d} roll pop pop }}\n", n+2, n); + break; + + case 2: // exponential + func2 = (ExponentialFunction *)func; + n = func2->getOutputSize(); + writePSFmt("{{ dup {0:.4g} lt {{ pop {1:.4g} }} {{ dup {2:.4g} gt {{ pop {3:.4g} }} if }} ifelse\n", + func2->getDomainMin(0), func2->getDomainMin(0), + func2->getDomainMax(0), func2->getDomainMax(0)); + // x + for (i = 0; i < n; ++i) { + // x y(0) .. y(i-1) + writePSFmt("{0:d} index {1:.4g} exp {2:.4g} mul {3:.4g} add\n", + i, func2->getE(), func2->getC1()[i] - func2->getC0()[i], + func2->getC0()[i]); + if (func2->getHasRange()) { + writePSFmt("dup {0:.4g} lt {{ pop {1:.4g} }} {{ dup {2:.4g} gt {{ pop {3:.4g} }} if }} ifelse\n", + func2->getRangeMin(i), func2->getRangeMin(i), + func2->getRangeMax(i), func2->getRangeMax(i)); + } + } + // x y(0) .. y(n-1) + writePSFmt("{0:d} {1:d} roll pop }}\n", n+1, n); + break; + + case 3: // stitching + func3 = (StitchingFunction *)func; + thisFunc = nextFunc++; + for (i = 0; i < func3->getNumFuncs(); ++i) { + cvtFunction(func3->getFunc(i)); + writePSFmt("/xpdfFunc{0:d}_{1:d} exch def\n", thisFunc, i); + } + writePSFmt("{{ dup {0:.4g} lt {{ pop {1:.4g} }} {{ dup {2:.4g} gt {{ pop {3:.4g} }} if }} ifelse\n", + func3->getDomainMin(0), func3->getDomainMin(0), + func3->getDomainMax(0), func3->getDomainMax(0)); + for (i = 0; i < func3->getNumFuncs() - 1; ++i) { + writePSFmt("dup {0:.4g} lt {{ {1:.4g} sub {2:.4g} mul {3:.4g} add xpdfFunc{4:d}_{5:d} }} {{\n", + func3->getBounds()[i+1], + func3->getBounds()[i], + func3->getScale()[i], + func3->getEncode()[2*i], + thisFunc, i); + } + writePSFmt("{0:.4g} sub {1:.4g} mul {2:.4g} add xpdfFunc{3:d}_{4:d}\n", + func3->getBounds()[i], + func3->getScale()[i], + func3->getEncode()[2*i], + thisFunc, i); + for (i = 0; i < func3->getNumFuncs() - 1; ++i) { + writePS("} ifelse\n"); + } + writePS("}\n"); + break; + + case 4: // PostScript + func4 = (PostScriptFunction *)func; + writePS(func4->getCodeString()->getCString()); + writePS("\n"); + break; + } +} + +void PSOutputDev::writePSChar(char c) { + if (t3String) { + t3String->append(c); + } else { + (*outputFunc)(outputStream, &c, 1); + } +} + +void PSOutputDev::writePS(char *s) { + if (t3String) { + t3String->append(s); + } else { + (*outputFunc)(outputStream, s, strlen(s)); + } +} + +void PSOutputDev::writePSFmt(const char *fmt, ...) { + va_list args; + GString *buf; + + va_start(args, fmt); + if (t3String) { + t3String->appendfv((char *)fmt, args); + } else { + buf = GString::formatv((char *)fmt, args); + (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); + delete buf; + } + va_end(args); +} + +void PSOutputDev::writePSString(GString *s) { + Guchar *p; + int n, line; + char buf[8]; + + writePSChar('('); + line = 1; + for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) { + if (line >= 64) { + writePSChar('\\'); + writePSChar('\n'); + line = 0; + } + if (*p == '(' || *p == ')' || *p == '\\') { + writePSChar('\\'); + writePSChar((char)*p); + line += 2; + } else if (*p < 0x20 || *p >= 0x80) { + sprintf(buf, "\\%03o", *p); + writePS(buf); + line += 4; + } else { + writePSChar((char)*p); + ++line; + } + } + writePSChar(')'); +} + +void PSOutputDev::writePSName(char *s) { + char *p; + char c; + + p = s; + while ((c = *p++)) { + if (c <= (char)0x20 || c >= (char)0x7f || + c == '(' || c == ')' || c == '<' || c == '>' || + c == '[' || c == ']' || c == '{' || c == '}' || + c == '/' || c == '%') { + writePSFmt("#{0:02x}", c & 0xff); + } else { + writePSChar(c); + } + } +} + +GString *PSOutputDev::filterPSName(GString *name) { + GString *name2; + char buf[8]; + int i; + char c; + + name2 = new GString(); + + // ghostscript chokes on names that begin with out-of-limits + // numbers, e.g., 1e4foo is handled correctly (as a name), but + // 1e999foo generates a limitcheck error + c = name->getChar(0); + if (c >= '0' && c <= '9') { + name2->append('f'); + } + + for (i = 0; i < name->getLength(); ++i) { + c = name->getChar(i); + if (c <= (char)0x20 || c >= (char)0x7f || + c == '(' || c == ')' || c == '<' || c == '>' || + c == '[' || c == ']' || c == '{' || c == '}' || + c == '/' || c == '%') { + sprintf(buf, "#%02x", c & 0xff); + name2->append(buf); + } else { + name2->append(c); + } + } + return name2; +} + +// Write a DSC-compliant . +void PSOutputDev::writePSTextLine(GString *s) { + int i, j, step; + int c; + + // - DSC comments must be printable ASCII; control chars and + // backslashes have to be escaped (we do cheap Unicode-to-ASCII + // conversion by simply ignoring the high byte) + // - lines are limited to 255 chars (we limit to 200 here to allow + // for the keyword, which was emitted by the caller) + // - lines that start with a left paren are treated as + // instead of , so we escape a leading paren + if (s->getLength() >= 2 && + (s->getChar(0) & 0xff) == 0xfe && + (s->getChar(1) & 0xff) == 0xff) { + i = 3; + step = 2; + } else { + i = 0; + step = 1; + } + for (j = 0; i < s->getLength() && j < 200; i += step) { + c = s->getChar(i) & 0xff; + if (c == '\\') { + writePS("\\\\"); + j += 2; + } else if (c < 0x20 || c > 0x7e || (j == 0 && c == '(')) { + writePSFmt("\\{0:03o}", c); + j += 4; + } else { + writePSChar(c); + ++j; + } + } + writePS("\n"); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PSOutputDev.h swftools-0.9.1/lib/pdf/xpdf/PSOutputDev.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/PSOutputDev.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PSOutputDev.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,395 @@ +//======================================================================== +// +// PSOutputDev.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PSOUTPUTDEV_H +#define PSOUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "config.h" +#include "Object.h" +#include "GlobalParams.h" +#include "OutputDev.h" + +class Function; +class GfxPath; +class GfxFont; +class GfxColorSpace; +class GfxSeparationColorSpace; +class PDFRectangle; +struct PSFont8Info; +struct PSFont16Enc; +class PSOutCustomColor; + +//------------------------------------------------------------------------ +// PSOutputDev +//------------------------------------------------------------------------ + +enum PSOutMode { + psModePS, + psModeEPS, + psModeForm +}; + +enum PSFileType { + psFile, // write to file + psPipe, // write to pipe + psStdout, // write to stdout + psGeneric // write to a generic stream +}; + +typedef void (*PSOutputFunc)(void *stream, char *data, int len); + +class PSOutputDev: public OutputDev { +public: + + // Open a PostScript output file, and write the prolog. + PSOutputDev(char *fileName, XRef *xrefA, Catalog *catalog, + int firstPage, int lastPage, PSOutMode modeA, + int imgLLXA = 0, int imgLLYA = 0, + int imgURXA = 0, int imgURYA = 0, + GBool manualCtrlA = gFalse); + + // Open a PSOutputDev that will write to a generic stream. + PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, + XRef *xrefA, Catalog *catalog, + int firstPage, int lastPage, PSOutMode modeA, + int imgLLXA = 0, int imgLLYA = 0, + int imgURXA = 0, int imgURYA = 0, + GBool manualCtrlA = gFalse); + + // Destructor -- writes the trailer and closes the file. + virtual ~PSOutputDev(); + + // Check if file was successfully created. + virtual GBool isOk() { return ok; } + + //---- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() { return gFalse; } + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() { return gFalse; } + + // Does this device use tilingPatternFill()? If this returns false, + // tiling pattern fills will be reduced to a series of other drawing + // operations. + virtual GBool useTilingPatternFill() { return gTrue; } + + // Does this device use functionShadedFill(), axialShadedFill(), and + // radialShadedFill()? If this returns false, these shaded fills + // will be reduced to a series of other drawing operations. + virtual GBool useShadedFills() + { return level >= psLevel2; } + + // Does this device use drawForm()? If this returns false, + // form-type XObjects will be interpreted (i.e., unrolled). + virtual GBool useDrawForm() { return preload; } + + // Does this device use beginType3Char/endType3Char? Otherwise, + // text in Type 3 fonts will be drawn with drawChar/drawString. + virtual GBool interpretType3Chars() { return gFalse; } + + //----- header/trailer (used only if manualCtrl is true) + + // Write the document-level header. + void writeHeader(int firstPage, int lastPage, + PDFRectangle *mediaBox, PDFRectangle *cropBox, + int pageRotate); + + // Write the Xpdf procset. + void writeXpdfProcset(); + + // Write the document-level setup. + void writeDocSetup(Catalog *catalog, int firstPage, int lastPage); + + // Write the trailer for the current page. + void writePageTrailer(); + + // Write the document trailer. + void writeTrailer(); + + //----- initialization and control + + // Check to see if a page slice should be displayed. If this + // returns false, the page display is aborted. Typically, an + // OutputDev will use some alternate means to display the page + // before returning false. + virtual GBool checkPageSlice(Page *page, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool printing, Catalog *catalog, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); + + // Start a page. + virtual void startPage(int pageNum, GfxState *state); + + // End a page. + virtual void endPage(); + + //----- save/restore graphics state + virtual void saveState(GfxState *state); + virtual void restoreState(GfxState *state); + + //----- update graphics state + virtual void updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32); + virtual void updateLineDash(GfxState *state); + virtual void updateFlatness(GfxState *state); + virtual void updateLineJoin(GfxState *state); + virtual void updateLineCap(GfxState *state); + virtual void updateMiterLimit(GfxState *state); + virtual void updateLineWidth(GfxState *state); + virtual void updateFillColorSpace(GfxState *state); + virtual void updateStrokeColorSpace(GfxState *state); + virtual void updateFillColor(GfxState *state); + virtual void updateStrokeColor(GfxState *state); + virtual void updateFillOverprint(GfxState *state); + virtual void updateStrokeOverprint(GfxState *state); + virtual void updateTransfer(GfxState *state); + + //----- update text state + virtual void updateFont(GfxState *state); + virtual void updateTextMat(GfxState *state); + virtual void updateCharSpace(GfxState *state); + virtual void updateRender(GfxState *state); + virtual void updateRise(GfxState *state); + virtual void updateWordSpace(GfxState *state); + virtual void updateHorizScaling(GfxState *state); + virtual void updateTextPos(GfxState *state); + virtual void updateTextShift(GfxState *state, double shift); + + //----- path painting + virtual void stroke(GfxState *state); + virtual void fill(GfxState *state); + virtual void eoFill(GfxState *state); + virtual void tilingPatternFill(GfxState *state, Object *str, + int paintType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep); + virtual GBool functionShadedFill(GfxState *state, + GfxFunctionShading *shading); + virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading); + virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading); + + //----- path clipping + virtual void clip(GfxState *state); + virtual void eoClip(GfxState *state); + virtual void clipToStrokePath(GfxState *state); + + //----- text drawing + virtual void drawString(GfxState *state, GString *s); + virtual void endTextObject(GfxState *state); + + //----- image drawing + virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, int maskWidth, int maskHeight, + GBool maskInvert); + +#if OPI_SUPPORT + //----- OPI functions + virtual void opiBegin(GfxState *state, Dict *opiDict); + virtual void opiEnd(GfxState *state, Dict *opiDict); +#endif + + //----- Type 3 font operators + virtual void type3D0(GfxState *state, double wx, double wy); + virtual void type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury); + + //----- form XObjects + virtual void drawForm(Ref ref); + + //----- PostScript XObjects + virtual void psXObject(Stream *psStream, Stream *level1Stream); + + //----- miscellaneous + void setOffset(double x, double y) + { tx0 = x; ty0 = y; } + void setScale(double x, double y) + { xScale0 = x; yScale0 = y; } + void setRotate(int rotateA) + { rotate0 = rotateA; } + void setClip(double llx, double lly, double urx, double ury) + { clipLLX0 = llx; clipLLY0 = lly; clipURX0 = urx; clipURY0 = ury; } + void setUnderlayCbk(void (*cbk)(PSOutputDev *psOut, void *data), + void *data) + { underlayCbk = cbk; underlayCbkData = data; } + void setOverlayCbk(void (*cbk)(PSOutputDev *psOut, void *data), + void *data) + { overlayCbk = cbk; overlayCbkData = data; } + +private: + + void init(PSOutputFunc outputFuncA, void *outputStreamA, + PSFileType fileTypeA, XRef *xrefA, Catalog *catalog, + int firstPage, int lastPage, PSOutMode modeA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool manualCtrlA); + void setupResources(Dict *resDict); + void setupFonts(Dict *resDict); + void setupFont(GfxFont *font, Dict *parentResDict); + void setupEmbeddedType1Font(Ref *id, GString *psName); + void setupExternalType1Font(GString *fileName, GString *psName); + void setupEmbeddedType1CFont(GfxFont *font, Ref *id, GString *psName); + void setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id, GString *psName); + void setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, GString *psName); + void setupExternalTrueTypeFont(GfxFont *font, GString *psName); + void setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, GString *psName); + void setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, GString *psName, + GBool needVerticalMetrics); + void setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id, GString *psName); + void setupType3Font(GfxFont *font, GString *psName, Dict *parentResDict); + void setupImages(Dict *resDict); + void setupImage(Ref id, Stream *str); + void setupForms(Dict *resDict); + void setupForm(Ref id, Object *strObj); + void addProcessColor(double c, double m, double y, double k); + void addCustomColor(GfxSeparationColorSpace *sepCS); + void doPath(GfxPath *path); + void doImageL1(Object *ref, GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len); + void doImageL1Sep(GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len); + void doImageL2(Object *ref, GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len, + int *maskColors, Stream *maskStr, + int maskWidth, int maskHeight, GBool maskInvert); + void doImageL3(Object *ref, GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len, + int *maskColors, Stream *maskStr, + int maskWidth, int maskHeight, GBool maskInvert); + void dumpColorSpaceL2(GfxColorSpace *colorSpace, + GBool genXform, GBool updateColors, + GBool map01); +#if OPI_SUPPORT + void opiBegin20(GfxState *state, Dict *dict); + void opiBegin13(GfxState *state, Dict *dict); + void opiTransform(GfxState *state, double x0, double y0, + double *x1, double *y1); + GBool getFileSpec(Object *fileSpec, Object *fileName); +#endif + void cvtFunction(Function *func); + void writePSChar(char c); + void writePS(char *s); + void writePSFmt(const char *fmt, ...); + void writePSString(GString *s); + void writePSName(char *s); + GString *filterPSName(GString *name); + void writePSTextLine(GString *s); + + PSLevel level; // PostScript level (1, 2, separation) + PSOutMode mode; // PostScript mode (PS, EPS, form) + int paperWidth; // width of paper, in pts + int paperHeight; // height of paper, in pts + int imgLLX, imgLLY, // imageable area, in pts + imgURX, imgURY; + GBool preload; // load all images into memory, and + // predefine forms + + PSOutputFunc outputFunc; + void *outputStream; + PSFileType fileType; // file / pipe / stdout + GBool manualCtrl; + int seqPage; // current sequential page number + void (*underlayCbk)(PSOutputDev *psOut, void *data); + void *underlayCbkData; + void (*overlayCbk)(PSOutputDev *psOut, void *data); + void *overlayCbkData; + + XRef *xref; // the xref table for this PDF file + + Ref *fontIDs; // list of object IDs of all used fonts + int fontIDLen; // number of entries in fontIDs array + int fontIDSize; // size of fontIDs array + Ref *fontFileIDs; // list of object IDs of all embedded fonts + int fontFileIDLen; // number of entries in fontFileIDs array + int fontFileIDSize; // size of fontFileIDs array + GString **fontFileNames; // list of names of all embedded external fonts + int fontFileNameLen; // number of entries in fontFileNames array + int fontFileNameSize; // size of fontFileNames array + int nextTrueTypeNum; // next unique number to append to a TrueType + // font name + PSFont8Info *font8Info; // info for 8-bit fonts + int font8InfoLen; // number of entries in font8Info array + int font8InfoSize; // size of font8Info array + PSFont16Enc *font16Enc; // encodings for substitute 16-bit fonts + int font16EncLen; // number of entries in font16Enc array + int font16EncSize; // size of font16Enc array + Ref *imgIDs; // list of image IDs for in-memory images + int imgIDLen; // number of entries in imgIDs array + int imgIDSize; // size of imgIDs array + Ref *formIDs; // list of IDs for predefined forms + int formIDLen; // number of entries in formIDs array + int formIDSize; // size of formIDs array + GList *xobjStack; // stack of XObject dicts currently being + // processed + int numSaves; // current number of gsaves + int numTilingPatterns; // current number of nested tiling patterns + int nextFunc; // next unique number to use for a function + + double tx0, ty0; // global translation + double xScale0, yScale0; // global scaling + int rotate0; // rotation angle (0, 90, 180, 270) + double clipLLX0, clipLLY0, + clipURX0, clipURY0; + double tx, ty; // global translation for current page + double xScale, yScale; // global scaling for current page + int rotate; // rotation angle for current page + double epsX1, epsY1, // EPS bounding box (unrotated) + epsX2, epsY2; + + GString *embFontList; // resource comments for embedded fonts + + int processColors; // used process colors + PSOutCustomColor // used custom colors + *customColors; + + GBool haveTextClip; // set if text has been drawn with a + // clipping render mode + + GBool inType3Char; // inside a Type 3 CharProc + GString *t3String; // Type 3 content string + double t3WX, t3WY, // Type 3 character parameters + t3LLX, t3LLY, t3URX, t3URY; + GBool t3Cacheable; // cleared if char is not cacheable + GBool t3NeedsRestore; // set if a 'q' operator was issued + +#if OPI_SUPPORT + int opi13Nest; // nesting level of OPI 1.3 objects + int opi20Nest; // nesting level of OPI 2.0 objects +#endif + + GBool ok; // set up ok? + + + friend class WinPDFPrinter; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PSTokenizer.cc swftools-0.9.1/lib/pdf/xpdf/PSTokenizer.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/PSTokenizer.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PSTokenizer.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,135 @@ +//======================================================================== +// +// PSTokenizer.cc +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "PSTokenizer.h" + +//------------------------------------------------------------------------ + +// A '1' in this array means the character is white space. A '1' or +// '2' means the character ends a name or command. +static char specialChars[256] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx +}; + +//------------------------------------------------------------------------ + +PSTokenizer::PSTokenizer(int (*getCharFuncA)(void *), void *dataA) { + getCharFunc = getCharFuncA; + data = dataA; + charBuf = -1; +} + +PSTokenizer::~PSTokenizer() { +} + +GBool PSTokenizer::getToken(char *buf, int size, int *length) { + GBool comment, backslash; + int c; + int i; + + // skip whitespace and comments + comment = gFalse; + while (1) { + if ((c = getChar()) == EOF) { + buf[0] = '\0'; + *length = 0; + return gFalse; + } + if (comment) { + if (c == '\x0a' || c == '\x0d') { + comment = gFalse; + } + } else if (c == '%') { + comment = gTrue; + } else if (specialChars[c] != 1) { + break; + } + } + + // read a token + i = 0; + buf[i++] = c; + if (c == '(') { + backslash = gFalse; + while ((c = lookChar()) != EOF) { + if (i < size - 1) { + buf[i++] = c; + } + getChar(); + if (c == '\\') { + backslash = gTrue; + } else if (!backslash && c == ')') { + break; + } else { + backslash = gFalse; + } + } + } else if (c == '<') { + while ((c = lookChar()) != EOF) { + getChar(); + if (i < size - 1 && specialChars[c] != 1) { + buf[i++] = c; + } + if (c == '>') { + break; + } + } + } else if (c != '[' && c != ']') { + while ((c = lookChar()) != EOF && !specialChars[c]) { + getChar(); + if (i < size - 1) { + buf[i++] = c; + } + } + } + buf[i] = '\0'; + *length = i; + + return gTrue; +} + +int PSTokenizer::lookChar() { + if (charBuf < 0) { + charBuf = (*getCharFunc)(data); + } + return charBuf; +} + +int PSTokenizer::getChar() { + int c; + + if (charBuf < 0) { + charBuf = (*getCharFunc)(data); + } + c = charBuf; + charBuf = -1; + return c; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/PSTokenizer.h swftools-0.9.1/lib/pdf/xpdf/PSTokenizer.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/PSTokenizer.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/PSTokenizer.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,41 @@ +//======================================================================== +// +// PSTokenizer.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef PSTOKENIZER_H +#define PSTOKENIZER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +//------------------------------------------------------------------------ + +class PSTokenizer { +public: + + PSTokenizer(int (*getCharFuncA)(void *), void *dataA); + ~PSTokenizer(); + + // Get the next PostScript token. Returns false at end-of-stream. + GBool getToken(char *buf, int size, int *length); + +private: + + int lookChar(); + int getChar(); + + int (*getCharFunc)(void *); + void *data; + int charBuf; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/README swftools-0.9.1/lib/pdf/xpdf/README --- swftools-0.9.2+ds1/lib/pdf/xpdf/README 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/README 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,405 @@ +Xpdf +==== + +version 3.02 +2007-feb-27 + +The Xpdf software and documentation are +copyright 1996-2007 Glyph & Cog, LLC. + +Email: derekn@foolabs.com +WWW: http://www.foolabs.com/xpdf/ + +The PDF data structures, operators, and specification are +copyright 1985-2006 Adobe Systems Inc. + + +What is Xpdf? +------------- + +Xpdf is an open source viewer for Portable Document Format (PDF) +files. (These are also sometimes also called 'Acrobat' files, from +the name of Adobe's PDF software.) The Xpdf project also includes a +PDF text extractor, PDF-to-PostScript converter, and various other +utilities. + +Xpdf runs under the X Window System on UNIX, VMS, and OS/2. The non-X +components (pdftops, pdftotext, etc.) also run on Win32 systems and +should run on pretty much any system with a decent C++ compiler. + +Xpdf is designed to be small and efficient. It can use Type 1 or +TrueType fonts. + + +Distribution +------------ + +Xpdf is licensed under the GNU General Public License (GPL), version +2. In my opinion, the GPL is a convoluted, confusing, ambiguous mess. +But it's also pervasive, and I'm sick of arguing. And even if it is +confusing, the basic idea is good. + +In order to cut down on the confusion a little bit, here are some +informal clarifications: + +- I don't mind if you redistribute Xpdf in source and/or binary form, + as long as you include all of the documentation: README, man pages + (or help files), and COPYING. (Note that the README file contains a + pointer to a web page with the source code.) + +- Selling a CD-ROM that contains Xpdf is fine with me, as long as it + includes the documentation. I wouldn't mind receiving a sample + copy, but it's not necessary. + +- If you make useful changes to Xpdf, please make the source code + available -- post it on a web site, email it to me, whatever. + +If you're interested in commercial licensing, please see the Glyph & +Cog web site: + + http://www.glyphandcog.com/ + + +Compatibility +------------- + +Xpdf is developed and tested on a Linux 2.4 x86 system. + +In addition, it has been compiled by others on Solaris, AIX, HP-UX, +Digital Unix, Irix, and numerous other Unix implementations, as well +as VMS and OS/2. It should work on pretty much any system which runs +X11 and has Unix-like libraries. You'll need ANSI C++ and C compilers +to compile it. + +The non-X components of Xpdf (pdftops, pdftotext, pdfinfo, pdffonts, +pdftoppm, and pdfimages) can also be compiled on Win32 systems. See +the Xpdf web page for details. + +If you compile Xpdf for a system not listed on the web page, please +let me know. If you're willing to make your binary available by ftp +or on the web, I'll be happy to add a link from the Xpdf web page. I +have decided not to host any binaries I didn't compile myself (for +disk space and support reasons). + +If you can't get Xpdf to compile on your system, send me email and +I'll try to help. + +Xpdf has been ported to the Acorn, Amiga, BeOS, and EPOC. See the +Xpdf web page for links. + + +Getting Xpdf +------------ + +The latest version is available from: + + http://www.foolabs.com/xpdf/ + +or: + + ftp://ftp.foolabs.com/pub/xpdf/ + +Source code and several precompiled executables are available. + +Announcements of new versions are posted to several newsgroups +(comp.text.pdf, comp.os.linux.announce, and others) and emailed to a +list of people. If you'd like to receive email notification of new +versions, just let me know. + + +Running Xpdf +------------ + +To run xpdf, simply type: + + xpdf file.pdf + +To generate a PostScript file, hit the "print" button in xpdf, or run +pdftops: + + pdftops file.pdf + +To generate a plain text file, run pdftotext: + + pdftotext file.pdf + +There are four additional utilities (which are fully described in +their man pages): + + pdfinfo -- dumps a PDF file's Info dictionary (plus some other + useful information) + pdffonts -- lists the fonts used in a PDF file along with various + information for each font + pdftoppm -- converts a PDF file to a series of PPM/PGM/PBM-format + bitmaps + pdfimages -- extracts the images from a PDF file + +Command line options and many other details are described in the man +pages (xpdf.1, etc.) and the VMS help files (xpdf.hlp, etc.). + + +Upgrading from Xpdf 2.xx +------------------------ + +WARNING: Xpdf 3.00 switched to a new PDF rasterizer, which no longer +uses X fonts. You'll need a set of Base-14 fonts -- the URW fonts +distributed with ghostscript can be used for this. Xpdf will search +for the URW fonts, but if you have them installed in a non-standard +directory, you'll need to set up an xpdfrc config file to point to +them. For full details, please see the xpdfrc(5) man page. + + +Compiling Xpdf +-------------- + +See the separate file, INSTALL. + + +Bugs +---- + +If you find a bug in Xpdf, i.e., if it prints an error message, +crashes, or incorrectly displays a document, and you don't see that +bug listed here, please send me email, with a pointer (URL, ftp site, +etc.) to the PDF file. + + +Acknowledgments +--------------- + +Thanks to: + +* Patrick Voigt for help with the remote server code. +* Patrick Moreau, Martin P.J. Zinser, and David Mathog for the VMS + port. +* David Boldt and Rick Rodgers for sample man pages. +* Brendan Miller for the icon idea. +* Olly Betts for help testing pdftotext. +* Peter Ganten for the OS/2 port. +* Michael Richmond for the Win32 port of pdftops and pdftotext and the + xpdf/cygwin/XFree86 build instructions. +* Frank M. Siegert for improvements in the PostScript code. +* Leo Smiers for the decryption patches. +* Rainer Menzner for creating t1lib, and for helping me adapt it to + xpdf. +* Pine Tree Systems A/S for funding the OPI and EPS support in + pdftops. +* Easy Software Products for funding several improvements to the + PostScript output code. +* Tom Kacvinsky for help with FreeType and for being my interface to + the FreeType team. +* Theppitak Karoonboonyanan for help with Thai support. +* Leonard Rosenthol for help and contributions on a bunch of things. +* Alexandros Diamantidis and Maria Adaloglou for help with Greek + support. +* Lawrence Lai for help with the CJK Unicode maps. + +Various people have contributed modifications made for use by the +pdftex project: + +* Han The Thanh +* Martin Schröder of ArtCom GmbH + + +References +---------- + +Adobe Systems Inc., _PDF Reference, sixth edition: Adobe Portable +Document Format version 1.7_. +http://www.adobe.com/devnet/pdf/pdf_reference.html +[The manual for PDF version 1.7.] + +Adobe Systems Inc., "Errata for the PDF Reference, sixth edition, +version 1.7", October 16, 2006. +http://www.adobe.com/devnet/pdf/pdf_reference.html +[The errata for the PDF 1.7 spec.] + +Adobe Systems Inc., _PostScript Language Reference_, 3rd ed. +Addison-Wesley, 1999, ISBN 0-201-37922-8. +[The official PostScript manual.] + +Adobe Systems, Inc., _The Type 42 Font Format Specification_, +Adobe Developer Support Technical Specification #5012. 1998. +http://partners.adobe.com/asn/developer/pdfs/tn/5012.Type42_Spec.pdf +[Type 42 is the format used to embed TrueType fonts in PostScript +files.] + +Adobe Systems, Inc., _Adobe CMap and CIDFont Files Specification_, +Adobe Developer Support Technical Specification #5014. 1995. +http://www.adobe.com/supportservice/devrelations/PDFS/TN/5014.CIDFont_Spec.pdf +[CMap file format needed for Japanese and Chinese font support.] + +Adobe Systems, Inc., _Adobe-Japan1-4 Character Collection for +CID-Keyed Fonts_, Adobe Developer Support Technical Note #5078. +2000. +http://partners.adobe.com/asn/developer/PDFS/TN/5078.CID_Glyph.pdf +[The Adobe Japanese character set.] + +Adobe Systems, Inc., _Adobe-GB1-4 Character Collection for +CID-Keyed Fonts_, Adobe Developer Support Technical Note #5079. +2000. +http://partners.adobe.com/asn/developer/pdfs/tn/5079.Adobe-GB1-4.pdf +[The Adobe Chinese GB (simplified) character set.] + +Adobe Systems, Inc., _Adobe-CNS1-3 Character Collection for +CID-Keyed Fonts_, Adobe Developer Support Technical Note #5080. +2000. +http://partners.adobe.com/asn/developer/PDFS/TN/5080.CNS_CharColl.pdf +[The Adobe Chinese CNS (traditional) character set.] + +Adobe Systems Inc., _Supporting the DCT Filters in PostScript Level +2_, Adobe Developer Support Technical Note #5116. 1992. +http://www.adobe.com/supportservice/devrelations/PDFS/TN/5116.PS2_DCT.PDF +[Description of the DCTDecode filter parameters.] + +Adobe Systems Inc., _Open Prepress Interface (OPI) Specification - +Version 2.0_, Adobe Developer Support Technical Note #5660. 2000. +http://partners.adobe.com/asn/developer/PDFS/TN/5660.OPI_2.0.pdf + +Adobe Systems Inc., CMap files. +ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/ +[The actual CMap files for the 16-bit CJK encodings.] + +Adobe Systems Inc., Unicode glyph lists. +http://partners.adobe.com/asn/developer/type/unicodegn.html +http://partners.adobe.com/asn/developer/type/glyphlist.txt +http://partners.adobe.com/asn/developer/type/corporateuse.txt +http://partners.adobe.com/asn/developer/type/zapfdingbats.txt +[Mappings between character names to Unicode.] + +Adobe Systems Inc., OpenType Specification v. 1.4. +http://partners.adobe.com/public/developer/opentype/index_spec.html +[The OpenType font format spec.] + +Aldus Corp., _OPI: Open Prepress Interface Specification 1.3_. 1993. +http://partners.adobe.com/asn/developer/PDFS/TN/OPI_13.pdf + +Anonymous, RC4 source code. +ftp://ftp.ox.ac.uk/pub/crypto/misc/rc4.tar.gz +ftp://idea.sec.dsi.unimi.it/pub/crypt/code/rc4.tar.gz +[This is the algorithm used to encrypt PDF files.] + +T. Boutell, et al., "PNG (Portable Network Graphics) Specification, +Version 1.0". RFC 2083. +[PDF uses the PNG filter algorithms.] + +CCITT, "Information Technology - Digital Compression and Coding of +Continuous-tone Still Images - Requirements and Guidelines", CCITT +Recommendation T.81. +http://www.w3.org/Graphics/JPEG/ +[The official JPEG spec.] + +A. Chernov, "Registration of a Cyrillic Character Set". RFC 1489. +[Documentation for the KOI8-R Cyrillic encoding.] + +Roman Czyborra, "The ISO 8859 Alphabet Soup". +http://czyborra.com/charsets/iso8859.html +[Documentation on the various ISO 859 encodings.] + +L. Peter Deutsch, "ZLIB Compressed Data Format Specification version +3.3". RFC 1950. +[Information on the general format used in FlateDecode streams.] + +L. Peter Deutsch, "DEFLATE Compressed Data Format Specification +version 1.3". RFC 1951. +[The definition of the compression algorithm used in FlateDecode +streams.] + +Morris Dworkin, "Recommendation for Block Cipher Modes of Operation", +National Institute of Standards, NIST Special Publication 800-38A, +2001. +[The cipher block chaining (CBC) mode used with AES in PDF files.] + +Federal Information Processing Standards Publication 197 (FIPS PUBS +197), "Advanced Encryption Standard (AES)", November 26, 2001. +[AES encryption, used in PDF 1.6.] + +Jim Flowers, "X Logical Font Description Conventions", Version 1.5, X +Consortium Standard, X Version 11, Release 6.1. +ftp://ftp.x.org/pub/R6.1/xc/doc/hardcopy/XLFD/xlfd.PS.Z +[The official specification of X font descriptors, including font +transformation matrices.] + +Foley, van Dam, Feiner, and Hughes, _Computer Graphics: Principles and +Practice_, 2nd ed. Addison-Wesley, 1990, ISBN 0-201-12110-7. +[Colorspace conversion functions, Bezier spline math.] + +Robert L. Hummel, _Programmer's Technical Reference: Data and Fax +Communications_. Ziff-Davis Press, 1993, ISBN 1-56276-077-7. +[CCITT Group 3 and 4 fax decoding.] + +ISO/IEC, _Information technology -- Lossy/lossless coding of bi-level +images_. ISO/IEC 14492, First edition (2001-12-15). +http://webstore.ansi.org/ +[The official JBIG2 standard. The final draft of this spec is +available from http://www.jpeg.org/jbighomepage.html.] + +ISO/IEC, _Information technology -- JPEG 2000 image coding system -- +Part 1: Core coding system_. ISO/IEC 15444-1, First edition +(2000-12-15). +http://webstore.ansi.org/ +[The official JPEG 2000 standard. The final committee draft of this +spec is available from http://www.jpeg.org/JPEG2000.html, but there +were changes made to the bitstream format between that draft and the +published spec.] + +ITU, "Standardization of Group 3 facsimile terminals for document +transmission", ITU-T Recommendation T.4, 1999. +ITU, "Facsimile coding schemes and coding control functions for Group 4 +facsimile apparatus", ITU-T Recommendation T.6, 1993. +http://www.itu.int/ +[The official Group 3 and 4 fax standards - used by the CCITTFaxDecode +stream, as well as the JBIG2Decode stream.] + +B. Kaliski, "PKCS #5: Password-Based Cryptography Specification, +Version 2.0". RFC 2898. +[Defines the padding scheme used with AES encryption in PDF files.] + +Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, "Practical +Fast 1-D DCT Algorithms with 11 Multiplications". IEEE Intl. Conf. on +Acoustics, Speech & Signal Processing, 1989, 988-991. +[The fast IDCT algorithm used in the DCTDecode filter.] + +Microsoft, _TrueType 1.0 Font Files_, rev. 1.66. 1995. +http://www.microsoft.com/typography/tt/tt.htm +[The TrueType font spec (in MS Word format, naturally).] + +V. Ostromoukhov, R.D. Hersch, "Stochastic Clustered-Dot Dithering", +Conf. Color Imaging: Device-Independent Color, Color Hardcopy, and +Graphic Arts IV, 1999, SPIE Vol. 3648, 496-505. +http://diwww.epfl.ch/w3lsp/publications/colour/scd.html +[The stochastic dithering algorithm used in Xpdf.] + +P. Peterlin, "ISO 8859-2 (Latin 2) Resources". +http://sizif.mf.uni-lj.si/linux/cee/iso8859-2.html +[This is a web page with all sorts of useful Latin-2 character set and +font information.] + +Charles Poynton, "Color FAQ". +http://www.inforamp.net/~poynton/ColorFAQ.html +[The mapping from the CIE 1931 (XYZ) color space to RGB.] + +R. Rivest, "The MD5 Message-Digest Algorithm". RFC 1321. +[MD5 is used in PDF document encryption.] + +Thai Industrial Standard, "Standard for Thai Character Codes for +Computers", TIS-620-2533 (1990). +http://www.nectec.or.th/it-standards/std620/std620.htm +[The TIS-620 Thai encoding.] + +Unicode Consortium, "Unicode Home Page". +http://www.unicode.org/ +[Online copy of the Unicode spec.] + +W3C Recommendation, "PNG (Portable Network Graphics) Specification +Version 1.0". +http://www.w3.org/Graphics/PNG/ +[Defines the PNG image predictor.] + +Gregory K. Wallace, "The JPEG Still Picture Compression Standard". +ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz +[Good description of the JPEG standard. Also published in CACM, April +1991, and submitted to IEEE Transactions on Consumer Electronics.] + +F. Yergeau, "UTF-8, a transformation format of ISO 10646". RFC 2279. +[A commonly used Unicode encoding.] diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/rightArrowDis.xbm swftools-0.9.1/lib/pdf/xpdf/rightArrowDis.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/rightArrowDis.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/rightArrowDis.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,5 @@ +#define rightArrowDis_width 8 +#define rightArrowDis_height 15 +static unsigned char rightArrowDis_bits[] = { + 0x01, 0x02, 0x05, 0x0a, 0x15, 0x2a, 0x55, 0xaa, 0x55, 0x2a, 0x15, 0x0a, + 0x05, 0x02, 0x01}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/rightArrow.xbm swftools-0.9.1/lib/pdf/xpdf/rightArrow.xbm --- swftools-0.9.2+ds1/lib/pdf/xpdf/rightArrow.xbm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/rightArrow.xbm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,5 @@ +#define rightArrow_width 8 +#define rightArrow_height 15 +static unsigned char rightArrow_bits[] = { + 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x7f, 0x3f, 0x1f, 0x0f, + 0x07, 0x03, 0x01}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/sample-xpdfrc swftools-0.9.1/lib/pdf/xpdf/sample-xpdfrc --- swftools-0.9.2+ds1/lib/pdf/xpdf/sample-xpdfrc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/sample-xpdfrc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,91 @@ +#======================================================================== +# +# Sample xpdfrc file +# +# The Xpdf tools look for a config file in two places: +# 1. ~/.xpdfrc +# 2. in a system-wide directory, typically /usr/local/etc/xpdfrc +# +# This sample config file demonstrates some of the more common +# configuration options. Everything here is commented out. You +# should edit things (especially the file/directory paths, since +# they'll likely be different on your system), and uncomment whichever +# options you want to use. For complete details on config file syntax +# and available options, please see the xpdfrc(5) man page. +# +# Also, the Xpdf language support packages each include a set of +# options to be added to the xpdfrc file. +# +# http://www.foolabs.com/xpdf/ +# +#======================================================================== + +#----- display fonts + +# These map the Base-14 fonts to the Type 1 fonts that ship with +# ghostscript. You'll almost certainly want to use something like +# this, but you'll need to adjust this to point to wherever +# ghostscript is installed on your system. (But if the fonts are +# installed in a "standard" location, xpdf will find them +# automatically.) + +#displayFontT1 Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb +#displayFontT1 Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb +#displayFontT1 Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb +#displayFontT1 Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb +#displayFontT1 Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb +#displayFontT1 Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb +#displayFontT1 Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb +#displayFontT1 Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb +#displayFontT1 Courier /usr/local/share/ghostscript/fonts/n022003l.pfb +#displayFontT1 Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb +#displayFontT1 Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb +#displayFontT1 Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb +#displayFontT1 Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb +#displayFontT1 ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb + +# If you need to display PDF files that refer to non-embedded fonts, +# you should add one or more fontDir options to point to the +# directories containing the font files. Xpdf will only look at .pfa, +# .pfb, and .ttf files in those directories (other files will simply +# be ignored). + +#fontDir /usr/local/fonts/bakoma + +#----- PostScript output control + +# Set the default PostScript file or command. + +#psFile "|lpr -Pmyprinter" + +# Set the default PostScript paper size -- this can be letter, legal, +# A4, or A3. You can also specify a paper size as width and height +# (in points). + +#psPaperSize letter + +#----- text output control + +# Choose a text encoding for copy-and-paste and for pdftotext output. +# The Latin1, ASCII7, and UTF-8 encodings are built into Xpdf. Other +# encodings are available in the language support packages. + +#textEncoding UTF-8 + +# Choose the end-of-line convention for multi-line copy-and-past and +# for pdftotext output. The available options are unix, mac, and dos. + +#textEOL unix + +#----- misc settings + +# Enable t1lib, FreeType, and anti-aliased text. + +#enableT1lib yes +#enableFreeType yes +#antialias yes + +# Set the command used to run a web browser when a URL hyperlink is +# clicked. + +#urlCommand "netscape -remote 'openURL(%s)'" diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SecurityHandler.cc swftools-0.9.1/lib/pdf/xpdf/SecurityHandler.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SecurityHandler.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SecurityHandler.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,390 @@ +//======================================================================== +// +// SecurityHandler.cc +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "GString.h" +#include "PDFDoc.h" +#include "Decrypt.h" +#include "Error.h" +#include "GlobalParams.h" +#if HAVE_XPDFCORE +# include "XPDFCore.h" +#elif HAVE_WINPDFCORE +# include "WinPDFCore.h" +#endif +#ifdef ENABLE_PLUGINS +# include "XpdfPluginAPI.h" +#endif +#include "SecurityHandler.h" + +//------------------------------------------------------------------------ +// SecurityHandler +//------------------------------------------------------------------------ + +SecurityHandler *SecurityHandler::make(PDFDoc *docA, Object *encryptDictA) { + Object filterObj; + SecurityHandler *secHdlr; +#ifdef ENABLE_PLUGINS + XpdfSecurityHandler *xsh; +#endif + + encryptDictA->dictLookup("Filter", &filterObj); + if (filterObj.isName("Standard")) { + secHdlr = new StandardSecurityHandler(docA, encryptDictA); + } else if (filterObj.isName()) { +#ifdef ENABLE_PLUGINS + if ((xsh = globalParams->getSecurityHandler(filterObj.getName()))) { + secHdlr = new ExternalSecurityHandler(docA, encryptDictA, xsh); + } else { +#endif + error(-1, "Couldn't find the '%s' security handler", + filterObj.getName()); + secHdlr = NULL; +#ifdef ENABLE_PLUGINS + } +#endif + } else { + error(-1, "Missing or invalid 'Filter' entry in encryption dictionary"); + secHdlr = NULL; + } + filterObj.free(); + return secHdlr; +} + +SecurityHandler::SecurityHandler(PDFDoc *docA) { + doc = docA; +} + +SecurityHandler::~SecurityHandler() { +} + +GBool SecurityHandler::checkEncryption(GString *ownerPassword, + GString *userPassword) { + void *authData; + GBool ok; + int i; + + if (ownerPassword || userPassword) { + authData = makeAuthData(ownerPassword, userPassword); + } else { + authData = NULL; + } + ok = authorize(authData); + if (authData) { + freeAuthData(authData); + } + for (i = 0; !ok && i < 3; ++i) { + if (!(authData = getAuthData())) { + break; + } + ok = authorize(authData); + if (authData) { + freeAuthData(authData); + } + } + if (!ok) { + error(-1, "Incorrect password"); + } + return ok; +} + +//------------------------------------------------------------------------ +// StandardSecurityHandler +//------------------------------------------------------------------------ + +class StandardAuthData { +public: + + StandardAuthData(GString *ownerPasswordA, GString *userPasswordA) { + ownerPassword = ownerPasswordA; + userPassword = userPasswordA; + } + + ~StandardAuthData() { + if (ownerPassword) { + delete ownerPassword; + } + if (userPassword) { + delete userPassword; + } + } + + GString *ownerPassword; + GString *userPassword; +}; + +StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA, + Object *encryptDictA): + SecurityHandler(docA) +{ + Object versionObj, revisionObj, lengthObj; + Object ownerKeyObj, userKeyObj, permObj, fileIDObj; + Object fileIDObj1; + Object cryptFiltersObj, streamFilterObj, stringFilterObj; + Object cryptFilterObj, cfmObj, cfLengthObj; + Object encryptMetadataObj; + + ok = gFalse; + fileID = NULL; + ownerKey = NULL; + userKey = NULL; + + encryptDictA->dictLookup("V", &versionObj); + encryptDictA->dictLookup("R", &revisionObj); + encryptDictA->dictLookup("Length", &lengthObj); + encryptDictA->dictLookup("O", &ownerKeyObj); + encryptDictA->dictLookup("U", &userKeyObj); + encryptDictA->dictLookup("P", &permObj); + doc->getXRef()->getTrailerDict()->dictLookup("ID", &fileIDObj); + if (versionObj.isInt() && + revisionObj.isInt() && + ownerKeyObj.isString() && ownerKeyObj.getString()->getLength() == 32 && + userKeyObj.isString() && userKeyObj.getString()->getLength() == 32 && + permObj.isInt()) { + encVersion = versionObj.getInt(); + encRevision = revisionObj.getInt(); + encAlgorithm = cryptRC4; + // revision 2 forces a 40-bit key - some buggy PDF generators + // set the Length value incorrectly + if (encRevision == 2 || !lengthObj.isInt()) { + fileKeyLength = 5; + } else { + fileKeyLength = lengthObj.getInt() / 8; + } + encryptMetadata = gTrue; + //~ this currently only handles a subset of crypt filter functionality + if (encVersion == 4 && encRevision == 4) { + encryptDictA->dictLookup("CF", &cryptFiltersObj); + encryptDictA->dictLookup("StmF", &streamFilterObj); + encryptDictA->dictLookup("StrF", &stringFilterObj); + if (cryptFiltersObj.isDict() && + streamFilterObj.isName() && + stringFilterObj.isName() && + !strcmp(streamFilterObj.getName(), stringFilterObj.getName())) { + if (cryptFiltersObj.dictLookup(streamFilterObj.getName(), + &cryptFilterObj)->isDict()) { + cryptFilterObj.dictLookup("CFM", &cfmObj); + if (cfmObj.isName("V2")) { + encVersion = 2; + encRevision = 3; + if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) { + //~ according to the spec, this should be cfLengthObj / 8 + fileKeyLength = cfLengthObj.getInt(); + } + cfLengthObj.free(); + } else if (cfmObj.isName("AESV2")) { + encVersion = 2; + encRevision = 3; + encAlgorithm = cryptAES; + if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) { + //~ according to the spec, this should be cfLengthObj / 8 + fileKeyLength = cfLengthObj.getInt(); + } + cfLengthObj.free(); + } + cfmObj.free(); + } + cryptFilterObj.free(); + } + stringFilterObj.free(); + streamFilterObj.free(); + cryptFiltersObj.free(); + if (encryptDictA->dictLookup("EncryptMetadata", + &encryptMetadataObj)->isBool()) { + encryptMetadata = encryptMetadataObj.getBool(); + } + encryptMetadataObj.free(); + } + permFlags = permObj.getInt(); + ownerKey = ownerKeyObj.getString()->copy(); + userKey = userKeyObj.getString()->copy(); + if (encVersion >= 1 && encVersion <= 2 && + encRevision >= 2 && encRevision <= 3) { + if (fileIDObj.isArray()) { + if (fileIDObj.arrayGet(0, &fileIDObj1)->isString()) { + fileID = fileIDObj1.getString()->copy(); + } else { + fileID = new GString(); + } + fileIDObj1.free(); + } else { + fileID = new GString(); + } + ok = gTrue; + } else { + error(-1, "Unsupported version/revision (%d/%d) of Standard security handler", + encVersion, encRevision); + } + } else { + error(-1, "Weird encryption info"); + } + if (fileKeyLength > 16) { + fileKeyLength = 16; + } + fileIDObj.free(); + permObj.free(); + userKeyObj.free(); + ownerKeyObj.free(); + lengthObj.free(); + revisionObj.free(); + versionObj.free(); +} + +StandardSecurityHandler::~StandardSecurityHandler() { + if (fileID) { + delete fileID; + } + if (ownerKey) { + delete ownerKey; + } + if (userKey) { + delete userKey; + } +} + +void *StandardSecurityHandler::makeAuthData(GString *ownerPassword, + GString *userPassword) { + return new StandardAuthData(ownerPassword ? ownerPassword->copy() + : (GString *)NULL, + userPassword ? userPassword->copy() + : (GString *)NULL); +} + +void *StandardSecurityHandler::getAuthData() { +#if HAVE_XPDFCORE + XPDFCore *core; + GString *password; + + if (!(core = (XPDFCore *)doc->getGUIData()) || + !(password = core->getPassword())) { + return NULL; + } + return new StandardAuthData(password, password->copy()); +#elif HAVE_WINPDFCORE + WinPDFCore *core; + GString *password; + + if (!(core = (WinPDFCore *)doc->getGUIData()) || + !(password = core->getPassword())) { + return NULL; + } + return new StandardAuthData(password, password->copy()); +#else + return NULL; +#endif +} + +void StandardSecurityHandler::freeAuthData(void *authData) { + delete (StandardAuthData *)authData; +} + +GBool StandardSecurityHandler::authorize(void *authData) { + GString *ownerPassword, *userPassword; + + if (!ok) { + return gFalse; + } + if (authData) { + ownerPassword = ((StandardAuthData *)authData)->ownerPassword; + userPassword = ((StandardAuthData *)authData)->userPassword; + } else { + ownerPassword = NULL; + userPassword = NULL; + } + if (!Decrypt::makeFileKey(encVersion, encRevision, fileKeyLength, + ownerKey, userKey, permFlags, fileID, + ownerPassword, userPassword, fileKey, + encryptMetadata, &ownerPasswordOk)) { + return gFalse; + } + return gTrue; +} + +#ifdef ENABLE_PLUGINS + +//------------------------------------------------------------------------ +// ExternalSecurityHandler +//------------------------------------------------------------------------ + +ExternalSecurityHandler::ExternalSecurityHandler(PDFDoc *docA, + Object *encryptDictA, + XpdfSecurityHandler *xshA): + SecurityHandler(docA) +{ + encryptDictA->copy(&encryptDict); + xsh = xshA; + encAlgorithm = cryptRC4; //~ this should be obtained via getKey + ok = gFalse; + + if (!(*xsh->newDoc)(xsh->handlerData, (XpdfDoc)docA, + (XpdfObject)encryptDictA, &docData)) { + return; + } + + ok = gTrue; +} + +ExternalSecurityHandler::~ExternalSecurityHandler() { + (*xsh->freeDoc)(xsh->handlerData, docData); + encryptDict.free(); +} + +void *ExternalSecurityHandler::makeAuthData(GString *ownerPassword, + GString *userPassword) { + char *opw, *upw; + void *authData; + + opw = ownerPassword ? ownerPassword->getCString() : (char *)NULL; + upw = userPassword ? userPassword->getCString() : (char *)NULL; + if (!(*xsh->makeAuthData)(xsh->handlerData, docData, opw, upw, &authData)) { + return NULL; + } + return authData; +} + +void *ExternalSecurityHandler::getAuthData() { + void *authData; + + if (!(*xsh->getAuthData)(xsh->handlerData, docData, &authData)) { + return NULL; + } + return authData; +} + +void ExternalSecurityHandler::freeAuthData(void *authData) { + (*xsh->freeAuthData)(xsh->handlerData, docData, authData); +} + +GBool ExternalSecurityHandler::authorize(void *authData) { + char *key; + int length; + + if (!ok) { + return gFalse; + } + permFlags = (*xsh->authorize)(xsh->handlerData, docData, authData); + if (!(permFlags & xpdfPermissionOpen)) { + return gFalse; + } + if (!(*xsh->getKey)(xsh->handlerData, docData, &key, &length, &encVersion)) { + return gFalse; + } + if ((fileKeyLength = length) > 16) { + fileKeyLength = 16; + } + memcpy(fileKey, key, fileKeyLength); + (*xsh->freeKey)(xsh->handlerData, docData, key, length); + return gTrue; +} + +#endif // ENABLE_PLUGINS diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SecurityHandler.h swftools-0.9.1/lib/pdf/xpdf/SecurityHandler.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SecurityHandler.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SecurityHandler.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,160 @@ +//======================================================================== +// +// SecurityHandler.h +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef SECURITYHANDLER_H +#define SECURITYHANDLER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" + +class GString; +class PDFDoc; +struct XpdfSecurityHandler; + +//------------------------------------------------------------------------ +// SecurityHandler +//------------------------------------------------------------------------ + +class SecurityHandler { +public: + + static SecurityHandler *make(PDFDoc *docA, Object *encryptDictA); + + SecurityHandler(PDFDoc *docA); + virtual ~SecurityHandler(); + + // Check the document's encryption. If the document is encrypted, + // this will first try and (in + // "batch" mode), and if those fail, it will attempt to request a + // password from the user. This is the high-level function that + // calls the lower level functions for the specific security handler + // (requesting a password three times, etc.). Returns true if the + // document can be opened (if it's unencrypted, or if a correct + // password is obtained); false otherwise (encrypted and no correct + // password). + GBool checkEncryption(GString *ownerPassword, + GString *userPassword); + + // Create authorization data for the specified owner and user + // passwords. If the security handler doesn't support "batch" mode, + // this function should return NULL. + virtual void *makeAuthData(GString *ownerPassword, + GString *userPassword) = 0; + + // Construct authorization data, typically by prompting the user for + // a password. Returns an authorization data object, or NULL to + // cancel. + virtual void *getAuthData() = 0; + + // Free the authorization data returned by makeAuthData or + // getAuthData. + virtual void freeAuthData(void *authData) = 0; + + // Attempt to authorize the document, using the supplied + // authorization data (which may be NULL). Returns true if + // successful (i.e., if at least the right to open the document was + // granted). + virtual GBool authorize(void *authData) = 0; + + // Return the various authorization parameters. These are only + // valid after authorize has returned true. + virtual int getPermissionFlags() = 0; + virtual GBool getOwnerPasswordOk() = 0; + virtual Guchar *getFileKey() = 0; + virtual int getFileKeyLength() = 0; + virtual int getEncVersion() = 0; + virtual CryptAlgorithm getEncAlgorithm() = 0; + +protected: + + PDFDoc *doc; +}; + +//------------------------------------------------------------------------ +// StandardSecurityHandler +//------------------------------------------------------------------------ + +class StandardSecurityHandler: public SecurityHandler { +public: + + StandardSecurityHandler(PDFDoc *docA, Object *encryptDictA); + virtual ~StandardSecurityHandler(); + + virtual void *makeAuthData(GString *ownerPassword, + GString *userPassword); + virtual void *getAuthData(); + virtual void freeAuthData(void *authData); + virtual GBool authorize(void *authData); + virtual int getPermissionFlags() { return permFlags; } + virtual GBool getOwnerPasswordOk() { return ownerPasswordOk; } + virtual Guchar *getFileKey() { return fileKey; } + virtual int getFileKeyLength() { return fileKeyLength; } + virtual int getEncVersion() { return encVersion; } + virtual CryptAlgorithm getEncAlgorithm() { return encAlgorithm; } + +private: + + int permFlags; + GBool ownerPasswordOk; + Guchar fileKey[16]; + int fileKeyLength; + int encVersion; + int encRevision; + CryptAlgorithm encAlgorithm; + GBool encryptMetadata; + + GString *ownerKey, *userKey; + GString *fileID; + GBool ok; +}; + +#ifdef ENABLE_PLUGINS +//------------------------------------------------------------------------ +// ExternalSecurityHandler +//------------------------------------------------------------------------ + +class ExternalSecurityHandler: public SecurityHandler { +public: + + ExternalSecurityHandler(PDFDoc *docA, Object *encryptDictA, + XpdfSecurityHandler *xshA); + virtual ~ExternalSecurityHandler(); + + virtual void *makeAuthData(GString *ownerPassword, + GString *userPassword); + virtual void *getAuthData(); + virtual void freeAuthData(void *authData); + virtual GBool authorize(void *authData); + virtual int getPermissionFlags() { return permFlags; } + virtual GBool getOwnerPasswordOk() { return gFalse; } + virtual Guchar *getFileKey() { return fileKey; } + virtual int getFileKeyLength() { return fileKeyLength; } + virtual int getEncVersion() { return encVersion; } + virtual CryptAlgorithm getEncAlgorithm() { return encAlgorithm; } + +private: + + Object encryptDict; + XpdfSecurityHandler *xsh; + void *docData; + int permFlags; + Guchar fileKey[16]; + int fileKeyLength; + int encVersion; + CryptAlgorithm encAlgorithm; + GBool ok; +}; +#endif // ENABLE_PLUGINS + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashBitmap.cc swftools-0.9.1/lib/pdf/xpdf/SplashBitmap.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashBitmap.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashBitmap.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,188 @@ +//======================================================================== +// +// SplashBitmap.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "SplashErrorCodes.h" +#include "SplashBitmap.h" + +//------------------------------------------------------------------------ +// SplashBitmap +//------------------------------------------------------------------------ + +SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPad, + SplashColorMode modeA, GBool alphaA, + GBool topDown) { + width = widthA; + height = heightA; + mode = modeA; + switch (mode) { + case splashModeMono1: + rowSize = (width + 7) >> 3; + break; + case splashModeMono8: + rowSize = width; + break; + case splashModeRGB8: + case splashModeBGR8: + rowSize = width * 3; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + rowSize = width * 4; + break; +#endif + } + rowSize += rowPad - 1; + rowSize -= rowSize % rowPad; + data = (SplashColorPtr)gmalloc(rowSize * height); + if (!topDown) { + data += (height - 1) * rowSize; + rowSize = -rowSize; + } + if (alphaA) { + alpha = (Guchar *)gmalloc(width * height); + } else { + alpha = NULL; + } +} + + +SplashBitmap::~SplashBitmap() { + if (rowSize < 0) { + gfree(data + (height - 1) * rowSize); + } else { + gfree(data); + } + gfree(alpha); +} + +SplashError SplashBitmap::writePNMFile(char *fileName) { + FILE *f; + SplashColorPtr row, p; + int x, y; + + if (!(f = fopen(fileName, "wb"))) { + return splashErrOpenFile; + } + + switch (mode) { + + case splashModeMono1: + fprintf(f, "P4\n%d %d\n", width, height); + row = data; + for (y = 0; y < height; ++y) { + p = row; + for (x = 0; x < width; x += 8) { + fputc(*p ^ 0xff, f); + ++p; + } + row += rowSize; + } + break; + + case splashModeMono8: + fprintf(f, "P5\n%d %d\n255\n", width, height); + row = data; + for (y = 0; y < height; ++y) { + p = row; + for (x = 0; x < width; ++x) { + fputc(*p, f); + ++p; + } + row += rowSize; + } + break; + + case splashModeRGB8: + fprintf(f, "P6\n%d %d\n255\n", width, height); + row = data; + for (y = 0; y < height; ++y) { + p = row; + for (x = 0; x < width; ++x) { + fputc(splashRGB8R(p), f); + fputc(splashRGB8G(p), f); + fputc(splashRGB8B(p), f); + p += 3; + } + row += rowSize; + } + break; + + case splashModeBGR8: + fprintf(f, "P6\n%d %d\n255\n", width, height); + row = data; + for (y = 0; y < height; ++y) { + p = row; + for (x = 0; x < width; ++x) { + fputc(splashBGR8R(p), f); + fputc(splashBGR8G(p), f); + fputc(splashBGR8B(p), f); + p += 3; + } + row += rowSize; + } + break; + +#if SPLASH_CMYK + case splashModeCMYK8: + // PNM doesn't support CMYK + break; +#endif + } + + fclose(f); + return splashOk; +} + +void SplashBitmap::getPixel(int x, int y, SplashColorPtr pixel) { + SplashColorPtr p; + + if (y < 0 || y >= height || x < 0 || x >= width) { + return; + } + switch (mode) { + case splashModeMono1: + p = &data[y * rowSize + (x >> 3)]; + pixel[0] = (p[0] & (0x80 >> (x & 7))) ? 0xff : 0x00; + break; + case splashModeMono8: + p = &data[y * rowSize + x]; + pixel[0] = p[0]; + break; + case splashModeRGB8: + p = &data[y * rowSize + 3 * x]; + pixel[0] = p[0]; + pixel[1] = p[1]; + pixel[2] = p[2]; + break; + case splashModeBGR8: + p = &data[y * rowSize + 3 * x]; + pixel[0] = p[2]; + pixel[1] = p[1]; + pixel[2] = p[0]; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + p = &data[y * rowSize + 4 * x]; + pixel[0] = p[0]; + pixel[1] = p[1]; + pixel[2] = p[2]; + pixel[3] = p[3]; + break; +#endif + } +} + +Guchar SplashBitmap::getAlpha(int x, int y) { + return alpha[y * width + x]; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashBitmap.h swftools-0.9.1/lib/pdf/xpdf/SplashBitmap.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashBitmap.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashBitmap.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,61 @@ +//======================================================================== +// +// SplashBitmap.h +// +//======================================================================== + +#ifndef SPLASHBITMAP_H +#define SPLASHBITMAP_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" + +//------------------------------------------------------------------------ +// SplashBitmap +//------------------------------------------------------------------------ + +class SplashBitmap { +public: + + // Create a new bitmap. It will have x pixels in + // color mode . Rows will be padded out to a multiple of + // bytes. If is false, the bitmap will be stored + // upside-down, i.e., with the last row first in memory. + SplashBitmap(int widthA, int heightA, int rowPad, + SplashColorMode modeA, GBool alphaA, + GBool topDown = gTrue); + + ~SplashBitmap(); + + int getWidth() { return width; } + int getHeight() { return height; } + int getRowSize() { return rowSize; } + int getAlphaRowSize() { return width; } + SplashColorMode getMode() { return mode; } + SplashColorPtr getDataPtr() { return data; } + Guchar *getAlphaPtr() { return alpha; } + + SplashError writePNMFile(char *fileName); + + void getPixel(int x, int y, SplashColorPtr pixel); + Guchar getAlpha(int x, int y); + +private: + + int width, height; // size of bitmap + int rowSize; // size of one row of data, in bytes + // - negative for bottom-up bitmaps + SplashColorMode mode; // color mode + SplashColorPtr data; // pointer to row zero of the color data + Guchar *alpha; // pointer to row zero of the alpha data + // (always top-down) + + friend class Splash; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Splash.cc swftools-0.9.1/lib/pdf/xpdf/Splash.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Splash.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Splash.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,3310 @@ +//======================================================================== +// +// Splash.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "SplashErrorCodes.h" +#include "SplashMath.h" +#include "SplashBitmap.h" +#include "SplashState.h" +#include "SplashPath.h" +#include "SplashXPath.h" +#include "SplashXPathScanner.h" +#include "SplashPattern.h" +#include "SplashScreen.h" +#include "SplashFont.h" +#include "SplashGlyphBitmap.h" +#include "Splash.h" + +//------------------------------------------------------------------------ + +// distance of Bezier control point from center for circle approximation +// = (4 * (sqrt(2) - 1) / 3) * r +#define bezierCircle ((SplashCoord)0.55228475) +#define bezierCircle2 ((SplashCoord)(0.5 * 0.55228475)) + +// Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result. +static inline Guchar div255(int x) { + return (Guchar)((x + (x >> 8) + 0x80) >> 8); +} + +//------------------------------------------------------------------------ +// SplashPipe +//------------------------------------------------------------------------ + +#define splashPipeMaxStages 9 + +struct SplashPipe { + // pixel coordinates + int x, y; + + // source pattern + SplashPattern *pattern; + + // source alpha and color + SplashCoord aInput; + GBool usesShape; + Guchar aSrc; + SplashColorPtr cSrc; + SplashColor cSrcVal; + + // non-isolated group alpha0 + Guchar *alpha0Ptr; + + // soft mask + SplashColorPtr softMaskPtr; + + // destination alpha and color + SplashColorPtr destColorPtr; + int destColorMask; + Guchar *destAlphaPtr; + + // shape + SplashCoord shape; + + // result alpha and color + GBool noTransparency; + SplashPipeResultColorCtrl resultColorCtrl; + + // non-isolated group correction + int nonIsolatedGroup; +}; + +SplashPipeResultColorCtrl Splash::pipeResultColorNoAlphaBlend[] = { + splashPipeResultColorNoAlphaBlendMono, + splashPipeResultColorNoAlphaBlendMono, + splashPipeResultColorNoAlphaBlendRGB, + splashPipeResultColorNoAlphaBlendRGB +#if SPLASH_CMYK + , + splashPipeResultColorNoAlphaBlendCMYK +#endif +}; + +SplashPipeResultColorCtrl Splash::pipeResultColorAlphaNoBlend[] = { + splashPipeResultColorAlphaNoBlendMono, + splashPipeResultColorAlphaNoBlendMono, + splashPipeResultColorAlphaNoBlendRGB, + splashPipeResultColorAlphaNoBlendRGB +#if SPLASH_CMYK + , + splashPipeResultColorAlphaNoBlendCMYK +#endif +}; + +SplashPipeResultColorCtrl Splash::pipeResultColorAlphaBlend[] = { + splashPipeResultColorAlphaBlendMono, + splashPipeResultColorAlphaBlendMono, + splashPipeResultColorAlphaBlendRGB, + splashPipeResultColorAlphaBlendRGB +#if SPLASH_CMYK + , + splashPipeResultColorAlphaBlendCMYK +#endif +}; + +//------------------------------------------------------------------------ + +static void blendXor(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = src[i] ^ dest[i]; + } +} + +//------------------------------------------------------------------------ +// modified region +//------------------------------------------------------------------------ + +void Splash::clearModRegion() { + modXMin = bitmap->getWidth(); + modYMin = bitmap->getHeight(); + modXMax = -1; + modYMax = -1; +} + +inline void Splash::updateModX(int x) { + if (x < modXMin) { + modXMin = x; + } + if (x > modXMax) { + modXMax = x; + } +} + +inline void Splash::updateModY(int y) { + if (y < modYMin) { + modYMin = y; + } + if (y > modYMax) { + modYMax = y; + } +} + +//------------------------------------------------------------------------ +// pipeline +//------------------------------------------------------------------------ + +inline void Splash::pipeInit(SplashPipe *pipe, int x, int y, + SplashPattern *pattern, SplashColorPtr cSrc, + SplashCoord aInput, GBool usesShape, + GBool nonIsolatedGroup) { + pipeSetXY(pipe, x, y); + pipe->pattern = NULL; + + // source color + if (pattern) { + if (pattern->isStatic()) { + pattern->getColor(x, y, pipe->cSrcVal); + } else { + pipe->pattern = pattern; + } + pipe->cSrc = pipe->cSrcVal; + } else { + pipe->cSrc = cSrc; + } + + // source alpha + pipe->aInput = aInput; + if (!state->softMask) { + if (usesShape) { + pipe->aInput *= 255; + } else { + pipe->aSrc = (Guchar)splashRound(pipe->aInput * 255); + } + } + pipe->usesShape = usesShape; + + // result alpha + if (aInput == 1 && !state->softMask && !usesShape && + !state->inNonIsolatedGroup) { + pipe->noTransparency = gTrue; + } else { + pipe->noTransparency = gFalse; + } + + // result color + if (pipe->noTransparency) { + // the !state->blendFunc case is handled separately in pipeRun + pipe->resultColorCtrl = pipeResultColorNoAlphaBlend[bitmap->mode]; + } else if (!state->blendFunc) { + pipe->resultColorCtrl = pipeResultColorAlphaNoBlend[bitmap->mode]; + } else { + pipe->resultColorCtrl = pipeResultColorAlphaBlend[bitmap->mode]; + } + + // non-isolated group correction + if (nonIsolatedGroup) { + pipe->nonIsolatedGroup = splashColorModeNComps[bitmap->mode]; + } else { + pipe->nonIsolatedGroup = 0; + } +} + +inline void Splash::pipeRun(SplashPipe *pipe) { + Guchar aSrc, aDest, alpha2, alpha0, aResult; + SplashColor cDest, cBlend; + Guchar cResult0, cResult1, cResult2, cResult3; + + //----- source color + + // static pattern: handled in pipeInit + // fixed color: handled in pipeInit + + // dynamic pattern + if (pipe->pattern) { + pipe->pattern->getColor(pipe->x, pipe->y, pipe->cSrcVal); + } + + if (pipe->noTransparency && !state->blendFunc) { + + //----- write destination pixel + + switch (bitmap->mode) { + case splashModeMono1: + cResult0 = pipe->cSrc[0]; + if (state->screen->test(pipe->x, pipe->y, cResult0)) { + *pipe->destColorPtr |= pipe->destColorMask; + } else { + *pipe->destColorPtr &= ~pipe->destColorMask; + } + if (!(pipe->destColorMask >>= 1)) { + pipe->destColorMask = 0x80; + ++pipe->destColorPtr; + } + break; + case splashModeMono8: + *pipe->destColorPtr++ = pipe->cSrc[0]; + break; + case splashModeRGB8: + *pipe->destColorPtr++ = pipe->cSrc[0]; + *pipe->destColorPtr++ = pipe->cSrc[1]; + *pipe->destColorPtr++ = pipe->cSrc[2]; + break; + case splashModeBGR8: + *pipe->destColorPtr++ = pipe->cSrc[2]; + *pipe->destColorPtr++ = pipe->cSrc[1]; + *pipe->destColorPtr++ = pipe->cSrc[0]; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + *pipe->destColorPtr++ = pipe->cSrc[0]; + *pipe->destColorPtr++ = pipe->cSrc[1]; + *pipe->destColorPtr++ = pipe->cSrc[2]; + *pipe->destColorPtr++ = pipe->cSrc[3]; + break; +#endif + } + if (pipe->destAlphaPtr) { + *pipe->destAlphaPtr++ = 255; + } + + } else { + + //----- read destination pixel + + switch (bitmap->mode) { + case splashModeMono1: + cDest[0] = (*pipe->destColorPtr & pipe->destColorMask) ? 0xff : 0x00; + break; + case splashModeMono8: + cDest[0] = *pipe->destColorPtr; + break; + case splashModeRGB8: + cDest[0] = pipe->destColorPtr[0]; + cDest[1] = pipe->destColorPtr[1]; + cDest[2] = pipe->destColorPtr[2]; + break; + case splashModeBGR8: + cDest[0] = pipe->destColorPtr[2]; + cDest[1] = pipe->destColorPtr[1]; + cDest[2] = pipe->destColorPtr[0]; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + cDest[0] = pipe->destColorPtr[0]; + cDest[1] = pipe->destColorPtr[1]; + cDest[2] = pipe->destColorPtr[2]; + cDest[3] = pipe->destColorPtr[3]; + break; +#endif + } + if (pipe->destAlphaPtr) { + aDest = *pipe->destAlphaPtr; + } else { + aDest = 0xff; + } + + //----- blend function + + if (state->blendFunc) { + (*state->blendFunc)(pipe->cSrc, cDest, cBlend, bitmap->mode); + } + + //----- source alpha + + if (state->softMask) { + if (pipe->usesShape) { + aSrc = (Guchar)splashRound(pipe->aInput * *pipe->softMaskPtr++ + * pipe->shape); + } else { + aSrc = (Guchar)splashRound(pipe->aInput * *pipe->softMaskPtr++); + } + } else if (pipe->usesShape) { + // pipe->aInput is premultiplied by 255 in pipeInit + aSrc = (Guchar)splashRound(pipe->aInput * pipe->shape); + } else { + // precomputed in pipeInit + aSrc = pipe->aSrc; + } + + //----- result alpha and non-isolated group element correction + + if (pipe->noTransparency) { + alpha2 = aResult = 255; + } else { + aResult = aSrc + aDest - div255(aSrc * aDest); + + if (pipe->alpha0Ptr) { + alpha0 = *pipe->alpha0Ptr++; + alpha2 = aResult + alpha0 - div255(aResult * alpha0); + } else { + alpha2 = aResult; + } + } + + //----- result color + + cResult0 = cResult1 = cResult2 = cResult3 = 0; // make gcc happy + + switch (pipe->resultColorCtrl) { + +#if SPLASH_CMYK + case splashPipeResultColorNoAlphaBlendCMYK: + cResult3 = div255((255 - aDest) * pipe->cSrc[3] + aDest * cBlend[3]); +#endif + case splashPipeResultColorNoAlphaBlendRGB: + cResult2 = div255((255 - aDest) * pipe->cSrc[2] + aDest * cBlend[2]); + cResult1 = div255((255 - aDest) * pipe->cSrc[1] + aDest * cBlend[1]); + case splashPipeResultColorNoAlphaBlendMono: + cResult0 = div255((255 - aDest) * pipe->cSrc[0] + aDest * cBlend[0]); + break; + + case splashPipeResultColorAlphaNoBlendMono: + if (alpha2 == 0) { + cResult0 = 0; + } else { + cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + + aSrc * pipe->cSrc[0]) / alpha2); + } + break; + case splashPipeResultColorAlphaNoBlendRGB: + if (alpha2 == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + } else { + cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + + aSrc * pipe->cSrc[0]) / alpha2); + cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] + + aSrc * pipe->cSrc[1]) / alpha2); + cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] + + aSrc * pipe->cSrc[2]) / alpha2); + } + break; +#if SPLASH_CMYK + case splashPipeResultColorAlphaNoBlendCMYK: + if (alpha2 == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + cResult3 = 0; + } else { + cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + + aSrc * pipe->cSrc[0]) / alpha2); + cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] + + aSrc * pipe->cSrc[1]) / alpha2); + cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] + + aSrc * pipe->cSrc[2]) / alpha2); + cResult3 = (Guchar)(((alpha2 - aSrc) * cDest[3] + + aSrc * pipe->cSrc[3]) / alpha2); + } + break; +#endif + + case splashPipeResultColorAlphaBlendMono: + if (alpha2 == 0) { + cResult0 = 0; + } else { + cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + + aSrc * ((255 - aDest) * pipe->cSrc[0] + + aDest * cBlend[0]) / 255) / + alpha2); + } + break; + case splashPipeResultColorAlphaBlendRGB: + if (alpha2 == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + } else { + cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + + aSrc * ((255 - aDest) * pipe->cSrc[0] + + aDest * cBlend[0]) / 255) / + alpha2); + cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] + + aSrc * ((255 - aDest) * pipe->cSrc[1] + + aDest * cBlend[1]) / 255) / + alpha2); + cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] + + aSrc * ((255 - aDest) * pipe->cSrc[2] + + aDest * cBlend[2]) / 255) / + alpha2); + } + break; +#if SPLASH_CMYK + case splashPipeResultColorAlphaBlendCMYK: + if (alpha2 == 0) { + cResult0 = 0; + cResult1 = 0; + cResult2 = 0; + cResult3 = 0; + } else { + cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] + + aSrc * ((255 - aDest) * pipe->cSrc[0] + + aDest * cBlend[0]) / 255) / + alpha2); + cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] + + aSrc * ((255 - aDest) * pipe->cSrc[1] + + aDest * cBlend[1]) / 255) / + alpha2); + cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] + + aSrc * ((255 - aDest) * pipe->cSrc[2] + + aDest * cBlend[2]) / 255) / + alpha2); + cResult3 = (Guchar)(((alpha2 - aSrc) * cDest[3] + + aSrc * ((255 - aDest) * pipe->cSrc[3] + + aDest * cBlend[3]) / 255) / + alpha2); + } + break; +#endif + } + + //----- non-isolated group correction + + if (aResult != 0) { + switch (pipe->nonIsolatedGroup) { +#if SPLASH_CMYK + case 4: + cResult3 += (cResult3 - cDest[3]) * aDest * + (255 - aResult) / (255 * aResult); +#endif + case 3: + cResult2 += (cResult2 - cDest[2]) * aDest * + (255 - aResult) / (255 * aResult); + cResult1 += (cResult1 - cDest[1]) * aDest * + (255 - aResult) / (255 * aResult); + case 1: + cResult0 += (cResult0 - cDest[0]) * aDest * + (255 - aResult) / (255 * aResult); + case 0: + break; + } + } + + //----- write destination pixel + + switch (bitmap->mode) { + case splashModeMono1: + if (state->screen->test(pipe->x, pipe->y, cResult0)) { + *pipe->destColorPtr |= pipe->destColorMask; + } else { + *pipe->destColorPtr &= ~pipe->destColorMask; + } + if (!(pipe->destColorMask >>= 1)) { + pipe->destColorMask = 0x80; + ++pipe->destColorPtr; + } + break; + case splashModeMono8: + *pipe->destColorPtr++ = cResult0; + break; + case splashModeRGB8: + *pipe->destColorPtr++ = cResult0; + *pipe->destColorPtr++ = cResult1; + *pipe->destColorPtr++ = cResult2; + break; + case splashModeBGR8: + *pipe->destColorPtr++ = cResult2; + *pipe->destColorPtr++ = cResult1; + *pipe->destColorPtr++ = cResult0; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + *pipe->destColorPtr++ = cResult0; + *pipe->destColorPtr++ = cResult1; + *pipe->destColorPtr++ = cResult2; + *pipe->destColorPtr++ = cResult3; + break; +#endif + } + if (pipe->destAlphaPtr) { + *pipe->destAlphaPtr++ = aResult; + } + + } + + ++pipe->x; +} + +inline void Splash::pipeSetXY(SplashPipe *pipe, int x, int y) { + pipe->x = x; + pipe->y = y; + if (state->softMask) { + pipe->softMaskPtr = + &state->softMask->data[y * state->softMask->rowSize + x]; + } + switch (bitmap->mode) { + case splashModeMono1: + pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + (x >> 3)]; + pipe->destColorMask = 0x80 >> (x & 7); + break; + case splashModeMono8: + pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + x]; + break; + case splashModeRGB8: + case splashModeBGR8: + pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + 3 * x]; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + pipe->destColorPtr = &bitmap->data[y * bitmap->rowSize + 4 * x]; + break; +#endif + } + if (bitmap->alpha) { + pipe->destAlphaPtr = &bitmap->alpha[y * bitmap->width + x]; + } else { + pipe->destAlphaPtr = NULL; + } + if (state->inNonIsolatedGroup && alpha0Bitmap->alpha) { + pipe->alpha0Ptr = + &alpha0Bitmap->alpha[(alpha0Y + y) * alpha0Bitmap->width + + (alpha0X + x)]; + } else { + pipe->alpha0Ptr = NULL; + } +} + +inline void Splash::pipeIncX(SplashPipe *pipe) { + ++pipe->x; + if (state->softMask) { + ++pipe->softMaskPtr; + } + switch (bitmap->mode) { + case splashModeMono1: + if (!(pipe->destColorMask >>= 1)) { + pipe->destColorMask = 0x80; + ++pipe->destColorPtr; + } + break; + case splashModeMono8: + ++pipe->destColorPtr; + break; + case splashModeRGB8: + case splashModeBGR8: + pipe->destColorPtr += 3; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + pipe->destColorPtr += 4; + break; +#endif + } + if (pipe->destAlphaPtr) { + ++pipe->destAlphaPtr; + } + if (pipe->alpha0Ptr) { + ++pipe->alpha0Ptr; + } +} + +inline void Splash::drawPixel(SplashPipe *pipe, int x, int y, GBool noClip) { + if (noClip || state->clip->test(x, y)) { + pipeSetXY(pipe, x, y); + pipeRun(pipe); + updateModX(x); + updateModY(y); + } +} + +inline void Splash::drawAAPixelInit() { + aaBufY = -1; +} + +inline void Splash::drawAAPixel(SplashPipe *pipe, int x, int y) { +#if splashAASize == 4 + static int bitCount4[16] = { 0, 1, 1, 2, 1, 2, 2, 3, + 1, 2, 2, 3, 2, 3, 3, 4 }; + int w; +#else + int xx, yy; +#endif + SplashColorPtr p; + int x0, x1, t; + + if (x < 0 || x >= bitmap->width || + y < state->clip->getYMinI() || y > state->clip->getYMaxI()) { + return; + } + + // update aaBuf + if (y != aaBufY) { + memset(aaBuf->getDataPtr(), 0xff, + aaBuf->getRowSize() * aaBuf->getHeight()); + x0 = 0; + x1 = bitmap->width - 1; + state->clip->clipAALine(aaBuf, &x0, &x1, y); + aaBufY = y; + } + + // compute the shape value +#if splashAASize == 4 + p = aaBuf->getDataPtr() + (x >> 1); + w = aaBuf->getRowSize(); + if (x & 1) { + t = bitCount4[*p & 0x0f] + bitCount4[p[w] & 0x0f] + + bitCount4[p[2*w] & 0x0f] + bitCount4[p[3*w] & 0x0f]; + } else { + t = bitCount4[*p >> 4] + bitCount4[p[w] >> 4] + + bitCount4[p[2*w] >> 4] + bitCount4[p[3*w] >> 4]; + } +#else + t = 0; + for (yy = 0; yy < splashAASize; ++yy) { + for (xx = 0; xx < splashAASize; ++xx) { + p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + + ((x * splashAASize + xx) >> 3); + t += (*p >> (7 - ((x * splashAASize + xx) & 7))) & 1; + } + } +#endif + + // draw the pixel + if (t != 0) { + pipeSetXY(pipe, x, y); + pipe->shape *= aaGamma[t]; + pipeRun(pipe); + updateModX(x); + updateModY(y); + } +} + +inline void Splash::drawSpan(SplashPipe *pipe, int x0, int x1, int y, + GBool noClip) { + int x; + + pipeSetXY(pipe, x0, y); + if (noClip) { + for (x = x0; x <= x1; ++x) { + pipeRun(pipe); + } + updateModX(x0); + updateModX(x1); + updateModY(y); + } else { + for (x = x0; x <= x1; ++x) { + if (state->clip->test(x, y)) { + pipeRun(pipe); + updateModX(x); + updateModY(y); + } else { + pipeIncX(pipe); + } + } + } +} + +inline void Splash::drawAALine(SplashPipe *pipe, int x0, int x1, int y) { +#if splashAASize == 4 + static int bitCount4[16] = { 0, 1, 1, 2, 1, 2, 2, 3, + 1, 2, 2, 3, 2, 3, 3, 4 }; + SplashColorPtr p0, p1, p2, p3; + int t; +#else + SplashColorPtr p; + int xx, yy, t; +#endif + int x; + +#if splashAASize == 4 + p0 = aaBuf->getDataPtr() + (x0 >> 1); + p1 = p0 + aaBuf->getRowSize(); + p2 = p1 + aaBuf->getRowSize(); + p3 = p2 + aaBuf->getRowSize(); +#endif + pipeSetXY(pipe, x0, y); + for (x = x0; x <= x1; ++x) { + + // compute the shape value +#if splashAASize == 4 + if (x & 1) { + t = bitCount4[*p0 & 0x0f] + bitCount4[*p1 & 0x0f] + + bitCount4[*p2 & 0x0f] + bitCount4[*p3 & 0x0f]; + ++p0; ++p1; ++p2; ++p3; + } else { + t = bitCount4[*p0 >> 4] + bitCount4[*p1 >> 4] + + bitCount4[*p2 >> 4] + bitCount4[*p3 >> 4]; + } +#else + t = 0; + for (yy = 0; yy < splashAASize; ++yy) { + for (xx = 0; xx < splashAASize; ++xx) { + p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + + ((x * splashAASize + xx) >> 3); + t += (*p >> (7 - ((x * splashAASize + xx) & 7))) & 1; + } + } +#endif + + if (t != 0) { + pipe->shape = aaGamma[t]; + pipeRun(pipe); + updateModX(x); + updateModY(y); + } else { + pipeIncX(pipe); + } + } +} + +//------------------------------------------------------------------------ + +// Transform a point from user space to device space. +inline void Splash::transform(SplashCoord *matrix, + SplashCoord xi, SplashCoord yi, + SplashCoord *xo, SplashCoord *yo) { + // [ m[0] m[1] 0 ] + // [xo yo 1] = [xi yi 1] * [ m[2] m[3] 0 ] + // [ m[4] m[5] 1 ] + *xo = xi * matrix[0] + yi * matrix[2] + matrix[4]; + *yo = xi * matrix[1] + yi * matrix[3] + matrix[5]; +} + +//------------------------------------------------------------------------ +// Splash +//------------------------------------------------------------------------ + +Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, + SplashScreenParams *screenParams) { + int i; + + bitmap = bitmapA; + vectorAntialias = vectorAntialiasA; + state = new SplashState(bitmap->width, bitmap->height, vectorAntialias, + screenParams); + if (vectorAntialias) { + aaBuf = new SplashBitmap(splashAASize * bitmap->width, splashAASize, + 1, splashModeMono1, gFalse); + for (i = 0; i <= splashAASize * splashAASize; ++i) { + aaGamma[i] = splashPow((SplashCoord)i / + (SplashCoord)(splashAASize * splashAASize), + 1.5); + } + } else { + aaBuf = NULL; + } + clearModRegion(); + debugMode = gFalse; +} + +Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, + SplashScreen *screenA) { + int i; + + bitmap = bitmapA; + vectorAntialias = vectorAntialiasA; + state = new SplashState(bitmap->width, bitmap->height, vectorAntialias, + screenA); + if (vectorAntialias) { + aaBuf = new SplashBitmap(splashAASize * bitmap->width, splashAASize, + 1, splashModeMono1, gFalse); + for (i = 0; i <= splashAASize * splashAASize; ++i) { + aaGamma[i] = splashPow((SplashCoord)i / + (SplashCoord)(splashAASize * splashAASize), + 1.5); + } + } else { + aaBuf = NULL; + } + clearModRegion(); + debugMode = gFalse; +} + +Splash::~Splash() { + while (state->next) { + restoreState(); + } + delete state; + if (vectorAntialias) { + delete aaBuf; + } +} + +//------------------------------------------------------------------------ +// state read +//------------------------------------------------------------------------ + +SplashCoord *Splash::getMatrix() { + return state->matrix; +} + +SplashPattern *Splash::getStrokePattern() { + return state->strokePattern; +} + +SplashPattern *Splash::getFillPattern() { + return state->fillPattern; +} + +SplashScreen *Splash::getScreen() { + return state->screen; +} + +SplashBlendFunc Splash::getBlendFunc() { + return state->blendFunc; +} + +SplashCoord Splash::getStrokeAlpha() { + return state->strokeAlpha; +} + +SplashCoord Splash::getFillAlpha() { + return state->fillAlpha; +} + +SplashCoord Splash::getLineWidth() { + return state->lineWidth; +} + +int Splash::getLineCap() { + return state->lineCap; +} + +int Splash::getLineJoin() { + return state->lineJoin; +} + +SplashCoord Splash::getMiterLimit() { + return state->miterLimit; +} + +SplashCoord Splash::getFlatness() { + return state->flatness; +} + +SplashCoord *Splash::getLineDash() { + return state->lineDash; +} + +int Splash::getLineDashLength() { + return state->lineDashLength; +} + +SplashCoord Splash::getLineDashPhase() { + return state->lineDashPhase; +} + +SplashClip *Splash::getClip() { + return state->clip; +} + +SplashBitmap *Splash::getSoftMask() { + return state->softMask; +} + +GBool Splash::getInNonIsolatedGroup() { + return state->inNonIsolatedGroup; +} + +//------------------------------------------------------------------------ +// state write +//------------------------------------------------------------------------ + +void Splash::setMatrix(SplashCoord *matrix) { + memcpy(state->matrix, matrix, 6 * sizeof(SplashCoord)); +} + +void Splash::setStrokePattern(SplashPattern *strokePattern) { + state->setStrokePattern(strokePattern); +} + +void Splash::setFillPattern(SplashPattern *fillPattern) { + state->setFillPattern(fillPattern); +} + +void Splash::setScreen(SplashScreen *screen) { + state->setScreen(screen); +} + +void Splash::setBlendFunc(SplashBlendFunc func) { + state->blendFunc = func; +} + +void Splash::setStrokeAlpha(SplashCoord alpha) { + state->strokeAlpha = alpha; +} + +void Splash::setFillAlpha(SplashCoord alpha) { + state->fillAlpha = alpha; +} + +void Splash::setLineWidth(SplashCoord lineWidth) { + state->lineWidth = lineWidth; +} + +void Splash::setLineCap(int lineCap) { + state->lineCap = lineCap; +} + +void Splash::setLineJoin(int lineJoin) { + state->lineJoin = lineJoin; +} + +void Splash::setMiterLimit(SplashCoord miterLimit) { + state->miterLimit = miterLimit; +} + +void Splash::setFlatness(SplashCoord flatness) { + if (flatness < 1) { + state->flatness = 1; + } else { + state->flatness = flatness; + } +} + +void Splash::setLineDash(SplashCoord *lineDash, int lineDashLength, + SplashCoord lineDashPhase) { + state->setLineDash(lineDash, lineDashLength, lineDashPhase); +} + +void Splash::setStrokeAdjust(GBool strokeAdjust) { + state->strokeAdjust = strokeAdjust; +} + +void Splash::clipResetToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1) { + state->clip->resetToRect(x0, y0, x1, y1); +} + +SplashError Splash::clipToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1) { + return state->clip->clipToRect(x0, y0, x1, y1); +} + +SplashError Splash::clipToPath(SplashPath *path, GBool eo) { + return state->clip->clipToPath(path, state->matrix, state->flatness, eo); +} + +void Splash::setSoftMask(SplashBitmap *softMask) { + state->setSoftMask(softMask); +} + +void Splash::setInNonIsolatedGroup(SplashBitmap *alpha0BitmapA, + int alpha0XA, int alpha0YA) { + alpha0Bitmap = alpha0BitmapA; + alpha0X = alpha0XA; + alpha0Y = alpha0YA; + state->inNonIsolatedGroup = gTrue; +} + +//------------------------------------------------------------------------ +// state save/restore +//------------------------------------------------------------------------ + +void Splash::saveState() { + SplashState *newState; + + newState = state->copy(); + newState->next = state; + state = newState; +} + +SplashError Splash::restoreState() { + SplashState *oldState; + + if (!state->next) { + return splashErrNoSave; + } + oldState = state; + state = state->next; + delete oldState; + return splashOk; +} + +//------------------------------------------------------------------------ +// drawing operations +//------------------------------------------------------------------------ + +void Splash::clear(SplashColorPtr color, Guchar alpha) { + SplashColorPtr row, p; + Guchar mono; + int x, y; + + switch (bitmap->mode) { + case splashModeMono1: + mono = (color[0] & 0x80) ? 0xff : 0x00; + if (bitmap->rowSize < 0) { + memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1), + mono, -bitmap->rowSize * bitmap->height); + } else { + memset(bitmap->data, mono, bitmap->rowSize * bitmap->height); + } + break; + case splashModeMono8: + if (bitmap->rowSize < 0) { + memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1), + color[0], -bitmap->rowSize * bitmap->height); + } else { + memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height); + } + break; + case splashModeRGB8: + if (color[0] == color[1] && color[1] == color[2]) { + if (bitmap->rowSize < 0) { + memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1), + color[0], -bitmap->rowSize * bitmap->height); + } else { + memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height); + } + } else { + row = bitmap->data; + for (y = 0; y < bitmap->height; ++y) { + p = row; + for (x = 0; x < bitmap->width; ++x) { + *p++ = color[2]; + *p++ = color[1]; + *p++ = color[0]; + } + row += bitmap->rowSize; + } + } + break; + case splashModeBGR8: + if (color[0] == color[1] && color[1] == color[2]) { + if (bitmap->rowSize < 0) { + memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1), + color[0], -bitmap->rowSize * bitmap->height); + } else { + memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height); + } + } else { + row = bitmap->data; + for (y = 0; y < bitmap->height; ++y) { + p = row; + for (x = 0; x < bitmap->width; ++x) { + *p++ = color[0]; + *p++ = color[1]; + *p++ = color[2]; + } + row += bitmap->rowSize; + } + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + if (color[0] == color[1] && color[1] == color[2] && color[2] == color[3]) { + if (bitmap->rowSize < 0) { + memset(bitmap->data + bitmap->rowSize * (bitmap->height - 1), + color[0], -bitmap->rowSize * bitmap->height); + } else { + memset(bitmap->data, color[0], bitmap->rowSize * bitmap->height); + } + } else { + row = bitmap->data; + for (y = 0; y < bitmap->height; ++y) { + p = row; + for (x = 0; x < bitmap->width; ++x) { + *p++ = color[0]; + *p++ = color[1]; + *p++ = color[2]; + *p++ = color[3]; + } + row += bitmap->rowSize; + } + } + break; +#endif + } + + if (bitmap->alpha) { + memset(bitmap->alpha, alpha, bitmap->width * bitmap->height); + } + + updateModX(0); + updateModY(0); + updateModX(bitmap->width - 1); + updateModY(bitmap->height - 1); +} + +SplashError Splash::stroke(SplashPath *path) { + SplashPath *path2, *dPath; + + if (debugMode) { + printf("stroke [dash:%d] [width:%.2f]:\n", + state->lineDashLength, (double)state->lineWidth); + dumpPath(path); + } + opClipRes = splashClipAllOutside; + if (path->length == 0) { + return splashErrEmptyPath; + } + path2 = flattenPath(path, state->matrix, state->flatness); + if (state->lineDashLength > 0) { + dPath = makeDashedPath(path2); + delete path2; + path2 = dPath; + } + if (state->lineWidth == 0) { + strokeNarrow(path2); + } else { + strokeWide(path2); + } + delete path2; + return splashOk; +} + +void Splash::strokeNarrow(SplashPath *path) { + SplashPipe pipe; + SplashXPath *xPath; + SplashXPathSeg *seg; + int x0, x1, x2, x3, y0, y1, x, y, t; + SplashCoord dx, dy, dxdy; + SplashClipResult clipRes; + int nClipRes[3]; + int i; + + nClipRes[0] = nClipRes[1] = nClipRes[2] = 0; + + xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse); + + pipeInit(&pipe, 0, 0, state->strokePattern, NULL, state->strokeAlpha, + gFalse, gFalse); + + for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) { + + x0 = splashFloor(seg->x0); + x1 = splashFloor(seg->x1); + y0 = splashFloor(seg->y0); + y1 = splashFloor(seg->y1); + + // horizontal segment + if (y0 == y1) { + if (x0 > x1) { + t = x0; x0 = x1; x1 = t; + } + if ((clipRes = state->clip->testSpan(x0, x1, y0)) + != splashClipAllOutside) { + drawSpan(&pipe, x0, x1, y0, clipRes == splashClipAllInside); + } + + // segment with |dx| > |dy| + } else if (splashAbs(seg->dxdy) > 1) { + dx = seg->x1 - seg->x0; + dy = seg->y1 - seg->y0; + dxdy = seg->dxdy; + if (y0 > y1) { + t = y0; y0 = y1; y1 = t; + t = x0; x0 = x1; x1 = t; + dx = -dx; + dy = -dy; + } + if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0, + x0 <= x1 ? x1 : x0, y1)) + != splashClipAllOutside) { + if (dx > 0) { + x2 = x0; + x3 = splashFloor(seg->x0 + ((SplashCoord)y0 + 1 - seg->y0) * dxdy); + drawSpan(&pipe, x2, (x2 <= x3 - 1) ? x3 - 1 : x2, y0, + clipRes == splashClipAllInside); + x2 = x3; + for (y = y0 + 1; y <= y1 - 1; ++y) { + x3 = splashFloor(seg->x0 + ((SplashCoord)y + 1 - seg->y0) * dxdy); + drawSpan(&pipe, x2, x3 - 1, y, clipRes == splashClipAllInside); + x2 = x3; + } + drawSpan(&pipe, x2, x2 <= x1 ? x1 : x2, y1, + clipRes == splashClipAllInside); + } else { + x2 = x0; + x3 = splashFloor(seg->x0 + ((SplashCoord)y0 + 1 - seg->y0) * dxdy); + drawSpan(&pipe, (x3 + 1 <= x2) ? x3 + 1 : x2, x2, y0, + clipRes == splashClipAllInside); + x2 = x3; + for (y = y0 + 1; y <= y1 - 1; ++y) { + x3 = splashFloor(seg->x0 + ((SplashCoord)y + 1 - seg->y0) * dxdy); + drawSpan(&pipe, x3 + 1, x2, y, clipRes == splashClipAllInside); + x2 = x3; + } + drawSpan(&pipe, x1, (x1 <= x2) ? x2 : x1, y1, + clipRes == splashClipAllInside); + } + } + + // segment with |dy| > |dx| + } else { + dxdy = seg->dxdy; + if (y0 > y1) { + t = x0; x0 = x1; x1 = t; + t = y0; y0 = y1; y1 = t; + } + if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0, + x0 <= x1 ? x1 : x0, y1)) + != splashClipAllOutside) { + drawPixel(&pipe, x0, y0, clipRes == splashClipAllInside); + for (y = y0 + 1; y <= y1 - 1; ++y) { + x = splashFloor(seg->x0 + ((SplashCoord)y - seg->y0) * dxdy); + drawPixel(&pipe, x, y, clipRes == splashClipAllInside); + } + drawPixel(&pipe, x1, y1, clipRes == splashClipAllInside); + } + } + ++nClipRes[clipRes]; + } + if (nClipRes[splashClipPartial] || + (nClipRes[splashClipAllInside] && nClipRes[splashClipAllOutside])) { + opClipRes = splashClipPartial; + } else if (nClipRes[splashClipAllInside]) { + opClipRes = splashClipAllInside; + } else { + opClipRes = splashClipAllOutside; + } + + delete xPath; +} + +void Splash::strokeWide(SplashPath *path) { + SplashPath *path2; + + path2 = makeStrokePath(path, gFalse); + fillWithPattern(path2, gFalse, state->strokePattern, state->strokeAlpha); + delete path2; +} + +SplashPath *Splash::flattenPath(SplashPath *path, SplashCoord *matrix, + SplashCoord flatness) { + SplashPath *fPath; + SplashCoord flatness2; + Guchar flag; + int i; + + fPath = new SplashPath(); + flatness2 = flatness * flatness; + i = 0; + while (i < path->length) { + flag = path->flags[i]; + if (flag & splashPathFirst) { + fPath->moveTo(path->pts[i].x, path->pts[i].y); + ++i; + } else { + if (flag & splashPathCurve) { + flattenCurve(path->pts[i-1].x, path->pts[i-1].y, + path->pts[i ].x, path->pts[i ].y, + path->pts[i+1].x, path->pts[i+1].y, + path->pts[i+2].x, path->pts[i+2].y, + matrix, flatness2, fPath); + i += 3; + } else { + fPath->lineTo(path->pts[i].x, path->pts[i].y); + ++i; + } + if (path->flags[i-1] & splashPathClosed) { + fPath->close(); + } + } + } + return fPath; +} + +void Splash::flattenCurve(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + SplashCoord x2, SplashCoord y2, + SplashCoord x3, SplashCoord y3, + SplashCoord *matrix, SplashCoord flatness2, + SplashPath *fPath) { + SplashCoord cx[splashMaxCurveSplits + 1][3]; + SplashCoord cy[splashMaxCurveSplits + 1][3]; + int cNext[splashMaxCurveSplits + 1]; + SplashCoord xl0, xl1, xl2, xr0, xr1, xr2, xr3, xx1, xx2, xh; + SplashCoord yl0, yl1, yl2, yr0, yr1, yr2, yr3, yy1, yy2, yh; + SplashCoord dx, dy, mx, my, tx, ty, d1, d2; + int p1, p2, p3; + + // initial segment + p1 = 0; + p2 = splashMaxCurveSplits; + cx[p1][0] = x0; cy[p1][0] = y0; + cx[p1][1] = x1; cy[p1][1] = y1; + cx[p1][2] = x2; cy[p1][2] = y2; + cx[p2][0] = x3; cy[p2][0] = y3; + cNext[p1] = p2; + + while (p1 < splashMaxCurveSplits) { + + // get the next segment + xl0 = cx[p1][0]; yl0 = cy[p1][0]; + xx1 = cx[p1][1]; yy1 = cy[p1][1]; + xx2 = cx[p1][2]; yy2 = cy[p1][2]; + p2 = cNext[p1]; + xr3 = cx[p2][0]; yr3 = cy[p2][0]; + + // compute the distances (in device space) from the control points + // to the midpoint of the straight line (this is a bit of a hack, + // but it's much faster than computing the actual distances to the + // line) + transform(matrix, (xl0 + xr3) * 0.5, (yl0 + yr3) * 0.5, &mx, &my); + transform(matrix, xx1, yy1, &tx, &ty); + dx = tx - mx; + dy = ty - my; + d1 = dx*dx + dy*dy; + transform(matrix, xx2, yy2, &tx, &ty); + dx = tx - mx; + dy = ty - my; + d2 = dx*dx + dy*dy; + + // if the curve is flat enough, or no more subdivisions are + // allowed, add the straight line segment + if (p2 - p1 == 1 || (d1 <= flatness2 && d2 <= flatness2)) { + fPath->lineTo(xr3, yr3); + p1 = p2; + + // otherwise, subdivide the curve + } else { + xl1 = (xl0 + xx1) * 0.5; + yl1 = (yl0 + yy1) * 0.5; + xh = (xx1 + xx2) * 0.5; + yh = (yy1 + yy2) * 0.5; + xl2 = (xl1 + xh) * 0.5; + yl2 = (yl1 + yh) * 0.5; + xr2 = (xx2 + xr3) * 0.5; + yr2 = (yy2 + yr3) * 0.5; + xr1 = (xh + xr2) * 0.5; + yr1 = (yh + yr2) * 0.5; + xr0 = (xl2 + xr1) * 0.5; + yr0 = (yl2 + yr1) * 0.5; + // add the new subdivision points + p3 = (p1 + p2) / 2; + cx[p1][1] = xl1; cy[p1][1] = yl1; + cx[p1][2] = xl2; cy[p1][2] = yl2; + cNext[p1] = p3; + cx[p3][0] = xr0; cy[p3][0] = yr0; + cx[p3][1] = xr1; cy[p3][1] = yr1; + cx[p3][2] = xr2; cy[p3][2] = yr2; + cNext[p3] = p2; + } + } +} + +SplashPath *Splash::makeDashedPath(SplashPath *path) { + SplashPath *dPath; + SplashCoord lineDashTotal; + SplashCoord lineDashStartPhase, lineDashDist, segLen; + SplashCoord x0, y0, x1, y1, xa, ya; + GBool lineDashStartOn, lineDashOn, newPath; + int lineDashStartIdx, lineDashIdx; + int i, j, k; + + lineDashTotal = 0; + for (i = 0; i < state->lineDashLength; ++i) { + lineDashTotal += state->lineDash[i]; + } + lineDashStartPhase = state->lineDashPhase; + i = splashFloor(lineDashStartPhase / lineDashTotal); + lineDashStartPhase -= (SplashCoord)i * lineDashTotal; + lineDashStartOn = gTrue; + lineDashStartIdx = 0; + while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) { + lineDashStartOn = !lineDashStartOn; + lineDashStartPhase -= state->lineDash[lineDashStartIdx]; + ++lineDashStartIdx; + } + + dPath = new SplashPath(); + + // process each subpath + i = 0; + while (i < path->length) { + + // find the end of the subpath + for (j = i; + j < path->length - 1 && !(path->flags[j] & splashPathLast); + ++j) ; + + // initialize the dash parameters + lineDashOn = lineDashStartOn; + lineDashIdx = lineDashStartIdx; + lineDashDist = state->lineDash[lineDashIdx] - lineDashStartPhase; + + // process each segment of the subpath + newPath = gTrue; + for (k = i; k < j; ++k) { + + // grab the segment + x0 = path->pts[k].x; + y0 = path->pts[k].y; + x1 = path->pts[k+1].x; + y1 = path->pts[k+1].y; + segLen = splashDist(x0, y0, x1, y1); + + // process the segment + while (segLen > 0) { + + if (lineDashDist >= segLen) { + if (lineDashOn) { + if (newPath) { + dPath->moveTo(x0, y0); + newPath = gFalse; + } + dPath->lineTo(x1, y1); + } + lineDashDist -= segLen; + segLen = 0; + + } else { + xa = x0 + (lineDashDist / segLen) * (x1 - x0); + ya = y0 + (lineDashDist / segLen) * (y1 - y0); + if (lineDashOn) { + if (newPath) { + dPath->moveTo(x0, y0); + newPath = gFalse; + } + dPath->lineTo(xa, ya); + } + x0 = xa; + y0 = ya; + segLen -= lineDashDist; + lineDashDist = 0; + } + + // get the next entry in the dash array + if (lineDashDist <= 0) { + lineDashOn = !lineDashOn; + if (++lineDashIdx == state->lineDashLength) { + lineDashIdx = 0; + } + lineDashDist = state->lineDash[lineDashIdx]; + newPath = gTrue; + } + } + } + i = j + 1; + } + + return dPath; +} + +SplashError Splash::fill(SplashPath *path, GBool eo) { + if (debugMode) { + printf("fill [eo:%d]:\n", eo); + dumpPath(path); + } + return fillWithPattern(path, eo, state->fillPattern, state->fillAlpha); +} + +SplashError Splash::fillWithPattern(SplashPath *path, GBool eo, + SplashPattern *pattern, + SplashCoord alpha) { + SplashPipe pipe; + SplashXPath *xPath; + SplashXPathScanner *scanner; + int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y; + SplashClipResult clipRes, clipRes2; + + if (path->length == 0) { + return splashErrEmptyPath; + } + xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue); + if (vectorAntialias) { + xPath->aaScale(); + } + xPath->sort(); + scanner = new SplashXPathScanner(xPath, eo); + + // get the min and max x and y values + if (vectorAntialias) { + scanner->getBBoxAA(&xMinI, &yMinI, &xMaxI, &yMaxI); + } else { + scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI); + } + + // check clipping + if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI)) + != splashClipAllOutside) { + + // limit the y range + if (yMinI < state->clip->getYMinI()) { + yMinI = state->clip->getYMinI(); + } + if (yMaxI > state->clip->getYMaxI()) { + yMaxI = state->clip->getYMaxI(); + } + + pipeInit(&pipe, 0, yMinI, pattern, NULL, alpha, vectorAntialias, gFalse); + + // draw the spans + if (vectorAntialias) { + for (y = yMinI; y <= yMaxI; ++y) { + scanner->renderAALine(aaBuf, &x0, &x1, y); + if (clipRes != splashClipAllInside) { + state->clip->clipAALine(aaBuf, &x0, &x1, y); + } + drawAALine(&pipe, x0, x1, y); + } + } else { + for (y = yMinI; y <= yMaxI; ++y) { + while (scanner->getNextSpan(y, &x0, &x1)) { + if (clipRes == splashClipAllInside) { + drawSpan(&pipe, x0, x1, y, gTrue); + } else { + // limit the x range + if (x0 < state->clip->getXMinI()) { + x0 = state->clip->getXMinI(); + } + if (x1 > state->clip->getXMaxI()) { + x1 = state->clip->getXMaxI(); + } + clipRes2 = state->clip->testSpan(x0, x1, y); + drawSpan(&pipe, x0, x1, y, clipRes2 == splashClipAllInside); + } + } + } + } + } + opClipRes = clipRes; + + delete scanner; + delete xPath; + return splashOk; +} + +SplashError Splash::xorFill(SplashPath *path, GBool eo) { + SplashPipe pipe; + SplashXPath *xPath; + SplashXPathScanner *scanner; + int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y; + SplashClipResult clipRes, clipRes2; + SplashBlendFunc origBlendFunc; + + if (path->length == 0) { + return splashErrEmptyPath; + } + xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue); + xPath->sort(); + scanner = new SplashXPathScanner(xPath, eo); + + // get the min and max x and y values + scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI); + + // check clipping + if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI)) + != splashClipAllOutside) { + + // limit the y range + if (yMinI < state->clip->getYMinI()) { + yMinI = state->clip->getYMinI(); + } + if (yMaxI > state->clip->getYMaxI()) { + yMaxI = state->clip->getYMaxI(); + } + + origBlendFunc = state->blendFunc; + state->blendFunc = &blendXor; + pipeInit(&pipe, 0, yMinI, state->fillPattern, NULL, 1, gFalse, gFalse); + + // draw the spans + for (y = yMinI; y <= yMaxI; ++y) { + while (scanner->getNextSpan(y, &x0, &x1)) { + if (clipRes == splashClipAllInside) { + drawSpan(&pipe, x0, x1, y, gTrue); + } else { + // limit the x range + if (x0 < state->clip->getXMinI()) { + x0 = state->clip->getXMinI(); + } + if (x1 > state->clip->getXMaxI()) { + x1 = state->clip->getXMaxI(); + } + clipRes2 = state->clip->testSpan(x0, x1, y); + drawSpan(&pipe, x0, x1, y, clipRes2 == splashClipAllInside); + } + } + } + state->blendFunc = origBlendFunc; + } + opClipRes = clipRes; + + delete scanner; + delete xPath; + return splashOk; +} + +SplashError Splash::fillChar(SplashCoord x, SplashCoord y, + int c, SplashFont *font) { + SplashGlyphBitmap glyph; + SplashCoord xt, yt; + int x0, y0, xFrac, yFrac; + SplashError err; + + if (debugMode) { + printf("fillChar: x=%.2f y=%.2f c=%3d=0x%02x='%c'\n", + (double)x, (double)y, c, c, c); + } + transform(state->matrix, x, y, &xt, &yt); + x0 = splashFloor(xt); + xFrac = splashFloor((xt - x0) * splashFontFraction); + y0 = splashFloor(yt); + yFrac = splashFloor((yt - y0) * splashFontFraction); + if (!font->getGlyph(c, xFrac, yFrac, &glyph)) { + return splashErrNoGlyph; + } + err = fillGlyph2(x0, y0, &glyph); + if (glyph.freeData) { + gfree(glyph.data); + } + return err; +} + +SplashError Splash::fillGlyph(SplashCoord x, SplashCoord y, + SplashGlyphBitmap *glyph) { + SplashCoord xt, yt; + int x0, y0; + + transform(state->matrix, x, y, &xt, &yt); + x0 = splashFloor(xt); + y0 = splashFloor(yt); + return fillGlyph2(x0, y0, glyph); +} + +SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) { + SplashPipe pipe; + SplashClipResult clipRes; + GBool noClip; + int alpha0, alpha; + Guchar *p; + int x1, y1, xx, xx1, yy; + + if ((clipRes = state->clip->testRect(x0 - glyph->x, + y0 - glyph->y, + x0 - glyph->x + glyph->w - 1, + y0 - glyph->y + glyph->h - 1)) + != splashClipAllOutside) { + noClip = clipRes == splashClipAllInside; + + if (noClip) { + if (glyph->aa) { + pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, + state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse); + p = glyph->data; + for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { + pipeSetXY(&pipe, x0 - glyph->x, y1); + for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) { + alpha = *p++; + if (alpha != 0) { + pipe.shape = (SplashCoord)(alpha / 255.0); + pipeRun(&pipe); + updateModX(x1); + updateModY(y1); + } else { + pipeIncX(&pipe); + } + } + } + } else { + pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, + state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse); + p = glyph->data; + for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { + pipeSetXY(&pipe, x0 - glyph->x, y1); + for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) { + alpha0 = *p++; + for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) { + if (alpha0 & 0x80) { + pipeRun(&pipe); + updateModX(x1); + updateModY(y1); + } else { + pipeIncX(&pipe); + } + alpha0 <<= 1; + } + } + } + } + } else { + if (glyph->aa) { + pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, + state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse); + p = glyph->data; + for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { + pipeSetXY(&pipe, x0 - glyph->x, y1); + for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) { + if (state->clip->test(x1, y1)) { + alpha = *p++; + if (alpha != 0) { + pipe.shape = (SplashCoord)(alpha / 255.0); + pipeRun(&pipe); + updateModX(x1); + updateModY(y1); + } else { + pipeIncX(&pipe); + } + } else { + pipeIncX(&pipe); + ++p; + } + } + } + } else { + pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, + state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse); + p = glyph->data; + for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { + pipeSetXY(&pipe, x0 - glyph->x, y1); + for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) { + alpha0 = *p++; + for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) { + if (state->clip->test(x1, y1)) { + if (alpha0 & 0x80) { + pipeRun(&pipe); + updateModX(x1); + updateModY(y1); + } else { + pipeIncX(&pipe); + } + } else { + pipeIncX(&pipe); + } + alpha0 <<= 1; + } + } + } + } + } + } + opClipRes = clipRes; + + return splashOk; +} + +SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData, + int w, int h, SplashCoord *mat, + GBool glyphMode) { + SplashPipe pipe; + GBool rot; + SplashCoord xScale, yScale, xShear, yShear, yShear1; + int tx, tx2, ty, ty2, scaledWidth, scaledHeight, xSign, ySign; + int ulx, uly, llx, lly, urx, ury, lrx, lry; + int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1; + int xMin, xMax, yMin, yMax; + SplashClipResult clipRes, clipRes2; + int yp, yq, yt, yStep, lastYStep; + int xp, xq, xt, xStep, xSrc; + int k1, spanXMin, spanXMax, spanY; + SplashColorPtr pixBuf, p; + int pixAcc; + int x, y, x1, x2, y2; + SplashCoord y1; + int n, m, i, j; + + if (debugMode) { + printf("fillImageMask: w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n", + w, h, (double)mat[0], (double)mat[1], (double)mat[2], + (double)mat[3], (double)mat[4], (double)mat[5]); + } + + // check for singular matrix + if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.000001) { + return splashErrSingularMatrix; + } + + // compute scale, shear, rotation, translation parameters + rot = splashAbs(mat[1]) > splashAbs(mat[0]); + if (rot) { + xScale = -mat[1]; + yScale = mat[2] - (mat[0] * mat[3]) / mat[1]; + xShear = -mat[3] / yScale; + yShear = -mat[0] / mat[1]; + } else { + xScale = mat[0]; + yScale = mat[3] - (mat[1] * mat[2]) / mat[0]; + xShear = mat[2] / yScale; + yShear = mat[1] / mat[0]; + } + // Note 1: The PDF spec says that all pixels whose *centers* lie + // within the region get painted -- but that doesn't seem to match + // up with what Acrobat actually does: it ends up leaving gaps + // between image stripes. So we use the same rule here as for + // fills: any pixel that overlaps the region gets painted. + // Note 2: The "glyphMode" flag is a kludge: it switches back to + // "correct" behavior (matching the spec), for use in rendering Type + // 3 fonts. + // Note 3: The +/-0.01 in these computations is to avoid floating + // point precision problems which can lead to gaps between image + // stripes (it can cause image stripes to overlap, but that's a much + // less visible problem). + if (glyphMode) { + if (xScale >= 0) { + tx = splashRound(mat[4]); + tx2 = splashRound(mat[4] + xScale) - 1; + } else { + tx = splashRound(mat[4]) - 1; + tx2 = splashRound(mat[4] + xScale); + } + } else { + if (xScale >= 0) { + tx = splashFloor(mat[4] - 0.01); + tx2 = splashFloor(mat[4] + xScale + 0.01); + } else { + tx = splashFloor(mat[4] + 0.01); + tx2 = splashFloor(mat[4] + xScale - 0.01); + } + } + scaledWidth = abs(tx2 - tx) + 1; + if (glyphMode) { + if (yScale >= 0) { + ty = splashRound(mat[5]); + ty2 = splashRound(mat[5] + yScale) - 1; + } else { + ty = splashRound(mat[5]) - 1; + ty2 = splashRound(mat[5] + yScale); + } + } else { + if (yScale >= 0) { + ty = splashFloor(mat[5] - 0.01); + ty2 = splashFloor(mat[5] + yScale + 0.01); + } else { + ty = splashFloor(mat[5] + 0.01); + ty2 = splashFloor(mat[5] + yScale - 0.01); + } + } + scaledHeight = abs(ty2 - ty) + 1; + xSign = (xScale < 0) ? -1 : 1; + ySign = (yScale < 0) ? -1 : 1; + yShear1 = (SplashCoord)xSign * yShear; + + // clipping + ulx1 = 0; + uly1 = 0; + urx1 = xSign * (scaledWidth - 1); + ury1 = (int)(yShear * urx1); + llx1 = splashRound(xShear * ySign * (scaledHeight - 1)); + lly1 = ySign * (scaledHeight - 1) + (int)(yShear * llx1); + lrx1 = xSign * (scaledWidth - 1) + + splashRound(xShear * ySign * (scaledHeight - 1)); + lry1 = ySign * (scaledHeight - 1) + (int)(yShear * lrx1); + if (rot) { + ulx = tx + uly1; uly = ty - ulx1; + urx = tx + ury1; ury = ty - urx1; + llx = tx + lly1; lly = ty - llx1; + lrx = tx + lry1; lry = ty - lrx1; + } else { + ulx = tx + ulx1; uly = ty + uly1; + urx = tx + urx1; ury = ty + ury1; + llx = tx + llx1; lly = ty + lly1; + lrx = tx + lrx1; lry = ty + lry1; + } + xMin = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx + : (llx < lrx) ? llx : lrx + : (urx < llx) ? (urx < lrx) ? urx : lrx + : (llx < lrx) ? llx : lrx; + xMax = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx + : (llx > lrx) ? llx : lrx + : (urx > llx) ? (urx > lrx) ? urx : lrx + : (llx > lrx) ? llx : lrx; + yMin = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry + : (lly < lry) ? lly : lry + : (ury < lly) ? (ury < lry) ? ury : lry + : (lly < lry) ? lly : lry; + yMax = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry + : (lly > lry) ? lly : lry + : (ury > lly) ? (ury > lry) ? ury : lry + : (lly > lry) ? lly : lry; + clipRes = state->clip->testRect(xMin, yMin, xMax, yMax); + opClipRes = clipRes; + + // compute Bresenham parameters for x and y scaling + yp = h / scaledHeight; + yq = h % scaledHeight; + xp = w / scaledWidth; + xq = w % scaledWidth; + + // allocate pixel buffer + pixBuf = (SplashColorPtr)gmalloc((yp + 1) * w); + + // initialize the pixel pipe + pipeInit(&pipe, 0, 0, state->fillPattern, NULL, state->fillAlpha, + gTrue, gFalse); + if (vectorAntialias) { + drawAAPixelInit(); + } + + // init y scale Bresenham + yt = 0; + lastYStep = 1; + + for (y = 0; y < scaledHeight; ++y) { + + // y scale Bresenham + yStep = yp; + yt += yq; + if (yt >= scaledHeight) { + yt -= scaledHeight; + ++yStep; + } + + // read row(s) from image + n = (yp > 0) ? yStep : lastYStep; + if (n > 0) { + p = pixBuf; + for (i = 0; i < n; ++i) { + (*src)(srcData, p); + p += w; + } + } + lastYStep = yStep; + + // loop-invariant constants + k1 = splashRound(xShear * ySign * y); + + // clipping test + if (clipRes != splashClipAllInside && + !rot && + (int)(yShear * k1) == + (int)(yShear * (xSign * (scaledWidth - 1) + k1))) { + if (xSign > 0) { + spanXMin = tx + k1; + spanXMax = spanXMin + (scaledWidth - 1); + } else { + spanXMax = tx + k1; + spanXMin = spanXMax - (scaledWidth - 1); + } + spanY = ty + ySign * y + (int)(yShear * k1); + clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY); + if (clipRes2 == splashClipAllOutside) { + continue; + } + } else { + clipRes2 = clipRes; + } + + // init x scale Bresenham + xt = 0; + xSrc = 0; + + // x shear + x1 = k1; + + // y shear + y1 = (SplashCoord)ySign * y + yShear * x1; + // this is a kludge: if yShear1 is negative, then (int)y1 would + // change immediately after the first pixel, which is not what we + // want + if (yShear1 < 0) { + y1 += 0.999; + } + + // loop-invariant constants + n = yStep > 0 ? yStep : 1; + + for (x = 0; x < scaledWidth; ++x) { + + // x scale Bresenham + xStep = xp; + xt += xq; + if (xt >= scaledWidth) { + xt -= scaledWidth; + ++xStep; + } + + // rotation + if (rot) { + x2 = (int)y1; + y2 = -x1; + } else { + x2 = x1; + y2 = (int)y1; + } + + // compute the alpha value for (x,y) after the x and y scaling + // operations + m = xStep > 0 ? xStep : 1; + p = pixBuf + xSrc; + pixAcc = 0; + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + pixAcc += *p++; + } + p += w - m; + } + + // blend fill color with background + if (pixAcc != 0) { + pipe.shape = (pixAcc == n * m) + ? (SplashCoord)1 + : (SplashCoord)pixAcc / (SplashCoord)(n * m); + if (vectorAntialias && clipRes2 != splashClipAllInside) { + drawAAPixel(&pipe, tx + x2, ty + y2); + } else { + drawPixel(&pipe, tx + x2, ty + y2, clipRes2 == splashClipAllInside); + } + } + + // x scale Bresenham + xSrc += xStep; + + // x shear + x1 += xSign; + + // y shear + y1 += yShear1; + } + } + + // free memory + gfree(pixBuf); + + return splashOk; +} + +SplashError Splash::drawImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, GBool srcAlpha, + int w, int h, SplashCoord *mat) { + SplashPipe pipe; + GBool ok, rot; + SplashCoord xScale, yScale, xShear, yShear, yShear1; + int tx, tx2, ty, ty2, scaledWidth, scaledHeight, xSign, ySign; + int ulx, uly, llx, lly, urx, ury, lrx, lry; + int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1; + int xMin, xMax, yMin, yMax; + SplashClipResult clipRes, clipRes2; + int yp, yq, yt, yStep, lastYStep; + int xp, xq, xt, xStep, xSrc; + int k1, spanXMin, spanXMax, spanY; + SplashColorPtr colorBuf, p; + SplashColor pix; + Guchar *alphaBuf, *q; +#if SPLASH_CMYK + int pixAcc0, pixAcc1, pixAcc2, pixAcc3; +#else + int pixAcc0, pixAcc1, pixAcc2; +#endif + int alphaAcc; + SplashCoord pixMul, alphaMul, alpha; + int x, y, x1, x2, y2; + SplashCoord y1; + int nComps, n, m, i, j; + + if (debugMode) { + printf("drawImage: srcMode=%d srcAlpha=%d w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n", + srcMode, srcAlpha, w, h, (double)mat[0], (double)mat[1], (double)mat[2], + (double)mat[3], (double)mat[4], (double)mat[5]); + } + + // check color modes + ok = gFalse; // make gcc happy + nComps = 0; // make gcc happy + switch (bitmap->mode) { + case splashModeMono1: + case splashModeMono8: + ok = srcMode == splashModeMono8; + nComps = 1; + break; + case splashModeRGB8: + ok = srcMode == splashModeRGB8; + nComps = 3; + break; + case splashModeBGR8: + ok = srcMode == splashModeBGR8; + nComps = 3; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + ok = srcMode == splashModeCMYK8; + nComps = 4; + break; +#endif + } + if (!ok) { + return splashErrModeMismatch; + } + + // check for singular matrix + if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.000001) { + return splashErrSingularMatrix; + } + + // compute scale, shear, rotation, translation parameters + rot = splashAbs(mat[1]) > splashAbs(mat[0]); + if (rot) { + xScale = -mat[1]; + yScale = mat[2] - (mat[0] * mat[3]) / mat[1]; + xShear = -mat[3] / yScale; + yShear = -mat[0] / mat[1]; + } else { + xScale = mat[0]; + yScale = mat[3] - (mat[1] * mat[2]) / mat[0]; + xShear = mat[2] / yScale; + yShear = mat[1] / mat[0]; + } + // Note 1: The PDF spec says that all pixels whose *centers* lie + // within the region get painted -- but that doesn't seem to match + // up with what Acrobat actually does: it ends up leaving gaps + // between image stripes. So we use the same rule here as for + // fills: any pixel that overlaps the region gets painted. + // Note 2: The +/-0.01 in these computations is to avoid floating + // point precision problems which can lead to gaps between image + // stripes (it can cause image stripes to overlap, but that's a much + // less visible problem). + if (xScale >= 0) { + tx = splashFloor(mat[4] - 0.01); + tx2 = splashFloor(mat[4] + xScale + 0.01); + } else { + tx = splashFloor(mat[4] + 0.01); + tx2 = splashFloor(mat[4] + xScale - 0.01); + } + scaledWidth = abs(tx2 - tx) + 1; + if (yScale >= 0) { + ty = splashFloor(mat[5] - 0.01); + ty2 = splashFloor(mat[5] + yScale + 0.01); + } else { + ty = splashFloor(mat[5] + 0.01); + ty2 = splashFloor(mat[5] + yScale - 0.01); + } + scaledHeight = abs(ty2 - ty) + 1; + xSign = (xScale < 0) ? -1 : 1; + ySign = (yScale < 0) ? -1 : 1; + yShear1 = (SplashCoord)xSign * yShear; + + // clipping + ulx1 = 0; + uly1 = 0; + urx1 = xSign * (scaledWidth - 1); + ury1 = (int)(yShear * urx1); + llx1 = splashRound(xShear * ySign * (scaledHeight - 1)); + lly1 = ySign * (scaledHeight - 1) + (int)(yShear * llx1); + lrx1 = xSign * (scaledWidth - 1) + + splashRound(xShear * ySign * (scaledHeight - 1)); + lry1 = ySign * (scaledHeight - 1) + (int)(yShear * lrx1); + if (rot) { + ulx = tx + uly1; uly = ty - ulx1; + urx = tx + ury1; ury = ty - urx1; + llx = tx + lly1; lly = ty - llx1; + lrx = tx + lry1; lry = ty - lrx1; + } else { + ulx = tx + ulx1; uly = ty + uly1; + urx = tx + urx1; ury = ty + ury1; + llx = tx + llx1; lly = ty + lly1; + lrx = tx + lrx1; lry = ty + lry1; + } + xMin = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx + : (llx < lrx) ? llx : lrx + : (urx < llx) ? (urx < lrx) ? urx : lrx + : (llx < lrx) ? llx : lrx; + xMax = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx + : (llx > lrx) ? llx : lrx + : (urx > llx) ? (urx > lrx) ? urx : lrx + : (llx > lrx) ? llx : lrx; + yMin = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry + : (lly < lry) ? lly : lry + : (ury < lly) ? (ury < lry) ? ury : lry + : (lly < lry) ? lly : lry; + yMax = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry + : (lly > lry) ? lly : lry + : (ury > lly) ? (ury > lry) ? ury : lry + : (lly > lry) ? lly : lry; + clipRes = state->clip->testRect(xMin, yMin, xMax, yMax); + opClipRes = clipRes; + if (clipRes == splashClipAllOutside) { + return splashOk; + } + + // compute Bresenham parameters for x and y scaling + yp = h / scaledHeight; + yq = h % scaledHeight; + xp = w / scaledWidth; + xq = w % scaledWidth; + + // allocate pixel buffers + colorBuf = (SplashColorPtr)gmalloc((yp + 1) * w * nComps); + if (srcAlpha) { + alphaBuf = (Guchar *)gmalloc((yp + 1) * w); + } else { + alphaBuf = NULL; + } + + pixAcc0 = pixAcc1 = pixAcc2 = 0; // make gcc happy +#if SPLASH_CMYK + pixAcc3 = 0; // make gcc happy +#endif + + // initialize the pixel pipe + pipeInit(&pipe, 0, 0, NULL, pix, state->fillAlpha, + srcAlpha || (vectorAntialias && clipRes != splashClipAllInside), + gFalse); + if (vectorAntialias) { + drawAAPixelInit(); + } + + if (srcAlpha) { + + // init y scale Bresenham + yt = 0; + lastYStep = 1; + + for (y = 0; y < scaledHeight; ++y) { + + // y scale Bresenham + yStep = yp; + yt += yq; + if (yt >= scaledHeight) { + yt -= scaledHeight; + ++yStep; + } + + // read row(s) from image + n = (yp > 0) ? yStep : lastYStep; + if (n > 0) { + p = colorBuf; + q = alphaBuf; + for (i = 0; i < n; ++i) { + (*src)(srcData, p, q); + p += w * nComps; + q += w; + } + } + lastYStep = yStep; + + // loop-invariant constants + k1 = splashRound(xShear * ySign * y); + + // clipping test + if (clipRes != splashClipAllInside && + !rot && + (int)(yShear * k1) == + (int)(yShear * (xSign * (scaledWidth - 1) + k1))) { + if (xSign > 0) { + spanXMin = tx + k1; + spanXMax = spanXMin + (scaledWidth - 1); + } else { + spanXMax = tx + k1; + spanXMin = spanXMax - (scaledWidth - 1); + } + spanY = ty + ySign * y + (int)(yShear * k1); + clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY); + if (clipRes2 == splashClipAllOutside) { + continue; + } + } else { + clipRes2 = clipRes; + } + + // init x scale Bresenham + xt = 0; + xSrc = 0; + + // x shear + x1 = k1; + + // y shear + y1 = (SplashCoord)ySign * y + yShear * x1; + // this is a kludge: if yShear1 is negative, then (int)y1 would + // change immediately after the first pixel, which is not what + // we want + if (yShear1 < 0) { + y1 += 0.999; + } + + // loop-invariant constants + n = yStep > 0 ? yStep : 1; + + switch (srcMode) { + + case splashModeMono1: + case splashModeMono8: + for (x = 0; x < scaledWidth; ++x) { + + // x scale Bresenham + xStep = xp; + xt += xq; + if (xt >= scaledWidth) { + xt -= scaledWidth; + ++xStep; + } + + // rotation + if (rot) { + x2 = (int)y1; + y2 = -x1; + } else { + x2 = x1; + y2 = (int)y1; + } + + // compute the filtered pixel at (x,y) after the x and y scaling + // operations + m = xStep > 0 ? xStep : 1; + alphaAcc = 0; + p = colorBuf + xSrc; + q = alphaBuf + xSrc; + pixAcc0 = 0; + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + pixAcc0 += *p++; + alphaAcc += *q++; + } + p += w - m; + q += w - m; + } + pixMul = (SplashCoord)1 / (SplashCoord)(n * m); + alphaMul = pixMul * (1.0 / 255.0); + alpha = (SplashCoord)alphaAcc * alphaMul; + + if (alpha > 0) { + pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); + + // set pixel + pipe.shape = alpha; + if (vectorAntialias && clipRes != splashClipAllInside) { + drawAAPixel(&pipe, tx + x2, ty + y2); + } else { + drawPixel(&pipe, tx + x2, ty + y2, + clipRes2 == splashClipAllInside); + } + } + + // x scale Bresenham + xSrc += xStep; + + // x shear + x1 += xSign; + + // y shear + y1 += yShear1; + } + break; + + case splashModeRGB8: + case splashModeBGR8: + for (x = 0; x < scaledWidth; ++x) { + + // x scale Bresenham + xStep = xp; + xt += xq; + if (xt >= scaledWidth) { + xt -= scaledWidth; + ++xStep; + } + + // rotation + if (rot) { + x2 = (int)y1; + y2 = -x1; + } else { + x2 = x1; + y2 = (int)y1; + } + + // compute the filtered pixel at (x,y) after the x and y scaling + // operations + m = xStep > 0 ? xStep : 1; + alphaAcc = 0; + p = colorBuf + xSrc * 3; + q = alphaBuf + xSrc; + pixAcc0 = pixAcc1 = pixAcc2 = 0; + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + pixAcc0 += *p++; + pixAcc1 += *p++; + pixAcc2 += *p++; + alphaAcc += *q++; + } + p += 3 * (w - m); + q += w - m; + } + pixMul = (SplashCoord)1 / (SplashCoord)(n * m); + alphaMul = pixMul * (1.0 / 255.0); + alpha = (SplashCoord)alphaAcc * alphaMul; + + if (alpha > 0) { + pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); + pix[1] = (int)((SplashCoord)pixAcc1 * pixMul); + pix[2] = (int)((SplashCoord)pixAcc2 * pixMul); + + // set pixel + pipe.shape = alpha; + if (vectorAntialias && clipRes != splashClipAllInside) { + drawAAPixel(&pipe, tx + x2, ty + y2); + } else { + drawPixel(&pipe, tx + x2, ty + y2, + clipRes2 == splashClipAllInside); + } + } + + // x scale Bresenham + xSrc += xStep; + + // x shear + x1 += xSign; + + // y shear + y1 += yShear1; + } + break; + +#if SPLASH_CMYK + case splashModeCMYK8: + for (x = 0; x < scaledWidth; ++x) { + + // x scale Bresenham + xStep = xp; + xt += xq; + if (xt >= scaledWidth) { + xt -= scaledWidth; + ++xStep; + } + + // rotation + if (rot) { + x2 = (int)y1; + y2 = -x1; + } else { + x2 = x1; + y2 = (int)y1; + } + + // compute the filtered pixel at (x,y) after the x and y scaling + // operations + m = xStep > 0 ? xStep : 1; + alphaAcc = 0; + p = colorBuf + xSrc * 4; + q = alphaBuf + xSrc; + pixAcc0 = pixAcc1 = pixAcc2 = pixAcc3 = 0; + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + pixAcc0 += *p++; + pixAcc1 += *p++; + pixAcc2 += *p++; + pixAcc3 += *p++; + alphaAcc += *q++; + } + p += 4 * (w - m); + q += w - m; + } + pixMul = (SplashCoord)1 / (SplashCoord)(n * m); + alphaMul = pixMul * (1.0 / 255.0); + alpha = (SplashCoord)alphaAcc * alphaMul; + + if (alpha > 0) { + pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); + pix[1] = (int)((SplashCoord)pixAcc1 * pixMul); + pix[2] = (int)((SplashCoord)pixAcc2 * pixMul); + pix[3] = (int)((SplashCoord)pixAcc3 * pixMul); + + // set pixel + pipe.shape = alpha; + if (vectorAntialias && clipRes != splashClipAllInside) { + drawAAPixel(&pipe, tx + x2, ty + y2); + } else { + drawPixel(&pipe, tx + x2, ty + y2, + clipRes2 == splashClipAllInside); + } + } + + // x scale Bresenham + xSrc += xStep; + + // x shear + x1 += xSign; + + // y shear + y1 += yShear1; + } + break; +#endif // SPLASH_CMYK + } + } + + } else { + + // init y scale Bresenham + yt = 0; + lastYStep = 1; + + for (y = 0; y < scaledHeight; ++y) { + + // y scale Bresenham + yStep = yp; + yt += yq; + if (yt >= scaledHeight) { + yt -= scaledHeight; + ++yStep; + } + + // read row(s) from image + n = (yp > 0) ? yStep : lastYStep; + if (n > 0) { + p = colorBuf; + for (i = 0; i < n; ++i) { + (*src)(srcData, p, NULL); + p += w * nComps; + } + } + lastYStep = yStep; + + // loop-invariant constants + k1 = splashRound(xShear * ySign * y); + + // clipping test + if (clipRes != splashClipAllInside && + !rot && + (int)(yShear * k1) == + (int)(yShear * (xSign * (scaledWidth - 1) + k1))) { + if (xSign > 0) { + spanXMin = tx + k1; + spanXMax = spanXMin + (scaledWidth - 1); + } else { + spanXMax = tx + k1; + spanXMin = spanXMax - (scaledWidth - 1); + } + spanY = ty + ySign * y + (int)(yShear * k1); + clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY); + if (clipRes2 == splashClipAllOutside) { + continue; + } + } else { + clipRes2 = clipRes; + } + + // init x scale Bresenham + xt = 0; + xSrc = 0; + + // x shear + x1 = k1; + + // y shear + y1 = (SplashCoord)ySign * y + yShear * x1; + // this is a kludge: if yShear1 is negative, then (int)y1 would + // change immediately after the first pixel, which is not what + // we want + if (yShear1 < 0) { + y1 += 0.999; + } + + // loop-invariant constants + n = yStep > 0 ? yStep : 1; + + switch (srcMode) { + + case splashModeMono1: + case splashModeMono8: + for (x = 0; x < scaledWidth; ++x) { + + // x scale Bresenham + xStep = xp; + xt += xq; + if (xt >= scaledWidth) { + xt -= scaledWidth; + ++xStep; + } + + // rotation + if (rot) { + x2 = (int)y1; + y2 = -x1; + } else { + x2 = x1; + y2 = (int)y1; + } + + // compute the filtered pixel at (x,y) after the x and y scaling + // operations + m = xStep > 0 ? xStep : 1; + p = colorBuf + xSrc; + pixAcc0 = 0; + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + pixAcc0 += *p++; + } + p += w - m; + } + pixMul = (SplashCoord)1 / (SplashCoord)(n * m); + + pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); + + // set pixel + if (vectorAntialias && clipRes != splashClipAllInside) { + pipe.shape = (SplashCoord)1; + drawAAPixel(&pipe, tx + x2, ty + y2); + } else { + drawPixel(&pipe, tx + x2, ty + y2, + clipRes2 == splashClipAllInside); + } + + // x scale Bresenham + xSrc += xStep; + + // x shear + x1 += xSign; + + // y shear + y1 += yShear1; + } + break; + + case splashModeRGB8: + case splashModeBGR8: + for (x = 0; x < scaledWidth; ++x) { + + // x scale Bresenham + xStep = xp; + xt += xq; + if (xt >= scaledWidth) { + xt -= scaledWidth; + ++xStep; + } + + // rotation + if (rot) { + x2 = (int)y1; + y2 = -x1; + } else { + x2 = x1; + y2 = (int)y1; + } + + // compute the filtered pixel at (x,y) after the x and y scaling + // operations + m = xStep > 0 ? xStep : 1; + p = colorBuf + xSrc * 3; + pixAcc0 = pixAcc1 = pixAcc2 = 0; + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + pixAcc0 += *p++; + pixAcc1 += *p++; + pixAcc2 += *p++; + } + p += 3 * (w - m); + } + pixMul = (SplashCoord)1 / (SplashCoord)(n * m); + + pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); + pix[1] = (int)((SplashCoord)pixAcc1 * pixMul); + pix[2] = (int)((SplashCoord)pixAcc2 * pixMul); + + // set pixel + if (vectorAntialias && clipRes != splashClipAllInside) { + pipe.shape = (SplashCoord)1; + drawAAPixel(&pipe, tx + x2, ty + y2); + } else { + drawPixel(&pipe, tx + x2, ty + y2, + clipRes2 == splashClipAllInside); + } + + // x scale Bresenham + xSrc += xStep; + + // x shear + x1 += xSign; + + // y shear + y1 += yShear1; + } + break; + +#if SPLASH_CMYK + case splashModeCMYK8: + for (x = 0; x < scaledWidth; ++x) { + + // x scale Bresenham + xStep = xp; + xt += xq; + if (xt >= scaledWidth) { + xt -= scaledWidth; + ++xStep; + } + + // rotation + if (rot) { + x2 = (int)y1; + y2 = -x1; + } else { + x2 = x1; + y2 = (int)y1; + } + + // compute the filtered pixel at (x,y) after the x and y scaling + // operations + m = xStep > 0 ? xStep : 1; + p = colorBuf + xSrc * 4; + pixAcc0 = pixAcc1 = pixAcc2 = pixAcc3 = 0; + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + pixAcc0 += *p++; + pixAcc1 += *p++; + pixAcc2 += *p++; + pixAcc3 += *p++; + } + p += 4 * (w - m); + } + pixMul = (SplashCoord)1 / (SplashCoord)(n * m); + + pix[0] = (int)((SplashCoord)pixAcc0 * pixMul); + pix[1] = (int)((SplashCoord)pixAcc1 * pixMul); + pix[2] = (int)((SplashCoord)pixAcc2 * pixMul); + pix[3] = (int)((SplashCoord)pixAcc3 * pixMul); + + // set pixel + if (vectorAntialias && clipRes != splashClipAllInside) { + pipe.shape = (SplashCoord)1; + drawAAPixel(&pipe, tx + x2, ty + y2); + } else { + drawPixel(&pipe, tx + x2, ty + y2, + clipRes2 == splashClipAllInside); + } + + // x scale Bresenham + xSrc += xStep; + + // x shear + x1 += xSign; + + // y shear + y1 += yShear1; + } + break; +#endif // SPLASH_CMYK + } + } + + } + + gfree(colorBuf); + gfree(alphaBuf); + + return splashOk; +} + +SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc, + int xDest, int yDest, int w, int h, + GBool noClip, GBool nonIsolated) { + SplashPipe pipe; + SplashColor pixel; + Guchar alpha; + Guchar *ap; + int x, y; + + if (src->mode != bitmap->mode) { + return splashErrModeMismatch; + } + + if (src->alpha) { + pipeInit(&pipe, xDest, yDest, NULL, pixel, state->fillAlpha, + gTrue, nonIsolated); + for (y = 0; y < h; ++y) { + pipeSetXY(&pipe, xDest, yDest + y); + ap = src->getAlphaPtr() + (ySrc + y) * src->getWidth() + xSrc; + for (x = 0; x < w; ++x) { + src->getPixel(xSrc + x, ySrc + y, pixel); + alpha = *ap++; + if (noClip || state->clip->test(xDest + x, yDest + y)) { + // this uses shape instead of alpha, which isn't technically + // correct, but works out the same + pipe.shape = (SplashCoord)(alpha / 255.0); + pipeRun(&pipe); + updateModX(xDest + x); + updateModY(yDest + y); + } else { + pipeIncX(&pipe); + } + } + } + } else { + pipeInit(&pipe, xDest, yDest, NULL, pixel, state->fillAlpha, + gFalse, nonIsolated); + for (y = 0; y < h; ++y) { + pipeSetXY(&pipe, xDest, yDest + y); + for (x = 0; x < w; ++x) { + src->getPixel(xSrc + x, ySrc + y, pixel); + if (noClip || state->clip->test(xDest + x, yDest + y)) { + pipeRun(&pipe); + updateModX(xDest + x); + updateModY(yDest + y); + } else { + pipeIncX(&pipe); + } + } + } + } + + return splashOk; +} + +void Splash::compositeBackground(SplashColorPtr color) { + SplashColorPtr p; + Guchar *q; + Guchar alpha, alpha1, c, color0, color1, color2, color3; + int x, y, mask; + + switch (bitmap->mode) { + case splashModeMono1: + color0 = color[0]; + for (y = 0; y < bitmap->height; ++y) { + p = &bitmap->data[y * bitmap->rowSize]; + q = &bitmap->alpha[y * bitmap->width]; + mask = 0x80; + for (x = 0; x < bitmap->width; ++x) { + alpha = *q++; + alpha1 = 255 - alpha; + c = (*p & mask) ? 0xff : 0x00; + c = div255(alpha1 * color0 + alpha * c); + if (c & 0x80) { + *p |= mask; + } else { + *p &= ~mask; + } + if (!(mask >>= 1)) { + mask = 0x80; + ++p; + } + } + } + break; + case splashModeMono8: + color0 = color[0]; + for (y = 0; y < bitmap->height; ++y) { + p = &bitmap->data[y * bitmap->rowSize]; + q = &bitmap->alpha[y * bitmap->width]; + for (x = 0; x < bitmap->width; ++x) { + alpha = *q++; + alpha1 = 255 - alpha; + p[0] = div255(alpha1 * color0 + alpha * p[0]); + ++p; + } + } + break; + case splashModeRGB8: + case splashModeBGR8: + color0 = color[0]; + color1 = color[1]; + color2 = color[2]; + for (y = 0; y < bitmap->height; ++y) { + p = &bitmap->data[y * bitmap->rowSize]; + q = &bitmap->alpha[y * bitmap->width]; + for (x = 0; x < bitmap->width; ++x) { + alpha = *q++; + alpha1 = 255 - alpha; + p[0] = div255(alpha1 * color0 + alpha * p[0]); + p[1] = div255(alpha1 * color1 + alpha * p[1]); + p[2] = div255(alpha1 * color2 + alpha * p[2]); + p += 3; + } + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + color0 = color[0]; + color1 = color[1]; + color2 = color[2]; + color3 = color[3]; + for (y = 0; y < bitmap->height; ++y) { + p = &bitmap->data[y * bitmap->rowSize]; + q = &bitmap->alpha[y * bitmap->width]; + for (x = 0; x < bitmap->width; ++x) { + alpha = *q++; + alpha1 = 255 - alpha; + p[0] = div255(alpha1 * color0 + alpha * p[0]); + p[1] = div255(alpha1 * color1 + alpha * p[1]); + p[2] = div255(alpha1 * color2 + alpha * p[2]); + p[3] = div255(alpha1 * color3 + alpha * p[3]); + p += 4; + } + } + break; +#endif + } + memset(bitmap->alpha, 255, bitmap->width * bitmap->height); +} + +SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, + int xDest, int yDest, int w, int h) { + SplashColor pixel; + SplashColorPtr p; + Guchar *q; + int x, y, mask; + + if (src->mode != bitmap->mode) { + return splashErrModeMismatch; + } + + switch (bitmap->mode) { + case splashModeMono1: + for (y = 0; y < h; ++y) { + p = &bitmap->data[(yDest + y) * bitmap->rowSize + (xDest >> 3)]; + mask = 0x80 >> (xDest & 7); + for (x = 0; x < w; ++x) { + src->getPixel(xSrc + x, ySrc + y, pixel); + if (pixel[0]) { + *p |= mask; + } else { + *p &= ~mask; + } + if (!(mask >>= 1)) { + mask = 0x80; + ++p; + } + } + } + break; + case splashModeMono8: + for (y = 0; y < h; ++y) { + p = &bitmap->data[(yDest + y) * bitmap->rowSize + xDest]; + for (x = 0; x < w; ++x) { + src->getPixel(xSrc + x, ySrc + y, pixel); + *p++ = pixel[0]; + } + } + break; + case splashModeRGB8: + case splashModeBGR8: + for (y = 0; y < h; ++y) { + p = &bitmap->data[(yDest + y) * bitmap->rowSize + 3 * xDest]; + for (x = 0; x < w; ++x) { + src->getPixel(xSrc + x, ySrc + y, pixel); + *p++ = pixel[0]; + *p++ = pixel[1]; + *p++ = pixel[2]; + } + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + for (y = 0; y < h; ++y) { + p = &bitmap->data[(yDest + y) * bitmap->rowSize + 4 * xDest]; + for (x = 0; x < w; ++x) { + src->getPixel(xSrc + x, ySrc + y, pixel); + *p++ = pixel[0]; + *p++ = pixel[1]; + *p++ = pixel[2]; + *p++ = pixel[3]; + } + } + break; +#endif + } + + if (bitmap->alpha) { + for (y = 0; y < h; ++y) { + q = &bitmap->alpha[(yDest + y) * bitmap->width + xDest]; + for (x = 0; x < w; ++x) { + *q++ = 0x00; + } + } + } + + return splashOk; +} + +SplashPath *Splash::makeStrokePath(SplashPath *path, GBool flatten) { + SplashPath *pathIn, *pathOut; + SplashCoord w, d, dx, dy, wdx, wdy, dxNext, dyNext, wdxNext, wdyNext; + SplashCoord crossprod, dotprod, miter, m; + GBool first, last, closed; + int subpathStart, next, i; + int left0, left1, left2, right0, right1, right2, join0, join1, join2; + int leftFirst, rightFirst, firstPt; + + if (flatten) { + pathIn = flattenPath(path, state->matrix, state->flatness); + if (state->lineDashLength > 0) { + pathOut = makeDashedPath(pathIn); + delete pathIn; + pathIn = pathOut; + } + } else { + pathIn = path; + } + + subpathStart = 0; // make gcc happy + closed = gFalse; // make gcc happy + left0 = left1 = right0 = right1 = join0 = join1 = 0; // make gcc happy + leftFirst = rightFirst = firstPt = 0; // make gcc happy + + pathOut = new SplashPath(); + w = state->lineWidth; + + for (i = 0; i < pathIn->length - 1; ++i) { + if (pathIn->flags[i] & splashPathLast) { + continue; + } + if ((first = pathIn->flags[i] & splashPathFirst)) { + subpathStart = i; + closed = pathIn->flags[i] & splashPathClosed; + } + last = pathIn->flags[i+1] & splashPathLast; + + // compute the deltas for segment (i, i+1) + d = splashDist(pathIn->pts[i].x, pathIn->pts[i].y, + pathIn->pts[i+1].x, pathIn->pts[i+1].y); + if (d == 0) { + // we need to draw end caps on zero-length lines + //~ not clear what the behavior should be for splashLineCapButt + //~ with d==0 + dx = 0; + dy = 1; + } else { + d = (SplashCoord)1 / d; + dx = d * (pathIn->pts[i+1].x - pathIn->pts[i].x); + dy = d * (pathIn->pts[i+1].y - pathIn->pts[i].y); + } + wdx = (SplashCoord)0.5 * w * dx; + wdy = (SplashCoord)0.5 * w * dy; + + // compute the deltas for segment (i+1, next) + next = last ? subpathStart + 1 : i + 2; + d = splashDist(pathIn->pts[i+1].x, pathIn->pts[i+1].y, + pathIn->pts[next].x, pathIn->pts[next].y); + if (d == 0) { + // we need to draw end caps on zero-length lines + //~ not clear what the behavior should be for splashLineCapButt + //~ with d==0 + dxNext = 0; + dyNext = 1; + } else { + d = (SplashCoord)1 / d; + dxNext = d * (pathIn->pts[next].x - pathIn->pts[i+1].x); + dyNext = d * (pathIn->pts[next].y - pathIn->pts[i+1].y); + } + wdxNext = (SplashCoord)0.5 * w * dxNext; + wdyNext = (SplashCoord)0.5 * w * dyNext; + + // draw the start cap + pathOut->moveTo(pathIn->pts[i].x - wdy, pathIn->pts[i].y + wdx); + if (i == subpathStart) { + firstPt = pathOut->length - 1; + } + if (first && !closed) { + switch (state->lineCap) { + case splashLineCapButt: + pathOut->lineTo(pathIn->pts[i].x + wdy, pathIn->pts[i].y - wdx); + break; + case splashLineCapRound: + pathOut->curveTo(pathIn->pts[i].x - wdy - bezierCircle * wdx, + pathIn->pts[i].y + wdx - bezierCircle * wdy, + pathIn->pts[i].x - wdx - bezierCircle * wdy, + pathIn->pts[i].y - wdy + bezierCircle * wdx, + pathIn->pts[i].x - wdx, + pathIn->pts[i].y - wdy); + pathOut->curveTo(pathIn->pts[i].x - wdx + bezierCircle * wdy, + pathIn->pts[i].y - wdy - bezierCircle * wdx, + pathIn->pts[i].x + wdy - bezierCircle * wdx, + pathIn->pts[i].y - wdx - bezierCircle * wdy, + pathIn->pts[i].x + wdy, + pathIn->pts[i].y - wdx); + break; + case splashLineCapProjecting: + pathOut->lineTo(pathIn->pts[i].x - wdx - wdy, + pathIn->pts[i].y + wdx - wdy); + pathOut->lineTo(pathIn->pts[i].x - wdx + wdy, + pathIn->pts[i].y - wdx - wdy); + pathOut->lineTo(pathIn->pts[i].x + wdy, + pathIn->pts[i].y - wdx); + break; + } + } else { + pathOut->lineTo(pathIn->pts[i].x + wdy, pathIn->pts[i].y - wdx); + } + + // draw the left side of the segment rectangle + left2 = pathOut->length - 1; + pathOut->lineTo(pathIn->pts[i+1].x + wdy, pathIn->pts[i+1].y - wdx); + + // draw the end cap + if (last && !closed) { + switch (state->lineCap) { + case splashLineCapButt: + pathOut->lineTo(pathIn->pts[i+1].x - wdy, pathIn->pts[i+1].y + wdx); + break; + case splashLineCapRound: + pathOut->curveTo(pathIn->pts[i+1].x + wdy + bezierCircle * wdx, + pathIn->pts[i+1].y - wdx + bezierCircle * wdy, + pathIn->pts[i+1].x + wdx + bezierCircle * wdy, + pathIn->pts[i+1].y + wdy - bezierCircle * wdx, + pathIn->pts[i+1].x + wdx, + pathIn->pts[i+1].y + wdy); + pathOut->curveTo(pathIn->pts[i+1].x + wdx - bezierCircle * wdy, + pathIn->pts[i+1].y + wdy + bezierCircle * wdx, + pathIn->pts[i+1].x - wdy + bezierCircle * wdx, + pathIn->pts[i+1].y + wdx + bezierCircle * wdy, + pathIn->pts[i+1].x - wdy, + pathIn->pts[i+1].y + wdx); + break; + case splashLineCapProjecting: + pathOut->lineTo(pathIn->pts[i+1].x + wdy + wdx, + pathIn->pts[i+1].y - wdx + wdy); + pathOut->lineTo(pathIn->pts[i+1].x - wdy + wdx, + pathIn->pts[i+1].y + wdx + wdy); + pathOut->lineTo(pathIn->pts[i+1].x - wdy, + pathIn->pts[i+1].y + wdx); + break; + } + } else { + pathOut->lineTo(pathIn->pts[i+1].x - wdy, pathIn->pts[i+1].y + wdx); + } + + // draw the right side of the segment rectangle + right2 = pathOut->length - 1; + pathOut->close(); + + // draw the join + join2 = pathOut->length; + if (!last || closed) { + crossprod = dx * dyNext - dy * dxNext; + dotprod = -(dx * dxNext + dy * dyNext); + if (dotprod > 0.99999) { + // avoid a divide-by-zero -- set miter to something arbitrary + // such that sqrt(miter) will exceed miterLimit (and m is never + // used in that situation) + miter = (state->miterLimit + 1) * (state->miterLimit + 1); + m = 0; + } else { + miter = (SplashCoord)2 / ((SplashCoord)1 - dotprod); + if (miter < 1) { + // this can happen because of floating point inaccuracies + miter = 1; + } + m = splashSqrt(miter - 1); + } + + // round join + if (state->lineJoin == splashLineJoinRound) { + pathOut->moveTo(pathIn->pts[i+1].x + (SplashCoord)0.5 * w, + pathIn->pts[i+1].y); + pathOut->curveTo(pathIn->pts[i+1].x + (SplashCoord)0.5 * w, + pathIn->pts[i+1].y + bezierCircle2 * w, + pathIn->pts[i+1].x + bezierCircle2 * w, + pathIn->pts[i+1].y + (SplashCoord)0.5 * w, + pathIn->pts[i+1].x, + pathIn->pts[i+1].y + (SplashCoord)0.5 * w); + pathOut->curveTo(pathIn->pts[i+1].x - bezierCircle2 * w, + pathIn->pts[i+1].y + (SplashCoord)0.5 * w, + pathIn->pts[i+1].x - (SplashCoord)0.5 * w, + pathIn->pts[i+1].y + bezierCircle2 * w, + pathIn->pts[i+1].x - (SplashCoord)0.5 * w, + pathIn->pts[i+1].y); + pathOut->curveTo(pathIn->pts[i+1].x - (SplashCoord)0.5 * w, + pathIn->pts[i+1].y - bezierCircle2 * w, + pathIn->pts[i+1].x - bezierCircle2 * w, + pathIn->pts[i+1].y - (SplashCoord)0.5 * w, + pathIn->pts[i+1].x, + pathIn->pts[i+1].y - (SplashCoord)0.5 * w); + pathOut->curveTo(pathIn->pts[i+1].x + bezierCircle2 * w, + pathIn->pts[i+1].y - (SplashCoord)0.5 * w, + pathIn->pts[i+1].x + (SplashCoord)0.5 * w, + pathIn->pts[i+1].y - bezierCircle2 * w, + pathIn->pts[i+1].x + (SplashCoord)0.5 * w, + pathIn->pts[i+1].y); + + } else { + pathOut->moveTo(pathIn->pts[i+1].x, pathIn->pts[i+1].y); + + // angle < 180 + if (crossprod < 0) { + pathOut->lineTo(pathIn->pts[i+1].x - wdyNext, + pathIn->pts[i+1].y + wdxNext); + // miter join inside limit + if (state->lineJoin == splashLineJoinMiter && + splashSqrt(miter) <= state->miterLimit) { + pathOut->lineTo(pathIn->pts[i+1].x - wdy + wdx * m, + pathIn->pts[i+1].y + wdx + wdy * m); + pathOut->lineTo(pathIn->pts[i+1].x - wdy, + pathIn->pts[i+1].y + wdx); + // bevel join or miter join outside limit + } else { + pathOut->lineTo(pathIn->pts[i+1].x - wdy, pathIn->pts[i+1].y + wdx); + } + + // angle >= 180 + } else { + pathOut->lineTo(pathIn->pts[i+1].x + wdy, + pathIn->pts[i+1].y - wdx); + // miter join inside limit + if (state->lineJoin == splashLineJoinMiter && + splashSqrt(miter) <= state->miterLimit) { + pathOut->lineTo(pathIn->pts[i+1].x + wdy + wdx * m, + pathIn->pts[i+1].y - wdx + wdy * m); + pathOut->lineTo(pathIn->pts[i+1].x + wdyNext, + pathIn->pts[i+1].y - wdxNext); + // bevel join or miter join outside limit + } else { + pathOut->lineTo(pathIn->pts[i+1].x + wdyNext, + pathIn->pts[i+1].y - wdxNext); + } + } + } + + pathOut->close(); + } + + // add stroke adjustment hints + if (state->strokeAdjust) { + if (i >= subpathStart + 1) { + if (i >= subpathStart + 2) { + pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0); + pathOut->addStrokeAdjustHint(left1, right1, join0, left2); + } else { + pathOut->addStrokeAdjustHint(left1, right1, firstPt, left2); + } + pathOut->addStrokeAdjustHint(left1, right1, right2 + 1, right2 + 1); + } + left0 = left1; + left1 = left2; + right0 = right1; + right1 = right2; + join0 = join1; + join1 = join2; + if (i == subpathStart) { + leftFirst = left2; + rightFirst = right2; + } + if (last) { + if (i >= subpathStart + 2) { + pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0); + pathOut->addStrokeAdjustHint(left1, right1, + join0, pathOut->length - 1); + } else { + pathOut->addStrokeAdjustHint(left1, right1, + firstPt, pathOut->length - 1); + } + if (closed) { + pathOut->addStrokeAdjustHint(left1, right1, firstPt, leftFirst); + pathOut->addStrokeAdjustHint(left1, right1, + rightFirst + 1, rightFirst + 1); + pathOut->addStrokeAdjustHint(leftFirst, rightFirst, + left1 + 1, right1); + pathOut->addStrokeAdjustHint(leftFirst, rightFirst, + join1, pathOut->length - 1); + } + } + } + } + + if (pathIn != path) { + delete pathIn; + } + + return pathOut; +} + +void Splash::dumpPath(SplashPath *path) { + int i; + + for (i = 0; i < path->length; ++i) { + printf(" %3d: x=%8.2f y=%8.2f%s%s%s%s\n", + i, (double)path->pts[i].x, (double)path->pts[i].y, + (path->flags[i] & splashPathFirst) ? " first" : "", + (path->flags[i] & splashPathLast) ? " last" : "", + (path->flags[i] & splashPathClosed) ? " closed" : "", + (path->flags[i] & splashPathCurve) ? " curve" : ""); + } +} + +void Splash::dumpXPath(SplashXPath *path) { + int i; + + for (i = 0; i < path->length; ++i) { + printf(" %4d: x0=%8.2f y0=%8.2f x1=%8.2f y1=%8.2f %s%s%s%s%s%s%s\n", + i, (double)path->segs[i].x0, (double)path->segs[i].y0, + (double)path->segs[i].x1, (double)path->segs[i].y1, + (path->segs[i].flags & splashXPathFirst) ? "F" : " ", + (path->segs[i].flags & splashXPathLast) ? "L" : " ", + (path->segs[i].flags & splashXPathEnd0) ? "0" : " ", + (path->segs[i].flags & splashXPathEnd1) ? "1" : " ", + (path->segs[i].flags & splashXPathHoriz) ? "H" : " ", + (path->segs[i].flags & splashXPathVert) ? "V" : " ", + (path->segs[i].flags & splashXPathFlip) ? "P" : " "); + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashClip.cc swftools-0.9.1/lib/pdf/xpdf/SplashClip.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashClip.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashClip.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,382 @@ +//======================================================================== +// +// SplashClip.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "SplashErrorCodes.h" +#include "SplashPath.h" +#include "SplashXPath.h" +#include "SplashXPathScanner.h" +#include "SplashBitmap.h" +#include "SplashClip.h" + +//------------------------------------------------------------------------ +// SplashClip.flags +//------------------------------------------------------------------------ + +#define splashClipEO 0x01 // use even-odd rule + +//------------------------------------------------------------------------ +// SplashClip +//------------------------------------------------------------------------ + +SplashClip::SplashClip(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + GBool antialiasA) { + antialias = antialiasA; + if (x0 < x1) { + xMin = x0; + xMax = x1; + } else { + xMin = x1; + xMax = x0; + } + if (y0 < y1) { + yMin = y0; + yMax = y1; + } else { + yMin = y1; + yMax = y0; + } + xMinI = splashFloor(xMin); + yMinI = splashFloor(yMin); + xMaxI = splashFloor(xMax); + yMaxI = splashFloor(yMax); + paths = NULL; + flags = NULL; + scanners = NULL; + length = size = 0; +} + +SplashClip::SplashClip(SplashClip *clip) { + int i; + + antialias = clip->antialias; + xMin = clip->xMin; + yMin = clip->yMin; + xMax = clip->xMax; + yMax = clip->yMax; + xMinI = clip->xMinI; + yMinI = clip->yMinI; + xMaxI = clip->xMaxI; + yMaxI = clip->yMaxI; + length = clip->length; + size = clip->size; + paths = (SplashXPath **)gmallocn(size, sizeof(SplashXPath *)); + flags = (Guchar *)gmallocn(size, sizeof(Guchar)); + scanners = (SplashXPathScanner **) + gmallocn(size, sizeof(SplashXPathScanner *)); + for (i = 0; i < length; ++i) { + paths[i] = clip->paths[i]->copy(); + flags[i] = clip->flags[i]; + scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO); + } +} + +SplashClip::~SplashClip() { + int i; + + for (i = 0; i < length; ++i) { + delete paths[i]; + delete scanners[i]; + } + gfree(paths); + gfree(flags); + gfree(scanners); +} + +void SplashClip::grow(int nPaths) { + if (length + nPaths > size) { + if (size == 0) { + size = 32; + } + while (size < length + nPaths) { + size *= 2; + } + paths = (SplashXPath **)greallocn(paths, size, sizeof(SplashXPath *)); + flags = (Guchar *)greallocn(flags, size, sizeof(Guchar)); + scanners = (SplashXPathScanner **) + greallocn(scanners, size, sizeof(SplashXPathScanner *)); + } +} + +void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1) { + int i; + + for (i = 0; i < length; ++i) { + delete paths[i]; + delete scanners[i]; + } + gfree(paths); + gfree(flags); + gfree(scanners); + paths = NULL; + flags = NULL; + scanners = NULL; + length = size = 0; + + if (x0 < x1) { + xMin = x0; + xMax = x1; + } else { + xMin = x1; + xMax = x0; + } + if (y0 < y1) { + yMin = y0; + yMax = y1; + } else { + yMin = y1; + yMax = y0; + } + xMinI = splashFloor(xMin); + yMinI = splashFloor(yMin); + xMaxI = splashFloor(xMax); + yMaxI = splashFloor(yMax); +} + +SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1) { + if (x0 < x1) { + if (x0 > xMin) { + xMin = x0; + xMinI = splashFloor(xMin); + } + if (x1 < xMax) { + xMax = x1; + xMaxI = splashFloor(xMax); + } + } else { + if (x1 > xMin) { + xMin = x1; + xMinI = splashFloor(xMin); + } + if (x0 < xMax) { + xMax = x0; + xMaxI = splashFloor(xMax); + } + } + if (y0 < y1) { + if (y0 > yMin) { + yMin = y0; + yMinI = splashFloor(yMin); + } + if (y1 < yMax) { + yMax = y1; + yMaxI = splashFloor(yMax); + } + } else { + if (y1 > yMin) { + yMin = y1; + yMinI = splashFloor(yMin); + } + if (y0 < yMax) { + yMax = y0; + yMaxI = splashFloor(yMax); + } + } + return splashOk; +} + +SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix, + SplashCoord flatness, GBool eo) { + SplashXPath *xPath; + + xPath = new SplashXPath(path, matrix, flatness, gTrue); + + // check for an empty path + if (xPath->length == 0) { + xMax = xMin - 1; + yMax = yMin - 1; + xMaxI = splashFloor(xMax); + yMaxI = splashFloor(yMax); + delete xPath; + + // check for a rectangle + } else if (xPath->length == 4 && + ((xPath->segs[0].x0 == xPath->segs[0].x1 && + xPath->segs[0].x0 == xPath->segs[1].x0 && + xPath->segs[0].x0 == xPath->segs[3].x1 && + xPath->segs[2].x0 == xPath->segs[2].x1 && + xPath->segs[2].x0 == xPath->segs[1].x1 && + xPath->segs[2].x0 == xPath->segs[3].x0 && + xPath->segs[1].y0 == xPath->segs[1].y1 && + xPath->segs[1].y0 == xPath->segs[0].y1 && + xPath->segs[1].y0 == xPath->segs[2].y0 && + xPath->segs[3].y0 == xPath->segs[3].y1 && + xPath->segs[3].y0 == xPath->segs[0].y0 && + xPath->segs[3].y0 == xPath->segs[2].y1) || + (xPath->segs[0].y0 == xPath->segs[0].y1 && + xPath->segs[0].y0 == xPath->segs[1].y0 && + xPath->segs[0].y0 == xPath->segs[3].y1 && + xPath->segs[2].y0 == xPath->segs[2].y1 && + xPath->segs[2].y0 == xPath->segs[1].y1 && + xPath->segs[2].y0 == xPath->segs[3].y0 && + xPath->segs[1].x0 == xPath->segs[1].x1 && + xPath->segs[1].x0 == xPath->segs[0].x1 && + xPath->segs[1].x0 == xPath->segs[2].x0 && + xPath->segs[3].x0 == xPath->segs[3].x1 && + xPath->segs[3].x0 == xPath->segs[0].x0 && + xPath->segs[3].x0 == xPath->segs[2].x1))) { + clipToRect(xPath->segs[0].x0, xPath->segs[0].y0, + xPath->segs[2].x0, xPath->segs[2].y0); + delete xPath; + + } else { + grow(1); + if (antialias) { + xPath->aaScale(); + } + xPath->sort(); + paths[length] = xPath; + flags[length] = eo ? splashClipEO : 0; + scanners[length] = new SplashXPathScanner(xPath, eo); + ++length; + } + + return splashOk; +} + +GBool SplashClip::test(int x, int y) { + int i; + + // check the rectangle + if (x < xMinI || x > xMaxI || y < yMinI || y > yMaxI) { + return gFalse; + } + + // check the paths + if (antialias) { + for (i = 0; i < length; ++i) { + if (!scanners[i]->test(x * splashAASize, y * splashAASize)) { + return gFalse; + } + } + } else { + for (i = 0; i < length; ++i) { + if (!scanners[i]->test(x, y)) { + return gFalse; + } + } + } + + return gTrue; +} + +SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin, + int rectXMax, int rectYMax) { + // This tests the rectangle: + // x = [rectXMin, rectXMax + 1) (note: rect coords are ints) + // y = [rectYMin, rectYMax + 1) + // against the clipping region: + // x = [xMin, xMax] (note: clipping coords are fp) + // y = [yMin, yMax] + if ((SplashCoord)(rectXMax + 1) <= xMin || (SplashCoord)rectXMin > xMax || + (SplashCoord)(rectYMax + 1) <= yMin || (SplashCoord)rectYMin > yMax) { + return splashClipAllOutside; + } + if ((SplashCoord)rectXMin >= xMin && (SplashCoord)(rectXMax + 1) <= xMax && + (SplashCoord)rectYMin >= yMin && (SplashCoord)(rectYMax + 1) <= yMax && + length == 0) { + return splashClipAllInside; + } + return splashClipPartial; +} + +SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) { + int i; + + // This tests the rectangle: + // x = [spanXMin, spanXMax + 1) (note: span coords are ints) + // y = [spanY, spanY + 1) + // against the clipping region: + // x = [xMin, xMax] (note: clipping coords are fp) + // y = [yMin, yMax] + if ((SplashCoord)(spanXMax + 1) <= xMin || (SplashCoord)spanXMin > xMax || + (SplashCoord)(spanY + 1) <= yMin || (SplashCoord)spanY > yMax) { + return splashClipAllOutside; + } + if (!((SplashCoord)spanXMin >= xMin && (SplashCoord)(spanXMax + 1) <= xMax && + (SplashCoord)spanY >= yMin && (SplashCoord)(spanY + 1) <= yMax)) { + return splashClipPartial; + } + if (antialias) { + for (i = 0; i < length; ++i) { + if (!scanners[i]->testSpan(spanXMin * splashAASize, + spanXMax * splashAASize + (splashAASize - 1), + spanY * splashAASize)) { + return splashClipPartial; + } + } + } else { + for (i = 0; i < length; ++i) { + if (!scanners[i]->testSpan(spanXMin, spanXMax, spanY)) { + return splashClipPartial; + } + } + } + return splashClipAllInside; +} + +void SplashClip::clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y) { + int xx0, xx1, xx, yy, i; + SplashColorPtr p; + + // zero out pixels with x < xMin + xx0 = *x0 * splashAASize; + xx1 = splashFloor(xMin * splashAASize); + if (xx1 > aaBuf->getWidth()) { + xx1 = aaBuf->getWidth(); + } + if (xx0 < xx1) { + xx0 &= ~7; + for (yy = 0; yy < splashAASize; ++yy) { + p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3); + for (xx = xx0; xx + 7 < xx1; xx += 8) { + *p++ = 0; + } + if (xx < xx1) { + *p &= 0xff >> (xx1 & 7); + } + } + *x0 = splashFloor(xMin); + } + + // zero out pixels with x > xMax + xx0 = splashFloor(xMax * splashAASize) + 1; + if (xx0 < 0) { + xx0 = 0; + } + xx1 = (*x1 + 1) * splashAASize; + if (xx0 < xx1) { + for (yy = 0; yy < splashAASize; ++yy) { + p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3); + xx = xx0; + if (xx & 7) { + *p &= 0xff00 >> (xx & 7); + xx = (xx & ~7) + 8; + ++p; + } + for (; xx < xx1; xx += 8) { + *p++ = 0; + } + } + *x1 = splashFloor(xMax); + } + + // check the paths + for (i = 0; i < length; ++i) { + scanners[i]->clipAALine(aaBuf, x0, x1, y); + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashClip.h swftools-0.9.1/lib/pdf/xpdf/SplashClip.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashClip.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashClip.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,107 @@ +//======================================================================== +// +// SplashClip.h +// +//======================================================================== + +#ifndef SPLASHCLIP_H +#define SPLASHCLIP_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" +#include "SplashMath.h" + +class SplashPath; +class SplashXPath; +class SplashXPathScanner; +class SplashBitmap; + +//------------------------------------------------------------------------ + +enum SplashClipResult { + splashClipAllInside, + splashClipAllOutside, + splashClipPartial +}; + +//------------------------------------------------------------------------ +// SplashClip +//------------------------------------------------------------------------ + +class SplashClip { +public: + + // Create a clip, for the given rectangle. + SplashClip(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + GBool antialiasA); + + // Copy a clip. + SplashClip *copy() { return new SplashClip(this); } + + ~SplashClip(); + + // Reset the clip to a rectangle. + void resetToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1); + + // Intersect the clip with a rectangle. + SplashError clipToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1); + + // Interesect the clip with . + SplashError clipToPath(SplashPath *path, SplashCoord *matrix, + SplashCoord flatness, GBool eo); + + // Returns true if (,) is inside the clip. + GBool test(int x, int y); + + // Tests a rectangle against the clipping region. Returns one of: + // - splashClipAllInside if the entire rectangle is inside the + // clipping region, i.e., all pixels in the rectangle are + // visible + // - splashClipAllOutside if the entire rectangle is outside the + // clipping region, i.e., all the pixels in the rectangle are + // clipped + // - splashClipPartial if the rectangle is part inside and part + // outside the clipping region + SplashClipResult testRect(int rectXMin, int rectYMin, + int rectXMax, int rectYMax); + + // Similar to testRect, but tests a horizontal span. + SplashClipResult testSpan(int spanXMin, int spanXMax, int spanY); + + // Clips an anti-aliased line by setting pixels to zero. On entry, + // all non-zero pixels are between and . This function + // will update and . + void clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y); + + // Get the rectangle part of the clip region, in integer coordinates. + int getXMinI() { return xMinI; } + int getXMaxI() { return xMaxI; } + int getYMinI() { return yMinI; } + int getYMaxI() { return yMaxI; } + + // Get the number of arbitrary paths used by the clip region. + int getNumPaths() { return length; } + +private: + + SplashClip(SplashClip *clip); + void grow(int nPaths); + + GBool antialias; + SplashCoord xMin, yMin, xMax, yMax; + int xMinI, yMinI, xMaxI, yMaxI; + SplashXPath **paths; + Guchar *flags; + SplashXPathScanner **scanners; + int length, size; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashErrorCodes.h swftools-0.9.1/lib/pdf/xpdf/SplashErrorCodes.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashErrorCodes.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashErrorCodes.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,32 @@ +//======================================================================== +// +// SplashErrorCodes.h +// +//======================================================================== + +#ifndef SPLASHERRORCODES_H +#define SPLASHERRORCODES_H + +#include + +//------------------------------------------------------------------------ + +#define splashOk 0 // no error + +#define splashErrNoCurPt 1 // no current point + +#define splashErrEmptyPath 2 // zero points in path + +#define splashErrBogusPath 3 // only one point in subpath + +#define splashErrNoSave 4 // state stack is empty + +#define splashErrOpenFile 5 // couldn't open file + +#define splashErrNoGlyph 6 // couldn't get the requested glyph + +#define splashErrModeMismatch 7 // invalid combination of color modes + +#define splashErrSingularMatrix 8 // matrix is singular + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFont.cc swftools-0.9.1/lib/pdf/xpdf/SplashFont.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFont.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFont.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,184 @@ +//======================================================================== +// +// SplashFont.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "SplashMath.h" +#include "SplashGlyphBitmap.h" +#include "SplashFontFile.h" +#include "SplashFont.h" + +//------------------------------------------------------------------------ + +struct SplashFontCacheTag { + int c; + short xFrac, yFrac; // x and y fractions + int mru; // valid bit (0x80000000) and MRU index + int x, y, w, h; // offset and size of glyph +}; + +//------------------------------------------------------------------------ +// SplashFont +//------------------------------------------------------------------------ + +SplashFont::SplashFont(SplashFontFile *fontFileA, SplashCoord *matA, + SplashCoord *textMatA, GBool aaA) { + fontFile = fontFileA; + fontFile->incRefCnt(); + mat[0] = matA[0]; + mat[1] = matA[1]; + mat[2] = matA[2]; + mat[3] = matA[3]; + textMat[0] = textMatA[0]; + textMat[1] = textMatA[1]; + textMat[2] = textMatA[2]; + textMat[3] = textMatA[3]; + aa = aaA; + + cache = NULL; + cacheTags = NULL; + + xMin = yMin = xMax = yMax = 0; + + last_advance = -1; + ascender = -1; + descender = -1; +} + +void SplashFont::initCache() { + int i; + + // this should be (max - min + 1), but we add some padding to + // deal with rounding errors + glyphW = xMax - xMin + 3; + glyphH = yMax - yMin + 3; + if (aa) { + glyphSize = glyphW * glyphH; + } else { + glyphSize = ((glyphW + 7) >> 3) * glyphH; + } + + // set up the glyph pixmap cache + cacheAssoc = 8; + if (glyphSize <= 256) { + cacheSets = 8; + } else if (glyphSize <= 512) { + cacheSets = 4; + } else if (glyphSize <= 1024) { + cacheSets = 2; + } else { + cacheSets = 1; + } + cache = (Guchar *)gmallocn_noexit(cacheSets * cacheAssoc, glyphSize); + if(cache) { + cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc, + sizeof(SplashFontCacheTag)); + for (i = 0; i < cacheSets * cacheAssoc; ++i) { + cacheTags[i].mru = i & (cacheAssoc - 1); + } + } else { + cacheAssoc = 0; + } +} + +SplashFont::~SplashFont() { + fontFile->decRefCnt(); + if (cache) { + gfree(cache); + } + if (cacheTags) { + gfree(cacheTags); + } +} + +GBool SplashFont::getGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap) { + SplashGlyphBitmap bitmap2; + int size; + Guchar *p; + int i, j, k; + + // no fractional coordinates for large glyphs or non-anti-aliased + // glyphs + if (!aa || glyphH > 50) { + xFrac = yFrac = 0; + } + + // check the cache + i = (c & (cacheSets - 1)) * cacheAssoc; + for (j = 0; j < cacheAssoc; ++j) { + if ((cacheTags[i+j].mru & 0x80000000) && + cacheTags[i+j].c == c && + (int)cacheTags[i+j].xFrac == xFrac && + (int)cacheTags[i+j].yFrac == yFrac) { + bitmap->x = cacheTags[i+j].x; + bitmap->y = cacheTags[i+j].y; + bitmap->w = cacheTags[i+j].w; + bitmap->h = cacheTags[i+j].h; + for (k = 0; k < cacheAssoc; ++k) { + if (k != j && + (cacheTags[i+k].mru & 0x7fffffff) < + (cacheTags[i+j].mru & 0x7fffffff)) { + ++cacheTags[i+k].mru; + } + } + cacheTags[i+j].mru = 0x80000000; + bitmap->aa = aa; + bitmap->data = cache + (i+j) * glyphSize; + bitmap->freeData = gFalse; + return gTrue; + } + } + + // generate the glyph bitmap + if (!makeGlyph(c, xFrac, yFrac, &bitmap2)) { + return gFalse; + } + + // if the glyph doesn't fit in the bounding box, return a temporary + // uncached bitmap + if (bitmap2.w > glyphW || bitmap2.h > glyphH) { + *bitmap = bitmap2; + return gTrue; + } + + // insert glyph pixmap in cache + if (aa) { + size = bitmap2.w * bitmap2.h; + } else { + size = ((bitmap2.w + 7) >> 3) * bitmap2.h; + } + p = NULL; // make gcc happy + for (j = 0; j < cacheAssoc; ++j) { + if ((cacheTags[i+j].mru & 0x7fffffff) == cacheAssoc - 1) { + cacheTags[i+j].mru = 0x80000000; + cacheTags[i+j].c = c; + cacheTags[i+j].xFrac = (short)xFrac; + cacheTags[i+j].yFrac = (short)yFrac; + cacheTags[i+j].x = bitmap2.x; + cacheTags[i+j].y = bitmap2.y; + cacheTags[i+j].w = bitmap2.w; + cacheTags[i+j].h = bitmap2.h; + p = cache + (i+j) * glyphSize; + memcpy(p, bitmap2.data, size); + } else { + ++cacheTags[i+j].mru; + } + } + *bitmap = bitmap2; + bitmap->data = p; + bitmap->freeData = gFalse; + if (bitmap2.freeData) { + gfree(bitmap2.data); + } + return gTrue; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontEngine.cc swftools-0.9.1/lib/pdf/xpdf/SplashFontEngine.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontEngine.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFontEngine.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,317 @@ +//======================================================================== +// +// SplashFontEngine.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#if HAVE_T1LIB_H +#include +#endif + +#include +#include +#ifndef WIN32 +# include +#endif +#include "gmem.h" +#include "GString.h" +#include "SplashMath.h" +#include "SplashT1FontEngine.h" +#include "SplashFTFontEngine.h" +#include "SplashFontFile.h" +#include "SplashFontFileID.h" +#include "SplashFont.h" +#include "SplashFontEngine.h" + +#ifdef VMS +#if (__VMS_VER < 70000000) +extern "C" int unlink(char *filename); +#endif +#endif + +//------------------------------------------------------------------------ +// SplashFontEngine +//------------------------------------------------------------------------ + +SplashFontEngine::SplashFontEngine( +#if HAVE_T1LIB_H + GBool enableT1lib, +#endif +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + GBool enableFreeType, +#endif + GBool aa) { + int i; + + for (i = 0; i < splashFontCacheSize; ++i) { + fontCache[i] = NULL; + } + +#if HAVE_T1LIB_H + if (enableT1lib) { + t1Engine = SplashT1FontEngine::init(aa); + } else { + t1Engine = NULL; + } +#endif +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + if (enableFreeType) { + ftEngine = SplashFTFontEngine::init(aa); + } else { + ftEngine = NULL; + } +#endif +} + +SplashFontEngine::~SplashFontEngine() { + int i; + + for (i = 0; i < splashFontCacheSize; ++i) { + if (fontCache[i]) { + delete fontCache[i]; + } + } + +#if HAVE_T1LIB_H + if (t1Engine) { + delete t1Engine; + } +#endif +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + if (ftEngine) { + delete ftEngine; + } +#endif +} + +SplashFontFile *SplashFontEngine::getFontFile(SplashFontFileID *id) { + SplashFontFile *fontFile; + int i; + + for (i = 0; i < splashFontCacheSize; ++i) { + if (fontCache[i]) { + fontFile = fontCache[i]->getFontFile(); + if (fontFile && fontFile->getID()->matches(id)) { + return fontFile; + } + } + } + return NULL; +} + +SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA, + char *fileName, + GBool deleteFile, char **enc) { + SplashFontFile *fontFile; + + fontFile = NULL; +#if HAVE_T1LIB_H + if (!fontFile && t1Engine) { + fontFile = t1Engine->loadType1Font(idA, fileName, deleteFile, enc); + } +#endif +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + if (!fontFile && ftEngine) { + fontFile = ftEngine->loadType1Font(idA, fileName, deleteFile, enc); + } +#endif + +#ifndef WIN32 + // delete the (temporary) font file -- with Unix hard link + // semantics, this will remove the last link; otherwise it will + // return an error, leaving the file to be deleted later (if + // loadXYZFont failed, the file will always be deleted) + if (deleteFile) { + unlink(fontFile ? fontFile->fileName->getCString() : fileName); + } +#endif + + return fontFile; +} + +SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA, + char *fileName, + GBool deleteFile, + char **enc) { + SplashFontFile *fontFile; + + fontFile = NULL; +#if HAVE_T1LIB_H + if (!fontFile && t1Engine) { + fontFile = t1Engine->loadType1CFont(idA, fileName, deleteFile, enc); + } +#endif +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + if (!fontFile && ftEngine) { + fontFile = ftEngine->loadType1CFont(idA, fileName, deleteFile, enc); + } +#endif + +#ifndef WIN32 + // delete the (temporary) font file -- with Unix hard link + // semantics, this will remove the last link; otherwise it will + // return an error, leaving the file to be deleted later (if + // loadXYZFont failed, the file will always be deleted) + if (deleteFile) { + unlink(fontFile ? fontFile->fileName->getCString() : fileName); + } +#endif + + return fontFile; +} + +SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA, + char *fileName, + GBool deleteFile, + char **enc) { + SplashFontFile *fontFile; + + fontFile = NULL; +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + if (!fontFile && ftEngine) { + fontFile = ftEngine->loadOpenTypeT1CFont(idA, fileName, deleteFile, enc); + } +#endif + +#ifndef WIN32 + // delete the (temporary) font file -- with Unix hard link + // semantics, this will remove the last link; otherwise it will + // return an error, leaving the file to be deleted later (if + // loadXYZFont failed, the file will always be deleted) + if (deleteFile) { + unlink(fontFile ? fontFile->fileName->getCString() : fileName); + } +#endif + + return fontFile; +} + +SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA, + char *fileName, + GBool deleteFile) { + SplashFontFile *fontFile; + + fontFile = NULL; +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + if (!fontFile && ftEngine) { + fontFile = ftEngine->loadCIDFont(idA, fileName, deleteFile); + } +#endif + +#ifndef WIN32 + // delete the (temporary) font file -- with Unix hard link + // semantics, this will remove the last link; otherwise it will + // return an error, leaving the file to be deleted later (if + // loadXYZFont failed, the file will always be deleted) + if (deleteFile) { + unlink(fontFile ? fontFile->fileName->getCString() : fileName); + } +#endif + + return fontFile; +} + +SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA, + char *fileName, + GBool deleteFile) { + SplashFontFile *fontFile; + + fontFile = NULL; +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + if (!fontFile && ftEngine) { + fontFile = ftEngine->loadOpenTypeCFFFont(idA, fileName, deleteFile); + } +#endif + +#ifndef WIN32 + // delete the (temporary) font file -- with Unix hard link + // semantics, this will remove the last link; otherwise it will + // return an error, leaving the file to be deleted later (if + // loadXYZFont failed, the file will always be deleted) + if (deleteFile) { + unlink(fontFile ? fontFile->fileName->getCString() : fileName); + } +#endif + + return fontFile; +} + +SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA, + char *fileName, + GBool deleteFile, + Gushort *codeToGID, + int codeToGIDLen) { + SplashFontFile *fontFile; + + fontFile = NULL; +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + if (!fontFile && ftEngine) { + fontFile = ftEngine->loadTrueTypeFont(idA, fileName, deleteFile, + codeToGID, codeToGIDLen); + } +#endif + + if (!fontFile) { + gfree(codeToGID); + } + +#ifndef WIN32 + // delete the (temporary) font file -- with Unix hard link + // semantics, this will remove the last link; otherwise it will + // return an error, leaving the file to be deleted later (if + // loadXYZFont failed, the file will always be deleted) + if (deleteFile) { + unlink(fontFile ? fontFile->fileName->getCString() : fileName); + } +#endif + + return fontFile; +} + +SplashFont *SplashFontEngine::getFont(SplashFontFile *fontFile, + SplashCoord *textMat, + SplashCoord *ctm) { + SplashCoord mat[4]; + SplashFont *font; + int i, j; + + mat[0] = textMat[0] * ctm[0] + textMat[1] * ctm[2]; + mat[1] = -(textMat[0] * ctm[1] + textMat[1] * ctm[3]); + mat[2] = textMat[2] * ctm[0] + textMat[3] * ctm[2]; + mat[3] = -(textMat[2] * ctm[1] + textMat[3] * ctm[3]); + if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.01) { + // avoid a singular (or close-to-singular) matrix + mat[0] = 0.01; mat[1] = 0; + mat[2] = 0; mat[3] = 0.01; + } + + font = fontCache[0]; + if (font && font->matches(fontFile, mat, textMat)) { + return font; + } + for (i = 1; i < splashFontCacheSize; ++i) { + font = fontCache[i]; + if (font && font->matches(fontFile, mat, textMat)) { + for (j = i; j > 0; --j) { + fontCache[j] = fontCache[j-1]; + } + fontCache[0] = font; + return font; + } + } + font = fontFile->makeFont(mat, textMat); + if (fontCache[splashFontCacheSize - 1]) { + delete fontCache[splashFontCacheSize - 1]; + } + for (j = splashFontCacheSize - 1; j > 0; --j) { + fontCache[j] = fontCache[j-1]; + } + fontCache[0] = font; + return font; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontEngine.h swftools-0.9.1/lib/pdf/xpdf/SplashFontEngine.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontEngine.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFontEngine.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,91 @@ +//======================================================================== +// +// SplashFontEngine.h +// +//======================================================================== + +#ifndef SPLASHFONTENGINE_H +#define SPLASHFONTENGINE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +class SplashT1FontEngine; +class SplashFTFontEngine; +class SplashDTFontEngine; +class SplashDT4FontEngine; +class SplashFontFile; +class SplashFontFileID; +class SplashFont; + +//------------------------------------------------------------------------ + +#define splashFontCacheSize 16 + +//------------------------------------------------------------------------ +// SplashFontEngine +//------------------------------------------------------------------------ + +class SplashFontEngine { +public: + + // Create a font engine. + SplashFontEngine( +#if HAVE_T1LIB_H + GBool enableT1lib, +#endif +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + GBool enableFreeType, +#endif + GBool aa); + + ~SplashFontEngine(); + + // Get a font file from the cache. Returns NULL if there is no + // matching entry in the cache. + SplashFontFile *getFontFile(SplashFontFileID *id); + + // Load fonts - these create new SplashFontFile objects. + SplashFontFile *loadType1Font(SplashFontFileID *idA, char *fileName, + GBool deleteFile, char **enc); + SplashFontFile *loadType1CFont(SplashFontFileID *idA, char *fileName, + GBool deleteFile, char **enc); + SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA, char *fileName, + GBool deleteFile, char **enc); + SplashFontFile *loadCIDFont(SplashFontFileID *idA, char *fileName, + GBool deleteFile); + SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA, char *fileName, + GBool deleteFile); + SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, char *fileName, + GBool deleteFile, + Gushort *codeToGID, int codeToGIDLen); + + // Get a font - this does a cache lookup first, and if not found, + // creates a new SplashFont object and adds it to the cache. The + // matrix, mat = textMat * ctm: + // [ mat[0] mat[1] ] + // [ mat[2] mat[3] ] + // specifies the font transform in PostScript style: + // [x' y'] = [x y] * mat + // Note that the Splash y axis points downward. + SplashFont *getFont(SplashFontFile *fontFile, + SplashCoord *textMat, SplashCoord *ctm); + +private: + + SplashFont *fontCache[splashFontCacheSize]; + +#if HAVE_T1LIB_H + SplashT1FontEngine *t1Engine; +#endif +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + SplashFTFontEngine *ftEngine; +#endif +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontFile.cc swftools-0.9.1/lib/pdf/xpdf/SplashFontFile.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontFile.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFontFile.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,53 @@ +//======================================================================== +// +// SplashFontFile.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "GString.h" +#include "SplashFontFile.h" +#include "SplashFontFileID.h" + +#ifdef VMS +#if (__VMS_VER < 70000000) +extern "C" int unlink(char *filename); +#endif +#endif + +//------------------------------------------------------------------------ +// SplashFontFile +//------------------------------------------------------------------------ + +SplashFontFile::SplashFontFile(SplashFontFileID *idA, char *fileNameA, + GBool deleteFileA) { + id = idA; + fileName = new GString(fileNameA); + deleteFile = deleteFileA; + refCnt = 0; +} + +SplashFontFile::~SplashFontFile() { + if (deleteFile) { + unlink(fileName->getCString()); + } + delete fileName; + delete id; +} + +void SplashFontFile::incRefCnt() { + ++refCnt; +} + +void SplashFontFile::decRefCnt() { + if (!--refCnt) { + delete this; + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontFile.h swftools-0.9.1/lib/pdf/xpdf/SplashFontFile.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontFile.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFontFile.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,60 @@ +//======================================================================== +// +// SplashFontFile.h +// +//======================================================================== + +#ifndef SPLASHFONTFILE_H +#define SPLASHFONTFILE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "SplashTypes.h" + +class GString; +class SplashFontEngine; +class SplashFont; +class SplashFontFileID; + +//------------------------------------------------------------------------ +// SplashFontFile +//------------------------------------------------------------------------ + +class SplashFontFile { +public: + + virtual ~SplashFontFile(); + + // Create a new SplashFont, i.e., a scaled instance of this font + // file. + virtual SplashFont *makeFont(SplashCoord *mat, SplashCoord *textMat) = 0; + + // Get the font file ID. + SplashFontFileID *getID() { return id; } + + // Increment the reference count. + void incRefCnt(); + + // Decrement the reference count. If the new value is zero, delete + // the SplashFontFile object. + void decRefCnt(); + +protected: + + SplashFontFile(SplashFontFileID *idA, char *fileNameA, + GBool deleteFileA); + + SplashFontFileID *id; + GString *fileName; + GBool deleteFile; + int refCnt; + + friend class SplashFontEngine; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontFileID.cc swftools-0.9.1/lib/pdf/xpdf/SplashFontFileID.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontFileID.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFontFileID.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,23 @@ +//======================================================================== +// +// SplashFontFileID.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "SplashFontFileID.h" + +//------------------------------------------------------------------------ +// SplashFontFileID +//------------------------------------------------------------------------ + +SplashFontFileID::SplashFontFileID() { +} + +SplashFontFileID::~SplashFontFileID() { +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontFileID.h swftools-0.9.1/lib/pdf/xpdf/SplashFontFileID.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFontFileID.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFontFileID.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,30 @@ +//======================================================================== +// +// SplashFontFileID.h +// +//======================================================================== + +#ifndef SPLASHFONTFILEID_H +#define SPLASHFONTFILEID_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +//------------------------------------------------------------------------ +// SplashFontFileID +//------------------------------------------------------------------------ + +class SplashFontFileID { +public: + + SplashFontFileID(); + virtual ~SplashFontFileID(); + virtual GBool matches(SplashFontFileID *id) = 0; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFont.h swftools-0.9.1/lib/pdf/xpdf/SplashFont.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFont.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFont.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,110 @@ +//======================================================================== +// +// SplashFont.h +// +//======================================================================== + +#ifndef SPLASHFONT_H +#define SPLASHFONT_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "SplashTypes.h" + +struct SplashGlyphBitmap; +struct SplashFontCacheTag; +class SplashFontFile; +class SplashPath; + +//------------------------------------------------------------------------ + +// Fractional positioning uses this many bits to the right of the +// decimal points. +#define splashFontFractionBits 2 +#define splashFontFraction (1 << splashFontFractionBits) +#define splashFontFractionMul \ + ((SplashCoord)1 / (SplashCoord)splashFontFraction) + +//------------------------------------------------------------------------ +// SplashFont +//------------------------------------------------------------------------ + +class SplashFont { +public: + + SplashFont(SplashFontFile *fontFileA, SplashCoord *matA, + SplashCoord *textMatA, GBool aaA); + + // This must be called after the constructor, so that the subclass + // constructor has a chance to compute the bbox. + void initCache(); + + virtual ~SplashFont(); + + SplashFontFile *getFontFile() { return fontFile; } + + // Return true if matches the specified font file and matrix. + GBool matches(SplashFontFile *fontFileA, SplashCoord *matA, + SplashCoord *textMatA) { + return fontFileA == fontFile && + matA[0] == mat[0] && matA[1] == mat[1] && + matA[2] == mat[2] && matA[3] == mat[3] && + textMatA[0] == textMat[0] && textMatA[1] == textMat[1] && + textMatA[2] == textMat[2] && textMatA[3] == textMat[3]; + } + + // Get a glyph - this does a cache lookup first, and if not found, + // creates a new bitmap and adds it to the cache. The and + // values are splashFontFractionBits bits each, representing + // the numerators of fractions in [0, 1), where the denominator is + // splashFontFraction = 1 << splashFontFractionBits. Subclasses + // should override this to zero out xFrac and/or yFrac if they don't + // support fractional coordinates. + virtual GBool getGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap); + + // Rasterize a glyph. The and values are the same + // as described for getGlyph. + virtual GBool makeGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap) = 0; + + // return the number of characters in this font + virtual int getNumChars() = 0; + + // Return the path for a glyph. + virtual SplashPath *getGlyphPath(int c) = 0; + + // Return the font transform matrix. + SplashCoord *getMatrix() { return mat; } + + // Return the glyph bounding box. + void getBBox(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA) + { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; } + + double ascender; + double descender; + double last_advance; //set after getGlyphPath() +protected: + + SplashFontFile *fontFile; + SplashCoord mat[4]; // font transform matrix + // (text space -> device space) + SplashCoord textMat[4]; // text transform matrix + // (text space -> user space) + GBool aa; // anti-aliasing + int xMin, yMin, xMax, yMax; // glyph bounding box + Guchar *cache; // glyph bitmap cache + SplashFontCacheTag * // cache tags + cacheTags; + int glyphW, glyphH; // size of glyph bitmaps + int glyphSize; // size of glyph bitmaps, in bytes + int cacheSets; // number of sets in cache + int cacheAssoc; // cache associativity (glyphs per set) +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFont.cc swftools-0.9.1/lib/pdf/xpdf/SplashFTFont.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFont.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFTFont.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,379 @@ +//======================================================================== +// +// SplashFTFont.cc +// +//======================================================================== + +#include + +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include FT_OUTLINE_H +#include FT_SIZES_H +#include FT_GLYPH_H +#include "gmem.h" +#include "SplashMath.h" +#include "SplashGlyphBitmap.h" +#include "SplashPath.h" +#include "SplashFTFontEngine.h" +#include "SplashFTFontFile.h" +#include "SplashFTFont.h" + +//------------------------------------------------------------------------ + +static int glyphPathMoveTo(const FT_Vector *pt, void *path); +static int glyphPathLineTo(const FT_Vector *pt, void *path); +static int glyphPathConicTo(const FT_Vector *ctrl, const FT_Vector *pt, + void *path); +static int glyphPathCubicTo(const FT_Vector *ctrl1, const FT_Vector *ctrl2, + const FT_Vector *pt, void *path); + +//------------------------------------------------------------------------ +// SplashFTFont +//------------------------------------------------------------------------ + +SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA, + SplashCoord *textMatA): + SplashFont(fontFileA, matA, textMatA, fontFileA->engine->aa) +{ + FT_Face face; + SplashCoord size, div; + int x, y; + + face = fontFileA->face; + + if (FT_New_Size(face, &sizeObj)) { + return; + } + face->size = sizeObj; + size = splashSqrt(mat[2]*mat[2] + mat[3]*mat[3]); + if (FT_Set_Pixel_Sizes(face, 0, (int)size)) { + return; + } + + this->ascender = face->ascender; + this->descender = face->descender; + + // if the textMat values are too small, FreeType's fixed point + // arithmetic doesn't work so well + textScale = splashSqrt(textMat[2]*textMat[2] + textMat[3]*textMat[3]) / size; + + div = face->bbox.xMax > 20000 ? 65536 : 1; + + // transform the four corners of the font bounding box -- the min + // and max values form the bounding box of the transformed font + x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMin) / + (div * face->units_per_EM)); + xMin = xMax = x; + y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMin) / + (div * face->units_per_EM)); + yMin = yMax = y; + x = (int)((mat[0] * face->bbox.xMin + mat[2] * face->bbox.yMax) / + (div * face->units_per_EM)); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + y = (int)((mat[1] * face->bbox.xMin + mat[3] * face->bbox.yMax) / + (div * face->units_per_EM)); + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMin) / + (div * face->units_per_EM)); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMin) / + (div * face->units_per_EM)); + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + x = (int)((mat[0] * face->bbox.xMax + mat[2] * face->bbox.yMax) / + (div * face->units_per_EM)); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + y = (int)((mat[1] * face->bbox.xMax + mat[3] * face->bbox.yMax) / + (div * face->units_per_EM)); + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + // This is a kludge: some buggy PDF generators embed fonts with + // zero bounding boxes. + if (xMax == xMin) { + xMin = 0; + xMax = (int)size; + } + if (yMax == yMin) { + yMin = 0; + yMax = (int)((SplashCoord)1.2 * size); + } + + // compute the transform matrix +#if USE_FIXEDPOINT + matrix.xx = (FT_Fixed)((mat[0] / size).getRaw()); + matrix.yx = (FT_Fixed)((mat[1] / size).getRaw()); + matrix.xy = (FT_Fixed)((mat[2] / size).getRaw()); + matrix.yy = (FT_Fixed)((mat[3] / size).getRaw()); + textMatrix.xx = (FT_Fixed)((textMat[0] / (size * textScale)).getRaw()); + textMatrix.yx = (FT_Fixed)((textMat[1] / (size * textScale)).getRaw()); + textMatrix.xy = (FT_Fixed)((textMat[2] / (size * textScale)).getRaw()); + textMatrix.yy = (FT_Fixed)((textMat[3] / (size * textScale)).getRaw()); +#else + matrix.xx = (FT_Fixed)((mat[0] / size) * 65536); + matrix.yx = (FT_Fixed)((mat[1] / size) * 65536); + matrix.xy = (FT_Fixed)((mat[2] / size) * 65536); + matrix.yy = (FT_Fixed)((mat[3] / size) * 65536); + textMatrix.xx = (FT_Fixed)((textMat[0] / (size * textScale)) * 65536); + textMatrix.yx = (FT_Fixed)((textMat[1] / (size * textScale)) * 65536); + textMatrix.xy = (FT_Fixed)((textMat[2] / (size * textScale)) * 65536); + textMatrix.yy = (FT_Fixed)((textMat[3] / (size * textScale)) * 65536); +#endif +} + +SplashFTFont::~SplashFTFont() { +} + +GBool SplashFTFont::getGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap) { + return SplashFont::getGlyph(c, xFrac, 0, bitmap); +} + +GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap) { + SplashFTFontFile *ff; + FT_Vector offset; + FT_GlyphSlot slot; + FT_UInt gid; + int rowSize; + Guchar *p, *q; + int i; + + ff = (SplashFTFontFile *)fontFile; + + ff->face->size = sizeObj; + offset.x = (FT_Pos)(int)((SplashCoord)xFrac * splashFontFractionMul * 64); + offset.y = 0; + FT_Set_Transform(ff->face, &matrix, &offset); + slot = ff->face->glyph; + + if (ff->codeToGID && c < ff->codeToGIDLen) { + gid = (FT_UInt)ff->codeToGID[c]; + } else { + gid = (FT_UInt)c; + } + if (ff->trueType && gid == 0) { + // skip the TrueType notdef glyph + return gFalse; + } + + // if we have the FT2 bytecode interpreter, autohinting won't be used +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + if (FT_Load_Glyph(ff->face, gid, + aa ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT)) { + return gFalse; + } +#else + // FT2's autohinting doesn't always work very well (especially with + // font subsets), so turn it off if anti-aliasing is enabled; if + // anti-aliasing is disabled, this seems to be a tossup - some fonts + // look better with hinting, some without, so leave hinting on + if (FT_Load_Glyph(ff->face, gid, + aa ? FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP + : FT_LOAD_DEFAULT)) { + return gFalse; + } +#endif + if (FT_Render_Glyph(slot, aa ? ft_render_mode_normal + : ft_render_mode_mono)) { + return gFalse; + } + + bitmap->x = -slot->bitmap_left; + bitmap->y = slot->bitmap_top; + bitmap->w = slot->bitmap.width; + bitmap->h = slot->bitmap.rows; + bitmap->aa = aa; + if (aa) { + rowSize = bitmap->w; + } else { + rowSize = (bitmap->w + 7) >> 3; + } + bitmap->data = (Guchar *)gmalloc(rowSize * bitmap->h); + bitmap->freeData = gTrue; + for (i = 0, p = bitmap->data, q = slot->bitmap.buffer; + i < bitmap->h; + ++i, p += rowSize, q += slot->bitmap.pitch) { + memcpy(p, q, rowSize); + } + + return gTrue; +} + +struct SplashFTFontPath { + SplashPath *path; + SplashCoord textScale; + GBool needClose; +}; + +int SplashFTFont::getNumChars() +{ + SplashFTFontFile* ff = (SplashFTFontFile *)fontFile; + return ff->face->num_glyphs; +} + +SplashPath *SplashFTFont::getGlyphPath(int c) { + static FT_Outline_Funcs outlineFuncs = { +#if FREETYPE_MINOR <= 1 + (int (*)(FT_Vector *, void *))&glyphPathMoveTo, + (int (*)(FT_Vector *, void *))&glyphPathLineTo, + (int (*)(FT_Vector *, FT_Vector *, void *))&glyphPathConicTo, + (int (*)(FT_Vector *, FT_Vector *, FT_Vector *, void *))&glyphPathCubicTo, +#else + &glyphPathMoveTo, + &glyphPathLineTo, + &glyphPathConicTo, + &glyphPathCubicTo, +#endif + 0, 0 + }; + SplashFTFontFile *ff; + SplashFTFontPath path; + FT_GlyphSlot slot; + FT_UInt gid; + FT_Glyph glyph; + + this->last_advance = -1; + + ff = (SplashFTFontFile *)fontFile; + ff->face->size = sizeObj; + FT_Set_Transform(ff->face, &textMatrix, NULL); + slot = ff->face->glyph; + if (ff->codeToGID && c < ff->codeToGIDLen) { + gid = ff->codeToGID[c]; + } else { + gid = (FT_UInt)c; + } + if (ff->trueType && gid == 0) { + // skip the TrueType notdef glyph + return NULL; + } + int error = 0; + if ((error=FT_Load_Glyph(ff->face, gid, FT_LOAD_NO_BITMAP))) { + if ((error=FT_Load_Glyph(ff->face, gid, FT_LOAD_NO_BITMAP|FT_LOAD_NO_HINTING))) { + fprintf(stderr, "Truetype wasn't able to load glyph %d, error %d\n", gid, error); + return NULL; + } + } + if (FT_Get_Glyph(slot, &glyph)) { + return NULL; + } + this->last_advance = glyph->advance.x/65536.0; + + path.path = new SplashPath(); + path.textScale = textScale; + path.needClose = gFalse; + error = FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline, + &outlineFuncs, &path); + if(error) { + fprintf(stderr, "Truetype wasn't able to read glyph %d, error %d\n", gid, error); + } + if (path.needClose) { + path.path->close(); + } + FT_Done_Glyph(glyph); + return path.path; +} + +static int glyphPathMoveTo(const FT_Vector *pt, void *path) { + SplashFTFontPath *p = (SplashFTFontPath *)path; + + if (p->needClose) { + p->path->close(); + p->needClose = gFalse; + } + p->path->moveTo((SplashCoord)pt->x * p->textScale / 64.0, + (SplashCoord)pt->y * p->textScale / 64.0); + return 0; +} + +static int glyphPathLineTo(const FT_Vector *pt, void *path) { + SplashFTFontPath *p = (SplashFTFontPath *)path; + + p->path->lineTo((SplashCoord)pt->x * p->textScale / 64.0, + (SplashCoord)pt->y * p->textScale / 64.0); + p->needClose = gTrue; + return 0; +} + +static int glyphPathConicTo(const FT_Vector *ctrl, const FT_Vector *pt, + void *path) { + SplashFTFontPath *p = (SplashFTFontPath *)path; + SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xc, yc; + + if (!p->path->getCurPt(&x0, &y0)) { + return 0; + } + xc = (SplashCoord)ctrl->x * p->textScale / 64.0; + yc = (SplashCoord)ctrl->y * p->textScale / 64.0; + x3 = (SplashCoord)pt->x * p->textScale / 64.0; + y3 = (SplashCoord)pt->y * p->textScale / 64.0; + + // A second-order Bezier curve is defined by two endpoints, p0 and + // p3, and one control point, pc: + // + // p(t) = (1-t)^2*p0 + t*(1-t)*pc + t^2*p3 + // + // A third-order Bezier curve is defined by the same two endpoints, + // p0 and p3, and two control points, p1 and p2: + // + // p(t) = (1-t)^3*p0 + 3t*(1-t)^2*p1 + 3t^2*(1-t)*p2 + t^3*p3 + // + // Applying some algebra, we can convert a second-order curve to a + // third-order curve: + // + // p1 = (1/3) * (p0 + 2pc) + // p2 = (1/3) * (2pc + p3) + + x1 = (SplashCoord)(1.0 / 3.0) * (x0 + (SplashCoord)2 * xc); + y1 = (SplashCoord)(1.0 / 3.0) * (y0 + (SplashCoord)2 * yc); + x2 = (SplashCoord)(1.0 / 3.0) * ((SplashCoord)2 * xc + x3); + y2 = (SplashCoord)(1.0 / 3.0) * ((SplashCoord)2 * yc + y3); + + p->path->curveTo(x1, y1, x2, y2, x3, y3); + p->needClose = gTrue; + return 0; +} + +static int glyphPathCubicTo(const FT_Vector *ctrl1, const FT_Vector *ctrl2, + const FT_Vector *pt, void *path) { + SplashFTFontPath *p = (SplashFTFontPath *)path; + + p->path->curveTo((SplashCoord)ctrl1->x * p->textScale / 64.0, + (SplashCoord)ctrl1->y * p->textScale / 64.0, + (SplashCoord)ctrl2->x * p->textScale / 64.0, + (SplashCoord)ctrl2->y * p->textScale / 64.0, + (SplashCoord)pt->x * p->textScale / 64.0, + (SplashCoord)pt->y * p->textScale / 64.0); + p->needClose = gTrue; + return 0; +} + +#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFontEngine.cc swftools-0.9.1/lib/pdf/xpdf/SplashFTFontEngine.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFontEngine.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFTFontEngine.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,177 @@ +//======================================================================== +// +// SplashFTFontEngine.cc +// +//======================================================================== + +#include + +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +# include +#include "gmem.h" +#include "GString.h" +#include "gfile.h" +#include "FoFiTrueType.h" +#include "FoFiType1C.h" +#include "SplashFTFontFile.h" +#include "SplashFTFontEngine.h" + +#ifdef VMS +#if (__VMS_VER < 70000000) +extern "C" int unlink(char *filename); +#endif +#endif + +//------------------------------------------------------------------------ + +static void fileWrite(void *stream, char *data, int len) { + fwrite(data, 1, len, (FILE *)stream); +} + +//------------------------------------------------------------------------ +// SplashFTFontEngine +//------------------------------------------------------------------------ + +SplashFTFontEngine::SplashFTFontEngine(GBool aaA, FT_Library libA) { + FT_Int major, minor, patch; + + aa = aaA; + lib = libA; + + // as of FT 2.1.8, CID fonts are indexed by CID instead of GID + FT_Library_Version(lib, &major, &minor, &patch); + useCIDs = major > 2 || + (major == 2 && (minor > 1 || (minor == 1 && patch > 7))); +} + +SplashFTFontEngine *SplashFTFontEngine::init(GBool aaA) { + FT_Library libA; + + if (FT_Init_FreeType(&libA)) { + return NULL; + } + return new SplashFTFontEngine(aaA, libA); +} + +SplashFTFontEngine::~SplashFTFontEngine() { + FT_Done_FreeType(lib); +} + +SplashFontFile *SplashFTFontEngine::loadType1Font(SplashFontFileID *idA, + char *fileName, + GBool deleteFile, + char **enc) { + return SplashFTFontFile::loadType1Font(this, idA, fileName, deleteFile, enc); +} + +SplashFontFile *SplashFTFontEngine::loadType1CFont(SplashFontFileID *idA, + char *fileName, + GBool deleteFile, + char **enc) { + return SplashFTFontFile::loadType1Font(this, idA, fileName, deleteFile, enc); +} + +SplashFontFile *SplashFTFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA, + char *fileName, + GBool deleteFile, + char **enc) { + return SplashFTFontFile::loadType1Font(this, idA, fileName, deleteFile, enc); +} + +SplashFontFile *SplashFTFontEngine::loadCIDFont(SplashFontFileID *idA, + char *fileName, + GBool deleteFile) { + FoFiType1C *ff; + Gushort *cidToGIDMap; + int nCIDs; + SplashFontFile *ret; + + // check for a CFF font + if (useCIDs) { + cidToGIDMap = NULL; + nCIDs = 0; + } else if ((ff = FoFiType1C::load(fileName))) { + cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); + delete ff; + } else { + cidToGIDMap = NULL; + nCIDs = 0; + } + ret = SplashFTFontFile::loadCIDFont(this, idA, fileName, deleteFile, + cidToGIDMap, nCIDs); + if (!ret) { + gfree(cidToGIDMap); + } + return ret; +} + +SplashFontFile *SplashFTFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA, + char *fileName, + GBool deleteFile) { + FoFiTrueType *ff; + GBool isCID; + Gushort *cidToGIDMap; + int nCIDs; + SplashFontFile *ret; + + cidToGIDMap = NULL; + nCIDs = 0; + isCID = gFalse; + if (!useCIDs) { + if ((ff = FoFiTrueType::load(fileName))) { + if (ff->isOpenTypeCFF()) { + cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); + } + delete ff; + } + } + ret = SplashFTFontFile::loadCIDFont(this, idA, fileName, deleteFile, + cidToGIDMap, nCIDs); + if (!ret) { + gfree(cidToGIDMap); + } + return ret; +} + +SplashFontFile *SplashFTFontEngine::loadTrueTypeFont(SplashFontFileID *idA, + char *fileName, + GBool deleteFile, + Gushort *codeToGID, + int codeToGIDLen) { + FoFiTrueType *ff; + GString *tmpFileName; + FILE *tmpFile; + SplashFontFile *ret; + + if (!(ff = FoFiTrueType::load(fileName))) { + return NULL; + } + tmpFileName = NULL; + if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { + delete ff; + return NULL; + } + ff->writeTTF(&fileWrite, tmpFile); + delete ff; + fclose(tmpFile); + ret = SplashFTFontFile::loadTrueTypeFont(this, idA, + tmpFileName->getCString(), + gTrue, codeToGID, codeToGIDLen); + if (ret) { + if (deleteFile) { + unlink(fileName); + } + } else { + unlink(tmpFileName->getCString()); + } + delete tmpFileName; + return ret; +} + +#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFontEngine.h swftools-0.9.1/lib/pdf/xpdf/SplashFTFontEngine.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFontEngine.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFTFontEngine.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,65 @@ +//======================================================================== +// +// SplashFTFontEngine.h +// +//======================================================================== + +#ifndef SPLASHFTFONTENGINE_H +#define SPLASHFTFONTENGINE_H + +#include + +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include FT_FREETYPE_H +#include "gtypes.h" + +class SplashFontFile; +class SplashFontFileID; + +//------------------------------------------------------------------------ +// SplashFTFontEngine +//------------------------------------------------------------------------ + +class SplashFTFontEngine { +public: + + static SplashFTFontEngine *init(GBool aaA); + + ~SplashFTFontEngine(); + + // Load fonts. + SplashFontFile *loadType1Font(SplashFontFileID *idA, char *fileName, + GBool deleteFile, char **enc); + SplashFontFile *loadType1CFont(SplashFontFileID *idA, char *fileName, + GBool deleteFile, char **enc); + SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA, char *fileName, + GBool deleteFile, char **enc); + SplashFontFile *loadCIDFont(SplashFontFileID *idA, char *fileName, + GBool deleteFile); + SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA, char *fileName, + GBool deleteFile); + SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, char *fileName, + GBool deleteFile, + Gushort *codeToGID, int codeToGIDLen); + +private: + + SplashFTFontEngine(GBool aaA, FT_Library libA); + + GBool aa; + FT_Library lib; + GBool useCIDs; + + friend class SplashFTFontFile; + friend class SplashFTFont; +}; + +#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFontFile.cc swftools-0.9.1/lib/pdf/xpdf/SplashFTFontFile.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFontFile.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFTFontFile.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,114 @@ +//======================================================================== +// +// SplashFTFontFile.cc +// +//======================================================================== + +#include + +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "gmem.h" +#include "SplashFTFontEngine.h" +#include "SplashFTFont.h" +#include "SplashFTFontFile.h" + +//------------------------------------------------------------------------ +// SplashFTFontFile +//------------------------------------------------------------------------ + +SplashFontFile *SplashFTFontFile::loadType1Font(SplashFTFontEngine *engineA, + SplashFontFileID *idA, + char *fileNameA, + GBool deleteFileA, + char **encA) { + FT_Face faceA; + Gushort *codeToGIDA; + char *name; + int i; + + if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) { + return NULL; + } + codeToGIDA = (Gushort *)gmallocn(256, sizeof(int)); + for (i = 0; i < 256; ++i) { + codeToGIDA[i] = 0; + if ((name = encA[i])) { + codeToGIDA[i] = (Gushort)FT_Get_Name_Index(faceA, name); + } + } + + return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA, + faceA, codeToGIDA, 256, gFalse); +} + +SplashFontFile *SplashFTFontFile::loadCIDFont(SplashFTFontEngine *engineA, + SplashFontFileID *idA, + char *fileNameA, + GBool deleteFileA, + Gushort *codeToGIDA, + int codeToGIDLenA) { + FT_Face faceA; + + if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) { + return NULL; + } + + return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA, + faceA, codeToGIDA, codeToGIDLenA, gFalse); +} + +SplashFontFile *SplashFTFontFile::loadTrueTypeFont(SplashFTFontEngine *engineA, + SplashFontFileID *idA, + char *fileNameA, + GBool deleteFileA, + Gushort *codeToGIDA, + int codeToGIDLenA) { + FT_Face faceA; + + if (FT_New_Face(engineA->lib, fileNameA, 0, &faceA)) { + return NULL; + } + + return new SplashFTFontFile(engineA, idA, fileNameA, deleteFileA, + faceA, codeToGIDA, codeToGIDLenA, gTrue); +} + +SplashFTFontFile::SplashFTFontFile(SplashFTFontEngine *engineA, + SplashFontFileID *idA, + char *fileNameA, GBool deleteFileA, + FT_Face faceA, + Gushort *codeToGIDA, int codeToGIDLenA, + GBool trueTypeA): + SplashFontFile(idA, fileNameA, deleteFileA) +{ + engine = engineA; + face = faceA; + codeToGID = codeToGIDA; + codeToGIDLen = codeToGIDLenA; + trueType = trueTypeA; +} + +SplashFTFontFile::~SplashFTFontFile() { + if (face) { + FT_Done_Face(face); + } + if (codeToGID) { + gfree(codeToGID); + } +} + +SplashFont *SplashFTFontFile::makeFont(SplashCoord *mat, + SplashCoord *textMat) { + SplashFont *font; + + font = new SplashFTFont(this, mat, textMat); + font->initCache(); + return font; +} + +#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFontFile.h swftools-0.9.1/lib/pdf/xpdf/SplashFTFontFile.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFontFile.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFTFontFile.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,73 @@ +//======================================================================== +// +// SplashFTFontFile.h +// +//======================================================================== + +#ifndef SPLASHFTFONTFILE_H +#define SPLASHFTFONTFILE_H + +#include + +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include FT_FREETYPE_H +#include "SplashFontFile.h" + +class SplashFontFileID; +class SplashFTFontEngine; + +//------------------------------------------------------------------------ +// SplashFTFontFile +//------------------------------------------------------------------------ + +class SplashFTFontFile: public SplashFontFile { +public: + + static SplashFontFile *loadType1Font(SplashFTFontEngine *engineA, + SplashFontFileID *idA, char *fileNameA, + GBool deleteFileA, char **encA); + static SplashFontFile *loadCIDFont(SplashFTFontEngine *engineA, + SplashFontFileID *idA, char *fileNameA, + GBool deleteFileA, + Gushort *codeToCIDA, int codeToGIDLenA); + static SplashFontFile *loadTrueTypeFont(SplashFTFontEngine *engineA, + SplashFontFileID *idA, + char *fileNameA, + GBool deleteFileA, + Gushort *codeToGIDA, + int codeToGIDLenA); + + virtual ~SplashFTFontFile(); + + // Create a new SplashFTFont, i.e., a scaled instance of this font + // file. + virtual SplashFont *makeFont(SplashCoord *mat, + SplashCoord *textMat); + +private: + + SplashFTFontFile(SplashFTFontEngine *engineA, + SplashFontFileID *idA, + char *fileNameA, GBool deleteFileA, + FT_Face faceA, + Gushort *codeToGIDA, int codeToGIDLenA, + GBool trueTypeA); + + SplashFTFontEngine *engine; + FT_Face face; + Gushort *codeToGID; + int codeToGIDLen; + GBool trueType; + + friend class SplashFTFont; +}; + +#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFont.h swftools-0.9.1/lib/pdf/xpdf/SplashFTFont.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashFTFont.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashFTFont.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,61 @@ +//======================================================================== +// +// SplashFTFont.h +// +//======================================================================== + +#ifndef SPLASHFTFONT_H +#define SPLASHFTFONT_H + +#include + +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include FT_FREETYPE_H +#include "SplashFont.h" + +class SplashFTFontFile; + +//------------------------------------------------------------------------ +// SplashFTFont +//------------------------------------------------------------------------ + +class SplashFTFont: public SplashFont { +public: + + SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA, + SplashCoord *textMatA); + + virtual ~SplashFTFont(); + + // Munge xFrac and yFrac before calling SplashFont::getGlyph. + virtual GBool getGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap); + + // Rasterize a glyph. The and values are the same + // as described for getGlyph. + virtual GBool makeGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap); + + // return the number of characters in this font + virtual int getNumChars(); + + // Return the path for a glyph. + virtual SplashPath *getGlyphPath(int c); + +private: + + FT_Size sizeObj; + FT_Matrix matrix; + FT_Matrix textMatrix; + SplashCoord textScale; +}; + +#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashGlyphBitmap.h swftools-0.9.1/lib/pdf/xpdf/SplashGlyphBitmap.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashGlyphBitmap.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashGlyphBitmap.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,26 @@ +//======================================================================== +// +// SplashGlyphBitmap.h +// +//======================================================================== + +#ifndef SPLASHGLYPHBITMAP_H +#define SPLASHGLYPHBITMAP_H + +#include + +#include "gtypes.h" + +//------------------------------------------------------------------------ +// SplashGlyphBitmap +//------------------------------------------------------------------------ + +struct SplashGlyphBitmap { + int x, y, w, h; // offset and size of glyph + GBool aa; // anti-aliased: true means 8-bit alpha + // bitmap; false means 1-bit + Guchar *data; // bitmap data + GBool freeData; // true if data memory should be freed +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Splash.h swftools-0.9.1/lib/pdf/xpdf/Splash.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Splash.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Splash.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,293 @@ +//======================================================================== +// +// Splash.h +// +//======================================================================== + +#ifndef SPLASH_H +#define SPLASH_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" +#include "SplashClip.h" + +class Splash; +class SplashBitmap; +struct SplashGlyphBitmap; +class SplashState; +class SplashPattern; +class SplashScreen; +class SplashPath; +class SplashXPath; +class SplashFont; +struct SplashPipe; + +//------------------------------------------------------------------------ + +// Retrieves the next line of pixels in an image mask. Normally, +// fills in * and returns true. If the image stream is +// exhausted, returns false. +typedef GBool (*SplashImageMaskSource)(void *data, SplashColorPtr pixel); + +// Retrieves the next line of pixels in an image. Normally, fills in +// * and returns true. If the image stream is exhausted, +// returns false. +typedef GBool (*SplashImageSource)(void *data, SplashColorPtr colorLine, + Guchar *alphaLine); + +//------------------------------------------------------------------------ + +enum SplashPipeResultColorCtrl { +#if SPLASH_CMYK + splashPipeResultColorNoAlphaBlendCMYK, +#endif + splashPipeResultColorNoAlphaBlendRGB, + splashPipeResultColorNoAlphaBlendMono, + splashPipeResultColorAlphaNoBlendMono, + splashPipeResultColorAlphaNoBlendRGB, +#if SPLASH_CMYK + splashPipeResultColorAlphaNoBlendCMYK, +#endif + splashPipeResultColorAlphaBlendMono, + splashPipeResultColorAlphaBlendRGB +#if SPLASH_CMYK + , + splashPipeResultColorAlphaBlendCMYK +#endif +}; + +//------------------------------------------------------------------------ +// Splash +//------------------------------------------------------------------------ + +class Splash { +public: + + // Create a new rasterizer object. + Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, + SplashScreenParams *screenParams = NULL); + Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, + SplashScreen *screenA); + + ~Splash(); + + //----- state read + + SplashCoord *getMatrix(); + SplashPattern *getStrokePattern(); + SplashPattern *getFillPattern(); + SplashScreen *getScreen(); + SplashBlendFunc getBlendFunc(); + SplashCoord getStrokeAlpha(); + SplashCoord getFillAlpha(); + SplashCoord getLineWidth(); + int getLineCap(); + int getLineJoin(); + SplashCoord getMiterLimit(); + SplashCoord getFlatness(); + SplashCoord *getLineDash(); + int getLineDashLength(); + SplashCoord getLineDashPhase(); + SplashClip *getClip(); + SplashBitmap *getSoftMask(); + GBool getInNonIsolatedGroup(); + + //----- state write + + void setMatrix(SplashCoord *matrix); + void setStrokePattern(SplashPattern *strokeColor); + void setFillPattern(SplashPattern *fillColor); + void setScreen(SplashScreen *screen); + void setBlendFunc(SplashBlendFunc func); + void setStrokeAlpha(SplashCoord alpha); + void setFillAlpha(SplashCoord alpha); + void setLineWidth(SplashCoord lineWidth); + void setLineCap(int lineCap); + void setLineJoin(int lineJoin); + void setMiterLimit(SplashCoord miterLimit); + void setFlatness(SplashCoord flatness); + // the array will be copied + void setLineDash(SplashCoord *lineDash, int lineDashLength, + SplashCoord lineDashPhase); + void setStrokeAdjust(GBool strokeAdjust); + // NB: uses transformed coordinates. + void clipResetToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1); + // NB: uses transformed coordinates. + SplashError clipToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1); + // NB: uses untransformed coordinates. + SplashError clipToPath(SplashPath *path, GBool eo); + void setSoftMask(SplashBitmap *softMask); + void setInNonIsolatedGroup(SplashBitmap *alpha0BitmapA, + int alpha0XA, int alpha0YA); + + //----- state save/restore + + void saveState(); + SplashError restoreState(); + + //----- drawing operations + + // Fill the bitmap with . This is not subject to clipping. + void clear(SplashColorPtr color, Guchar alpha = 0x00); + + // Stroke a path using the current stroke pattern. + SplashError stroke(SplashPath *path); + + // Fill a path using the current fill pattern. + SplashError fill(SplashPath *path, GBool eo); + + // Fill a path, XORing with the current fill pattern. + SplashError xorFill(SplashPath *path, GBool eo); + + // Draw a character, using the current fill pattern. + SplashError fillChar(SplashCoord x, SplashCoord y, int c, SplashFont *font); + + // Draw a glyph, using the current fill pattern. This function does + // not free any data, i.e., it ignores glyph->freeData. + SplashError fillGlyph(SplashCoord x, SplashCoord y, + SplashGlyphBitmap *glyph); + + // Draws an image mask using the fill color. This will read + // lines of pixels from , starting with the top line. "1" + // pixels will be drawn with the current fill color; "0" pixels are + // transparent. The matrix: + // [ mat[0] mat[1] 0 ] + // [ mat[2] mat[3] 0 ] + // [ mat[4] mat[5] 1 ] + // maps a unit square to the desired destination for the image, in + // PostScript style: + // [x' y' 1] = [x y 1] * mat + // Note that the Splash y axis points downward, and the image source + // is assumed to produce pixels in raster order, starting from the + // top line. + SplashError fillImageMask(SplashImageMaskSource src, void *srcData, + int w, int h, SplashCoord *mat, + GBool glyphMode); + + // Draw an image. This will read lines of pixels from + // , starting with the top line. These pixels are assumed to + // be in the source mode, . If is true, the + // alpha values returned by are used; otherwise they are + // ignored. The following combinations of source and target modes + // are supported: + // source target + // ------ ------ + // Mono1 Mono1 + // Mono8 Mono1 -- with dithering + // Mono8 Mono8 + // RGB8 RGB8 + // BGR8 BGR8 + // CMYK8 CMYK8 + // The matrix behaves as for fillImageMask. + SplashError drawImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, GBool srcAlpha, + int w, int h, SplashCoord *mat); + + // Composite a rectangular region from onto this Splash + // object. + SplashError composite(SplashBitmap *src, int xSrc, int ySrc, + int xDest, int yDest, int w, int h, + GBool noClip, GBool nonIsolated); + + // Composite this Splash object onto a background color. The + // background alpha is assumed to be 1. + void compositeBackground(SplashColorPtr color); + + // Copy a rectangular region from onto the bitmap belonging to + // this Splash object. The destination alpha values are all set to + // zero. + SplashError blitTransparent(SplashBitmap *src, int xSrc, int ySrc, + int xDest, int yDest, int w, int h); + + //----- misc + + // Construct a path for a stroke, given the path to be stroked, and + // using the current line parameters. If is true, this + // function will first flatten the path and handle the linedash. + SplashPath *makeStrokePath(SplashPath *path, GBool flatten = gTrue); + + // Return the associated bitmap. + SplashBitmap *getBitmap() { return bitmap; } + + // Get a bounding box which includes all modifications since the + // last call to clearModRegion. + void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax) + { *xMin = modXMin; *yMin = modYMin; *xMax = modXMax; *yMax = modYMax; } + + // Clear the modified region bounding box. + void clearModRegion(); + + // Get clipping status for the last drawing operation subject to + // clipping. + SplashClipResult getClipRes() { return opClipRes; } + + // Toggle debug mode on or off. + void setDebugMode(GBool debugModeA) { debugMode = debugModeA; } + +#if 1 //~tmp: turn off anti-aliasing temporarily + GBool getVectorAntialias() { return vectorAntialias; } + void setVectorAntialias(GBool vaa) { vectorAntialias = vaa; } +#endif + +private: + + void pipeInit(SplashPipe *pipe, int x, int y, + SplashPattern *pattern, SplashColorPtr cSrc, + SplashCoord aInput, GBool usesShape, + GBool nonIsolatedGroup); + void pipeRun(SplashPipe *pipe); + void pipeSetXY(SplashPipe *pipe, int x, int y); + void pipeIncX(SplashPipe *pipe); + void drawPixel(SplashPipe *pipe, int x, int y, GBool noClip); + void drawAAPixelInit(); + void drawAAPixel(SplashPipe *pipe, int x, int y); + void drawSpan(SplashPipe *pipe, int x0, int x1, int y, GBool noClip); + void drawAALine(SplashPipe *pipe, int x0, int x1, int y); + void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi, + SplashCoord *xo, SplashCoord *yo); + void updateModX(int x); + void updateModY(int y); + void strokeNarrow(SplashPath *path); + void strokeWide(SplashPath *path); + SplashPath *flattenPath(SplashPath *path, SplashCoord *matrix, + SplashCoord flatness); + void flattenCurve(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + SplashCoord x2, SplashCoord y2, + SplashCoord x3, SplashCoord y3, + SplashCoord *matrix, SplashCoord flatness2, + SplashPath *fPath); + SplashPath *makeDashedPath(SplashPath *xPath); + SplashError fillWithPattern(SplashPath *path, GBool eo, + SplashPattern *pattern, SplashCoord alpha); + SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph); + void dumpPath(SplashPath *path); + void dumpXPath(SplashXPath *path); + + static SplashPipeResultColorCtrl pipeResultColorNoAlphaBlend[]; + static SplashPipeResultColorCtrl pipeResultColorAlphaNoBlend[]; + static SplashPipeResultColorCtrl pipeResultColorAlphaBlend[]; + static int pipeNonIsoGroupCorrection[]; + + SplashBitmap *bitmap; + SplashState *state; + SplashBitmap *aaBuf; + int aaBufY; + SplashBitmap *alpha0Bitmap; // for non-isolated groups, this is the + // bitmap containing the alpha0 values + int alpha0X, alpha0Y; // offset within alpha0Bitmap + SplashCoord aaGamma[splashAASize * splashAASize + 1]; + int modXMin, modYMin, modXMax, modYMax; + SplashClipResult opClipRes; + GBool vectorAntialias; + GBool debugMode; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashMath.h swftools-0.9.1/lib/pdf/xpdf/SplashMath.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashMath.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashMath.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,89 @@ +//======================================================================== +// +// SplashMath.h +// +//======================================================================== + +#ifndef SPLASHMATH_H +#define SPLASHMATH_H + +#include +#if USE_FIXEDPONT +#include "FixedPoint.h" +#else +#include +#endif +#include "SplashTypes.h" + +static inline SplashCoord splashAbs(SplashCoord x) { +#if USE_FIXEDPOINT + return FixedPoint::abs(x); +#else + return fabs(x); +#endif +} + +static inline int splashFloor(SplashCoord x) { +#if USE_FIXEDPOINT + return FixedPoint::floor(x); +#else + return (int)floor(x); +#endif +} + +static inline int splashCeil(SplashCoord x) { +#if USE_FIXEDPOINT + return FixedPoint::ceil(x); +#else + return (int)ceil(x); +#endif +} + +static inline int splashRound(SplashCoord x) { +#if USE_FIXEDPOINT + return FixedPoint::round(x); +#else + return (int)floor(x + 0.5); +#endif +} + +static inline SplashCoord splashSqrt(SplashCoord x) { +#if USE_FIXEDPOINT + return FixedPoint::sqrt(x); +#else + return sqrt(x); +#endif +} + +static inline SplashCoord splashPow(SplashCoord x, SplashCoord y) { +#if USE_FIXEDPOINT + return FixedPoint::pow(x, y); +#else + return pow(x, y); +#endif +} + +static inline SplashCoord splashDist(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1) { + SplashCoord dx, dy; + dx = x1 - x0; + dy = y1 - y0; +#if USE_FIXEDPOINT + // this handles the situation where dx*dx or dy*dy is too large to + // fit in the 16.16 fixed point format + SplashCoord dxa, dya; + dxa = splashAbs(dx); + dya = splashAbs(dy); + if (dxa == 0 && dya == 0) { + return 0; + } else if (dxa > dya) { + return dxa * FixedPoint::sqrt(dya / dxa + 1); + } else { + return dya * FixedPoint::sqrt(dxa / dya + 1); + } +#else + return sqrt(dx * dx + dy * dy); +#endif +} + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashOutputDev.cc swftools-0.9.1/lib/pdf/xpdf/SplashOutputDev.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashOutputDev.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashOutputDev.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,2846 @@ +//======================================================================== +// +// SplashOutputDev.cc +// +// Copyright 2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include "gfile.h" +#include "GlobalParams.h" +#include "Error.h" +#include "Object.h" +#include "GfxFont.h" +#include "Link.h" +#include "CharCodeToUnicode.h" +#include "FontEncodingTables.h" +#include "FoFiTrueType.h" +#include "SplashBitmap.h" +#include "SplashGlyphBitmap.h" +#include "SplashPattern.h" +#include "SplashScreen.h" +#include "SplashPath.h" +#include "SplashState.h" +#include "SplashErrorCodes.h" +#include "SplashFontEngine.h" +#include "SplashFont.h" +#include "SplashFontFile.h" +#include "SplashFontFileID.h" +#include "Splash.h" +#include "SplashOutputDev.h" + +#ifdef VMS +#if (__VMS_VER < 70000000) +extern "C" int unlink(char *filename); +#endif +#endif + +//------------------------------------------------------------------------ + +// Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result. +static inline Guchar div255(int x) { + return (Guchar)((x + (x >> 8) + 0x80) >> 8); +} + +//------------------------------------------------------------------------ +// Blend functions +//------------------------------------------------------------------------ + +static void splashOutBlendMultiply(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = (dest[i] * src[i]) / 255; + } +} + +static void splashOutBlendScreen(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = dest[i] + src[i] - (dest[i] * src[i]) / 255; + } +} + +static void splashOutBlendOverlay(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = dest[i] < 0x80 + ? (src[i] * 2 * dest[i]) / 255 + : 255 - 2 * ((255 - src[i]) * (255 - dest[i])) / 255; + } +} + +static void splashOutBlendDarken(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = dest[i] < src[i] ? dest[i] : src[i]; + } +} + +static void splashOutBlendLighten(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = dest[i] > src[i] ? dest[i] : src[i]; + } +} + +static void splashOutBlendColorDodge(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, + SplashColorMode cm) { + int i, x; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + if (src[i] == 255) { + blend[i] = 255; + } else { + x = (dest[i] * 255) / (255 - src[i]); + blend[i] = x <= 255 ? x : 255; + } + } +} + +static void splashOutBlendColorBurn(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i, x; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + if (src[i] == 0) { + blend[i] = 0; + } else { + x = ((255 - dest[i]) * 255) / src[i]; + blend[i] = x <= 255 ? 255 - x : 0; + } + } +} + +static void splashOutBlendHardLight(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = src[i] < 0x80 + ? (dest[i] * 2 * src[i]) / 255 + : 255 - 2 * ((255 - dest[i]) * (255 - src[i])) / 255; + } +} + +static void splashOutBlendSoftLight(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i, x; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + if (src[i] < 0x80) { + blend[i] = dest[i] - (255 - 2 * src[i]) * dest[i] * (255 - dest[i]) / + (255 * 255); + } else { + if (dest[i] < 0x40) { + x = (((((16 * dest[i] - 12 * 255) * dest[i]) / 255) + + 4 * 255) * dest[i]) / 255; + } else { + x = (int)sqrt(255.0 * dest[i]); + } + blend[i] = dest[i] + (2 * src[i] - 255) * (x - dest[i]) / 255; + } + } +} + +static void splashOutBlendDifference(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, + SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = dest[i] < src[i] ? src[i] - dest[i] : dest[i] - src[i]; + } +} + +static void splashOutBlendExclusion(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int i; + + for (i = 0; i < splashColorModeNComps[cm]; ++i) { + blend[i] = dest[i] + src[i] - (2 * dest[i] * src[i]) / 255; + } +} + +static void cvtRGBToHSV(Guchar r, Guchar g, Guchar b, int *h, int *s, int *v) { + int cmax, cmid, cmin, x; + + if (r >= g) { + if (g >= b) { x = 0; cmax = r; cmid = g; cmin = b; } + else if (b >= r) { x = 4; cmax = b; cmid = r; cmin = g; } + else { x = 5; cmax = r; cmid = b; cmin = g; } + } else { + if (r >= b) { x = 1; cmax = g; cmid = r; cmin = b; } + else if (g >= b) { x = 2; cmax = g; cmid = b; cmin = r; } + else { x = 3; cmax = b; cmid = g; cmin = r; } + } + if (cmax == cmin) { + *h = *s = 0; + } else { + *h = x * 60; + if (x & 1) { + *h += ((cmax - cmid) * 60) / (cmax - cmin); + } else { + *h += ((cmid - cmin) * 60) / (cmax - cmin); + } + *s = (255 * (cmax - cmin)) / cmax; + } + *v = cmax; +} + +static void cvtHSVToRGB(int h, int s, int v, Guchar *r, Guchar *g, Guchar *b) { + int x, f, cmax, cmid, cmin; + + if (s == 0) { + *r = *g = *b = v; + } else { + x = h / 60; + f = h % 60; + cmax = v; + if (x & 1) { + cmid = div255(v * 255 - ((s * f) / 60)); + } else { + cmid = div255(v * (255 - ((s * (60 - f)) / 60))); + } + cmin = div255(v * (255 - s)); + switch (x) { + case 0: *r = cmax; *g = cmid; *b = cmin; break; + case 1: *g = cmax; *r = cmid; *b = cmin; break; + case 2: *g = cmax; *b = cmid; *r = cmin; break; + case 3: *b = cmax; *g = cmid; *r = cmin; break; + case 4: *b = cmax; *r = cmid; *g = cmin; break; + case 5: *r = cmax; *b = cmid; *g = cmin; break; + } + } +} + +static void splashOutBlendHue(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int hs, ss, vs, hd, sd, vd; +#if SPLASH_CMYK + Guchar r, g, b; +#endif + + switch (cm) { + case splashModeMono1: + case splashModeMono8: + blend[0] = dest[0]; + break; + case splashModeRGB8: + case splashModeBGR8: + cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs); + cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd); + cvtHSVToRGB(hs, sd, vd, &blend[0], &blend[1], &blend[2]); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + //~ (0xff - ...) should be clipped + cvtRGBToHSV(0xff - (src[0] + src[3]), + 0xff - (src[1] + src[3]), + 0xff - (src[2] + src[3]), &hs, &ss, &vs); + cvtRGBToHSV(0xff - (dest[0] + dest[3]), + 0xff - (dest[1] + dest[3]), + 0xff - (dest[2] + dest[3]), &hd, &sd, &vd); + cvtHSVToRGB(hs, sd, vd, &r, &g, &b); + //~ should do black generation + blend[0] = 0xff - r; + blend[1] = 0xff - g; + blend[2] = 0xff - b; + blend[3] = 0; + break; +#endif + } +} + +static void splashOutBlendSaturation(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, + SplashColorMode cm) { + int hs, ss, vs, hd, sd, vd; +#if SPLASH_CMYK + Guchar r, g, b; +#endif + + switch (cm) { + case splashModeMono1: + case splashModeMono8: + blend[0] = dest[0]; + break; + case splashModeRGB8: + case splashModeBGR8: + cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs); + cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd); + cvtHSVToRGB(hd, ss, vd, &blend[0], &blend[1], &blend[2]); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + //~ (0xff - ...) should be clipped + cvtRGBToHSV(0xff - (src[0] + src[3]), + 0xff - (src[1] + src[3]), + 0xff - (src[2] + src[3]), &hs, &ss, &vs); + cvtRGBToHSV(0xff - (dest[0] + dest[3]), + 0xff - (dest[1] + dest[3]), + 0xff - (dest[2] + dest[3]), &hd, &sd, &vd); + cvtHSVToRGB(hd, ss, vd, &r, &g, &b); + //~ should do black generation + blend[0] = 0xff - r; + blend[1] = 0xff - g; + blend[2] = 0xff - b; + blend[3] = 0; + break; +#endif + } +} + +static void splashOutBlendColor(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm) { + int hs, ss, vs, hd, sd, vd; +#if SPLASH_CMYK + Guchar r, g, b; +#endif + + switch (cm) { + case splashModeMono1: + case splashModeMono8: + blend[0] = dest[0]; + break; + case splashModeRGB8: + case splashModeBGR8: + cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs); + cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd); + cvtHSVToRGB(hs, ss, vd, &blend[0], &blend[1], &blend[2]); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + //~ (0xff - ...) should be clipped + cvtRGBToHSV(0xff - (src[0] + src[3]), + 0xff - (src[1] + src[3]), + 0xff - (src[2] + src[3]), &hs, &ss, &vs); + cvtRGBToHSV(0xff - (dest[0] + dest[3]), + 0xff - (dest[1] + dest[3]), + 0xff - (dest[2] + dest[3]), &hd, &sd, &vd); + cvtHSVToRGB(hs, ss, vd, &r, &g, &b); + //~ should do black generation + blend[0] = 0xff - r; + blend[1] = 0xff - g; + blend[2] = 0xff - b; + blend[3] = 0; + break; +#endif + } +} + +static void splashOutBlendLuminosity(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, + SplashColorMode cm) { + int hs, ss, vs, hd, sd, vd; +#if SPLASH_CMYK + Guchar r, g, b; +#endif + + switch (cm) { + case splashModeMono1: + case splashModeMono8: + blend[0] = dest[0]; + break; + case splashModeRGB8: + case splashModeBGR8: + cvtRGBToHSV(src[0], src[1], src[2], &hs, &ss, &vs); + cvtRGBToHSV(dest[0], dest[1], dest[2], &hd, &sd, &vd); + cvtHSVToRGB(hd, sd, vs, &blend[0], &blend[1], &blend[2]); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + //~ (0xff - ...) should be clipped + cvtRGBToHSV(0xff - (src[0] + src[3]), + 0xff - (src[1] + src[3]), + 0xff - (src[2] + src[3]), &hs, &ss, &vs); + cvtRGBToHSV(0xff - (dest[0] + dest[3]), + 0xff - (dest[1] + dest[3]), + 0xff - (dest[2] + dest[3]), &hd, &sd, &vd); + cvtHSVToRGB(hd, sd, vs, &r, &g, &b); + //~ should do black generation + blend[0] = 0xff - r; + blend[1] = 0xff - g; + blend[2] = 0xff - b; + blend[3] = 0; + break; +#endif + } +} + +// NB: This must match the GfxBlendMode enum defined in GfxState.h. +SplashBlendFunc splashOutBlendFuncs[] = { + NULL, + &splashOutBlendMultiply, + &splashOutBlendScreen, + &splashOutBlendOverlay, + &splashOutBlendDarken, + &splashOutBlendLighten, + &splashOutBlendColorDodge, + &splashOutBlendColorBurn, + &splashOutBlendHardLight, + &splashOutBlendSoftLight, + &splashOutBlendDifference, + &splashOutBlendExclusion, + &splashOutBlendHue, + &splashOutBlendSaturation, + &splashOutBlendColor, + &splashOutBlendLuminosity +}; + +//------------------------------------------------------------------------ +// Font substitutions +//------------------------------------------------------------------------ + +struct SplashOutFontSubst { + char *name; + double mWidth; +}; + +// index: {symbolic:12, fixed:8, serif:4, sans-serif:0} + bold*2 + italic +static SplashOutFontSubst splashOutSubstFonts[16] = { + {"Helvetica", 0.833}, + {"Helvetica-Oblique", 0.833}, + {"Helvetica-Bold", 0.889}, + {"Helvetica-BoldOblique", 0.889}, + {"Times-Roman", 0.788}, + {"Times-Italic", 0.722}, + {"Times-Bold", 0.833}, + {"Times-BoldItalic", 0.778}, + {"Courier", 0.600}, + {"Courier-Oblique", 0.600}, + {"Courier-Bold", 0.600}, + {"Courier-BoldOblique", 0.600}, + {"Symbol", 0.576}, + {"Symbol", 0.576}, + {"Symbol", 0.576}, + {"Symbol", 0.576} +}; + +//------------------------------------------------------------------------ +// SplashOutFontFileID +//------------------------------------------------------------------------ + +class SplashOutFontFileID: public SplashFontFileID { +public: + + SplashOutFontFileID(Ref *rA) { r = *rA; substIdx = -1; } + + ~SplashOutFontFileID() {} + + GBool matches(SplashFontFileID *id) { + return ((SplashOutFontFileID *)id)->r.num == r.num && + ((SplashOutFontFileID *)id)->r.gen == r.gen; + } + + void setSubstIdx(int substIdxA) { substIdx = substIdxA; } + int getSubstIdx() { return substIdx; } + +private: + + Ref r; + int substIdx; +}; + +//------------------------------------------------------------------------ +// T3FontCache +//------------------------------------------------------------------------ + +struct T3FontCacheTag { + Gushort code; + Gushort mru; // valid bit (0x8000) and MRU index +}; + +class T3FontCache { +public: + + T3FontCache(Ref *fontID, double m11A, double m12A, + double m21A, double m22A, + int glyphXA, int glyphYA, int glyphWA, int glyphHA, + GBool aa, GBool validBBoxA); + ~T3FontCache(); + GBool matches(Ref *idA, double m11A, double m12A, + double m21A, double m22A) + { return fontID.num == idA->num && fontID.gen == idA->gen && + m11 == m11A && m12 == m12A && m21 == m21A && m22 == m22A; } + + Ref fontID; // PDF font ID + double m11, m12, m21, m22; // transform matrix + int glyphX, glyphY; // pixel offset of glyph bitmaps + int glyphW, glyphH; // size of glyph bitmaps, in pixels + GBool validBBox; // false if the bbox was [0 0 0 0] + int glyphSize; // size of glyph bitmaps, in bytes + int cacheSets; // number of sets in cache + int cacheAssoc; // cache associativity (glyphs per set) + Guchar *cacheData; // glyph pixmap cache + T3FontCacheTag *cacheTags; // cache tags, i.e., char codes +}; + +T3FontCache::T3FontCache(Ref *fontIDA, double m11A, double m12A, + double m21A, double m22A, + int glyphXA, int glyphYA, int glyphWA, int glyphHA, + GBool validBBoxA, GBool aa) { + int i; + + fontID = *fontIDA; + m11 = m11A; + m12 = m12A; + m21 = m21A; + m22 = m22A; + glyphX = glyphXA; + glyphY = glyphYA; + glyphW = glyphWA; + glyphH = glyphHA; + validBBox = validBBoxA; + if (aa) { + glyphSize = glyphW * glyphH; + } else { + glyphSize = ((glyphW + 7) >> 3) * glyphH; + } + cacheAssoc = 8; + if (glyphSize <= 256) { + cacheSets = 8; + } else if (glyphSize <= 512) { + cacheSets = 4; + } else if (glyphSize <= 1024) { + cacheSets = 2; + } else { + cacheSets = 1; + } + cacheData = (Guchar *)gmallocn(cacheSets * cacheAssoc, glyphSize); + cacheTags = (T3FontCacheTag *)gmallocn(cacheSets * cacheAssoc, + sizeof(T3FontCacheTag)); + for (i = 0; i < cacheSets * cacheAssoc; ++i) { + cacheTags[i].mru = i & (cacheAssoc - 1); + } +} + +T3FontCache::~T3FontCache() { + gfree(cacheData); + gfree(cacheTags); +} + +struct T3GlyphStack { + Gushort code; // character code + + //----- cache info + T3FontCache *cache; // font cache for the current font + T3FontCacheTag *cacheTag; // pointer to cache tag for the glyph + Guchar *cacheData; // pointer to cache data for the glyph + + //----- saved state + SplashBitmap *origBitmap; + Splash *origSplash; + double origCTM4, origCTM5; + + T3GlyphStack *next; // next object on stack +}; + +//------------------------------------------------------------------------ +// SplashTransparencyGroup +//------------------------------------------------------------------------ + +struct SplashTransparencyGroup { + int tx, ty; // translation coordinates + SplashBitmap *tBitmap; // bitmap for transparency group + GfxColorSpace *blendingColorSpace; + GBool isolated; + + //----- saved state + SplashBitmap *origBitmap; + Splash *origSplash; + + SplashTransparencyGroup *next; +}; + +//------------------------------------------------------------------------ +// SplashOutputDev +//------------------------------------------------------------------------ + +SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA, + int bitmapRowPadA, + GBool reverseVideoA, + SplashColorPtr paperColorA, + GBool bitmapTopDownA, + GBool allowAntialiasA) { + colorMode = colorModeA; + bitmapRowPad = bitmapRowPadA; + bitmapTopDown = bitmapTopDownA; + allowAntialias = allowAntialiasA; + vectorAntialias = allowAntialias && + globalParams->getVectorAntialias() && + colorMode != splashModeMono1; + setupScreenParams(72.0, 72.0); + reverseVideo = reverseVideoA; + splashColorCopy(paperColor, paperColorA); + + xref = NULL; + + bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode, + colorMode != splashModeMono1, bitmapTopDown); + splash = new Splash(bitmap, vectorAntialias, &screenParams); + splash->clear(paperColor, 0); + + fontEngine = NULL; + + nT3Fonts = 0; + t3GlyphStack = NULL; + + font = NULL; + needFontUpdate = gFalse; + textClipPath = NULL; + + transpGroupStack = NULL; +} + +void SplashOutputDev::setupScreenParams(double hDPI, double vDPI) { + screenParams.size = globalParams->getScreenSize(); + screenParams.dotRadius = globalParams->getScreenDotRadius(); + screenParams.gamma = (SplashCoord)globalParams->getScreenGamma(); + screenParams.blackThreshold = + (SplashCoord)globalParams->getScreenBlackThreshold(); + screenParams.whiteThreshold = + (SplashCoord)globalParams->getScreenWhiteThreshold(); + switch (globalParams->getScreenType()) { + case screenDispersed: + screenParams.type = splashScreenDispersed; + if (screenParams.size < 0) { + screenParams.size = 4; + } + break; + case screenClustered: + screenParams.type = splashScreenClustered; + if (screenParams.size < 0) { + screenParams.size = 10; + } + break; + case screenStochasticClustered: + screenParams.type = splashScreenStochasticClustered; + if (screenParams.size < 0) { + screenParams.size = 100; + } + if (screenParams.dotRadius < 0) { + screenParams.dotRadius = 2; + } + break; + case screenUnset: + default: + // use clustered dithering for resolution >= 300 dpi + // (compare to 299.9 to avoid floating point issues) + if (hDPI > 299.9 && vDPI > 299.9) { + screenParams.type = splashScreenStochasticClustered; + if (screenParams.size < 0) { + screenParams.size = 100; + } + if (screenParams.dotRadius < 0) { + screenParams.dotRadius = 2; + } + } else { + screenParams.type = splashScreenDispersed; + if (screenParams.size < 0) { + screenParams.size = 4; + } + } + } +} + +SplashOutputDev::~SplashOutputDev() { + int i; + + for (i = 0; i < nT3Fonts; ++i) { + delete t3FontCache[i]; + } + if (fontEngine) { + delete fontEngine; + } + if (splash) { + delete splash; + } + if (bitmap) { + delete bitmap; + } +} + +void SplashOutputDev::startDoc(XRef *xrefA) { + int i; + + xref = xrefA; + if (fontEngine) { + delete fontEngine; + } + fontEngine = new SplashFontEngine( +#if HAVE_T1LIB_H + globalParams->getEnableT1lib(), +#endif +#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H + globalParams->getEnableFreeType(), +#endif + allowAntialias && + globalParams->getAntialias() && + colorMode != splashModeMono1); + for (i = 0; i < nT3Fonts; ++i) { + delete t3FontCache[i]; + } + nT3Fonts = 0; +} + +void SplashOutputDev::startPage(int pageNum, GfxState *state) { + int w, h; + double *ctm; + SplashCoord mat[6]; + SplashColor color; + + if (state) { + setupScreenParams(state->getHDPI(), state->getVDPI()); + w = (int)(state->getPageWidth() + 0.5); + if (w <= 0) { + w = 1; + } + h = (int)(state->getPageHeight() + 0.5); + if (h <= 0) { + h = 1; + } + } else { + w = h = 1; + } + if (splash) { + delete splash; + } + if (!bitmap || w != bitmap->getWidth() || h != bitmap->getHeight()) { + if (bitmap) { + delete bitmap; + } + bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, + colorMode != splashModeMono1, bitmapTopDown); + } + splash = new Splash(bitmap, vectorAntialias, &screenParams); + if (state) { + ctm = state->getCTM(); + mat[0] = (SplashCoord)ctm[0]; + mat[1] = (SplashCoord)ctm[1]; + mat[2] = (SplashCoord)ctm[2]; + mat[3] = (SplashCoord)ctm[3]; + mat[4] = (SplashCoord)ctm[4]; + mat[5] = (SplashCoord)ctm[5]; + splash->setMatrix(mat); + } + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + color[0] = 0; + break; + case splashModeRGB8: + case splashModeBGR8: + color[0] = color[1] = color[2] = 0; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + color[0] = color[1] = color[2] = color[3] = 0; + break; +#endif + } + splash->setStrokePattern(new SplashSolidColor(color)); + splash->setFillPattern(new SplashSolidColor(color)); + splash->setLineCap(splashLineCapButt); + splash->setLineJoin(splashLineJoinMiter); + splash->setLineDash(NULL, 0, 0); + splash->setMiterLimit(10); + splash->setFlatness(1); + // the SA parameter supposedly defaults to false, but Acrobat + // apparently hardwires it to true + splash->setStrokeAdjust(globalParams->getStrokeAdjust()); + splash->clear(paperColor, 0); +} + +void SplashOutputDev::endPage() { + if (colorMode != splashModeMono1) { + splash->compositeBackground(paperColor); + } +} + +void SplashOutputDev::saveState(GfxState *state) { + splash->saveState(); +} + +void SplashOutputDev::restoreState(GfxState *state) { + splash->restoreState(); + needFontUpdate = gTrue; +} + +void SplashOutputDev::updateAll(GfxState *state) { + updateLineDash(state); + updateLineJoin(state); + updateLineCap(state); + updateLineWidth(state); + updateFlatness(state); + updateMiterLimit(state); + updateStrokeAdjust(state); + updateFillColor(state); + updateStrokeColor(state); + needFontUpdate = gTrue; +} + +void SplashOutputDev::updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, + double m31, double m32) { + double *ctm; + SplashCoord mat[6]; + + ctm = state->getCTM(); + mat[0] = (SplashCoord)ctm[0]; + mat[1] = (SplashCoord)ctm[1]; + mat[2] = (SplashCoord)ctm[2]; + mat[3] = (SplashCoord)ctm[3]; + mat[4] = (SplashCoord)ctm[4]; + mat[5] = (SplashCoord)ctm[5]; + splash->setMatrix(mat); +} + +void SplashOutputDev::updateLineDash(GfxState *state) { + double *dashPattern; + int dashLength; + double dashStart; + SplashCoord dash[20]; + int i; + + state->getLineDash(&dashPattern, &dashLength, &dashStart); + if (dashLength > 20) { + dashLength = 20; + } + for (i = 0; i < dashLength; ++i) { + dash[i] = (SplashCoord)dashPattern[i]; + if (dash[i] < 0) { + dash[i] = 0; + } + } + splash->setLineDash(dash, dashLength, (SplashCoord)dashStart); +} + +void SplashOutputDev::updateFlatness(GfxState *state) { + splash->setFlatness(state->getFlatness()); +} + +void SplashOutputDev::updateLineJoin(GfxState *state) { + splash->setLineJoin(state->getLineJoin()); +} + +void SplashOutputDev::updateLineCap(GfxState *state) { + splash->setLineCap(state->getLineCap()); +} + +void SplashOutputDev::updateMiterLimit(GfxState *state) { + splash->setMiterLimit(state->getMiterLimit()); +} + +void SplashOutputDev::updateLineWidth(GfxState *state) { + splash->setLineWidth(state->getLineWidth()); +} + +void SplashOutputDev::updateStrokeAdjust(GfxState *state) { +#if 0 // the SA parameter supposedly defaults to false, but Acrobat + // apparently hardwires it to true + splash->setStrokeAdjust(state->getStrokeAdjust()); +#endif +} + +void SplashOutputDev::updateFillColor(GfxState *state) { + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + + state->getFillGray(&gray); + state->getFillRGB(&rgb); +#if SPLASH_CMYK + state->getFillCMYK(&cmyk); + splash->setFillPattern(getColor(gray, &rgb, &cmyk)); +#else + splash->setFillPattern(getColor(gray, &rgb)); +#endif +} + +void SplashOutputDev::updateStrokeColor(GfxState *state) { + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + + state->getStrokeGray(&gray); + state->getStrokeRGB(&rgb); +#if SPLASH_CMYK + state->getStrokeCMYK(&cmyk); + splash->setStrokePattern(getColor(gray, &rgb, &cmyk)); +#else + splash->setStrokePattern(getColor(gray, &rgb)); +#endif +} + +#if SPLASH_CMYK +SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb, + GfxCMYK *cmyk) { +#else +SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb) { +#endif + SplashPattern *pattern; + SplashColor color; + GfxColorComp r, g, b; + + if (reverseVideo) { + gray = gfxColorComp1 - gray; + r = gfxColorComp1 - rgb->r; + g = gfxColorComp1 - rgb->g; + b = gfxColorComp1 - rgb->b; + } else { + r = rgb->r; + g = rgb->g; + b = rgb->b; + } + + pattern = NULL; // make gcc happy + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + color[0] = colToByte(gray); + pattern = new SplashSolidColor(color); + break; + case splashModeRGB8: + case splashModeBGR8: + color[0] = colToByte(r); + color[1] = colToByte(g); + color[2] = colToByte(b); + pattern = new SplashSolidColor(color); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + color[0] = colToByte(cmyk->c); + color[1] = colToByte(cmyk->m); + color[2] = colToByte(cmyk->y); + color[3] = colToByte(cmyk->k); + pattern = new SplashSolidColor(color); + break; +#endif + } + + return pattern; +} + +void SplashOutputDev::updateBlendMode(GfxState *state) { + splash->setBlendFunc(splashOutBlendFuncs[state->getBlendMode()]); +} + +void SplashOutputDev::updateFillOpacity(GfxState *state) { + splash->setFillAlpha((SplashCoord)state->getFillOpacity()); +} + +void SplashOutputDev::updateStrokeOpacity(GfxState *state) { + splash->setStrokeAlpha((SplashCoord)state->getStrokeOpacity()); +} + +void SplashOutputDev::updateFont(GfxState *state) { + needFontUpdate = gTrue; +} + +void SplashOutputDev::doUpdateFont(GfxState *state) { + GfxFont *gfxFont; + GfxFontType fontType; + SplashOutFontFileID *id; + SplashFontFile *fontFile; + FoFiTrueType *ff; + Ref embRef; + Object refObj, strObj; + GString *tmpFileName, *fileName, *substName; + FILE *tmpFile; + Gushort *codeToGID; + DisplayFontParam *dfp; + CharCodeToUnicode *ctu; + double *textMat; + double m11, m12, m21, m22, w1, w2, fontSize; + SplashCoord mat[4]; + char *name; + Unicode uBuf[8]; + int c, substIdx, n, code, cmap; + + needFontUpdate = gFalse; + font = NULL; + tmpFileName = NULL; + substIdx = -1; + dfp = NULL; + + if (!(gfxFont = state->getFont())) { + goto err1; + } + fontType = gfxFont->getType(); + if (fontType == fontType3) { + goto err1; + } + + // check the font file cache + id = new SplashOutFontFileID(gfxFont->getID()); + if ((fontFile = fontEngine->getFontFile(id))) { + delete id; + + } else { + + // if there is an embedded font, write it to disk + if (gfxFont->getEmbeddedFontID(&embRef)) { + if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { + error(-1, "Couldn't create temporary font file"); + goto err2; + } + refObj.initRef(embRef.num, embRef.gen); + refObj.fetch(xref, &strObj); + refObj.free(); + if (!strObj.isStream()) { + error(-1, "Embedded font object is wrong type"); + strObj.free(); + fclose(tmpFile); + goto err2; + } + strObj.streamReset(); + while ((c = strObj.streamGetChar()) != EOF) { + fputc(c, tmpFile); + } + strObj.streamClose(); + strObj.free(); + fclose(tmpFile); + fileName = tmpFileName; + + // if there is an external font file, use it + } else if (!(fileName = gfxFont->getExtFontFile())) { + + // look for a display font mapping or a substitute font + if (gfxFont->isCIDFont()) { + if (((GfxCIDFont *)gfxFont)->getCollection()) { + dfp = globalParams-> + getDisplayCIDFont(gfxFont->getName(), + ((GfxCIDFont *)gfxFont)->getCollection()); + } + } else { + if (gfxFont->getName()) { + dfp = globalParams->getDisplayFont(gfxFont->getName()); + } + if (!dfp) { + // 8-bit font substitution + if (gfxFont->isFixedWidth()) { + substIdx = 8; + } else if (gfxFont->isSerif()) { + substIdx = 4; + } else { + substIdx = 0; + } + if (gfxFont->isBold()) { + substIdx += 2; + } + if (gfxFont->isItalic()) { + substIdx += 1; + } + substName = new GString(splashOutSubstFonts[substIdx].name); + dfp = globalParams->getDisplayFont(substName); + delete substName; + id->setSubstIdx(substIdx); + } + } + if (!dfp) { + error(-1, "Couldn't find a font for '%s'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + goto err2; + } + switch (dfp->kind) { + case displayFontT1: + fileName = dfp->t1.fileName; + fontType = gfxFont->isCIDFont() ? fontCIDType0 : fontType1; + break; + case displayFontTT: + fileName = dfp->tt.fileName; + fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType; + break; + } + } + + // load the font file + switch (fontType) { + case fontType1: + if (!(fontFile = fontEngine->loadType1Font( + id, + fileName->getCString(), + fileName == tmpFileName, + ((Gfx8BitFont *)gfxFont)->getEncoding()))) { + error(-1, "Couldn't create a font for '%s'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + goto err2; + } + break; + case fontType1C: + if (!(fontFile = fontEngine->loadType1CFont( + id, + fileName->getCString(), + fileName == tmpFileName, + ((Gfx8BitFont *)gfxFont)->getEncoding()))) { + error(-1, "Couldn't create a font for '%s'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + goto err2; + } + break; + case fontType1COT: + if (!(fontFile = fontEngine->loadOpenTypeT1CFont( + id, + fileName->getCString(), + fileName == tmpFileName, + ((Gfx8BitFont *)gfxFont)->getEncoding()))) { + error(-1, "Couldn't create a font for '%s'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + goto err2; + } + break; + case fontTrueType: + case fontTrueTypeOT: + if ((ff = FoFiTrueType::load(fileName->getCString()))) { + codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff); + n = 256; + delete ff; + } else { + codeToGID = NULL; + n = 0; + } + if (!(fontFile = fontEngine->loadTrueTypeFont( + id, + fileName->getCString(), + fileName == tmpFileName, + codeToGID, n))) { + error(-1, "Couldn't create a font for '%s'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + goto err2; + } + break; + case fontCIDType0: + case fontCIDType0C: + if (!(fontFile = fontEngine->loadCIDFont( + id, + fileName->getCString(), + fileName == tmpFileName))) { + error(-1, "Couldn't create a font for '%s'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + goto err2; + } + break; + case fontCIDType0COT: + if (!(fontFile = fontEngine->loadOpenTypeCFFFont( + id, + fileName->getCString(), + fileName == tmpFileName))) { + error(-1, "Couldn't create a font for '%s'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + goto err2; + } + break; + case fontCIDType2: + case fontCIDType2OT: + codeToGID = NULL; + n = 0; + if (dfp) { + // create a CID-to-GID mapping, via Unicode + if ((ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) { + if ((ff = FoFiTrueType::load(fileName->getCString()))) { + // look for a Unicode cmap + for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) { + if ((ff->getCmapPlatform(cmap) == 3 && + ff->getCmapEncoding(cmap) == 1) || + ff->getCmapPlatform(cmap) == 0) { + break; + } + } + if (cmap < ff->getNumCmaps()) { + // map CID -> Unicode -> GID + n = ctu->getLength(); + codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort)); + for (code = 0; code < n; ++code) { + if (ctu->mapToUnicode(code, uBuf, 8) > 0) { + codeToGID[code] = ff->mapCodeToGID(cmap, uBuf[0]); + } else { + codeToGID[code] = 0; + } + } + } + delete ff; + } + ctu->decRefCnt(); + } else { + error(-1, "Couldn't find a mapping to Unicode for font '%s'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + } + } else { + if (((GfxCIDFont *)gfxFont)->getCIDToGID()) { + n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen(); + codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort)); + memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(), + n * sizeof(Gushort)); + } + } + if (!(fontFile = fontEngine->loadTrueTypeFont( + id, + fileName->getCString(), + fileName == tmpFileName, + codeToGID, n))) { + error(-1, "Couldn't create a font for '%s'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); + goto err2; + } + break; + default: + // this shouldn't happen + goto err2; + } + } + + // get the font matrix + textMat = state->getTextMat(); + fontSize = state->getFontSize(); + m11 = textMat[0] * fontSize * state->getHorizScaling(); + m12 = textMat[1] * fontSize * state->getHorizScaling(); + m21 = textMat[2] * fontSize; + m22 = textMat[3] * fontSize; + + // for substituted fonts: adjust the font matrix -- compare the + // width of 'm' in the original font and the substituted font + substIdx = ((SplashOutFontFileID *)fontFile->getID())->getSubstIdx(); + if (substIdx >= 0) { + for (code = 0; code < 256; ++code) { + if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) && + name[0] == 'm' && name[1] == '\0') { + break; + } + } + if (code < 256) { + w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code); + w2 = splashOutSubstFonts[substIdx].mWidth; + if (!gfxFont->isSymbolic()) { + // if real font is substantially narrower than substituted + // font, reduce the font size accordingly + if (w1 > 0.01 && w1 < 0.9 * w2) { + w1 /= w2; + m11 *= w1; + m21 *= w1; + } + } + } + } + + // create the scaled font + mat[0] = m11; mat[1] = m12; + mat[2] = m21; mat[3] = m22; + font = fontEngine->getFont(fontFile, mat, splash->getMatrix()); + + if (tmpFileName) { + delete tmpFileName; + } + return; + + err2: + delete id; + err1: + if (tmpFileName) { + unlink(tmpFileName->getCString()); + delete tmpFileName; + } + return; +} + +void SplashOutputDev::stroke(GfxState *state) { + SplashPath *path; + + if (state->getStrokeColorSpace()->isNonMarking()) { + return; + } + path = convertPath(state, state->getPath()); + splash->stroke(path); + delete path; +} + +void SplashOutputDev::fill(GfxState *state) { + SplashPath *path; + + if (state->getFillColorSpace()->isNonMarking()) { + return; + } + path = convertPath(state, state->getPath()); + splash->fill(path, gFalse); + delete path; +} + +void SplashOutputDev::eoFill(GfxState *state) { + SplashPath *path; + + if (state->getFillColorSpace()->isNonMarking()) { + return; + } + path = convertPath(state, state->getPath()); + splash->fill(path, gTrue); + delete path; +} + +void SplashOutputDev::clip(GfxState *state) { + SplashPath *path; + + path = convertPath(state, state->getPath()); + splash->clipToPath(path, gFalse); + delete path; +} + +void SplashOutputDev::eoClip(GfxState *state) { + SplashPath *path; + + path = convertPath(state, state->getPath()); + splash->clipToPath(path, gTrue); + delete path; +} + +void SplashOutputDev::clipToStrokePath(GfxState *state) { + SplashPath *path, *path2; + + path = convertPath(state, state->getPath()); + path2 = splash->makeStrokePath(path); + delete path; + splash->clipToPath(path2, gFalse); + delete path2; +} + +SplashPath *SplashOutputDev::convertPath(GfxState *state, GfxPath *path) { + SplashPath *sPath; + GfxSubpath *subpath; + int i, j; + + sPath = new SplashPath(); + for (i = 0; i < path->getNumSubpaths(); ++i) { + subpath = path->getSubpath(i); + if (subpath->getNumPoints() > 0) { + sPath->moveTo((SplashCoord)subpath->getX(0), + (SplashCoord)subpath->getY(0)); + j = 1; + while (j < subpath->getNumPoints()) { + if (subpath->getCurve(j)) { + sPath->curveTo((SplashCoord)subpath->getX(j), + (SplashCoord)subpath->getY(j), + (SplashCoord)subpath->getX(j+1), + (SplashCoord)subpath->getY(j+1), + (SplashCoord)subpath->getX(j+2), + (SplashCoord)subpath->getY(j+2)); + j += 3; + } else { + sPath->lineTo((SplashCoord)subpath->getX(j), + (SplashCoord)subpath->getY(j)); + ++j; + } + } + if (subpath->isClosed()) { + sPath->close(); + } + } + } + return sPath; +} + +void SplashOutputDev::drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, + Unicode *u, int uLen) { + SplashPath *path; + int render; + + // check for invisible text -- this is used by Acrobat Capture + render = state->getRender(); + if (render == 3) { + return; + } + + if (needFontUpdate) { + doUpdateFont(state); + } + if (!font) { + return; + } + + x -= originX; + y -= originY; + + // fill + if (!(render & 1)) { + if (!state->getFillColorSpace()->isNonMarking()) { + splash->fillChar((SplashCoord)x, (SplashCoord)y, code, font); + } + } + + // stroke + if ((render & 3) == 1 || (render & 3) == 2) { + if (!state->getStrokeColorSpace()->isNonMarking()) { + if ((path = font->getGlyphPath(code))) { + path->offset((SplashCoord)x, (SplashCoord)y); + splash->stroke(path); + delete path; + } + } + } + + // clip + if (render & 4) { + if ((path = font->getGlyphPath(code))) { + path->offset((SplashCoord)x, (SplashCoord)y); + if (textClipPath) { + textClipPath->append(path); + delete path; + } else { + textClipPath = path; + } + } + } +} + +GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen) { + GfxFont *gfxFont; + Ref *fontID; + double *ctm, *bbox; + T3FontCache *t3Font; + T3GlyphStack *t3gs; + GBool validBBox; + double x1, y1, xMin, yMin, xMax, yMax, xt, yt; + int i, j; + + if (!(gfxFont = state->getFont())) { + return gFalse; + } + fontID = gfxFont->getID(); + ctm = state->getCTM(); + state->transform(0, 0, &xt, &yt); + + // is it the first (MRU) font in the cache? + if (!(nT3Fonts > 0 && + t3FontCache[0]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3]))) { + + // is the font elsewhere in the cache? + for (i = 1; i < nT3Fonts; ++i) { + if (t3FontCache[i]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3])) { + t3Font = t3FontCache[i]; + for (j = i; j > 0; --j) { + t3FontCache[j] = t3FontCache[j - 1]; + } + t3FontCache[0] = t3Font; + break; + } + } + if (i >= nT3Fonts) { + + // create new entry in the font cache + if (nT3Fonts == splashOutT3FontCacheSize) { + delete t3FontCache[nT3Fonts - 1]; + --nT3Fonts; + } + for (j = nT3Fonts; j > 0; --j) { + t3FontCache[j] = t3FontCache[j - 1]; + } + ++nT3Fonts; + bbox = gfxFont->getFontBBox(); + if (bbox[0] == 0 && bbox[1] == 0 && bbox[2] == 0 && bbox[3] == 0) { + // unspecified bounding box -- just take a guess + xMin = xt - 5; + xMax = xMin + 30; + yMax = yt + 15; + yMin = yMax - 45; + validBBox = gFalse; + } else { + state->transform(bbox[0], bbox[1], &x1, &y1); + xMin = xMax = x1; + yMin = yMax = y1; + state->transform(bbox[0], bbox[3], &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + state->transform(bbox[2], bbox[1], &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + state->transform(bbox[2], bbox[3], &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + validBBox = gTrue; + } + t3FontCache[0] = new T3FontCache(fontID, ctm[0], ctm[1], ctm[2], ctm[3], + (int)floor(xMin - xt), + (int)floor(yMin - yt), + (int)ceil(xMax) - (int)floor(xMin) + 3, + (int)ceil(yMax) - (int)floor(yMin) + 3, + validBBox, + colorMode != splashModeMono1); + } + } + t3Font = t3FontCache[0]; + + // is the glyph in the cache? + i = (code & (t3Font->cacheSets - 1)) * t3Font->cacheAssoc; + for (j = 0; j < t3Font->cacheAssoc; ++j) { + if ((t3Font->cacheTags[i+j].mru & 0x8000) && + t3Font->cacheTags[i+j].code == code) { + drawType3Glyph(t3Font, &t3Font->cacheTags[i+j], + t3Font->cacheData + (i+j) * t3Font->glyphSize); + return gTrue; + } + } + + // push a new Type 3 glyph record + t3gs = new T3GlyphStack(); + t3gs->next = t3GlyphStack; + t3GlyphStack = t3gs; + t3GlyphStack->code = code; + t3GlyphStack->cache = t3Font; + t3GlyphStack->cacheTag = NULL; + t3GlyphStack->cacheData = NULL; + + return gFalse; +} + +void SplashOutputDev::endType3Char(GfxState *state) { + T3GlyphStack *t3gs; + double *ctm; + + if (t3GlyphStack->cacheTag) { + memcpy(t3GlyphStack->cacheData, bitmap->getDataPtr(), + t3GlyphStack->cache->glyphSize); + delete bitmap; + delete splash; + bitmap = t3GlyphStack->origBitmap; + splash = t3GlyphStack->origSplash; + ctm = state->getCTM(); + state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3], + t3GlyphStack->origCTM4, t3GlyphStack->origCTM5); + updateCTM(state, 0, 0, 0, 0, 0, 0); + drawType3Glyph(t3GlyphStack->cache, + t3GlyphStack->cacheTag, t3GlyphStack->cacheData); + } + t3gs = t3GlyphStack; + t3GlyphStack = t3gs->next; + delete t3gs; +} + +void SplashOutputDev::type3D0(GfxState *state, double wx, double wy) { +} + +void SplashOutputDev::type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury) { + double *ctm; + T3FontCache *t3Font; + SplashColor color; + double xt, yt, xMin, xMax, yMin, yMax, x1, y1; + int i, j; + + t3Font = t3GlyphStack->cache; + + // check for a valid bbox + state->transform(0, 0, &xt, &yt); + state->transform(llx, lly, &x1, &y1); + xMin = xMax = x1; + yMin = yMax = y1; + state->transform(llx, ury, &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + state->transform(urx, lly, &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + state->transform(urx, ury, &x1, &y1); + if (x1 < xMin) { + xMin = x1; + } else if (x1 > xMax) { + xMax = x1; + } + if (y1 < yMin) { + yMin = y1; + } else if (y1 > yMax) { + yMax = y1; + } + if (xMin - xt < t3Font->glyphX || + yMin - yt < t3Font->glyphY || + xMax - xt > t3Font->glyphX + t3Font->glyphW || + yMax - yt > t3Font->glyphY + t3Font->glyphH) { + if (t3Font->validBBox) { + error(-1, "Bad bounding box in Type 3 glyph"); + } + return; + } + + // allocate a cache entry + i = (t3GlyphStack->code & (t3Font->cacheSets - 1)) * t3Font->cacheAssoc; + for (j = 0; j < t3Font->cacheAssoc; ++j) { + if ((t3Font->cacheTags[i+j].mru & 0x7fff) == t3Font->cacheAssoc - 1) { + t3Font->cacheTags[i+j].mru = 0x8000; + t3Font->cacheTags[i+j].code = t3GlyphStack->code; + t3GlyphStack->cacheTag = &t3Font->cacheTags[i+j]; + t3GlyphStack->cacheData = t3Font->cacheData + (i+j) * t3Font->glyphSize; + } else { + ++t3Font->cacheTags[i+j].mru; + } + } + + // save state + t3GlyphStack->origBitmap = bitmap; + t3GlyphStack->origSplash = splash; + ctm = state->getCTM(); + t3GlyphStack->origCTM4 = ctm[4]; + t3GlyphStack->origCTM5 = ctm[5]; + + // create the temporary bitmap + if (colorMode == splashModeMono1) { + bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1, + splashModeMono1, gFalse); + splash = new Splash(bitmap, gFalse, + t3GlyphStack->origSplash->getScreen()); + color[0] = 0; + splash->clear(color); + color[0] = 1; + } else { + bitmap = new SplashBitmap(t3Font->glyphW, t3Font->glyphH, 1, + splashModeMono8, gFalse); + splash = new Splash(bitmap, vectorAntialias, + t3GlyphStack->origSplash->getScreen()); + color[0] = 0x00; + splash->clear(color); + color[0] = 0xff; + } + splash->setFillPattern(new SplashSolidColor(color)); + splash->setStrokePattern(new SplashSolidColor(color)); + //~ this should copy other state from t3GlyphStack->origSplash? + state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3], + -t3Font->glyphX, -t3Font->glyphY); + updateCTM(state, 0, 0, 0, 0, 0, 0); +} + +void SplashOutputDev::drawType3Glyph(T3FontCache *t3Font, + T3FontCacheTag *tag, Guchar *data) { + SplashGlyphBitmap glyph; + + glyph.x = -t3Font->glyphX; + glyph.y = -t3Font->glyphY; + glyph.w = t3Font->glyphW; + glyph.h = t3Font->glyphH; + glyph.aa = colorMode != splashModeMono1; + glyph.data = data; + glyph.freeData = gFalse; + splash->fillGlyph(0, 0, &glyph); +} + +void SplashOutputDev::endTextObject(GfxState *state) { + if (textClipPath) { + splash->clipToPath(textClipPath, gFalse); + delete textClipPath; + textClipPath = NULL; + } +} + +struct SplashOutImageMaskData { + ImageStream *imgStr; + GBool invert; + int width, height, y; +}; + +GBool SplashOutputDev::imageMaskSrc(void *data, SplashColorPtr line) { + SplashOutImageMaskData *imgMaskData = (SplashOutImageMaskData *)data; + Guchar *p; + SplashColorPtr q; + int x; + + if (imgMaskData->y == imgMaskData->height) { + return gFalse; + } + for (x = 0, p = imgMaskData->imgStr->getLine(), q = line; + x < imgMaskData->width; + ++x) { + *q++ = *p++ ^ imgMaskData->invert; + } + ++imgMaskData->y; + return gTrue; +} + +void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg) { + double *ctm; + SplashCoord mat[6]; + SplashOutImageMaskData imgMaskData; + + if (state->getFillColorSpace()->isNonMarking()) { + return; + } + + ctm = state->getCTM(); + mat[0] = ctm[0]; + mat[1] = ctm[1]; + mat[2] = -ctm[2]; + mat[3] = -ctm[3]; + mat[4] = ctm[2] + ctm[4]; + mat[5] = ctm[3] + ctm[5]; + + imgMaskData.imgStr = new ImageStream(str, width, 1, 1); + imgMaskData.imgStr->reset(); + imgMaskData.invert = invert ? 0 : 1; + imgMaskData.width = width; + imgMaskData.height = height; + imgMaskData.y = 0; + + splash->fillImageMask(&imageMaskSrc, &imgMaskData, width, height, mat, + t3GlyphStack != NULL); + if (inlineImg) { + while (imgMaskData.y < height) { + imgMaskData.imgStr->getLine(); + ++imgMaskData.y; + } + } + + delete imgMaskData.imgStr; + str->close(); +} + +struct SplashOutImageData { + ImageStream *imgStr; + GfxImageColorMap *colorMap; + SplashColorPtr lookup; + int *maskColors; + SplashColorMode colorMode; + int width, height, y; +}; + +GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine, + Guchar *alphaLine) { + SplashOutImageData *imgData = (SplashOutImageData *)data; + Guchar *p; + SplashColorPtr q, col; + GfxRGB rgb; + GfxGray gray; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + int nComps, x; + + if (imgData->y == imgData->height) { + return gFalse; + } + + nComps = imgData->colorMap->getNumPixelComps(); + + if (imgData->lookup) { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + for (x = 0, p = imgData->imgStr->getLine(), q = colorLine; + x < imgData->width; + ++x, ++p) { + *q++ = imgData->lookup[*p]; + } + break; + case splashModeRGB8: + case splashModeBGR8: + for (x = 0, p = imgData->imgStr->getLine(), q = colorLine; + x < imgData->width; + ++x, ++p) { + col = &imgData->lookup[3 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + for (x = 0, p = imgData->imgStr->getLine(), q = colorLine; + x < imgData->width; + ++x, ++p) { + col = &imgData->lookup[4 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + *q++ = col[3]; + } + break; +#endif + } + } else { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + for (x = 0, p = imgData->imgStr->getLine(), q = colorLine; + x < imgData->width; + ++x, p += nComps) { + imgData->colorMap->getGray(p, &gray); + *q++ = colToByte(gray); + } + break; + case splashModeRGB8: + case splashModeBGR8: + for (x = 0, p = imgData->imgStr->getLine(), q = colorLine; + x < imgData->width; + ++x, p += nComps) { + imgData->colorMap->getRGB(p, &rgb); + *q++ = colToByte(rgb.r); + *q++ = colToByte(rgb.g); + *q++ = colToByte(rgb.b); + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + for (x = 0, p = imgData->imgStr->getLine(), q = colorLine; + x < imgData->width; + ++x, p += nComps) { + imgData->colorMap->getCMYK(p, &cmyk); + *q++ = colToByte(cmyk.c); + *q++ = colToByte(cmyk.m); + *q++ = colToByte(cmyk.y); + *q++ = colToByte(cmyk.k); + } + break; +#endif + } + } + + ++imgData->y; + return gTrue; +} + +GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine, + Guchar *alphaLine) { + SplashOutImageData *imgData = (SplashOutImageData *)data; + Guchar *p, *aq; + SplashColorPtr q, col; + GfxRGB rgb; + GfxGray gray; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + Guchar alpha; + int nComps, x, i; + + if (imgData->y == imgData->height) { + return gFalse; + } + + nComps = imgData->colorMap->getNumPixelComps(); + + for (x = 0, p = imgData->imgStr->getLine(), q = colorLine, aq = alphaLine; + x < imgData->width; + ++x, p += nComps) { + alpha = 0; + for (i = 0; i < nComps; ++i) { + if (p[i] < imgData->maskColors[2*i] || + p[i] > imgData->maskColors[2*i+1]) { + alpha = 0xff; + break; + } + } + if (imgData->lookup) { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + *q++ = imgData->lookup[*p]; + *aq++ = alpha; + break; + case splashModeRGB8: + case splashModeBGR8: + col = &imgData->lookup[3 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + *aq++ = alpha; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + col = &imgData->lookup[4 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + *q++ = col[3]; + *aq++ = alpha; + break; +#endif + } + } else { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData->colorMap->getGray(p, &gray); + *q++ = colToByte(gray); + *aq++ = alpha; + break; + case splashModeRGB8: + case splashModeBGR8: + imgData->colorMap->getRGB(p, &rgb); + *q++ = colToByte(rgb.r); + *q++ = colToByte(rgb.g); + *q++ = colToByte(rgb.b); + *aq++ = alpha; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData->colorMap->getCMYK(p, &cmyk); + *q++ = colToByte(cmyk.c); + *q++ = colToByte(cmyk.m); + *q++ = colToByte(cmyk.y); + *q++ = colToByte(cmyk.k); + *aq++ = alpha; + break; +#endif + } + } + } + + ++imgData->y; + return gTrue; +} + +void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg) { + double *ctm; + SplashCoord mat[6]; + SplashOutImageData imgData; + SplashColorMode srcMode; + SplashImageSource src; + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + Guchar pix; + int n, i; + + ctm = state->getCTM(); + mat[0] = ctm[0]; + mat[1] = ctm[1]; + mat[2] = -ctm[2]; + mat[3] = -ctm[3]; + mat[4] = ctm[2] + ctm[4]; + mat[5] = ctm[3] + ctm[5]; + + imgData.imgStr = new ImageStream(str, width, + colorMap->getNumPixelComps(), + colorMap->getBits()); + imgData.imgStr->reset(); + imgData.colorMap = colorMap; + imgData.maskColors = maskColors; + imgData.colorMode = colorMode; + imgData.width = width; + imgData.height = height; + imgData.y = 0; + + // special case for one-channel (monochrome/gray/separation) images: + // build a lookup table here + imgData.lookup = NULL; + if (colorMap->getNumPixelComps() == 1) { + n = 1 << colorMap->getBits(); + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData.lookup = (SplashColorPtr)gmalloc(n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getGray(&pix, &gray); + imgData.lookup[i] = colToByte(gray); + } + break; + case splashModeRGB8: + case splashModeBGR8: + imgData.lookup = (SplashColorPtr)gmalloc(3 * n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getRGB(&pix, &rgb); + imgData.lookup[3*i] = colToByte(rgb.r); + imgData.lookup[3*i+1] = colToByte(rgb.g); + imgData.lookup[3*i+2] = colToByte(rgb.b); + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData.lookup = (SplashColorPtr)gmalloc(4 * n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getCMYK(&pix, &cmyk); + imgData.lookup[4*i] = colToByte(cmyk.c); + imgData.lookup[4*i+1] = colToByte(cmyk.m); + imgData.lookup[4*i+2] = colToByte(cmyk.y); + imgData.lookup[4*i+3] = colToByte(cmyk.k); + } + break; +#endif + break; + } + } + + if (colorMode == splashModeMono1) { + srcMode = splashModeMono8; + } else { + srcMode = colorMode; + } + src = maskColors ? &alphaImageSrc : &imageSrc; + splash->drawImage(src, &imgData, srcMode, maskColors ? gTrue : gFalse, + width, height, mat); + if (inlineImg) { + while (imgData.y < height) { + imgData.imgStr->getLine(); + ++imgData.y; + } + } + + gfree(imgData.lookup); + delete imgData.imgStr; + str->close(); +} + +struct SplashOutMaskedImageData { + ImageStream *imgStr; + GfxImageColorMap *colorMap; + SplashBitmap *mask; + SplashColorPtr lookup; + SplashColorMode colorMode; + int width, height, y; +}; + +GBool SplashOutputDev::maskedImageSrc(void *data, SplashColorPtr colorLine, + Guchar *alphaLine) { + SplashOutMaskedImageData *imgData = (SplashOutMaskedImageData *)data; + Guchar *p, *aq; + SplashColor maskColor; + SplashColorPtr q, col; + GfxRGB rgb; + GfxGray gray; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + Guchar alpha; + int nComps, x; + + if (imgData->y == imgData->height) { + return gFalse; + } + + nComps = imgData->colorMap->getNumPixelComps(); + + for (x = 0, p = imgData->imgStr->getLine(), q = colorLine, aq = alphaLine; + x < imgData->width; + ++x, p += nComps) { + imgData->mask->getPixel(x, imgData->y, maskColor); + alpha = maskColor[0] ? 0xff : 0x00; + if (imgData->lookup) { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + *q++ = imgData->lookup[*p]; + *aq++ = alpha; + break; + case splashModeRGB8: + case splashModeBGR8: + col = &imgData->lookup[3 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + *aq++ = alpha; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + col = &imgData->lookup[4 * *p]; + *q++ = col[0]; + *q++ = col[1]; + *q++ = col[2]; + *q++ = col[3]; + *aq++ = alpha; + break; +#endif + } + } else { + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData->colorMap->getGray(p, &gray); + *q++ = colToByte(gray); + *aq++ = alpha; + break; + case splashModeRGB8: + case splashModeBGR8: + imgData->colorMap->getRGB(p, &rgb); + *q++ = colToByte(rgb.r); + *q++ = colToByte(rgb.g); + *q++ = colToByte(rgb.b); + *aq++ = alpha; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData->colorMap->getCMYK(p, &cmyk); + *q++ = colToByte(cmyk.c); + *q++ = colToByte(cmyk.m); + *q++ = colToByte(cmyk.y); + *q++ = colToByte(cmyk.k); + *aq++ = alpha; + break; +#endif + } + } + } + + ++imgData->y; + return gTrue; +} + +void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref, + Stream *str, int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, int maskWidth, + int maskHeight, GBool maskInvert) { + GfxImageColorMap *maskColorMap; + Object maskDecode, decodeLow, decodeHigh; + double *ctm; + SplashCoord mat[6]; + SplashOutMaskedImageData imgData; + SplashOutImageMaskData imgMaskData; + SplashColorMode srcMode; + SplashBitmap *maskBitmap; + Splash *maskSplash; + SplashColor maskColor; + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + Guchar pix; + int n, i; + + // If the mask is higher resolution than the image, use + // drawSoftMaskedImage() instead. + if (maskWidth > width || maskHeight > height) { + decodeLow.initInt(maskInvert ? 0 : 1); + decodeHigh.initInt(maskInvert ? 1 : 0); + maskDecode.initArray(xref); + maskDecode.arrayAdd(&decodeLow); + maskDecode.arrayAdd(&decodeHigh); + maskColorMap = new GfxImageColorMap(1, &maskDecode, + new GfxDeviceGrayColorSpace()); + maskDecode.free(); + drawSoftMaskedImage(state, ref, str, width, height, colorMap, + maskStr, maskWidth, maskHeight, maskColorMap); + delete maskColorMap; + + } else { + + //----- scale the mask image to the same size as the source image + + mat[0] = (SplashCoord)width; + mat[1] = 0; + mat[2] = 0; + mat[3] = (SplashCoord)height; + mat[4] = 0; + mat[5] = 0; + imgMaskData.imgStr = new ImageStream(maskStr, maskWidth, 1, 1); + imgMaskData.imgStr->reset(); + imgMaskData.invert = maskInvert ? 0 : 1; + imgMaskData.width = maskWidth; + imgMaskData.height = maskHeight; + imgMaskData.y = 0; + maskBitmap = new SplashBitmap(width, height, 1, splashModeMono1, gFalse); + maskSplash = new Splash(maskBitmap, gFalse); + maskColor[0] = 0; + maskSplash->clear(maskColor); + maskColor[0] = 0xff; + maskSplash->setFillPattern(new SplashSolidColor(maskColor)); + maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData, + maskWidth, maskHeight, mat, gFalse); + delete imgMaskData.imgStr; + maskStr->close(); + delete maskSplash; + + //----- draw the source image + + ctm = state->getCTM(); + mat[0] = ctm[0]; + mat[1] = ctm[1]; + mat[2] = -ctm[2]; + mat[3] = -ctm[3]; + mat[4] = ctm[2] + ctm[4]; + mat[5] = ctm[3] + ctm[5]; + + imgData.imgStr = new ImageStream(str, width, + colorMap->getNumPixelComps(), + colorMap->getBits()); + imgData.imgStr->reset(); + imgData.colorMap = colorMap; + imgData.mask = maskBitmap; + imgData.colorMode = colorMode; + imgData.width = width; + imgData.height = height; + imgData.y = 0; + + // special case for one-channel (monochrome/gray/separation) images: + // build a lookup table here + imgData.lookup = NULL; + if (colorMap->getNumPixelComps() == 1) { + n = 1 << colorMap->getBits(); + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData.lookup = (SplashColorPtr)gmalloc(n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getGray(&pix, &gray); + imgData.lookup[i] = colToByte(gray); + } + break; + case splashModeRGB8: + case splashModeBGR8: + imgData.lookup = (SplashColorPtr)gmalloc(3 * n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getRGB(&pix, &rgb); + imgData.lookup[3*i] = colToByte(rgb.r); + imgData.lookup[3*i+1] = colToByte(rgb.g); + imgData.lookup[3*i+2] = colToByte(rgb.b); + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData.lookup = (SplashColorPtr)gmalloc(4 * n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getCMYK(&pix, &cmyk); + imgData.lookup[4*i] = colToByte(cmyk.c); + imgData.lookup[4*i+1] = colToByte(cmyk.m); + imgData.lookup[4*i+2] = colToByte(cmyk.y); + imgData.lookup[4*i+3] = colToByte(cmyk.k); + } + break; +#endif + } + } + + if (colorMode == splashModeMono1) { + srcMode = splashModeMono8; + } else { + srcMode = colorMode; + } + splash->drawImage(&maskedImageSrc, &imgData, srcMode, gTrue, + width, height, mat); + + delete maskBitmap; + gfree(imgData.lookup); + delete imgData.imgStr; + str->close(); + } +} + +void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, + Stream *str, int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap) { + double *ctm; + SplashCoord mat[6]; + SplashOutImageData imgData; + SplashOutImageData imgMaskData; + SplashColorMode srcMode; + SplashBitmap *maskBitmap; + Splash *maskSplash; + SplashColor maskColor; + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + Guchar pix; + int n, i; + + ctm = state->getCTM(); + mat[0] = ctm[0]; + mat[1] = ctm[1]; + mat[2] = -ctm[2]; + mat[3] = -ctm[3]; + mat[4] = ctm[2] + ctm[4]; + mat[5] = ctm[3] + ctm[5]; + + //----- set up the soft mask + + imgMaskData.imgStr = new ImageStream(maskStr, maskWidth, + maskColorMap->getNumPixelComps(), + maskColorMap->getBits()); + imgMaskData.imgStr->reset(); + imgMaskData.colorMap = maskColorMap; + imgMaskData.maskColors = NULL; + imgMaskData.colorMode = splashModeMono8; + imgMaskData.width = maskWidth; + imgMaskData.height = maskHeight; + imgMaskData.y = 0; + n = 1 << maskColorMap->getBits(); + imgMaskData.lookup = (SplashColorPtr)gmalloc(n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + maskColorMap->getGray(&pix, &gray); + imgMaskData.lookup[i] = colToByte(gray); + } + maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(), + 1, splashModeMono8, gFalse); + maskSplash = new Splash(maskBitmap, vectorAntialias); + maskColor[0] = 0; + maskSplash->clear(maskColor); + maskSplash->drawImage(&imageSrc, &imgMaskData, splashModeMono8, gFalse, + maskWidth, maskHeight, mat); + delete imgMaskData.imgStr; + maskStr->close(); + gfree(imgMaskData.lookup); + delete maskSplash; + splash->setSoftMask(maskBitmap); + + //----- draw the source image + + imgData.imgStr = new ImageStream(str, width, + colorMap->getNumPixelComps(), + colorMap->getBits()); + imgData.imgStr->reset(); + imgData.colorMap = colorMap; + imgData.maskColors = NULL; + imgData.colorMode = colorMode; + imgData.width = width; + imgData.height = height; + imgData.y = 0; + + // special case for one-channel (monochrome/gray/separation) images: + // build a lookup table here + imgData.lookup = NULL; + if (colorMap->getNumPixelComps() == 1) { + n = 1 << colorMap->getBits(); + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData.lookup = (SplashColorPtr)gmalloc(n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getGray(&pix, &gray); + imgData.lookup[i] = colToByte(gray); + } + break; + case splashModeRGB8: + case splashModeBGR8: + imgData.lookup = (SplashColorPtr)gmalloc(3 * n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getRGB(&pix, &rgb); + imgData.lookup[3*i] = colToByte(rgb.r); + imgData.lookup[3*i+1] = colToByte(rgb.g); + imgData.lookup[3*i+2] = colToByte(rgb.b); + } + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData.lookup = (SplashColorPtr)gmalloc(4 * n); + for (i = 0; i < n; ++i) { + pix = (Guchar)i; + colorMap->getCMYK(&pix, &cmyk); + imgData.lookup[4*i] = colToByte(cmyk.c); + imgData.lookup[4*i+1] = colToByte(cmyk.m); + imgData.lookup[4*i+2] = colToByte(cmyk.y); + imgData.lookup[4*i+3] = colToByte(cmyk.k); + } + break; +#endif + } + } + + if (colorMode == splashModeMono1) { + srcMode = splashModeMono8; + } else { + srcMode = colorMode; + } + splash->drawImage(&imageSrc, &imgData, srcMode, gFalse, width, height, mat); + + splash->setSoftMask(NULL); + gfree(imgData.lookup); + delete imgData.imgStr; + str->close(); +} + +void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask) { + SplashTransparencyGroup *transpGroup; + SplashColor color; + double xMin, yMin, xMax, yMax, x, y; + int tx, ty, w, h; + + // transform the bbox + state->transform(bbox[0], bbox[1], &x, &y); + xMin = xMax = x; + yMin = yMax = y; + state->transform(bbox[0], bbox[3], &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + state->transform(bbox[2], bbox[1], &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + state->transform(bbox[2], bbox[3], &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + tx = (int)floor(xMin); + if (tx < 0) { + tx = 0; + } else if (tx > bitmap->getWidth()) { + tx = bitmap->getWidth(); + } + ty = (int)floor(yMin); + if (ty < 0) { + ty = 0; + } else if (ty > bitmap->getHeight()) { + ty = bitmap->getHeight(); + } + w = (int)ceil(xMax) - tx + 1; + if (tx + w > bitmap->getWidth()) { + w = bitmap->getWidth() - tx; + } + if (w < 1) { + w = 1; + } + h = (int)ceil(yMax) - ty + 1; + if (ty + h > bitmap->getHeight()) { + h = bitmap->getHeight() - ty; + } + if (h < 1) { + h = 1; + } + + // push a new stack entry + transpGroup = new SplashTransparencyGroup(); + transpGroup->tx = tx; + transpGroup->ty = ty; + transpGroup->blendingColorSpace = blendingColorSpace; + transpGroup->isolated = isolated; + transpGroup->next = transpGroupStack; + transpGroupStack = transpGroup; + + // save state + transpGroup->origBitmap = bitmap; + transpGroup->origSplash = splash; + + //~ this ignores the blendingColorSpace arg + + // create the temporary bitmap + bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, gTrue, + bitmapTopDown); + splash = new Splash(bitmap, vectorAntialias, + transpGroup->origSplash->getScreen()); + if (isolated) { + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + color[0] = 0; + break; + case splashModeRGB8: + case splashModeBGR8: + color[0] = color[1] = color[2] = 0; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + color[0] = color[1] = color[2] = color[3] = 0; + break; +#endif + default: + // make gcc happy + break; + } + splash->clear(color, 0); + } else { + splash->blitTransparent(transpGroup->origBitmap, tx, ty, 0, 0, w, h); + splash->setInNonIsolatedGroup(transpGroup->origBitmap, tx, ty); + } + transpGroup->tBitmap = bitmap; + state->shiftCTM(-tx, -ty); + updateCTM(state, 0, 0, 0, 0, 0, 0); +} + +void SplashOutputDev::endTransparencyGroup(GfxState *state) { + double *ctm; + + // restore state + delete splash; + bitmap = transpGroupStack->origBitmap; + splash = transpGroupStack->origSplash; + ctm = state->getCTM(); + state->shiftCTM(transpGroupStack->tx, transpGroupStack->ty); + updateCTM(state, 0, 0, 0, 0, 0, 0); +} + +void SplashOutputDev::paintTransparencyGroup(GfxState *state, double *bbox) { + SplashBitmap *tBitmap; + SplashTransparencyGroup *transpGroup; + GBool isolated; + int tx, ty; + + tx = transpGroupStack->tx; + ty = transpGroupStack->ty; + tBitmap = transpGroupStack->tBitmap; + isolated = transpGroupStack->isolated; + + // paint the transparency group onto the parent bitmap + // - the clip path was set in the parent's state) + splash->composite(tBitmap, 0, 0, tx, ty, + tBitmap->getWidth(), tBitmap->getHeight(), + gFalse, !isolated); + + // pop the stack + transpGroup = transpGroupStack; + transpGroupStack = transpGroup->next; + delete transpGroup; + + delete tBitmap; +} + +void SplashOutputDev::setSoftMask(GfxState *state, double *bbox, + GBool alpha, Function *transferFunc, + GfxColor *backdropColor) { + SplashBitmap *softMask, *tBitmap; + Splash *tSplash; + SplashTransparencyGroup *transpGroup; + SplashColor color; + SplashColorPtr p; + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + double lum, lum2; + int tx, ty, x, y; + + tx = transpGroupStack->tx; + ty = transpGroupStack->ty; + tBitmap = transpGroupStack->tBitmap; + + // composite with backdrop color + if (!alpha && colorMode != splashModeMono1) { + //~ need to correctly handle the case where no blending color + //~ space is given + tSplash = new Splash(tBitmap, vectorAntialias, + transpGroupStack->origSplash->getScreen()); + if (transpGroupStack->blendingColorSpace) { + switch (colorMode) { + case splashModeMono1: + // transparency is not supported in mono1 mode + break; + case splashModeMono8: + transpGroupStack->blendingColorSpace->getGray(backdropColor, &gray); + color[0] = colToByte(gray); + tSplash->compositeBackground(color); + break; + case splashModeRGB8: + case splashModeBGR8: + transpGroupStack->blendingColorSpace->getRGB(backdropColor, &rgb); + color[0] = colToByte(rgb.r); + color[1] = colToByte(rgb.g); + color[2] = colToByte(rgb.b); + tSplash->compositeBackground(color); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + transpGroupStack->blendingColorSpace->getCMYK(backdropColor, &cmyk); + color[0] = colToByte(cmyk.c); + color[1] = colToByte(cmyk.m); + color[2] = colToByte(cmyk.y); + color[3] = colToByte(cmyk.k); + tSplash->compositeBackground(color); + break; +#endif + } + delete tSplash; + } + } + + softMask = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(), + 1, splashModeMono8, gFalse); + memset(softMask->getDataPtr(), 0x00, softMask->getRowSize()*softMask->getHeight()); + p = softMask->getDataPtr() + ty * softMask->getRowSize() + tx; + if (txgetWidth() && tygetHeight()) + for (y = 0; y < tBitmap->getHeight(); ++y) { + for (x = 0; x < tBitmap->getWidth(); ++x) { + tBitmap->getPixel(x, y, color); + if (alpha) { + //~ unimplemented + } else { + // convert to luminosity + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + lum = color[0] / 255.0; + break; + case splashModeRGB8: + case splashModeBGR8: + lum = (0.3 / 255.0) * color[0] + + (0.59 / 255.0) * color[1] + + (0.11 / 255.0) * color[2]; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + lum = (1 - color[4] / 255.0) + - (0.3 / 255.0) * color[0] + - (0.59 / 255.0) * color[1] + - (0.11 / 255.0) * color[2]; + if (lum < 0) { + lum = 0; + } + break; +#endif + } + if (transferFunc) { + transferFunc->transform(&lum, &lum2); + } else { + lum2 = lum; + } + p[x] = (int)(lum2 * 255.0 + 0.5); + } + } + p += softMask->getRowSize(); + } + splash->setSoftMask(softMask); + + // pop the stack + transpGroup = transpGroupStack; + transpGroupStack = transpGroup->next; + delete transpGroup; + + delete tBitmap; +} + +void SplashOutputDev::clearSoftMask(GfxState *state) { + splash->setSoftMask(NULL); +} + +void SplashOutputDev::setPaperColor(SplashColorPtr paperColorA) { + splashColorCopy(paperColor, paperColorA); +} + +int SplashOutputDev::getBitmapWidth() { + return bitmap->getWidth(); +} + +int SplashOutputDev::getBitmapHeight() { + return bitmap->getHeight(); +} + +SplashBitmap *SplashOutputDev::takeBitmap() { + SplashBitmap *ret; + + ret = bitmap; + bitmap = new SplashBitmap(1, 1, bitmapRowPad, colorMode, + colorMode != splashModeMono1, bitmapTopDown); + return ret; +} + +void SplashOutputDev::getModRegion(int *xMin, int *yMin, + int *xMax, int *yMax) { + splash->getModRegion(xMin, yMin, xMax, yMax); +} + +void SplashOutputDev::clearModRegion() { + splash->clearModRegion(); +} + +void SplashOutputDev::setFillColor(int r, int g, int b) { + GfxRGB rgb; + GfxGray gray; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + + rgb.r = byteToCol(r); + rgb.g = byteToCol(g); + rgb.b = byteToCol(b); + gray = (GfxColorComp)(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.g + 0.5); + if (gray > gfxColorComp1) { + gray = gfxColorComp1; + } +#if SPLASH_CMYK + cmyk.c = gfxColorComp1 - rgb.r; + cmyk.m = gfxColorComp1 - rgb.g; + cmyk.y = gfxColorComp1 - rgb.b; + cmyk.k = 0; + splash->setFillPattern(getColor(gray, &rgb, &cmyk)); +#else + splash->setFillPattern(getColor(gray, &rgb)); +#endif +} + +SplashFont *SplashOutputDev::getFont(GString *name, double *textMatA) { + DisplayFontParam *dfp; + Ref ref; + SplashOutFontFileID *id; + SplashFontFile *fontFile; + SplashFont *fontObj; + FoFiTrueType *ff; + Gushort *codeToGID; + Unicode u; + SplashCoord textMat[4]; + int cmap, i; + + for (i = 0; i < 16; ++i) { + if (!name->cmp(splashOutSubstFonts[i].name)) { + break; + } + } + if (i == 16) { + return NULL; + } + ref.num = i; + ref.gen = -1; + id = new SplashOutFontFileID(&ref); + + // check the font file cache + if ((fontFile = fontEngine->getFontFile(id))) { + delete id; + + // load the font file + } else { + dfp = globalParams->getDisplayFont(name); + if (dfp && dfp->kind == displayFontT1) { + fontFile = fontEngine->loadType1Font(id, dfp->t1.fileName->getCString(), + gFalse, winAnsiEncoding); + } else if (dfp && dfp->kind == displayFontTT) { + if (!(ff = FoFiTrueType::load(dfp->tt.fileName->getCString()))) { + return NULL; + } + for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) { + if ((ff->getCmapPlatform(cmap) == 3 && + ff->getCmapEncoding(cmap) == 1) || + ff->getCmapPlatform(cmap) == 0) { + break; + } + } + if (cmap == ff->getNumCmaps()) { + delete ff; + return NULL; + } + codeToGID = (Gushort *)gmallocn(256, sizeof(Gushort)); + for (i = 0; i < 256; ++i) { + codeToGID[i] = 0; + if (winAnsiEncoding[i] && + (u = globalParams->mapNameToUnicode(winAnsiEncoding[i]))) { + codeToGID[i] = ff->mapCodeToGID(cmap, u); + } + } + delete ff; + fontFile = fontEngine->loadTrueTypeFont(id, + dfp->tt.fileName->getCString(), + gFalse, codeToGID, 256); + } else { + return NULL; + } + } + + // create the scaled font + textMat[0] = (SplashCoord)textMatA[0]; + textMat[1] = (SplashCoord)textMatA[1]; + textMat[2] = (SplashCoord)textMatA[2]; + textMat[3] = (SplashCoord)textMatA[3]; + fontObj = fontEngine->getFont(fontFile, textMat, splash->getMatrix()); + + return fontObj; +} + +#if 1 //~tmp: turn off anti-aliasing temporarily +GBool SplashOutputDev::getVectorAntialias() { + return splash->getVectorAntialias(); +} + +void SplashOutputDev::setVectorAntialias(GBool vaa) { + splash->setVectorAntialias(vaa); +} +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashOutputDev.h swftools-0.9.1/lib/pdf/xpdf/SplashOutputDev.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashOutputDev.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashOutputDev.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,248 @@ +//======================================================================== +// +// SplashOutputDev.h +// +// Copyright 2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef SPLASHOUTPUTDEV_H +#define SPLASHOUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "SplashTypes.h" +#include "config.h" +#include "OutputDev.h" +#include "GfxState.h" + +class Gfx8BitFont; +class SplashBitmap; +class Splash; +class SplashPath; +class SplashPattern; +class SplashFontEngine; +class SplashFont; +class T3FontCache; +struct T3FontCacheTag; +struct T3GlyphStack; +struct SplashTransparencyGroup; + +//------------------------------------------------------------------------ + +// number of Type 3 fonts to cache +#define splashOutT3FontCacheSize 8 + +//------------------------------------------------------------------------ +// SplashOutputDev +//------------------------------------------------------------------------ + +class SplashOutputDev: public OutputDev { +public: + + // Constructor. + SplashOutputDev(SplashColorMode colorModeA, int bitmapRowPadA, + GBool reverseVideoA, SplashColorPtr paperColorA, + GBool bitmapTopDownA = gTrue, + GBool allowAntialiasA = gTrue); + + // Destructor. + virtual ~SplashOutputDev(); + + //----- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() { return gTrue; } + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() { return gTrue; } + + // Does this device use beginType3Char/endType3Char? Otherwise, + // text in Type 3 fonts will be drawn with drawChar/drawString. + virtual GBool interpretType3Chars() { return gTrue; } + + //----- initialization and control + + // Start a page. + virtual void startPage(int pageNum, GfxState *state); + + // End a page. + virtual void endPage(); + + //----- save/restore graphics state + virtual void saveState(GfxState *state); + virtual void restoreState(GfxState *state); + + //----- update graphics state + virtual void updateAll(GfxState *state); + virtual void updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32); + virtual void updateLineDash(GfxState *state); + virtual void updateFlatness(GfxState *state); + virtual void updateLineJoin(GfxState *state); + virtual void updateLineCap(GfxState *state); + virtual void updateMiterLimit(GfxState *state); + virtual void updateLineWidth(GfxState *state); + virtual void updateStrokeAdjust(GfxState *state); + virtual void updateFillColor(GfxState *state); + virtual void updateStrokeColor(GfxState *state); + virtual void updateBlendMode(GfxState *state); + virtual void updateFillOpacity(GfxState *state); + virtual void updateStrokeOpacity(GfxState *state); + + //----- update text state + virtual void updateFont(GfxState *state); + + //----- path painting + virtual void stroke(GfxState *state); + virtual void fill(GfxState *state); + virtual void eoFill(GfxState *state); + + //----- path clipping + virtual void clip(GfxState *state); + virtual void eoClip(GfxState *state); + virtual void clipToStrokePath(GfxState *state); + + //----- text drawing + virtual void drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, Unicode *u, int uLen); + virtual GBool beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen); + virtual void endType3Char(GfxState *state); + virtual void endTextObject(GfxState *state); + + //----- image drawing + virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, int maskWidth, int maskHeight, + GBool maskInvert); + virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap); + + //----- Type 3 font operators + virtual void type3D0(GfxState *state, double wx, double wy); + virtual void type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury); + + //----- transparency groups and soft masks + virtual void beginTransparencyGroup(GfxState *state, double *bbox, + GfxColorSpace *blendingColorSpace, + GBool isolated, GBool knockout, + GBool forSoftMask); + virtual void endTransparencyGroup(GfxState *state); + virtual void paintTransparencyGroup(GfxState *state, double *bbox); + virtual void setSoftMask(GfxState *state, double *bbox, GBool alpha, + Function *transferFunc, GfxColor *backdropColor); + virtual void clearSoftMask(GfxState *state); + + //----- special access + + // Called to indicate that a new PDF document has been loaded. + void startDoc(XRef *xrefA); + + void setPaperColor(SplashColorPtr paperColorA); + + GBool isReverseVideo() { return reverseVideo; } + void setReverseVideo(GBool reverseVideoA) { reverseVideo = reverseVideoA; } + + // Get the bitmap and its size. + SplashBitmap *getBitmap() { return bitmap; } + int getBitmapWidth(); + int getBitmapHeight(); + + // Returns the last rasterized bitmap, transferring ownership to the + // caller. + SplashBitmap *takeBitmap(); + + // Get the Splash object. + Splash *getSplash() { return splash; } + + // Get the modified region. + void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax); + + // Clear the modified region. + void clearModRegion(); + + // Set the Splash fill color. + void setFillColor(int r, int g, int b); + + // Get a font object for a Base-14 font, using the Latin-1 encoding. + SplashFont *getFont(GString *name, double *textMatA); + + SplashFont *getCurrentFont() { return font; } + +#if 1 //~tmp: turn off anti-aliasing temporarily + virtual GBool getVectorAntialias(); + virtual void setVectorAntialias(GBool vaa); +#endif + + void doUpdateFont(GfxState *state); + GBool needFontUpdate; // set when the font needs to be updated + + SplashPath *convertPath(GfxState *state, GfxPath *path); +private: + + void setupScreenParams(double hDPI, double vDPI); +#if SPLASH_CMYK + SplashPattern *getColor(GfxGray gray, GfxRGB *rgb, GfxCMYK *cmyk); +#else + SplashPattern *getColor(GfxGray gray, GfxRGB *rgb); +#endif + void drawType3Glyph(T3FontCache *t3Font, + T3FontCacheTag *tag, Guchar *data); + static GBool imageMaskSrc(void *data, SplashColorPtr line); + static GBool imageSrc(void *data, SplashColorPtr colorLine, + Guchar *alphaLine); + static GBool alphaImageSrc(void *data, SplashColorPtr line, + Guchar *alphaLine); + static GBool maskedImageSrc(void *data, SplashColorPtr line, + Guchar *alphaLine); + + SplashColorMode colorMode; + int bitmapRowPad; + GBool bitmapTopDown; + GBool allowAntialias; + GBool vectorAntialias; + GBool reverseVideo; // reverse video mode + SplashColor paperColor; // paper color + SplashScreenParams screenParams; + + XRef *xref; // xref table for current document + + SplashBitmap *bitmap; + Splash *splash; + SplashFontEngine *fontEngine; + + T3FontCache * // Type 3 font cache + t3FontCache[splashOutT3FontCacheSize]; + int nT3Fonts; // number of valid entries in t3FontCache + T3GlyphStack *t3GlyphStack; // Type 3 glyph context stack + + SplashFont *font; // current font + SplashPath *textClipPath; // clipping path built with text object + + SplashTransparencyGroup * // transparency group stack + transpGroupStack; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashPath.cc swftools-0.9.1/lib/pdf/xpdf/SplashPath.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashPath.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashPath.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,184 @@ +//======================================================================== +// +// SplashPath.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "SplashErrorCodes.h" +#include "SplashPath.h" + +//------------------------------------------------------------------------ +// SplashPath +//------------------------------------------------------------------------ + +// A path can be in three possible states: +// +// 1. no current point -- zero or more finished subpaths +// [curSubpath == length] +// +// 2. one point in subpath +// [curSubpath == length - 1] +// +// 3. open subpath with two or more points +// [curSubpath < length - 1] + +SplashPath::SplashPath() { + pts = NULL; + flags = NULL; + length = size = 0; + curSubpath = 0; + hints = NULL; + hintsLength = hintsSize = 0; +} + +SplashPath::SplashPath(SplashPath *path) { + length = path->length; + size = path->size; + pts = (SplashPathPoint *)gmallocn(size, sizeof(SplashPathPoint)); + flags = (Guchar *)gmallocn(size, sizeof(Guchar)); + memcpy(pts, path->pts, length * sizeof(SplashPathPoint)); + memcpy(flags, path->flags, length * sizeof(Guchar)); + curSubpath = path->curSubpath; + if (path->hints) { + hintsLength = hintsSize = path->hintsLength; + hints = (SplashPathHint *)gmallocn(hintsSize, sizeof(SplashPathHint)); + memcpy(hints, path->hints, hintsLength * sizeof(SplashPathHint)); + } else { + hints = NULL; + } +} + +SplashPath::~SplashPath() { + gfree(pts); + gfree(flags); + gfree(hints); +} + +// Add space for more points. +void SplashPath::grow(int nPts) { + if (length + nPts > size) { + if (size == 0) { + size = 32; + } + while (size < length + nPts) { + size *= 2; + } + pts = (SplashPathPoint *)greallocn(pts, size, sizeof(SplashPathPoint)); + flags = (Guchar *)greallocn(flags, size, sizeof(Guchar)); + } +} + +void SplashPath::append(SplashPath *path) { + int i; + + curSubpath = length + path->curSubpath; + grow(path->length); + for (i = 0; i < path->length; ++i) { + pts[length] = path->pts[i]; + flags[length] = path->flags[i]; + ++length; + } +} + +SplashError SplashPath::moveTo(SplashCoord x, SplashCoord y) { + if (onePointSubpath()) { + return splashErrBogusPath; + } + grow(1); + pts[length].x = x; + pts[length].y = y; + flags[length] = splashPathFirst | splashPathLast; + curSubpath = length++; + return splashOk; +} + +SplashError SplashPath::lineTo(SplashCoord x, SplashCoord y) { + if (noCurrentPoint()) { + return splashErrNoCurPt; + } + flags[length-1] &= ~splashPathLast; + grow(1); + pts[length].x = x; + pts[length].y = y; + flags[length] = splashPathLast; + ++length; + return splashOk; +} + +SplashError SplashPath::curveTo(SplashCoord x1, SplashCoord y1, + SplashCoord x2, SplashCoord y2, + SplashCoord x3, SplashCoord y3) { + if (noCurrentPoint()) { + return splashErrNoCurPt; + } + flags[length-1] &= ~splashPathLast; + grow(3); + pts[length].x = x1; + pts[length].y = y1; + flags[length] = splashPathCurve; + ++length; + pts[length].x = x2; + pts[length].y = y2; + flags[length] = splashPathCurve; + ++length; + pts[length].x = x3; + pts[length].y = y3; + flags[length] = splashPathLast; + ++length; + return splashOk; +} + +SplashError SplashPath::close() { + if (noCurrentPoint()) { + return splashErrNoCurPt; + } + if (curSubpath == length - 1 || + pts[length - 1].x != pts[curSubpath].x || + pts[length - 1].y != pts[curSubpath].y) { + lineTo(pts[curSubpath].x, pts[curSubpath].y); + } + flags[curSubpath] |= splashPathClosed; + flags[length - 1] |= splashPathClosed; + curSubpath = length; + return splashOk; +} + +void SplashPath::addStrokeAdjustHint(int ctrl0, int ctrl1, + int firstPt, int lastPt) { + if (hintsLength == hintsSize) { + hintsSize = hintsLength ? 2 * hintsLength : 8; + hints = (SplashPathHint *)greallocn(hints, hintsSize, + sizeof(SplashPathHint)); + } + hints[hintsLength].ctrl0 = ctrl0; + hints[hintsLength].ctrl1 = ctrl1; + hints[hintsLength].firstPt = firstPt; + hints[hintsLength].lastPt = lastPt; + ++hintsLength; +} + +void SplashPath::offset(SplashCoord dx, SplashCoord dy) { + int i; + + for (i = 0; i < length; ++i) { + pts[i].x += dx; + pts[i].y += dy; + } +} + +GBool SplashPath::getCurPt(SplashCoord *x, SplashCoord *y) { + if (noCurrentPoint()) { + return gFalse; + } + *x = pts[length - 1].x; + *y = pts[length - 1].y; + return gTrue; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashPath.h swftools-0.9.1/lib/pdf/xpdf/SplashPath.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashPath.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashPath.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,121 @@ +//======================================================================== +// +// SplashPath.h +// +//======================================================================== + +#ifndef SPLASHPATH_H +#define SPLASHPATH_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" + +//------------------------------------------------------------------------ +// SplashPathPoint +//------------------------------------------------------------------------ + +struct SplashPathPoint { + SplashCoord x, y; +}; + +//------------------------------------------------------------------------ +// SplashPath.flags +//------------------------------------------------------------------------ + +// first point on each subpath sets this flag +#define splashPathFirst 0x01 + +// last point on each subpath sets this flag +#define splashPathLast 0x02 + +// if the subpath is closed, its first and last points must be +// identical, and must set this flag +#define splashPathClosed 0x04 + +// curve control points set this flag +#define splashPathCurve 0x08 + +//------------------------------------------------------------------------ +// SplashPathHint +//------------------------------------------------------------------------ + +struct SplashPathHint { + int ctrl0, ctrl1; + int firstPt, lastPt; +}; + +//------------------------------------------------------------------------ +// SplashPath +//------------------------------------------------------------------------ + +class SplashPath { +public: + + // Create an empty path. + SplashPath(); + + // Copy a path. + SplashPath *copy() { return new SplashPath(this); } + + ~SplashPath(); + + // Append to . + void append(SplashPath *path); + + // Start a new subpath. + SplashError moveTo(SplashCoord x, SplashCoord y); + + // Add a line segment to the last subpath. + SplashError lineTo(SplashCoord x, SplashCoord y); + + // Add a third-order (cubic) Bezier curve segment to the last + // subpath. + SplashError curveTo(SplashCoord x1, SplashCoord y1, + SplashCoord x2, SplashCoord y2, + SplashCoord x3, SplashCoord y3); + + // Close the last subpath, adding a line segment if necessary. + SplashError close(); + + // Add a stroke adjustment hint. The controlling segments are + // and (where segments are identified by their first + // point), and the points to be adjusted are .. . + void addStrokeAdjustHint(int ctrl0, int ctrl1, int firstPt, int lastPt); + + // Add (, ) to every point on this path. + void offset(SplashCoord dx, SplashCoord dy); + + // Get the points on the path. + int getLength() { return length; } + void getPoint(int i, double *x, double *y, Guchar *f) + { *x = pts[i].x; *y = pts[i].y; *f = flags[i]; } + + // Get the current point. + GBool getCurPt(SplashCoord *x, SplashCoord *y); + +private: + + SplashPath(SplashPath *path); + void grow(int nPts); + GBool noCurrentPoint() { return curSubpath == length; } + GBool onePointSubpath() { return curSubpath == length - 1; } + GBool openSubpath() { return curSubpath < length - 1; } + + SplashPathPoint *pts; // array of points + Guchar *flags; // array of flags + int length, size; // length/size of the pts and flags arrays + int curSubpath; // index of first point in last subpath + + SplashPathHint *hints; // list of hints + int hintsLength, hintsSize; + + friend class SplashXPath; + friend class Splash; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashPattern.cc swftools-0.9.1/lib/pdf/xpdf/SplashPattern.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashPattern.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashPattern.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,40 @@ +//======================================================================== +// +// SplashPattern.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "SplashMath.h" +#include "SplashScreen.h" +#include "SplashPattern.h" + +//------------------------------------------------------------------------ +// SplashPattern +//------------------------------------------------------------------------ + +SplashPattern::SplashPattern() { +} + +SplashPattern::~SplashPattern() { +} + +//------------------------------------------------------------------------ +// SplashSolidColor +//------------------------------------------------------------------------ + +SplashSolidColor::SplashSolidColor(SplashColorPtr colorA) { + splashColorCopy(color, colorA); +} + +SplashSolidColor::~SplashSolidColor() { +} + +void SplashSolidColor::getColor(int x, int y, SplashColorPtr c) { + splashColorCopy(c, color); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashPattern.h swftools-0.9.1/lib/pdf/xpdf/SplashPattern.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashPattern.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashPattern.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,65 @@ +//======================================================================== +// +// SplashPattern.h +// +//======================================================================== + +#ifndef SPLASHPATTERN_H +#define SPLASHPATTERN_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" + +class SplashScreen; + +//------------------------------------------------------------------------ +// SplashPattern +//------------------------------------------------------------------------ + +class SplashPattern { +public: + + SplashPattern(); + + virtual SplashPattern *copy() = 0; + + virtual ~SplashPattern(); + + // Return the color value for a specific pixel. + virtual void getColor(int x, int y, SplashColorPtr c) = 0; + + // Returns true if this pattern object will return the same color + // value for all pixels. + virtual GBool isStatic() = 0; + +private: +}; + +//------------------------------------------------------------------------ +// SplashSolidColor +//------------------------------------------------------------------------ + +class SplashSolidColor: public SplashPattern { +public: + + SplashSolidColor(SplashColorPtr colorA); + + virtual SplashPattern *copy() { return new SplashSolidColor(color); } + + virtual ~SplashSolidColor(); + + virtual void getColor(int x, int y, SplashColorPtr c); + + virtual GBool isStatic() { return gTrue; } + +private: + + SplashColor color; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashScreen.cc swftools-0.9.1/lib/pdf/xpdf/SplashScreen.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashScreen.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashScreen.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,385 @@ +//======================================================================== +// +// SplashScreen.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "SplashMath.h" +#include "SplashScreen.h" + +//------------------------------------------------------------------------ + +static SplashScreenParams defaultParams = { + splashScreenDispersed, // type + 2, // size + 2, // dotRadius + 1.0, // gamma + 0.0, // blackThreshold + 1.0 // whiteThreshold +}; + +//------------------------------------------------------------------------ + +struct SplashScreenPoint { + int x, y; + int dist; +}; + +static int cmpDistances(const void *p0, const void *p1) { + return ((SplashScreenPoint *)p0)->dist - ((SplashScreenPoint *)p1)->dist; +} + +//------------------------------------------------------------------------ +// SplashScreen +//------------------------------------------------------------------------ + +// If is true, this generates a 45 degree screen using a +// circular dot spot function. DPI = resolution / ((size / 2) * +// sqrt(2)). If is false, this generates an optimal +// threshold matrix using recursive tesselation. Gamma correction +// (gamma = 1 / 1.33) is also computed here. +SplashScreen::SplashScreen(SplashScreenParams *params) { + Guchar u, black, white; + int i; + + if (!params) { + params = &defaultParams; + } + + switch (params->type) { + + case splashScreenDispersed: + // size must be a power of 2 + for (size = 1; size < params->size; size <<= 1) ; + mat = (Guchar *)gmallocn(size * size, sizeof(Guchar)); + buildDispersedMatrix(size/2, size/2, 1, size/2, 1); + break; + + case splashScreenClustered: + // size must be even + size = (params->size >> 1) << 1; + if (size < 2) { + size = 2; + } + mat = (Guchar *)gmallocn(size * size, sizeof(Guchar)); + buildClusteredMatrix(); + break; + + case splashScreenStochasticClustered: + // size must be at least 2*r + if (params->size < 2 * params->dotRadius) { + size = 2 * params->dotRadius; + } else { + size = params->size; + } + mat = (Guchar *)gmallocn(size * size, sizeof(Guchar)); + buildSCDMatrix(params->dotRadius); + break; + } + + // do gamma correction and compute minVal/maxVal + minVal = 255; + maxVal = 0; + black = splashRound((SplashCoord)255.0 * params->blackThreshold); + if (black < 1) { + black = 1; + } + white = splashRound((SplashCoord)255.0 * params->whiteThreshold); + if (white > 255) { + white = 255; + } + for (i = 0; i < size * size; ++i) { + u = splashRound((SplashCoord)255.0 * + splashPow((SplashCoord)mat[i] / 255.0, params->gamma)); + if (u < black) { + u = black; + } else if (u >= white) { + u = white; + } + mat[i] = u; + if (u < minVal) { + minVal = u; + } else if (u > maxVal) { + maxVal = u; + } + } +} + +void SplashScreen::buildDispersedMatrix(int i, int j, int val, + int delta, int offset) { + if (delta == 0) { + // map values in [1, size^2] --> [1, 255] + mat[i * size + j] = 1 + (254 * (val - 1)) / (size * size - 1); + } else { + buildDispersedMatrix(i, j, + val, delta / 2, 4*offset); + buildDispersedMatrix((i + delta) % size, (j + delta) % size, + val + offset, delta / 2, 4*offset); + buildDispersedMatrix((i + delta) % size, j, + val + 2*offset, delta / 2, 4*offset); + buildDispersedMatrix((i + 2*delta) % size, (j + delta) % size, + val + 3*offset, delta / 2, 4*offset); + } +} + +void SplashScreen::buildClusteredMatrix() { + SplashCoord *dist; + SplashCoord u, v, d; + Guchar val; + int size2, x, y, x1, y1, i; + + size2 = size >> 1; + + // initialize the threshold matrix + for (y = 0; y < size; ++y) { + for (x = 0; x < size; ++x) { + mat[y * size + x] = 0; + } + } + + // build the distance matrix + dist = (SplashCoord *)gmallocn(size * size2, sizeof(SplashCoord)); + for (y = 0; y < size2; ++y) { + for (x = 0; x < size2; ++x) { + if (x + y < size2 - 1) { + u = (SplashCoord)x + 0.5 - 0; + v = (SplashCoord)y + 0.5 - 0; + } else { + u = (SplashCoord)x + 0.5 - (SplashCoord)size2; + v = (SplashCoord)y + 0.5 - (SplashCoord)size2; + } + dist[y * size2 + x] = u*u + v*v; + } + } + for (y = 0; y < size2; ++y) { + for (x = 0; x < size2; ++x) { + if (x < y) { + u = (SplashCoord)x + 0.5 - 0; + v = (SplashCoord)y + 0.5 - (SplashCoord)size2; + } else { + u = (SplashCoord)x + 0.5 - (SplashCoord)size2; + v = (SplashCoord)y + 0.5 - 0; + } + dist[(size2 + y) * size2 + x] = u*u + v*v; + } + } + + // build the threshold matrix + minVal = 1; + maxVal = 0; + x1 = y1 = 0; // make gcc happy + for (i = 0; i < size * size2; ++i) { + d = -1; + for (y = 0; y < size; ++y) { + for (x = 0; x < size2; ++x) { + if (mat[y * size + x] == 0 && + dist[y * size2 + x] > d) { + x1 = x; + y1 = y; + d = dist[y1 * size2 + x1]; + } + } + } + // map values in [0, 2*size*size2-1] --> [1, 255] + val = 1 + (254 * (2*i)) / (2*size*size2 - 1); + mat[y1 * size + x1] = val; + val = 1 + (254 * (2*i+1)) / (2*size*size2 - 1); + if (y1 < size2) { + mat[(y1 + size2) * size + x1 + size2] = val; + } else { + mat[(y1 - size2) * size + x1 + size2] = val; + } + } + + gfree(dist); +} + +// Compute the distance between two points on a toroid. +int SplashScreen::distance(int x0, int y0, int x1, int y1) { + int dx0, dx1, dx, dy0, dy1, dy; + + dx0 = abs(x0 - x1); + dx1 = size - dx0; + dx = dx0 < dx1 ? dx0 : dx1; + dy0 = abs(y0 - y1); + dy1 = size - dy0; + dy = dy0 < dy1 ? dy0 : dy1; + return dx * dx + dy * dy; +} + +// Algorithm taken from: +// Victor Ostromoukhov and Roger D. Hersch, "Stochastic Clustered-Dot +// Dithering" in Color Imaging: Device-Independent Color, Color +// Hardcopy, and Graphic Arts IV, SPIE Vol. 3648, pp. 496-505, 1999. +void SplashScreen::buildSCDMatrix(int r) { + SplashScreenPoint *dots, *pts; + int dotsLen, dotsSize; + char *tmpl; + char *grid; + int *region, *dist; + int x, y, xx, yy, x0, x1, y0, y1, i, j, d, iMin, dMin, n; + + //~ this should probably happen somewhere else + srand(123); + + // generate the random space-filling curve + pts = (SplashScreenPoint *)gmallocn(size * size, sizeof(SplashScreenPoint)); + i = 0; + for (y = 0; y < size; ++y) { + for (x = 0; x < size; ++x) { + pts[i].x = x; + pts[i].y = y; + ++i; + } + } + for (i = 0; i < size * size; ++i) { + j = i + (int)((double)(size * size - i) * + (double)rand() / ((double)RAND_MAX + 1.0)); + x = pts[i].x; + y = pts[i].y; + pts[i].x = pts[j].x; + pts[i].y = pts[j].y; + pts[j].x = x; + pts[j].y = y; + } + + // construct the circle template + tmpl = (char *)gmallocn((r+1)*(r+1), sizeof(char)); + for (y = 0; y <= r; ++y) { + for (x = 0; x <= r; ++x) { + tmpl[y*(r+1) + x] = (x * y <= r * r) ? 1 : 0; + } + } + + // mark all grid cells as free + grid = (char *)gmallocn(size * size, sizeof(char)); + for (y = 0; y < size; ++y) { + for (x = 0; x < size; ++x) { + grid[y*size + x] = 0; + } + } + + // walk the space-filling curve, adding dots + dotsLen = 0; + dotsSize = 32; + dots = (SplashScreenPoint *)gmallocn(dotsSize, sizeof(SplashScreenPoint)); + for (i = 0; i < size * size; ++i) { + x = pts[i].x; + y = pts[i].y; + if (!grid[y*size + x]) { + if (dotsLen == dotsSize) { + dotsSize *= 2; + dots = (SplashScreenPoint *)greallocn(dots, dotsSize, + sizeof(SplashScreenPoint)); + } + dots[dotsLen++] = pts[i]; + for (yy = 0; yy <= r; ++yy) { + y0 = (y + yy) % size; + y1 = (y - yy + size) % size; + for (xx = 0; xx <= r; ++xx) { + if (tmpl[yy*(r+1) + xx]) { + x0 = (x + xx) % size; + x1 = (x - xx + size) % size; + grid[y0*size + x0] = 1; + grid[y0*size + x1] = 1; + grid[y1*size + x0] = 1; + grid[y1*size + x1] = 1; + } + } + } + } + } + + gfree(tmpl); + gfree(grid); + + // assign each cell to a dot, compute distance to center of dot + region = (int *)gmallocn(size * size, sizeof(int)); + dist = (int *)gmallocn(size * size, sizeof(int)); + for (y = 0; y < size; ++y) { + for (x = 0; x < size; ++x) { + iMin = 0; + dMin = distance(dots[0].x, dots[0].y, x, y); + for (i = 1; i < dotsLen; ++i) { + d = distance(dots[i].x, dots[i].y, x, y); + if (d < dMin) { + iMin = i; + dMin = d; + } + } + region[y*size + x] = iMin; + dist[y*size + x] = dMin; + } + } + + // compute threshold values + for (i = 0; i < dotsLen; ++i) { + n = 0; + for (y = 0; y < size; ++y) { + for (x = 0; x < size; ++x) { + if (region[y*size + x] == i) { + pts[n].x = x; + pts[n].y = y; + pts[n].dist = distance(dots[i].x, dots[i].y, x, y); + ++n; + } + } + } + qsort(pts, n, sizeof(SplashScreenPoint), &cmpDistances); + for (j = 0; j < n; ++j) { + // map values in [0 .. n-1] --> [255 .. 1] + mat[pts[j].y * size + pts[j].x] = 255 - (254 * j) / (n - 1); + } + } + + gfree(pts); + gfree(region); + gfree(dist); + + gfree(dots); +} + +SplashScreen::SplashScreen(SplashScreen *screen) { + size = screen->size; + mat = (Guchar *)gmallocn(size * size, sizeof(Guchar)); + memcpy(mat, screen->mat, size * size * sizeof(Guchar)); + minVal = screen->minVal; + maxVal = screen->maxVal; +} + +SplashScreen::~SplashScreen() { + gfree(mat); +} + +int SplashScreen::test(int x, int y, Guchar value) { + int xx, yy; + + return 1; + + if (value < minVal) { + return 0; + } + if (value >= maxVal) { + return 1; + } + if ((xx = x % size) < 0) { + xx = -xx; + } + if ((yy = y % size) < 0) { + yy = -yy; + } + return value < mat[yy * size + xx] ? 0 : 1; +} + +GBool SplashScreen::isStatic(Guchar value) { + return value < minVal || value >= maxVal; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashScreen.h swftools-0.9.1/lib/pdf/xpdf/SplashScreen.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashScreen.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashScreen.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,56 @@ +//======================================================================== +// +// SplashScreen.h +// +//======================================================================== + +#ifndef SPLASHSCREEN_H +#define SPLASHSCREEN_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" + +//------------------------------------------------------------------------ +// SplashScreen +//------------------------------------------------------------------------ + +class SplashScreen { +public: + + SplashScreen(SplashScreenParams *params); + SplashScreen(SplashScreen *screen); + ~SplashScreen(); + + SplashScreen *copy() { return new SplashScreen(this); } + + // Return the computed pixel value (0=black, 1=white) for the gray + // level at (, ). + int test(int x, int y, Guchar value); + + // Returns true if value is above the white threshold or below the + // black threshold, i.e., if the corresponding halftone will be + // solid white or black. + GBool isStatic(Guchar value); + +private: + + void buildDispersedMatrix(int i, int j, int val, + int delta, int offset); + void buildClusteredMatrix(); + int distance(int x0, int y0, int x1, int y1); + void buildSCDMatrix(int r); + + Guchar *mat; // threshold matrix + int size; // size of the threshold matrix + Guchar minVal; // any pixel value below minVal generates + // solid black + Guchar maxVal; // any pixel value above maxVal generates + // solid white +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashState.cc swftools-0.9.1/lib/pdf/xpdf/SplashState.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashState.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashState.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,165 @@ +//======================================================================== +// +// SplashState.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include "gmem.h" +#include "SplashPattern.h" +#include "SplashScreen.h" +#include "SplashClip.h" +#include "SplashBitmap.h" +#include "SplashState.h" + +//------------------------------------------------------------------------ +// SplashState +//------------------------------------------------------------------------ + +// number of components in each color mode +int splashColorModeNComps[] = { + 1, 1, 3, 3, 4 +}; + +SplashState::SplashState(int width, int height, GBool vectorAntialias, + SplashScreenParams *screenParams) { + SplashColor color; + + matrix[0] = 1; matrix[1] = 0; + matrix[2] = 0; matrix[3] = 1; + matrix[4] = 0; matrix[5] = 0; + memset(&color, 0, sizeof(SplashColor)); + strokePattern = new SplashSolidColor(color); + fillPattern = new SplashSolidColor(color); + screen = new SplashScreen(screenParams); + blendFunc = NULL; + strokeAlpha = 1; + fillAlpha = 1; + lineWidth = 0; + lineCap = splashLineCapButt; + lineJoin = splashLineJoinMiter; + miterLimit = 10; + flatness = 1; + lineDash = NULL; + lineDashLength = 0; + lineDashPhase = 0; + strokeAdjust = gFalse; + clip = new SplashClip(0, 0, width - 0.001, height - 0.001, vectorAntialias); + softMask = NULL; + deleteSoftMask = gFalse; + inNonIsolatedGroup = gFalse; + next = NULL; +} + +SplashState::SplashState(int width, int height, GBool vectorAntialias, + SplashScreen *screenA) { + SplashColor color; + + matrix[0] = 1; matrix[1] = 0; + matrix[2] = 0; matrix[3] = 1; + matrix[4] = 0; matrix[5] = 0; + memset(&color, 0, sizeof(SplashColor)); + strokePattern = new SplashSolidColor(color); + fillPattern = new SplashSolidColor(color); + screen = screenA->copy(); + blendFunc = NULL; + strokeAlpha = 1; + fillAlpha = 1; + lineWidth = 0; + lineCap = splashLineCapButt; + lineJoin = splashLineJoinMiter; + miterLimit = 10; + flatness = 1; + lineDash = NULL; + lineDashLength = 0; + lineDashPhase = 0; + strokeAdjust = gFalse; + clip = new SplashClip(0, 0, width - 0.001, height - 0.001, vectorAntialias); + softMask = NULL; + deleteSoftMask = gFalse; + inNonIsolatedGroup = gFalse; + next = NULL; +} + +SplashState::SplashState(SplashState *state) { + memcpy(matrix, state->matrix, 6 * sizeof(SplashCoord)); + strokePattern = state->strokePattern->copy(); + fillPattern = state->fillPattern->copy(); + screen = state->screen->copy(); + blendFunc = state->blendFunc; + strokeAlpha = state->strokeAlpha; + fillAlpha = state->fillAlpha; + lineWidth = state->lineWidth; + lineCap = state->lineCap; + lineJoin = state->lineJoin; + miterLimit = state->miterLimit; + flatness = state->flatness; + if (state->lineDash) { + lineDashLength = state->lineDashLength; + lineDash = (SplashCoord *)gmallocn(lineDashLength, sizeof(SplashCoord)); + memcpy(lineDash, state->lineDash, lineDashLength * sizeof(SplashCoord)); + } else { + lineDash = NULL; + lineDashLength = 0; + } + lineDashPhase = state->lineDashPhase; + strokeAdjust = state->strokeAdjust; + clip = state->clip->copy(); + softMask = state->softMask; + deleteSoftMask = gFalse; + inNonIsolatedGroup = state->inNonIsolatedGroup; + next = NULL; +} + +SplashState::~SplashState() { + delete strokePattern; + delete fillPattern; + delete screen; + gfree(lineDash); + delete clip; + if (deleteSoftMask && softMask) { + delete softMask; + } +} + +void SplashState::setStrokePattern(SplashPattern *strokePatternA) { + delete strokePattern; + strokePattern = strokePatternA; +} + +void SplashState::setFillPattern(SplashPattern *fillPatternA) { + delete fillPattern; + fillPattern = fillPatternA; +} + +void SplashState::setScreen(SplashScreen *screenA) { + delete screen; + screen = screenA; +} + +void SplashState::setLineDash(SplashCoord *lineDashA, int lineDashLengthA, + SplashCoord lineDashPhaseA) { + gfree(lineDash); + lineDashLength = lineDashLengthA; + if (lineDashLength > 0) { + lineDash = (SplashCoord *)gmallocn(lineDashLength, sizeof(SplashCoord)); + memcpy(lineDash, lineDashA, lineDashLength * sizeof(SplashCoord)); + } else { + lineDash = NULL; + } + lineDashPhase = lineDashPhaseA; +} + +void SplashState::setSoftMask(SplashBitmap *softMaskA) { + if (deleteSoftMask) { + delete softMask; + } + softMask = softMaskA; + deleteSoftMask = gTrue; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashState.h swftools-0.9.1/lib/pdf/xpdf/SplashState.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashState.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashState.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,103 @@ +//======================================================================== +// +// SplashState.h +// +//======================================================================== + +#ifndef SPLASHSTATE_H +#define SPLASHSTATE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" + +class SplashPattern; +class SplashScreen; +class SplashClip; +class SplashBitmap; + +//------------------------------------------------------------------------ +// line cap values +//------------------------------------------------------------------------ + +#define splashLineCapButt 0 +#define splashLineCapRound 1 +#define splashLineCapProjecting 2 + +//------------------------------------------------------------------------ +// line join values +//------------------------------------------------------------------------ + +#define splashLineJoinMiter 0 +#define splashLineJoinRound 1 +#define splashLineJoinBevel 2 + +//------------------------------------------------------------------------ +// SplashState +//------------------------------------------------------------------------ + +class SplashState { +public: + + // Create a new state object, initialized with default settings. + SplashState(int width, int height, GBool vectorAntialias, + SplashScreenParams *screenParams); + SplashState(int width, int height, GBool vectorAntialias, + SplashScreen *screenA); + + // Copy a state object. + SplashState *copy() { return new SplashState(this); } + + ~SplashState(); + + // Set the stroke pattern. This does not copy . + void setStrokePattern(SplashPattern *strokePatternA); + + // Set the fill pattern. This does not copy . + void setFillPattern(SplashPattern *fillPatternA); + + // Set the screen. This does not copy . + void setScreen(SplashScreen *screenA); + + // Set the line dash pattern. This copies the array. + void setLineDash(SplashCoord *lineDashA, int lineDashLengthA, + SplashCoord lineDashPhaseA); + + // Set the soft mask bitmap. + void setSoftMask(SplashBitmap *softMaskA); + +private: + + SplashState(SplashState *state); + + SplashCoord matrix[6]; + SplashPattern *strokePattern; + SplashPattern *fillPattern; + SplashScreen *screen; + SplashBlendFunc blendFunc; + SplashCoord strokeAlpha; + SplashCoord fillAlpha; + SplashCoord lineWidth; + int lineCap; + int lineJoin; + SplashCoord miterLimit; + SplashCoord flatness; + SplashCoord *lineDash; + int lineDashLength; + SplashCoord lineDashPhase; + GBool strokeAdjust; + SplashClip *clip; + SplashBitmap *softMask; + GBool deleteSoftMask; + GBool inNonIsolatedGroup; + + SplashState *next; // used by Splash class + + friend class Splash; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1Font.cc swftools-0.9.1/lib/pdf/xpdf/SplashT1Font.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1Font.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashT1Font.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,287 @@ +//======================================================================== +// +// SplashT1Font.cc +// +//======================================================================== + +#include + +#if HAVE_T1LIB_H + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "SplashMath.h" +#include "SplashGlyphBitmap.h" +#include "SplashPath.h" +#include "SplashT1FontEngine.h" +#include "SplashT1FontFile.h" +#include "SplashT1Font.h" + +//------------------------------------------------------------------------ + +static Guchar bitReverse[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + +//------------------------------------------------------------------------ +// SplashT1Font +//------------------------------------------------------------------------ + +SplashT1Font::SplashT1Font(SplashT1FontFile *fontFileA, SplashCoord *matA, + SplashCoord *textMatA): + SplashFont(fontFileA, matA, textMatA, fontFileA->engine->aa) +{ + T1_TMATRIX matrix; + BBox bbox; + SplashCoord bbx0, bby0, bbx1, bby1; + int x, y; + + t1libID = T1_CopyFont(fontFileA->t1libID); + outlineID = -1; + + // compute font size + size = (float)splashSqrt(mat[2]*mat[2] + mat[3]*mat[3]); + + // transform the four corners of the font bounding box -- the min + // and max values form the bounding box of the transformed font + bbox = T1_GetFontBBox(t1libID); + bbx0 = 0.001 * bbox.llx; + bby0 = 0.001 * bbox.lly; + bbx1 = 0.001 * bbox.urx; + bby1 = 0.001 * bbox.ury; + // some fonts are completely broken, so we fake it (with values + // large enough that most glyphs should fit) + if (bbx0 == 0 && bby0 == 0 && bbx1 == 0 && bby1 == 0) { + bbx0 = bby0 = -0.5; + bbx1 = bby1 = 1.5; + } + x = (int)(mat[0] * bbx0 + mat[2] * bby0); + xMin = xMax = x; + y = (int)(mat[1] * bbx0 + mat[3] * bby0); + yMin = yMax = y; + x = (int)(mat[0] * bbx0 + mat[2] * bby1); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + y = (int)(mat[1] * bbx0 + mat[3] * bby1); + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + x = (int)(mat[0] * bbx1 + mat[2] * bby0); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + y = (int)(mat[1] * bbx1 + mat[3] * bby0); + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + x = (int)(mat[0] * bbx1 + mat[2] * bby1); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + y = (int)(mat[1] * bbx1 + mat[3] * bby1); + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + // This is a kludge: some buggy PDF generators embed fonts with + // zero bounding boxes. + if (xMax == xMin) { + xMin = 0; + xMax = (int)size; + } + if (yMax == yMin) { + yMin = 0; + yMax = (int)(1.2 * size); + } + // Another kludge: an unusually large xMin or yMin coordinate is + // probably wrong. + if (xMin > 0) { + xMin = 0; + } + if (yMin > 0) { + yMin = 0; + } + // Another kludge: t1lib doesn't correctly handle fonts with + // real (non-integer) bounding box coordinates. + if (xMax - xMin > 5000) { + xMin = 0; + xMax = (int)size; + } + if (yMax - yMin > 5000) { + yMin = 0; + yMax = (int)(1.2 * size); + } + + // transform the font + matrix.cxx = (double)mat[0] / size; + matrix.cxy = (double)mat[1] / size; + matrix.cyx = (double)mat[2] / size; + matrix.cyy = (double)mat[3] / size; + T1_TransformFont(t1libID, &matrix); +} + +SplashT1Font::~SplashT1Font() { + T1_DeleteFont(t1libID); + if (outlineID >= 0) { + T1_DeleteFont(outlineID); + } +} + +GBool SplashT1Font::getGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap) { + return SplashFont::getGlyph(c, 0, 0, bitmap); +} + +GBool SplashT1Font::makeGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap) { + GLYPH *glyph; + int n, i; + + if (aa) { + glyph = T1_AASetChar(t1libID, c, size, NULL); + } else { + glyph = T1_SetChar(t1libID, c, size, NULL); + } + if (!glyph) { + return gFalse; + } + + bitmap->x = -glyph->metrics.leftSideBearing; + bitmap->y = glyph->metrics.ascent; + bitmap->w = glyph->metrics.rightSideBearing - glyph->metrics.leftSideBearing; + bitmap->h = glyph->metrics.ascent - glyph->metrics.descent; + bitmap->aa = aa; + if (aa) { + bitmap->data = (Guchar *)glyph->bits; + bitmap->freeData = gFalse; + } else { + n = bitmap->h * ((bitmap->w + 7) >> 3); + bitmap->data = (Guchar *)gmalloc(n); + for (i = 0; i < n; ++i) { + bitmap->data[i] = bitReverse[glyph->bits[i] & 0xff]; + } + bitmap->freeData = gTrue; + } + + return gTrue; +} + +SplashPath *SplashT1Font::getGlyphPath(int c) { + T1_TMATRIX matrix; + SplashPath *path; + T1_OUTLINE *outline; + T1_PATHSEGMENT *seg; + T1_BEZIERSEGMENT *bez; + SplashCoord x, y, x1, y1; + GBool needClose; + + if (outlineID < 0) { + outlineID = T1_CopyFont(((SplashT1FontFile *)fontFile)->t1libID); + outlineSize = (float)splashSqrt(textMat[2]*textMat[2] + + textMat[3]*textMat[3]); + matrix.cxx = (double)textMat[0] / outlineSize; + matrix.cxy = (double)textMat[1] / outlineSize; + matrix.cyx = (double)textMat[2] / outlineSize; + matrix.cyy = (double)textMat[3] / outlineSize; + // t1lib doesn't seem to handle small sizes correctly here, so set + // the size to 1000, and scale the resulting coordinates later + outlineMul = (float)(outlineSize / 65536000.0); + outlineSize = 1000; + T1_TransformFont(outlineID, &matrix); + } + + path = new SplashPath(); + if ((outline = T1_GetCharOutline(outlineID, c, outlineSize, NULL))) { + x = 0; + y = 0; + needClose = gFalse; + for (seg = outline; seg; seg = seg->link) { + switch (seg->type) { + case T1_PATHTYPE_MOVE: + if (needClose) { + path->close(); + needClose = gFalse; + } + x += seg->dest.x * outlineMul; + y += seg->dest.y * outlineMul; + path->moveTo(x, -y); + break; + case T1_PATHTYPE_LINE: + x += seg->dest.x * outlineMul; + y += seg->dest.y * outlineMul; + path->lineTo(x, -y); + needClose = gTrue; + break; + case T1_PATHTYPE_BEZIER: + bez = (T1_BEZIERSEGMENT *)seg; + x1 = x + (SplashCoord)(bez->dest.x * outlineMul); + y1 = y + (SplashCoord)(bez->dest.y * outlineMul); + path->curveTo(x + (SplashCoord)(bez->B.x * outlineMul), + -(y + (SplashCoord)(bez->B.y * outlineMul)), + x + (SplashCoord)(bez->C.x * outlineMul), + -(y + (SplashCoord)(bez->C.y * outlineMul)), + x1, -y1); + x = x1; + y = y1; + needClose = gTrue; + break; + } + } + if (needClose) { + path->close(); + } + T1_FreeOutline(outline); + } + + return path; +} + +#endif // HAVE_T1LIB_H diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1FontEngine.cc swftools-0.9.1/lib/pdf/xpdf/SplashT1FontEngine.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1FontEngine.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashT1FontEngine.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,124 @@ +//======================================================================== +// +// SplashT1FontEngine.cc +// +//======================================================================== + +#include + +#if HAVE_T1LIB_H + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#ifndef WIN32 +# include +#endif +#include +#include "GString.h" +#include "gfile.h" +#include "FoFiType1C.h" +#include "SplashT1FontFile.h" +#include "SplashT1FontEngine.h" + +#ifdef VMS +#if (__VMS_VER < 70000000) +extern "C" int unlink(char *filename); +#endif +#endif + +//------------------------------------------------------------------------ + +int SplashT1FontEngine::t1libInitCount = 0; + +//------------------------------------------------------------------------ + +static void fileWrite(void *stream, char *data, int len) { + fwrite(data, 1, len, (FILE *)stream); +} + +//------------------------------------------------------------------------ +// SplashT1FontEngine +//------------------------------------------------------------------------ + +SplashT1FontEngine::SplashT1FontEngine(GBool aaA) { + aa = aaA; +} + +SplashT1FontEngine *SplashT1FontEngine::init(GBool aaA) { + // grayVals[i] = round(i * 255 / 16) + static unsigned long grayVals[17] = { + 0, 16, 32, 48, 64, 80, 96, 112, 128, 143, 159, 175, 191, 207, 223, 239, 255 + }; + + //~ for multithreading: need a mutex here + if (t1libInitCount == 0) { + T1_SetBitmapPad(8); + if (!T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE | + T1_NO_AFM)) { + return NULL; + } + if (aaA) { + T1_AASetBitsPerPixel(8); + T1_AASetLevel(T1_AA_HIGH); + T1_AAHSetGrayValues(grayVals); + } else { + T1_AANSetGrayValues(0, 1); + } + } + ++t1libInitCount; + + return new SplashT1FontEngine(aaA); +} + +SplashT1FontEngine::~SplashT1FontEngine() { + //~ for multithreading: need a mutex here + if (--t1libInitCount == 0) { + T1_CloseLib(); + } +} + +SplashFontFile *SplashT1FontEngine::loadType1Font(SplashFontFileID *idA, + char *fileName, + GBool deleteFile, + char **enc) { + return SplashT1FontFile::loadType1Font(this, idA, fileName, deleteFile, enc); +} + +SplashFontFile *SplashT1FontEngine::loadType1CFont(SplashFontFileID *idA, + char *fileName, + GBool deleteFile, + char **enc) { + FoFiType1C *ff; + GString *tmpFileName; + FILE *tmpFile; + SplashFontFile *ret; + + if (!(ff = FoFiType1C::load(fileName))) { + return NULL; + } + tmpFileName = NULL; + if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { + delete ff; + return NULL; + } + ff->convertToType1(NULL, NULL, gTrue, &fileWrite, tmpFile); + delete ff; + fclose(tmpFile); + ret = SplashT1FontFile::loadType1Font(this, idA, tmpFileName->getCString(), + gTrue, enc); + if (ret) { + if (deleteFile) { + unlink(fileName); + } + } else { + unlink(tmpFileName->getCString()); + } + delete tmpFileName; + return ret; +} + +#endif // HAVE_T1LIB_H diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1FontEngine.h swftools-0.9.1/lib/pdf/xpdf/SplashT1FontEngine.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1FontEngine.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashT1FontEngine.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,53 @@ +//======================================================================== +// +// SplashT1FontEngine.h +// +//======================================================================== + +#ifndef SPLASHT1FONTENGINE_H +#define SPLASHT1FONTENGINE_H + +#include + +#if HAVE_T1LIB_H + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" + +class SplashFontFile; +class SplashFontFileID; + +//------------------------------------------------------------------------ +// SplashT1FontEngine +//------------------------------------------------------------------------ + +class SplashT1FontEngine { +public: + + static SplashT1FontEngine *init(GBool aaA); + + ~SplashT1FontEngine(); + + // Load fonts. + SplashFontFile *loadType1Font(SplashFontFileID *idA, char *fileName, + GBool deleteFile, char **enc); + SplashFontFile *loadType1CFont(SplashFontFileID *idA, char *fileName, + GBool deleteFile, char **enc); + +private: + + SplashT1FontEngine(GBool aaA); + + static int t1libInitCount; + GBool aa; + + friend class SplashT1FontFile; + friend class SplashT1Font; +}; + +#endif // HAVE_T1LIB_H + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1FontFile.cc swftools-0.9.1/lib/pdf/xpdf/SplashT1FontFile.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1FontFile.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashT1FontFile.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,97 @@ +//======================================================================== +// +// SplashT1FontFile.cc +// +//======================================================================== + +#include + +#if HAVE_T1LIB_H + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "SplashT1FontEngine.h" +#include "SplashT1Font.h" +#include "SplashT1FontFile.h" + +//------------------------------------------------------------------------ +// SplashT1FontFile +//------------------------------------------------------------------------ + +SplashFontFile *SplashT1FontFile::loadType1Font(SplashT1FontEngine *engineA, + SplashFontFileID *idA, + char *fileNameA, + GBool deleteFileA, + char **encA) { + int t1libIDA; + char **encTmp; + char *encStrTmp; + int encStrSize; + char *encPtr; + int i; + + // load the font file + if ((t1libIDA = T1_AddFont(fileNameA)) < 0) { + return NULL; + } + T1_LoadFont(t1libIDA); + + // reencode it + encStrSize = 0; + for (i = 0; i < 256; ++i) { + if (encA[i]) { + encStrSize += strlen(encA[i]) + 1; + } + } + encTmp = (char **)gmallocn(257, sizeof(char *)); + encStrTmp = (char *)gmallocn(encStrSize, sizeof(char)); + encPtr = encStrTmp; + for (i = 0; i < 256; ++i) { + if (encA[i]) { + strcpy(encPtr, encA[i]); + encTmp[i] = encPtr; + encPtr += strlen(encPtr) + 1; + } else { + encTmp[i] = ".notdef"; + } + } + encTmp[256] = "custom"; + T1_ReencodeFont(t1libIDA, encTmp); + + return new SplashT1FontFile(engineA, idA, fileNameA, deleteFileA, + t1libIDA, encTmp, encStrTmp); +} + +SplashT1FontFile::SplashT1FontFile(SplashT1FontEngine *engineA, + SplashFontFileID *idA, + char *fileNameA, GBool deleteFileA, + int t1libIDA, char **encA, char *encStrA): + SplashFontFile(idA, fileNameA, deleteFileA) +{ + engine = engineA; + t1libID = t1libIDA; + enc = encA; + encStr = encStrA; +} + +SplashT1FontFile::~SplashT1FontFile() { + gfree(encStr); + gfree(enc); + T1_DeleteFont(t1libID); +} + +SplashFont *SplashT1FontFile::makeFont(SplashCoord *mat, + SplashCoord *textMat) { + SplashFont *font; + + font = new SplashT1Font(this, mat, textMat); + font->initCache(); + return font; +} + +#endif // HAVE_T1LIB_H diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1FontFile.h swftools-0.9.1/lib/pdf/xpdf/SplashT1FontFile.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1FontFile.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashT1FontFile.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,58 @@ +//======================================================================== +// +// SplashT1FontFile.h +// +//======================================================================== + +#ifndef SPLASHT1FONTFILE_H +#define SPLASHT1FONTFILE_H + +#include + +#if HAVE_T1LIB_H + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashFontFile.h" + +class SplashT1FontEngine; + +//------------------------------------------------------------------------ +// SplashT1FontFile +//------------------------------------------------------------------------ + +class SplashT1FontFile: public SplashFontFile { +public: + + static SplashFontFile *loadType1Font(SplashT1FontEngine *engineA, + SplashFontFileID *idA, + char *fileNameA, GBool deleteFileA, + char **encA); + + virtual ~SplashT1FontFile(); + + // Create a new SplashT1Font, i.e., a scaled instance of this font + // file. + virtual SplashFont *makeFont(SplashCoord *mat, + SplashCoord *textMat); + +private: + + SplashT1FontFile(SplashT1FontEngine *engineA, + SplashFontFileID *idA, + char *fileNameA, GBool deleteFileA, + int t1libIDA, char **encA, char *encStrA); + + SplashT1FontEngine *engine; + int t1libID; // t1lib font ID + char **enc; + char *encStr; + + friend class SplashT1Font; +}; + +#endif // HAVE_T1LIB_H + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1Font.h swftools-0.9.1/lib/pdf/xpdf/SplashT1Font.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashT1Font.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashT1Font.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,57 @@ +//======================================================================== +// +// SplashT1Font.h +// +//======================================================================== + +#ifndef SPLASHT1FONT_H +#define SPLASHT1FONT_H + +#include + +#if HAVE_T1LIB_H + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashFont.h" + +class SplashT1FontFile; + +//------------------------------------------------------------------------ +// SplashT1Font +//------------------------------------------------------------------------ + +class SplashT1Font: public SplashFont { +public: + + SplashT1Font(SplashT1FontFile *fontFileA, SplashCoord *matA, + SplashCoord *textMatA); + + virtual ~SplashT1Font(); + + // Munge xFrac and yFrac before calling SplashFont::getGlyph. + virtual GBool getGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap); + + // Rasterize a glyph. The and values are the same + // as described for getGlyph. + virtual GBool makeGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap); + + // Return the path for a glyph. + virtual SplashPath *getGlyphPath(int c); + +private: + + int t1libID; // t1lib font ID + int outlineID; // t1lib font ID for glyph outlines + float size; + float outlineSize; // size for glyph outlines + float outlineMul; +}; + +#endif // HAVE_T1LIB_H + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashTypes.h swftools-0.9.1/lib/pdf/xpdf/SplashTypes.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashTypes.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashTypes.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,132 @@ +//======================================================================== +// +// SplashTypes.h +// +//======================================================================== + +#ifndef SPLASHTYPES_H +#define SPLASHTYPES_H + +#include +#include "gtypes.h" + +//------------------------------------------------------------------------ +// coordinates +//------------------------------------------------------------------------ + +#if USE_FIXEDPOINT +#include "FixedPoint.h" +typedef FixedPoint SplashCoord; +#else +typedef double SplashCoord; +#endif + +//------------------------------------------------------------------------ +// antialiasing +//------------------------------------------------------------------------ + +#define splashAASize 4 + +//------------------------------------------------------------------------ +// colors +//------------------------------------------------------------------------ + +enum SplashColorMode { + splashModeMono1, // 1 bit per component, 8 pixels per byte, + // MSbit is on the left + splashModeMono8, // 1 byte per component, 1 byte per pixel + splashModeRGB8, // 1 byte per component, 3 bytes per pixel: + // RGBRGB... + splashModeBGR8 // 1 byte per component, 3 bytes per pixel: + // BGRBGR... + +#if SPLASH_CMYK + , + splashModeCMYK8 // 1 byte per component, 4 bytes per pixel: + // CMYKCMYK... +#endif +}; + +// number of components in each color mode +// (defined in SplashState.cc) +extern int splashColorModeNComps[]; + +// max number of components in any SplashColor +#if SPLASH_CMYK +# define splashMaxColorComps 4 +#else +# define splashMaxColorComps 3 +#endif + +typedef Guchar SplashColor[splashMaxColorComps]; +typedef Guchar *SplashColorPtr; + +// RGB8 +static inline Guchar splashRGB8R(SplashColorPtr rgb8) { return rgb8[0]; } +static inline Guchar splashRGB8G(SplashColorPtr rgb8) { return rgb8[1]; } +static inline Guchar splashRGB8B(SplashColorPtr rgb8) { return rgb8[2]; } + +// BGR8 +static inline Guchar splashBGR8R(SplashColorPtr bgr8) { return bgr8[2]; } +static inline Guchar splashBGR8G(SplashColorPtr bgr8) { return bgr8[1]; } +static inline Guchar splashBGR8B(SplashColorPtr bgr8) { return bgr8[0]; } + +#if SPLASH_CMYK +// CMYK8 +static inline Guchar splashCMYK8C(SplashColorPtr cmyk8) { return cmyk8[0]; } +static inline Guchar splashCMYK8M(SplashColorPtr cmyk8) { return cmyk8[1]; } +static inline Guchar splashCMYK8Y(SplashColorPtr cmyk8) { return cmyk8[2]; } +static inline Guchar splashCMYK8K(SplashColorPtr cmyk8) { return cmyk8[3]; } +#endif + +static inline void splashColorCopy(SplashColorPtr dest, SplashColorPtr src) { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; +#if SPLASH_CMYK + dest[3] = src[3]; +#endif +} + +static inline void splashColorXor(SplashColorPtr dest, SplashColorPtr src) { + dest[0] ^= src[0]; + dest[1] ^= src[1]; + dest[2] ^= src[2]; +#if SPLASH_CMYK + dest[3] ^= src[3]; +#endif +} + +//------------------------------------------------------------------------ +// blend functions +//------------------------------------------------------------------------ + +typedef void (*SplashBlendFunc)(SplashColorPtr src, SplashColorPtr dest, + SplashColorPtr blend, SplashColorMode cm); + +//------------------------------------------------------------------------ +// screen parameters +//------------------------------------------------------------------------ + +enum SplashScreenType { + splashScreenDispersed, + splashScreenClustered, + splashScreenStochasticClustered +}; + +struct SplashScreenParams { + SplashScreenType type; + int size; + int dotRadius; + SplashCoord gamma; + SplashCoord blackThreshold; + SplashCoord whiteThreshold; +}; + +//------------------------------------------------------------------------ +// error results +//------------------------------------------------------------------------ + +typedef int SplashError; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashXPath.cc swftools-0.9.1/lib/pdf/xpdf/SplashXPath.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashXPath.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashXPath.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,438 @@ +//======================================================================== +// +// SplashXPath.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "SplashMath.h" +#include "SplashPath.h" +#include "SplashXPath.h" + +//------------------------------------------------------------------------ + +struct SplashXPathPoint { + SplashCoord x, y; +}; + +struct SplashXPathAdjust { + int firstPt, lastPt; // range of points + GBool vert; // vertical or horizontal hint + SplashCoord x0a, x0b, // hint boundaries + xma, xmb, + x1a, x1b; + SplashCoord x0, x1, xm; // adjusted coordinates +}; + +//------------------------------------------------------------------------ + +// Transform a point from user space to device space. +inline void SplashXPath::transform(SplashCoord *matrix, + SplashCoord xi, SplashCoord yi, + SplashCoord *xo, SplashCoord *yo) { + // [ m[0] m[1] 0 ] + // [xo yo 1] = [xi yi 1] * [ m[2] m[3] 0 ] + // [ m[4] m[5] 1 ] + *xo = xi * matrix[0] + yi * matrix[2] + matrix[4]; + *yo = xi * matrix[1] + yi * matrix[3] + matrix[5]; +} + +//------------------------------------------------------------------------ +// SplashXPath +//------------------------------------------------------------------------ + +SplashXPath::SplashXPath() { + segs = NULL; + length = size = 0; +} + +SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix, + SplashCoord flatness, GBool closeSubpaths) { + SplashPathHint *hint; + SplashXPathPoint *pts; + SplashXPathAdjust *adjusts, *adjust; + SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xsp, ysp; + SplashCoord adj0, adj1, w; + int ww; + int curSubpath, curSubpathX, i, j; + + // transform the points + pts = (SplashXPathPoint *)gmallocn(path->length, sizeof(SplashXPathPoint)); + for (i = 0; i < path->length; ++i) { + transform(matrix, path->pts[i].x, path->pts[i].y, &pts[i].x, &pts[i].y); + } + + // set up the stroke adjustment hints + if (path->hints) { + adjusts = (SplashXPathAdjust *)gmallocn(path->hintsLength, + sizeof(SplashXPathAdjust)); + for (i = 0; i < path->hintsLength; ++i) { + hint = &path->hints[i]; + x0 = pts[hint->ctrl0 ].x; y0 = pts[hint->ctrl0 ].y; + x1 = pts[hint->ctrl0 + 1].x; y1 = pts[hint->ctrl0 + 1].y; + x2 = pts[hint->ctrl1 ].x; y2 = pts[hint->ctrl1 ].y; + x3 = pts[hint->ctrl1 + 1].x; y3 = pts[hint->ctrl1 + 1].y; + if (x0 == x1 && x2 == x3) { + adjusts[i].vert = gTrue; + adj0 = x0; + adj1 = x2; + } else if (y0 == y1 && y2 == y3) { + adjusts[i].vert = gFalse; + adj0 = y0; + adj1 = y2; + } else { + gfree(adjusts); + adjusts = NULL; + break; + } + if (adj0 > adj1) { + x0 = adj0; + adj0 = adj1; + adj1 = x0; + } + w = adj1 - adj0; + ww = splashRound(w); + if (ww == 0) { + ww = 1; + } + adjusts[i].x0a = adj0 - 0.01; + adjusts[i].x0b = adj0 + 0.01; + adjusts[i].xma = (SplashCoord)0.5 * (adj0 + adj1) - 0.01; + adjusts[i].xmb = (SplashCoord)0.5 * (adj0 + adj1) + 0.01; + adjusts[i].x1a = adj1 - 0.01; + adjusts[i].x1b = adj1 + 0.01; + adjusts[i].x0 = (SplashCoord)splashRound(adj0); + adjusts[i].x1 = adjusts[i].x0 + ww - 0.01; + adjusts[i].xm = (SplashCoord)0.5 * (adjusts[i].x0 + adjusts[i].x1); + adjusts[i].firstPt = hint->firstPt; + adjusts[i].lastPt = hint->lastPt; + } + + } else { + adjusts = NULL; + } + + // perform stroke adjustment + if (adjusts) { + for (i = 0, adjust = adjusts; i < path->hintsLength; ++i, ++adjust) { + for (j = adjust->firstPt; j <= adjust->lastPt; ++j) { + strokeAdjust(adjust, &pts[j].x, &pts[j].y); + } + } + gfree(adjusts); + } + + segs = NULL; + length = size = 0; + + x0 = y0 = xsp = ysp = 0; // make gcc happy + adj0 = adj1 = 0; // make gcc happy + curSubpath = 0; + curSubpathX = 0; + i = 0; + while (i < path->length) { + + // first point in subpath - skip it + if (path->flags[i] & splashPathFirst) { + x0 = pts[i].x; + y0 = pts[i].y; + xsp = x0; + ysp = y0; + curSubpath = i; + curSubpathX = length; + ++i; + + } else { + + // curve segment + if (path->flags[i] & splashPathCurve) { + x1 = pts[i].x; + y1 = pts[i].y; + x2 = pts[i+1].x; + y2 = pts[i+1].y; + x3 = pts[i+2].x; + y3 = pts[i+2].y; + addCurve(x0, y0, x1, y1, x2, y2, x3, y3, + flatness, + (path->flags[i-1] & splashPathFirst), + (path->flags[i+2] & splashPathLast), + !closeSubpaths && + (path->flags[i-1] & splashPathFirst) && + !(path->flags[i-1] & splashPathClosed), + !closeSubpaths && + (path->flags[i+2] & splashPathLast) && + !(path->flags[i+2] & splashPathClosed)); + x0 = x3; + y0 = y3; + i += 3; + + // line segment + } else { + x1 = pts[i].x; + y1 = pts[i].y; + addSegment(x0, y0, x1, y1, + path->flags[i-1] & splashPathFirst, + path->flags[i] & splashPathLast, + !closeSubpaths && + (path->flags[i-1] & splashPathFirst) && + !(path->flags[i-1] & splashPathClosed), + !closeSubpaths && + (path->flags[i] & splashPathLast) && + !(path->flags[i] & splashPathClosed)); + x0 = x1; + y0 = y1; + ++i; + } + + // close a subpath + if (closeSubpaths && + (path->flags[i-1] & splashPathLast) && + (pts[i-1].x != pts[curSubpath].x || + pts[i-1].y != pts[curSubpath].y)) { + addSegment(x0, y0, xsp, ysp, + gFalse, gTrue, gFalse, gFalse); + } + } + } + + gfree(pts); +} + +// Apply the stroke adjust hints to point : (*, *). +void SplashXPath::strokeAdjust(SplashXPathAdjust *adjust, + SplashCoord *xp, SplashCoord *yp) { + SplashCoord x, y; + + if (adjust->vert) { + x = *xp; + if (x > adjust->x0a && x < adjust->x0b) { + *xp = adjust->x0; + } else if (x > adjust->xma && x < adjust->xmb) { + *xp = adjust->xm; + } else if (x > adjust->x1a && x < adjust->x1b) { + *xp = adjust->x1; + } + } else { + y = *yp; + if (y > adjust->x0a && y < adjust->x0b) { + *yp = adjust->x0; + } else if (y > adjust->xma && y < adjust->xmb) { + *yp = adjust->xm; + } else if (y > adjust->x1a && y < adjust->x1b) { + *yp = adjust->x1; + } + } +} + +SplashXPath::SplashXPath(SplashXPath *xPath) { + length = xPath->length; + size = xPath->size; + segs = (SplashXPathSeg *)gmallocn(size, sizeof(SplashXPathSeg)); + memcpy(segs, xPath->segs, length * sizeof(SplashXPathSeg)); +} + +SplashXPath::~SplashXPath() { + gfree(segs); +} + +// Add space for more segments +void SplashXPath::grow(int nSegs) { + if (length + nSegs > size) { + if (size == 0) { + size = 32; + } + while (size < length + nSegs) { + size *= 2; + } + segs = (SplashXPathSeg *)greallocn(segs, size, sizeof(SplashXPathSeg)); + } +} + +void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + SplashCoord x2, SplashCoord y2, + SplashCoord x3, SplashCoord y3, + SplashCoord flatness, + GBool first, GBool last, GBool end0, GBool end1) { + SplashCoord cx[splashMaxCurveSplits + 1][3]; + SplashCoord cy[splashMaxCurveSplits + 1][3]; + int cNext[splashMaxCurveSplits + 1]; + SplashCoord xl0, xl1, xl2, xr0, xr1, xr2, xr3, xx1, xx2, xh; + SplashCoord yl0, yl1, yl2, yr0, yr1, yr2, yr3, yy1, yy2, yh; + SplashCoord dx, dy, mx, my, d1, d2, flatness2; + int p1, p2, p3; + + flatness2 = flatness * flatness; + + // initial segment + p1 = 0; + p2 = splashMaxCurveSplits; + cx[p1][0] = x0; cy[p1][0] = y0; + cx[p1][1] = x1; cy[p1][1] = y1; + cx[p1][2] = x2; cy[p1][2] = y2; + cx[p2][0] = x3; cy[p2][0] = y3; + cNext[p1] = p2; + + while (p1 < splashMaxCurveSplits) { + + // get the next segment + xl0 = cx[p1][0]; yl0 = cy[p1][0]; + xx1 = cx[p1][1]; yy1 = cy[p1][1]; + xx2 = cx[p1][2]; yy2 = cy[p1][2]; + p2 = cNext[p1]; + xr3 = cx[p2][0]; yr3 = cy[p2][0]; + + // compute the distances from the control points to the + // midpoint of the straight line (this is a bit of a hack, but + // it's much faster than computing the actual distances to the + // line) + mx = (xl0 + xr3) * 0.5; + my = (yl0 + yr3) * 0.5; + dx = xx1 - mx; + dy = yy1 - my; + d1 = dx*dx + dy*dy; + dx = xx2 - mx; + dy = yy2 - my; + d2 = dx*dx + dy*dy; + + // if the curve is flat enough, or no more subdivisions are + // allowed, add the straight line segment + if (p2 - p1 == 1 || (d1 <= flatness2 && d2 <= flatness2)) { + addSegment(xl0, yl0, xr3, yr3, + p1 == 0 && first, + p2 == splashMaxCurveSplits && last, + p1 == 0 && end0, + p2 == splashMaxCurveSplits && end1); + p1 = p2; + + // otherwise, subdivide the curve + } else { + xl1 = (xl0 + xx1) * 0.5; + yl1 = (yl0 + yy1) * 0.5; + xh = (xx1 + xx2) * 0.5; + yh = (yy1 + yy2) * 0.5; + xl2 = (xl1 + xh) * 0.5; + yl2 = (yl1 + yh) * 0.5; + xr2 = (xx2 + xr3) * 0.5; + yr2 = (yy2 + yr3) * 0.5; + xr1 = (xh + xr2) * 0.5; + yr1 = (yh + yr2) * 0.5; + xr0 = (xl2 + xr1) * 0.5; + yr0 = (yl2 + yr1) * 0.5; + // add the new subdivision points + p3 = (p1 + p2) / 2; + cx[p1][1] = xl1; cy[p1][1] = yl1; + cx[p1][2] = xl2; cy[p1][2] = yl2; + cNext[p1] = p3; + cx[p3][0] = xr0; cy[p3][0] = yr0; + cx[p3][1] = xr1; cy[p3][1] = yr1; + cx[p3][2] = xr2; cy[p3][2] = yr2; + cNext[p3] = p2; + } + } +} + +void SplashXPath::addSegment(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + GBool first, GBool last, GBool end0, GBool end1) { + grow(1); + segs[length].x0 = x0; + segs[length].y0 = y0; + segs[length].x1 = x1; + segs[length].y1 = y1; + segs[length].flags = 0; + if (first) { + segs[length].flags |= splashXPathFirst; + } + if (last) { + segs[length].flags |= splashXPathLast; + } + if (end0) { + segs[length].flags |= splashXPathEnd0; + } + if (end1) { + segs[length].flags |= splashXPathEnd1; + } + if (y1 == y0) { + segs[length].dxdy = segs[length].dydx = 0; + segs[length].flags |= splashXPathHoriz; + if (x1 == x0) { + segs[length].flags |= splashXPathVert; + } + } else if (x1 == x0) { + segs[length].dxdy = segs[length].dydx = 0; + segs[length].flags |= splashXPathVert; + } else { +#if USE_FIXEDPOINT + if (FixedPoint::divCheck(x1 - x0, y1 - y0, &segs[length].dxdy)) { + segs[length].dydx = (SplashCoord)1 / segs[length].dxdy; + } else { + segs[length].dxdy = segs[length].dydx = 0; + if (splashAbs(x1 - x0) > splashAbs(y1 - y0)) { + segs[length].flags |= splashXPathHoriz; + } else { + segs[length].flags |= splashXPathVert; + } + } +#else + segs[length].dxdy = (x1 - x0) / (y1 - y0); + segs[length].dydx = (SplashCoord)1 / segs[length].dxdy; +#endif + } + if (y0 > y1) { + segs[length].flags |= splashXPathFlip; + } + ++length; +} + +static int cmpXPathSegs(const void *arg0, const void *arg1) { + SplashXPathSeg *seg0 = (SplashXPathSeg *)arg0; + SplashXPathSeg *seg1 = (SplashXPathSeg *)arg1; + SplashCoord x0, y0, x1, y1; + + if (seg0->flags & splashXPathFlip) { + x0 = seg0->x1; + y0 = seg0->y1; + } else { + x0 = seg0->x0; + y0 = seg0->y0; + } + if (seg1->flags & splashXPathFlip) { + x1 = seg1->x1; + y1 = seg1->y1; + } else { + x1 = seg1->x0; + y1 = seg1->y0; + } + if (y0 != y1) { + return (y0 > y1) ? 1 : -1; + } + if (x0 != x1) { + return (x0 > x1) ? 1 : -1; + } + return 0; +} + +void SplashXPath::aaScale() { + SplashXPathSeg *seg; + int i; + + for (i = 0, seg = segs; i < length; ++i, ++seg) { + seg->x0 *= splashAASize; + seg->y0 *= splashAASize; + seg->x1 *= splashAASize; + seg->y1 *= splashAASize; + } +} + +void SplashXPath::sort() { + qsort(segs, length, sizeof(SplashXPathSeg), &cmpXPathSegs); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashXPath.h swftools-0.9.1/lib/pdf/xpdf/SplashXPath.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashXPath.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashXPath.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,100 @@ +//======================================================================== +// +// SplashXPath.h +// +//======================================================================== + +#ifndef SPLASHXPATH_H +#define SPLASHXPATH_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" + +class SplashPath; +struct SplashXPathAdjust; + +//------------------------------------------------------------------------ + +#define splashMaxCurveSplits (1 << 10) + +//------------------------------------------------------------------------ +// SplashXPathSeg +//------------------------------------------------------------------------ + +struct SplashXPathSeg { + SplashCoord x0, y0; // first endpoint + SplashCoord x1, y1; // second endpoint + SplashCoord dxdy; // slope: delta-x / delta-y + SplashCoord dydx; // slope: delta-y / delta-x + Guint flags; +}; + +#define splashXPathFirst 0x01 // first segment of a subpath +#define splashXPathLast 0x02 // last segment of a subpath +#define splashXPathEnd0 0x04 // first endpoint is end of an open subpath +#define splashXPathEnd1 0x08 // second endpoint is end of an open subpath +#define splashXPathHoriz 0x10 // segment is vertical (y0 == y1) + // (dxdy is undef) +#define splashXPathVert 0x20 // segment is horizontal (x0 == x1) + // (dydx is undef) +#define splashXPathFlip 0x40 // y0 > y1 + +//------------------------------------------------------------------------ +// SplashXPath +//------------------------------------------------------------------------ + +class SplashXPath { +public: + + // Expands (converts to segments) and flattens (converts curves to + // lines) . Transforms all points from user space to device + // space, via . If is true, closes all open + // subpaths. + SplashXPath(SplashPath *path, SplashCoord *matrix, + SplashCoord flatness, GBool closeSubpaths); + + // Copy an expanded path. + SplashXPath *copy() { return new SplashXPath(this); } + + ~SplashXPath(); + + // Multiply all coordinates by splashAASize, in preparation for + // anti-aliased rendering. + void aaScale(); + + // Sort by upper coordinate (lower y), in y-major order. + void sort(); + +private: + + SplashXPath(); + SplashXPath(SplashXPath *xPath); + void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi, + SplashCoord *xo, SplashCoord *yo); + void strokeAdjust(SplashXPathAdjust *adjust, + SplashCoord *xp, SplashCoord *yp); + void grow(int nSegs); + void addCurve(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + SplashCoord x2, SplashCoord y2, + SplashCoord x3, SplashCoord y3, + SplashCoord flatness, + GBool first, GBool last, GBool end0, GBool end1); + void addSegment(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + GBool first, GBool last, GBool end0, GBool end1); + + SplashXPathSeg *segs; + int length, size; // length and size of segs array + + friend class SplashXPathScanner; + friend class SplashClip; + friend class Splash; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashXPathScanner.cc swftools-0.9.1/lib/pdf/xpdf/SplashXPathScanner.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashXPathScanner.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashXPathScanner.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,428 @@ +//======================================================================== +// +// SplashXPathScanner.cc +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "SplashMath.h" +#include "SplashXPath.h" +#include "SplashBitmap.h" +#include "SplashXPathScanner.h" + +//------------------------------------------------------------------------ + +struct SplashIntersect { + int x0, x1; // intersection of segment with [y, y+1) + int count; // EO/NZWN counter increment +}; + +static int cmpIntersect(const void *p0, const void *p1) { + return ((SplashIntersect *)p0)->x0 - ((SplashIntersect *)p1)->x0; +} + +//------------------------------------------------------------------------ +// SplashXPathScanner +//------------------------------------------------------------------------ + +SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA) { + SplashXPathSeg *seg; + SplashCoord xMinFP, yMinFP, xMaxFP, yMaxFP; + int i; + + xPath = xPathA; + eo = eoA; + + // compute the bbox + if (xPath->length == 0) { + xMin = yMin = 1; + xMax = yMax = 0; + } else { + seg = &xPath->segs[0]; + if (seg->x0 <= seg->x1) { + xMinFP = seg->x0; + xMaxFP = seg->x1; + } else { + xMinFP = seg->x1; + xMaxFP = seg->x0; + } + if (seg->flags & splashXPathFlip) { + yMinFP = seg->y1; + yMaxFP = seg->y0; + } else { + yMinFP = seg->y0; + yMaxFP = seg->y1; + } + for (i = 1; i < xPath->length; ++i) { + seg = &xPath->segs[i]; + if (seg->x0 < xMinFP) { + xMinFP = seg->x0; + } else if (seg->x0 > xMaxFP) { + xMaxFP = seg->x0; + } + if (seg->x1 < xMinFP) { + xMinFP = seg->x1; + } else if (seg->x1 > xMaxFP) { + xMaxFP = seg->x1; + } + if (seg->flags & splashXPathFlip) { + if (seg->y0 > yMaxFP) { + yMaxFP = seg->y0; + } + } else { + if (seg->y1 > yMaxFP) { + yMaxFP = seg->y1; + } + } + } + xMin = splashFloor(xMinFP); + xMax = splashFloor(xMaxFP); + yMin = splashFloor(yMinFP); + yMax = splashFloor(yMaxFP); + } + + interY = yMin - 1; + xPathIdx = 0; + inter = NULL; + interLen = interSize = 0; +} + +SplashXPathScanner::~SplashXPathScanner() { + gfree(inter); +} + +void SplashXPathScanner::getBBoxAA(int *xMinA, int *yMinA, + int *xMaxA, int *yMaxA) { + *xMinA = xMin / splashAASize; + *yMinA = yMin / splashAASize; + *xMaxA = xMax / splashAASize; + *yMaxA = yMax / splashAASize; +} + +void SplashXPathScanner::getSpanBounds(int y, int *spanXMin, int *spanXMax) { + if (interY != y) { + computeIntersections(y); + } + if (interLen > 0) { + *spanXMin = inter[0].x0; + *spanXMax = inter[interLen - 1].x1; + } else { + *spanXMin = xMax + 1; + *spanXMax = xMax; + } +} + +GBool SplashXPathScanner::test(int x, int y) { + int count, i; + + if (interY != y) { + computeIntersections(y); + } + count = 0; + for (i = 0; i < interLen && inter[i].x0 <= x; ++i) { + if (x <= inter[i].x1) { + return gTrue; + } + count += inter[i].count; + } + return eo ? (count & 1) : (count != 0); +} + +GBool SplashXPathScanner::testSpan(int x0, int x1, int y) { + int count, xx1, i; + + if (interY != y) { + computeIntersections(y); + } + + count = 0; + for (i = 0; i < interLen && inter[i].x1 < x0; ++i) { + count += inter[i].count; + } + + // invariant: the subspan [x0,xx1] is inside the path + xx1 = x0 - 1; + while (xx1 < x1) { + if (i >= interLen) { + return gFalse; + } + if (inter[i].x0 > xx1 + 1 && + !(eo ? (count & 1) : (count != 0))) { + return gFalse; + } + if (inter[i].x1 > xx1) { + xx1 = inter[i].x1; + } + count += inter[i].count; + ++i; + } + + return gTrue; +} + +GBool SplashXPathScanner::getNextSpan(int y, int *x0, int *x1) { + int xx0, xx1; + + if (interY != y) { + computeIntersections(y); + } + if (interIdx >= interLen) { + return gFalse; + } + xx0 = inter[interIdx].x0; + xx1 = inter[interIdx].x1; + interCount += inter[interIdx].count; + ++interIdx; + while (interIdx < interLen && + (inter[interIdx].x0 <= xx1 || + (eo ? (interCount & 1) : (interCount != 0)))) { + if (inter[interIdx].x1 > xx1) { + xx1 = inter[interIdx].x1; + } + interCount += inter[interIdx].count; + ++interIdx; + } + *x0 = xx0; + *x1 = xx1; + return gTrue; +} + +void SplashXPathScanner::computeIntersections(int y) { + SplashCoord xSegMin, xSegMax, ySegMin, ySegMax, xx0, xx1; + SplashXPathSeg *seg; + int i, j; + + // find the first segment that intersects [y, y+1) + i = (y >= interY) ? xPathIdx : 0; + while (i < xPath->length && + xPath->segs[i].y0 < y && xPath->segs[i].y1 < y) { + ++i; + } + xPathIdx = i; + + // find all of the segments that intersect [y, y+1) and create an + // Intersect element for each one + interLen = 0; + for (j = i; j < xPath->length; ++j) { + seg = &xPath->segs[j]; + if (seg->flags & splashXPathFlip) { + ySegMin = seg->y1; + ySegMax = seg->y0; + } else { + ySegMin = seg->y0; + ySegMax = seg->y1; + } + + // ensure that: ySegMin < y+1 + // y <= ySegMax + if (ySegMin >= y + 1) { + break; + } + if (ySegMax < y) { + continue; + } + + if (interLen == interSize) { + if (interSize == 0) { + interSize = 16; + } else { + interSize *= 2; + } + inter = (SplashIntersect *)greallocn(inter, interSize, + sizeof(SplashIntersect)); + } + + if (seg->flags & splashXPathHoriz) { + xx0 = seg->x0; + xx1 = seg->x1; + } else if (seg->flags & splashXPathVert) { + xx0 = xx1 = seg->x0; + } else { + if (seg->x0 < seg->x1) { + xSegMin = seg->x0; + xSegMax = seg->x1; + } else { + xSegMin = seg->x1; + xSegMax = seg->x0; + } + // intersection with top edge + xx0 = seg->x0 + ((SplashCoord)y - seg->y0) * seg->dxdy; + // intersection with bottom edge + xx1 = seg->x0 + ((SplashCoord)y + 1 - seg->y0) * seg->dxdy; + // the segment may not actually extend to the top and/or bottom edges + if (xx0 < xSegMin) { + xx0 = xSegMin; + } else if (xx0 > xSegMax) { + xx0 = xSegMax; + } + if (xx1 < xSegMin) { + xx1 = xSegMin; + } else if (xx1 > xSegMax) { + xx1 = xSegMax; + } + } + if (xx0 < xx1) { + inter[interLen].x0 = splashFloor(xx0); + inter[interLen].x1 = splashFloor(xx1); + } else { + inter[interLen].x0 = splashFloor(xx1); + inter[interLen].x1 = splashFloor(xx0); + } + if (ySegMin <= y && + (SplashCoord)y < ySegMax && + !(seg->flags & splashXPathHoriz)) { + inter[interLen].count = eo ? 1 + : (seg->flags & splashXPathFlip) ? 1 : -1; + } else { + inter[interLen].count = 0; + } + ++interLen; + } + + qsort(inter, interLen, sizeof(SplashIntersect), &cmpIntersect); + + interY = y; + interIdx = 0; + interCount = 0; +} + +void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf, + int *x0, int *x1, int y) { + int xx0, xx1, xx, xxMin, xxMax, yy; + Guchar mask; + SplashColorPtr p; + + memset(aaBuf->getDataPtr(), 0, aaBuf->getRowSize() * aaBuf->getHeight()); + xxMin = aaBuf->getWidth(); + xxMax = -1; + for (yy = 0; yy < splashAASize; ++yy) { + computeIntersections(splashAASize * y + yy); + while (interIdx < interLen) { + xx0 = inter[interIdx].x0; + xx1 = inter[interIdx].x1; + interCount += inter[interIdx].count; + ++interIdx; + while (interIdx < interLen && + (inter[interIdx].x0 <= xx1 || + (eo ? (interCount & 1) : (interCount != 0)))) { + if (inter[interIdx].x1 > xx1) { + xx1 = inter[interIdx].x1; + } + interCount += inter[interIdx].count; + ++interIdx; + } + if (xx0 < 0) { + xx0 = 0; + } + ++xx1; + if (xx1 > aaBuf->getWidth()) { + xx1 = aaBuf->getWidth(); + } + // set [xx0, xx1) to 1 + if (xx0 < xx1) { + xx = xx0; + p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3); + if (xx & 7) { + mask = 0xff >> (xx & 7); + if ((xx & ~7) == (xx1 & ~7)) { + mask &= (Guchar)(0xff00 >> (xx1 & 7)); + } + *p++ |= mask; + xx = (xx & ~7) + 8; + } + for (; xx + 7 < xx1; xx += 8) { + *p++ |= 0xff; + } + if (xx < xx1) { + *p |= (Guchar)(0xff00 >> (xx1 & 7)); + } + } + if (xx0 < xxMin) { + xxMin = xx0; + } + if (xx1 > xxMax) { + xxMax = xx1; + } + } + } + *x0 = xxMin / splashAASize; + *x1 = (xxMax - 1) / splashAASize; +} + +void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf, + int *x0, int *x1, int y) { + int xx0, xx1, xx, yy; + Guchar mask; + SplashColorPtr p; + + for (yy = 0; yy < splashAASize; ++yy) { + xx = *x0 * splashAASize; + computeIntersections(splashAASize * y + yy); + while (interIdx < interLen && xx < (*x1 + 1) * splashAASize) { + xx0 = inter[interIdx].x0; + xx1 = inter[interIdx].x1; + interCount += inter[interIdx].count; + ++interIdx; + while (interIdx < interLen && + (inter[interIdx].x0 <= xx1 || + (eo ? (interCount & 1) : (interCount != 0)))) { + if (inter[interIdx].x1 > xx1) { + xx1 = inter[interIdx].x1; + } + interCount += inter[interIdx].count; + ++interIdx; + } + if (xx0 > aaBuf->getWidth()) { + xx0 = aaBuf->getWidth(); + } + // set [xx, xx0) to 0 + if (xx < xx0) { + p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3); + if (xx & 7) { + mask = (Guchar)(0xff00 >> (xx & 7)); + if ((xx & ~7) == (xx0 & ~7)) { + mask |= 0xff >> (xx0 & 7); + } + *p++ &= mask; + xx = (xx & ~7) + 8; + } + for (; xx + 7 < xx0; xx += 8) { + *p++ = 0x00; + } + if (xx < xx0) { + *p &= 0xff >> (xx0 & 7); + } + } + if (xx1 >= xx) { + xx = xx1 + 1; + } + } + xx0 = (*x1 + 1) * splashAASize; + // set [xx, xx0) to 0 + if (xx < xx0) { + p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3); + if (xx & 7) { + mask = (Guchar)(0xff00 >> (xx & 7)); + if ((xx & ~7) == (xx0 & ~7)) { + mask &= 0xff >> (xx0 & 7); + } + *p++ &= mask; + xx = (xx & ~7) + 8; + } + for (; xx + 7 < xx0; xx += 8) { + *p++ = 0x00; + } + if (xx < xx0) { + *p &= 0xff >> (xx0 & 7); + } + } + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/SplashXPathScanner.h swftools-0.9.1/lib/pdf/xpdf/SplashXPathScanner.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/SplashXPathScanner.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/SplashXPathScanner.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,87 @@ +//======================================================================== +// +// SplashXPathScanner.h +// +//======================================================================== + +#ifndef SPLASHXPATHSCANNER_H +#define SPLASHXPATHSCANNER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "SplashTypes.h" + +class SplashXPath; +class SplashBitmap; +struct SplashIntersect; + +//------------------------------------------------------------------------ +// SplashXPathScanner +//------------------------------------------------------------------------ + +class SplashXPathScanner { +public: + + // Create a new SplashXPathScanner object. must be sorted. + SplashXPathScanner(SplashXPath *xPathA, GBool eoA); + + ~SplashXPathScanner(); + + // Return the path's bounding box. + void getBBox(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA) + { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; } + + // Return the path's bounding box. + void getBBoxAA(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA); + + // Return the min/max x values for the span at . + void getSpanBounds(int y, int *spanXMin, int *spanXMax); + + // Returns true if (,) is inside the path. + GBool test(int x, int y); + + // Returns true if the entire span ([,], ) is inside the + // path. + GBool testSpan(int x0, int x1, int y); + + // Returns the next span inside the path at . If is + // different than the previous call to getNextSpan, this returns the + // first span at ; otherwise it returns the next span (relative + // to the previous call to getNextSpan). Returns false if there are + // no more spans at . + GBool getNextSpan(int y, int *x0, int *x1); + + // Renders one anti-aliased line into . Returns the min and + // max x coordinates with non-zero pixels in and . + void renderAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y); + + // Clips an anti-aliased line by setting pixels to zero. On entry, + // all non-zero pixels are between and . This function + // will update and . + void clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y); + +private: + + void computeIntersections(int y); + + SplashXPath *xPath; + GBool eo; + int xMin, yMin, xMax, yMax; + + int interY; // current y value + int interIdx; // current index into - used by + // getNextSpan + int interCount; // current EO/NZWN counter - used by + // getNextSpan + int xPathIdx; // current index into - used by + // computeIntersections + SplashIntersect *inter; // intersections array for + int interLen; // number of intersections in + int interSize; // size of the array +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Stream.cc swftools-0.9.1/lib/pdf/xpdf/Stream.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/Stream.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Stream.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,4644 @@ +//======================================================================== +// +// Stream.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#ifndef WIN32 +#include +#else +extern "C" int unlink(char *filename); +#endif +#include +#include +#include "gmem.h" +#include "gfile.h" +#include "config.h" +#include "Error.h" +#include "Object.h" +#include "Lexer.h" +#include "GfxState.h" +#include "Stream.h" +#include "JBIG2Stream.h" +#include "JPXStream.h" +#include "Stream-CCITT.h" + +#ifdef __DJGPP__ +static GBool setDJSYSFLAGS = gFalse; +#endif + +#ifdef VMS +#ifdef __GNUC__ +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif +#endif + +//------------------------------------------------------------------------ +// Stream (base class) +//------------------------------------------------------------------------ + +Stream::Stream() { + ref = 1; +} + +Stream::~Stream() { +} + +void Stream::close() { +} + +int Stream::getRawChar() { + error(-1, "Internal: called getRawChar() on non-predictor stream"); + return EOF; +} + +char *Stream::getLine(char *buf, int size) { + int i; + int c; + + if (lookChar() == EOF) + return NULL; + for (i = 0; i < size - 1; ++i) { + c = getChar(); + if (c == EOF || c == '\n') + break; + if (c == '\r') { + if ((c = lookChar()) == '\n') + getChar(); + break; + } + buf[i] = c; + } + buf[i] = '\0'; + return buf; +} + +GString *Stream::getPSFilter(int psLevel, char *indent) { + return new GString(); +} + +Stream *Stream::addFilters(Object *dict) { + Object obj, obj2; + Object params, params2; + Stream *str; + int i; + + str = this; + dict->dictLookup("Filter", &obj); + if (obj.isNull()) { + obj.free(); + dict->dictLookup("F", &obj); + } + dict->dictLookup("DecodeParms", ¶ms); + if (params.isNull()) { + params.free(); + dict->dictLookup("DP", ¶ms); + } + if (obj.isName()) { + str = makeFilter(obj.getName(), str, ¶ms); + } else if (obj.isArray()) { + for (i = 0; i < obj.arrayGetLength(); ++i) { + obj.arrayGet(i, &obj2); + if (params.isArray()) + params.arrayGet(i, ¶ms2); + else + params2.initNull(); + if (obj2.isName()) { + str = makeFilter(obj2.getName(), str, ¶ms2); + } else { + error(getPos(), "Bad filter name"); + str = new EOFStream(str); + } + obj2.free(); + params2.free(); + } + } else if (!obj.isNull()) { + error(getPos(), "Bad 'Filter' attribute in stream"); + } + obj.free(); + params.free(); + + return str; +} + +Stream *Stream::makeFilter(char *name, Stream *str, Object *params) { + int pred; // parameters + int colors; + int bits; + int early; + int encoding; + GBool endOfLine, byteAlign, endOfBlock, black; + int columns, rows; + int colorXform; + Object globals, obj; + + if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) { + str = new ASCIIHexStream(str); + } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) { + str = new ASCII85Stream(str); + } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) { + pred = 1; + columns = 1; + colors = 1; + bits = 8; + early = 1; + if (params->isDict()) { + params->dictLookup("Predictor", &obj); + if (obj.isInt()) + pred = obj.getInt(); + obj.free(); + params->dictLookup("Columns", &obj); + if (obj.isInt()) + columns = obj.getInt(); + obj.free(); + params->dictLookup("Colors", &obj); + if (obj.isInt()) + colors = obj.getInt(); + obj.free(); + params->dictLookup("BitsPerComponent", &obj); + if (obj.isInt()) + bits = obj.getInt(); + obj.free(); + params->dictLookup("EarlyChange", &obj); + if (obj.isInt()) + early = obj.getInt(); + obj.free(); + } + str = new LZWStream(str, pred, columns, colors, bits, early); + } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) { + str = new RunLengthStream(str); + } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) { + encoding = 0; + endOfLine = gFalse; + byteAlign = gFalse; + columns = 1728; + rows = 0; + endOfBlock = gTrue; + black = gFalse; + if (params->isDict()) { + params->dictLookup("K", &obj); + if (obj.isInt()) { + encoding = obj.getInt(); + } + obj.free(); + params->dictLookup("EndOfLine", &obj); + if (obj.isBool()) { + endOfLine = obj.getBool(); + } + obj.free(); + params->dictLookup("EncodedByteAlign", &obj); + if (obj.isBool()) { + byteAlign = obj.getBool(); + } + obj.free(); + params->dictLookup("Columns", &obj); + if (obj.isInt()) { + columns = obj.getInt(); + } + obj.free(); + params->dictLookup("Rows", &obj); + if (obj.isInt()) { + rows = obj.getInt(); + } + obj.free(); + params->dictLookup("EndOfBlock", &obj); + if (obj.isBool()) { + endOfBlock = obj.getBool(); + } + obj.free(); + params->dictLookup("BlackIs1", &obj); + if (obj.isBool()) { + black = obj.getBool(); + } + obj.free(); + } + str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign, + columns, rows, endOfBlock, black); + } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) { + colorXform = -1; + if (params->isDict()) { + if (params->dictLookup("ColorTransform", &obj)->isInt()) { + colorXform = obj.getInt(); + } + obj.free(); + } + str = new DCTStream(str, colorXform); + } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) { + pred = 1; + columns = 1; + colors = 1; + bits = 8; + if (params->isDict()) { + params->dictLookup("Predictor", &obj); + if (obj.isInt()) + pred = obj.getInt(); + obj.free(); + params->dictLookup("Columns", &obj); + if (obj.isInt()) + columns = obj.getInt(); + obj.free(); + params->dictLookup("Colors", &obj); + if (obj.isInt()) + colors = obj.getInt(); + obj.free(); + params->dictLookup("BitsPerComponent", &obj); + if (obj.isInt()) + bits = obj.getInt(); + obj.free(); + } + str = new FlateStream(str, pred, columns, colors, bits); + } else if (!strcmp(name, "JBIG2Decode")) { + if (params->isDict()) { + params->dictLookup("JBIG2Globals", &globals); + } + str = new JBIG2Stream(str, &globals); + globals.free(); + } else if (!strcmp(name, "JPXDecode")) { + str = new JPXStream(str); + } else { + error(getPos(), "Unknown filter '%s'", name); + str = new EOFStream(str); + } + return str; +} + +//------------------------------------------------------------------------ +// BaseStream +//------------------------------------------------------------------------ + +BaseStream::BaseStream(Object *dictA) { + dict = *dictA; +} + +BaseStream::~BaseStream() { + dict.free(); +} + +//------------------------------------------------------------------------ +// FilterStream +//------------------------------------------------------------------------ + +FilterStream::FilterStream(Stream *strA) { + str = strA; +} + +FilterStream::~FilterStream() { +} + +void FilterStream::close() { + str->close(); +} + +void FilterStream::setPos(Guint pos, int dir) { + error(-1, "Internal: called setPos() on FilterStream"); +} + +//------------------------------------------------------------------------ +// ImageStream +//------------------------------------------------------------------------ + +ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) { + int imgLineSize; + + str = strA; + width = widthA; + nComps = nCompsA; + nBits = nBitsA; + + nVals = width * nComps; + if (nBits == 1) { + imgLineSize = (nVals + 7) & ~7; + } else { + imgLineSize = nVals; + } + imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar)); + imgIdx = nVals; +} + +ImageStream::~ImageStream() { + gfree(imgLine); +} + +void ImageStream::reset() { + str->reset(); +} + +GBool ImageStream::getPixel(Guchar *pix) { + int i; + + if (imgIdx >= nVals) { + getLine(); + imgIdx = 0; + } + for (i = 0; i < nComps; ++i) { + pix[i] = imgLine[imgIdx++]; + } + return gTrue; +} + +Guchar *ImageStream::getLine() { + Gulong buf, bitMask; + int bits; + int c; + int i; + + if (nBits == 1) { + for (i = 0; i < nVals; i += 8) { + c = str->getChar(); + imgLine[i+0] = (Guchar)((c >> 7) & 1); + imgLine[i+1] = (Guchar)((c >> 6) & 1); + imgLine[i+2] = (Guchar)((c >> 5) & 1); + imgLine[i+3] = (Guchar)((c >> 4) & 1); + imgLine[i+4] = (Guchar)((c >> 3) & 1); + imgLine[i+5] = (Guchar)((c >> 2) & 1); + imgLine[i+6] = (Guchar)((c >> 1) & 1); + imgLine[i+7] = (Guchar)(c & 1); + } + } else if (nBits == 8) { + for (i = 0; i < nVals; ++i) { + imgLine[i] = str->getChar(); + } + } else { + bitMask = (1 << nBits) - 1; + buf = 0; + bits = 0; + for (i = 0; i < nVals; ++i) { + if (bits < nBits) { + buf = (buf << 8) | (str->getChar() & 0xff); + bits += 8; + } + imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask); + bits -= nBits; + } + } + return imgLine; +} + +void ImageStream::skipLine() { + int n, i; + + n = (nVals * nBits + 7) >> 3; + for (i = 0; i < n; ++i) { + str->getChar(); + } +} + +//------------------------------------------------------------------------ +// StreamPredictor +//------------------------------------------------------------------------ + +StreamPredictor::StreamPredictor(Stream *strA, int predictorA, + int widthA, int nCompsA, int nBitsA) { + str = strA; + predictor = predictorA; + width = widthA; + nComps = nCompsA; + nBits = nBitsA; + predLine = NULL; + ok = gFalse; + + nVals = width * nComps; + if (width <= 0 || nComps <= 0 || nBits <= 0 || + nComps >= INT_MAX / nBits || + width >= INT_MAX / nComps / nBits || + nVals * nBits + 7 < 0) { + return; + } + pixBytes = (nComps * nBits + 7) >> 3; + rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes; + if (rowBytes <= 0) { + return; + } + predLine = (Guchar *)gmalloc(rowBytes); + memset(predLine, 0, rowBytes); + predIdx = rowBytes; + + ok = gTrue; +} + +StreamPredictor::~StreamPredictor() { + gfree(predLine); +} + +int StreamPredictor::lookChar() { + if (predIdx >= rowBytes) { + if (!getNextLine()) { + return EOF; + } + } + return predLine[predIdx]; +} + +int StreamPredictor::getChar() { + if (predIdx >= rowBytes) { + if (!getNextLine()) { + return EOF; + } + } + return predLine[predIdx++]; +} + +GBool StreamPredictor::getNextLine() { + int curPred; + Guchar upLeftBuf[gfxColorMaxComps * 2 + 1]; + int left, up, upLeft, p, pa, pb, pc; + int c; + Gulong inBuf, outBuf, bitMask; + int inBits, outBits; + int i, j, k, kk; + + // get PNG optimum predictor number + if (predictor >= 10) { + if ((curPred = str->getRawChar()) == EOF) { + return gFalse; + } + curPred += 10; + } else { + curPred = predictor; + } + + // read the raw line, apply PNG (byte) predictor + memset(upLeftBuf, 0, pixBytes + 1); + for (i = pixBytes; i < rowBytes; ++i) { + for (j = pixBytes; j > 0; --j) { + upLeftBuf[j] = upLeftBuf[j-1]; + } + upLeftBuf[0] = predLine[i]; + if ((c = str->getRawChar()) == EOF) { + if (i > pixBytes) { + // this ought to return false, but some (broken) PDF files + // contain truncated image data, and Adobe apparently reads the + // last partial line + break; + } + return gFalse; + } + switch (curPred) { + case 11: // PNG sub + predLine[i] = predLine[i - pixBytes] + (Guchar)c; + break; + case 12: // PNG up + predLine[i] = predLine[i] + (Guchar)c; + break; + case 13: // PNG average + predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) + + (Guchar)c; + break; + case 14: // PNG Paeth + left = predLine[i - pixBytes]; + up = predLine[i]; + upLeft = upLeftBuf[pixBytes]; + p = left + up - upLeft; + if ((pa = p - left) < 0) + pa = -pa; + if ((pb = p - up) < 0) + pb = -pb; + if ((pc = p - upLeft) < 0) + pc = -pc; + if (pa <= pb && pa <= pc) + predLine[i] = left + (Guchar)c; + else if (pb <= pc) + predLine[i] = up + (Guchar)c; + else + predLine[i] = upLeft + (Guchar)c; + break; + case 10: // PNG none + default: // no predictor or TIFF predictor + predLine[i] = (Guchar)c; + break; + } + } + + // apply TIFF (component) predictor + if (predictor == 2) { + if (nBits == 1) { + inBuf = predLine[pixBytes - 1]; + for (i = pixBytes; i < rowBytes; i += 8) { + // 1-bit add is just xor + inBuf = (inBuf << 8) | predLine[i]; + predLine[i] ^= inBuf >> nComps; + } + } else if (nBits == 8) { + for (i = pixBytes; i < rowBytes; ++i) { + predLine[i] += predLine[i - nComps]; + } + } else { + memset(upLeftBuf, 0, nComps + 1); + bitMask = (1 << nBits) - 1; + inBuf = outBuf = 0; + inBits = outBits = 0; + j = k = pixBytes; + for (i = 0; i < width; ++i) { + for (kk = 0; kk < nComps; ++kk) { + if (inBits < nBits) { + inBuf = (inBuf << 8) | (predLine[j++] & 0xff); + inBits += 8; + } + upLeftBuf[kk] = (Guchar)((upLeftBuf[kk] + + (inBuf >> (inBits - nBits))) & bitMask); + inBits -= nBits; + outBuf = (outBuf << nBits) | upLeftBuf[kk]; + outBits += nBits; + if (outBits >= 8) { + predLine[k++] = (Guchar)(outBuf >> (outBits - 8)); + outBits -= 8; + } + } + } + if (outBits > 0) { + predLine[k++] = (Guchar)((outBuf << (8 - outBits)) + + (inBuf & ((1 << (8 - outBits)) - 1))); + } + } + } + + // reset to start of line + predIdx = pixBytes; + + return gTrue; +} + +//------------------------------------------------------------------------ +// FileStream +//------------------------------------------------------------------------ + +FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA, + Guint lengthA, Object *dictA): + BaseStream(dictA) { + f = fA; + start = startA; + limited = limitedA; + length = lengthA; + bufPtr = bufEnd = buf; + bufPos = start; + savePos = 0; + saved = gFalse; +} + +FileStream::~FileStream() { + close(); +} + +Stream *FileStream::makeSubStream(Guint startA, GBool limitedA, + Guint lengthA, Object *dictA) { + return new FileStream(f, startA, limitedA, lengthA, dictA); +} + +void FileStream::reset() { +#if HAVE_FSEEKO + savePos = (Guint)ftello(f); + fseeko(f, start, SEEK_SET); +#elif HAVE_FSEEK64 + savePos = (Guint)ftell64(f); + fseek64(f, start, SEEK_SET); +#else + savePos = (Guint)ftell(f); + fseek(f, start, SEEK_SET); +#endif + saved = gTrue; + bufPtr = bufEnd = buf; + bufPos = start; +} + +void FileStream::close() { + if (saved) { +#if HAVE_FSEEKO + fseeko(f, savePos, SEEK_SET); +#elif HAVE_FSEEK64 + fseek64(f, savePos, SEEK_SET); +#else + fseek(f, savePos, SEEK_SET); +#endif + saved = gFalse; + } +} + +GBool FileStream::fillBuf() { + int n; + + bufPos += bufEnd - buf; + bufPtr = bufEnd = buf; + if (limited && bufPos >= start + length) { + return gFalse; + } + if (limited && bufPos + fileStreamBufSize > start + length) { + n = start + length - bufPos; + } else { + n = fileStreamBufSize; + } + n = fread(buf, 1, n, f); + bufEnd = buf + n; + if (bufPtr >= bufEnd) { + return gFalse; + } + return gTrue; +} + +void FileStream::setPos(Guint pos, int dir) { + Guint size; + + if (dir >= 0) { +#if HAVE_FSEEKO + fseeko(f, pos, SEEK_SET); +#elif HAVE_FSEEK64 + fseek64(f, pos, SEEK_SET); +#else + fseek(f, pos, SEEK_SET); +#endif + bufPos = pos; + } else { +#if HAVE_FSEEKO + fseeko(f, 0, SEEK_END); + size = (Guint)ftello(f); +#elif HAVE_FSEEK64 + fseek64(f, 0, SEEK_END); + size = (Guint)ftell64(f); +#else + fseek(f, 0, SEEK_END); + size = (Guint)ftell(f); +#endif + if (pos > size) + pos = (Guint)size; +#ifdef __CYGWIN32__ + //~ work around a bug in cygwin's implementation of fseek + rewind(f); +#endif +#if HAVE_FSEEKO + fseeko(f, -(int)pos, SEEK_END); + bufPos = (Guint)ftello(f); +#elif HAVE_FSEEK64 + fseek64(f, -(int)pos, SEEK_END); + bufPos = (Guint)ftell64(f); +#else + fseek(f, -(int)pos, SEEK_END); + bufPos = (Guint)ftell(f); +#endif + } + bufPtr = bufEnd = buf; +} + +void FileStream::moveStart(int delta) { + start += delta; + bufPtr = bufEnd = buf; + bufPos = start; +} + +//------------------------------------------------------------------------ +// MemStream +//------------------------------------------------------------------------ + +MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA): + BaseStream(dictA) { + buf = bufA; + start = startA; + length = lengthA; + bufEnd = buf + start + length; + bufPtr = buf + start; + needFree = gFalse; +} + +MemStream::~MemStream() { + if (needFree) { + gfree(buf); + } +} + +Stream *MemStream::makeSubStream(Guint startA, GBool limited, + Guint lengthA, Object *dictA) { + MemStream *subStr; + Guint newLength; + + if (!limited || startA + lengthA > start + length) { + newLength = start + length - startA; + } else { + newLength = lengthA; + } + subStr = new MemStream(buf, startA, newLength, dictA); + return subStr; +} + +void MemStream::reset() { + bufPtr = buf + start; +} + +void MemStream::close() { +} + +void MemStream::setPos(Guint pos, int dir) { + Guint i; + + if (dir >= 0) { + i = pos; + } else { + i = start + length - pos; + } + if (i < start) { + i = start; + } else if (i > start + length) { + i = start + length; + } + bufPtr = buf + i; +} + +void MemStream::moveStart(int delta) { + start += delta; + length -= delta; + bufPtr = buf + start; +} + +//------------------------------------------------------------------------ +// EmbedStream +//------------------------------------------------------------------------ + +EmbedStream::EmbedStream(Stream *strA, Object *dictA, + GBool limitedA, Guint lengthA): + BaseStream(dictA) { + str = strA; + limited = limitedA; + length = lengthA; +} + +EmbedStream::~EmbedStream() { +} + +Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA, + Guint lengthA, Object *dictA) { + error(-1, "Internal: called makeSubStream() on EmbedStream"); + return NULL; +} + +int EmbedStream::getChar() { + if (limited && !length) { + return EOF; + } + --length; + return str->getChar(); +} + +int EmbedStream::lookChar() { + if (limited && !length) { + return EOF; + } + return str->lookChar(); +} + +void EmbedStream::setPos(Guint pos, int dir) { + error(-1, "Internal: called setPos() on EmbedStream"); +} + +Guint EmbedStream::getStart() { + error(-1, "Internal: called getStart() on EmbedStream"); + return 0; +} + +void EmbedStream::moveStart(int delta) { + error(-1, "Internal: called moveStart() on EmbedStream"); +} + +//------------------------------------------------------------------------ +// ASCIIHexStream +//------------------------------------------------------------------------ + +ASCIIHexStream::ASCIIHexStream(Stream *strA): + FilterStream(strA) { + buf = EOF; + eof = gFalse; +} + +ASCIIHexStream::~ASCIIHexStream() { + delete str; +} + +void ASCIIHexStream::reset() { + str->reset(); + buf = EOF; + eof = gFalse; +} + +int ASCIIHexStream::lookChar() { + int c1, c2, x; + + if (buf != EOF) + return buf; + if (eof) { + buf = EOF; + return EOF; + } + do { + c1 = str->getChar(); + } while (isspace(c1)); + if (c1 == '>') { + eof = gTrue; + buf = EOF; + return buf; + } + do { + c2 = str->getChar(); + } while (isspace(c2)); + if (c2 == '>') { + eof = gTrue; + c2 = '0'; + } + if (c1 >= '0' && c1 <= '9') { + x = (c1 - '0') << 4; + } else if (c1 >= 'A' && c1 <= 'F') { + x = (c1 - 'A' + 10) << 4; + } else if (c1 >= 'a' && c1 <= 'f') { + x = (c1 - 'a' + 10) << 4; + } else if (c1 == EOF) { + eof = gTrue; + x = 0; + } else { + error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1); + x = 0; + } + if (c2 >= '0' && c2 <= '9') { + x += c2 - '0'; + } else if (c2 >= 'A' && c2 <= 'F') { + x += c2 - 'A' + 10; + } else if (c2 >= 'a' && c2 <= 'f') { + x += c2 - 'a' + 10; + } else if (c2 == EOF) { + eof = gTrue; + x = 0; + } else { + error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2); + } + buf = x & 0xff; + return buf; +} + +GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) { + GString *s; + + if (psLevel < 2) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent))) { + return NULL; + } + s->append(indent)->append("/ASCIIHexDecode filter\n"); + return s; +} + +GBool ASCIIHexStream::isBinary(GBool last) { + return str->isBinary(gFalse); +} + +//------------------------------------------------------------------------ +// ASCII85Stream +//------------------------------------------------------------------------ + +ASCII85Stream::ASCII85Stream(Stream *strA): + FilterStream(strA) { + index = n = 0; + eof = gFalse; +} + +ASCII85Stream::~ASCII85Stream() { + delete str; +} + +void ASCII85Stream::reset() { + str->reset(); + index = n = 0; + eof = gFalse; +} + +int ASCII85Stream::lookChar() { + int k; + Gulong t; + + if (index >= n) { + if (eof) + return EOF; + index = 0; + do { + c[0] = str->getChar(); + } while (Lexer::isSpace(c[0])); + if (c[0] == '~' || c[0] == EOF) { + eof = gTrue; + n = 0; + return EOF; + } else if (c[0] == 'z') { + b[0] = b[1] = b[2] = b[3] = 0; + n = 4; + } else { + for (k = 1; k < 5; ++k) { + do { + c[k] = str->getChar(); + } while (Lexer::isSpace(c[k])); + if (c[k] == '~' || c[k] == EOF) + break; + } + n = k - 1; + if (k < 5 && (c[k] == '~' || c[k] == EOF)) { + for (++k; k < 5; ++k) + c[k] = 0x21 + 84; + eof = gTrue; + } + t = 0; + for (k = 0; k < 5; ++k) + t = t * 85 + (c[k] - 0x21); + for (k = 3; k >= 0; --k) { + b[k] = (int)(t & 0xff); + t >>= 8; + } + } + } + return b[index]; +} + +GString *ASCII85Stream::getPSFilter(int psLevel, char *indent) { + GString *s; + + if (psLevel < 2) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent))) { + return NULL; + } + s->append(indent)->append("/ASCII85Decode filter\n"); + return s; +} + +GBool ASCII85Stream::isBinary(GBool last) { + return str->isBinary(gFalse); +} + +//------------------------------------------------------------------------ +// LZWStream +//------------------------------------------------------------------------ + +LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors, + int bits, int earlyA): + FilterStream(strA) { + if (predictor != 1) { + pred = new StreamPredictor(this, predictor, columns, colors, bits); + if (!pred->isOk()) { + delete pred; + pred = NULL; + } + } else { + pred = NULL; + } + early = earlyA; + eof = gFalse; + inputBits = 0; + clearTable(); +} + +LZWStream::~LZWStream() { + if (pred) { + delete pred; + } + delete str; +} + +int LZWStream::getChar() { + if (pred) { + return pred->getChar(); + } + if (eof) { + return EOF; + } + if (seqIndex >= seqLength) { + if (!processNextCode()) { + return EOF; + } + } + return seqBuf[seqIndex++]; +} + +int LZWStream::lookChar() { + if (pred) { + return pred->lookChar(); + } + if (eof) { + return EOF; + } + if (seqIndex >= seqLength) { + if (!processNextCode()) { + return EOF; + } + } + return seqBuf[seqIndex]; +} + +int LZWStream::getRawChar() { + if (eof) { + return EOF; + } + if (seqIndex >= seqLength) { + if (!processNextCode()) { + return EOF; + } + } + return seqBuf[seqIndex++]; +} + +void LZWStream::reset() { + str->reset(); + eof = gFalse; + inputBits = 0; + clearTable(); +} + +GBool LZWStream::processNextCode() { + int code; + int nextLength; + int i, j; + + // check for EOF + if (eof) { + return gFalse; + } + + // check for eod and clear-table codes + start: + code = getCode(); + if (code == EOF || code == 257) { + eof = gTrue; + return gFalse; + } + if (code == 256) { + clearTable(); + goto start; + } + if (nextCode >= 4097) { + error(getPos(), "Bad LZW stream - expected clear-table code"); + clearTable(); + } + + // process the next code + nextLength = seqLength + 1; + if (code < 256) { + seqBuf[0] = code; + seqLength = 1; + } else if (code < nextCode) { + seqLength = table[code].length; + for (i = seqLength - 1, j = code; i > 0; --i) { + seqBuf[i] = table[j].tail; + j = table[j].head; + } + seqBuf[0] = j; + } else if (code == nextCode) { + seqBuf[seqLength] = newChar; + ++seqLength; + } else { + error(getPos(), "Bad LZW stream - unexpected code"); + eof = gTrue; + return gFalse; + } + newChar = seqBuf[0]; + if (first) { + first = gFalse; + } else { + table[nextCode].length = nextLength; + table[nextCode].head = prevCode; + table[nextCode].tail = newChar; + ++nextCode; + if (nextCode + early == 512) + nextBits = 10; + else if (nextCode + early == 1024) + nextBits = 11; + else if (nextCode + early == 2048) + nextBits = 12; + } + prevCode = code; + + // reset buffer + seqIndex = 0; + + return gTrue; +} + +void LZWStream::clearTable() { + nextCode = 258; + nextBits = 9; + seqIndex = seqLength = 0; + first = gTrue; +} + +int LZWStream::getCode() { + int c; + int code; + + while (inputBits < nextBits) { + if ((c = str->getChar()) == EOF) + return EOF; + inputBuf = (inputBuf << 8) | (c & 0xff); + inputBits += 8; + } + code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1); + inputBits -= nextBits; + return code; +} + +GString *LZWStream::getPSFilter(int psLevel, char *indent) { + GString *s; + + if (psLevel < 2 || pred) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent))) { + return NULL; + } + s->append(indent)->append("<< "); + if (!early) { + s->append("/EarlyChange 0 "); + } + s->append(">> /LZWDecode filter\n"); + return s; +} + +GBool LZWStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +//------------------------------------------------------------------------ +// RunLengthStream +//------------------------------------------------------------------------ + +RunLengthStream::RunLengthStream(Stream *strA): + FilterStream(strA) { + bufPtr = bufEnd = buf; + eof = gFalse; +} + +RunLengthStream::~RunLengthStream() { + delete str; +} + +void RunLengthStream::reset() { + str->reset(); + bufPtr = bufEnd = buf; + eof = gFalse; +} + +GString *RunLengthStream::getPSFilter(int psLevel, char *indent) { + GString *s; + + if (psLevel < 2) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent))) { + return NULL; + } + s->append(indent)->append("/RunLengthDecode filter\n"); + return s; +} + +GBool RunLengthStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +GBool RunLengthStream::fillBuf() { + int c; + int n, i; + + if (eof) + return gFalse; + c = str->getChar(); + if (c == 0x80 || c == EOF) { + eof = gTrue; + return gFalse; + } + if (c < 0x80) { + n = c + 1; + for (i = 0; i < n; ++i) + buf[i] = (char)str->getChar(); + } else { + n = 0x101 - c; + c = str->getChar(); + for (i = 0; i < n; ++i) + buf[i] = (char)c; + } + bufPtr = buf; + bufEnd = buf + n; + return gTrue; +} + +//------------------------------------------------------------------------ +// CCITTFaxStream +//------------------------------------------------------------------------ + +CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, + GBool byteAlignA, int columnsA, int rowsA, + GBool endOfBlockA, GBool blackA): + FilterStream(strA) { + encoding = encodingA; + endOfLine = endOfLineA; + byteAlign = byteAlignA; + columns = columnsA; + if (columns < 1) { + columns = 1; + } + if (columns + 4 <= 0) { + columns = INT_MAX - 4; + } + rows = rowsA; + endOfBlock = endOfBlockA; + black = blackA; + refLine = (short *)gmallocn(columns + 3, sizeof(short)); + codingLine = (short *)gmallocn(columns + 2, sizeof(short)); + + eof = gFalse; + row = 0; + nextLine2D = encoding < 0; + inputBits = 0; + codingLine[0] = 0; + codingLine[1] = refLine[2] = columns; + a0 = 1; + + buf = EOF; +} + +CCITTFaxStream::~CCITTFaxStream() { + delete str; + gfree(refLine); + gfree(codingLine); +} + +void CCITTFaxStream::reset() { + short code1; + + str->reset(); + eof = gFalse; + row = 0; + nextLine2D = encoding < 0; + inputBits = 0; + codingLine[0] = 0; + codingLine[1] = columns; + a0 = 1; + buf = EOF; + + // skip any initial zero bits and end-of-line marker, and get the 2D + // encoding tag + while ((code1 = lookBits(12)) == 0) { + eatBits(1); + } + if (code1 == 0x001) { + eatBits(12); + } + if (encoding > 0) { + nextLine2D = !lookBits(1); + eatBits(1); + } +} + +int CCITTFaxStream::lookChar() { + short code1, code2, code3; + int a0New; + GBool err, gotEOL; + int ret; + int bits, i; + + // if at eof just return EOF + if (eof && codingLine[a0] >= columns) { + return EOF; + } + + // read the next row + err = gFalse; + if (codingLine[a0] >= columns) { + + // 2-D encoding + if (nextLine2D) { + // state: + // a0New = current position in coding line (0 <= a0New <= columns) + // codingLine[a0] = last change in coding line + // (black-to-white if a0 is even, + // white-to-black if a0 is odd) + // refLine[b1] = next change in reference line of opposite color + // to a0 + // invariants: + // 0 <= codingLine[a0] <= a0New + // <= refLine[b1] <= refLine[b1+1] <= columns + // 0 <= a0 <= columns+1 + // refLine[0] = 0 + // refLine[n] = refLine[n+1] = columns + // -- for some 1 <= n <= columns+1 + // end condition: + // 0 = codingLine[0] <= codingLine[1] < codingLine[2] < ... + // < codingLine[n-1] < codingLine[n] = columns + // -- where 1 <= n <= columns+1 + for (i = 0; codingLine[i] < columns; ++i) { + refLine[i] = codingLine[i]; + } + refLine[i] = refLine[i + 1] = columns; + b1 = 1; + a0New = codingLine[a0 = 0] = 0; + do { + code1 = getTwoDimCode(); + switch (code1) { + case twoDimPass: + if (refLine[b1] < columns) { + a0New = refLine[b1 + 1]; + b1 += 2; + } + break; + case twoDimHoriz: + if ((a0 & 1) == 0) { + code1 = code2 = 0; + do { + code1 += code3 = getWhiteCode(); + } while (code3 >= 64); + do { + code2 += code3 = getBlackCode(); + } while (code3 >= 64); + } else { + code1 = code2 = 0; + do { + code1 += code3 = getBlackCode(); + } while (code3 >= 64); + do { + code2 += code3 = getWhiteCode(); + } while (code3 >= 64); + } + if (code1 > 0 || code2 > 0) { + if (a0New + code1 <= columns) { + codingLine[a0 + 1] = a0New + code1; + } else { + codingLine[a0 + 1] = columns; + } + ++a0; + if (codingLine[a0] + code2 <= columns) { + codingLine[a0 + 1] = codingLine[a0] + code2; + } else { + codingLine[a0 + 1] = columns; + } + ++a0; + a0New = codingLine[a0]; + while (refLine[b1] <= a0New && refLine[b1] < columns) { + b1 += 2; + } + } + break; + case twoDimVert0: + if (refLine[b1] < columns) { + a0New = codingLine[++a0] = refLine[b1]; + ++b1; + while (refLine[b1] <= a0New && refLine[b1] < columns) { + b1 += 2; + } + } else { + a0New = codingLine[++a0] = columns; + } + break; + case twoDimVertR1: + if (refLine[b1] + 1 < columns) { + a0New = codingLine[++a0] = refLine[b1] + 1; + ++b1; + while (refLine[b1] <= a0New && refLine[b1] < columns) { + b1 += 2; + } + } else { + a0New = codingLine[++a0] = columns; + } + break; + case twoDimVertL1: + if (refLine[b1] - 1 > a0New || (a0 == 0 && refLine[b1] == 1)) { + a0New = codingLine[++a0] = refLine[b1] - 1; + --b1; + while (refLine[b1] <= a0New && refLine[b1] < columns) { + b1 += 2; + } + } + break; + case twoDimVertR2: + if (refLine[b1] + 2 < columns) { + a0New = codingLine[++a0] = refLine[b1] + 2; + ++b1; + while (refLine[b1] <= a0New && refLine[b1] < columns) { + b1 += 2; + } + } else { + a0New = codingLine[++a0] = columns; + } + break; + case twoDimVertL2: + if (refLine[b1] - 2 > a0New || (a0 == 0 && refLine[b1] == 2)) { + a0New = codingLine[++a0] = refLine[b1] - 2; + --b1; + while (refLine[b1] <= a0New && refLine[b1] < columns) { + b1 += 2; + } + } + break; + case twoDimVertR3: + if (refLine[b1] + 3 < columns) { + a0New = codingLine[++a0] = refLine[b1] + 3; + ++b1; + while (refLine[b1] <= a0New && refLine[b1] < columns) { + b1 += 2; + } + } else { + a0New = codingLine[++a0] = columns; + } + break; + case twoDimVertL3: + if (refLine[b1] - 3 > a0New || (a0 == 0 && refLine[b1] == 3)) { + a0New = codingLine[++a0] = refLine[b1] - 3; + --b1; + while (refLine[b1] <= a0New && refLine[b1] < columns) { + b1 += 2; + } + } + break; + case EOF: + eof = gTrue; + codingLine[a0 = 0] = columns; + return EOF; + default: + error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1); + err = gTrue; + break; + } + } while (codingLine[a0] < columns); + + // 1-D encoding + } else { + codingLine[a0 = 0] = 0; + while (1) { + code1 = 0; + do { + code1 += code3 = getWhiteCode(); + } while (code3 >= 64); + codingLine[a0+1] = codingLine[a0] + code1; + ++a0; + if (codingLine[a0] >= columns) { + break; + } + code2 = 0; + do { + code2 += code3 = getBlackCode(); + } while (code3 >= 64); + codingLine[a0+1] = codingLine[a0] + code2; + ++a0; + if (codingLine[a0] >= columns) { + break; + } + } + } + + if (codingLine[a0] != columns) { + error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]); + // force the row to be the correct length + while (codingLine[a0] > columns) { + --a0; + } + codingLine[++a0] = columns; + err = gTrue; + } + + // byte-align the row + if (byteAlign) { + inputBits &= ~7; + } + + // check for end-of-line marker, skipping over any extra zero bits + gotEOL = gFalse; + if (!endOfBlock && row == rows - 1) { + eof = gTrue; + } else { + code1 = lookBits(12); + while (code1 == 0) { + eatBits(1); + code1 = lookBits(12); + } + if (code1 == 0x001) { + eatBits(12); + gotEOL = gTrue; + } else if (code1 == EOF) { + eof = gTrue; + } + } + + // get 2D encoding tag + if (!eof && encoding > 0) { + nextLine2D = !lookBits(1); + eatBits(1); + } + + // check for end-of-block marker + if (endOfBlock && gotEOL) { + code1 = lookBits(12); + if (code1 == 0x001) { + eatBits(12); + if (encoding > 0) { + lookBits(1); + eatBits(1); + } + if (encoding >= 0) { + for (i = 0; i < 4; ++i) { + code1 = lookBits(12); + if (code1 != 0x001) { + error(getPos(), "Bad RTC code in CCITTFax stream"); + } + eatBits(12); + if (encoding > 0) { + lookBits(1); + eatBits(1); + } + } + } + eof = gTrue; + } + + // look for an end-of-line marker after an error -- we only do + // this if we know the stream contains end-of-line markers because + // the "just plow on" technique tends to work better otherwise + } else if (err && endOfLine) { + do { + if (code1 == EOF) { + eof = gTrue; + return EOF; + } + eatBits(1); + code1 = lookBits(13); + } while ((code1 >> 1) != 0x001); + eatBits(12); + if (encoding > 0) { + eatBits(1); + nextLine2D = !(code1 & 1); + } + } + + a0 = 0; + outputBits = codingLine[1] - codingLine[0]; + if (outputBits == 0) { + a0 = 1; + outputBits = codingLine[2] - codingLine[1]; + } + + ++row; + } + + // get a byte + if (outputBits >= 8) { + ret = ((a0 & 1) == 0) ? 0xff : 0x00; + if ((outputBits -= 8) == 0) { + ++a0; + if (codingLine[a0] < columns) { + outputBits = codingLine[a0 + 1] - codingLine[a0]; + } + } + } else { + bits = 8; + ret = 0; + do { + if (outputBits > bits) { + i = bits; + bits = 0; + if ((a0 & 1) == 0) { + ret |= 0xff >> (8 - i); + } + outputBits -= i; + } else { + i = outputBits; + bits -= outputBits; + if ((a0 & 1) == 0) { + ret |= (0xff >> (8 - i)) << bits; + } + outputBits = 0; + ++a0; + if (codingLine[a0] < columns) { + outputBits = codingLine[a0 + 1] - codingLine[a0]; + } + } + } while (bits > 0 && codingLine[a0] < columns); + } + buf = black ? (ret ^ 0xff) : ret; + return buf; +} + +short CCITTFaxStream::getTwoDimCode() { + short code; + CCITTCode *p; + int n; + + code = 0; // make gcc happy + if (endOfBlock) { + code = lookBits(7); + p = &twoDimTab1[code]; + if (p->bits > 0) { + eatBits(p->bits); + return p->n; + } + } else { + for (n = 1; n <= 7; ++n) { + code = lookBits(n); + if (n < 7) { + code <<= 7 - n; + } + p = &twoDimTab1[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code); + return EOF; +} + +short CCITTFaxStream::getWhiteCode() { + short code; + CCITTCode *p; + int n; + + code = 0; // make gcc happy + if (endOfBlock) { + code = lookBits(12); + if ((code >> 5) == 0) { + p = &whiteTab1[code]; + } else { + p = &whiteTab2[code >> 3]; + } + if (p->bits > 0) { + eatBits(p->bits); + return p->n; + } + } else { + for (n = 1; n <= 9; ++n) { + code = lookBits(n); + if (n < 9) { + code <<= 9 - n; + } + p = &whiteTab2[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + for (n = 11; n <= 12; ++n) { + code = lookBits(n); + if (n < 12) { + code <<= 12 - n; + } + p = &whiteTab1[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + error(getPos(), "Bad white code (%04x) in CCITTFax stream", code); + // eat a bit and return a positive number so that the caller doesn't + // go into an infinite loop + eatBits(1); + return 1; +} + +short CCITTFaxStream::getBlackCode() { + short code; + CCITTCode *p; + int n; + + code = 0; // make gcc happy + if (endOfBlock) { + code = lookBits(13); + if ((code >> 7) == 0) { + p = &blackTab1[code]; + } else if ((code >> 9) == 0) { + p = &blackTab2[(code >> 1) - 64]; + } else { + p = &blackTab3[code >> 7]; + } + if (p->bits > 0) { + eatBits(p->bits); + return p->n; + } + } else { + for (n = 2; n <= 6; ++n) { + code = lookBits(n); + if (n < 6) { + code <<= 6 - n; + } + p = &blackTab3[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + for (n = 7; n <= 12; ++n) { + code = lookBits(n); + if (n < 12) { + code <<= 12 - n; + } + if (code >= 64) { + p = &blackTab2[code - 64]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + for (n = 10; n <= 13; ++n) { + code = lookBits(n); + if (n < 13) { + code <<= 13 - n; + } + p = &blackTab1[code]; + if (p->bits == n) { + eatBits(n); + return p->n; + } + } + } + error(getPos(), "Bad black code (%04x) in CCITTFax stream", code); + // eat a bit and return a positive number so that the caller doesn't + // go into an infinite loop + eatBits(1); + return 1; +} + +short CCITTFaxStream::lookBits(int n) { + int c; + + while (inputBits < n) { + if ((c = str->getChar()) == EOF) { + if (inputBits == 0) { + return EOF; + } + // near the end of the stream, the caller may ask for more bits + // than are available, but there may still be a valid code in + // however many bits are available -- we need to return correct + // data in this case + return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n)); + } + inputBuf = (inputBuf << 8) + c; + inputBits += 8; + } + return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n)); +} + +GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) { + GString *s; + char s1[50]; + + if (psLevel < 2) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent))) { + return NULL; + } + s->append(indent)->append("<< "); + if (encoding != 0) { + sprintf(s1, "/K %d ", encoding); + s->append(s1); + } + if (endOfLine) { + s->append("/EndOfLine true "); + } + if (byteAlign) { + s->append("/EncodedByteAlign true "); + } + sprintf(s1, "/Columns %d ", columns); + s->append(s1); + if (rows != 0) { + sprintf(s1, "/Rows %d ", rows); + s->append(s1); + } + if (!endOfBlock) { + s->append("/EndOfBlock false "); + } + if (black) { + s->append("/BlackIs1 true "); + } + s->append(">> /CCITTFaxDecode filter\n"); + return s; +} + +GBool CCITTFaxStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +//------------------------------------------------------------------------ +// DCTStream +//------------------------------------------------------------------------ + +// IDCT constants (20.12 fixed point format) +#define dctCos1 4017 // cos(pi/16) +#define dctSin1 799 // sin(pi/16) +#define dctCos3 3406 // cos(3*pi/16) +#define dctSin3 2276 // sin(3*pi/16) +#define dctCos6 1567 // cos(6*pi/16) +#define dctSin6 3784 // sin(6*pi/16) +#define dctSqrt2 5793 // sqrt(2) +#define dctSqrt1d2 2896 // sqrt(2) / 2 + +// color conversion parameters (16.16 fixed point format) +#define dctCrToR 91881 // 1.4020 +#define dctCbToG -22553 // -0.3441363 +#define dctCrToG -46802 // -0.71413636 +#define dctCbToB 116130 // 1.772 + +// clip [-256,511] --> [0,255] +#define dctClipOffset 256 +static Guchar dctClip[768]; +static int dctClipInit = 0; + +// zig zag decode map +static int dctZigZag[64] = { + 0, + 1, 8, + 16, 9, 2, + 3, 10, 17, 24, + 32, 25, 18, 11, 4, + 5, 12, 19, 26, 33, 40, + 48, 41, 34, 27, 20, 13, 6, + 7, 14, 21, 28, 35, 42, 49, 56, + 57, 50, 43, 36, 29, 22, 15, + 23, 30, 37, 44, 51, 58, + 59, 52, 45, 38, 31, + 39, 46, 53, 60, + 61, 54, 47, + 55, 62, + 63 +}; + +DCTStream::DCTStream(Stream *strA, GBool colorXformA): + FilterStream(strA) { + int i, j; + + colorXform = colorXformA; + progressive = interleaved = gFalse; + width = height = 0; + mcuWidth = mcuHeight = 0; + numComps = 0; + comp = 0; + x = y = dy = 0; + for (i = 0; i < 4; ++i) { + for (j = 0; j < 32; ++j) { + rowBuf[i][j] = NULL; + } + frameBuf[i] = NULL; + } + + if (!dctClipInit) { + for (i = -256; i < 0; ++i) + dctClip[dctClipOffset + i] = 0; + for (i = 0; i < 256; ++i) + dctClip[dctClipOffset + i] = i; + for (i = 256; i < 512; ++i) + dctClip[dctClipOffset + i] = 255; + dctClipInit = 1; + } +} + +DCTStream::~DCTStream() { + close(); + delete str; +} + +void DCTStream::reset() { + int i, j; + + str->reset(); + + progressive = interleaved = gFalse; + width = height = 0; + numComps = 0; + numQuantTables = 0; + numDCHuffTables = 0; + numACHuffTables = 0; + gotJFIFMarker = gFalse; + gotAdobeMarker = gFalse; + restartInterval = 0; + + if (!readHeader()) { + y = height; + return; + } + + // compute MCU size + if (numComps == 1) { + compInfo[0].hSample = compInfo[0].vSample = 1; + } + mcuWidth = compInfo[0].hSample; + mcuHeight = compInfo[0].vSample; + for (i = 1; i < numComps; ++i) { + if (compInfo[i].hSample > mcuWidth) { + mcuWidth = compInfo[i].hSample; + } + if (compInfo[i].vSample > mcuHeight) { + mcuHeight = compInfo[i].vSample; + } + } + mcuWidth *= 8; + mcuHeight *= 8; + + // figure out color transform + if (colorXform == -1) { + if (numComps == 3) { + if (gotJFIFMarker) { + colorXform = 1; + } else if (compInfo[0].id == 82 && compInfo[1].id == 71 && + compInfo[2].id == 66) { // ASCII "RGB" + colorXform = 0; + } else { + colorXform = 1; + } + } else { + colorXform = 0; + } + } + + if (progressive || !interleaved) { + + // allocate a buffer for the whole image + bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; + bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight; + for (i = 0; i < numComps; ++i) { + frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int)); + memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int)); + } + + // read the image data + do { + restartMarker = 0xd0; + restart(); + readScan(); + } while (readHeader()); + + // decode + decodeImage(); + + // initialize counters + comp = 0; + x = 0; + y = 0; + + } else { + + // allocate a buffer for one row of MCUs + bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; + for (i = 0; i < numComps; ++i) { + for (j = 0; j < mcuHeight; ++j) { + rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar)); + } + } + + // initialize counters + comp = 0; + x = 0; + y = 0; + dy = mcuHeight; + + restartMarker = 0xd0; + restart(); + } +} + +void DCTStream::close() { + int i, j; + + for (i = 0; i < 4; ++i) { + for (j = 0; j < 32; ++j) { + gfree(rowBuf[i][j]); + rowBuf[i][j] = NULL; + } + gfree(frameBuf[i]); + frameBuf[i] = NULL; + } + FilterStream::close(); +} + +int DCTStream::getChar() { + int c; + + if (y >= height) { + return EOF; + } + if (progressive || !interleaved) { + c = frameBuf[comp][y * bufWidth + x]; + if (++comp == numComps) { + comp = 0; + if (++x == width) { + x = 0; + ++y; + } + } + } else { + if (dy >= mcuHeight) { + if (!readMCURow()) { + y = height; + return EOF; + } + comp = 0; + x = 0; + dy = 0; + } + c = rowBuf[comp][dy][x]; + if (++comp == numComps) { + comp = 0; + if (++x == width) { + x = 0; + ++y; + ++dy; + if (y == height) { + readTrailer(); + } + } + } + } + return c; +} + +int DCTStream::lookChar() { + if (y >= height) { + return EOF; + } + if (progressive || !interleaved) { + return frameBuf[comp][y * bufWidth + x]; + } else { + if (dy >= mcuHeight) { + if (!readMCURow()) { + y = height; + return EOF; + } + comp = 0; + x = 0; + dy = 0; + } + return rowBuf[comp][dy][x]; + } +} + +void DCTStream::restart() { + int i; + + inputBits = 0; + restartCtr = restartInterval; + for (i = 0; i < numComps; ++i) { + compInfo[i].prevDC = 0; + } + eobRun = 0; +} + +// Read one row of MCUs from a sequential JPEG stream. +GBool DCTStream::readMCURow() { + int data1[64]; + Guchar data2[64]; + Guchar *p1, *p2; + int pY, pCb, pCr, pR, pG, pB; + int h, v, horiz, vert, hSub, vSub; + int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i; + int c; + + for (x1 = 0; x1 < width; x1 += mcuWidth) { + + // deal with restart marker + if (restartInterval > 0 && restartCtr == 0) { + c = readMarker(); + if (c != restartMarker) { + error(getPos(), "Bad DCT data: incorrect restart marker"); + return gFalse; + } + if (++restartMarker == 0xd8) + restartMarker = 0xd0; + restart(); + } + + // read one MCU + for (cc = 0; cc < numComps; ++cc) { + h = compInfo[cc].hSample; + v = compInfo[cc].vSample; + horiz = mcuWidth / h; + vert = mcuHeight / v; + hSub = horiz / 8; + vSub = vert / 8; + for (y2 = 0; y2 < mcuHeight; y2 += vert) { + for (x2 = 0; x2 < mcuWidth; x2 += horiz) { + if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]], + &acHuffTables[scanInfo.acHuffTable[cc]], + &compInfo[cc].prevDC, + data1)) { + return gFalse; + } + transformDataUnit(quantTables[compInfo[cc].quantTable], + data1, data2); + if (hSub == 1 && vSub == 1) { + for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { + p1 = &rowBuf[cc][y2+y3][x1+x2]; + p1[0] = data2[i]; + p1[1] = data2[i+1]; + p1[2] = data2[i+2]; + p1[3] = data2[i+3]; + p1[4] = data2[i+4]; + p1[5] = data2[i+5]; + p1[6] = data2[i+6]; + p1[7] = data2[i+7]; + } + } else if (hSub == 2 && vSub == 2) { + for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) { + p1 = &rowBuf[cc][y2+y3][x1+x2]; + p2 = &rowBuf[cc][y2+y3+1][x1+x2]; + p1[0] = p1[1] = p2[0] = p2[1] = data2[i]; + p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1]; + p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2]; + p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3]; + p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4]; + p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5]; + p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6]; + p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7]; + } + } else { + i = 0; + for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) { + for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) { + for (y5 = 0; y5 < vSub; ++y5) + for (x5 = 0; x5 < hSub; ++x5) + rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i]; + ++i; + } + } + } + } + } + } + --restartCtr; + + // color space conversion + if (colorXform) { + // convert YCbCr to RGB + if (numComps == 3) { + for (y2 = 0; y2 < mcuHeight; ++y2) { + for (x2 = 0; x2 < mcuWidth; ++x2) { + pY = rowBuf[0][y2][x1+x2]; + pCb = rowBuf[1][y2][x1+x2] - 128; + pCr = rowBuf[2][y2][x1+x2] - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR]; + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; + rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG]; + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB]; + } + } + // convert YCbCrK to CMYK (K is passed through unchanged) + } else if (numComps == 4) { + for (y2 = 0; y2 < mcuHeight; ++y2) { + for (x2 = 0; x2 < mcuWidth; ++x2) { + pY = rowBuf[0][y2][x1+x2]; + pCb = rowBuf[1][y2][x1+x2] - 128; + pCr = rowBuf[2][y2][x1+x2] - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR]; + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; + rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG]; + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB]; + } + } + } + } + } + return gTrue; +} + +// Read one scan from a progressive or non-interleaved JPEG stream. +void DCTStream::readScan() { + int data[64]; + int x1, y1, dx1, dy1, x2, y2, y3, cc, i; + int h, v, horiz, vert, vSub; + int *p1; + int c; + + if (scanInfo.numComps == 1) { + for (cc = 0; cc < numComps; ++cc) { + if (scanInfo.comp[cc]) { + break; + } + } + dx1 = mcuWidth / compInfo[cc].hSample; + dy1 = mcuHeight / compInfo[cc].vSample; + } else { + dx1 = mcuWidth; + dy1 = mcuHeight; + } + + for (y1 = 0; y1 < height; y1 += dy1) { + for (x1 = 0; x1 < width; x1 += dx1) { + + // deal with restart marker + if (restartInterval > 0 && restartCtr == 0) { + c = readMarker(); + if (c != restartMarker) { + error(getPos(), "Bad DCT data: incorrect restart marker"); + return; + } + if (++restartMarker == 0xd8) { + restartMarker = 0xd0; + } + restart(); + } + + // read one MCU + for (cc = 0; cc < numComps; ++cc) { + if (!scanInfo.comp[cc]) { + continue; + } + + h = compInfo[cc].hSample; + v = compInfo[cc].vSample; + horiz = mcuWidth / h; + vert = mcuHeight / v; + vSub = vert / 8; + for (y2 = 0; y2 < dy1; y2 += vert) { + for (x2 = 0; x2 < dx1; x2 += horiz) { + + // pull out the current values + p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; + for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { + data[i] = p1[0]; + data[i+1] = p1[1]; + data[i+2] = p1[2]; + data[i+3] = p1[3]; + data[i+4] = p1[4]; + data[i+5] = p1[5]; + data[i+6] = p1[6]; + data[i+7] = p1[7]; + p1 += bufWidth * vSub; + } + + // read one data unit + if (progressive) { + if (!readProgressiveDataUnit( + &dcHuffTables[scanInfo.dcHuffTable[cc]], + &acHuffTables[scanInfo.acHuffTable[cc]], + &compInfo[cc].prevDC, + data)) { + return; + } + } else { + if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]], + &acHuffTables[scanInfo.acHuffTable[cc]], + &compInfo[cc].prevDC, + data)) { + return; + } + } + + // add the data unit into frameBuf + p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; + for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { + p1[0] = data[i]; + p1[1] = data[i+1]; + p1[2] = data[i+2]; + p1[3] = data[i+3]; + p1[4] = data[i+4]; + p1[5] = data[i+5]; + p1[6] = data[i+6]; + p1[7] = data[i+7]; + p1 += bufWidth * vSub; + } + } + } + } + --restartCtr; + } + } +} + +// Read one data unit from a sequential JPEG stream. +GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]) { + int run, size, amp; + int c; + int i, j; + + if ((size = readHuffSym(dcHuffTable)) == 9999) { + return gFalse; + } + if (size > 0) { + if ((amp = readAmp(size)) == 9999) { + return gFalse; + } + } else { + amp = 0; + } + data[0] = *prevDC += amp; + for (i = 1; i < 64; ++i) { + data[i] = 0; + } + i = 1; + while (i < 64) { + run = 0; + while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) { + run += 0x10; + } + if (c == 9999) { + return gFalse; + } + if (c == 0x00) { + break; + } else { + run += (c >> 4) & 0x0f; + size = c & 0x0f; + amp = readAmp(size); + if (amp == 9999) { + return gFalse; + } + i += run; + if (i < 64) { + j = dctZigZag[i++]; + data[j] = amp; + } + } + } + return gTrue; +} + +// Read one data unit from a sequential JPEG stream. +GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]) { + int run, size, amp, bit, c; + int i, j, k; + + // get the DC coefficient + i = scanInfo.firstCoeff; + if (i == 0) { + if (scanInfo.ah == 0) { + if ((size = readHuffSym(dcHuffTable)) == 9999) { + return gFalse; + } + if (size > 0) { + if ((amp = readAmp(size)) == 9999) { + return gFalse; + } + } else { + amp = 0; + } + data[0] += (*prevDC += amp) << scanInfo.al; + } else { + if ((bit = readBit()) == 9999) { + return gFalse; + } + data[0] += bit << scanInfo.al; + } + ++i; + } + if (scanInfo.lastCoeff == 0) { + return gTrue; + } + + // check for an EOB run + if (eobRun > 0) { + while (i <= scanInfo.lastCoeff) { + if(i>=64) { + return gFalse; + } + j = dctZigZag[i++]; + if (data[j] != 0) { + if ((bit = readBit()) == EOF) { + return gFalse; + } + if (bit) { + data[j] += 1 << scanInfo.al; + } + } + } + --eobRun; + return gTrue; + } + + // read the AC coefficients + while (i <= scanInfo.lastCoeff) { + if ((c = readHuffSym(acHuffTable)) == 9999) { + return gFalse; + } + + // ZRL + if (c == 0xf0) { + k = 0; + while (k < 16) { + if(i>=64) { + return gFalse; + } + j = dctZigZag[i++]; + if (data[j] == 0) { + ++k; + } else { + if ((bit = readBit()) == EOF) { + return gFalse; + } + if (bit) { + data[j] += 1 << scanInfo.al; + } + } + } + + // EOB run + } else if ((c & 0x0f) == 0x00) { + j = c >> 4; + eobRun = 0; + for (k = 0; k < j; ++k) { + if ((bit = readBit()) == EOF) { + return gFalse; + } + eobRun = (eobRun << 1) | bit; + } + eobRun += 1 << j; + while (i <= scanInfo.lastCoeff) { + if(i>=64) { + return gFalse; + } + j = dctZigZag[i++]; + if (data[j] != 0) { + if ((bit = readBit()) == EOF) { + return gFalse; + } + if (bit) { + data[j] += 1 << scanInfo.al; + } + } + } + --eobRun; + break; + + // zero run and one AC coefficient + } else { + run = (c >> 4) & 0x0f; + size = c & 0x0f; + if ((amp = readAmp(size)) == 9999) { + return gFalse; + } + k = 0; + do { + if(i>=64) { + return gFalse; + } + j = dctZigZag[i++]; + while (data[j] != 0) { + if ((bit = readBit()) == EOF) { + return gFalse; + } + if (bit) { + data[j] += 1 << scanInfo.al; + } + if(i>=64) { + return gFalse; + } + j = dctZigZag[i++]; + } + ++k; + } while (k <= run); + data[j] = amp << scanInfo.al; + } + } + + return gTrue; +} + +// Decode a progressive JPEG image. +void DCTStream::decodeImage() { + int dataIn[64]; + Guchar dataOut[64]; + Gushort *quantTable; + int pY, pCb, pCr, pR, pG, pB; + int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i; + int h, v, horiz, vert, hSub, vSub; + int *p0, *p1, *p2; + + for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) { + for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) { + for (cc = 0; cc < numComps; ++cc) { + quantTable = quantTables[compInfo[cc].quantTable]; + h = compInfo[cc].hSample; + v = compInfo[cc].vSample; + horiz = mcuWidth / h; + vert = mcuHeight / v; + hSub = horiz / 8; + vSub = vert / 8; + for (y2 = 0; y2 < mcuHeight; y2 += vert) { + for (x2 = 0; x2 < mcuWidth; x2 += horiz) { + + // pull out the coded data unit + p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; + for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { + dataIn[i] = p1[0]; + dataIn[i+1] = p1[1]; + dataIn[i+2] = p1[2]; + dataIn[i+3] = p1[3]; + dataIn[i+4] = p1[4]; + dataIn[i+5] = p1[5]; + dataIn[i+6] = p1[6]; + dataIn[i+7] = p1[7]; + p1 += bufWidth * vSub; + } + + // transform + transformDataUnit(quantTable, dataIn, dataOut); + + // store back into frameBuf, doing replication for + // subsampled components + p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; + if (hSub == 1 && vSub == 1) { + for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { + p1[0] = dataOut[i] & 0xff; + p1[1] = dataOut[i+1] & 0xff; + p1[2] = dataOut[i+2] & 0xff; + p1[3] = dataOut[i+3] & 0xff; + p1[4] = dataOut[i+4] & 0xff; + p1[5] = dataOut[i+5] & 0xff; + p1[6] = dataOut[i+6] & 0xff; + p1[7] = dataOut[i+7] & 0xff; + p1 += bufWidth; + } + } else if (hSub == 2 && vSub == 2) { + p2 = p1 + bufWidth; + for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) { + p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff; + p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff; + p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff; + p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff; + p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff; + p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff; + p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff; + p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff; + p1 += bufWidth * 2; + p2 += bufWidth * 2; + } + } else { + i = 0; + for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) { + for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) { + p2 = p1 + x4; + for (y5 = 0; y5 < vSub; ++y5) { + for (x5 = 0; x5 < hSub; ++x5) { + p2[x5] = dataOut[i] & 0xff; + } + p2 += bufWidth; + } + ++i; + } + p1 += bufWidth * vSub; + } + } + } + } + } + + // color space conversion + if (colorXform) { + // convert YCbCr to RGB + if (numComps == 3) { + for (y2 = 0; y2 < mcuHeight; ++y2) { + p0 = &frameBuf[0][(y1+y2) * bufWidth + x1]; + p1 = &frameBuf[1][(y1+y2) * bufWidth + x1]; + p2 = &frameBuf[2][(y1+y2) * bufWidth + x1]; + for (x2 = 0; x2 < mcuWidth; ++x2) { + pY = *p0; + pCb = *p1 - 128; + pCr = *p2 - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + *p0++ = dctClip[dctClipOffset + pR]; + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + + 32768) >> 16; + *p1++ = dctClip[dctClipOffset + pG]; + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + *p2++ = dctClip[dctClipOffset + pB]; + } + } + // convert YCbCrK to CMYK (K is passed through unchanged) + } else if (numComps == 4) { + for (y2 = 0; y2 < mcuHeight; ++y2) { + p0 = &frameBuf[0][(y1+y2) * bufWidth + x1]; + p1 = &frameBuf[1][(y1+y2) * bufWidth + x1]; + p2 = &frameBuf[2][(y1+y2) * bufWidth + x1]; + for (x2 = 0; x2 < mcuWidth; ++x2) { + pY = *p0; + pCb = *p1 - 128; + pCr = *p2 - 128; + pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; + *p0++ = 255 - dctClip[dctClipOffset + pR]; + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + + 32768) >> 16; + *p1++ = 255 - dctClip[dctClipOffset + pG]; + pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; + *p2++ = 255 - dctClip[dctClipOffset + pB]; + } + } + } + } + } + } +} + +// Transform one data unit -- this performs the dequantization and +// IDCT steps. This IDCT algorithm is taken from: +// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, +// "Practical Fast 1-D DCT Algorithms with 11 Multiplications", +// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, +// 988-991. +// The stage numbers mentioned in the comments refer to Figure 1 in this +// paper. +void DCTStream::transformDataUnit(Gushort *quantTable, + int dataIn[64], Guchar dataOut[64]) { + int v0, v1, v2, v3, v4, v5, v6, v7, t; + int *p; + int i; + + // dequant + for (i = 0; i < 64; ++i) { + dataIn[i] *= quantTable[i]; + } + + // inverse DCT on rows + for (i = 0; i < 64; i += 8) { + p = dataIn + i; + + // check for all-zero AC coefficients + if (p[1] == 0 && p[2] == 0 && p[3] == 0 && + p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) { + t = (dctSqrt2 * p[0] + 512) >> 10; + p[0] = t; + p[1] = t; + p[2] = t; + p[3] = t; + p[4] = t; + p[5] = t; + p[6] = t; + p[7] = t; + continue; + } + + // stage 4 + v0 = (dctSqrt2 * p[0] + 128) >> 8; + v1 = (dctSqrt2 * p[4] + 128) >> 8; + v2 = p[2]; + v3 = p[6]; + v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8; + v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8; + v5 = p[3] << 4; + v6 = p[5] << 4; + + // stage 3 + t = (v0 - v1+ 1) >> 1; + v0 = (v0 + v1 + 1) >> 1; + v1 = t; + t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8; + v3 = t; + t = (v4 - v6 + 1) >> 1; + v4 = (v4 + v6 + 1) >> 1; + v6 = t; + t = (v7 + v5 + 1) >> 1; + v5 = (v7 - v5 + 1) >> 1; + v7 = t; + + // stage 2 + t = (v0 - v3 + 1) >> 1; + v0 = (v0 + v3 + 1) >> 1; + v3 = t; + t = (v1 - v2 + 1) >> 1; + v1 = (v1 + v2 + 1) >> 1; + v2 = t; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + p[0] = v0 + v7; + p[7] = v0 - v7; + p[1] = v1 + v6; + p[6] = v1 - v6; + p[2] = v2 + v5; + p[5] = v2 - v5; + p[3] = v3 + v4; + p[4] = v3 - v4; + } + + // inverse DCT on columns + for (i = 0; i < 8; ++i) { + p = dataIn + i; + + // check for all-zero AC coefficients + if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 && + p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) { + t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14; + p[0*8] = t; + p[1*8] = t; + p[2*8] = t; + p[3*8] = t; + p[4*8] = t; + p[5*8] = t; + p[6*8] = t; + p[7*8] = t; + continue; + } + + // stage 4 + v0 = (dctSqrt2 * p[0*8] + 2048) >> 12; + v1 = (dctSqrt2 * p[4*8] + 2048) >> 12; + v2 = p[2*8]; + v3 = p[6*8]; + v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12; + v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12; + v5 = p[3*8]; + v6 = p[5*8]; + + // stage 3 + t = (v0 - v1 + 1) >> 1; + v0 = (v0 + v1 + 1) >> 1; + v1 = t; + t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12; + v3 = t; + t = (v4 - v6 + 1) >> 1; + v4 = (v4 + v6 + 1) >> 1; + v6 = t; + t = (v7 + v5 + 1) >> 1; + v5 = (v7 - v5 + 1) >> 1; + v7 = t; + + // stage 2 + t = (v0 - v3 + 1) >> 1; + v0 = (v0 + v3 + 1) >> 1; + v3 = t; + t = (v1 - v2 + 1) >> 1; + v1 = (v1 + v2 + 1) >> 1; + v2 = t; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + p[0*8] = v0 + v7; + p[7*8] = v0 - v7; + p[1*8] = v1 + v6; + p[6*8] = v1 - v6; + p[2*8] = v2 + v5; + p[5*8] = v2 - v5; + p[3*8] = v3 + v4; + p[4*8] = v3 - v4; + } + + // convert to 8-bit integers + for (i = 0; i < 64; ++i) { + dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)]; + } +} + +int DCTStream::readHuffSym(DCTHuffTable *table) { + Gushort code; + int bit; + int codeBits; + + code = 0; + codeBits = 0; + do { + // add a bit to the code + if ((bit = readBit()) == EOF) + return 9999; + code = (code << 1) + bit; + ++codeBits; + + // look up code + if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) { + code -= table->firstCode[codeBits]; + return table->sym[table->firstSym[codeBits] + code]; + } + } while (codeBits < 16); + + error(getPos(), "Bad Huffman code in DCT stream"); + return 9999; +} + +int DCTStream::readAmp(int size) { + int amp, bit; + int bits; + + amp = 0; + for (bits = 0; bits < size; ++bits) { + if ((bit = readBit()) == EOF) + return 9999; + amp = (amp << 1) + bit; + } + if (amp < (1 << (size - 1))) + amp -= (1 << size) - 1; + return amp; +} + +int DCTStream::readBit() { + int bit; + int c, c2; + + if (inputBits == 0) { + if ((c = str->getChar()) == EOF) + return EOF; + if (c == 0xff) { + do { + c2 = str->getChar(); + } while (c2 == 0xff); + if (c2 != 0x00) { + error(getPos(), "Bad DCT data: missing 00 after ff"); + return EOF; + } + } + inputBuf = c; + inputBits = 8; + } + bit = (inputBuf >> (inputBits - 1)) & 1; + --inputBits; + return bit; +} + +GBool DCTStream::readHeader() { + GBool doScan; + int n; + int c = 0; + int i; + + // read headers + doScan = gFalse; + while (!doScan) { + c = readMarker(); + switch (c) { + case 0xc0: // SOF0 (sequential) + case 0xc1: // SOF1 (extended sequential) + if (!readBaselineSOF()) { + return gFalse; + } + break; + case 0xc2: // SOF2 (progressive) + if (!readProgressiveSOF()) { + return gFalse; + } + break; + case 0xc4: // DHT + if (!readHuffmanTables()) { + return gFalse; + } + break; + case 0xd8: // SOI + break; + case 0xd9: // EOI + return gFalse; + case 0xda: // SOS + if (!readScanInfo()) { + return gFalse; + } + doScan = gTrue; + break; + case 0xdb: // DQT + if (!readQuantTables()) { + return gFalse; + } + break; + case 0xdd: // DRI + if (!readRestartInterval()) { + return gFalse; + } + break; + case 0xe0: // APP0 + if (!readJFIFMarker()) { + return gFalse; + } + break; + case 0xee: // APP14 + if (!readAdobeMarker()) { + return gFalse; + } + break; + case EOF: + error(getPos(), "Bad DCT header"); + return gFalse; + default: + // skip APPn / COM / etc. + if (c >= 0xe0) { + n = read16() - 2; + for (i = 0; i < n; ++i) { + str->getChar(); + } + } else { + error(getPos(), "Unknown DCT marker <%02x>", c); + return gFalse; + } + break; + } + } + + return gTrue; +} + +GBool DCTStream::readBaselineSOF() { + int length; + int prec; + int i; + int c; + + length = read16(); + prec = str->getChar(); + height = read16(); + width = read16(); + numComps = str->getChar(); + if (numComps <= 0 || numComps > 4) { + error(getPos(), "Bad number of components in DCT stream"); + numComps = 0; + return gFalse; + } + if (prec != 8) { + error(getPos(), "Bad DCT precision %d", prec); + return gFalse; + } + for (i = 0; i < numComps; ++i) { + compInfo[i].id = str->getChar(); + c = str->getChar(); + compInfo[i].hSample = (c >> 4) & 0x0f; + compInfo[i].vSample = c & 0x0f; + compInfo[i].quantTable = str->getChar(); + } + progressive = gFalse; + return gTrue; +} + +GBool DCTStream::readProgressiveSOF() { + int length; + int prec; + int i; + int c; + + length = read16(); + prec = str->getChar(); + height = read16(); + width = read16(); + numComps = str->getChar(); + if (numComps <= 0 || numComps > 4) { + error(getPos(), "Bad number of components in DCT stream"); + numComps = 0; + return gFalse; + } + if (prec != 8) { + error(getPos(), "Bad DCT precision %d", prec); + return gFalse; + } + for (i = 0; i < numComps; ++i) { + compInfo[i].id = str->getChar(); + c = str->getChar(); + compInfo[i].hSample = (c >> 4) & 0x0f; + compInfo[i].vSample = c & 0x0f; + compInfo[i].quantTable = str->getChar(); + } + progressive = gTrue; + return gTrue; +} + +GBool DCTStream::readScanInfo() { + int length; + int id, c; + int i, j; + + length = read16() - 2; + scanInfo.numComps = str->getChar(); + if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) { + error(getPos(), "Bad number of components in DCT stream"); + scanInfo.numComps = 0; + return gFalse; + } + --length; + if (length != 2 * scanInfo.numComps + 3) { + error(getPos(), "Bad DCT scan info block"); + return gFalse; + } + interleaved = scanInfo.numComps == numComps; + for (j = 0; j < numComps; ++j) { + scanInfo.comp[j] = gFalse; + } + for (i = 0; i < scanInfo.numComps; ++i) { + id = str->getChar(); + // some (broken) DCT streams reuse ID numbers, but at least they + // keep the components in order, so we check compInfo[i] first to + // work around the problem + if (id == compInfo[i].id) { + j = i; + } else { + for (j = 0; j < numComps; ++j) { + if (id == compInfo[j].id) { + break; + } + } + if (j == numComps) { + error(getPos(), "Bad DCT component ID in scan info block"); + return gFalse; + } + } + scanInfo.comp[j] = gTrue; + c = str->getChar(); + scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f; + scanInfo.acHuffTable[j] = c & 0x0f; + } + scanInfo.firstCoeff = str->getChar(); + scanInfo.lastCoeff = str->getChar(); + c = str->getChar(); + scanInfo.ah = (c >> 4) & 0x0f; + scanInfo.al = c & 0x0f; + return gTrue; +} + +GBool DCTStream::readQuantTables() { + int length, prec, i, index; + + length = read16() - 2; + while (length > 0) { + index = str->getChar(); + prec = (index >> 4) & 0x0f; + index &= 0x0f; + if (prec > 1 || index >= 4) { + error(getPos(), "Bad DCT quantization table"); + return gFalse; + } + if (index == numQuantTables) { + numQuantTables = index + 1; + } + for (i = 0; i < 64; ++i) { + if (prec) { + quantTables[index][dctZigZag[i]] = read16(); + } else { + quantTables[index][dctZigZag[i]] = str->getChar(); + } + } + if (prec) { + length -= 129; + } else { + length -= 65; + } + } + return gTrue; +} + +GBool DCTStream::readHuffmanTables() { + DCTHuffTable *tbl; + int length; + int index; + Gushort code; + Guchar sym; + int i; + int c; + + length = read16() - 2; + while (length > 0) { + index = str->getChar(); + --length; + if ((index & 0x0f) >= 4) { + error(getPos(), "Bad DCT Huffman table"); + return gFalse; + } + if (index & 0x10) { + index &= 0x0f; + if (index >= numACHuffTables) + numACHuffTables = index+1; + tbl = &acHuffTables[index]; + } else { + index &= 0x0f; + if (index >= numDCHuffTables) + numDCHuffTables = index+1; + tbl = &dcHuffTables[index]; + } + sym = 0; + code = 0; + for (i = 1; i <= 16; ++i) { + c = str->getChar(); + tbl->firstSym[i] = sym; + tbl->firstCode[i] = code; + tbl->numCodes[i] = c; + sym += c; + code = (code + c) << 1; + } + length -= 16; + for (i = 0; i < sym; ++i) + tbl->sym[i] = str->getChar(); + length -= sym; + } + return gTrue; +} + +GBool DCTStream::readRestartInterval() { + int length; + + length = read16(); + if (length != 4) { + error(getPos(), "Bad DCT restart interval"); + return gFalse; + } + restartInterval = read16(); + return gTrue; +} + +GBool DCTStream::readJFIFMarker() { + int length, i; + char buf[5]; + int c; + + length = read16(); + length -= 2; + if (length >= 5) { + for (i = 0; i < 5; ++i) { + if ((c = str->getChar()) == EOF) { + error(getPos(), "Bad DCT APP0 marker"); + return gFalse; + } + buf[i] = c; + } + length -= 5; + if (!memcmp(buf, "JFIF\0", 5)) { + gotJFIFMarker = gTrue; + } + } + while (length > 0) { + if (str->getChar() == EOF) { + error(getPos(), "Bad DCT APP0 marker"); + return gFalse; + } + --length; + } + return gTrue; +} + +GBool DCTStream::readAdobeMarker() { + int length, i; + char buf[12]; + int c; + + length = read16(); + if (length < 14) { + goto err; + } + for (i = 0; i < 12; ++i) { + if ((c = str->getChar()) == EOF) { + goto err; + } + buf[i] = c; + } + if (strncmp(buf, "Adobe", 5)) { + goto err; + } + colorXform = buf[11]; + gotAdobeMarker = gTrue; + for (i = 14; i < length; ++i) { + if (str->getChar() == EOF) { + goto err; + } + } + return gTrue; + + err: + error(getPos(), "Bad DCT Adobe APP14 marker"); + return gFalse; +} + +GBool DCTStream::readTrailer() { + int c; + + c = readMarker(); + if (c != 0xd9) { // EOI + error(getPos(), "Bad DCT trailer"); + return gFalse; + } + return gTrue; +} + +int DCTStream::readMarker() { + int c; + + do { + do { + c = str->getChar(); + } while (c != 0xff && c != EOF); + do { + c = str->getChar(); + } while (c == 0xff); + } while (c == 0x00); + return c; +} + +int DCTStream::read16() { + int c1, c2; + + if ((c1 = str->getChar()) == EOF) + return EOF; + if ((c2 = str->getChar()) == EOF) + return EOF; + return (c1 << 8) + c2; +} + +GString *DCTStream::getPSFilter(int psLevel, char *indent) { + GString *s; + + if (psLevel < 2) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent))) { + return NULL; + } + s->append(indent)->append("<< >> /DCTDecode filter\n"); + return s; +} + +GBool DCTStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +//------------------------------------------------------------------------ +// FlateStream +//------------------------------------------------------------------------ + +int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = { + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 +}; + +FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = { + {0, 3}, + {0, 4}, + {0, 5}, + {0, 6}, + {0, 7}, + {0, 8}, + {0, 9}, + {0, 10}, + {1, 11}, + {1, 13}, + {1, 15}, + {1, 17}, + {2, 19}, + {2, 23}, + {2, 27}, + {2, 31}, + {3, 35}, + {3, 43}, + {3, 51}, + {3, 59}, + {4, 67}, + {4, 83}, + {4, 99}, + {4, 115}, + {5, 131}, + {5, 163}, + {5, 195}, + {5, 227}, + {0, 258}, + {0, 258}, + {0, 258} +}; + +FlateDecode FlateStream::distDecode[flateMaxDistCodes] = { + { 0, 1}, + { 0, 2}, + { 0, 3}, + { 0, 4}, + { 1, 5}, + { 1, 7}, + { 2, 9}, + { 2, 13}, + { 3, 17}, + { 3, 25}, + { 4, 33}, + { 4, 49}, + { 5, 65}, + { 5, 97}, + { 6, 129}, + { 6, 193}, + { 7, 257}, + { 7, 385}, + { 8, 513}, + { 8, 769}, + { 9, 1025}, + { 9, 1537}, + {10, 2049}, + {10, 3073}, + {11, 4097}, + {11, 6145}, + {12, 8193}, + {12, 12289}, + {13, 16385}, + {13, 24577} +}; + +static FlateCode flateFixedLitCodeTabCodes[512] = { + {7, 0x0100}, + {8, 0x0050}, + {8, 0x0010}, + {8, 0x0118}, + {7, 0x0110}, + {8, 0x0070}, + {8, 0x0030}, + {9, 0x00c0}, + {7, 0x0108}, + {8, 0x0060}, + {8, 0x0020}, + {9, 0x00a0}, + {8, 0x0000}, + {8, 0x0080}, + {8, 0x0040}, + {9, 0x00e0}, + {7, 0x0104}, + {8, 0x0058}, + {8, 0x0018}, + {9, 0x0090}, + {7, 0x0114}, + {8, 0x0078}, + {8, 0x0038}, + {9, 0x00d0}, + {7, 0x010c}, + {8, 0x0068}, + {8, 0x0028}, + {9, 0x00b0}, + {8, 0x0008}, + {8, 0x0088}, + {8, 0x0048}, + {9, 0x00f0}, + {7, 0x0102}, + {8, 0x0054}, + {8, 0x0014}, + {8, 0x011c}, + {7, 0x0112}, + {8, 0x0074}, + {8, 0x0034}, + {9, 0x00c8}, + {7, 0x010a}, + {8, 0x0064}, + {8, 0x0024}, + {9, 0x00a8}, + {8, 0x0004}, + {8, 0x0084}, + {8, 0x0044}, + {9, 0x00e8}, + {7, 0x0106}, + {8, 0x005c}, + {8, 0x001c}, + {9, 0x0098}, + {7, 0x0116}, + {8, 0x007c}, + {8, 0x003c}, + {9, 0x00d8}, + {7, 0x010e}, + {8, 0x006c}, + {8, 0x002c}, + {9, 0x00b8}, + {8, 0x000c}, + {8, 0x008c}, + {8, 0x004c}, + {9, 0x00f8}, + {7, 0x0101}, + {8, 0x0052}, + {8, 0x0012}, + {8, 0x011a}, + {7, 0x0111}, + {8, 0x0072}, + {8, 0x0032}, + {9, 0x00c4}, + {7, 0x0109}, + {8, 0x0062}, + {8, 0x0022}, + {9, 0x00a4}, + {8, 0x0002}, + {8, 0x0082}, + {8, 0x0042}, + {9, 0x00e4}, + {7, 0x0105}, + {8, 0x005a}, + {8, 0x001a}, + {9, 0x0094}, + {7, 0x0115}, + {8, 0x007a}, + {8, 0x003a}, + {9, 0x00d4}, + {7, 0x010d}, + {8, 0x006a}, + {8, 0x002a}, + {9, 0x00b4}, + {8, 0x000a}, + {8, 0x008a}, + {8, 0x004a}, + {9, 0x00f4}, + {7, 0x0103}, + {8, 0x0056}, + {8, 0x0016}, + {8, 0x011e}, + {7, 0x0113}, + {8, 0x0076}, + {8, 0x0036}, + {9, 0x00cc}, + {7, 0x010b}, + {8, 0x0066}, + {8, 0x0026}, + {9, 0x00ac}, + {8, 0x0006}, + {8, 0x0086}, + {8, 0x0046}, + {9, 0x00ec}, + {7, 0x0107}, + {8, 0x005e}, + {8, 0x001e}, + {9, 0x009c}, + {7, 0x0117}, + {8, 0x007e}, + {8, 0x003e}, + {9, 0x00dc}, + {7, 0x010f}, + {8, 0x006e}, + {8, 0x002e}, + {9, 0x00bc}, + {8, 0x000e}, + {8, 0x008e}, + {8, 0x004e}, + {9, 0x00fc}, + {7, 0x0100}, + {8, 0x0051}, + {8, 0x0011}, + {8, 0x0119}, + {7, 0x0110}, + {8, 0x0071}, + {8, 0x0031}, + {9, 0x00c2}, + {7, 0x0108}, + {8, 0x0061}, + {8, 0x0021}, + {9, 0x00a2}, + {8, 0x0001}, + {8, 0x0081}, + {8, 0x0041}, + {9, 0x00e2}, + {7, 0x0104}, + {8, 0x0059}, + {8, 0x0019}, + {9, 0x0092}, + {7, 0x0114}, + {8, 0x0079}, + {8, 0x0039}, + {9, 0x00d2}, + {7, 0x010c}, + {8, 0x0069}, + {8, 0x0029}, + {9, 0x00b2}, + {8, 0x0009}, + {8, 0x0089}, + {8, 0x0049}, + {9, 0x00f2}, + {7, 0x0102}, + {8, 0x0055}, + {8, 0x0015}, + {8, 0x011d}, + {7, 0x0112}, + {8, 0x0075}, + {8, 0x0035}, + {9, 0x00ca}, + {7, 0x010a}, + {8, 0x0065}, + {8, 0x0025}, + {9, 0x00aa}, + {8, 0x0005}, + {8, 0x0085}, + {8, 0x0045}, + {9, 0x00ea}, + {7, 0x0106}, + {8, 0x005d}, + {8, 0x001d}, + {9, 0x009a}, + {7, 0x0116}, + {8, 0x007d}, + {8, 0x003d}, + {9, 0x00da}, + {7, 0x010e}, + {8, 0x006d}, + {8, 0x002d}, + {9, 0x00ba}, + {8, 0x000d}, + {8, 0x008d}, + {8, 0x004d}, + {9, 0x00fa}, + {7, 0x0101}, + {8, 0x0053}, + {8, 0x0013}, + {8, 0x011b}, + {7, 0x0111}, + {8, 0x0073}, + {8, 0x0033}, + {9, 0x00c6}, + {7, 0x0109}, + {8, 0x0063}, + {8, 0x0023}, + {9, 0x00a6}, + {8, 0x0003}, + {8, 0x0083}, + {8, 0x0043}, + {9, 0x00e6}, + {7, 0x0105}, + {8, 0x005b}, + {8, 0x001b}, + {9, 0x0096}, + {7, 0x0115}, + {8, 0x007b}, + {8, 0x003b}, + {9, 0x00d6}, + {7, 0x010d}, + {8, 0x006b}, + {8, 0x002b}, + {9, 0x00b6}, + {8, 0x000b}, + {8, 0x008b}, + {8, 0x004b}, + {9, 0x00f6}, + {7, 0x0103}, + {8, 0x0057}, + {8, 0x0017}, + {8, 0x011f}, + {7, 0x0113}, + {8, 0x0077}, + {8, 0x0037}, + {9, 0x00ce}, + {7, 0x010b}, + {8, 0x0067}, + {8, 0x0027}, + {9, 0x00ae}, + {8, 0x0007}, + {8, 0x0087}, + {8, 0x0047}, + {9, 0x00ee}, + {7, 0x0107}, + {8, 0x005f}, + {8, 0x001f}, + {9, 0x009e}, + {7, 0x0117}, + {8, 0x007f}, + {8, 0x003f}, + {9, 0x00de}, + {7, 0x010f}, + {8, 0x006f}, + {8, 0x002f}, + {9, 0x00be}, + {8, 0x000f}, + {8, 0x008f}, + {8, 0x004f}, + {9, 0x00fe}, + {7, 0x0100}, + {8, 0x0050}, + {8, 0x0010}, + {8, 0x0118}, + {7, 0x0110}, + {8, 0x0070}, + {8, 0x0030}, + {9, 0x00c1}, + {7, 0x0108}, + {8, 0x0060}, + {8, 0x0020}, + {9, 0x00a1}, + {8, 0x0000}, + {8, 0x0080}, + {8, 0x0040}, + {9, 0x00e1}, + {7, 0x0104}, + {8, 0x0058}, + {8, 0x0018}, + {9, 0x0091}, + {7, 0x0114}, + {8, 0x0078}, + {8, 0x0038}, + {9, 0x00d1}, + {7, 0x010c}, + {8, 0x0068}, + {8, 0x0028}, + {9, 0x00b1}, + {8, 0x0008}, + {8, 0x0088}, + {8, 0x0048}, + {9, 0x00f1}, + {7, 0x0102}, + {8, 0x0054}, + {8, 0x0014}, + {8, 0x011c}, + {7, 0x0112}, + {8, 0x0074}, + {8, 0x0034}, + {9, 0x00c9}, + {7, 0x010a}, + {8, 0x0064}, + {8, 0x0024}, + {9, 0x00a9}, + {8, 0x0004}, + {8, 0x0084}, + {8, 0x0044}, + {9, 0x00e9}, + {7, 0x0106}, + {8, 0x005c}, + {8, 0x001c}, + {9, 0x0099}, + {7, 0x0116}, + {8, 0x007c}, + {8, 0x003c}, + {9, 0x00d9}, + {7, 0x010e}, + {8, 0x006c}, + {8, 0x002c}, + {9, 0x00b9}, + {8, 0x000c}, + {8, 0x008c}, + {8, 0x004c}, + {9, 0x00f9}, + {7, 0x0101}, + {8, 0x0052}, + {8, 0x0012}, + {8, 0x011a}, + {7, 0x0111}, + {8, 0x0072}, + {8, 0x0032}, + {9, 0x00c5}, + {7, 0x0109}, + {8, 0x0062}, + {8, 0x0022}, + {9, 0x00a5}, + {8, 0x0002}, + {8, 0x0082}, + {8, 0x0042}, + {9, 0x00e5}, + {7, 0x0105}, + {8, 0x005a}, + {8, 0x001a}, + {9, 0x0095}, + {7, 0x0115}, + {8, 0x007a}, + {8, 0x003a}, + {9, 0x00d5}, + {7, 0x010d}, + {8, 0x006a}, + {8, 0x002a}, + {9, 0x00b5}, + {8, 0x000a}, + {8, 0x008a}, + {8, 0x004a}, + {9, 0x00f5}, + {7, 0x0103}, + {8, 0x0056}, + {8, 0x0016}, + {8, 0x011e}, + {7, 0x0113}, + {8, 0x0076}, + {8, 0x0036}, + {9, 0x00cd}, + {7, 0x010b}, + {8, 0x0066}, + {8, 0x0026}, + {9, 0x00ad}, + {8, 0x0006}, + {8, 0x0086}, + {8, 0x0046}, + {9, 0x00ed}, + {7, 0x0107}, + {8, 0x005e}, + {8, 0x001e}, + {9, 0x009d}, + {7, 0x0117}, + {8, 0x007e}, + {8, 0x003e}, + {9, 0x00dd}, + {7, 0x010f}, + {8, 0x006e}, + {8, 0x002e}, + {9, 0x00bd}, + {8, 0x000e}, + {8, 0x008e}, + {8, 0x004e}, + {9, 0x00fd}, + {7, 0x0100}, + {8, 0x0051}, + {8, 0x0011}, + {8, 0x0119}, + {7, 0x0110}, + {8, 0x0071}, + {8, 0x0031}, + {9, 0x00c3}, + {7, 0x0108}, + {8, 0x0061}, + {8, 0x0021}, + {9, 0x00a3}, + {8, 0x0001}, + {8, 0x0081}, + {8, 0x0041}, + {9, 0x00e3}, + {7, 0x0104}, + {8, 0x0059}, + {8, 0x0019}, + {9, 0x0093}, + {7, 0x0114}, + {8, 0x0079}, + {8, 0x0039}, + {9, 0x00d3}, + {7, 0x010c}, + {8, 0x0069}, + {8, 0x0029}, + {9, 0x00b3}, + {8, 0x0009}, + {8, 0x0089}, + {8, 0x0049}, + {9, 0x00f3}, + {7, 0x0102}, + {8, 0x0055}, + {8, 0x0015}, + {8, 0x011d}, + {7, 0x0112}, + {8, 0x0075}, + {8, 0x0035}, + {9, 0x00cb}, + {7, 0x010a}, + {8, 0x0065}, + {8, 0x0025}, + {9, 0x00ab}, + {8, 0x0005}, + {8, 0x0085}, + {8, 0x0045}, + {9, 0x00eb}, + {7, 0x0106}, + {8, 0x005d}, + {8, 0x001d}, + {9, 0x009b}, + {7, 0x0116}, + {8, 0x007d}, + {8, 0x003d}, + {9, 0x00db}, + {7, 0x010e}, + {8, 0x006d}, + {8, 0x002d}, + {9, 0x00bb}, + {8, 0x000d}, + {8, 0x008d}, + {8, 0x004d}, + {9, 0x00fb}, + {7, 0x0101}, + {8, 0x0053}, + {8, 0x0013}, + {8, 0x011b}, + {7, 0x0111}, + {8, 0x0073}, + {8, 0x0033}, + {9, 0x00c7}, + {7, 0x0109}, + {8, 0x0063}, + {8, 0x0023}, + {9, 0x00a7}, + {8, 0x0003}, + {8, 0x0083}, + {8, 0x0043}, + {9, 0x00e7}, + {7, 0x0105}, + {8, 0x005b}, + {8, 0x001b}, + {9, 0x0097}, + {7, 0x0115}, + {8, 0x007b}, + {8, 0x003b}, + {9, 0x00d7}, + {7, 0x010d}, + {8, 0x006b}, + {8, 0x002b}, + {9, 0x00b7}, + {8, 0x000b}, + {8, 0x008b}, + {8, 0x004b}, + {9, 0x00f7}, + {7, 0x0103}, + {8, 0x0057}, + {8, 0x0017}, + {8, 0x011f}, + {7, 0x0113}, + {8, 0x0077}, + {8, 0x0037}, + {9, 0x00cf}, + {7, 0x010b}, + {8, 0x0067}, + {8, 0x0027}, + {9, 0x00af}, + {8, 0x0007}, + {8, 0x0087}, + {8, 0x0047}, + {9, 0x00ef}, + {7, 0x0107}, + {8, 0x005f}, + {8, 0x001f}, + {9, 0x009f}, + {7, 0x0117}, + {8, 0x007f}, + {8, 0x003f}, + {9, 0x00df}, + {7, 0x010f}, + {8, 0x006f}, + {8, 0x002f}, + {9, 0x00bf}, + {8, 0x000f}, + {8, 0x008f}, + {8, 0x004f}, + {9, 0x00ff} +}; + +FlateHuffmanTab FlateStream::fixedLitCodeTab = { + flateFixedLitCodeTabCodes, 9 +}; + +static FlateCode flateFixedDistCodeTabCodes[32] = { + {5, 0x0000}, + {5, 0x0010}, + {5, 0x0008}, + {5, 0x0018}, + {5, 0x0004}, + {5, 0x0014}, + {5, 0x000c}, + {5, 0x001c}, + {5, 0x0002}, + {5, 0x0012}, + {5, 0x000a}, + {5, 0x001a}, + {5, 0x0006}, + {5, 0x0016}, + {5, 0x000e}, + {0, 0x0000}, + {5, 0x0001}, + {5, 0x0011}, + {5, 0x0009}, + {5, 0x0019}, + {5, 0x0005}, + {5, 0x0015}, + {5, 0x000d}, + {5, 0x001d}, + {5, 0x0003}, + {5, 0x0013}, + {5, 0x000b}, + {5, 0x001b}, + {5, 0x0007}, + {5, 0x0017}, + {5, 0x000f}, + {0, 0x0000} +}; + +FlateHuffmanTab FlateStream::fixedDistCodeTab = { + flateFixedDistCodeTabCodes, 5 +}; + +FlateStream::FlateStream(Stream *strA, int predictor, int columns, + int colors, int bits): + FilterStream(strA) { + if (predictor != 1) { + pred = new StreamPredictor(this, predictor, columns, colors, bits); + if (!pred->isOk()) { + delete pred; + pred = NULL; + } + } else { + pred = NULL; + } + litCodeTab.codes = NULL; + distCodeTab.codes = NULL; + memset(buf, 0, flateWindow); +} + +FlateStream::~FlateStream() { + if (litCodeTab.codes != fixedLitCodeTab.codes) { + gfree(litCodeTab.codes); + } + if (distCodeTab.codes != fixedDistCodeTab.codes) { + gfree(distCodeTab.codes); + } + if (pred) { + delete pred; + } + delete str; +} + +void FlateStream::reset() { + int cmf, flg; + + index = 0; + remain = 0; + codeBuf = 0; + codeSize = 0; + compressedBlock = gFalse; + endOfBlock = gTrue; + eof = gTrue; + + str->reset(); + + // read header + //~ need to look at window size? + endOfBlock = eof = gTrue; + cmf = str->getChar(); + flg = str->getChar(); + if (cmf == EOF || flg == EOF) + return; + if ((cmf & 0x0f) != 0x08) { + error(getPos(), "Unknown compression method in flate stream"); + return; + } + if ((((cmf << 8) + flg) % 31) != 0) { + error(getPos(), "Bad FCHECK in flate stream"); + return; + } + if (flg & 0x20) { + error(getPos(), "FDICT bit set in flate stream"); + return; + } + + eof = gFalse; +} + +int FlateStream::getChar() { + int c; + + if (pred) { + return pred->getChar(); + } + while (remain == 0) { + if (endOfBlock && eof) + return EOF; + readSome(); + } + c = buf[index]; + index = (index + 1) & flateMask; + --remain; + return c; +} + +int FlateStream::lookChar() { + int c; + + if (pred) { + return pred->lookChar(); + } + while (remain == 0) { + if (endOfBlock && eof) + return EOF; + readSome(); + } + c = buf[index]; + return c; +} + +int FlateStream::getRawChar() { + int c; + + while (remain == 0) { + if (endOfBlock && eof) + return EOF; + readSome(); + } + c = buf[index]; + index = (index + 1) & flateMask; + --remain; + return c; +} + +GString *FlateStream::getPSFilter(int psLevel, char *indent) { + GString *s; + + if (psLevel < 3 || pred) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent))) { + return NULL; + } + s->append(indent)->append("<< >> /FlateDecode filter\n"); + return s; +} + +GBool FlateStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +void FlateStream::readSome() { + int code1, code2; + int len, dist; + int i, j, k; + int c; + + if (endOfBlock) { + if (!startBlock()) + return; + } + + if (compressedBlock) { + if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF) + goto err; + if (code1 < 256) { + buf[index] = code1; + remain = 1; + } else if (code1 == 256) { + endOfBlock = gTrue; + remain = 0; + } else { + code1 -= 257; + code2 = lengthDecode[code1].bits; + if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF) + goto err; + len = lengthDecode[code1].first + code2; + if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF) + goto err; + code2 = distDecode[code1].bits; + if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF) + goto err; + dist = distDecode[code1].first + code2; + i = index; + j = (index - dist) & flateMask; + for (k = 0; k < len; ++k) { + buf[i] = buf[j]; + i = (i + 1) & flateMask; + j = (j + 1) & flateMask; + } + remain = len; + } + + } else { + len = (blockLen < flateWindow) ? blockLen : flateWindow; + for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) { + if ((c = str->getChar()) == EOF) { + endOfBlock = eof = gTrue; + break; + } + buf[j] = c & 0xff; + } + remain = i; + blockLen -= len; + if (blockLen == 0) + endOfBlock = gTrue; + } + + return; + +err: + error(getPos(), "Unexpected end of file in flate stream"); + endOfBlock = eof = gTrue; + remain = 0; +} + +GBool FlateStream::startBlock() { + int blockHdr; + int c; + int check; + + // free the code tables from the previous block + if (litCodeTab.codes != fixedLitCodeTab.codes) { + gfree(litCodeTab.codes); + } + litCodeTab.codes = NULL; + if (distCodeTab.codes != fixedDistCodeTab.codes) { + gfree(distCodeTab.codes); + } + distCodeTab.codes = NULL; + + // read block header + blockHdr = getCodeWord(3); + if (blockHdr & 1) + eof = gTrue; + blockHdr >>= 1; + + // uncompressed block + if (blockHdr == 0) { + compressedBlock = gFalse; + if ((c = str->getChar()) == EOF) + goto err; + blockLen = c & 0xff; + if ((c = str->getChar()) == EOF) + goto err; + blockLen |= (c & 0xff) << 8; + if ((c = str->getChar()) == EOF) + goto err; + check = c & 0xff; + if ((c = str->getChar()) == EOF) + goto err; + check |= (c & 0xff) << 8; + if (check != (~blockLen & 0xffff)) + error(getPos(), "Bad uncompressed block length in flate stream"); + codeBuf = 0; + codeSize = 0; + + // compressed block with fixed codes + } else if (blockHdr == 1) { + compressedBlock = gTrue; + loadFixedCodes(); + + // compressed block with dynamic codes + } else if (blockHdr == 2) { + compressedBlock = gTrue; + if (!readDynamicCodes()) { + goto err; + } + + // unknown block type + } else { + goto err; + } + + endOfBlock = gFalse; + return gTrue; + +err: + error(getPos(), "Bad block header in flate stream"); + endOfBlock = eof = gTrue; + return gFalse; +} + +void FlateStream::loadFixedCodes() { + litCodeTab.codes = fixedLitCodeTab.codes; + litCodeTab.maxLen = fixedLitCodeTab.maxLen; + distCodeTab.codes = fixedDistCodeTab.codes; + distCodeTab.maxLen = fixedDistCodeTab.maxLen; +} + +GBool FlateStream::readDynamicCodes() { + int numCodeLenCodes; + int numLitCodes; + int numDistCodes; + int codeLenCodeLengths[flateMaxCodeLenCodes]; + FlateHuffmanTab codeLenCodeTab; + int len, repeat, code; + int i; + + codeLenCodeTab.codes = NULL; + + // read lengths + if ((numLitCodes = getCodeWord(5)) == EOF) { + goto err; + } + numLitCodes += 257; + if ((numDistCodes = getCodeWord(5)) == EOF) { + goto err; + } + numDistCodes += 1; + if ((numCodeLenCodes = getCodeWord(4)) == EOF) { + goto err; + } + numCodeLenCodes += 4; + if (numLitCodes > flateMaxLitCodes || + numDistCodes > flateMaxDistCodes || + numCodeLenCodes > flateMaxCodeLenCodes) { + goto err; + } + + // build the code length code table + for (i = 0; i < flateMaxCodeLenCodes; ++i) { + codeLenCodeLengths[i] = 0; + } + for (i = 0; i < numCodeLenCodes; ++i) { + if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) { + goto err; + } + } + compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab); + + // build the literal and distance code tables + len = 0; + repeat = 0; + i = 0; + while (i < numLitCodes + numDistCodes) { + if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) { + goto err; + } + if (code == 16) { + if ((repeat = getCodeWord(2)) == EOF) { + goto err; + } + repeat += 3; + if (i + repeat > numLitCodes + numDistCodes) { + goto err; + } + for (; repeat > 0; --repeat) { + codeLengths[i++] = len; + } + } else if (code == 17) { + if ((repeat = getCodeWord(3)) == EOF) { + goto err; + } + repeat += 3; + if (i + repeat > numLitCodes + numDistCodes) { + goto err; + } + len = 0; + for (; repeat > 0; --repeat) { + codeLengths[i++] = 0; + } + } else if (code == 18) { + if ((repeat = getCodeWord(7)) == EOF) { + goto err; + } + repeat += 11; + if (i + repeat > numLitCodes + numDistCodes) { + goto err; + } + len = 0; + for (; repeat > 0; --repeat) { + codeLengths[i++] = 0; + } + } else { + codeLengths[i++] = len = code; + } + } + compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab); + compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab); + + gfree(codeLenCodeTab.codes); + return gTrue; + +err: + error(getPos(), "Bad dynamic code table in flate stream"); + gfree(codeLenCodeTab.codes); + return gFalse; +} + +// Convert an array of lengths, in value order, into a +// Huffman code lookup table. +void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) { + int tabSize, len, code, code2, skip, val, i, t; + + // find max code length + tab->maxLen = 0; + for (val = 0; val < n; ++val) { + if (lengths[val] > tab->maxLen) { + tab->maxLen = lengths[val]; + } + } + + // allocate the table + tabSize = 1 << tab->maxLen; + tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode)); + + // clear the table + for (i = 0; i < tabSize; ++i) { + tab->codes[i].len = 0; + tab->codes[i].val = 0; + } + + // build the table + for (len = 1, code = 0, skip = 2; + len <= tab->maxLen; + ++len, code <<= 1, skip <<= 1) { + for (val = 0; val < n; ++val) { + if (lengths[val] == len) { + + // bit-reverse the code + code2 = 0; + t = code; + for (i = 0; i < len; ++i) { + code2 = (code2 << 1) | (t & 1); + t >>= 1; + } + + // fill in the table entries + for (i = code2; i < tabSize; i += skip) { + tab->codes[i].len = (Gushort)len; + tab->codes[i].val = (Gushort)val; + } + + ++code; + } + } + } +} + +int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) { + FlateCode *code; + int c; + + while (codeSize < tab->maxLen) { + if ((c = str->getChar()) == EOF) { + break; + } + codeBuf |= (c & 0xff) << codeSize; + codeSize += 8; + } + code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)]; + if (codeSize == 0 || codeSize < code->len || code->len == 0) { + return EOF; + } + codeBuf >>= code->len; + codeSize -= code->len; + return (int)code->val; +} + +int FlateStream::getCodeWord(int bits) { + int c; + + while (codeSize < bits) { + if ((c = str->getChar()) == EOF) + return EOF; + codeBuf |= (c & 0xff) << codeSize; + codeSize += 8; + } + c = codeBuf & ((1 << bits) - 1); + codeBuf >>= bits; + codeSize -= bits; + return c; +} + +//------------------------------------------------------------------------ +// EOFStream +//------------------------------------------------------------------------ + +EOFStream::EOFStream(Stream *strA): + FilterStream(strA) { +} + +EOFStream::~EOFStream() { + delete str; +} + +//------------------------------------------------------------------------ +// FixedLengthEncoder +//------------------------------------------------------------------------ + +FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA): + FilterStream(strA) { + length = lengthA; + count = 0; +} + +FixedLengthEncoder::~FixedLengthEncoder() { + if (str->isEncoder()) + delete str; +} + +void FixedLengthEncoder::reset() { + str->reset(); + count = 0; +} + +int FixedLengthEncoder::getChar() { + if (length >= 0 && count >= length) + return EOF; + ++count; + return str->getChar(); +} + +int FixedLengthEncoder::lookChar() { + if (length >= 0 && count >= length) + return EOF; + return str->getChar(); +} + +GBool FixedLengthEncoder::isBinary(GBool last) { + return str->isBinary(gTrue); +} + +//------------------------------------------------------------------------ +// ASCIIHexEncoder +//------------------------------------------------------------------------ + +ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA): + FilterStream(strA) { + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +ASCIIHexEncoder::~ASCIIHexEncoder() { + if (str->isEncoder()) { + delete str; + } +} + +void ASCIIHexEncoder::reset() { + str->reset(); + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +GBool ASCIIHexEncoder::fillBuf() { + static char *hex = "0123456789abcdef"; + int c; + + if (eof) { + return gFalse; + } + bufPtr = bufEnd = buf; + if ((c = str->getChar()) == EOF) { + *bufEnd++ = '>'; + eof = gTrue; + } else { + if (lineLen >= 64) { + *bufEnd++ = '\n'; + lineLen = 0; + } + *bufEnd++ = hex[(c >> 4) & 0x0f]; + *bufEnd++ = hex[c & 0x0f]; + lineLen += 2; + } + return gTrue; +} + +//------------------------------------------------------------------------ +// ASCII85Encoder +//------------------------------------------------------------------------ + +ASCII85Encoder::ASCII85Encoder(Stream *strA): + FilterStream(strA) { + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +ASCII85Encoder::~ASCII85Encoder() { + if (str->isEncoder()) + delete str; +} + +void ASCII85Encoder::reset() { + str->reset(); + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +GBool ASCII85Encoder::fillBuf() { + Gulong t; + char buf1[5]; + int c0, c1, c2, c3; + int n, i; + + if (eof) { + return gFalse; + } + c0 = str->getChar(); + c1 = str->getChar(); + c2 = str->getChar(); + c3 = str->getChar(); + bufPtr = bufEnd = buf; + if (c3 == EOF) { + if (c0 == EOF) { + n = 0; + t = 0; + } else { + if (c1 == EOF) { + n = 1; + t = c0 << 24; + } else if (c2 == EOF) { + n = 2; + t = (c0 << 24) | (c1 << 16); + } else { + n = 3; + t = (c0 << 24) | (c1 << 16) | (c2 << 8); + } + for (i = 4; i >= 0; --i) { + buf1[i] = (char)(t % 85 + 0x21); + t /= 85; + } + for (i = 0; i <= n; ++i) { + *bufEnd++ = buf1[i]; + if (++lineLen == 65) { + *bufEnd++ = '\n'; + lineLen = 0; + } + } + } + *bufEnd++ = '~'; + *bufEnd++ = '>'; + eof = gTrue; + } else { + t = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3; + if (t == 0) { + *bufEnd++ = 'z'; + if (++lineLen == 65) { + *bufEnd++ = '\n'; + lineLen = 0; + } + } else { + for (i = 4; i >= 0; --i) { + buf1[i] = (char)(t % 85 + 0x21); + t /= 85; + } + for (i = 0; i <= 4; ++i) { + *bufEnd++ = buf1[i]; + if (++lineLen == 65) { + *bufEnd++ = '\n'; + lineLen = 0; + } + } + } + } + return gTrue; +} + +//------------------------------------------------------------------------ +// RunLengthEncoder +//------------------------------------------------------------------------ + +RunLengthEncoder::RunLengthEncoder(Stream *strA): + FilterStream(strA) { + bufPtr = bufEnd = nextEnd = buf; + eof = gFalse; +} + +RunLengthEncoder::~RunLengthEncoder() { + if (str->isEncoder()) + delete str; +} + +void RunLengthEncoder::reset() { + str->reset(); + bufPtr = bufEnd = nextEnd = buf; + eof = gFalse; +} + +// +// When fillBuf finishes, buf[] looks like this: +// +-----+--------------+-----------------+-- +// + tag | ... data ... | next 0, 1, or 2 | +// +-----+--------------+-----------------+-- +// ^ ^ ^ +// bufPtr bufEnd nextEnd +// +GBool RunLengthEncoder::fillBuf() { + int c, c1, c2; + int n; + + // already hit EOF? + if (eof) + return gFalse; + + // grab two bytes + if (nextEnd < bufEnd + 1) { + if ((c1 = str->getChar()) == EOF) { + eof = gTrue; + return gFalse; + } + } else { + c1 = bufEnd[0] & 0xff; + } + if (nextEnd < bufEnd + 2) { + if ((c2 = str->getChar()) == EOF) { + eof = gTrue; + buf[0] = 0; + buf[1] = c1; + bufPtr = buf; + bufEnd = &buf[2]; + return gTrue; + } + } else { + c2 = bufEnd[1] & 0xff; + } + + // check for repeat + c = 0; // make gcc happy + if (c1 == c2) { + n = 2; + while (n < 128 && (c = str->getChar()) == c1) + ++n; + buf[0] = (char)(257 - n); + buf[1] = c1; + bufEnd = &buf[2]; + if (c == EOF) { + eof = gTrue; + } else if (n < 128) { + buf[2] = c; + nextEnd = &buf[3]; + } else { + nextEnd = bufEnd; + } + + // get up to 128 chars + } else { + buf[1] = c1; + buf[2] = c2; + n = 2; + while (n < 128) { + if ((c = str->getChar()) == EOF) { + eof = gTrue; + break; + } + ++n; + buf[n] = c; + if (buf[n] == buf[n-1]) + break; + } + if (buf[n] == buf[n-1]) { + buf[0] = (char)(n-2-1); + bufEnd = &buf[n-1]; + nextEnd = &buf[n+1]; + } else { + buf[0] = (char)(n-1); + bufEnd = nextEnd = &buf[n+1]; + } + } + bufPtr = buf; + return gTrue; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Stream-CCITT.h swftools-0.9.1/lib/pdf/xpdf/Stream-CCITT.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Stream-CCITT.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Stream-CCITT.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,459 @@ +//======================================================================== +// +// Stream-CCITT.h +// +// Tables for CCITT Fax decoding. +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +struct CCITTCode { + short bits; + short n; +}; + +#define ccittEOL -2 + +//------------------------------------------------------------------------ +// 2D codes +//------------------------------------------------------------------------ + +#define twoDimPass 0 +#define twoDimHoriz 1 +#define twoDimVert0 2 +#define twoDimVertR1 3 +#define twoDimVertL1 4 +#define twoDimVertR2 5 +#define twoDimVertL2 6 +#define twoDimVertR3 7 +#define twoDimVertL3 8 + +// 1-7 bit codes +static CCITTCode twoDimTab1[128] = { + {-1, -1}, {-1, -1}, // 000000x + {7, twoDimVertL3}, // 0000010 + {7, twoDimVertR3}, // 0000011 + {6, twoDimVertL2}, {6, twoDimVertL2}, // 000010x + {6, twoDimVertR2}, {6, twoDimVertR2}, // 000011x + {4, twoDimPass}, {4, twoDimPass}, // 0001xxx + {4, twoDimPass}, {4, twoDimPass}, + {4, twoDimPass}, {4, twoDimPass}, + {4, twoDimPass}, {4, twoDimPass}, + {3, twoDimHoriz}, {3, twoDimHoriz}, // 001xxxx + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimHoriz}, {3, twoDimHoriz}, + {3, twoDimVertL1}, {3, twoDimVertL1}, // 010xxxx + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertL1}, {3, twoDimVertL1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, // 011xxxx + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {3, twoDimVertR1}, {3, twoDimVertR1}, + {1, twoDimVert0}, {1, twoDimVert0}, // 1xxxxxx + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0}, + {1, twoDimVert0}, {1, twoDimVert0} +}; + +//------------------------------------------------------------------------ +// white run lengths +//------------------------------------------------------------------------ + +// 11-12 bit codes (upper 7 bits are 0) +static CCITTCode whiteTab1[32] = { + {-1, -1}, // 00000 + {12, ccittEOL}, // 00001 + {-1, -1}, {-1, -1}, // 0001x + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 001xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 010xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 011xx + {11, 1792}, {11, 1792}, // 1000x + {12, 1984}, // 10010 + {12, 2048}, // 10011 + {12, 2112}, // 10100 + {12, 2176}, // 10101 + {12, 2240}, // 10110 + {12, 2304}, // 10111 + {11, 1856}, {11, 1856}, // 1100x + {11, 1920}, {11, 1920}, // 1101x + {12, 2368}, // 11100 + {12, 2432}, // 11101 + {12, 2496}, // 11110 + {12, 2560} // 11111 +}; + +// 1-9 bit codes +static CCITTCode whiteTab2[512] = { + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 0000000xx + {8, 29}, {8, 29}, // 00000010x + {8, 30}, {8, 30}, // 00000011x + {8, 45}, {8, 45}, // 00000100x + {8, 46}, {8, 46}, // 00000101x + {7, 22}, {7, 22}, {7, 22}, {7, 22}, // 0000011xx + {7, 23}, {7, 23}, {7, 23}, {7, 23}, // 0000100xx + {8, 47}, {8, 47}, // 00001010x + {8, 48}, {8, 48}, // 00001011x + {6, 13}, {6, 13}, {6, 13}, {6, 13}, // 000011xxx + {6, 13}, {6, 13}, {6, 13}, {6, 13}, + {7, 20}, {7, 20}, {7, 20}, {7, 20}, // 0001000xx + {8, 33}, {8, 33}, // 00010010x + {8, 34}, {8, 34}, // 00010011x + {8, 35}, {8, 35}, // 00010100x + {8, 36}, {8, 36}, // 00010101x + {8, 37}, {8, 37}, // 00010110x + {8, 38}, {8, 38}, // 00010111x + {7, 19}, {7, 19}, {7, 19}, {7, 19}, // 0001100xx + {8, 31}, {8, 31}, // 00011010x + {8, 32}, {8, 32}, // 00011011x + {6, 1}, {6, 1}, {6, 1}, {6, 1}, // 000111xxx + {6, 1}, {6, 1}, {6, 1}, {6, 1}, + {6, 12}, {6, 12}, {6, 12}, {6, 12}, // 001000xxx + {6, 12}, {6, 12}, {6, 12}, {6, 12}, + {8, 53}, {8, 53}, // 00100100x + {8, 54}, {8, 54}, // 00100101x + {7, 26}, {7, 26}, {7, 26}, {7, 26}, // 0010011xx + {8, 39}, {8, 39}, // 00101000x + {8, 40}, {8, 40}, // 00101001x + {8, 41}, {8, 41}, // 00101010x + {8, 42}, {8, 42}, // 00101011x + {8, 43}, {8, 43}, // 00101100x + {8, 44}, {8, 44}, // 00101101x + {7, 21}, {7, 21}, {7, 21}, {7, 21}, // 0010111xx + {7, 28}, {7, 28}, {7, 28}, {7, 28}, // 0011000xx + {8, 61}, {8, 61}, // 00110010x + {8, 62}, {8, 62}, // 00110011x + {8, 63}, {8, 63}, // 00110100x + {8, 0}, {8, 0}, // 00110101x + {8, 320}, {8, 320}, // 00110110x + {8, 384}, {8, 384}, // 00110111x + {5, 10}, {5, 10}, {5, 10}, {5, 10}, // 00111xxxx + {5, 10}, {5, 10}, {5, 10}, {5, 10}, + {5, 10}, {5, 10}, {5, 10}, {5, 10}, + {5, 10}, {5, 10}, {5, 10}, {5, 10}, + {5, 11}, {5, 11}, {5, 11}, {5, 11}, // 01000xxxx + {5, 11}, {5, 11}, {5, 11}, {5, 11}, + {5, 11}, {5, 11}, {5, 11}, {5, 11}, + {5, 11}, {5, 11}, {5, 11}, {5, 11}, + {7, 27}, {7, 27}, {7, 27}, {7, 27}, // 0100100xx + {8, 59}, {8, 59}, // 01001010x + {8, 60}, {8, 60}, // 01001011x + {9, 1472}, // 010011000 + {9, 1536}, // 010011001 + {9, 1600}, // 010011010 + {9, 1728}, // 010011011 + {7, 18}, {7, 18}, {7, 18}, {7, 18}, // 0100111xx + {7, 24}, {7, 24}, {7, 24}, {7, 24}, // 0101000xx + {8, 49}, {8, 49}, // 01010010x + {8, 50}, {8, 50}, // 01010011x + {8, 51}, {8, 51}, // 01010100x + {8, 52}, {8, 52}, // 01010101x + {7, 25}, {7, 25}, {7, 25}, {7, 25}, // 0101011xx + {8, 55}, {8, 55}, // 01011000x + {8, 56}, {8, 56}, // 01011001x + {8, 57}, {8, 57}, // 01011010x + {8, 58}, {8, 58}, // 01011011x + {6, 192}, {6, 192}, {6, 192}, {6, 192}, // 010111xxx + {6, 192}, {6, 192}, {6, 192}, {6, 192}, + {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664}, // 011000xxx + {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664}, + {8, 448}, {8, 448}, // 01100100x + {8, 512}, {8, 512}, // 01100101x + {9, 704}, // 011001100 + {9, 768}, // 011001101 + {8, 640}, {8, 640}, // 01100111x + {8, 576}, {8, 576}, // 01101000x + {9, 832}, // 011010010 + {9, 896}, // 011010011 + {9, 960}, // 011010100 + {9, 1024}, // 011010101 + {9, 1088}, // 011010110 + {9, 1152}, // 011010111 + {9, 1216}, // 011011000 + {9, 1280}, // 011011001 + {9, 1344}, // 011011010 + {9, 1408}, // 011011011 + {7, 256}, {7, 256}, {7, 256}, {7, 256}, // 0110111xx + {4, 2}, {4, 2}, {4, 2}, {4, 2}, // 0111xxxxx + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 2}, {4, 2}, {4, 2}, {4, 2}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, // 1000xxxxx + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, + {5, 128}, {5, 128}, {5, 128}, {5, 128}, // 10010xxxx + {5, 128}, {5, 128}, {5, 128}, {5, 128}, + {5, 128}, {5, 128}, {5, 128}, {5, 128}, + {5, 128}, {5, 128}, {5, 128}, {5, 128}, + {5, 8}, {5, 8}, {5, 8}, {5, 8}, // 10011xxxx + {5, 8}, {5, 8}, {5, 8}, {5, 8}, + {5, 8}, {5, 8}, {5, 8}, {5, 8}, + {5, 8}, {5, 8}, {5, 8}, {5, 8}, + {5, 9}, {5, 9}, {5, 9}, {5, 9}, // 10100xxxx + {5, 9}, {5, 9}, {5, 9}, {5, 9}, + {5, 9}, {5, 9}, {5, 9}, {5, 9}, + {5, 9}, {5, 9}, {5, 9}, {5, 9}, + {6, 16}, {6, 16}, {6, 16}, {6, 16}, // 101010xxx + {6, 16}, {6, 16}, {6, 16}, {6, 16}, + {6, 17}, {6, 17}, {6, 17}, {6, 17}, // 101011xxx + {6, 17}, {6, 17}, {6, 17}, {6, 17}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, // 1011xxxxx + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 4}, {4, 4}, {4, 4}, {4, 4}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 1100xxxxx + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {4, 5}, {4, 5}, {4, 5}, {4, 5}, + {6, 14}, {6, 14}, {6, 14}, {6, 14}, // 110100xxx + {6, 14}, {6, 14}, {6, 14}, {6, 14}, + {6, 15}, {6, 15}, {6, 15}, {6, 15}, // 110101xxx + {6, 15}, {6, 15}, {6, 15}, {6, 15}, + {5, 64}, {5, 64}, {5, 64}, {5, 64}, // 11011xxxx + {5, 64}, {5, 64}, {5, 64}, {5, 64}, + {5, 64}, {5, 64}, {5, 64}, {5, 64}, + {5, 64}, {5, 64}, {5, 64}, {5, 64}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 1110xxxxx + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 6}, {4, 6}, {4, 6}, {4, 6}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, // 1111xxxxx + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7}, + {4, 7}, {4, 7}, {4, 7}, {4, 7} +}; + +//------------------------------------------------------------------------ +// black run lengths +//------------------------------------------------------------------------ + +// 10-13 bit codes (upper 6 bits are 0) +static CCITTCode blackTab1[128] = { + {-1, -1}, {-1, -1}, // 000000000000x + {12, ccittEOL}, {12, ccittEOL}, // 000000000001x + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000001xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000010xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000011xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000100xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000101xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000110xx + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000111xx + {11, 1792}, {11, 1792}, {11, 1792}, {11, 1792}, // 00000001000xx + {12, 1984}, {12, 1984}, // 000000010010x + {12, 2048}, {12, 2048}, // 000000010011x + {12, 2112}, {12, 2112}, // 000000010100x + {12, 2176}, {12, 2176}, // 000000010101x + {12, 2240}, {12, 2240}, // 000000010110x + {12, 2304}, {12, 2304}, // 000000010111x + {11, 1856}, {11, 1856}, {11, 1856}, {11, 1856}, // 00000001100xx + {11, 1920}, {11, 1920}, {11, 1920}, {11, 1920}, // 00000001101xx + {12, 2368}, {12, 2368}, // 000000011100x + {12, 2432}, {12, 2432}, // 000000011101x + {12, 2496}, {12, 2496}, // 000000011110x + {12, 2560}, {12, 2560}, // 000000011111x + {10, 18}, {10, 18}, {10, 18}, {10, 18}, // 0000001000xxx + {10, 18}, {10, 18}, {10, 18}, {10, 18}, + {12, 52}, {12, 52}, // 000000100100x + {13, 640}, // 0000001001010 + {13, 704}, // 0000001001011 + {13, 768}, // 0000001001100 + {13, 832}, // 0000001001101 + {12, 55}, {12, 55}, // 000000100111x + {12, 56}, {12, 56}, // 000000101000x + {13, 1280}, // 0000001010010 + {13, 1344}, // 0000001010011 + {13, 1408}, // 0000001010100 + {13, 1472}, // 0000001010101 + {12, 59}, {12, 59}, // 000000101011x + {12, 60}, {12, 60}, // 000000101100x + {13, 1536}, // 0000001011010 + {13, 1600}, // 0000001011011 + {11, 24}, {11, 24}, {11, 24}, {11, 24}, // 00000010111xx + {11, 25}, {11, 25}, {11, 25}, {11, 25}, // 00000011000xx + {13, 1664}, // 0000001100100 + {13, 1728}, // 0000001100101 + {12, 320}, {12, 320}, // 000000110011x + {12, 384}, {12, 384}, // 000000110100x + {12, 448}, {12, 448}, // 000000110101x + {13, 512}, // 0000001101100 + {13, 576}, // 0000001101101 + {12, 53}, {12, 53}, // 000000110111x + {12, 54}, {12, 54}, // 000000111000x + {13, 896}, // 0000001110010 + {13, 960}, // 0000001110011 + {13, 1024}, // 0000001110100 + {13, 1088}, // 0000001110101 + {13, 1152}, // 0000001110110 + {13, 1216}, // 0000001110111 + {10, 64}, {10, 64}, {10, 64}, {10, 64}, // 0000001111xxx + {10, 64}, {10, 64}, {10, 64}, {10, 64} +}; + +// 7-12 bit codes (upper 4 bits are 0) +static CCITTCode blackTab2[192] = { + {8, 13}, {8, 13}, {8, 13}, {8, 13}, // 00000100xxxx + {8, 13}, {8, 13}, {8, 13}, {8, 13}, + {8, 13}, {8, 13}, {8, 13}, {8, 13}, + {8, 13}, {8, 13}, {8, 13}, {8, 13}, + {11, 23}, {11, 23}, // 00000101000x + {12, 50}, // 000001010010 + {12, 51}, // 000001010011 + {12, 44}, // 000001010100 + {12, 45}, // 000001010101 + {12, 46}, // 000001010110 + {12, 47}, // 000001010111 + {12, 57}, // 000001011000 + {12, 58}, // 000001011001 + {12, 61}, // 000001011010 + {12, 256}, // 000001011011 + {10, 16}, {10, 16}, {10, 16}, {10, 16}, // 0000010111xx + {10, 17}, {10, 17}, {10, 17}, {10, 17}, // 0000011000xx + {12, 48}, // 000001100100 + {12, 49}, // 000001100101 + {12, 62}, // 000001100110 + {12, 63}, // 000001100111 + {12, 30}, // 000001101000 + {12, 31}, // 000001101001 + {12, 32}, // 000001101010 + {12, 33}, // 000001101011 + {12, 40}, // 000001101100 + {12, 41}, // 000001101101 + {11, 22}, {11, 22}, // 00000110111x + {8, 14}, {8, 14}, {8, 14}, {8, 14}, // 00000111xxxx + {8, 14}, {8, 14}, {8, 14}, {8, 14}, + {8, 14}, {8, 14}, {8, 14}, {8, 14}, + {8, 14}, {8, 14}, {8, 14}, {8, 14}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, // 0000100xxxxx + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 10}, {7, 10}, {7, 10}, {7, 10}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, // 0000101xxxxx + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {7, 11}, {7, 11}, {7, 11}, {7, 11}, + {9, 15}, {9, 15}, {9, 15}, {9, 15}, // 000011000xxx + {9, 15}, {9, 15}, {9, 15}, {9, 15}, + {12, 128}, // 000011001000 + {12, 192}, // 000011001001 + {12, 26}, // 000011001010 + {12, 27}, // 000011001011 + {12, 28}, // 000011001100 + {12, 29}, // 000011001101 + {11, 19}, {11, 19}, // 00001100111x + {11, 20}, {11, 20}, // 00001101000x + {12, 34}, // 000011010010 + {12, 35}, // 000011010011 + {12, 36}, // 000011010100 + {12, 37}, // 000011010101 + {12, 38}, // 000011010110 + {12, 39}, // 000011010111 + {11, 21}, {11, 21}, // 00001101100x + {12, 42}, // 000011011010 + {12, 43}, // 000011011011 + {10, 0}, {10, 0}, {10, 0}, {10, 0}, // 0000110111xx + {7, 12}, {7, 12}, {7, 12}, {7, 12}, // 0000111xxxxx + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12}, + {7, 12}, {7, 12}, {7, 12}, {7, 12} +}; + +// 2-6 bit codes +static CCITTCode blackTab3[64] = { + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 0000xx + {6, 9}, // 000100 + {6, 8}, // 000101 + {5, 7}, {5, 7}, // 00011x + {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 0010xx + {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 0011xx + {3, 1}, {3, 1}, {3, 1}, {3, 1}, // 010xxx + {3, 1}, {3, 1}, {3, 1}, {3, 1}, + {3, 4}, {3, 4}, {3, 4}, {3, 4}, // 011xxx + {3, 4}, {3, 4}, {3, 4}, {3, 4}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, // 10xxxx + {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, // 11xxxx + {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2} +}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/Stream.h swftools-0.9.1/lib/pdf/xpdf/Stream.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/Stream.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/Stream.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,859 @@ +//======================================================================== +// +// Stream.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef STREAM_H +#define STREAM_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "gtypes.h" +#include "Object.h" + +class BaseStream; + +//------------------------------------------------------------------------ + +enum StreamKind { + strFile, + strASCIIHex, + strASCII85, + strLZW, + strRunLength, + strCCITTFax, + strDCT, + strFlate, + strJBIG2, + strJPX, + strWeird // internal-use stream types +}; + +enum StreamColorSpaceMode { + streamCSNone, + streamCSDeviceGray, + streamCSDeviceRGB, + streamCSDeviceCMYK, + streamCSDeviceRGBX +}; + +//------------------------------------------------------------------------ + +// This is in Stream.h instead of Decrypt.h to avoid really annoying +// include file dependency loops. +enum CryptAlgorithm { + cryptRC4, + cryptAES +}; + +//------------------------------------------------------------------------ +// Stream (base class) +//------------------------------------------------------------------------ + +class Stream { +public: + + // Constructor. + Stream(); + + // Destructor. + virtual ~Stream(); + + // Reference counting. + int incRef() { return ++ref; } + int decRef() { return --ref; } + + // Get kind of stream. + virtual StreamKind getKind() = 0; + + // Reset stream to beginning. + virtual void reset() = 0; + + // Close down the stream. + virtual void close(); + + // Get next char from stream. + virtual int getChar() = 0; + + // Peek at next char in stream. + virtual int lookChar() = 0; + + // Get next char from stream without using the predictor. + // This is only used by StreamPredictor. + virtual int getRawChar(); + + // Get next line from stream. + virtual char *getLine(char *buf, int size); + + // Get current position in file. + virtual int getPos() = 0; + + // Go to a position in the stream. If
    is negative, the + // position is from the end of the file; otherwise the position is + // from the start of the file. + virtual void setPos(Guint pos, int dir = 0) = 0; + + // Get PostScript command for the filter(s). + virtual GString *getPSFilter(int psLevel, char *indent); + + // Does this stream type potentially contain non-printable chars? + virtual GBool isBinary(GBool last = gTrue) = 0; + + // Get the BaseStream of this stream. + virtual BaseStream *getBaseStream() = 0; + + // Get the stream after the last decoder (this may be a BaseStream + // or a DecryptStream). + virtual Stream *getUndecodedStream() = 0; + + // Get the dictionary associated with this stream. + virtual Dict *getDict() = 0; + + // Is this an encoding filter? + virtual GBool isEncoder() { return gFalse; } + + // Get image parameters which are defined by the stream contents. + virtual void getImageParams(int *bitsPerComponent, + StreamColorSpaceMode *csMode) {} + + // Return the next stream in the "stack". + virtual Stream *getNextStream() { return NULL; } + + // Add filters to this stream according to the parameters in . + // Returns the new stream. + Stream *addFilters(Object *dict); + +private: + + Stream *makeFilter(char *name, Stream *str, Object *params); + + int ref; // reference count +}; + +//------------------------------------------------------------------------ +// BaseStream +// +// This is the base class for all streams that read directly from a file. +//------------------------------------------------------------------------ + +class BaseStream: public Stream { +public: + + BaseStream(Object *dictA); + virtual ~BaseStream(); + virtual Stream *makeSubStream(Guint start, GBool limited, + Guint length, Object *dict) = 0; + virtual void setPos(Guint pos, int dir = 0) = 0; + virtual GBool isBinary(GBool last = gTrue) { return last; } + virtual BaseStream *getBaseStream() { return this; } + virtual Stream *getUndecodedStream() { return this; } + virtual Dict *getDict() { return dict.getDict(); } + virtual GString *getFileName() { return NULL; } + + // Get/set position of first byte of stream within the file. + virtual Guint getStart() = 0; + virtual void moveStart(int delta) = 0; + +private: + + Object dict; +}; + +//------------------------------------------------------------------------ +// FilterStream +// +// This is the base class for all streams that filter another stream. +//------------------------------------------------------------------------ + +class FilterStream: public Stream { +public: + + FilterStream(Stream *strA); + virtual ~FilterStream(); + virtual void close(); + virtual int getPos() { return str->getPos(); } + virtual void setPos(Guint pos, int dir = 0); + virtual BaseStream *getBaseStream() { return str->getBaseStream(); } + virtual Stream *getUndecodedStream() { return str->getUndecodedStream(); } + virtual Dict *getDict() { return str->getDict(); } + virtual Stream *getNextStream() { return str; } + +protected: + + Stream *str; +}; + +//------------------------------------------------------------------------ +// ImageStream +//------------------------------------------------------------------------ + +class ImageStream { +public: + + // Create an image stream object for an image with the specified + // parameters. Note that these are the actual image parameters, + // which may be different from the predictor parameters. + ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA); + + ~ImageStream(); + + // Reset the stream. + void reset(); + + // Gets the next pixel from the stream. should be able to hold + // at least nComps elements. Returns false at end of file. + GBool getPixel(Guchar *pix); + + // Returns a pointer to the next line of pixels. Returns NULL at + // end of file. + Guchar *getLine(); + + // Skip an entire line from the image. + void skipLine(); + +private: + + Stream *str; // base stream + int width; // pixels per line + int nComps; // components per pixel + int nBits; // bits per component + int nVals; // components per line + Guchar *imgLine; // line buffer + int imgIdx; // current index in imgLine +}; + +//------------------------------------------------------------------------ +// StreamPredictor +//------------------------------------------------------------------------ + +class StreamPredictor { +public: + + // Create a predictor object. Note that the parameters are for the + // predictor, and may not match the actual image parameters. + StreamPredictor(Stream *strA, int predictorA, + int widthA, int nCompsA, int nBitsA); + + ~StreamPredictor(); + + GBool isOk() { return ok; } + + int lookChar(); + int getChar(); + +private: + + GBool getNextLine(); + + Stream *str; // base stream + int predictor; // predictor + int width; // pixels per line + int nComps; // components per pixel + int nBits; // bits per component + int nVals; // components per line + int pixBytes; // bytes per pixel + int rowBytes; // bytes per line + Guchar *predLine; // line buffer + int predIdx; // current index in predLine + GBool ok; +}; + +//------------------------------------------------------------------------ +// FileStream +//------------------------------------------------------------------------ + +#define fileStreamBufSize 256 + +class FileStream: public BaseStream { +public: + + FileStream(FILE *fA, Guint startA, GBool limitedA, + Guint lengthA, Object *dictA); + virtual ~FileStream(); + virtual Stream *makeSubStream(Guint startA, GBool limitedA, + Guint lengthA, Object *dictA); + virtual StreamKind getKind() { return strFile; } + virtual void reset(); + virtual void close(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual int getPos() { return bufPos + (bufPtr - buf); } + virtual void setPos(Guint pos, int dir = 0); + virtual Guint getStart() { return start; } + virtual void moveStart(int delta); + +private: + + GBool fillBuf(); + + FILE *f; + Guint start; + GBool limited; + Guint length; + char buf[fileStreamBufSize]; + char *bufPtr; + char *bufEnd; + Guint bufPos; + int savePos; + GBool saved; +}; + +//------------------------------------------------------------------------ +// MemStream +//------------------------------------------------------------------------ + +class MemStream: public BaseStream { +public: + + MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); + virtual ~MemStream(); + virtual Stream *makeSubStream(Guint start, GBool limited, + Guint lengthA, Object *dictA); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual void close(); + virtual int getChar() + { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; } + virtual int lookChar() + { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; } + virtual int getPos() { return (int)(bufPtr - buf); } + virtual void setPos(Guint pos, int dir = 0); + virtual Guint getStart() { return start; } + virtual void moveStart(int delta); + +private: + + char *buf; + Guint start; + Guint length; + char *bufEnd; + char *bufPtr; + GBool needFree; +}; + +//------------------------------------------------------------------------ +// EmbedStream +// +// This is a special stream type used for embedded streams (inline +// images). It reads directly from the base stream -- after the +// EmbedStream is deleted, reads from the base stream will proceed where +// the BaseStream left off. Note that this is very different behavior +// that creating a new FileStream (using makeSubStream). +//------------------------------------------------------------------------ + +class EmbedStream: public BaseStream { +public: + + EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA); + virtual ~EmbedStream(); + virtual Stream *makeSubStream(Guint start, GBool limitedA, + Guint lengthA, Object *dictA); + virtual StreamKind getKind() { return str->getKind(); } + virtual void reset() {} + virtual int getChar(); + virtual int lookChar(); + virtual int getPos() { return str->getPos(); } + virtual void setPos(Guint pos, int dir = 0); + virtual Guint getStart(); + virtual void moveStart(int delta); + +private: + + Stream *str; + GBool limited; + Guint length; +}; + +//------------------------------------------------------------------------ +// ASCIIHexStream +//------------------------------------------------------------------------ + +class ASCIIHexStream: public FilterStream { +public: + + ASCIIHexStream(Stream *strA); + virtual ~ASCIIHexStream(); + virtual StreamKind getKind() { return strASCIIHex; } + virtual void reset(); + virtual int getChar() + { int c = lookChar(); buf = EOF; return c; } + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + int buf; + GBool eof; +}; + +//------------------------------------------------------------------------ +// ASCII85Stream +//------------------------------------------------------------------------ + +class ASCII85Stream: public FilterStream { +public: + + ASCII85Stream(Stream *strA); + virtual ~ASCII85Stream(); + virtual StreamKind getKind() { return strASCII85; } + virtual void reset(); + virtual int getChar() + { int ch = lookChar(); ++index; return ch; } + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + int c[5]; + int b[4]; + int index, n; + GBool eof; +}; + +//------------------------------------------------------------------------ +// LZWStream +//------------------------------------------------------------------------ + +class LZWStream: public FilterStream { +public: + + LZWStream(Stream *strA, int predictor, int columns, int colors, + int bits, int earlyA); + virtual ~LZWStream(); + virtual StreamKind getKind() { return strLZW; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getRawChar(); + virtual GString *getPSFilter(int psLevel, char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + StreamPredictor *pred; // predictor + int early; // early parameter + GBool eof; // true if at eof + int inputBuf; // input buffer + int inputBits; // number of bits in input buffer + struct { // decoding table + int length; + int head; + Guchar tail; + } table[4097]; + int nextCode; // next code to be used + int nextBits; // number of bits in next code word + int prevCode; // previous code used in stream + int newChar; // next char to be added to table + Guchar seqBuf[4097]; // buffer for current sequence + int seqLength; // length of current sequence + int seqIndex; // index into current sequence + GBool first; // first code after a table clear + + GBool processNextCode(); + void clearTable(); + int getCode(); +}; + +//------------------------------------------------------------------------ +// RunLengthStream +//------------------------------------------------------------------------ + +class RunLengthStream: public FilterStream { +public: + + RunLengthStream(Stream *strA); + virtual ~RunLengthStream(); + virtual StreamKind getKind() { return strRunLength; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual GString *getPSFilter(int psLevel, char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + char buf[128]; // buffer + char *bufPtr; // next char to read + char *bufEnd; // end of buffer + GBool eof; + + GBool fillBuf(); +}; + +//------------------------------------------------------------------------ +// CCITTFaxStream +//------------------------------------------------------------------------ + +struct CCITTCodeTable; + +class CCITTFaxStream: public FilterStream { +public: + + CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, + GBool byteAlignA, int columnsA, int rowsA, + GBool endOfBlockA, GBool blackA); + virtual ~CCITTFaxStream(); + virtual StreamKind getKind() { return strCCITTFax; } + virtual void reset(); + virtual int getChar() + { int c = lookChar(); buf = EOF; return c; } + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + int encoding; // 'K' parameter + GBool endOfLine; // 'EndOfLine' parameter + GBool byteAlign; // 'EncodedByteAlign' parameter + int columns; // 'Columns' parameter + int rows; // 'Rows' parameter + GBool endOfBlock; // 'EndOfBlock' parameter + GBool black; // 'BlackIs1' parameter + GBool eof; // true if at eof + GBool nextLine2D; // true if next line uses 2D encoding + int row; // current row + int inputBuf; // input buffer + int inputBits; // number of bits in input buffer + short *refLine; // reference line changing elements + int b1; // index into refLine + short *codingLine; // coding line changing elements + int a0; // index into codingLine + int outputBits; // remaining ouput bits + int buf; // character buffer + + short getTwoDimCode(); + short getWhiteCode(); + short getBlackCode(); + short lookBits(int n); + void eatBits(int n) { if ((inputBits -= n) < 0) inputBits = 0; } +}; + +//------------------------------------------------------------------------ +// DCTStream +//------------------------------------------------------------------------ + +// DCT component info +struct DCTCompInfo { + int id; // component ID + int hSample, vSample; // horiz/vert sampling resolutions + int quantTable; // quantization table number + int prevDC; // DC coefficient accumulator +}; + +struct DCTScanInfo { + GBool comp[4]; // comp[i] is set if component i is + // included in this scan + int numComps; // number of components in the scan + int dcHuffTable[4]; // DC Huffman table numbers + int acHuffTable[4]; // AC Huffman table numbers + int firstCoeff, lastCoeff; // first and last DCT coefficient + int ah, al; // successive approximation parameters +}; + +// DCT Huffman decoding table +struct DCTHuffTable { + Guchar firstSym[17]; // first symbol for this bit length + Gushort firstCode[17]; // first code for this bit length + Gushort numCodes[17]; // number of codes of this bit length + Guchar sym[256]; // symbols +}; + +class DCTStream: public FilterStream { +public: + + DCTStream(Stream *strA, int colorXformA); + virtual ~DCTStream(); + virtual StreamKind getKind() { return strDCT; } + virtual void reset(); + virtual void close(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, char *indent); + virtual GBool isBinary(GBool last = gTrue); + Stream *getRawStream() { return str; } + +private: + + GBool progressive; // set if in progressive mode + GBool interleaved; // set if in interleaved mode + int width, height; // image size + int mcuWidth, mcuHeight; // size of min coding unit, in data units + int bufWidth, bufHeight; // frameBuf size + DCTCompInfo compInfo[4]; // info for each component + DCTScanInfo scanInfo; // info for the current scan + int numComps; // number of components in image + int colorXform; // color transform: -1 = unspecified + // 0 = none + // 1 = YUV/YUVK -> RGB/CMYK + GBool gotJFIFMarker; // set if APP0 JFIF marker was present + GBool gotAdobeMarker; // set if APP14 Adobe marker was present + int restartInterval; // restart interval, in MCUs + Gushort quantTables[4][64]; // quantization tables + int numQuantTables; // number of quantization tables + DCTHuffTable dcHuffTables[4]; // DC Huffman tables + DCTHuffTable acHuffTables[4]; // AC Huffman tables + int numDCHuffTables; // number of DC Huffman tables + int numACHuffTables; // number of AC Huffman tables + Guchar *rowBuf[4][32]; // buffer for one MCU (non-progressive mode) + int *frameBuf[4]; // buffer for frame (progressive mode) + int comp, x, y, dy; // current position within image/MCU + int restartCtr; // MCUs left until restart + int restartMarker; // next restart marker + int eobRun; // number of EOBs left in the current run + int inputBuf; // input buffer for variable length codes + int inputBits; // number of valid bits in input buffer + + void restart(); + GBool readMCURow(); + void readScan(); + GBool readDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]); + GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]); + void decodeImage(); + void transformDataUnit(Gushort *quantTable, + int dataIn[64], Guchar dataOut[64]); + int readHuffSym(DCTHuffTable *table); + int readAmp(int size); + int readBit(); + GBool readHeader(); + GBool readBaselineSOF(); + GBool readProgressiveSOF(); + GBool readScanInfo(); + GBool readQuantTables(); + GBool readHuffmanTables(); + GBool readRestartInterval(); + GBool readJFIFMarker(); + GBool readAdobeMarker(); + GBool readTrailer(); + int readMarker(); + int read16(); +}; + +//------------------------------------------------------------------------ +// FlateStream +//------------------------------------------------------------------------ + +#define flateWindow 32768 // buffer size +#define flateMask (flateWindow-1) +#define flateMaxHuffman 15 // max Huffman code length +#define flateMaxCodeLenCodes 19 // max # code length codes +#define flateMaxLitCodes 288 // max # literal codes +#define flateMaxDistCodes 30 // max # distance codes + +// Huffman code table entry +struct FlateCode { + Gushort len; // code length, in bits + Gushort val; // value represented by this code +}; + +struct FlateHuffmanTab { + FlateCode *codes; + int maxLen; +}; + +// Decoding info for length and distance code words +struct FlateDecode { + int bits; // # extra bits + int first; // first length/distance +}; + +class FlateStream: public FilterStream { +public: + + FlateStream(Stream *strA, int predictor, int columns, + int colors, int bits); + virtual ~FlateStream(); + virtual StreamKind getKind() { return strFlate; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getRawChar(); + virtual GString *getPSFilter(int psLevel, char *indent); + virtual GBool isBinary(GBool last = gTrue); + +private: + + StreamPredictor *pred; // predictor + Guchar buf[flateWindow]; // output data buffer + int index; // current index into output buffer + int remain; // number valid bytes in output buffer + int codeBuf; // input buffer + int codeSize; // number of bits in input buffer + int // literal and distance code lengths + codeLengths[flateMaxLitCodes + flateMaxDistCodes]; + FlateHuffmanTab litCodeTab; // literal code table + FlateHuffmanTab distCodeTab; // distance code table + GBool compressedBlock; // set if reading a compressed block + int blockLen; // remaining length of uncompressed block + GBool endOfBlock; // set when end of block is reached + GBool eof; // set when end of stream is reached + + static int // code length code reordering + codeLenCodeMap[flateMaxCodeLenCodes]; + static FlateDecode // length decoding info + lengthDecode[flateMaxLitCodes-257]; + static FlateDecode // distance decoding info + distDecode[flateMaxDistCodes]; + static FlateHuffmanTab // fixed literal code table + fixedLitCodeTab; + static FlateHuffmanTab // fixed distance code table + fixedDistCodeTab; + + void readSome(); + GBool startBlock(); + void loadFixedCodes(); + GBool readDynamicCodes(); + void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab); + int getHuffmanCodeWord(FlateHuffmanTab *tab); + int getCodeWord(int bits); +}; + +//------------------------------------------------------------------------ +// EOFStream +//------------------------------------------------------------------------ + +class EOFStream: public FilterStream { +public: + + EOFStream(Stream *strA); + virtual ~EOFStream(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset() {} + virtual int getChar() { return EOF; } + virtual int lookChar() { return EOF; } + virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gFalse; } +}; + +//------------------------------------------------------------------------ +// FixedLengthEncoder +//------------------------------------------------------------------------ + +class FixedLengthEncoder: public FilterStream { +public: + + FixedLengthEncoder(Stream *strA, int lengthA); + ~FixedLengthEncoder(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } + virtual GBool isBinary(GBool last = gTrue); + virtual GBool isEncoder() { return gTrue; } + +private: + + int length; + int count; +}; + +//------------------------------------------------------------------------ +// ASCIIHexEncoder +//------------------------------------------------------------------------ + +class ASCIIHexEncoder: public FilterStream { +public: + + ASCIIHexEncoder(Stream *strA); + virtual ~ASCIIHexEncoder(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gFalse; } + virtual GBool isEncoder() { return gTrue; } + +private: + + char buf[4]; + char *bufPtr; + char *bufEnd; + int lineLen; + GBool eof; + + GBool fillBuf(); +}; + +//------------------------------------------------------------------------ +// ASCII85Encoder +//------------------------------------------------------------------------ + +class ASCII85Encoder: public FilterStream { +public: + + ASCII85Encoder(Stream *strA); + virtual ~ASCII85Encoder(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gFalse; } + virtual GBool isEncoder() { return gTrue; } + +private: + + char buf[8]; + char *bufPtr; + char *bufEnd; + int lineLen; + GBool eof; + + GBool fillBuf(); +}; + +//------------------------------------------------------------------------ +// RunLengthEncoder +//------------------------------------------------------------------------ + +class RunLengthEncoder: public FilterStream { +public: + + RunLengthEncoder(Stream *strA); + virtual ~RunLengthEncoder(); + virtual StreamKind getKind() { return strWeird; } + virtual void reset(); + virtual int getChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } + virtual int lookChar() + { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } + virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } + virtual GBool isBinary(GBool last = gTrue) { return gTrue; } + virtual GBool isEncoder() { return gTrue; } + +private: + + char buf[131]; + char *bufPtr; + char *bufEnd; + char *nextEnd; + GBool eof; + + GBool fillBuf(); +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/TextOutputDev.cc swftools-0.9.1/lib/pdf/xpdf/TextOutputDev.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/TextOutputDev.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/TextOutputDev.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,4090 @@ +//======================================================================== +// +// TextOutputDev.cc +// +// Copyright 1997-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#ifdef WIN32 +#include // for O_BINARY +#include // for setmode +#endif +#include "gmem.h" +#include "GString.h" +#include "GList.h" +#include "config.h" +#include "Error.h" +#include "GlobalParams.h" +#include "UnicodeMap.h" +#include "UnicodeTypeTable.h" +#include "GfxState.h" +#include "Link.h" +#include "TextOutputDev.h" + +#ifdef MACOS +// needed for setting type/creator of MacOS files +#include "ICSupport.h" +#endif + +//------------------------------------------------------------------------ +// parameters +//------------------------------------------------------------------------ + +// Each bucket in a text pool includes baselines within a range of +// this many points. +#define textPoolStep 4 + +// Inter-character space width which will cause addChar to start a new +// word. +#define minWordBreakSpace 0.1 + +// Negative inter-character space width, i.e., overlap, which will +// cause addChar to start a new word. +#define minDupBreakOverlap 0.2 + +// Max distance between baselines of two lines within a block, as a +// fraction of the font size. +#define maxLineSpacingDelta 1.5 + +// Max difference in primary font sizes on two lines in the same +// block. Delta1 is used when examining new lines above and below the +// current block; delta2 is used when examining text that overlaps the +// current block; delta3 is used when examining text to the left and +// right of the current block. +#define maxBlockFontSizeDelta1 0.05 +#define maxBlockFontSizeDelta2 0.6 +#define maxBlockFontSizeDelta3 0.2 + +// Max difference in font sizes inside a word. +#define maxWordFontSizeDelta 0.05 + +// Maximum distance between baselines of two words on the same line, +// e.g., distance between subscript or superscript and the primary +// baseline, as a fraction of the font size. +#define maxIntraLineDelta 0.5 + +// Minimum inter-word spacing, as a fraction of the font size. (Only +// used for raw ordering.) +#define minWordSpacing 0.15 + +// Maximum inter-word spacing, as a fraction of the font size. +#define maxWordSpacing 1.5 + +// Maximum horizontal spacing which will allow a word to be pulled +// into a block. +#define minColSpacing1 0.3 + +// Minimum spacing between columns, as a fraction of the font size. +#define minColSpacing2 1.0 + +// Maximum vertical spacing between blocks within a flow, as a +// multiple of the font size. +#define maxBlockSpacing 2.5 + +// Minimum spacing between characters within a word, as a fraction of +// the font size. +#define minCharSpacing -0.2 + +// Maximum spacing between characters within a word, as a fraction of +// the font size, when there is no obvious extra-wide character +// spacing. +#define maxCharSpacing 0.03 + +// When extra-wide character spacing is detected, the inter-character +// space threshold is set to the minimum inter-character space +// multiplied by this constant. +#define maxWideCharSpacingMul 1.3 + +// Upper limit on spacing between characters in a word. +#define maxWideCharSpacing 0.4 + +// Max difference in primary,secondary coordinates (as a fraction of +// the font size) allowed for duplicated text (fake boldface, drop +// shadows) which is to be discarded. +#define dupMaxPriDelta 0.1 +#define dupMaxSecDelta 0.2 + +// Max width of underlines (in points). +#define maxUnderlineWidth 3 + +// Min distance between baseline and underline (in points). +//~ this should be font-size-dependent +#define minUnderlineGap -2 + +// Max distance between baseline and underline (in points). +//~ this should be font-size-dependent +#define maxUnderlineGap 4 + +// Max horizontal distance between edge of word and start of underline +// (in points). +//~ this should be font-size-dependent +#define underlineSlack 1 + +// Max distance between edge of text and edge of link border +#define hyperlinkSlack 2 + +//------------------------------------------------------------------------ +// TextUnderline +//------------------------------------------------------------------------ + +class TextUnderline { +public: + + TextUnderline(double x0A, double y0A, double x1A, double y1A) + { x0 = x0A; y0 = y0A; x1 = x1A; y1 = y1A; horiz = y0 == y1; } + ~TextUnderline() {} + + double x0, y0, x1, y1; + GBool horiz; +}; + +//------------------------------------------------------------------------ +// TextLink +//------------------------------------------------------------------------ + +class TextLink { +public: + + TextLink(int xMinA, int yMinA, int xMaxA, int yMaxA, Link *linkA) + { xMin = xMinA; yMin = yMinA; xMax = xMaxA; yMax = yMaxA; link = linkA; } + ~TextLink() {} + + int xMin, yMin, xMax, yMax; + Link *link; +}; + +//------------------------------------------------------------------------ +// TextFontInfo +//------------------------------------------------------------------------ + +TextFontInfo::TextFontInfo(GfxState *state) { + gfxFont = state->getFont(); +#if TEXTOUT_WORD_LIST + fontName = (gfxFont && gfxFont->getOrigName()) + ? gfxFont->getOrigName()->copy() + : (GString *)NULL; + flags = gfxFont ? gfxFont->getFlags() : 0; +#endif +} + +TextFontInfo::~TextFontInfo() { +#if TEXTOUT_WORD_LIST + if (fontName) { + delete fontName; + } +#endif +} + +GBool TextFontInfo::matches(GfxState *state) { + return state->getFont() == gfxFont; +} + +//------------------------------------------------------------------------ +// TextWord +//------------------------------------------------------------------------ + +TextWord::TextWord(GfxState *state, int rotA, double x0, double y0, + int charPosA, TextFontInfo *fontA, double fontSizeA) { + GfxFont *gfxFont; + double x, y, ascent, descent; + + rot = rotA; + charPos = charPosA; + charLen = 0; + font = fontA; + fontSize = fontSizeA; + state->transform(x0, y0, &x, &y); + if ((gfxFont = font->gfxFont)) { + ascent = gfxFont->getAscent() * fontSize; + descent = gfxFont->getDescent() * fontSize; + } else { + // this means that the PDF file draws text without a current font, + // which should never happen + ascent = 0.95 * fontSize; + descent = -0.35 * fontSize; + } + switch (rot) { + case 0: + yMin = y - ascent; + yMax = y - descent; + if (yMin == yMax) { + // this is a sanity check for a case that shouldn't happen -- but + // if it does happen, we want to avoid dividing by zero later + yMin = y; + yMax = y + 1; + } + base = y; + break; + case 1: + xMin = x + descent; + xMax = x + ascent; + if (xMin == xMax) { + // this is a sanity check for a case that shouldn't happen -- but + // if it does happen, we want to avoid dividing by zero later + xMin = x; + xMax = x + 1; + } + base = x; + break; + case 2: + yMin = y + descent; + yMax = y + ascent; + if (yMin == yMax) { + // this is a sanity check for a case that shouldn't happen -- but + // if it does happen, we want to avoid dividing by zero later + yMin = y; + yMax = y + 1; + } + base = y; + break; + case 3: + xMin = x - ascent; + xMax = x - descent; + if (xMin == xMax) { + // this is a sanity check for a case that shouldn't happen -- but + // if it does happen, we want to avoid dividing by zero later + xMin = x; + xMax = x + 1; + } + base = x; + break; + } + text = NULL; + edge = NULL; + len = size = 0; + spaceAfter = gFalse; + next = NULL; + +#if TEXTOUT_WORD_LIST + GfxRGB rgb; + + if ((state->getRender() & 3) == 1) { + state->getStrokeRGB(&rgb); + } else { + state->getFillRGB(&rgb); + } + colorR = colToDbl(rgb.r); + colorG = colToDbl(rgb.g); + colorB = colToDbl(rgb.b); +#endif + + underlined = gFalse; + link = NULL; +} + +TextWord::~TextWord() { + gfree(text); + gfree(edge); +} + +void TextWord::addChar(GfxState *state, double x, double y, + double dx, double dy, Unicode u) { + if (len == size) { + size += 16; + text = (Unicode *)greallocn(text, size, sizeof(Unicode)); + edge = (double *)greallocn(edge, size + 1, sizeof(double)); + } + text[len] = u; + switch (rot) { + case 0: + if (len == 0) { + xMin = x; + } + edge[len] = x; + xMax = edge[len+1] = x + dx; + break; + case 1: + if (len == 0) { + yMin = y; + } + edge[len] = y; + yMax = edge[len+1] = y + dy; + break; + case 2: + if (len == 0) { + xMax = x; + } + edge[len] = x; + xMin = edge[len+1] = x + dx; + break; + case 3: + if (len == 0) { + yMax = y; + } + edge[len] = y; + yMin = edge[len+1] = y + dy; + break; + } + ++len; +} + +void TextWord::merge(TextWord *word) { + int i; + + if (word->xMin < xMin) { + xMin = word->xMin; + } + if (word->yMin < yMin) { + yMin = word->yMin; + } + if (word->xMax > xMax) { + xMax = word->xMax; + } + if (word->yMax > yMax) { + yMax = word->yMax; + } + if (len + word->len > size) { + size = len + word->len; + text = (Unicode *)greallocn(text, size, sizeof(Unicode)); + edge = (double *)greallocn(edge, size + 1, sizeof(double)); + } + for (i = 0; i < word->len; ++i) { + text[len + i] = word->text[i]; + edge[len + i] = word->edge[i]; + } + edge[len + word->len] = word->edge[word->len]; + len += word->len; + charLen += word->charLen; +} + +inline int TextWord::primaryCmp(TextWord *word) { + double cmp; + + cmp = 0; // make gcc happy + switch (rot) { + case 0: + cmp = xMin - word->xMin; + break; + case 1: + cmp = yMin - word->yMin; + break; + case 2: + cmp = word->xMax - xMax; + break; + case 3: + cmp = word->yMax - yMax; + break; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +double TextWord::primaryDelta(TextWord *word) { + double delta; + + delta = 0; // make gcc happy + switch (rot) { + case 0: + delta = word->xMin - xMax; + break; + case 1: + delta = word->yMin - yMax; + break; + case 2: + delta = xMin - word->xMax; + break; + case 3: + delta = yMin - word->yMax; + break; + } + return delta; +} + +int TextWord::cmpYX(const void *p1, const void *p2) { + TextWord *word1 = *(TextWord **)p1; + TextWord *word2 = *(TextWord **)p2; + double cmp; + + cmp = word1->yMin - word2->yMin; + if (cmp == 0) { + cmp = word1->xMin - word2->xMin; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +#if TEXTOUT_WORD_LIST + +GString *TextWord::getText() { + GString *s; + UnicodeMap *uMap; + char buf[8]; + int n, i; + + s = new GString(); + if (!(uMap = globalParams->getTextEncoding())) { + return s; + } + for (i = 0; i < len; ++i) { + n = uMap->mapUnicode(text[i], buf, sizeof(buf)); + s->append(buf, n); + } + uMap->decRefCnt(); + return s; +} + +void TextWord::getCharBBox(int charIdx, double *xMinA, double *yMinA, + double *xMaxA, double *yMaxA) { + if (charIdx < 0 || charIdx >= len) { + return; + } + switch (rot) { + case 0: + *xMinA = edge[charIdx]; + *xMaxA = edge[charIdx + 1]; + *yMinA = yMin; + *yMaxA = yMax; + break; + case 1: + *xMinA = xMin; + *xMaxA = xMax; + *yMinA = edge[charIdx]; + *yMaxA = edge[charIdx + 1]; + break; + case 2: + *xMinA = edge[charIdx + 1]; + *xMaxA = edge[charIdx]; + *yMinA = yMin; + *yMaxA = yMax; + break; + case 3: + *xMinA = xMin; + *xMaxA = xMax; + *yMinA = edge[charIdx + 1]; + *yMaxA = edge[charIdx]; + break; + } +} + +#endif // TEXTOUT_WORD_LIST + +//------------------------------------------------------------------------ +// TextPool +//------------------------------------------------------------------------ + +TextPool::TextPool() { + minBaseIdx = 0; + maxBaseIdx = -1; + pool = NULL; + cursor = NULL; + cursorBaseIdx = -1; +} + +TextPool::~TextPool() { + int baseIdx; + TextWord *word, *word2; + + for (baseIdx = minBaseIdx; baseIdx <= maxBaseIdx; ++baseIdx) { + for (word = pool[baseIdx - minBaseIdx]; word; word = word2) { + word2 = word->next; + delete word; + } + } + gfree(pool); +} + +int TextPool::getBaseIdx(double base) { + int baseIdx; + + baseIdx = (int)(base / textPoolStep); + if (baseIdx < minBaseIdx) { + return minBaseIdx; + } + if (baseIdx > maxBaseIdx) { + return maxBaseIdx; + } + return baseIdx; +} + +void TextPool::addWord(TextWord *word) { + TextWord **newPool; + int wordBaseIdx, newMinBaseIdx, newMaxBaseIdx, baseIdx; + TextWord *w0, *w1; + + // expand the array if needed + wordBaseIdx = (int)(word->base / textPoolStep); + if (minBaseIdx > maxBaseIdx) { + minBaseIdx = wordBaseIdx - 128; + maxBaseIdx = wordBaseIdx + 128; + pool = (TextWord **)gmallocn(maxBaseIdx - minBaseIdx + 1, + sizeof(TextWord *)); + for (baseIdx = minBaseIdx; baseIdx <= maxBaseIdx; ++baseIdx) { + pool[baseIdx - minBaseIdx] = NULL; + } + } else if (wordBaseIdx < minBaseIdx) { + newMinBaseIdx = wordBaseIdx - 128; + newPool = (TextWord **)gmallocn(maxBaseIdx - newMinBaseIdx + 1, + sizeof(TextWord *)); + for (baseIdx = newMinBaseIdx; baseIdx < minBaseIdx; ++baseIdx) { + newPool[baseIdx - newMinBaseIdx] = NULL; + } + memcpy(&newPool[minBaseIdx - newMinBaseIdx], pool, + (maxBaseIdx - minBaseIdx + 1) * sizeof(TextWord *)); + gfree(pool); + pool = newPool; + minBaseIdx = newMinBaseIdx; + } else if (wordBaseIdx > maxBaseIdx) { + newMaxBaseIdx = wordBaseIdx + 128; + pool = (TextWord **)greallocn(pool, newMaxBaseIdx - minBaseIdx + 1, + sizeof(TextWord *)); + for (baseIdx = maxBaseIdx + 1; baseIdx <= newMaxBaseIdx; ++baseIdx) { + pool[baseIdx - minBaseIdx] = NULL; + } + maxBaseIdx = newMaxBaseIdx; + } + + // insert the new word + if (cursor && wordBaseIdx == cursorBaseIdx && + word->primaryCmp(cursor) > 0) { + w0 = cursor; + w1 = cursor->next; + } else { + w0 = NULL; + w1 = pool[wordBaseIdx - minBaseIdx]; + } + for (; w1 && word->primaryCmp(w1) > 0; w0 = w1, w1 = w1->next) ; + word->next = w1; + if (w0) { + w0->next = word; + } else { + pool[wordBaseIdx - minBaseIdx] = word; + } + cursor = word; + cursorBaseIdx = wordBaseIdx; +} + +//------------------------------------------------------------------------ +// TextLine +//------------------------------------------------------------------------ + +TextLine::TextLine(TextBlock *blkA, int rotA, double baseA) { + blk = blkA; + rot = rotA; + xMin = yMin = 0; + xMax = yMax = -1; + base = baseA; + words = lastWord = NULL; + text = NULL; + edge = NULL; + col = NULL; + len = 0; + convertedLen = 0; + hyphenated = gFalse; + next = NULL; +} + +TextLine::~TextLine() { + TextWord *word; + + while (words) { + word = words; + words = words->next; + delete word; + } + gfree(text); + gfree(edge); + gfree(col); +} + +void TextLine::addWord(TextWord *word) { + if (lastWord) { + lastWord->next = word; + } else { + words = word; + } + lastWord = word; + + if (xMin > xMax) { + xMin = word->xMin; + xMax = word->xMax; + yMin = word->yMin; + yMax = word->yMax; + } else { + if (word->xMin < xMin) { + xMin = word->xMin; + } + if (word->xMax > xMax) { + xMax = word->xMax; + } + if (word->yMin < yMin) { + yMin = word->yMin; + } + if (word->yMax > yMax) { + yMax = word->yMax; + } + } +} + +double TextLine::primaryDelta(TextLine *line) { + double delta; + + delta = 0; // make gcc happy + switch (rot) { + case 0: + delta = line->xMin - xMax; + break; + case 1: + delta = line->yMin - yMax; + break; + case 2: + delta = xMin - line->xMax; + break; + case 3: + delta = yMin - line->yMax; + break; + } + return delta; +} + +int TextLine::primaryCmp(TextLine *line) { + double cmp; + + cmp = 0; // make gcc happy + switch (rot) { + case 0: + cmp = xMin - line->xMin; + break; + case 1: + cmp = yMin - line->yMin; + break; + case 2: + cmp = line->xMax - xMax; + break; + case 3: + cmp = line->yMax - yMax; + break; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +int TextLine::secondaryCmp(TextLine *line) { + double cmp; + + cmp = (rot == 0 || rot == 3) ? base - line->base : line->base - base; + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +int TextLine::cmpYX(TextLine *line) { + int cmp; + + if ((cmp = secondaryCmp(line))) { + return cmp; + } + return primaryCmp(line); +} + +int TextLine::cmpXY(const void *p1, const void *p2) { + TextLine *line1 = *(TextLine **)p1; + TextLine *line2 = *(TextLine **)p2; + int cmp; + + if ((cmp = line1->primaryCmp(line2))) { + return cmp; + } + return line1->secondaryCmp(line2); +} + +void TextLine::coalesce(UnicodeMap *uMap) { + TextWord *word0, *word1; + double space, delta, minSpace; + GBool isUnicode; + char buf[8]; + int i, j; + + if (words->next) { + + // compute the inter-word space threshold + if (words->len > 1 || words->next->len > 1) { + minSpace = 0; + } else { + minSpace = words->primaryDelta(words->next); + for (word0 = words->next, word1 = word0->next; + word1 && minSpace > 0; + word0 = word1, word1 = word0->next) { + if (word1->len > 1) { + minSpace = 0; + } + delta = word0->primaryDelta(word1); + if (delta < minSpace) { + minSpace = delta; + } + } + } + if (minSpace <= 0) { + space = maxCharSpacing * words->fontSize; + } else { + space = maxWideCharSpacingMul * minSpace; + if (space > maxWideCharSpacing * words->fontSize) { + space = maxWideCharSpacing * words->fontSize; + } + } + + // merge words + word0 = words; + word1 = words->next; + while (word1) { + if (word0->primaryDelta(word1) >= space) { + word0->spaceAfter = gTrue; + word0 = word1; + word1 = word1->next; + } else if (word0->font == word1->font && + word0->underlined == word1->underlined && + fabs(word0->fontSize - word1->fontSize) < + maxWordFontSizeDelta * words->fontSize && + word1->charPos == word0->charPos + word0->charLen) { + word0->merge(word1); + word0->next = word1->next; + delete word1; + word1 = word0->next; + } else { + word0 = word1; + word1 = word1->next; + } + } + } + + // build the line text + isUnicode = uMap ? uMap->isUnicode() : gFalse; + len = 0; + for (word1 = words; word1; word1 = word1->next) { + len += word1->len; + if (word1->spaceAfter) { + ++len; + } + } + text = (Unicode *)gmallocn(len, sizeof(Unicode)); + edge = (double *)gmallocn(len + 1, sizeof(double)); + i = 0; + for (word1 = words; word1; word1 = word1->next) { + for (j = 0; j < word1->len; ++j) { + text[i] = word1->text[j]; + edge[i] = word1->edge[j]; + ++i; + } + edge[i] = word1->edge[word1->len]; + if (word1->spaceAfter) { + text[i] = (Unicode)0x0020; + ++i; + } + } + + // compute convertedLen and set up the col array + col = (int *)gmallocn(len + 1, sizeof(int)); + convertedLen = 0; + for (i = 0; i < len; ++i) { + col[i] = convertedLen; + if (isUnicode) { + ++convertedLen; + } else if (uMap) { + convertedLen += uMap->mapUnicode(text[i], buf, sizeof(buf)); + } + } + col[len] = convertedLen; + + // check for hyphen at end of line + //~ need to check for other chars used as hyphens + hyphenated = text[len - 1] == (Unicode)'-'; +} + +//------------------------------------------------------------------------ +// TextLineFrag +//------------------------------------------------------------------------ + +class TextLineFrag { +public: + + TextLine *line; // the line object + int start, len; // offset and length of this fragment + // (in Unicode chars) + double xMin, xMax; // bounding box coordinates + double yMin, yMax; + double base; // baseline virtual coordinate + int col; // first column + + void init(TextLine *lineA, int startA, int lenA); + void computeCoords(GBool oneRot); + + static int cmpYXPrimaryRot(const void *p1, const void *p2); + static int cmpYXLineRot(const void *p1, const void *p2); + static int cmpXYLineRot(const void *p1, const void *p2); + static int cmpXYColumnPrimaryRot(const void *p1, const void *p2); + static int cmpXYColumnLineRot(const void *p1, const void *p2); +}; + +void TextLineFrag::init(TextLine *lineA, int startA, int lenA) { + line = lineA; + start = startA; + len = lenA; + col = line->col[start]; +} + +void TextLineFrag::computeCoords(GBool oneRot) { + TextBlock *blk; + double d0, d1, d2, d3, d4; + + if (oneRot) { + + switch (line->rot) { + case 0: + xMin = line->edge[start]; + xMax = line->edge[start + len]; + yMin = line->yMin; + yMax = line->yMax; + break; + case 1: + xMin = line->xMin; + xMax = line->xMax; + yMin = line->edge[start]; + yMax = line->edge[start + len]; + break; + case 2: + xMin = line->edge[start + len]; + xMax = line->edge[start]; + yMin = line->yMin; + yMax = line->yMax; + break; + case 3: + xMin = line->xMin; + xMax = line->xMax; + yMin = line->edge[start + len]; + yMax = line->edge[start]; + break; + } + base = line->base; + + } else { + + if (line->rot == 0 && line->blk->page->primaryRot == 0) { + + xMin = line->edge[start]; + xMax = line->edge[start + len]; + yMin = line->yMin; + yMax = line->yMax; + base = line->base; + + } else { + + blk = line->blk; + d0 = line->edge[start]; + d1 = line->edge[start + len]; + d2 = d3 = d4 = 0; // make gcc happy + + switch (line->rot) { + case 0: + d2 = line->yMin; + d3 = line->yMax; + d4 = line->base; + d0 = (d0 - blk->xMin) / (blk->xMax - blk->xMin); + d1 = (d1 - blk->xMin) / (blk->xMax - blk->xMin); + d2 = (d2 - blk->yMin) / (blk->yMax - blk->yMin); + d3 = (d3 - blk->yMin) / (blk->yMax - blk->yMin); + d4 = (d4 - blk->yMin) / (blk->yMax - blk->yMin); + break; + case 1: + d2 = line->xMax; + d3 = line->xMin; + d4 = line->base; + d0 = (d0 - blk->yMin) / (blk->yMax - blk->yMin); + d1 = (d1 - blk->yMin) / (blk->yMax - blk->yMin); + d2 = (blk->xMax - d2) / (blk->xMax - blk->xMin); + d3 = (blk->xMax - d3) / (blk->xMax - blk->xMin); + d4 = (blk->xMax - d4) / (blk->xMax - blk->xMin); + break; + case 2: + d2 = line->yMax; + d3 = line->yMin; + d4 = line->base; + d0 = (blk->xMax - d0) / (blk->xMax - blk->xMin); + d1 = (blk->xMax - d1) / (blk->xMax - blk->xMin); + d2 = (blk->yMax - d2) / (blk->yMax - blk->yMin); + d3 = (blk->yMax - d3) / (blk->yMax - blk->yMin); + d4 = (blk->yMax - d4) / (blk->yMax - blk->yMin); + break; + case 3: + d2 = line->xMin; + d3 = line->xMax; + d4 = line->base; + d0 = (blk->yMax - d0) / (blk->yMax - blk->yMin); + d1 = (blk->yMax - d1) / (blk->yMax - blk->yMin); + d2 = (d2 - blk->xMin) / (blk->xMax - blk->xMin); + d3 = (d3 - blk->xMin) / (blk->xMax - blk->xMin); + d4 = (d4 - blk->xMin) / (blk->xMax - blk->xMin); + break; + } + + switch (line->blk->page->primaryRot) { + case 0: + xMin = blk->xMin + d0 * (blk->xMax - blk->xMin); + xMax = blk->xMin + d1 * (blk->xMax - blk->xMin); + yMin = blk->yMin + d2 * (blk->yMax - blk->yMin); + yMax = blk->yMin + d3 * (blk->yMax - blk->yMin); + base = blk->yMin + base * (blk->yMax - blk->yMin); + break; + case 1: + xMin = blk->xMax - d3 * (blk->xMax - blk->xMin); + xMax = blk->xMax - d2 * (blk->xMax - blk->xMin); + yMin = blk->yMin + d0 * (blk->yMax - blk->yMin); + yMax = blk->yMin + d1 * (blk->yMax - blk->yMin); + base = blk->xMax - d4 * (blk->xMax - blk->xMin); + break; + case 2: + xMin = blk->xMax - d1 * (blk->xMax - blk->xMin); + xMax = blk->xMax - d0 * (blk->xMax - blk->xMin); + yMin = blk->yMax - d3 * (blk->yMax - blk->yMin); + yMax = blk->yMax - d2 * (blk->yMax - blk->yMin); + base = blk->yMax - d4 * (blk->yMax - blk->yMin); + break; + case 3: + xMin = blk->xMin + d2 * (blk->xMax - blk->xMin); + xMax = blk->xMin + d3 * (blk->xMax - blk->xMin); + yMin = blk->yMax - d1 * (blk->yMax - blk->yMin); + yMax = blk->yMax - d0 * (blk->yMax - blk->yMin); + base = blk->xMin + d4 * (blk->xMax - blk->xMin); + break; + } + + } + } +} + +int TextLineFrag::cmpYXPrimaryRot(const void *p1, const void *p2) { + TextLineFrag *frag1 = (TextLineFrag *)p1; + TextLineFrag *frag2 = (TextLineFrag *)p2; + double cmp; + + cmp = 0; // make gcc happy + switch (frag1->line->blk->page->primaryRot) { + case 0: + if (fabs(cmp = frag1->yMin - frag2->yMin) < 0.01) { + cmp = frag1->xMin - frag2->xMin; + } + break; + case 1: + if (fabs(cmp = frag2->xMax - frag1->xMax) < 0.01) { + cmp = frag1->yMin - frag2->yMin; + } + break; + case 2: + if (fabs(cmp = frag2->yMin - frag1->yMin) < 0.01) { + cmp = frag2->xMax - frag1->xMax; + } + break; + case 3: + if (fabs(cmp = frag1->xMax - frag2->xMax) < 0.01) { + cmp = frag2->yMax - frag1->yMax; + } + break; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +int TextLineFrag::cmpYXLineRot(const void *p1, const void *p2) { + TextLineFrag *frag1 = (TextLineFrag *)p1; + TextLineFrag *frag2 = (TextLineFrag *)p2; + double cmp; + + cmp = 0; // make gcc happy + switch (frag1->line->rot) { + case 0: + if ((cmp = frag1->yMin - frag2->yMin) == 0) { + cmp = frag1->xMin - frag2->xMin; + } + break; + case 1: + if ((cmp = frag2->xMax - frag1->xMax) == 0) { + cmp = frag1->yMin - frag2->yMin; + } + break; + case 2: + if ((cmp = frag2->yMin - frag1->yMin) == 0) { + cmp = frag2->xMax - frag1->xMax; + } + break; + case 3: + if ((cmp = frag1->xMax - frag2->xMax) == 0) { + cmp = frag2->yMax - frag1->yMax; + } + break; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +int TextLineFrag::cmpXYLineRot(const void *p1, const void *p2) { + TextLineFrag *frag1 = (TextLineFrag *)p1; + TextLineFrag *frag2 = (TextLineFrag *)p2; + double cmp; + + cmp = 0; // make gcc happy + switch (frag1->line->rot) { + case 0: + if ((cmp = frag1->xMin - frag2->xMin) == 0) { + cmp = frag1->yMin - frag2->yMin; + } + break; + case 1: + if ((cmp = frag1->yMin - frag2->yMin) == 0) { + cmp = frag2->xMax - frag1->xMax; + } + break; + case 2: + if ((cmp = frag2->xMax - frag1->xMax) == 0) { + cmp = frag2->yMin - frag1->yMin; + } + break; + case 3: + if ((cmp = frag2->yMax - frag1->yMax) == 0) { + cmp = frag1->xMax - frag2->xMax; + } + break; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +int TextLineFrag::cmpXYColumnPrimaryRot(const void *p1, const void *p2) { + TextLineFrag *frag1 = (TextLineFrag *)p1; + TextLineFrag *frag2 = (TextLineFrag *)p2; + double cmp; + + // if columns overlap, compare y values + if (frag1->col < frag2->col + (frag2->line->col[frag2->start + frag2->len] - + frag2->line->col[frag2->start]) && + frag2->col < frag1->col + (frag1->line->col[frag1->start + frag1->len] - + frag1->line->col[frag1->start])) { + cmp = 0; // make gcc happy + switch (frag1->line->blk->page->primaryRot) { + case 0: cmp = frag1->yMin - frag2->yMin; break; + case 1: cmp = frag2->xMax - frag1->xMax; break; + case 2: cmp = frag2->yMin - frag1->yMin; break; + case 3: cmp = frag1->xMax - frag2->xMax; break; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; + } + + // otherwise, compare starting column + return frag1->col - frag2->col; +} + +int TextLineFrag::cmpXYColumnLineRot(const void *p1, const void *p2) { + TextLineFrag *frag1 = (TextLineFrag *)p1; + TextLineFrag *frag2 = (TextLineFrag *)p2; + double cmp; + + // if columns overlap, compare y values + if (frag1->col < frag2->col + (frag2->line->col[frag2->start + frag2->len] - + frag2->line->col[frag2->start]) && + frag2->col < frag1->col + (frag1->line->col[frag1->start + frag1->len] - + frag1->line->col[frag1->start])) { + cmp = 0; // make gcc happy + switch (frag1->line->rot) { + case 0: cmp = frag1->yMin - frag2->yMin; break; + case 1: cmp = frag2->xMax - frag1->xMax; break; + case 2: cmp = frag2->yMin - frag1->yMin; break; + case 3: cmp = frag1->xMax - frag2->xMax; break; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; + } + + // otherwise, compare starting column + return frag1->col - frag2->col; +} + +//------------------------------------------------------------------------ +// TextBlock +//------------------------------------------------------------------------ + +TextBlock::TextBlock(TextPage *pageA, int rotA) { + page = pageA; + rot = rotA; + xMin = yMin = 0; + xMax = yMax = -1; + priMin = 0; + priMax = page->pageWidth; + pool = new TextPool(); + lines = NULL; + curLine = NULL; + next = NULL; + stackNext = NULL; +} + +TextBlock::~TextBlock() { + TextLine *line; + + delete pool; + while (lines) { + line = lines; + lines = lines->next; + delete line; + } +} + +void TextBlock::addWord(TextWord *word) { + pool->addWord(word); + if (xMin > xMax) { + xMin = word->xMin; + xMax = word->xMax; + yMin = word->yMin; + yMax = word->yMax; + } else { + if (word->xMin < xMin) { + xMin = word->xMin; + } + if (word->xMax > xMax) { + xMax = word->xMax; + } + if (word->yMin < yMin) { + yMin = word->yMin; + } + if (word->yMax > yMax) { + yMax = word->yMax; + } + } +} + +void TextBlock::coalesce(UnicodeMap *uMap) { + TextWord *word0, *word1, *word2, *bestWord0, *bestWord1, *lastWord; + TextLine *line, *line0, *line1; + int poolMinBaseIdx, startBaseIdx, minBaseIdx, maxBaseIdx; + int baseIdx, bestWordBaseIdx, idx0, idx1; + double minBase, maxBase; + double fontSize, delta, priDelta, secDelta; + TextLine **lineArray; + GBool found; + int col1, col2; + int i, j, k; + + // discard duplicated text (fake boldface, drop shadows) + for (idx0 = pool->minBaseIdx; idx0 <= pool->maxBaseIdx; ++idx0) { + word0 = pool->getPool(idx0); + while (word0) { + priDelta = dupMaxPriDelta * word0->fontSize; + secDelta = dupMaxSecDelta * word0->fontSize; + if (rot == 0 || rot == 3) { + maxBaseIdx = pool->getBaseIdx(word0->base + secDelta); + } else { + maxBaseIdx = pool->getBaseIdx(word0->base - secDelta); + } + found = gFalse; + word1 = word2 = NULL; // make gcc happy + for (idx1 = idx0; idx1 <= maxBaseIdx; ++idx1) { + if (idx1 == idx0) { + word1 = word0; + word2 = word0->next; + } else { + word1 = NULL; + word2 = pool->getPool(idx1); + } + for (; word2; word1 = word2, word2 = word2->next) { + if (word2->len == word0->len && + !memcmp(word2->text, word0->text, + word0->len * sizeof(Unicode))) { + switch (rot) { + case 0: + case 2: + found = fabs(word0->xMin - word2->xMin) < priDelta && + fabs(word0->xMax - word2->xMax) < priDelta && + fabs(word0->yMin - word2->yMin) < secDelta && + fabs(word0->yMax - word2->yMax) < secDelta; + break; + case 1: + case 3: + found = fabs(word0->xMin - word2->xMin) < secDelta && + fabs(word0->xMax - word2->xMax) < secDelta && + fabs(word0->yMin - word2->yMin) < priDelta && + fabs(word0->yMax - word2->yMax) < priDelta; + break; + } + } + if (found) { + break; + } + } + if (found) { + break; + } + } + if (found) { + if (word1) { + word1->next = word2->next; + } else { + pool->setPool(idx1, word2->next); + } + delete word2; + } else { + word0 = word0->next; + } + } + } + + // build the lines + curLine = NULL; + poolMinBaseIdx = pool->minBaseIdx; + charCount = 0; + nLines = 0; + while (1) { + + // find the first non-empty line in the pool + for (; + poolMinBaseIdx <= pool->maxBaseIdx && !pool->getPool(poolMinBaseIdx); + ++poolMinBaseIdx) ; + if (poolMinBaseIdx > pool->maxBaseIdx) { + break; + } + + // look for the left-most word in the first four lines of the + // pool -- this avoids starting with a superscript word + startBaseIdx = poolMinBaseIdx; + for (baseIdx = poolMinBaseIdx + 1; + baseIdx < poolMinBaseIdx + 4 && baseIdx <= pool->maxBaseIdx; + ++baseIdx) { + if (!pool->getPool(baseIdx)) { + continue; + } + if (pool->getPool(baseIdx)->primaryCmp(pool->getPool(startBaseIdx)) + < 0) { + startBaseIdx = baseIdx; + } + } + + // create a new line + word0 = pool->getPool(startBaseIdx); + pool->setPool(startBaseIdx, word0->next); + word0->next = NULL; + line = new TextLine(this, word0->rot, word0->base); + line->addWord(word0); + lastWord = word0; + + // compute the search range + fontSize = word0->fontSize; + minBase = word0->base - maxIntraLineDelta * fontSize; + maxBase = word0->base + maxIntraLineDelta * fontSize; + minBaseIdx = pool->getBaseIdx(minBase); + maxBaseIdx = pool->getBaseIdx(maxBase); + + // find the rest of the words in this line + while (1) { + + // find the left-most word whose baseline is in the range for + // this line + bestWordBaseIdx = 0; + bestWord0 = bestWord1 = NULL; + for (baseIdx = minBaseIdx; baseIdx <= maxBaseIdx; ++baseIdx) { + for (word0 = NULL, word1 = pool->getPool(baseIdx); + word1; + word0 = word1, word1 = word1->next) { + if (word1->base >= minBase && + word1->base <= maxBase && + (delta = lastWord->primaryDelta(word1)) >= + minCharSpacing * fontSize) { + if (delta < maxWordSpacing * fontSize && + (!bestWord1 || word1->primaryCmp(bestWord1) < 0)) { + bestWordBaseIdx = baseIdx; + bestWord0 = word0; + bestWord1 = word1; + } + break; + } + } + } + if (!bestWord1) { + break; + } + + // remove it from the pool, and add it to the line + if (bestWord0) { + bestWord0->next = bestWord1->next; + } else { + pool->setPool(bestWordBaseIdx, bestWord1->next); + } + bestWord1->next = NULL; + line->addWord(bestWord1); + lastWord = bestWord1; + } + + // add the line + if (curLine && line->cmpYX(curLine) > 0) { + line0 = curLine; + line1 = curLine->next; + } else { + line0 = NULL; + line1 = lines; + } + for (; + line1 && line->cmpYX(line1) > 0; + line0 = line1, line1 = line1->next) ; + if (line0) { + line0->next = line; + } else { + lines = line; + } + line->next = line1; + curLine = line; + line->coalesce(uMap); + charCount += line->len; + ++nLines; + } + + // sort lines into xy order for column assignment + lineArray = (TextLine **)gmallocn(nLines, sizeof(TextLine *)); + for (line = lines, i = 0; line; line = line->next, ++i) { + lineArray[i] = line; + } + qsort(lineArray, nLines, sizeof(TextLine *), &TextLine::cmpXY); + + // column assignment + nColumns = 0; + for (i = 0; i < nLines; ++i) { + line0 = lineArray[i]; + col1 = 0; + for (j = 0; j < i; ++j) { + line1 = lineArray[j]; + if (line1->primaryDelta(line0) >= 0) { + col2 = line1->col[line1->len] + 1; + } else { + k = 0; // make gcc happy + switch (rot) { + case 0: + for (k = 0; + k < line1->len && + line0->xMin >= 0.5 * (line1->edge[k] + line1->edge[k+1]); + ++k) ; + break; + case 1: + for (k = 0; + k < line1->len && + line0->yMin >= 0.5 * (line1->edge[k] + line1->edge[k+1]); + ++k) ; + break; + case 2: + for (k = 0; + k < line1->len && + line0->xMax <= 0.5 * (line1->edge[k] + line1->edge[k+1]); + ++k) ; + break; + case 3: + for (k = 0; + k < line1->len && + line0->yMax <= 0.5 * (line1->edge[k] + line1->edge[k+1]); + ++k) ; + break; + } + col2 = line1->col[k]; + } + if (col2 > col1) { + col1 = col2; + } + } + for (k = 0; k <= line0->len; ++k) { + line0->col[k] += col1; + } + if (line0->col[line0->len] > nColumns) { + nColumns = line0->col[line0->len]; + } + } + gfree(lineArray); +} + +void TextBlock::updatePriMinMax(TextBlock *blk) { + double newPriMin, newPriMax; + GBool gotPriMin, gotPriMax; + + gotPriMin = gotPriMax = gFalse; + newPriMin = newPriMax = 0; // make gcc happy + switch (page->primaryRot) { + case 0: + case 2: + if (blk->yMin < yMax && blk->yMax > yMin) { + if (blk->xMin < xMin) { + newPriMin = blk->xMax; + gotPriMin = gTrue; + } + if (blk->xMax > xMax) { + newPriMax = blk->xMin; + gotPriMax = gTrue; + } + } + break; + case 1: + case 3: + if (blk->xMin < xMax && blk->xMax > xMin) { + if (blk->yMin < yMin) { + newPriMin = blk->yMax; + gotPriMin = gTrue; + } + if (blk->yMax > yMax) { + newPriMax = blk->yMin; + gotPriMax = gTrue; + } + } + break; + } + if (gotPriMin) { + if (newPriMin > xMin) { + newPriMin = xMin; + } + if (newPriMin > priMin) { + priMin = newPriMin; + } + } + if (gotPriMax) { + if (newPriMax < xMax) { + newPriMax = xMax; + } + if (newPriMax < priMax) { + priMax = newPriMax; + } + } +} + +int TextBlock::cmpXYPrimaryRot(const void *p1, const void *p2) { + TextBlock *blk1 = *(TextBlock **)p1; + TextBlock *blk2 = *(TextBlock **)p2; + double cmp; + + cmp = 0; // make gcc happy + switch (blk1->page->primaryRot) { + case 0: + if ((cmp = blk1->xMin - blk2->xMin) == 0) { + cmp = blk1->yMin - blk2->yMin; + } + break; + case 1: + if ((cmp = blk1->yMin - blk2->yMin) == 0) { + cmp = blk2->xMax - blk1->xMax; + } + break; + case 2: + if ((cmp = blk2->xMax - blk1->xMax) == 0) { + cmp = blk2->yMin - blk1->yMin; + } + break; + case 3: + if ((cmp = blk2->yMax - blk1->yMax) == 0) { + cmp = blk1->xMax - blk2->xMax; + } + break; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +int TextBlock::cmpYXPrimaryRot(const void *p1, const void *p2) { + TextBlock *blk1 = *(TextBlock **)p1; + TextBlock *blk2 = *(TextBlock **)p2; + double cmp; + + cmp = 0; // make gcc happy + switch (blk1->page->primaryRot) { + case 0: + if ((cmp = blk1->yMin - blk2->yMin) == 0) { + cmp = blk1->xMin - blk2->xMin; + } + break; + case 1: + if ((cmp = blk2->xMax - blk1->xMax) == 0) { + cmp = blk1->yMin - blk2->yMin; + } + break; + case 2: + if ((cmp = blk2->yMin - blk1->yMin) == 0) { + cmp = blk2->xMax - blk1->xMax; + } + break; + case 3: + if ((cmp = blk1->xMax - blk2->xMax) == 0) { + cmp = blk2->yMax - blk1->yMax; + } + break; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +int TextBlock::primaryCmp(TextBlock *blk) { + double cmp; + + cmp = 0; // make gcc happy + switch (rot) { + case 0: + cmp = xMin - blk->xMin; + break; + case 1: + cmp = yMin - blk->yMin; + break; + case 2: + cmp = blk->xMax - xMax; + break; + case 3: + cmp = blk->yMax - yMax; + break; + } + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + +double TextBlock::secondaryDelta(TextBlock *blk) { + double delta; + + delta = 0; // make gcc happy + switch (rot) { + case 0: + delta = blk->yMin - yMax; + break; + case 1: + delta = xMin - blk->xMax; + break; + case 2: + delta = yMin - blk->yMax; + break; + case 3: + delta = blk->xMin - xMax; + break; + } + return delta; +} + +GBool TextBlock::isBelow(TextBlock *blk) { + GBool below; + + below = gFalse; // make gcc happy + switch (page->primaryRot) { + case 0: + below = xMin >= blk->priMin && xMax <= blk->priMax && + yMin > blk->yMin; + break; + case 1: + below = yMin >= blk->priMin && yMax <= blk->priMax && + xMax < blk->xMax; + break; + case 2: + below = xMin >= blk->priMin && xMax <= blk->priMax && + yMax < blk->yMax; + break; + case 3: + below = yMin >= blk->priMin && yMax <= blk->priMax && + xMin > blk->xMin; + break; + } + + return below; +} + +//------------------------------------------------------------------------ +// TextFlow +//------------------------------------------------------------------------ + +TextFlow::TextFlow(TextPage *pageA, TextBlock *blk) { + page = pageA; + xMin = blk->xMin; + xMax = blk->xMax; + yMin = blk->yMin; + yMax = blk->yMax; + priMin = blk->priMin; + priMax = blk->priMax; + blocks = lastBlk = blk; + next = NULL; +} + +TextFlow::~TextFlow() { + TextBlock *blk; + + while (blocks) { + blk = blocks; + blocks = blocks->next; + delete blk; + } +} + +void TextFlow::addBlock(TextBlock *blk) { + if (lastBlk) { + lastBlk->next = blk; + } else { + blocks = blk; + } + lastBlk = blk; + if (blk->xMin < xMin) { + xMin = blk->xMin; + } + if (blk->xMax > xMax) { + xMax = blk->xMax; + } + if (blk->yMin < yMin) { + yMin = blk->yMin; + } + if (blk->yMax > yMax) { + yMax = blk->yMax; + } +} + +GBool TextFlow::blockFits(TextBlock *blk, TextBlock *prevBlk) { + GBool fits; + + // lower blocks must use smaller fonts + if (blk->lines->words->fontSize > lastBlk->lines->words->fontSize) { + return gFalse; + } + + fits = gFalse; // make gcc happy + switch (page->primaryRot) { + case 0: + fits = blk->xMin >= priMin && blk->xMax <= priMax; + break; + case 1: + fits = blk->yMin >= priMin && blk->yMax <= priMax; + break; + case 2: + fits = blk->xMin >= priMin && blk->xMax <= priMax; + break; + case 3: + fits = blk->yMin >= priMin && blk->yMax <= priMax; + break; + } + return fits; +} + +#if TEXTOUT_WORD_LIST + +//------------------------------------------------------------------------ +// TextWordList +//------------------------------------------------------------------------ + +TextWordList::TextWordList(TextPage *text, GBool physLayout) { + TextFlow *flow; + TextBlock *blk; + TextLine *line; + TextWord *word; + TextWord **wordArray; + int nWords, i; + + words = new GList(); + + if (text->rawOrder) { + for (word = text->rawWords; word; word = word->next) { + words->append(word); + } + + } else if (physLayout) { + // this is inefficient, but it's also the least useful of these + // three cases + nWords = 0; + for (flow = text->flows; flow; flow = flow->next) { + for (blk = flow->blocks; blk; blk = blk->next) { + for (line = blk->lines; line; line = line->next) { + for (word = line->words; word; word = word->next) { + ++nWords; + } + } + } + } + wordArray = (TextWord **)gmallocn(nWords, sizeof(TextWord *)); + i = 0; + for (flow = text->flows; flow; flow = flow->next) { + for (blk = flow->blocks; blk; blk = blk->next) { + for (line = blk->lines; line; line = line->next) { + for (word = line->words; word; word = word->next) { + wordArray[i++] = word; + } + } + } + } + qsort(wordArray, nWords, sizeof(TextWord *), &TextWord::cmpYX); + for (i = 0; i < nWords; ++i) { + words->append(wordArray[i]); + } + gfree(wordArray); + + } else { + for (flow = text->flows; flow; flow = flow->next) { + for (blk = flow->blocks; blk; blk = blk->next) { + for (line = blk->lines; line; line = line->next) { + for (word = line->words; word; word = word->next) { + words->append(word); + } + } + } + } + } +} + +TextWordList::~TextWordList() { + delete words; +} + +int TextWordList::getLength() { + return words->getLength(); +} + +TextWord *TextWordList::get(int idx) { + if (idx < 0 || idx >= words->getLength()) { + return NULL; + } + return (TextWord *)words->get(idx); +} + +#endif // TEXTOUT_WORD_LIST + +//------------------------------------------------------------------------ +// TextPage +//------------------------------------------------------------------------ + +TextPage::TextPage(GBool rawOrderA) { + int rot; + + rawOrder = rawOrderA; + curWord = NULL; + charPos = 0; + curFont = NULL; + curFontSize = 0; + nest = 0; + nTinyChars = 0; + lastCharOverlap = gFalse; + if (!rawOrder) { + for (rot = 0; rot < 4; ++rot) { + pools[rot] = new TextPool(); + } + } + flows = NULL; + blocks = NULL; + rawWords = NULL; + rawLastWord = NULL; + fonts = new GList(); + lastFindXMin = lastFindYMin = 0; + haveLastFind = gFalse; + underlines = new GList(); + links = new GList(); +} + +TextPage::~TextPage() { + int rot; + + clear(); + if (!rawOrder) { + for (rot = 0; rot < 4; ++rot) { + delete pools[rot]; + } + } + delete fonts; + deleteGList(underlines, TextUnderline); + deleteGList(links, TextLink); +} + +void TextPage::startPage(GfxState *state) { + clear(); + if (state) { + pageWidth = state->getPageWidth(); + pageHeight = state->getPageHeight(); + } else { + pageWidth = pageHeight = 0; + } +} + +void TextPage::endPage() { + if (curWord) { + endWord(); + } +} + +void TextPage::clear() { + int rot; + TextFlow *flow; + TextWord *word; + + if (curWord) { + delete curWord; + curWord = NULL; + } + if (rawOrder) { + while (rawWords) { + word = rawWords; + rawWords = rawWords->next; + delete word; + } + } else { + for (rot = 0; rot < 4; ++rot) { + delete pools[rot]; + } + while (flows) { + flow = flows; + flows = flows->next; + delete flow; + } + gfree(blocks); + } + deleteGList(fonts, TextFontInfo); + + curWord = NULL; + charPos = 0; + curFont = NULL; + curFontSize = 0; + nest = 0; + nTinyChars = 0; + if (!rawOrder) { + for (rot = 0; rot < 4; ++rot) { + pools[rot] = new TextPool(); + } + } + flows = NULL; + blocks = NULL; + rawWords = NULL; + rawLastWord = NULL; + fonts = new GList(); +} + +void TextPage::updateFont(GfxState *state) { + GfxFont *gfxFont; + double *fm; + char *name; + int code, mCode, letterCode, anyCode; + double w; + int i; + + // get the font info object + curFont = NULL; + for (i = 0; i < fonts->getLength(); ++i) { + curFont = (TextFontInfo *)fonts->get(i); + if (curFont->matches(state)) { + break; + } + curFont = NULL; + } + if (!curFont) { + curFont = new TextFontInfo(state); + fonts->append(curFont); + } + + // adjust the font size + gfxFont = state->getFont(); + curFontSize = state->getTransformedFontSize(); + if (gfxFont && gfxFont->getType() == fontType3) { + // This is a hack which makes it possible to deal with some Type 3 + // fonts. The problem is that it's impossible to know what the + // base coordinate system used in the font is without actually + // rendering the font. This code tries to guess by looking at the + // width of the character 'm' (which breaks if the font is a + // subset that doesn't contain 'm'). + mCode = letterCode = anyCode = -1; + for (code = 0; code < 256; ++code) { + name = ((Gfx8BitFont *)gfxFont)->getCharName(code); + if (name && name[0] == 'm' && name[1] == '\0') { + mCode = code; + } + if (letterCode < 0 && name && name[1] == '\0' && + ((name[0] >= 'A' && name[0] <= 'Z') || + (name[0] >= 'a' && name[0] <= 'z'))) { + letterCode = code; + } + if (anyCode < 0 && name && + ((Gfx8BitFont *)gfxFont)->getWidth(code) > 0) { + anyCode = code; + } + } + if (mCode >= 0 && + (w = ((Gfx8BitFont *)gfxFont)->getWidth(mCode)) > 0) { + // 0.6 is a generic average 'm' width -- yes, this is a hack + curFontSize *= w / 0.6; + } else if (letterCode >= 0 && + (w = ((Gfx8BitFont *)gfxFont)->getWidth(letterCode)) > 0) { + // even more of a hack: 0.5 is a generic letter width + curFontSize *= w / 0.5; + } else if (anyCode >= 0 && + (w = ((Gfx8BitFont *)gfxFont)->getWidth(anyCode)) > 0) { + // better than nothing: 0.5 is a generic character width + curFontSize *= w / 0.5; + } + fm = gfxFont->getFontMatrix(); + if (fm[0] != 0) { + curFontSize *= fabs(fm[3] / fm[0]); + } + } +} + +void TextPage::beginWord(GfxState *state, double x0, double y0) { + double *fontm; + double m[4], m2[4]; + int rot; + + // This check is needed because Type 3 characters can contain + // text-drawing operations (when TextPage is being used via + // {X,Win}SplashOutputDev rather than TextOutputDev). + if (curWord) { + ++nest; + return; + } + + // compute the rotation + state->getFontTransMat(&m[0], &m[1], &m[2], &m[3]); + if (state->getFont()->getType() == fontType3) { + fontm = state->getFont()->getFontMatrix(); + m2[0] = fontm[0] * m[0] + fontm[1] * m[2]; + m2[1] = fontm[0] * m[1] + fontm[1] * m[3]; + m2[2] = fontm[2] * m[0] + fontm[3] * m[2]; + m2[3] = fontm[2] * m[1] + fontm[3] * m[3]; + m[0] = m2[0]; + m[1] = m2[1]; + m[2] = m2[2]; + m[3] = m2[3]; + } + if (fabs(m[0] * m[3]) > fabs(m[1] * m[2])) { + rot = (m[3] < 0) ? 0 : 2; + } else { + rot = (m[2] > 0) ? 1 : 3; + } + + curWord = new TextWord(state, rot, x0, y0, charPos, curFont, curFontSize); +} + +void TextPage::addChar(GfxState *state, double x, double y, + double dx, double dy, + CharCode c, int nBytes, Unicode *u, int uLen) { + double x1, y1, w1, h1, dx2, dy2, base, sp, delta; + GBool overlap; + int i; + + // subtract char and word spacing from the dx,dy values + sp = state->getCharSpace(); + if (c == (CharCode)0x20) { + sp += state->getWordSpace(); + } + state->textTransformDelta(sp * state->getHorizScaling(), 0, &dx2, &dy2); + dx -= dx2; + dy -= dy2; + state->transformDelta(dx, dy, &w1, &h1); + + // throw away chars that aren't inside the page bounds + // (and also do a sanity check on the character size) + state->transform(x, y, &x1, &y1); + if (x1 + w1 < 0 || x1 > pageWidth || + y1 + h1 < 0 || y1 > pageHeight || + w1 > pageWidth || h1 > pageHeight) { + charPos += nBytes; + return; + } + + // check the tiny chars limit + if (!globalParams->getTextKeepTinyChars() && + fabs(w1) < 3 && fabs(h1) < 3) { + if (++nTinyChars > 50000) { + charPos += nBytes; + return; + } + } + + // break words at space character + if (uLen == 1 && u[0] == (Unicode)0x20) { + if (curWord) { + ++curWord->charLen; + } + charPos += nBytes; + endWord(); + return; + } + + // start a new word if: + // (1) this character doesn't fall in the right place relative to + // the end of the previous word (this places upper and lower + // constraints on the position deltas along both the primary + // and secondary axes), or + // (2) this character overlaps the previous one (duplicated text), or + // (3) the previous character was an overlap (we want each duplicated + // character to be in a word by itself at this stage), + // (4) the font size has changed + if (curWord && curWord->len > 0) { + base = sp = delta = 0; // make gcc happy + switch (curWord->rot) { + case 0: + base = y1; + sp = x1 - curWord->xMax; + delta = x1 - curWord->edge[curWord->len - 1]; + break; + case 1: + base = x1; + sp = y1 - curWord->yMax; + delta = y1 - curWord->edge[curWord->len - 1]; + break; + case 2: + base = y1; + sp = curWord->xMin - x1; + delta = curWord->edge[curWord->len - 1] - x1; + break; + case 3: + base = x1; + sp = curWord->yMin - y1; + delta = curWord->edge[curWord->len - 1] - y1; + break; + } + overlap = fabs(delta) < dupMaxPriDelta * curWord->fontSize && + fabs(base - curWord->base) < dupMaxSecDelta * curWord->fontSize; + if (overlap || lastCharOverlap || + sp < -minDupBreakOverlap * curWord->fontSize || + sp > minWordBreakSpace * curWord->fontSize || + fabs(base - curWord->base) > 0.5 || + curFontSize != curWord->fontSize) { + endWord(); + } + lastCharOverlap = overlap; + } else { + lastCharOverlap = gFalse; + } + + if (uLen != 0) { + // start a new word if needed + if (!curWord) { + beginWord(state, x, y); + } + + // page rotation and/or transform matrices can cause text to be + // drawn in reverse order -- in this case, swap the begin/end + // coordinates and break text into individual chars + if ((curWord->rot == 0 && w1 < 0) || + (curWord->rot == 1 && h1 < 0) || + (curWord->rot == 2 && w1 > 0) || + (curWord->rot == 3 && h1 > 0)) { + endWord(); + beginWord(state, x + dx, y + dy); + x1 += w1; + y1 += h1; + w1 = -w1; + h1 = -h1; + } + + // add the characters to the current word + w1 /= uLen; + h1 /= uLen; + for (i = 0; i < uLen; ++i) { + curWord->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1, u[i]); + } + } + if (curWord) { + curWord->charLen += nBytes; + } + charPos += nBytes; +} + +void TextPage::endWord() { + // This check is needed because Type 3 characters can contain + // text-drawing operations (when TextPage is being used via + // {X,Win}SplashOutputDev rather than TextOutputDev). + if (nest > 0) { + --nest; + return; + } + + if (curWord) { + addWord(curWord); + curWord = NULL; + } +} + +void TextPage::addWord(TextWord *word) { + // throw away zero-length words -- they don't have valid xMin/xMax + // values, and they're useless anyway + if (word->len == 0) { + delete word; + return; + } + + if (rawOrder) { + if (rawLastWord) { + rawLastWord->next = word; + } else { + rawWords = word; + } + rawLastWord = word; + } else { + pools[word->rot]->addWord(word); + } +} + +void TextPage::addUnderline(double x0, double y0, double x1, double y1) { + underlines->append(new TextUnderline(x0, y0, x1, y1)); +} + +void TextPage::addLink(int xMin, int yMin, int xMax, int yMax, Link *link) { + links->append(new TextLink(xMin, yMin, xMax, yMax, link)); +} + +void TextPage::coalesce(GBool physLayout, GBool doHTML) { + UnicodeMap *uMap; + TextPool *pool; + TextWord *word0, *word1, *word2; + TextLine *line; + TextBlock *blkList, *blkStack, *blk, *lastBlk, *blk0, *blk1; + TextBlock **blkArray; + TextFlow *flow, *lastFlow; + TextUnderline *underline; + TextLink *link; + int rot, poolMinBaseIdx, baseIdx, startBaseIdx, endBaseIdx; + double minBase, maxBase, newMinBase, newMaxBase; + double fontSize, colSpace1, colSpace2, lineSpace, intraLineSpace, blkSpace; + GBool found; + int count[4]; + int lrCount; + int firstBlkIdx, nBlocksLeft; + int col1, col2; + int i, j, n; + + if (rawOrder) { + primaryRot = 0; + primaryLR = gTrue; + return; + } + + uMap = globalParams->getTextEncoding(); + blkList = NULL; + lastBlk = NULL; + nBlocks = 0; + primaryRot = -1; + +#if 0 // for debugging + printf("*** initial words ***\n"); + for (rot = 0; rot < 4; ++rot) { + pool = pools[rot]; + for (baseIdx = pool->minBaseIdx; baseIdx <= pool->maxBaseIdx; ++baseIdx) { + for (word0 = pool->getPool(baseIdx); word0; word0 = word0->next) { + printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f rot=%d link=%p '", + word0->xMin, word0->xMax, word0->yMin, word0->yMax, + word0->base, word0->fontSize, rot*90, word0->link); + for (i = 0; i < word0->len; ++i) { + fputc(word0->text[i] & 0xff, stdout); + } + printf("'\n"); + } + } + } + printf("\n"); +#endif + +#if 0 //~ for debugging + for (i = 0; i < underlines->getLength(); ++i) { + underline = (TextUnderline *)underlines->get(i); + printf("underline: x=%g..%g y=%g..%g horiz=%d\n", + underline->x0, underline->x1, underline->y0, underline->y1, + underline->horiz); + } +#endif + + if (doHTML) { + + //----- handle underlining + for (i = 0; i < underlines->getLength(); ++i) { + underline = (TextUnderline *)underlines->get(i); + if (underline->horiz) { + // rot = 0 + if (pools[0]->minBaseIdx <= pools[0]->maxBaseIdx) { + startBaseIdx = pools[0]->getBaseIdx(underline->y0 + minUnderlineGap); + endBaseIdx = pools[0]->getBaseIdx(underline->y0 + maxUnderlineGap); + for (j = startBaseIdx; j <= endBaseIdx; ++j) { + for (word0 = pools[0]->getPool(j); word0; word0 = word0->next) { + //~ need to check the y value against the word baseline + if (underline->x0 < word0->xMin + underlineSlack && + word0->xMax - underlineSlack < underline->x1) { + word0->underlined = gTrue; + } + } + } + } + + // rot = 2 + if (pools[2]->minBaseIdx <= pools[2]->maxBaseIdx) { + startBaseIdx = pools[2]->getBaseIdx(underline->y0 - maxUnderlineGap); + endBaseIdx = pools[2]->getBaseIdx(underline->y0 - minUnderlineGap); + for (j = startBaseIdx; j <= endBaseIdx; ++j) { + for (word0 = pools[2]->getPool(j); word0; word0 = word0->next) { + if (underline->x0 < word0->xMin + underlineSlack && + word0->xMax - underlineSlack < underline->x1) { + word0->underlined = gTrue; + } + } + } + } + } else { + // rot = 1 + if (pools[1]->minBaseIdx <= pools[1]->maxBaseIdx) { + startBaseIdx = pools[1]->getBaseIdx(underline->x0 - maxUnderlineGap); + endBaseIdx = pools[1]->getBaseIdx(underline->x0 - minUnderlineGap); + for (j = startBaseIdx; j <= endBaseIdx; ++j) { + for (word0 = pools[1]->getPool(j); word0; word0 = word0->next) { + if (underline->y0 < word0->yMin + underlineSlack && + word0->yMax - underlineSlack < underline->y1) { + word0->underlined = gTrue; + } + } + } + } + + // rot = 3 + if (pools[3]->minBaseIdx <= pools[3]->maxBaseIdx) { + startBaseIdx = pools[3]->getBaseIdx(underline->x0 + minUnderlineGap); + endBaseIdx = pools[3]->getBaseIdx(underline->x0 + maxUnderlineGap); + for (j = startBaseIdx; j <= endBaseIdx; ++j) { + for (word0 = pools[3]->getPool(j); word0; word0 = word0->next) { + if (underline->y0 < word0->yMin + underlineSlack && + word0->yMax - underlineSlack < underline->y1) { + word0->underlined = gTrue; + } + } + } + } + } + } + + //----- handle links + for (i = 0; i < links->getLength(); ++i) { + link = (TextLink *)links->get(i); + + // rot = 0 + if (pools[0]->minBaseIdx <= pools[0]->maxBaseIdx) { + startBaseIdx = pools[0]->getBaseIdx(link->yMin); + endBaseIdx = pools[0]->getBaseIdx(link->yMax); + for (j = startBaseIdx; j <= endBaseIdx; ++j) { + for (word0 = pools[0]->getPool(j); word0; word0 = word0->next) { + if (link->xMin < word0->xMin + hyperlinkSlack && + word0->xMax - hyperlinkSlack < link->xMax && + link->yMin < word0->yMin + hyperlinkSlack && + word0->yMax - hyperlinkSlack < link->yMax) { + word0->link = link->link; + } + } + } + } + + // rot = 2 + if (pools[2]->minBaseIdx <= pools[2]->maxBaseIdx) { + startBaseIdx = pools[2]->getBaseIdx(link->yMin); + endBaseIdx = pools[2]->getBaseIdx(link->yMax); + for (j = startBaseIdx; j <= endBaseIdx; ++j) { + for (word0 = pools[2]->getPool(j); word0; word0 = word0->next) { + if (link->xMin < word0->xMin + hyperlinkSlack && + word0->xMax - hyperlinkSlack < link->xMax && + link->yMin < word0->yMin + hyperlinkSlack && + word0->yMax - hyperlinkSlack < link->yMax) { + word0->link = link->link; + } + } + } + } + + // rot = 1 + if (pools[1]->minBaseIdx <= pools[1]->maxBaseIdx) { + startBaseIdx = pools[1]->getBaseIdx(link->xMin); + endBaseIdx = pools[1]->getBaseIdx(link->xMax); + for (j = startBaseIdx; j <= endBaseIdx; ++j) { + for (word0 = pools[1]->getPool(j); word0; word0 = word0->next) { + if (link->yMin < word0->yMin + hyperlinkSlack && + word0->yMax - hyperlinkSlack < link->yMax && + link->xMin < word0->xMin + hyperlinkSlack && + word0->xMax - hyperlinkSlack < link->xMax) { + word0->link = link->link; + } + } + } + } + + // rot = 3 + if (pools[3]->minBaseIdx <= pools[3]->maxBaseIdx) { + startBaseIdx = pools[3]->getBaseIdx(link->xMin); + endBaseIdx = pools[3]->getBaseIdx(link->xMax); + for (j = startBaseIdx; j <= endBaseIdx; ++j) { + for (word0 = pools[3]->getPool(j); word0; word0 = word0->next) { + if (link->yMin < word0->yMin + hyperlinkSlack && + word0->yMax - hyperlinkSlack < link->yMax && + link->xMin < word0->xMin + hyperlinkSlack && + word0->xMax - hyperlinkSlack < link->xMax) { + word0->link = link->link; + } + } + } + } + } + } + + //----- assemble the blocks + + //~ add an outer loop for writing mode (vertical text) + + // build blocks for each rotation value + for (rot = 0; rot < 4; ++rot) { + pool = pools[rot]; + poolMinBaseIdx = pool->minBaseIdx; + count[rot] = 0; + + // add blocks until no more words are left + while (1) { + + // find the first non-empty line in the pool + for (; + poolMinBaseIdx <= pool->maxBaseIdx && + !pool->getPool(poolMinBaseIdx); + ++poolMinBaseIdx) ; + if (poolMinBaseIdx > pool->maxBaseIdx) { + break; + } + + // look for the left-most word in the first four lines of the + // pool -- this avoids starting with a superscript word + startBaseIdx = poolMinBaseIdx; + for (baseIdx = poolMinBaseIdx + 1; + baseIdx < poolMinBaseIdx + 4 && baseIdx <= pool->maxBaseIdx; + ++baseIdx) { + if (!pool->getPool(baseIdx)) { + continue; + } + if (pool->getPool(baseIdx)->primaryCmp(pool->getPool(startBaseIdx)) + < 0) { + startBaseIdx = baseIdx; + } + } + + // create a new block + word0 = pool->getPool(startBaseIdx); + pool->setPool(startBaseIdx, word0->next); + word0->next = NULL; + blk = new TextBlock(this, rot); + blk->addWord(word0); + + fontSize = word0->fontSize; + minBase = maxBase = word0->base; + colSpace1 = minColSpacing1 * fontSize; + colSpace2 = minColSpacing2 * fontSize; + lineSpace = maxLineSpacingDelta * fontSize; + intraLineSpace = maxIntraLineDelta * fontSize; + + // add words to the block + do { + found = gFalse; + + // look for words on the line above the current top edge of + // the block + newMinBase = minBase; + for (baseIdx = pool->getBaseIdx(minBase); + baseIdx >= pool->getBaseIdx(minBase - lineSpace); + --baseIdx) { + word0 = NULL; + word1 = pool->getPool(baseIdx); + while (word1) { + if (word1->base < minBase && + word1->base >= minBase - lineSpace && + ((rot == 0 || rot == 2) + ? (word1->xMin < blk->xMax && word1->xMax > blk->xMin) + : (word1->yMin < blk->yMax && word1->yMax > blk->yMin)) && + fabs(word1->fontSize - fontSize) < + maxBlockFontSizeDelta1 * fontSize) { + word2 = word1; + if (word0) { + word0->next = word1->next; + } else { + pool->setPool(baseIdx, word1->next); + } + word1 = word1->next; + word2->next = NULL; + blk->addWord(word2); + found = gTrue; + newMinBase = word2->base; + } else { + word0 = word1; + word1 = word1->next; + } + } + } + minBase = newMinBase; + + // look for words on the line below the current bottom edge of + // the block + newMaxBase = maxBase; + for (baseIdx = pool->getBaseIdx(maxBase); + baseIdx <= pool->getBaseIdx(maxBase + lineSpace); + ++baseIdx) { + word0 = NULL; + word1 = pool->getPool(baseIdx); + while (word1) { + if (word1->base > maxBase && + word1->base <= maxBase + lineSpace && + ((rot == 0 || rot == 2) + ? (word1->xMin < blk->xMax && word1->xMax > blk->xMin) + : (word1->yMin < blk->yMax && word1->yMax > blk->yMin)) && + fabs(word1->fontSize - fontSize) < + maxBlockFontSizeDelta1 * fontSize) { + word2 = word1; + if (word0) { + word0->next = word1->next; + } else { + pool->setPool(baseIdx, word1->next); + } + word1 = word1->next; + word2->next = NULL; + blk->addWord(word2); + found = gTrue; + newMaxBase = word2->base; + } else { + word0 = word1; + word1 = word1->next; + } + } + } + maxBase = newMaxBase; + + // look for words that are on lines already in the block, and + // that overlap the block horizontally + for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); + baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); + ++baseIdx) { + word0 = NULL; + word1 = pool->getPool(baseIdx); + while (word1) { + if (word1->base >= minBase - intraLineSpace && + word1->base <= maxBase + intraLineSpace && + ((rot == 0 || rot == 2) + ? (word1->xMin < blk->xMax + colSpace1 && + word1->xMax > blk->xMin - colSpace1) + : (word1->yMin < blk->yMax + colSpace1 && + word1->yMax > blk->yMin - colSpace1)) && + fabs(word1->fontSize - fontSize) < + maxBlockFontSizeDelta2 * fontSize) { + word2 = word1; + if (word0) { + word0->next = word1->next; + } else { + pool->setPool(baseIdx, word1->next); + } + word1 = word1->next; + word2->next = NULL; + blk->addWord(word2); + found = gTrue; + } else { + word0 = word1; + word1 = word1->next; + } + } + } + + // only check for outlying words (the next two chunks of code) + // if we didn't find anything else + if (found) { + continue; + } + + // scan down the left side of the block, looking for words + // that are near (but not overlapping) the block; if there are + // three or fewer, add them to the block + n = 0; + for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); + baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); + ++baseIdx) { + word1 = pool->getPool(baseIdx); + while (word1) { + if (word1->base >= minBase - intraLineSpace && + word1->base <= maxBase + intraLineSpace && + ((rot == 0 || rot == 2) + ? (word1->xMax <= blk->xMin && + word1->xMax > blk->xMin - colSpace2) + : (word1->yMax <= blk->yMin && + word1->yMax > blk->yMin - colSpace2)) && + fabs(word1->fontSize - fontSize) < + maxBlockFontSizeDelta3 * fontSize) { + ++n; + break; + } + word1 = word1->next; + } + } + if (n > 0 && n <= 3) { + for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); + baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); + ++baseIdx) { + word0 = NULL; + word1 = pool->getPool(baseIdx); + while (word1) { + if (word1->base >= minBase - intraLineSpace && + word1->base <= maxBase + intraLineSpace && + ((rot == 0 || rot == 2) + ? (word1->xMax <= blk->xMin && + word1->xMax > blk->xMin - colSpace2) + : (word1->yMax <= blk->yMin && + word1->yMax > blk->yMin - colSpace2)) && + fabs(word1->fontSize - fontSize) < + maxBlockFontSizeDelta3 * fontSize) { + word2 = word1; + if (word0) { + word0->next = word1->next; + } else { + pool->setPool(baseIdx, word1->next); + } + word1 = word1->next; + word2->next = NULL; + blk->addWord(word2); + if (word2->base < minBase) { + minBase = word2->base; + } else if (word2->base > maxBase) { + maxBase = word2->base; + } + found = gTrue; + break; + } else { + word0 = word1; + word1 = word1->next; + } + } + } + } + + // scan down the right side of the block, looking for words + // that are near (but not overlapping) the block; if there are + // three or fewer, add them to the block + n = 0; + for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); + baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); + ++baseIdx) { + word1 = pool->getPool(baseIdx); + while (word1) { + if (word1->base >= minBase - intraLineSpace && + word1->base <= maxBase + intraLineSpace && + ((rot == 0 || rot == 2) + ? (word1->xMin >= blk->xMax && + word1->xMin < blk->xMax + colSpace2) + : (word1->yMin >= blk->yMax && + word1->yMin < blk->yMax + colSpace2)) && + fabs(word1->fontSize - fontSize) < + maxBlockFontSizeDelta3 * fontSize) { + ++n; + break; + } + word1 = word1->next; + } + } + if (n > 0 && n <= 3) { + for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); + baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); + ++baseIdx) { + word0 = NULL; + word1 = pool->getPool(baseIdx); + while (word1) { + if (word1->base >= minBase - intraLineSpace && + word1->base <= maxBase + intraLineSpace && + ((rot == 0 || rot == 2) + ? (word1->xMin >= blk->xMax && + word1->xMin < blk->xMax + colSpace2) + : (word1->yMin >= blk->yMax && + word1->yMin < blk->yMax + colSpace2)) && + fabs(word1->fontSize - fontSize) < + maxBlockFontSizeDelta3 * fontSize) { + word2 = word1; + if (word0) { + word0->next = word1->next; + } else { + pool->setPool(baseIdx, word1->next); + } + word1 = word1->next; + word2->next = NULL; + blk->addWord(word2); + if (word2->base < minBase) { + minBase = word2->base; + } else if (word2->base > maxBase) { + maxBase = word2->base; + } + found = gTrue; + break; + } else { + word0 = word1; + word1 = word1->next; + } + } + } + } + + } while (found); + + //~ need to compute the primary writing mode (horiz/vert) in + //~ addition to primary rotation + + // coalesce the block, and add it to the list + blk->coalesce(uMap); + if (lastBlk) { + lastBlk->next = blk; + } else { + blkList = blk; + } + lastBlk = blk; + count[rot] += blk->charCount; + if (primaryRot < 0 || count[rot] > count[primaryRot]) { + primaryRot = rot; + } + ++nBlocks; + } + } + +#if 0 // for debugging + printf("*** rotation ***\n"); + for (rot = 0; rot < 4; ++rot) { + printf(" %d: %6d\n", rot, count[rot]); + } + printf(" primary rot = %d\n", primaryRot); + printf("\n"); +#endif + +#if 0 // for debugging + printf("*** blocks ***\n"); + for (blk = blkList; blk; blk = blk->next) { + printf("block: rot=%d x=%.2f..%.2f y=%.2f..%.2f\n", + blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax); + for (line = blk->lines; line; line = line->next) { + printf(" line: x=%.2f..%.2f y=%.2f..%.2f base=%.2f\n", + line->xMin, line->xMax, line->yMin, line->yMax, line->base); + for (word0 = line->words; word0; word0 = word0->next) { + printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '", + word0->xMin, word0->xMax, word0->yMin, word0->yMax, + word0->base, word0->fontSize, word0->spaceAfter); + for (i = 0; i < word0->len; ++i) { + fputc(word0->text[i] & 0xff, stdout); + } + printf("'\n"); + } + } + } + printf("\n"); +#endif + + // determine the primary direction + lrCount = 0; + for (blk = blkList; blk; blk = blk->next) { + for (line = blk->lines; line; line = line->next) { + for (word0 = line->words; word0; word0 = word0->next) { + for (i = 0; i < word0->len; ++i) { + if (unicodeTypeL(word0->text[i])) { + ++lrCount; + } else if (unicodeTypeR(word0->text[i])) { + --lrCount; + } + } + } + } + } + primaryLR = lrCount >= 0; + +#if 0 // for debugging + printf("*** direction ***\n"); + printf("lrCount = %d\n", lrCount); + printf("primaryLR = %d\n", primaryLR); +#endif + + //----- column assignment + + // sort blocks into xy order for column assignment + blocks = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *)); + for (blk = blkList, i = 0; blk; blk = blk->next, ++i) { + blocks[i] = blk; + } + qsort(blocks, nBlocks, sizeof(TextBlock *), &TextBlock::cmpXYPrimaryRot); + + // column assignment + for (i = 0; i < nBlocks; ++i) { + blk0 = blocks[i]; + col1 = 0; + for (j = 0; j < i; ++j) { + blk1 = blocks[j]; + col2 = 0; // make gcc happy + switch (primaryRot) { + case 0: + if (blk0->xMin > blk1->xMax) { + col2 = blk1->col + blk1->nColumns + 3; + } else if (blk1->xMax == blk1->xMin) { + col2 = blk1->col; + } else { + col2 = blk1->col + (int)(((blk0->xMin - blk1->xMin) / + (blk1->xMax - blk1->xMin)) * + blk1->nColumns); + } + break; + case 1: + if (blk0->yMin > blk1->yMax) { + col2 = blk1->col + blk1->nColumns + 3; + } else if (blk1->yMax == blk1->yMin) { + col2 = blk1->col; + } else { + col2 = blk1->col + (int)(((blk0->yMin - blk1->yMin) / + (blk1->yMax - blk1->yMin)) * + blk1->nColumns); + } + break; + case 2: + if (blk0->xMax < blk1->xMin) { + col2 = blk1->col + blk1->nColumns + 3; + } else if (blk1->xMin == blk1->xMax) { + col2 = blk1->col; + } else { + col2 = blk1->col + (int)(((blk0->xMax - blk1->xMax) / + (blk1->xMin - blk1->xMax)) * + blk1->nColumns); + } + break; + case 3: + if (blk0->yMax < blk1->yMin) { + col2 = blk1->col + blk1->nColumns + 3; + } else if (blk1->yMin == blk1->yMax) { + col2 = blk1->col; + } else { + col2 = blk1->col + (int)(((blk0->yMax - blk1->yMax) / + (blk1->yMin - blk1->yMax)) * + blk1->nColumns); + } + break; + } + if (col2 > col1) { + col1 = col2; + } + } + blk0->col = col1; + for (line = blk0->lines; line; line = line->next) { + for (j = 0; j <= line->len; ++j) { + line->col[j] += col1; + } + } + } + +#if 0 // for debugging + printf("*** blocks, after column assignment ***\n"); + for (blk = blkList; blk; blk = blk->next) { + printf("block: rot=%d x=%.2f..%.2f y=%.2f..%.2f col=%d nCols=%d\n", + blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax, blk->col, + blk->nColumns); + for (line = blk->lines; line; line = line->next) { + printf(" line:\n"); + for (word0 = line->words; word0; word0 = word0->next) { + printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '", + word0->xMin, word0->xMax, word0->yMin, word0->yMax, + word0->base, word0->fontSize, word0->spaceAfter); + for (i = 0; i < word0->len; ++i) { + fputc(word0->text[i] & 0xff, stdout); + } + printf("'\n"); + } + } + } + printf("\n"); +#endif + + //----- reading order sort + + // sort blocks into yx order (in preparation for reading order sort) + qsort(blocks, nBlocks, sizeof(TextBlock *), &TextBlock::cmpYXPrimaryRot); + + // compute space on left and right sides of each block + for (i = 0; i < nBlocks; ++i) { + blk0 = blocks[i]; + for (j = 0; j < nBlocks; ++j) { + blk1 = blocks[j]; + if (blk1 != blk0) { + blk0->updatePriMinMax(blk1); + } + } + } + +#if 0 // for debugging + printf("*** blocks, after yx sort ***\n"); + for (i = 0; i < nBlocks; ++i) { + blk = blocks[i]; + printf("block: rot=%d x=%.2f..%.2f y=%.2f..%.2f space=%.2f..%.2f\n", + blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax, + blk->priMin, blk->priMax); + for (line = blk->lines; line; line = line->next) { + printf(" line:\n"); + for (word0 = line->words; word0; word0 = word0->next) { + printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '", + word0->xMin, word0->xMax, word0->yMin, word0->yMax, + word0->base, word0->fontSize, word0->spaceAfter); + for (j = 0; j < word0->len; ++j) { + fputc(word0->text[j] & 0xff, stdout); + } + printf("'\n"); + } + } + } + printf("\n"); +#endif + + // build the flows + //~ this needs to be adjusted for writing mode (vertical text) + //~ this also needs to account for right-to-left column ordering + blkArray = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *)); + memcpy(blkArray, blocks, nBlocks * sizeof(TextBlock *)); + flows = lastFlow = NULL; + firstBlkIdx = 0; + nBlocksLeft = nBlocks; + while (nBlocksLeft > 0) { + + // find the upper-left-most block + for (; !blkArray[firstBlkIdx]; ++firstBlkIdx) ; + i = firstBlkIdx; + blk = blkArray[i]; + for (j = firstBlkIdx + 1; j < nBlocks; ++j) { + blk1 = blkArray[j]; + if (blk1) { + if (blk && blk->secondaryDelta(blk1) > 0) { + break; + } + if (blk1->primaryCmp(blk) < 0) { + i = j; + blk = blk1; + } + } + } + blkArray[i] = NULL; + --nBlocksLeft; + blk->next = NULL; + + // create a new flow, starting with the upper-left-most block + flow = new TextFlow(this, blk); + if (lastFlow) { + lastFlow->next = flow; + } else { + flows = flow; + } + lastFlow = flow; + fontSize = blk->lines->words->fontSize; + + // push the upper-left-most block on the stack + blk->stackNext = NULL; + blkStack = blk; + + // find the other blocks in this flow + while (blkStack) { + + // find the upper-left-most block under (but within + // maxBlockSpacing of) the top block on the stack + blkSpace = maxBlockSpacing * blkStack->lines->words->fontSize; + blk = NULL; + i = -1; + for (j = firstBlkIdx; j < nBlocks; ++j) { + blk1 = blkArray[j]; + if (blk1) { + if (blkStack->secondaryDelta(blk1) > blkSpace) { + break; + } + if (blk && blk->secondaryDelta(blk1) > 0) { + break; + } + if (blk1->isBelow(blkStack) && + (!blk || blk1->primaryCmp(blk) < 0)) { + i = j; + blk = blk1; + } + } + } + + // if a suitable block was found, add it to the flow and push it + // onto the stack + if (blk && flow->blockFits(blk, blkStack)) { + blkArray[i] = NULL; + --nBlocksLeft; + blk->next = NULL; + flow->addBlock(blk); + fontSize = blk->lines->words->fontSize; + blk->stackNext = blkStack; + blkStack = blk; + + // otherwise (if there is no block under the top block or the + // block is not suitable), pop the stack + } else { + blkStack = blkStack->stackNext; + } + } + } + gfree(blkArray); + +#if 0 // for debugging + printf("*** flows ***\n"); + for (flow = flows; flow; flow = flow->next) { + printf("flow: x=%.2f..%.2f y=%.2f..%.2f pri:%.2f..%.2f\n", + flow->xMin, flow->xMax, flow->yMin, flow->yMax, + flow->priMin, flow->priMax); + for (blk = flow->blocks; blk; blk = blk->next) { + printf(" block: rot=%d x=%.2f..%.2f y=%.2f..%.2f pri=%.2f..%.2f\n", + blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax, + blk->priMin, blk->priMax); + for (line = blk->lines; line; line = line->next) { + printf(" line:\n"); + for (word0 = line->words; word0; word0 = word0->next) { + printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '", + word0->xMin, word0->xMax, word0->yMin, word0->yMax, + word0->base, word0->fontSize, word0->spaceAfter); + for (i = 0; i < word0->len; ++i) { + fputc(word0->text[i] & 0xff, stdout); + } + printf("'\n"); + } + } + } + } + printf("\n"); +#endif + + if (uMap) { + uMap->decRefCnt(); + } +} + +GBool TextPage::findText(Unicode *s, int len, + GBool startAtTop, GBool stopAtBottom, + GBool startAtLast, GBool stopAtLast, + GBool caseSensitive, GBool backward, + double *xMin, double *yMin, + double *xMax, double *yMax) { + TextBlock *blk; + TextLine *line; + Unicode *s2, *txt; + Unicode *p; + int txtSize, m, i, j, k; + double xStart, yStart, xStop, yStop; + double xMin0, yMin0, xMax0, yMax0; + double xMin1, yMin1, xMax1, yMax1; + GBool found; + + //~ needs to handle right-to-left text + + if (rawOrder) { + return gFalse; + } + + // convert the search string to uppercase + if (!caseSensitive) { + s2 = (Unicode *)gmallocn(len, sizeof(Unicode)); + for (i = 0; i < len; ++i) { + s2[i] = unicodeToUpper(s[i]); + } + } else { + s2 = s; + } + + txt = NULL; + txtSize = 0; + + xStart = yStart = xStop = yStop = 0; + if (startAtLast && haveLastFind) { + xStart = lastFindXMin; + yStart = lastFindYMin; + } else if (!startAtTop) { + xStart = *xMin; + yStart = *yMin; + } + if (stopAtLast && haveLastFind) { + xStop = lastFindXMin; + yStop = lastFindYMin; + } else if (!stopAtBottom) { + xStop = *xMax; + yStop = *yMax; + } + + found = gFalse; + xMin0 = xMax0 = yMin0 = yMax0 = 0; // make gcc happy + xMin1 = xMax1 = yMin1 = yMax1 = 0; // make gcc happy + + for (i = backward ? nBlocks - 1 : 0; + backward ? i >= 0 : i < nBlocks; + i += backward ? -1 : 1) { + blk = blocks[i]; + + // check: is the block above the top limit? + if (!startAtTop && (backward ? blk->yMin > yStart : blk->yMax < yStart)) { + continue; + } + + // check: is the block below the bottom limit? + if (!stopAtBottom && (backward ? blk->yMax < yStop : blk->yMin > yStop)) { + break; + } + + for (line = blk->lines; line; line = line->next) { + + // check: is the line above the top limit? + if (!startAtTop && + (backward ? line->yMin > yStart : line->yMin < yStart)) { + continue; + } + + // check: is the line below the bottom limit? + if (!stopAtBottom && + (backward ? line->yMin < yStop : line->yMin > yStop)) { + continue; + } + + // convert the line to uppercase + m = line->len; + if (!caseSensitive) { + if (m > txtSize) { + txt = (Unicode *)greallocn(txt, m, sizeof(Unicode)); + txtSize = m; + } + for (k = 0; k < m; ++k) { + txt[k] = unicodeToUpper(line->text[k]); + } + } else { + txt = line->text; + } + + // search each position in this line + j = backward ? m - len : 0; + p = txt + j; + while (backward ? j >= 0 : j <= m - len) { + + // compare the strings + for (k = 0; k < len; ++k) { + if (p[k] != s2[k]) { + break; + } + } + + // found it + if (k == len) { + switch (line->rot) { + case 0: + xMin1 = line->edge[j]; + xMax1 = line->edge[j + len]; + yMin1 = line->yMin; + yMax1 = line->yMax; + break; + case 1: + xMin1 = line->xMin; + xMax1 = line->xMax; + yMin1 = line->edge[j]; + yMax1 = line->edge[j + len]; + break; + case 2: + xMin1 = line->edge[j + len]; + xMax1 = line->edge[j]; + yMin1 = line->yMin; + yMax1 = line->yMax; + break; + case 3: + xMin1 = line->xMin; + xMax1 = line->xMax; + yMin1 = line->edge[j + len]; + yMax1 = line->edge[j]; + break; + } + if (backward) { + if ((startAtTop || + yMin1 < yStart || (yMin1 == yStart && xMin1 < xStart)) && + (stopAtBottom || + yMin1 > yStop || (yMin1 == yStop && xMin1 > xStop))) { + if (!found || + yMin1 > yMin0 || (yMin1 == yMin0 && xMin1 > xMin0)) { + xMin0 = xMin1; + xMax0 = xMax1; + yMin0 = yMin1; + yMax0 = yMax1; + found = gTrue; + } + } + } else { + if ((startAtTop || + yMin1 > yStart || (yMin1 == yStart && xMin1 > xStart)) && + (stopAtBottom || + yMin1 < yStop || (yMin1 == yStop && xMin1 < xStop))) { + if (!found || + yMin1 < yMin0 || (yMin1 == yMin0 && xMin1 < xMin0)) { + xMin0 = xMin1; + xMax0 = xMax1; + yMin0 = yMin1; + yMax0 = yMax1; + found = gTrue; + } + } + } + } + if (backward) { + --j; + --p; + } else { + ++j; + ++p; + } + } + } + } + + if (!caseSensitive) { + gfree(s2); + gfree(txt); + } + + if (found) { + *xMin = xMin0; + *xMax = xMax0; + *yMin = yMin0; + *yMax = yMax0; + lastFindXMin = xMin0; + lastFindYMin = yMin0; + haveLastFind = gTrue; + return gTrue; + } + + return gFalse; +} + +GString *TextPage::getText(double xMin, double yMin, + double xMax, double yMax) { + GString *s; + UnicodeMap *uMap; + GBool isUnicode; + TextBlock *blk; + TextLine *line; + TextLineFrag *frags; + int nFrags, fragsSize; + TextLineFrag *frag; + char space[8], eol[16]; + int spaceLen, eolLen; + int lastRot; + double x, y, delta; + int col, idx0, idx1, i, j; + GBool multiLine, oneRot; + + s = new GString(); + + if (rawOrder) { + return s; + } + + // get the output encoding + if (!(uMap = globalParams->getTextEncoding())) { + return s; + } + isUnicode = uMap->isUnicode(); + spaceLen = uMap->mapUnicode(0x20, space, sizeof(space)); + eolLen = 0; // make gcc happy + switch (globalParams->getTextEOL()) { + case eolUnix: + eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol)); + break; + case eolDOS: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + eolLen += uMap->mapUnicode(0x0a, eol + eolLen, sizeof(eol) - eolLen); + break; + case eolMac: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + break; + } + + //~ writing mode (horiz/vert) + + // collect the line fragments that are in the rectangle + fragsSize = 256; + frags = (TextLineFrag *)gmallocn(fragsSize, sizeof(TextLineFrag)); + nFrags = 0; + lastRot = -1; + oneRot = gTrue; + for (i = 0; i < nBlocks; ++i) { + blk = blocks[i]; + if (xMin < blk->xMax && blk->xMin < xMax && + yMin < blk->yMax && blk->yMin < yMax) { + for (line = blk->lines; line; line = line->next) { + if (xMin < line->xMax && line->xMin < xMax && + yMin < line->yMax && line->yMin < yMax) { + idx0 = idx1 = -1; + switch (line->rot) { + case 0: + y = 0.5 * (line->yMin + line->yMax); + if (yMin < y && y < yMax) { + j = 0; + while (j < line->len) { + if (0.5 * (line->edge[j] + line->edge[j+1]) > xMin) { + idx0 = j; + break; + } + ++j; + } + j = line->len - 1; + while (j >= 0) { + if (0.5 * (line->edge[j] + line->edge[j+1]) < xMax) { + idx1 = j; + break; + } + --j; + } + } + break; + case 1: + x = 0.5 * (line->xMin + line->xMax); + if (xMin < x && x < xMax) { + j = 0; + while (j < line->len) { + if (0.5 * (line->edge[j] + line->edge[j+1]) > yMin) { + idx0 = j; + break; + } + ++j; + } + j = line->len - 1; + while (j >= 0) { + if (0.5 * (line->edge[j] + line->edge[j+1]) < yMax) { + idx1 = j; + break; + } + --j; + } + } + break; + case 2: + y = 0.5 * (line->yMin + line->yMax); + if (yMin < y && y < yMax) { + j = 0; + while (j < line->len) { + if (0.5 * (line->edge[j] + line->edge[j+1]) < xMax) { + idx0 = j; + break; + } + ++j; + } + j = line->len - 1; + while (j >= 0) { + if (0.5 * (line->edge[j] + line->edge[j+1]) > xMin) { + idx1 = j; + break; + } + --j; + } + } + break; + case 3: + x = 0.5 * (line->xMin + line->xMax); + if (xMin < x && x < xMax) { + j = 0; + while (j < line->len) { + if (0.5 * (line->edge[j] + line->edge[j+1]) < yMax) { + idx0 = j; + break; + } + ++j; + } + j = line->len - 1; + while (j >= 0) { + if (0.5 * (line->edge[j] + line->edge[j+1]) > yMin) { + idx1 = j; + break; + } + --j; + } + } + break; + } + if (idx0 >= 0 && idx1 >= 0) { + if (nFrags == fragsSize) { + fragsSize *= 2; + frags = (TextLineFrag *) + greallocn(frags, fragsSize, sizeof(TextLineFrag)); + } + frags[nFrags].init(line, idx0, idx1 - idx0 + 1); + ++nFrags; + if (lastRot >= 0 && line->rot != lastRot) { + oneRot = gFalse; + } + lastRot = line->rot; + } + } + } + } + } + + // sort the fragments and generate the string + if (nFrags > 0) { + + for (i = 0; i < nFrags; ++i) { + frags[i].computeCoords(oneRot); + } + assignColumns(frags, nFrags, oneRot); + + // if all lines in the region have the same rotation, use it; + // otherwise, use the page's primary rotation + if (oneRot) { + qsort(frags, nFrags, sizeof(TextLineFrag), + &TextLineFrag::cmpYXLineRot); + } else { + qsort(frags, nFrags, sizeof(TextLineFrag), + &TextLineFrag::cmpYXPrimaryRot); + } + i = 0; + while (i < nFrags) { + delta = maxIntraLineDelta * frags[i].line->words->fontSize; + for (j = i+1; + j < nFrags && fabs(frags[j].base - frags[i].base) < delta; + ++j) ; + qsort(frags + i, j - i, sizeof(TextLineFrag), + oneRot ? &TextLineFrag::cmpXYColumnLineRot + : &TextLineFrag::cmpXYColumnPrimaryRot); + i = j; + } + + col = 0; + multiLine = gFalse; + for (i = 0; i < nFrags; ++i) { + frag = &frags[i]; + + // insert a return + if (frag->col < col || + (i > 0 && fabs(frag->base - frags[i-1].base) > + maxIntraLineDelta * frags[i-1].line->words->fontSize)) { + s->append(eol, eolLen); + col = 0; + multiLine = gTrue; + } + + // column alignment + for (; col < frag->col; ++col) { + s->append(space, spaceLen); + } + + // get the fragment text + col += dumpFragment(frag->line->text + frag->start, frag->len, uMap, s); + } + + if (multiLine) { + s->append(eol, eolLen); + } + } + + gfree(frags); + uMap->decRefCnt(); + + return s; +} + +GBool TextPage::findCharRange(int pos, int length, + double *xMin, double *yMin, + double *xMax, double *yMax) { + TextBlock *blk; + TextLine *line; + TextWord *word; + double xMin0, xMax0, yMin0, yMax0; + double xMin1, xMax1, yMin1, yMax1; + GBool first; + int i, j0, j1; + + if (rawOrder) { + return gFalse; + } + + //~ this doesn't correctly handle: + //~ - ranges split across multiple lines (the highlighted region + //~ is the bounding box of all the parts of the range) + //~ - cases where characters don't convert one-to-one into Unicode + first = gTrue; + xMin0 = xMax0 = yMin0 = yMax0 = 0; // make gcc happy + xMin1 = xMax1 = yMin1 = yMax1 = 0; // make gcc happy + for (i = 0; i < nBlocks; ++i) { + blk = blocks[i]; + for (line = blk->lines; line; line = line->next) { + for (word = line->words; word; word = word->next) { + if (pos < word->charPos + word->charLen && + word->charPos < pos + length) { + j0 = pos - word->charPos; + if (j0 < 0) { + j0 = 0; + } + j1 = pos + length - 1 - word->charPos; + if (j1 >= word->len) { + j1 = word->len - 1; + } + switch (line->rot) { + case 0: + xMin1 = word->edge[j0]; + xMax1 = word->edge[j1 + 1]; + yMin1 = word->yMin; + yMax1 = word->yMax; + break; + case 1: + xMin1 = word->xMin; + xMax1 = word->xMax; + yMin1 = word->edge[j0]; + yMax1 = word->edge[j1 + 1]; + break; + case 2: + xMin1 = word->edge[j1 + 1]; + xMax1 = word->edge[j0]; + yMin1 = word->yMin; + yMax1 = word->yMax; + break; + case 3: + xMin1 = word->xMin; + xMax1 = word->xMax; + yMin1 = word->edge[j1 + 1]; + yMax1 = word->edge[j0]; + break; + } + if (first || xMin1 < xMin0) { + xMin0 = xMin1; + } + if (first || xMax1 > xMax0) { + xMax0 = xMax1; + } + if (first || yMin1 < yMin0) { + yMin0 = yMin1; + } + if (first || yMax1 > yMax0) { + yMax0 = yMax1; + } + first = gFalse; + } + } + } + } + if (!first) { + *xMin = xMin0; + *xMax = xMax0; + *yMin = yMin0; + *yMax = yMax0; + return gTrue; + } + return gFalse; +} + +void TextPage::dump(void *outputStream, TextOutputFunc outputFunc, + GBool physLayout) { + UnicodeMap *uMap; + TextFlow *flow; + TextBlock *blk; + TextLine *line; + TextLineFrag *frags; + TextWord *word; + int nFrags, fragsSize; + TextLineFrag *frag; + char space[8], eol[16], eop[8]; + int spaceLen, eolLen, eopLen; + GBool pageBreaks; + GString *s; + double delta; + int col, i, j, d, n; + + // get the output encoding + if (!(uMap = globalParams->getTextEncoding())) { + return; + } + spaceLen = uMap->mapUnicode(0x20, space, sizeof(space)); + eolLen = 0; // make gcc happy + switch (globalParams->getTextEOL()) { + case eolUnix: + eolLen = uMap->mapUnicode(0x0a, eol, sizeof(eol)); + break; + case eolDOS: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + eolLen += uMap->mapUnicode(0x0a, eol + eolLen, sizeof(eol) - eolLen); + break; + case eolMac: + eolLen = uMap->mapUnicode(0x0d, eol, sizeof(eol)); + break; + } + eopLen = uMap->mapUnicode(0x0c, eop, sizeof(eop)); + pageBreaks = globalParams->getTextPageBreaks(); + + //~ writing mode (horiz/vert) + + // output the page in raw (content stream) order + if (rawOrder) { + + for (word = rawWords; word; word = word->next) { + s = new GString(); + dumpFragment(word->text, word->len, uMap, s); + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + delete s; + if (word->next && + fabs(word->next->base - word->base) < + maxIntraLineDelta * word->fontSize) { + if (word->next->xMin > word->xMax + minWordSpacing * word->fontSize) { + (*outputFunc)(outputStream, space, spaceLen); + } + } else { + (*outputFunc)(outputStream, eol, eolLen); + } + } + + // output the page, maintaining the original physical layout + } else if (physLayout) { + + // collect the line fragments for the page and sort them + fragsSize = 256; + frags = (TextLineFrag *)gmallocn(fragsSize, sizeof(TextLineFrag)); + nFrags = 0; + for (i = 0; i < nBlocks; ++i) { + blk = blocks[i]; + for (line = blk->lines; line; line = line->next) { + if (nFrags == fragsSize) { + fragsSize *= 2; + frags = (TextLineFrag *)greallocn(frags, + fragsSize, sizeof(TextLineFrag)); + } + frags[nFrags].init(line, 0, line->len); + frags[nFrags].computeCoords(gTrue); + ++nFrags; + } + } + qsort(frags, nFrags, sizeof(TextLineFrag), &TextLineFrag::cmpYXPrimaryRot); + i = 0; + while (i < nFrags) { + delta = maxIntraLineDelta * frags[i].line->words->fontSize; + for (j = i+1; + j < nFrags && fabs(frags[j].base - frags[i].base) < delta; + ++j) ; + qsort(frags + i, j - i, sizeof(TextLineFrag), + &TextLineFrag::cmpXYColumnPrimaryRot); + i = j; + } + +#if 0 // for debugging + printf("*** line fragments ***\n"); + for (i = 0; i < nFrags; ++i) { + frag = &frags[i]; + printf("frag: x=%.2f..%.2f y=%.2f..%.2f base=%.2f '", + frag->xMin, frag->xMax, frag->yMin, frag->yMax, frag->base); + for (n = 0; n < frag->len; ++n) { + fputc(frag->line->text[frag->start + n] & 0xff, stdout); + } + printf("'\n"); + } + printf("\n"); +#endif + + // generate output + col = 0; + for (i = 0; i < nFrags; ++i) { + frag = &frags[i]; + + // column alignment + for (; col < frag->col; ++col) { + (*outputFunc)(outputStream, space, spaceLen); + } + + // print the line + s = new GString(); + col += dumpFragment(frag->line->text + frag->start, frag->len, uMap, s); + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + delete s; + + // print one or more returns if necessary + if (i == nFrags - 1 || + frags[i+1].col < col || + fabs(frags[i+1].base - frag->base) > + maxIntraLineDelta * frag->line->words->fontSize) { + if (i < nFrags - 1) { + d = (int)((frags[i+1].base - frag->base) / + frag->line->words->fontSize); + if (d < 1) { + d = 1; + } else if (d > 5) { + d = 5; + } + } else { + d = 1; + } + for (; d > 0; --d) { + (*outputFunc)(outputStream, eol, eolLen); + } + col = 0; + } + } + + gfree(frags); + + // output the page, "undoing" the layout + } else { + for (flow = flows; flow; flow = flow->next) { + for (blk = flow->blocks; blk; blk = blk->next) { + for (line = blk->lines; line; line = line->next) { + n = line->len; + if (line->hyphenated && (line->next || blk->next)) { + --n; + } + s = new GString(); + dumpFragment(line->text, n, uMap, s); + (*outputFunc)(outputStream, s->getCString(), s->getLength()); + delete s; + if (!line->hyphenated) { + if (line->next) { + (*outputFunc)(outputStream, space, spaceLen); + } else if (blk->next) { + //~ this is a bit of a kludge - we should really do a more + //~ intelligent determination of paragraphs + if (blk->next->lines->words->fontSize == + blk->lines->words->fontSize) { + (*outputFunc)(outputStream, space, spaceLen); + } else { + (*outputFunc)(outputStream, eol, eolLen); + } + } + } + } + } + (*outputFunc)(outputStream, eol, eolLen); + (*outputFunc)(outputStream, eol, eolLen); + } + } + + // end of page + if (pageBreaks) { + (*outputFunc)(outputStream, eop, eopLen); + } + + uMap->decRefCnt(); +} + +void TextPage::assignColumns(TextLineFrag *frags, int nFrags, GBool oneRot) { + TextLineFrag *frag0, *frag1; + int rot, col1, col2, i, j, k; + + // all text in the region has the same rotation -- recompute the + // column numbers based only on the text in the region + if (oneRot) { + qsort(frags, nFrags, sizeof(TextLineFrag), &TextLineFrag::cmpXYLineRot); + rot = frags[0].line->rot; + for (i = 0; i < nFrags; ++i) { + frag0 = &frags[i]; + col1 = 0; + for (j = 0; j < i; ++j) { + frag1 = &frags[j]; + col2 = 0; // make gcc happy + switch (rot) { + case 0: + if (frag0->xMin >= frag1->xMax) { + col2 = frag1->col + (frag1->line->col[frag1->start + frag1->len] - + frag1->line->col[frag1->start]) + 1; + } else { + for (k = frag1->start; + k < frag1->start + frag1->len && + frag0->xMin >= 0.5 * (frag1->line->edge[k] + + frag1->line->edge[k+1]); + ++k) ; + col2 = frag1->col + + frag1->line->col[k] - frag1->line->col[frag1->start]; + } + break; + case 1: + if (frag0->yMin >= frag1->yMax) { + col2 = frag1->col + (frag1->line->col[frag1->start + frag1->len] - + frag1->line->col[frag1->start]) + 1; + } else { + for (k = frag1->start; + k < frag1->start + frag1->len && + frag0->yMin >= 0.5 * (frag1->line->edge[k] + + frag1->line->edge[k+1]); + ++k) ; + col2 = frag1->col + + frag1->line->col[k] - frag1->line->col[frag1->start]; + } + break; + case 2: + if (frag0->xMax <= frag1->xMin) { + col2 = frag1->col + (frag1->line->col[frag1->start + frag1->len] - + frag1->line->col[frag1->start]) + 1; + } else { + for (k = frag1->start; + k < frag1->start + frag1->len && + frag0->xMax <= 0.5 * (frag1->line->edge[k] + + frag1->line->edge[k+1]); + ++k) ; + col2 = frag1->col + + frag1->line->col[k] - frag1->line->col[frag1->start]; + } + break; + case 3: + if (frag0->yMax <= frag1->yMin) { + col2 = frag1->col + (frag1->line->col[frag1->start + frag1->len] - + frag1->line->col[frag1->start]) + 1; + } else { + for (k = frag1->start; + k < frag1->start + frag1->len && + frag0->yMax <= 0.5 * (frag1->line->edge[k] + + frag1->line->edge[k+1]); + ++k) ; + col2 = frag1->col + + frag1->line->col[k] - frag1->line->col[frag1->start]; + } + break; + } + if (col2 > col1) { + col1 = col2; + } + } + frag0->col = col1; + } + + // the region includes text at different rotations -- use the + // globally assigned column numbers, offset by the minimum column + // number (i.e., shift everything over to column 0) + } else { + col1 = frags[0].col; + for (i = 1; i < nFrags; ++i) { + if (frags[i].col < col1) { + col1 = frags[i].col; + } + } + for (i = 0; i < nFrags; ++i) { + frags[i].col -= col1; + } + } +} + +int TextPage::dumpFragment(Unicode *text, int len, UnicodeMap *uMap, + GString *s) { + char lre[8], rle[8], popdf[8], buf[8]; + int lreLen, rleLen, popdfLen, n; + int nCols, i, j, k; + + nCols = 0; + + if (uMap->isUnicode()) { + + lreLen = uMap->mapUnicode(0x202a, lre, sizeof(lre)); + rleLen = uMap->mapUnicode(0x202b, rle, sizeof(rle)); + popdfLen = uMap->mapUnicode(0x202c, popdf, sizeof(popdf)); + + if (primaryLR) { + + i = 0; + while (i < len) { + // output a left-to-right section + for (j = i; j < len && !unicodeTypeR(text[j]); ++j) ; + for (k = i; k < j; ++k) { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + s->append(buf, n); + ++nCols; + } + i = j; + // output a right-to-left section + for (j = i; j < len && !unicodeTypeL(text[j]); ++j) ; + if (j > i) { + s->append(rle, rleLen); + for (k = j - 1; k >= i; --k) { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + s->append(buf, n); + ++nCols; + } + s->append(popdf, popdfLen); + i = j; + } + } + + } else { + + s->append(rle, rleLen); + i = len - 1; + while (i >= 0) { + // output a right-to-left section + for (j = i; j >= 0 && !unicodeTypeL(text[j]); --j) ; + for (k = i; k > j; --k) { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + s->append(buf, n); + ++nCols; + } + i = j; + // output a left-to-right section + for (j = i; j >= 0 && !unicodeTypeR(text[j]); --j) ; + if (j < i) { + s->append(lre, lreLen); + for (k = j + 1; k <= i; ++k) { + n = uMap->mapUnicode(text[k], buf, sizeof(buf)); + s->append(buf, n); + ++nCols; + } + s->append(popdf, popdfLen); + i = j; + } + } + s->append(popdf, popdfLen); + + } + + } else { + for (i = 0; i < len; ++i) { + n = uMap->mapUnicode(text[i], buf, sizeof(buf)); + s->append(buf, n); + nCols += n; + } + } + + return nCols; +} + +#if TEXTOUT_WORD_LIST +TextWordList *TextPage::makeWordList(GBool physLayout) { + return new TextWordList(this, physLayout); +} +#endif + +//------------------------------------------------------------------------ +// TextOutputDev +//------------------------------------------------------------------------ + +static void outputToFile(void *stream, char *text, int len) { + fwrite(text, 1, len, (FILE *)stream); +} + +TextOutputDev::TextOutputDev(char *fileName, GBool physLayoutA, + GBool rawOrderA, GBool append) { + text = NULL; + physLayout = physLayoutA; + rawOrder = rawOrderA; + doHTML = gFalse; + ok = gTrue; + + // open file + needClose = gFalse; + if (fileName) { + if (!strcmp(fileName, "-")) { + outputStream = stdout; +#ifdef WIN32 + // keep DOS from munging the end-of-line characters + setmode(fileno(stdout), O_BINARY); +#endif + } else if ((outputStream = fopen(fileName, append ? "ab" : "wb"))) { + needClose = gTrue; + } else { + error(-1, "Couldn't open text file '%s'", fileName); + ok = gFalse; + return; + } + outputFunc = &outputToFile; + } else { + outputStream = NULL; + } + + // set up text object + text = new TextPage(rawOrderA); +} + +TextOutputDev::TextOutputDev(TextOutputFunc func, void *stream, + GBool physLayoutA, GBool rawOrderA) { + outputFunc = func; + outputStream = stream; + needClose = gFalse; + physLayout = physLayoutA; + rawOrder = rawOrderA; + doHTML = gFalse; + text = new TextPage(rawOrderA); + ok = gTrue; +} + +TextOutputDev::~TextOutputDev() { + if (needClose) { +#ifdef MACOS + ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle); +#endif + fclose((FILE *)outputStream); + } + if (text) { + delete text; + } +} + +void TextOutputDev::startPage(int pageNum, GfxState *state) { + text->startPage(state); +} + +void TextOutputDev::endPage() { + text->endPage(); + text->coalesce(physLayout, doHTML); + if (outputStream) { + text->dump(outputStream, outputFunc, physLayout); + } +} + +void TextOutputDev::updateFont(GfxState *state) { + text->updateFont(state); +} + +void TextOutputDev::beginString(GfxState *state, GString *s) { +} + +void TextOutputDev::endString(GfxState *state) { +} + +void TextOutputDev::drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode c, int nBytes, Unicode *u, int uLen) { + text->addChar(state, x, y, dx, dy, c, nBytes, u, uLen); +} + +void TextOutputDev::stroke(GfxState *state) { + GfxPath *path; + GfxSubpath *subpath; + double x[2], y[2]; + + if (!doHTML) { + return; + } + path = state->getPath(); + if (path->getNumSubpaths() != 1) { + return; + } + subpath = path->getSubpath(0); + if (subpath->getNumPoints() != 2) { + return; + } + state->transform(subpath->getX(0), subpath->getY(0), &x[0], &y[0]); + state->transform(subpath->getX(1), subpath->getY(1), &x[1], &y[1]); + + // look for a vertical or horizontal line + if (x[0] == x[1] || y[0] == y[1]) { + text->addUnderline(x[0], y[0], x[1], y[1]); + } +} + +void TextOutputDev::fill(GfxState *state) { + GfxPath *path; + GfxSubpath *subpath; + double x[5], y[5]; + double rx0, ry0, rx1, ry1, t; + int i; + + if (!doHTML) { + return; + } + path = state->getPath(); + if (path->getNumSubpaths() != 1) { + return; + } + subpath = path->getSubpath(0); + if (subpath->getNumPoints() != 5) { + return; + } + for (i = 0; i < 5; ++i) { + if (subpath->getCurve(i)) { + return; + } + state->transform(subpath->getX(i), subpath->getY(i), &x[i], &y[i]); + } + + // look for a rectangle + if (x[0] == x[1] && y[1] == y[2] && x[2] == x[3] && y[3] == y[4] && + x[0] == x[4] && y[0] == y[4]) { + rx0 = x[0]; + ry0 = y[0]; + rx1 = x[2]; + ry1 = y[1]; + } else if (y[0] == y[1] && x[1] == x[2] && y[2] == y[3] && x[3] == x[4] && + x[0] == x[4] && y[0] == y[4]) { + rx0 = x[0]; + ry0 = y[0]; + rx1 = x[1]; + ry1 = y[2]; + } else { + return; + } + if (rx1 < rx0) { + t = rx0; + rx0 = rx1; + rx1 = t; + } + if (ry1 < ry0) { + t = ry0; + ry0 = ry1; + ry1 = t; + } + + // skinny horizontal rectangle + if (ry1 - ry0 < rx1 - rx0) { + if (ry1 - ry0 < maxUnderlineWidth) { + ry0 = 0.5 * (ry0 + ry1); + text->addUnderline(rx0, ry0, rx1, ry0); + } + + // skinny vertical rectangle + } else { + if (rx1 - rx0 < maxUnderlineWidth) { + rx0 = 0.5 * (rx0 + rx1); + text->addUnderline(rx0, ry0, rx0, ry1); + } + } +} + +void TextOutputDev::eoFill(GfxState *state) { + if (!doHTML) { + return; + } + fill(state); +} + +void TextOutputDev::processLink(Link *link, Catalog *catalog) { + double x1, y1, x2, y2; + int xMin, yMin, xMax, yMax, x, y; + + if (!doHTML) { + return; + } + link->getRect(&x1, &y1, &x2, &y2); + cvtUserToDev(x1, y1, &x, &y); + xMin = xMax = x; + yMin = yMax = y; + cvtUserToDev(x1, y2, &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + cvtUserToDev(x2, y1, &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + cvtUserToDev(x2, y2, &x, &y); + if (x < xMin) { + xMin = x; + } else if (x > xMax) { + xMax = x; + } + if (y < yMin) { + yMin = y; + } else if (y > yMax) { + yMax = y; + } + text->addLink(xMin, yMin, xMax, yMax, link); +} + +GBool TextOutputDev::findText(Unicode *s, int len, + GBool startAtTop, GBool stopAtBottom, + GBool startAtLast, GBool stopAtLast, + GBool caseSensitive, GBool backward, + double *xMin, double *yMin, + double *xMax, double *yMax) { + return text->findText(s, len, startAtTop, stopAtBottom, + startAtLast, stopAtLast, caseSensitive, backward, + xMin, yMin, xMax, yMax); +} + +GString *TextOutputDev::getText(double xMin, double yMin, + double xMax, double yMax) { + return text->getText(xMin, yMin, xMax, yMax); +} + +GBool TextOutputDev::findCharRange(int pos, int length, + double *xMin, double *yMin, + double *xMax, double *yMax) { + return text->findCharRange(pos, length, xMin, yMin, xMax, yMax); +} + +#if TEXTOUT_WORD_LIST +TextWordList *TextOutputDev::makeWordList() { + return text->makeWordList(physLayout); +} +#endif + +TextPage *TextOutputDev::takeText() { + TextPage *ret; + + ret = text; + text = new TextPage(rawOrder); + return ret; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/TextOutputDev.h swftools-0.9.1/lib/pdf/xpdf/TextOutputDev.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/TextOutputDev.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/TextOutputDev.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,662 @@ +//======================================================================== +// +// TextOutputDev.h +// +// Copyright 1997-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef TEXTOUTPUTDEV_H +#define TEXTOUTPUTDEV_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include +#include "gtypes.h" +#include "GfxFont.h" +#include "OutputDev.h" + +class GString; +class GList; +class GfxFont; +class GfxState; +class UnicodeMap; +class Link; + +class TextWord; +class TextPool; +class TextLine; +class TextLineFrag; +class TextBlock; +class TextFlow; +class TextWordList; +class TextPage; + +//------------------------------------------------------------------------ + +typedef void (*TextOutputFunc)(void *stream, char *text, int len); + +//------------------------------------------------------------------------ +// TextFontInfo +//------------------------------------------------------------------------ + +class TextFontInfo { +public: + + TextFontInfo(GfxState *state); + ~TextFontInfo(); + + GBool matches(GfxState *state); + +#if TEXTOUT_WORD_LIST + // Get the font name (which may be NULL). + GString *getFontName() { return fontName; } + + // Get font descriptor flags. + GBool isFixedWidth() { return flags & fontFixedWidth; } + GBool isSerif() { return flags & fontSerif; } + GBool isSymbolic() { return flags & fontSymbolic; } + GBool isItalic() { return flags & fontItalic; } + GBool isBold() { return flags & fontBold; } +#endif + +private: + + GfxFont *gfxFont; +#if TEXTOUT_WORD_LIST + GString *fontName; + int flags; +#endif + + friend class TextWord; + friend class TextPage; +}; + +//------------------------------------------------------------------------ +// TextWord +//------------------------------------------------------------------------ + +class TextWord { +public: + + // Constructor. + TextWord(GfxState *state, int rotA, double x0, double y0, + int charPosA, TextFontInfo *fontA, double fontSize); + + // Destructor. + ~TextWord(); + + // Add a character to the word. + void addChar(GfxState *state, double x, double y, + double dx, double dy, Unicode u); + + // Merge onto the end of . + void merge(TextWord *word); + + // Compares to , returning -1 (<), 0 (=), or +1 (>), + // based on a primary-axis comparison, e.g., x ordering if rot=0. + int primaryCmp(TextWord *word); + + // Return the distance along the primary axis between and + // . + double primaryDelta(TextWord *word); + + static int cmpYX(const void *p1, const void *p2); + + // Get the TextFontInfo object associated with this word. + TextFontInfo *getFontInfo() { return font; } + + // Get the next TextWord on the linked list. + TextWord *getNext() { return next; } + +#if TEXTOUT_WORD_LIST + int getLength() { return len; } + Unicode getChar(int idx) { return text[idx]; } + GString *getText(); + GString *getFontName() { return font->fontName; } + void getColor(double *r, double *g, double *b) + { *r = colorR; *g = colorG; *b = colorB; } + void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA) + { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; } + void getCharBBox(int charIdx, double *xMinA, double *yMinA, + double *xMaxA, double *yMaxA); + double getFontSize() { return fontSize; } + int getRotation() { return rot; } + int getCharPos() { return charPos; } + int getCharLen() { return charLen; } + GBool getSpaceAfter() { return spaceAfter; } +#endif + + GBool isUnderlined() { return underlined; } + Link *getLink() { return link; } + +private: + + int rot; // rotation, multiple of 90 degrees + // (0, 1, 2, or 3) + double xMin, xMax; // bounding box x coordinates + double yMin, yMax; // bounding box y coordinates + double base; // baseline x or y coordinate + Unicode *text; // the text + double *edge; // "near" edge x or y coord of each char + // (plus one extra entry for the last char) + int len; // length of text and edge arrays + int size; // size of text and edge arrays + int charPos; // character position (within content stream) + int charLen; // number of content stream characters in + // this word + TextFontInfo *font; // font information + double fontSize; // font size + GBool spaceAfter; // set if there is a space between this + // word and the next word on the line + TextWord *next; // next word in line + +#if TEXTOUT_WORD_LIST + double colorR, // word color + colorG, + colorB; +#endif + + GBool underlined; + Link *link; + + friend class TextPool; + friend class TextLine; + friend class TextBlock; + friend class TextFlow; + friend class TextWordList; + friend class TextPage; + friend class XMLOutputDev; +}; + +//------------------------------------------------------------------------ +// TextPool +//------------------------------------------------------------------------ + +class TextPool { +public: + + TextPool(); + ~TextPool(); + + TextWord *getPool(int baseIdx) { return pool[baseIdx - minBaseIdx]; } + void setPool(int baseIdx, TextWord *p) { pool[baseIdx - minBaseIdx] = p; } + + int getBaseIdx(double base); + + void addWord(TextWord *word); + +private: + + int minBaseIdx; // min baseline bucket index + int maxBaseIdx; // max baseline bucket index + TextWord **pool; // array of linked lists, one for each + // baseline value (multiple of 4 pts) + TextWord *cursor; // pointer to last-accessed word + int cursorBaseIdx; // baseline bucket index of last-accessed word + + friend class TextBlock; + friend class TextPage; +}; + +//------------------------------------------------------------------------ +// TextLine +//------------------------------------------------------------------------ + +class TextLine { +public: + + TextLine(TextBlock *blkA, int rotA, double baseA); + ~TextLine(); + + void addWord(TextWord *word); + + // Return the distance along the primary axis between and + // . + double primaryDelta(TextLine *line); + + // Compares to , returning -1 (<), 0 (=), or +1 (>), + // based on a primary-axis comparison, e.g., x ordering if rot=0. + int primaryCmp(TextLine *line); + + // Compares to , returning -1 (<), 0 (=), or +1 (>), + // based on a secondary-axis comparison of the baselines, e.g., y + // ordering if rot=0. + int secondaryCmp(TextLine *line); + + int cmpYX(TextLine *line); + + static int cmpXY(const void *p1, const void *p2); + + void coalesce(UnicodeMap *uMap); + + // Get the head of the linked list of TextWords. + TextWord *getWords() { return words; } + + // Get the next TextLine on the linked list. + TextLine *getNext() { return next; } + + // Returns true if the last char of the line is a hyphen. + GBool isHyphenated() { return hyphenated; } + +private: + + TextBlock *blk; // parent block + int rot; // text rotation + double xMin, xMax; // bounding box x coordinates + double yMin, yMax; // bounding box y coordinates + double base; // baseline x or y coordinate + TextWord *words; // words in this line + TextWord *lastWord; // last word in this line + Unicode *text; // Unicode text of the line, including + // spaces between words + double *edge; // "near" edge x or y coord of each char + // (plus one extra entry for the last char) + int *col; // starting column number of each Unicode char + int len; // number of Unicode chars + int convertedLen; // total number of converted characters + GBool hyphenated; // set if last char is a hyphen + TextLine *next; // next line in block + + friend class TextLineFrag; + friend class TextBlock; + friend class TextFlow; + friend class TextWordList; + friend class TextPage; +}; + +//------------------------------------------------------------------------ +// TextBlock +//------------------------------------------------------------------------ + +class TextBlock { +public: + + TextBlock(TextPage *pageA, int rotA); + ~TextBlock(); + + void addWord(TextWord *word); + + void coalesce(UnicodeMap *uMap); + + // Update this block's priMin and priMax values, looking at . + void updatePriMinMax(TextBlock *blk); + + static int cmpXYPrimaryRot(const void *p1, const void *p2); + + static int cmpYXPrimaryRot(const void *p1, const void *p2); + + int primaryCmp(TextBlock *blk); + + double secondaryDelta(TextBlock *blk); + + // Returns true if is below , relative to the page's + // primary rotation. + GBool isBelow(TextBlock *blk); + + // Get the head of the linked list of TextLines. + TextLine *getLines() { return lines; } + + // Get the next TextBlock on the linked list. + TextBlock *getNext() { return next; } + +private: + + TextPage *page; // the parent page + int rot; // text rotation + double xMin, xMax; // bounding box x coordinates + double yMin, yMax; // bounding box y coordinates + double priMin, priMax; // whitespace bounding box along primary axis + + TextPool *pool; // pool of words (used only until lines + // are built) + TextLine *lines; // linked list of lines + TextLine *curLine; // most recently added line + int nLines; // number of lines + int charCount; // number of characters in the block + int col; // starting column + int nColumns; // number of columns in the block + + TextBlock *next; + TextBlock *stackNext; + + friend class TextLine; + friend class TextLineFrag; + friend class TextFlow; + friend class TextWordList; + friend class TextPage; +}; + +//------------------------------------------------------------------------ +// TextFlow +//------------------------------------------------------------------------ + +class TextFlow { +public: + + TextFlow(TextPage *pageA, TextBlock *blk); + ~TextFlow(); + + // Add a block to the end of this flow. + void addBlock(TextBlock *blk); + + // Returns true if fits below in the flow, i.e., (1) + // it uses a font no larger than the last block added to the flow, + // and (2) it fits within the flow's [priMin, priMax] along the + // primary axis. + GBool blockFits(TextBlock *blk, TextBlock *prevBlk); + + // Get the head of the linked list of TextBlocks. + TextBlock *getBlocks() { return blocks; } + + // Get the next TextFlow on the linked list. + TextFlow *getNext() { return next; } + +private: + + TextPage *page; // the parent page + double xMin, xMax; // bounding box x coordinates + double yMin, yMax; // bounding box y coordinates + double priMin, priMax; // whitespace bounding box along primary axis + TextBlock *blocks; // blocks in flow + TextBlock *lastBlk; // last block in this flow + TextFlow *next; + + friend class TextWordList; + friend class TextPage; +}; + +#if TEXTOUT_WORD_LIST + +//------------------------------------------------------------------------ +// TextWordList +//------------------------------------------------------------------------ + +class TextWordList { +public: + + // Build a flat word list, in content stream order (if + // text->rawOrder is true), physical layout order (if + // is true and text->rawOrder is false), or reading order (if both + // flags are false). + TextWordList(TextPage *text, GBool physLayout); + + ~TextWordList(); + + // Return the number of words on the list. + int getLength(); + + // Return the th word from the list. + TextWord *get(int idx); + +private: + + GList *words; // [TextWord] +}; + +#endif // TEXTOUT_WORD_LIST + +//------------------------------------------------------------------------ +// TextPage +//------------------------------------------------------------------------ + +class TextPage { +public: + + // Constructor. + TextPage(GBool rawOrderA); + + // Destructor. + ~TextPage(); + + // Start a new page. + void startPage(GfxState *state); + + // End the current page. + void endPage(); + + // Update the current font. + void updateFont(GfxState *state); + + // Begin a new word. + void beginWord(GfxState *state, double x0, double y0); + + // Add a character to the current word. + void addChar(GfxState *state, double x, double y, + double dx, double dy, + CharCode c, int nBytes, Unicode *u, int uLen); + + // End the current word, sorting it into the list of words. + void endWord(); + + // Add a word, sorting it into the list of words. + void addWord(TextWord *word); + + // Add a (potential) underline. + void addUnderline(double x0, double y0, double x1, double y1); + + // Add a hyperlink. + void addLink(int xMin, int yMin, int xMax, int yMax, Link *link); + + // Coalesce strings that look like parts of the same line. + void coalesce(GBool physLayout, GBool doHTML); + + // Find a string. If is true, starts looking at the + // top of the page; else if is true, starts looking + // immediately after the last find result; else starts looking at + // ,. If is true, stops looking at the + // bottom of the page; else if is true, stops looking + // just before the last find result; else stops looking at + // ,. + GBool findText(Unicode *s, int len, + GBool startAtTop, GBool stopAtBottom, + GBool startAtLast, GBool stopAtLast, + GBool caseSensitive, GBool backward, + double *xMin, double *yMin, + double *xMax, double *yMax); + + // Get the text which is inside the specified rectangle. + GString *getText(double xMin, double yMin, + double xMax, double yMax); + + // Find a string by character position and length. If found, sets + // the text bounding rectangle and returns true; otherwise returns + // false. + GBool findCharRange(int pos, int length, + double *xMin, double *yMin, + double *xMax, double *yMax); + + // Dump contents of page to a file. + void dump(void *outputStream, TextOutputFunc outputFunc, + GBool physLayout); + + // Get the head of the linked list of TextFlows. + TextFlow *getFlows() { return flows; } + +#if TEXTOUT_WORD_LIST + // Build a flat word list, in content stream order (if + // this->rawOrder is true), physical layout order (if + // is true and this->rawOrder is false), or reading order (if both + // flags are false). + TextWordList *makeWordList(GBool physLayout); +#endif + +private: + + void clear(); + void assignColumns(TextLineFrag *frags, int nFrags, int rot); + int dumpFragment(Unicode *text, int len, UnicodeMap *uMap, GString *s); + + GBool rawOrder; // keep text in content stream order + + double pageWidth, pageHeight; // width and height of current page + TextWord *curWord; // currently active string + int charPos; // next character position (within content + // stream) + TextFontInfo *curFont; // current font + double curFontSize; // current font size + int nest; // current nesting level (for Type 3 fonts) + int nTinyChars; // number of "tiny" chars seen so far + GBool lastCharOverlap; // set if the last added char overlapped the + // previous char + + TextPool *pools[4]; // a "pool" of TextWords for each rotation + TextFlow *flows; // linked list of flows + TextBlock **blocks; // array of blocks, in yx order + int nBlocks; // number of blocks + int primaryRot; // primary rotation + GBool primaryLR; // primary direction (true means L-to-R, + // false means R-to-L) + TextWord *rawWords; // list of words, in raw order (only if + // rawOrder is set) + TextWord *rawLastWord; // last word on rawWords list + + GList *fonts; // all font info objects used on this + // page [TextFontInfo] + + double lastFindXMin, // coordinates of the last "find" result + lastFindYMin; + GBool haveLastFind; + + GList *underlines; // [TextUnderline] + GList *links; // [TextLink] + + friend class TextLine; + friend class TextLineFrag; + friend class TextBlock; + friend class TextFlow; + friend class TextWordList; +}; + +//------------------------------------------------------------------------ +// TextOutputDev +//------------------------------------------------------------------------ + +class TextOutputDev: public OutputDev { +public: + + // Open a text output file. If is NULL, no file is + // written (this is useful, e.g., for searching text). If + // is true, the original physical layout of the text + // is maintained. If is true, the text is kept in + // content stream order. + TextOutputDev(char *fileName, GBool physLayoutA, + GBool rawOrderA, GBool append); + + // Create a TextOutputDev which will write to a generic stream. If + // is true, the original physical layout of the text + // is maintained. If is true, the text is kept in + // content stream order. + TextOutputDev(TextOutputFunc func, void *stream, + GBool physLayoutA, GBool rawOrderA); + + // Destructor. + virtual ~TextOutputDev(); + + // Check if file was successfully created. + virtual GBool isOk() { return ok; } + + //---- get info about output device + + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() { return gTrue; } + + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() { return gTrue; } + + // Does this device use beginType3Char/endType3Char? Otherwise, + // text in Type 3 fonts will be drawn with drawChar/drawString. + virtual GBool interpretType3Chars() { return gFalse; } + + // Does this device need non-text content? + virtual GBool needNonText() { return gFalse; } + + //----- initialization and control + + // Start a page. + virtual void startPage(int pageNum, GfxState *state); + + // End a page. + virtual void endPage(); + + //----- update text state + virtual void updateFont(GfxState *state); + + //----- text drawing + virtual void beginString(GfxState *state, GString *s); + virtual void endString(GfxState *state); + virtual void drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode c, int nBytes, Unicode *u, int uLen); + + //----- path painting + virtual void stroke(GfxState *state); + virtual void fill(GfxState *state); + virtual void eoFill(GfxState *state); + + //----- link borders + virtual void processLink(Link *link, Catalog *catalog); + + //----- special access + + // Find a string. If is true, starts looking at the + // top of the page; else if is true, starts looking + // immediately after the last find result; else starts looking at + // ,. If is true, stops looking at the + // bottom of the page; else if is true, stops looking + // just before the last find result; else stops looking at + // ,. + GBool findText(Unicode *s, int len, + GBool startAtTop, GBool stopAtBottom, + GBool startAtLast, GBool stopAtLast, + GBool caseSensitive, GBool backward, + double *xMin, double *yMin, + double *xMax, double *yMax); + + // Get the text which is inside the specified rectangle. + GString *getText(double xMin, double yMin, + double xMax, double yMax); + + // Find a string by character position and length. If found, sets + // the text bounding rectangle and returns true; otherwise returns + // false. + GBool findCharRange(int pos, int length, + double *xMin, double *yMin, + double *xMax, double *yMax); + +#if TEXTOUT_WORD_LIST + // Build a flat word list, in content stream order (if + // this->rawOrder is true), physical layout order (if + // this->physLayout is true and this->rawOrder is false), or reading + // order (if both flags are false). + TextWordList *makeWordList(); +#endif + + // Returns the TextPage object for the last rasterized page, + // transferring ownership to the caller. + TextPage *takeText(); + + // Turn extra processing for HTML conversion on or off. + void enableHTMLExtras(GBool doHTMLA) { doHTML = doHTMLA; } + +private: + + TextOutputFunc outputFunc; // output function + void *outputStream; // output stream + GBool needClose; // need to close the output file? + // (only if outputStream is a FILE*) + TextPage *text; // text for the current page + GBool physLayout; // maintain original physical layout when + // dumping text + GBool rawOrder; // keep text in content stream order + GBool doHTML; // extra processing for HTML conversion + GBool ok; // set up ok? +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/UnicodeMap.cc swftools-0.9.1/lib/pdf/xpdf/UnicodeMap.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/UnicodeMap.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/UnicodeMap.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,293 @@ +//======================================================================== +// +// UnicodeMap.cc +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include "gmem.h" +#include "gfile.h" +#include "GString.h" +#include "GList.h" +#include "Error.h" +#include "GlobalParams.h" +#include "UnicodeMap.h" + +//------------------------------------------------------------------------ + +#define maxExtCode 16 + +struct UnicodeMapExt { + Unicode u; // Unicode char + char code[maxExtCode]; + Guint nBytes; +}; + +//------------------------------------------------------------------------ + +UnicodeMap *UnicodeMap::parse(GString *encodingNameA) { + FILE *f; + UnicodeMap *map; + UnicodeMapRange *range; + UnicodeMapExt *eMap; + int size, eMapsSize; + char buf[256]; + int line, nBytes, i, x; + char *tok1, *tok2, *tok3; + + if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) { + error(-1, "Couldn't find unicodeMap file for the '%s' encoding", + encodingNameA->getCString()); + return NULL; + } + + map = new UnicodeMap(encodingNameA->copy()); + + size = 8; + map->ranges = (UnicodeMapRange *)gmallocn(size, sizeof(UnicodeMapRange)); + eMapsSize = 0; + + line = 1; + while (getLine(buf, sizeof(buf), f)) { + if ((tok1 = strtok(buf, " \t\r\n")) && + (tok2 = strtok(NULL, " \t\r\n"))) { + if (!(tok3 = strtok(NULL, " \t\r\n"))) { + tok3 = tok2; + tok2 = tok1; + } + nBytes = strlen(tok3) / 2; + if (nBytes <= 4) { + if (map->len == size) { + size *= 2; + map->ranges = (UnicodeMapRange *) + greallocn(map->ranges, size, sizeof(UnicodeMapRange)); + } + range = &map->ranges[map->len]; + sscanf(tok1, "%x", &range->start); + sscanf(tok2, "%x", &range->end); + sscanf(tok3, "%x", &range->code); + range->nBytes = nBytes; + ++map->len; + } else if (tok2 == tok1) { + if (map->eMapsLen == eMapsSize) { + eMapsSize += 16; + map->eMaps = (UnicodeMapExt *) + greallocn(map->eMaps, eMapsSize, sizeof(UnicodeMapExt)); + } + eMap = &map->eMaps[map->eMapsLen]; + sscanf(tok1, "%x", &eMap->u); + for (i = 0; i < nBytes; ++i) { + sscanf(tok3 + i*2, "%2x", &x); + eMap->code[i] = (char)x; + } + eMap->nBytes = nBytes; + ++map->eMapsLen; + } else { + error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding", + line, encodingNameA->getCString()); + } + } else { + error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding", + line, encodingNameA->getCString()); + } + ++line; + } + + fclose(f); + + return map; +} + +UnicodeMap::UnicodeMap(GString *encodingNameA) { + encodingName = encodingNameA; + unicodeOut = gFalse; + kind = unicodeMapUser; + ranges = NULL; + len = 0; + eMaps = NULL; + eMapsLen = 0; + refCnt = 1; +#if MULTITHREADED + gInitMutex(&mutex); +#endif +} + +UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA, + UnicodeMapRange *rangesA, int lenA) { + encodingName = new GString(encodingNameA); + unicodeOut = unicodeOutA; + kind = unicodeMapResident; + ranges = rangesA; + len = lenA; + eMaps = NULL; + eMapsLen = 0; + refCnt = 1; +#if MULTITHREADED + gInitMutex(&mutex); +#endif +} + +UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA, + UnicodeMapFunc funcA) { + encodingName = new GString(encodingNameA); + unicodeOut = unicodeOutA; + kind = unicodeMapFunc; + func = funcA; + eMaps = NULL; + eMapsLen = 0; + refCnt = 1; +#if MULTITHREADED + gInitMutex(&mutex); +#endif +} + +UnicodeMap::~UnicodeMap() { + delete encodingName; + if (kind == unicodeMapUser && ranges) { + gfree(ranges); + } + if (eMaps) { + gfree(eMaps); + } +#if MULTITHREADED + gDestroyMutex(&mutex); +#endif +} + +void UnicodeMap::incRefCnt() { +#if MULTITHREADED + gLockMutex(&mutex); +#endif + ++refCnt; +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif +} + +void UnicodeMap::decRefCnt() { + GBool done; + +#if MULTITHREADED + gLockMutex(&mutex); +#endif + done = --refCnt == 0; +#if MULTITHREADED + gUnlockMutex(&mutex); +#endif + if (done) { + delete this; + } +} + +GBool UnicodeMap::match(GString *encodingNameA) { + return !encodingName->cmp(encodingNameA); +} + +int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) { + int a, b, m, n, i, j; + Guint code; + + if (kind == unicodeMapFunc) { + return (*func)(u, buf, bufSize); + } + + a = 0; + b = len; + if (u >= ranges[a].start) { + // invariant: ranges[a].start <= u < ranges[b].start + while (b - a > 1) { + m = (a + b) / 2; + if (u >= ranges[m].start) { + a = m; + } else if (u < ranges[m].start) { + b = m; + } + } + if (u <= ranges[a].end) { + n = ranges[a].nBytes; + if (n > bufSize) { + return 0; + } + code = ranges[a].code + (u - ranges[a].start); + for (i = n - 1; i >= 0; --i) { + buf[i] = (char)(code & 0xff); + code >>= 8; + } + return n; + } + } + + for (i = 0; i < eMapsLen; ++i) { + if (eMaps[i].u == u) { + n = eMaps[i].nBytes; + for (j = 0; j < n; ++j) { + buf[j] = eMaps[i].code[j]; + } + return n; + } + } + + return 0; +} + +//------------------------------------------------------------------------ + +UnicodeMapCache::UnicodeMapCache() { + int i; + + for (i = 0; i < unicodeMapCacheSize; ++i) { + cache[i] = NULL; + } +} + +UnicodeMapCache::~UnicodeMapCache() { + int i; + + for (i = 0; i < unicodeMapCacheSize; ++i) { + if (cache[i]) { + cache[i]->decRefCnt(); + } + } +} + +UnicodeMap *UnicodeMapCache::getUnicodeMap(GString *encodingName) { + UnicodeMap *map; + int i, j; + + if (cache[0] && cache[0]->match(encodingName)) { + cache[0]->incRefCnt(); + return cache[0]; + } + for (i = 1; i < unicodeMapCacheSize; ++i) { + if (cache[i] && cache[i]->match(encodingName)) { + map = cache[i]; + for (j = i; j >= 1; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = map; + map->incRefCnt(); + return map; + } + } + if ((map = UnicodeMap::parse(encodingName))) { + if (cache[unicodeMapCacheSize - 1]) { + cache[unicodeMapCacheSize - 1]->decRefCnt(); + } + for (j = unicodeMapCacheSize - 1; j >= 1; --j) { + cache[j] = cache[j - 1]; + } + cache[0] = map; + map->incRefCnt(); + return map; + } + return NULL; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/UnicodeMap.h swftools-0.9.1/lib/pdf/xpdf/UnicodeMap.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/UnicodeMap.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/UnicodeMap.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,123 @@ +//======================================================================== +// +// UnicodeMap.h +// +// Mapping from Unicode to an encoding. +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef UNICODEMAP_H +#define UNICODEMAP_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "CharTypes.h" + +#if MULTITHREADED +#include "GMutex.h" +#endif + +class GString; + +//------------------------------------------------------------------------ + +enum UnicodeMapKind { + unicodeMapUser, // read from a file + unicodeMapResident, // static list of ranges + unicodeMapFunc // function pointer +}; + +typedef int (*UnicodeMapFunc)(Unicode u, char *buf, int bufSize); + +struct UnicodeMapRange { + Unicode start, end; // range of Unicode chars + Guint code, nBytes; // first output code +}; + +struct UnicodeMapExt; + +//------------------------------------------------------------------------ + +class UnicodeMap { +public: + + // Create the UnicodeMap specified by . Sets the + // initial reference count to 1. Returns NULL on failure. + static UnicodeMap *parse(GString *encodingNameA); + + // Create a resident UnicodeMap. + UnicodeMap(char *encodingNameA, GBool unicodeOutA, + UnicodeMapRange *rangesA, int lenA); + + // Create a resident UnicodeMap that uses a function instead of a + // list of ranges. + UnicodeMap(char *encodingNameA, GBool unicodeOutA, + UnicodeMapFunc funcA); + + ~UnicodeMap(); + + void incRefCnt(); + void decRefCnt(); + + GString *getEncodingName() { return encodingName; } + + GBool isUnicode() { return unicodeOut; } + + // Return true if this UnicodeMap matches the specified + // . + GBool match(GString *encodingNameA); + + // Map Unicode to the target encoding. Fills in with the + // output and returns the number of bytes used. Output will be + // truncated at bytes. No string terminator is written. + // Returns 0 if no mapping is found. + int mapUnicode(Unicode u, char *buf, int bufSize); + +private: + + UnicodeMap(GString *encodingNameA); + + GString *encodingName; + UnicodeMapKind kind; + GBool unicodeOut; + union { + UnicodeMapRange *ranges; // (user, resident) + UnicodeMapFunc func; // (func) + }; + int len; // (user, resident) + UnicodeMapExt *eMaps; // (user) + int eMapsLen; // (user) + int refCnt; +#if MULTITHREADED + GMutex mutex; +#endif +}; + +//------------------------------------------------------------------------ + +#define unicodeMapCacheSize 4 + +class UnicodeMapCache { +public: + + UnicodeMapCache(); + ~UnicodeMapCache(); + + // Get the UnicodeMap for . Increments its reference + // count; there will be one reference for the cache plus one for the + // caller of this function. Returns NULL on failure. + UnicodeMap *getUnicodeMap(GString *encodingName); + +private: + + UnicodeMap *cache[unicodeMapCacheSize]; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/UnicodeMapTables.h swftools-0.9.1/lib/pdf/xpdf/UnicodeMapTables.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/UnicodeMapTables.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/UnicodeMapTables.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,361 @@ +//======================================================================== +// +// UnicodeMapTables.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +static UnicodeMapRange latin1UnicodeMapRanges[] = { + { 0x000a, 0x000a, 0x0a, 1 }, + { 0x000c, 0x000d, 0x0c, 1 }, + { 0x0020, 0x007e, 0x20, 1 }, + { 0x00a0, 0x00a0, 0x20, 1 }, + { 0x00a1, 0x00ac, 0xa1, 1 }, + { 0x00ae, 0x00ff, 0xae, 1 }, + { 0x010c, 0x010c, 0x43, 1 }, + { 0x010d, 0x010d, 0x63, 1 }, + { 0x0131, 0x0131, 0x69, 1 }, + { 0x0141, 0x0141, 0x4c, 1 }, + { 0x0142, 0x0142, 0x6c, 1 }, + { 0x0152, 0x0152, 0x4f45, 2 }, + { 0x0153, 0x0153, 0x6f65, 2 }, + { 0x0160, 0x0160, 0x53, 1 }, + { 0x0161, 0x0161, 0x73, 1 }, + { 0x0178, 0x0178, 0x59, 1 }, + { 0x017d, 0x017d, 0x5a, 1 }, + { 0x017e, 0x017e, 0x7a, 1 }, + { 0x02c6, 0x02c6, 0x5e, 1 }, + { 0x02da, 0x02da, 0xb0, 1 }, + { 0x02dc, 0x02dc, 0x7e, 1 }, + { 0x2013, 0x2013, 0xad, 1 }, + { 0x2014, 0x2014, 0x2d2d, 2 }, + { 0x2018, 0x2018, 0x60, 1 }, + { 0x2019, 0x2019, 0x27, 1 }, + { 0x201a, 0x201a, 0x2c, 1 }, + { 0x201c, 0x201c, 0x22, 1 }, + { 0x201d, 0x201d, 0x22, 1 }, + { 0x201e, 0x201e, 0x2c2c, 2 }, + { 0x2022, 0x2022, 0xb7, 1 }, + { 0x2026, 0x2026, 0x2e2e2e, 3 }, + { 0x2039, 0x2039, 0x3c, 1 }, + { 0x203a, 0x203a, 0x3e, 1 }, + { 0x2044, 0x2044, 0x2f, 1 }, + { 0x2122, 0x2122, 0x544d, 2 }, + { 0x2212, 0x2212, 0x2d, 1 }, + { 0xf6f9, 0xf6f9, 0x4c, 1 }, + { 0xf6fa, 0xf6fa, 0x4f45, 2 }, + { 0xf6fc, 0xf6fc, 0xb0, 1 }, + { 0xf6fd, 0xf6fd, 0x53, 1 }, + { 0xf6fe, 0xf6fe, 0x7e, 1 }, + { 0xf6ff, 0xf6ff, 0x5a, 1 }, + { 0xf721, 0xf721, 0x21, 1 }, + { 0xf724, 0xf724, 0x24, 1 }, + { 0xf726, 0xf726, 0x26, 1 }, + { 0xf730, 0xf739, 0x30, 1 }, + { 0xf73f, 0xf73f, 0x3f, 1 }, + { 0xf761, 0xf77a, 0x41, 1 }, + { 0xf7a1, 0xf7a2, 0xa1, 1 }, + { 0xf7bf, 0xf7bf, 0xbf, 1 }, + { 0xf7e0, 0xf7f6, 0xc0, 1 }, + { 0xf7f8, 0xf7fe, 0xd8, 1 }, + { 0xf7ff, 0xf7ff, 0x59, 1 }, + { 0xfb00, 0xfb00, 0x6666, 2 }, + { 0xfb01, 0xfb01, 0x6669, 2 }, + { 0xfb02, 0xfb02, 0x666c, 2 }, + { 0xfb03, 0xfb03, 0x666669, 3 }, + { 0xfb04, 0xfb04, 0x66666c, 3 } +}; +#define latin1UnicodeMapLen (sizeof(latin1UnicodeMapRanges) / sizeof(UnicodeMapRange)) + +static UnicodeMapRange ascii7UnicodeMapRanges[] = { + { 0x000a, 0x000a, 0x0a, 1 }, + { 0x000c, 0x000d, 0x0c, 1 }, + { 0x0020, 0x005f, 0x20, 1 }, + { 0x0061, 0x007e, 0x61, 1 }, + { 0x00a6, 0x00a6, 0x7c, 1 }, + { 0x00a9, 0x00a9, 0x286329, 3 }, + { 0x00ae, 0x00ae, 0x285229, 3 }, + { 0x00b7, 0x00b7, 0x2a, 1 }, + { 0x00bc, 0x00bc, 0x312f34, 3 }, + { 0x00bd, 0x00bd, 0x312f32, 3 }, + { 0x00be, 0x00be, 0x332f34, 3 }, + { 0x00c0, 0x00c0, 0x41, 1 }, + { 0x00c1, 0x00c1, 0x41, 1 }, + { 0x00c2, 0x00c2, 0x41, 1 }, + { 0x00c3, 0x00c3, 0x41, 1 }, + { 0x00c4, 0x00c4, 0x41, 1 }, + { 0x00c5, 0x00c5, 0x41, 1 }, + { 0x00c6, 0x00c6, 0x4145, 2 }, + { 0x00c7, 0x00c7, 0x43, 1 }, + { 0x00c8, 0x00c8, 0x45, 1 }, + { 0x00c9, 0x00c9, 0x45, 1 }, + { 0x00ca, 0x00ca, 0x45, 1 }, + { 0x00cb, 0x00cb, 0x45, 1 }, + { 0x00cc, 0x00cc, 0x49, 1 }, + { 0x00cd, 0x00cd, 0x49, 1 }, + { 0x00ce, 0x00ce, 0x49, 1 }, + { 0x00cf, 0x00cf, 0x49, 1 }, + { 0x00d1, 0x00d2, 0x4e, 1 }, + { 0x00d3, 0x00d3, 0x4f, 1 }, + { 0x00d4, 0x00d4, 0x4f, 1 }, + { 0x00d5, 0x00d5, 0x4f, 1 }, + { 0x00d6, 0x00d6, 0x4f, 1 }, + { 0x00d7, 0x00d7, 0x78, 1 }, + { 0x00d8, 0x00d8, 0x4f, 1 }, + { 0x00d9, 0x00d9, 0x55, 1 }, + { 0x00da, 0x00da, 0x55, 1 }, + { 0x00db, 0x00db, 0x55, 1 }, + { 0x00dc, 0x00dc, 0x55, 1 }, + { 0x00dd, 0x00dd, 0x59, 1 }, + { 0x00e0, 0x00e0, 0x61, 1 }, + { 0x00e1, 0x00e1, 0x61, 1 }, + { 0x00e2, 0x00e2, 0x61, 1 }, + { 0x00e3, 0x00e3, 0x61, 1 }, + { 0x00e4, 0x00e4, 0x61, 1 }, + { 0x00e5, 0x00e5, 0x61, 1 }, + { 0x00e6, 0x00e6, 0x6165, 2 }, + { 0x00e7, 0x00e7, 0x63, 1 }, + { 0x00e8, 0x00e8, 0x65, 1 }, + { 0x00e9, 0x00e9, 0x65, 1 }, + { 0x00ea, 0x00ea, 0x65, 1 }, + { 0x00eb, 0x00eb, 0x65, 1 }, + { 0x00ec, 0x00ec, 0x69, 1 }, + { 0x00ed, 0x00ed, 0x69, 1 }, + { 0x00ee, 0x00ee, 0x69, 1 }, + { 0x00ef, 0x00ef, 0x69, 1 }, + { 0x00f1, 0x00f2, 0x6e, 1 }, + { 0x00f3, 0x00f3, 0x6f, 1 }, + { 0x00f4, 0x00f4, 0x6f, 1 }, + { 0x00f5, 0x00f5, 0x6f, 1 }, + { 0x00f6, 0x00f6, 0x6f, 1 }, + { 0x00f7, 0x00f7, 0x2f, 1 }, + { 0x00f8, 0x00f8, 0x6f, 1 }, + { 0x00f9, 0x00f9, 0x75, 1 }, + { 0x00fa, 0x00fa, 0x75, 1 }, + { 0x00fb, 0x00fb, 0x75, 1 }, + { 0x00fc, 0x00fc, 0x75, 1 }, + { 0x00fd, 0x00fd, 0x79, 1 }, + { 0x00ff, 0x00ff, 0x79, 1 }, + { 0x0131, 0x0131, 0x69, 1 }, + { 0x0141, 0x0141, 0x4c, 1 }, + { 0x0152, 0x0152, 0x4f45, 2 }, + { 0x0153, 0x0153, 0x6f65, 2 }, + { 0x0160, 0x0160, 0x53, 1 }, + { 0x0178, 0x0178, 0x59, 1 }, + { 0x017d, 0x017d, 0x5a, 1 }, + { 0x2013, 0x2013, 0x2d, 1 }, + { 0x2014, 0x2014, 0x2d2d, 2 }, + { 0x2018, 0x2018, 0x60, 1 }, + { 0x2019, 0x2019, 0x27, 1 }, + { 0x201c, 0x201c, 0x22, 1 }, + { 0x201d, 0x201d, 0x22, 1 }, + { 0x2022, 0x2022, 0x2a, 1 }, + { 0x2026, 0x2026, 0x2e2e2e, 3 }, + { 0x2122, 0x2122, 0x544d, 2 }, + { 0x2212, 0x2212, 0x2d, 1 }, + { 0xf6f9, 0xf6f9, 0x4c, 1 }, + { 0xf6fa, 0xf6fa, 0x4f45, 2 }, + { 0xf6fd, 0xf6fd, 0x53, 1 }, + { 0xf6fe, 0xf6fe, 0x7e, 1 }, + { 0xf6ff, 0xf6ff, 0x5a, 1 }, + { 0xf721, 0xf721, 0x21, 1 }, + { 0xf724, 0xf724, 0x24, 1 }, + { 0xf726, 0xf726, 0x26, 1 }, + { 0xf730, 0xf739, 0x30, 1 }, + { 0xf73f, 0xf73f, 0x3f, 1 }, + { 0xf761, 0xf77a, 0x41, 1 }, + { 0xf7e0, 0xf7e0, 0x41, 1 }, + { 0xf7e1, 0xf7e1, 0x41, 1 }, + { 0xf7e2, 0xf7e2, 0x41, 1 }, + { 0xf7e3, 0xf7e3, 0x41, 1 }, + { 0xf7e4, 0xf7e4, 0x41, 1 }, + { 0xf7e5, 0xf7e5, 0x41, 1 }, + { 0xf7e6, 0xf7e6, 0x4145, 2 }, + { 0xf7e7, 0xf7e7, 0x43, 1 }, + { 0xf7e8, 0xf7e8, 0x45, 1 }, + { 0xf7e9, 0xf7e9, 0x45, 1 }, + { 0xf7ea, 0xf7ea, 0x45, 1 }, + { 0xf7eb, 0xf7eb, 0x45, 1 }, + { 0xf7ec, 0xf7ec, 0x49, 1 }, + { 0xf7ed, 0xf7ed, 0x49, 1 }, + { 0xf7ee, 0xf7ee, 0x49, 1 }, + { 0xf7ef, 0xf7ef, 0x49, 1 }, + { 0xf7f1, 0xf7f2, 0x4e, 1 }, + { 0xf7f3, 0xf7f3, 0x4f, 1 }, + { 0xf7f4, 0xf7f4, 0x4f, 1 }, + { 0xf7f5, 0xf7f5, 0x4f, 1 }, + { 0xf7f6, 0xf7f6, 0x4f, 1 }, + { 0xf7f8, 0xf7f8, 0x4f, 1 }, + { 0xf7f9, 0xf7f9, 0x55, 1 }, + { 0xf7fa, 0xf7fa, 0x55, 1 }, + { 0xf7fb, 0xf7fb, 0x55, 1 }, + { 0xf7fc, 0xf7fc, 0x55, 1 }, + { 0xf7fd, 0xf7fd, 0x59, 1 }, + { 0xf7ff, 0xf7ff, 0x59, 1 }, + { 0xfb00, 0xfb00, 0x6666, 2 }, + { 0xfb01, 0xfb01, 0x6669, 2 }, + { 0xfb02, 0xfb02, 0x666c, 2 }, + { 0xfb03, 0xfb03, 0x666669, 3 }, + { 0xfb04, 0xfb04, 0x66666c, 3 } +}; +#define ascii7UnicodeMapLen (sizeof(ascii7UnicodeMapRanges) / sizeof(UnicodeMapRange)) + +static UnicodeMapRange symbolUnicodeMapRanges[] = { + { 0x0020, 0x0021, 0x20, 1 }, + { 0x0023, 0x0023, 0x23, 1 }, + { 0x0025, 0x0026, 0x25, 1 }, + { 0x0028, 0x0029, 0x28, 1 }, + { 0x002b, 0x002c, 0x2b, 1 }, + { 0x002e, 0x003f, 0x2e, 1 }, + { 0x005b, 0x005b, 0x5b, 1 }, + { 0x005d, 0x005d, 0x5d, 1 }, + { 0x005f, 0x005f, 0x5f, 1 }, + { 0x007b, 0x007d, 0x7b, 1 }, + { 0x00ac, 0x00ac, 0xd8, 1 }, + { 0x00b0, 0x00b1, 0xb0, 1 }, + { 0x00b5, 0x00b5, 0x6d, 1 }, + { 0x00d7, 0x00d7, 0xb4, 1 }, + { 0x00f7, 0x00f7, 0xb8, 1 }, + { 0x0192, 0x0192, 0xa6, 1 }, + { 0x0391, 0x0392, 0x41, 1 }, + { 0x0393, 0x0393, 0x47, 1 }, + { 0x0395, 0x0395, 0x45, 1 }, + { 0x0396, 0x0396, 0x5a, 1 }, + { 0x0397, 0x0397, 0x48, 1 }, + { 0x0398, 0x0398, 0x51, 1 }, + { 0x0399, 0x0399, 0x49, 1 }, + { 0x039a, 0x039d, 0x4b, 1 }, + { 0x039e, 0x039e, 0x58, 1 }, + { 0x039f, 0x03a0, 0x4f, 1 }, + { 0x03a1, 0x03a1, 0x52, 1 }, + { 0x03a3, 0x03a5, 0x53, 1 }, + { 0x03a6, 0x03a6, 0x46, 1 }, + { 0x03a7, 0x03a7, 0x43, 1 }, + { 0x03a8, 0x03a8, 0x59, 1 }, + { 0x03b1, 0x03b2, 0x61, 1 }, + { 0x03b3, 0x03b3, 0x67, 1 }, + { 0x03b4, 0x03b5, 0x64, 1 }, + { 0x03b6, 0x03b6, 0x7a, 1 }, + { 0x03b7, 0x03b7, 0x68, 1 }, + { 0x03b8, 0x03b8, 0x71, 1 }, + { 0x03b9, 0x03b9, 0x69, 1 }, + { 0x03ba, 0x03bb, 0x6b, 1 }, + { 0x03bd, 0x03bd, 0x6e, 1 }, + { 0x03be, 0x03be, 0x78, 1 }, + { 0x03bf, 0x03c0, 0x6f, 1 }, + { 0x03c1, 0x03c1, 0x72, 1 }, + { 0x03c2, 0x03c2, 0x56, 1 }, + { 0x03c3, 0x03c5, 0x73, 1 }, + { 0x03c6, 0x03c6, 0x66, 1 }, + { 0x03c7, 0x03c7, 0x63, 1 }, + { 0x03c8, 0x03c8, 0x79, 1 }, + { 0x03c9, 0x03c9, 0x77, 1 }, + { 0x03d1, 0x03d1, 0x4a, 1 }, + { 0x03d2, 0x03d2, 0xa1, 1 }, + { 0x03d5, 0x03d5, 0x6a, 1 }, + { 0x03d6, 0x03d6, 0x76, 1 }, + { 0x2022, 0x2022, 0xb7, 1 }, + { 0x2026, 0x2026, 0xbc, 1 }, + { 0x2032, 0x2032, 0xa2, 1 }, + { 0x2033, 0x2033, 0xb2, 1 }, + { 0x2044, 0x2044, 0xa4, 1 }, + { 0x2111, 0x2111, 0xc1, 1 }, + { 0x2118, 0x2118, 0xc3, 1 }, + { 0x211c, 0x211c, 0xc2, 1 }, + { 0x2126, 0x2126, 0x57, 1 }, + { 0x2135, 0x2135, 0xc0, 1 }, + { 0x2190, 0x2193, 0xac, 1 }, + { 0x2194, 0x2194, 0xab, 1 }, + { 0x21b5, 0x21b5, 0xbf, 1 }, + { 0x21d0, 0x21d3, 0xdc, 1 }, + { 0x21d4, 0x21d4, 0xdb, 1 }, + { 0x2200, 0x2200, 0x22, 1 }, + { 0x2202, 0x2202, 0xb6, 1 }, + { 0x2203, 0x2203, 0x24, 1 }, + { 0x2205, 0x2205, 0xc6, 1 }, + { 0x2206, 0x2206, 0x44, 1 }, + { 0x2207, 0x2207, 0xd1, 1 }, + { 0x2208, 0x2209, 0xce, 1 }, + { 0x220b, 0x220b, 0x27, 1 }, + { 0x220f, 0x220f, 0xd5, 1 }, + { 0x2211, 0x2211, 0xe5, 1 }, + { 0x2212, 0x2212, 0x2d, 1 }, + { 0x2217, 0x2217, 0x2a, 1 }, + { 0x221a, 0x221a, 0xd6, 1 }, + { 0x221d, 0x221d, 0xb5, 1 }, + { 0x221e, 0x221e, 0xa5, 1 }, + { 0x2220, 0x2220, 0xd0, 1 }, + { 0x2227, 0x2228, 0xd9, 1 }, + { 0x2229, 0x222a, 0xc7, 1 }, + { 0x222b, 0x222b, 0xf2, 1 }, + { 0x2234, 0x2234, 0x5c, 1 }, + { 0x223c, 0x223c, 0x7e, 1 }, + { 0x2245, 0x2245, 0x40, 1 }, + { 0x2248, 0x2248, 0xbb, 1 }, + { 0x2260, 0x2261, 0xb9, 1 }, + { 0x2264, 0x2264, 0xa3, 1 }, + { 0x2265, 0x2265, 0xb3, 1 }, + { 0x2282, 0x2282, 0xcc, 1 }, + { 0x2283, 0x2283, 0xc9, 1 }, + { 0x2284, 0x2284, 0xcb, 1 }, + { 0x2286, 0x2286, 0xcd, 1 }, + { 0x2287, 0x2287, 0xca, 1 }, + { 0x2295, 0x2295, 0xc5, 1 }, + { 0x2297, 0x2297, 0xc4, 1 }, + { 0x22a5, 0x22a5, 0x5e, 1 }, + { 0x22c5, 0x22c5, 0xd7, 1 }, + { 0x2320, 0x2320, 0xf3, 1 }, + { 0x2321, 0x2321, 0xf5, 1 }, + { 0x2329, 0x2329, 0xe1, 1 }, + { 0x232a, 0x232a, 0xf1, 1 }, + { 0x25ca, 0x25ca, 0xe0, 1 }, + { 0x2660, 0x2660, 0xaa, 1 }, + { 0x2663, 0x2663, 0xa7, 1 }, + { 0x2665, 0x2665, 0xa9, 1 }, + { 0x2666, 0x2666, 0xa8, 1 }, + { 0xf6d9, 0xf6d9, 0xd3, 1 }, + { 0xf6da, 0xf6da, 0xd2, 1 }, + { 0xf6db, 0xf6db, 0xd4, 1 }, + { 0xf8e5, 0xf8e5, 0x60, 1 }, + { 0xf8e6, 0xf8e7, 0xbd, 1 }, + { 0xf8e8, 0xf8ea, 0xe2, 1 }, + { 0xf8eb, 0xf8f4, 0xe6, 1 }, + { 0xf8f5, 0xf8f5, 0xf4, 1 }, + { 0xf8f6, 0xf8fe, 0xf6, 1 } +}; +#define symbolUnicodeMapLen (sizeof(symbolUnicodeMapRanges) / sizeof(UnicodeMapRange)) + +static UnicodeMapRange zapfDingbatsUnicodeMapRanges[] = { + { 0x0020, 0x0020, 0x20, 1 }, + { 0x2192, 0x2192, 0xd5, 1 }, + { 0x2194, 0x2195, 0xd6, 1 }, + { 0x2460, 0x2469, 0xac, 1 }, + { 0x25a0, 0x25a0, 0x6e, 1 }, + { 0x25b2, 0x25b2, 0x73, 1 }, + { 0x25bc, 0x25bc, 0x74, 1 }, + { 0x25c6, 0x25c6, 0x75, 1 }, + { 0x25cf, 0x25cf, 0x6c, 1 }, + { 0x25d7, 0x25d7, 0x77, 1 }, + { 0x2605, 0x2605, 0x48, 1 }, + { 0x260e, 0x260e, 0x25, 1 }, + { 0x261b, 0x261b, 0x2a, 1 }, + { 0x261e, 0x261e, 0x2b, 1 }, + { 0x2660, 0x2660, 0xab, 1 }, + { 0x2663, 0x2663, 0xa8, 1 }, + { 0x2665, 0x2665, 0xaa, 1 }, + { 0x2666, 0x2666, 0xa9, 1 }, + { 0x2701, 0x2704, 0x21, 1 }, + { 0x2706, 0x2709, 0x26, 1 }, + { 0x270c, 0x2727, 0x2c, 1 }, + { 0x2729, 0x274b, 0x49, 1 }, + { 0x274d, 0x274d, 0x6d, 1 }, + { 0x274f, 0x2752, 0x6f, 1 }, + { 0x2756, 0x2756, 0x76, 1 }, + { 0x2758, 0x275e, 0x78, 1 }, + { 0x2761, 0x2767, 0xa1, 1 }, + { 0x2776, 0x2794, 0xb6, 1 }, + { 0x2798, 0x27af, 0xd8, 1 }, + { 0x27b1, 0x27be, 0xf1, 1 } +}; +#define zapfDingbatsUnicodeMapLen (sizeof(zapfDingbatsUnicodeMapRanges) / sizeof(UnicodeMapRange)) diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/UnicodeTypeTable.cc swftools-0.9.1/lib/pdf/xpdf/UnicodeTypeTable.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/UnicodeTypeTable.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/UnicodeTypeTable.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,949 @@ +//======================================================================== +// +// UnicodeTypeTable.cc +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include "CharTypes.h" +#include "UnicodeTypeTable.h" + +struct UnicodeMapTableEntry { + char *vector; + char type; +}; + +struct UnicodeCaseTableVector { + Unicode codes[256]; +}; + +static UnicodeMapTableEntry typeTable[256] = { + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNLNNNNLNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL", 'X' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLNNNNNNNNNNNNNNLLNNNNNNNNNNNNNNLLLLLNNNNNNNNNLNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLNNNNNNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRNRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' }, + { "RRRRNNNNNNNNNRNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNRNNNNNNNRRNNNNNNNRRNNNNNNNNNNRRRRRR", 'X' }, + { "RRRRRRRRRRRRRRNNRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNNNNNNNNNNRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { NULL, 'N' }, + { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLNNNNLLLLLLLLLLLLLNNLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNLLLLLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLNNLLLLLLLNNNNN", 'X' }, + { "NNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLNNNNNNNNLLLLNLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLNNNNNNNNNNNNNNNN", 'X' }, + { "NNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLNLNNNLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNNNNLLLLLLLNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLNNNNNNNNNLLLLLLLLLLNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNLNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNLNNNNNLNNLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLNNNNNNLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNLLLLLLLLNLLNNNNNNNNNNNLLLLLLLNLNLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLNNNNNLLLLLLNLLLLLLNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLNNNLLLLLLLLLLLNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLNNNLLLLLLLLLLLLLNNN", 'X' }, + { "NNNNNNNNNNNNNNLRNNNNNNNNNNNNNNNNNNNNNNNNNNLRNLRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNLNNNNLNNLLLLLLLLLLNLNNNLLLLLNNNNNNLNLNLNLLLLNLLLNLLLLLLLNNLLLLNNNNNLLLLLNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { NULL, 'N' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { NULL, 'N' }, + { NULL, 'N' }, + { NULL, 'N' }, + { NULL, 'L' }, + { NULL, 'N' }, + { NULL, 'N' }, + { NULL, 'N' }, + { NULL, 'N' }, + { NULL, 'N' }, + { NULL, 'N' }, + { NULL, 'N' }, + { "NNNNNLLLNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLNNNNNNNLLLLLNNLLLLLNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLL", 'X' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN", 'X' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", 'X' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL", 'X' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { NULL, 'L' }, + { "LLLLLLLLLLLLLLLLLLLLLLLLRRRRRRNRRRRRRRRRRNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR", 'X' }, + { NULL, 'R' }, + { "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRNNN", 'X' }, + { "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNLL", 'X' } +}; + +static UnicodeCaseTableVector caseTable00 = {{ + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x03bc, 0x00b6, 0x00b7, + 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00d7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff +}}; +static UnicodeCaseTableVector caseTable01 = {{ + 0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107, + 0x0109, 0x0109, 0x010b, 0x010b, 0x010d, 0x010d, 0x010f, 0x010f, + 0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117, + 0x0119, 0x0119, 0x011b, 0x011b, 0x011d, 0x011d, 0x011f, 0x011f, + 0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127, + 0x0129, 0x0129, 0x012b, 0x012b, 0x012d, 0x012d, 0x012f, 0x012f, + 0x0130, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0137, + 0x0138, 0x013a, 0x013a, 0x013c, 0x013c, 0x013e, 0x013e, 0x0140, + 0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148, + 0x0148, 0x0149, 0x014b, 0x014b, 0x014d, 0x014d, 0x014f, 0x014f, + 0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157, + 0x0159, 0x0159, 0x015b, 0x015b, 0x015d, 0x015d, 0x015f, 0x015f, + 0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167, + 0x0169, 0x0169, 0x016b, 0x016b, 0x016d, 0x016d, 0x016f, 0x016f, + 0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177, + 0x00ff, 0x017a, 0x017a, 0x017c, 0x017c, 0x017e, 0x017e, 0x0073, + 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, + 0x0188, 0x0256, 0x0257, 0x018c, 0x018c, 0x018d, 0x01dd, 0x0259, + 0x025b, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, + 0x0199, 0x0199, 0x019a, 0x019b, 0x026f, 0x0272, 0x019e, 0x0275, + 0x01a1, 0x01a1, 0x01a3, 0x01a3, 0x01a5, 0x01a5, 0x0280, 0x01a8, + 0x01a8, 0x0283, 0x01aa, 0x01ab, 0x01ad, 0x01ad, 0x0288, 0x01b0, + 0x01b0, 0x028a, 0x028b, 0x01b4, 0x01b4, 0x01b6, 0x01b6, 0x0292, + 0x01b9, 0x01b9, 0x01ba, 0x01bb, 0x01bd, 0x01bd, 0x01be, 0x01bf, + 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x01c6, 0x01c6, 0x01c6, 0x01c9, + 0x01c9, 0x01c9, 0x01cc, 0x01cc, 0x01cc, 0x01ce, 0x01ce, 0x01d0, + 0x01d0, 0x01d2, 0x01d2, 0x01d4, 0x01d4, 0x01d6, 0x01d6, 0x01d8, + 0x01d8, 0x01da, 0x01da, 0x01dc, 0x01dc, 0x01dd, 0x01df, 0x01df, + 0x01e1, 0x01e1, 0x01e3, 0x01e3, 0x01e5, 0x01e5, 0x01e7, 0x01e7, + 0x01e9, 0x01e9, 0x01eb, 0x01eb, 0x01ed, 0x01ed, 0x01ef, 0x01ef, + 0x01f0, 0x01f3, 0x01f3, 0x01f3, 0x01f5, 0x01f5, 0x0195, 0x01bf, + 0x01f9, 0x01f9, 0x01fb, 0x01fb, 0x01fd, 0x01fd, 0x01ff, 0x01ff +}}; +static UnicodeCaseTableVector caseTable02 = {{ + 0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207, + 0x0209, 0x0209, 0x020b, 0x020b, 0x020d, 0x020d, 0x020f, 0x020f, + 0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217, + 0x0219, 0x0219, 0x021b, 0x021b, 0x021d, 0x021d, 0x021f, 0x021f, + 0x019e, 0x0221, 0x0223, 0x0223, 0x0225, 0x0225, 0x0227, 0x0227, + 0x0229, 0x0229, 0x022b, 0x022b, 0x022d, 0x022d, 0x022f, 0x022f, + 0x0231, 0x0231, 0x0233, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237, + 0x0238, 0x0239, 0x023a, 0x023b, 0x023c, 0x023d, 0x023e, 0x023f, + 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, + 0x0248, 0x0249, 0x024a, 0x024b, 0x024c, 0x024d, 0x024e, 0x024f, + 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257, + 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 0x025d, 0x025e, 0x025f, + 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267, + 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e, 0x026f, + 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, + 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f, + 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287, + 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d, 0x028e, 0x028f, + 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, + 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f, + 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7, + 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af, + 0x02b0, 0x02b1, 0x02b2, 0x02b3, 0x02b4, 0x02b5, 0x02b6, 0x02b7, + 0x02b8, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf, + 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7, + 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf, + 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7, + 0x02d8, 0x02d9, 0x02da, 0x02db, 0x02dc, 0x02dd, 0x02de, 0x02df, + 0x02e0, 0x02e1, 0x02e2, 0x02e3, 0x02e4, 0x02e5, 0x02e6, 0x02e7, + 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef, + 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7, + 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff +}}; +static UnicodeCaseTableVector caseTable03 = {{ + 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, + 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f, + 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, + 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f, + 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, + 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f, + 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, + 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f, + 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x03b9, 0x0346, 0x0347, + 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f, + 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, + 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f, + 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, + 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, + 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, + 0x0378, 0x0379, 0x037a, 0x037b, 0x037c, 0x037d, 0x037e, 0x037f, + 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x03ac, 0x0387, + 0x03ad, 0x03ae, 0x03af, 0x038b, 0x03cc, 0x038d, 0x03cd, 0x03ce, + 0x0390, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03a2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, + 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03ac, 0x03ad, 0x03ae, 0x03af, + 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c3, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, + 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x03cf, + 0x03b2, 0x03b8, 0x03d2, 0x03d3, 0x03d4, 0x03c6, 0x03c0, 0x03d7, + 0x03d9, 0x03d9, 0x03db, 0x03db, 0x03dd, 0x03dd, 0x03df, 0x03df, + 0x03e1, 0x03e1, 0x03e3, 0x03e3, 0x03e5, 0x03e5, 0x03e7, 0x03e7, + 0x03e9, 0x03e9, 0x03eb, 0x03eb, 0x03ed, 0x03ed, 0x03ef, 0x03ef, + 0x03ba, 0x03c1, 0x03f2, 0x03f3, 0x03b8, 0x03b5, 0x03f6, 0x03f8, + 0x03f8, 0x03f2, 0x03fb, 0x03fb, 0x03fc, 0x03fd, 0x03fe, 0x03ff +}}; +static UnicodeCaseTableVector caseTable04 = {{ + 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045d, 0x045e, 0x045f, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, + 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045d, 0x045e, 0x045f, + 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, + 0x0469, 0x0469, 0x046b, 0x046b, 0x046d, 0x046d, 0x046f, 0x046f, + 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477, + 0x0479, 0x0479, 0x047b, 0x047b, 0x047d, 0x047d, 0x047f, 0x047f, + 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, + 0x0488, 0x0489, 0x048b, 0x048b, 0x048d, 0x048d, 0x048f, 0x048f, + 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, + 0x0499, 0x0499, 0x049b, 0x049b, 0x049d, 0x049d, 0x049f, 0x049f, + 0x04a1, 0x04a1, 0x04a3, 0x04a3, 0x04a5, 0x04a5, 0x04a7, 0x04a7, + 0x04a9, 0x04a9, 0x04ab, 0x04ab, 0x04ad, 0x04ad, 0x04af, 0x04af, + 0x04b1, 0x04b1, 0x04b3, 0x04b3, 0x04b5, 0x04b5, 0x04b7, 0x04b7, + 0x04b9, 0x04b9, 0x04bb, 0x04bb, 0x04bd, 0x04bd, 0x04bf, 0x04bf, + 0x04c0, 0x04c2, 0x04c2, 0x04c4, 0x04c4, 0x04c6, 0x04c6, 0x04c8, + 0x04c8, 0x04ca, 0x04ca, 0x04cc, 0x04cc, 0x04ce, 0x04ce, 0x04cf, + 0x04d1, 0x04d1, 0x04d3, 0x04d3, 0x04d5, 0x04d5, 0x04d7, 0x04d7, + 0x04d9, 0x04d9, 0x04db, 0x04db, 0x04dd, 0x04dd, 0x04df, 0x04df, + 0x04e1, 0x04e1, 0x04e3, 0x04e3, 0x04e5, 0x04e5, 0x04e7, 0x04e7, + 0x04e9, 0x04e9, 0x04eb, 0x04eb, 0x04ed, 0x04ed, 0x04ef, 0x04ef, + 0x04f1, 0x04f1, 0x04f3, 0x04f3, 0x04f5, 0x04f5, 0x04f6, 0x04f7, + 0x04f9, 0x04f9, 0x04fa, 0x04fb, 0x04fc, 0x04fd, 0x04fe, 0x04ff +}}; +static UnicodeCaseTableVector caseTable05 = {{ + 0x0501, 0x0501, 0x0503, 0x0503, 0x0505, 0x0505, 0x0507, 0x0507, + 0x0509, 0x0509, 0x050b, 0x050b, 0x050d, 0x050d, 0x050f, 0x050f, + 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, + 0x0518, 0x0519, 0x051a, 0x051b, 0x051c, 0x051d, 0x051e, 0x051f, + 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, + 0x0528, 0x0529, 0x052a, 0x052b, 0x052c, 0x052d, 0x052e, 0x052f, + 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, + 0x0568, 0x0569, 0x056a, 0x056b, 0x056c, 0x056d, 0x056e, 0x056f, + 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, + 0x0578, 0x0579, 0x057a, 0x057b, 0x057c, 0x057d, 0x057e, 0x057f, + 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557, + 0x0558, 0x0559, 0x055a, 0x055b, 0x055c, 0x055d, 0x055e, 0x055f, + 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, + 0x0568, 0x0569, 0x056a, 0x056b, 0x056c, 0x056d, 0x056e, 0x056f, + 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, + 0x0578, 0x0579, 0x057a, 0x057b, 0x057c, 0x057d, 0x057e, 0x057f, + 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587, + 0x0588, 0x0589, 0x058a, 0x058b, 0x058c, 0x058d, 0x058e, 0x058f, + 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, + 0x0598, 0x0599, 0x059a, 0x059b, 0x059c, 0x059d, 0x059e, 0x059f, + 0x05a0, 0x05a1, 0x05a2, 0x05a3, 0x05a4, 0x05a5, 0x05a6, 0x05a7, + 0x05a8, 0x05a9, 0x05aa, 0x05ab, 0x05ac, 0x05ad, 0x05ae, 0x05af, + 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, + 0x05b8, 0x05b9, 0x05ba, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf, + 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05c4, 0x05c5, 0x05c6, 0x05c7, + 0x05c8, 0x05c9, 0x05ca, 0x05cb, 0x05cc, 0x05cd, 0x05ce, 0x05cf, + 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, + 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, + 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, + 0x05e8, 0x05e9, 0x05ea, 0x05eb, 0x05ec, 0x05ed, 0x05ee, 0x05ef, + 0x05f0, 0x05f1, 0x05f2, 0x05f3, 0x05f4, 0x05f5, 0x05f6, 0x05f7, + 0x05f8, 0x05f9, 0x05fa, 0x05fb, 0x05fc, 0x05fd, 0x05fe, 0x05ff +}}; +static UnicodeCaseTableVector caseTable1e = {{ + 0x1e01, 0x1e01, 0x1e03, 0x1e03, 0x1e05, 0x1e05, 0x1e07, 0x1e07, + 0x1e09, 0x1e09, 0x1e0b, 0x1e0b, 0x1e0d, 0x1e0d, 0x1e0f, 0x1e0f, + 0x1e11, 0x1e11, 0x1e13, 0x1e13, 0x1e15, 0x1e15, 0x1e17, 0x1e17, + 0x1e19, 0x1e19, 0x1e1b, 0x1e1b, 0x1e1d, 0x1e1d, 0x1e1f, 0x1e1f, + 0x1e21, 0x1e21, 0x1e23, 0x1e23, 0x1e25, 0x1e25, 0x1e27, 0x1e27, + 0x1e29, 0x1e29, 0x1e2b, 0x1e2b, 0x1e2d, 0x1e2d, 0x1e2f, 0x1e2f, + 0x1e31, 0x1e31, 0x1e33, 0x1e33, 0x1e35, 0x1e35, 0x1e37, 0x1e37, + 0x1e39, 0x1e39, 0x1e3b, 0x1e3b, 0x1e3d, 0x1e3d, 0x1e3f, 0x1e3f, + 0x1e41, 0x1e41, 0x1e43, 0x1e43, 0x1e45, 0x1e45, 0x1e47, 0x1e47, + 0x1e49, 0x1e49, 0x1e4b, 0x1e4b, 0x1e4d, 0x1e4d, 0x1e4f, 0x1e4f, + 0x1e51, 0x1e51, 0x1e53, 0x1e53, 0x1e55, 0x1e55, 0x1e57, 0x1e57, + 0x1e59, 0x1e59, 0x1e5b, 0x1e5b, 0x1e5d, 0x1e5d, 0x1e5f, 0x1e5f, + 0x1e61, 0x1e61, 0x1e63, 0x1e63, 0x1e65, 0x1e65, 0x1e67, 0x1e67, + 0x1e69, 0x1e69, 0x1e6b, 0x1e6b, 0x1e6d, 0x1e6d, 0x1e6f, 0x1e6f, + 0x1e71, 0x1e71, 0x1e73, 0x1e73, 0x1e75, 0x1e75, 0x1e77, 0x1e77, + 0x1e79, 0x1e79, 0x1e7b, 0x1e7b, 0x1e7d, 0x1e7d, 0x1e7f, 0x1e7f, + 0x1e81, 0x1e81, 0x1e83, 0x1e83, 0x1e85, 0x1e85, 0x1e87, 0x1e87, + 0x1e89, 0x1e89, 0x1e8b, 0x1e8b, 0x1e8d, 0x1e8d, 0x1e8f, 0x1e8f, + 0x1e91, 0x1e91, 0x1e93, 0x1e93, 0x1e95, 0x1e95, 0x1e96, 0x1e97, + 0x1e98, 0x1e99, 0x1e9a, 0x1e61, 0x1e9c, 0x1e9d, 0x1e9e, 0x1e9f, + 0x1ea1, 0x1ea1, 0x1ea3, 0x1ea3, 0x1ea5, 0x1ea5, 0x1ea7, 0x1ea7, + 0x1ea9, 0x1ea9, 0x1eab, 0x1eab, 0x1ead, 0x1ead, 0x1eaf, 0x1eaf, + 0x1eb1, 0x1eb1, 0x1eb3, 0x1eb3, 0x1eb5, 0x1eb5, 0x1eb7, 0x1eb7, + 0x1eb9, 0x1eb9, 0x1ebb, 0x1ebb, 0x1ebd, 0x1ebd, 0x1ebf, 0x1ebf, + 0x1ec1, 0x1ec1, 0x1ec3, 0x1ec3, 0x1ec5, 0x1ec5, 0x1ec7, 0x1ec7, + 0x1ec9, 0x1ec9, 0x1ecb, 0x1ecb, 0x1ecd, 0x1ecd, 0x1ecf, 0x1ecf, + 0x1ed1, 0x1ed1, 0x1ed3, 0x1ed3, 0x1ed5, 0x1ed5, 0x1ed7, 0x1ed7, + 0x1ed9, 0x1ed9, 0x1edb, 0x1edb, 0x1edd, 0x1edd, 0x1edf, 0x1edf, + 0x1ee1, 0x1ee1, 0x1ee3, 0x1ee3, 0x1ee5, 0x1ee5, 0x1ee7, 0x1ee7, + 0x1ee9, 0x1ee9, 0x1eeb, 0x1eeb, 0x1eed, 0x1eed, 0x1eef, 0x1eef, + 0x1ef1, 0x1ef1, 0x1ef3, 0x1ef3, 0x1ef5, 0x1ef5, 0x1ef7, 0x1ef7, + 0x1ef9, 0x1ef9, 0x1efa, 0x1efb, 0x1efc, 0x1efd, 0x1efe, 0x1eff +}}; +static UnicodeCaseTableVector caseTable1f = {{ + 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07, + 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07, + 0x1f10, 0x1f11, 0x1f12, 0x1f13, 0x1f14, 0x1f15, 0x1f16, 0x1f17, + 0x1f10, 0x1f11, 0x1f12, 0x1f13, 0x1f14, 0x1f15, 0x1f1e, 0x1f1f, + 0x1f20, 0x1f21, 0x1f22, 0x1f23, 0x1f24, 0x1f25, 0x1f26, 0x1f27, + 0x1f20, 0x1f21, 0x1f22, 0x1f23, 0x1f24, 0x1f25, 0x1f26, 0x1f27, + 0x1f30, 0x1f31, 0x1f32, 0x1f33, 0x1f34, 0x1f35, 0x1f36, 0x1f37, + 0x1f30, 0x1f31, 0x1f32, 0x1f33, 0x1f34, 0x1f35, 0x1f36, 0x1f37, + 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0x1f46, 0x1f47, + 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0x1f4e, 0x1f4f, + 0x1f50, 0x1f51, 0x1f52, 0x1f53, 0x1f54, 0x1f55, 0x1f56, 0x1f57, + 0x1f58, 0x1f51, 0x1f5a, 0x1f53, 0x1f5c, 0x1f55, 0x1f5e, 0x1f57, + 0x1f60, 0x1f61, 0x1f62, 0x1f63, 0x1f64, 0x1f65, 0x1f66, 0x1f67, + 0x1f60, 0x1f61, 0x1f62, 0x1f63, 0x1f64, 0x1f65, 0x1f66, 0x1f67, + 0x1f70, 0x1f71, 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1f76, 0x1f77, + 0x1f78, 0x1f79, 0x1f7a, 0x1f7b, 0x1f7c, 0x1f7d, 0x1f7e, 0x1f7f, + 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87, + 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87, + 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97, + 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97, + 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7, + 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7, + 0x1fb0, 0x1fb1, 0x1fb2, 0x1fb3, 0x1fb4, 0x1fb5, 0x1fb6, 0x1fb7, + 0x1fb0, 0x1fb1, 0x1f70, 0x1f71, 0x1fb3, 0x1fbd, 0x03b9, 0x1fbf, + 0x1fc0, 0x1fc1, 0x1fc2, 0x1fc3, 0x1fc4, 0x1fc5, 0x1fc6, 0x1fc7, + 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1fc3, 0x1fcd, 0x1fce, 0x1fcf, + 0x1fd0, 0x1fd1, 0x1fd2, 0x1fd3, 0x1fd4, 0x1fd5, 0x1fd6, 0x1fd7, + 0x1fd0, 0x1fd1, 0x1f76, 0x1f77, 0x1fdc, 0x1fdd, 0x1fde, 0x1fdf, + 0x1fe0, 0x1fe1, 0x1fe2, 0x1fe3, 0x1fe4, 0x1fe5, 0x1fe6, 0x1fe7, + 0x1fe0, 0x1fe1, 0x1f7a, 0x1f7b, 0x1fe5, 0x1fed, 0x1fee, 0x1fef, + 0x1ff0, 0x1ff1, 0x1ff2, 0x1ff3, 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, + 0x1f78, 0x1f79, 0x1f7c, 0x1f7d, 0x1ff3, 0x1ffd, 0x1ffe, 0x1fff +}}; +static UnicodeCaseTableVector caseTable21 = {{ + 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, + 0x2108, 0x2109, 0x210a, 0x210b, 0x210c, 0x210d, 0x210e, 0x210f, + 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, + 0x2118, 0x2119, 0x211a, 0x211b, 0x211c, 0x211d, 0x211e, 0x211f, + 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x03c9, 0x2127, + 0x2128, 0x2129, 0x006b, 0x00e5, 0x212c, 0x212d, 0x212e, 0x212f, + 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, + 0x2138, 0x2139, 0x213a, 0x213b, 0x213c, 0x213d, 0x213e, 0x213f, + 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, + 0x2148, 0x2149, 0x214a, 0x214b, 0x214c, 0x214d, 0x214e, 0x214f, + 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, + 0x2158, 0x2159, 0x215a, 0x215b, 0x215c, 0x215d, 0x215e, 0x215f, + 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, + 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f, + 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, + 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f, + 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, + 0x2188, 0x2189, 0x218a, 0x218b, 0x218c, 0x218d, 0x218e, 0x218f, + 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, + 0x2198, 0x2199, 0x219a, 0x219b, 0x219c, 0x219d, 0x219e, 0x219f, + 0x21a0, 0x21a1, 0x21a2, 0x21a3, 0x21a4, 0x21a5, 0x21a6, 0x21a7, + 0x21a8, 0x21a9, 0x21aa, 0x21ab, 0x21ac, 0x21ad, 0x21ae, 0x21af, + 0x21b0, 0x21b1, 0x21b2, 0x21b3, 0x21b4, 0x21b5, 0x21b6, 0x21b7, + 0x21b8, 0x21b9, 0x21ba, 0x21bb, 0x21bc, 0x21bd, 0x21be, 0x21bf, + 0x21c0, 0x21c1, 0x21c2, 0x21c3, 0x21c4, 0x21c5, 0x21c6, 0x21c7, + 0x21c8, 0x21c9, 0x21ca, 0x21cb, 0x21cc, 0x21cd, 0x21ce, 0x21cf, + 0x21d0, 0x21d1, 0x21d2, 0x21d3, 0x21d4, 0x21d5, 0x21d6, 0x21d7, + 0x21d8, 0x21d9, 0x21da, 0x21db, 0x21dc, 0x21dd, 0x21de, 0x21df, + 0x21e0, 0x21e1, 0x21e2, 0x21e3, 0x21e4, 0x21e5, 0x21e6, 0x21e7, + 0x21e8, 0x21e9, 0x21ea, 0x21eb, 0x21ec, 0x21ed, 0x21ee, 0x21ef, + 0x21f0, 0x21f1, 0x21f2, 0x21f3, 0x21f4, 0x21f5, 0x21f6, 0x21f7, + 0x21f8, 0x21f9, 0x21fa, 0x21fb, 0x21fc, 0x21fd, 0x21fe, 0x21ff +}}; +static UnicodeCaseTableVector caseTable24 = {{ + 0x2400, 0x2401, 0x2402, 0x2403, 0x2404, 0x2405, 0x2406, 0x2407, + 0x2408, 0x2409, 0x240a, 0x240b, 0x240c, 0x240d, 0x240e, 0x240f, + 0x2410, 0x2411, 0x2412, 0x2413, 0x2414, 0x2415, 0x2416, 0x2417, + 0x2418, 0x2419, 0x241a, 0x241b, 0x241c, 0x241d, 0x241e, 0x241f, + 0x2420, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427, + 0x2428, 0x2429, 0x242a, 0x242b, 0x242c, 0x242d, 0x242e, 0x242f, + 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, + 0x2438, 0x2439, 0x243a, 0x243b, 0x243c, 0x243d, 0x243e, 0x243f, + 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, + 0x2448, 0x2449, 0x244a, 0x244b, 0x244c, 0x244d, 0x244e, 0x244f, + 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, + 0x2458, 0x2459, 0x245a, 0x245b, 0x245c, 0x245d, 0x245e, 0x245f, + 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, + 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x246f, + 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477, + 0x2478, 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, 0x247e, 0x247f, + 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, + 0x2488, 0x2489, 0x248a, 0x248b, 0x248c, 0x248d, 0x248e, 0x248f, + 0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497, + 0x2498, 0x2499, 0x249a, 0x249b, 0x249c, 0x249d, 0x249e, 0x249f, + 0x24a0, 0x24a1, 0x24a2, 0x24a3, 0x24a4, 0x24a5, 0x24a6, 0x24a7, + 0x24a8, 0x24a9, 0x24aa, 0x24ab, 0x24ac, 0x24ad, 0x24ae, 0x24af, + 0x24b0, 0x24b1, 0x24b2, 0x24b3, 0x24b4, 0x24b5, 0x24d0, 0x24d1, + 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, 0x24d8, 0x24d9, + 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, 0x24e0, 0x24e1, + 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, 0x24e8, 0x24e9, + 0x24d0, 0x24d1, 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, + 0x24d8, 0x24d9, 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, + 0x24e0, 0x24e1, 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, + 0x24e8, 0x24e9, 0x24ea, 0x24eb, 0x24ec, 0x24ed, 0x24ee, 0x24ef, + 0x24f0, 0x24f1, 0x24f2, 0x24f3, 0x24f4, 0x24f5, 0x24f6, 0x24f7, + 0x24f8, 0x24f9, 0x24fa, 0x24fb, 0x24fc, 0x24fd, 0x24fe, 0x24ff +}}; +static UnicodeCaseTableVector caseTableff = {{ + 0xff00, 0xff01, 0xff02, 0xff03, 0xff04, 0xff05, 0xff06, 0xff07, + 0xff08, 0xff09, 0xff0a, 0xff0b, 0xff0c, 0xff0d, 0xff0e, 0xff0f, + 0xff10, 0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, + 0xff18, 0xff19, 0xff1a, 0xff1b, 0xff1c, 0xff1d, 0xff1e, 0xff1f, + 0xff20, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, + 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, + 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, + 0xff58, 0xff59, 0xff5a, 0xff3b, 0xff3c, 0xff3d, 0xff3e, 0xff3f, + 0xff40, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, + 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, + 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, + 0xff58, 0xff59, 0xff5a, 0xff5b, 0xff5c, 0xff5d, 0xff5e, 0xff5f, + 0xff60, 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67, + 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f, + 0xff70, 0xff71, 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77, + 0xff78, 0xff79, 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f, + 0xff80, 0xff81, 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87, + 0xff88, 0xff89, 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f, + 0xff90, 0xff91, 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97, + 0xff98, 0xff99, 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f, + 0xffa0, 0xffa1, 0xffa2, 0xffa3, 0xffa4, 0xffa5, 0xffa6, 0xffa7, + 0xffa8, 0xffa9, 0xffaa, 0xffab, 0xffac, 0xffad, 0xffae, 0xffaf, + 0xffb0, 0xffb1, 0xffb2, 0xffb3, 0xffb4, 0xffb5, 0xffb6, 0xffb7, + 0xffb8, 0xffb9, 0xffba, 0xffbb, 0xffbc, 0xffbd, 0xffbe, 0xffbf, + 0xffc0, 0xffc1, 0xffc2, 0xffc3, 0xffc4, 0xffc5, 0xffc6, 0xffc7, + 0xffc8, 0xffc9, 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf, + 0xffd0, 0xffd1, 0xffd2, 0xffd3, 0xffd4, 0xffd5, 0xffd6, 0xffd7, + 0xffd8, 0xffd9, 0xffda, 0xffdb, 0xffdc, 0xffdd, 0xffde, 0xffdf, + 0xffe0, 0xffe1, 0xffe2, 0xffe3, 0xffe4, 0xffe5, 0xffe6, 0xffe7, + 0xffe8, 0xffe9, 0xffea, 0xffeb, 0xffec, 0xffed, 0xffee, 0xffef, + 0xfff0, 0xfff1, 0xfff2, 0xfff3, 0xfff4, 0xfff5, 0xfff6, 0xfff7, + 0xfff8, 0xfff9, 0xfffa, 0xfffb, 0xfffc, 0xfffd, 0xfffe, 0xffff +}}; +static UnicodeCaseTableVector *caseTable[256] = { + &caseTable00, + &caseTable01, + &caseTable02, + &caseTable03, + &caseTable04, + &caseTable05, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &caseTable1e, + &caseTable1f, + NULL, + &caseTable21, + NULL, + NULL, + &caseTable24, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &caseTableff +}; + +static inline char getType(Unicode c) { + int i; + char type; + + if (c > 0xffff) { + type = 'X'; + } else { + i = (c >> 8) & 0xff; + if ((type = typeTable[i].type) == 'X') { + type = typeTable[i].vector[c & 0xff]; + } + } + return type; +} + +GBool unicodeTypeL(Unicode c) { + return getType(c) == 'L'; +} + +GBool unicodeTypeR(Unicode c) { + return getType(c) == 'R'; +} + +Unicode unicodeToUpper(Unicode c) { + int i; + + if (c > 0xffff) { + return c; + } + i = (c >> 8) & 0xff; + if (caseTable[i]) { + return caseTable[i]->codes[c & 0xff]; + } + return c; +} + diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/UnicodeTypeTable.h swftools-0.9.1/lib/pdf/xpdf/UnicodeTypeTable.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/UnicodeTypeTable.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/UnicodeTypeTable.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,20 @@ +//======================================================================== +// +// UnicodeTypeTable.h +// +// Copyright 2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef UNICODETYPETABLE_H +#define UNICODETYPETABLE_H + +#include "gtypes.h" + +extern GBool unicodeTypeL(Unicode c); + +extern GBool unicodeTypeR(Unicode c); + +extern Unicode unicodeToUpper(Unicode c); + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/UTF8.h swftools-0.9.1/lib/pdf/xpdf/UTF8.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/UTF8.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/UTF8.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,56 @@ +//======================================================================== +// +// UTF8.h +// +// Copyright 2001-2003 Glyph & Cog, LLC +// +//======================================================================== + +static int mapUTF8(Unicode u, char *buf, int bufSize) { + if (u <= 0x0000007f) { + if (bufSize < 1) { + return 0; + } + buf[0] = (char)u; + return 1; + } else if (u <= 0x000007ff) { + if (bufSize < 2) { + return 0; + } + buf[0] = (char)(0xc0 + (u >> 6)); + buf[1] = (char)(0x80 + (u & 0x3f)); + return 2; + } else if (u <= 0x0000ffff) { + if (bufSize < 3) { + return 0; + } + buf[0] = (char)(0xe0 + (u >> 12)); + buf[1] = (char)(0x80 + ((u >> 6) & 0x3f)); + buf[2] = (char)(0x80 + (u & 0x3f)); + return 3; + } else if (u <= 0x0010ffff) { + if (bufSize < 4) { + return 0; + } + buf[0] = (char)(0xf0 + (u >> 18)); + buf[1] = (char)(0x80 + ((u >> 12) & 0x3f)); + buf[2] = (char)(0x80 + ((u >> 6) & 0x3f)); + buf[3] = (char)(0x80 + (u & 0x3f)); + return 4; + } else { + return 0; + } +} + +static int mapUCS2(Unicode u, char *buf, int bufSize) { + if (u <= 0xffff) { + if (bufSize < 2) { + return 0; + } + buf[0] = (char)((u >> 8) & 0xff); + buf[1] = (char)(u & 0xff); + return 2; + } else { + return 0; + } +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/vms_directory.c swftools-0.9.1/lib/pdf/xpdf/vms_directory.c --- swftools-0.9.2+ds1/lib/pdf/xpdf/vms_directory.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/vms_directory.c 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,214 @@ +/* + * DIRECTORY.C - VMS emulation routines for UNIX Directory + * callable routines + * + * Author: Patrick L. Mahan + * Location: TGV, Inc + * Date: 19-November-1991 + * + * Purpose: Provides emulation of the BSD directory routines + * which are used by some of the X11 R4 release + * software. + * + * Side effects: This is only a partial emulation. Not all of + * the required information is passed to the user. + * + * Modification History + * + * Date | Who | Version | History + * ------------+-----------+---------------+---------------------------- + * 19-Nov-1991 | PLM | 1.0 | First Write + * 20-Apr-1992 | PLM | 1.1 | Added validation check for + * | | | for the directory + */ + +#include +#include +#include +#include +#include +#include +#include "vms_dirent.h" + +#define NOWILD 0x00000001 +#define MULTIPLE 0x00000002 + +static unsigned long context = 0; + +static struct dsc$descriptor_s *create_descriptor ( name ) +char *name; +{ + struct dsc$descriptor_s *retdescrip; + + retdescrip = (struct dsc$descriptor_s *)calloc(1, sizeof(struct dsc$descriptor_s)); + + if (retdescrip == NULL) return ((struct dsc$descriptor_s *)NULL); + + retdescrip->dsc$b_dtype = DSC$K_DTYPE_T; + retdescrip->dsc$b_class = DSC$K_CLASS_S; + retdescrip->dsc$w_length = strlen(name); + retdescrip->dsc$a_pointer = name; + + return (retdescrip); +} + +static int Check_Directory( dirname ) +char *dirname; +{ + static char *tmpdir, *cp; + FILE *tfp; + int status; + + status = 1; + + tmpdir = calloc(strlen(dirname)+15,sizeof(char)); + + strcpy(tmpdir, dirname); + + cp = strrchr(tmpdir, '.'); + + if (cp != NULL) { + *cp = ']'; + cp = strrchr(tmpdir, ']'); + *cp = '.'; + strcat(tmpdir, "dir"); + } + else { + char *tmp1; + tmp1 = calloc(strlen(dirname)+1,sizeof(char)); + cp = strchr(tmpdir, '['); + cp++; + strcpy(tmp1, cp); + cp = strrchr(tmp1, ']'); + *cp = '\0'; + cp = strchr(tmpdir, '['); + cp++; + *cp = '\0'; + strcat(tmpdir, "000000]"); + strcat(tmpdir, tmp1); + strcat(tmpdir, ".dir"); + } + + tfp = fopen(tmpdir, "r"); + + if (tfp == NULL) status = 0; + + fclose(tfp); + + return (status); +} + +DIR *opendir( dirname ) +char *dirname; +{ + DIR *retdir; + struct dsc$descriptor_s filedescriptor; + char *filepathname; + + retdir = (DIR *) calloc(1, sizeof(DIR)); + + if (retdir == NULL) return ((DIR *)NULL); + + if (!Check_Directory(dirname)) return ((DIR *)NULL); + + filepathname = (char *)calloc(256, sizeof(char)); + + strcpy(filepathname, dirname); + strcat(filepathname, "*.*.*"); + + retdir->dd_fd = (unsigned long) create_descriptor(filepathname); + retdir->dd_loc = 0; + retdir->dd_size = strlen(filepathname); + retdir->dd_bsize = 0; + retdir->dd_off = 0; + retdir->dd_buf = filepathname; + + return (retdir); +} + +struct dirent *readdir( dirp ) +DIR *dirp; +{ + static struct dirent *retdirent; + struct dsc$descriptor_s retfilenamedesc; + struct dsc$descriptor_s searchpathdesc = *((struct dsc$descriptor_s *)dirp->dd_fd); + char retfilename[256]; + char *sp; + unsigned long istatus; + unsigned long rms_status; + unsigned long flags; + + retdirent = (struct dirent *)NULL; + + flags = MULTIPLE; + + retfilenamedesc.dsc$b_dtype = DSC$K_DTYPE_T; + retfilenamedesc.dsc$b_class = DSC$K_CLASS_S; + retfilenamedesc.dsc$w_length = 255; + retfilenamedesc.dsc$a_pointer= retfilename; + + istatus = lib$find_file (&searchpathdesc, + &retfilenamedesc, + &dirp->dd_loc, + 0, 0, + &rms_status, + &flags); + + if (!(istatus & 1) && (istatus != RMS$_NMF) && (istatus != RMS$_FNF)) + { + lib$signal (istatus); + return (retdirent); + } + else if ((istatus == RMS$_NMF) || (istatus == RMS$_FNF)) + return (retdirent); + + retfilename[retfilenamedesc.dsc$w_length] = '\0'; + + sp = strchr(retfilename, ' '); + if (sp != NULL) *sp = '\0'; + + sp = strrchr(retfilename, ']'); + if (sp != NULL) + sp++; + else + sp = retfilename; + + retdirent = (struct dirent *)calloc(1, sizeof(struct dirent)); + + strcpy(retdirent->d_name, sp); + retdirent->d_namlen = strlen(sp); + retdirent->d_fileno = 0; + retdirent->d_off = 0; + retdirent->d_reclen = DIRSIZ(retdirent); + + return (retdirent); +} + +long telldir( dirp ) +DIR *dirp; +{ + return(0); +} + +void seekdir( dirp, loc ) +DIR *dirp; +int loc; +{ + return; +} + +void rewinddir( dirp ) +DIR *dirp; +{ + lib$find_file_end (&dirp->dd_loc); +} + +void closedir( dirp ) +DIR *dirp; +{ + lib$find_file_end (&dirp->dd_loc); + + cfree ((void *) dirp->dd_fd); + cfree (dirp->dd_buf); + cfree (dirp); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/vms_dirent.h swftools-0.9.1/lib/pdf/xpdf/vms_dirent.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/vms_dirent.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/vms_dirent.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,67 @@ +/* @(#)dirent.h 1.7 89/06/25 SMI */ + +/* + * Filesystem-independent directory information. + */ + +#ifndef __dirent_h +#define __dirent_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* Make sure we don't get the V7 RTL dirent functions. These are broken. */ + +#ifndef __CRTL_VER +# define __CRTL_VER __VMS_VER +#endif +#if __CRTL_VER >= 70000000 +#include +#endif + +#include + +#define opendir goo_opendir +#define readdir goo_readdir +#define closedir goo_closedir +#define seekdir goo_seekdir +#define telldir goo_telldir +#define rewinddir goo_rewindir +#define DIR GOO_DIR + +#ifndef _POSIX_SOURCE +#define d_ino d_fileno /* compatability */ +#ifndef NULL +#define NULL 0 +#endif +#endif /* !_POSIX_SOURCE */ + +/* + * Definitions for library routines operating on directories. + */ +typedef struct __dirdesc { + unsigned long dd_fd; /* file descriptor */ + long dd_loc; /* buf offset of entry from last readddir() */ + long dd_size; /* amount of valid data in buffer */ + long dd_bsize; /* amount of entries read at a time */ + long dd_off; /* Current offset in dir (for telldir) */ + char *dd_buf; /* directory data buffer */ +} DIR; + +#include "vms_sys_dirent.h" + +extern DIR *opendir(char *dirname); +extern struct dirent *readdir(DIR *dirp); +extern void closedir(DIR *dirp); +#ifndef _POSIX_SOURCE +extern void seekdir(DIR *dirp, int loc); +extern long telldir(DIR *dirp); +#endif /* POSIX_SOURCE */ +extern void rewinddir(DIR *dirp); + +#ifdef __cplusplus +} +#endif + +#endif /* !__dirent_h */ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/vms_make.com swftools-0.9.1/lib/pdf/xpdf/vms_make.com --- swftools-0.9.2+ds1/lib/pdf/xpdf/vms_make.com 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/vms_make.com 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,82 @@ +$!======================================================================== +$! +$! Goo library compile script for VMS. +$! +$! Written by Patrick Moreau, Martin P.J. Zinser. +$! +$! Copyright 1996-2003 Glyph & Cog, LLC +$! +$!======================================================================== +$! +$ GOO_CXXOBJS = "GString.obj,gmempp.obj,gfile.obj,ghash.obj,glist.obj" +$ GOO_CCOBJS = "gmem.obj,parseargs.obj,vms_directory.obj,vms_unix_times.obj" +$! +$ if f$extract(1,3,f$getsyi("Version")) .lts. "7.0" +$ then +$ GOO_CCOBJS = GOO_CCOBJS + ",vms_unlink.obj" +$ endif +$! +$ i = 0 +$ j = 0 +$COMPILE_CXX_LOOP: +$ file = f$element(i, ",",GOO_CXXOBJS) +$ if file .eqs. "," then goto COMPILE_CC_LOOP +$ i = i + 1 +$ name = f$parse(file,,,"NAME") +$ call make 'file "CXXCOMP ''name'.cc" - + 'name'.cc +$ goto COMPILE_CXX_LOOP +$! +$COMPILE_CC_LOOP: +$ file = f$element(j, ",",GOO_CCOBJS) +$ if file .eqs. "," then goto COMPILE_END +$ j = j + 1 +$ name = f$parse(file,,,"NAME") +$ call make 'file "CCOMP ''name'.c" - + 'name'.c +$ goto COMPILE_CC_LOOP +$! +$COMPILE_END: +$ call make libgoo.olb "lib/cre libgoo.olb ''GOO_CXXOBJS',''GOO_CCOBJS'" *.obj +$! +$ exit +$! +$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES +$ V = 'F$Verify(0) +$! P1 = What we are trying to make +$! P2 = Command to make it +$! P3 - P8 What it depends on +$ +$ If F$Search(P1) .Eqs. "" Then Goto Makeit +$ Time = F$CvTime(F$File(P1,"RDT")) +$arg=3 +$Loop: +$ Argument = P'arg +$ If Argument .Eqs. "" Then Goto Exit +$ El=0 +$Loop2: +$ File = F$Element(El," ",Argument) +$ If File .Eqs. " " Then Goto Endl +$ AFile = "" +$Loop3: +$ OFile = AFile +$ AFile = F$Search(File) +$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl +$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit +$ Goto Loop3 +$NextEL: +$ El = El + 1 +$ Goto Loop2 +$EndL: +$ arg=arg+1 +$ If arg .Le. 8 Then Goto Loop +$ Goto Exit +$ +$Makeit: +$ VV=F$VERIFY(0) +$ write sys$output P2 +$ 'P2 +$ VV='F$Verify(VV) +$Exit: +$ If V Then Set Verify +$ENDSUBROUTINE diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/vms_sys_dirent.h swftools-0.9.1/lib/pdf/xpdf/vms_sys_dirent.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/vms_sys_dirent.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/vms_sys_dirent.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,54 @@ +/* @(#)dirent.h 1.4 89/06/16 SMI */ + +/* + * Filesystem-independent directory information. + * Directory entry structures are of variable length. + * Each directory entry is a struct dirent containing its file number, the + * offset of the next entry (a cookie interpretable only the filesystem + * type that generated it), the length of the entry, and the length of the + * name contained in the entry. These are followed by the name. The + * entire entry is padded with null bytes to a 4 byte boundary. All names + * are guaranteed null terminated. The maximum length of a name in a + * directory is MAXNAMLEN, plus a null byte. + */ + +#ifndef __sys_dirent_h +#define __sys_dirent_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define dirent GOO_dirent + +struct dirent { + long d_off; /* offset of next disk dir entry */ + unsigned long d_fileno; /* file number of entry */ + unsigned short d_reclen; /* length of this record */ + unsigned short d_namlen; /* length of string in d_name */ + char d_name[255+1]; /* name (up to MAXNAMLEN + 1) */ +}; + +#ifndef _POSIX_SOURCE +/* + * It's unlikely to change, but make sure that sizeof d_name above is + * at least MAXNAMLEN + 1 (more may be added for padding). + */ +#define MAXNAMLEN 255 +/* + * The macro DIRSIZ(dp) gives the minimum amount of space required to represent + * a directory entry. For any directory entry dp->d_reclen >= DIRSIZ(dp). + * Specific filesystem types may use this macro to construct the value + * for d_reclen. + */ +#undef DIRSIZ +#define DIRSIZ(dp) \ + (((sizeof(struct dirent) - (MAXNAMLEN+1) + ((dp)->d_namlen+1)) +3) & ~3) + +#endif /* !_POSIX_SOURCE */ + +#ifdef __cplusplus +} +#endif + +#endif /* !__sys_dirent_h */ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/vms_unix_time.h swftools-0.9.1/lib/pdf/xpdf/vms_unix_time.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/vms_unix_time.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/vms_unix_time.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,102 @@ +/* @(#)time.h 2.9 87/01/17 SMI; from UCB 7.1 6/4/86 */ + +/* + Definitions of various structures used on UNIX for + time-related syscalls. +*/ + +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#ifndef _UNIX_TIME_ +#define _UNIX_TIME_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Structure returned by gettimeofday(2) system call, + * and used in other calls. + */ +#ifndef __DECC +struct timeval +{ + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#else +#if (__DECC_VER < 50200000) && (__VMS_VER < 70000000) +struct timeval +{ + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif /* __DECC_VER */ +#endif /* __DECC */ +struct timezone +{ + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +#define DST_NONE 0 /* not on dst */ +#define DST_USA 1 /* USA style dst */ +#define DST_AUST 2 /* Australian style dst */ +#define DST_WET 3 /* Western European dst */ +#define DST_MET 4 /* Middle European dst */ +#define DST_EET 5 /* Eastern European dst */ +#define DST_CAN 6 /* Canada */ +#define DST_GB 7 /* Great Britain and Eire */ +#define DST_RUM 8 /* Rumania */ +#define DST_TUR 9 /* Turkey */ +#define DST_AUSTALT 10 /* Australian style with shift in 1986 */ + +/* + * Operations on timevals. + * + * NB: timercmp does not work for >= or <=. + */ +#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#define timercmp(tvp, uvp, cmp) \ + ((tvp)->tv_sec cmp (uvp)->tv_sec || \ + (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec) +#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 + +/* + * Names of the interval timers, and structure + * defining a timer setting. + */ +#define ITIMER_REAL 0 +#define ITIMER_VIRTUAL 1 +#define ITIMER_PROF 2 + +#ifndef __DECC +struct itimerval +{ + struct timeval it_interval; /* timer interval */ + struct timeval it_value; /* current value */ +}; +#else +#if (__DECC_VER < 50200000) && (__VMS_VER < 70000000) +struct itimerval +{ + struct timeval it_interval; /* timer interval */ + struct timeval it_value; /* current value */ +}; +#endif /* __DECC_VER */ +#endif /* __DECC */ + +#ifndef KERNEL +#include +#endif + +#ifdef __cplusplus +} +#endif + +#endif /*!_UNIX_TIME_*/ + diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/vms_unix_times.c swftools-0.9.1/lib/pdf/xpdf/vms_unix_times.c --- swftools-0.9.2+ds1/lib/pdf/xpdf/vms_unix_times.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/vms_unix_times.c 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * UNIX-style Time Functions + * + */ +#include +#include +#include +#include "vms_unix_time.h" + +/* + * gettimeofday(2) - Returns the current time + * + * NOTE: The timezone portion is useless on VMS. + * Even on UNIX, it is only provided for backwards + * compatibilty and is not guaranteed to be correct. + */ + +#if (__VMS_VER < 70000000) +int gettimeofday(tv, tz) +struct timeval *tv; +struct timezone *tz; +{ + timeb_t tmp_time; + + ftime(&tmp_time); + + if (tv != NULL) + { + tv->tv_sec = tmp_time.time; + tv->tv_usec = tmp_time.millitm * 1000; + } + + if (tz != NULL) + { + tz->tz_minuteswest = tmp_time.timezone; + tz->tz_dsttime = tmp_time.dstflag; + } + + return (0); + +} /*** End gettimeofday() ***/ +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/vms_unlink.c swftools-0.9.1/lib/pdf/xpdf/vms_unlink.c --- swftools-0.9.2+ds1/lib/pdf/xpdf/vms_unlink.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/vms_unlink.c 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,22 @@ +/* + * vms_unlink.c + * + * A UNIX-style unlink() function for VMS. + * + * Thanks to Patrick Moreau (pmoreau@cena.dgac.fr). + */ + +#include +#include +#include + +int unlink(char *filename) { + static struct dsc$descriptor_s file_desc; + + file_desc.dsc$w_length = strlen(filename); + file_desc.dsc$b_dtype = DSC$K_DTYPE_T; + file_desc.dsc$b_class = DSC$K_CLASS_S; + file_desc.dsc$a_pointer= filename; + + return (lib$delete_file(&file_desc)); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/xpdf.1 swftools-0.9.1/lib/pdf/xpdf/xpdf.1 --- swftools-0.9.2+ds1/lib/pdf/xpdf/xpdf.1 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/xpdf.1 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,863 @@ +.\" Copyright 1996-2007 Glyph & Cog, LLC +.TH xpdf 1 "27 February 2007" +.SH NAME +xpdf \- Portable Document Format (PDF) file viewer for X (version 3.02) +.SH SYNOPSIS +.B xpdf +[options] +.RI [ PDF-file +.RI [ page " | +" dest ]] +.SH DESCRIPTION +.B Xpdf +is a viewer for Portable Document Format (PDF) files. (These are also +sometimes also called \'Acrobat' files, from the name of Adobe's PDF +software.) Xpdf runs under the X Window System on UNIX, VMS, and +OS/2. +.PP +To run xpdf, simply type: +.PP +.RS +xpdf file.pdf +.RE +.PP +where +.I file.pdf +is your PDF file. The file name can be followed by a number +specifying the page which should be displayed first, e.g.: +.PP +.RS +xpdf file.pdf 18 +.RE +.PP +You can also give a named destination, prefixed with \'+' in place of +the page number. (This is only useful with PDF files that provide +named destination targets.) +.PP +You can also start xpdf without opening any files: +.PP +.RS +xpdf +.RE +.SH CONFIGURATION FILE +Xpdf reads a configuration file at startup. It first tries to find +the user's private config file, ~/.xpdfrc. If that doesn't exist, it +looks for a system-wide config file, typically /usr/local/etc/xpdfrc +(but this location can be changed when xpdf is built). See the +.BR xpdfrc (5) +man page for details. +.SH OPTIONS +Many of the following options can be set with configuration file +commands or X resources. These are listed in square brackets with the +description of the corresponding command line option. +.TP +.BI \-g " geometry" +Set the initial window geometry. +.RB ( \-geometry +is equivalent.) +.RB "[X resource: " xpdf.geometry ] +.TP +.BI \-title " title" +Set the window title. By default, the title will be "xpdf: foo.pdf". +.RB "[X resource: " xpdf.title ] +.TP +.B \-cmap +Install a private colormap. This is ignored on TrueColor visuals. +.RB "[X resource: " xpdf.installCmap ] +.TP +.BI \-rgb " number" +Set the size of largest RGB cube xpdf will try to allocate. The +default is 5 (for a 5x5x5 cube); set to a smaller number to conserve +color table entries. This is ignored with private colormaps and on +TrueColor visuals. +.RB "[X resource: " xpdf.rgbCubeSize ] +.TP +.B \-rv +Set reverse video mode. This reverses the colors of everything except +images. It may not always produce great results for PDF files which +do weird things with color. This also causes the paper color to +default to black. +.RB "[X resource: " xpdf.reverseVideo ] +.TP +.BI \-papercolor " color" +Set the "paper color", i.e., the background of the page display. This +will not work too well with PDF files that do things like filling in +white behind the text. +.RB "[X resource: " xpdf.paperColor ] +.TP +.BI \-mattecolor " color" +Set the matte color, i.e., the color used for background outside the +actual page area. (There is a separate setting, +xpdf.fullScreenMatteColor, for full-screen mode.) +.RB "[X resource: " xpdf.matteColor ] +.TP +.BI \-z " zoom" +Set the initial zoom factor. A number specifies a zoom percentage, +where 100 means 72 dpi.You may also specify \'page', to fit the page +to the window size, or \'width', to fit the page width to the window +width. +.RB "[config file: " initialZoom "; or X resource: " xpdf.initialZoom ] +.TP +.B \-cont +Start in continuous view mode, i.e., with one vertical scroll bar for +the whole document. +.RB "[config file: " continuousView ] +.TP +.BI \-t1lib " yes | no" +Enable or disable t1lib (a Type 1 font rasterizer). This defaults to +"yes". +.RB "[config file: " enableT1lib ] +.TP +.BI \-freetype " yes | no" +Enable or disable FreeType (a TrueType / Type 1 font rasterizer). +This defaults to "yes". +.RB "[config file: " enableFreeType ] +.TP +.BI \-aa " yes | no" +Enable or disable font anti-aliasing. This defaults to "yes". +.RB "[config file: " antialias ] +.TP +.BI \-aaVector " yes | no" +Enable or disable vector anti-aliasing. This defaults to "yes". +.RB "[config file: " vectorAntialias ] +.TP +.BI \-ps " PS-file" +Set the default file name for PostScript output (i.e., the name which +will appear in the print dialog). This can also be of the form +\'|command' to pipe the PostScript through a command. +.RB "[config file: " psFile ] +.TP +.BI \-paper " size" +Set the paper size to one of "letter", "legal", "A4", or "A3". This +can also be set to "match", which will set the paper size to match the +size specified in the PDF file. +.RB "[config file: " psPaperSize ] +.TP +.BI \-paperw " size" +Set the paper width, in points. +.RB "[config file: " psPaperSize ] +.TP +.BI \-paperh " size" +Set the paper height, in points. +.RB "[config file: " psPaperSize ] +.TP +.B \-level1 +Generate Level 1 PostScript. The resulting PostScript files will be +significantly larger (if they contain images), but will print on Level +1 printers. This also converts all images to black and white. +.RB "[config file: " psLevel ] +.TP +.BI \-enc " encoding-name" +Sets the encoding to use for text output. The +.I encoding\-name +must be defined with the unicodeMap command (see +.BR xpdfrc (5)). +This defaults to "Latin1" (which is a built-in encoding). +.RB "[config file: " textEncoding ] +.TP +.BI \-eol " unix | dos | mac" +Sets the end-of-line convention to use for text output. +.RB "[config file: " textEOL ] +.TP +.BI \-opw " password" +Specify the owner password for the PDF file. Providing this will +bypass all security restrictions. +.TP +.BI \-upw " password" +Specify the user password for the PDF file. +.TP +.B \-fullscreen +Open xpdf in full-screen mode, useful for presentations. +.TP +.BI \-remote " name" +Start/contact xpdf remote server with specified name (see the +.B "REMOTE SERVER MODE" +section below). +.TP +.BI \-exec " command" +Execute a command (see the +.B COMMANDS +section below) in an xpdf remote server window (with -remote only). +.TP +.B \-reload +Reload xpdf remote server window (with -remote only). +.TP +.B \-raise +Raise xpdf remote server window (with -remote only). +.TP +.B \-quit +Kill xpdf remote server (with -remote only). +.TP +.B \-cmd +Print commands as they're executed (useful for debugging). +.RB "[config file: " printCommands ] +.TP +.B \-q +Don't print any messages or errors. +.RB "[config file: " errQuiet ] +.TP +.BI \-cfg " config-file" +Read +.I config-file +in place of ~/.xpdfrc or the system-wide config file. +.TP +.B \-v +Print copyright and version information. +.TP +.B \-h +Print usage information. +.RB ( \-help +and +.B \-\-help +are equivalent.) +.PP +Several other standard X options and resources will work as expected: +.TP +.BI \-display " display" +.RB "[X resource: " xpdf.display ] +.TP +.BI \-fg " color" +.RB ( \-foreground +is equivalent.) +.RB "[X resource: " xpdf*Foreground ] +.TP +.BI \-bg " color" +.RB ( \-background +is equivalent.) +.RB "[X resource: " xpdf*Background ] +.TP +.BI \-font " font" +.RB ( \-fn +is equivalent.) +.RB "[X resource: " xpdf*fontList ] +.PP +The color and font options only affect the user interface elements, +not the PDF display (the \'paper'). +.PP +The following X resources do not have command line option equivalents: +.TP +.B xpdf.toolTipEnable +Enables (if set to true) or disables (if set to false) the tool-tips +on the toolbar buttons. +.TP +.B xpdf.fullScreenMatteColor +Sets the matte color to be used in full-screen mode. The default +setting is "black". +.SH CONTROLS +.SS On-screen controls, at the bottom of the xpdf window +.TP +.B "left/right arrow buttons" +Move to the previous/next page. +.TP +.B "double left/right arrow buttons" +Move backward or forward by ten pages. +.TP +.B "dashed left/right arrow buttons" +Move backward or forward along the history path. +.TP +.B "\'Page' entry box" +Move to a specific page number. Click in the box to activate it, type +the page number, then hit return. +.TP +.B "zoom popup menu" +Change the zoom factor (see the description of the -z option above). +.TP +.B "binoculars button" +Find a text string. +.TP +.B "print button" +Bring up a dialog for generating a PostScript file. The dialog has +options to set the pages to be printed and the PostScript file name. +The file name can be \'-' for stdout or \'|command' to pipe the +PostScript through a command, e.g., \'|lpr'. +.TP +.B "\'?' button" +Bring up the \'about xpdf' window. +.TP +.B "link info" +The space between the \'?' and \'Quit' buttons is used to show the URL +or external file name when the mouse is over a link. +.TP +.B "\'Quit' button" +Quit xpdf. +.PP +.SS Menu +Pressing the right mouse button will post a popup menu with the +following commands: +.TP +.B "Open..." +Open a new PDF file via a file requester. +.TP +.B "Open in new window..." +Create a new window and open a new PDF file via a file requester. +.TP +.B "Reload" +Reload the current PDF file. Note that Xpdf will reload the file +automatically (on a page change or redraw) if it has changed since it +was last loaded. +.TP +.B "Save as..." +Save the current file via a file requester. +.TP +.B "Continuous view" +Toggles between single page and continuous view modes. +.TP +.B "Rotate counterclockwise" +Rotate the page 90 degrees counterclockwise. +.TP +.B "Rotate clockwise" +Rotate the page 90 degrees clockwise. The two rotate commands are +intended primarily for PDF files where the rotation isn't correctly +specified in the file. +.TP +.B "Zoom to selection" +Zoom in to the currently selected rectangle. +.TP +.B "Close" +Close the current window. If this is the only open window, the +document is closed, but the window is left open (i.e., this menu +command won't quit xpdf). +.TP +.B "Quit" +Quit xpdf. +.PP +.SS Outline +If the PDF contains an outline (a.k.a., bookmarks), there will be an +outline pane on the left side of the window. The width of the outline +pane is adjustable with a vertical split bar via the knob near its +bottom end. +.PP +.SS Text selection +Dragging the mouse with the left button held down will highlight an +arbitrary rectangle. Any text inside this rectangle will be copied to +the X selection buffer. +.PP +.SS Links +Clicking on a hyperlink will jump to the link's destination. A link +to another PDF document will make xpdf load that document. A +\'launch' link to an executable program will display a dialog, and if +you click \'ok', execute the program. URL links call an external +command (see the +.B WEB BROWSERS +section below). +.PP +.SS Panning +Dragging the mouse with the middle button held down pans the window. +.PP +.SS Key bindings +.TP +.B o +Open a new PDF file via a file requester. +.TP +.B r +Reload the current PDF file. Note that Xpdf will reload the file +automatically (on a page change or redraw) if it has changed since it +was last loaded. +.TP +.B control-L +Redraw the current page. +.TP +.B control-W +Close the current window. +.TP +.B f or control-F +Find a text string. +.TP +.B control-G +Find next occurrence. +.TP +.B control-P +Print. +.TP +.B n +Move to the next page. Scrolls to the top of the page, unless scroll +lock is turned on. +.TP +.B p +Move to the previous page. Scrolls to the top of the page, unless +scroll lock is turned on. +.TP +.BR " or " " or " +Scroll down on the current page; if already at bottom, move to next +page. +.TP +.BR " or " " or " " or " +Scroll up on the current page; if already at top, move to previous +page. +.TP +.B v +Move forward along the history path. +.TP +.B b +Move backward along the history path. +.TP +.B +Scroll to top of current page. +.TP +.B +Scroll to bottom of current page. +.TP +.B control- +Scroll to first page of document. +.TP +.B control- +Scroll to last page of document. +.TP +.B arrows +Scroll the current page. +.TP +.B g +Activate the page number text field ("goto page"). +.TP +.B 0 +Set the zoom factor to 125%. +.TP +.B + +Zoom in (increment the zoom factor by 1). +.TP +.B - +Zoom out (decrement the zoom factor by 1). +.TP +.B z +Set the zoom factor to 'page' (fit page to window). +.TP +.B w +Set the zoom factor to 'width' (fit page width to window). +.TP +.B alt-F +Toggle full-screen mode. +.TP +.B q +Quit xpdf. +.SH "WEB BROWSERS" +If you want to run xpdf automatically from netscape or mosaic (and +probably other browsers) when you click on a link to a PDF file, you +need to edit (or create) the files +.I .mime.types +and +.I .mailcap +in your home directory. In +.I .mime.types +add the line: +.PP +.RS +application/pdf pdf +.RE +.PP +In +.I .mailcap +add the lines: +.PP +.RS +# Use xpdf to view PDF files. +.RE +.RS +application/pdf; xpdf -q %s +.RE +.PP +Make sure that xpdf is on your executable search path. +.PP +When you click on a URL link in a PDF file, xpdf will execute the +command specified by the urlCommand config file option, replacing an +occurrence of \'%s' with the URL. For example, to call netscape with +the URL, add this line to your config file: +.PP +.RS +urlCommand "netscape -remote 'openURL(%s)'" +.RE +.SH COMMANDS +Xpdf's key and mouse bindings are user-configurable, using the bind and +unbind options in the config file (see +.BR xpdfrc (5)). +The bind command allows you to bind a key or mouse button to a +sequence of one or more commands. +.SS Available Commands +The following commands are supported: +.TP +.BI gotoPage( page ) +Go to the specified page. +.TP +.BI gotoPageNoScroll( page ) +Go to the specified page, with the current relative scroll position. +.TP +.BI gotoDest( dest ) +Go to a named destination. +.TP +.B gotoLastPage +Go to the last page in the PDF file. +.TP +.B gotoLastPageNoScroll +Go to the last page in the PDF file, with the current relative scroll +position. +.TP +.B nextPage +Go to the next page. +.TP +.B nextPageNoScroll +Go to the next page, with the current relative scroll position. +.TP +.B prevPage +Go to the previous page. +.TP +.B prevPageNoScroll +Go to the previous page, with the current relative scroll position. +.TP +.B pageUp +Scroll up by one screenful. +.TP +.B pageDown +Scroll down by one screenful. +.TP +.BI scrollLeft( n ) +Scroll left by +.I n +pixels. +.TP +.BI scrollRight( n ) +Scroll right by +.I n +pixels. +.TP +.BI scrollUp( n ) +Scroll up by +.I n +pixels. +.TP +.BI scrollDown( n ) +Scroll down by +.I n +pixels. +.TP +.BI scrollUpPrevPage( n ) +Scroll up by +.I n +pixels, moving to the previous page if appropriate. +.TP +.BI scrollDownPrevPage( n ) +Scroll down by +.I n +pixels, moving to the next page if appropriate. +.TP +.B scrollToTopEdge +Scroll to the top edge of the current page, with no horizontal +movement. +.TP +.B scrollToBottomEdge +Scroll to the bottom edge of the current page, with no horizontal +movement. +.TP +.B scrollToLeftEdge +Scroll to the left edge of the current page, with no vertical +movement. +.TP +.B scrollToRightEdge +Scroll to the right edge of the current page, with no vertical +movement. +.TP +.B scrollToTopLeft +Scroll to the top-left corner of the current page. +.TP +.B scrollToBottomRight +Scroll to the bottom-right corner of the current page. +.TP +.B goForward +Move forward along the history path. +.TP +.B goBackward +Move backward along the history path. +.TP +.BI zoomPercent( z ) +Set the zoom factor to +.IR z %. +.TP +.B zoomFitPage +Set the zoom factor to fit-page. +.TP +.B zoomFitWidth +Set the zoom factor to fit-width. +.TP +.B zoomIn +Zoom in - go to the next higher zoom factor. +.TP +.B zoomOut +Zoom out - go the next lower zoom factor. +.TP +.B continuousMode +Go to continuous view mode. +.TP +.B singlePageMode +Go to single-page view mode. +.TP +.B toggleContinuousMode +Toggle between continuous and single page view modes. +.TP +.B fullScreenMode +Go to full-screen mode. +.TP +.B windowMode +Go to window (non-full-screen) mode. +.TP +.B toggleFullScreenMode +Toggle between full-screen and window modes. +.TP +.B open +Open a PDF file in this window, using the open dialog. +.TP +.B openInNewWin +Open a PDF file in a new window, using the open dialog. +.TP +.BI openFile( file ) +Open a specified PDF file in this window. +.TP +.BI openFileInNewWin( file ) +Open a specified PDF file in a new window. +.TP +.BI openFileAtDest( file , dest ) +Open a specified PDF file in this window and go to a named +destination. +.TP +.BI openFileAtDestInNewWin( file , dest ) +Open a specified PDF file in a new window and go to a named +destination. +.TP +.B reload +Reload the current PDF file. +.TP +.B redraw +Redraw the window. +.TP +.B raise +Raise the window to the front. +.TP +.B closeWindow +Close the window. +.TP +.BI run( external-command-string ) +Run an external command. The following escapes are allowed in the +command string: +.nf + + %f => PDF file name (or an empty string if no + file is open) + %b => PDF file base name, i.e., file name minus + the extension (or an empty string if no + file is open) + %u => link URL (or an empty string if not over + a URL link) + %x => selection upper-left x coordinate + (or 0 if there is no selection) + %y => selection upper-left y coordinate + (or 0 if there is no selection) + %X => selection lower-right x coordinate + (or 0 if there is no selection) + %Y => selection lower-right y coordinate + (or 0 if there is no selection) + %% => % + +.fi +.TP +.B openOutline +Open the outline pane. +.TP +.B closeOutline +Close the outline pane. +.TP +.B toggleOutline +Toggle the outline pane between open and closed. +.TP +.BI scrollOutlineDown( n ) +Scroll the outline down by +.I n +increments. +.TP +.BI scrollOutlineUp( n ) +Scroll the outline up by +.I n +increments. +.TP +.B focusToDocWin +Set the keyboard focus to the main document window. +.TP +.B focusToPageNum +Set the keyboard focus to the page number text box. +.TP +.B find +Open the 'find' dialog. +.TP +.B findNext +Finds the next occurrence of the search string (no dialog). +.TP +.B print +Open the 'print' dialog. +.TP +.B about +Open the 'about' dialog. +.TP +.B quit +Quit from xpdf. +.PP +The following commands depend on the current mouse position: +.TP +.B startSelection +Start a selection, which will be extended as the mouse moves. +.TP +.B endSelection +End a selection. +.TP +.B startPan +Start a pan, which will scroll the document as the mouse moves +.TP +.B endPan +End a pan. +.TP +.B postPopupMenu +Display the popup menu. +.TP +.B followLink +Follow a hyperlink (does nothing if the mouse is not over a link). +.TP +.B followLinkInNewWin +Follow a hyperlink, opening PDF files in a new window (does nothing if +the mouse is not over a link). For links to non-PDF files, this +command is identical to followLink. +.TP +.B followLinkNoSel +Same as followLink, but does nothing if there is a non-empty selection. +(This is useful as a mouse button binding.) +.TP +.B followLinkInNewWinNoSel +Same as followLinkInNewWin, but does nothing if there is a non-empty +selection. (This is useful as a mouse button binding.) +.SS Default Bindings +The default mouse bindings are as follows: +.nf + + bind mousePress1 any startSelection + bind mouseRelease1 any endSelection followLinkNoSel + bind mousePress2 any startPan + bind mouseRelease2 any endPan + bind mousePress3 any postPopupMenu + bind mousePress4 any scrollUpPrevPage(16) + bind mousePress5 any scrollDownNextPage(16) + bind mousePress6 any scrollLeft(16) + bind mousePress7 any scrollRight(16) + +.fi +The default key bindings are as follows: +.nf + + bind ctrl-home any gotoPage(1) + bind home any scrollToTopLeft + bind ctrl-end any gotoLastPage + bind end any scrollToBottomRight + bind pgup any pageUp + bind backspace any pageUp + bind delete any pageUp + bind pgdn any pageDown + bind space any pageDown + bind left any scrollLeft(16) + bind right any scrollRight(16) + bind up any scrollUp(16) + bind down any scrollDown(16) + bind o any open + bind O any open + bind r any reload + bind R any reload + bind f any find + bind F any find + bind ctrl-f any find + bind ctrl-g any findNext + bind ctrl-p any print + bind n scrLockOff nextPage + bind N scrLockOff nextPage + bind n scrLockOn nextPageNoScroll + bind N scrLockOn nextPageNoScroll + bind p scrLockOff prevPage + bind P scrLockOff prevPage + bind p scrLockOn prevPageNoScroll + bind P scrLockOn prevPageNoScroll + bind v any goForward + bind b any goBackward + bind g any focusToPageNum + bind 0 any zoomPercent(125) + bind + any zoomIn + bind - any zoomOut + bind z any zoomFitPage + bind w any zoomFitWidth + bind alt-f any toggleFullScreenMode + bind ctrl-l any redraw + bind ctrl-w any closeWindow + bind ? any about + bind q any quit + bind Q any quit + +.fi +Previous versions of xpdf included a "viKeys" X resource. It is no +longer available, but the following bindings are equivalent: +.nf + + bind h any scrollLeft(16) + bind l any scrollRight(16) + bind k any scrollUp(16) + bind j any scrollDown(16) + +.fi +.SH "REMOTE SERVER MODE" +Xpdf can be started in remote server mode by specifying a server name +(in addition to the file name and page number). For example: +.PP +.RS +xpdf -remote myServer file.pdf +.RE +.PP +If there is currently no xpdf running in server mode with the name +\'myServer', a new xpdf window will be opened. If another command: +.PP +.RS +xpdf -remote myServer another.pdf 9 +.RE +.PP +is issued, a new copy of xpdf will not be started. Instead, the first +xpdf (the server) will load +.I another.pdf +and display page nine. If the file name is the same: +.PP +.RS +xpdf -remote myServer another.pdf 4 +.RE +.PP +the xpdf server will simply display the specified page. +.PP +The -raise option tells the server to raise its window; it can be +specified with or without a file name and page number. +.PP +The -quit option tells the server to close its window and exit. +.SH EXIT CODES +The Xpdf tools use the following exit codes: +.TP +0 +No error. +.TP +1 +Error opening a PDF file. +.TP +2 +Error opening an output file. +.TP +3 +Error related to PDF permissions. +.TP +99 +Other error. +.SH AUTHOR +The xpdf software and documentation are copyright 1996-2007 Glyph & +Cog, LLC. +.SH "SEE ALSO" +.BR pdftops (1), +.BR pdftotext (1), +.BR pdfinfo (1), +.BR pdffonts (1), +.BR pdftoppm (1), +.BR pdfimages (1), +.BR xpdfrc (5) +.br +.B http://www.foolabs.com/xpdf/ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFApp.cc swftools-0.9.1/lib/pdf/xpdf/XPDFApp.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFApp.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XPDFApp.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,447 @@ +//======================================================================== +// +// XPDFApp.cc +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include "GString.h" +#include "GList.h" +#include "Error.h" +#include "XPDFViewer.h" +#include "XPDFApp.h" +#include "config.h" + +// these macro defns conflict with xpdf's Object class +#ifdef LESSTIF_VERSION +#undef XtDisplay +#undef XtScreen +#undef XtWindow +#undef XtParent +#undef XtIsRealized +#endif + +//------------------------------------------------------------------------ + +#define remoteCmdSize 512 + +//------------------------------------------------------------------------ + +static String fallbackResources[] = { + "*.zoomComboBox*fontList: -*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1", + "*XmTextField.fontList: -*-courier-medium-r-normal--12-*-*-*-*-*-iso8859-1", + "*.fontList: -*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1", + "*XmTextField.translations: #override\\n" + " Ctrla:beginning-of-line()\\n" + " Ctrlb:backward-character()\\n" + " Ctrld:delete-next-character()\\n" + " Ctrle:end-of-line()\\n" + " Ctrlf:forward-character()\\n" + " Ctrlu:beginning-of-line()delete-to-end-of-line()\\n" + " Ctrlk:delete-to-end-of-line()\\n", + "*.toolTipEnable: True", + "*.toolTipPostDelay: 1500", + "*.toolTipPostDuration: 0", + "*.TipLabel.foreground: black", + "*.TipLabel.background: LightYellow", + "*.TipShell.borderWidth: 1", + "*.TipShell.borderColor: black", + NULL +}; + +static XrmOptionDescRec xOpts[] = { + {"-display", ".display", XrmoptionSepArg, NULL}, + {"-foreground", "*Foreground", XrmoptionSepArg, NULL}, + {"-fg", "*Foreground", XrmoptionSepArg, NULL}, + {"-background", "*Background", XrmoptionSepArg, NULL}, + {"-bg", "*Background", XrmoptionSepArg, NULL}, + {"-geometry", ".geometry", XrmoptionSepArg, NULL}, + {"-g", ".geometry", XrmoptionSepArg, NULL}, + {"-font", "*.fontList", XrmoptionSepArg, NULL}, + {"-fn", "*.fontList", XrmoptionSepArg, NULL}, + {"-title", ".title", XrmoptionSepArg, NULL}, + {"-cmap", ".installCmap", XrmoptionNoArg, (XPointer)"on"}, + {"-rgb", ".rgbCubeSize", XrmoptionSepArg, NULL}, + {"-rv", ".reverseVideo", XrmoptionNoArg, (XPointer)"true"}, + {"-papercolor", ".paperColor", XrmoptionSepArg, NULL}, + {"-mattecolor", ".matteColor", XrmoptionSepArg, NULL}, + {"-z", ".initialZoom", XrmoptionSepArg, NULL} +}; + +#define nXOpts (sizeof(xOpts) / sizeof(XrmOptionDescRec)) + +struct XPDFAppResources { + String geometry; + String title; + Bool installCmap; + int rgbCubeSize; + Bool reverseVideo; + String paperColor; + String matteColor; + String fullScreenMatteColor; + String initialZoom; +}; + +static Bool defInstallCmap = False; +static int defRGBCubeSize = defaultRGBCube; +static Bool defReverseVideo = False; + +static XtResource xResources[] = { + { "geometry", "Geometry", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, geometry), XtRString, (XtPointer)NULL }, + { "title", "Title", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, title), XtRString, (XtPointer)NULL }, + { "installCmap", "InstallCmap", XtRBool, sizeof(Bool), XtOffsetOf(XPDFAppResources, installCmap), XtRBool, (XtPointer)&defInstallCmap }, + { "rgbCubeSize", "RgbCubeSize", XtRInt, sizeof(int), XtOffsetOf(XPDFAppResources, rgbCubeSize), XtRInt, (XtPointer)&defRGBCubeSize }, + { "reverseVideo", "ReverseVideo", XtRBool, sizeof(Bool), XtOffsetOf(XPDFAppResources, reverseVideo), XtRBool, (XtPointer)&defReverseVideo }, + { "paperColor", "PaperColor", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, paperColor), XtRString, (XtPointer)NULL }, + { "matteColor", "MatteColor", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, matteColor), XtRString, (XtPointer)"gray50" }, + { "fullScreenMatteColor", "FullScreenMatteColor", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, fullScreenMatteColor), XtRString, (XtPointer)"black" }, + { "initialZoom", "InitialZoom", XtRString, sizeof(String), XtOffsetOf(XPDFAppResources, initialZoom), XtRString, (XtPointer)NULL } +}; + +#define nXResources (sizeof(xResources) / sizeof(XtResource)) + +//------------------------------------------------------------------------ +// XPDFApp +//------------------------------------------------------------------------ + +#if 0 //~ for debugging +static int xErrorHandler(Display *display, XErrorEvent *ev) { + printf("X error:\n"); + printf(" resource ID = %08lx\n", ev->resourceid); + printf(" serial = %lu\n", ev->serial); + printf(" error_code = %d\n", ev->error_code); + printf(" request_code = %d\n", ev->request_code); + printf(" minor_code = %d\n", ev->minor_code); + fflush(stdout); + abort(); +} +#endif + +XPDFApp::XPDFApp(int *argc, char *argv[]) { + appShell = XtAppInitialize(&appContext, xpdfAppName, xOpts, nXOpts, + argc, argv, fallbackResources, NULL, 0); + display = XtDisplay(appShell); + screenNum = XScreenNumberOfScreen(XtScreen(appShell)); +#if XmVERSION > 1 + XtVaSetValues(XmGetXmDisplay(XtDisplay(appShell)), + XmNenableButtonTab, True, NULL); +#endif +#if XmVERSION > 1 + // Drag-and-drop appears to be buggy -- I'm seeing weird crashes + // deep in the Motif code when I destroy widgets in the XpdfForms + // code. Xpdf doesn't use it, so just turn it off. + XtVaSetValues(XmGetXmDisplay(XtDisplay(appShell)), + XmNdragInitiatorProtocolStyle, XmDRAG_NONE, + XmNdragReceiverProtocolStyle, XmDRAG_NONE, + NULL); +#endif + +#if 0 //~ for debugging + XSynchronize(display, True); + XSetErrorHandler(&xErrorHandler); +#endif + + fullScreen = gFalse; + remoteAtom = None; + remoteViewer = NULL; + remoteWin = None; + + getResources(); + + viewers = new GList(); + +} + +void XPDFApp::getResources() { + XPDFAppResources resources; + XColor xcol, xcol2; + Colormap colormap; + + XtGetApplicationResources(appShell, &resources, xResources, nXResources, + NULL, 0); + geometry = resources.geometry ? new GString(resources.geometry) + : (GString *)NULL; + title = resources.title ? new GString(resources.title) : (GString *)NULL; + installCmap = (GBool)resources.installCmap; + rgbCubeSize = resources.rgbCubeSize; + reverseVideo = (GBool)resources.reverseVideo; + if (reverseVideo) { + paperRGB[0] = paperRGB[1] = paperRGB[2] = 0; + paperPixel = BlackPixel(display, screenNum); + } else { + paperRGB[0] = paperRGB[1] = paperRGB[2] = 0xff; + paperPixel = WhitePixel(display, screenNum); + } + XtVaGetValues(appShell, XmNcolormap, &colormap, NULL); + if (resources.paperColor) { + if (XAllocNamedColor(display, colormap, resources.paperColor, + &xcol, &xcol2)) { + paperRGB[0] = xcol.red >> 8; + paperRGB[1] = xcol.green >> 8; + paperRGB[2] = xcol.blue >> 8; + paperPixel = xcol.pixel; + } else { + error(-1, "Couldn't allocate color '%s'", resources.paperColor); + } + } + if (XAllocNamedColor(display, colormap, resources.matteColor, + &xcol, &xcol2)) { + mattePixel = xcol.pixel; + } else { + mattePixel = paperPixel; + } + if (XAllocNamedColor(display, colormap, resources.fullScreenMatteColor, + &xcol, &xcol2)) { + fullScreenMattePixel = xcol.pixel; + } else { + fullScreenMattePixel = paperPixel; + } + initialZoom = resources.initialZoom ? new GString(resources.initialZoom) + : (GString *)NULL; +} + +XPDFApp::~XPDFApp() { + deleteGList(viewers, XPDFViewer); + if (geometry) { + delete geometry; + } + if (title) { + delete title; + } + if (initialZoom) { + delete initialZoom; + } +} + +XPDFViewer *XPDFApp::open(GString *fileName, int page, + GString *ownerPassword, GString *userPassword) { + XPDFViewer *viewer; + + viewer = new XPDFViewer(this, fileName, page, NULL, fullScreen, + ownerPassword, userPassword); + if (!viewer->isOk()) { + delete viewer; + return NULL; + } + if (remoteAtom != None) { + remoteViewer = viewer; + remoteWin = viewer->getWindow(); + XtAddEventHandler(remoteWin, PropertyChangeMask, False, + &remoteMsgCbk, this); + XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin), CurrentTime); + } + viewers->append(viewer); + return viewer; +} + +XPDFViewer *XPDFApp::openAtDest(GString *fileName, GString *dest, + GString *ownerPassword, + GString *userPassword) { + XPDFViewer *viewer; + + viewer = new XPDFViewer(this, fileName, 1, dest, fullScreen, + ownerPassword, userPassword); + if (!viewer->isOk()) { + delete viewer; + return NULL; + } + if (remoteAtom != None) { + remoteViewer = viewer; + remoteWin = viewer->getWindow(); + XtAddEventHandler(remoteWin, PropertyChangeMask, False, + &remoteMsgCbk, this); + XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin), CurrentTime); + } + viewers->append(viewer); + return viewer; +} + +XPDFViewer *XPDFApp::reopen(XPDFViewer *viewer, PDFDoc *doc, int page, + GBool fullScreenA) { + int i; + + for (i = 0; i < viewers->getLength(); ++i) { + if (((XPDFViewer *)viewers->get(i)) == viewer) { + viewers->del(i); + delete viewer; + } + } + viewer = new XPDFViewer(this, doc, page, NULL, fullScreenA); + if (!viewer->isOk()) { + delete viewer; + return NULL; + } + if (remoteAtom != None) { + remoteViewer = viewer; + remoteWin = viewer->getWindow(); + XtAddEventHandler(remoteWin, PropertyChangeMask, False, + &remoteMsgCbk, this); + XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin), CurrentTime); + } + viewers->append(viewer); + return viewer; +} + +void XPDFApp::close(XPDFViewer *viewer, GBool closeLast) { + int i; + + if (viewers->getLength() == 1) { + if (viewer != (XPDFViewer *)viewers->get(0)) { + return; + } + if (closeLast) { + quit(); + } else { + viewer->clear(); + } + } else { + for (i = 0; i < viewers->getLength(); ++i) { + if (((XPDFViewer *)viewers->get(i)) == viewer) { + viewers->del(i); + if (remoteAtom != None && remoteViewer == viewer) { + remoteViewer = (XPDFViewer *)viewers->get(viewers->getLength() - 1); + remoteWin = remoteViewer->getWindow(); + XSetSelectionOwner(display, remoteAtom, XtWindow(remoteWin), + CurrentTime); + } + delete viewer; + return; + } + } + } +} + +void XPDFApp::quit() { + if (remoteAtom != None) { + XSetSelectionOwner(display, remoteAtom, None, CurrentTime); + } + while (viewers->getLength() > 0) { + delete (XPDFViewer *)viewers->del(0); + } +#if HAVE_XTAPPSETEXITFLAG + XtAppSetExitFlag(appContext); +#else + exit(0); +#endif +} + +void XPDFApp::run() { + XtAppMainLoop(appContext); +} + +void XPDFApp::setRemoteName(char *remoteName) { + remoteAtom = XInternAtom(display, remoteName, False); + remoteXWin = XGetSelectionOwner(display, remoteAtom); +} + +GBool XPDFApp::remoteServerRunning() { + return remoteXWin != None; +} + +void XPDFApp::remoteExec(char *cmd) { + char cmd2[remoteCmdSize]; + int n; + + n = strlen(cmd); + if (n > remoteCmdSize - 2) { + n = remoteCmdSize - 2; + } + memcpy(cmd2, cmd, n); + cmd2[n] = '\n'; + cmd2[n+1] = '\0'; + XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8, + PropModeReplace, (Guchar *)cmd2, n + 2); + XFlush(display); +} + +void XPDFApp::remoteOpen(GString *fileName, int page, GBool raise) { + char cmd[remoteCmdSize]; + + sprintf(cmd, "openFileAtPage(%.200s,%d)\n", + fileName->getCString(), page); + if (raise) { + strcat(cmd, "raise\n"); + } + XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8, + PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1); + XFlush(display); +} + +void XPDFApp::remoteOpenAtDest(GString *fileName, GString *dest, GBool raise) { + char cmd[remoteCmdSize]; + + sprintf(cmd, "openFileAtDest(%.200s,%.256s)\n", + fileName->getCString(), dest->getCString()); + if (raise) { + strcat(cmd, "raise\n"); + } + XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8, + PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1); + XFlush(display); +} + +void XPDFApp::remoteReload(GBool raise) { + char cmd[remoteCmdSize]; + + strcpy(cmd, "reload\n"); + if (raise) { + strcat(cmd, "raise\n"); + } + XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8, + PropModeReplace, (Guchar *)cmd, strlen(cmd) + 1); + XFlush(display); +} + +void XPDFApp::remoteRaise() { + XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8, + PropModeReplace, (Guchar *)"raise\n", 7); + XFlush(display); +} + +void XPDFApp::remoteQuit() { + XChangeProperty(display, remoteXWin, remoteAtom, remoteAtom, 8, + PropModeReplace, (Guchar *)"quit\n", 6); + XFlush(display); +} + +void XPDFApp::remoteMsgCbk(Widget widget, XtPointer ptr, + XEvent *event, Boolean *cont) { + XPDFApp *app = (XPDFApp *)ptr; + char *cmd, *p0, *p1; + Atom type; + int format; + Gulong size, remain; + GString *cmdStr; + + if (event->xproperty.atom != app->remoteAtom) { + *cont = True; + return; + } + *cont = False; + + if (XGetWindowProperty(app->display, XtWindow(app->remoteWin), + app->remoteAtom, 0, remoteCmdSize/4, + True, app->remoteAtom, + &type, &format, &size, &remain, + (Guchar **)&cmd) != Success) { + return; + } + if (!cmd) { + return; + } + p0 = cmd; + while (*p0 && (p1 = strchr(p0, '\n'))) { + cmdStr = new GString(p0, p1 - p0); + app->remoteViewer->execCmd(cmdStr, NULL); + delete cmdStr; + p0 = p1 + 1; + } + XFree((XPointer)cmd); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFApp.h swftools-0.9.1/lib/pdf/xpdf/XPDFApp.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFApp.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XPDFApp.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,114 @@ +//======================================================================== +// +// XPDFApp.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef XPDFAPP_H +#define XPDFAPP_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#define Object XtObject +#include +#undef Object +#include "gtypes.h" +#include "SplashTypes.h" + +class GString; +class GList; +class PDFDoc; +class XPDFViewer; + +//------------------------------------------------------------------------ + +#define xpdfAppName "Xpdf" + +//------------------------------------------------------------------------ +// XPDFApp +//------------------------------------------------------------------------ + +class XPDFApp { +public: + + XPDFApp(int *argc, char *argv[]); + ~XPDFApp(); + + XPDFViewer *open(GString *fileName, int page = 1, + GString *ownerPassword = NULL, + GString *userPassword = NULL); + XPDFViewer *openAtDest(GString *fileName, GString *dest, + GString *ownerPassword = NULL, + GString *userPassword = NULL); + XPDFViewer *reopen(XPDFViewer *viewer, PDFDoc *doc, int page, + GBool fullScreenA); + void close(XPDFViewer *viewer, GBool closeLast); + void quit(); + + void run(); + + //----- remote server + void setRemoteName(char *remoteName); + GBool remoteServerRunning(); + void remoteExec(char *cmd); + void remoteOpen(GString *fileName, int page, GBool raise); + void remoteOpenAtDest(GString *fileName, GString *dest, GBool raise); + void remoteReload(GBool raise); + void remoteRaise(); + void remoteQuit(); + + //----- resource/option values + GString *getGeometry() { return geometry; } + GString *getTitle() { return title; } + GBool getInstallCmap() { return installCmap; } + int getRGBCubeSize() { return rgbCubeSize; } + GBool getReverseVideo() { return reverseVideo; } + SplashColorPtr getPaperRGB() { return paperRGB; } + Gulong getPaperPixel() { return paperPixel; } + Gulong getMattePixel(GBool fullScreenA) + { return fullScreenA ? fullScreenMattePixel : mattePixel; } + GString *getInitialZoom() { return initialZoom; } + void setFullScreen(GBool fullScreenA) { fullScreen = fullScreenA; } + GBool getFullScreen() { return fullScreen; } + + XtAppContext getAppContext() { return appContext; } + Widget getAppShell() { return appShell; } + +private: + + void getResources(); + static void remoteMsgCbk(Widget widget, XtPointer ptr, + XEvent *event, Boolean *cont); + + Display *display; + int screenNum; + XtAppContext appContext; + Widget appShell; + GList *viewers; // [XPDFViewer] + + Atom remoteAtom; + Window remoteXWin; + XPDFViewer *remoteViewer; + Widget remoteWin; + + //----- resource/option values + GString *geometry; + GString *title; + GBool installCmap; + int rgbCubeSize; + GBool reverseVideo; + SplashColor paperRGB; + Gulong paperPixel; + Gulong mattePixel; + Gulong fullScreenMattePixel; + GString *initialZoom; + GBool fullScreen; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/xpdf.cat swftools-0.9.1/lib/pdf/xpdf/xpdf.cat --- swftools-0.9.2+ds1/lib/pdf/xpdf/xpdf.cat 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/xpdf.cat 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,809 @@ +xpdf(1) xpdf(1) + + + +NAME + xpdf - Portable Document Format (PDF) file viewer for X + (version 3.02) + +SYNOPSIS + xpdf [options] [PDF-file [page | +dest]] + +DESCRIPTION + Xpdf is a viewer for Portable Document Format (PDF) files. + (These are also sometimes also called 'Acrobat' files, + from the name of Adobe's PDF software.) Xpdf runs under + the X Window System on UNIX, VMS, and OS/2. + + To run xpdf, simply type: + + xpdf file.pdf + + where file.pdf is your PDF file. The file name can be + followed by a number specifying the page which should be + displayed first, e.g.: + + xpdf file.pdf 18 + + You can also give a named destination, prefixed with '+' + in place of the page number. (This is only useful with + PDF files that provide named destination targets.) + + You can also start xpdf without opening any files: + + xpdf + +CONFIGURATION FILE + Xpdf reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when xpdf is built). See the xpdfrc(5) man + page for details. + +OPTIONS + Many of the following options can be set with configura- + tion file commands or X resources. These are listed in + square brackets with the description of the corresponding + command line option. + + -g geometry + Set the initial window geometry. (-geometry is + equivalent.) [X resource: xpdf.geometry] + + -title title + Set the window title. By default, the title will + be "xpdf: foo.pdf". [X resource: xpdf.title] + + -cmap Install a private colormap. This is ignored on + TrueColor visuals. [X resource: xpdf.installCmap] + + -rgb number + Set the size of largest RGB cube xpdf will try to + allocate. The default is 5 (for a 5x5x5 cube); set + to a smaller number to conserve color table + entries. This is ignored with private colormaps + and on TrueColor visuals. [X resource: + xpdf.rgbCubeSize] + + -rv Set reverse video mode. This reverses the colors + of everything except images. It may not always + produce great results for PDF files which do weird + things with color. This also causes the paper + color to default to black. [X resource: + xpdf.reverseVideo] + + -papercolor color + Set the "paper color", i.e., the background of the + page display. This will not work too well with PDF + files that do things like filling in white behind + the text. [X resource: xpdf.paperColor] + + -mattecolor color + Set the matte color, i.e., the color used for back- + ground outside the actual page area. (There is a + separate setting, xpdf.fullScreenMatteColor, for + full-screen mode.) [X resource: xpdf.matteColor] + + -z zoom + Set the initial zoom factor. A number specifies a + zoom percentage, where 100 means 72 dpi.You may + also specify 'page', to fit the page to the window + size, or 'width', to fit the page width to the win- + dow width. [config file: initialZoom; or X + resource: xpdf.initialZoom] + + -cont Start in continuous view mode, i.e., with one ver- + tical scroll bar for the whole document. [config + file: continuousView] + + -t1lib yes | no + Enable or disable t1lib (a Type 1 font rasterizer). + This defaults to "yes". [config file: enableT1lib] + + -freetype yes | no + Enable or disable FreeType (a TrueType / Type 1 + font rasterizer). This defaults to "yes". [config + file: enableFreeType] + + -aa yes | no + Enable or disable font anti-aliasing. This + defaults to "yes". [config file: antialias] + + -aaVector yes | no + Enable or disable vector anti-aliasing. This + defaults to "yes". [config file: vectorAntialias] + + -ps PS-file + Set the default file name for PostScript output + (i.e., the name which will appear in the print dia- + log). This can also be of the form '|command' to + pipe the PostScript through a command. [config + file: psFile] + + -paper size + Set the paper size to one of "letter", "legal", + "A4", or "A3". This can also be set to "match", + which will set the paper size to match the size + specified in the PDF file. [config file: psPaper- + Size] + + -paperw size + Set the paper width, in points. [config file: + psPaperSize] + + -paperh size + Set the paper height, in points. [config file: + psPaperSize] + + -level1 + Generate Level 1 PostScript. The resulting + PostScript files will be significantly larger (if + they contain images), but will print on Level 1 + printers. This also converts all images to black + and white. [config file: psLevel] + + -enc encoding-name + Sets the encoding to use for text output. The + encoding-name must be defined with the unicodeMap + command (see xpdfrc(5)). This defaults to "Latin1" + (which is a built-in encoding). [config file: tex- + tEncoding] + + -eol unix | dos | mac + Sets the end-of-line convention to use for text + output. [config file: textEOL] + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -fullscreen + Open xpdf in full-screen mode, useful for presenta- + tions. + + -remote name + Start/contact xpdf remote server with specified + name (see the REMOTE SERVER MODE section below). + + -exec command + Execute a command (see the COMMANDS section below) + in an xpdf remote server window (with -remote + only). + + -reload + Reload xpdf remote server window (with -remote + only). + + -raise Raise xpdf remote server window (with -remote + only). + + -quit Kill xpdf remote server (with -remote only). + + -cmd Print commands as they're executed (useful for + debugging). [config file: printCommands] + + -q Don't print any messages or errors. [config file: + errQuiet] + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the sys- + tem-wide config file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + + Several other standard X options and resources will work + as expected: + + -display display + [X resource: xpdf.display] + + -fg color + (-foreground is equivalent.) [X resource: + xpdf*Foreground] + + -bg color + (-background is equivalent.) [X resource: + xpdf*Background] + + -font font + (-fn is equivalent.) [X resource: xpdf*fontList] + + The color and font options only affect the user interface + elements, not the PDF display (the 'paper'). + + The following X resources do not have command line option + equivalents: + + xpdf.toolTipEnable + Enables (if set to true) or disables (if set to + false) the tool-tips on the toolbar buttons. + + xpdf.fullScreenMatteColor + Sets the matte color to be used in full-screen + mode. The default setting is "black". + +CONTROLS + On-screen controls, at the bottom of the xpdf window + left/right arrow buttons + Move to the previous/next page. + + double left/right arrow buttons + Move backward or forward by ten pages. + + dashed left/right arrow buttons + Move backward or forward along the history path. + + 'Page' entry box + Move to a specific page number. Click in the box + to activate it, type the page number, then hit + return. + + zoom popup menu + Change the zoom factor (see the description of the + -z option above). + + binoculars button + Find a text string. + + print button + Bring up a dialog for generating a PostScript file. + The dialog has options to set the pages to be + printed and the PostScript file name. The file + name can be '-' for stdout or '|command' to pipe + the PostScript through a command, e.g., '|lpr'. + + '?' button + Bring up the 'about xpdf' window. + + link info + The space between the '?' and 'Quit' buttons is + used to show the URL or external file name when the + mouse is over a link. + + 'Quit' button + Quit xpdf. + + + Menu + Pressing the right mouse button will post a popup menu + with the following commands: + + Open... + Open a new PDF file via a file requester. + + Open in new window... + Create a new window and open a new PDF file via a + file requester. + + Reload Reload the current PDF file. Note that Xpdf will + reload the file automatically (on a page change or + redraw) if it has changed since it was last loaded. + + Save as... + Save the current file via a file requester. + + Continuous view + Toggles between single page and continuous view + modes. + + Rotate counterclockwise + Rotate the page 90 degrees counterclockwise. + + Rotate clockwise + Rotate the page 90 degrees clockwise. The two + rotate commands are intended primarily for PDF + files where the rotation isn't correctly specified + in the file. + + Zoom to selection + Zoom in to the currently selected rectangle. + + Close Close the current window. If this is the only open + window, the document is closed, but the window is + left open (i.e., this menu command won't quit + xpdf). + + Quit Quit xpdf. + + + Outline + If the PDF contains an outline (a.k.a., bookmarks), there + will be an outline pane on the left side of the window. + The width of the outline pane is adjustable with a verti- + cal split bar via the knob near its bottom end. + + + Text selection + Dragging the mouse with the left button held down will + highlight an arbitrary rectangle. Any text inside this + rectangle will be copied to the X selection buffer. + + + Links + Clicking on a hyperlink will jump to the link's + destination. A link to another PDF document will make + xpdf load that document. A 'launch' link to an executable + program will display a dialog, and if you click 'ok', exe- + cute the program. URL links call an external command (see + the WEB BROWSERS section below). + + + Panning + Dragging the mouse with the middle button held down pans + the window. + + + Key bindings + o Open a new PDF file via a file requester. + + r Reload the current PDF file. Note that Xpdf will + reload the file automatically (on a page change or + redraw) if it has changed since it was last loaded. + + control-L + Redraw the current page. + + control-W + Close the current window. + + f or control-F + Find a text string. + + control-G + Find next occurrence. + + control-P + Print. + + n Move to the next page. Scrolls to the top of the + page, unless scroll lock is turned on. + + p Move to the previous page. Scrolls to the top of + the page, unless scroll lock is turned on. + + or or + Scroll down on the current page; if already at bot- + tom, move to next page. + + or or or + Scroll up on the current page; if already at top, + move to previous page. + + v Move forward along the history path. + + b Move backward along the history path. + + Scroll to top of current page. + + Scroll to bottom of current page. + + control- + Scroll to first page of document. + + control- + Scroll to last page of document. + + arrows Scroll the current page. + + g Activate the page number text field ("goto page"). + + 0 Set the zoom factor to 125%. + + + Zoom in (increment the zoom factor by 1). + + - Zoom out (decrement the zoom factor by 1). + + z Set the zoom factor to 'page' (fit page to window). + + w Set the zoom factor to 'width' (fit page width to + window). + + alt-F Toggle full-screen mode. + + q Quit xpdf. + +WEB BROWSERS + If you want to run xpdf automatically from netscape or + mosaic (and probably other browsers) when you click on a + link to a PDF file, you need to edit (or create) the files + .mime.types and .mailcap in your home directory. In + .mime.types add the line: + + application/pdf pdf + + In .mailcap add the lines: + + # Use xpdf to view PDF files. + application/pdf; xpdf -q %s + + Make sure that xpdf is on your executable search path. + + When you click on a URL link in a PDF file, xpdf will exe- + cute the command specified by the urlCommand config file + option, replacing an occurrence of '%s' with the URL. For + example, to call netscape with the URL, add this line to + your config file: + + urlCommand "netscape -remote 'openURL(%s)'" + +COMMANDS + Xpdf's key and mouse bindings are user-configurable, using + the bind and unbind options in the config file (see + xpdfrc(5)). The bind command allows you to bind a key or + mouse button to a sequence of one or more commands. + + Available Commands + The following commands are supported: + + gotoPage(page) + Go to the specified page. + + gotoPageNoScroll(page) + Go to the specified page, with the current relative + scroll position. + + gotoDest(dest) + Go to a named destination. + + gotoLastPage + Go to the last page in the PDF file. + + gotoLastPageNoScroll + Go to the last page in the PDF file, with the cur- + rent relative scroll position. + + nextPage + Go to the next page. + + nextPageNoScroll + Go to the next page, with the current relative + scroll position. + + prevPage + Go to the previous page. + + prevPageNoScroll + Go to the previous page, with the current relative + scroll position. + + pageUp Scroll up by one screenful. + + pageDown + Scroll down by one screenful. + + scrollLeft(n) + Scroll left by n pixels. + + scrollRight(n) + Scroll right by n pixels. + + scrollUp(n) + Scroll up by n pixels. + + scrollDown(n) + Scroll down by n pixels. + + scrollUpPrevPage(n) + Scroll up by n pixels, moving to the previous page + if appropriate. + + scrollDownPrevPage(n) + Scroll down by n pixels, moving to the next page if + appropriate. + + scrollToTopEdge + Scroll to the top edge of the current page, with no + horizontal movement. + + scrollToBottomEdge + Scroll to the bottom edge of the current page, with + no horizontal movement. + + scrollToLeftEdge + Scroll to the left edge of the current page, with + no vertical movement. + + scrollToRightEdge + Scroll to the right edge of the current page, with + no vertical movement. + + scrollToTopLeft + Scroll to the top-left corner of the current page. + + scrollToBottomRight + Scroll to the bottom-right corner of the current + page. + + goForward + Move forward along the history path. + + goBackward + Move backward along the history path. + + zoomPercent(z) + Set the zoom factor to z%. + + zoomFitPage + Set the zoom factor to fit-page. + + zoomFitWidth + Set the zoom factor to fit-width. + + zoomIn Zoom in - go to the next higher zoom factor. + + zoomOut + Zoom out - go the next lower zoom factor. + + continuousMode + Go to continuous view mode. + + singlePageMode + Go to single-page view mode. + + toggleContinuousMode + Toggle between continuous and single page view + modes. + + fullScreenMode + Go to full-screen mode. + + windowMode + Go to window (non-full-screen) mode. + + toggleFullScreenMode + Toggle between full-screen and window modes. + + open Open a PDF file in this window, using the open dia- + log. + + openInNewWin + Open a PDF file in a new window, using the open + dialog. + + openFile(file) + Open a specified PDF file in this window. + + openFileInNewWin(file) + Open a specified PDF file in a new window. + + openFileAtDest(file,dest) + Open a specified PDF file in this window and go to + a named destination. + + openFileAtDestInNewWin(file,dest) + Open a specified PDF file in a new window and go to + a named destination. + + reload Reload the current PDF file. + + redraw Redraw the window. + + raise Raise the window to the front. + + closeWindow + Close the window. + + run(external-command-string) + Run an external command. The following escapes are + allowed in the command string: + + %f => PDF file name (or an empty string if no + file is open) + %b => PDF file base name, i.e., file name minus + the extension (or an empty string if no + file is open) + %u => link URL (or an empty string if not over + a URL link) + %x => selection upper-left x coordinate + (or 0 if there is no selection) + %y => selection upper-left y coordinate + (or 0 if there is no selection) + %X => selection lower-right x coordinate + (or 0 if there is no selection) + %Y => selection lower-right y coordinate + (or 0 if there is no selection) + %% => % + + + openOutline + Open the outline pane. + + closeOutline + Close the outline pane. + + toggleOutline + Toggle the outline pane between open and closed. + + scrollOutlineDown(n) + Scroll the outline down by n increments. + + scrollOutlineUp(n) + Scroll the outline up by n increments. + + focusToDocWin + Set the keyboard focus to the main document window. + + focusToPageNum + Set the keyboard focus to the page number text box. + + find Open the 'find' dialog. + + findNext + Finds the next occurrence of the search string (no + dialog). + + print Open the 'print' dialog. + + about Open the 'about' dialog. + + quit Quit from xpdf. + + The following commands depend on the current mouse posi- + tion: + + startSelection + Start a selection, which will be extended as the + mouse moves. + + endSelection + End a selection. + + startPan + Start a pan, which will scroll the document as the + mouse moves + + endPan End a pan. + + postPopupMenu + Display the popup menu. + + followLink + Follow a hyperlink (does nothing if the mouse is + not over a link). + + followLinkInNewWin + Follow a hyperlink, opening PDF files in a new win- + dow (does nothing if the mouse is not over a link). + For links to non-PDF files, this command is identi- + cal to followLink. + + followLinkNoSel + Same as followLink, but does nothing if there is a + non-empty selection. (This is useful as a mouse + button binding.) + + followLinkInNewWinNoSel + Same as followLinkInNewWin, but does nothing if + there is a non-empty selection. (This is useful as + a mouse button binding.) + + Default Bindings + The default mouse bindings are as follows: + + bind mousePress1 any startSelection + bind mouseRelease1 any endSelection followLinkNoSel + bind mousePress2 any startPan + bind mouseRelease2 any endPan + bind mousePress3 any postPopupMenu + bind mousePress4 any scrollUpPrevPage(16) + bind mousePress5 any scrollDownNextPage(16) + bind mousePress6 any scrollLeft(16) + bind mousePress7 any scrollRight(16) + + The default key bindings are as follows: + + bind ctrl-home any gotoPage(1) + bind home any scrollToTopLeft + bind ctrl-end any gotoLastPage + bind end any scrollToBottomRight + bind pgup any pageUp + bind backspace any pageUp + bind delete any pageUp + bind pgdn any pageDown + bind space any pageDown + bind left any scrollLeft(16) + bind right any scrollRight(16) + bind up any scrollUp(16) + bind down any scrollDown(16) + bind o any open + bind O any open + bind r any reload + bind R any reload + bind f any find + bind F any find + bind ctrl-f any find + bind ctrl-g any findNext + bind ctrl-p any print + bind n scrLockOff nextPage + bind N scrLockOff nextPage + bind n scrLockOn nextPageNoScroll + bind N scrLockOn nextPageNoScroll + bind p scrLockOff prevPage + bind P scrLockOff prevPage + bind p scrLockOn prevPageNoScroll + bind P scrLockOn prevPageNoScroll + bind v any goForward + bind b any goBackward + bind g any focusToPageNum + bind 0 any zoomPercent(125) + bind + any zoomIn + bind - any zoomOut + bind z any zoomFitPage + bind w any zoomFitWidth + bind alt-f any toggleFullScreenMode + bind ctrl-l any redraw + bind ctrl-w any closeWindow + bind ? any about + bind q any quit + bind Q any quit + + Previous versions of xpdf included a "viKeys" X resource. + It is no longer available, but the following bindings are + equivalent: + + bind h any scrollLeft(16) + bind l any scrollRight(16) + bind k any scrollUp(16) + bind j any scrollDown(16) + + +REMOTE SERVER MODE + Xpdf can be started in remote server mode by specifying a + server name (in addition to the file name and page num- + ber). For example: + + xpdf -remote myServer file.pdf + + If there is currently no xpdf running in server mode with + the name 'myServer', a new xpdf window will be opened. If + another command: + + xpdf -remote myServer another.pdf 9 + + is issued, a new copy of xpdf will not be started. + Instead, the first xpdf (the server) will load another.pdf + and display page nine. If the file name is the same: + + xpdf -remote myServer another.pdf 4 + + the xpdf server will simply display the specified page. + + The -raise option tells the server to raise its window; it + can be specified with or without a file name and page num- + ber. + + The -quit option tells the server to close its window and + exit. + +EXIT CODES + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + +AUTHOR + The xpdf software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + +SEE ALSO + pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), + pdftoppm(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + + + 27 February 2007 xpdf(1) diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/xpdf.cc swftools-0.9.1/lib/pdf/xpdf/xpdf.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/xpdf.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/xpdf.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,344 @@ +//======================================================================== +// +// xpdf.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include "gtypes.h" +#include "GString.h" +#include "parseargs.h" +#include "gfile.h" +#include "gmem.h" +#include "GlobalParams.h" +#include "Object.h" +#include "XPDFApp.h" +#include "config.h" + +//------------------------------------------------------------------------ +// command line options +//------------------------------------------------------------------------ + +static GBool contView = gFalse; +static char enableT1libStr[16] = ""; +static char enableFreeTypeStr[16] = ""; +static char antialiasStr[16] = ""; +static char vectorAntialiasStr[16] = ""; +static char psFileArg[256]; +static char paperSize[15] = ""; +static int paperWidth = 0; +static int paperHeight = 0; +static GBool level1 = gFalse; +static char textEncName[128] = ""; +static char textEOL[16] = ""; +static char ownerPassword[33] = "\001"; +static char userPassword[33] = "\001"; +static GBool fullScreen = gFalse; +static char remoteName[100] = "xpdf_"; +static char remoteCmd[512] = ""; +static GBool doRemoteReload = gFalse; +static GBool doRemoteRaise = gFalse; +static GBool doRemoteQuit = gFalse; +static GBool printCommands = gFalse; +static GBool quiet = gFalse; +static char cfgFileName[256] = ""; +static GBool printVersion = gFalse; +static GBool printHelp = gFalse; + +static ArgDesc argDesc[] = { + {"-g", argStringDummy, NULL, 0, + "initial window geometry"}, + {"-geometry", argStringDummy, NULL, 0, + "initial window geometry"}, + {"-title", argStringDummy, NULL, 0, + "window title"}, + {"-cmap", argFlagDummy, NULL, 0, + "install a private colormap"}, + {"-rgb", argIntDummy, NULL, 0, + "biggest RGB cube to allocate (default is 5)"}, + {"-rv", argFlagDummy, NULL, 0, + "reverse video"}, + {"-papercolor", argStringDummy, NULL, 0, + "color of paper background"}, + {"-z", argStringDummy, NULL, 0, + "initial zoom level (percent, 'page', 'width')"}, + {"-cont", argFlag, &contView, 0, + "start in continuous view mode" }, +#if HAVE_T1LIB_H + {"-t1lib", argString, enableT1libStr, sizeof(enableT1libStr), + "enable t1lib font rasterizer: yes, no"}, +#endif +#if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H + {"-freetype", argString, enableFreeTypeStr, sizeof(enableFreeTypeStr), + "enable FreeType font rasterizer: yes, no"}, +#endif + {"-aa", argString, antialiasStr, sizeof(antialiasStr), + "enable font anti-aliasing: yes, no"}, + {"-aaVector", argString, vectorAntialiasStr, sizeof(vectorAntialiasStr), + "enable vector anti-aliasing: yes, no"}, + {"-ps", argString, psFileArg, sizeof(psFileArg), + "default PostScript file name or command"}, + {"-paper", argString, paperSize, sizeof(paperSize), + "paper size (letter, legal, A4, A3, match)"}, + {"-paperw", argInt, &paperWidth, 0, + "paper width, in points"}, + {"-paperh", argInt, &paperHeight, 0, + "paper height, in points"}, + {"-level1", argFlag, &level1, 0, + "generate Level 1 PostScript"}, + {"-enc", argString, textEncName, sizeof(textEncName), + "output text encoding name"}, + {"-eol", argString, textEOL, sizeof(textEOL), + "output end-of-line convention (unix, dos, or mac)"}, + {"-opw", argString, ownerPassword, sizeof(ownerPassword), + "owner password (for encrypted files)"}, + {"-upw", argString, userPassword, sizeof(userPassword), + "user password (for encrypted files)"}, + {"-fullscreen", argFlag, &fullScreen, 0, + "run in full-screen (presentation) mode"}, + {"-remote", argString, remoteName + 5, sizeof(remoteName) - 5, + "start/contact xpdf remote server with specified name"}, + {"-exec", argString, remoteCmd, sizeof(remoteCmd), + "execute command on xpdf remote server (with -remote only)"}, + {"-reload", argFlag, &doRemoteReload, 0, + "reload xpdf remove server window (with -remote only)"}, + {"-raise", argFlag, &doRemoteRaise, 0, + "raise xpdf remote server window (with -remote only)"}, + {"-quit", argFlag, &doRemoteQuit, 0, + "kill xpdf remote server (with -remote only)"}, + {"-cmd", argFlag, &printCommands, 0, + "print commands as they're executed"}, + {"-q", argFlag, &quiet, 0, + "don't print any messages or errors"}, + {"-cfg", argString, cfgFileName, sizeof(cfgFileName), + "configuration file to use in place of .xpdfrc"}, + {"-v", argFlag, &printVersion, 0, + "print copyright and version info"}, + {"-h", argFlag, &printHelp, 0, + "print usage information"}, + {"-help", argFlag, &printHelp, 0, + "print usage information"}, + {"--help", argFlag, &printHelp, 0, + "print usage information"}, + {"-?", argFlag, &printHelp, 0, + "print usage information"}, + {NULL} +}; + +//------------------------------------------------------------------------ + +int main(int argc, char *argv[]) { + XPDFApp *app; + GString *fileName; + int pg; + GString *destName; + GString *userPasswordStr, *ownerPasswordStr; + GBool ok; + int exitCode; + + exitCode = 0; + userPasswordStr = ownerPasswordStr = NULL; + + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (!ok || printVersion || printHelp) { + fprintf(stderr, "xpdf version %s\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("xpdf", "[ [ | +]]", argDesc); + } + exitCode = 99; + goto done0; + } + + // read config file + globalParams = new GlobalParams(cfgFileName); + globalParams->setupBaseFonts(NULL); + if (contView) { + globalParams->setContinuousView(contView); + } + if (psFileArg[0]) { + globalParams->setPSFile(psFileArg); + } + if (paperSize[0]) { + if (!globalParams->setPSPaperSize(paperSize)) { + fprintf(stderr, "Invalid paper size\n"); + } + } else { + if (paperWidth) { + globalParams->setPSPaperWidth(paperWidth); + } + if (paperHeight) { + globalParams->setPSPaperHeight(paperHeight); + } + } + if (level1) { + globalParams->setPSLevel(psLevel1); + } + if (textEncName[0]) { + globalParams->setTextEncoding(textEncName); + } + if (textEOL[0]) { + if (!globalParams->setTextEOL(textEOL)) { + fprintf(stderr, "Bad '-eol' value on command line\n"); + } + } + if (enableT1libStr[0]) { + if (!globalParams->setEnableT1lib(enableT1libStr)) { + fprintf(stderr, "Bad '-t1lib' value on command line\n"); + } + } + if (enableFreeTypeStr[0]) { + if (!globalParams->setEnableFreeType(enableFreeTypeStr)) { + fprintf(stderr, "Bad '-freetype' value on command line\n"); + } + } + if (antialiasStr[0]) { + if (!globalParams->setAntialias(antialiasStr)) { + fprintf(stderr, "Bad '-aa' value on command line\n"); + } + } + if (vectorAntialiasStr[0]) { + if (!globalParams->setVectorAntialias(vectorAntialiasStr)) { + fprintf(stderr, "Bad '-aaVector' value on command line\n"); + } + } + if (printCommands) { + globalParams->setPrintCommands(printCommands); + } + if (quiet) { + globalParams->setErrQuiet(quiet); + } + + // create the XPDFApp object + app = new XPDFApp(&argc, argv); + + // the initialZoom parameter can be set in either the config file or + // as an X resource (or command line arg) + if (app->getInitialZoom()) { + globalParams->setInitialZoom(app->getInitialZoom()->getCString()); + } + + // check command line + ok = ok && argc >= 1 && argc <= 3; + if (remoteCmd[0]) { + ok = ok && remoteName[5] && !doRemoteReload && !doRemoteRaise && + !doRemoteQuit && argc == 1; + } + if (doRemoteReload) { + ok = ok && remoteName[5] && !doRemoteQuit && argc == 1; + } + if (doRemoteRaise) { + ok = ok && remoteName[5] && !doRemoteQuit; + } + if (doRemoteQuit) { + ok = ok && remoteName[5] && argc == 1; + } + if (!ok || printVersion || printHelp) { + fprintf(stderr, "xpdf version %s\n", xpdfVersion); + fprintf(stderr, "%s\n", xpdfCopyright); + if (!printVersion) { + printUsage("xpdf", "[ [ | +]]", argDesc); + } + exitCode = 99; + goto done1; + } + if (argc >= 2) { + fileName = new GString(argv[1]); + } else { + fileName = NULL; + } + pg = 1; + destName = NULL; + if (argc == 3) { + if (argv[2][0] == '+') { + destName = new GString(&argv[2][1]); + } else { + pg = atoi(argv[2]); + if (pg < 0) { + fprintf(stderr, "Invalid page number (%d)\n", pg); + exitCode = 99; + goto done2; + } + } + } + + // handle remote server stuff + if (remoteName[5]) { + app->setRemoteName(remoteName); + if (app->remoteServerRunning()) { + if (fileName) { + if (destName) { + app->remoteOpenAtDest(fileName, destName, doRemoteRaise); + } else { + app->remoteOpen(fileName, pg, doRemoteRaise); + } + } else if (remoteCmd[0]) { + app->remoteExec(remoteCmd); + } else if (doRemoteReload) { + app->remoteReload(doRemoteRaise); + } else if (doRemoteRaise) { + app->remoteRaise(); + } else if (doRemoteQuit) { + app->remoteQuit(); + } + goto done2; + } + if (doRemoteQuit) { + goto done2; + } + } + + // set options + app->setFullScreen(fullScreen); + + // check for password string(s) + ownerPasswordStr = ownerPassword[0] != '\001' ? new GString(ownerPassword) + : (GString *)NULL; + userPasswordStr = userPassword[0] != '\001' ? new GString(userPassword) + : (GString *)NULL; + + // open the file and run the main loop + if (destName) { + if (!app->openAtDest(fileName, destName, + ownerPasswordStr, userPasswordStr)) { + exitCode = 1; + goto done2; + } + } else { + if (!app->open(fileName, pg, ownerPasswordStr, userPasswordStr)) { + exitCode = 1; + goto done2; + } + } + app->run(); + + exitCode = 0; + + // clean up + done2: + if (userPasswordStr) { + delete userPasswordStr; + } + if (ownerPasswordStr) { + delete ownerPasswordStr; + } + if (destName) { + delete destName; + } + if (fileName) { + delete fileName; + } + done1: + delete app; + delete globalParams; + + // check for memory leaks + done0: + Object::memCheck(stderr); + gMemReport(stderr); + + return exitCode; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFCore.cc swftools-0.9.1/lib/pdf/xpdf/XPDFCore.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFCore.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XPDFCore.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,1655 @@ +//======================================================================== +// +// XPDFCore.cc +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include "gmem.h" +#include "GString.h" +#include "GList.h" +#include "Error.h" +#include "GlobalParams.h" +#include "PDFDoc.h" +#include "Link.h" +#include "ErrorCodes.h" +#include "GfxState.h" +#include "CoreOutputDev.h" +#include "PSOutputDev.h" +#include "TextOutputDev.h" +#include "SplashBitmap.h" +#include "SplashPattern.h" +#include "XPDFApp.h" +#include "XPDFCore.h" + +// these macro defns conflict with xpdf's Object class +#ifdef LESSTIF_VERSION +#undef XtDisplay +#undef XtScreen +#undef XtWindow +#undef XtParent +#undef XtIsRealized +#endif + +//------------------------------------------------------------------------ + +// Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result. +static inline Guchar div255(int x) { + return (Guchar)((x + (x >> 8) + 0x80) >> 8); +} + +//------------------------------------------------------------------------ + +GString *XPDFCore::currentSelection = NULL; +XPDFCore *XPDFCore::currentSelectionOwner = NULL; +Atom XPDFCore::targetsAtom; + +//------------------------------------------------------------------------ +// XPDFCoreTile +//------------------------------------------------------------------------ + +class XPDFCoreTile: public PDFCoreTile { +public: + XPDFCoreTile(int xDestA, int yDestA); + virtual ~XPDFCoreTile(); + XImage *image; +}; + +XPDFCoreTile::XPDFCoreTile(int xDestA, int yDestA): + PDFCoreTile(xDestA, yDestA) +{ + image = NULL; +} + +XPDFCoreTile::~XPDFCoreTile() { + if (image) { + gfree(image->data); + image->data = NULL; + XDestroyImage(image); + } +} + +//------------------------------------------------------------------------ +// XPDFCore +//------------------------------------------------------------------------ + +XPDFCore::XPDFCore(Widget shellA, Widget parentWidgetA, + SplashColorPtr paperColorA, Gulong paperPixelA, + Gulong mattePixelA, GBool fullScreenA, GBool reverseVideoA, + GBool installCmap, int rgbCubeSizeA): + PDFCore(splashModeRGB8, 4, reverseVideoA, paperColorA, !fullScreenA) +{ + GString *initialZoom; + + shell = shellA; + parentWidget = parentWidgetA; + display = XtDisplay(parentWidget); + screenNum = XScreenNumberOfScreen(XtScreen(parentWidget)); + targetsAtom = XInternAtom(display, "TARGETS", False); + + paperPixel = paperPixelA; + mattePixel = mattePixelA; + fullScreen = fullScreenA; + + setupX(installCmap, rgbCubeSizeA); + + scrolledWin = NULL; + hScrollBar = NULL; + vScrollBar = NULL; + drawAreaFrame = NULL; + drawArea = NULL; + + // get the initial zoom value + if (fullScreen) { + zoom = zoomPage; + } else { + initialZoom = globalParams->getInitialZoom(); + if (!initialZoom->cmp("page")) { + zoom = zoomPage; + } else if (!initialZoom->cmp("width")) { + zoom = zoomWidth; + } else { + zoom = atoi(initialZoom->getCString()); + if (zoom <= 0) { + zoom = defZoom; + } + } + delete initialZoom; + } + + linkAction = NULL; + + panning = gFalse; + + updateCbk = NULL; + actionCbk = NULL; + keyPressCbk = NULL; + mouseCbk = NULL; + + // optional features default to on + hyperlinksEnabled = gTrue; + selectEnabled = gTrue; + + // do X-specific initialization and create the widgets + initWindow(); + initPasswordDialog(); +} + +XPDFCore::~XPDFCore() { + if (currentSelectionOwner == this && currentSelection) { + delete currentSelection; + currentSelection = NULL; + currentSelectionOwner = NULL; + } + if (drawAreaGC) { + XFreeGC(display, drawAreaGC); + } + if (scrolledWin) { + XtDestroyWidget(scrolledWin); + } + if (busyCursor) { + XFreeCursor(display, busyCursor); + } + if (linkCursor) { + XFreeCursor(display, linkCursor); + } + if (selectCursor) { + XFreeCursor(display, selectCursor); + } +} + +//------------------------------------------------------------------------ +// loadFile / displayPage / displayDest +//------------------------------------------------------------------------ + +int XPDFCore::loadFile(GString *fileName, GString *ownerPassword, + GString *userPassword) { + int err; + + err = PDFCore::loadFile(fileName, ownerPassword, userPassword); + if (err == errNone) { + // save the modification time + modTime = getModTime(doc->getFileName()->getCString()); + + // update the parent window + if (updateCbk) { + (*updateCbk)(updateCbkData, doc->getFileName(), -1, + doc->getNumPages(), NULL); + } + } + return err; +} + +int XPDFCore::loadFile(BaseStream *stream, GString *ownerPassword, + GString *userPassword) { + int err; + + err = PDFCore::loadFile(stream, ownerPassword, userPassword); + if (err == errNone) { + // no file + modTime = 0; + + // update the parent window + if (updateCbk) { + (*updateCbk)(updateCbkData, doc->getFileName(), -1, + doc->getNumPages(), NULL); + } + } + return err; +} + +void XPDFCore::loadDoc(PDFDoc *docA) { + PDFCore::loadDoc(docA); + + // save the modification time + if (doc->getFileName()) { + modTime = getModTime(doc->getFileName()->getCString()); + } + + // update the parent window + if (updateCbk) { + (*updateCbk)(updateCbkData, doc->getFileName(), -1, + doc->getNumPages(), NULL); + } +} + +void XPDFCore::resizeToPage(int pg) { + Dimension width, height; + double width1, height1; + Dimension topW, topH, topBorder, daW, daH; + Dimension displayW, displayH; + + displayW = DisplayWidth(display, screenNum); + displayH = DisplayHeight(display, screenNum); + if (fullScreen) { + width = displayW; + height = displayH; + } else { + if (!doc || pg <= 0 || pg > doc->getNumPages()) { + width1 = 612; + height1 = 792; + } else if (doc->getPageRotate(pg) == 90 || + doc->getPageRotate(pg) == 270) { + width1 = doc->getPageCropHeight(pg); + height1 = doc->getPageCropWidth(pg); + } else { + width1 = doc->getPageCropWidth(pg); + height1 = doc->getPageCropHeight(pg); + } + if (zoom == zoomPage || zoom == zoomWidth) { + width = (Dimension)(width1 * 0.01 * defZoom + 0.5); + height = (Dimension)(height1 * 0.01 * defZoom + 0.5); + } else { + width = (Dimension)(width1 * 0.01 * zoom + 0.5); + height = (Dimension)(height1 * 0.01 * zoom + 0.5); + } + if (continuousMode) { + height += continuousModePageSpacing; + } + if (width > displayW - 100) { + width = displayW - 100; + } + if (height > displayH - 100) { + height = displayH - 100; + } + } + + if (XtIsRealized(shell)) { + XtVaGetValues(shell, XmNwidth, &topW, XmNheight, &topH, + XmNborderWidth, &topBorder, NULL); + XtVaGetValues(drawArea, XmNwidth, &daW, XmNheight, &daH, NULL); + XtVaSetValues(shell, XmNwidth, width + (topW - daW), + XmNheight, height + (topH - daH), NULL); + } else { + XtVaSetValues(drawArea, XmNwidth, width, XmNheight, height, NULL); + } +} + +void XPDFCore::update(int topPageA, int scrollXA, int scrollYA, + double zoomA, int rotateA, + GBool force, GBool addToHist) { + int oldPage; + + oldPage = topPage; + PDFCore::update(topPageA, scrollXA, scrollYA, zoomA, rotateA, + force, addToHist); + linkAction = NULL; + if (doc && topPage != oldPage) { + if (updateCbk) { + (*updateCbk)(updateCbkData, NULL, topPage, -1, ""); + } + } +} + +GBool XPDFCore::checkForNewFile() { + time_t newModTime; + + if (doc->getFileName()) { + newModTime = getModTime(doc->getFileName()->getCString()); + if (newModTime != modTime) { + modTime = newModTime; + return gTrue; + } + } + return gFalse; +} + +//------------------------------------------------------------------------ +// page/position changes +//------------------------------------------------------------------------ + +GBool XPDFCore::gotoNextPage(int inc, GBool top) { + if (!PDFCore::gotoNextPage(inc, top)) { + XBell(display, 0); + return gFalse; + } + return gTrue; +} + +GBool XPDFCore::gotoPrevPage(int dec, GBool top, GBool bottom) { + if (!PDFCore::gotoPrevPage(dec, top, bottom)) { + XBell(display, 0); + return gFalse; + } + return gTrue; +} + +GBool XPDFCore::goForward() { + if (!PDFCore::goForward()) { + XBell(display, 0); + return gFalse; + } + return gTrue; +} + +GBool XPDFCore::goBackward() { + if (!PDFCore::goBackward()) { + XBell(display, 0); + return gFalse; + } + return gTrue; +} + +void XPDFCore::startPan(int wx, int wy) { + panning = gTrue; + panMX = wx; + panMY = wy; +} + +void XPDFCore::endPan(int wx, int wy) { + panning = gFalse; +} + +//------------------------------------------------------------------------ +// selection +//------------------------------------------------------------------------ + +void XPDFCore::startSelection(int wx, int wy) { + int pg, x, y; + + takeFocus(); + if (doc && doc->getNumPages() > 0) { + if (selectEnabled) { + if (cvtWindowToDev(wx, wy, &pg, &x, &y)) { + setSelection(pg, x, y, x, y); + setCursor(selectCursor); + dragging = gTrue; + } + } + } +} + +void XPDFCore::endSelection(int wx, int wy) { + int pg, x, y; + GBool ok; + + if (doc && doc->getNumPages() > 0) { + ok = cvtWindowToDev(wx, wy, &pg, &x, &y); + if (dragging) { + dragging = gFalse; + setCursor(None); + if (ok) { + moveSelection(pg, x, y); + } +#ifndef NO_TEXT_SELECT + if (selectULX != selectLRX && + selectULY != selectLRY) { + if (doc->okToCopy()) { + copySelection(); + } else { + error(-1, "Copying of text from this document is not allowed."); + } + } +#endif + } + } +} + +// X's copy-and-paste mechanism is brain damaged. Xt doesn't help +// any, but doesn't make it too much worse, either. Motif, on the +// other hand, adds significant complexity to the mess. So here we +// blow off the Motif junk and stick to plain old Xt. The next two +// functions (copySelection and convertSelectionCbk) implement the +// magic needed to deal with Xt's mechanism. Note that this requires +// global variables (currentSelection and currentSelectionOwner). + +void XPDFCore::copySelection() { + int pg; + double ulx, uly, lrx, lry; + + if (!doc->okToCopy()) { + return; + } + if (getSelection(&pg, &ulx, &uly, &lrx, &lry)) { + //~ for multithreading: need a mutex here + if (currentSelection) { + delete currentSelection; + } + currentSelection = extractText(pg, ulx, uly, lrx, lry); + currentSelectionOwner = this; + XtOwnSelection(drawArea, XA_PRIMARY, XtLastTimestampProcessed(display), + &convertSelectionCbk, NULL, NULL); + } +} + +Boolean XPDFCore::convertSelectionCbk(Widget widget, Atom *selection, + Atom *target, Atom *type, + XtPointer *value, unsigned long *length, + int *format) { + Atom *array; + + // send back a list of supported conversion targets + if (*target == targetsAtom) { + if (!(array = (Atom *)XtMalloc(sizeof(Atom)))) { + return False; + } + array[0] = XA_STRING; + *value = (XtPointer)array; + *type = XA_ATOM; + *format = 32; + *length = 1; + return True; + + // send the selected text + } else if (*target == XA_STRING) { + //~ for multithreading: need a mutex here + *value = XtNewString(currentSelection->getCString()); + *length = currentSelection->getLength(); + *type = XA_STRING; + *format = 8; // 8-bit elements + return True; + } + + return False; +} + +//------------------------------------------------------------------------ +// hyperlinks +//------------------------------------------------------------------------ + +void XPDFCore::doAction(LinkAction *action) { + LinkActionKind kind; + LinkDest *dest; + GString *namedDest; + char *s; + GString *fileName, *fileName2; + GString *cmd; + GString *actionName; + Object movieAnnot, obj1, obj2; + GString *msg; + int i; + + switch (kind = action->getKind()) { + + // GoTo / GoToR action + case actionGoTo: + case actionGoToR: + if (kind == actionGoTo) { + dest = NULL; + namedDest = NULL; + if ((dest = ((LinkGoTo *)action)->getDest())) { + dest = dest->copy(); + } else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) { + namedDest = namedDest->copy(); + } + } else { + dest = NULL; + namedDest = NULL; + if ((dest = ((LinkGoToR *)action)->getDest())) { + dest = dest->copy(); + } else if ((namedDest = ((LinkGoToR *)action)->getNamedDest())) { + namedDest = namedDest->copy(); + } + s = ((LinkGoToR *)action)->getFileName()->getCString(); + //~ translate path name for VMS (deal with '/') + if (isAbsolutePath(s)) { + fileName = new GString(s); + } else { + fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s); + } + if (loadFile(fileName) != errNone) { + if (dest) { + delete dest; + } + if (namedDest) { + delete namedDest; + } + delete fileName; + return; + } + delete fileName; + } + if (namedDest) { + dest = doc->findDest(namedDest); + delete namedDest; + } + if (dest) { + displayDest(dest, zoom, rotate, gTrue); + delete dest; + } else { + if (kind == actionGoToR) { + displayPage(1, zoom, 0, gFalse, gTrue); + } + } + break; + + // Launch action + case actionLaunch: + fileName = ((LinkLaunch *)action)->getFileName(); + s = fileName->getCString(); + if (!strcmp(s + fileName->getLength() - 4, ".pdf") || + !strcmp(s + fileName->getLength() - 4, ".PDF")) { + //~ translate path name for VMS (deal with '/') + if (isAbsolutePath(s)) { + fileName = fileName->copy(); + } else { + fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s); + } + if (loadFile(fileName) != errNone) { + delete fileName; + return; + } + delete fileName; + displayPage(1, zoom, rotate, gFalse, gTrue); + } else { + fileName = fileName->copy(); + if (((LinkLaunch *)action)->getParams()) { + fileName->append(' '); + fileName->append(((LinkLaunch *)action)->getParams()); + } +#ifdef VMS + fileName->insert(0, "spawn/nowait "); +#elif defined(__EMX__) + fileName->insert(0, "start /min /n "); +#else + fileName->append(" &"); +#endif + msg = new GString("About to execute the command:\n"); + msg->append(fileName); + if (doQuestionDialog("Launching external application", msg)) { + system(fileName->getCString()); + } + delete fileName; + delete msg; + } + break; + + // URI action + case actionURI: + if (!(cmd = globalParams->getURLCommand())) { + error(-1, "No urlCommand defined in config file"); + break; + } + runCommand(cmd, ((LinkURI *)action)->getURI()); + break; + + // Named action + case actionNamed: + actionName = ((LinkNamed *)action)->getName(); + if (!actionName->cmp("NextPage")) { + gotoNextPage(1, gTrue); + } else if (!actionName->cmp("PrevPage")) { + gotoPrevPage(1, gTrue, gFalse); + } else if (!actionName->cmp("FirstPage")) { + if (topPage != 1) { + displayPage(1, zoom, rotate, gTrue, gTrue); + } + } else if (!actionName->cmp("LastPage")) { + if (topPage != doc->getNumPages()) { + displayPage(doc->getNumPages(), zoom, rotate, gTrue, gTrue); + } + } else if (!actionName->cmp("GoBack")) { + goBackward(); + } else if (!actionName->cmp("GoForward")) { + goForward(); + } else if (!actionName->cmp("Quit")) { + if (actionCbk) { + (*actionCbk)(actionCbkData, actionName->getCString()); + } + } else { + error(-1, "Unknown named action: '%s'", actionName->getCString()); + } + break; + + // Movie action + case actionMovie: + if (!(cmd = globalParams->getMovieCommand())) { + error(-1, "No movieCommand defined in config file"); + break; + } + if (((LinkMovie *)action)->hasAnnotRef()) { + doc->getXRef()->fetch(((LinkMovie *)action)->getAnnotRef()->num, + ((LinkMovie *)action)->getAnnotRef()->gen, + &movieAnnot); + } else { + //~ need to use the correct page num here + doc->getCatalog()->getPage(topPage)->getAnnots(&obj1); + if (obj1.isArray()) { + for (i = 0; i < obj1.arrayGetLength(); ++i) { + if (obj1.arrayGet(i, &movieAnnot)->isDict()) { + if (movieAnnot.dictLookup("Subtype", &obj2)->isName("Movie")) { + obj2.free(); + break; + } + obj2.free(); + } + movieAnnot.free(); + } + obj1.free(); + } + } + if (movieAnnot.isDict()) { + if (movieAnnot.dictLookup("Movie", &obj1)->isDict()) { + if (obj1.dictLookup("F", &obj2)) { + if ((fileName = LinkAction::getFileSpecName(&obj2))) { + if (!isAbsolutePath(fileName->getCString())) { + fileName2 = appendToPath( + grabPath(doc->getFileName()->getCString()), + fileName->getCString()); + delete fileName; + fileName = fileName2; + } + runCommand(cmd, fileName); + delete fileName; + } + obj2.free(); + } + obj1.free(); + } + } + movieAnnot.free(); + break; + + // unknown action type + case actionUnknown: + error(-1, "Unknown link action type: '%s'", + ((LinkUnknown *)action)->getAction()->getCString()); + break; + } +} + +// Run a command, given a string with one '%s' in it, and an +// string to insert in place of the '%s'. +void XPDFCore::runCommand(GString *cmdFmt, GString *arg) { + GString *cmd; + char *s; + + if ((s = strstr(cmdFmt->getCString(), "%s"))) { + cmd = mungeURL(arg); + cmd->insert(0, cmdFmt->getCString(), + s - cmdFmt->getCString()); + cmd->append(s + 2); + } else { + cmd = cmdFmt->copy(); + } +#ifdef VMS + cmd->insert(0, "spawn/nowait "); +#elif defined(__EMX__) + cmd->insert(0, "start /min /n "); +#else + cmd->append(" &"); +#endif + system(cmd->getCString()); + delete cmd; +} + +// Escape any characters in a URL which might cause problems when +// calling system(). +GString *XPDFCore::mungeURL(GString *url) { + static char *allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "-_.~/?:@&=+,#%"; + GString *newURL; + char c; + char buf[4]; + int i; + + newURL = new GString(); + for (i = 0; i < url->getLength(); ++i) { + c = url->getChar(i); + if (strchr(allowed, c)) { + newURL->append(c); + } else { + sprintf(buf, "%%%02x", c & 0xff); + newURL->append(buf); + } + } + return newURL; +} + +//------------------------------------------------------------------------ +// find +//------------------------------------------------------------------------ + +GBool XPDFCore::find(char *s, GBool caseSensitive, + GBool next, GBool backward, GBool onePageOnly) { + if (!PDFCore::find(s, caseSensitive, next, backward, onePageOnly)) { + XBell(display, 0); + return gFalse; + } +#ifndef NO_TEXT_SELECT + copySelection(); +#endif + return gTrue; +} + +GBool XPDFCore::findU(Unicode *u, int len, GBool caseSensitive, + GBool next, GBool backward, GBool onePageOnly) { + if (!PDFCore::findU(u, len, caseSensitive, next, backward, onePageOnly)) { + XBell(display, 0); + return gFalse; + } +#ifndef NO_TEXT_SELECT + copySelection(); +#endif + return gTrue; +} + +//------------------------------------------------------------------------ +// misc access +//------------------------------------------------------------------------ + +void XPDFCore::setBusyCursor(GBool busy) { + setCursor(busy ? busyCursor : None); +} + +void XPDFCore::takeFocus() { + XmProcessTraversal(drawArea, XmTRAVERSE_CURRENT); +} + +//------------------------------------------------------------------------ +// GUI code +//------------------------------------------------------------------------ + +void XPDFCore::setupX(GBool installCmap, int rgbCubeSizeA) { + XVisualInfo visualTempl; + XVisualInfo *visualList; + Gulong mask; + int nVisuals; + XColor xcolor; + XColor *xcolors; + int r, g, b, n, m; + GBool ok; + + // for some reason, querying XmNvisual doesn't work (even if done + // after the window is mapped) + visual = DefaultVisual(display, screenNum); + XtVaGetValues(shell, XmNcolormap, &colormap, NULL); + + // check for TrueColor visual + //~ this should scan the list, not just look at the first one + visualTempl.visualid = XVisualIDFromVisual(visual); + visualList = XGetVisualInfo(display, VisualIDMask, + &visualTempl, &nVisuals); + if (nVisuals < 1) { + // this shouldn't happen + XFree((XPointer)visualList); + visualList = XGetVisualInfo(display, VisualNoMask, &visualTempl, + &nVisuals); + } + depth = visualList->depth; + if (visualList->c_class == TrueColor) { + trueColor = gTrue; + for (mask = visualList->red_mask, rShift = 0; + mask && !(mask & 1); + mask >>= 1, ++rShift) ; + for (rDiv = 8; mask; mask >>= 1, --rDiv) ; + for (mask = visualList->green_mask, gShift = 0; + mask && !(mask & 1); + mask >>= 1, ++gShift) ; + for (gDiv = 8; mask; mask >>= 1, --gDiv) ; + for (mask = visualList->blue_mask, bShift = 0; + mask && !(mask & 1); + mask >>= 1, ++bShift) ; + for (bDiv = 8; mask; mask >>= 1, --bDiv) ; + } else { + trueColor = gFalse; + } + XFree((XPointer)visualList); + + // allocate a color cube + if (!trueColor) { + + // set colors in private colormap + if (installCmap) { + for (rgbCubeSize = xMaxRGBCube; rgbCubeSize >= 2; --rgbCubeSize) { + m = rgbCubeSize * rgbCubeSize * rgbCubeSize; + if (XAllocColorCells(display, colormap, False, NULL, 0, colors, m)) { + break; + } + } + if (rgbCubeSize >= 2) { + m = rgbCubeSize * rgbCubeSize * rgbCubeSize; + xcolors = (XColor *)gmallocn(m, sizeof(XColor)); + n = 0; + for (r = 0; r < rgbCubeSize; ++r) { + for (g = 0; g < rgbCubeSize; ++g) { + for (b = 0; b < rgbCubeSize; ++b) { + xcolors[n].pixel = colors[n]; + xcolors[n].red = (r * 65535) / (rgbCubeSize - 1); + xcolors[n].green = (g * 65535) / (rgbCubeSize - 1); + xcolors[n].blue = (b * 65535) / (rgbCubeSize - 1); + xcolors[n].flags = DoRed | DoGreen | DoBlue; + ++n; + } + } + } + XStoreColors(display, colormap, xcolors, m); + gfree(xcolors); + } else { + rgbCubeSize = 1; + colors[0] = BlackPixel(display, screenNum); + colors[1] = WhitePixel(display, screenNum); + } + + // allocate colors in shared colormap + } else { + if (rgbCubeSize > xMaxRGBCube) { + rgbCubeSize = xMaxRGBCube; + } + ok = gFalse; + for (rgbCubeSize = rgbCubeSizeA; rgbCubeSize >= 2; --rgbCubeSize) { + ok = gTrue; + n = 0; + for (r = 0; r < rgbCubeSize && ok; ++r) { + for (g = 0; g < rgbCubeSize && ok; ++g) { + for (b = 0; b < rgbCubeSize && ok; ++b) { + if (n == 0) { + colors[n] = BlackPixel(display, screenNum); + ++n; + } else { + xcolor.red = (r * 65535) / (rgbCubeSize - 1); + xcolor.green = (g * 65535) / (rgbCubeSize - 1); + xcolor.blue = (b * 65535) / (rgbCubeSize - 1); + if (XAllocColor(display, colormap, &xcolor)) { + colors[n++] = xcolor.pixel; + } else { + ok = gFalse; + } + } + } + } + } + if (ok) { + break; + } + XFreeColors(display, colormap, &colors[1], n-1, 0); + } + if (!ok) { + rgbCubeSize = 1; + colors[0] = BlackPixel(display, screenNum); + colors[1] = WhitePixel(display, screenNum); + } + } + } +} + +void XPDFCore::initWindow() { + Arg args[20]; + int n; + + // create the cursors + busyCursor = XCreateFontCursor(display, XC_watch); + linkCursor = XCreateFontCursor(display, XC_hand2); + selectCursor = XCreateFontCursor(display, XC_cross); + currentCursor = 0; + + // create the scrolled window and scrollbars + n = 0; + XtSetArg(args[n], XmNscrollingPolicy, XmAPPLICATION_DEFINED); ++n; + XtSetArg(args[n], XmNvisualPolicy, XmVARIABLE); ++n; + scrolledWin = XmCreateScrolledWindow(parentWidget, "scroll", args, n); + XtManageChild(scrolledWin); + n = 0; + XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n; + XtSetArg(args[n], XmNminimum, 0); ++n; + XtSetArg(args[n], XmNmaximum, 1); ++n; + XtSetArg(args[n], XmNsliderSize, 1); ++n; + XtSetArg(args[n], XmNvalue, 0); ++n; + XtSetArg(args[n], XmNincrement, 1); ++n; + XtSetArg(args[n], XmNpageIncrement, 1); ++n; + hScrollBar = XmCreateScrollBar(scrolledWin, "hScrollBar", args, n); + if (!fullScreen) { + XtManageChild(hScrollBar); + } + XtAddCallback(hScrollBar, XmNvalueChangedCallback, + &hScrollChangeCbk, (XtPointer)this); +#ifndef DISABLE_SMOOTH_SCROLL + XtAddCallback(hScrollBar, XmNdragCallback, + &hScrollDragCbk, (XtPointer)this); +#endif + n = 0; + XtSetArg(args[n], XmNorientation, XmVERTICAL); ++n; + XtSetArg(args[n], XmNminimum, 0); ++n; + XtSetArg(args[n], XmNmaximum, 1); ++n; + XtSetArg(args[n], XmNsliderSize, 1); ++n; + XtSetArg(args[n], XmNvalue, 0); ++n; + XtSetArg(args[n], XmNincrement, 1); ++n; + XtSetArg(args[n], XmNpageIncrement, 1); ++n; + vScrollBar = XmCreateScrollBar(scrolledWin, "vScrollBar", args, n); + if (!fullScreen) { + XtManageChild(vScrollBar); + } + XtAddCallback(vScrollBar, XmNvalueChangedCallback, + &vScrollChangeCbk, (XtPointer)this); +#ifndef DISABLE_SMOOTH_SCROLL + XtAddCallback(vScrollBar, XmNdragCallback, + &vScrollDragCbk, (XtPointer)this); +#endif + + // create the drawing area + n = 0; + XtSetArg(args[n], XmNshadowType, XmSHADOW_IN); ++n; + XtSetArg(args[n], XmNmarginWidth, 0); ++n; + XtSetArg(args[n], XmNmarginHeight, 0); ++n; + if (fullScreen) { + XtSetArg(args[n], XmNshadowThickness, 0); ++n; + } + drawAreaFrame = XmCreateFrame(scrolledWin, "drawAreaFrame", args, n); + XtManageChild(drawAreaFrame); + n = 0; + XtSetArg(args[n], XmNresizePolicy, XmRESIZE_ANY); ++n; + XtSetArg(args[n], XmNwidth, 700); ++n; + XtSetArg(args[n], XmNheight, 500); ++n; + drawArea = XmCreateDrawingArea(drawAreaFrame, "drawArea", args, n); + XtManageChild(drawArea); + XtAddCallback(drawArea, XmNresizeCallback, &resizeCbk, (XtPointer)this); + XtAddCallback(drawArea, XmNexposeCallback, &redrawCbk, (XtPointer)this); + XtAddCallback(drawArea, XmNinputCallback, &inputCbk, (XtPointer)this); + resizeCbk(drawArea, this, NULL); + + // set up mouse motion translations + XtOverrideTranslations(drawArea, XtParseTranslationTable( + ":DrawingAreaInput()\n" + ":DrawingAreaInput()\n" + ":DrawingAreaInput()\n" + ":DrawingAreaInput()")); + + // can't create a GC until the window gets mapped + drawAreaGC = NULL; +} + +void XPDFCore::hScrollChangeCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData; + + core->scrollTo(data->value, core->scrollY); +} + +void XPDFCore::hScrollDragCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData; + + core->scrollTo(data->value, core->scrollY); +} + +void XPDFCore::vScrollChangeCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData; + + core->scrollTo(core->scrollX, data->value); +} + +void XPDFCore::vScrollDragCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + XmScrollBarCallbackStruct *data = (XmScrollBarCallbackStruct *)callData; + + core->scrollTo(core->scrollX, data->value); +} + +void XPDFCore::resizeCbk(Widget widget, XtPointer ptr, XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + XEvent event; + Widget top; + Window rootWin; + int x1, y1; + Guint w1, h1, bw1, depth1; + Arg args[2]; + int n; + Dimension w, h; + int sx, sy; + + // find the top-most widget which has an associated window, and look + // for a pending ConfigureNotify in the event queue -- if there is + // one, and it specifies a different width or height, that means + // we're still resizing, and we want to skip the current event + for (top = core->parentWidget; + XtParent(top) && XtWindow(XtParent(top)); + top = XtParent(top)) ; + if (XCheckTypedWindowEvent(core->display, XtWindow(top), + ConfigureNotify, &event)) { + XPutBackEvent(core->display, &event); + XGetGeometry(core->display, event.xconfigure.window, + &rootWin, &x1, &y1, &w1, &h1, &bw1, &depth1); + if ((Guint)event.xconfigure.width != w1 || + (Guint)event.xconfigure.height != h1) { + return; + } + } + + n = 0; + XtSetArg(args[n], XmNwidth, &w); ++n; + XtSetArg(args[n], XmNheight, &h); ++n; + XtGetValues(core->drawArea, args, n); + core->drawAreaWidth = (int)w; + core->drawAreaHeight = (int)h; + if (core->zoom == zoomPage || core->zoom == zoomWidth) { + sx = sy = -1; + } else { + sx = core->scrollX; + sy = core->scrollY; + } + core->update(core->topPage, sx, sy, core->zoom, core->rotate, gTrue, gFalse); +} + +void XPDFCore::redrawCbk(Widget widget, XtPointer ptr, XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + XmDrawingAreaCallbackStruct *data = (XmDrawingAreaCallbackStruct *)callData; + int x, y, w, h; + + if (data->reason == XmCR_EXPOSE) { + x = data->event->xexpose.x; + y = data->event->xexpose.y; + w = data->event->xexpose.width; + h = data->event->xexpose.height; + } else { + x = 0; + y = 0; + w = core->drawAreaWidth; + h = core->drawAreaHeight; + } + core->redrawWindow(x, y, w, h, gFalse); +} + +void XPDFCore::inputCbk(Widget widget, XtPointer ptr, XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + XmDrawingAreaCallbackStruct *data = (XmDrawingAreaCallbackStruct *)callData; + LinkAction *action; + int pg, x, y; + double xu, yu; + char *s; + KeySym key; + GBool ok; + + switch (data->event->type) { + case ButtonPress: + if (*core->mouseCbk) { + (*core->mouseCbk)(core->mouseCbkData, data->event); + } + break; + case ButtonRelease: + if (*core->mouseCbk) { + (*core->mouseCbk)(core->mouseCbkData, data->event); + } + break; + case MotionNotify: + if (core->doc && core->doc->getNumPages() > 0) { + ok = core->cvtWindowToDev(data->event->xmotion.x, data->event->xmotion.y, + &pg, &x, &y); + if (core->dragging) { + if (ok) { + core->moveSelection(pg, x, y); + } + } else if (core->hyperlinksEnabled) { + core->cvtDevToUser(pg, x, y, &xu, &yu); + if (ok && (action = core->findLink(pg, xu, yu))) { + core->setCursor(core->linkCursor); + if (action != core->linkAction) { + core->linkAction = action; + if (core->updateCbk) { + s = ""; + switch (action->getKind()) { + case actionGoTo: + s = "[internal link]"; + break; + case actionGoToR: + s = ((LinkGoToR *)action)->getFileName()->getCString(); + break; + case actionLaunch: + s = ((LinkLaunch *)action)->getFileName()->getCString(); + break; + case actionURI: + s = ((LinkURI *)action)->getURI()->getCString(); + break; + case actionNamed: + s = ((LinkNamed *)action)->getName()->getCString(); + break; + case actionMovie: + s = "[movie]"; + break; + case actionUnknown: + s = "[unknown link]"; + break; + } + (*core->updateCbk)(core->updateCbkData, NULL, -1, -1, s); + } + } + } else { + core->setCursor(None); + if (core->linkAction) { + core->linkAction = NULL; + if (core->updateCbk) { + (*core->updateCbk)(core->updateCbkData, NULL, -1, -1, ""); + } + } + } + } + } + if (core->panning) { + core->scrollTo(core->scrollX - (data->event->xmotion.x - core->panMX), + core->scrollY - (data->event->xmotion.y - core->panMY)); + core->panMX = data->event->xmotion.x; + core->panMY = data->event->xmotion.y; + } + break; + case KeyPress: + if (core->keyPressCbk) { + key = XLookupKeysym(&data->event->xkey, + (data->event->xkey.state & ShiftMask) ? 1 : 0); + (*core->keyPressCbk)(core->keyPressCbkData, + key, data->event->xkey.state, data->event); + } + break; + } +} + +PDFCoreTile *XPDFCore::newTile(int xDestA, int yDestA) { + return new XPDFCoreTile(xDestA, yDestA); +} + +void XPDFCore::updateTileData(PDFCoreTile *tileA, int xSrc, int ySrc, + int width, int height, GBool composited) { + XPDFCoreTile *tile = (XPDFCoreTile *)tileA; + XImage *image; + SplashColorPtr dataPtr, p; + Gulong pixel; + Guchar *ap; + Guchar alpha, alpha1; + int w, h, bw, x, y, r, g, b, gray; + int *errDownR, *errDownG, *errDownB; + int errRightR, errRightG, errRightB; + int errDownRightR, errDownRightG, errDownRightB; + int r0, g0, b0, re, ge, be; + + if (!tile->image) { + w = tile->xMax - tile->xMin; + h = tile->yMax - tile->yMin; + image = XCreateImage(display, visual, depth, ZPixmap, 0, NULL, w, h, 8, 0); + image->data = (char *)gmalloc(h * image->bytes_per_line); + tile->image = image; + } else { + image = (XImage *)tile->image; + } + + //~ optimize for known XImage formats + bw = tile->bitmap->getRowSize(); + dataPtr = tile->bitmap->getDataPtr(); + + if (trueColor) { + for (y = 0; y < height; ++y) { + p = dataPtr + (ySrc + y) * bw + xSrc * 3; + if (!composited && tile->bitmap->getAlphaPtr()) { + ap = tile->bitmap->getAlphaPtr() + + (ySrc + y) * tile->bitmap->getWidth() + xSrc; + } else { + ap = NULL; + } + for (x = 0; x < width; ++x) { + r = splashRGB8R(p); + g = splashRGB8G(p); + b = splashRGB8B(p); + if (ap) { + alpha = *ap++; + alpha1 = 255 - alpha; + r = div255(alpha1 * paperColor[0] + alpha * r); + g = div255(alpha1 * paperColor[1] + alpha * g); + b = div255(alpha1 * paperColor[2] + alpha * b); + } + r >>= rDiv; + g >>= gDiv; + b >>= bDiv; + pixel = ((Gulong)r << rShift) + + ((Gulong)g << gShift) + + ((Gulong)b << bShift); + XPutPixel(image, xSrc + x, ySrc + y, pixel); + p += 3; + } + } + } else if (rgbCubeSize == 1) { + //~ this should really use splashModeMono, with non-clustered dithering + for (y = 0; y < height; ++y) { + p = dataPtr + (ySrc + y) * bw + xSrc * 3; + if (!composited && tile->bitmap->getAlphaPtr()) { + ap = tile->bitmap->getAlphaPtr() + + (ySrc + y) * tile->bitmap->getWidth() + xSrc; + } else { + ap = NULL; + } + for (x = 0; x < width; ++x) { + r = splashRGB8R(p); + g = splashRGB8G(p); + b = splashRGB8B(p); + if (ap) { + alpha = *ap++; + alpha1 = 255 - alpha; + r = div255(alpha1 * paperColor[0] + alpha * r); + g = div255(alpha1 * paperColor[1] + alpha * g); + b = div255(alpha1 * paperColor[2] + alpha * b); + } + gray = (int)(0.299 * r + 0.587 * g + 0.114 * b + 0.5); + if (gray < 128) { + pixel = colors[0]; + } else { + pixel = colors[1]; + } + XPutPixel(image, xSrc + x, ySrc + y, pixel); + p += 3; + } + } + } else { + // do Floyd-Steinberg dithering on the whole bitmap + errDownR = (int *)gmallocn(width + 2, sizeof(int)); + errDownG = (int *)gmallocn(width + 2, sizeof(int)); + errDownB = (int *)gmallocn(width + 2, sizeof(int)); + errRightR = errRightG = errRightB = 0; + errDownRightR = errDownRightG = errDownRightB = 0; + memset(errDownR, 0, (width + 2) * sizeof(int)); + memset(errDownG, 0, (width + 2) * sizeof(int)); + memset(errDownB, 0, (width + 2) * sizeof(int)); + for (y = 0; y < height; ++y) { + p = dataPtr + (ySrc + y) * bw + xSrc * 3; + if (!composited && tile->bitmap->getAlphaPtr()) { + ap = tile->bitmap->getAlphaPtr() + + (ySrc + y) * tile->bitmap->getWidth() + xSrc; + } else { + ap = NULL; + } + for (x = 0; x < width; ++x) { + r = splashRGB8R(p); + g = splashRGB8G(p); + b = splashRGB8B(p); + if (ap) { + alpha = *ap++; + alpha1 = 255 - alpha; + r = div255(alpha1 * paperColor[0] + alpha * r); + g = div255(alpha1 * paperColor[1] + alpha * g); + b = div255(alpha1 * paperColor[2] + alpha * b); + } + r0 = r + errRightR + errDownR[x+1]; + g0 = g + errRightG + errDownG[x+1]; + b0 = b + errRightB + errDownB[x+1]; + if (r0 < 0) { + r = 0; + } else if (r0 >= 255) { + r = rgbCubeSize - 1; + } else { + r = div255(r0 * (rgbCubeSize - 1)); + } + if (g0 < 0) { + g = 0; + } else if (g0 >= 255) { + g = rgbCubeSize - 1; + } else { + g = div255(g0 * (rgbCubeSize - 1)); + } + if (b0 < 0) { + b = 0; + } else if (b0 >= 255) { + b = rgbCubeSize - 1; + } else { + b = div255(b0 * (rgbCubeSize - 1)); + } + re = r0 - ((r << 8) - r) / (rgbCubeSize - 1); + ge = g0 - ((g << 8) - g) / (rgbCubeSize - 1); + be = b0 - ((b << 8) - b) / (rgbCubeSize - 1); + errRightR = (re * 7) >> 4; + errRightG = (ge * 7) >> 4; + errRightB = (be * 7) >> 4; + errDownR[x] += (re * 3) >> 4; + errDownG[x] += (ge * 3) >> 4; + errDownB[x] += (be * 3) >> 4; + errDownR[x+1] = ((re * 5) >> 4) + errDownRightR; + errDownG[x+1] = ((ge * 5) >> 4) + errDownRightG; + errDownB[x+1] = ((be * 5) >> 4) + errDownRightB; + errDownRightR = re >> 4; + errDownRightG = ge >> 4; + errDownRightB = be >> 4; + pixel = colors[(r * rgbCubeSize + g) * rgbCubeSize + b]; + XPutPixel(image, xSrc + x, ySrc + y, pixel); + p += 3; + } + } + gfree(errDownR); + gfree(errDownG); + gfree(errDownB); + } +} + +void XPDFCore::redrawRect(PDFCoreTile *tileA, int xSrc, int ySrc, + int xDest, int yDest, int width, int height, + GBool composited) { + XPDFCoreTile *tile = (XPDFCoreTile *)tileA; + Window drawAreaWin; + XGCValues gcValues; + + // create a GC for the drawing area + drawAreaWin = XtWindow(drawArea); + if (!drawAreaGC) { + gcValues.foreground = mattePixel; + drawAreaGC = XCreateGC(display, drawAreaWin, GCForeground, &gcValues); + } + + // draw the document + if (tile) { + XPutImage(display, drawAreaWin, drawAreaGC, tile->image, + xSrc, ySrc, xDest, yDest, width, height); + + // draw the background + } else { + XFillRectangle(display, drawAreaWin, drawAreaGC, + xDest, yDest, width, height); + } +} + +void XPDFCore::updateScrollbars() { + Arg args[20]; + int n; + int maxPos; + + if (pages->getLength() > 0) { + if (continuousMode) { + maxPos = maxPageW; + } else { + maxPos = ((PDFCorePage *)pages->get(0))->w; + } + } else { + maxPos = 1; + } + if (maxPos < drawAreaWidth) { + maxPos = drawAreaWidth; + } + n = 0; + XtSetArg(args[n], XmNvalue, scrollX); ++n; + XtSetArg(args[n], XmNmaximum, maxPos); ++n; + XtSetArg(args[n], XmNsliderSize, drawAreaWidth); ++n; + XtSetArg(args[n], XmNincrement, 16); ++n; + XtSetArg(args[n], XmNpageIncrement, drawAreaWidth); ++n; + XtSetValues(hScrollBar, args, n); + + if (pages->getLength() > 0) { + if (continuousMode) { + maxPos = totalDocH; + } else { + maxPos = ((PDFCorePage *)pages->get(0))->h; + } + } else { + maxPos = 1; + } + if (maxPos < drawAreaHeight) { + maxPos = drawAreaHeight; + } + n = 0; + XtSetArg(args[n], XmNvalue, scrollY); ++n; + XtSetArg(args[n], XmNmaximum, maxPos); ++n; + XtSetArg(args[n], XmNsliderSize, drawAreaHeight); ++n; + XtSetArg(args[n], XmNincrement, 16); ++n; + XtSetArg(args[n], XmNpageIncrement, drawAreaHeight); ++n; + XtSetValues(vScrollBar, args, n); +} + +void XPDFCore::setCursor(Cursor cursor) { + Window topWin; + + if (cursor == currentCursor) { + return; + } + if (!(topWin = XtWindow(shell))) { + return; + } + if (cursor == None) { + XUndefineCursor(display, topWin); + } else { + XDefineCursor(display, topWin, cursor); + } + XFlush(display); + currentCursor = cursor; +} + +GBool XPDFCore::doQuestionDialog(char *title, GString *msg) { + return doDialog(XmDIALOG_QUESTION, gTrue, title, msg); +} + +void XPDFCore::doInfoDialog(char *title, GString *msg) { + doDialog(XmDIALOG_INFORMATION, gFalse, title, msg); +} + +void XPDFCore::doErrorDialog(char *title, GString *msg) { + doDialog(XmDIALOG_ERROR, gFalse, title, msg); +} + +GBool XPDFCore::doDialog(int type, GBool hasCancel, + char *title, GString *msg) { + Widget dialog, scroll, text; + XtAppContext appContext; + Arg args[20]; + int n; + XmString s1, s2; + XEvent event; + + n = 0; + XtSetArg(args[n], XmNdialogType, type); ++n; + XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n; + s1 = XmStringCreateLocalized(title); + XtSetArg(args[n], XmNdialogTitle, s1); ++n; + s2 = NULL; // make gcc happy + if (msg->getLength() <= 80) { + s2 = XmStringCreateLocalized(msg->getCString()); + XtSetArg(args[n], XmNmessageString, s2); ++n; + } + dialog = XmCreateMessageDialog(drawArea, "questionDialog", args, n); + XmStringFree(s1); + if (msg->getLength() <= 80) { + XmStringFree(s2); + } else { + n = 0; + XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); ++n; + if (drawAreaWidth > 300) { + XtSetArg(args[n], XmNwidth, drawAreaWidth - 100); ++n; + } + scroll = XmCreateScrolledWindow(dialog, "scroll", args, n); + XtManageChild(scroll); + n = 0; + XtSetArg(args[n], XmNeditable, False); ++n; + XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); ++n; + XtSetArg(args[n], XmNvalue, msg->getCString()); ++n; + XtSetArg(args[n], XmNshadowThickness, 0); ++n; + text = XmCreateText(scroll, "text", args, n); + XtManageChild(text); + } + XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON)); + XtAddCallback(dialog, XmNokCallback, + &dialogOkCbk, (XtPointer)this); + if (hasCancel) { + XtAddCallback(dialog, XmNcancelCallback, + &dialogCancelCbk, (XtPointer)this); + } else { + XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON)); + } + + XtManageChild(dialog); + + appContext = XtWidgetToApplicationContext(dialog); + dialogDone = 0; + do { + XtAppNextEvent(appContext, &event); + XtDispatchEvent(&event); + } while (!dialogDone); + + XtUnmanageChild(dialog); + XtDestroyWidget(dialog); + + return dialogDone > 0; +} + +void XPDFCore::dialogOkCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + + core->dialogDone = 1; +} + +void XPDFCore::dialogCancelCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + + core->dialogDone = -1; +} + +//------------------------------------------------------------------------ +// password dialog +//------------------------------------------------------------------------ + +void XPDFCore::initPasswordDialog() { + Widget row, label, okBtn, cancelBtn; + Arg args[20]; + int n; + XmString s; + + //----- dialog + n = 0; + s = XmStringCreateLocalized(xpdfAppName ": Password"); + XtSetArg(args[n], XmNdialogTitle, s); ++n; + XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n; + passwordDialog = XmCreateFormDialog(drawArea, "passwordDialog", args, n); + XmStringFree(s); + + //----- message + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNtopOffset, 4); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 4); ++n; + s = XmStringCreateLocalized("This document requires a password."); + XtSetArg(args[n], XmNlabelString, s); ++n; + label = XmCreateLabel(passwordDialog, "msg", args, n); + XmStringFree(s); + XtManageChild(label); + + //----- label and password entry + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNtopWidget, label); ++n; + XtSetArg(args[n], XmNtopOffset, 4); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 4); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 4); ++n; + XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n; + XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); ++n; + row = XmCreateRowColumn(passwordDialog, "row", args, n); + XtManageChild(row); + n = 0; + s = XmStringCreateLocalized("Password: "); + XtSetArg(args[n], XmNlabelString, s); ++n; + label = XmCreateLabel(row, "label", args, n); + XmStringFree(s); + XtManageChild(label); + n = 0; + XtSetArg(args[n], XmNcolumns, 16); ++n; + passwordText = XmCreateTextField(row, "text", args, n); + XtManageChild(passwordText); + XtAddCallback(passwordText, XmNmodifyVerifyCallback, + &passwordTextVerifyCbk, this); + + //----- "Ok" and "Cancel" buttons + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNtopWidget, row); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 4); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomOffset, 4); ++n; + XtSetArg(args[n], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP); ++n; + okBtn = XmCreatePushButton(passwordDialog, "Ok", args, n); + XtManageChild(okBtn); + XtAddCallback(okBtn, XmNactivateCallback, + &passwordOkCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNtopWidget, row); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightOffset, 4); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomOffset, 4); ++n; + XtSetArg(args[n], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP); ++n; + cancelBtn = XmCreatePushButton(passwordDialog, "Cancel", args, n); + XtManageChild(cancelBtn); + XtAddCallback(cancelBtn, XmNactivateCallback, + &passwordCancelCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNdefaultButton, okBtn); ++n; + XtSetArg(args[n], XmNcancelButton, cancelBtn); ++n; +#if XmVersion > 1001 + XtSetArg(args[n], XmNinitialFocus, passwordText); ++n; +#endif + XtSetValues(passwordDialog, args, n); +} + +void XPDFCore::passwordTextVerifyCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + XmTextVerifyCallbackStruct *data = + (XmTextVerifyCallbackStruct *)callData; + int i, n; + + i = (int)data->startPos; + n = (int)data->endPos - i; + if (i > core->password->getLength()) { + i = core->password->getLength(); + } + if (i + n > core->password->getLength()) { + n = core->password->getLength() - i; + } + core->password->del(i, n); + core->password->insert(i, data->text->ptr, data->text->length); + + for (i = 0; i < data->text->length; ++i) { + data->text->ptr[i] = '*'; + } + data->doit = True; +} + +void XPDFCore::passwordOkCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + + core->dialogDone = 1; +} + +void XPDFCore::passwordCancelCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFCore *core = (XPDFCore *)ptr; + + core->dialogDone = -1; +} + +GString *XPDFCore::getPassword() { + XtAppContext appContext; + XEvent event; + + // NB: set before calling XmTextFieldSetString, because + // SetString will trigger a call to passwordTextVerifyCbk, which + // expects to be valid + password = new GString(); + XmTextFieldSetString(passwordText, ""); + XtManageChild(passwordDialog); + + appContext = XtWidgetToApplicationContext(passwordDialog); + dialogDone = 0; + do { + XtAppNextEvent(appContext, &event); + XtDispatchEvent(&event); + } while (!dialogDone); + XtUnmanageChild(passwordDialog); + + if (dialogDone < 0) { + delete password; + return NULL; + } + return password; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFCore.h swftools-0.9.1/lib/pdf/xpdf/XPDFCore.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFCore.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XPDFCore.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,251 @@ +//======================================================================== +// +// XPDFCore.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef XPDFCORE_H +#define XPDFCORE_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#define Object XtObject +#include +#undef Object +#include "gtypes.h" +#include "gfile.h" // for time_t +#include "SplashTypes.h" +#include "PDFCore.h" + +class GString; +class BaseStream; +class PDFDoc; +class LinkAction; + +//------------------------------------------------------------------------ + +#define xMaxRGBCube 6 // max size of RGB color cube + +//------------------------------------------------------------------------ +// callbacks +//------------------------------------------------------------------------ + +typedef void (*XPDFUpdateCbk)(void *data, GString *fileName, + int pageNum, int numPages, char *linkLabel); + +typedef void (*XPDFActionCbk)(void *data, char *action); + +typedef void (*XPDFKeyPressCbk)(void *data, KeySym key, Guint modifiers, + XEvent *event); + +typedef void (*XPDFMouseCbk)(void *data, XEvent *event); + +//------------------------------------------------------------------------ +// XPDFCore +//------------------------------------------------------------------------ + +class XPDFCore: public PDFCore { +public: + + // Create viewer core inside . + XPDFCore(Widget shellA, Widget parentWidgetA, + SplashColorPtr paperColorA, Gulong paperPixelA, + Gulong mattePixelA, GBool fullScreenA, GBool reverseVideoA, + GBool installCmap, int rgbCubeSizeA); + + ~XPDFCore(); + + //----- loadFile / displayPage / displayDest + + // Load a new file. Returns pdfOk or error code. + virtual int loadFile(GString *fileName, GString *ownerPassword = NULL, + GString *userPassword = NULL); + + // Load a new file, via a Stream instead of a file name. Returns + // pdfOk or error code. + virtual int loadFile(BaseStream *stream, GString *ownerPassword = NULL, + GString *userPassword = NULL); + + // Load an already-created PDFDoc object. + virtual void loadDoc(PDFDoc *docA); + + // Resize the window to fit page of the current document. + void resizeToPage(int pg); + + // Update the display, given the specified parameters. + virtual void update(int topPageA, int scrollXA, int scrollYA, + double zoomA, int rotateA, + GBool force, GBool addToHist); + + //----- page/position changes + + virtual GBool gotoNextPage(int inc, GBool top); + virtual GBool gotoPrevPage(int dec, GBool top, GBool bottom); + virtual GBool goForward(); + virtual GBool goBackward(); + + //----- selection + + void startSelection(int wx, int wy); + void endSelection(int wx, int wy); + void copySelection(); + void startPan(int wx, int wy); + void endPan(int wx, int wy); + + //----- hyperlinks + + void doAction(LinkAction *action); + LinkAction *getLinkAction() { return linkAction; } + GString *mungeURL(GString *url); + + //----- find + + virtual GBool find(char *s, GBool caseSensitive, + GBool next, GBool backward, GBool onePageOnly); + virtual GBool findU(Unicode *u, int len, GBool caseSensitive, + GBool next, GBool backward, GBool onePageOnly); + + //----- simple modal dialogs + + GBool doQuestionDialog(char *title, GString *msg); + void doInfoDialog(char *title, GString *msg); + void doErrorDialog(char *title, GString *msg); + + //----- password dialog + + GString *getPassword(); + + //----- misc access + + Widget getWidget() { return scrolledWin; } + Widget getDrawAreaWidget() { return drawArea; } + virtual void setBusyCursor(GBool busy); + Cursor getBusyCursor() { return busyCursor; } + void takeFocus(); + void enableHyperlinks(GBool on) { hyperlinksEnabled = on; } + GBool getHyperlinksEnabled() { return hyperlinksEnabled; } + void enableSelect(GBool on) { selectEnabled = on; } + void setUpdateCbk(XPDFUpdateCbk cbk, void *data) + { updateCbk = cbk; updateCbkData = data; } + void setActionCbk(XPDFActionCbk cbk, void *data) + { actionCbk = cbk; actionCbkData = data; } + void setKeyPressCbk(XPDFKeyPressCbk cbk, void *data) + { keyPressCbk = cbk; keyPressCbkData = data; } + void setMouseCbk(XPDFMouseCbk cbk, void *data) + { mouseCbk = cbk; mouseCbkData = data; } + GBool getFullScreen() { return fullScreen; } + +private: + + virtual GBool checkForNewFile(); + + //----- hyperlinks + void runCommand(GString *cmdFmt, GString *arg); + + //----- selection + static Boolean convertSelectionCbk(Widget widget, Atom *selection, + Atom *target, Atom *type, + XtPointer *value, unsigned long *length, + int *format); + + //----- GUI code + void setupX(GBool installCmap, int rgbCubeSizeA); + void initWindow(); + static void hScrollChangeCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void hScrollDragCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void vScrollChangeCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void vScrollDragCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void resizeCbk(Widget widget, XtPointer ptr, XtPointer callData); + static void redrawCbk(Widget widget, XtPointer ptr, XtPointer callData); + static void inputCbk(Widget widget, XtPointer ptr, XtPointer callData); + virtual PDFCoreTile *newTile(int xDestA, int yDestA); + virtual void updateTileData(PDFCoreTile *tileA, int xSrc, int ySrc, + int width, int height, GBool composited); + virtual void redrawRect(PDFCoreTile *tileA, int xSrc, int ySrc, + int xDest, int yDest, int width, int height, + GBool composited); + virtual void updateScrollbars(); + void setCursor(Cursor cursor); + GBool doDialog(int type, GBool hasCancel, + char *title, GString *msg); + static void dialogOkCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void dialogCancelCbk(Widget widget, XtPointer ptr, + XtPointer callData); + void initPasswordDialog(); + static void passwordTextVerifyCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void passwordOkCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void passwordCancelCbk(Widget widget, XtPointer ptr, + XtPointer callData); + + Gulong paperPixel; + Gulong mattePixel; + //~unimp: move fullScreen into PDFCore? + GBool fullScreen; + + Display *display; + int screenNum; + Visual *visual; + Colormap colormap; + Guint depth; // visual depth + GBool trueColor; // set if using a TrueColor visual + int rDiv, gDiv, bDiv; // RGB right shifts (for TrueColor) + int rShift, gShift, bShift; // RGB left shifts (for TrueColor) + int rgbCubeSize; // size of color cube (for non-TrueColor) + Gulong // color cube (for non-TrueColor) + colors[xMaxRGBCube * xMaxRGBCube * xMaxRGBCube]; + + Widget shell; // top-level shell containing the widget + Widget parentWidget; // parent widget (not created by XPDFCore) + Widget scrolledWin; + Widget hScrollBar; + Widget vScrollBar; + Widget drawAreaFrame; + Widget drawArea; + Cursor busyCursor, linkCursor, selectCursor; + Cursor currentCursor; + GC drawAreaGC; // GC for blitting into drawArea + + static GString *currentSelection; // selected text + static XPDFCore *currentSelectionOwner; + static Atom targetsAtom; + + GBool panning; + int panMX, panMY; + + time_t modTime; // last modification time of PDF file + + LinkAction *linkAction; // mouse cursor is over this link + + XPDFUpdateCbk updateCbk; + void *updateCbkData; + XPDFActionCbk actionCbk; + void *actionCbkData; + XPDFKeyPressCbk keyPressCbk; + void *keyPressCbkData; + XPDFMouseCbk mouseCbk; + void *mouseCbkData; + + GBool hyperlinksEnabled; + GBool selectEnabled; + + int dialogDone; + + Widget passwordDialog; + Widget passwordText; + GString *password; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/xpdf.dt swftools-0.9.1/lib/pdf/xpdf/xpdf.dt --- swftools-0.9.2+ds1/lib/pdf/xpdf/xpdf.dt 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/xpdf.dt 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,28 @@ +# simple CDE action for xpdf +# written by Roland.Mainz@informatik.med.uni-giessen.de +# +# To use, copy this file into $HOME/.dt/types +# +# NOTE: this overrides the actions AcroRead and AcroReadPrint +# defined in /usr/dt/appconfig/types/C/solaris.dt + +ACTION AcroRead +{ + TYPE COMMAND + WINDOW_TYPE NO_STDIO + EXEC_STRING xpdf "%(File)Arg_1%" +} + +# NOTE: Add a '-level1' switch to pdftops if your printer does not +# support Level 2 Postscript. +ACTION AcroReadPrint +{ + TYPE COMMAND + WINDOW_TYPE NO_STDIO + EXEC_STRING ksh -c ' \ + MYFILE="%(File)Arg_1%" ; \ + pdftops "${MYFILE}" /dev/stdout | \ + dtlp -w -b "${MYFILE}"' +} + +# EOF. diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/xpdf.hlp swftools-0.9.1/lib/pdf/xpdf/xpdf.hlp --- swftools-0.9.2+ds1/lib/pdf/xpdf/xpdf.hlp 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/xpdf.hlp 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,823 @@ +! Generated automatically by mantohlp +1 xpdf + + xpdf - Portable Document Format (PDF) file viewer for X + (version 3.02) + + xpdf [options] [PDF-file [page | +dest]] + + Xpdf is a viewer for Portable Document Format (PDF) files. + (These are also sometimes also called 'Acrobat' files, + from the name of Adobe's PDF software.) Xpdf runs under + the X Window System on UNIX, VMS, and OS/2. + + To run xpdf, simply type: + + xpdf file.pdf + + where file.pdf is your PDF file. The file name can be + followed by a number specifying the page which should be + displayed first, e.g.: + + xpdf file.pdf 18 + + You can also give a named destination, prefixed with '+' + in place of the page number. (This is only useful with + PDF files that provide named destination targets.) + + You can also start xpdf without opening any files: + + xpdf + + () + +2 ONFIGURATION_FIL + + Xpdf reads a configuration file at startup. It first + tries to find the user's private config file, ~/.xpdfrc. + If that doesn't exist, it looks for a system-wide config + file, typically /usr/local/etc/xpdfrc (but this location + can be changed when xpdf is built). See the xpdfrc(5) man + page for details. + + () + +2 OPTIONS + + Many of the following options can be set with configura- + tion file commands or X resources. These are listed in + square brackets with the description of the corresponding + command line option. + + -g geometry + Set the initial window geometry. (-geometry is + equivalent.) [X resource: xpdf.geometry] + + -title title + Set the window title. By default, the title will + be "xpdf: foo.pdf". [X resource: xpdf.title] + + -cmap Install a private colormap. This is ignored on + TrueColor visuals. [X resource: xpdf.installCmap] + + -rgb number + Set the size of largest RGB cube xpdf will try to + allocate. The default is 5 (for a 5x5x5 cube); set + to a smaller number to conserve color table + entries. This is ignored with private colormaps + and on TrueColor visuals. [X resource: + xpdf.rgbCubeSize] + + -rv Set reverse video mode. This reverses the colors + of everything except images. It may not always + produce great results for PDF files which do weird + things with color. This also causes the paper + color to default to black. [X resource: + xpdf.reverseVideo] + + -papercolor color + Set the "paper color", i.e., the background of the + page display. This will not work too well with PDF + files that do things like filling in white behind + the text. [X resource: xpdf.paperColor] + + -mattecolor color + Set the matte color, i.e., the color used for back- + ground outside the actual page area. (There is a + separate setting, xpdf.fullScreenMatteColor, for + full-screen mode.) [X resource: xpdf.matteColor] + + -z zoom + Set the initial zoom factor. A number specifies a + zoom percentage, where 100 means 72 dpi.You may + also specify 'page', to fit the page to the window + size, or 'width', to fit the page width to the win- + dow width. [config file: initialZoom; or X + resource: xpdf.initialZoom] + + -cont Start in continuous view mode, i.e., with one ver- + tical scroll bar for the whole document. [config + file: continuousView] + + -t1lib yes | no + Enable or disable t1lib (a Type 1 font rasterizer). + This defaults to "yes". [config file: enableT1lib] + + -freetype yes | no + Enable or disable FreeType (a TrueType / Type 1 + font rasterizer). This defaults to "yes". [config + file: enableFreeType] + + -aa yes | no + Enable or disable font anti-aliasing. This + defaults to "yes". [config file: antialias] + + -aaVector yes | no + Enable or disable vector anti-aliasing. This + defaults to "yes". [config file: vectorAntialias] + + -ps PS-file + Set the default file name for PostScript output + (i.e., the name which will appear in the print dia- + log). This can also be of the form '|command' to + pipe the PostScript through a command. [config + file: psFile] + + -paper size + Set the paper size to one of "letter", "legal", + "A4", or "A3". This can also be set to "match", + which will set the paper size to match the size + specified in the PDF file. [config file: psPaper- + Size] + + -paperw size + Set the paper width, in points. [config file: + psPaperSize] + + -paperh size + Set the paper height, in points. [config file: + psPaperSize] + + -level1 + Generate Level 1 PostScript. The resulting + PostScript files will be significantly larger (if + they contain images), but will print on Level 1 + printers. This also converts all images to black + and white. [config file: psLevel] + + -enc encoding-name + Sets the encoding to use for text output. The + encoding-name must be defined with the unicodeMap + command (see xpdfrc(5)). This defaults to "Latin1" + (which is a built-in encoding). [config file: tex- + tEncoding] + + -eol unix | dos | mac + Sets the end-of-line convention to use for text + output. [config file: textEOL] + + -opw password + Specify the owner password for the PDF file. Pro- + viding this will bypass all security restrictions. + + -upw password + Specify the user password for the PDF file. + + -fullscreen + Open xpdf in full-screen mode, useful for presenta- + tions. + + -remote name + Start/contact xpdf remote server with specified + name (see the REMOTE SERVER MODE section below). + + -exec command + Execute a command (see the COMMANDS section below) + in an xpdf remote server window (with -remote + only). + + -reload + Reload xpdf remote server window (with -remote + only). + + -raise Raise xpdf remote server window (with -remote + only). + + -quit Kill xpdf remote server (with -remote only). + + -cmd Print commands as they're executed (useful for + debugging). [config file: printCommands] + + -q Don't print any messages or errors. [config file: + errQuiet] + + -cfg config-file + Read config-file in place of ~/.xpdfrc or the sys- + tem-wide config file. + + -v Print copyright and version information. + + -h Print usage information. (-help and --help are + equivalent.) + + Several other standard X options and resources will work + as expected: + + -display display + [X resource: xpdf.display] + + -fg color + (-foreground is equivalent.) [X resource: + xpdf*Foreground] + + -bg color + (-background is equivalent.) [X resource: + xpdf*Background] + + -font font + (-fn is equivalent.) [X resource: xpdf*fontList] + + The color and font options only affect the user interface + elements, not the PDF display (the 'paper'). + + The following X resources do not have command line option + equivalents: + + xpdf.toolTipEnable + Enables (if set to true) or disables (if set to + false) the tool-tips on the toolbar buttons. + + xpdf.fullScreenMatteColor + Sets the matte color to be used in full-screen + mode. The default setting is "black". + + () + +2 CONTROLS + + On-screen controls, at the bottom of the xpdf window + left/right arrow buttons + Move to the previous/next page. + + double left/right arrow buttons + Move backward or forward by ten pages. + + dashed left/right arrow buttons + Move backward or forward along the history path. + + 'Page' entry box + Move to a specific page number. Click in the box + to activate it, type the page number, then hit + return. + + zoom popup menu + Change the zoom factor (see the description of the + -z option above). + + binoculars button + Find a text string. + + print button + Bring up a dialog for generating a PostScript file. + The dialog has options to set the pages to be + printed and the PostScript file name. The file + name can be '-' for stdout or '|command' to pipe + the PostScript through a command, e.g., '|lpr'. + + '?' button + Bring up the 'about xpdf' window. + + link info + The space between the '?' and 'Quit' buttons is + used to show the URL or external file name when the + mouse is over a link. + + 'Quit' button + Quit xpdf. + + Menu + Pressing the right mouse button will post a popup menu + with the following commands: + + Open... + Open a new PDF file via a file requester. + + Open in new window... + Create a new window and open a new PDF file via a + file requester. + + Reload Reload the current PDF file. Note that Xpdf will + reload the file automatically (on a page change or + redraw) if it has changed since it was last loaded. + + Save as... + Save the current file via a file requester. + + Continuous view + Toggles between single page and continuous view + modes. + + Rotate counterclockwise + Rotate the page 90 degrees counterclockwise. + + Rotate clockwise + Rotate the page 90 degrees clockwise. The two + rotate commands are intended primarily for PDF + files where the rotation isn't correctly specified + in the file. + + Zoom to selection + Zoom in to the currently selected rectangle. + + Close Close the current window. If this is the only open + window, the document is closed, but the window is + left open (i.e., this menu command won't quit + xpdf). + + Quit Quit xpdf. + + Outline + If the PDF contains an outline (a.k.a., bookmarks), there + will be an outline pane on the left side of the window. + The width of the outline pane is adjustable with a verti- + cal split bar via the knob near its bottom end. + + Text selection + Dragging the mouse with the left button held down will + highlight an arbitrary rectangle. Any text inside this + rectangle will be copied to the X selection buffer. + + Links + Clicking on a hyperlink will jump to the link's destina- + tion. A link to another PDF document will make xpdf load + that document. A 'launch' link to an executable program + will display a dialog, and if you click 'ok', execute the + program. URL links call an external command (see the WEB + BROWSERS section below). + + Panning + Dragging the mouse with the middle button held down pans + the window. + + Key bindings + o Open a new PDF file via a file requester. + + r Reload the current PDF file. Note that Xpdf will + reload the file automatically (on a page change or + redraw) if it has changed since it was last loaded. + + control-L + Redraw the current page. + + control-W + Close the current window. + + f or control-F + Find a text string. + + control-G + Find next occurrence. + + control-P + Print. + + n Move to the next page. Scrolls to the top of the + page, unless scroll lock is turned on. + + p Move to the previous page. Scrolls to the top of + the page, unless scroll lock is turned on. + + or or + Scroll down on the current page; if already at bot- + tom, move to next page. + + or or or + Scroll up on the current page; if already at top, + move to previous page. + + v Move forward along the history path. + + b Move backward along the history path. + + Scroll to top of current page. + + Scroll to bottom of current page. + + control- + Scroll to first page of document. + + control- + Scroll to last page of document. + + arrows Scroll the current page. + + g Activate the page number text field ("goto page"). + + 0 Set the zoom factor to 125%. + + + Zoom in (increment the zoom factor by 1). + + - Zoom out (decrement the zoom factor by 1). + + z Set the zoom factor to 'page' (fit page to window). + + w Set the zoom factor to 'width' (fit page width to + window). + + alt-F Toggle full-screen mode. + + q Quit xpdf. + + () + +2 WEB_BROWSERS + + If you want to run xpdf automatically from netscape or + mosaic (and probably other browsers) when you click on a + link to a PDF file, you need to edit (or create) the files + .mime.types and .mailcap in your home directory. In + .mime.types add the line: + + application/pdf pdf + + In .mailcap add the lines: + + # Use xpdf to view PDF files. + application/pdf; xpdf -q %s + + Make sure that xpdf is on your executable search path. + + When you click on a URL link in a PDF file, xpdf will exe- + cute the command specified by the urlCommand config file + option, replacing an occurrence of '%s' with the URL. For + example, to call netscape with the URL, add this line to + your config file: + + urlCommand "netscape -remote 'openURL(%s)'" + + () + +2 COMMANDS + + Xpdf's key and mouse bindings are user-configurable, using + the bind and unbind options in the config file (see + xpdfrc(5)). The bind command allows you to bind a key or + mouse button to a sequence of one or more commands. + + Available Commands + The following commands are supported: + + gotoPage(page) + Go to the specified page. + + gotoPageNoScroll(page) + Go to the specified page, with the current relative + scroll position. + + gotoDest(dest) + Go to a named destination. + + gotoLastPage + Go to the last page in the PDF file. + + gotoLastPageNoScroll + Go to the last page in the PDF file, with the cur- + rent relative scroll position. + + nextPage + Go to the next page. + + nextPageNoScroll + Go to the next page, with the current relative + scroll position. + + prevPage + Go to the previous page. + + prevPageNoScroll + Go to the previous page, with the current relative + scroll position. + + pageUp Scroll up by one screenful. + + pageDown + Scroll down by one screenful. + + scrollLeft(n) + Scroll left by n pixels. + + scrollRight(n) + Scroll right by n pixels. + + scrollUp(n) + Scroll up by n pixels. + + scrollDown(n) + Scroll down by n pixels. + + scrollUpPrevPage(n) + Scroll up by n pixels, moving to the previous page + if appropriate. + + scrollDownPrevPage(n) + Scroll down by n pixels, moving to the next page if + appropriate. + + scrollToTopEdge + Scroll to the top edge of the current page, with no + horizontal movement. + + scrollToBottomEdge + Scroll to the bottom edge of the current page, with + no horizontal movement. + + scrollToLeftEdge + Scroll to the left edge of the current page, with + no vertical movement. + + scrollToRightEdge + Scroll to the right edge of the current page, with + no vertical movement. + + scrollToTopLeft + Scroll to the top-left corner of the current page. + + scrollToBottomRight + Scroll to the bottom-right corner of the current + page. + + goForward + Move forward along the history path. + + goBackward + Move backward along the history path. + + zoomPercent(z) + Set the zoom factor to z%. + + zoomFitPage + Set the zoom factor to fit-page. + + zoomFitWidth + Set the zoom factor to fit-width. + + zoomIn Zoom in - go to the next higher zoom factor. + + zoomOut + Zoom out - go the next lower zoom factor. + + continuousMode + Go to continuous view mode. + + singlePageMode + Go to single-page view mode. + + toggleContinuousMode + Toggle between continuous and single page view + modes. + + fullScreenMode + Go to full-screen mode. + + windowMode + Go to window (non-full-screen) mode. + + toggleFullScreenMode + Toggle between full-screen and window modes. + + open Open a PDF file in this window, using the open + dialog. + + openInNewWin + Open a PDF file in a new window, using the open + dialog. + + openFile(file) + Open a specified PDF file in this window. + + openFileInNewWin(file) + Open a specified PDF file in a new window. + + openFileAtDest(file,dest) + Open a specified PDF file in this window and go to + a named destination. + + openFileAtDestInNewWin(file,dest) + Open a specified PDF file in a new window and go to + a named destination. + + reload Reload the current PDF file. + + redraw Redraw the window. + + raise Raise the window to the front. + + closeWindow + Close the window. + + run(external-command-string) + Run an external command. The following escapes are + allowed in the command string: + + %f => PDF file name (or an empty string if no + file is open) + %b => PDF file base name, i.e., file name minus + the extension (or an empty string if no + file is open) + %u => link URL (or an empty string if not over + a URL link) + %x => selection upper-left x coordinate + (or 0 if there is no selection) + %y => selection upper-left y coordinate + (or 0 if there is no selection) + %X => selection lower-right x coordinate + (or 0 if there is no selection) + %Y => selection lower-right y coordinate + (or 0 if there is no selection) + %% => % + + openOutline + Open the outline pane. + + closeOutline + Close the outline pane. + + toggleOutline + Toggle the outline pane between open and closed. + + scrollOutlineDown(n) + Scroll the outline down by n increments. + + scrollOutlineUp(n) + Scroll the outline up by n increments. + + focusToDocWin + Set the keyboard focus to the main document window. + + focusToPageNum + Set the keyboard focus to the page number text box. + + find Open the 'find' dialog. + + findNext + Finds the next occurrence of the search string (no + dialog). + + print Open the 'print' dialog. + + about Open the 'about' dialog. + + quit Quit from xpdf. + + The following commands depend on the current mouse posi- + tion: + + startSelection + Start a selection, which will be extended as the + mouse moves. + + endSelection + End a selection. + + startPan + Start a pan, which will scroll the document as the + mouse moves + + endPan End a pan. + + postPopupMenu + Display the popup menu. + + followLink + Follow a hyperlink (does nothing if the mouse is + not over a link). + + followLinkInNewWin + Follow a hyperlink, opening PDF files in a new win- + dow (does nothing if the mouse is not over a link). + For links to non-PDF files, this command is identi- + cal to followLink. + + followLinkNoSel + Same as followLink, but does nothing if there is a + non-empty selection. (This is useful as a mouse + button binding.) + + followLinkInNewWinNoSel + Same as followLinkInNewWin, but does nothing if + there is a non-empty selection. (This is useful as + a mouse button binding.) + + Default Bindings + The default mouse bindings are as follows: + + bind mousePress1 any startSelection + bind mouseRelease1 any endSelection followLinkNoSel + bind mousePress2 any startPan + bind mouseRelease2 any endPan + bind mousePress3 any postPopupMenu + bind mousePress4 any scrollUpPrevPage(16) + bind mousePress5 any scrollDownNextPage(16) + bind mousePress6 any scrollLeft(16) + bind mousePress7 any scrollRight(16) + + The default key bindings are as follows: + + bind ctrl-home any gotoPage(1) + bind home any scrollToTopLeft + bind ctrl-end any gotoLastPage + bind end any scrollToBottomRight + bind pgup any pageUp + bind backspace any pageUp + bind delete any pageUp + bind pgdn any pageDown + bind space any pageDown + bind left any scrollLeft(16) + bind right any scrollRight(16) + bind up any scrollUp(16) + bind down any scrollDown(16) + bind o any open + bind O any open + bind r any reload + bind R any reload + bind f any find + bind F any find + bind ctrl-f any find + bind ctrl-g any findNext + bind ctrl-p any print + bind n scrLockOff nextPage + bind N scrLockOff nextPage + bind n scrLockOn nextPageNoScroll + bind N scrLockOn nextPageNoScroll + bind p scrLockOff prevPage + bind P scrLockOff prevPage + bind p scrLockOn prevPageNoScroll + bind P scrLockOn prevPageNoScroll + bind v any goForward + bind b any goBackward + bind g any focusToPageNum + bind 0 any zoomPercent(125) + bind + any zoomIn + bind - any zoomOut + bind z any zoomFitPage + bind w any zoomFitWidth + bind alt-f any toggleFullScreenMode + bind ctrl-l any redraw + bind ctrl-w any closeWindow + bind ? any about + bind q any quit + bind Q any quit + + Previous versions of xpdf included a "viKeys" X resource. + It is no longer available, but the following bindings are + equivalent: + + bind h any scrollLeft(16) + bind l any scrollRight(16) + bind k any scrollUp(16) + bind j any scrollDown(16) + + () + +2 REMOTE_SERVER_MODE + + Xpdf can be started in remote server mode by specifying a + server name (in addition to the file name and page num- + ber). For example: + + xpdf -remote myServer file.pdf + + If there is currently no xpdf running in server mode with + the name 'myServer', a new xpdf window will be opened. If + another command: + + xpdf -remote myServer another.pdf 9 + + is issued, a new copy of xpdf will not be started. + Instead, the first xpdf (the server) will load another.pdf + and display page nine. If the file name is the same: + + xpdf -remote myServer another.pdf 4 + + the xpdf server will simply display the specified page. + + The -raise option tells the server to raise its window; it + can be specified with or without a file name and page num- + ber. + + The -quit option tells the server to close its window and + exit. + + () + +2 XIT_CODE + + The Xpdf tools use the following exit codes: + + 0 No error. + + 1 Error opening a PDF file. + + 2 Error opening an output file. + + 3 Error related to PDF permissions. + + 99 Other error. + + () + +2 AUTHOR + + The xpdf software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + + () + +2 SEE_ALSO + + pdftops(1), pdftotext(1), pdfinfo(1), pdffonts(1), + pdftoppm(1), pdfimages(1), xpdfrc(5) + http://www.foolabs.com/xpdf/ + + () + diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/xpdfIcon.xpm swftools-0.9.1/lib/pdf/xpdf/xpdfIcon.xpm --- swftools-0.9.2+ds1/lib/pdf/xpdf/xpdfIcon.xpm 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/xpdfIcon.xpm 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,62 @@ +/* XPM */ +static char *xpdfIcon[] = { +/* width height num_colors chars_per_pixel */ +" 48 48 7 1", +/* colors */ +". c #000000", +"# c #a00000", +"a c #a0a0a0", +"b c #c0c0c0", +"c c #e00000", +"d c #e0e0e0", +"e c #ffffff", +/* pixels */ +"................................................", +"................................................", +"................................................", +"................................................", +"#ccccccc#................................#ccc#..", +".#ccccccc#..............................#ccc#...", +"..#ccccccc#............................#ccc#....", +"...#ccccccc#................bbba.....abbbc#.....", +"....#ccccccc#...............beea....debbed......", +".....#ccccccc#...............ee....bebccee......", +"......#ccccccc#..............ee....eecc#bb......", +".......#ccccccc#............aee...#eec#.........", +"........#ccccccc#...........bed..#beb#..........", +".........#ccccccc#..........beb.#cbeb...........", +"..........#ccccccc#.........beb#ccbeb...........", +"...........#ccccccc#........bebcccbeb...........", +"............#ccccccc#.......eebcc#dea...........", +".............#ccccccc#......eecc#.ee............", +".........ae...#ccccccc#....#eec#..ee............", +"........aeeaeeeebcccccabeeeaee#.beeeeee.........", +".......aeeeea..debcccaed##ceee....ee............", +"......addee.....eeccaedccccbed...beb............", +"......a.bee.....ee#cbeaccccbeb...beb............", +"........beb.....ee.#eecccccbeb...beb............", +"........beb.....ee..eecccccbeb...beb............", +"........beb.....ee..eeccccceeb...dea............", +"........deb....aeb.#eeccccceec#..ee.............", +"........eea....dea#cee##ccceecc#.ee.............", +"........eee...dea#ccbeda#cdeeccc#ee.............", +"........eeaeeeba#ccc#beeeeaeeecceeee............", +"........ee.....#ccc#......#ccccccc#.............", +".......bee....#ccc#........#ccccccc#............", +".......beb...#ccc#..........#ccccccc#...........", +".......beb..#ccc#............#ccccccc#..........", +".......beb.#ccc#..............#ccccccc#.........", +".......deb#ccc#................#ccccccc#........", +".......eeaccc#..................#ccccccc#.......", +".......eeccc#....................#ccccccc#......", +".......eecc#......................#ccccccc#.....", +"......beeb#........................#ccccccc#....", +".....#bbbb..........................#ccccccc#...", +"....#ccc#............................#ccccccc#..", +"...#ccc#..............................#ccccccc#.", +"..#ccc#................................#ccccccc.", +"................................................", +"................................................", +"................................................", +"................................................" +}; diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XpdfPluginAPI.cc swftools-0.9.1/lib/pdf/xpdf/XpdfPluginAPI.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/XpdfPluginAPI.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XpdfPluginAPI.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,262 @@ +//======================================================================== +// +// XpdfPluginAPI.cc +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#include "aconf.h" + +#ifdef ENABLE_PLUGINS + +#include "gmem.h" +#include "GlobalParams.h" +#include "Object.h" +#include "PDFDoc.h" +#ifdef WIN32 +#include "WinPDFCore.h" +#else +#include "XPDFCore.h" +#endif +#include "XpdfPluginAPI.h" + +//------------------------------------------------------------------------ + +//~ This should use a pool of Objects; change xpdfFreeObj to match. +static Object *allocObj() { + return (Object *)gmalloc(sizeof(Object)); +} + +//------------------------------------------------------------------------ +// Document access functions +//------------------------------------------------------------------------ + +XpdfObject _xpdfGetInfoDict(XpdfDoc doc) { + Object *obj; + + obj = allocObj(); + return (XpdfObject)((PDFDoc *)doc)->getDocInfo(obj); +} + +XpdfObject _xpdfGetCatalog(XpdfDoc doc) { + Object *obj; + + obj = allocObj(); + return (XpdfObject)((PDFDoc *)doc)->getXRef()->getCatalog(obj); +} + +#ifdef _WIN32 + +HWND _xpdfWin32GetWindow(XpdfDoc doc) { + WinPDFCore *core; + + if (!(core = (WinPDFCore *)((PDFDoc *)doc)->getGUIData())) { + return NULL; + } + return core->getDrawFrame(); +} + +#else + +Widget _xpdfXGetWindow(XpdfDoc doc) { + XPDFCore *core; + + if (!(core = (XPDFCore *)((PDFDoc *)doc)->getGUIData())) { + return NULL; + } + return core->getWidget(); +} + +#endif + +//------------------------------------------------------------------------ +// Object access functions. +//------------------------------------------------------------------------ + +XpdfBool _xpdfObjIsBool(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isBool(); +} + +XpdfBool _xpdfObjIsInt(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isInt(); +} + +XpdfBool _xpdfObjIsReal(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isReal(); +} + +XpdfBool _xpdfObjIsNumber(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isNum(); +} + +XpdfBool _xpdfObjIsString(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isString(); +} + +XpdfBool _xpdfObjIsName(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isName(); +} + +XpdfBool _xpdfObjIsNull(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isNull(); +} + +XpdfBool _xpdfObjIsArray(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isArray(); +} + +XpdfBool _xpdfObjIsDict(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isDict(); +} + +XpdfBool _xpdfObjIsStream(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isStream(); +} + +XpdfBool _xpdfObjIsRef(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->isRef(); +} + +XpdfBool _xpdfBoolValue(XpdfObject obj) { + return (XpdfBool)((Object *)obj)->getBool(); +} + +int _xpdfIntValue(XpdfObject obj) { + if (!((Object *)obj)->isInt()) { + return 0; + } + return ((Object *)obj)->getInt(); +} + +double _xpdfRealValue(XpdfObject obj) { + if (!((Object *)obj)->isReal()) { + return 0; + } + return ((Object *)obj)->getReal(); +} + +double _xpdfNumberValue(XpdfObject obj) { + if (!((Object *)obj)->isNum()) { + return 0; + } + return ((Object *)obj)->getNum(); +} + +int _xpdfStringLength(XpdfObject obj) { + if (!((Object *)obj)->isString()) { + return 0; + } + return ((Object *)obj)->getString()->getLength(); +} + +char *_xpdfStringValue(XpdfObject obj) { + if (!((Object *)obj)->isString()) { + return 0; + } + return ((Object *)obj)->getString()->getCString(); +} + +char *_xpdfNameValue(XpdfObject obj) { + if (!((Object *)obj)->isName()) { + return NULL; + } + return ((Object *)obj)->getName(); +} + +int _xpdfArrayLength(XpdfObject obj) { + if (!((Object *)obj)->isArray()) { + return 0; + } + return ((Object *)obj)->arrayGetLength(); +} + +XpdfObject _xpdfArrayGet(XpdfObject obj, int idx) { + Object *elem; + + elem = allocObj(); + if (!((Object *)obj)->isArray()) { + return (XpdfObject)elem->initNull(); + } + return (XpdfObject)((Object *)obj)->arrayGet(idx, elem); +} + +XpdfObject _xpdfDictGet(XpdfObject obj, char *key) { + Object *elem; + + elem = allocObj(); + if (!((Object *)obj)->isDict()) { + return (XpdfObject)elem->initNull(); + } + return (XpdfObject)((Object *)obj)->dictLookup(key, elem); +} + +void _xpdfFreeObj(XpdfObject obj) { + ((Object *)obj)->free(); + gfree(obj); +} + +//------------------------------------------------------------------------ +// Memory allocation functions +//------------------------------------------------------------------------ + +void *_xpdfMalloc(int size) { + return gmalloc(size); +} + +void *_xpdfRealloc(void *p, int size) { + return grealloc(p, size); +} + +void _xpdfFree(void *p) { + gfree(p); +} + +//------------------------------------------------------------------------ +// Security handlers +//------------------------------------------------------------------------ + +void _xpdfRegisterSecurityHandler(XpdfSecurityHandler *handler) { + if (handler->version <= xpdfPluginAPIVersion) { + globalParams->addSecurityHandler(handler); + } +} + +//------------------------------------------------------------------------ + +XpdfPluginVecTable xpdfPluginVecTable = { + xpdfPluginAPIVersion, + &_xpdfGetInfoDict, + &_xpdfGetCatalog, +#ifdef _WIN32 + &_xpdfWin32GetWindow, +#else + &_xpdfXGetWindow, +#endif + &_xpdfObjIsBool, + &_xpdfObjIsInt, + &_xpdfObjIsReal, + &_xpdfObjIsString, + &_xpdfObjIsName, + &_xpdfObjIsNull, + &_xpdfObjIsArray, + &_xpdfObjIsDict, + &_xpdfObjIsStream, + &_xpdfObjIsRef, + &_xpdfBoolValue, + &_xpdfIntValue, + &_xpdfRealValue, + &_xpdfStringLength, + &_xpdfStringValue, + &_xpdfNameValue, + &_xpdfArrayLength, + &_xpdfArrayGet, + &_xpdfDictGet, + &_xpdfFreeObj, + &_xpdfMalloc, + &_xpdfRealloc, + &_xpdfFree, + &_xpdfRegisterSecurityHandler, +}; + +#endif // ENABLE_PLUGINS diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XpdfPluginAPI.h swftools-0.9.1/lib/pdf/xpdf/XpdfPluginAPI.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/XpdfPluginAPI.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XpdfPluginAPI.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,341 @@ +/* + * XpdfPluginAPI.h + * + * Copyright 2004 Glyph & Cog, LLC + */ + +#ifndef XPDFPLUGINAPI_H +#define XPDFPLUGINAPI_H + +#ifdef _WIN32 +#include +#else +#define Object XtObject +#include +#undef Object +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*------------------------------------------------------------------------ + * Macros + *------------------------------------------------------------------------*/ + +/* + * The current API version. + */ +#define xpdfPluginAPIVersion 1 + +#ifdef _WIN32 +# ifdef __cplusplus +# define PLUGINFUNC(retType) extern "C" __declspec(dllexport) retType +# else +# define PLUGINFUNC(retType) extern __declspec(dllexport) retType +# endif +#else +# ifdef __cplusplus +# define PLUGINFUNC(retType) extern "C" retType +# else +# define PLUGINFUNC(retType) extern retType +# endif +#endif + +/*------------------------------------------------------------------------ + * Plugin setup/cleanup + *------------------------------------------------------------------------*/ + +/* + * All plugins are required to implement two functions: + * + * -- Initialize the plugin. Returns non-zero if successful. + * PLUGINFUNC(XpdfBool) xpdfInitPlugin(void); + * + * -- Free the plugin. + * PLUGINFUNC(void) xpdfFreePlugin(void); + */ + +/*------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------*/ + +/* + * Standard C boolean -- zero = false, non-zero = true. + */ +typedef int XpdfBool; +#define xpdfTrue 1 +#define xpdfFalse 0 + +/* + * PDF document handle. + */ +typedef struct _XpdfDoc *XpdfDoc; + +/* + * PDF object handle. + */ +typedef struct _XpdfObject *XpdfObject; + +/* + * Document access permissions. Any of these can be bitwise 'or'ed + * together. If xpdfPermissionOpen is not included, the document + * cannot be opened at all, and the other bits are ignored. + */ +typedef unsigned int XpdfPermission; +#define xpdfPermissionOpen (1 << 0) +#define xpdfPermissionPrint (1 << 2) +#define xpdfPermissionChange (1 << 3) +#define xpdfPermissionCopy (1 << 4) +#define xpdfPermissionNotes (1 << 5) + +/*------------------------------------------------------------------------ + * Security handler + *------------------------------------------------------------------------*/ + +/* + * XpdfSecurityHandler - a security handler plugin should create one + * of these and pass it to xpdfRegisterSecurityHandler. + */ +#ifdef __cplusplus +struct XpdfSecurityHandler { +#else +typedef struct { +#endif + + /* + * Version of the security handler spec (this document) -- use + * xpdfPluginAPIVersion. + */ + int version; + + /* + * Security handler name. + */ + char *name; + + /* + * Any global data the security handler needs. XpdfViewer will pass + * this pointer to all handler functions as the + * argument. + */ + void *handlerData; + + /* + * Allocate and initialize data for a new document. XpdfViewer will + * pass the returned pointer to all other handler functions as the + * argument. Returns non-zero if successful. + */ + XpdfBool (*newDoc)(void *handlerData, XpdfDoc doc, + XpdfObject encryptDict, void **docData); + + /* + * Free the data allocated by newDoc. + */ + void (*freeDoc)(void *handlerData, void *docData); + + /* + * Construct authorization data based on the supplied owner and user + * passwords (either or both of which may be NULL). This function + * is called in "batch" mode, i.e., if the password was supplied on + * the command line or via an Xpdf library API. It should not + * generate any user interaction (e.g., a password dialog). It is + * not required to support this function: the makeAuthData function + * pointer can be set to NULL. Returns non-zero if successful. + */ + XpdfBool (*makeAuthData)(void *handlerData, void *docData, + char *ownerPassword, char *userPassword, + void **authData); + + /* + * Request any needed information (e.g., a password) from the user, + * and construct an authorization data object. Returns non-zero if + * successful. + */ + XpdfBool (*getAuthData)(void *handlerData, void *docData, + void **authData); + + /* + * Free the data allocated by getAuthData. + */ + void (*freeAuthData)(void *handlerData, void *docData, + void *authData); + + /* + * Request permission to access the document. This returns all + * permissions granted by authData. + */ + XpdfPermission (*authorize)(void *handlerData, void *docData, + void *authData); + + /* + * Get the decryption key and algorithm version associated with the + * document. Returns non-zero if successful. + */ + XpdfBool (*getKey)(void *handlerData, void *docData, + char **key, int *keyLen, int *cryptVersion); + + /* + * Free the data allocated by getKey. + */ + void (*freeKey)(void *handlerData, void *docData, + char *key, int keyLen); + +#ifdef __cplusplus +}; +#else +} XpdfSecurityHandler; +#endif + +/*------------------------------------------------------------------------*/ + +typedef struct { + int version; + +/*------------------------------------------------------------------------ + * Document access functions + *------------------------------------------------------------------------*/ + +/* + * Get a document's info dictionary. (The returned object must be + * freed with xpdfFreeObj.) + */ +XpdfObject (*_xpdfGetInfoDict)(XpdfDoc doc); + +/* + * Get a document's catalog ("root") dictionary. (The returned object + * must be freed with xpdfFreeObj.) + */ +XpdfObject (*_xpdfGetCatalog)(XpdfDoc doc); + +#ifdef _WIN32 + +/* + * Get the handle for the viewer window associated with the specified + * document. [Win32 only] + */ +HWND (*_xpdfWin32GetWindow)(XpdfDoc doc); + +#else + +/* + * Get the Motif widget for the viewer window associated with the + * specified document. [X only] + */ +Widget (*_xpdfXGetWindow)(XpdfDoc doc); + +#endif + +/*------------------------------------------------------------------------ + * Object access functions + *------------------------------------------------------------------------*/ + +/* + * Check an object's type. + */ +XpdfBool (*_xpdfObjIsBool)(XpdfObject obj); +XpdfBool (*_xpdfObjIsInt)(XpdfObject obj); +XpdfBool (*_xpdfObjIsReal)(XpdfObject obj); +XpdfBool (*_xpdfObjIsString)(XpdfObject obj); +XpdfBool (*_xpdfObjIsName)(XpdfObject obj); +XpdfBool (*_xpdfObjIsNull)(XpdfObject obj); +XpdfBool (*_xpdfObjIsArray)(XpdfObject obj); +XpdfBool (*_xpdfObjIsDict)(XpdfObject obj); +XpdfBool (*_xpdfObjIsStream)(XpdfObject obj); +XpdfBool (*_xpdfObjIsRef)(XpdfObject obj); + +/* + * Value access. + * (Objects returned by xpdfArrayGet and xpdfDictGet must be freed + * with xpdfFreeObj.) + */ +XpdfBool (*_xpdfBoolValue)(XpdfObject obj); +int (*_xpdfIntValue)(XpdfObject obj); +double (*_xpdfRealValue)(XpdfObject obj); +int (*_xpdfStringLength)(XpdfObject obj); +char *(*_xpdfStringValue)(XpdfObject obj); +char *(*_xpdfNameValue)(XpdfObject obj); +int (*_xpdfArrayLength)(XpdfObject obj); +XpdfObject (*_xpdfArrayGet)(XpdfObject obj, int idx); +XpdfObject (*_xpdfDictGet)(XpdfObject obj, char *key); + +/* + * Object destruction. NB: *all* objects must be freed after use. + */ +void (*_xpdfFreeObj)(XpdfObject obj); + +/*------------------------------------------------------------------------ + * Memory allocation functions + *------------------------------------------------------------------------*/ + +void *(*_xpdfMalloc)(int size); +void *(*_xpdfRealloc)(void *p, int size); +void (*_xpdfFree)(void *p); + +/*------------------------------------------------------------------------ + * Security handler functions + *------------------------------------------------------------------------*/ + +/* + * Register a new security handler. + */ +void (*_xpdfRegisterSecurityHandler)(XpdfSecurityHandler *handler); + +/*------------------------------------------------------------------------*/ + +} XpdfPluginVecTable; + +#ifdef _WIN32 + +extern __declspec(dllexport) XpdfPluginVecTable xpdfPluginVecTable; + +#define xpdfPluginSetup \ + extern __declspec(dllexport) \ + XpdfPluginVecTable xpdfPluginVecTable = {xpdfPluginAPIVersion}; + +#else + +extern XpdfPluginVecTable xpdfPluginVecTable; + +#define xpdfPluginSetup \ + XpdfPluginVecTable xpdfPluginVecTable = {xpdfPluginAPIVersion}; + +#endif + +#define xpdfGetInfoDict (*xpdfPluginVecTable._xpdfGetInfoDict) +#define xpdfGetCatalog (*xpdfPluginVecTable._xpdfGetCatalog) +#ifdef _WIN32 +#define xpdfWin32GetWindow (*xpdfPluginVecTable._xpdfWin32GetWindow) +#else +#define xpdfXGetWindow (*xpdfPluginVecTable._xpdfXGetWindow) +#endif +#define xpdfObjIsBool (*xpdfPluginVecTable._xpdfObjIsBool) +#define xpdfObjIsInt (*xpdfPluginVecTable._xpdfObjIsInt) +#define xpdfObjIsReal (*xpdfPluginVecTable._xpdfObjIsReal) +#define xpdfObjIsString (*xpdfPluginVecTable._xpdfObjIsString) +#define xpdfObjIsName (*xpdfPluginVecTable._xpdfObjIsName) +#define xpdfObjIsNull (*xpdfPluginVecTable._xpdfObjIsNull) +#define xpdfObjIsArray (*xpdfPluginVecTable._xpdfObjIsArray) +#define xpdfObjIsDict (*xpdfPluginVecTable._xpdfObjIsDict) +#define xpdfObjIsStream (*xpdfPluginVecTable._xpdfObjIsStream) +#define xpdfObjIsRef (*xpdfPluginVecTable._xpdfObjIsRef) +#define xpdfBoolValue (*xpdfPluginVecTable._xpdfBoolValue) +#define xpdfIntValue (*xpdfPluginVecTable._xpdfIntValue) +#define xpdfRealValue (*xpdfPluginVecTable._xpdfRealValue) +#define xpdfStringLength (*xpdfPluginVecTable._xpdfStringLength) +#define xpdfStringValue (*xpdfPluginVecTable._xpdfStringValue) +#define xpdfNameValue (*xpdfPluginVecTable._xpdfNameValue) +#define xpdfArrayLength (*xpdfPluginVecTable._xpdfArrayLength) +#define xpdfArrayGet (*xpdfPluginVecTable._xpdfArrayGet) +#define xpdfDictGet (*xpdfPluginVecTable._xpdfDictGet) +#define xpdfFreeObj (*xpdfPluginVecTable._xpdfFreeObj) +#define xpdfMalloc (*xpdfPluginVecTable._xpdfMalloc) +#define xpdfRealloc (*xpdfPluginVecTable._xpdfRealloc) +#define xpdfFree (*xpdfPluginVecTable._xpdfFree) +#define xpdfRegisterSecurityHandler (*xpdfPluginVecTable._xpdfRegisterSecurityHandler) + +#ifdef __cplusplus +} +#endif + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/xpdfrc.5 swftools-0.9.1/lib/pdf/xpdf/xpdfrc.5 --- swftools-0.9.2+ds1/lib/pdf/xpdf/xpdfrc.5 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/xpdfrc.5 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,617 @@ +.\" Copyright 2002-2007 Glyph & Cog, LLC +.TH xpdfrc 5 "27 February 2007" +.SH NAME +xpdfrc \- configuration file for Xpdf tools (version 3.02) +.SH DESCRIPTION +All of the Xpdf tools read a single configuration file. If you have a +.I .xpdfrc +file in your home directory, it will be read. Otherwise, a +system-wide configuration file will be read from +.IR /usr/local/etc/xpdfrc , +if it exists. (This is its default location; depending on build +options, it may be placed elsewhere.) On Win32 systems, the +.I xpdfrc +file should be placed in the same directory as the executables. +.PP +The xpdfrc file consists of a series of configuration options, one +per line. Blank lines and lines starting with a \'#' (comments) are +ignored. +.PP +The following sections list all of the configuration options, sorted +into functional groups. There is an examples section at the end. +.SH INCLUDE FILES +.TP +.BI include " config\-file" +Includes the specified config file. The effect of this is equivalent +to inserting the contents of +.I config\-file +directly into the parent config file in place of the +.I include +command. Config files can be nested arbitrarily deeply. +.SH CHARACTER MAPPING +.TP +.BI nameToUnicode " map\-file" +Specifies a file with the mapping from character names to Unicode. +This is used to handle PDF fonts that have valid encodings but no +ToUnicode entry. Each line of a nameToUnicode file looks like this: + +.I " " hex\-string name + +The +.I hex\-string +is the Unicode (UCS-2) character index, and +.I name +is the corresponding character name. Multiple nameToUnicode files can +be used; if a character name is given more than once, the code in the +last specified file is used. There is a built-in default +nameToUnicode table with all of Adobe's standard character names. +.TP +.BI cidToUnicode " registry\-ordering map\-file" +Specifies the file with the mapping from character collection to +Unicode. Each line of a cidToUnicode file represents one character: + +.I " " hex\-string + +The +.I hex\-string +is the Unicode (UCS-2) index for that character. The first line maps +CID 0, the second line CID 1, etc. File size is determined by size of +the character collection. Only one file is allowed per character +collection; the last specified file is used. There are no built-in +cidToUnicode mappings. +.TP +.BI unicodeToUnicode " font\-name\-substring map\-file" +This is used to work around PDF fonts which have incorrect Unicode +information. It specifies a file which maps from the given +(incorrect) Unicode indexes to the correct ones. The mapping will be +used for any font whose name contains +.IR font\-name\-substring . +Each line of a unicodeToUnicode file represents one Unicode character: + +.RI " " in\-hex " " out\-hex1 " " out\-hex2 " ..." + +The +.I in\-hex +field is an input (incorrect) Unicode index, and the rest of the +fields are one or more output (correct) Unicode indexes. Each +occurrence of +.I in\-hex +will be converted to the specified output sequence. +.TP +.BI unicodeMap " encoding\-name map\-file" +Specifies the file with mapping from Unicode to +.IR encoding\-name . +These encodings are used for X display fonts and text output (see +below). Each line of a unicodeMap file represents a range of one or +more Unicode characters which maps linearly to a range in the output +encoding: +.nf + +.I " " in\-start\-hex in\-end\-hex out\-start\-hex + +.fi +Entries for single characters can be abbreviated to: +.nf + +.I " " in\-hex out\-hex + +.fi +The +.I in\-start\-hex +and +.I in\-end\-hex +fields (or the single +.I in\-hex +field) specify the Unicode range. The +.I out\-start\-hex +field (or the +.I out\-hex +field) specifies the start of the output encoding range. The length +of the +.I out\-start\-hex +(or +.IR out\-hex ) +string determines the length of the output characters (e.g., UTF-8 +uses different numbers of bytes to represent characters in different +ranges). Entries must be given in increasing Unicode order. Only one +file is allowed per encoding; the last specified file is used. The +.IR Latin1 , +.IR ASCII7 , +.IR Symbol , +.IR ZapfDingbats , +.IR UTF-8 , +and +.I UCS-2 +encodings are predefined. +.TP +.BI cMapDir " registry\-ordering dir" +Specifies a search directory, +.IR dir , +for CMaps for the +.I registry\-ordering +character collection. There can be multiple directories for a +particular collection. There are no default CMap directories. +.TP +.BI toUnicodeDir " dir" +Specifies a search directory, +.IR dir , +for ToUnicode CMaps. There can be multiple ToUnicode directories. +There are no default ToUnicode directories. +.SH DISPLAY FONTS +.TP +.BI displayFontT1 " PDF\-font\-name T1\-file" +Maps a PDF font, +.IR PDF\-font\-name , +to a Type 1 font for display. The Type 1 font file, +.IR T1\-file , +should be a standard .pfa or .pfb file. +.TP +.BI displayFontTT " PDF\-font\-name TT\-file" +Maps a PDF font, +.IR PDF\-font\-name , +to a TrueType font for display. The TrueType font file, +.IR TT\-file , +should be a standard .ttf file. +.TP +.BI displayNamedCIDFontT1 " PDF\-font\-name T1\-file" +Maps a specific PDF CID (16-bit) font, +.IR PDF\-font\-name , +to a CID font (16-bit PostScript font), for display. There are no +default CID font mappings. +.TP +.BI displayCIDFontT1 " registry\-ordering T1\-file" +Maps the +.I registry\-ordering +character collection to a CID font (16-bit PostScript font), for +display. This mapping is used if the font name doesn't match any of +the fonts declared with displayNamedCIDFont* commands. There are no +default CID font mappings. +.TP +.BI displayNamedCIDFontTT " PDF\-font\-name TT\-file" +Maps a specific PDF CID (16-bit) font, +.IR PDF\-font\-name , +to a (16-bit) TrueType font, for display. There are no default CID +font mappings. +.TP +.BI displayCIDFontTT " registry\-ordering TT\-file" +Maps the +.I registry\-ordering +character collection to a (16-bit) TrueType font, for display. This +mapping is used if the font name doesn't match any of the fonts +declared with displayNamedCIDFont* commands. There are no default CID +font mappings. +.TP +.BI fontDir " dir" +Specifies a search directory for external font files. There can be +multiple fontDir directories. If a PDF file uses a font but doesn't +embed it, these directories will be searched for a matching font file. +These fonts are used by both xpdf (for display) and pdftops (for +embedding in the generated PostScript). Type 1 fonts must have a +suffix of ".pfa", ".pfb", ".ps", or no suffix at all. TrueType fonts +must have a ".ttf" suffix. Other files in these directories will be +ignored. There are no default fontDir directories. +.SH POSTSCRIPT CONTROL +.TP +.BI psPaperSize " width(pts) height(pts)" +Sets the paper size for PostScript output. The +.I width +and +.I height +parameters give the paper size in PostScript points (1 point = 1/72 +inch). +.TP +.BR psPaperSize " letter | legal | A4 | A3 | match" +Sets the paper size for PostScript output to a standard size. The +default paper size is set when xpdf and pdftops are built, typically +to "letter" or "A4". This can also be set to "match", which will set +the paper size to match the size specified in the PDF file. +.TP +.BR psImageableArea " llx lly urx ury" +Sets the imageable area for PostScript output. The four integers are +the coordinates of the lower-left and upper-right corners of the +imageable region, specified in points (with the origin being the +lower-left corner of the paper). This defaults to the full paper +size; the psPaperSize option will reset the imageable area +coordinates. +.TP +.BR psCrop " yes | no" +If set to "yes", PostScript output is cropped to the CropBox specified +in the PDF file; otherwise no cropping is done. This defaults to +"yes". +.TP +.BR psExpandSmaller " yes | no" +If set to "yes", PDF pages smaller than the PostScript imageable area +are expanded to fill the imageable area. Otherwise, no scalling is +done on smaller pages. This defaults to "no". +.TP +.BR psShrinkLarger " yes | no" +If set to yes, PDF pages larger than the PostScript imageable area are +shrunk to fit the imageable area. Otherwise, no scaling is done on +larger pages. This defaults to "yes". +.TP +.BR psCenter " yes | no" +If set to yes, PDF pages smaller than the PostScript imageable area +(after any scaling) are centered in the imageable area. Otherwise, +they are aligned at the lower-left corner of the imageable area. This +defaults to "yes". +.TP +.BR psDuplex " yes | no" +If set to "yes", the generated PostScript will set the "Duplex" +pagedevice entry. This tells duplex-capable printers to enable +duplexing. This defaults to "no". +.TP +.BR psLevel " level1 | level1sep | level2 | level2sep | level3 | level3Sep" +Sets the PostScript level to generate. This defaults to "level2". +.TP +.BI psFont " PDF\-font\-name PS\-font\-name" +When the +.I PDF\-font\-name +font is used in a PDF file, it will be translated to the PostScript +font +.IR PS\-font\-name , +which is assumed to be resident in the printer. Typically, +.I PDF\-font\-name +and +.I PS\-font\-name +are the same. By default, only the Base-14 fonts are assumed to be +resident. +.TP +.BI psNamedFont16 " PDF\-font\-name wMode PS\-font\-name encoding" +When the 16-bit font +.I PDF\-font\-name +is used in a PDF file with the +.I wMode +writing mode and is not embedded, the +.I PS\-font\-name +font is substituted for it. The writing mode must be either \'H' for +horizontal or \'V' for vertical. The +.I PS\-font\-name +font is assumed to be resident in the printer and to use the specified +encoding (which must have been defined with the unicodeMap command). +.TP +.BI psFont16 " registry\-ordering wMode PS\-font\-name encoding" +When a 16-bit font using the +.I registry\-ordering +character collection and +.I wMode +writing mode is not embedded and does not match any of the fonts +declared in psNamedFont16 commands, the +.I PS\-font\-name +font is substituted for it. The writing mode must be either \'H' for +horizontal or \'V' for vertical. The +.I PS\-font\-name +font is assumed to be resident in the printer and to use the specified +writing mode and encoding (which must have been defined with the +unicodeMap command). +.TP +.BR psEmbedType1Fonts " yes | no" +If set to "no", prevents embedding of Type 1 fonts in generated +PostScript. This defaults to "yes". +.TP +.BR psEmbedTrueTypeFonts " yes | no" +If set to "no", prevents embedding of TrueType fonts in generated +PostScript. This defaults to "yes". +.TP +.BR psEmbedCIDTrueTypeFonts " yes | no" +If set to "no", prevents embedding of CID TrueType fonts in generated +PostScript. For Level 3 PostScript, this generates a CID font, for +lower levels it generates a non-CID composite font. +.TP +.BR psEmbedCIDPostScriptFonts " yes | no" +If set to "no", prevents embedding of CID PostScript fonts in +generated PostScript. For Level 3 PostScript, this generates a CID +font, for lower levels it generates a non-CID composite font. +.TP +.BR psPreload " yes | no" +If set to "yes", PDF forms are converted to PS procedures, and image +data is preloaded. This uses more memory in the PostScript +interpreter, but generates significantly smaller PS files in +situations where, e.g., the same image is drawn on every page of a +long document. This defaults to "no". +.TP +.BR psOPI " yes | no" +If set to "yes", generates PostScript OPI comments for all images and +forms which have OPI information. This option is only available if +the Xpdf tools were compiled with OPI support. This defaults to "no". +.TP +.BR psASCIIHex " yes | no" +If set to "yes", the ASCIIHexEncode filter will be used instead of +ASCII85Encode for binary data. This defaults to "no". +.TP +.BI psFile " file\-or\-command" +Sets the default PostScript file or print command for xpdf. Commands +start with a \'|' character; anything else is a file. If the file +name or command contains spaces it must be quoted. This defaults to +unset, which tells xpdf to generate a name of the form .ps for a +PDF file .pdf. +.TP +.BI fontDir " dir" +See the description above, in the DISPLAY FONTS section. +.SH TEXT CONTROL +.TP +.BI textEncoding " encoding\-name" +Sets the encoding to use for text output. (This can be overridden +with the "-enc" switch on the command line.) The +.I encoding\-name +must be defined with the unicodeMap command (see above). This +defaults to "Latin1". +.TP +.BR textEOL " unix | dos | mac" +Sets the end-of-line convention to use for text output. The options +are: +.nf + + unix = LF + dos = CR+LF + mac = CR + +.fi +(This can be overridden with the "-eol" switch on the command line.) +The default value is based on the OS where xpdf and pdftotext were +built. +.TP +.BR textPageBreaks " yes | no" +If set to "yes", text extraction will insert page breaks (form feed +characters) between pages. This defaults to "yes". +.TP +.BR textKeepTinyChars " yes | no" +If set to "yes", text extraction will keep all characters. If set to +"no", text extraction will discard tiny (smaller than 3 point) +characters after the first 50000 per page, avoiding extremely slow run +times for PDF files that use special fonts to do shading or +cross-hatching. This defaults to "no". +.SH MISCELLANEOUS SETTINGS +.TP +.BR initialZoom " \fIpercentage\fR | page | width" +Sets the initial zoom factor. A number specifies a zoom percentage, +where 100 means 72 dpi. You may also specify \'page', to fit the page +to the window size, or \'width', to fit the page width to the window +width. +.TP +.BR continuousView " yes | no" +If set to "yes", xpdf will start in continuous view mode, i.e., with +one vertical screoll bar for the whole document. This defaults to +"no". +.TP +.BR enableT1lib " yes | no" +Enables or disables use of t1lib (a Type 1 font rasterizer). This is +only relevant if the Xpdf tools were built with t1lib support. +("enableT1lib" replaces the old "t1libControl" option.) This option +defaults to "yes". +.TP +.BR enableFreeType " yes | no" +Enables or disables use of FreeType (a TrueType / Type 1 font +rasterizer). This is only relevant if the Xpdf tools were built with +FreeType support. ("enableFreeType" replaces the old +"freetypeControl" option.) This option defaults to "yes". +.TP +.BR antialias " yes | no" +Enables or disables font anti-aliasing in the PDF rasterizer. This +option affects all font rasterizers. ("antialias" replaces the +anti-aliasing control provided by the old "t1libControl" and +"freetypeControl" options.) This default to "yes". +.TP +.BR vectorAntialias " yes | no" +Enables or disables anti-aliasing of vector graphics in the PDF +rasterizer. This defaults to "yes". +.TP +.BR strokeAdjust " yes | no" +Enables or disables stroke adjustment. This defaults to "yes". +.TP +.BR screenType " dispersed | clustered | stochasticClustered" +Sets the halftone screen type, which will be used when generating a +monochrome (1-bit) bitmap. The three options are dispersed-dot +dithering, clustered-dot dithering (with a round dot and 45-degree +screen angle), and stochastic clustered-dot dithering. By default, +"stochasticClustered" is used for resolutions of 300 dpi and higher, +and "dispersed" is used for resolutions lower then 300 dpi. +.TP +.BI screenSize " integer" +Sets the size of the (square) halftone screen threshold matrix. By +default, this is 4 for dispersed-dot dithering, 10 for clustered-dot +dithering, and 100 for stochastic clustered-dot dithering. +.TP +.BI screenDotRadius " integer" +Sets the halftone screen dot radius. This is only used when +screenType is set to stochasticClustered, and it defaults to 2. In +clustered-dot mode, the dot radius is half of the screen size. +Dispersed-dot dithering doesn't have a dot radius. +.TP +.BI screenGamma " float" +Sets the halftone screen gamma correction parameter. Gamma values +greater than 1 make the output brighter; gamma values less than 1 make +it darker. The default value is 1. +.TP +.BI screenBlackThreshold " float" +When halftoning, all values below this threshold are forced to solid +black. This parameter is a floating point value between 0 (black) and +1 (white). The default value is 0. +.TP +.BI screenWhiteThreshold " float" +When halftoning, all values above this threshold are forced to solid +white. This parameter is a floating point value between 0 (black) and +1 (white). The default value is 1. +.TP +.BI urlCommand " command" +Sets the command executed when you click on a URL link. The string +"%s" will be replaced with the URL. (See the example below.) This +has no default value. +.TP +.BI movieCommand " command" +Sets the command executed when you click on a movie annotation. The +string "%s" will be replaced with the movie file name. This has no +default value. +.TP +.BI mapNumericCharNames " yes | no" +If set to "yes", the Xpdf tools will attempt to map various numeric +character names sometimes used in font subsets. In some cases this +leads to usable text, and in other cases it leads to gibberish -- +there is no way for Xpdf to tell. This defaults to "yes". +.TP +.BI mapUnknownCharNames " yes | no" +If set to "yes", and mapNumericCharNames is set to "no", the Xpdf +tools will apply a simple pass-through mapping (Unicode index = +character code) for all unrecognized glyph names. In some cases, this +leads to usable text, and in other cases it leads to gibberish -- +there is no way for Xpdf to tell. This defaults to "no". +.TP +.BI bind " modifiers-key context command ..." +Add a key or mouse button binding. +.I Modifiers +can be zero or more of: +.nf + + shift- + ctrl- + alt- + +.fi +.I Key +can be a regular ASCII character, or any one of: +.nf + + space + tab + return + enter + backspace + insert + delete + home + end + pgup + pgdn + left / right / up / down (arrow keys) + f1 .. f35 (function keys) + mousePress1 .. mousePress7 (mouse buttons) + mouseRelease1 .. mouseRelease7 (mouse buttons) + +.fi +.I Context +is either "any" or a comma-separated combination of: +.nf + + fullScreen / window (full screen mode on/off) + continuous / singlePage (continuous mode on/off) + overLink / offLink (mouse over link or not) + scrLockOn / scrLockOff (scroll lock on/off) + +.fi +The context string can include only one of each pair in the above +list. + +.I Command +is an Xpdf command (see the COMMANDS section of the +.BR xpdf (1) +man page for details). Multiple commands are separated by whitespace. + +The bind command replaces any existing binding, but only if it was +defined for the exact same modifiers, key, and context. All tokens +(modifiers, key, context, commands) are case-sensitive. + +Example key bindings: +.nf + + # bind ctrl-a in any context to the nextPage + # command + bind ctrl-a any nextPage + + # bind uppercase B, when in continuous mode + # with scroll lock on, to the reload command + # followed by the prevPage command + bind B continuous,scrLockOn reload prevPage + +.fi +See the +.BR xpdf (1) +man page for more examples. +.TP +.BI unbind " modifiers-key context" +Removes a key binding established with the bind command. This is most +useful to remove default key bindings before establishing new ones +(e.g., if the default key binding is given for "any" context, and you +want to create new key bindings for multiple contexts). +.TP +.BI printCommands " yes | no" +If set to "yes", drawing commands are printed as they're executed +(useful for debugging). This defaults to "no". +.TP +.BI errQuiet " yes | no" +If set to "yes", this suppresses all error and warning messages from +all of the Xpdf tools. This defaults to "no". +.SH EXAMPLES +The following is a sample xpdfrc file. +.nf + +# from the Thai support package +nameToUnicode /usr/local/share/xpdf/Thai.nameToUnicode + +# from the Japanese support package +cidToUnicode Adobe-Japan1 /usr/local/share/xpdf/Adobe-Japan1.cidToUnicode +unicodeMap JISX0208 /usr/local/share/xpdf/JISX0208.unicodeMap +cMapDir Adobe-Japan1 /usr/local/share/xpdf/cmap/Adobe-Japan1 + +# use the Base-14 Type 1 fonts from ghostscript +displayFontT1 Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb +displayFontT1 Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb +displayFontT1 Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb +displayFontT1 Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb +displayFontT1 Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb +displayFontT1 Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb +displayFontT1 Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb +displayFontT1 Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb +displayFontT1 Courier /usr/local/share/ghostscript/fonts/n022003l.pfb +displayFontT1 Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb +displayFontT1 Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb +displayFontT1 Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb +displayFontT1 Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb +displayFontT1 ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb + +# use the Bakoma Type 1 fonts +# (this assumes they happen to be installed in /usr/local/fonts/bakoma) +fontDir /usr/local/fonts/bakoma + +# set some PostScript options +psPaperSize letter +psDuplex no +psLevel level2 +psEmbedType1Fonts yes +psEmbedTrueTypeFonts yes +psFile "| lpr -Pprinter5" + +# assume that the PostScript printer has the Univers and +# Univers-Bold fonts +psFont Univers Univers +psFont Univers-Bold Univers-Bold + +# set the text output options +textEncoding UTF-8 +textEOL unix + +# misc options +t1libControl low +freetypeControl low +urlCommand "netscape -remote 'openURL(%s)'" + +.fi +.SH FILES +.TP +.B /usr/local/etc/xpdfrc +This is the default location for the system-wide configuration file. +Depending on build options, it may be placed elsewhere. +.TP +.B $HOME/.xpdfrc +This is the user's configuration file. If it exists, it will be read +in place of the system-wide file. +.SH AUTHOR +The Xpdf software and documentation are copyright 1996-2007 Glyph & +Cog, LLC. +.SH "SEE ALSO" +.BR xpdf (1), +.BR pdftops (1), +.BR pdftotext (1), +.BR pdfinfo (1), +.BR pdftoppm (1), +.BR pdfimages (1) +.br +.B http://www.foolabs.com/xpdf/ diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/xpdfrc.cat swftools-0.9.1/lib/pdf/xpdf/xpdfrc.cat --- swftools-0.9.2+ds1/lib/pdf/xpdf/xpdfrc.cat 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/xpdfrc.cat 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,614 @@ +xpdfrc(5) xpdfrc(5) + + + +NAME + xpdfrc - configuration file for Xpdf tools (version 3.02) + +DESCRIPTION + All of the Xpdf tools read a single configuration file. + If you have a .xpdfrc file in your home directory, it will + be read. Otherwise, a system-wide configuration file will + be read from /usr/local/etc/xpdfrc, if it exists. (This + is its default location; depending on build options, it + may be placed elsewhere.) On Win32 systems, the xpdfrc + file should be placed in the same directory as the exe- + cutables. + + The xpdfrc file consists of a series of configuration + options, one per line. Blank lines and lines starting + with a '#' (comments) are ignored. + + The following sections list all of the configuration + options, sorted into functional groups. There is an exam- + ples section at the end. + +INCLUDE FILES + include config-file + Includes the specified config file. The effect of + this is equivalent to inserting the contents of + config-file directly into the parent config file in + place of the include command. Config files can be + nested arbitrarily deeply. + +CHARACTER MAPPING + nameToUnicode map-file + Specifies a file with the mapping from character + names to Unicode. This is used to handle PDF fonts + that have valid encodings but no ToUnicode entry. + Each line of a nameToUnicode file looks like this: + + hex-string name + + The hex-string is the Unicode (UCS-2) character + index, and name is the corresponding character + name. Multiple nameToUnicode files can be used; if + a character name is given more than once, the code + in the last specified file is used. There is a + built-in default nameToUnicode table with all of + Adobe's standard character names. + + cidToUnicode registry-ordering map-file + Specifies the file with the mapping from character + collection to Unicode. Each line of a cidToUnicode + file represents one character: + + hex-string + + The hex-string is the Unicode (UCS-2) index for + that character. The first line maps CID 0, the + second line CID 1, etc. File size is determined by + size of the character collection. Only one file is + allowed per character collection; the last speci- + fied file is used. There are no built-in cidToUni- + code mappings. + + unicodeToUnicode font-name-substring map-file + This is used to work around PDF fonts which have + incorrect Unicode information. It specifies a file + which maps from the given (incorrect) Unicode + indexes to the correct ones. The mapping will be + used for any font whose name contains + font-name-substring. Each line of a unicodeToUni- + code file represents one Unicode character: + + in-hex out-hex1 out-hex2 ... + + The in-hex field is an input (incorrect) Unicode + index, and the rest of the fields are one or more + output (correct) Unicode indexes. Each occurrence + of in-hex will be converted to the specified output + sequence. + + unicodeMap encoding-name map-file + Specifies the file with mapping from Unicode to + encoding-name. These encodings are used for X dis- + play fonts and text output (see below). Each line + of a unicodeMap file represents a range of one or + more Unicode characters which maps linearly to a + range in the output encoding: + + in-start-hex in-end-hex out-start-hex + + Entries for single characters can be abbreviated + to: + + in-hex out-hex + + The in-start-hex and in-end-hex fields (or the sin- + gle in-hex field) specify the Unicode range. The + out-start-hex field (or the out-hex field) speci- + fies the start of the output encoding range. The + length of the out-start-hex (or out-hex) string + determines the length of the output characters + (e.g., UTF-8 uses different numbers of bytes to + represent characters in different ranges). Entries + must be given in increasing Unicode order. Only + one file is allowed per encoding; the last speci- + fied file is used. The Latin1, ASCII7, Symbol, + ZapfDingbats, UTF-8, and UCS-2 encodings are prede- + fined. + + cMapDir registry-ordering dir + Specifies a search directory, dir, for CMaps for + the registry-ordering character collection. There + can be multiple directories for a particular col- + lection. There are no default CMap directories. + + toUnicodeDir dir + Specifies a search directory, dir, for ToUnicode + CMaps. There can be multiple ToUnicode directo- + ries. There are no default ToUnicode directories. + +DISPLAY FONTS + displayFontT1 PDF-font-name T1-file + Maps a PDF font, PDF-font-name, to a Type 1 font + for display. The Type 1 font file, T1-file, should + be a standard .pfa or .pfb file. + + displayFontTT PDF-font-name TT-file + Maps a PDF font, PDF-font-name, to a TrueType font + for display. The TrueType font file, TT-file, + should be a standard .ttf file. + + displayNamedCIDFontT1 PDF-font-name T1-file + Maps a specific PDF CID (16-bit) font, + PDF-font-name, to a CID font (16-bit PostScript + font), for display. There are no default CID font + mappings. + + displayCIDFontT1 registry-ordering T1-file + Maps the registry-ordering character collection to + a CID font (16-bit PostScript font), for display. + This mapping is used if the font name doesn't match + any of the fonts declared with displayNamedCIDFont* + commands. There are no default CID font mappings. + + displayNamedCIDFontTT PDF-font-name TT-file + Maps a specific PDF CID (16-bit) font, + PDF-font-name, to a (16-bit) TrueType font, for + display. There are no default CID font mappings. + + displayCIDFontTT registry-ordering TT-file + Maps the registry-ordering character collection to + a (16-bit) TrueType font, for display. This map- + ping is used if the font name doesn't match any of + the fonts declared with displayNamedCIDFont* com- + mands. There are no default CID font mappings. + + fontDir dir + Specifies a search directory for external font + files. There can be multiple fontDir directories. + If a PDF file uses a font but doesn't embed it, + these directories will be searched for a matching + font file. These fonts are used by both xpdf (for + display) and pdftops (for embedding in the gener- + ated PostScript). Type 1 fonts must have a suffix + of ".pfa", ".pfb", ".ps", or no suffix at all. + TrueType fonts must have a ".ttf" suffix. Other + files in these directories will be ignored. There + are no default fontDir directories. + +POSTSCRIPT CONTROL + psPaperSize width(pts) height(pts) + Sets the paper size for PostScript output. The + width and height parameters give the paper size in + PostScript points (1 point = 1/72 inch). + + psPaperSize letter | legal | A4 | A3 | match + Sets the paper size for PostScript output to a + standard size. The default paper size is set when + xpdf and pdftops are built, typically to "letter" + or "A4". This can also be set to "match", which + will set the paper size to match the size specified + in the PDF file. + + psImageableArea llx lly urx ury + Sets the imageable area for PostScript output. The + four integers are the coordinates of the lower-left + and upper-right corners of the imageable region, + specified in points (with the origin being the + lower-left corner of the paper). This defaults to + the full paper size; the psPaperSize option will + reset the imageable area coordinates. + + psCrop yes | no + If set to "yes", PostScript output is cropped to + the CropBox specified in the PDF file; otherwise no + cropping is done. This defaults to "yes". + + psExpandSmaller yes | no + If set to "yes", PDF pages smaller than the + PostScript imageable area are expanded to fill the + imageable area. Otherwise, no scalling is done on + smaller pages. This defaults to "no". + + psShrinkLarger yes | no + If set to yes, PDF pages larger than the PostScript + imageable area are shrunk to fit the imageable + area. Otherwise, no scaling is done on larger + pages. This defaults to "yes". + + psCenter yes | no + If set to yes, PDF pages smaller than the + PostScript imageable area (after any scaling) are + centered in the imageable area. Otherwise, they + are aligned at the lower-left corner of the image- + able area. This defaults to "yes". + + psDuplex yes | no + If set to "yes", the generated PostScript will set + the "Duplex" pagedevice entry. This tells duplex- + capable printers to enable duplexing. This + defaults to "no". + + psLevel level1 | level1sep | level2 | level2sep | level3 | + level3Sep + Sets the PostScript level to generate. This + defaults to "level2". + + psFont PDF-font-name PS-font-name + When the PDF-font-name font is used in a PDF file, + it will be translated to the PostScript font + PS-font-name, which is assumed to be resident in + the printer. Typically, PDF-font-name and + PS-font-name are the same. By default, only the + Base-14 fonts are assumed to be resident. + + psNamedFont16 PDF-font-name wMode PS-font-name encoding + When the 16-bit font PDF-font-name is used in a PDF + file with the wMode writing mode and is not embed- + ded, the PS-font-name font is substituted for it. + The writing mode must be either 'H' for horizontal + or 'V' for vertical. The PS-font-name font is + assumed to be resident in the printer and to use + the specified encoding (which must have been + defined with the unicodeMap command). + + psFont16 registry-ordering wMode PS-font-name encoding + When a 16-bit font using the registry-ordering + character collection and wMode writing mode is not + embedded and does not match any of the fonts + declared in psNamedFont16 commands, the + PS-font-name font is substituted for it. The writ- + ing mode must be either 'H' for horizontal or 'V' + for vertical. The PS-font-name font is assumed to + be resident in the printer and to use the specified + writing mode and encoding (which must have been + defined with the unicodeMap command). + + psEmbedType1Fonts yes | no + If set to "no", prevents embedding of Type 1 fonts + in generated PostScript. This defaults to "yes". + + psEmbedTrueTypeFonts yes | no + If set to "no", prevents embedding of TrueType + fonts in generated PostScript. This defaults to + "yes". + + psEmbedCIDTrueTypeFonts yes | no + If set to "no", prevents embedding of CID TrueType + fonts in generated PostScript. For Level 3 + PostScript, this generates a CID font, for lower + levels it generates a non-CID composite font. + + psEmbedCIDPostScriptFonts yes | no + If set to "no", prevents embedding of CID + PostScript fonts in generated PostScript. For + Level 3 PostScript, this generates a CID font, for + lower levels it generates a non-CID composite font. + + psPreload yes | no + If set to "yes", PDF forms are converted to PS pro- + cedures, and image data is preloaded. This uses + more memory in the PostScript interpreter, but gen- + erates significantly smaller PS files in situations + where, e.g., the same image is drawn on every page + of a long document. This defaults to "no". + + psOPI yes | no + If set to "yes", generates PostScript OPI comments + for all images and forms which have OPI informa- + tion. This option is only available if the Xpdf + tools were compiled with OPI support. This + defaults to "no". + + psASCIIHex yes | no + If set to "yes", the ASCIIHexEncode filter will be + used instead of ASCII85Encode for binary data. + This defaults to "no". + + psFile file-or-command + Sets the default PostScript file or print command + for xpdf. Commands start with a '|' character; + anything else is a file. If the file name or com- + mand contains spaces it must be quoted. This + defaults to unset, which tells xpdf to generate a + name of the form .ps for a PDF file + .pdf. + + fontDir dir + See the description above, in the DISPLAY FONTS + section. + +TEXT CONTROL + textEncoding encoding-name + Sets the encoding to use for text output. (This + can be overridden with the "-enc" switch on the + command line.) The encoding-name must be defined + with the unicodeMap command (see above). This + defaults to "Latin1". + + textEOL unix | dos | mac + Sets the end-of-line convention to use for text + output. The options are: + + unix = LF + dos = CR+LF + mac = CR + + (This can be overridden with the "-eol" switch on + the command line.) The default value is based on + the OS where xpdf and pdftotext were built. + + textPageBreaks yes | no + If set to "yes", text extraction will insert page + breaks (form feed characters) between pages. This + defaults to "yes". + + textKeepTinyChars yes | no + If set to "yes", text extraction will keep all + characters. If set to "no", text extraction will + discard tiny (smaller than 3 point) characters + after the first 50000 per page, avoiding extremely + slow run times for PDF files that use special fonts + to do shading or cross-hatching. This defaults to + "no". + +MISCELLANEOUS SETTINGS + initialZoom percentage | page | width + Sets the initial zoom factor. A number specifies a + zoom percentage, where 100 means 72 dpi. You may + also specify 'page', to fit the page to the window + size, or 'width', to fit the page width to the win- + dow width. + + continuousView yes | no + If set to "yes", xpdf will start in continuous view + mode, i.e., with one vertical screoll bar for the + whole document. This defaults to "no". + + enableT1lib yes | no + Enables or disables use of t1lib (a Type 1 font + rasterizer). This is only relevant if the Xpdf + tools were built with t1lib support. + ("enableT1lib" replaces the old "t1libControl" + option.) This option defaults to "yes". + + enableFreeType yes | no + Enables or disables use of FreeType (a TrueType / + Type 1 font rasterizer). This is only relevant if + the Xpdf tools were built with FreeType support. + ("enableFreeType" replaces the old "freetypeCon- + trol" option.) This option defaults to "yes". + + antialias yes | no + Enables or disables font anti-aliasing in the PDF + rasterizer. This option affects all font rasteriz- + ers. ("antialias" replaces the anti-aliasing con- + trol provided by the old "t1libControl" and + "freetypeControl" options.) This default to "yes". + + vectorAntialias yes | no + Enables or disables anti-aliasing of vector graph- + ics in the PDF rasterizer. This defaults to "yes". + + strokeAdjust yes | no + Enables or disables stroke adjustment. This + defaults to "yes". + + screenType dispersed | clustered | stochasticClustered + Sets the halftone screen type, which will be used + when generating a monochrome (1-bit) bitmap. The + three options are dispersed-dot dithering, clus- + tered-dot dithering (with a round dot and 45-degree + screen angle), and stochastic clustered-dot dither- + ing. By default, "stochasticClustered" is used for + resolutions of 300 dpi and higher, and "dispersed" + is used for resolutions lower then 300 dpi. + + screenSize integer + Sets the size of the (square) halftone screen + threshold matrix. By default, this is 4 for dis- + persed-dot dithering, 10 for clustered-dot dither- + ing, and 100 for stochastic clustered-dot dither- + ing. + + screenDotRadius integer + Sets the halftone screen dot radius. This is only + used when screenType is set to stochasticClustered, + and it defaults to 2. In clustered-dot mode, the + dot radius is half of the screen size. Dispersed- + dot dithering doesn't have a dot radius. + + screenGamma float + Sets the halftone screen gamma correction parame- + ter. Gamma values greater than 1 make the output + brighter; gamma values less than 1 make it darker. + The default value is 1. + + screenBlackThreshold float + When halftoning, all values below this threshold + are forced to solid black. This parameter is a + floating point value between 0 (black) and 1 + (white). The default value is 0. + + screenWhiteThreshold float + When halftoning, all values above this threshold + are forced to solid white. This parameter is a + floating point value between 0 (black) and 1 + (white). The default value is 1. + + urlCommand command + Sets the command executed when you click on a URL + link. The string "%s" will be replaced with the + URL. (See the example below.) This has no default + value. + + movieCommand command + Sets the command executed when you click on a movie + annotation. The string "%s" will be replaced with + the movie file name. This has no default value. + + mapNumericCharNames yes | no + If set to "yes", the Xpdf tools will attempt to map + various numeric character names sometimes used in + font subsets. In some cases this leads to usable + text, and in other cases it leads to gibberish -- + there is no way for Xpdf to tell. This defaults to + "yes". + + mapUnknownCharNames yes | no + If set to "yes", and mapNumericCharNames is set to + "no", the Xpdf tools will apply a simple pass- + through mapping (Unicode index = character code) + for all unrecognized glyph names. In some cases, + this leads to usable text, and in other cases it + leads to gibberish -- there is no way for Xpdf to + tell. This defaults to "no". + + bind modifiers-key context command ... + Add a key or mouse button binding. Modifiers can + be zero or more of: + + shift- + ctrl- + alt- + + Key can be a regular ASCII character, or any one + of: + + space + tab + return + enter + backspace + insert + delete + home + end + pgup + pgdn + left / right / up / down (arrow keys) + f1 .. f35 (function keys) + mousePress1 .. mousePress7 (mouse buttons) + mouseRelease1 .. mouseRelease7 (mouse buttons) + + Context is either "any" or a comma-separated combi- + nation of: + + fullScreen / window (full screen mode on/off) + continuous / singlePage (continuous mode on/off) + overLink / offLink (mouse over link or not) + scrLockOn / scrLockOff (scroll lock on/off) + + The context string can include only one of each + pair in the above list. + + Command is an Xpdf command (see the COMMANDS sec- + tion of the xpdf(1) man page for details). Multi- + ple commands are separated by whitespace. + + The bind command replaces any existing binding, but + only if it was defined for the exact same modi- + fiers, key, and context. All tokens (modifiers, + key, context, commands) are case-sensitive. + + Example key bindings: + + # bind ctrl-a in any context to the nextPage + # command + bind ctrl-a any nextPage + + # bind uppercase B, when in continuous mode + # with scroll lock on, to the reload command + # followed by the prevPage command + bind B continuous,scrLockOn reload prevPage + + See the xpdf(1) man page for more examples. + + unbind modifiers-key context + Removes a key binding established with the bind + command. This is most useful to remove default key + bindings before establishing new ones (e.g., if the + default key binding is given for "any" context, and + you want to create new key bindings for multiple + contexts). + + printCommands yes | no + If set to "yes", drawing commands are printed as + they're executed (useful for debugging). This + defaults to "no". + + errQuiet yes | no + If set to "yes", this suppresses all error and + warning messages from all of the Xpdf tools. This + defaults to "no". + +EXAMPLES + The following is a sample xpdfrc file. + + # from the Thai support package + nameToUnicode /usr/local/share/xpdf/Thai.nameToUnicode + + # from the Japanese support package + cidToUnicode Adobe-Japan1 /usr/local/share/xpdf/Adobe-Japan1.cidToUnicode + unicodeMap JISX0208 /usr/local/share/xpdf/JISX0208.unicodeMap + cMapDir Adobe-Japan1 /usr/local/share/xpdf/cmap/Adobe-Japan1 + + # use the Base-14 Type 1 fonts from ghostscript + displayFontT1 Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb + displayFontT1 Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb + displayFontT1 Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb + displayFontT1 Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb + displayFontT1 Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb + displayFontT1 Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb + displayFontT1 Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb + displayFontT1 Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb + displayFontT1 Courier /usr/local/share/ghostscript/fonts/n022003l.pfb + displayFontT1 Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb + displayFontT1 Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb + displayFontT1 Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb + displayFontT1 Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb + displayFontT1 ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb + + # use the Bakoma Type 1 fonts + # (this assumes they happen to be installed in /usr/local/fonts/bakoma) + fontDir /usr/local/fonts/bakoma + + # set some PostScript options + psPaperSize letter + psDuplex no + psLevel level2 + psEmbedType1Fonts yes + psEmbedTrueTypeFonts yes + psFile "| lpr -Pprinter5" + + # assume that the PostScript printer has the Univers and + # Univers-Bold fonts + psFont Univers Univers + psFont Univers-Bold Univers-Bold + + # set the text output options + textEncoding UTF-8 + textEOL unix + + # misc options + t1libControl low + freetypeControl low + urlCommand "netscape -remote 'openURL(%s)'" + + +FILES + /usr/local/etc/xpdfrc + This is the default location for the system-wide + configuration file. Depending on build options, it + may be placed elsewhere. + + $HOME/.xpdfrc + This is the user's configuration file. If it + exists, it will be read in place of the system-wide + file. + +AUTHOR + The Xpdf software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + +SEE ALSO + xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), + pdftoppm(1), pdfimages(1) + http://www.foolabs.com/xpdf/ + + + + 27 February 2007 xpdfrc(5) diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/xpdfrc.hlp swftools-0.9.1/lib/pdf/xpdf/xpdfrc.hlp --- swftools-0.9.2+ds1/lib/pdf/xpdf/xpdfrc.hlp 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/xpdfrc.hlp 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,619 @@ +! Generated automatically by mantohlp +1 xpdfrc +2 NCLUDE_FILE + + xpdfrc - configuration file for Xpdf tools (version 3.02) + + include config-file + Includes the specified config file. The effect of + this is equivalent to inserting the contents of + config-file directly into the parent config file in + place of the include command. Config files can be + nested arbitrarily deeply. + + () + +2 HARACTER_MAPPIN + + nameToUnicode map-file + Specifies a file with the mapping from character + names to Unicode. This is used to handle PDF fonts + that have valid encodings but no ToUnicode entry. + Each line of a nameToUnicode file looks like this: + + hex-string name + + The hex-string is the Unicode (UCS-2) character + index, and name is the corresponding character + name. Multiple nameToUnicode files can be used; if + a character name is given more than once, the code + in the last specified file is used. There is a + built-in default nameToUnicode table with all of + Adobe's standard character names. + + cidToUnicode registry-ordering map-file + Specifies the file with the mapping from character + collection to Unicode. Each line of a cidToUnicode + file represents one character: + + hex-string + + The hex-string is the Unicode (UCS-2) index for + that character. The first line maps CID 0, the + second line CID 1, etc. File size is determined by + size of the character collection. Only one file is + allowed per character collection; the last speci- + fied file is used. There are no built-in cidToUni- + code mappings. + + unicodeToUnicode font-name-substring map-file + This is used to work around PDF fonts which have + incorrect Unicode information. It specifies a file + which maps from the given (incorrect) Unicode + indexes to the correct ones. The mapping will be + used for any font whose name contains + font-name-substring. Each line of a unicodeToUni- + code file represents one Unicode character: + + in-hex out-hex1 out-hex2 ... + + The in-hex field is an input (incorrect) Unicode + index, and the rest of the fields are one or more + output (correct) Unicode indexes. Each occurrence + of in-hex will be converted to the specified output + sequence. + + unicodeMap encoding-name map-file + Specifies the file with mapping from Unicode to + encoding-name. These encodings are used for X dis- + play fonts and text output (see below). Each line + of a unicodeMap file represents a range of one or + more Unicode characters which maps linearly to a + range in the output encoding: + + in-start-hex in-end-hex out-start-hex + + Entries for single characters can be abbreviated + to: + + in-hex out-hex + + The in-start-hex and in-end-hex fields (or the sin- + gle in-hex field) specify the Unicode range. The + out-start-hex field (or the out-hex field) speci- + fies the start of the output encoding range. The + length of the out-start-hex (or out-hex) string + determines the length of the output characters + (e.g., UTF-8 uses different numbers of bytes to + represent characters in different ranges). Entries + must be given in increasing Unicode order. Only + one file is allowed per encoding; the last speci- + fied file is used. The Latin1, ASCII7, Symbol, + ZapfDingbats, UTF-8, and UCS-2 encodings are prede- + fined. + + cMapDir registry-ordering dir + Specifies a search directory, dir, for CMaps for + the registry-ordering character collection. There + can be multiple directories for a particular col- + lection. There are no default CMap directories. + + toUnicodeDir dir + Specifies a search directory, dir, for ToUnicode + CMaps. There can be multiple ToUnicode directo- + ries. There are no default ToUnicode directories. + + () + +2 ISPLAY_FONT + + displayFontT1 PDF-font-name T1-file + Maps a PDF font, PDF-font-name, to a Type 1 font + for display. The Type 1 font file, T1-file, should + be a standard .pfa or .pfb file. + + displayFontTT PDF-font-name TT-file + Maps a PDF font, PDF-font-name, to a TrueType font + for display. The TrueType font file, TT-file, + should be a standard .ttf file. + + displayNamedCIDFontT1 PDF-font-name T1-file + Maps a specific PDF CID (16-bit) font, + PDF-font-name, to a CID font (16-bit PostScript + font), for display. There are no default CID font + mappings. + + displayCIDFontT1 registry-ordering T1-file + Maps the registry-ordering character collection to + a CID font (16-bit PostScript font), for display. + This mapping is used if the font name doesn't match + any of the fonts declared with displayNamedCIDFont* + commands. There are no default CID font mappings. + + displayNamedCIDFontTT PDF-font-name TT-file + Maps a specific PDF CID (16-bit) font, + PDF-font-name, to a (16-bit) TrueType font, for + display. There are no default CID font mappings. + + displayCIDFontTT registry-ordering TT-file + Maps the registry-ordering character collection to + a (16-bit) TrueType font, for display. This map- + ping is used if the font name doesn't match any of + the fonts declared with displayNamedCIDFont* com- + mands. There are no default CID font mappings. + + fontDir dir + Specifies a search directory for external font + files. There can be multiple fontDir directories. + If a PDF file uses a font but doesn't embed it, + these directories will be searched for a matching + font file. These fonts are used by both xpdf (for + display) and pdftops (for embedding in the gener- + ated PostScript). Type 1 fonts must have a suffix + of ".pfa", ".pfb", ".ps", or no suffix at all. + TrueType fonts must have a ".ttf" suffix. Other + files in these directories will be ignored. There + are no default fontDir directories. + + () + +2 OSTSCRIPT_CONTRO + + psPaperSize width(pts) height(pts) + Sets the paper size for PostScript output. The + width and height parameters give the paper size in + PostScript points (1 point = 1/72 inch). + + psPaperSize letter | legal | A4 | A3 | match + Sets the paper size for PostScript output to a + standard size. The default paper size is set when + xpdf and pdftops are built, typically to "letter" + or "A4". This can also be set to "match", which + will set the paper size to match the size specified + in the PDF file. + + psImageableArea llx lly urx ury + Sets the imageable area for PostScript output. The + four integers are the coordinates of the lower-left + and upper-right corners of the imageable region, + specified in points (with the origin being the + lower-left corner of the paper). This defaults to + the full paper size; the psPaperSize option will + reset the imageable area coordinates. + + psCrop yes | no + If set to "yes", PostScript output is cropped to + the CropBox specified in the PDF file; otherwise no + cropping is done. This defaults to "yes". + + psExpandSmaller yes | no + If set to "yes", PDF pages smaller than the + PostScript imageable area are expanded to fill the + imageable area. Otherwise, no scalling is done on + smaller pages. This defaults to "no". + + psShrinkLarger yes | no + If set to yes, PDF pages larger than the PostScript + imageable area are shrunk to fit the imageable + area. Otherwise, no scaling is done on larger + pages. This defaults to "yes". + + psCenter yes | no + If set to yes, PDF pages smaller than the + PostScript imageable area (after any scaling) are + centered in the imageable area. Otherwise, they + are aligned at the lower-left corner of the image- + able area. This defaults to "yes". + + psDuplex yes | no + If set to "yes", the generated PostScript will set + the "Duplex" pagedevice entry. This tells duplex- + capable printers to enable duplexing. This + defaults to "no". + + psLevel level1 | level1sep | level2 | level2sep | level3 | + level3Sep + Sets the PostScript level to generate. This + defaults to "level2". + + psFont PDF-font-name PS-font-name + When the PDF-font-name font is used in a PDF file, + it will be translated to the PostScript font + PS-font-name, which is assumed to be resident in + the printer. Typically, PDF-font-name and + PS-font-name are the same. By default, only the + Base-14 fonts are assumed to be resident. + + psNamedFont16 PDF-font-name wMode PS-font-name encoding + When the 16-bit font PDF-font-name is used in a PDF + file with the wMode writing mode and is not embed- + ded, the PS-font-name font is substituted for it. + The writing mode must be either 'H' for horizontal + or 'V' for vertical. The PS-font-name font is + assumed to be resident in the printer and to use + the specified encoding (which must have been + defined with the unicodeMap command). + + psFont16 registry-ordering wMode PS-font-name encoding + When a 16-bit font using the registry-ordering + character collection and wMode writing mode is not + embedded and does not match any of the fonts + declared in psNamedFont16 commands, the + PS-font-name font is substituted for it. The writ- + ing mode must be either 'H' for horizontal or 'V' + for vertical. The PS-font-name font is assumed to + be resident in the printer and to use the specified + writing mode and encoding (which must have been + defined with the unicodeMap command). + + psEmbedType1Fonts yes | no + If set to "no", prevents embedding of Type 1 fonts + in generated PostScript. This defaults to "yes". + + psEmbedTrueTypeFonts yes | no + If set to "no", prevents embedding of TrueType + fonts in generated PostScript. This defaults to + "yes". + + psEmbedCIDTrueTypeFonts yes | no + If set to "no", prevents embedding of CID TrueType + fonts in generated PostScript. For Level 3 + PostScript, this generates a CID font, for lower + levels it generates a non-CID composite font. + + psEmbedCIDPostScriptFonts yes | no + If set to "no", prevents embedding of CID + PostScript fonts in generated PostScript. For + Level 3 PostScript, this generates a CID font, for + lower levels it generates a non-CID composite font. + + psPreload yes | no + If set to "yes", PDF forms are converted to PS pro- + cedures, and image data is preloaded. This uses + more memory in the PostScript interpreter, but gen- + erates significantly smaller PS files in situations + where, e.g., the same image is drawn on every page + of a long document. This defaults to "no". + + psOPI yes | no + If set to "yes", generates PostScript OPI comments + for all images and forms which have OPI informa- + tion. This option is only available if the Xpdf + tools were compiled with OPI support. This + defaults to "no". + + psASCIIHex yes | no + If set to "yes", the ASCIIHexEncode filter will be + used instead of ASCII85Encode for binary data. + This defaults to "no". + + psFile file-or-command + Sets the default PostScript file or print command + for xpdf. Commands start with a '|' character; + anything else is a file. If the file name or com- + mand contains spaces it must be quoted. This + defaults to unset, which tells xpdf to generate a + name of the form .ps for a PDF file + .pdf. + + fontDir dir + See the description above, in the DISPLAY FONTS + section. + + () + +2 EXT_CONTRO + + textEncoding encoding-name + Sets the encoding to use for text output. (This + can be overridden with the "-enc" switch on the + command line.) The encoding-name must be defined + with the unicodeMap command (see above). This + defaults to "Latin1". + + textEOL unix | dos | mac + Sets the end-of-line convention to use for text + output. The options are: + + unix = LF + dos = CR+LF + mac = CR + + (This can be overridden with the "-eol" switch on + the command line.) The default value is based on + the OS where xpdf and pdftotext were built. + + textPageBreaks yes | no + If set to "yes", text extraction will insert page + breaks (form feed characters) between pages. This + defaults to "yes". + + textKeepTinyChars yes | no + If set to "yes", text extraction will keep all + characters. If set to "no", text extraction will + discard tiny (smaller than 3 point) characters + after the first 50000 per page, avoiding extremely + slow run times for PDF files that use special fonts + to do shading or cross-hatching. This defaults to + "no". + + () + +2 ISCELLANEOUS_SETTING + + initialZoom percentage | page | width + Sets the initial zoom factor. A number specifies a + zoom percentage, where 100 means 72 dpi. You may + also specify 'page', to fit the page to the window + size, or 'width', to fit the page width to the win- + dow width. + + continuousView yes | no + If set to "yes", xpdf will start in continuous view + mode, i.e., with one vertical screoll bar for the + whole document. This defaults to "no". + + enableT1lib yes | no + Enables or disables use of t1lib (a Type 1 font + rasterizer). This is only relevant if the Xpdf + tools were built with t1lib support. + ("enableT1lib" replaces the old "t1libControl" + option.) This option defaults to "yes". + + enableFreeType yes | no + Enables or disables use of FreeType (a TrueType / + Type 1 font rasterizer). This is only relevant if + the Xpdf tools were built with FreeType support. + ("enableFreeType" replaces the old "freetypeCon- + trol" option.) This option defaults to "yes". + + antialias yes | no + Enables or disables font anti-aliasing in the PDF + rasterizer. This option affects all font rasteriz- + ers. ("antialias" replaces the anti-aliasing con- + trol provided by the old "t1libControl" and + "freetypeControl" options.) This default to "yes". + + vectorAntialias yes | no + Enables or disables anti-aliasing of vector graph- + ics in the PDF rasterizer. This defaults to "yes". + + strokeAdjust yes | no + Enables or disables stroke adjustment. This + defaults to "yes". + + screenType dispersed | clustered | stochasticClustered + Sets the halftone screen type, which will be used + when generating a monochrome (1-bit) bitmap. The + three options are dispersed-dot dithering, clus- + tered-dot dithering (with a round dot and 45-degree + screen angle), and stochastic clustered-dot dither- + ing. By default, "stochasticClustered" is used for + resolutions of 300 dpi and higher, and "dispersed" + is used for resolutions lower then 300 dpi. + + screenSize integer + Sets the size of the (square) halftone screen + threshold matrix. By default, this is 4 for dis- + persed-dot dithering, 10 for clustered-dot dither- + ing, and 100 for stochastic clustered-dot dither- + ing. + + screenDotRadius integer + Sets the halftone screen dot radius. This is only + used when screenType is set to stochasticClustered, + and it defaults to 2. In clustered-dot mode, the + dot radius is half of the screen size. Dispersed- + dot dithering doesn't have a dot radius. + + screenGamma float + Sets the halftone screen gamma correction parame- + ter. Gamma values greater than 1 make the output + brighter; gamma values less than 1 make it darker. + The default value is 1. + + screenBlackThreshold float + When halftoning, all values below this threshold + are forced to solid black. This parameter is a + floating point value between 0 (black) and 1 + (white). The default value is 0. + + screenWhiteThreshold float + When halftoning, all values above this threshold + are forced to solid white. This parameter is a + floating point value between 0 (black) and 1 + (white). The default value is 1. + + urlCommand command + Sets the command executed when you click on a URL + link. The string "%s" will be replaced with the + URL. (See the example below.) This has no default + value. + + movieCommand command + Sets the command executed when you click on a movie + annotation. The string "%s" will be replaced with + the movie file name. This has no default value. + + mapNumericCharNames yes | no + If set to "yes", the Xpdf tools will attempt to map + various numeric character names sometimes used in + font subsets. In some cases this leads to usable + text, and in other cases it leads to gibberish -- + there is no way for Xpdf to tell. This defaults to + "yes". + + mapUnknownCharNames yes | no + If set to "yes", and mapNumericCharNames is set to + "no", the Xpdf tools will apply a simple pass- + through mapping (Unicode index = character code) + for all unrecognized glyph names. In some cases, + this leads to usable text, and in other cases it + leads to gibberish -- there is no way for Xpdf to + tell. This defaults to "no". + + bind modifiers-key context command ... + Add a key or mouse button binding. Modifiers can + be zero or more of: + + shift- + ctrl- + alt- + + Key can be a regular ASCII character, or any one + of: + + space + tab + return + enter + backspace + insert + delete + home + end + pgup + pgdn + left / right / up / down (arrow keys) + f1 .. f35 (function keys) + mousePress1 .. mousePress7 (mouse buttons) + mouseRelease1 .. mouseRelease7 (mouse buttons) + + Context is either "any" or a comma-separated combi- + nation of: + + fullScreen / window (full screen mode on/off) + continuous / singlePage (continuous mode on/off) + overLink / offLink (mouse over link or not) + scrLockOn / scrLockOff (scroll lock on/off) + + The context string can include only one of each + pair in the above list. + + Command is an Xpdf command (see the COMMANDS sec- + tion of the xpdf(1) man page for details). Multi- + ple commands are separated by whitespace. + + The bind command replaces any existing binding, but + only if it was defined for the exact same modi- + fiers, key, and context. All tokens (modifiers, + key, context, commands) are case-sensitive. + + Example key bindings: + + # bind ctrl-a in any context to the nextPage + # command + bind ctrl-a any nextPage + + # bind uppercase B, when in continuous mode + # with scroll lock on, to the reload command + # followed by the prevPage command + bind B continuous,scrLockOn reload prevPage + + See the xpdf(1) man page for more examples. + + unbind modifiers-key context + Removes a key binding established with the bind + command. This is most useful to remove default key + bindings before establishing new ones (e.g., if the + default key binding is given for "any" context, and + you want to create new key bindings for multiple + contexts). + + printCommands yes | no + If set to "yes", drawing commands are printed as + they're executed (useful for debugging). This + defaults to "no". + + errQuiet yes | no + If set to "yes", this suppresses all error and + warning messages from all of the Xpdf tools. This + defaults to "no". + + () + +2 EXAMPLES + + The following is a sample xpdfrc file. + + # from the Thai support package + nameToUnicode /usr/local/share/xpdf/Thai.nameToUnicode + + # from the Japanese support package + cidToUnicode Adobe-Japan1 /usr/local/share/xpdf/Adobe-Japan1.cidToUnicode + unicodeMap JISX0208 /usr/local/share/xpdf/JISX0208.unicodeMap + cMapDir Adobe-Japan1 /usr/local/share/xpdf/cmap/Adobe-Japan1 + + # use the Base-14 Type 1 fonts from ghostscript + displayFontT1 Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb + displayFontT1 Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb + displayFontT1 Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb + displayFontT1 Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb + displayFontT1 Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb + displayFontT1 Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb + displayFontT1 Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb + displayFontT1 Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb + displayFontT1 Courier /usr/local/share/ghostscript/fonts/n022003l.pfb + displayFontT1 Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb + displayFontT1 Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb + displayFontT1 Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb + displayFontT1 Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb + displayFontT1 ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb + + # use the Bakoma Type 1 fonts + # (this assumes they happen to be installed in /usr/local/fonts/bakoma) + fontDir /usr/local/fonts/bakoma + + # set some PostScript options + psPaperSize letter + psDuplex no + psLevel level2 + psEmbedType1Fonts yes + psEmbedTrueTypeFonts yes + psFile "| lpr -Pprinter5" + + # assume that the PostScript printer has the Univers and + # Univers-Bold fonts + psFont Univers Univers + psFont Univers-Bold Univers-Bold + + # set the text output options + textEncoding UTF-8 + textEOL unix + + # misc options + t1libControl low + freetypeControl low + urlCommand "netscape -remote 'openURL(%s)'" + + () + +2 FILES + + /usr/local/etc/xpdfrc + This is the default location for the system-wide + configuration file. Depending on build options, it + may be placed elsewhere. + + $HOME/.xpdfrc + This is the user's configuration file. If it + exists, it will be read in place of the system-wide + file. + + () + +2 AUTHOR + + The Xpdf software and documentation are copyright + 1996-2007 Glyph & Cog, LLC. + + () + +2 SEE_ALSO + + xpdf(1), pdftops(1), pdftotext(1), pdfinfo(1), + pdftoppm(1), pdfimages(1) + http://www.foolabs.com/xpdf/ + + () + diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFTree.cc swftools-0.9.1/lib/pdf/xpdf/XPDFTree.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFTree.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XPDFTree.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,931 @@ +//======================================================================== +// +// XPDFTree.cc +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include +#include "gmem.h" +#include "XPDFTreeP.h" + +//------------------------------------------------------------------------ + +#define xpdfTreeIndent 16 + +//------------------------------------------------------------------------ + +struct _XPDFTreeEntry { + Widget widget; + XPDFTreeEntry *children; + XPDFTreeEntry *next; +}; + +//------------------------------------------------------------------------ + +static void classPartInitialize(WidgetClass widgetClass); +static void initialize(Widget requestWidget, Widget newWidget, + ArgList args, Cardinal *numArgs); +static void destroy(Widget widget); +static void destroySubtree(XPDFTreeEntry *e); +static void resize(Widget widget); +static void redisplay(Widget widget, XEvent *event, Region region); +static void redisplaySubtree(XPDFTreeWidget w, XPDFTreeEntry *e, + XEvent *event, Region region); +static void drawExpandedIcon(XPDFTreeWidget w, Position x, Position y); +static void drawCollapsedIcon(XPDFTreeWidget w, Position x, Position y); +static Boolean setValues(Widget oldWidget, Widget requestWidget, + Widget newWidget, ArgList args, Cardinal *numArgs); +static void setValuesAlmost(Widget oldWidget, Widget newWidget, + XtWidgetGeometry *request, + XtWidgetGeometry *reply); +static XtGeometryResult queryGeometry(Widget widget, + XtWidgetGeometry *request, + XtWidgetGeometry *reply); +static XtGeometryResult geometryManager(Widget widget, + XtWidgetGeometry *request, + XtWidgetGeometry *reply); +static void changeManaged(Widget widget); +static void initConstraint(Widget requestWidget, Widget newWidget, + ArgList args, Cardinal *numArgs); +static void destroyConstraint(Widget widget); +static void deleteSubtree(Widget widget); +static Boolean constraintSetValues(Widget oldWidget, Widget requestWidget, + Widget newWidget, + ArgList args, Cardinal *numArgs); +static void insertChildOnList(XPDFTreeEntry *e, XPDFTreeEntry **listHead); +static void deleteChildFromList(XPDFTreeEntry *e, XPDFTreeEntry **listHead); +static void createGC(Widget widget); +static void destroyGC(Widget widget); +static void layout(Widget widget, Widget instigator); +static int layoutSubtree(XPDFTreeWidget w, Widget instigator, + XPDFTreeEntry *e, Position x, Position y, + Boolean visible); +static void calcSize(Widget widget, Widget instigator, + Dimension *totalWidth, + Dimension *totalHeight); +static void calcSubtreeSize(XPDFTreeWidget w, Widget instigator, + XPDFTreeEntry *e, + Dimension *width, Dimension *height); +static Boolean needRelayout(Widget oldWidget, Widget newWidget); +static void click(Widget widget, XEvent *event, + String *params, Cardinal *numParams); +static Boolean findPosition(XPDFTreeWidget w, int x, int y, + XPDFTreeEntry **e, Boolean *onExpandIcon); +static Boolean findPositionInSubtree(XPDFTreeWidget w, int x, int y, + XPDFTreeEntry **e, + Boolean *onExpandIcon); + +//------------------------------------------------------------------------ + +static XtResource resources[] = { + { XmNmarginWidth, XmCMarginWidth, XmRHorizontalDimension, + sizeof(Dimension), XtOffsetOf(XPDFTreeRec, tree.marginWidth), + XmRImmediate, (XtPointer)0 }, + { XmNmarginHeight, XmCMarginHeight, XmRVerticalDimension, + sizeof(Dimension), XtOffsetOf(XPDFTreeRec, tree.marginHeight), + XmRImmediate, (XtPointer)0 }, + { XPDFNselectionCallback, XmCCallback, XmRCallback, + sizeof(XtCallbackList), XtOffsetOf(XPDFTreeRec, tree.selectCallback), + XmRImmediate, (XtPointer)NULL } +}; + +static XmSyntheticResource synResources[] = { + { XmNmarginWidth, sizeof(Dimension), + XtOffsetOf(XPDFTreeRec, tree.marginWidth), +#if XmVERSION > 1 + XmeFromHorizontalPixels, XmeToHorizontalPixels +#else + _XmFromHorizontalPixels, _XmToHorizontalPixels +#endif + }, + { XmNmarginHeight, sizeof(Dimension), + XtOffsetOf(XPDFTreeRec, tree.marginHeight), +#if XmVERSION > 1 + XmeFromVerticalPixels, XmeToVerticalPixels +#else + _XmFromVerticalPixels, _XmToVerticalPixels +#endif + } +}; + +static XtResource constraints[] = { + { XPDFNentryParent, XPDFCentryParent, XmRWidget, + sizeof(Widget), XtOffsetOf(XPDFTreeConstraintRec, tree.entryParent), + XmRImmediate, (XtPointer)NULL }, + { XPDFNentryExpanded, XPDFCentryExpanded, XmRBoolean, + sizeof(Boolean), XtOffsetOf(XPDFTreeConstraintRec, tree.entryExpanded), + XmRImmediate, (XtPointer)False }, + { XPDFNentryPosition, XPDFCentryPosition, XmRInt, + sizeof(int), XtOffsetOf(XPDFTreeConstraintRec, tree.entryPosition), + XmRImmediate, (XtPointer)0 } +}; + +static char defaultTranslations[] = + ": XPDFTreeClick()"; + +static XtActionsRec actions[] = { + { "XPDFTreeClick", click } +}; + +externaldef(xpdftreeclassrec) XPDFTreeClassRec xpdfTreeClassRec = { + { // Core + (WidgetClass)&xmManagerClassRec, // superclass + "XPDFTree", // class_name + sizeof(XPDFTreeRec), // widget_size + NULL, // class_initialize + &classPartInitialize, // class_part_initialize + FALSE, // class_inited + &initialize, // initialize + NULL, // initialize_hook + XtInheritRealize, // realize + actions, // actions + XtNumber(actions), // num_actions + resources, // resources + XtNumber(resources), // num_resources + NULLQUARK, // xrm_class + TRUE, // compress_motion + XtExposeCompressMaximal, // compress_exposure + TRUE, // compress_enterleave + FALSE, // visible_interest + &destroy, // destroy + &resize, // resize + &redisplay, // expose + &setValues, // set_values + NULL, // set_values_hook + &setValuesAlmost, // set_values_almost + NULL, // get_values_hook + NULL, // accept_focus + XtVersion, // version + NULL, // callback_private + defaultTranslations, // tm_table + &queryGeometry, // query_geometry + NULL, // display_accelerator + NULL // extension + }, + { // Composite + &geometryManager, // geometry_manager + &changeManaged, // change_managed + XtInheritInsertChild, // insert_child + XtInheritDeleteChild, // delete_child + NULL // extension + }, + { // Constraint + constraints, // constraint_resources + XtNumber(constraints), // constraint_num_resources + sizeof(XPDFTreeConstraintRec), // constraint_size + &initConstraint, // constraint_initialize + &destroyConstraint, // constraint_destroy + &constraintSetValues, // constraint_set_values + NULL // extension + }, + { // XmManager + XtInheritTranslations, // translations +#if XmVERSION > 1 + synResources, // syn_resources + XtNumber(synResources), // num_syn_resources +#else + NULL, // syn_resources + 0, // num_syn_resources +#endif + NULL, // syn_constraint_resources + 0, // num_syn_constraint_res's + XmInheritParentProcess, // parent_process + NULL // extension + }, + { // XPDFTree + &createGC, // createGC + &destroyGC, // destroyGC + &layout, // layout + &calcSize, // calcSize + &needRelayout, // needRelayout + NULL // extension + } +}; + +externaldef(xpdftreewidgetclass) WidgetClass xpdfTreeWidgetClass = + (WidgetClass)&xpdfTreeClassRec; + +//------------------------------------------------------------------------ + +static void classPartInitialize(WidgetClass widgetCls) { + XPDFTreeWidgetClass wc = (XPDFTreeWidgetClass)widgetCls; + XPDFTreeWidgetClass sc = (XPDFTreeWidgetClass)wc->coreClass.superclass; + + // method inheritance + if (wc->treeClass.createGC == XPDFInheritCreateGC) { + wc->treeClass.createGC = sc->treeClass.createGC; + } + if (wc->treeClass.destroyGC == XPDFInheritDestroyGC) { + wc->treeClass.destroyGC = sc->treeClass.destroyGC; + } + if (wc->treeClass.layout == XPDFInheritLayout) { + wc->treeClass.layout = sc->treeClass.layout; + } + if (wc->treeClass.calcSize == XPDFInheritCalcSize) { + wc->treeClass.calcSize = sc->treeClass.calcSize; + } + if (wc->treeClass.needRelayout == XPDFInheritNeedRelayout) { + wc->treeClass.needRelayout = sc->treeClass.needRelayout; + } +} + +static void initialize(Widget requestWidget, Widget newWidget, + ArgList args, Cardinal *numArgs) { + XPDFTreeWidget nw = (XPDFTreeWidget)newWidget; + XPDFTreeWidgetClass cls = (XPDFTreeWidgetClass)XtClass(newWidget); + + nw->tree.root = NULL; + nw->tree.redrawY = -1; + if (cls->treeClass.createGC) { + (*cls->treeClass.createGC)(newWidget); + } else { + createGC(newWidget); + } +} + +static void destroy(Widget widget) { + XPDFTreeWidget w = (XPDFTreeWidget)widget; + XPDFTreeWidgetClass cls = (XPDFTreeWidgetClass)XtClass(widget); + + if (w->tree.root) { + destroySubtree(w->tree.root); + w->tree.root = NULL; + } + if (cls->treeClass.destroyGC) { + (*cls->treeClass.destroyGC)(widget); + } else { + destroyGC(widget); + } +} + +static void destroySubtree(XPDFTreeEntry *e) { + if (e->children) { + destroySubtree(e->children); + } + if (e->next) { + destroySubtree(e->next); + } +} + +static void resize(Widget widget) { + XPDFTreeWidgetClass cls = (XPDFTreeWidgetClass)XtClass(widget); + + if (cls->treeClass.layout) { + (*cls->treeClass.layout)(widget, NULL); + } else { + layout(widget, NULL); + } +} + +static void redisplay(Widget widget, XEvent *event, Region region) { + XPDFTreeWidget w = (XPDFTreeWidget)widget; + XPDFTreeEntry *e; + + if (w->tree.redrawY >= 0) { + XClearArea(XtDisplay((Widget)w), XtWindow((Widget)w), + 0, w->tree.redrawY, w->core.width, w->core.height, False); + w->tree.redrawY = -1; + } + for (e = w->tree.root; e; e = e->next) { + redisplaySubtree(w, e, event, region); + } +} + +static void redisplaySubtree(XPDFTreeWidget w, XPDFTreeEntry *e, + XEvent *event, Region region) { + XPDFTreeConstraint c; + Position x, y, y2; + XPDFTreeEntry *child; + + (*XtClass(e->widget)->core_class.expose)(e->widget, event, region); + c = XPDFTreeCPart(e->widget); + x = e->widget->core.x; + y = e->widget->core.y + e->widget->core.height / 2; + if (e->children) { + if (c->entryExpanded) { + drawExpandedIcon(w, x - 8, y); + y2 = y; // make gcc happy + for (child = e->children; child; child = child->next) { + y2 = child->widget->core.y + child->widget->core.height / 2; + XDrawLine(XtDisplay((Widget)w), XtWindow((Widget)w), w->tree.dottedGC, + x - 8, y2, x + 6, y2); + redisplaySubtree(w, child, event, region); + } + XDrawLine(XtDisplay((Widget)w), XtWindow((Widget)w), w->tree.dottedGC, + x - 8, y + 2, x - 8, y2); + } else { + drawCollapsedIcon(w, x - 8, y); + } + } +} + +static void drawExpandedIcon(XPDFTreeWidget w, Position x, Position y) { + XPoint pts[4]; + + pts[0].x = x - 4; pts[0].y = y - 2; + pts[1].x = x + 4; pts[1].y = y - 2; + pts[2].x = x; pts[2].y = y + 2; + pts[3].x = x - 4; pts[3].y = y - 2; + XDrawLines(XtDisplay((Widget)w), XtWindow((Widget)w), w->tree.plainGC, + pts, 4, CoordModeOrigin); +} + +static void drawCollapsedIcon(XPDFTreeWidget w, Position x, Position y) { + XPoint pts[4]; + + pts[0].x = x - 2; pts[0].y = y - 4; + pts[1].x = x - 2; pts[1].y = y + 4; + pts[2].x = x + 2; pts[2].y = y; + pts[3].x = x - 2; pts[3].y = y - 4; + XDrawLines(XtDisplay((Widget)w), XtWindow((Widget)w), w->tree.plainGC, + pts, 4, CoordModeOrigin); +} + +static Boolean setValues(Widget oldWidget, Widget requestWidget, + Widget newWidget, ArgList args, Cardinal *numArgs) { + XPDFTreeWidget ow = (XPDFTreeWidget)oldWidget; + XPDFTreeWidget nw = (XPDFTreeWidget)newWidget; + XPDFTreeWidgetClass cls = (XPDFTreeWidgetClass)XtClass(nw); + Boolean relayout, redisp; + + // check to see if layout-affecting resources have changed + if (cls->treeClass.needRelayout) { + relayout = (*cls->treeClass.needRelayout)((Widget)ow, (Widget)nw); + } else { + relayout = needRelayout((Widget)ow, (Widget)nw); + } + redisp = False; + if (relayout) { + + // calculate a new ideal size (reset the widget size first so + // calcSize will compute a new one) + if (nw->core.width == ow->core.width) { + nw->core.width = 0; + } + if (nw->core.height == ow->core.height) { + nw->core.height = 0; + } + if (cls->treeClass.calcSize) { + (*cls->treeClass.calcSize)((Widget)nw, NULL, + &nw->core.width, &nw->core.height); + } else { + calcSize((Widget)nw, NULL, &nw->core.width, &nw->core.height); + } + + // if resources have changed but size hasn't, layout manually + // (because Xt just looks at the size) + if (nw->core.width == ow->core.width && + nw->core.height == ow->core.height) { + if (cls->treeClass.layout) { + (*cls->treeClass.layout)((Widget)nw, NULL); + } else { + layout((Widget)nw, NULL); + } + redisp = True; + } + } + + return redisp; +} + +static void setValuesAlmost(Widget oldWidget, Widget newWidget, + XtWidgetGeometry *request, + XtWidgetGeometry *reply) { + XPDFTreeWidgetClass cls = (XPDFTreeWidgetClass)XtClass(newWidget); + + // our parent rejected a geometry request, so accept the compromise + // and relayout + if (!reply->request_mode) { + if (cls->treeClass.layout) { + (*cls->treeClass.layout)(newWidget, NULL); + } else { + layout(newWidget, NULL); + } + } + *request = *reply; +} + +static XtGeometryResult queryGeometry(Widget widget, + XtWidgetGeometry *request, + XtWidgetGeometry *reply) { + XPDFTreeWidgetClass cls = (XPDFTreeWidgetClass)XtClass(widget); + + if (!XtIsRealized(widget)) { + reply->width = XtWidth(widget); + reply->height = XtHeight(widget); + } else { + reply->width = 0; + reply->height = 0; + } + if (cls->treeClass.calcSize) { + (*cls->treeClass.calcSize)(widget, NULL, &reply->width, &reply->height); + } else { + calcSize(widget, NULL, &reply->width, &reply->height); + } +#if XmVERSION > 1 + return XmeReplyToQueryGeometry(widget, request, reply); +#else + if ((request->request_mode & CWWidth) && + (request->request_mode & CWHeight) && + request->width == reply->width && + request->height == reply->height) { + return XtGeometryYes; + } + if (reply->width == XtWidth(widget) && + reply->height == XtHeight(widget)) { + return XtGeometryNo; + } + reply->request_mode = CWWidth | CWHeight; + return XtGeometryAlmost; +#endif +} + +static XtGeometryResult geometryManager(Widget widget, + XtWidgetGeometry *request, + XtWidgetGeometry *reply) { + XPDFTreeWidget w = (XPDFTreeWidget)XtParent(widget); + XPDFTreeWidgetClass cls = (XPDFTreeWidgetClass)XtClass(w); + Dimension curWidth, curHeight, curBW; + XtWidgetGeometry parentReq; + XtGeometryResult result; + + // deny any requests for a new position + if ((request->request_mode & CWX) || (request->request_mode & CWY)) { + return XtGeometryNo; + } + + // save the current geometry + curWidth = w->core.width; + curHeight = w->core.height; + curBW = w->core.border_width; + + // make the requested changes + if (request->request_mode & CWWidth) { + w->core.width = request->width; + } + if (request->request_mode & CWHeight) { + w->core.height = request->height; + } + if (request->request_mode & CWBorderWidth) { + w->core.border_width = request->border_width; + } + + // calculate the new ideal size + parentReq.width = 0; + parentReq.height = 0; + if (cls->treeClass.calcSize) { + (*cls->treeClass.calcSize)((Widget)w, widget, + &parentReq.width, &reply->height); + } else { + calcSize((Widget)w, widget, &parentReq.width, &reply->height); + } + + // send geometry request to our parent + parentReq.request_mode = CWWidth | CWHeight; + if (request->request_mode & XtCWQueryOnly) { + parentReq.request_mode |= XtCWQueryOnly; + } + result = XtMakeGeometryRequest((Widget)w, &parentReq, NULL); + if (result == XtGeometryAlmost) { + result = XtGeometryNo; + } + + if (result == XtGeometryNo || (request->request_mode & XtCWQueryOnly)) { + // restore the original geometry + w->core.width = curWidth; + w->core.height = curHeight; + w->core.border_width = curBW; + } else { + if (cls->treeClass.layout) { + (*cls->treeClass.layout)((Widget)w, widget); + } else { + layout((Widget)w, widget); + } + } + + return result; +} + +static void changeManaged(Widget widget) { + Dimension width, height; + XPDFTreeWidgetClass cls = (XPDFTreeWidgetClass)XtClass(widget); + + // compute the ideal size + if (!XtIsRealized(widget)) { + width = XtWidth(widget); + height = XtHeight(widget); + } else { + width = 0; + height = 0; + } + if (cls->treeClass.calcSize) { + (*cls->treeClass.calcSize)(widget, NULL, &width, &height); + } else { + calcSize(widget, NULL, &width, &height); + } + + // make resize request to parent -- keep asking until we get a yes + // or no + while (XtMakeResizeRequest(widget, width, height, &width, &height) + == XtGeometryAlmost) ; + + // relayout + if (cls->treeClass.layout) { + (*cls->treeClass.layout)(widget, NULL); + } else { + layout(widget, NULL); + } + +#if XmVERSION > 1 + // update keyboard traversal + XmeNavigChangeManaged(widget); +#else + _XmNavigChangeManaged(widget); +#endif +} + +static void initConstraint(Widget requestWidget, Widget newWidget, + ArgList args, Cardinal *numArgs) { + XPDFTreeWidget w = (XPDFTreeWidget)XtParent(newWidget); + XPDFTreeConstraint c; + + c = XPDFTreeCPart(newWidget); + c->e = (XPDFTreeEntry *)gmalloc(sizeof(XPDFTreeEntry)); + c->e->widget = newWidget; + c->e->children = NULL; + c->e->next = NULL; + if (c->entryParent) { + insertChildOnList(c->e, &XPDFTreeCPart(c->entryParent)->e->children); + } else { + insertChildOnList(c->e, &w->tree.root); + } +} + +static void destroyConstraint(Widget widget) { + deleteSubtree(widget); +} + +static void deleteSubtree(Widget widget) { + XPDFTreeWidget w = (XPDFTreeWidget)XtParent(widget); + XPDFTreeConstraint c; + + c = XPDFTreeCPart(widget); + if (!c->e) { + return; + } + while (c->e->children) { + deleteSubtree(c->e->children->widget); + } + if (c->entryParent) { + deleteChildFromList(c->e, &XPDFTreeCPart(c->entryParent)->e->children); + } else { + deleteChildFromList(c->e, &w->tree.root); + } + gfree(c->e); + c->e = NULL; +} + +static Boolean constraintSetValues(Widget oldWidget, Widget requestWidget, + Widget newWidget, + ArgList args, Cardinal *numArgs) { + XPDFTreeWidget w = (XPDFTreeWidget)XtParent(newWidget); + XPDFTreeWidgetClass cls = (XPDFTreeWidgetClass)XtClass((Widget)w); + XPDFTreeConstraint oc, nc; + Boolean relayout; + Dimension width, height; + + if (!XtIsManaged(newWidget)) { + return False; + } + oc = XPDFTreeCPart(oldWidget); + nc = XPDFTreeCPart(newWidget); + relayout = False; + if (nc->entryParent != oc->entryParent || + nc->entryPosition != oc->entryPosition) { + if (oc->entryParent) { + deleteChildFromList(oc->e, &XPDFTreeCPart(oc->entryParent)->e->children); + } else { + deleteChildFromList(oc->e, &w->tree.root); + } + if (nc->entryParent) { + insertChildOnList(nc->e, &XPDFTreeCPart(nc->entryParent)->e->children); + } else { + insertChildOnList(nc->e, &w->tree.root); + } + relayout = True; + } else if (nc->entryExpanded != oc->entryExpanded) { + relayout = True; + } + + if (relayout) { + + // calculate a new ideal size (reset the widget size first so + // calcSize will compute a new one) + width = 0; + height = 0; + if (cls->treeClass.calcSize) { + (*cls->treeClass.calcSize)((Widget)w, NULL, &width, &height); + } else { + calcSize((Widget)w, NULL, &width, &height); + } + + // make resize request to parent -- keep asking until we get a yes + // or no + while (XtMakeResizeRequest((Widget)w, width, height, &width, &height) + == XtGeometryAlmost) ; + + // relayout the widget + if (cls->treeClass.layout) { + (*cls->treeClass.layout)((Widget)w, NULL); + } else { + layout((Widget)w, NULL); + } + } + + return relayout; +} + +static void insertChildOnList(XPDFTreeEntry *e, XPDFTreeEntry **listHead) { + int pos; + XPDFTreeEntry *e2; + + pos = XPDFTreeCPart(e->widget)->entryPosition; + if (!*listHead || pos < XPDFTreeCPart((*listHead)->widget)->entryPosition) { + e->next = *listHead; + *listHead = e; + } else { + for (e2 = *listHead; + e2->next && pos >= XPDFTreeCPart(e2->next->widget)->entryPosition; + e2 = e2->next) ; + e->next = e2->next; + e2->next = e; + } +} + +static void deleteChildFromList(XPDFTreeEntry *e, XPDFTreeEntry **listHead) { + XPDFTreeEntry **p; + + for (p = listHead; *p; p = &(*p)->next) { + if (*p == e) { + *p = e->next; + e->next = NULL; + return; + } + } +} + +static void createGC(Widget widget) { + XPDFTreeWidget w = (XPDFTreeWidget)widget; + XGCValues gcValues; + + gcValues.foreground = w->manager.foreground; + gcValues.line_width = 0; + gcValues.line_style = LineSolid; + w->tree.plainGC = XtGetGC(widget, + GCForeground | GCLineWidth | GCLineStyle, + &gcValues); + + gcValues.line_style = LineOnOffDash; + gcValues.dashes = 1; + gcValues.dash_offset = 0; + w->tree.dottedGC = XtGetGC(widget, + GCForeground | GCLineWidth | GCLineStyle | + GCDashList | GCDashOffset, + &gcValues); +} + +static void destroyGC(Widget widget) { + XPDFTreeWidget w = (XPDFTreeWidget)widget; + + XtReleaseGC(widget, w->tree.plainGC); + XtReleaseGC(widget, w->tree.dottedGC); +} + +static void layout(Widget widget, Widget instigator) { + XPDFTreeWidget w = (XPDFTreeWidget)widget; + XPDFTreeEntry *e; + Position x, y; + + x = w->tree.marginWidth + xpdfTreeIndent; + y = w->tree.marginHeight; + for (e = w->tree.root; e; e = e->next) { + y = layoutSubtree(w, instigator, e, x, y, True); + } +} + +static int layoutSubtree(XPDFTreeWidget w, Widget instigator, + XPDFTreeEntry *e, Position x, Position y, + Boolean visible) { + Widget ew; + XPDFTreeEntry *child; + XPDFTreeConstraint c; + + ew = e->widget; + if (!XtIsManaged(ew)) { + return y; + } + c = XPDFTreeCPart(ew); + + // place this entry + if (ew) { + if (visible) { + if (ew == instigator) { + ew->core.x = x; + ew->core.y = y; + } else { +#if XmVERSION > 1 + XmeConfigureObject(ew, x, y, ew->core.width, ew->core.height, + ew->core.border_width); +#else + _XmConfigureObject(ew, x, y, ew->core.width, ew->core.height, + ew->core.border_width); +#endif + } + y += ew->core.height + 2 * ew->core.border_width; + } + } + + // place this entry's children + x += xpdfTreeIndent; + for (child = e->children; child; child = child->next) { + y = layoutSubtree(w, instigator, child, x, y, + visible && (!c || c->entryExpanded)); + } + + return y; +} + +static void calcSize(Widget widget, Widget instigator, + Dimension *totalWidth, + Dimension *totalHeight) { + XPDFTreeWidget w = (XPDFTreeWidget)widget; + XPDFTreeEntry *e; + Dimension w1, h1, w2, h2; + + w1 = h1 = 0; + for (e = w->tree.root; e; e = e->next) { + calcSubtreeSize(w, instigator, e, &w2, &h2); + if (w2 > w1) { + w1 = w2; + } + h1 += h2; + } + w1 += xpdfTreeIndent + 2 * w->tree.marginWidth; + h1 += 2 * w->tree.marginHeight; + if (h1 == 0) { + h1 = 1; + } + if (!*totalWidth) { + *totalWidth = w1; + } + if (!*totalHeight) { + *totalHeight = h1; + } +} + +static void calcSubtreeSize(XPDFTreeWidget w, Widget instigator, + XPDFTreeEntry *e, + Dimension *width, Dimension *height) { + Widget ew; + XPDFTreeEntry *child; + XPDFTreeConstraint c; + XtWidgetGeometry geom; + Dimension w1, h1, w2, h2; + + ew = e->widget; + if (!XtIsManaged(ew)) { + *width = *height = 0; + return; + } + c = XPDFTreeCPart(ew); + + // get size of this entry + if (ew) { + if (!XtIsManaged(ew)) { + *width = *height = 0; + return; + } + if (ew == instigator) { + w1 = ew->core.width; + h1 = ew->core.height; + } else { + XtQueryGeometry(ew, NULL, &geom); + w1 = (geom.request_mode & CWWidth) ? geom.width : ew->core.width; + h1 = (geom.request_mode & CWHeight) ? geom.height : ew->core.height; + } + h1 += 2 * ew->core.border_width; + } else { + // root of tree + w1 = 0; + h1 = 0; + } + + // if this entry is expanded, get size of all of its children + if (c->entryExpanded) { + for (child = e->children; child; child = child->next) { + calcSubtreeSize(w, instigator, child, &w2, &h2); + w2 += xpdfTreeIndent; + if (w2 > w1) { + w1 = w2; + } + h1 += h2; + } + } + + *width = w1; + *height = h1; +} + +static Boolean needRelayout(Widget oldWidget, Widget newWidget) { + XPDFTreeWidget ow = (XPDFTreeWidget)oldWidget; + XPDFTreeWidget nw = (XPDFTreeWidget)newWidget; + + if (nw->tree.marginWidth != ow->tree.marginWidth || + nw->tree.marginHeight != ow->tree.marginHeight) { + return True; + } + return False; +} + +static void click(Widget widget, XEvent *event, + String *params, Cardinal *numParams) { + XPDFTreeWidget w = (XPDFTreeWidget)widget; + XButtonPressedEvent *bpe; + XPDFTreeEntry *e; + Boolean onExpandIcon; + XPDFTreeConstraint c; + XPDFTreeSelectCallbackStruct cbs; + + if (event->type != ButtonPress) { + return; + } + bpe = (XButtonPressedEvent *)event; + if (findPosition(w, bpe->x, bpe->y, &e, &onExpandIcon)) { + if (onExpandIcon) { + c = XPDFTreeCPart(e->widget); + w->tree.redrawY = e->widget->core.y; + XtVaSetValues(e->widget, XPDFNentryExpanded, !c->entryExpanded, NULL); + } else { + XmProcessTraversal(e->widget, XmTRAVERSE_CURRENT); + XtCallActionProc(widget, "ManagerGadgetActivate", event, NULL, 0); + cbs.reason = XmCR_ACTIVATE; + cbs.event = event; + cbs.selectedItem = e->widget; + XtCallCallbackList(widget, w->tree.selectCallback, &cbs); + } + } +} + +static Boolean findPosition(XPDFTreeWidget w, int x, int y, + XPDFTreeEntry **e, Boolean *onExpandIcon) { + XPDFTreeEntry *e2; + + for (e2 = w->tree.root; e2; e2 = e2->next) { + *e = e2; + if (findPositionInSubtree(w, x, y, e, onExpandIcon)) { + return True; + } + } + return False; +} + +// If (x,y) falls on either an expand/collapse icon or a label gadget, +// set * and * and return true. +static Boolean findPositionInSubtree(XPDFTreeWidget w, int x, int y, + XPDFTreeEntry **e, + Boolean *onExpandIcon) { + Widget child; + XPDFTreeConstraint c; + XPDFTreeEntry *e2; + int y1; + + child = (*e)->widget; + y1 = child->core.y + child->core.height / 2; + if (x >= child->core.x && x < child->core.x + child->core.width && + y >= child->core.y && y < child->core.y + child->core.height) { + *onExpandIcon = False; + return True; + } else if (x >= child->core.x - 16 && x < child->core.x - 4 && + y >= y1 - 6 && y < y1 + 6 && + (*e)->children) { + *onExpandIcon = True; + return True; + } + c = XPDFTreeCPart(child); + if (!c || c->entryExpanded) { + for (e2 = (*e)->children; e2; e2 = e2->next) { + *e = e2; + if (findPositionInSubtree(w, x, y, e, onExpandIcon)) { + return True; + } + } + } + return False; +} + +Widget XPDFCreateTree(Widget parent, char *name, + ArgList argList, Cardinal numArgs) { + return XtCreateWidget(name, xpdfTreeWidgetClass, parent, argList, numArgs); +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFTree.h swftools-0.9.1/lib/pdf/xpdf/XPDFTree.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFTree.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XPDFTree.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,45 @@ +//======================================================================== +// +// XPDFTree.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef XPDFTREE_H +#define XPDFTREE_H + +#include + +extern "C" { + +externalref WidgetClass xpdfTreeWidgetClass; + +typedef struct _XPDFTreeClassRec *XPDFTreeWidgetClass; +typedef struct _XPDFTreeRec *XPDFTreeWidget; + +#ifndef XPDFIsTree +#define XPDFIsTree(w) XtIsSubclass(w, xpdfTreeWidgetClass) +#endif + +#define XPDFNentryParent "entryParent" +#define XPDFNentryExpanded "entryExpanded" +#define XPDFNentryPosition "entryPosition" +#define XPDFNselectionCallback "selectionCallback" + +#define XPDFCentryParent "EntryParent" +#define XPDFCentryExpanded "EntryExpanded" +#define XPDFCentryPosition "EntryPosition" + +typedef struct { + int reason; + XEvent *event; + Widget selectedItem; +} XPDFTreeSelectCallbackStruct; + +extern Widget XPDFCreateTree(Widget parent, char *name, + ArgList argList, Cardinal argCount); + +} // extern "C" + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFTreeP.h swftools-0.9.1/lib/pdf/xpdf/XPDFTreeP.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFTreeP.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XPDFTreeP.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,87 @@ +//======================================================================== +// +// XPDFTreeP.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef XPDFTREEP_H +#define XPDFTREEP_H + +#include +#include "XPDFTree.h" + +extern "C" { + +typedef void (*XPDFLayoutProc)(Widget widget, Widget instigator); +typedef void (*XPDFCalcSizeProc)(Widget widget, Widget instigator, + Dimension *totalWidth, + Dimension *totalHeight); +typedef Boolean (*XPDFNeedRelayoutProc)(Widget oldWidget, Widget newWidget); + +#define XPDFInheritCreateGC ((XtWidgetProc)_XtInherit) +#define XPDFInheritDestroyGC ((XtWidgetProc)_XtInherit) +#define XPDFInheritLayout ((XPDFLayoutProc)_XtInherit) +#define XPDFInheritCalcSize ((XPDFCalcSizeProc)_XtInherit) +#define XPDFInheritNeedRelayout ((XPDFNeedRelayoutProc)_XtInherit) + +typedef struct { + XtWidgetProc createGC; + XtWidgetProc destroyGC; + XPDFLayoutProc layout; + XPDFCalcSizeProc calcSize; + XPDFNeedRelayoutProc needRelayout; + XtPointer extension; +} XPDFTreeClassPart; + +typedef struct _XPDFTreeClassRec { + CoreClassPart coreClass; + CompositeClassPart compositeClass; + ConstraintClassPart constraintClass; + XmManagerClassPart managerClass; + XPDFTreeClassPart treeClass; +} XPDFTreeClassRec; + +externalref XPDFTreeClassRec xpdfTreeClassRec; + +typedef struct _XPDFTreeEntry XPDFTreeEntry; + +typedef struct { + Dimension marginWidth; + Dimension marginHeight; + XtCallbackList selectCallback; + GC plainGC; + GC dottedGC; + XPDFTreeEntry *root; + int redrawY; +} XPDFTreePart; + +typedef struct _XPDFTreeRec { + CorePart core; + CompositePart composite; + ConstraintPart constraint; + XmManagerPart manager; + XPDFTreePart tree; +} XPDFTreeRec; + +#define XPDFTreeIndex (XmManagerIndex + 1) + +typedef struct _XPDFTreeConstraintPart { + Widget entryParent; + Boolean entryExpanded; + int entryPosition; + XPDFTreeEntry *e; +} XPDFTreeConstraintPart, *XPDFTreeConstraint; + +typedef struct _XPDFTreeConstraintRec { + XmManagerConstraintPart manager; + XPDFTreeConstraintPart tree; +} XPDFTreeConstraintRec, *XPDFTreeConstraintPtr; + +#define XPDFTreeCPart(w) \ + (&((XPDFTreeConstraintPtr)(w)->core.constraints)->tree) + +} // extern "C" + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFViewer.cc swftools-0.9.1/lib/pdf/xpdf/XPDFViewer.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFViewer.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XPDFViewer.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,3488 @@ +//======================================================================== +// +// XPDFViewer.cc +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include +#ifdef HAVE_X11_XPM_H +#include +#endif +#if defined(__sgi) && (XmVERSION <= 1) +#define Object XtObject +#include +#undef Object +#endif +#include "gmem.h" +#include "gfile.h" +#include "GString.h" +#include "GList.h" +#include "Error.h" +#include "GlobalParams.h" +#include "PDFDoc.h" +#include "Link.h" +#include "ErrorCodes.h" +#include "Outline.h" +#include "UnicodeMap.h" +#ifndef DISABLE_OUTLINE +#define Object XtObject +#include "XPDFTree.h" +#undef Object +#endif +#include "XPDFApp.h" +#include "XPDFViewer.h" +#include "PSOutputDev.h" +#include "config.h" + +// these macro defns conflict with xpdf's Object class +#ifdef LESSTIF_VERSION +#undef XtDisplay +#undef XtScreen +#undef XtWindow +#undef XtParent +#undef XtIsRealized +#endif + +#if XmVERSION <= 1 +#define XmSET True +#define XmUNSET False +#endif + +// hack around old X includes which are missing these symbols +#ifndef XK_Page_Up +#define XK_Page_Up 0xFF55 +#endif +#ifndef XK_Page_Down +#define XK_Page_Down 0xFF56 +#endif +#ifndef XK_KP_Home +#define XK_KP_Home 0xFF95 +#endif +#ifndef XK_KP_Left +#define XK_KP_Left 0xFF96 +#endif +#ifndef XK_KP_Up +#define XK_KP_Up 0xFF97 +#endif +#ifndef XK_KP_Right +#define XK_KP_Right 0xFF98 +#endif +#ifndef XK_KP_Down +#define XK_KP_Down 0xFF99 +#endif +#ifndef XK_KP_Prior +#define XK_KP_Prior 0xFF9A +#endif +#ifndef XK_KP_Page_Up +#define XK_KP_Page_Up 0xFF9A +#endif +#ifndef XK_KP_Next +#define XK_KP_Next 0xFF9B +#endif +#ifndef XK_KP_Page_Down +#define XK_KP_Page_Down 0xFF9B +#endif +#ifndef XK_KP_End +#define XK_KP_End 0xFF9C +#endif +#ifndef XK_KP_Begin +#define XK_KP_Begin 0xFF9D +#endif +#ifndef XK_KP_Insert +#define XK_KP_Insert 0xFF9E +#endif +#ifndef XK_KP_Delete +#define XK_KP_Delete 0xFF9F +#endif + +//------------------------------------------------------------------------ +// GUI includes +//------------------------------------------------------------------------ + +#include "xpdfIcon.xpm" +#include "leftArrow.xbm" +#include "leftArrowDis.xbm" +#include "dblLeftArrow.xbm" +#include "dblLeftArrowDis.xbm" +#include "rightArrow.xbm" +#include "rightArrowDis.xbm" +#include "dblRightArrow.xbm" +#include "dblRightArrowDis.xbm" +#include "backArrow.xbm" +#include "backArrowDis.xbm" +#include "forwardArrow.xbm" +#include "forwardArrowDis.xbm" +#include "find.xbm" +#include "findDis.xbm" +#include "print.xbm" +#include "printDis.xbm" +#include "about.xbm" +#include "about-text.h" + +//------------------------------------------------------------------------ + +struct ZoomMenuInfo { + char *label; + double zoom; +}; + +static ZoomMenuInfo zoomMenuInfo[nZoomMenuItems] = { + { "400%", 400 }, + { "200%", 200 }, + { "150%", 150 }, + { "125%", 125 }, + { "100%", 100 }, + { "50%", 50 }, + { "25%", 25 }, + { "12.5%", 12.5 }, + { "fit page", zoomPage }, + { "fit width", zoomWidth } +}; + +#define maxZoomIdx 0 +#define defZoomIdx 3 +#define minZoomIdx 7 +#define zoomPageIdx 8 +#define zoomWidthIdx 9 + +//------------------------------------------------------------------------ + +#define cmdMaxArgs 2 + +XPDFViewerCmd XPDFViewer::cmdTab[] = { + { "about", 0, gFalse, gFalse, &XPDFViewer::cmdAbout }, + { "closeOutline", 0, gFalse, gFalse, &XPDFViewer::cmdCloseOutline }, + { "closeWindow", 0, gFalse, gFalse, &XPDFViewer::cmdCloseWindow }, + { "continuousMode", 0, gFalse, gFalse, &XPDFViewer::cmdContinuousMode }, + { "endPan", 0, gTrue, gTrue, &XPDFViewer::cmdEndPan }, + { "endSelection", 0, gTrue, gTrue, &XPDFViewer::cmdEndSelection }, + { "find", 0, gTrue, gFalse, &XPDFViewer::cmdFind }, + { "findNext", 0, gTrue, gFalse, &XPDFViewer::cmdFindNext }, + { "focusToDocWin", 0, gFalse, gFalse, &XPDFViewer::cmdFocusToDocWin }, + { "focusToPageNum", 0, gFalse, gFalse, &XPDFViewer::cmdFocusToPageNum }, + { "followLink", 0, gTrue, gTrue, &XPDFViewer::cmdFollowLink }, + { "followLinkInNewWin", 0, gTrue, gTrue, &XPDFViewer::cmdFollowLinkInNewWin }, + { "followLinkInNewWinNoSel", 0, gTrue, gTrue, &XPDFViewer::cmdFollowLinkInNewWinNoSel }, + { "followLinkNoSel", 0, gTrue, gTrue, &XPDFViewer::cmdFollowLinkNoSel }, + { "fullScreenMode", 0, gFalse, gFalse, &XPDFViewer::cmdFullScreenMode }, + { "goBackward", 0, gFalse, gFalse, &XPDFViewer::cmdGoBackward }, + { "goForward", 0, gFalse, gFalse, &XPDFViewer::cmdGoForward }, + { "gotoDest", 1, gTrue, gFalse, &XPDFViewer::cmdGotoDest }, + { "gotoLastPage", 0, gTrue, gFalse, &XPDFViewer::cmdGotoLastPage }, + { "gotoLastPageNoScroll", 0, gTrue, gFalse, &XPDFViewer::cmdGotoLastPageNoScroll }, + { "gotoPage", 1, gTrue, gFalse, &XPDFViewer::cmdGotoPage }, + { "gotoPageNoScroll", 1, gTrue, gFalse, &XPDFViewer::cmdGotoPageNoScroll }, + { "nextPage", 0, gTrue, gFalse, &XPDFViewer::cmdNextPage }, + { "nextPageNoScroll", 0, gTrue, gFalse, &XPDFViewer::cmdNextPageNoScroll }, + { "open", 0, gFalse, gFalse, &XPDFViewer::cmdOpen }, + { "openFile", 1, gFalse, gFalse, &XPDFViewer::cmdOpenFile }, + { "openFileAtDest", 2, gFalse, gFalse, &XPDFViewer::cmdOpenFileAtDest }, + { "openFileAtDestInNewWin", 2, gFalse, gFalse, &XPDFViewer::cmdOpenFileAtDestInNewWin }, + { "openFileAtPage", 2, gFalse, gFalse, &XPDFViewer::cmdOpenFileAtPage }, + { "openFileAtPageInNewWin", 2, gFalse, gFalse, &XPDFViewer::cmdOpenFileAtPageInNewWin }, + { "openFileInNewWin", 1, gFalse, gFalse, &XPDFViewer::cmdOpenFileInNewWin }, + { "openInNewWin", 0, gFalse, gFalse, &XPDFViewer::cmdOpenInNewWin }, + { "openOutline", 0, gFalse, gFalse, &XPDFViewer::cmdOpenOutline }, + { "pageDown", 0, gTrue, gFalse, &XPDFViewer::cmdPageDown }, + { "pageUp", 0, gTrue, gFalse, &XPDFViewer::cmdPageUp }, + { "postPopupMenu", 0, gFalse, gTrue, &XPDFViewer::cmdPostPopupMenu }, + { "prevPage", 0, gTrue, gFalse, &XPDFViewer::cmdPrevPage }, + { "prevPageNoScroll", 0, gTrue, gFalse, &XPDFViewer::cmdPrevPageNoScroll }, + { "print", 0, gTrue, gFalse, &XPDFViewer::cmdPrint }, + { "quit", 0, gFalse, gFalse, &XPDFViewer::cmdQuit }, + { "raise", 0, gFalse, gFalse, &XPDFViewer::cmdRaise }, + { "redraw", 0, gTrue, gFalse, &XPDFViewer::cmdRedraw }, + { "reload", 0, gTrue, gFalse, &XPDFViewer::cmdReload }, + { "run", 1, gFalse, gFalse, &XPDFViewer::cmdRun }, + { "scrollDown", 1, gTrue, gFalse, &XPDFViewer::cmdScrollDown }, + { "scrollDownNextPage", 1, gTrue, gFalse, &XPDFViewer::cmdScrollDownNextPage }, + { "scrollLeft", 1, gTrue, gFalse, &XPDFViewer::cmdScrollLeft }, + { "scrollOutlineDown", 1, gTrue, gFalse, &XPDFViewer::cmdScrollOutlineDown }, + { "scrollOutlineUp", 1, gTrue, gFalse, &XPDFViewer::cmdScrollOutlineUp }, + { "scrollRight", 1, gTrue, gFalse, &XPDFViewer::cmdScrollRight }, + { "scrollToBottomEdge", 0, gTrue, gFalse, &XPDFViewer::cmdScrollToBottomEdge }, + { "scrollToBottomRight", 0, gTrue, gFalse, &XPDFViewer::cmdScrollToBottomRight }, + { "scrollToLeftEdge", 0, gTrue, gFalse, &XPDFViewer::cmdScrollToLeftEdge }, + { "scrollToRightEdge", 0, gTrue, gFalse, &XPDFViewer::cmdScrollToRightEdge }, + { "scrollToTopEdge", 0, gTrue, gFalse, &XPDFViewer::cmdScrollToTopEdge }, + { "scrollToTopLeft", 0, gTrue, gFalse, &XPDFViewer::cmdScrollToTopLeft }, + { "scrollUp", 1, gTrue, gFalse, &XPDFViewer::cmdScrollUp }, + { "scrollUpPrevPage", 1, gTrue, gFalse, &XPDFViewer::cmdScrollUpPrevPage }, + { "singlePageMode", 0, gFalse, gFalse, &XPDFViewer::cmdSinglePageMode }, + { "startPan", 0, gTrue, gTrue, &XPDFViewer::cmdStartPan }, + { "startSelection", 0, gTrue, gTrue, &XPDFViewer::cmdStartSelection }, + { "toggleContinuousMode", 0, gFalse, gFalse, &XPDFViewer::cmdToggleContinuousMode }, + { "toggleFullScreenMode", 0, gFalse, gFalse, &XPDFViewer::cmdToggleFullScreenMode }, + { "toggleOutline", 0, gFalse, gFalse, &XPDFViewer::cmdToggleOutline }, + { "windowMode", 0, gFalse, gFalse, &XPDFViewer::cmdWindowMode }, + { "zoomFitPage", 0, gFalse, gFalse, &XPDFViewer::cmdZoomFitPage }, + { "zoomFitWidth", 0, gFalse, gFalse, &XPDFViewer::cmdZoomFitWidth }, + { "zoomIn", 0, gFalse, gFalse, &XPDFViewer::cmdZoomIn }, + { "zoomOut", 0, gFalse, gFalse, &XPDFViewer::cmdZoomOut }, + { "zoomPercent", 1, gFalse, gFalse, &XPDFViewer::cmdZoomPercent }, + { "zoomToSelection", 0, gTrue, gFalse, &XPDFViewer::cmdZoomToSelection } +}; + +#define nCmds (sizeof(cmdTab) / sizeof(XPDFViewerCmd)) + +//------------------------------------------------------------------------ + +XPDFViewer::XPDFViewer(XPDFApp *appA, GString *fileName, + int pageA, GString *destName, GBool fullScreen, + GString *ownerPassword, GString *userPassword) { + LinkDest *dest; + int pg; + double z; + + app = appA; + win = NULL; + core = NULL; + ok = gFalse; +#ifndef DISABLE_OUTLINE + outlineLabels = NULL; + outlineLabelsLength = outlineLabelsSize = 0; + outlinePaneWidth = 175; +#endif + + // do Motif-specific initialization and create the window; + // this also creates the core object + initWindow(fullScreen); + initAboutDialog(); + initFindDialog(); + initPrintDialog(); + openDialog = NULL; + saveAsDialog = NULL; + + dest = NULL; // make gcc happy + pg = pageA; // make gcc happy + + if (fileName) { + if (loadFile(fileName, ownerPassword, userPassword)) { + getPageAndDest(pageA, destName, &pg, &dest); +#ifndef DISABLE_OUTLINE + if (outlineScroll != None && + core->getDoc()->getOutline()->getItems() && + core->getDoc()->getOutline()->getItems()->getLength() > 0) { + XtVaSetValues(outlineScroll, XmNwidth, outlinePaneWidth, NULL); + } +#endif + } else { + return; + } + } + core->resizeToPage(pg); + + // map the window -- we do this after calling resizeToPage to avoid + // an annoying on-screen resize + mapWindow(); + + // display the first page + z = core->getZoom(); + if (dest) { + displayDest(dest, z, core->getRotate(), gTrue); + delete dest; + } else { + displayPage(pg, z, core->getRotate(), gTrue, gTrue); + } + + ok = gTrue; +} + +XPDFViewer::XPDFViewer(XPDFApp *appA, PDFDoc *doc, int pageA, + GString *destName, GBool fullScreen) { + LinkDest *dest; + int pg; + double z; + + app = appA; + win = NULL; + core = NULL; + ok = gFalse; +#ifndef DISABLE_OUTLINE + outlineLabels = NULL; + outlineLabelsLength = outlineLabelsSize = 0; + outlinePaneWidth = 175; +#endif + + // do Motif-specific initialization and create the window; + // this also creates the core object + initWindow(fullScreen); + initAboutDialog(); + initFindDialog(); + initPrintDialog(); + openDialog = NULL; + saveAsDialog = NULL; + + dest = NULL; // make gcc happy + pg = pageA; // make gcc happy + + if (doc) { + core->loadDoc(doc); + getPageAndDest(pageA, destName, &pg, &dest); +#ifndef DISABLE_OUTLINE + if (outlineScroll != None && + core->getDoc()->getOutline()->getItems() && + core->getDoc()->getOutline()->getItems()->getLength() > 0) { + XtVaSetValues(outlineScroll, XmNwidth, outlinePaneWidth, NULL); + } +#endif + } + core->resizeToPage(pg); + + // map the window -- we do this after calling resizeToPage to avoid + // an annoying on-screen resize + mapWindow(); + + // display the first page + z = core->getZoom(); + if (dest) { + displayDest(dest, z, core->getRotate(), gTrue); + delete dest; + } else { + displayPage(pg, z, core->getRotate(), gTrue, gTrue); + } + + ok = gTrue; +} + +XPDFViewer::~XPDFViewer() { + delete core; + XmFontListFree(aboutBigFont); + XmFontListFree(aboutVersionFont); + XmFontListFree(aboutFixedFont); + closeWindow(); +#ifndef DISABLE_OUTLINE + if (outlineLabels) { + gfree(outlineLabels); + } +#endif +} + +void XPDFViewer::open(GString *fileName, int pageA, GString *destName) { + LinkDest *dest; + int pg; + double z; + + if (!core->getDoc() || fileName->cmp(core->getDoc()->getFileName())) { + if (!loadFile(fileName, NULL, NULL)) { + return; + } + } + getPageAndDest(pageA, destName, &pg, &dest); + z = core->getZoom(); + if (dest) { + displayDest(dest, z, core->getRotate(), gTrue); + delete dest; + } else { + displayPage(pg, z, core->getRotate(), gTrue, gTrue); + } +} + +void XPDFViewer::clear() { + char *title; + XmString s; + + core->clear(); + + // set up title, number-of-pages display + title = app->getTitle() ? app->getTitle()->getCString() + : (char *)xpdfAppName; + XtVaSetValues(win, XmNtitle, title, XmNiconName, title, NULL); + s = XmStringCreateLocalized(""); + XtVaSetValues(pageNumText, XmNlabelString, s, NULL); + XmStringFree(s); + s = XmStringCreateLocalized(" of 0"); + XtVaSetValues(pageCountLabel, XmNlabelString, s, NULL); + XmStringFree(s); + + // disable buttons + XtVaSetValues(prevTenPageBtn, XmNsensitive, False, NULL); + XtVaSetValues(prevPageBtn, XmNsensitive, False, NULL); + XtVaSetValues(nextTenPageBtn, XmNsensitive, False, NULL); + XtVaSetValues(nextPageBtn, XmNsensitive, False, NULL); + + // remove the old outline +#ifndef DISABLE_OUTLINE + setupOutline(); +#endif +} + +//------------------------------------------------------------------------ +// load / display +//------------------------------------------------------------------------ + +GBool XPDFViewer::loadFile(GString *fileName, GString *ownerPassword, + GString *userPassword) { + return core->loadFile(fileName, ownerPassword, userPassword) == errNone; +} + +void XPDFViewer::reloadFile() { + int pg; + + if (!core->getDoc()) { + return; + } + pg = core->getPageNum(); + loadFile(core->getDoc()->getFileName()); + if (pg > core->getDoc()->getNumPages()) { + pg = core->getDoc()->getNumPages(); + } + displayPage(pg, core->getZoom(), core->getRotate(), gFalse, gFalse); +} + +void XPDFViewer::displayPage(int pageA, double zoomA, int rotateA, + GBool scrollToTop, GBool addToHist) { + core->displayPage(pageA, zoomA, rotateA, scrollToTop, addToHist); +} + +void XPDFViewer::displayDest(LinkDest *dest, double zoomA, int rotateA, + GBool addToHist) { + core->displayDest(dest, zoomA, rotateA, addToHist); +} + +void XPDFViewer::getPageAndDest(int pageA, GString *destName, + int *pageOut, LinkDest **destOut) { + Ref pageRef; + + // find the page number for a named destination + *pageOut = pageA; + *destOut = NULL; + if (destName && (*destOut = core->getDoc()->findDest(destName))) { + if ((*destOut)->isPageRef()) { + pageRef = (*destOut)->getPageRef(); + *pageOut = core->getDoc()->findPage(pageRef.num, pageRef.gen); + } else { + *pageOut = (*destOut)->getPageNum(); + } + } + + if (*pageOut <= 0) { + *pageOut = 1; + } + if (*pageOut > core->getDoc()->getNumPages()) { + *pageOut = core->getDoc()->getNumPages(); + } +} + +//------------------------------------------------------------------------ +// hyperlinks / actions +//------------------------------------------------------------------------ + +void XPDFViewer::doLink(int wx, int wy, GBool onlyIfNoSelection, + GBool newWin) { + XPDFViewer *newViewer; + LinkAction *action; + int pg, selPg; + double xu, yu, selULX, selULY, selLRX, selLRY; + + if (core->getHyperlinksEnabled() && + core->cvtWindowToUser(wx, wy, &pg, &xu, &yu) && + !(onlyIfNoSelection && + core->getSelection(&selPg, &selULX, &selULY, &selLRX, &selLRY))) { + if ((action = core->findLink(pg, xu, yu))) { + if (newWin && + core->getDoc()->getFileName() && + (action->getKind() == actionGoTo || + action->getKind() == actionGoToR || + (action->getKind() == actionNamed && + ((LinkNamed *)action)->getName()->cmp("Quit")))) { + newViewer = app->open(core->getDoc()->getFileName()); + newViewer->core->doAction(action); + } else { + core->doAction(action); + } + } + } +} + +void XPDFViewer::actionCbk(void *data, char *action) { + XPDFViewer *viewer = (XPDFViewer *)data; + + if (!strcmp(action, "Quit")) { + viewer->app->quit(); + } +} + +//------------------------------------------------------------------------ +// keyboard/mouse input +//------------------------------------------------------------------------ + +void XPDFViewer::keyPressCbk(void *data, KeySym key, Guint modifiers, + XEvent *event) { + XPDFViewer *viewer = (XPDFViewer *)data; + int keyCode; + GList *cmds; + int i; + + if (key >= 0x20 && key <= 0xfe) { + keyCode = (int)key; + } else if (key == XK_Tab || + key == XK_KP_Tab) { + keyCode = xpdfKeyCodeTab; + } else if (key == XK_Return) { + keyCode = xpdfKeyCodeReturn; + } else if (key == XK_KP_Enter) { + keyCode = xpdfKeyCodeEnter; + } else if (key == XK_BackSpace) { + keyCode = xpdfKeyCodeBackspace; + } else if (key == XK_Insert || + key == XK_KP_Insert) { + keyCode = xpdfKeyCodeInsert; + } else if (key == XK_Delete || + key == XK_KP_Delete) { + keyCode = xpdfKeyCodeDelete; + } else if (key == XK_Home || + key == XK_KP_Home) { + keyCode = xpdfKeyCodeHome; + } else if (key == XK_End || + key == XK_KP_End) { + keyCode = xpdfKeyCodeEnd; + } else if (key == XK_Page_Up || + key == XK_KP_Page_Up) { + keyCode = xpdfKeyCodePgUp; + } else if (key == XK_Page_Down || + key == XK_KP_Page_Down) { + keyCode = xpdfKeyCodePgDn; + } else if (key == XK_Left || + key == XK_KP_Left) { + keyCode = xpdfKeyCodeLeft; + } else if (key == XK_Right || + key == XK_KP_Right) { + keyCode = xpdfKeyCodeRight; + } else if (key == XK_Up || + key == XK_KP_Up) { + keyCode = xpdfKeyCodeUp; + } else if (key == XK_Down || + key == XK_KP_Down) { + keyCode = xpdfKeyCodeDown; + } else if (key >= XK_F1 && key <= XK_F35) { + keyCode = xpdfKeyCodeF1 + (key - XK_F1); + } else { + return; + } + + if ((cmds = globalParams->getKeyBinding(keyCode, + viewer->getModifiers(modifiers), + viewer->getContext(modifiers)))) { + for (i = 0; i < cmds->getLength(); ++i) { + viewer->execCmd((GString *)cmds->get(i), event); + } + deleteGList(cmds, GString); + } +} + +void XPDFViewer::mouseCbk(void *data, XEvent *event) { + XPDFViewer *viewer = (XPDFViewer *)data; + int keyCode; + GList *cmds; + int i; + + if (event->type == ButtonPress) { + if (event->xbutton.button >= 1 && event->xbutton.button <= 7) { + keyCode = xpdfKeyCodeMousePress1 + event->xbutton.button - 1; + } else { + return; + } + } else if (event->type == ButtonRelease) { + if (event->xbutton.button >= 1 && event->xbutton.button <= 7) { + keyCode = xpdfKeyCodeMouseRelease1 + event->xbutton.button - 1; + } else { + return; + } + } else { + return; + } + + if ((cmds = globalParams->getKeyBinding(keyCode, + viewer->getModifiers( + event->xkey.state), + viewer->getContext( + event->xkey.state)))) { + for (i = 0; i < cmds->getLength(); ++i) { + viewer->execCmd((GString *)cmds->get(i), event); + } + deleteGList(cmds, GString); + } +} + +int XPDFViewer::getModifiers(Guint modifiers) { + int mods; + + mods = 0; + if (modifiers & ShiftMask) { + mods |= xpdfKeyModShift; + } + if (modifiers & ControlMask) { + mods |= xpdfKeyModCtrl; + } + if (modifiers & Mod1Mask) { + mods |= xpdfKeyModAlt; + } + return mods; +} + +int XPDFViewer::getContext(Guint modifiers) { + int context; + + context = (core->getFullScreen() ? xpdfKeyContextFullScreen + : xpdfKeyContextWindow) | + (core->getContinuousMode() ? xpdfKeyContextContinuous + : xpdfKeyContextSinglePage) | + (core->getLinkAction() ? xpdfKeyContextOverLink + : xpdfKeyContextOffLink) | + ((modifiers & Mod5Mask) ? xpdfKeyContextScrLockOn + : xpdfKeyContextScrLockOff); + return context; +} + +void XPDFViewer::execCmd(GString *cmd, XEvent *event) { + GString *name; + GString *args[cmdMaxArgs]; + char *p0, *p1; + int nArgs, i; + int a, b, m, cmp; + + //----- parse the command + name = NULL; + nArgs = 0; + for (i = 0; i < cmdMaxArgs; ++i) { + args[i] = NULL; + } + p0 = cmd->getCString(); + for (p1 = p0; *p1 && isalnum(*p1); ++p1) ; + if (p1 == p0) { + goto err1; + } + name = new GString(p0, p1 - p0); + if (*p1 == '(') { + while (nArgs < cmdMaxArgs) { + p0 = p1 + 1; + for (p1 = p0; *p1 && *p1 != ',' && *p1 != ')'; ++p1) ; + args[nArgs++] = new GString(p0, p1 - p0); + if (*p1 != ',') { + break; + } + } + if (*p1 != ')') { + goto err1; + } + ++p1; + } + if (*p1) { + goto err1; + } + + //----- find the command + a = -1; + b = nCmds; + // invariant: cmdTab[a].name < name < cmdTab[b].name + while (b - a > 1) { + m = (a + b) / 2; + cmp = strcmp(cmdTab[m].name, name->getCString()); + if (cmp < 0) { + a = m; + } else if (cmp > 0) { + b = m; + } else { + a = b = m; + } + } + if (cmp != 0) { + goto err1; + } + + //----- execute the command + if (nArgs != cmdTab[a].nArgs || + (cmdTab[a].requiresEvent && !event)) { + goto err1; + } + if (cmdTab[a].requiresDoc && !core->getDoc()) { + // don't issue an error message for this -- it happens, e.g., when + // clicking in a window with no open PDF file + goto err2; + } + (this->*cmdTab[a].func)(args, nArgs, event); + + //----- clean up + delete name; + for (i = 0; i < nArgs; ++i) { + if (args[i]) { + delete args[i]; + } + } + return; + + err1: + error(-1, "Invalid command syntax: '%s'", cmd->getCString()); + err2: + if (name) { + delete name; + } + for (i = 0; i < nArgs; ++i) { + if (args[i]) { + delete args[i]; + } + } +} + +//------------------------------------------------------------------------ +// command functions +//------------------------------------------------------------------------ + +static int mouseX(XEvent *event) { + switch (event->type) { + case ButtonPress: + case ButtonRelease: + return event->xbutton.x; + case KeyPress: + return event->xkey.x; + } + return 0; +} + +static int mouseY(XEvent *event) { + switch (event->type) { + case ButtonPress: + case ButtonRelease: + return event->xbutton.y; + case KeyPress: + return event->xkey.y; + } + return 0; +} + +void XPDFViewer::cmdAbout(GString *args[], int nArgs, + XEvent *event) { + XtManageChild(aboutDialog); +} + +void XPDFViewer::cmdCloseOutline(GString *args[], int nArgs, + XEvent *event) { +#ifndef DISABLE_OUTLINE + Dimension w; + + if (outlineScroll == None) { + return; + } + XtVaGetValues(outlineScroll, XmNwidth, &w, NULL); + if (w > 1) { + outlinePaneWidth = w; + // this ugly kludge is apparently the only way to resize the panes + // within an XmPanedWindow + XtVaSetValues(outlineScroll, XmNpaneMinimum, 1, + XmNpaneMaximum, 1, NULL); + XtVaSetValues(outlineScroll, XmNpaneMinimum, 1, + XmNpaneMaximum, 10000, NULL); + } +#endif +} + +void XPDFViewer::cmdCloseWindow(GString *args[], int nArgs, + XEvent *event) { + app->close(this, gFalse); +} + +void XPDFViewer::cmdContinuousMode(GString *args[], int nArgs, + XEvent *event) { + Widget btn; + + if (core->getContinuousMode()) { + return; + } + core->setContinuousMode(gTrue); + + btn = XtNameToWidget(popupMenu, "continuousMode"); + XtVaSetValues(btn, XmNset, XmSET, NULL); +} + +void XPDFViewer::cmdEndPan(GString *args[], int nArgs, + XEvent *event) { + core->endPan(mouseX(event), mouseY(event)); +} + +void XPDFViewer::cmdEndSelection(GString *args[], int nArgs, + XEvent *event) { + core->endSelection(mouseX(event), mouseY(event)); +} + +void XPDFViewer::cmdFind(GString *args[], int nArgs, + XEvent *event) { + mapFindDialog(); +} + +void XPDFViewer::cmdFindNext(GString *args[], int nArgs, + XEvent *event) { + doFind(gTrue); +} + +void XPDFViewer::cmdFocusToDocWin(GString *args[], int nArgs, + XEvent *event) { + core->takeFocus(); +} + +void XPDFViewer::cmdFocusToPageNum(GString *args[], int nArgs, + XEvent *event) { + XmTextFieldSetSelection(pageNumText, 0, + strlen(XmTextFieldGetString(pageNumText)), + XtLastTimestampProcessed(display)); + XmProcessTraversal(pageNumText, XmTRAVERSE_CURRENT); +} + +void XPDFViewer::cmdFollowLink(GString *args[], int nArgs, + XEvent *event) { + doLink(mouseX(event), mouseY(event), gFalse, gFalse); +} + +void XPDFViewer::cmdFollowLinkInNewWin(GString *args[], int nArgs, + XEvent *event) { + doLink(mouseX(event), mouseY(event), gFalse, gTrue); +} + +void XPDFViewer::cmdFollowLinkInNewWinNoSel(GString *args[], int nArgs, + XEvent *event) { + doLink(mouseX(event), mouseY(event), gTrue, gTrue); +} + +void XPDFViewer::cmdFollowLinkNoSel(GString *args[], int nArgs, + XEvent *event) { + doLink(mouseX(event), mouseY(event), gTrue, gFalse); +} + +void XPDFViewer::cmdFullScreenMode(GString *args[], int nArgs, + XEvent *event) { + PDFDoc *doc; + XPDFViewer *viewer; + int pg; + Widget btn; + + if (core->getFullScreen()) { + return; + } + pg = core->getPageNum(); + XtPopdown(win); + doc = core->takeDoc(gFalse); + viewer = app->reopen(this, doc, pg, gTrue); + + btn = XtNameToWidget(viewer->popupMenu, "fullScreen"); + XtVaSetValues(btn, XmNset, XmSET, NULL); +} + +void XPDFViewer::cmdGoBackward(GString *args[], int nArgs, + XEvent *event) { + core->goBackward(); +} + +void XPDFViewer::cmdGoForward(GString *args[], int nArgs, + XEvent *event) { + core->goForward(); +} + +void XPDFViewer::cmdGotoDest(GString *args[], int nArgs, + XEvent *event) { + int pg; + LinkDest *dest; + + getPageAndDest(1, args[0], &pg, &dest); + if (dest) { + displayDest(dest, core->getZoom(), core->getRotate(), gTrue); + delete dest; + } +} + +void XPDFViewer::cmdGotoLastPage(GString *args[], int nArgs, + XEvent *event) { + displayPage(core->getDoc()->getNumPages(), + core->getZoom(), core->getRotate(), + gTrue, gTrue); +} + +void XPDFViewer::cmdGotoLastPageNoScroll(GString *args[], int nArgs, + XEvent *event) { + displayPage(core->getDoc()->getNumPages(), + core->getZoom(), core->getRotate(), + gFalse, gTrue); +} + +void XPDFViewer::cmdGotoPage(GString *args[], int nArgs, + XEvent *event) { + int pg; + + pg = atoi(args[0]->getCString()); + if (pg < 1 || pg > core->getDoc()->getNumPages()) { + return; + } + displayPage(pg, core->getZoom(), core->getRotate(), gTrue, gTrue); +} + +void XPDFViewer::cmdGotoPageNoScroll(GString *args[], int nArgs, + XEvent *event) { + int pg; + + pg = atoi(args[0]->getCString()); + if (pg < 1 || pg > core->getDoc()->getNumPages()) { + return; + } + displayPage(pg, core->getZoom(), core->getRotate(), gFalse, gTrue); +} + +void XPDFViewer::cmdNextPage(GString *args[], int nArgs, + XEvent *event) { + core->gotoNextPage(1, gTrue); +} + +void XPDFViewer::cmdNextPageNoScroll(GString *args[], int nArgs, + XEvent *event) { + core->gotoNextPage(1, gFalse); +} + +void XPDFViewer::cmdOpen(GString *args[], int nArgs, + XEvent *event) { + mapOpenDialog(gFalse); +} + +void XPDFViewer::cmdOpenFile(GString *args[], int nArgs, + XEvent *event) { + open(args[0], 1, NULL); +} + +void XPDFViewer::cmdOpenFileAtDest(GString *args[], int nArgs, + XEvent *event) { + open(args[0], 1, args[1]); +} + +void XPDFViewer::cmdOpenFileAtDestInNewWin(GString *args[], int nArgs, + XEvent *event) { + app->openAtDest(args[0], args[1]); +} + +void XPDFViewer::cmdOpenFileAtPage(GString *args[], int nArgs, + XEvent *event) { + open(args[0], atoi(args[1]->getCString()), NULL); +} + +void XPDFViewer::cmdOpenFileAtPageInNewWin(GString *args[], int nArgs, + XEvent *event) { + app->open(args[0], atoi(args[1]->getCString())); +} + +void XPDFViewer::cmdOpenFileInNewWin(GString *args[], int nArgs, + XEvent *event) { + app->open(args[0]); +} + +void XPDFViewer::cmdOpenInNewWin(GString *args[], int nArgs, + XEvent *event) { + mapOpenDialog(gTrue); +} + +void XPDFViewer::cmdOpenOutline(GString *args[], int nArgs, + XEvent *event) { +#ifndef DISABLE_OUTLINE + Dimension w; + + if (outlineScroll == None) { + return; + } + XtVaGetValues(outlineScroll, XmNwidth, &w, NULL); + if (w == 1) { + // this ugly kludge is apparently the only way to resize the panes + // within an XmPanedWindow + XtVaSetValues(outlineScroll, XmNpaneMinimum, outlinePaneWidth, + XmNpaneMaximum, outlinePaneWidth, NULL); + XtVaSetValues(outlineScroll, XmNpaneMinimum, 1, + XmNpaneMaximum, 10000, NULL); + } +#endif +} + +void XPDFViewer::cmdPageDown(GString *args[], int nArgs, + XEvent *event) { + core->scrollPageDown(); +} + +void XPDFViewer::cmdPageUp(GString *args[], int nArgs, + XEvent *event) { + core->scrollPageUp(); +} + +void XPDFViewer::cmdPostPopupMenu(GString *args[], int nArgs, + XEvent *event) { + XmMenuPosition(popupMenu, event->type == ButtonPress ? &event->xbutton + : (XButtonEvent *)NULL); + XtManageChild(popupMenu); + + // this is magic (taken from DDD) - weird things happen if this + // call isn't made (this is done in two different places, in hopes + // of squashing this stupid bug) + XtUngrabButton(core->getDrawAreaWidget(), AnyButton, AnyModifier); +} + +void XPDFViewer::cmdPrevPage(GString *args[], int nArgs, + XEvent *event) { + core->gotoPrevPage(1, gTrue, gFalse); +} + +void XPDFViewer::cmdPrevPageNoScroll(GString *args[], int nArgs, + XEvent *event) { + core->gotoPrevPage(1, gFalse, gFalse); +} + +void XPDFViewer::cmdPrint(GString *args[], int nArgs, + XEvent *event) { + XtManageChild(printDialog); +} + +void XPDFViewer::cmdQuit(GString *args[], int nArgs, + XEvent *event) { + app->quit(); +} + +void XPDFViewer::cmdRaise(GString *args[], int nArgs, + XEvent *event) { + XMapRaised(display, XtWindow(win)); + XFlush(display); +} + +void XPDFViewer::cmdRedraw(GString *args[], int nArgs, + XEvent *event) { + displayPage(core->getPageNum(), core->getZoom(), core->getRotate(), + gFalse, gFalse); +} + +void XPDFViewer::cmdReload(GString *args[], int nArgs, + XEvent *event) { + reloadFile(); +} + +void XPDFViewer::cmdRun(GString *args[], int nArgs, + XEvent *event) { + GString *fmt, *cmd, *s; + LinkAction *action; + double selLRX, selLRY, selURX, selURY; + int selPage; + GBool gotSel; + char buf[64]; + char *p; + char c0, c1; + int i; + + cmd = new GString(); + fmt = args[0]; + i = 0; + gotSel = gFalse; + while (i < fmt->getLength()) { + c0 = fmt->getChar(i); + if (c0 == '%' && i+1 < fmt->getLength()) { + c1 = fmt->getChar(i+1); + switch (c1) { + case 'f': + if (core->getDoc() && (s = core->getDoc()->getFileName())) { + cmd->append(s); + } + break; + case 'b': + if (core->getDoc() && (s = core->getDoc()->getFileName())) { + if ((p = strrchr(s->getCString(), '.'))) { + cmd->append(s->getCString(), p - s->getCString()); + } else { + cmd->append(s); + } + } + break; + case 'u': + if ((action = core->getLinkAction()) && + action->getKind() == actionURI) { + s = core->mungeURL(((LinkURI *)action)->getURI()); + cmd->append(s); + delete s; + } + break; + case 'x': + case 'y': + case 'X': + case 'Y': + if (!gotSel) { + if (!core->getSelection(&selPage, &selURX, &selURY, + &selLRX, &selLRY)) { + selPage = 0; + selURX = selURY = selLRX = selLRY = 0; + } + gotSel = gTrue; + } + sprintf(buf, "%g", + (c1 == 'x') ? selURX : + (c1 == 'y') ? selURY : + (c1 == 'X') ? selLRX : selLRY); + cmd->append(buf); + break; + default: + cmd->append(c1); + break; + } + i += 2; + } else { + cmd->append(c0); + ++i; + } + } +#ifdef VMS + cmd->insert(0, "spawn/nowait "); +#elif defined(__EMX__) + cmd->insert(0, "start /min /n "); +#else + cmd->append(" &"); +#endif + system(cmd->getCString()); + delete cmd; +} + +void XPDFViewer::cmdScrollDown(GString *args[], int nArgs, + XEvent *event) { + core->scrollDown(atoi(args[0]->getCString())); +} + +void XPDFViewer::cmdScrollDownNextPage(GString *args[], int nArgs, + XEvent *event) { + core->scrollDownNextPage(atoi(args[0]->getCString())); +} + +void XPDFViewer::cmdScrollLeft(GString *args[], int nArgs, + XEvent *event) { + core->scrollLeft(atoi(args[0]->getCString())); +} + +void XPDFViewer::cmdScrollOutlineDown(GString *args[], int nArgs, + XEvent *event) { +#ifndef DISABLE_OUTLINE + Widget sb; + int val, inc, pageInc, m, slider; + + if (outlineScroll == None) { + return; + } + if ((sb = XtNameToWidget(outlineScroll, "VertScrollBar"))) { + XtVaGetValues(sb, XmNvalue, &val, XmNincrement, &inc, + XmNpageIncrement, &pageInc, XmNmaximum, &m, + XmNsliderSize, &slider, NULL); + if ((val += inc * atoi(args[0]->getCString())) > m - slider) { + val = m - slider; + } + XmScrollBarSetValues(sb, val, slider, inc, pageInc, True); + } +#endif +} + +void XPDFViewer::cmdScrollOutlineUp(GString *args[], int nArgs, + XEvent *event) { +#ifndef DISABLE_OUTLINE + Widget sb; + int val, inc, pageInc, m, slider; + + if (outlineScroll == None) { + return; + } + if ((sb = XtNameToWidget(outlineScroll, "VertScrollBar"))) { + XtVaGetValues(sb, XmNvalue, &val, XmNincrement, &inc, + XmNpageIncrement, &pageInc, XmNminimum, &m, + XmNsliderSize, &slider, NULL); + if ((val -= inc * atoi(args[0]->getCString())) < m) { + val = m; + } + XmScrollBarSetValues(sb, val, slider, inc, pageInc, True); + } +#endif +} + +void XPDFViewer::cmdScrollRight(GString *args[], int nArgs, + XEvent *event) { + core->scrollRight(atoi(args[0]->getCString())); +} + +void XPDFViewer::cmdScrollToBottomEdge(GString *args[], int nArgs, + XEvent *event) { + core->scrollToBottomEdge(); +} + +void XPDFViewer::cmdScrollToBottomRight(GString *args[], int nArgs, + XEvent *event) { + core->scrollToBottomRight(); +} + +void XPDFViewer::cmdScrollToLeftEdge(GString *args[], int nArgs, + XEvent *event) { + core->scrollToLeftEdge(); +} + +void XPDFViewer::cmdScrollToRightEdge(GString *args[], int nArgs, + XEvent *event) { + core->scrollToRightEdge(); +} + +void XPDFViewer::cmdScrollToTopEdge(GString *args[], int nArgs, + XEvent *event) { + core->scrollToTopEdge(); +} + +void XPDFViewer::cmdScrollToTopLeft(GString *args[], int nArgs, + XEvent *event) { + core->scrollToTopLeft(); +} + +void XPDFViewer::cmdScrollUp(GString *args[], int nArgs, + XEvent *event) { + core->scrollUp(atoi(args[0]->getCString())); +} + +void XPDFViewer::cmdScrollUpPrevPage(GString *args[], int nArgs, + XEvent *event) { + core->scrollUpPrevPage(atoi(args[0]->getCString())); +} + +void XPDFViewer::cmdSinglePageMode(GString *args[], int nArgs, + XEvent *event) { + Widget btn; + + if (!core->getContinuousMode()) { + return; + } + core->setContinuousMode(gFalse); + + btn = XtNameToWidget(popupMenu, "continuousMode"); + XtVaSetValues(btn, XmNset, XmUNSET, NULL); +} + +void XPDFViewer::cmdStartPan(GString *args[], int nArgs, + XEvent *event) { + core->startPan(mouseX(event), mouseY(event)); +} + +void XPDFViewer::cmdStartSelection(GString *args[], int nArgs, + XEvent *event) { + core->startSelection(mouseX(event), mouseY(event)); +} + +void XPDFViewer::cmdToggleContinuousMode(GString *args[], int nArgs, + XEvent *event) { + if (core->getContinuousMode()) { + cmdSinglePageMode(NULL, 0, event); + } else { + cmdContinuousMode(NULL, 0, event); + } +} + +void XPDFViewer::cmdToggleFullScreenMode(GString *args[], int nArgs, + XEvent *event) { + if (core->getFullScreen()) { + cmdWindowMode(NULL, 0, event); + } else { + cmdFullScreenMode(NULL, 0, event); + } +} + +void XPDFViewer::cmdToggleOutline(GString *args[], int nArgs, + XEvent *event) { +#ifndef DISABLE_OUTLINE + Dimension w; + + if (outlineScroll == None) { + return; + } + XtVaGetValues(outlineScroll, XmNwidth, &w, NULL); + if (w > 1) { + cmdCloseOutline(NULL, 0, event); + } else { + cmdOpenOutline(NULL, 0, event); + } +#endif +} + +void XPDFViewer::cmdWindowMode(GString *args[], int nArgs, + XEvent *event) { + PDFDoc *doc; + XPDFViewer *viewer; + int pg; + Widget btn; + + if (!core->getFullScreen()) { + return; + } + pg = core->getPageNum(); + XtPopdown(win); + doc = core->takeDoc(gFalse); + viewer = app->reopen(this, doc, pg, gFalse); + + btn = XtNameToWidget(viewer->popupMenu, "fullScreen"); + XtVaSetValues(btn, XmNset, XmUNSET, NULL); +} + +void XPDFViewer::cmdZoomFitPage(GString *args[], int nArgs, + XEvent *event) { + if (core->getZoom() != zoomPage) { + setZoomIdx(zoomPageIdx); + displayPage(core->getPageNum(), zoomPage, + core->getRotate(), gTrue, gFalse); + } +} + +void XPDFViewer::cmdZoomFitWidth(GString *args[], int nArgs, + XEvent *event) { + if (core->getZoom() != zoomWidth) { + setZoomIdx(zoomWidthIdx); + displayPage(core->getPageNum(), zoomWidth, + core->getRotate(), gTrue, gFalse); + } +} + +void XPDFViewer::cmdZoomIn(GString *args[], int nArgs, + XEvent *event) { + int z; + + z = getZoomIdx(); + if (z <= minZoomIdx && z > maxZoomIdx) { + --z; + setZoomIdx(z); + displayPage(core->getPageNum(), zoomMenuInfo[z].zoom, + core->getRotate(), gTrue, gFalse); + } +} + +void XPDFViewer::cmdZoomOut(GString *args[], int nArgs, + XEvent *event) { + int z; + + z = getZoomIdx(); + if (z < minZoomIdx && z >= maxZoomIdx) { + ++z; + setZoomIdx(z); + displayPage(core->getPageNum(), zoomMenuInfo[z].zoom, + core->getRotate(), gTrue, gFalse); + } +} + +void XPDFViewer::cmdZoomPercent(GString *args[], int nArgs, + XEvent *event) { + double z; + + z = atof(args[0]->getCString()); + setZoomVal(z); + displayPage(core->getPageNum(), z, core->getRotate(), gTrue, gFalse); +} + +void XPDFViewer::cmdZoomToSelection(GString *args[], int nArgs, + XEvent *event) { + int pg; + double ulx, uly, lrx, lry; + + if (core->getSelection(&pg, &ulx, &uly, &lrx, &lry)) { + core->zoomToRect(pg, ulx, uly, lrx, lry); + } +} + +//------------------------------------------------------------------------ +// GUI code: main window +//------------------------------------------------------------------------ + +void XPDFViewer::initWindow(GBool fullScreen) { + Colormap colormap; + XColor xcol; + Atom state, val; + Arg args[20]; + int n; + char *title; + + display = XtDisplay(app->getAppShell()); + screenNum = XScreenNumberOfScreen(XtScreen(app->getAppShell())); + + toolBar = None; +#ifndef DISABLE_OUTLINE + outlineScroll = None; +#endif + + // private colormap + if (app->getInstallCmap()) { + XtVaGetValues(app->getAppShell(), XmNcolormap, &colormap, NULL); + // ensure that BlackPixel and WhitePixel are reserved in the + // new colormap + xcol.red = xcol.green = xcol.blue = 0; + XAllocColor(display, colormap, &xcol); + xcol.red = xcol.green = xcol.blue = 65535; + XAllocColor(display, colormap, &xcol); + colormap = XCopyColormapAndFree(display, colormap); + } + + // top-level window + n = 0; + title = app->getTitle() ? app->getTitle()->getCString() + : (char *)xpdfAppName; + XtSetArg(args[n], XmNtitle, title); ++n; + XtSetArg(args[n], XmNiconName, title); ++n; + XtSetArg(args[n], XmNminWidth, 100); ++n; + XtSetArg(args[n], XmNminHeight, 100); ++n; + XtSetArg(args[n], XmNbaseWidth, 0); ++n; + XtSetArg(args[n], XmNbaseHeight, 0); ++n; + XtSetArg(args[n], XmNdeleteResponse, XmDO_NOTHING); ++n; + win = XtCreatePopupShell("win", topLevelShellWidgetClass, + app->getAppShell(), args, n); + if (app->getInstallCmap()) { + XtVaSetValues(win, XmNcolormap, colormap, NULL); + } + XmAddWMProtocolCallback(win, XInternAtom(display, "WM_DELETE_WINDOW", False), + &closeMsgCbk, this); + + // create the full-screen window + if (fullScreen) { + initCore(win, gTrue); + + // create the normal (non-full-screen) window + } else { + if (app->getGeometry()) { + n = 0; + XtSetArg(args[n], XmNgeometry, app->getGeometry()->getCString()); ++n; + XtSetValues(win, args, n); + } + + n = 0; + form = XmCreateForm(win, "form", args, n); + XtManageChild(form); + +#ifdef DISABLE_OUTLINE + initToolbar(form); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetValues(toolBar, args, n); + + initCore(form, gFalse); + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNbottomWidget, toolBar); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetValues(core->getWidget(), args, n); +#else + initToolbar(form); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetValues(toolBar, args, n); + + initPanedWin(form); + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNbottomWidget, toolBar); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetValues(panedWin, args, n); + + initCore(panedWin, fullScreen); + n = 0; + XtSetArg(args[n], XmNpositionIndex, 1); ++n; + XtSetArg(args[n], XmNallowResize, True); ++n; + XtSetArg(args[n], XmNpaneMinimum, 1); ++n; + XtSetArg(args[n], XmNpaneMaximum, 10000); ++n; + XtSetValues(core->getWidget(), args, n); +#endif + } + + // set the zoom menu to match the initial zoom setting + setZoomVal(core->getZoom()); + + // set traversal order + XtVaSetValues(core->getDrawAreaWidget(), + XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, NULL); + if (toolBar != None) { + XtVaSetValues(backBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(prevTenPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(prevPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(nextPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(nextTenPageBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(forwardBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(pageNumText, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(zoomWidget, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(findBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(printBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(aboutBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + XtVaSetValues(quitBtn, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, + NULL); + } + + initPopupMenu(); + + if (fullScreen) { + // Set both the old-style Motif decorations hint and the new-style + // _NET_WM_STATE property. This is redundant, but might be useful + // for older window managers. We also set the geometry to +0+0 to + // avoid interactive placement. (Note: we need to realize the + // shell, so it has a Window on which to set the _NET_WM_STATE + // property, but we don't want to map it until later, so we set + // mappedWhenManaged to false.) + n = 0; + XtSetArg(args[n], XmNmappedWhenManaged, False); ++n; + XtSetArg(args[n], XmNmwmDecorations, 0); ++n; + XtSetArg(args[n], XmNgeometry, "+0+0"); ++n; + XtSetValues(win, args, n); + XtRealizeWidget(win); + state = XInternAtom(display, "_NET_WM_STATE", False); + val = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", False); + XChangeProperty(display, XtWindow(win), state, XA_ATOM, 32, + PropModeReplace, (Guchar *)&val, 1); + } +} + +void XPDFViewer::initToolbar(Widget parent) { + Widget label, lastBtn; +#ifndef USE_COMBO_BOX + Widget btn; +#endif + Arg args[20]; + int n; + XmString s, emptyString; + int i; + + // toolbar + n = 0; + toolBar = XmCreateForm(parent, "toolBar", args, n); + XtManageChild(toolBar); + + // create an empty string -- this is used for buttons that will get + // pixmaps later + emptyString = XmStringCreateLocalized(""); + + // page movement buttons + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 6); ++n; + XtSetArg(args[n], XmNsensitive, False); ++n; + XtSetArg(args[n], XmNlabelString, emptyString); ++n; + backBtn = XmCreatePushButton(toolBar, "back", args, n); + addToolTip(backBtn, "Back"); + XtManageChild(backBtn); + XtAddCallback(backBtn, XmNactivateCallback, + &backCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, backBtn); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 6); ++n; + XtSetArg(args[n], XmNsensitive, False); ++n; + XtSetArg(args[n], XmNlabelString, emptyString); ++n; + prevTenPageBtn = XmCreatePushButton(toolBar, "prevTenPage", args, n); + addToolTip(prevTenPageBtn, "-10 pages"); + XtManageChild(prevTenPageBtn); + XtAddCallback(prevTenPageBtn, XmNactivateCallback, + &prevTenPageCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, prevTenPageBtn); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 6); ++n; + XtSetArg(args[n], XmNsensitive, False); ++n; + XtSetArg(args[n], XmNlabelString, emptyString); ++n; + prevPageBtn = XmCreatePushButton(toolBar, "prevPage", args, n); + addToolTip(prevPageBtn, "Previous page"); + XtManageChild(prevPageBtn); + XtAddCallback(prevPageBtn, XmNactivateCallback, + &prevPageCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, prevPageBtn); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 6); ++n; + XtSetArg(args[n], XmNsensitive, False); ++n; + XtSetArg(args[n], XmNlabelString, emptyString); ++n; + nextPageBtn = XmCreatePushButton(toolBar, "nextPage", args, n); + addToolTip(nextPageBtn, "Next page"); + XtManageChild(nextPageBtn); + XtAddCallback(nextPageBtn, XmNactivateCallback, + &nextPageCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, nextPageBtn); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 6); ++n; + XtSetArg(args[n], XmNsensitive, False); ++n; + XtSetArg(args[n], XmNlabelString, emptyString); ++n; + nextTenPageBtn = XmCreatePushButton(toolBar, "nextTenPage", args, n); + addToolTip(nextTenPageBtn, "+10 pages"); + XtManageChild(nextTenPageBtn); + XtAddCallback(nextTenPageBtn, XmNactivateCallback, + &nextTenPageCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, nextTenPageBtn); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 6); ++n; + XtSetArg(args[n], XmNsensitive, False); ++n; + XtSetArg(args[n], XmNlabelString, emptyString); ++n; + forwardBtn = XmCreatePushButton(toolBar, "forward", args, n); + addToolTip(forwardBtn, "Forward"); + XtManageChild(forwardBtn); + XtAddCallback(forwardBtn, XmNactivateCallback, + &forwardCbk, (XtPointer)this); + + // page number display + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, forwardBtn); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + s = XmStringCreateLocalized("Page "); + XtSetArg(args[n], XmNlabelString, s); ++n; + label = XmCreateLabel(toolBar, "pageLabel", args, n); + XmStringFree(s); + XtManageChild(label); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, label); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 3); ++n; + XtSetArg(args[n], XmNmarginHeight, 3); ++n; + XtSetArg(args[n], XmNcolumns, 5); ++n; + pageNumText = XmCreateTextField(toolBar, "pageNum", args, n); + XtManageChild(pageNumText); + XtAddCallback(pageNumText, XmNactivateCallback, + &pageNumCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, pageNumText); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + s = XmStringCreateLocalized(" of 00000"); + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); ++n; + XtSetArg(args[n], XmNrecomputeSize, False); ++n; + pageCountLabel = XmCreateLabel(toolBar, "pageCountLabel", args, n); + XmStringFree(s); + XtManageChild(pageCountLabel); + s = XmStringCreateLocalized(" of 0"); + XtVaSetValues(pageCountLabel, XmNlabelString, s, NULL); + XmStringFree(s); + + // zoom menu +#if USE_COMBO_BOX + XmString st[nZoomMenuItems]; + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, pageCountLabel); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 0); ++n; + XtSetArg(args[n], XmNmarginHeight, 0); ++n; + XtSetArg(args[n], XmNcomboBoxType, XmDROP_DOWN_COMBO_BOX); ++n; + XtSetArg(args[n], XmNpositionMode, XmONE_BASED); ++n; + XtSetArg(args[n], XmNcolumns, 7); ++n; + for (i = 0; i < nZoomMenuItems; ++i) { + st[i] = XmStringCreateLocalized(zoomMenuInfo[i].label); + } + XtSetArg(args[n], XmNitems, st); ++n; + XtSetArg(args[n], XmNitemCount, nZoomMenuItems); ++n; + zoomComboBox = XmCreateComboBox(toolBar, "zoomComboBox", args, n); + for (i = 0; i < nZoomMenuItems; ++i) { + XmStringFree(st[i]); + } + addToolTip(zoomComboBox, "Zoom"); + XtAddCallback(zoomComboBox, XmNselectionCallback, + &zoomComboBoxCbk, (XtPointer)this); + XtManageChild(zoomComboBox); + zoomWidget = zoomComboBox; +#else + Widget menuPane; + char buf[16]; + n = 0; + menuPane = XmCreatePulldownMenu(toolBar, "zoomMenuPane", args, n); + for (i = 0; i < nZoomMenuItems; ++i) { + n = 0; + s = XmStringCreateLocalized(zoomMenuInfo[i].label); + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNuserData, (XtPointer)i); ++n; + sprintf(buf, "zoom%d", i); + btn = XmCreatePushButton(menuPane, buf, args, n); + XmStringFree(s); + XtManageChild(btn); + XtAddCallback(btn, XmNactivateCallback, + &zoomMenuCbk, (XtPointer)this); + zoomMenuBtns[i] = btn; + } + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, pageCountLabel); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 0); ++n; + XtSetArg(args[n], XmNmarginHeight, 0); ++n; + XtSetArg(args[n], XmNsubMenuId, menuPane); ++n; + zoomMenu = XmCreateOptionMenu(toolBar, "zoomMenu", args, n); + addToolTip(zoomMenu, "Zoom"); + XtManageChild(zoomMenu); + zoomWidget = zoomMenu; +#endif + + // find/print/about buttons + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, zoomWidget); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 6); ++n; + XtSetArg(args[n], XmNlabelString, emptyString); ++n; + findBtn = XmCreatePushButton(toolBar, "find", args, n); + addToolTip(findBtn, "Find"); + XtManageChild(findBtn); + XtAddCallback(findBtn, XmNactivateCallback, + &findCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, findBtn); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 6); ++n; + XtSetArg(args[n], XmNlabelString, emptyString); ++n; + printBtn = XmCreatePushButton(toolBar, "print", args, n); + addToolTip(printBtn, "Print"); + XtManageChild(printBtn); + XtAddCallback(printBtn, XmNactivateCallback, + &printCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, printBtn); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 6); ++n; + XtSetArg(args[n], XmNlabelString, emptyString); ++n; + aboutBtn = XmCreatePushButton(toolBar, "about", args, n); + addToolTip(aboutBtn, "About / help"); + XtManageChild(aboutBtn); + XtAddCallback(aboutBtn, XmNactivateCallback, + &aboutCbk, (XtPointer)this); + lastBtn = aboutBtn; + + // quit button + n = 0; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNmarginWidth, 6); ++n; + s = XmStringCreateLocalized("Quit"); + XtSetArg(args[n], XmNlabelString, s); ++n; + quitBtn = XmCreatePushButton(toolBar, "quit", args, n); + XmStringFree(s); + XtManageChild(quitBtn); + XtAddCallback(quitBtn, XmNactivateCallback, + &quitCbk, (XtPointer)this); + + // link label + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, lastBtn); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNrightWidget, quitBtn); ++n; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + s = XmStringCreateLocalized(""); + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNrecomputeSize, True); ++n; + XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); ++n; + linkLabel = XmCreateLabel(toolBar, "linkLabel", args, n); + XmStringFree(s); + XtManageChild(linkLabel); + + XmStringFree(emptyString); +} + +#ifndef DISABLE_OUTLINE +void XPDFViewer::initPanedWin(Widget parent) { + Widget clipWin; + Arg args[20]; + int n; + + // paned window + n = 0; + XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n; +#if defined(__sgi) && (XmVERSION <= 1) + panedWin = SgCreateHorzPanedWindow(parent, "panedWin", args, n); +#else + panedWin = XmCreatePanedWindow(parent, "panedWin", args, n); +#endif + XtManageChild(panedWin); + + // scrolled window for outline container + n = 0; + XtSetArg(args[n], XmNpositionIndex, 0); ++n; + XtSetArg(args[n], XmNallowResize, True); ++n; + XtSetArg(args[n], XmNpaneMinimum, 1); ++n; + XtSetArg(args[n], XmNpaneMaximum, 10000); ++n; +#if !(defined(__sgi) && (XmVERSION <= 1)) + XtSetArg(args[n], XmNwidth, 1); ++n; +#endif + XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); ++n; + outlineScroll = XmCreateScrolledWindow(panedWin, "outlineScroll", args, n); + XtManageChild(outlineScroll); + XtVaGetValues(outlineScroll, XmNclipWindow, &clipWin, NULL); + XtVaSetValues(clipWin, XmNbackground, app->getPaperPixel(), NULL); + + // outline tree + n = 0; + XtSetArg(args[n], XmNbackground, app->getPaperPixel()); ++n; + outlineTree = XPDFCreateTree(outlineScroll, "outlineTree", args, n); + XtManageChild(outlineTree); + XtAddCallback(outlineTree, XPDFNselectionCallback, &outlineSelectCbk, + (XtPointer)this); +} +#endif + +void XPDFViewer::initCore(Widget parent, GBool fullScreen) { + core = new XPDFCore(win, parent, + app->getPaperRGB(), app->getPaperPixel(), + app->getMattePixel(fullScreen), + fullScreen, app->getReverseVideo(), + app->getInstallCmap(), app->getRGBCubeSize()); + core->setUpdateCbk(&updateCbk, this); + core->setActionCbk(&actionCbk, this); + core->setKeyPressCbk(&keyPressCbk, this); + core->setMouseCbk(&mouseCbk, this); +} + +void XPDFViewer::initPopupMenu() { + Widget btn; + Arg args[20]; + int n; + XmString s, s2; + + n = 0; +#if XmVersion < 1002 + // older versions of Motif need this, newer ones choke on it, + // sometimes not displaying the menu at all, maybe depending on the + // state of the NumLock key (taken from DDD) + XtSetArg(args[n], XmNmenuPost, ""); ++n; +#endif + popupMenu = XmCreatePopupMenu(core->getDrawAreaWidget(), "popupMenu", + args, n); + n = 0; + s = XmStringCreateLocalized("Open..."); + XtSetArg(args[n], XmNlabelString, s); ++n; + s2 = XmStringCreateLocalized("O"); + XtSetArg(args[n], XmNacceleratorText, s2); ++n; + btn = XmCreatePushButton(popupMenu, "open", args, n); + XmStringFree(s); + XmStringFree(s2); + XtManageChild(btn); + XtAddCallback(btn, XmNactivateCallback, + &openCbk, (XtPointer)this); + n = 0; + s = XmStringCreateLocalized("Open in new window..."); + XtSetArg(args[n], XmNlabelString, s); ++n; + btn = XmCreatePushButton(popupMenu, "openInNewWindow", args, n); + XmStringFree(s); + XtManageChild(btn); + XtAddCallback(btn, XmNactivateCallback, + &openInNewWindowCbk, (XtPointer)this); + n = 0; + s = XmStringCreateLocalized("Reload"); + XtSetArg(args[n], XmNlabelString, s); ++n; + s2 = XmStringCreateLocalized("R"); + XtSetArg(args[n], XmNacceleratorText, s2); ++n; + btn = XmCreatePushButton(popupMenu, "reload", args, n); + XmStringFree(s); + XmStringFree(s2); + XtManageChild(btn); + XtAddCallback(btn, XmNactivateCallback, + &reloadCbk, (XtPointer)this); + n = 0; + s = XmStringCreateLocalized("Save as..."); + XtSetArg(args[n], XmNlabelString, s); ++n; + btn = XmCreatePushButton(popupMenu, "saveAs", args, n); + XmStringFree(s); + XtManageChild(btn); + XtAddCallback(btn, XmNactivateCallback, + &saveAsCbk, (XtPointer)this); + n = 0; + btn = XmCreateSeparator(popupMenu, "sep1", args, n); + XtManageChild(btn); + n = 0; + s = XmStringCreateLocalized("Continuous view"); + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNindicatorType, XmN_OF_MANY); ++n; + XtSetArg(args[n], XmNvisibleWhenOff, True); ++n; + XtSetArg(args[n], XmNset, core->getContinuousMode() ? XmSET : XmUNSET); ++n; + btn = XmCreateToggleButton(popupMenu, "continuousMode", args, n); + XmStringFree(s); + XtManageChild(btn); + XtAddCallback(btn, XmNvalueChangedCallback, + &continuousModeToggleCbk, (XtPointer)this); + n = 0; + s = XmStringCreateLocalized("Full screen"); + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNindicatorType, XmN_OF_MANY); ++n; + XtSetArg(args[n], XmNvisibleWhenOff, True); ++n; + XtSetArg(args[n], XmNset, core->getFullScreen() ? XmSET : XmUNSET); ++n; + btn = XmCreateToggleButton(popupMenu, "fullScreen", args, n); + XmStringFree(s); + XtManageChild(btn); + XtAddCallback(btn, XmNvalueChangedCallback, + &fullScreenToggleCbk, (XtPointer)this); + n = 0; + s = XmStringCreateLocalized("Rotate counterclockwise"); + XtSetArg(args[n], XmNlabelString, s); ++n; + btn = XmCreatePushButton(popupMenu, "rotateCCW", args, n); + XmStringFree(s); + XtManageChild(btn); + XtAddCallback(btn, XmNactivateCallback, + &rotateCCWCbk, (XtPointer)this); + n = 0; + s = XmStringCreateLocalized("Rotate clockwise"); + XtSetArg(args[n], XmNlabelString, s); ++n; + btn = XmCreatePushButton(popupMenu, "rotateCW", args, n); + XmStringFree(s); + XtManageChild(btn); + XtAddCallback(btn, XmNactivateCallback, + &rotateCWCbk, (XtPointer)this); + n = 0; + s = XmStringCreateLocalized("Zoom to selection"); + XtSetArg(args[n], XmNlabelString, s); ++n; + btn = XmCreatePushButton(popupMenu, "zoomToSelection", args, n); + XmStringFree(s); + XtManageChild(btn); + XtAddCallback(btn, XmNactivateCallback, + &zoomToSelectionCbk, (XtPointer)this); + n = 0; + btn = XmCreateSeparator(popupMenu, "sep2", args, n); + XtManageChild(btn); + n = 0; + s = XmStringCreateLocalized("Close"); + XtSetArg(args[n], XmNlabelString, s); ++n; + s2 = XmStringCreateLocalized("Ctrl+W"); + XtSetArg(args[n], XmNacceleratorText, s2); ++n; + btn = XmCreatePushButton(popupMenu, "close", args, n); + XmStringFree(s); + XmStringFree(s2); + XtManageChild(btn); + XtAddCallback(btn, XmNactivateCallback, + &closeCbk, (XtPointer)this); + n = 0; + s = XmStringCreateLocalized("Quit"); + XtSetArg(args[n], XmNlabelString, s); ++n; + s2 = XmStringCreateLocalized("Q"); + XtSetArg(args[n], XmNacceleratorText, s2); ++n; + btn = XmCreatePushButton(popupMenu, "quit", args, n); + XmStringFree(s); + XmStringFree(s2); + XtManageChild(btn); + XtAddCallback(btn, XmNactivateCallback, + &quitCbk, (XtPointer)this); + + // this is magic (taken from DDD) - weird things happen if this + // call isn't made + XtUngrabButton(core->getDrawAreaWidget(), AnyButton, AnyModifier); +} + +void XPDFViewer::addToolTip(Widget widget, char *text) { +#ifdef XmNtoolTipString + XmString s; + Cardinal n, i; + WidgetList children; + + if (XtIsComposite(widget)) { + XtVaGetValues(widget, XmNnumChildren, &n, XmNchildren, &children, NULL); + for (i = 0; i < n; ++i) { + addToolTip(children[i], text); + } + } else { + s = XmStringCreateLocalized(text); + XtVaSetValues(widget, XmNtoolTipString, s, NULL); + XmStringFree(s); + } +#endif +} + +void XPDFViewer::mapWindow() { +#ifdef HAVE_X11_XPM_H + Pixmap iconPixmap; +#endif + int depth; + Pixel fg, bg, arm; + + // show the window + XtPopup(win, XtGrabNone); + core->takeFocus(); + + // create the icon +#ifdef HAVE_X11_XPM_H + if (XpmCreatePixmapFromData(display, XtWindow(win), xpdfIcon, + &iconPixmap, NULL, NULL) == XpmSuccess) { + XtVaSetValues(win, XmNiconPixmap, iconPixmap, NULL); + } +#endif + + // set button bitmaps (must be done after the window is mapped) + if (toolBar != None) { + XtVaGetValues(backBtn, XmNdepth, &depth, + XmNforeground, &fg, XmNbackground, &bg, + XmNarmColor, &arm, NULL); + XtVaSetValues(backBtn, XmNlabelType, XmPIXMAP, + XmNlabelPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)backArrow_bits, + backArrow_width, + backArrow_height, + fg, bg, depth), + XmNarmPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)backArrow_bits, + backArrow_width, + backArrow_height, + fg, arm, depth), + XmNlabelInsensitivePixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)backArrowDis_bits, + backArrowDis_width, + backArrowDis_height, + fg, bg, depth), + NULL); + XtVaSetValues(prevTenPageBtn, XmNlabelType, XmPIXMAP, + XmNlabelPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)dblLeftArrow_bits, + dblLeftArrow_width, + dblLeftArrow_height, + fg, bg, depth), + XmNarmPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)dblLeftArrow_bits, + dblLeftArrow_width, + dblLeftArrow_height, + fg, arm, depth), + XmNlabelInsensitivePixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)dblLeftArrowDis_bits, + dblLeftArrowDis_width, + dblLeftArrowDis_height, + fg, bg, depth), + NULL); + XtVaSetValues(prevPageBtn, XmNlabelType, XmPIXMAP, + XmNlabelPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)leftArrow_bits, + leftArrow_width, + leftArrow_height, + fg, bg, depth), + XmNarmPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)leftArrow_bits, + leftArrow_width, + leftArrow_height, + fg, arm, depth), + XmNlabelInsensitivePixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)leftArrowDis_bits, + leftArrowDis_width, + leftArrowDis_height, + fg, bg, depth), + NULL); + XtVaSetValues(nextPageBtn, XmNlabelType, XmPIXMAP, + XmNlabelPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)rightArrow_bits, + rightArrow_width, + rightArrow_height, + fg, bg, depth), + XmNarmPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)rightArrow_bits, + rightArrow_width, + rightArrow_height, + fg, arm, depth), + XmNlabelInsensitivePixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)rightArrowDis_bits, + rightArrowDis_width, + rightArrowDis_height, + fg, bg, depth), + NULL); + XtVaSetValues(nextTenPageBtn, XmNlabelType, XmPIXMAP, + XmNlabelPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)dblRightArrow_bits, + dblRightArrow_width, + dblRightArrow_height, + fg, bg, depth), + XmNarmPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)dblRightArrow_bits, + dblRightArrow_width, + dblRightArrow_height, + fg, arm, depth), + XmNlabelInsensitivePixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)dblRightArrowDis_bits, + dblRightArrowDis_width, + dblRightArrowDis_height, + fg, bg, depth), + NULL); + XtVaSetValues(forwardBtn, XmNlabelType, XmPIXMAP, + XmNlabelPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)forwardArrow_bits, + forwardArrow_width, + forwardArrow_height, + fg, bg, depth), + XmNarmPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)forwardArrow_bits, + forwardArrow_width, + forwardArrow_height, + fg, arm, depth), + XmNlabelInsensitivePixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)forwardArrowDis_bits, + forwardArrowDis_width, + forwardArrowDis_height, + fg, bg, depth), + NULL); + XtVaSetValues(findBtn, XmNlabelType, XmPIXMAP, + XmNlabelPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)find_bits, + find_width, + find_height, + fg, bg, depth), + XmNarmPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)find_bits, + find_width, + find_height, + fg, arm, depth), + XmNlabelInsensitivePixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)findDis_bits, + findDis_width, + findDis_height, + fg, bg, depth), + NULL); + XtVaSetValues(printBtn, XmNlabelType, XmPIXMAP, + XmNlabelPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)print_bits, + print_width, + print_height, + fg, bg, depth), + XmNarmPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)print_bits, + print_width, + print_height, + fg, arm, depth), + XmNlabelInsensitivePixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)printDis_bits, + printDis_width, + printDis_height, + fg, bg, depth), + NULL); + XtVaSetValues(aboutBtn, XmNlabelType, XmPIXMAP, + XmNlabelPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)about_bits, + about_width, + about_height, + fg, bg, depth), + XmNarmPixmap, + XCreatePixmapFromBitmapData(display, XtWindow(toolBar), + (char *)about_bits, + about_width, + about_height, + fg, arm, depth), + NULL); + } +} + +void XPDFViewer::closeWindow() { + XtPopdown(win); + XtDestroyWidget(win); +} + +int XPDFViewer::getZoomIdx() { + int i; + + for (i = 0; i < nZoomMenuItems; ++i) { + if (core->getZoom() == zoomMenuInfo[i].zoom) { + return i; + } + } + return -1; +} + +void XPDFViewer::setZoomIdx(int idx) { + if (toolBar == None) { + return; + } +#if USE_COMBO_BOX + XtVaSetValues(zoomComboBox, XmNselectedPosition, idx + 1, NULL); +#else + XtVaSetValues(zoomMenu, XmNmenuHistory, zoomMenuBtns[idx], NULL); +#endif +} + +void XPDFViewer::setZoomVal(double z) { + if (toolBar == None) { + return; + } + +#if USE_COMBO_BOX + char buf[32]; + XmString s; + int i; + + for (i = 0; i < nZoomMenuItems; ++i) { + if (z == zoomMenuInfo[i].zoom) { + XtVaSetValues(zoomComboBox, XmNselectedPosition, i + 1, NULL); + return; + } + } + sprintf(buf, "%d%%", (int)z); + s = XmStringCreateLocalized(buf); + XtVaSetValues(zoomComboBox, XmNselectedItem, s, NULL); + XmStringFree(s); +#else + int i; + + for (i = 0; i < nZoomMenuItems; ++i) { + if (z == zoomMenuInfo[i].zoom) { + XtVaSetValues(zoomMenu, XmNmenuHistory, zoomMenuBtns[i], NULL); + return; + } + } + for (i = maxZoomIdx; i < minZoomIdx; ++i) { + if (z > zoomMenuInfo[i].zoom) { + break; + } + } + XtVaSetValues(zoomMenu, XmNmenuHistory, zoomMenuBtns[i], NULL); +#endif +} + +void XPDFViewer::prevPageCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->core->gotoPrevPage(1, gTrue, gFalse); + viewer->core->takeFocus(); +} + +void XPDFViewer::prevTenPageCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->core->gotoPrevPage(10, gTrue, gFalse); + viewer->core->takeFocus(); +} + +void XPDFViewer::nextPageCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->core->gotoNextPage(1, gTrue); + viewer->core->takeFocus(); +} + +void XPDFViewer::nextTenPageCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->core->gotoNextPage(10, gTrue); + viewer->core->takeFocus(); +} + +void XPDFViewer::backCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->core->goBackward(); + viewer->core->takeFocus(); +} + +void XPDFViewer::forwardCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->core->goForward(); + viewer->core->takeFocus(); +} + +#if USE_COMBO_BOX + +void XPDFViewer::zoomComboBoxCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + XmComboBoxCallbackStruct *data = (XmComboBoxCallbackStruct *)callData; + double z; + char *s; + XmStringContext context; + XmStringCharSet charSet; + XmStringDirection dir; + Boolean sep; + + z = viewer->core->getZoom(); + if (data->item_position == 0) { + XmStringInitContext(&context, data->item_or_text); + if (XmStringGetNextSegment(context, &s, &charSet, &dir, &sep)) { + z = atof(s); + if (z <= 1) { + z = defZoom; + } + XtFree(charSet); + XtFree(s); + } + XmStringFreeContext(context); + } else { + z = zoomMenuInfo[data->item_position - 1].zoom; + } + // only redraw if this was triggered by an event; otherwise + // the caller is responsible for doing the redraw + if (z != viewer->core->getZoom() && data->event) { + viewer->displayPage(viewer->core->getPageNum(), z, + viewer->core->getRotate(), gTrue, gFalse); + } + viewer->core->takeFocus(); +} + +#else // USE_COMBO_BOX + +void XPDFViewer::zoomMenuCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + XmPushButtonCallbackStruct *data = (XmPushButtonCallbackStruct *)callData; + XtPointer userData; + double z; + + XtVaGetValues(widget, XmNuserData, &userData, NULL); + z = zoomMenuInfo[(long)userData].zoom; + // only redraw if this was triggered by an event; otherwise + // the caller is responsible for doing the redraw + if (z != viewer->core->getZoom() && data->event) { + viewer->displayPage(viewer->core->getPageNum(), z, + viewer->core->getRotate(), gTrue, gFalse); + } + viewer->core->takeFocus(); +} + +#endif // USE_COMBO_BOX + +void XPDFViewer::findCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + if (!viewer->core->getDoc()) { + return; + } + viewer->mapFindDialog(); +} + +void XPDFViewer::printCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + if (!viewer->core->getDoc()) { + return; + } + XtManageChild(viewer->printDialog); +} + +void XPDFViewer::aboutCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + XtManageChild(viewer->aboutDialog); +} + +void XPDFViewer::quitCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->app->quit(); +} + +void XPDFViewer::openCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->mapOpenDialog(gFalse); +} + +void XPDFViewer::openInNewWindowCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->mapOpenDialog(gTrue); +} + +void XPDFViewer::reloadCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->reloadFile(); +} + +void XPDFViewer::saveAsCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + if (!viewer->core->getDoc()) { + return; + } + viewer->mapSaveAsDialog(); +} + +void XPDFViewer::continuousModeToggleCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + XmToggleButtonCallbackStruct *data = + (XmToggleButtonCallbackStruct *)callData; + + viewer->core->setContinuousMode(data->set == XmSET); +} + +void XPDFViewer::fullScreenToggleCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + XmToggleButtonCallbackStruct *data = + (XmToggleButtonCallbackStruct *)callData; + + if (data->set == XmSET) { + viewer->cmdFullScreenMode(NULL, 0, NULL); + } else { + viewer->cmdWindowMode(NULL, 0, NULL); + } +} + +void XPDFViewer::rotateCCWCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + int r; + + r = viewer->core->getRotate(); + r = (r == 0) ? 270 : r - 90; + viewer->displayPage(viewer->core->getPageNum(), viewer->core->getZoom(), + r, gTrue, gFalse); +} + +void XPDFViewer::rotateCWCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + int r; + + r = viewer->core->getRotate(); + r = (r == 270) ? 0 : r + 90; + viewer->displayPage(viewer->core->getPageNum(), viewer->core->getZoom(), + r, gTrue, gFalse); +} + +void XPDFViewer::zoomToSelectionCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + int pg; + double ulx, uly, lrx, lry; + + if (viewer->core->getSelection(&pg, &ulx, &uly, &lrx, &lry)) { + viewer->core->zoomToRect(pg, ulx, uly, lrx, lry); + } +} + +void XPDFViewer::closeCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->app->close(viewer, gFalse); +} + +void XPDFViewer::closeMsgCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->app->close(viewer, gTrue); +} + +void XPDFViewer::pageNumCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + char *s, *p; + int pg; + char buf[20]; + + if (!viewer->core->getDoc()) { + goto err; + } + s = XmTextFieldGetString(viewer->pageNumText); + for (p = s; *p; ++p) { + if (!isdigit(*p)) { + goto err; + } + } + pg = atoi(s); + if (pg < 1 || pg > viewer->core->getDoc()->getNumPages()) { + goto err; + } + viewer->displayPage(pg, viewer->core->getZoom(), + viewer->core->getRotate(), gFalse, gTrue); + viewer->core->takeFocus(); + return; + + err: + XBell(viewer->display, 0); + sprintf(buf, "%d", viewer->core->getPageNum()); + XmTextFieldSetString(viewer->pageNumText, buf); +} + +void XPDFViewer::updateCbk(void *data, GString *fileName, + int pageNum, int numPages, char *linkString) { + XPDFViewer *viewer = (XPDFViewer *)data; + GString *title; + char buf[20]; + XmString s; + + if (fileName) { + if (!(title = viewer->app->getTitle())) { + title = (new GString(xpdfAppName))->append(": ")->append(fileName); + } + XtVaSetValues(viewer->win, XmNtitle, title->getCString(), + XmNiconName, title->getCString(), NULL); + if (!viewer->app->getTitle()) { + delete title; + } +#ifndef DISABLE_OUTLINE + viewer->setupOutline(); +#endif + viewer->setupPrintDialog(); + } + + if (viewer->toolBar != None) { + if (pageNum >= 0) { + s = XmStringCreateLocalized(""); + XtVaSetValues(viewer->linkLabel, XmNlabelString, s, NULL); + XmStringFree(s); + sprintf(buf, "%d", pageNum); + XmTextFieldSetString(viewer->pageNumText, buf); + XtVaSetValues(viewer->prevTenPageBtn, XmNsensitive, + pageNum > 1, NULL); + XtVaSetValues(viewer->prevPageBtn, XmNsensitive, + pageNum > 1, NULL); + XtVaSetValues(viewer->nextTenPageBtn, XmNsensitive, + pageNum < viewer->core->getDoc()->getNumPages(), NULL); + XtVaSetValues(viewer->nextPageBtn, XmNsensitive, + pageNum < viewer->core->getDoc()->getNumPages(), NULL); + XtVaSetValues(viewer->backBtn, XmNsensitive, + viewer->core->canGoBack(), NULL); + XtVaSetValues(viewer->forwardBtn, XmNsensitive, + viewer->core->canGoForward(), NULL); + } + + if (numPages >= 0) { + sprintf(buf, " of %d", numPages); + s = XmStringCreateLocalized(buf); + XtVaSetValues(viewer->pageCountLabel, XmNlabelString, s, NULL); + XmStringFree(s); + } + + if (linkString) { + s = XmStringCreateLocalized(linkString); + XtVaSetValues(viewer->linkLabel, XmNlabelString, s, NULL); + XmStringFree(s); + } + } +} + + +//------------------------------------------------------------------------ +// GUI code: outline +//------------------------------------------------------------------------ + +#ifndef DISABLE_OUTLINE + +void XPDFViewer::setupOutline() { + GList *items; + UnicodeMap *uMap; + GString *enc; + int i; + + if (outlineScroll == None) { + return; + } + + // unmanage and destroy the old labels + if (outlineLabels) { + XtUnmanageChildren(outlineLabels, outlineLabelsLength); + for (i = 0; i < outlineLabelsLength; ++i) { + XtDestroyWidget(outlineLabels[i]); + } + gfree(outlineLabels); + outlineLabels = NULL; + outlineLabelsLength = outlineLabelsSize = 0; + } + + if (core->getDoc()) { + + // create the new labels + items = core->getDoc()->getOutline()->getItems(); + if (items && items->getLength() > 0) { + enc = new GString("Latin1"); + uMap = globalParams->getUnicodeMap(enc); + delete enc; + setupOutlineItems(items, NULL, uMap); + uMap->decRefCnt(); + } + + // manage the new labels + XtManageChildren(outlineLabels, outlineLabelsLength); + } +} + +void XPDFViewer::setupOutlineItems(GList *items, Widget parent, + UnicodeMap *uMap) { + OutlineItem *item; + GList *kids; + Widget label; + Arg args[20]; + GString *title; + char buf[8]; + XmString s; + int i, j, n; + + for (i = 0; i < items->getLength(); ++i) { + item = (OutlineItem *)items->get(i); + title = new GString(); + for (j = 0; j < item->getTitleLength(); ++j) { + n = uMap->mapUnicode(item->getTitle()[j], buf, sizeof(buf)); + title->append(buf, n); + } + n = 0; + XtSetArg(args[n], XPDFNentryPosition, i); ++n; + if (parent) { + XtSetArg(args[n], XPDFNentryParent, parent); ++n; + } + XtSetArg(args[n], XPDFNentryExpanded, item->isOpen()); ++n; + s = XmStringCreateLocalized(title->getCString()); + delete title; + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNuserData, item); ++n; + XtSetArg(args[n], XmNmarginWidth, 0); ++n; + XtSetArg(args[n], XmNmarginHeight, 2); ++n; + XtSetArg(args[n], XmNshadowThickness, 0); ++n; + XtSetArg(args[n], XmNforeground, + app->getReverseVideo() ? WhitePixel(display, screenNum) + : BlackPixel(display, screenNum)); ++n; + XtSetArg(args[n], XmNbackground, app->getPaperPixel()); ++n; + label = XmCreateLabelGadget(outlineTree, "label", args, n); + XmStringFree(s); + if (outlineLabelsLength == outlineLabelsSize) { + outlineLabelsSize += 64; + outlineLabels = (Widget *)greallocn(outlineLabels, + outlineLabelsSize, sizeof(Widget *)); + } + outlineLabels[outlineLabelsLength++] = label; + item->open(); + if ((kids = item->getKids())) { + setupOutlineItems(kids, label, uMap); + } + } +} + +void XPDFViewer::outlineSelectCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + XPDFTreeSelectCallbackStruct *data = + (XPDFTreeSelectCallbackStruct *)callData; + OutlineItem *item; + + XtVaGetValues(data->selectedItem, XmNuserData, &item, NULL); + if (item) { + if (item->getAction()) { + viewer->core->doAction(item->getAction()); + } + } + viewer->core->takeFocus(); +} + +#endif // !DISABLE_OUTLINE + +//------------------------------------------------------------------------ +// GUI code: "about" dialog +//------------------------------------------------------------------------ + +void XPDFViewer::initAboutDialog() { + Widget scrolledWin, col, label, sep, closeBtn; + Arg args[20]; + int n, i; + XmString s; + char buf[20]; + + //----- dialog + n = 0; + s = XmStringCreateLocalized(xpdfAppName ": About"); + XtSetArg(args[n], XmNdialogTitle, s); ++n; + XtSetArg(args[n], XmNwidth, 450); ++n; + XtSetArg(args[n], XmNheight, 300); ++n; + aboutDialog = XmCreateFormDialog(win, "aboutDialog", args, n); + XmStringFree(s); + + //----- "close" button + n = 0; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightOffset, 4); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomOffset, 4); ++n; + closeBtn = XmCreatePushButton(aboutDialog, "Close", args, n); + XtManageChild(closeBtn); + n = 0; + XtSetArg(args[n], XmNdefaultButton, closeBtn); ++n; + XtSetArg(args[n], XmNcancelButton, closeBtn); ++n; + XtSetValues(aboutDialog, args, n); + + //----- scrolled window and RowColumn + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNbottomWidget, closeBtn); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); ++n; + scrolledWin = XmCreateScrolledWindow(aboutDialog, "scrolledWin", args, n); + XtManageChild(scrolledWin); + n = 0; + XtSetArg(args[n], XmNorientation, XmVERTICAL); ++n; + XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); ++n; + col = XmCreateRowColumn(scrolledWin, "col", args, n); + XtManageChild(col); + + //----- fonts + aboutBigFont = + createFontList("-*-times-bold-i-normal--20-*-*-*-*-*-iso8859-1"); + aboutVersionFont = + createFontList("-*-times-medium-r-normal--16-*-*-*-*-*-iso8859-1"); + aboutFixedFont = + createFontList("-*-courier-medium-r-normal--12-*-*-*-*-*-iso8859-1"); + + //----- heading + n = 0; + s = XmStringCreateLocalized("Xpdf"); + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNfontList, aboutBigFont); ++n; + label = XmCreateLabel(col, "h0", args, n); + XmStringFree(s); + XtManageChild(label); + n = 0; + s = XmStringCreateLocalized("Version " xpdfVersion); + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n; + label = XmCreateLabel(col, "h1", args, n); + XmStringFree(s); + XtManageChild(label); + n = 0; + s = XmStringCreateLocalized(xpdfCopyright); + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n; + label = XmCreateLabel(col, "h2", args, n); + XmStringFree(s); + XtManageChild(label); + n = 0; + s = XmStringCreateLocalized(" "); + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n; + label = XmCreateLabel(col, "h3", args, n); + XmStringFree(s); + XtManageChild(label); + n = 0; + XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n; + sep = XmCreateSeparator(col, "sep", args, n); + XtManageChild(sep); + n = 0; + s = XmStringCreateLocalized(" "); + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNfontList, aboutVersionFont); ++n; + label = XmCreateLabel(col, "h4", args, n); + XmStringFree(s); + XtManageChild(label); + n = 0; + + //----- text + for (i = 0; aboutWinText[i]; ++i) { + n = 0; + s = XmStringCreateLocalized(aboutWinText[i]); + XtSetArg(args[n], XmNlabelString, s); ++n; + XtSetArg(args[n], XmNfontList, aboutFixedFont); ++n; + sprintf(buf, "t%d", i); + label = XmCreateLabel(col, buf, args, n); + XtManageChild(label); + XmStringFree(s); + } +} + +//------------------------------------------------------------------------ +// GUI code: "open" dialog +//------------------------------------------------------------------------ + +void XPDFViewer::initOpenDialog() { + Arg args[20]; + int n; + XmString s1, s2, s3; + GString *dir; + + n = 0; + s1 = XmStringCreateLocalized("Open"); + XtSetArg(args[n], XmNokLabelString, s1); ++n; + s2 = XmStringCreateLocalized("*.[Pp][Dd][Ff]"); + XtSetArg(args[n], XmNpattern, s2); ++n; + s3 = XmStringCreateLocalized(xpdfAppName ": Open"); + XtSetArg(args[n], XmNdialogTitle, s3); ++n; + XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n; + XtSetArg(args[n], XmNautoUnmanage, True); ++n; + openDialog = XmCreateFileSelectionDialog(win, "openDialog", args, n); + XmStringFree(s1); + XmStringFree(s2); + XmStringFree(s3); + XtUnmanageChild(XmFileSelectionBoxGetChild(openDialog, + XmDIALOG_HELP_BUTTON)); + XtAddCallback(openDialog, XmNokCallback, + &openOkCbk, (XtPointer)this); + + if (core->getDoc() && core->getDoc()->getFileName()) { + dir = makePathAbsolute(grabPath( + core->getDoc()->getFileName()->getCString())); + s1 = XmStringCreateLocalized(dir->getCString()); + XtVaSetValues(openDialog, XmNdirectory, s1, NULL); + XmStringFree(s1); + delete dir; + } +} + +void XPDFViewer::mapOpenDialog(GBool openInNewWindowA) { + if (!openDialog) { + initOpenDialog(); + } + openInNewWindow = openInNewWindowA; + XmFileSelectionDoSearch(openDialog, NULL); + XtManageChild(openDialog); +} + +void XPDFViewer::openOkCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + XmFileSelectionBoxCallbackStruct *data = + (XmFileSelectionBoxCallbackStruct *)callData; + char *fileName; + XmStringContext context; + XmStringCharSet charSet; + XmStringDirection dir; + Boolean sep; + GString *fileNameStr; + + XmStringInitContext(&context, data->value); + if (XmStringGetNextSegment(context, &fileName, &charSet, &dir, &sep)) { + fileNameStr = new GString(fileName); + if (viewer->openInNewWindow) { + viewer->app->open(fileNameStr); + } else { + if (viewer->loadFile(fileNameStr)) { + viewer->displayPage(1, viewer->core->getZoom(), + viewer->core->getRotate(), gTrue, gTrue); + } + } + delete fileNameStr; + XtFree(charSet); + XtFree(fileName); + } + XmStringFreeContext(context); +} + +//------------------------------------------------------------------------ +// GUI code: "find" dialog +//------------------------------------------------------------------------ + +void XPDFViewer::initFindDialog() { + Widget form1, label, okBtn, closeBtn; + Arg args[20]; + int n; + XmString s; + + //----- dialog + n = 0; + s = XmStringCreateLocalized(xpdfAppName ": Find"); + XtSetArg(args[n], XmNdialogTitle, s); ++n; + XtSetArg(args[n], XmNnavigationType, XmNONE); ++n; + XtSetArg(args[n], XmNautoUnmanage, False); ++n; + findDialog = XmCreateFormDialog(win, "findDialog", args, n); + XmStringFree(s); + + //----- "find" and "close" buttons + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 4); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomOffset, 4); ++n; + XtSetArg(args[n], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP); ++n; + okBtn = XmCreatePushButton(findDialog, "Find", args, n); + XtManageChild(okBtn); + XtAddCallback(okBtn, XmNactivateCallback, + &findFindCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightOffset, 4); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomOffset, 4); ++n; + XtSetArg(args[n], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP); ++n; + closeBtn = XmCreatePushButton(findDialog, "Close", args, n); + XtManageChild(closeBtn); + XtAddCallback(closeBtn, XmNactivateCallback, + &findCloseCbk, (XtPointer)this); + + //----- checkboxes + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 4); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNbottomWidget, okBtn); ++n; + XtSetArg(args[n], XmNindicatorType, XmN_OF_MANY); ++n; +#if XmVERSION <= 1 + XtSetArg(args[n], XmNindicatorOn, True); ++n; +#else + XtSetArg(args[n], XmNindicatorOn, XmINDICATOR_FILL); ++n; +#endif + XtSetArg(args[n], XmNset, XmUNSET); ++n; + s = XmStringCreateLocalized("Search backward"); + XtSetArg(args[n], XmNlabelString, s); ++n; + findBackwardToggle = XmCreateToggleButton(findDialog, "backward", args, n); + XmStringFree(s); + XtManageChild(findBackwardToggle); + n = 0; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, findBackwardToggle); ++n; + XtSetArg(args[n], XmNleftOffset, 16); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightOffset, 4); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNbottomWidget, okBtn); ++n; + XtSetArg(args[n], XmNindicatorType, XmN_OF_MANY); ++n; +#if XmVERSION <= 1 + XtSetArg(args[n], XmNindicatorOn, True); ++n; +#else + XtSetArg(args[n], XmNindicatorOn, XmINDICATOR_FILL); ++n; +#endif + XtSetArg(args[n], XmNset, XmUNSET); ++n; + s = XmStringCreateLocalized("Match case"); + XtSetArg(args[n], XmNlabelString, s); ++n; + findCaseSensitiveToggle = + XmCreateToggleButton(findDialog, "matchCase", args, n); + XmStringFree(s); + XtManageChild(findCaseSensitiveToggle); + + //----- search string entry + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNtopOffset, 4); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNbottomWidget, findBackwardToggle); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 2); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightOffset, 2); ++n; + form1 = XmCreateForm(findDialog, "form", args, n); + XtManageChild(form1); + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + s = XmStringCreateLocalized("Find text: "); + XtSetArg(args[n], XmNlabelString, s); ++n; + label = XmCreateLabel(form1, "label", args, n); + XmStringFree(s); + XtManageChild(label); + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNleftWidget, label); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + findText = XmCreateTextField(form1, "text", args, n); + XtManageChild(findText); +#ifdef LESSTIF_VERSION + XtAddCallback(findText, XmNactivateCallback, + &findFindCbk, (XtPointer)this); +#endif + + //----- dialog parameters + n = 0; + XtSetArg(args[n], XmNdefaultButton, okBtn); ++n; + XtSetArg(args[n], XmNcancelButton, closeBtn); ++n; +#if XmVersion > 1001 + XtSetArg(args[n], XmNinitialFocus, findText); ++n; +#endif + XtSetValues(findDialog, args, n); +} + +void XPDFViewer::findFindCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + viewer->doFind(gFalse); +} + +void XPDFViewer::mapFindDialog() { + XmTextFieldSetSelection(findText, 0, XmTextFieldGetLastPosition(findText), + XtLastTimestampProcessed(display)); + XmTextFieldSetInsertionPosition(findText, 0); + XtManageChild(findDialog); +} + +void XPDFViewer::doFind(GBool next) { + if (XtWindow(findDialog)) { + XDefineCursor(display, XtWindow(findDialog), core->getBusyCursor()); + } + core->find(XmTextFieldGetString(findText), + XmToggleButtonGetState(findCaseSensitiveToggle), + next, + XmToggleButtonGetState(findBackwardToggle), + gFalse); + if (XtWindow(findDialog)) { + XUndefineCursor(display, XtWindow(findDialog)); + } +} + +void XPDFViewer::findCloseCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + + XtUnmanageChild(viewer->findDialog); +} + +//------------------------------------------------------------------------ +// GUI code: "save as" dialog +//------------------------------------------------------------------------ + +void XPDFViewer::initSaveAsDialog() { + Arg args[20]; + int n; + XmString s1, s2, s3; + GString *dir; + + n = 0; + s1 = XmStringCreateLocalized("Save"); + XtSetArg(args[n], XmNokLabelString, s1); ++n; + s2 = XmStringCreateLocalized("*.[Pp][Dd][Ff]"); + XtSetArg(args[n], XmNpattern, s2); ++n; + s3 = XmStringCreateLocalized(xpdfAppName ": Save as"); + XtSetArg(args[n], XmNdialogTitle, s3); ++n; + XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n; + XtSetArg(args[n], XmNautoUnmanage, True); ++n; + saveAsDialog = XmCreateFileSelectionDialog(win, "saveAsDialog", args, n); + XmStringFree(s1); + XmStringFree(s2); + XmStringFree(s3); + XtUnmanageChild(XmFileSelectionBoxGetChild(saveAsDialog, + XmDIALOG_HELP_BUTTON)); + XtAddCallback(saveAsDialog, XmNokCallback, + &saveAsOkCbk, (XtPointer)this); + + if (core->getDoc() && core->getDoc()->getFileName()) { + dir = makePathAbsolute(grabPath( + core->getDoc()->getFileName()->getCString())); + s1 = XmStringCreateLocalized(dir->getCString()); + XtVaSetValues(saveAsDialog, XmNdirectory, s1, NULL); + XmStringFree(s1); + delete dir; + } +} + +void XPDFViewer::mapSaveAsDialog() { + if (!saveAsDialog) { + initSaveAsDialog(); + } + XmFileSelectionDoSearch(saveAsDialog, NULL); + XtManageChild(saveAsDialog); +} + +void XPDFViewer::saveAsOkCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + XmFileSelectionBoxCallbackStruct *data = + (XmFileSelectionBoxCallbackStruct *)callData; + char *fileName; + GString *fileNameStr; + XmStringContext context; + XmStringCharSet charSet; + XmStringDirection dir; + Boolean sep; + + XmStringInitContext(&context, data->value); + if (XmStringGetNextSegment(context, &fileName, &charSet, &dir, &sep)) { + fileNameStr = new GString(fileName); + viewer->core->getDoc()->saveAs(fileNameStr); + delete fileNameStr; + XtFree(charSet); + XtFree(fileName); + } + XmStringFreeContext(context); +} + +//------------------------------------------------------------------------ +// GUI code: "print" dialog +//------------------------------------------------------------------------ + +void XPDFViewer::initPrintDialog() { + Widget sep1, sep2, row, label1, label2, okBtn, cancelBtn; + Arg args[20]; + int n; + XmString s; + GString *psFileName; + + //----- dialog + n = 0; + s = XmStringCreateLocalized(xpdfAppName ": Print"); + XtSetArg(args[n], XmNdialogTitle, s); ++n; + XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); ++n; + printDialog = XmCreateFormDialog(win, "printDialog", args, n); + XmStringFree(s); + + //----- "print with command" + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNtopOffset, 4); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNindicatorType, XmONE_OF_MANY); ++n; + XtSetArg(args[n], XmNset, XmSET); ++n; + s = XmStringCreateLocalized("Print with command:"); + XtSetArg(args[n], XmNlabelString, s); ++n; + printWithCmdBtn = XmCreateToggleButton(printDialog, "printWithCmd", args, n); + XmStringFree(s); + XtManageChild(printWithCmdBtn); + XtAddCallback(printWithCmdBtn, XmNvalueChangedCallback, + &printWithCmdBtnCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNtopWidget, printWithCmdBtn); ++n; + XtSetArg(args[n], XmNtopOffset, 2); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 16); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightOffset, 4); ++n; + XtSetArg(args[n], XmNcolumns, 40); ++n; + printCmdText = XmCreateTextField(printDialog, "printCmd", args, n); + XtManageChild(printCmdText); + + //----- "print to file" + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNtopWidget, printCmdText); ++n; + XtSetArg(args[n], XmNtopOffset, 4); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNindicatorType, XmONE_OF_MANY); ++n; + XtSetArg(args[n], XmNset, XmUNSET); ++n; + s = XmStringCreateLocalized("Print to file:"); + XtSetArg(args[n], XmNlabelString, s); ++n; + printToFileBtn = XmCreateToggleButton(printDialog, "printToFile", args, n); + XmStringFree(s); + XtManageChild(printToFileBtn); + XtAddCallback(printToFileBtn, XmNvalueChangedCallback, + &printToFileBtnCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNtopWidget, printToFileBtn); ++n; + XtSetArg(args[n], XmNtopOffset, 2); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 16); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightOffset, 4); ++n; + XtSetArg(args[n], XmNcolumns, 40); ++n; + XtSetArg(args[n], XmNsensitive, False); ++n; + printFileText = XmCreateTextField(printDialog, "printFile", args, n); + XtManageChild(printFileText); + + //----- separator + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNtopWidget, printFileText); ++n; + XtSetArg(args[n], XmNtopOffset, 8); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 8); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightOffset, 8); ++n; + XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n; + sep1 = XmCreateSeparator(printDialog, "sep1", args, n); + XtManageChild(sep1); + + //----- page range + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNtopWidget, sep1); ++n; + XtSetArg(args[n], XmNtopOffset, 8); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 4); ++n; + XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n; + XtSetArg(args[n], XmNpacking, XmPACK_TIGHT); ++n; + row = XmCreateRowColumn(printDialog, "row", args, n); + XtManageChild(row); + n = 0; + s = XmStringCreateLocalized("Pages:"); + XtSetArg(args[n], XmNlabelString, s); ++n; + label1 = XmCreateLabel(row, "label1", args, n); + XmStringFree(s); + XtManageChild(label1); + n = 0; + XtSetArg(args[n], XmNcolumns, 5); ++n; + printFirstPage = XmCreateTextField(row, "printFirstPage", args, n); + XtManageChild(printFirstPage); + n = 0; + s = XmStringCreateLocalized("to"); + XtSetArg(args[n], XmNlabelString, s); ++n; + label2 = XmCreateLabel(row, "label2", args, n); + XmStringFree(s); + XtManageChild(label2); + n = 0; + XtSetArg(args[n], XmNcolumns, 5); ++n; + printLastPage = XmCreateTextField(row, "printLastPage", args, n); + XtManageChild(printLastPage); + + //----- separator + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNtopWidget, row); ++n; + XtSetArg(args[n], XmNtopOffset, 8); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 8); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightOffset, 8); ++n; + XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n; + sep2 = XmCreateSeparator(printDialog, "sep2", args, n); + XtManageChild(sep2); + + //----- "print" and "cancel" buttons + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNtopWidget, sep2); ++n; + XtSetArg(args[n], XmNtopOffset, 8); ++n; + XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNleftOffset, 4); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomOffset, 4); ++n; + okBtn = XmCreatePushButton(printDialog, "Print", args, n); + XtManageChild(okBtn); + XtAddCallback(okBtn, XmNactivateCallback, + &printPrintCbk, (XtPointer)this); + n = 0; + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); ++n; + XtSetArg(args[n], XmNtopWidget, sep2); ++n; + XtSetArg(args[n], XmNtopOffset, 8); ++n; + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNrightOffset, 4); ++n; + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); ++n; + XtSetArg(args[n], XmNbottomOffset, 4); ++n; + cancelBtn = XmCreatePushButton(printDialog, "Cancel", args, n); + XtManageChild(cancelBtn); + n = 0; + XtSetArg(args[n], XmNdefaultButton, okBtn); ++n; + XtSetArg(args[n], XmNcancelButton, cancelBtn); ++n; + XtSetValues(printDialog, args, n); + + //----- initial values + if ((psFileName = globalParams->getPSFile())) { + if (psFileName->getChar(0) == '|') { + XmTextFieldSetString(printCmdText, + psFileName->getCString() + 1); + } else { + XmTextFieldSetString(printFileText, psFileName->getCString()); + } + delete psFileName; + } +} + +void XPDFViewer::setupPrintDialog() { + PDFDoc *doc; + char buf[20]; + GString *pdfFileName, *psFileName, *psFileName2; + char *p; + + doc = core->getDoc(); + psFileName = globalParams->getPSFile(); + if (!psFileName || psFileName->getChar(0) == '|') { + pdfFileName = doc->getFileName(); + p = pdfFileName->getCString() + pdfFileName->getLength() - 4; + if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) { + psFileName2 = new GString(pdfFileName->getCString(), + pdfFileName->getLength() - 4); + } else { + psFileName2 = pdfFileName->copy(); + } + psFileName2->append(".ps"); + XmTextFieldSetString(printFileText, psFileName2->getCString()); + delete psFileName2; + } + if (psFileName && psFileName->getChar(0) == '|') { + XmToggleButtonSetState(printWithCmdBtn, True, False); + XmToggleButtonSetState(printToFileBtn, False, False); + XtVaSetValues(printCmdText, XmNsensitive, True, NULL); + XtVaSetValues(printFileText, XmNsensitive, False, NULL); + } else { + XmToggleButtonSetState(printWithCmdBtn, False, False); + XmToggleButtonSetState(printToFileBtn, True, False); + XtVaSetValues(printCmdText, XmNsensitive, False, NULL); + XtVaSetValues(printFileText, XmNsensitive, True, NULL); + } + if (psFileName) { + delete psFileName; + } + + sprintf(buf, "%d", doc->getNumPages()); + XmTextFieldSetString(printFirstPage, "1"); + XmTextFieldSetString(printLastPage, buf); +} + +void XPDFViewer::printWithCmdBtnCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + XmToggleButtonCallbackStruct *data = + (XmToggleButtonCallbackStruct *)callData; + + if (data->set != XmSET) { + XmToggleButtonSetState(viewer->printWithCmdBtn, True, False); + } + XmToggleButtonSetState(viewer->printToFileBtn, False, False); + XtVaSetValues(viewer->printCmdText, XmNsensitive, True, NULL); + XtVaSetValues(viewer->printFileText, XmNsensitive, False, NULL); +} + +void XPDFViewer::printToFileBtnCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + XmToggleButtonCallbackStruct *data = + (XmToggleButtonCallbackStruct *)callData; + + if (data->set != XmSET) { + XmToggleButtonSetState(viewer->printToFileBtn, True, False); + } + XmToggleButtonSetState(viewer->printWithCmdBtn, False, False); + XtVaSetValues(viewer->printFileText, XmNsensitive, True, NULL); + XtVaSetValues(viewer->printCmdText, XmNsensitive, False, NULL); +} + +void XPDFViewer::printPrintCbk(Widget widget, XtPointer ptr, + XtPointer callData) { + XPDFViewer *viewer = (XPDFViewer *)ptr; + unsigned char withCmd; + GString *psFileName; + int firstPage, lastPage; + PDFDoc *doc; + PSOutputDev *psOut; + + doc = viewer->core->getDoc(); + if (!doc->okToPrint()) { + error(-1, "Printing this document is not allowed."); + return; + } + + viewer->core->setBusyCursor(gTrue); + + XtVaGetValues(viewer->printWithCmdBtn, XmNset, &withCmd, NULL); + if (withCmd) { + psFileName = new GString(XmTextFieldGetString(viewer->printCmdText)); + psFileName->insert(0, '|'); + } else { + psFileName = new GString(XmTextFieldGetString(viewer->printFileText)); + } + + firstPage = atoi(XmTextFieldGetString(viewer->printFirstPage)); + lastPage = atoi(XmTextFieldGetString(viewer->printLastPage)); + if (firstPage < 1) { + firstPage = 1; + } else if (firstPage > doc->getNumPages()) { + firstPage = doc->getNumPages(); + } + if (lastPage < firstPage) { + lastPage = firstPage; + } else if (lastPage > doc->getNumPages()) { + lastPage = doc->getNumPages(); + } + + psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(), + doc->getCatalog(), firstPage, lastPage, + psModePS); + if (psOut->isOk()) { + doc->displayPages(psOut, firstPage, lastPage, 72, 72, + 0, gTrue, globalParams->getPSCrop(), gTrue); + } + delete psOut; + delete psFileName; + + viewer->core->setBusyCursor(gFalse); +} + +//------------------------------------------------------------------------ +// Motif support +//------------------------------------------------------------------------ + +XmFontList XPDFViewer::createFontList(char *xlfd) { + XmFontList fontList; + +#if XmVersion <= 1001 + + XFontStruct *font; + String params; + Cardinal nParams; + + font = XLoadQueryFont(display, xlfd); + if (font) { + fontList = XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET); + } else { + params = (String)xlfd; + nParams = 1; + XtAppWarningMsg(app->getAppContext(), + "noSuchFont", "CvtStringToXmFontList", + "XtToolkitError", "No such font: %s", + ¶ms, &nParams); + fontList = NULL; + } + +#else + + XmFontListEntry entry; + + entry = XmFontListEntryLoad(display, xlfd, + XmFONT_IS_FONT, XmFONTLIST_DEFAULT_TAG); + fontList = XmFontListAppendEntry(NULL, entry); + XmFontListEntryFree(&entry); + +#endif + + return fontList; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFViewer.h swftools-0.9.1/lib/pdf/xpdf/XPDFViewer.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/XPDFViewer.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XPDFViewer.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,352 @@ +//======================================================================== +// +// XPDFViewer.h +// +// Copyright 2002-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef XPDFVIEWER_H +#define XPDFVIEWER_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#define Object XtObject +#include +#undef Object +#include "gtypes.h" +#include "XPDFCore.h" + +#if (XmVERSION <= 1) && !defined(__sgi) +#define DISABLE_OUTLINE +#endif + +#if (XmVERSION >= 2 && !defined(LESSTIF_VERSION)) +# define USE_COMBO_BOX 1 +#else +# undef USE_COMBO_BOX +#endif + +class GString; +class GList; +class UnicodeMap; +class LinkDest; +class XPDFApp; +class XPDFViewer; + +//------------------------------------------------------------------------ + +// NB: this must match the defn of zoomMenuBtnInfo in XPDFViewer.cc +#define nZoomMenuItems 10 + +//------------------------------------------------------------------------ + +struct XPDFViewerCmd { + char *name; + int nArgs; + GBool requiresDoc; + GBool requiresEvent; + void (XPDFViewer::*func)(GString *args[], int nArgs, XEvent *event); +}; + +//------------------------------------------------------------------------ +// XPDFViewer +//------------------------------------------------------------------------ + +class XPDFViewer { +public: + + XPDFViewer(XPDFApp *appA, GString *fileName, + int pageA, GString *destName, GBool fullScreen, + GString *ownerPassword, GString *userPassword); + XPDFViewer(XPDFApp *appA, PDFDoc *doc, int pageA, + GString *destName, GBool fullScreen); + GBool isOk() { return ok; } + ~XPDFViewer(); + + void open(GString *fileName, int pageA, GString *destName); + void clear(); + void reloadFile(); + + void execCmd(GString *cmd, XEvent *event); + + Widget getWindow() { return win; } + +private: + + //----- load / display + GBool loadFile(GString *fileName, GString *ownerPassword = NULL, + GString *userPassword = NULL); + void displayPage(int pageA, double zoomA, int rotateA, + GBool scrollToTop, GBool addToHist); + void displayDest(LinkDest *dest, double zoomA, int rotateA, + GBool addToHist); + void getPageAndDest(int pageA, GString *destName, + int *pageOut, LinkDest **destOut); + + //----- hyperlinks / actions + void doLink(int wx, int wy, GBool onlyIfNoSelection, GBool newWin); + static void actionCbk(void *data, char *action); + + //----- keyboard/mouse input + static void keyPressCbk(void *data, KeySym key, Guint modifiers, + XEvent *event); + static void mouseCbk(void *data, XEvent *event); + int getModifiers(Guint modifiers); + int getContext(Guint modifiers); + + //----- command functions + void cmdAbout(GString *args[], int nArgs, XEvent *event); + void cmdCloseOutline(GString *args[], int nArgs, XEvent *event); + void cmdCloseWindow(GString *args[], int nArgs, XEvent *event); + void cmdContinuousMode(GString *args[], int nArgs, XEvent *event); + void cmdEndPan(GString *args[], int nArgs, XEvent *event); + void cmdEndSelection(GString *args[], int nArgs, XEvent *event); + void cmdFind(GString *args[], int nArgs, XEvent *event); + void cmdFindNext(GString *args[], int nArgs, XEvent *event); + void cmdFocusToDocWin(GString *args[], int nArgs, XEvent *event); + void cmdFocusToPageNum(GString *args[], int nArgs, XEvent *event); + void cmdFollowLink(GString *args[], int nArgs, XEvent *event); + void cmdFollowLinkInNewWin(GString *args[], int nArgs, XEvent *event); + void cmdFollowLinkInNewWinNoSel(GString *args[], int nArgs, XEvent *event); + void cmdFollowLinkNoSel(GString *args[], int nArgs, XEvent *event); + void cmdFullScreenMode(GString *args[], int nArgs, XEvent *event); + void cmdGoBackward(GString *args[], int nArgs, XEvent *event); + void cmdGoForward(GString *args[], int nArgs, XEvent *event); + void cmdGotoDest(GString *args[], int nArgs, XEvent *event); + void cmdGotoLastPage(GString *args[], int nArgs, XEvent *event); + void cmdGotoLastPageNoScroll(GString *args[], int nArgs, XEvent *event); + void cmdGotoPage(GString *args[], int nArgs, XEvent *event); + void cmdGotoPageNoScroll(GString *args[], int nArgs, XEvent *event); + void cmdNextPage(GString *args[], int nArgs, XEvent *event); + void cmdNextPageNoScroll(GString *args[], int nArgs, XEvent *event); + void cmdOpen(GString *args[], int nArgs, XEvent *event); + void cmdOpenFile(GString *args[], int nArgs, XEvent *event); + void cmdOpenFileAtDest(GString *args[], int nArgs, XEvent *event); + void cmdOpenFileAtDestInNewWin(GString *args[], int nArgs, XEvent *event); + void cmdOpenFileAtPage(GString *args[], int nArgs, XEvent *event); + void cmdOpenFileAtPageInNewWin(GString *args[], int nArgs, XEvent *event); + void cmdOpenFileInNewWin(GString *args[], int nArgs, XEvent *event); + void cmdOpenInNewWin(GString *args[], int nArgs, XEvent *event); + void cmdOpenOutline(GString *args[], int nArgs, XEvent *event); + void cmdPageDown(GString *args[], int nArgs, XEvent *event); + void cmdPageUp(GString *args[], int nArgs, XEvent *event); + void cmdPostPopupMenu(GString *args[], int nArgs, XEvent *event); + void cmdPrevPage(GString *args[], int nArgs, XEvent *event); + void cmdPrevPageNoScroll(GString *args[], int nArgs, XEvent *event); + void cmdPrint(GString *args[], int nArgs, XEvent *event); + void cmdQuit(GString *args[], int nArgs, XEvent *event); + void cmdRaise(GString *args[], int nArgs, XEvent *event); + void cmdRedraw(GString *args[], int nArgs, XEvent *event); + void cmdReload(GString *args[], int nArgs, XEvent *event); + void cmdRun(GString *args[], int nArgs, XEvent *event); + void cmdScrollDown(GString *args[], int nArgs, XEvent *event); + void cmdScrollDownNextPage(GString *args[], int nArgs, XEvent *event); + void cmdScrollLeft(GString *args[], int nArgs, XEvent *event); + void cmdScrollOutlineDown(GString *args[], int nArgs, XEvent *event); + void cmdScrollOutlineUp(GString *args[], int nArgs, XEvent *event); + void cmdScrollRight(GString *args[], int nArgs, XEvent *event); + void cmdScrollToBottomEdge(GString *args[], int nArgs, XEvent *event); + void cmdScrollToBottomRight(GString *args[], int nArgs, XEvent *event); + void cmdScrollToLeftEdge(GString *args[], int nArgs, XEvent *event); + void cmdScrollToRightEdge(GString *args[], int nArgs, XEvent *event); + void cmdScrollToTopEdge(GString *args[], int nArgs, XEvent *event); + void cmdScrollToTopLeft(GString *args[], int nArgs, XEvent *event); + void cmdScrollUp(GString *args[], int nArgs, XEvent *event); + void cmdScrollUpPrevPage(GString *args[], int nArgs, XEvent *event); + void cmdSinglePageMode(GString *args[], int nArgs, XEvent *event); + void cmdStartPan(GString *args[], int nArgs, XEvent *event); + void cmdStartSelection(GString *args[], int nArgs, XEvent *event); + void cmdToggleContinuousMode(GString *args[], int nArgs, XEvent *event); + void cmdToggleFullScreenMode(GString *args[], int nArgs, XEvent *event); + void cmdToggleOutline(GString *args[], int nArgs, XEvent *event); + void cmdWindowMode(GString *args[], int nArgs, XEvent *event); + void cmdZoomFitPage(GString *args[], int nArgs, XEvent *event); + void cmdZoomFitWidth(GString *args[], int nArgs, XEvent *event); + void cmdZoomIn(GString *args[], int nArgs, XEvent *event); + void cmdZoomOut(GString *args[], int nArgs, XEvent *event); + void cmdZoomPercent(GString *args[], int nArgs, XEvent *event); + void cmdZoomToSelection(GString *args[], int nArgs, XEvent *event); + + //----- GUI code: main window + void initWindow(GBool fullScreen); + void initToolbar(Widget parent); +#ifndef DISABLE_OUTLINE + void initPanedWin(Widget parent); +#endif + void initCore(Widget parent, GBool fullScreen); + void initPopupMenu(); + void addToolTip(Widget widget, char *text); + void mapWindow(); + void closeWindow(); + int getZoomIdx(); + void setZoomIdx(int idx); + void setZoomVal(double z); + static void prevPageCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void prevTenPageCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void nextPageCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void nextTenPageCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void backCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void forwardCbk(Widget widget, XtPointer ptr, + XtPointer callData); +#if USE_COMBO_BOX + static void zoomComboBoxCbk(Widget widget, XtPointer ptr, + XtPointer callData); +#else + static void zoomMenuCbk(Widget widget, XtPointer ptr, + XtPointer callData); +#endif + static void findCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void printCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void aboutCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void quitCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void openCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void openInNewWindowCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void reloadCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void saveAsCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void continuousModeToggleCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void fullScreenToggleCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void rotateCCWCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void rotateCWCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void zoomToSelectionCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void closeCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void closeMsgCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void pageNumCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void updateCbk(void *data, GString *fileName, + int pageNum, int numPages, char *linkString); + + //----- GUI code: outline +#ifndef DISABLE_OUTLINE + void setupOutline(); + void setupOutlineItems(GList *items, Widget parent, UnicodeMap *uMap); + static void outlineSelectCbk(Widget widget, XtPointer ptr, + XtPointer callData); +#endif + + //----- GUI code: "about" dialog + void initAboutDialog(); + + //----- GUI code: "open" dialog + void initOpenDialog(); + void mapOpenDialog(GBool openInNewWindowA); + static void openOkCbk(Widget widget, XtPointer ptr, + XtPointer callData); + + //----- GUI code: "find" dialog + void initFindDialog(); + static void findFindCbk(Widget widget, XtPointer ptr, + XtPointer callData); + void mapFindDialog(); + void doFind(GBool next); + static void findCloseCbk(Widget widget, XtPointer ptr, + XtPointer callData); + + //----- GUI code: "save as" dialog + void initSaveAsDialog(); + void mapSaveAsDialog(); + static void saveAsOkCbk(Widget widget, XtPointer ptr, + XtPointer callData); + + //----- GUI code: "print" dialog + void initPrintDialog(); + void setupPrintDialog(); + static void printWithCmdBtnCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void printToFileBtnCbk(Widget widget, XtPointer ptr, + XtPointer callData); + static void printPrintCbk(Widget widget, XtPointer ptr, + XtPointer callData); + + //----- Motif support + XmFontList createFontList(char *xlfd); + + static XPDFViewerCmd cmdTab[]; + + XPDFApp *app; + GBool ok; + + Display *display; + int screenNum; + Widget win; // top-level window + Widget form; + Widget panedWin; +#ifndef DISABLE_OUTLINE + Widget outlineScroll; + Widget outlineTree; + Widget *outlineLabels; + int outlineLabelsLength; + int outlineLabelsSize; + Dimension outlinePaneWidth; +#endif + XPDFCore *core; + Widget toolBar; + Widget backBtn; + Widget prevTenPageBtn; + Widget prevPageBtn; + Widget nextPageBtn; + Widget nextTenPageBtn; + Widget forwardBtn; + Widget pageNumText; + Widget pageCountLabel; +#if USE_COMBO_BOX + Widget zoomComboBox; +#else + Widget zoomMenu; + Widget zoomMenuBtns[nZoomMenuItems]; +#endif + Widget zoomWidget; + Widget findBtn; + Widget printBtn; + Widget aboutBtn; + Widget linkLabel; + Widget quitBtn; + Widget popupMenu; + + Widget aboutDialog; + XmFontList aboutBigFont, aboutVersionFont, aboutFixedFont; + + Widget openDialog; + GBool openInNewWindow; + + Widget findDialog; + Widget findText; + Widget findBackwardToggle; + Widget findCaseSensitiveToggle; + + Widget saveAsDialog; + + Widget printDialog; + Widget printWithCmdBtn; + Widget printToFileBtn; + Widget printCmdText; + Widget printFileText; + Widget printFirstPage; + Widget printLastPage; +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XRef.cc swftools-0.9.1/lib/pdf/xpdf/XRef.cc --- swftools-0.9.2+ds1/lib/pdf/xpdf/XRef.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XRef.cc 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,896 @@ +//======================================================================== +// +// XRef.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include +#include +#include +#include +#include "gmem.h" +#include "Object.h" +#include "Stream.h" +#include "Lexer.h" +#include "Parser.h" +#include "Dict.h" +#include "Error.h" +#include "ErrorCodes.h" +#include "XRef.h" + +//------------------------------------------------------------------------ + +#define xrefSearchSize 1024 // read this many bytes at end of file + // to look for 'startxref' + +//------------------------------------------------------------------------ +// Permission bits +//------------------------------------------------------------------------ + +#define permPrint (1<<2) +#define permChange (1<<3) +#define permCopy (1<<4) +#define permNotes (1<<5) +#define defPermFlags 0xfffc + +//------------------------------------------------------------------------ +// ObjectStream +//------------------------------------------------------------------------ + +class ObjectStream { +public: + + // Create an object stream, using object number , + // generation 0. + ObjectStream(XRef *xref, int objStrNumA); + + ~ObjectStream(); + + // Return the object number of this object stream. + int getObjStrNum() { return objStrNum; } + + // Get the th object from this stream, which should be + // object number , generation 0. + Object *getObject(int objIdx, int objNum, Object *obj); + +private: + + int objStrNum; // object number of the object stream + int nObjects; // number of objects in the stream + Object *objs; // the objects (length = nObjects) + int *objNums; // the object numbers (length = nObjects) +}; + +ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { + Stream *str; + Parser *parser; + int *offsets; + Object objStr, obj1, obj2; + int first, i; + + objStrNum = objStrNumA; + nObjects = 0; + objs = NULL; + objNums = NULL; + + if (!xref->fetch(objStrNum, 0, &objStr)->isStream()) { + goto err1; + } + + if (!objStr.streamGetDict()->lookup("N", &obj1)->isInt()) { + obj1.free(); + goto err1; + } + nObjects = obj1.getInt(); + obj1.free(); + if (nObjects <= 0) { + goto err1; + } + + if (!objStr.streamGetDict()->lookup("First", &obj1)->isInt()) { + obj1.free(); + goto err1; + } + first = obj1.getInt(); + obj1.free(); + if (first < 0) { + goto err1; + } + + objs = new Object[nObjects]; + objNums = (int *)gmallocn(nObjects, sizeof(int)); + offsets = (int *)gmallocn(nObjects, sizeof(int)); + + // parse the header: object numbers and offsets + objStr.streamReset(); + obj1.initNull(); + str = new EmbedStream(objStr.getStream(), &obj1, gTrue, first); + parser = new Parser(xref, new Lexer(xref, str), gFalse); + for (i = 0; i < nObjects; ++i) { + parser->getObj(&obj1); + parser->getObj(&obj2); + if (!obj1.isInt() || !obj2.isInt()) { + obj1.free(); + obj2.free(); + delete parser; + gfree(offsets); + goto err1; + } + objNums[i] = obj1.getInt(); + offsets[i] = obj2.getInt(); + obj1.free(); + obj2.free(); + if (objNums[i] < 0 || offsets[i] < 0 || + (i > 0 && offsets[i] < offsets[i-1])) { + delete parser; + gfree(offsets); + goto err1; + } + } + while (str->getChar() != EOF) ; + delete parser; + + // skip to the first object - this shouldn't be necessary because + // the First key is supposed to be equal to offsets[0], but just in + // case... + for (i = first; i < offsets[0]; ++i) { + objStr.getStream()->getChar(); + } + + // parse the objects + for (i = 0; i < nObjects; ++i) { + obj1.initNull(); + if (i == nObjects - 1) { + str = new EmbedStream(objStr.getStream(), &obj1, gFalse, 0); + } else { + str = new EmbedStream(objStr.getStream(), &obj1, gTrue, + offsets[i+1] - offsets[i]); + } + parser = new Parser(xref, new Lexer(xref, str), gFalse); + parser->getObj(&objs[i]); + while (str->getChar() != EOF) ; + delete parser; + } + + gfree(offsets); + + err1: + objStr.free(); + return; +} + +ObjectStream::~ObjectStream() { + int i; + + if (objs) { + for (i = 0; i < nObjects; ++i) { + objs[i].free(); + } + delete[] objs; + } + gfree(objNums); +} + +Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) { + if (objIdx < 0 || objIdx >= nObjects || objNum != objNums[objIdx]) { + return obj->initNull(); + } + return objs[objIdx].copy(obj); +} + +//------------------------------------------------------------------------ +// XRef +//------------------------------------------------------------------------ + +XRef::XRef(BaseStream *strA) { + Guint pos; + Object obj; + + ok = gTrue; + errCode = errNone; + size = 0; + entries = NULL; + streamEnds = NULL; + streamEndsLen = 0; + objStr = NULL; + + encrypted = gFalse; + permFlags = defPermFlags; + ownerPasswordOk = gFalse; + + // read the trailer + str = strA; + start = str->getStart(); + pos = getStartXref(); + + // if there was a problem with the 'startxref' position, try to + // reconstruct the xref table + if (pos == 0) { + if (!(ok = constructXRef())) { + errCode = errDamaged; + return; + } + + // read the xref table + } else { + while (readXRef(&pos)) ; + + // if there was a problem with the xref table, + // try to reconstruct it + if (!ok) { + if (!(ok = constructXRef())) { + errCode = errDamaged; + return; + } + } + } + + // get the root dictionary (catalog) object + trailerDict.dictLookupNF("Root", &obj); + if (obj.isRef()) { + rootNum = obj.getRefNum(); + rootGen = obj.getRefGen(); + obj.free(); + } else { + obj.free(); + if (!(ok = constructXRef())) { + errCode = errDamaged; + return; + } + } + + // now set the trailer dictionary's xref pointer so we can fetch + // indirect objects from it + trailerDict.getDict()->setXRef(this); +} + +XRef::~XRef() { + gfree(entries); + trailerDict.free(); + if (streamEnds) { + gfree(streamEnds); + } + if (objStr) { + delete objStr; + } +} + +// Read the 'startxref' position. +Guint XRef::getStartXref() { + char buf[xrefSearchSize+1]; + char *p; + int c, n, i; + + // read last xrefSearchSize bytes + str->setPos(xrefSearchSize, -1); + for (n = 0; n < xrefSearchSize; ++n) { + if ((c = str->getChar()) == EOF) { + break; + } + buf[n] = c; + } + buf[n] = '\0'; + + // find startxref + for (i = n - 9; i >= 0; --i) { + if (!strncmp(&buf[i], "startxref", 9)) { + break; + } + } + if (i < 0) { + return 0; + } + for (p = &buf[i+9]; isspace(*p); ++p) ; + lastXRefPos = strToUnsigned(p); + + return lastXRefPos; +} + +// Read one xref table section. Also reads the associated trailer +// dictionary, and returns the prev pointer (if any). +GBool XRef::readXRef(Guint *pos) { + Parser *parser; + Object obj; + GBool more; + + // start up a parser, parse one token + obj.initNull(); + parser = new Parser(NULL, + new Lexer(NULL, + str->makeSubStream(start + *pos, gFalse, 0, &obj)), + gTrue); + parser->getObj(&obj); + + // parse an old-style xref table + if (obj.isCmd("xref")) { + obj.free(); + more = readXRefTable(parser, pos); + + // parse an xref stream + } else if (obj.isInt()) { + obj.free(); + if (!parser->getObj(&obj)->isInt()) { + goto err1; + } + obj.free(); + if (!parser->getObj(&obj)->isCmd("obj")) { + goto err1; + } + obj.free(); + if (!parser->getObj(&obj)->isStream()) { + goto err1; + } + more = readXRefStream(obj.getStream(), pos); + obj.free(); + + } else { + goto err1; + } + + delete parser; + return more; + + err1: + obj.free(); + delete parser; + ok = gFalse; + return gFalse; +} + +GBool XRef::readXRefTable(Parser *parser, Guint *pos) { + XRefEntry entry; + GBool more; + Object obj, obj2; + Guint pos2; + int first, n, newSize, i; + + while (1) { + parser->getObj(&obj); + if (obj.isCmd("trailer")) { + obj.free(); + break; + } + if (!obj.isInt()) { + goto err1; + } + first = obj.getInt(); + obj.free(); + if (!parser->getObj(&obj)->isInt()) { + goto err1; + } + n = obj.getInt(); + obj.free(); + if (first < 0 || n < 0 || first + n < 0) { + goto err1; + } + if (first + n > size) { + for (newSize = size ? 2 * size : 1024; + first + n > newSize && newSize > 0; + newSize <<= 1) ; + if (newSize < 0) { + goto err1; + } + entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); + for (i = size; i < newSize; ++i) { + entries[i].offset = 0xffffffff; + entries[i].type = xrefEntryFree; + } + size = newSize; + } + for (i = first; i < first + n; ++i) { + if (!parser->getObj(&obj)->isInt()) { + goto err1; + } + entry.offset = (Guint)obj.getInt(); + obj.free(); + if (!parser->getObj(&obj)->isInt()) { + goto err1; + } + entry.gen = obj.getInt(); + obj.free(); + parser->getObj(&obj); + if (obj.isCmd("n")) { + entry.type = xrefEntryUncompressed; + } else if (obj.isCmd("f")) { + entry.type = xrefEntryFree; + } else { + goto err1; + } + obj.free(); + if (entries[i].offset == 0xffffffff) { + entries[i] = entry; + // PDF files of patents from the IBM Intellectual Property + // Network have a bug: the xref table claims to start at 1 + // instead of 0. + if (i == 1 && first == 1 && + entries[1].offset == 0 && entries[1].gen == 65535 && + entries[1].type == xrefEntryFree) { + i = first = 0; + entries[0] = entries[1]; + entries[1].offset = 0xffffffff; + } + } + } + } + + // read the trailer dictionary + if (!parser->getObj(&obj)->isDict()) { + goto err1; + } + + // get the 'Prev' pointer + obj.getDict()->lookupNF("Prev", &obj2); + if (obj2.isInt()) { + *pos = (Guint)obj2.getInt(); + more = gTrue; + } else if (obj2.isRef()) { + // certain buggy PDF generators generate "/Prev NNN 0 R" instead + // of "/Prev NNN" + *pos = (Guint)obj2.getRefNum(); + more = gTrue; + } else { + more = gFalse; + } + obj2.free(); + + // save the first trailer dictionary + if (trailerDict.isNone()) { + obj.copy(&trailerDict); + } + + // check for an 'XRefStm' key + if (obj.getDict()->lookup("XRefStm", &obj2)->isInt()) { + pos2 = (Guint)obj2.getInt(); + readXRef(&pos2); + if (!ok) { + obj2.free(); + goto err1; + } + } + obj2.free(); + + obj.free(); + return more; + + err1: + obj.free(); + ok = gFalse; + return gFalse; +} + +GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) { + Dict *dict; + int w[3]; + GBool more; + Object obj, obj2, idx; + int newSize, first, n, i; + + dict = xrefStr->getDict(); + + if (!dict->lookupNF("Size", &obj)->isInt()) { + goto err1; + } + newSize = obj.getInt(); + obj.free(); + if (newSize < 0) { + goto err1; + } + if (newSize > size) { + entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); + for (i = size; i < newSize; ++i) { + entries[i].offset = 0xffffffff; + entries[i].type = xrefEntryFree; + } + size = newSize; + } + + if (!dict->lookupNF("W", &obj)->isArray() || + obj.arrayGetLength() < 3) { + goto err1; + } + for (i = 0; i < 3; ++i) { + if (!obj.arrayGet(i, &obj2)->isInt()) { + obj2.free(); + goto err1; + } + w[i] = obj2.getInt(); + obj2.free(); + if (w[i] < 0 || w[i] > 4) { + goto err1; + } + } + obj.free(); + + xrefStr->reset(); + dict->lookupNF("Index", &idx); + if (idx.isArray()) { + for (i = 0; i+1 < idx.arrayGetLength(); i += 2) { + if (!idx.arrayGet(i, &obj)->isInt()) { + idx.free(); + goto err1; + } + first = obj.getInt(); + obj.free(); + if (!idx.arrayGet(i+1, &obj)->isInt()) { + idx.free(); + goto err1; + } + n = obj.getInt(); + obj.free(); + if (first < 0 || n < 0 || + !readXRefStreamSection(xrefStr, w, first, n)) { + idx.free(); + goto err0; + } + } + } else { + if (!readXRefStreamSection(xrefStr, w, 0, newSize)) { + idx.free(); + goto err0; + } + } + idx.free(); + + dict->lookupNF("Prev", &obj); + if (obj.isInt()) { + *pos = (Guint)obj.getInt(); + more = gTrue; + } else { + more = gFalse; + } + obj.free(); + if (trailerDict.isNone()) { + trailerDict.initDict(dict); + } + + return more; + + err1: + obj.free(); + err0: + ok = gFalse; + return gFalse; +} + +GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) { + Guint offset; + int type, gen, c, newSize, i, j; + + if (first + n < 0) { + return gFalse; + } + if (first + n > size) { + for (newSize = size ? 2 * size : 1024; + first + n > newSize && newSize > 0; + newSize <<= 1) ; + if (newSize < 0) { + return gFalse; + } + entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); + for (i = size; i < newSize; ++i) { + entries[i].offset = 0xffffffff; + entries[i].type = xrefEntryFree; + } + size = newSize; + } + for (i = first; i < first + n; ++i) { + if (w[0] == 0) { + type = 1; + } else { + for (type = 0, j = 0; j < w[0]; ++j) { + if ((c = xrefStr->getChar()) == EOF) { + return gFalse; + } + type = (type << 8) + c; + } + } + for (offset = 0, j = 0; j < w[1]; ++j) { + if ((c = xrefStr->getChar()) == EOF) { + return gFalse; + } + offset = (offset << 8) + c; + } + for (gen = 0, j = 0; j < w[2]; ++j) { + if ((c = xrefStr->getChar()) == EOF) { + return gFalse; + } + gen = (gen << 8) + c; + } + if (entries[i].offset == 0xffffffff) { + switch (type) { + case 0: + entries[i].offset = offset; + entries[i].gen = gen; + entries[i].type = xrefEntryFree; + break; + case 1: + entries[i].offset = offset; + entries[i].gen = gen; + entries[i].type = xrefEntryUncompressed; + break; + case 2: + entries[i].offset = offset; + entries[i].gen = gen; + entries[i].type = xrefEntryCompressed; + break; + default: + return gFalse; + } + } + } + + return gTrue; +} + +// Attempt to construct an xref table for a damaged file. +GBool XRef::constructXRef() { + Parser *parser; + Object newTrailerDict, obj; + char buf[256]; + Guint pos; + int num, gen; + int newSize; + int streamEndsSize; + char *p; + int i; + GBool gotRoot; + + gfree(entries); + size = 0; + entries = NULL; + + error(-1, "PDF file is damaged - attempting to reconstruct xref table..."); + gotRoot = gFalse; + streamEndsLen = streamEndsSize = 0; + + str->reset(); + while (1) { + pos = str->getPos(); + if (!str->getLine(buf, 256)) { + break; + } + p = buf; + + // skip whitespace + while (*p && Lexer::isSpace(*p & 0xff)) ++p; + + // got trailer dictionary + if (!strncmp(p, "trailer", 7)) { + obj.initNull(); + parser = new Parser(NULL, + new Lexer(NULL, + str->makeSubStream(pos + 7, gFalse, 0, &obj)), + gFalse); + parser->getObj(&newTrailerDict); + if (newTrailerDict.isDict()) { + newTrailerDict.dictLookupNF("Root", &obj); + if (obj.isRef()) { + rootNum = obj.getRefNum(); + rootGen = obj.getRefGen(); + if (!trailerDict.isNone()) { + trailerDict.free(); + } + newTrailerDict.copy(&trailerDict); + gotRoot = gTrue; + } + obj.free(); + } + newTrailerDict.free(); + delete parser; + + // look for object + } else if (isdigit(*p)) { + num = atoi(p); + if (num > 0) { + do { + ++p; + } while (*p && isdigit(*p)); + if (isspace(*p)) { + do { + ++p; + } while (*p && isspace(*p)); + if (isdigit(*p)) { + gen = atoi(p); + do { + ++p; + } while (*p && isdigit(*p)); + if (isspace(*p)) { + do { + ++p; + } while (*p && isspace(*p)); + if (!strncmp(p, "obj", 3)) { + if (num >= size) { + newSize = (num + 1 + 255) & ~255; + if (newSize < 0) { + error(-1, "Bad object number"); + return gFalse; + } + entries = (XRefEntry *) + greallocn(entries, newSize, sizeof(XRefEntry)); + for (i = size; i < newSize; ++i) { + entries[i].offset = 0xffffffff; + entries[i].type = xrefEntryFree; + } + size = newSize; + } + if (entries[num].type == xrefEntryFree || + gen >= entries[num].gen) { + entries[num].offset = pos - start; + entries[num].gen = gen; + entries[num].type = xrefEntryUncompressed; + } + } + } + } + } + } + + } else if (!strncmp(p, "endstream", 9)) { + if (streamEndsLen == streamEndsSize) { + streamEndsSize += 64; + streamEnds = (Guint *)greallocn(streamEnds, + streamEndsSize, sizeof(int)); + } + streamEnds[streamEndsLen++] = pos; + } + } + + if (gotRoot) + return gTrue; + + error(-1, "Couldn't find trailer dictionary"); + return gFalse; +} + +void XRef::setEncryption(int permFlagsA, GBool ownerPasswordOkA, + Guchar *fileKeyA, int keyLengthA, int encVersionA, + CryptAlgorithm encAlgorithmA) { + int i; + + encrypted = gTrue; + permFlags = permFlagsA; + ownerPasswordOk = ownerPasswordOkA; + if (keyLengthA <= 16) { + keyLength = keyLengthA; + } else { + keyLength = 16; + } + for (i = 0; i < keyLength; ++i) { + fileKey[i] = fileKeyA[i]; + } + encVersion = encVersionA; + encAlgorithm = encAlgorithmA; +} + +GBool XRef::okToPrint(GBool ignoreOwnerPW) { + return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permPrint); +} + +GBool XRef::okToChange(GBool ignoreOwnerPW) { + return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permChange); +} + +GBool XRef::okToCopy(GBool ignoreOwnerPW) { + return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permCopy); +} + +GBool XRef::okToAddNotes(GBool ignoreOwnerPW) { + return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permNotes); +} + +Object *XRef::fetch(int num, int gen, Object *obj) { + XRefEntry *e; + Parser *parser; + Object obj1, obj2, obj3; + + // check for bogus ref - this can happen in corrupted PDF files + if (num < 0 || num >= size) { + goto err; + } + + e = &entries[num]; + switch (e->type) { + + case xrefEntryUncompressed: + if (e->gen != gen) { + goto err; + } + obj1.initNull(); + parser = new Parser(this, + new Lexer(this, + str->makeSubStream(start + e->offset, gFalse, 0, &obj1)), + gTrue); + parser->getObj(&obj1); + parser->getObj(&obj2); + parser->getObj(&obj3); + if (!obj1.isInt() || obj1.getInt() != num || + !obj2.isInt() || obj2.getInt() != gen || + !obj3.isCmd("obj")) { + obj1.free(); + obj2.free(); + obj3.free(); + delete parser; + goto err; + } + parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, + encAlgorithm, keyLength, num, gen); + obj1.free(); + obj2.free(); + obj3.free(); + delete parser; + break; + + case xrefEntryCompressed: + if (gen != 0) { + goto err; + } + if (!objStr || objStr->getObjStrNum() != (int)e->offset) { + if (objStr) { + delete objStr; + } + objStr = new ObjectStream(this, e->offset); + } + objStr->getObject(e->gen, num, obj); + break; + + default: + goto err; + } + + return obj; + + err: + return obj->initNull(); +} + +Object *XRef::getDocInfo(Object *obj) { + return trailerDict.dictLookup("Info", obj); +} + +// Added for the pdftex project. +Object *XRef::getDocInfoNF(Object *obj) { + return trailerDict.dictLookupNF("Info", obj); +} + +GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) { + int a, b, m; + + if (streamEndsLen == 0 || + streamStart > streamEnds[streamEndsLen - 1]) { + return gFalse; + } + + a = -1; + b = streamEndsLen - 1; + // invariant: streamEnds[a] < streamStart <= streamEnds[b] + while (b - a > 1) { + m = (a + b) / 2; + if (streamStart <= streamEnds[m]) { + b = m; + } else { + a = m; + } + } + *streamEnd = streamEnds[b]; + return gTrue; +} + +Guint XRef::strToUnsigned(char *s) { + Guint x; + char *p; + int i; + + x = 0; + for (p = s, i = 0; *p && isdigit(*p) && i < 10; ++p, ++i) { + x = 10 * x + (*p - '0'); + } + return x; +} diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf/XRef.h swftools-0.9.1/lib/pdf/xpdf/XRef.h --- swftools-0.9.2+ds1/lib/pdf/xpdf/XRef.h 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf/XRef.h 2012-06-20 15:37:22.000000000 +0000 @@ -0,0 +1,133 @@ +//======================================================================== +// +// XRef.h +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef XREF_H +#define XREF_H + +#include + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "gtypes.h" +#include "Object.h" + +class Dict; +class Stream; +class Parser; +class ObjectStream; + +//------------------------------------------------------------------------ +// XRef +//------------------------------------------------------------------------ + +enum XRefEntryType { + xrefEntryFree, + xrefEntryUncompressed, + xrefEntryCompressed +}; + +struct XRefEntry { + Guint offset; + int gen; + XRefEntryType type; +}; + +class XRef { +public: + + // Constructor. Read xref table from stream. + XRef(BaseStream *strA); + + // Destructor. + ~XRef(); + + // Is xref table valid? + GBool isOk() { return ok; } + + // Get the error code (if isOk() returns false). + int getErrorCode() { return errCode; } + + // Set the encryption parameters. + void setEncryption(int permFlagsA, GBool ownerPasswordOkA, + Guchar *fileKeyA, int keyLengthA, int encVersionA, + CryptAlgorithm encAlgorithmA); + + // Is the file encrypted? + GBool isEncrypted() { return encrypted; } + + // Check various permissions. + GBool okToPrint(GBool ignoreOwnerPW = gFalse); + GBool okToChange(GBool ignoreOwnerPW = gFalse); + GBool okToCopy(GBool ignoreOwnerPW = gFalse); + GBool okToAddNotes(GBool ignoreOwnerPW = gFalse); + + // Get catalog object. + Object *getCatalog(Object *obj) { return fetch(rootNum, rootGen, obj); } + + // Fetch an indirect reference. + Object *fetch(int num, int gen, Object *obj); + + // Return the document's Info dictionary (if any). + Object *getDocInfo(Object *obj); + Object *getDocInfoNF(Object *obj); + + // Return the number of objects in the xref table. + int getNumObjects() { return size; } + + // Return the offset of the last xref table. + Guint getLastXRefPos() { return lastXRefPos; } + + // Return the catalog object reference. + int getRootNum() { return rootNum; } + int getRootGen() { return rootGen; } + + // Get end position for a stream in a damaged file. + // Returns false if unknown or file is not damaged. + GBool getStreamEnd(Guint streamStart, Guint *streamEnd); + + // Direct access. + int getSize() { return size; } + XRefEntry *getEntry(int i) { return &entries[i]; } + Object *getTrailerDict() { return &trailerDict; } + +private: + + BaseStream *str; // input stream + Guint start; // offset in file (to allow for garbage + // at beginning of file) + XRefEntry *entries; // xref entries + int size; // size of array + int rootNum, rootGen; // catalog dict + GBool ok; // true if xref table is valid + int errCode; // error code (if is false) + Object trailerDict; // trailer dictionary + Guint lastXRefPos; // offset of last xref table + Guint *streamEnds; // 'endstream' positions - only used in + // damaged files + int streamEndsLen; // number of valid entries in streamEnds + ObjectStream *objStr; // cached object stream + GBool encrypted; // true if file is encrypted + int permFlags; // permission bits + GBool ownerPasswordOk; // true if owner password is correct + Guchar fileKey[16]; // file decryption key + int keyLength; // length of key, in bytes + int encVersion; // encryption version + CryptAlgorithm encAlgorithm; // encryption algorithm + + Guint getStartXref(); + GBool readXRef(Guint *pos); + GBool readXRefTable(Parser *parser, Guint *pos); + GBool readXRefStreamSection(Stream *xrefStr, int *w, int first, int n); + GBool readXRefStream(Stream *xrefStr, Guint *pos); + GBool constructXRef(); + Guint strToUnsigned(char *s); +}; + +#endif diff -Nru swftools-0.9.2+ds1/lib/pdf/xpdf-changes.patch swftools-0.9.1/lib/pdf/xpdf-changes.patch --- swftools-0.9.2+ds1/lib/pdf/xpdf-changes.patch 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/pdf/xpdf-changes.patch 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,2329 @@ +--- xpdf/Catalog.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/Catalog.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -193,7 +193,7 @@ + if (!kids.isArray()) { + error(-1, "Kids object (page %d) is wrong type (%s)", + start+1, kids.getTypeName()); +- goto err1; ++ return start; + } + for (i = 0; i < kids.arrayGetLength(); ++i) { + kids.arrayGetNF(i, &kidRef); +--- xpdf/CharCodeToUnicode.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/CharCodeToUnicode.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -208,13 +208,13 @@ + int nBits) { + PSTokenizer *pst; + char tok1[256], tok2[256], tok3[256]; +- int nDigits, n1, n2, n3; ++ int maxCode, n1, n2, n3; + CharCode i; + CharCode code1, code2; + GString *name; + FILE *f; + +- nDigits = nBits / 4; ++ maxCode = (nBits == 8) ? 0xff : (nBits == 16) ? 0xffff : 0xffffffff; + pst = new PSTokenizer(getCharFunc, data); + pst->getToken(tok1, sizeof(tok1), &n1); + while (pst->getToken(tok2, sizeof(tok2), &n2)) { +@@ -241,9 +241,9 @@ + error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); + break; + } +- if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' && ++ if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' && + tok2[0] == '<' && tok2[n2 - 1] == '>')) { +- error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); ++ error(-1, "Illegal entry in bfchar block in ToUnicode CMap."); + continue; + } + tok1[n1 - 1] = tok2[n2 - 1] = '\0'; +@@ -251,6 +251,9 @@ + error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); + continue; + } ++ if (code1 > maxCode) { ++ error(-1, "Invalid entry in bfchar block in ToUnicode CMap"); ++ } + addMapping(code1, tok2 + 1, n2 - 2, 0); + } + pst->getToken(tok1, sizeof(tok1), &n1); +@@ -266,8 +269,8 @@ + error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); + break; + } +- if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' && +- n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) { ++ if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' && ++ tok2[0] == '<' && tok2[n2 - 1] == '>')) { + error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); + continue; + } +@@ -277,6 +280,10 @@ + error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); + continue; + } ++ if (code1 > maxCode || code2 > maxCode) { ++ error(-1, "Invalid entry in bfrange block in ToUnicode CMap"); ++ } ++ + if (!strcmp(tok3, "[")) { + i = 0; + while (pst->getToken(tok1, sizeof(tok1), &n1) && +@@ -320,7 +327,13 @@ + if (code >= mapLen) { + oldLen = mapLen; + mapLen = (code + 256) & ~255; ++ Unicode *oldmap; + map = (Unicode *)greallocn(map, mapLen, sizeof(Unicode)); ++ if(!map) { ++ /* we sometimes get overflows for files trying to use 0xffffffff as charcode */ ++ map = oldmap; ++ return; ++ } + for (i = oldLen; i < mapLen; ++i) { + map[i] = 0; + } +--- xpdf/Decrypt.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/Decrypt.cc 2010-10-19 12:21:16.000000000 -0700 +@@ -596,6 +596,7 @@ + s->bufIdx = 0; + if (last) { + n = s->buf[15]; ++ if(!n || n>16) n=16; + for (i = 15; i >= n; --i) { + s->buf[i] = s->buf[i-n]; + } +--- xpdf/Function.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/Function.cc 2010-10-19 12:21:32.000000000 -0700 +@@ -401,7 +401,7 @@ + for (k = 0, t = j; k < m; ++k, t >>= 1) { + idx += idxMul[k] * (e[k][t & 1]); + } +- sBuf[j] = samples[idx]; ++ sBuf[j] = (idx>=0&&idxgetPrintCommands(); ++ parser = NULL; + + // start the resource stack + res = new GfxResources(xref, resDict, NULL); +@@ -465,6 +466,7 @@ + abortCheckCbkData = abortCheckCbkDataA; + + // set crop box ++#ifdef XPDFEXE + if (cropBox) { + state->moveTo(cropBox->x1, cropBox->y1); + state->lineTo(cropBox->x2, cropBox->y1); +@@ -475,6 +477,7 @@ + out->clip(state); + state->clearPath(); + } ++#endif + } + + Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict, +@@ -3182,8 +3185,11 @@ + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); + dx = dx * state->getFontSize() + state->getCharSpace(); +- if (n == 1 && *p == ' ') { +- dx += state->getWordSpace(); ++ if (n == 1 && (*p == ' ' || *p == 0)) { ++ double w=state->getWordSpace(); ++ if (w==0 && dx==0) ++ w=state->getFontSize()/3; // workaround for zero word space ++ dx += w; + } + dx *= state->getHorizScaling(); + dy *= state->getFontSize(); +@@ -3476,11 +3482,13 @@ + } + } + if (!obj1.isNull()) { +- colorSpace = GfxColorSpace::parse(&obj1); ++ colorSpace = GfxColorSpace::parse(&obj1, csMode); + } else if (csMode == streamCSDeviceGray) { + colorSpace = new GfxDeviceGrayColorSpace(); + } else if (csMode == streamCSDeviceRGB) { + colorSpace = new GfxDeviceRGBColorSpace(); ++ } else if (csMode == streamCSDeviceRGBX) { ++ colorSpace = new GfxDeviceRGBXColorSpace(); + } else if (csMode == streamCSDeviceCMYK) { + colorSpace = new GfxDeviceCMYKColorSpace(); + } else { +@@ -3824,6 +3832,7 @@ + out->beginTransparencyGroup(state, bbox, blendingColorSpace, + isolated, knockout, softMask); + } ++ GfxState*old_state = state; + + // set new base matrix + for (i = 0; i < 6; ++i) { +@@ -3835,6 +3844,9 @@ + display(str, gFalse); + + if (softMask || transpGroup) { ++ // restore graphics state ++ while(state != old_state) ++ restoreState(); + out->endTransparencyGroup(state); + } + +@@ -3921,6 +3933,10 @@ + obj.free(); + + // make stream ++ if(!parser->getStream()) { ++ error(getPos(), "Couldn't get stream"); ++ return NULL; ++ } + str = new EmbedStream(parser->getStream(), &dict, gFalse, 0); + str = str->addFilters(&dict); + +--- xpdf/GfxFont.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/GfxFont.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -194,7 +194,7 @@ + embFontID = obj2.getRef(); + if (type != fontType1) { + error(-1, "Mismatch between font type and embedded font file"); +- type = fontType1; ++ type = isCIDFont() ? fontCIDType0 : fontType1; + } + } + obj2.free(); +@@ -919,6 +919,10 @@ + return 1; + } + ++CharCodeToUnicode* Gfx8BitFont::getCTU() { ++ return ctu; ++} ++ + CharCodeToUnicode *Gfx8BitFont::getToUnicode() { + ctu->incRefCnt(); + return ctu; +@@ -1411,6 +1415,10 @@ + } + } + ++CharCodeToUnicode* GfxCIDFont::getCTU() { ++ return ctu; ++} ++ + int GfxCIDFont::getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy) { +--- xpdf/GfxFont.h.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/GfxFont.h 2010-08-16 14:02:38.000000000 -0700 +@@ -164,6 +164,7 @@ + virtual int getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy) = 0; ++ virtual CharCodeToUnicode* getCTU() = 0; + + protected: + +@@ -204,6 +205,7 @@ + virtual int getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy); ++ virtual CharCodeToUnicode* getCTU(); + + // Return the encoding. + char **getEncoding() { return enc; } +@@ -212,7 +214,7 @@ + CharCodeToUnicode *getToUnicode(); + + // Return the character name associated with . +- char *getCharName(int code) { return enc[code]; } ++ char *getCharName(int code) { return code>=256?0:enc[code]; } + + // Returns true if the PDF font specified an encoding. + GBool getHasEncoding() { return hasEncoding; } +@@ -266,6 +268,7 @@ + virtual int getNextChar(char *s, int len, CharCode *code, + Unicode *u, int uSize, int *uLen, + double *dx, double *dy, double *ox, double *oy); ++ virtual CharCodeToUnicode* getCTU(); + + // Return the writing mode (0=horizontal, 1=vertical). + virtual int getWMode(); +--- xpdf/GfxState.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/GfxState.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -21,6 +21,7 @@ + #include "Array.h" + #include "Page.h" + #include "GfxState.h" ++#include "cmyk.h" + + //------------------------------------------------------------------------ + +@@ -92,7 +93,7 @@ + GfxColorSpace::~GfxColorSpace() { + } + +-GfxColorSpace *GfxColorSpace::parse(Object *csObj) { ++GfxColorSpace *GfxColorSpace::parse(Object *csObj, StreamColorSpaceMode csMode) { + GfxColorSpace *cs; + Object obj1; + +@@ -101,7 +102,10 @@ + if (csObj->isName("DeviceGray") || csObj->isName("G")) { + cs = new GfxDeviceGrayColorSpace(); + } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) { +- cs = new GfxDeviceRGBColorSpace(); ++ if(csMode == streamCSDeviceRGBX) ++ cs = new GfxDeviceRGBXColorSpace(); ++ else ++ cs = new GfxDeviceRGBColorSpace(); + } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) { + cs = new GfxDeviceCMYKColorSpace(); + } else if (csObj->isName("Pattern")) { +@@ -114,7 +118,10 @@ + if (obj1.isName("DeviceGray") || obj1.isName("G")) { + cs = new GfxDeviceGrayColorSpace(); + } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) { +- cs = new GfxDeviceRGBColorSpace(); ++ if(csMode == streamCSDeviceRGBX) ++ cs = new GfxDeviceRGBColorSpace(); ++ else ++ cs = new GfxDeviceRGBColorSpace(); + } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) { + cs = new GfxDeviceCMYKColorSpace(); + } else if (obj1.isName("CalGray")) { +@@ -333,6 +340,17 @@ + } + + //------------------------------------------------------------------------ ++// GfxDeviceRGBXColorSpace ++//------------------------------------------------------------------------ ++ ++GfxDeviceRGBXColorSpace::GfxDeviceRGBXColorSpace() { ++} ++ ++GfxColorSpace *GfxDeviceRGBXColorSpace::copy() { ++ return new GfxDeviceRGBXColorSpace(); ++} ++ ++//------------------------------------------------------------------------ + // GfxCalRGBColorSpace + //------------------------------------------------------------------------ + +@@ -490,6 +508,18 @@ + - 0.11 * color->c[2] + 0.5)); + } + ++/*void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { ++ unsigned char r,g,b; ++ float c = color->c[0]; ++ float m = color->c[1]; ++ float y = color->c[2]; ++ float k = color->c[3]; ++ convert_cmyk2rgb(c,m,y,k, &r,&g,&b); ++ rgb->r = r/255.0; ++ rgb->g = g/255.0; ++ rgb->b = b/255.0; ++}*/ ++ + void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { + double c, m, y, k, c1, m1, y1, k1, r, g, b, x; + +@@ -3187,6 +3217,7 @@ + GfxIndexedColorSpace *indexedCS; + GfxSeparationColorSpace *sepCS; + int maxPixel, indexHigh; ++ int maxPixelForAlloc; + Guchar *lookup2; + Function *sepFunc; + Object obj; +@@ -3199,6 +3230,7 @@ + // bits per component and color space + bits = bitsA; + maxPixel = (1 << bits) - 1; ++ maxPixelForAlloc = (1 << (bits>8?bits:8)); + colorSpace = colorSpaceA; + + // initialize +@@ -3253,7 +3285,7 @@ + lookup2 = indexedCS->getLookup(); + colorSpace2->getDefaultRanges(x, y, indexHigh); + for (k = 0; k < nComps2; ++k) { +- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1, ++ lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1, + sizeof(GfxColorComp)); + for (i = 0; i <= maxPixel; ++i) { + j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5); +@@ -3272,7 +3304,7 @@ + nComps2 = colorSpace2->getNComps(); + sepFunc = sepCS->getFunc(); + for (k = 0; k < nComps2; ++k) { +- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1, ++ lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1, + sizeof(GfxColorComp)); + for (i = 0; i <= maxPixel; ++i) { + x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel; +@@ -3282,7 +3314,7 @@ + } + } else { + for (k = 0; k < nComps; ++k) { +- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1, ++ lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1, + sizeof(GfxColorComp)); + for (i = 0; i <= maxPixel; ++i) { + lookup[k][i] = dblToCol(decodeLow[k] + +@@ -3754,7 +3786,10 @@ + } + + void GfxState::setPath(GfxPath *pathA) { ++ if(pathA) { ++ if(path) + delete path; ++ } + path = pathA; + } + +--- xpdf/GfxState.h.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/GfxState.h 2010-08-16 14:02:38.000000000 -0700 +@@ -138,7 +138,7 @@ + virtual GfxColorSpaceMode getMode() = 0; + + // Construct a color space. Returns NULL if unsuccessful. +- static GfxColorSpace *parse(Object *csObj); ++ static GfxColorSpace *parse(Object *csObj, StreamColorSpaceMode csMode = streamCSNone); + + // Convert to gray, RGB, or CMYK. + virtual void getGray(GfxColor *color, GfxGray *gray) = 0; +@@ -251,6 +251,19 @@ + private: + }; + ++//------------------------------------------------------------------------ ++// GfxDeviceRGBXColorSpace ++//------------------------------------------------------------------------ ++ ++class GfxDeviceRGBXColorSpace: public GfxDeviceRGBColorSpace { ++public: ++ ++ GfxDeviceRGBXColorSpace(); ++ virtual GfxColorSpace *copy(); ++ virtual int getNComps() { return 4; } ++private: ++}; ++ + //------------------------------------------------------------------------ + // GfxCalRGBColorSpace + //------------------------------------------------------------------------ +--- xpdf/GlobalParams.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/GlobalParams.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -914,6 +914,29 @@ + int line; + char buf[512]; + ++ /* extract path */ ++ if(fileName) { ++ char* cfgFileName = fileName->getCString(); ++ char* pos1 = strrchr(cfgFileName, '/'); ++ char* pos2 = strrchr(cfgFileName, '\\'); ++ char* p = pos1>pos2?pos1:pos2; ++ int pos = p ? p-cfgFileName : -1; ++ GString*path = new GString(new GString(cfgFileName), 0, (pos < 0 ? strlen(cfgFileName): pos)); ++ if(pos1>=0) ++ path->append('/'); ++ else if(pos2>=0) ++ path->append('\\'); ++ else ++#ifdef WIN32 ++ path->append('\\'); ++#else ++ path->append('/'); ++#endif ++ this->path = path; ++ } else { ++ this->path = new GString(); ++ } ++ + line = 1; + while (getLine(buf, sizeof(buf) - 1, f)) { + parseLine(buf, fileName, line); +@@ -1114,6 +1137,42 @@ + deleteGList(tokens, GString); + } + ++static char is_absolute(char*filename) ++{ ++ int l = strlen(filename); ++ if(filename[0] == '/' || filename[0] == '\\') ++ return 1; ++ if(l>2 && filename[1]==':' && (filename[2]=='\\' || filename[2]=='/')) ++ return 1; ++ return 0; ++} ++ ++static GString* qualify_filename(GString*path, GString*filename) ++{ ++ GString*fullpath = 0; ++ char*prefix = "/usr/local/share/xpdf/"; ++ ++ if (!is_absolute(filename->getCString())) { ++ /* relative path */ ++ fullpath = path->copy(); ++ fullpath->append(filename); ++ } else if (!strncmp(filename->getCString(), prefix, strlen(prefix))) { ++ /* xpdf default path */ ++ char*s = strchr(filename->getCString()+strlen(prefix), '/'); ++ if(s) { ++ fullpath = path->copy(); ++ fullpath->append(s+1); ++ } else { ++ fullpath = filename->copy(); ++ } ++ } else { ++ /* absolute path */ ++ fullpath = filename->copy(); ++ } ++ //printf("%s -%s-> %s\n", filename->getCString(), path->getCString(), fullpath->getCString()); ++ return fullpath; ++} ++ + void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName, + int line) { + GString *name; +@@ -1128,10 +1187,10 @@ + fileName->getCString(), line); + return; + } +- name = (GString *)tokens->get(1); ++ name = qualify_filename(this->path, (GString *)tokens->get(1)); + if (!(f = fopen(name->getCString(), "r"))) { +- error(-1, "Couldn't open 'nameToUnicode' file '%s'", +- name->getCString()); ++ error(-1, "Couldn't open 'nameToUnicode' file '%s' using path '%s'", ++ name->getCString(), path->getCString()); + return; + } + line2 = 1; +@@ -1160,10 +1219,12 @@ + } + collection = (GString *)tokens->get(1); + name = (GString *)tokens->get(2); ++ + if ((old = (GString *)cidToUnicodes->remove(collection))) { + delete old; + } +- cidToUnicodes->add(collection->copy(), name->copy()); ++ ++ cidToUnicodes->add(collection->copy(), qualify_filename(this->path, name)); + } + + void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName, +@@ -1180,7 +1241,8 @@ + if ((old = (GString *)unicodeToUnicodes->remove(font))) { + delete old; + } +- unicodeToUnicodes->add(font->copy(), file->copy()); ++ ++ unicodeToUnicodes->add(font->copy(), qualify_filename(this->path, file)); + } + + void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName, +@@ -1197,7 +1259,8 @@ + if ((old = (GString *)unicodeMaps->remove(encodingName))) { + delete old; + } +- unicodeMaps->add(encodingName->copy(), name->copy()); ++ ++ unicodeMaps->add(encodingName->copy(), qualify_filename(this->path, name)); + } + + void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) { +@@ -1215,23 +1278,30 @@ + list = new GList(); + cMapDirs->add(collection->copy(), list); + } +- list->append(dir->copy()); ++ ++ list->append(qualify_filename(this->path, dir)); + } + + void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName, + int line) { ++ GString *dir; ++ + if (tokens->getLength() != 2) { + error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)", + fileName->getCString(), line); + return; + } +- toUnicodeDirs->append(((GString *)tokens->get(1))->copy()); ++ ++ dir = (GString *)tokens->get(1); ++ ++ toUnicodeDirs->append(qualify_filename(this->path, dir)); + } + + void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash, + DisplayFontParamKind kind, + GString *fileName, int line) { + DisplayFontParam *param, *old; ++ GString *file; + + if (tokens->getLength() < 2) { + goto err1; +@@ -1243,13 +1313,15 @@ + if (tokens->getLength() != 3) { + goto err2; + } +- param->t1.fileName = ((GString *)tokens->get(2))->copy(); ++ file = (GString *)tokens->get(2); ++ param->t1.fileName = qualify_filename(this->path, file); + break; + case displayFontTT: + if (tokens->getLength() != 3) { + goto err2; + } +- param->tt.fileName = ((GString *)tokens->get(2))->copy(); ++ file = (GString *)tokens->get(2); ++ param->tt.fileName = qualify_filename(this->path, file); + break; + } + +--- xpdf/GlobalParams.h.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/GlobalParams.h 2010-08-16 14:02:38.000000000 -0700 +@@ -196,7 +196,7 @@ + // file. + GlobalParams(char *cfgFileName); + +- ~GlobalParams(); ++ virtual ~GlobalParams(); + + void setBaseDir(char *dir); + void setupBaseFonts(char *dir); +@@ -213,8 +213,8 @@ + FILE *getUnicodeMapFile(GString *encodingName); + FILE *findCMapFile(GString *collection, GString *cMapName); + FILE *findToUnicodeFile(GString *name); +- DisplayFontParam *getDisplayFont(GString *fontName); +- DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection); ++ virtual DisplayFontParam *getDisplayFont(GString *fontName); ++ virtual DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection); + GString *getPSFile(); + int getPSPaperWidth(); + int getPSPaperHeight(); +@@ -316,7 +316,7 @@ + private: + + void createDefaultKeyBindings(); +- void parseFile(GString *fileName, FILE *f); ++public: void parseFile(GString *fileName, FILE *f); private: + void parseNameToUnicode(GList *tokens, GString *fileName, int line); + void parseCIDToUnicode(GList *tokens, GString *fileName, int line); + void parseUnicodeToUnicode(GList *tokens, GString *fileName, int line); +@@ -358,6 +358,10 @@ + GBool loadPlugin(char *type, char *name); + #endif + ++ //----- config file base path ++ ++ GString*path; ++ + //----- static tables + + NameToCharCode * // mapping from char name to +--- xpdf/JBIG2Stream.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/JBIG2Stream.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -6,7 +6,24 @@ + // + //======================================================================== + +-#include ++//======================================================================== ++// ++// Modified under the Poppler project - http://poppler.freedesktop.org ++// ++// All changes made under the Poppler project to this file are licensed ++// under GPL version 2 or later ++// ++// Copyright (C) 2006 Raj Kumar ++// Copyright (C) 2006 Paul Walmsley ++// Copyright (C) 2006-2009 Albert Astals Cid ++// Copyright (C) 2009 David Benjamin ++// ++// To see a description of the changes please see the Changelog file that ++// came with your tarball or type make ChangeLog if you are building from git ++// ++//======================================================================== ++ ++#include + + #ifdef USE_GCC_PRAGMAS + #pragma implementation +@@ -24,8 +41,8 @@ + + //------------------------------------------------------------------------ + +-static int contextSize[4] = { 16, 13, 10, 10 }; +-static int refContextSize[2] = { 13, 10 }; ++static const int contextSize[4] = { 16, 13, 10, 10 }; ++static const int refContextSize[2] = { 13, 10 }; + + //------------------------------------------------------------------------ + // JBIG2HuffmanTable +@@ -42,7 +59,7 @@ + Guint prefix; + }; + +-JBIG2HuffmanTable huffTableA[] = { ++static JBIG2HuffmanTable huffTableA[] = { + { 0, 1, 4, 0x000 }, + { 16, 2, 8, 0x002 }, + { 272, 3, 16, 0x006 }, +@@ -50,7 +67,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableB[] = { ++static JBIG2HuffmanTable huffTableB[] = { + { 0, 1, 0, 0x000 }, + { 1, 2, 0, 0x002 }, + { 2, 3, 0, 0x006 }, +@@ -61,7 +78,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableC[] = { ++static JBIG2HuffmanTable huffTableC[] = { + { 0, 1, 0, 0x000 }, + { 1, 2, 0, 0x002 }, + { 2, 3, 0, 0x006 }, +@@ -74,7 +91,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableD[] = { ++static JBIG2HuffmanTable huffTableD[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 0, 0x006 }, +@@ -84,7 +101,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableE[] = { ++static JBIG2HuffmanTable huffTableE[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 0, 0x006 }, +@@ -96,7 +113,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableF[] = { ++static JBIG2HuffmanTable huffTableF[] = { + { 0, 2, 7, 0x000 }, + { 128, 3, 7, 0x002 }, + { 256, 3, 8, 0x003 }, +@@ -114,7 +131,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableG[] = { ++static JBIG2HuffmanTable huffTableG[] = { + { -512, 3, 8, 0x000 }, + { 256, 3, 8, 0x001 }, + { 512, 3, 9, 0x002 }, +@@ -133,7 +150,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableH[] = { ++static JBIG2HuffmanTable huffTableH[] = { + { 0, 2, 1, 0x000 }, + { 0, 2, jbig2HuffmanOOB, 0x001 }, + { 4, 3, 4, 0x004 }, +@@ -158,7 +175,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableI[] = { ++static JBIG2HuffmanTable huffTableI[] = { + { 0, 2, jbig2HuffmanOOB, 0x000 }, + { -1, 3, 1, 0x002 }, + { 1, 3, 1, 0x003 }, +@@ -184,7 +201,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableJ[] = { ++static JBIG2HuffmanTable huffTableJ[] = { + { -2, 2, 2, 0x000 }, + { 6, 2, 6, 0x001 }, + { 0, 2, jbig2HuffmanOOB, 0x002 }, +@@ -209,7 +226,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableK[] = { ++static JBIG2HuffmanTable huffTableK[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 1, 0x002 }, + { 4, 4, 0, 0x00c }, +@@ -226,7 +243,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableL[] = { ++static JBIG2HuffmanTable huffTableL[] = { + { 1, 1, 0, 0x000 }, + { 2, 2, 0, 0x002 }, + { 3, 3, 1, 0x006 }, +@@ -243,7 +260,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableM[] = { ++static JBIG2HuffmanTable huffTableM[] = { + { 1, 1, 0, 0x000 }, + { 2, 3, 0, 0x004 }, + { 7, 3, 3, 0x005 }, +@@ -260,7 +277,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableN[] = { ++static JBIG2HuffmanTable huffTableN[] = { + { 0, 1, 0, 0x000 }, + { -2, 3, 0, 0x004 }, + { -1, 3, 0, 0x005 }, +@@ -269,7 +286,7 @@ + { 0, 0, jbig2HuffmanEOT, 0 } + }; + +-JBIG2HuffmanTable huffTableO[] = { ++static JBIG2HuffmanTable huffTableO[] = { + { 0, 1, 0, 0x000 }, + { -1, 3, 0, 0x004 }, + { 1, 3, 0, 0x005 }, +@@ -473,7 +490,7 @@ + } + + int JBIG2MMRDecoder::get2DCode() { +- CCITTCode *p; ++ const CCITTCode *p; + + if (bufLen == 0) { + buf = str->getChar() & 0xff; +@@ -500,7 +517,7 @@ + } + + int JBIG2MMRDecoder::getWhiteCode() { +- CCITTCode *p; ++ const CCITTCode *p; + Guint code; + + if (bufLen == 0) { +@@ -543,7 +560,7 @@ + } + + int JBIG2MMRDecoder::getBlackCode() { +- CCITTCode *p; ++ const CCITTCode *p; + Guint code; + + if (bufLen == 0) { +@@ -670,6 +687,7 @@ + void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp); + Guchar *getDataPtr() { return data; } + int getDataSize() { return h * line; } ++ GBool isOk() { return data != NULL; } + + private: + +@@ -685,10 +703,11 @@ + w = wA; + h = hA; + line = (wA + 7) >> 3; ++ + if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { +- // force a call to gmalloc(-1), which will throw an exception +- h = -1; +- line = 2; ++ error(-1, "invalid width/height"); ++ data = NULL; ++ return; + } + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)gmalloc(h * line + 1); +@@ -701,10 +720,11 @@ + w = bitmap->w; + h = bitmap->h; + line = bitmap->line; ++ + if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { +- // force a call to gmalloc(-1), which will throw an exception +- h = -1; +- line = 2; ++ error(-1, "invalid width/height"); ++ data = NULL; ++ return; + } + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)gmalloc(h * line + 1); +@@ -735,6 +755,9 @@ + + void JBIG2Bitmap::expand(int newH, Guint pixel) { + if (newH <= h || line <= 0 || newH >= (INT_MAX - 1) / line) { ++ error(-1, "invalid width/height"); ++ gfree(data); ++ data = NULL; + return; + } + // need to allocate one extra guard byte for use in combine() +@@ -1002,6 +1025,7 @@ + Guint getSize() { return size; } + void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; } + JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; } ++ GBool isOk() { return bitmaps != NULL; } + void setGenericRegionStats(JArithmeticDecoderStats *stats) + { genericRegionStats = stats; } + void setRefinementRegionStats(JArithmeticDecoderStats *stats) +@@ -1022,13 +1046,9 @@ + JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA): + JBIG2Segment(segNumA) + { +- Guint i; +- + size = sizeA; + bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); +- for (i = 0; i < size; ++i) { +- bitmaps[i] = NULL; +- } ++ if (!bitmaps) size = 0; + genericRegionStats = NULL; + refinementRegionStats = NULL; + } +@@ -1037,9 +1057,7 @@ + Guint i; + + for (i = 0; i < size; ++i) { +- if (bitmaps[i]) { +- delete bitmaps[i]; +- } ++ delete bitmaps[i]; + } + gfree(bitmaps); + if (genericRegionStats) { +@@ -1247,6 +1265,7 @@ + Guint segNum, segFlags, segType, page, segLength; + Guint refFlags, nRefSegs; + Guint *refSegs; ++ int segDataPos; + int c1, c2, c3; + Guint i; + +@@ -1314,6 +1333,9 @@ + goto eofError2; + } + ++ // keep track of the start of the segment data ++ segDataPos = getPos(); ++ + // check for missing page information segment + if (!pageBitmap && ((segType >= 4 && segType <= 7) || + (segType >= 20 && segType <= 43))) { +@@ -1398,6 +1420,45 @@ + break; + } + ++ // Make sure the segment handler read all of the bytes in the ++ // segment data, unless this segment is marked as having an ++ // unknown length (section 7.2.7 of the JBIG2 Final Committee Draft) ++ ++ if (segLength != 0xffffffff) { ++ ++ int segExtraBytes = segDataPos + segLength - getPos(); ++ if (segExtraBytes > 0) { ++ ++ // If we didn't read all of the bytes in the segment data, ++ // indicate an error, and throw away the rest of the data. ++ ++ // v.3.1.01.13 of the LuraTech PDF Compressor Server will ++ // sometimes generate an extraneous NULL byte at the end of ++ // arithmetic-coded symbol dictionary segments when numNewSyms ++ // == 0. Segments like this often occur for blank pages. ++ ++ error(getPos(), "%d extraneous byte%s after segment", ++ segExtraBytes, (segExtraBytes > 1) ? "s" : ""); ++ ++ // Burn through the remaining bytes -- inefficient, but ++ // hopefully we're not doing this much ++ ++ int trash; ++ for (int i = segExtraBytes; i > 0; i--) { ++ readByte(&trash); ++ } ++ ++ } else if (segExtraBytes < 0) { ++ ++ // If we read more bytes than we should have, according to the ++ // segment length field, note an error. ++ ++ error(getPos(), "Previous segment handler read too many bytes"); ++ ++ } ++ ++ } ++ + gfree(refSegs); + } + +@@ -1493,6 +1554,9 @@ + codeTables = new GList(); + numInputSyms = 0; + for (i = 0; i < nRefSegs; ++i) { ++ // This is need by bug 12014, returning gFalse makes it not crash ++ // but we end up with a empty page while acroread is able to render ++ // part of it + if ((seg = findSegment(refSegs[i]))) { + if (seg->getType() == jbig2SegSymbolDict) { + j = ((JBIG2SymbolDict *)seg)->getSize(); +@@ -1503,8 +1567,11 @@ + } + numInputSyms += j; + } else if (seg->getType() == jbig2SegCodeTable) { +- codeTables->append(seg); ++ codeTables->append(seg); + } ++ } else { ++ delete codeTables; ++ return gFalse; + } + } + if (numInputSyms > UINT_MAX - numNewSyms) { +@@ -1514,11 +1581,14 @@ + } + + // compute symbol code length +- symCodeLen = 1; +- i = (numInputSyms + numNewSyms) >> 1; +- while (i) { +- ++symCodeLen; +- i >>= 1; ++ symCodeLen = 0; ++ i = 1; ++ while (i < numInputSyms + numNewSyms) { ++ ++symCodeLen; ++ i <<= 1; ++ } ++ if (huff && symCodeLen == 0) { ++ symCodeLen = 1; + } + + // get the input symbol bitmaps +@@ -1530,12 +1600,11 @@ + k = 0; + inputSymbolDict = NULL; + for (i = 0; i < nRefSegs; ++i) { +- if ((seg = findSegment(refSegs[i]))) { +- if (seg->getType() == jbig2SegSymbolDict) { +- inputSymbolDict = (JBIG2SymbolDict *)seg; +- for (j = 0; j < inputSymbolDict->getSize(); ++j) { +- bitmaps[k++] = inputSymbolDict->getBitmap(j); +- } ++ seg = findSegment(refSegs[i]); ++ if (seg != NULL && seg->getType() == jbig2SegSymbolDict) { ++ inputSymbolDict = (JBIG2SymbolDict *)seg; ++ for (j = 0; j < inputSymbolDict->getSize(); ++j) { ++ bitmaps[k++] = inputSymbolDict->getBitmap(j); + } + } + } +@@ -1753,6 +1822,10 @@ + + // create the symbol dict object + symbolDict = new JBIG2SymbolDict(segNum, numExSyms); ++ if (!symbolDict->isOk()) { ++ delete symbolDict; ++ goto syntaxError; ++ } + + // exported symbol list + i = j = 0; +@@ -1766,6 +1839,7 @@ + if (i + run > numInputSyms + numNewSyms || + (ex && j + run > numExSyms)) { + error(getPos(), "Too many exported symbols in JBIG2 symbol dictionary"); ++ for ( ; j < numExSyms; ++j) symbolDict->setBitmap(j, NULL); + delete symbolDict; + goto syntaxError; + } +@@ -1780,6 +1854,7 @@ + } + if (j != numExSyms) { + error(getPos(), "Too few symbols in JBIG2 symbol dictionary"); ++ for ( ; j < numExSyms; ++j) symbolDict->setBitmap(j, NULL); + delete symbolDict; + goto syntaxError; + } +@@ -1921,6 +1996,9 @@ + ++symCodeLen; + i <<= 1; + } ++ if (huff && symCodeLen == 0) { ++ symCodeLen = 1; ++ } + + // get the symbol bitmaps + syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *)); +@@ -2095,18 +2173,20 @@ + + gfree(syms); + +- // combine the region bitmap into the page bitmap +- if (imm) { +- if (pageH == 0xffffffff && y + h > curPageH) { +- pageBitmap->expand(y + h, pageDefPixel); +- } +- pageBitmap->combine(bitmap, x, y, extCombOp); +- delete bitmap; ++ if (bitmap) { ++ // combine the region bitmap into the page bitmap ++ if (imm) { ++ if (pageH == 0xffffffff && y + h > curPageH) { ++ pageBitmap->expand(y + h, pageDefPixel); ++ } ++ pageBitmap->combine(bitmap, x, y, extCombOp); ++ delete bitmap; + +- // store the region bitmap +- } else { +- bitmap->setSegNum(segNum); +- segments->append(bitmap); ++ // store the region bitmap ++ } else { ++ bitmap->setSegNum(segNum); ++ segments->append(bitmap); ++ } + } + + // clean up the Huffman decoder +@@ -2159,6 +2239,10 @@ + + // allocate the bitmap + bitmap = new JBIG2Bitmap(0, w, h); ++ if (!bitmap->isOk()) { ++ delete bitmap; ++ return NULL; ++ } + if (defPixel) { + bitmap->clearToOne(); + } else { +@@ -2235,73 +2319,84 @@ + ri = 0; + } + if (ri) { ++ GBool decodeSuccess; + if (huff) { +- huffDecoder->decodeInt(&rdw, huffRDWTable); +- huffDecoder->decodeInt(&rdh, huffRDHTable); +- huffDecoder->decodeInt(&rdx, huffRDXTable); +- huffDecoder->decodeInt(&rdy, huffRDYTable); +- huffDecoder->decodeInt(&bmSize, huffRSizeTable); ++ decodeSuccess = huffDecoder->decodeInt(&rdw, huffRDWTable); ++ decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdh, huffRDHTable); ++ decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdx, huffRDXTable); ++ decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdy, huffRDYTable); ++ decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&bmSize, huffRSizeTable); + huffDecoder->reset(); + arithDecoder->start(); + } else { +- arithDecoder->decodeInt(&rdw, iardwStats); +- arithDecoder->decodeInt(&rdh, iardhStats); +- arithDecoder->decodeInt(&rdx, iardxStats); +- arithDecoder->decodeInt(&rdy, iardyStats); ++ decodeSuccess = arithDecoder->decodeInt(&rdw, iardwStats); ++ decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdh, iardhStats); ++ decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdx, iardxStats); ++ decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdy, iardyStats); ++ } ++ ++ if (decodeSuccess && syms[symID]) ++ { ++ refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx; ++ refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy; ++ ++ symbolBitmap = ++ readGenericRefinementRegion(rdw + syms[symID]->getWidth(), ++ rdh + syms[symID]->getHeight(), ++ templ, gFalse, syms[symID], ++ refDX, refDY, atx, aty); + } +- refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx; +- refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy; +- +- symbolBitmap = +- readGenericRefinementRegion(rdw + syms[symID]->getWidth(), +- rdh + syms[symID]->getHeight(), +- templ, gFalse, syms[symID], +- refDX, refDY, atx, aty); + //~ do we need to use the bmSize value here (in Huffman mode)? + } else { + symbolBitmap = syms[symID]; + } + +- // combine the symbol bitmap into the region bitmap +- //~ something is wrong here - refCorner shouldn't degenerate into +- //~ two cases +- bw = symbolBitmap->getWidth() - 1; +- bh = symbolBitmap->getHeight() - 1; +- if (transposed) { +- switch (refCorner) { +- case 0: // bottom left +- bitmap->combine(symbolBitmap, tt, s, combOp); +- break; +- case 1: // top left +- bitmap->combine(symbolBitmap, tt, s, combOp); +- break; +- case 2: // bottom right +- bitmap->combine(symbolBitmap, tt - bw, s, combOp); +- break; +- case 3: // top right +- bitmap->combine(symbolBitmap, tt - bw, s, combOp); +- break; ++ if (symbolBitmap) { ++ // combine the symbol bitmap into the region bitmap ++ //~ something is wrong here - refCorner shouldn't degenerate into ++ //~ two cases ++ bw = symbolBitmap->getWidth() - 1; ++ bh = symbolBitmap->getHeight() - 1; ++ if (transposed) { ++ switch (refCorner) { ++ case 0: // bottom left ++ bitmap->combine(symbolBitmap, tt, s, combOp); ++ break; ++ case 1: // top left ++ bitmap->combine(symbolBitmap, tt, s, combOp); ++ break; ++ case 2: // bottom right ++ bitmap->combine(symbolBitmap, tt - bw, s, combOp); ++ break; ++ case 3: // top right ++ bitmap->combine(symbolBitmap, tt - bw, s, combOp); ++ break; ++ } ++ s += bh; ++ } else { ++ switch (refCorner) { ++ case 0: // bottom left ++ bitmap->combine(symbolBitmap, s, tt - bh, combOp); ++ break; ++ case 1: // top left ++ bitmap->combine(symbolBitmap, s, tt, combOp); ++ break; ++ case 2: // bottom right ++ bitmap->combine(symbolBitmap, s, tt - bh, combOp); ++ break; ++ case 3: // top right ++ bitmap->combine(symbolBitmap, s, tt, combOp); ++ break; ++ } ++ s += bw; + } +- s += bh; +- } else { +- switch (refCorner) { +- case 0: // bottom left +- bitmap->combine(symbolBitmap, s, tt - bh, combOp); +- break; +- case 1: // top left +- bitmap->combine(symbolBitmap, s, tt, combOp); +- break; +- case 2: // bottom right +- bitmap->combine(symbolBitmap, s, tt - bh, combOp); +- break; +- case 3: // top right +- bitmap->combine(symbolBitmap, s, tt, combOp); +- break; ++ if (ri) { ++ delete symbolBitmap; + } +- s += bw; +- } +- if (ri) { +- delete symbolBitmap; ++ } else { ++ // NULL symbolBitmap only happens on error ++ delete bitmap; ++ return NULL; + } + } + +@@ -2431,11 +2526,12 @@ + error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); + return; + } +- if (!(seg = findSegment(refSegs[0])) || +- seg->getType() != jbig2SegPatternDict) { ++ seg = findSegment(refSegs[0]); ++ if (seg == NULL || seg->getType() != jbig2SegPatternDict) { + error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); + return; + } ++ + patternDict = (JBIG2PatternDict *)seg; + bpp = 0; + i = 1; +@@ -2591,6 +2687,8 @@ + // read the bitmap + bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse, + NULL, atx, aty, mmr ? length - 18 : 0); ++ if (!bitmap) ++ return; + + // combine the region bitmap into the page bitmap + if (imm) { +@@ -2616,7 +2714,7 @@ + int *codingLine, int *a0i, int w) { + if (a1 > codingLine[*a0i]) { + if (a1 > w) { +- error(getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1); ++ error(getPos(), "JBIG2 MMR row is wrong length (%d)", a1); + a1 = w; + } + if ((*a0i & 1) ^ blackPixels) { +@@ -2630,7 +2728,7 @@ + int *codingLine, int *a0i, int w) { + if (a1 > codingLine[*a0i]) { + if (a1 > w) { +- error(getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1); ++ error(getPos(), "JBIG2 MMR row is wrong length (%d)", a1); + a1 = w; + } + if ((*a0i & 1) ^ blackPixels) { +@@ -2657,13 +2755,17 @@ + JBIG2Bitmap *bitmap; + GBool ltp; + Guint ltpCX, cx, cx0, cx1, cx2; +- JBIG2BitmapPtr cxPtr0, cxPtr1; +- JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3; ++ JBIG2BitmapPtr cxPtr0 = {0}, cxPtr1 = {0}; ++ JBIG2BitmapPtr atPtr0 = {0}, atPtr1 = {0}, atPtr2 = {0}, atPtr3 = {0}; + int *refLine, *codingLine; + int code1, code2, code3; + int x, y, a0i, b1i, blackPixels, pix, i; + + bitmap = new JBIG2Bitmap(0, w, h); ++ if (!bitmap->isOk()) { ++ delete bitmap; ++ return NULL; ++ } + bitmap->clearToZero(); + + //----- MMR decode +@@ -2682,7 +2784,7 @@ + // ---> max refLine size = w + 2 + codingLine = (int *)gmallocn(w + 1, sizeof(int)); + refLine = (int *)gmallocn(w + 2, sizeof(int)); +- codingLine[0] = w; ++ for (i = 0; i < w + 1; ++i) codingLine[i] = w; + + for (y = 0; y < h; ++y) { + +@@ -3093,8 +3195,8 @@ + return; + } + if (nRefSegs == 1) { +- if (!(seg = findSegment(refSegs[0])) || +- seg->getType() != jbig2SegBitmap) { ++ seg = findSegment(refSegs[0]); ++ if (seg == NULL || seg->getType() != jbig2SegBitmap) { + error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment"); + return; + } +@@ -3143,11 +3245,24 @@ + JBIG2Bitmap *bitmap; + GBool ltp; + Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2; +- JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6; +- JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2; ++ JBIG2BitmapPtr cxPtr0 = {0}; ++ JBIG2BitmapPtr cxPtr1 = {0}; ++ JBIG2BitmapPtr cxPtr2 = {0}; ++ JBIG2BitmapPtr cxPtr3 = {0}; ++ JBIG2BitmapPtr cxPtr4 = {0}; ++ JBIG2BitmapPtr cxPtr5 = {0}; ++ JBIG2BitmapPtr cxPtr6 = {0}; ++ JBIG2BitmapPtr tpgrCXPtr0 = {0}; ++ JBIG2BitmapPtr tpgrCXPtr1 = {0}; ++ JBIG2BitmapPtr tpgrCXPtr2 = {0}; + int x, y, pix; + + bitmap = new JBIG2Bitmap(0, w, h); ++ if (!bitmap->isOk()) ++ { ++ delete bitmap; ++ return NULL; ++ } + bitmap->clearToZero(); + + // set up the typical row context +@@ -3332,6 +3447,12 @@ + } + pageBitmap = new JBIG2Bitmap(0, pageW, curPageH); + ++ if (!pageBitmap->isOk()) { ++ delete pageBitmap; ++ pageBitmap = NULL; ++ return; ++ } ++ + // default pixel value + if (pageDefPixel) { + pageBitmap->clearToOne(); +--- xpdf/JPXStream.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/JPXStream.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -241,6 +241,12 @@ + haveCompMap = gFalse; + haveChannelDefn = gFalse; + ++ img.xSize = 0; ++ img.ySize = 0; ++ img.xOffset = 0; ++ img.yOffset = 0; ++ curX = 0; ++ curY = 0; + img.tiles = NULL; + bitBuf = 0; + bitBufLen = 0; +@@ -450,6 +456,7 @@ + GBool haveBPC, haveCSMode; + + csPrec = 0; // make gcc happy ++ Guint num_components = 0; + haveBPC = haveCSMode = gFalse; + str->reset(); + if (str->lookChar() == 0xff) { +@@ -463,7 +470,7 @@ + cover(1); + if (readULong(&dummy) && + readULong(&dummy) && +- readUWord(&dummy) && ++ readUWord(&num_components) && + readUByte(&bpc1) && + readUByte(&dummy) && + readUByte(&dummy) && +@@ -519,6 +526,9 @@ + } + } + } ++ if(*csMode == streamCSDeviceRGB && num_components == 4) { ++ *csMode = streamCSDeviceRGBX; ++ } + str->close(); + } + +--- xpdf/Lexer.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/Lexer.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -74,6 +74,7 @@ + curStr.streamReset(); + } + } ++static int illegalChars = 0; + + Lexer::~Lexer() { + if (!curStr.isNone()) { +@@ -83,6 +84,9 @@ + if (freeArray) { + delete streams; + } ++ if(illegalChars) ++ error(0, "Illegal characters in hex string (%d)", illegalChars); ++ illegalChars = 0; + } + + int Lexer::getChar() { +@@ -330,7 +334,8 @@ + } else if (c2 >= 'a' && c2 <= 'f') { + c += c2 - 'a' + 10; + } else { +- error(getPos(), "Illegal digit in hex char in name"); ++ illegalChars++; ++ //error(getPos(), "Illegal digit in hex char in name"); + } + } + notEscChar: +@@ -384,8 +389,10 @@ + c2 += c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + c2 += c - 'a' + 10; +- else +- error(getPos(), "Illegal character <%02x> in hex string", c); ++ else { ++ illegalChars++; ++ //error(getPos(), "Illegal character <%02x> in hex string", c); ++ } + if (++m == 2) { + if (n == tokBufSize) { + if (!s) +@@ -421,7 +428,8 @@ + tokBuf[2] = '\0'; + obj->initCmd(tokBuf); + } else { +- error(getPos(), "Illegal character '>'"); ++ illegalChars++; ++ //error(getPos(), "Illegal character '>'"); + obj->initError(); + } + break; +@@ -430,7 +438,8 @@ + case ')': + case '{': + case '}': +- error(getPos(), "Illegal character '%c'", c); ++ //error(getPos(), "Illegal character '%c'", c); ++ illegalChars++; + obj->initError(); + break; + +@@ -459,7 +468,6 @@ + } + break; + } +- + return obj; + } + +--- xpdf/Link.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/Link.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -430,10 +430,9 @@ + delete dest; + dest = NULL; + } +- + // error + } else { +- error(-1, "Illegal annotation destination"); ++ error(-1, "Illegal annotation destination %d", destObj->getType()); + } + } + +@@ -468,10 +467,9 @@ + delete dest; + dest = NULL; + } +- + // error + } else { +- error(-1, "Illegal annotation destination"); ++ error(-1, "Illegal annotation destination %d", destObj->getType()); + } + } + +--- xpdf/OutputDev.h.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/OutputDev.h 2010-08-16 14:02:38.000000000 -0700 +@@ -17,6 +17,7 @@ + + #include "gtypes.h" + #include "CharTypes.h" ++#include "Object.h" + + class GString; + class GfxState; +--- xpdf/SplashFTFont.h.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/SplashFTFont.h 2010-08-16 14:02:38.000000000 -0700 +@@ -42,6 +42,9 @@ + virtual GBool makeGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap); + ++ // return the number of characters in this font ++ virtual int getNumChars(); ++ + // Return the path for a glyph. + virtual SplashPath *getGlyphPath(int c); + +--- xpdf/SplashFTFontEngine.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/SplashFTFontEngine.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -13,9 +13,7 @@ + #endif + + #include +-#ifndef WIN32 + # include +-#endif + #include "gmem.h" + #include "GString.h" + #include "gfile.h" +--- xpdf/SplashFont.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/SplashFont.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -48,6 +48,10 @@ + cacheTags = NULL; + + xMin = yMin = xMax = yMax = 0; ++ ++ last_advance = -1; ++ ascender = -1; ++ descender = -1; + } + + void SplashFont::initCache() { +@@ -74,11 +78,15 @@ + } else { + cacheSets = 1; + } +- cache = (Guchar *)gmallocn(cacheSets * cacheAssoc, glyphSize); +- cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc, +- sizeof(SplashFontCacheTag)); +- for (i = 0; i < cacheSets * cacheAssoc; ++i) { +- cacheTags[i].mru = i & (cacheAssoc - 1); ++ cache = (Guchar *)gmallocn_noexit(cacheSets * cacheAssoc, glyphSize); ++ if(cache) { ++ cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc, ++ sizeof(SplashFontCacheTag)); ++ for (i = 0; i < cacheSets * cacheAssoc; ++i) { ++ cacheTags[i].mru = i & (cacheAssoc - 1); ++ } ++ } else { ++ cacheAssoc = 0; + } + } + +--- xpdf/SplashFont.h.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/SplashFont.h 2010-08-16 14:02:38.000000000 -0700 +@@ -73,6 +73,9 @@ + virtual GBool makeGlyph(int c, int xFrac, int yFrac, + SplashGlyphBitmap *bitmap) = 0; + ++ // return the number of characters in this font ++ virtual int getNumChars() = 0; ++ + // Return the path for a glyph. + virtual SplashPath *getGlyphPath(int c) = 0; + +@@ -83,6 +86,9 @@ + void getBBox(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA) + { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; } + ++ double ascender; ++ double descender; ++ double last_advance; //set after getGlyphPath() + protected: + + SplashFontFile *fontFile; +--- xpdf/SplashFontFile.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/SplashFontFile.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -11,9 +11,7 @@ + #endif + + #include +-#ifndef WIN32 +-# include +-#endif ++#include + #include "GString.h" + #include "SplashFontFile.h" + #include "SplashFontFileID.h" +--- xpdf/SplashScreen.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/SplashScreen.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -363,6 +363,8 @@ + int SplashScreen::test(int x, int y, Guchar value) { + int xx, yy; + ++ return 1; ++ + if (value < minVal) { + return 0; + } +--- xpdf/SplashXPathScanner.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/SplashXPathScanner.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -394,10 +394,10 @@ + *p++ &= mask; + xx = (xx & ~7) + 8; + } +- for (; xx + 7 <= xx0; xx += 8) { ++ for (; xx + 7 < xx0; xx += 8) { + *p++ = 0x00; + } +- if (xx <= xx0) { ++ if (xx < xx0) { + *p &= 0xff >> (xx0 & 7); + } + } +@@ -417,10 +417,10 @@ + *p++ &= mask; + xx = (xx & ~7) + 8; + } +- for (; xx + 7 <= xx0; xx += 8) { ++ for (; xx + 7 < xx0; xx += 8) { + *p++ = 0x00; + } +- if (xx <= xx0) { ++ if (xx < xx0) { + *p &= 0xff >> (xx0 & 7); + } + } +--- xpdf/Stream.cc.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/Stream.cc 2010-08-16 14:02:38.000000000 -0700 +@@ -18,6 +18,8 @@ + #include + #ifndef WIN32 + #include ++#else ++extern "C" int unlink(char *filename); + #endif + #include + #include +@@ -2456,6 +2458,9 @@ + // check for an EOB run + if (eobRun > 0) { + while (i <= scanInfo.lastCoeff) { ++ if(i>=64) { ++ return gFalse; ++ } + j = dctZigZag[i++]; + if (data[j] != 0) { + if ((bit = readBit()) == EOF) { +@@ -2480,6 +2485,9 @@ + if (c == 0xf0) { + k = 0; + while (k < 16) { ++ if(i>=64) { ++ return gFalse; ++ } + j = dctZigZag[i++]; + if (data[j] == 0) { + ++k; +@@ -2505,6 +2513,9 @@ + } + eobRun += 1 << j; + while (i <= scanInfo.lastCoeff) { ++ if(i>=64) { ++ return gFalse; ++ } + j = dctZigZag[i++]; + if (data[j] != 0) { + if ((bit = readBit()) == EOF) { +@@ -2527,6 +2538,9 @@ + } + k = 0; + do { ++ if(i>=64) { ++ return gFalse; ++ } + j = dctZigZag[i++]; + while (data[j] != 0) { + if ((bit = readBit()) == EOF) { +@@ -2535,6 +2549,9 @@ + if (bit) { + data[j] += 1 << scanInfo.al; + } ++ if(i>=64) { ++ return gFalse; ++ } + j = dctZigZag[i++]; + } + ++k; +--- xpdf/Stream.h.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/Stream.h 2010-08-16 14:02:38.000000000 -0700 +@@ -41,7 +41,8 @@ + streamCSNone, + streamCSDeviceGray, + streamCSDeviceRGB, +- streamCSDeviceCMYK ++ streamCSDeviceCMYK, ++ streamCSDeviceRGBX + }; + + //------------------------------------------------------------------------ +--- xpdf/TextOutputDev.h.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/TextOutputDev.h 2010-08-16 14:02:38.000000000 -0700 +@@ -170,6 +170,7 @@ + friend class TextFlow; + friend class TextWordList; + friend class TextPage; ++ friend class XMLOutputDev; + }; + + //------------------------------------------------------------------------ +--- xpdf/gfile.h.orig 2010-08-16 14:02:38.000000000 -0700 ++++ xpdf/gfile.h 2010-08-16 14:02:38.000000000 -0700 +@@ -58,6 +58,9 @@ + // Get current directory. + extern GString *getCurrentDir(); + ++/* create a temporary filename */ ++char* mktmpname(char*ptr); ++ + // Append a file name to a path string. may be an empty + // string, denoting the current directory). Returns . + extern GString *appendToPath(GString *path, char *fileName); +--- xpdf/gmem.cc.orig 2010-11-12 10:59:45.000000000 -0800 ++++ xpdf/gmem.cc 2010-11-23 10:09:47.000000000 -0800 +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include "gmem.h" +@@ -47,7 +48,7 @@ + + #endif /* DEBUG_MEM */ + +-void *gmalloc(int size) GMEM_EXCEP { ++void *gmalloc(int size, bool exit_on_error) GMEM_EXCEP { + #ifdef DEBUG_MEM + int size1; + char *mem; +@@ -60,7 +61,10 @@ + throw GMemException(); + #else + fprintf(stderr, "Invalid memory allocation size\n"); +- exit(1); ++ if(exit_on_error) ++ exit(1); ++ else ++ return NULL; + #endif + } + if (size == 0) { +@@ -72,7 +76,10 @@ + throw GMemException(); + #else + fprintf(stderr, "Out of memory\n"); +- exit(1); ++ if(exit_on_error) ++ exit(1); ++ else ++ return NULL; + #endif + } + hdr = (GMemHdr *)mem; +@@ -104,7 +111,10 @@ + throw GMemException(); + #else + fprintf(stderr, "Invalid memory allocation size\n"); +- exit(1); ++ if(exit_on_error) ++ exit(1); ++ else ++ return NULL; + #endif + } + if (size == 0) { +@@ -115,14 +125,23 @@ + throw GMemException(); + #else + fprintf(stderr, "Out of memory\n"); +- exit(1); ++ if(exit_on_error) ++ exit(1); ++ else ++ return NULL; + #endif + } + return p; + #endif + } ++void *gmalloc(int size) GMEM_EXCEP { ++ return gmalloc(size, true); ++} ++void *gmalloc_noexit(int size) GMEM_EXCEP { ++ return gmalloc(size, false); ++} + +-void *grealloc(void *p, int size) GMEM_EXCEP { ++void *grealloc(void *p, int size, bool exit_on_error) GMEM_EXCEP { + #ifdef DEBUG_MEM + GMemHdr *hdr; + void *q; +@@ -133,7 +152,10 @@ + throw GMemException(); + #else + fprintf(stderr, "Invalid memory allocation size\n"); +- exit(1); ++ if(exit_on_error) ++ exit(1); ++ else ++ return NULL; + #endif + } + if (size == 0) { +@@ -160,7 +182,10 @@ + throw GMemException(); + #else + fprintf(stderr, "Invalid memory allocation size\n"); +- exit(1); ++ if(exit_on_error) ++ exit(1); ++ else ++ return NULL; + #endif + } + if (size == 0) { +@@ -179,14 +204,23 @@ + throw GMemException(); + #else + fprintf(stderr, "Out of memory\n"); +- exit(1); ++ if(exit_on_error) ++ exit(1); ++ else ++ return NULL; + #endif + } + return q; + #endif + } ++void *grealloc(void *p, int size) GMEM_EXCEP { ++ return grealloc(p, size, true); ++} ++void *grealloc_noexit(void *p, int size) GMEM_EXCEP { ++ return grealloc(p, size, false); ++} + +-void *gmallocn(int nObjs, int objSize) GMEM_EXCEP { ++void *gmallocn(int nObjs, int objSize, bool exit_on_error) GMEM_EXCEP { + int n; + + if (nObjs == 0) { +@@ -198,13 +232,22 @@ + throw GMemException(); + #else + fprintf(stderr, "Bogus memory allocation size\n"); +- exit(1); ++ if(exit_on_error) ++ exit(1); ++ else ++ return NULL; + #endif + } + return gmalloc(n); + } ++void *gmallocn(int nObjs, int objSize) GMEM_EXCEP { ++ return gmallocn(nObjs, objSize, true); ++} ++void *gmallocn_noexit(int nObjs, int objSize) GMEM_EXCEP { ++ return gmallocn(nObjs, objSize, false); ++} + +-void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP { ++void *greallocn(void *p, int nObjs, int objSize, bool exit_on_error) GMEM_EXCEP { + int n; + + if (nObjs == 0) { +@@ -219,11 +262,20 @@ + throw GMemException(); + #else + fprintf(stderr, "Bogus memory allocation size\n"); +- exit(1); ++ if(exit_on_error) ++ exit(1); ++ else ++ return NULL; + #endif + } + return grealloc(p, n); + } ++void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP { ++ return greallocn(p, nObjs, objSize, true); ++} ++void *greallocn_noexit(void *p, int nObjs, int objSize) GMEM_EXCEP { ++ return greallocn(p, nObjs, objSize, false); ++} + + void gfree(void *p) { + #ifdef DEBUG_MEM +--- xpdf/gmem.h.orig 2010-11-12 10:59:45.000000000 -0800 ++++ xpdf/gmem.h 2010-11-23 10:09:43.000000000 -0800 +@@ -37,12 +37,14 @@ + * returns NULL. + */ + extern void *gmalloc(int size) GMEM_EXCEP; ++extern void *gmalloc_noexit(int size) GMEM_EXCEP; + + /* + * Same as realloc, but prints error message and exits if realloc() + * returns NULL. If

    is NULL, calls malloc instead of realloc(). + */ + extern void *grealloc(void *p, int size) GMEM_EXCEP; ++extern void *grealloc_noexit(void *p, int size) GMEM_EXCEP; + + /* + * These are similar to gmalloc and grealloc, but take an object count +@@ -52,6 +54,8 @@ + */ + extern void *gmallocn(int nObjs, int objSize) GMEM_EXCEP; + extern void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP; ++extern void *gmallocn_noexit(int nObjs, int objSize) GMEM_EXCEP; ++extern void *greallocn_noexit(void *p, int nObjs, int objSize) GMEM_EXCEP; + + /* + * Same as free, but checks for and ignores NULL pointers. + +--- xpdf/SplashOutputDev.h.orig 2010-12-14 11:15:36.000000000 -0800 ++++ xpdf/SplashOutputDev.h 2010-12-14 11:20:24.000000000 -0800 +@@ -196,6 +196,10 @@ + virtual void setVectorAntialias(GBool vaa); + #endif + ++ void doUpdateFont(GfxState *state); ++ GBool needFontUpdate; // set when the font needs to be updated ++ ++ SplashPath *convertPath(GfxState *state, GfxPath *path); + private: + + void setupScreenParams(double hDPI, double vDPI); +@@ -204,8 +208,6 @@ + #else + SplashPattern *getColor(GfxGray gray, GfxRGB *rgb); + #endif +- SplashPath *convertPath(GfxState *state, GfxPath *path); +- void doUpdateFont(GfxState *state); + void drawType3Glyph(T3FontCache *t3Font, + T3FontCacheTag *tag, Guchar *data); + static GBool imageMaskSrc(void *data, SplashColorPtr line); +@@ -237,7 +239,6 @@ + T3GlyphStack *t3GlyphStack; // Type 3 glyph context stack + + SplashFont *font; // current font +- GBool needFontUpdate; // set when the font needs to be updated + SplashPath *textClipPath; // clipping path built with text object + + SplashTransparencyGroup * // transparency group stack +--- xpdf/SplashOutputDev.cc.orig 2010-12-14 11:15:36.000000000 -0800 ++++ xpdf/SplashOutputDev.cc 2010-12-14 11:20:14.000000000 -0800 +@@ -13,6 +13,7 @@ + #endif + + #include ++#include + #include + #include "gfile.h" + #include "GlobalParams.h" +@@ -2646,9 +2647,9 @@ + + softMask = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(), + 1, splashModeMono8, gFalse); +- memset(softMask->getDataPtr(), 0, +- softMask->getRowSize() * softMask->getHeight()); ++ memset(softMask->getDataPtr(), 0x00, softMask->getRowSize()*softMask->getHeight()); + p = softMask->getDataPtr() + ty * softMask->getRowSize() + tx; ++ if (txgetWidth() && tygetHeight()) + for (y = 0; y < tBitmap->getHeight(); ++y) { + for (x = 0; x < tBitmap->getWidth(); ++x) { + tBitmap->getPixel(x, y, color); +--- xpdf/SplashFTFont.cc.orig 2010-12-14 11:36:18.000000000 -0800 ++++ xpdf/SplashFTFont.cc 2011-01-06 12:41:38.000000000 -0800 +@@ -46,6 +46,7 @@ + int x, y; + + face = fontFileA->face; ++ + if (FT_New_Size(face, &sizeObj)) { + return; + } +@@ -54,6 +55,10 @@ + if (FT_Set_Pixel_Sizes(face, 0, (int)size)) { + return; + } ++ ++ this->ascender = face->ascender; ++ this->descender = face->descender; ++ + // if the textMat values are too small, FreeType's fixed point + // arithmetic doesn't work so well + textScale = splashSqrt(textMat[2]*textMat[2] + textMat[3]*textMat[3]) / size; +@@ -228,6 +233,12 @@ + GBool needClose; + }; + ++int SplashFTFont::getNumChars() ++{ ++ SplashFTFontFile* ff = (SplashFTFontFile *)fontFile; ++ return ff->face->num_glyphs; ++} ++ + SplashPath *SplashFTFont::getGlyphPath(int c) { + static FT_Outline_Funcs outlineFuncs = { + #if FREETYPE_MINOR <= 1 +@@ -249,6 +260,8 @@ + FT_UInt gid; + FT_Glyph glyph; + ++ this->last_advance = -1; ++ + ff = (SplashFTFontFile *)fontFile; + ff->face->size = sizeObj; + FT_Set_Transform(ff->face, &textMatrix, NULL); +@@ -262,17 +275,26 @@ + // skip the TrueType notdef glyph + return NULL; + } +- if (FT_Load_Glyph(ff->face, gid, FT_LOAD_NO_BITMAP)) { +- return NULL; ++ int error = 0; ++ if ((error=FT_Load_Glyph(ff->face, gid, FT_LOAD_NO_BITMAP))) { ++ if ((error=FT_Load_Glyph(ff->face, gid, FT_LOAD_NO_BITMAP|FT_LOAD_NO_HINTING))) { ++ fprintf(stderr, "Truetype wasn't able to load glyph %d, error %d\n", gid, error); ++ return NULL; ++ } + } + if (FT_Get_Glyph(slot, &glyph)) { + return NULL; + } ++ this->last_advance = glyph->advance.x/65536.0; ++ + path.path = new SplashPath(); + path.textScale = textScale; + path.needClose = gFalse; +- FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline, ++ error = FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline, + &outlineFuncs, &path); ++ if(error) { ++ fprintf(stderr, "Truetype wasn't able to read glyph %d, error %d\n", gid, error); ++ } + if (path.needClose) { + path.path->close(); + } +--- xpdf/FoFiTrueType.cc.orig 2011-03-31 15:20:48.000000000 -0700 ++++ xpdf/FoFiTrueType.cc 2011-03-31 15:21:57.000000000 -0700 +@@ -1917,7 +1917,11 @@ + } else { + pos = getU16BE(tables[i].offset + j*2, &parsedOk); + } +- if (pos < 0 || pos > len) { ++ if(pos > len) { ++ nGlyphs = j; ++ break; ++ } ++ if (pos < 0) { + parsedOk = gFalse; + } + } +--- xpdf/gfile.cc.orig 2012-02-14 16:17:27.000000000 -0800 ++++ xpdf/gfile.cc 2012-03-07 15:55:29.000000000 -0800 +@@ -439,6 +439,53 @@ + #endif + } + ++static char* getTempDir() ++{ ++#ifdef WIN32 ++ char*dir = getenv("TMP"); ++ if(!dir) dir = getenv("TEMP"); ++ if(!dir) dir = getenv("tmp"); ++ if(!dir) dir = getenv("temp"); ++ if(!dir) dir = "C:\\"; ++#else ++ char*dir = getenv("SWFTOOLS_TMP"); ++ if(!dir) dir = "/tmp/"; ++#endif ++ return dir; ++} ++ ++char* mktmpname(char*ptr) { ++ static char tmpbuf[128]; ++ char*dir = getTempDir(); ++ int l = strlen(dir); ++ char*sep = ""; ++ if(!ptr) ++ ptr = tmpbuf; ++ if(l && dir[l-1]!='/' && dir[l-1]!='\\') { ++#ifdef WIN32 ++ sep = "\\"; ++#else ++ sep = "/"; ++#endif ++ } ++ ++ // used to be mktemp. This does remove the warnings, but ++ // It's not exactly an improvement. ++#ifdef HAVE_LRAND48 ++ sprintf(ptr, "%s%s%08x%08x",dir,sep,(unsigned int)lrand48(),(unsigned int)lrand48()); ++#else ++# ifdef HAVE_RAND ++ sprintf(ptr, "%s%s%08x%08x",dir,sep,rand(),rand()); ++# else ++ static int count = 1; ++ sprintf(ptr, "%s%s%08x%04x%04x",dir,sep,time(0),(unsigned int)tmpbuf^((unsigned int)tmpbuf)>>16,count); ++ count ++; ++# endif ++#endif ++ return ptr; ++} ++ ++ + GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) { + #if defined(WIN32) + //---------- Win32 ---------- +@@ -451,7 +498,7 @@ + // this has the standard race condition problem, but I haven't found + // a better way to generate temp file names with extensions on + // Windows +- if ((tempDir = getenv("TEMP"))) { ++ if ((tempDir = getenv("SWFTOOLS_TMP"))) { + s = new GString(tempDir); + s->append('\\'); + } else { +@@ -460,7 +507,7 @@ + s->append("x"); + t = (int)time(NULL); + for (i = 0; i < 1000; ++i) { +- sprintf(buf, "%d", t + i); ++ sprintf(buf, "%08x-%08x", t + i, GetCurrentThreadId()); + s2 = s->copy()->append(buf); + if (ext) { + s2->append(ext); +@@ -468,8 +515,7 @@ + if (!(f2 = fopen(s2->getCString(), "r"))) { + if (!(f2 = fopen(s2->getCString(), mode))) { + delete s2; +- delete s; +- return gFalse; ++ continue; + } + *name = s2; + *f = f2; +@@ -479,6 +525,7 @@ + fclose(f2); + delete s2; + } ++ fprintf(stderr, "Couldn't create temporary file\n"); + delete s; + return gFalse; + #elif defined(VMS) || defined(__EMX__) || defined(ACORN) || defined(MACOS) +@@ -489,7 +536,7 @@ + // with this file name after the tmpnam call and before the fopen + // call. I will happily accept fixes to this function for non-Unix + // OSs. +- if (!(s = tmpnam(NULL))) { ++ if (!(s = mktmpname(NULL))) { + return gFalse; + } + *name = new GString(s); +@@ -508,7 +555,7 @@ + + if (ext) { + #if HAVE_MKSTEMPS +- if ((s = getenv("TMPDIR"))) { ++ if ((s = getenv("SWFTOOLS_TMP"))) { + *name = new GString(s); + } else { + *name = new GString("/tmp"); +@@ -516,7 +563,7 @@ + (*name)->append("/XXXXXX")->append(ext); + fd = mkstemps((*name)->getCString(), strlen(ext)); + #else +- if (!(s = tmpnam(NULL))) { ++ if (!(s = mktmpname(NULL))) { + return gFalse; + } + *name = new GString(s); +@@ -525,7 +572,7 @@ + #endif + } else { + #if HAVE_MKSTEMP +- if ((s = getenv("TMPDIR"))) { ++ if ((s = getenv("SWFTOOLS_TMP"))) { + *name = new GString(s); + } else { + *name = new GString("/tmp"); +@@ -533,7 +580,7 @@ + (*name)->append("/XXXXXX"); + fd = mkstemp((*name)->getCString()); + #else // HAVE_MKSTEMP +- if (!(s = tmpnam(NULL))) { ++ if (!(s = mktmpname(NULL))) { + return gFalse; + } + *name = new GString(s); +--- xpdf/pdftoppm.cc.orig 2012-03-07 16:09:56.000000000 -0800 ++++ xpdf/pdftoppm.cc 2012-03-07 16:11:57.000000000 -0800 +@@ -7,7 +7,11 @@ + //======================================================================== + + #include ++#include ++#include ++#include + #include ++#include + #include "parseargs.h" + #include "gmem.h" + #include "GString.h" +@@ -93,6 +97,13 @@ + + exitCode = 99; + ++#ifdef HAVE_LRAND48 ++ srand48(time(0)*getpid()); ++#endif ++#ifdef HAVE_RAND ++ srand(time(0)*getpid()); ++#endif ++ + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (mono && gray) { +--- xpdf/pdftotext.cc.orig 2012-03-07 16:09:56.000000000 -0800 ++++ xpdf/pdftotext.cc 2012-03-07 16:21:49.000000000 -0800 +@@ -11,6 +11,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include "parseargs.h" + #include "GString.h" + #include "gmem.h" +@@ -101,6 +104,13 @@ + + exitCode = 99; + ++#ifdef HAVE_LRAND48 ++ srand48(time(0)*getpid()); ++#endif ++#ifdef HAVE_RAND ++ srand(time(0)*getpid()); ++#endif ++ + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) { +--- xpdf/pdfinfo.cc.orig 2012-03-07 16:09:56.000000000 -0800 ++++ xpdf/pdfinfo.cc 2012-03-07 16:21:40.000000000 -0800 +@@ -12,6 +12,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include "parseargs.h" + #include "GString.h" +@@ -95,6 +98,13 @@ + + exitCode = 99; + ++#ifdef HAVE_LRAND48 ++ srand48(time(0)*getpid()); ++#endif ++#ifdef HAVE_RAND ++ srand(time(0)*getpid()); ++#endif ++ + // parse args + ok = parseArgs(argDesc, &argc, argv); + if (!ok || argc != 2 || printVersion || printHelp) { diff -Nru swftools-0.9.2+ds1/lib/python/mypython.c swftools-0.9.1/lib/python/mypython.c --- swftools-0.9.2+ds1/lib/python/mypython.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/python/mypython.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,7 @@ +#include + +int main(int argn, char*argv[]) +{ + void* dummy = malloc(4096); + return Py_Main(argn, argv); +} diff -Nru swftools-0.9.2+ds1/lib/ruby/extconf.rb swftools-0.9.1/lib/ruby/extconf.rb --- swftools-0.9.2+ds1/lib/ruby/extconf.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/ruby/extconf.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,21 @@ +require 'mkmf' +require 'rbconfig' + +$LDFLAGS << " -L.. " +$LIBS << " -lm -lstdc++ " + +dir_config 'gfx' + +have_library("z", "deflate") +have_library("zzip", "zzip_get_default_io") +have_library("jpeg", "jpeg_write_raw_data") +have_library("fftw3", "fftw_plan_dft_r2c_2d") +have_library("freetype", "FT_Init_FreeType") +have_library("fontconfig", "FcInit") +have_library("base", "ringbuffer_init") +have_library("gfx", "gfxfontlist_create") +have_library("gfxpdf", "gfxsource_pdf_create") +have_library("rfxswf", "swf_uncgi") +have_library("gfxswf", "gfxdevice_swf_init") + +create_makefile('gfx') diff -Nru swftools-0.9.2+ds1/lib/ruby/gfx.c swftools-0.9.1/lib/ruby/gfx.c --- swftools-0.9.2+ds1/lib/ruby/gfx.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/ruby/gfx.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,855 @@ +#include +#include "../../config.h" +#include "../gfxdevice.h" +#include "../gfxsource.h" +#include "../gfxtools.h" +#include "../gfximage.h" +#include "../gfxfont.h" +#include "../gfxfilter.h" +#include "../devices/pdf.h" +#include "../readers/swf.h" +#include "../readers/image.h" +#include "../pdf/pdf.h" +#include "../mem.h" +#include "../types.h" +#include "../log.h" +#include "../args.h" + +#define RUBY_GFX_VERSION "0.9.0" + +static VALUE GFX; +static VALUE Font, Glyph, Bitmap, Document, DocumentPage, PDFClass, SWFClass, ImageClass, Device; +static ID id_doc; + +typedef struct doc_internal { + VALUE self; + gfxsource_t*driver; // filled by alloc + gfxdocument_t*doc; + gfxfontlist_t*fontlist; +} doc_internal_t; + +typedef struct page_internal { + doc_internal_t*doc; + gfxpage_t*page; +} page_internal_t; + +typedef struct image_internal { + doc_internal_t*doc; + gfximage_t*image; +} image_internal_t; + +typedef struct font_internal { + VALUE self; + VALUE glyph_array; + gfxfont_t*font; +} font_internal_t; + +typedef struct glyph_internal { + font_internal_t*font; + int nr; +} glyph_internal_t; + +static gfxsource_t* pdfdriver = 0; +static gfxsource_t* imagedriver = 0; +static gfxsource_t* swfdriver = 0; + +#define Get_Doc(doc,cls) doc_internal_t*doc=0;Data_Get_Struct(cls, doc_internal_t, doc); +#define Get_Page(page,cls) page_internal_t*page=0;Data_Get_Struct(cls, page_internal_t, page); + +static VALUE doc_allocate(VALUE cls, gfxsource_t*driver); +static VALUE page_allocate(VALUE cls); + +// ------------------------ documents --------------------------------------- + +static VALUE doc_initialize(VALUE cls, VALUE _filename) +{ + Check_Type(_filename, T_STRING); + Get_Doc(doc,cls); + const char*filename = StringValuePtr(_filename); + doc->fontlist = gfxfontlist_create(); + doc->doc = pdfdriver->open(pdfdriver, filename); + if(!doc->doc) { + rb_raise(rb_eIOError, "couldn't open %s", filename); + } + return cls; +} + +static VALUE doc_num_pages(VALUE cls) +{ + Get_Doc(doc,cls) + return INT2FIX(doc->doc->num_pages); +} + +static VALUE doc_get_page(VALUE cls, VALUE _nr) +{ + Check_Type(_nr, T_FIXNUM); + int nr = FIX2INT(_nr); + Get_Doc(doc,cls); + + VALUE v = page_allocate(DocumentPage); + Get_Page(page,v) + page->page = doc->doc->getpage(doc->doc, nr); + page->doc = doc; + if(!page->page) { + rb_raise(rb_eArgError, "No page %d in document", nr); + return Qnil; + } + return v; +} + +static VALUE doc_each_page(VALUE cls) +{ + Get_Doc(doc,cls); + int t; + for(t=1;t<=doc->doc->num_pages;t++) { + VALUE v = page_allocate(DocumentPage); + Get_Page(page,v) + page->page = doc->doc->getpage(doc->doc, t); + page->doc = doc; + rb_yield(v); + } + return cls; +} + +static void doc_mark(doc_internal_t*doc) +{ + gfxfontlist_t*l = doc->fontlist; + while(l) { + if(l->user) + rb_gc_mark((VALUE)l->user); + l = l->next; + } +} + +static void doc_free(doc_internal_t*doc) +{ + gfxfontlist_free(doc->fontlist, 0); + if(doc->doc) { + doc->doc->destroy(doc->doc); + } + doc->doc = 0; + free(doc); +} + +static VALUE doc_allocate(VALUE cls, gfxsource_t*driver) +{ + doc_internal_t*doc = 0; + VALUE v = Data_Make_Struct(cls, doc_internal_t, doc_mark, doc_free, doc); + doc->self = v; + memset(doc, 0, sizeof(doc_internal_t)); + doc->driver = driver; + return v; +} + +static VALUE pdf_allocate(VALUE cls) {return doc_allocate(cls, pdfdriver);} +static VALUE swf_allocate(VALUE cls) {return doc_allocate(cls, swfdriver);} +static VALUE imgdrv_allocate(VALUE cls) {return doc_allocate(cls, imagedriver);} + +// ------------------------ doc pages --------------------------------------- + +static void page_free(page_internal_t*page) +{ + if(!page) return; + if(page->page) { + page->page->destroy(page->page); + page->page = 0; + } + free(page); +} +static void page_mark(page_internal_t*page) +{ + rb_gc_mark(page->doc->self); +} +static VALUE page_allocate(VALUE cls) +{ + page_internal_t*page = 0; + VALUE v = Data_Make_Struct(cls, page_internal_t, page_mark, page_free, page); + memset(page, 0, sizeof(page_internal_t)); + return v; +} +static VALUE page_nr(VALUE cls) +{ + Get_Page(page,cls) + return INT2FIX(page->page->nr); +} +static VALUE page_width(VALUE cls) +{ + Get_Page(page,cls) + return INT2FIX(page->page->width); +} +static VALUE page_height(VALUE cls) +{ + Get_Page(page,cls) + return INT2FIX(page->page->height); +} + +// ------------------------ image ------------------------------------------- + +#define Get_Image(image,cls) image_internal_t*image=0;Data_Get_Struct(cls, image_internal_t, image); + +static void image_free(image_internal_t*image) +{ + free(image); +} +static void image_mark(image_internal_t*image) +{ + rb_gc_mark(image->doc->self); +} +static VALUE image_allocate(VALUE cls) +{ + image_internal_t*image = 0; + VALUE v = Data_Make_Struct(cls, image_internal_t, image_mark, image_free, image); + memset(image, 0, sizeof(image_internal_t)); + return v; +} +static VALUE image_width(VALUE cls) +{ + Get_Image(image,cls) + return INT2FIX(image->image->width); +} +static VALUE image_height(VALUE cls) +{ + Get_Image(image,cls) + return INT2FIX(image->image->height); +} +static VALUE image_rescale(VALUE cls, VALUE _width, VALUE _height) +{ + Get_Image(image,cls) + Check_Type(_width, T_FIXNUM); + Check_Type(_height, T_FIXNUM); + int width = FIX2INT(_width); + int height = FIX2INT(_height); + volatile VALUE v_image2 = image_allocate(Bitmap); + Get_Image(image2,v_image2) + image2->doc = image->doc; + image2->image = gfximage_rescale(image->image, width, height); + if(!image2->image) { + rb_raise(rb_eArgError, "Can't rescale to size %dx%d", width, height); + } + return v_image2; +} +static VALUE image_has_alpha(VALUE cls) +{ + Get_Image(image,cls) + int size = image->image->width * image->image->height; + gfxcolor_t*data = image->image->data; + int t; + for(t=0;timage, filename, FIX2INT(quality)); + return cls; +} +static VALUE image_save_png(VALUE cls, VALUE _filename) +{ + Get_Image(image,cls) + Check_Type(_filename, T_STRING); + const char*filename = StringValuePtr(_filename); + gfximage_save_png(image->image, filename); + return cls; +} +VALUE convert_image(doc_internal_t*doc,gfximage_t*_image) +{ + VALUE v = image_allocate(Bitmap); + Get_Image(image,v) + image->image = _image; + image->doc = doc; + return v; +} +void invalidate_image(VALUE v) +{ + Get_Image(image,v) + image->image = 0; +} + +// ------------------------ glyphs ------------------------------------------ + +static VALUE convert_line(gfxline_t*line); + +#define Get_Glyph(glyph,cls) glyph_internal_t*glyph=0;Data_Get_Struct(cls, glyph_internal_t, glyph); + +static void glyph_free(glyph_internal_t*glyph) +{ + free(glyph); +} + +static void glyph_mark(glyph_internal_t*glyph) +{ + rb_gc_mark(glyph->font->self); +} + +static VALUE glyph_allocate(VALUE cls) +{ + glyph_internal_t*glyph = 0; + VALUE v = Data_Make_Struct(cls, glyph_internal_t, glyph_mark, glyph_free, glyph); + memset(glyph, 0, sizeof(glyph_internal_t)); + return v; +} + +static VALUE glyph_polygon(VALUE cls) +{ + Get_Glyph(glyph,cls); + return convert_line(glyph->font->font->glyphs[glyph->nr].line); +} + +static VALUE glyph_advance(VALUE cls) +{ + Get_Glyph(glyph,cls); + return rb_float_new(glyph->font->font->glyphs[glyph->nr].advance); +} + +static VALUE glyph_bbox(VALUE cls) +{ + Get_Glyph(glyph,cls); + gfxbbox_t bbox = gfxline_getbbox(glyph->font->font->glyphs[glyph->nr].line); + return rb_ary_new3(4, rb_float_new(bbox.xmin), + rb_float_new(bbox.ymin), + rb_float_new(bbox.xmax), + rb_float_new(bbox.ymax)); +} + +static VALUE glyph_unicode(VALUE cls) +{ + Get_Glyph(glyph,cls); + return INT2FIX(glyph->font->font->glyphs[glyph->nr].unicode); +} + +// ------------------------ font -------------------------------------------- + +#define Get_Font(font,cls) font_internal_t*font=0;Data_Get_Struct(cls, font_internal_t, font); + +static void font_mark(font_internal_t*font) +{ + rb_gc_mark(font->glyph_array); +} + +static void font_free(font_internal_t*font) +{ + free(font); +} + +static VALUE font_allocate(VALUE cls) +{ + font_internal_t*font = 0; + VALUE v = Data_Make_Struct(cls, font_internal_t, font_mark, font_free, font); + memset(font, 0, sizeof(font_internal_t)); + font->self = v; + return v; +} + +static VALUE font_ascent(VALUE cls) +{ + Get_Font(font,cls); + return rb_float_new(font->font->ascent); +} + +static VALUE font_descent(VALUE cls) +{ + Get_Font(font,cls); + return rb_float_new(font->font->descent); +} + +static VALUE font_name(VALUE cls) +{ + Get_Font(font,cls); + return rb_tainted_str_new2(font->font->id); +} + +static VALUE font_glyphs(VALUE cls) +{ + Get_Font(font,cls); + return font->glyph_array; +} + +static VALUE font_save_ttf(VALUE cls, VALUE _filename) +{ + Get_Font(font,cls); + Check_Type(_filename, T_STRING); + const char*filename = StringValuePtr(_filename); + gfxfont_save(font->font, filename); + return Qnil; +} + +static VALUE font_save_eot(VALUE cls, VALUE _filename) +{ + Get_Font(font,cls); + Check_Type(_filename, T_STRING); + const char*filename = StringValuePtr(_filename); + gfxfont_save_eot(font->font, filename); + return Qnil; +} + +// ------------------------ gfx device -------------------------------------- + +typedef struct device_internal { + doc_internal_t*doc; + VALUE v; +} device_internal_t; + +static ID id_setparameter = 0; +static ID id_startpage = 0; +static ID id_startclip = 0; +static ID id_endclip = 0; +static ID id_stroke = 0; +static ID id_fill = 0; +static ID id_fillbitmap = 0; +static ID id_fillgradient = 0; +static ID id_addfont = 0; +static ID id_drawchar = 0; +static ID id_drawlink = 0; +static ID id_endpage = 0; +static ID id_geterror = 0; +static ID id_finish = 0; +static ID id_butt = 0; +static ID id_round = 0; +static ID id_square = 0; +static ID id_bevel = 0; +static ID id_miter = 0; +static ID id_move = 0; +static ID id_line = 0; +static ID id_spline = 0; +static ID id_radial = 0; +static ID id_linear = 0; +static ID id_remove_font_transforms = 0; +static ID id_maketransparent = 0; +static ID id_vectors_to_glyphs = 0; + +static VALUE noop(int argc, VALUE *argv, VALUE obj) {return obj;} + +#define forward(v,id,args...) rb_respond_to((v), (id))?rb_funcall((v), (id), args):0 + +VALUE convert_line(gfxline_t*line) +{ + int len = 0; + gfxline_t*l = line; + while(l) {l=l->next;len++;} + + volatile VALUE array = rb_ary_new2(len); + + int pos = 0; + l = line; + while(l) { + volatile VALUE e; + if(l->type == gfx_moveTo) { + e = rb_ary_new3(3, ID2SYM(id_move), Qfalse, Qfalse); + rb_ary_store(array, pos, e); + rb_ary_store(e, 1, rb_float_new(l->x)); + rb_ary_store(e, 2, rb_float_new(l->y)); + } else if(l->type == gfx_lineTo) { + e = rb_ary_new3(3, ID2SYM(id_line), Qfalse, Qfalse); + rb_ary_store(array, pos, e); + rb_ary_store(e, 1, rb_float_new(l->x)); + rb_ary_store(e, 2, rb_float_new(l->y)); + } else { + e = rb_ary_new3(5, ID2SYM(id_spline), Qfalse, Qfalse, Qfalse, Qfalse); + rb_ary_store(array, pos, e); + rb_ary_store(e, 1, rb_float_new(l->x)); + rb_ary_store(e, 2, rb_float_new(l->y)); + rb_ary_store(e, 3, rb_float_new(l->sx)); + rb_ary_store(e, 4, rb_float_new(l->sy)); + } + pos++; + l=l->next; + } + return array; +} +VALUE convert_color(gfxcolor_t*color) +{ + return rb_ary_new3(4, INT2FIX(color->a), INT2FIX(color->r), INT2FIX(color->g), INT2FIX(color->b)); +} +VALUE convert_matrix(gfxmatrix_t*matrix) +{ + volatile VALUE array = rb_ary_new2(3); + volatile VALUE a = rb_ary_new2(2); + rb_ary_store(array, 0, a); + rb_ary_store(a, 0, rb_float_new(matrix->m00)); + rb_ary_store(a, 1, rb_float_new(matrix->m01)); + a = rb_ary_new2(2); + rb_ary_store(array, 1, a); + rb_ary_store(a, 0, rb_float_new(matrix->m10)); + rb_ary_store(a, 1, rb_float_new(matrix->m11)); + a = rb_ary_new2(2); + rb_ary_store(array, 2, a); + rb_ary_store(a, 0, rb_float_new(matrix->tx)); + rb_ary_store(a, 1, rb_float_new(matrix->ty)); + return array; +} +static VALUE font_is_cached(device_internal_t*i, gfxfont_t*font) +{ + return (VALUE)gfxfontlist_getuserdata(i->doc->fontlist, font->id); +} +static void cache_font(device_internal_t*i, gfxfont_t*font, VALUE v) +{ + i->doc->fontlist = gfxfontlist_addfont2(i->doc->fontlist, font, (void*)v); +} +static VALUE convert_font(gfxfont_t*font) +{ + volatile VALUE v2 = font_allocate(Font); + Get_Font(f, v2); + f->font = font; + f->glyph_array = rb_ary_new2(font->num_glyphs); + + int t; + for(t=0;tnum_glyphs;t++) { + volatile VALUE a = glyph_allocate(Glyph); + rb_ary_store(f->glyph_array, t, a); + Get_Glyph(g, a); + g->font = f; + g->nr = t; + } + return v2; +} +static VALUE convert_gradient(gfxgradient_t*gradient) +{ + return Qnil; //TODO +} +#define HEAD \ + device_internal_t*i = (device_internal_t*)dev->internal; \ + VALUE v = i->v; +int rb_setparameter(gfxdevice_t*dev, const char*key, const char*value) +{ + HEAD + volatile VALUE v_key = rb_tainted_str_new2(key); + volatile VALUE v_value = rb_tainted_str_new2(value); + VALUE ret = forward(v,id_setparameter,2,v_key,v_value); + return 0; +} +void rb_startpage(gfxdevice_t*dev, int width, int height) +{ + HEAD + VALUE ret = forward(v,id_startpage,2,INT2FIX(width),INT2FIX(height)); +} +void rb_startclip(gfxdevice_t*dev, gfxline_t*line) +{ + HEAD + volatile VALUE v_line = convert_line(line); + VALUE ret = forward(v,id_startclip,1,v_line); +} +void rb_endclip(gfxdevice_t*dev) +{ + HEAD + VALUE ret = forward(v,id_endclip,0); +} +void rb_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit) +{ + HEAD + + ID cap = 0; + if(cap_style == gfx_capButt) cap = id_butt; + else if(cap_style == gfx_capRound) cap = id_round; + else if(cap_style == gfx_capSquare) cap = id_square; + + ID joint = 0; + if(joint_style == gfx_joinRound) joint = id_round; + else if(joint_style == gfx_joinMiter) joint = id_miter; + else if(joint_style == gfx_joinBevel) joint = id_bevel; + + volatile VALUE v_line = convert_line(line); + volatile VALUE v_width = rb_float_new(width); + volatile VALUE v_color = convert_color(color); + volatile VALUE v_miter = rb_float_new(miterLimit); + forward(v, id_stroke, 6, v_line, v_width, v_color, ID2SYM(cap), ID2SYM(joint), v_miter); +} +void rb_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) +{ + HEAD + + volatile VALUE v_line = convert_line(line); + volatile VALUE v_color = convert_color(color); + forward(v, id_fill, 2, v_line, v_color); +} +void rb_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform) +{ + HEAD + volatile VALUE v_image = convert_image(i->doc, img); + volatile VALUE v_line = convert_line(line); + volatile VALUE v_matrix = convert_matrix(matrix); + forward(v, id_fillbitmap, 4, v_line, v_image, v_matrix, Qnil); + invalidate_image(v_image); +} +void rb_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix) +{ + HEAD + ID typeid = (type == gfxgradient_linear)? id_linear : id_radial; + + volatile VALUE v_line = convert_line(line); + volatile VALUE v_matrix = convert_matrix(matrix); + volatile VALUE v_gradient = convert_gradient(gradient); + forward(v, id_fillgradient, 4, v_line, v_gradient, ID2SYM(typeid), v_matrix); +} +void rb_addfont(gfxdevice_t*dev, gfxfont_t*font) +{ + HEAD + + volatile VALUE f = font_is_cached(i, font); + if(!f) {f=convert_font(font);cache_font(i,font,f);} + + forward(v, id_addfont, 1, f); +} +void rb_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix) +{ + HEAD + volatile VALUE f = font_is_cached(i, font); + if(!f) {f=convert_font(font);cache_font(i,font,f);} + + volatile VALUE v_color = convert_color(color); + volatile VALUE v_matrix = convert_matrix(matrix); + forward(v, id_drawchar, 4, f, INT2FIX(glyphnr), v_color, v_matrix); +} +void rb_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action, const char*text) +{ + HEAD + volatile VALUE v_line = convert_line(line); + volatile VALUE v_action = rb_tainted_str_new2(action); + volatile VALUE v_text = rb_tainted_str_new2(text); + + forward(v, id_drawlink, 3, v_line, v_action, v_text); +} +void rb_endpage(gfxdevice_t*dev) +{ + HEAD + forward(v, id_endpage, 0); +} +void gfxresult_rb_destroy(gfxresult_t*r) +{ + free(r); +} +gfxresult_t* rb_finish(gfxdevice_t*dev) +{ + HEAD + VALUE ret = forward(v, id_finish, 0); + gfxresult_t*r = (gfxresult_t*)rfx_calloc(sizeof(gfxresult_t)); + r->destroy = gfxresult_rb_destroy; + r->internal = (void*)(ptroff_t)ret; + return r; +} + +#define make_device(dev, idoc, device) \ + gfxdevice_t dev; \ + device_internal_t i; \ + i.v = device; \ + i.doc = idoc; \ + dev.internal = &i; \ + dev.setparameter = rb_setparameter; \ + dev.startpage = rb_startpage; \ + dev.startclip = rb_startclip; \ + dev.endclip = rb_endclip; \ + dev.stroke = rb_stroke; \ + dev.fill = rb_fill; \ + dev.fillbitmap = rb_fillbitmap; \ + dev.fillgradient = rb_fillgradient; \ + dev.addfont = rb_addfont; \ + dev.drawchar = rb_drawchar; \ + dev.drawlink = rb_drawlink; \ + dev.endpage = rb_endpage; \ + dev.finish = rb_finish; + +static VALUE page_render(VALUE cls, VALUE device) +{ + Check_Type(device, T_OBJECT); + Get_Page(page,cls) + + make_device(dev, page->doc, device); + + dev.startpage(&dev, page->page->width, page->page->height); + page->page->render(page->page, &dev); + dev.endpage(&dev); + + return cls; +} + +static VALUE doc_render(VALUE cls, VALUE device, VALUE _range, VALUE filters) +{ + const char*range = 0; + if(!NIL_P(_range)) { + Check_Type(_range, T_STRING); + range = StringValuePtr(_range); + } + Get_Doc(doc,cls); + + make_device(_dev, doc, device); + gfxdevice_t*dev = &_dev; + + if(!NIL_P(filters)) { + if(TYPE(filters) != T_ARRAY) + rb_raise(rb_eArgError, "third argument of doc->render must be an array of symbols"); + + int len = RARRAY_LEN(filters); + int t=0; + while(tdoc->num_pages;pagenr++) { + if(is_in_range(pagenr, (char*)range)) { + gfxpage_t*page = doc->doc->getpage(doc->doc, pagenr); + dev->startpage(dev, page->width, page->height); + page->render(page, dev); + dev->endpage(dev); + page->destroy(page); + } + } + + + gfxresult_t*r = dev->finish(dev); + r->destroy(r); + + return Qnil; +} + +static VALUE doc_prepare(VALUE cls, VALUE device) +{ + Get_Doc(doc,cls); + make_device(dev, doc, device); + doc->doc->prepare(doc->doc, &dev); + return cls; +} + + +// ---------------------- global functions ---------------------------------- + +VALUE gfx_setparameter(VALUE module, VALUE _key, VALUE _value) +{ + Check_Type(_key, T_STRING); + Check_Type(_value, T_STRING); + const char*key = StringValuePtr(_key); + const char*value = StringValuePtr(_value); + pdfdriver->setparameter(pdfdriver, key, value); + swfdriver->setparameter(swfdriver, key, value); + imagedriver->setparameter(imagedriver, key, value); + return GFX; +} + +// -------------------------------------------------------------------------- + +void Init_gfx() +{ + initLog(0,0,0,0,0,2); +#ifdef HAVE_SRAND48 + srand48(time(0)); +#else +#ifdef HAVE_SRAND + srand(time(0)); +#endif +#endif + + pdfdriver = gfxsource_pdf_create(); + swfdriver = gfxsource_swf_create(); + imagedriver = gfxsource_image_create(); + + GFX = rb_define_module("GFX"); + rb_define_const(GFX, "VERSION", INT2FIX(20100309)); + + rb_define_module_function(GFX, "setparameter", gfx_setparameter, 2); + + DocumentPage = rb_define_class_under(GFX, "DocumentPage", rb_cObject); + rb_define_method(DocumentPage, "width", page_width, 0); + rb_define_method(DocumentPage, "height", page_height, 0); + rb_define_method(DocumentPage, "nr", page_nr, 0); + rb_define_method(DocumentPage, "render", page_render, 1); + + Document = rb_define_class_under(GFX, "Document", rb_cObject); + rb_define_method(Document, "initialize", doc_initialize, 1); + rb_define_method(Document, "page", doc_get_page, 1); + rb_define_method(Document, "each_page", doc_each_page, 0); + rb_define_method(Document, "prepare", doc_prepare, 1); + rb_define_method(Document, "render", doc_render, 3); + + Bitmap = rb_define_class_under(GFX, "Bitmap", rb_cObject); + rb_define_method(Bitmap, "save_jpeg", image_save_jpeg, 2); + rb_define_method(Bitmap, "save_png", image_save_png, 1); + rb_define_method(Bitmap, "width", image_width, 0); + rb_define_method(Bitmap, "height", image_height, 0); + rb_define_method(Bitmap, "rescale", image_rescale, 2); + rb_define_method(Bitmap, "has_alpha", image_has_alpha, 0); + + Glyph = rb_define_class_under(GFX, "Glyph", rb_cObject); + rb_define_method(Glyph, "polygon", glyph_polygon, 0); + rb_define_method(Glyph, "unicode", glyph_unicode, 0); + rb_define_method(Glyph, "advance", glyph_advance, 0); + rb_define_method(Glyph, "bbox", glyph_bbox, 0); + + Font = rb_define_class_under(GFX, "Font", rb_cObject); + rb_define_method(Font, "name", font_name, 0); + rb_define_method(Font, "ascent", font_ascent, 0); + rb_define_method(Font, "descent", font_descent, 0); + rb_define_method(Font, "glyphs", font_glyphs, 0); + rb_define_method(Font, "save_ttf", font_save_ttf, 1); + rb_define_method(Font, "save_eot", font_save_eot, 1); + + Device = rb_define_class_under(GFX, "Device", rb_cObject); + rb_define_method(Device, "startpage", noop, -1); + rb_define_method(Device, "endpage", noop, -1); + rb_define_method(Device, "startclip", noop, -1); + rb_define_method(Device, "endclip", noop, -1); + rb_define_method(Device, "stroke", noop, -1); + rb_define_method(Device, "fill", noop, -1); + rb_define_method(Device, "fillbitmap", noop, -1); + rb_define_method(Device, "fillgradient", noop, -1); + rb_define_method(Device, "addfont", noop, -1); + rb_define_method(Device, "drawchar", noop, -1); + rb_define_method(Device, "drawlink", noop, -1); + + PDFClass = rb_define_class_under(GFX, "PDF", Document); + rb_define_alloc_func(PDFClass, pdf_allocate); + + SWFClass = rb_define_class_under(GFX, "SWF", Document); + rb_define_alloc_func(SWFClass, swf_allocate); + + ImageClass = rb_define_class_under(GFX, "ImageRead", Document); + rb_define_alloc_func(ImageClass, imgdrv_allocate); + + id_setparameter = rb_intern("setparameter"); + id_startpage = rb_intern("startpage") ; + id_startclip = rb_intern("startclip") ; + id_endclip = rb_intern("endclip") ; + id_stroke = rb_intern("stroke") ; + id_fill = rb_intern("fill") ; + id_fillbitmap = rb_intern("fillbitmap") ; + id_fillgradient = rb_intern("fillgradient") ; + id_addfont = rb_intern("addfont") ; + id_drawchar = rb_intern("drawchar") ; + id_drawlink = rb_intern("drawlink") ; + id_endpage = rb_intern("endpage") ; + id_geterror = rb_intern("geterror") ; + id_finish = rb_intern("finish") ; + id_butt = rb_intern("butt"); + id_round = rb_intern("round"); + id_square = rb_intern("square"); + id_miter = rb_intern("miter"); + id_bevel = rb_intern("bevel"); + id_move = rb_intern("move"); + id_line = rb_intern("line"); + id_spline = rb_intern("spline"); + id_radial = rb_intern("radial"); + id_linear = rb_intern("linear"); + id_remove_font_transforms = rb_intern("remove_font_transforms"); + id_maketransparent = rb_intern("maketransparent"); + id_vectors_to_glyphs = rb_intern("vectors_to_glyphs"); +} + diff -Nru swftools-0.9.2+ds1/lib/ruby/Makefile.in swftools-0.9.1/lib/ruby/Makefile.in --- swftools-0.9.2+ds1/lib/ruby/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/ruby/Makefile.in 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,26 @@ +top_builddir = ../.. +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +include ../../Makefile.common + +all: gfx.$(SLEXT) + +gfx.$(O): gfx.c + $(C) $(RUBY_CPPFLAGS) -Wall -Wno-unused -fPIC -c gfx.c -o gfx.$(O) + +GFX_DEPS=../libgfxpdf$(A) ../libgfxswf$(A) ../librfxswf$(A) ../libgfx$(A) ../libocr$(A) ../libbase$(A) +gfx.$(SLEXT): gfx.$(O) $(GFX_DEPS) Makefile + $(L) $(RUBY_LDFLAGS) $(SHARED) gfx.$(O) -o gfx.$(SLEXT) $(GFX_DEPS) $(PYTHON_LIB) $(LIBS) $(RUBY_LIBS) $(CXXLIBS) + +clean: + rm -f *.o *.$(O) *.$(SLEXT) *.so + +INSTALL_LIB = echo installing $$file to $(RUBY_INSTALLDIR);$(INSTALL_PROGRAM) $$file $(RUBY_INSTALLDIR) +UNINSTALL_LIB = rm -f $(RUBY_INSTALLDIR)/$$file +install: + @file=gfx.$(SLEXT); if test -f $$file;then $(INSTALL_LIB);fi + +uninstall: + @file=gfx.$(SLEXT); $(UNINSTALL_LIB) + +.PHONY: all diff -Nru swftools-0.9.2+ds1/lib/ruby/test.rb swftools-0.9.1/lib/ruby/test.rb --- swftools-0.9.2+ds1/lib/ruby/test.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/lib/ruby/test.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,45 @@ +require 'gfx' + +class TestRender < GFX::Device + def startpage(width,height) + puts "startpage(#{width},#{height})" + end + def endpage() + puts "endpage()" + end + def setparameter(key,value) + puts "setparameter(#{key},#{value})" + end + def startclip(line) + puts "startclip(#{line.inspect})" + end + def endclip() + puts "endclip()" + end + def stroke(line, width, color, cap_style, joint_style, miterLimit) + puts "stroke(#{line.inspect}, #{width}, #{color.inspect}, #{cap_style}, #{joint_style}, #{miterLimit})" + end + def fill(line, color) + puts "fill(#{line.inspect}, #{color.inspect})" + end + def fillbitmap(line, img, imgcoord2devcoord, cxform) + puts "fillbitmap(#{line.inspect}, #{img}, #{imgcoord2devcoord}, #{cxform})" + end + def fillgradient(dev, line, gradient, type, gradcoord2devcoord) + puts "fillgradient(#{line.inspect}, #{gradient}, #{type}, #{gradcoord2devcoord})" + end + def addfont(font) + puts "addfont(#{font.name})" + end + def drawchar(font, glyph, color, matrix) + puts "drawchar(#{font.name}, #{glyph}, #{color.inspect}, #{matrix.inspect})" + end + def drawlink(line, action, text) + puts "drawchar(#{line.inspect}, #{action}, #{text})" + end +end + +pdf = GFX::PDF.new('abcdef.pdf') +r = TestRender.new +pdf.render(r, "1-5", [:remove_font_transforms]) + diff -Nru swftools-0.9.2+ds1/m4/fftw.m4 swftools-0.9.1/m4/fftw.m4 --- swftools-0.9.2+ds1/m4/fftw.m4 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/m4/fftw.m4 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,52 @@ +AC_DEFUN([RFX_CHECK_FFTW], +[ + OLDCPPFLAGS="${CPPFLAGS}" + OLDLIBS="${LIBS}" + + AC_CHECK_LIB(fftw3f, fftwf_plan_dft_r2c_2d, [HAVE_LIBFFTW3=1],) + AC_CHECK_HEADERS(fftw3.h,[HAVE_FFTW3_H=1]) + + if test "x${HAVE_LIBFFTW3}" != "x";then + if test "x${HAVE_FFTW3_H}" != "x";then + HAVE_FFTW3=1 + fi + fi + + if test "x${HAVE_FFTW3}" = "x1"; then + LIBS="$LIBS -lfftw3f" + AC_MSG_CHECKING([whether we can compile the fftw3 test program]) + + cat > conftest.c << EOF + #include + + int main() + { + char*data = fftwf_malloc(sizeof(fftwf_complex)*600*800); + fftwf_plan plan = fftwf_plan_dft_2d(600, 800, (fftwf_complex*)data, (fftwf_complex*)data, FFTW_FORWARD, FFTW_ESTIMATE); + plan = fftwf_plan_dft_r2c_2d(600, 800, (float*)data, (fftwf_complex*)data, FFTW_ESTIMATE); + plan = fftwf_plan_dft_c2r_2d(600, 800, (fftwf_complex*)data, (float*)data, FFTW_ESTIMATE); + fftwf_execute(plan); + fftwf_destroy_plan(plan); + } +EOF + + ac_link='$CC $CPPFLAGS $CFLAGS conftest.c $LDFLAGS $LIBS -o conftest${ac_exeext}' + if { (eval echo fftw3.m4:71: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_FFTW3], [1], [Define if fftw3 is available]) + else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 + HAVE_FFTW3=0 + AC_MSG_RESULT(no) + fi + rm -f conftest* + fi + + # if the above didn't work out, reset all changes to the compiler variables. + if test "x${HAVE_FFTW3}" "!=" "x1"; then + CPPFLAGS=$OLDCPPFLAGS + LIBS=$OLDLIBS + fi +]) + diff -Nru swftools-0.9.2+ds1/m4/lowercase.m4 swftools-0.9.1/m4/lowercase.m4 --- swftools-0.9.2+ds1/m4/lowercase.m4 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/m4/lowercase.m4 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,17 @@ +AC_DEFUN([RFX_CHECK_LOWERCASE_UPPERCASE], +[ +AC_MSG_CHECKING([whether the filesystem normalizes file names]) + +echo test1 > __abcdefghijklmnopqrstuvwxyz.txt +echo test2 > __ABCDEFGHIJKLMNOPQRSTUVWXYZ.txt +if test `cat __abcdefghijklmnopqrstuvwxyz.txt` = "test2";then + AC_MSG_RESULT(yes) + AC_DEFINE([LOWERCASE_UPPERCASE], [1], [Define if the file system is case invariant]) +else + AC_MSG_RESULT(no) +fi + +rm -f __abcdefghijklmnopqrstuvwxyz.txt +rm -f __ABCDEFGHIJKLMNOPQRSTUVWXYZ.txt +]) + diff -Nru swftools-0.9.2+ds1/m4/opengl.m4 swftools-0.9.1/m4/opengl.m4 --- swftools-0.9.2+ds1/m4/opengl.m4 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/m4/opengl.m4 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,55 @@ +AC_DEFUN([RFX_CHECK_OPENGL], +[ +OLDCPPFLAGS="${CPPFLAGS}" +OLDLIBS="${LIBS}" + +AC_CHECK_LIB(GL, glBegin) +AC_CHECK_LIB(GLU, gluBeginSurface) +AC_CHECK_LIB(glut, glutInit) +AC_CHECK_HEADERS(GL/gl.h GL/glut.h) + +cat > conftest.c << EOF +#include +#include +#include + +int main(int argc, char*argv[]) +{ + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); + glutInitWindowSize(320,200); + glutInitWindowPosition(0,0); + glutCreateWindow("main"); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glShadeModel(GL_SMOOTH); + glEnable (GL_LINE_SMOOTH); + glEnable (GL_POLYGON_SMOOTH); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE); + glHint (GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE); +} +EOF + +AC_MSG_CHECKING([whether we can compile the opengl test program]) + +ac_link='$CC $CPPFLAGS $CFLAGS conftest.c $LDFLAGS $LIBS -o conftest${ac_exeext}' +if { (eval echo opengl.m4:71: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + AC_MSG_RESULT(yes) + HAVE_OPENGL=1 + AC_DEFINE([HAVE_OPENGL], [1], [Defined if opengl is available]) +else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 + HAVE_OPENGL= + AC_MSG_RESULT(no) +fi +rm -f conftest* + +# if the above didn't work out, reset all changes to the compiler variables. +if test "x${HAVE_OPENGL}" "!=" "x1"; then + CPPFLAGS=$OLDCPPFLAGS + LIBS=$OLDLIBS +fi +]) + diff -Nru swftools-0.9.2+ds1/m4/ruby.m4 swftools-0.9.1/m4/ruby.m4 --- swftools-0.9.2+ds1/m4/ruby.m4 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/m4/ruby.m4 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,94 @@ +AC_DEFUN([RFX_CHECK_RUBY], +[ +AC_PATH_PROG([RUBY], [ruby],,) + +RUBY_CPPFLAGS="" +RUBY_LDFLAGS="" +RUBY_LIBS="" + +rubylib=ruby18 + +AC_MSG_CHECKING([for ruby's include directory]) +if test "x$RUBY" '!=' "x";then + rubyinc=`$RUBY -e 'require "rbconfig";puts Config::expand(Config::CONFIG.send("\x5b\x5d", "archdir"))' 2>/dev/null` + if test -d $rubyinc;then + AC_MSG_RESULT($rubyinc) + + # If we got a sensible archdir, we also ask ruby to supply us with CPPFLAGS + # and LDFLAGS. + AC_MSG_CHECKING([for ruby's cpp flags]) + rubycpp=`$RUBY -e 'require "rbconfig";puts Config::expand(Config::CONFIG.send("\x5b\x5d", "CPPFLAGS"))' 2>/dev/null` + AC_MSG_RESULT($rubycpp) + + AC_MSG_CHECKING([for ruby's ld flags]) + rubyld=`$RUBY -e 'require "rbconfig";puts Config::expand(Config::CONFIG.send("\x5b\x5d", "LIBRUBYARG_SHARED"))' 2>/dev/null` + rubyld2=`$RUBY -e 'require "rbconfig";v=Config::expand(Config::CONFIG.send("\x5b\x5d", "LIBRUBY_LDSHARED"));puts v.gsub(/^g?cc/,"")' 2>/dev/null` + AC_MSG_RESULT("$rubyld $rubyld2") + + AC_MSG_CHECKING([for ruby library name]) + rubylib=`$RUBY -e 'require "rbconfig";puts Config::expand(Config::CONFIG.send("\x5b\x5d", "RUBY_SO_NAME"))' 2>/dev/null` + AC_MSG_RESULT($rubylib) + + RUBY_CPPFLAGS="$rubycpp -I$rubyinc $RUBY_CPPFLAGS" + RUBY_LDFLAGS="$rubyld $rubyld2 $RUBY_LDFLAGS" + RUBY_INSTALLDIR="$rubyinc" + else + AC_MSG_RESULT('unknown') + fi +else + AC_MSG_RESULT('unknown') +fi + +#OLDLDFLAGS="$LDFLAGS" +#LDFLAGS="$LDFLAGS $RUBY_LDFLAGS" +#AC_CHECK_LIB($rubylib, rb_define_method, HAVE_RUBY_LIB=1,) +#LDFLAGS="$OLDLDFLAGS" + +OLDCPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $RUBY_CPPFLAGS" +AC_CHECK_HEADERS([ruby.h],[HAVE_RUBY_H=1]) +CPPFLAGS="$OLDCPPFLAGS" + +AC_MSG_CHECKING([whether we should compile the ruby module]) +if test "x${HAVE_RUBY_H}" '!=' "x";then + #RUBY_LIBS="$RUBY_LIBS -l$rubylib" + + cat > conftest.c << EOF +#include +static VALUE foobar; +VALUE foobar_set_foo(VALUE module, VALUE _key, VALUE _value) +{ + return Qnil; +} +int Init_foobar() +{ + foobar = rb_define_module("foobar"); + rb_define_module_function(foobar, "set_foo", foobar_set_foo, 2); + return 0; +} +int main() {return 0;} +EOF + ac_link='$CC $SHARED $CPPFLAGS $RUBY_CPPFLAGS $CFLAGS conftest.c $LDFLAGS $RUBY_LDFLAGS $LIBS $RUBY_LIBS -o conftest${SLEXT}' + if { (eval echo ruby.m4: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${SLEXT}; then + RUBY_OK=yes + else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 + fi + rm -f conftest* +fi + +if test "x${RUBY_OK}" '=' "xyes"; then + AC_MSG_RESULT([yes]) + AC_SUBST(RUBY_LIBS) + AC_SUBST(RUBY_CPPFLAGS) + AC_SUBST(RUBY_LDFLAGS) + AC_SUBST(RUBY_INSTALLDIR) +else + AC_MSG_RESULT([no]) + RUBY_CPPFLAGS="" + RUBY_LDFLAGS="" + RUBY_LIBS="" + RUBY_INSTALLDIR="" +fi +]) diff -Nru swftools-0.9.2+ds1/Makefile.new.in swftools-0.9.1/Makefile.new.in --- swftools-0.9.2+ds1/Makefile.new.in 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/Makefile.new.in 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,129 @@ +top_builddir = . +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +programs = wav2swf$(E) @PNG2SWF@ swfcombine$(E) swfstrings$(E) swfextract$(E) swfdump$(E) swfc$(E) @JPEG2SWF@ @GIF2SWF@ swfbbox$(E) font2swf$(E) as3compile$(E) swfrender$(E) @PDF2SWF@ +opt_programs = swfbytes$(E) +all: $(programs) + +include Makefile.common +include Makefile.deps + +executables = src/wav2swf.c src/png2swf.c src/pdf2swf.c src/gif2swf.c \ + src/swfcombine.c src/swfdump.c src/swfextract.c src/swfstrings.c \ + src/swfbbox.c src/jpeg2swf.c src/swfrender.c \ + src/font2swf.c src/swfbytes.c src/swfc.c \ + src/swfc-feedback.c src/swfc-history.c src/swfc-interpolation.c src/parser.yy.c + +lame_objects = lib/lame/psymodel.$(O) lib/lame/fft.$(O) lib/lame/newmdct.$(O) lib/lame/quantize.$(O) lib/lame/takehiro.$(O) lib/lame/reservoir.$(O) lib/lame/quantize_pvt.$(O) lib/lame/vbrquantize.$(O) lib/lame/encoder.$(O) lib/lame/id3tag.$(O) lib/lame/version.$(O) lib/lame/tables.$(O) lib/lame/util.$(O) lib/lame/bitstream.$(O) lib/lame/set_get.$(O) lib/lame/VbrTag.$(O) lib/lame/lame.$(O) +lame_in_source = @lame_in_source@ + +h263_objects = lib/h.263/dct.$(O) lib/h.263/h263tables.$(O) lib/h.263/swfvideo.$(O) + +as12compiler_objects = lib/action/assembler.$(O) lib/action/compile.$(O) lib/action/lex.swf4.$(O) lib/action/lex.swf5.$(O) lib/action/libming.$(O) lib/action/swf4compiler.tab.$(O) lib/action/swf5compiler.tab.$(O) lib/action/actioncompiler.$(O) +as12compiler_in_source = $(as12compiler_objects) + +as3compiler_objects = lib/as3/abc.$(O) lib/as3/pool.$(O) lib/as3/files.$(O) lib/as3/opcodes.$(O) lib/as3/code.$(O) lib/as3/registry.$(O) lib/as3/builtin.$(O) lib/as3/compiler.$(O) lib/as3/parser.tab.$(O) lib/as3/tokenizer.yy.$(O) + +rfxswf_modules = lib/modules/swfbits.$(O) lib/modules/swfaction.$(O) lib/modules/swfdump.$(O) lib/modules/swfcgi.$(O) lib/modules/swfbutton.$(O) lib/modules/swftext.$(O) lib/modules/swffont.$(O) lib/modules/swftools.$(O) lib/modules/swfsound.$(O) lib/modules/swfshape.$(O) lib/modules/swfobject.$(O) lib/modules/swfdraw.$(O) lib/modules/swffilter.$(O) lib/modules/swfrender.$(O) lib/h.263/swfvideo.$(O) + +base_objects=lib/q.$(O) lib/utf8.$(O) lib/png.$(O) lib/jpeg.$(O) lib/wav.$(O) lib/mp3.$(O) lib/os.$(O) lib/bitio.$(O) lib/log.$(O) lib/mem.$(O) +gfx_objects=lib/gfxtools.$(O) lib/gfxfont.$(O) lib/gfxpoly.$(O) lib/devices/dummy.$(O) lib/devices/file.$(O) lib/devices/render.$(O) lib/devices/text.$(O) lib/devices/record.$(O) lib/devices/ops.$(O) lib/devices/polyops.$(O) lib/devices/bbox.$(O) lib/devices/rescale.$(O) #@DEVICE_OPENGL@ + +art_objects = lib/art/art_affine.$(O) lib/art/art_alphagamma.$(O) lib/art/art_bpath.$(O) lib/art/art_gray_svp.$(O) lib/art/art_misc.$(O) lib/art/art_pixbuf.$(O) lib/art/art_rect.$(O) lib/art/art_rect_svp.$(O) lib/art/art_rect_uta.$(O) lib/art/art_render.$(O) lib/art/art_render_gradient.$(O) lib/art/art_render_mask.$(O) lib/art/art_render_svp.$(O) lib/art/art_rgb.$(O) lib/art/art_rgb_a_affine.$(O) lib/art/art_rgb_affine.$(O) lib/art/art_rgb_affine_private.$(O) lib/art/art_rgb_bitmap_affine.$(O) lib/art/art_rgb_pixbuf_affine.$(O) lib/art/art_rgb_rgba_affine.$(O) lib/art/art_rgb_svp.$(O) lib/art/art_rgba.$(O) lib/art/art_svp.$(O) lib/art/art_svp_intersect.$(O) lib/art/art_svp_ops.$(O) lib/art/art_svp_point.$(O) lib/art/art_svp_render_aa.$(O) lib/art/art_svp_vpath.$(O) lib/art/art_svp_vpath_stroke.$(O) lib/art/art_svp_wind.$(O) lib/art/art_uta.$(O) lib/art/art_uta_ops.$(O) lib/art/art_uta_rect.$(O) lib/art/art_uta_svp.$(O) lib/art/art_uta_vpath.$(O) lib/art/art_vpath.$(O) lib/art/art_vpath_bpath.$(O) lib/art/art_vpath_dash.$(O) lib/art/art_vpath_svp.$(O) +art_in_source = @art_in_source@ + +rfxswf_objects=lib/modules/swfaction.$(O) lib/modules/swfbits.$(O) lib/modules/swfbutton.$(O) lib/modules/swfcgi.$(O) lib/modules/swfdraw.$(O) lib/modules/swfdump.$(O) lib/modules/swffilter.$(O) lib/modules/swffont.$(O) lib/modules/swfobject.$(O) lib/modules/swfrender.$(O) lib/modules/swfshape.$(O) lib/modules/swfsound.$(O) lib/modules/swftext.$(O) lib/modules/swftools.$(O) +ocr_objects=lib/gocr/box.$(O) lib/gocr/database.$(O) lib/gocr/detect.$(O) lib/gocr/job.$(O) lib/gocr/lines.$(O) lib/gocr/list.$(O) lib/gocr/ocr0.$(O) lib/gocr/ocr0n.$(O) lib/gocr/ocr1.$(O) lib/gocr/otsu.$(O) lib/gocr/output.$(O) lib/gocr/pgm2asc.$(O) lib/gocr/pixel.$(O) lib/gocr/progress.$(O) lib/gocr/remove.$(O) lib/gocr/unicode.$(O) + +libpdf_objects = lib/pdf/GFXOutputDev.$(O) lib/pdf/InfoOutputDev.$(O) lib/pdf/BitmapOutputDev.$(O) lib/pdf/FullBitmapOutputDev.$(O) lib/pdf/pdf.$(O) lib/pdf/fonts.$(O) + +xpdf_in_source = @xpdf_in_source@ +xpdf_objects = lib/pdf/xpdf/GHash.$(O) lib/pdf/xpdf/GList.$(O) lib/pdf/xpdf/GString.$(O) lib/pdf/xpdf/gmem.$(O) lib/pdf/xpdf/gfile.$(O) \ + lib/pdf/xpdf/FoFiTrueType.$(O) lib/pdf/xpdf/FoFiType1.$(O) lib/pdf/xpdf/FoFiType1C.$(O) lib/pdf/xpdf/FoFiBase.$(O) lib/pdf/xpdf/FoFiEncodings.$(O) \ + lib/pdf/xpdf/OutputDev.$(O) lib/pdf/xpdf/PDFDoc.$(O) lib/pdf/xpdf/Error.$(O) lib/pdf/xpdf/Stream.$(O) lib/pdf/xpdf/Object.$(O) \ + lib/pdf/xpdf/Decrypt.$(O) lib/pdf/xpdf/Array.$(O) lib/pdf/xpdf/XRef.$(O) lib/pdf/xpdf/Dict.$(O) lib/pdf/xpdf/Parser.$(O) \ + lib/pdf/xpdf/Lexer.$(O) lib/pdf/xpdf/Outline.$(O) lib/pdf/xpdf/PDFDocEncoding.$(O) lib/pdf/xpdf/Catalog.$(O) \ + lib/pdf/xpdf/Link.$(O) lib/pdf/xpdf/GlobalParams.$(O) lib/pdf/xpdf/JBIG2Stream.$(O) lib/pdf/xpdf/Page.$(O) lib/pdf/xpdf/JPXStream.$(O) \ + lib/pdf/xpdf/JArithmeticDecoder.$(O) lib/pdf/xpdf/Gfx.$(O) lib/pdf/xpdf/GfxFont.$(O) lib/pdf/xpdf/CMap.$(O) lib/pdf/xpdf/CharCodeToUnicode.$(O) \ + lib/pdf/xpdf/PSTokenizer.$(O) lib/pdf/xpdf/FontEncodingTables.$(O) lib/pdf/xpdf/BuiltinFont.$(O) lib/pdf/xpdf/BuiltinFontTables.$(O) \ + lib/pdf/xpdf/GfxState.$(O) lib/pdf/xpdf/Function.$(O) lib/pdf/xpdf/Annot.$(O) lib/pdf/xpdf/NameToCharCode.$(O) lib/pdf/xpdf/UnicodeMap.$(O) \ + lib/pdf/xpdf/SecurityHandler.$(O) #lib/pdf/xpdf/OptionalContent.$(O) + +splash_in_source = @splash_in_source@ +splash_objects = lib/pdf/xpdf/SplashOutputDev.$(O) lib/pdf/xpdf/SplashFont.$(O) lib/pdf/xpdf/SplashState.$(O) lib/pdf/xpdf/Splash.$(O) \ + lib/pdf/xpdf/SplashBitmap.$(O) lib/pdf/xpdf/SplashClip.$(O) lib/pdf/xpdf/SplashPattern.$(O) \ + lib/pdf/xpdf/SplashFontEngine.$(O) lib/pdf/xpdf/SplashFontFile.$(O) lib/pdf/xpdf/SplashFontFileID.$(O) \ + lib/pdf/xpdf/SplashScreen.$(O) lib/pdf/xpdf/SplashPath.$(O) lib/pdf/xpdf/SplashXPath.$(O) lib/pdf/xpdf/SplashXPathScanner.$(O) \ + lib/pdf/xpdf/SplashFTFontEngine.$(O) lib/pdf/xpdf/SplashFTFontFile.$(O) lib/pdf/xpdf/SplashFTFont.$(O) + +OBJECTS=$(executables) $(lame_in_source) $(h263_objects) $(as12compiler_in_source) \ + $(as3compiler_objects) $(rfxswf_modules) $(base_objects) $(gfx_objects) $(art_objects) \ + $(rfx_objects) $(ocr_objects) \ + $(libpdf_objects) $(xpdf_in_source) $(splash_in_source) + +SOURCES=$(patsubst %.$(O),%.c,$(OBJECTS)) + +depend: Makefile.deps +Makefile.deps: $(SOURCES) + rm -f Makefile.deps + for s in $(SOURCES);do $(DEP) $$s >> Makefile.deps || >Makefile.deps;done + @echo "Dependencies have been regenerated. Please re-run make." + @false + +%.$(O): %.c + $(C) $< -o $@ + +lib/libpdf$(A): $(libpdf_objects) $(xpdf_in_source) $(splash_in_source) + $(AR) r lib/libpdf$(A) $(libpdf_objects) $(xpdf_in_source) $(splash_in_source) + $(RANLIB) lib/libpdf$(A) + +# TODO: include the following rule only if lex is available +src/parser.yy.c: src/parser.lex + flex -B -s -osrc/parser.yy.c src/parser.lex + +%$(E): src/%.$(O) lib/librfxswf$(A) lib/libbase$(A) + $(L) $< -o $@ lib/librfxswf$(A) lib/libbase$(A) $(LIBS) + +PDF2SWF_OBJ=lib/libpdf$(A) lib/devices/polyops.$(O) lib/devices/swf.$(O) lib/librfxswf$(A) lib/libgfx$(A) lib/libbase$(A) +pdf2swf$(E): src/pdf2swf.$(O) $(PDF2SWF_OBJ) + $(LL) src/pdf2swf.$(O) -o $@ $(PDF2SWF_OBJ) $(LIBS) $(CXXLIBS) + $(STRIP) $@ + +SWFRENDER_OBJ=lib/libgfxswf$(A) lib/libgfx$(A) lib/librfxswf$(A) lib/libbase$(A) +swfrender$(E): src/swfrender.$(O) $(SWFRENDER_OBJ) + $(L) src/swfrender.$(O) -o $@ $(SWFRENDER_OBJ) $(LIBS) + +swfc$(E): src/parser.yy.$(O) src/swfc.$(O) src/swfc-feedback.$(O) src/swfc-history.$(O) src/swfc-interpolation.$(O) lib/librfxswf$(A) lib/libbase$(A) + $(L) src/parser.yy.$(O) src/swfc.$(O) src/swfc-feedback.$(O) src/swfc-history.$(O) src/swfc-interpolation.$(O) -o $@ lib/librfxswf$(A) lib/libbase$(A) $(LIBS) + $(STRIP) $@ + +install: + $(mkinstalldirs) $(bindir) + $(mkinstalldirs) $(man1dir) + @for file in $(programs) $(opt_programs); do if test -f $$file;then $(INSTALL_BIN);$(INSTALL_MAN1);fi;done + +uninstall: + @for file in $(programs) $(opt_programs); do $(UNINSTALL_BIN);$(UNINSTALL_MAN1);done + +clean: + for d in . src lib lib/pdf lib/as3 lib/lame lib/action lib/modules swfs;do rm -f $$d/*.o $$d/*.obj $$d/*.lo $$d/*.la $$d/*~ $$d/gmon.out;done + rm -f $(programs) + @rm -f gif2swf swfbbox swfbytes swfbytes swfdump pdf2swf wav2swf png2swf swfcombine swfextract swfstrings png2swf jpeg2swf swfc font2swf as3compile + @rm -f gif2swf.exe swfbytes.exe swfbytes.exe pdf2swf.exe swfbbox.exe swfdump.exe wav2swf.exe png2swf.exe swfcombine.exe swfextract.exe swfstrings.exe png2swf.exe jpeg2swf.exe swfc.exe font2swf.exe + @rm -f gif2swf$(E) pdf2swf$(E) swfbytes$(E) swfbytes$(E) swfbbox$(E) swfdump$(E) wav2swf$(E) png2swf$(E) swfcombine$(E) swfextract$(E) swfstrings$(E) png2swf$(E) jpeg2swf$(E) swfc$(E) font2swf$(E) + +doc: + perl parsedoc.pl src/wav2swf.doc + perl parsedoc.pl src/png2swf.doc + perl parsedoc.pl src/gif2swf.doc + perl parsedoc.pl src/swfbbox.doc + perl parsedoc.pl src/font2swf.doc + perl parsedoc.pl src/jpeg2swf.doc + perl parsedoc.pl src/swfcombine.doc + perl parsedoc.pl src/swfdump.doc + perl parsedoc.pl src/swfc.doc + perl parsedoc.pl src/swfbytes.doc + perl parsedoc.pl src/as3compile.doc + +.PHONY: clean doc diff -Nru swftools-0.9.2+ds1/parsedoc.pl swftools-0.9.1/parsedoc.pl --- swftools-0.9.2+ds1/parsedoc.pl 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/parsedoc.pl 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,227 @@ +use File::Find; +use strict; + +my $file = $ARGV[0]; +if(!$file) { + print "Usage: parsedoc.pl \n"; + exit(0); +} + +my $paramhelp = ""; + +sub add_option_to_manpage +{ + my $shortopt = shift; + my $longopt = shift; + my $params = shift; + my $doc = shift; + my $longdoc = shift; + chomp $longdoc; + chomp $longdoc; + $shortopt =~ s|-|\\-|; + $params =~ s|<(.*)>|\\fI\1\\fR|; + $longdoc =~ s/<([a-zA-Z0-9_-]+)>/\\fI\1\\fR/; + #$longdoc =~ s/%/%%$1/g; + print manpage << "EOF" +.TP +\\fB\\-$shortopt\\fR, \\fB\\-\\-$longopt\\fR $params +$longdoc +EOF +; +} + +sub add_option_to_help +{ + my $shortopt = shift; + my $longopt = shift; + my $params = shift; + my $doc = shift; + my $longdoc = shift; + chomp $doc; + chomp $doc; + my $s1 = " "x(2-length($shortopt)); + my $s2 = " "x(20-length($longopt." ".$params)); + $doc =~ s/"/\\"/g; + $doc =~ s/%/%%/g; + $paramhelp .= " printf(\"-$shortopt$s1, --$longopt $params$s2$doc\\n\");\n"; +} + +sub add_header_to_manpage +{ + my $package = shift; + my $progname = shift; + my $short_description = shift; + my $long_description = shift; + my $usage = shift; + my $date = `date +"%B %Y"`; + my $newusage = ""; + chomp $date; + + $long_description =~ s/([^\\])-/\1\\-/g; + + my @chunks = split(/\n/,$usage); + my $p = ""; + foreach my $u (@chunks) { + $u =~ s/%s/$progname/g; + $newusage .= "$p.B $u\n"; + $p = ".PP\n"; + } + $newusage =~ s/([^\\])-/\1\\-/g; + print manpage << "EOF" +.TH $progname "1" "$date" "$progname" "$package" +.SH NAME +$progname \\- $short_description +.SH Synopsis +$newusage +.SH DESCRIPTION +$long_description +.SH OPTIONS +EOF +; +} +open(fi, "$file") or die "File not found"; + +my $package = "swftools"; +my $progname = $file; +$progname =~ s|(^/?([^/]+/))*([^/]+).doc|$3|; +my $path = $1; + +open(manpage, ">$path$progname.1") or die; + +my $usage = ""; +my $short_description = ""; +my $long_description = ""; +while() { + last if(/^\s*$/); + s/^\s*Usage:\s*//g; + s/^\s*OR:\s*//g; + $usage .= $_; +} +while() { + last if(/^\s*$/); + $short_description .= $_; +} +while() { + last if(/^\s*$/); + $long_description .= $_; +} + +add_header_to_manpage($package, $progname, $short_description, $long_description, $usage); + +$_=; + +my $numopts = 0; +my @shortopts; +my @longopts; + +while(1) { + if(/^-([^\s,]+)[\s,]+--([^\s]+)(\s+(.*))?$/) { + my $shortopt = $1; + my $longopt = $2; + my $params = $4; + my $doc = ""; + my $longdoc = ""; + while() { + last if(/^-/); + last if(/^\s*$/); + if(!$doc) { + $doc .= $_; + } else { + $longdoc .= $_; + } + } + $longdoc = $doc if(!$longdoc || ($longdoc =~ /^\s*$/)); + + $shortopts[$numopts] = $shortopt; + $longopts[$numopts] = $longopt; + $numopts++; + + add_option_to_manpage($shortopt,$longopt,$params,$doc,$longdoc); + add_option_to_help($shortopt,$longopt,$params,$doc,$longdoc); + last if(eof(fi)); + next; + } + last if(/^\s*/); + last if(!($_=)); + last if(/^\s*/); +} + +my $tail = ""; +while() { + $tail .= $_; +} +$tail =~ s/([^\\])-/\1\\-/g; + +print manpage $tail; +close(manpage); + + +my $filename = "$path$progname.c"; +my $cfile; +if(!open($cfile, "<$filename")) { + $filename = "$path$progname.cpp"; + if(!open($cfile, "<$filename")) { + $filename = "$path$progname.cc"; + if(!open($cfile, "<$filename")) { + $filename = "$path$progname.c++"; + open($cfile, "<$filename") or die; + } + } +} + +my $src=""; +while(<$cfile>) +{ + if(/void\s*args_callback_usage.*\(.*\*/) { + print "substituting usage in $filename\n"; + if(!/{/) {<$cfile>;} + $src .= "void args_callback_usage(char *name)\n"; + $src .= "{\n"; + $src .= " printf(\"\\n\");\n"; + while(<$cfile>) { + last if(/}\s*$/); + } + my @chunks = split(/\n/,$usage); + my $prefix = "Usage:"; + my $u; + foreach $u (@chunks) { + if($u =~ /%s/) { + $src .= " printf(\"$prefix $u\\n\", name);\n"; + } else { + $u =~ s/%/%%/; + $src .= " printf(\"$prefix $u\\n\");\n"; + } + $prefix = "OR: "; + } + $src .= " printf(\"\\n\");\n"; + + $src .= "$paramhelp"; + + $src .= " printf(\"\\n\");\n"; + + $src .= "}\n"; + next; + } + if(/^\s*(static\s+)?(struct\s+)?options_t.*=/) { + print "substituting options_t in $filename\n"; + while(<$cfile>) { + last if(/;$/); + } + split(/\n/,$usage); + $src .= "static struct options_t options[] = {\n"; + for(my $t=0;$t<$numopts;$t++) { + my $s = $shortopts[$t]; + my $l = $longopts[$t]; + $src .= "{\"$s\", \"$l\"},\n"; + } + $src .= "{0,0}\n};\n"; + next; + } + $src .= $_; +} + +close($cfile); +open($cfile, ">$filename") or die; +print $cfile $src; +close($cfile); + diff -Nru swftools-0.9.2+ds1/.pc/applied-patches swftools-0.9.1/.pc/applied-patches --- swftools-0.9.2+ds1/.pc/applied-patches 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/.pc/applied-patches 2012-06-20 15:37:24.000000000 +0000 @@ -0,0 +1 @@ +remove-pdf-protections.patch diff -Nru swftools-0.9.2+ds1/.pc/remove-pdf-protections.patch/lib/pdf/pdf.cc swftools-0.9.1/.pc/remove-pdf-protections.patch/lib/pdf/pdf.cc --- swftools-0.9.2+ds1/.pc/remove-pdf-protections.patch/lib/pdf/pdf.cc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/.pc/remove-pdf-protections.patch/lib/pdf/pdf.cc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,606 @@ +#include +#include +#include "../gfxdevice.h" +#include "../gfxsource.h" +#include "../devices/rescale.h" +#include "../log.h" +#include "../../config.h" +#ifdef HAVE_POPPLER + #include +#else + #include "xpdf/config.h" +#endif +#include "GlobalParams.h" +#include "InfoOutputDev.h" +#include "CharOutputDev.h" +#include "FullBitmapOutputDev.h" +#include "BitmapOutputDev.h" +#include "VectorGraphicOutputDev.h" +#include "../mem.h" +#include "pdf.h" +#define NO_ARGPARSER +#include "../args.h" +#include "../utf8.h" + +static double zoom = 72; /* xpdf: 86 */ +static int zoomtowidth = 0; +static double multiply = 1.0; +static char* global_page_range = 0; +static int threadsafe = 0; + +static int globalparams_count=0; + +typedef struct _pdf_page_info +{ + int xMin, yMin, xMax, yMax; + int width,height; + int number_of_images; + int number_of_links; + int number_of_fonts; + char has_info; +} pdf_page_info_t; + +typedef struct _pdf_doc_internal +{ + char config_bitmap_optimizing; + char config_full_bitmap_optimizing; + char config_only_text; + char config_print; + gfxparams_t* parameters; + + int protect; + int nocopy; + int noprint; + + GString*fileName; + GString*userPW; + PDFDoc*doc; + + Object docinfo; + InfoOutputDev*info; + + pdf_page_info_t*pages; + char*filename; + + /* page map */ + int*pagemap; + int pagemap_size; + int pagemap_pos; + + gfxsource_t*parent; +} pdf_doc_internal_t; + +typedef struct _pdf_page_internal +{ +} pdf_page_internal_t; + +typedef struct _dev_output_internal +{ + CommonOutputDev*outputDev; +} dev_output_internal_t; + + +typedef struct _gfxsource_internal +{ + gfxparams_t* parameters; +} gfxsource_internal_t; + + +static const char* dirseparator() +{ +#ifdef WIN32 + return "\\"; +#else + return "/"; +#endif +} + +void pdfpage_destroy(gfxpage_t*pdf_page) +{ + pdf_page_internal_t*i= (pdf_page_internal_t*)pdf_page->internal; + free(pdf_page->internal);pdf_page->internal = 0; + free(pdf_page);pdf_page=0; +} + +static void render2(gfxpage_t*page, gfxdevice_t*dev, int x,int y, int x1,int y1,int x2,int y2) +{ + pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; + gfxsource_internal_t*i = (gfxsource_internal_t*)pi->parent->internal; + + if(!pi->config_print && pi->nocopy) {msg(" PDF disallows copying");exit(0);} + if(pi->config_print && pi->noprint) {msg(" PDF disallows printing");exit(0);} + + CommonOutputDev*outputDev = 0; + if(pi->config_full_bitmap_optimizing) { + FullBitmapOutputDev*d = new FullBitmapOutputDev(pi->info, pi->doc, pi->pagemap, pi->pagemap_pos, x, y, x1, y1, x2, y2); + outputDev = (CommonOutputDev*)d; + } else if(pi->config_bitmap_optimizing) { + BitmapOutputDev*d = new BitmapOutputDev(pi->info, pi->doc, pi->pagemap, pi->pagemap_pos, x, y, x1, y1, x2, y2); + outputDev = (CommonOutputDev*)d; + } else if(pi->config_only_text) { + CharOutputDev*d = new CharOutputDev(pi->info, pi->doc, pi->pagemap, pi->pagemap_pos, x, y, x1, y1, x2, y2); + outputDev = (CommonOutputDev*)d; + } else { + VectorGraphicOutputDev*d = new VectorGraphicOutputDev(pi->info, pi->doc, pi->pagemap, pi->pagemap_pos, x, y, x1, y1, x2, y2); + outputDev = (CommonOutputDev*)d; + } + + /* pass global parameters to PDF driver*/ + gfxparam_t*p = i->parameters->params; + while(p) { + outputDev->setParameter(p->key, p->value); + p = p->next; + } + p = pi->parameters->params; + while(p) { + outputDev->setParameter(p->key, p->value); + p = p->next; + } + + gfxdevice_t* middev=0; + if(multiply!=1.0) { + middev = (gfxdevice_t*)malloc(sizeof(gfxdevice_t)); + gfxdevice_rescale_init(middev, 0x00000000, 0, 0, 1.0 / multiply); + gfxdevice_rescale_setdevice(middev, dev); + dev = middev; + } + + if(!pi) { + msg(" pdf_page_render: Parent PDF this page belongs to doesn't exist yet/anymore"); + return; + } + + if(!pi->pages[page->nr-1].has_info) { + msg(" pdf_page_render: page %d was previously set as not-to-render via the \"pages\" option", page->nr); + return; + } + + if(pi->protect) { + dev->setparameter(dev, "protect", "1"); + } + + outputDev->setDevice(dev); + pi->doc->processLinks((OutputDev*)outputDev, page->nr); + pi->doc->displayPage((OutputDev*)outputDev, page->nr, zoom*multiply, zoom*multiply, /*rotate*/0, true, true, pi->config_print); + outputDev->finishPage(); + outputDev->setDevice(0); + delete outputDev; + + if(middev) { + gfxdevice_rescale_setdevice(middev, 0x00000000); + middev->finish(middev); + } + +} + + +void pdfpage_render(gfxpage_t*page, gfxdevice_t*output) +{ + pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; + render2(page, output, 0,0, 0,0,0,0); +} + +void pdfpage_rendersection(gfxpage_t*page, gfxdevice_t*output, gfxcoord_t x, gfxcoord_t y, gfxcoord_t _x1, gfxcoord_t _y1, gfxcoord_t _x2, gfxcoord_t _y2) +{ + pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; + + int x1=(int)_x1,y1=(int)_y1,x2=(int)_x2,y2=(int)_y2; + if((x1|y1|x2|y2)==0) x2++; + + render2(page, output, (int)x*multiply,(int)y*multiply, + (int)x1*multiply,(int)y1*multiply,(int)x2*multiply,(int)y2*multiply); +} + +void pdf_doc_destroy(gfxdocument_t*gfx) +{ + pdf_doc_internal_t*i= (pdf_doc_internal_t*)gfx->internal; + + if (i->userPW) { + delete i->userPW;i->userPW = 0; + } + if (i->fileName) { + /* will be freed by PDFDoc::~PDFDoc */ + i->fileName = 0; + } + + if(i->doc) { + delete i->doc; i->doc=0; + } + free(i->pages); i->pages = 0; + + if(i->pagemap) { + free(i->pagemap); + } + + i->docinfo.free(); + + if(i->filename) { + free(i->filename);i->filename=0; + } + + if(i->info) { + delete i->info;i->info=0; + } + if(i->parameters) { + gfxparams_free(i->parameters); + i->parameters=0; + } + + free(gfx->internal);gfx->internal=0; + free(gfx);gfx=0; + + if(global_page_range) { + free(global_page_range); + global_page_range = 0; + } + + /*globalparams_count--; + if(!globalparams_count) { + delete globalParams; + globalParams = 0; + globalparams_count = 0; + }*/ +} + +static void add_page_to_map(gfxdocument_t*gfx, int pdfpage, int outputpage) +{ + pdf_doc_internal_t*i= (pdf_doc_internal_t*)gfx->internal; + if(pdfpage < 0) + return; + if(pdfpage >= i->pagemap_size) { + int oldlen = i->pagemap_size; + i->pagemap_size = oldlen + 1024; + if(pdfpage > i->pagemap_size) + i->pagemap_size = pdfpage+1; + + if(i->pages) { + i->pagemap = (int*)malloc(i->pagemap_size*sizeof(int)); + } else { + i->pagemap = (int*)realloc(i->pages, i->pagemap_size*sizeof(int)); + } + memset(&i->pagemap[oldlen], -1, (i->pagemap_size-oldlen)*sizeof(int)); + } + i->pagemap[pdfpage] = outputpage; + if(pdfpage > i->pagemap_pos) + i->pagemap_pos = pdfpage; +} + +void pdf_doc_setparameter(gfxdocument_t*gfx, const char*name, const char*value) +{ + pdf_doc_internal_t*i= (pdf_doc_internal_t*)gfx->internal; + if(!strcmp(name, "pagemap")) { + int pdfpage=0, outputpage=0; + sscanf(value,"%d:%d", &pdfpage, &outputpage); + add_page_to_map(gfx, pdfpage, outputpage); + } else if(!strcmp(name, "poly2bitmap")) { + i->config_bitmap_optimizing = atoi(value); + } else if(!strcmp(name, "bitmapfonts") || !strcmp(name, "bitmap")) { + i->config_full_bitmap_optimizing = atoi(value); + } else if(!strcmp(name, "asprint")) { + i->config_print = atoi(value); + } else if(!strcmp(name, "onlytext")) { + i->config_only_text = atoi(value); + } else { + gfxparams_store(i->parameters, name, value); + } +} + +gfxpage_t* pdf_doc_getpage(gfxdocument_t*doc, int page) +{ + pdf_doc_internal_t*di= (pdf_doc_internal_t*)doc->internal; + if(threadsafe) { + /* for multi-thread operation, we need to create a new PDFDoc instance + for each thread */ + di->doc = 0; + } + if(!di->doc) { + di->doc = new PDFDoc(di->fileName, di->userPW); + } + + if(page < 1 || page > doc->num_pages) + return 0; + + gfxpage_t* pdf_page = (gfxpage_t*)malloc(sizeof(gfxpage_t)); + pdf_page_internal_t*pi= (pdf_page_internal_t*)malloc(sizeof(pdf_page_internal_t)); + memset(pi, 0, sizeof(pdf_page_internal_t)); + pdf_page->internal = pi; + + pdf_page->destroy = pdfpage_destroy; + pdf_page->render = pdfpage_render; + pdf_page->rendersection = pdfpage_rendersection; + pdf_page->width = di->pages[page-1].width; + pdf_page->height = di->pages[page-1].height; + + pdf_page->parent = doc; + pdf_page->nr = page; + return pdf_page; +} + +static char*getInfoString(Dict *infoDict, const char *key) +{ + Object obj; + GString *s1, *s2; + int i; + unsigned int u; + + if (infoDict && infoDict->lookup((char*)key, &obj)->isString()) { + s1 = obj.getString(); + if ((s1->getChar(0) & 0xff) == 0xfe && + (s1->getChar(1) & 0xff) == 0xff) { + s2 = new GString(); + for (i = 2; i < obj.getString()->getLength(); i += 2) { + u = ((s1->getChar(i) & 0xff) << 8) | (s1->getChar(i+1) & 0xff); + s2->append(getUTF8(u)); + } + char*ret = strdup(s2->getCString()); + delete s2; + obj.free(); + return ret; + } else { + char*ret = strdup(s1->getCString()); + obj.free(); + return ret; + } + } + return strdup(""); +} + +static char*getInfoDate(Dict *infoDict, const char *key) +{ + Object obj; + char *s; + + if (infoDict && infoDict->lookup((char*)key, &obj)->isString()) { + s = obj.getString()->getCString(); + if (s[0] == 'D' && s[1] == ':') { + s += 2; + } + char*ret = strdup(s); + obj.free(); + return ret; + } + return strdup(""); +} + +char* pdf_doc_getinfo(gfxdocument_t*doc, const char*name) +{ + pdf_doc_internal_t*i= (pdf_doc_internal_t*)doc->internal; + if(!strcmp(name, "title")) return getInfoString(i->docinfo.getDict(), "Title"); + else if(!strcmp(name, "subject")) return getInfoString(i->docinfo.getDict(), "Subject"); + else if(!strcmp(name, "keywords")) return getInfoString(i->docinfo.getDict(), "Keywords"); + else if(!strcmp(name, "author")) return getInfoString(i->docinfo.getDict(), "Author"); + else if(!strcmp(name, "creator")) return getInfoString(i->docinfo.getDict(), "Creator"); + else if(!strcmp(name, "producer")) return getInfoString(i->docinfo.getDict(), "Producer"); + else if(!strcmp(name, "creationdate")) return getInfoDate(i->docinfo.getDict(), "CreationDate"); + else if(!strcmp(name, "moddate")) return getInfoDate(i->docinfo.getDict(), "ModDate"); + else if(!strcmp(name, "linearized")) return strdup(i->doc->isLinearized() ? "yes" : "no"); + else if(!strcmp(name, "tagged")) return strdup(i->doc->getStructTreeRoot()->isDict() ? "yes" : "no"); + else if(!strcmp(name, "encrypted")) return strdup(i->doc->isEncrypted() ? "yes" : "no"); + else if(!strcmp(name, "oktoprint")) return strdup(i->doc->okToPrint() ? "yes" : "no"); + else if(!strcmp(name, "oktocopy")) return strdup(i->doc->okToCopy() ? "yes" : "no"); + else if(!strcmp(name, "oktochange")) return strdup(i->doc->okToChange() ? "yes" : "no"); + else if(!strcmp(name, "oktoaddnotes")) return strdup(i->doc->okToAddNotes() ? "yes" : "no"); + else if(!strcmp(name, "version")) { + char buf[32]; +#ifdef HAVE_POPPLER + sprintf(buf, "%d.%d", i->doc->getPDFMajorVersion(), i->doc->getPDFMinorVersion()); +#else + sprintf(buf, "%.1f", i->doc->getPDFVersion()); +#endif + return strdup(buf); + } + return strdup(""); +} + + +/* shortcut to InfoOutputDev.cc */ +extern int config_unique_unicode; +extern int config_poly2bitmap_pass1; +extern int config_skewedtobitmap_pass1; +extern int config_addspace; +extern int config_fontquality; +extern int config_bigchar; +extern int config_marker_glyph; +extern int config_normalize_fonts; +extern int config_remove_font_transforms; +extern int config_remove_invisible_outlines; +extern int config_break_on_warning; + +static void pdf_setparameter(gfxsource_t*src, const char*name, const char*value) +{ + gfxsource_internal_t*i = (gfxsource_internal_t*)src->internal; + + gfxparams_store(i->parameters, name, value); + + msg(" setting parameter %s to \"%s\"", name, value); + if(!strncmp(name, "fontdir", strlen("fontdir"))) { + addGlobalFontDir(value); + } else if(!strcmp(name, "addspacechars")) { + config_addspace = atoi(value); + gfxparams_store(i->parameters, "detectspaces", "0"); + } else if(!strcmp(name, "detectspaces")) { + config_addspace = atoi(value); + } else if(!strcmp(name, "unique_unicode")) { + config_unique_unicode = atoi(value); + } else if(!strcmp(name, "poly2bitmap")) { + config_poly2bitmap_pass1 = atoi(value); + } else if(!strcmp(name, "marker_glyph")) { + config_marker_glyph = atoi(value); + } else if(!strcmp(name, "normalize_fonts")) { + config_normalize_fonts = atoi(value); + } else if(!strcmp(name, "skewedtobitmap")) { + config_skewedtobitmap_pass1 = atoi(value); + } else if(!strcmp(name, "remove_font_transforms")) { + config_remove_font_transforms = atoi(value); + } else if(!strcmp(name, "breakonwarning")) { + config_break_on_warning = atoi(value); + } else if(!strcmp(name, "remove_invisible_outlines")) { + config_remove_invisible_outlines = atoi(value); + } else if(!strcmp(name, "fontquality")) { + config_fontquality = atoi(value); + } else if(!strcmp(name, "bigchar")) { + config_bigchar = atoi(value); + } else if(!strcmp(name, "pages")) { + global_page_range = strdup(value); + } else if(!strncmp(name, "font", strlen("font")) && name[4]!='q') { + addGlobalFont(value); + } else if(!strncmp(name, "languagedir", strlen("languagedir"))) { + addGlobalLanguageDir(value); + } else if(!strcmp(name, "threadsafe")) { + threadsafe = atoi(value); + } else if(!strcmp(name, "zoomtowidth")) { + zoomtowidth = atoi(value); + } else if(!strcmp(name, "zoom")) { + char buf[80]; + zoom = atof(value); + } else if(!strcmp(name, "jpegdpi") || !strcmp(name, "ppmdpi")) { + msg(" %s not supported anymore. Please use jpegsubpixels/ppmsubpixels"); + } else if(!strcmp(name, "multiply")) { + multiply = atof(value); + } else if(!strcmp(name, "help")) { + printf("\nPDF device global parameters:\n"); + printf("fontdir=

    a directory with additional fonts\n"); + printf("font= an additional font filename\n"); + printf("pages= the range of pages to convert (example: pages=1-100,210-)\n"); + printf("zoom= the resultion (default: 72)\n"); + printf("languagedir= Add an xpdf language directory\n"); + printf("multiply= Render everything at the resolution\n"); + printf("poly2bitmap Convert graphics to bitmaps\n"); + printf("bitmap Convert everything to bitmaps\n"); + } +} + +void pdf_doc_prepare(gfxdocument_t*doc, gfxdevice_t*dev) +{ + pdf_doc_internal_t*i= (pdf_doc_internal_t*)doc->internal; + i->info->dumpfonts(dev); +} + +static gfxdocument_t*pdf_open(gfxsource_t*src, const char*filename) +{ + gfxsource_internal_t*isrc = (gfxsource_internal_t*)src->internal; + gfxdocument_t*pdf_doc = (gfxdocument_t*)malloc(sizeof(gfxdocument_t)); + memset(pdf_doc, 0, sizeof(gfxdocument_t)); + pdf_doc_internal_t*i= (pdf_doc_internal_t*)malloc(sizeof(pdf_doc_internal_t)); + memset(i, 0, sizeof(pdf_doc_internal_t)); + i->parent = src; + i->parameters = gfxparams_new(); + pdf_doc->internal = i; + char*userPassword=0; + + i->filename = strdup(filename); + + char*x = 0; + if((x = strchr((char*)filename, '|'))) { + *x = 0; + userPassword = x+1; + } + + i->fileName = new GString(filename); + + // open PDF file + if (userPassword && userPassword[0]) { + i->userPW = new GString(userPassword); + } else { + i->userPW = NULL; + } + i->doc = new PDFDoc(i->fileName, i->userPW); + if (!i->doc->isOk()) { + return 0; + } + + // get doc info + i->doc->getDocInfo(&i->docinfo); + + pdf_doc->num_pages = i->doc->getNumPages(); + i->protect = 0; + if (i->doc->isEncrypted()) { + if(!i->doc->okToCopy()) { + i->nocopy = 1; + } + if(!i->doc->okToPrint()) { + i->noprint = 1; + } + if(!i->doc->okToChange() || !i->doc->okToAddNotes()) + i->protect = 1; + } + + if(zoomtowidth && i->doc->getNumPages()) { + Page*page = i->doc->getCatalog()->getPage(1); + PDFRectangle *r = page->getCropBox(); + double width_before = r->x2 - r->x1; + zoom = 72.0 * zoomtowidth / width_before; + msg(" Rendering at %f DPI. (Page width at 72 DPI: %f, target width: %d)", zoom, width_before, zoomtowidth); + } + + i->info = new InfoOutputDev(i->doc->getXRef()); + int t; + i->pages = (pdf_page_info_t*)malloc(sizeof(pdf_page_info_t)*pdf_doc->num_pages); + memset(i->pages,0,sizeof(pdf_page_info_t)*pdf_doc->num_pages); + for(t=1;t<=pdf_doc->num_pages;t++) { + if(!global_page_range || is_in_range(t, global_page_range)) { + i->doc->displayPage((OutputDev*)i->info, t, zoom, zoom, /*rotate*/0, /*usemediabox*/true, /*crop*/true, i->config_print); + i->doc->processLinks((OutputDev*)i->info, t); + i->pages[t-1].xMin = i->info->x1; + i->pages[t-1].yMin = i->info->y1; + i->pages[t-1].xMax = i->info->x2; + i->pages[t-1].yMax = i->info->y2; + i->pages[t-1].width = i->info->x2 - i->info->x1; + i->pages[t-1].height = i->info->y2 - i->info->y1; + i->pages[t-1].number_of_images = i->info->num_ppm_images + i->info->num_jpeg_images; + i->pages[t-1].number_of_links = i->info->num_links; + i->pages[t-1].number_of_fonts = i->info->num_fonts; + i->pages[t-1].has_info = 1; + } + } + + pdf_doc->get = 0; + pdf_doc->destroy = pdf_doc_destroy; + pdf_doc->setparameter = pdf_doc_setparameter; + pdf_doc->getinfo = pdf_doc_getinfo; + pdf_doc->getpage = pdf_doc_getpage; + pdf_doc->prepare = pdf_doc_prepare; + + /* pass global parameters to PDF driver*/ + gfxparam_t*p = isrc->parameters->params; + while(p) { + pdf_doc->setparameter(pdf_doc, p->key, p->value); + p = p->next; + } + return pdf_doc; +} + +void pdf_destroy(gfxsource_t*src) +{ + if(!src->internal) + return; + gfxsource_internal_t*i = (gfxsource_internal_t*)src->internal; + + gfxparams_free(i->parameters); + i->parameters=0; + + free(src->internal);src->internal=0; + + delete globalParams;globalParams = 0; + free(src); +} + +gfxsource_t*gfxsource_pdf_create() +{ + gfxsource_t*src = (gfxsource_t*)malloc(sizeof(gfxsource_t)); + memset(src, 0, sizeof(gfxsource_t)); + src->setparameter = pdf_setparameter; + src->open = pdf_open; + src->destroy = pdf_destroy; + gfxsource_internal_t*i = (gfxsource_internal_t*)rfx_calloc(sizeof(gfxsource_internal_t)); + src->internal = (void*)i; + i->parameters = gfxparams_new(); + + if(!globalParams) { + globalParams = new GFXGlobalParams(); + //globalparams_count++; + } + + + return src; +} diff -Nru swftools-0.9.2+ds1/.pc/.version swftools-0.9.1/.pc/.version --- swftools-0.9.2+ds1/.pc/.version 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/.pc/.version 2012-06-20 15:37:24.000000000 +0000 @@ -0,0 +1 @@ +2 diff -Nru swftools-0.9.2+ds1/release.in swftools-0.9.1/release.in --- swftools-0.9.2+ds1/release.in 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/release.in 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,521 @@ +#!/bin/sh +name=@PACKAGE@-@VERSION@ +echo creating $name.tar.gz +rm -f ${name} +rm -f ${name}.tar +rm -f ${name}.tar.gz +ln -s ./ ${name} +cd lib/action;make generated >/dev/null 2>&1;cd ../.. + +SOURCES="${name}/src/swfcombine.1 \ +${name}/src/swfstrings.1 \ +${name}/src/swfdump.1 \ +${name}/src/swfextract.1 \ +${name}/src/jpeg2swf.1 \ +${name}/src/png2swf.1 \ +${name}/src/pdf2swf.1 \ +${name}/src/gif2swf.1 \ +${name}/src/wav2swf.1 \ +${name}/src/swfc.1 \ +${name}/src/swfbbox.1 \ +${name}/src/font2swf.1 \ +${name}/src/swfrender.1 \ +${name}/src/as3compile.1 \ +${name}/src/swfbytes.1 \ +${name}/src/pdf2pdf.1 \ +${name}/src/swfcombine.c \ +${name}/src/swfstrings.c \ +${name}/src/swfdump.c \ +${name}/src/font2swf.c \ +${name}/src/swfbbox.c \ +${name}/src/swfextract.c \ +${name}/src/jpeg2swf.c \ +${name}/src/ttftool.c \ +${name}/src/png2swf.c \ +${name}/src/gif2swf.c \ +${name}/src/wav2swf.c \ +${name}/src/pdf2swf.c \ +${name}/src/pdf2pdf.c \ +${name}/lib/pdf/pdf2jpeg.c \ +${name}/src/swfc.c \ +${name}/src/swfc-feedback.c \ +${name}/src/swfc-history.c \ +${name}/src/swfc-interpolation.c \ +${name}/src/swfc-feedback.h \ +${name}/src/swfc-history.h \ +${name}/src/swfc-interpolation.h \ +${name}/src/parser.yy.c \ +${name}/src/parser.lex \ +${name}/src/parser.h \ +${name}/src/swfrender.c \ +${name}/src/swfbytes.c \ +${name}/src/as3compile.c \ +${name}/swfs/simple_viewer.c \ +${name}/swfs/keyboard_viewer.c \ +${name}/swfs/PreLoaderTemplate.c \ +${name}/swfs/PreLoaderTemplate.sc \ +${name}/swfs/rfxview.sc \ +${name}/swfs/rfxview.swf \ +${name}/swfs/swft_loader.swf \ +${name}/swfs/tessel_loader.swf" + +AVI2SWF="${name}/avi2swf/avi2swf.cc \ +${name}/avi2swf/videoreader.h \ +${name}/avi2swf/videoreader_avifile.hh \ +${name}/avi2swf/videoreader_avifile.cc \ +${name}/avi2swf/videoreader_vfw.hh \ +${name}/avi2swf/videoreader_vfw.cc \ +${name}/avi2swf/v2swf.c \ +${name}/avi2swf/v2swf.h \ +${name}/avi2swf/avi2swf.1" + +MAKEFILES="${name}/src/Makefile.in \ +${name}/lib/readers/Makefile.in \ +${name}/lib/Makefile.in \ +${name}/avi2swf/Makefile.in \ +${name}/lib/pdf/Makefile.in \ +${name}/lib/action/Makefile.in \ +${name}/swfs/Makefile.in \ +${name}/Makefile.in \ +${name}/Makefile.common.in" + +LIB="${name}/lib/types.h \ +${name}/lib/action/lex.swf4.c \ +${name}/lib/action/lex.swf5.c \ +${name}/lib/action/swf4compiler.tab.c \ +${name}/lib/action/swf5compiler.tab.c \ +${name}/lib/action/swf4compiler.tab.h \ +${name}/lib/action/swf5compiler.tab.h \ +${name}/lib/args.h \ +${name}/lib/bitio.c \ +${name}/lib/bitio.h \ +${name}/lib/q.c \ +${name}/lib/q.h \ +${name}/lib/utf8.c \ +${name}/lib/utf8.h \ +${name}/lib/base64.c \ +${name}/lib/base64.h \ +${name}/lib/png.h \ +${name}/lib/png.c \ +${name}/lib/jpeg.h \ +${name}/lib/jpeg.c \ +${name}/lib/kdtree.h \ +${name}/lib/kdtree.c \ +${name}/lib/drawer.c \ +${name}/lib/drawer.h \ +${name}/lib/mem.c \ +${name}/lib/mem.h \ +${name}/lib/graphcut.c \ +${name}/lib/graphcut.h \ +${name}/lib/modules/swffilter.c \ +${name}/lib/modules/swfrender.c \ +${name}/lib/modules/swfalignzones.c \ +${name}/lib/readers/swf.c \ +${name}/lib/readers/swf.h \ +${name}/lib/readers/image.c \ +${name}/lib/readers/image.h \ +${name}/lib/modules/swfdump.c \ +${name}/lib/modules/swfobject.c \ +${name}/lib/modules/swfshape.c \ +${name}/lib/modules/swftext.c \ +${name}/lib/modules/swffont.c \ +${name}/lib/gocr/box.c \ +${name}/lib/gocr/database.c \ +${name}/lib/gocr/detect.c \ +${name}/lib/gocr/gocr.h \ +${name}/lib/gocr/job.c \ +${name}/lib/gocr/lines.c \ +${name}/lib/gocr/list.c \ +${name}/lib/gocr/list.h \ +${name}/lib/gocr/ocr0.c \ +${name}/lib/gocr/ocr0.h \ +${name}/lib/gocr/ocr0n.c \ +${name}/lib/gocr/ocr1.c \ +${name}/lib/gocr/ocr1.h \ +${name}/lib/gocr/otsu.c \ +${name}/lib/gocr/otsu.h \ +${name}/lib/gocr/output.c \ +${name}/lib/gocr/output.h \ +${name}/lib/gocr/pgm2asc.c \ +${name}/lib/gocr/pgm2asc.h \ +${name}/lib/gocr/pixel.c \ +${name}/lib/gocr/pnm.h \ +${name}/lib/gocr/progress.c \ +${name}/lib/gocr/progress.h \ +${name}/lib/gocr/remove.c \ +${name}/lib/gocr/unicode.c \ +${name}/lib/gocr/unicode.h \ +${name}/lib/gfxfont.h \ +${name}/lib/gfxfont.c \ +${name}/lib/modules/swfbutton.c \ +${name}/lib/modules/swfbits.c \ +${name}/lib/modules/swftools.c \ +${name}/lib/modules/swfcgi.c \ +${name}/lib/modules/swfsound.c \ +${name}/lib/mp3.c \ +${name}/lib/wav.c \ +${name}/lib/wav.h \ +${name}/lib/mp3.h \ +${name}/lib/xml.h \ +${name}/lib/xml.c \ +${name}/lib/ttf.h \ +${name}/lib/ttf.c \ +${name}/lib/modules/swfdraw.c \ +${name}/lib/modules/swfaction.c \ +${name}/lib/as3/parser_help.h \ +${name}/lib/as3/parser_help.c \ +${name}/lib/as3/state.h \ +${name}/lib/as3/state.c \ +${name}/lib/as3/assets.c \ +${name}/lib/as3/assets.h \ +${name}/lib/as3/code.c \ +${name}/lib/as3/code.h \ +${name}/lib/as3/import.c \ +${name}/lib/as3/import.h \ +${name}/lib/as3/registry.c \ +${name}/lib/as3/registry.h \ +${name}/lib/as3/builtin.c \ +${name}/lib/as3/builtin.h \ +${name}/lib/as3/opcodes.c \ +${name}/lib/as3/opcodes.h \ +${name}/lib/as3/pool.c \ +${name}/lib/as3/pool.h \ +${name}/lib/as3/files.c \ +${name}/lib/as3/files.h \ +${name}/lib/as3/abc.c \ +${name}/lib/as3/abc.h \ +${name}/lib/as3/compiler.c \ +${name}/lib/as3/compiler.h \ +${name}/lib/as3/parser.h \ +${name}/lib/as3/common.h \ +${name}/lib/as3/common.c \ +${name}/lib/as3/tokenizer.yy.c \ +${name}/lib/as3/tokenizer.h \ +${name}/lib/as3/expr.h \ +${name}/lib/as3/expr.c \ +${name}/lib/as3/parser.tab.c \ +${name}/lib/as3/parser.tab.h \ +${name}/lib/as3/initcode.c \ +${name}/lib/as3/initcode.h \ +${name}/lib/as3/scripts.c \ +${name}/lib/as3/scripts.h \ +${name}/lib/action/action.h \ +${name}/lib/action/actioncompiler.c \ +${name}/lib/action/actioncompiler.h \ +${name}/lib/action/assembler.c \ +${name}/lib/action/assembler.h \ +${name}/lib/action/blocks/error.h \ +${name}/lib/action/compile.c \ +${name}/lib/action/compile.h \ +${name}/lib/action/libming.c \ +${name}/lib/action/libming.h \ +${name}/lib/action/listaction.c \ +${name}/lib/action/ming.h \ +${name}/lib/action/swf4compiler.flex \ +${name}/lib/action/swf4compiler.y \ +${name}/lib/action/swf5compiler.flex \ +${name}/lib/action/swf5compiler.y \ +${name}/lib/h.263/swfvideo.c \ +${name}/lib/h.263/h263tables.c \ +${name}/lib/h.263/h263tables.h \ +${name}/lib/h.263/dct.c \ +${name}/lib/h.263/dct.h +${name}/lib/rfxswf.c \ +${name}/lib/rfxswf.h \ +${name}/lib/old_rfxswf.h \ +${name}/lib/log.c \ +${name}/lib/log.h \ +${name}/lib/os.c \ +${name}/lib/os.h \ +${name}/lib/gfximage.c \ +${name}/lib/gfximage.h \ +${name}/lib/gfxdevice.h \ +${name}/lib/gfxsource.h \ +${name}/lib/gfxtools.h \ +${name}/lib/gfxpoly.h \ +${name}/lib/gfxtools.c \ +${name}/lib/gfxfilter.h \ +${name}/lib/gfxfilter.c \ +${name}/lib/gfxpoly/active.c \ +${name}/lib/gfxpoly/active.h \ +${name}/lib/gfxpoly/convert.c \ +${name}/lib/gfxpoly/convert.h \ +${name}/lib/gfxpoly/poly.c \ +${name}/lib/gfxpoly/poly.h \ +${name}/lib/gfxpoly/renderpoly.c \ +${name}/lib/gfxpoly/renderpoly.h \ +${name}/lib/gfxpoly/stroke.c \ +${name}/lib/gfxpoly/stroke.h \ +${name}/lib/gfxpoly/wind.c \ +${name}/lib/gfxpoly/wind.h \ +${name}/lib/gfxpoly/xrow.c \ +${name}/lib/gfxpoly/xrow.h \ +${name}/lib/gfxpoly/moments.c \ +${name}/lib/gfxpoly/moments.h \ +${name}/lib/gfxpoly/heap.h \ +${name}/lib/pdf/bbox.c \ +${name}/lib/pdf/bbox.h \ +${name}/lib/kdtree.c \ +${name}/lib/kdtree.h \ +${name}/lib/devices/ocr.h \ +${name}/lib/devices/ocr.c \ +${name}/lib/devices/swf.h \ +${name}/lib/devices/swf.c \ +${name}/lib/devices/file.h \ +${name}/lib/devices/file.c \ +${name}/lib/devices/render.c \ +${name}/lib/devices/render.h \ +${name}/lib/devices/text.c \ +${name}/lib/devices/text.h \ +${name}/lib/devices/pdf.c \ +${name}/lib/devices/pdf.h \ +${name}/lib/devices/polyops.c \ +${name}/lib/devices/polyops.h \ +${name}/lib/devices/record.c \ +${name}/lib/devices/record.h \ +${name}/lib/devices/opengl.c \ +${name}/lib/devices/opengl.h \ +${name}/lib/devices/rescale.c \ +${name}/lib/devices/rescale.h \ +${name}/lib/devices/dummy.c \ +${name}/lib/devices/dummy.h \ +${name}/lib/devices/bbox.c \ +${name}/lib/devices/bbox.h \ +${name}/lib/devices/ops.c \ +${name}/lib/devices/ops.h \ +${name}/lib/filters/alpha.c \ +${name}/lib/filters/one_big_font.c \ +${name}/lib/filters/vectors_to_glyphs.c \ +${name}/lib/filters/remove_font_transforms.c \ +${name}/lib/filters/remove_invisible_characters.c \ +${name}/lib/filters/flatten.c \ +${name}/lib/filters/rescale_images.c \ +${name}/lib/pdf/popplercompat.cc \ +${name}/lib/pdf/popplercompat.h \ +${name}/lib/pdf/VectorGraphicOutputDev.h \ +${name}/lib/pdf/VectorGraphicOutputDev.cc \ +${name}/lib/pdf/CharOutputDev.h \ +${name}/lib/pdf/CharOutputDev.cc \ +${name}/lib/pdf/CommonOutputDev.h \ +${name}/lib/pdf/CommonOutputDev.cc \ +${name}/lib/pdf/BitmapOutputDev.h \ +${name}/lib/pdf/FullBitmapOutputDev.h \ +${name}/lib/pdf/BitmapOutputDev.cc \ +${name}/lib/pdf/FullBitmapOutputDev.cc \ +${name}/lib/pdf/InfoOutputDev.h \ +${name}/lib/pdf/InfoOutputDev.cc \ +${name}/lib/pdf/XMLOutputDev.h \ +${name}/lib/pdf/XMLOutputDev.cc \ +${name}/lib/pdf/CommonOutputDev.h \ +${name}/lib/pdf/fonts.c \ +${name}/lib/pdf/fonts.h \ +${name}/lib/pdf/pdf.cc \ +${name}/lib/pdf/pdf.h \ +${name}/lib/pdf/popplercompat.cc \ +${name}/lib/pdf/popplercompat.h \ +${name}/lib/pdf/xpdf/Annot.cc \ +${name}/lib/pdf/xpdf/Annot.h \ +${name}/lib/pdf/xpdf/Array.cc \ +${name}/lib/pdf/xpdf/Array.h \ +${name}/lib/pdf/xpdf/BuiltinFont.cc \ +${name}/lib/pdf/xpdf/BuiltinFont.h \ +${name}/lib/pdf/xpdf/BuiltinFontTables.cc \ +${name}/lib/pdf/xpdf/BuiltinFontTables.h \ +${name}/lib/pdf/xpdf/CMap.cc \ +${name}/lib/pdf/xpdf/CMap.h \ +${name}/lib/pdf/xpdf/SecurityHandler.cc \ +${name}/lib/pdf/xpdf/SecurityHandler.h \ +${name}/lib/pdf/xpdf/Catalog.cc \ +${name}/lib/pdf/xpdf/Catalog.h \ +${name}/lib/pdf/xpdf/CharCodeToUnicode.cc \ +${name}/lib/pdf/xpdf/CharCodeToUnicode.h \ +${name}/lib/pdf/xpdf/CharTypes.h \ +${name}/lib/pdf/xpdf/Decrypt.cc \ +${name}/lib/pdf/xpdf/Decrypt.h \ +${name}/lib/pdf/xpdf/Dict.cc \ +${name}/lib/pdf/xpdf/Dict.h \ +${name}/lib/pdf/xpdf/Error.cc \ +${name}/lib/pdf/xpdf/Error.h \ +${name}/lib/pdf/xpdf/ErrorCodes.h \ +${name}/lib/pdf/xpdf/FontEncodingTables.cc \ +${name}/lib/pdf/xpdf/FontEncodingTables.h \ +${name}/lib/pdf/xpdf/Function.cc \ +${name}/lib/pdf/xpdf/Function.h \ +${name}/lib/pdf/xpdf/GHash.cc \ +${name}/lib/pdf/xpdf/GHash.h \ +${name}/lib/pdf/xpdf/GList.cc \ +${name}/lib/pdf/xpdf/GList.h \ +${name}/lib/pdf/xpdf/GString.cc \ +${name}/lib/pdf/xpdf/GString.h \ +${name}/lib/pdf/xpdf/Gfx.cc \ +${name}/lib/pdf/xpdf/Gfx.h \ +${name}/lib/pdf/xpdf/GfxFont.cc \ +${name}/lib/pdf/xpdf/GfxFont.h \ +${name}/lib/pdf/xpdf/GfxState.cc \ +${name}/lib/pdf/xpdf/GfxState.h \ +${name}/lib/pdf/cmyk.cc \ +${name}/lib/pdf/cmyk.h \ +${name}/lib/pdf/xpdf/GlobalParams.cc \ +${name}/lib/pdf/xpdf/GlobalParams.h \ +${name}/lib/pdf/xpdf/Lexer.cc \ +${name}/lib/pdf/xpdf/Lexer.h \ +${name}/lib/pdf/xpdf/Link.cc \ +${name}/lib/pdf/xpdf/Link.h \ +${name}/lib/pdf/xpdf/NameToCharCode.cc \ +${name}/lib/pdf/xpdf/NameToCharCode.h \ +${name}/lib/pdf/xpdf/NameToUnicodeTable.h \ +${name}/lib/pdf/xpdf/UnicodeTypeTable.cc \ +${name}/lib/pdf/xpdf/UnicodeTypeTable.h \ +${name}/lib/pdf/xpdf/Object.cc \ +${name}/lib/pdf/xpdf/Object.h \ +${name}/lib/pdf/xpdf/OutputDev.cc \ +${name}/lib/pdf/xpdf/OutputDev.h \ +${name}/lib/pdf/xpdf/PDFDoc.cc \ +${name}/lib/pdf/xpdf/PDFDoc.h \ +${name}/lib/pdf/xpdf/PSTokenizer.cc \ +${name}/lib/pdf/xpdf/PSTokenizer.h \ +${name}/lib/pdf/xpdf/Page.cc \ +${name}/lib/pdf/xpdf/Page.h \ +${name}/lib/pdf/xpdf/Parser.cc \ +${name}/lib/pdf/xpdf/Parser.h \ +${name}/lib/pdf/xpdf/Stream-CCITT.h \ +${name}/lib/pdf/xpdf/Stream.cc \ +${name}/lib/pdf/xpdf/Stream.h \ +${name}/lib/pdf/xpdf/UTF8.h \ +${name}/lib/pdf/xpdf/UnicodeMap.cc \ +${name}/lib/pdf/xpdf/UnicodeMap.h \ +${name}/lib/pdf/xpdf/UnicodeMapTables.h \ +${name}/lib/pdf/xpdf/XRef.cc \ +${name}/lib/pdf/xpdf/XRef.h \ +${name}/lib/pdf/aconf.h \ +${name}/lib/pdf/xpdf/config.h \ +${name}/lib/pdf/xpdf/gfile.cc \ +${name}/lib/pdf/xpdf/gfile.h \ +${name}/lib/pdf/xpdf/gmem.cc \ +${name}/lib/pdf/xpdf/gmem.h \ +${name}/lib/pdf/xpdf/gtypes.h \ +${name}/lib/pdf/xpdf/FoFiBase.cc \ +${name}/lib/pdf/xpdf/FoFiEncodings.cc \ +${name}/lib/pdf/xpdf/FoFiTrueType.cc \ +${name}/lib/pdf/xpdf/FoFiType1.cc \ +${name}/lib/pdf/xpdf/FoFiType1C.cc \ +${name}/lib/pdf/xpdf/JArithmeticDecoder.cc \ +${name}/lib/pdf/xpdf/JBIG2Stream.cc \ +${name}/lib/pdf/xpdf/JPXStream.cc \ +${name}/lib/pdf/xpdf/Outline.cc \ +${name}/lib/pdf/xpdf/PDFDocEncoding.cc \ +${name}/lib/pdf/xpdf/FoFiBase.h \ +${name}/lib/pdf/xpdf/FoFiEncodings.h \ +${name}/lib/pdf/xpdf/FoFiTrueType.h \ +${name}/lib/pdf/xpdf/FoFiType1.h \ +${name}/lib/pdf/xpdf/FoFiType1C.h \ +${name}/lib/pdf/xpdf/GMutex.h \ +${name}/lib/pdf/xpdf/JArithmeticDecoder.h \ +${name}/lib/pdf/xpdf/JBIG2Stream.h \ +${name}/lib/pdf/xpdf/JPXStream.h \ +${name}/lib/pdf/xpdf/Outline.h \ +${name}/lib/pdf/xpdf/PDFDocEncoding.h \ +${name}/lib/pdf/xpdf/Splash.cc \ +${name}/lib/pdf/xpdf/Splash.h \ +${name}/lib/pdf/xpdf/SplashBitmap.cc \ +${name}/lib/pdf/xpdf/SplashBitmap.h \ +${name}/lib/pdf/xpdf/SplashClip.cc \ +${name}/lib/pdf/xpdf/SplashClip.h \ +${name}/lib/pdf/xpdf/SplashErrorCodes.h \ +${name}/lib/pdf/xpdf/SplashFTFont.cc \ +${name}/lib/pdf/xpdf/SplashFTFont.h \ +${name}/lib/pdf/xpdf/SplashFTFontEngine.cc \ +${name}/lib/pdf/xpdf/SplashFTFontEngine.h \ +${name}/lib/pdf/xpdf/SplashFTFontFile.cc \ +${name}/lib/pdf/xpdf/SplashFTFontFile.h \ +${name}/lib/pdf/xpdf/SplashFont.cc \ +${name}/lib/pdf/xpdf/SplashFont.h \ +${name}/lib/pdf/xpdf/SplashFontEngine.cc \ +${name}/lib/pdf/xpdf/SplashFontEngine.h \ +${name}/lib/pdf/xpdf/SplashFontFile.cc \ +${name}/lib/pdf/xpdf/SplashFontFile.h \ +${name}/lib/pdf/xpdf/SplashFontFileID.cc \ +${name}/lib/pdf/xpdf/SplashFontFileID.h \ +${name}/lib/pdf/xpdf/SplashGlyphBitmap.h \ +${name}/lib/pdf/xpdf/SplashMath.h \ +${name}/lib/pdf/xpdf/SplashOutputDev.cc \ +${name}/lib/pdf/xpdf/SplashOutputDev.h \ +${name}/lib/pdf/xpdf/TextOutputDev.cc \ +${name}/lib/pdf/xpdf/TextOutputDev.h \ +${name}/lib/pdf/xpdf/SplashPath.cc \ +${name}/lib/pdf/xpdf/SplashPath.h \ +${name}/lib/pdf/xpdf/SplashPattern.cc \ +${name}/lib/pdf/xpdf/SplashPattern.h \ +${name}/lib/pdf/xpdf/SplashScreen.cc \ +${name}/lib/pdf/xpdf/SplashScreen.h \ +${name}/lib/pdf/xpdf/SplashState.cc \ +${name}/lib/pdf/xpdf/SplashState.h \ +${name}/lib/pdf/xpdf/SplashT1Font.cc \ +${name}/lib/pdf/xpdf/SplashT1Font.h \ +${name}/lib/pdf/xpdf/SplashT1FontEngine.cc \ +${name}/lib/pdf/xpdf/SplashT1FontEngine.h \ +${name}/lib/pdf/xpdf/SplashT1FontFile.cc \ +${name}/lib/pdf/xpdf/SplashT1FontFile.h \ +${name}/lib/pdf/xpdf/SplashTypes.h \ +${name}/lib/pdf/xpdf/SplashXPath.cc \ +${name}/lib/pdf/xpdf/SplashXPath.h \ +${name}/lib/pdf/xpdf/SplashXPathScanner.cc \ +${name}/lib/pdf/xpdf/SplashXPathScanner.h" + +PYTHON="${name}/lib/python/Makefile.in \ +${name}/lib/python/SWF.c \ +${name}/lib/python/gfx.c \ +${name}/lib/python/image.c \ +${name}/lib/python/image.h \ +${name}/lib/python/primitives.c \ +${name}/lib/python/primitives.h \ +${name}/lib/python/pyutils.c \ +${name}/lib/python/pyutils.h \ +${name}/lib/python/action.c \ +${name}/lib/python/action.h \ +${name}/lib/python/tag.c \ +${name}/lib/python/tag.h \ +${name}/lib/python/tags.c \ +${name}/lib/python/tags.h \ +${name}/lib/python/taglist.c \ +${name}/lib/python/taglist.h \ +${name}/lib/python/tagmap.c \ +${name}/lib/python/tagmap.h \ +${name}/setup.py" + +WXPDF2SWF="" #TODO +#WXPDF2SWF=" \ +#${name}/wx/pdf2swf.py \ +#${name}/wx/images.py" + +CONFIGURE="${name}/configure.in \ +${name}/configure \ +${name}/config.h.in \ +${name}/config.guess \ +${name}/config.sub \ +${name}/m4/byteorder.m4 \ +${name}/m4/backticks.m4 \ +${name}/m4/fontconfig.m4 \ +${name}/m4/freetype.m4 \ +${name}/m4/gcc.2.95.m4 \ +${name}/m4/mingw.m4 \ +${name}/m4/python.m4 \ +${name}/m4/avi2swf.m4 \ +${name}/m4/Makefile \ +${name}/install-sh \ +${name}/mkinstalldirs \ +${name}/missing \ +${name}/ltmain.sh" + +DOC="${name}/doc/fileformat.sc \ +${name}/ChangeLog" + +tar -chf ${name}.tar \ +${SOURCES} ${AVI2SWF} ${MAKEFILES} ${DOC} ${LIB} ${PYTHON} ${WXPDF2SWF} ${CONFIGURE} \ +${name}/INSTALL \ +${name}/COPYING \ +${name}/AUTHORS \ + +gzip -9 ${name}.tar +rm -f ${name} + diff -Nru swftools-0.9.2+ds1/rendertest/athana.py swftools-0.9.1/rendertest/athana.py --- swftools-0.9.2+ds1/rendertest/athana.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/rendertest/athana.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,6845 @@ +#!/usr/bin/python +""" + Athana - standalone web server including the TAL template language + + Copyright (C) 2007 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 3 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, see . +""" + +#=============================================================== +# +# Athana +# +# A standalone webserver based on Medusa and the Zope TAL Parser +# +# This file is distributed under the GPL, see file COPYING for details. +# +#=============================================================== +""" +Parse HTML and compile to TALInterpreter intermediate code. +""" + +RCS_ID = '$Id: athana.py,v 1.15 2007/11/23 10:13:32 kramm Exp $' + +import sys + +from HTMLParser import HTMLParser, HTMLParseError + +BOOLEAN_HTML_ATTRS = [ + "compact", "nowrap", "ismap", "declare", "noshade", "checked", + "disabled", "readonly", "multiple", "selected", "noresize", + "defer" + ] + +EMPTY_HTML_TAGS = [ + "base", "meta", "link", "hr", "br", "param", "img", "area", + "input", "col", "basefont", "isindex", "frame", + ] + +PARA_LEVEL_HTML_TAGS = [ + "h1", "h2", "h3", "h4", "h5", "h6", "p", + ] + +BLOCK_CLOSING_TAG_MAP = { + "tr": ("tr", "td", "th"), + "td": ("td", "th"), + "th": ("td", "th"), + "li": ("li",), + "dd": ("dd", "dt"), + "dt": ("dd", "dt"), + } + +BLOCK_LEVEL_HTML_TAGS = [ + "blockquote", "table", "tr", "th", "td", "thead", "tfoot", "tbody", + "noframe", "ul", "ol", "li", "dl", "dt", "dd", "div", + ] + +TIGHTEN_IMPLICIT_CLOSE_TAGS = (PARA_LEVEL_HTML_TAGS + + BLOCK_CLOSING_TAG_MAP.keys()) + + +class NestingError(HTMLParseError): + """Exception raised when elements aren't properly nested.""" + + def __init__(self, tagstack, endtag, position=(None, None)): + self.endtag = endtag + if tagstack: + if len(tagstack) == 1: + msg = ('Open tag <%s> does not match close tag ' + % (tagstack[0], endtag)) + else: + msg = ('Open tags <%s> do not match close tag ' + % ('>, <'.join(tagstack), endtag)) + else: + msg = 'No tags are open to match ' % endtag + HTMLParseError.__init__(self, msg, position) + +class EmptyTagError(NestingError): + """Exception raised when empty elements have an end tag.""" + + def __init__(self, tag, position=(None, None)): + self.tag = tag + msg = 'Close tag should be removed' % tag + HTMLParseError.__init__(self, msg, position) + +class OpenTagError(NestingError): + """Exception raised when a tag is not allowed in another tag.""" + + def __init__(self, tagstack, tag, position=(None, None)): + self.tag = tag + msg = 'Tag <%s> is not allowed in <%s>' % (tag, tagstack[-1]) + HTMLParseError.__init__(self, msg, position) + +class HTMLTALParser(HTMLParser): + + + def __init__(self, gen=None): + HTMLParser.__init__(self) + if gen is None: + gen = TALGenerator(xml=0) + self.gen = gen + self.tagstack = [] + self.nsstack = [] + self.nsdict = {'tal': ZOPE_TAL_NS, + 'metal': ZOPE_METAL_NS, + 'i18n': ZOPE_I18N_NS, + } + + def parseFile(self, file): + f = open(file) + data = f.read() + f.close() + try: + self.parseString(data) + except TALError, e: + e.setFile(file) + raise + + def parseString(self, data): + self.feed(data) + self.close() + while self.tagstack: + self.implied_endtag(self.tagstack[-1], 2) + assert self.nsstack == [], self.nsstack + + def getCode(self): + return self.gen.getCode() + + def getWarnings(self): + return () + + + def handle_starttag(self, tag, attrs): + self.close_para_tags(tag) + self.scan_xmlns(attrs) + tag, attrlist, taldict, metaldict, i18ndict \ + = self.process_ns(tag, attrs) + if tag in EMPTY_HTML_TAGS and taldict.get("content"): + raise TALError( + "empty HTML tags cannot use tal:content: %s" % `tag`, + self.getpos()) + self.tagstack.append(tag) + self.gen.emitStartElement(tag, attrlist, taldict, metaldict, i18ndict, + self.getpos()) + if tag in EMPTY_HTML_TAGS: + self.implied_endtag(tag, -1) + + def handle_startendtag(self, tag, attrs): + self.close_para_tags(tag) + self.scan_xmlns(attrs) + tag, attrlist, taldict, metaldict, i18ndict \ + = self.process_ns(tag, attrs) + if taldict.get("content"): + if tag in EMPTY_HTML_TAGS: + raise TALError( + "empty HTML tags cannot use tal:content: %s" % `tag`, + self.getpos()) + self.gen.emitStartElement(tag, attrlist, taldict, metaldict, + i18ndict, self.getpos()) + self.gen.emitEndElement(tag, implied=-1) + else: + self.gen.emitStartElement(tag, attrlist, taldict, metaldict, + i18ndict, self.getpos(), isend=1) + self.pop_xmlns() + + def handle_endtag(self, tag): + if tag in EMPTY_HTML_TAGS: + raise EmptyTagError(tag, self.getpos()) + self.close_enclosed_tags(tag) + self.gen.emitEndElement(tag) + self.pop_xmlns() + self.tagstack.pop() + + def close_para_tags(self, tag): + if tag in EMPTY_HTML_TAGS: + return + close_to = -1 + if BLOCK_CLOSING_TAG_MAP.has_key(tag): + blocks_to_close = BLOCK_CLOSING_TAG_MAP[tag] + for i in range(len(self.tagstack)): + t = self.tagstack[i] + if t in blocks_to_close: + if close_to == -1: + close_to = i + elif t in BLOCK_LEVEL_HTML_TAGS: + close_to = -1 + elif tag in PARA_LEVEL_HTML_TAGS + BLOCK_LEVEL_HTML_TAGS: + i = len(self.tagstack) - 1 + while i >= 0: + closetag = self.tagstack[i] + if closetag in BLOCK_LEVEL_HTML_TAGS: + break + if closetag in PARA_LEVEL_HTML_TAGS: + if closetag != "p": + raise OpenTagError(self.tagstack, tag, self.getpos()) + close_to = i + i = i - 1 + if close_to >= 0: + while len(self.tagstack) > close_to: + self.implied_endtag(self.tagstack[-1], 1) + + def close_enclosed_tags(self, tag): + if tag not in self.tagstack: + raise NestingError(self.tagstack, tag, self.getpos()) + while tag != self.tagstack[-1]: + self.implied_endtag(self.tagstack[-1], 1) + assert self.tagstack[-1] == tag + + def implied_endtag(self, tag, implied): + assert tag == self.tagstack[-1] + assert implied in (-1, 1, 2) + isend = (implied < 0) + if tag in TIGHTEN_IMPLICIT_CLOSE_TAGS: + white = self.gen.unEmitWhitespace() + else: + white = None + self.gen.emitEndElement(tag, isend=isend, implied=implied) + if white: + self.gen.emitRawText(white) + self.tagstack.pop() + self.pop_xmlns() + + def handle_charref(self, name): + self.gen.emitRawText("&#%s;" % name) + + def handle_entityref(self, name): + self.gen.emitRawText("&%s;" % name) + + def handle_data(self, data): + self.gen.emitRawText(data) + + def handle_comment(self, data): + self.gen.emitRawText("" % data) + + def handle_decl(self, data): + self.gen.emitRawText("" % data) + + def handle_pi(self, data): + self.gen.emitRawText("" % data) + + + def scan_xmlns(self, attrs): + nsnew = {} + for key, value in attrs: + if key.startswith("xmlns:"): + nsnew[key[6:]] = value + if nsnew: + self.nsstack.append(self.nsdict) + self.nsdict = self.nsdict.copy() + self.nsdict.update(nsnew) + else: + self.nsstack.append(self.nsdict) + + def pop_xmlns(self): + self.nsdict = self.nsstack.pop() + + def fixname(self, name): + if ':' in name: + prefix, suffix = name.split(':', 1) + if prefix == 'xmlns': + nsuri = self.nsdict.get(suffix) + if nsuri in (ZOPE_TAL_NS, ZOPE_METAL_NS, ZOPE_I18N_NS): + return name, name, prefix + else: + nsuri = self.nsdict.get(prefix) + if nsuri == ZOPE_TAL_NS: + return name, suffix, 'tal' + elif nsuri == ZOPE_METAL_NS: + return name, suffix, 'metal' + elif nsuri == ZOPE_I18N_NS: + return name, suffix, 'i18n' + return name, name, 0 + + def process_ns(self, name, attrs): + attrlist = [] + taldict = {} + metaldict = {} + i18ndict = {} + name, namebase, namens = self.fixname(name) + for item in attrs: + key, value = item + key, keybase, keyns = self.fixname(key) + ns = keyns or namens # default to tag namespace + if ns and ns != 'unknown': + item = (key, value, ns) + if ns == 'tal': + if taldict.has_key(keybase): + raise TALError("duplicate TAL attribute " + + `keybase`, self.getpos()) + taldict[keybase] = value + elif ns == 'metal': + if metaldict.has_key(keybase): + raise METALError("duplicate METAL attribute " + + `keybase`, self.getpos()) + metaldict[keybase] = value + elif ns == 'i18n': + if i18ndict.has_key(keybase): + raise I18NError("duplicate i18n attribute " + + `keybase`, self.getpos()) + i18ndict[keybase] = value + attrlist.append(item) + if namens in ('metal', 'tal'): + taldict['tal tag'] = namens + return name, attrlist, taldict, metaldict, i18ndict +""" +Generic expat-based XML parser base class. +""" + + +class XMLParser: + + ordered_attributes = 0 + + handler_names = [ + "StartElementHandler", + "EndElementHandler", + "ProcessingInstructionHandler", + "CharacterDataHandler", + "UnparsedEntityDeclHandler", + "NotationDeclHandler", + "StartNamespaceDeclHandler", + "EndNamespaceDeclHandler", + "CommentHandler", + "StartCdataSectionHandler", + "EndCdataSectionHandler", + "DefaultHandler", + "DefaultHandlerExpand", + "NotStandaloneHandler", + "ExternalEntityRefHandler", + "XmlDeclHandler", + "StartDoctypeDeclHandler", + "EndDoctypeDeclHandler", + "ElementDeclHandler", + "AttlistDeclHandler" + ] + + def __init__(self, encoding=None): + self.parser = p = self.createParser() + if self.ordered_attributes: + try: + self.parser.ordered_attributes = self.ordered_attributes + except AttributeError: + print "Can't set ordered_attributes" + self.ordered_attributes = 0 + for name in self.handler_names: + method = getattr(self, name, None) + if method is not None: + try: + setattr(p, name, method) + except AttributeError: + print "Can't set expat handler %s" % name + + def createParser(self, encoding=None): + global XMLParseError + try: + from Products.ParsedXML.Expat import pyexpat + XMLParseError = pyexpat.ExpatError + return pyexpat.ParserCreate(encoding, ' ') + except ImportError: + from xml.parsers import expat + XMLParseError = expat.ExpatError + return expat.ParserCreate(encoding, ' ') + + def parseFile(self, filename): + f = open(filename) + self.parseStream(f) + #self.parseStream(open(filename)) + + def parseString(self, s): + self.parser.Parse(s, 1) + + def parseURL(self, url): + import urllib + self.parseStream(urllib.urlopen(url)) + + def parseStream(self, stream): + self.parser.ParseFile(stream) + + def parseFragment(self, s, end=0): + self.parser.Parse(s, end) +"""Interface that a TALES engine provides to the METAL/TAL implementation.""" + +try: + from Interface import Interface + from Interface.Attribute import Attribute +except: + class Interface: pass + def Attribute(*args): pass + + +class ITALESCompiler(Interface): + """Compile-time interface provided by a TALES implementation. + + The TAL compiler needs an instance of this interface to support + compilation of TALES expressions embedded in documents containing + TAL and METAL constructs. + """ + + def getCompilerError(): + """Return the exception class raised for compilation errors. + """ + + def compile(expression): + """Return a compiled form of 'expression' for later evaluation. + + 'expression' is the source text of the expression. + + The return value may be passed to the various evaluate*() + methods of the ITALESEngine interface. No compatibility is + required for the values of the compiled expression between + different ITALESEngine implementations. + """ + + +class ITALESEngine(Interface): + """Render-time interface provided by a TALES implementation. + + The TAL interpreter uses this interface to TALES to support + evaluation of the compiled expressions returned by + ITALESCompiler.compile(). + """ + + def getCompiler(): + """Return an object that supports ITALESCompiler.""" + + def getDefault(): + """Return the value of the 'default' TALES expression. + + Checking a value for a match with 'default' should be done + using the 'is' operator in Python. + """ + + def setPosition((lineno, offset)): + """Inform the engine of the current position in the source file. + + This is used to allow the evaluation engine to report + execution errors so that site developers can more easily + locate the offending expression. + """ + + def setSourceFile(filename): + """Inform the engine of the name of the current source file. + + This is used to allow the evaluation engine to report + execution errors so that site developers can more easily + locate the offending expression. + """ + + def beginScope(): + """Push a new scope onto the stack of open scopes. + """ + + def endScope(): + """Pop one scope from the stack of open scopes. + """ + + def evaluate(compiled_expression): + """Evaluate an arbitrary expression. + + No constraints are imposed on the return value. + """ + + def evaluateBoolean(compiled_expression): + """Evaluate an expression that must return a Boolean value. + """ + + def evaluateMacro(compiled_expression): + """Evaluate an expression that must return a macro program. + """ + + def evaluateStructure(compiled_expression): + """Evaluate an expression that must return a structured + document fragment. + + The result of evaluating 'compiled_expression' must be a + string containing a parsable HTML or XML fragment. Any TAL + markup cnotained in the result string will be interpreted. + """ + + def evaluateText(compiled_expression): + """Evaluate an expression that must return text. + + The returned text should be suitable for direct inclusion in + the output: any HTML or XML escaping or quoting is the + responsibility of the expression itself. + """ + + def evaluateValue(compiled_expression): + """Evaluate an arbitrary expression. + + No constraints are imposed on the return value. + """ + + def createErrorInfo(exception, (lineno, offset)): + """Returns an ITALESErrorInfo object. + + The returned object is used to provide information about the + error condition for the on-error handler. + """ + + def setGlobal(name, value): + """Set a global variable. + + The variable will be named 'name' and have the value 'value'. + """ + + def setLocal(name, value): + """Set a local variable in the current scope. + + The variable will be named 'name' and have the value 'value'. + """ + + def setRepeat(name, compiled_expression): + """ + """ + + def translate(domain, msgid, mapping, default=None): + """ + See ITranslationService.translate() + """ + + +class ITALESErrorInfo(Interface): + + type = Attribute("type", + "The exception class.") + + value = Attribute("value", + "The exception instance.") + + lineno = Attribute("lineno", + "The line number the error occurred on in the source.") + + offset = Attribute("offset", + "The character offset at which the error occurred.") +""" +Common definitions used by TAL and METAL compilation an transformation. +""" + +from types import ListType, TupleType + + +TAL_VERSION = "1.5" + +XML_NS = "http://www.w3.org/XML/1998/namespace" # URI for XML namespace +XMLNS_NS = "http://www.w3.org/2000/xmlns/" # URI for XML NS declarations + +ZOPE_TAL_NS = "http://xml.zope.org/namespaces/tal" +ZOPE_METAL_NS = "http://xml.zope.org/namespaces/metal" +ZOPE_I18N_NS = "http://xml.zope.org/namespaces/i18n" + +NAME_RE = "[a-zA-Z_][-a-zA-Z0-9_]*" + +KNOWN_METAL_ATTRIBUTES = [ + "define-macro", + "use-macro", + "define-slot", + "fill-slot", + "slot", + ] + +KNOWN_TAL_ATTRIBUTES = [ + "define", + "condition", + "content", + "replace", + "repeat", + "attributes", + "on-error", + "omit-tag", + "tal tag", + ] + +KNOWN_I18N_ATTRIBUTES = [ + "translate", + "domain", + "target", + "source", + "attributes", + "data", + "name", + ] + +class TALError(Exception): + + def __init__(self, msg, position=(None, None)): + assert msg != "" + self.msg = msg + self.lineno = position[0] + self.offset = position[1] + self.filename = None + + def setFile(self, filename): + self.filename = filename + + def __str__(self): + result = self.msg + if self.lineno is not None: + result = result + ", at line %d" % self.lineno + if self.offset is not None: + result = result + ", column %d" % (self.offset + 1) + if self.filename is not None: + result = result + ', in file %s' % self.filename + return result + +class METALError(TALError): + pass + +class TALESError(TALError): + pass + +class I18NError(TALError): + pass + + +class ErrorInfo: + + __implements__ = ITALESErrorInfo + + def __init__(self, err, position=(None, None)): + if isinstance(err, Exception): + self.type = err.__class__ + self.value = err + else: + self.type = err + self.value = None + self.lineno = position[0] + self.offset = position[1] + + + +import re +_attr_re = re.compile(r"\s*([^\s]+)\s+([^\s].*)\Z", re.S) +_subst_re = re.compile(r"\s*(?:(text|raw|structure)\s+)?(.*)\Z", re.S) +del re + +def parseAttributeReplacements(arg, xml): + dict = {} + for part in splitParts(arg): + m = _attr_re.match(part) + if not m: + raise TALError("Bad syntax in attributes: " + `part`) + name, expr = m.group(1, 2) + if not xml: + name = name.lower() + if dict.has_key(name): + raise TALError("Duplicate attribute name in attributes: " + `part`) + dict[name] = expr + return dict + +def parseSubstitution(arg, position=(None, None)): + m = _subst_re.match(arg) + if not m: + raise TALError("Bad syntax in substitution text: " + `arg`, position) + key, expr = m.group(1, 2) + if not key: + key = "text" + return key, expr + +def splitParts(arg): + arg = arg.replace(";;", "\0") + parts = arg.split(';') + parts = [p.replace("\0", ";") for p in parts] + if len(parts) > 1 and not parts[-1].strip(): + del parts[-1] # It ended in a semicolon + return parts + +def isCurrentVersion(program): + version = getProgramVersion(program) + return version == TAL_VERSION + +def getProgramMode(program): + version = getProgramVersion(program) + if (version == TAL_VERSION and isinstance(program[1], TupleType) and + len(program[1]) == 2): + opcode, mode = program[1] + if opcode == "mode": + return mode + return None + +def getProgramVersion(program): + if (len(program) >= 2 and + isinstance(program[0], TupleType) and len(program[0]) == 2): + opcode, version = program[0] + if opcode == "version": + return version + return None + +import re +_ent1_re = re.compile('&(?![A-Z#])', re.I) +_entch_re = re.compile('&([A-Z][A-Z0-9]*)(?![A-Z0-9;])', re.I) +_entn1_re = re.compile('&#(?![0-9X])', re.I) +_entnx_re = re.compile('&(#X[A-F0-9]*)(?![A-F0-9;])', re.I) +_entnd_re = re.compile('&(#[0-9][0-9]*)(?![0-9;])') +del re + +def attrEscape(s): + """Replace special characters '&<>' by character entities, + except when '&' already begins a syntactically valid entity.""" + s = _ent1_re.sub('&', s) + s = _entch_re.sub(r'&\1', s) + s = _entn1_re.sub('&#', s) + s = _entnx_re.sub(r'&\1', s) + s = _entnd_re.sub(r'&\1', s) + s = s.replace('<', '<') + s = s.replace('>', '>') + s = s.replace('"', '"') + return s +""" +Code generator for TALInterpreter intermediate code. +""" + +import re +import cgi + + + +I18N_REPLACE = 1 +I18N_CONTENT = 2 +I18N_EXPRESSION = 3 + +_name_rx = re.compile(NAME_RE) + + +class TALGenerator: + + inMacroUse = 0 + inMacroDef = 0 + source_file = None + + def __init__(self, expressionCompiler=None, xml=1, source_file=None): + if not expressionCompiler: + expressionCompiler = AthanaTALEngine() + self.expressionCompiler = expressionCompiler + self.CompilerError = expressionCompiler.getCompilerError() + self.program = [] + self.stack = [] + self.todoStack = [] + self.macros = {} + self.slots = {} + self.slotStack = [] + self.xml = xml + self.emit("version", TAL_VERSION) + self.emit("mode", xml and "xml" or "html") + if source_file is not None: + self.source_file = source_file + self.emit("setSourceFile", source_file) + self.i18nContext = TranslationContext() + self.i18nLevel = 0 + + def getCode(self): + assert not self.stack + assert not self.todoStack + return self.optimize(self.program), self.macros + + def optimize(self, program): + output = [] + collect = [] + cursor = 0 + if self.xml: + endsep = "/>" + else: + endsep = " />" + for cursor in xrange(len(program)+1): + try: + item = program[cursor] + except IndexError: + item = (None, None) + opcode = item[0] + if opcode == "rawtext": + collect.append(item[1]) + continue + if opcode == "endTag": + collect.append("" % item[1]) + continue + if opcode == "startTag": + if self.optimizeStartTag(collect, item[1], item[2], ">"): + continue + if opcode == "startEndTag": + if self.optimizeStartTag(collect, item[1], item[2], endsep): + continue + if opcode in ("beginScope", "endScope"): + output.append(self.optimizeArgsList(item)) + continue + if opcode == 'noop': + opcode = None + pass + text = "".join(collect) + if text: + i = text.rfind("\n") + if i >= 0: + i = len(text) - (i + 1) + output.append(("rawtextColumn", (text, i))) + else: + output.append(("rawtextOffset", (text, len(text)))) + if opcode != None: + output.append(self.optimizeArgsList(item)) + collect = [] + return self.optimizeCommonTriple(output) + + def optimizeArgsList(self, item): + if len(item) == 2: + return item + else: + return item[0], tuple(item[1:]) + + def optimizeStartTag(self, collect, name, attrlist, end): + if not attrlist: + collect.append("<%s%s" % (name, end)) + return 1 + opt = 1 + new = ["<" + name] + for i in range(len(attrlist)): + item = attrlist[i] + if len(item) > 2: + opt = 0 + name, value, action = item[:3] + attrlist[i] = (name, value, action) + item[3:] + else: + if item[1] is None: + s = item[0] + else: + s = '%s="%s"' % (item[0], attrEscape(item[1])) + attrlist[i] = item[0], s + new.append(" " + s) + if opt: + new.append(end) + collect.extend(new) + return opt + + def optimizeCommonTriple(self, program): + if len(program) < 3: + return program + output = program[:2] + prev2, prev1 = output + for item in program[2:]: + if ( item[0] == "beginScope" + and prev1[0] == "setPosition" + and prev2[0] == "rawtextColumn"): + position = output.pop()[1] + text, column = output.pop()[1] + prev1 = None, None + closeprev = 0 + if output and output[-1][0] == "endScope": + closeprev = 1 + output.pop() + item = ("rawtextBeginScope", + (text, column, position, closeprev, item[1])) + output.append(item) + prev2 = prev1 + prev1 = item + return output + + def todoPush(self, todo): + self.todoStack.append(todo) + + def todoPop(self): + return self.todoStack.pop() + + def compileExpression(self, expr): + try: + return self.expressionCompiler.compile(expr) + except self.CompilerError, err: + raise TALError('%s in expression %s' % (err.args[0], `expr`), + self.position) + + def pushProgram(self): + self.stack.append(self.program) + self.program = [] + + def popProgram(self): + program = self.program + self.program = self.stack.pop() + return self.optimize(program) + + def pushSlots(self): + self.slotStack.append(self.slots) + self.slots = {} + + def popSlots(self): + slots = self.slots + self.slots = self.slotStack.pop() + return slots + + def emit(self, *instruction): + self.program.append(instruction) + + def emitStartTag(self, name, attrlist, isend=0): + if isend: + opcode = "startEndTag" + else: + opcode = "startTag" + self.emit(opcode, name, attrlist) + + def emitEndTag(self, name): + if self.xml and self.program and self.program[-1][0] == "startTag": + self.program[-1] = ("startEndTag",) + self.program[-1][1:] + else: + self.emit("endTag", name) + + def emitOptTag(self, name, optTag, isend): + program = self.popProgram() #block + start = self.popProgram() #start tag + if (isend or not program) and self.xml: + start[-1] = ("startEndTag",) + start[-1][1:] + isend = 1 + cexpr = optTag[0] + if cexpr: + cexpr = self.compileExpression(optTag[0]) + self.emit("optTag", name, cexpr, optTag[1], isend, start, program) + + def emitRawText(self, text): + self.emit("rawtext", text) + + def emitText(self, text): + self.emitRawText(cgi.escape(text)) + + def emitDefines(self, defines): + for part in splitParts(defines): + m = re.match( + r"(?s)\s*(?:(global|local)\s+)?(%s)\s+(.*)\Z" % NAME_RE, part) + if not m: + raise TALError("invalid define syntax: " + `part`, + self.position) + scope, name, expr = m.group(1, 2, 3) + scope = scope or "local" + cexpr = self.compileExpression(expr) + if scope == "local": + self.emit("setLocal", name, cexpr) + else: + self.emit("setGlobal", name, cexpr) + + def emitOnError(self, name, onError, TALtag, isend): + block = self.popProgram() + key, expr = parseSubstitution(onError) + cexpr = self.compileExpression(expr) + if key == "text": + self.emit("insertText", cexpr, []) + elif key == "raw": + self.emit("insertRaw", cexpr, []) + else: + assert key == "structure" + self.emit("insertStructure", cexpr, {}, []) + if TALtag: + self.emitOptTag(name, (None, 1), isend) + else: + self.emitEndTag(name) + handler = self.popProgram() + self.emit("onError", block, handler) + + def emitCondition(self, expr): + cexpr = self.compileExpression(expr) + program = self.popProgram() + self.emit("condition", cexpr, program) + + def emitRepeat(self, arg): + + + m = re.match("(?s)\s*(%s)\s+(.*)\Z" % NAME_RE, arg) + if not m: + raise TALError("invalid repeat syntax: " + `arg`, + self.position) + name, expr = m.group(1, 2) + cexpr = self.compileExpression(expr) + program = self.popProgram() + self.emit("loop", name, cexpr, program) + + + def emitSubstitution(self, arg, attrDict={}): + key, expr = parseSubstitution(arg) + cexpr = self.compileExpression(expr) + program = self.popProgram() + if key == "text": + self.emit("insertText", cexpr, program) + elif key == "raw": + self.emit("insertRaw", cexpr, program) + else: + assert key == "structure" + self.emit("insertStructure", cexpr, attrDict, program) + + def emitI18nVariable(self, stuff): + varname, action, expression = stuff + m = _name_rx.match(varname) + if m is None or m.group() != varname: + raise TALError("illegal i18n:name: %r" % varname, self.position) + key = cexpr = None + program = self.popProgram() + if action == I18N_REPLACE: + program = program[1:-1] + elif action == I18N_CONTENT: + pass + else: + assert action == I18N_EXPRESSION + key, expr = parseSubstitution(expression) + cexpr = self.compileExpression(expr) + self.emit('i18nVariable', + varname, program, cexpr, int(key == "structure")) + + def emitTranslation(self, msgid, i18ndata): + program = self.popProgram() + if i18ndata is None: + self.emit('insertTranslation', msgid, program) + else: + key, expr = parseSubstitution(i18ndata) + cexpr = self.compileExpression(expr) + assert key == 'text' + self.emit('insertTranslation', msgid, program, cexpr) + + def emitDefineMacro(self, macroName): + program = self.popProgram() + macroName = macroName.strip() + if self.macros.has_key(macroName): + raise METALError("duplicate macro definition: %s" % `macroName`, + self.position) + if not re.match('%s$' % NAME_RE, macroName): + raise METALError("invalid macro name: %s" % `macroName`, + self.position) + self.macros[macroName] = program + self.inMacroDef = self.inMacroDef - 1 + self.emit("defineMacro", macroName, program) + + def emitUseMacro(self, expr): + cexpr = self.compileExpression(expr) + program = self.popProgram() + self.inMacroUse = 0 + self.emit("useMacro", expr, cexpr, self.popSlots(), program) + + def emitDefineSlot(self, slotName): + program = self.popProgram() + slotName = slotName.strip() + if not re.match('%s$' % NAME_RE, slotName): + raise METALError("invalid slot name: %s" % `slotName`, + self.position) + self.emit("defineSlot", slotName, program) + + def emitFillSlot(self, slotName): + program = self.popProgram() + slotName = slotName.strip() + if self.slots.has_key(slotName): + raise METALError("duplicate fill-slot name: %s" % `slotName`, + self.position) + if not re.match('%s$' % NAME_RE, slotName): + raise METALError("invalid slot name: %s" % `slotName`, + self.position) + self.slots[slotName] = program + self.inMacroUse = 1 + self.emit("fillSlot", slotName, program) + + def unEmitWhitespace(self): + collect = [] + i = len(self.program) - 1 + while i >= 0: + item = self.program[i] + if item[0] != "rawtext": + break + text = item[1] + if not re.match(r"\A\s*\Z", text): + break + collect.append(text) + i = i-1 + del self.program[i+1:] + if i >= 0 and self.program[i][0] == "rawtext": + text = self.program[i][1] + m = re.search(r"\s+\Z", text) + if m: + self.program[i] = ("rawtext", text[:m.start()]) + collect.append(m.group()) + collect.reverse() + return "".join(collect) + + def unEmitNewlineWhitespace(self): + collect = [] + i = len(self.program) + while i > 0: + i = i-1 + item = self.program[i] + if item[0] != "rawtext": + break + text = item[1] + if re.match(r"\A[ \t]*\Z", text): + collect.append(text) + continue + m = re.match(r"(?s)^(.*)(\n[ \t]*)\Z", text) + if not m: + break + text, rest = m.group(1, 2) + collect.reverse() + rest = rest + "".join(collect) + del self.program[i:] + if text: + self.emit("rawtext", text) + return rest + return None + + def replaceAttrs(self, attrlist, repldict): + if not repldict: + return attrlist + newlist = [] + for item in attrlist: + key = item[0] + if repldict.has_key(key): + expr, xlat, msgid = repldict[key] + item = item[:2] + ("replace", expr, xlat, msgid) + del repldict[key] + newlist.append(item) + for key, (expr, xlat, msgid) in repldict.items(): + newlist.append((key, None, "insert", expr, xlat, msgid)) + return newlist + + def emitStartElement(self, name, attrlist, taldict, metaldict, i18ndict, + position=(None, None), isend=0): + if not taldict and not metaldict and not i18ndict: + self.emitStartTag(name, attrlist, isend) + self.todoPush({}) + if isend: + self.emitEndElement(name, isend) + return + + self.position = position + for key, value in taldict.items(): + if key not in KNOWN_TAL_ATTRIBUTES: + raise TALError("bad TAL attribute: " + `key`, position) + if not (value or key == 'omit-tag'): + raise TALError("missing value for TAL attribute: " + + `key`, position) + for key, value in metaldict.items(): + if key not in KNOWN_METAL_ATTRIBUTES: + raise METALError("bad METAL attribute: " + `key`, + position) + if not value: + raise TALError("missing value for METAL attribute: " + + `key`, position) + for key, value in i18ndict.items(): + if key not in KNOWN_I18N_ATTRIBUTES: + raise I18NError("bad i18n attribute: " + `key`, position) + if not value and key in ("attributes", "data", "id"): + raise I18NError("missing value for i18n attribute: " + + `key`, position) + todo = {} + defineMacro = metaldict.get("define-macro") + useMacro = metaldict.get("use-macro") + defineSlot = metaldict.get("define-slot") + fillSlot = metaldict.get("fill-slot") + define = taldict.get("define") + condition = taldict.get("condition") + repeat = taldict.get("repeat") + content = taldict.get("content") + replace = taldict.get("replace") + attrsubst = taldict.get("attributes") + onError = taldict.get("on-error") + omitTag = taldict.get("omit-tag") + TALtag = taldict.get("tal tag") + i18nattrs = i18ndict.get("attributes") + msgid = i18ndict.get("translate") + varname = i18ndict.get('name') + i18ndata = i18ndict.get('data') + + if varname and not self.i18nLevel: + raise I18NError( + "i18n:name can only occur inside a translation unit", + position) + + if i18ndata and not msgid: + raise I18NError("i18n:data must be accompanied by i18n:translate", + position) + + if len(metaldict) > 1 and (defineMacro or useMacro): + raise METALError("define-macro and use-macro cannot be used " + "together or with define-slot or fill-slot", + position) + if replace: + if content: + raise TALError( + "tal:content and tal:replace are mutually exclusive", + position) + if msgid is not None: + raise I18NError( + "i18n:translate and tal:replace are mutually exclusive", + position) + + repeatWhitespace = None + if repeat: + repeatWhitespace = self.unEmitNewlineWhitespace() + if position != (None, None): + self.emit("setPosition", position) + if self.inMacroUse: + if fillSlot: + self.pushProgram() + if self.source_file is not None: + self.emit("setSourceFile", self.source_file) + todo["fillSlot"] = fillSlot + self.inMacroUse = 0 + else: + if fillSlot: + raise METALError("fill-slot must be within a use-macro", + position) + if not self.inMacroUse: + if defineMacro: + self.pushProgram() + self.emit("version", TAL_VERSION) + self.emit("mode", self.xml and "xml" or "html") + if self.source_file is not None: + self.emit("setSourceFile", self.source_file) + todo["defineMacro"] = defineMacro + self.inMacroDef = self.inMacroDef + 1 + if useMacro: + self.pushSlots() + self.pushProgram() + todo["useMacro"] = useMacro + self.inMacroUse = 1 + if defineSlot: + if not self.inMacroDef: + raise METALError( + "define-slot must be within a define-macro", + position) + self.pushProgram() + todo["defineSlot"] = defineSlot + + if defineSlot or i18ndict: + + domain = i18ndict.get("domain") or self.i18nContext.domain + source = i18ndict.get("source") or self.i18nContext.source + target = i18ndict.get("target") or self.i18nContext.target + if ( domain != DEFAULT_DOMAIN + or source is not None + or target is not None): + self.i18nContext = TranslationContext(self.i18nContext, + domain=domain, + source=source, + target=target) + self.emit("beginI18nContext", + {"domain": domain, "source": source, + "target": target}) + todo["i18ncontext"] = 1 + if taldict or i18ndict: + dict = {} + for item in attrlist: + key, value = item[:2] + dict[key] = value + self.emit("beginScope", dict) + todo["scope"] = 1 + if onError: + self.pushProgram() # handler + if TALtag: + self.pushProgram() # start + self.emitStartTag(name, list(attrlist)) # Must copy attrlist! + if TALtag: + self.pushProgram() # start + self.pushProgram() # block + todo["onError"] = onError + if define: + self.emitDefines(define) + todo["define"] = define + if condition: + self.pushProgram() + todo["condition"] = condition + if repeat: + todo["repeat"] = repeat + self.pushProgram() + if repeatWhitespace: + self.emitText(repeatWhitespace) + if content: + if varname: + todo['i18nvar'] = (varname, I18N_CONTENT, None) + todo["content"] = content + self.pushProgram() + else: + todo["content"] = content + elif replace: + if varname: + todo['i18nvar'] = (varname, I18N_EXPRESSION, replace) + else: + todo["replace"] = replace + self.pushProgram() + elif varname: + todo['i18nvar'] = (varname, I18N_REPLACE, None) + self.pushProgram() + if msgid is not None: + self.i18nLevel += 1 + todo['msgid'] = msgid + if i18ndata: + todo['i18ndata'] = i18ndata + optTag = omitTag is not None or TALtag + if optTag: + todo["optional tag"] = omitTag, TALtag + self.pushProgram() + if attrsubst or i18nattrs: + if attrsubst: + repldict = parseAttributeReplacements(attrsubst, + self.xml) + else: + repldict = {} + if i18nattrs: + i18nattrs = _parseI18nAttributes(i18nattrs, attrlist, repldict, + self.position, self.xml, + self.source_file) + else: + i18nattrs = {} + for key, value in repldict.items(): + if i18nattrs.get(key, None): + raise I18NError( + ("attribute [%s] cannot both be part of tal:attributes" + + " and have a msgid in i18n:attributes") % key, + position) + ce = self.compileExpression(value) + repldict[key] = ce, key in i18nattrs, i18nattrs.get(key) + for key in i18nattrs: + if not repldict.has_key(key): + repldict[key] = None, 1, i18nattrs.get(key) + else: + repldict = {} + if replace: + todo["repldict"] = repldict + repldict = {} + self.emitStartTag(name, self.replaceAttrs(attrlist, repldict), isend) + if optTag: + self.pushProgram() + if content and not varname: + self.pushProgram() + if msgid is not None: + self.pushProgram() + if content and varname: + self.pushProgram() + if todo and position != (None, None): + todo["position"] = position + self.todoPush(todo) + if isend: + self.emitEndElement(name, isend) + + def emitEndElement(self, name, isend=0, implied=0): + todo = self.todoPop() + if not todo: + if not isend: + self.emitEndTag(name) + return + + self.position = position = todo.get("position", (None, None)) + defineMacro = todo.get("defineMacro") + useMacro = todo.get("useMacro") + defineSlot = todo.get("defineSlot") + fillSlot = todo.get("fillSlot") + repeat = todo.get("repeat") + content = todo.get("content") + replace = todo.get("replace") + condition = todo.get("condition") + onError = todo.get("onError") + repldict = todo.get("repldict", {}) + scope = todo.get("scope") + optTag = todo.get("optional tag") + msgid = todo.get('msgid') + i18ncontext = todo.get("i18ncontext") + varname = todo.get('i18nvar') + i18ndata = todo.get('i18ndata') + + if implied > 0: + if defineMacro or useMacro or defineSlot or fillSlot: + exc = METALError + what = "METAL" + else: + exc = TALError + what = "TAL" + raise exc("%s attributes on <%s> require explicit " % + (what, name, name), position) + + if content: + self.emitSubstitution(content, {}) + if msgid is not None: + if (not varname) or ( + varname and (varname[1] == I18N_CONTENT)): + self.emitTranslation(msgid, i18ndata) + self.i18nLevel -= 1 + if optTag: + self.emitOptTag(name, optTag, isend) + elif not isend: + if varname: + self.emit('noop') + self.emitEndTag(name) + if replace: + self.emitSubstitution(replace, repldict) + elif varname: + assert (varname[1] + in [I18N_REPLACE, I18N_CONTENT, I18N_EXPRESSION]) + self.emitI18nVariable(varname) + if msgid is not None: + if varname and (varname[1] <> I18N_CONTENT): + self.emitTranslation(msgid, i18ndata) + if repeat: + self.emitRepeat(repeat) + if condition: + self.emitCondition(condition) + if onError: + self.emitOnError(name, onError, optTag and optTag[1], isend) + if scope: + self.emit("endScope") + if i18ncontext: + self.emit("endI18nContext") + assert self.i18nContext.parent is not None + self.i18nContext = self.i18nContext.parent + if defineSlot: + self.emitDefineSlot(defineSlot) + if fillSlot: + self.emitFillSlot(fillSlot) + if useMacro: + self.emitUseMacro(useMacro) + if defineMacro: + self.emitDefineMacro(defineMacro) + +def _parseI18nAttributes(i18nattrs, attrlist, repldict, position, + xml, source_file): + + def addAttribute(dic, attr, msgid, position, xml): + if not xml: + attr = attr.lower() + if attr in dic: + raise TALError( + "attribute may only be specified once in i18n:attributes: " + + attr, + position) + dic[attr] = msgid + + d = {} + if ';' in i18nattrs: + i18nattrlist = i18nattrs.split(';') + i18nattrlist = [attr.strip().split() + for attr in i18nattrlist if attr.strip()] + for parts in i18nattrlist: + if len(parts) > 2: + raise TALError("illegal i18n:attributes specification: %r" + % parts, position) + if len(parts) == 2: + attr, msgid = parts + else: + attr = parts[0] + msgid = None + addAttribute(d, attr, msgid, position, xml) + else: + i18nattrlist = i18nattrs.split() + if len(i18nattrlist) == 1: + addAttribute(d, i18nattrlist[0], None, position, xml) + elif len(i18nattrlist) == 2: + staticattrs = [attr[0] for attr in attrlist if len(attr) == 2] + if (not i18nattrlist[1] in staticattrs) and ( + not i18nattrlist[1] in repldict): + attr, msgid = i18nattrlist + addAttribute(d, attr, msgid, position, xml) + else: + import warnings + warnings.warn(I18N_ATTRIBUTES_WARNING + % (source_file, str(position), i18nattrs) + , DeprecationWarning) + msgid = None + for attr in i18nattrlist: + addAttribute(d, attr, msgid, position, xml) + else: + import warnings + warnings.warn(I18N_ATTRIBUTES_WARNING + % (source_file, str(position), i18nattrs) + , DeprecationWarning) + msgid = None + for attr in i18nattrlist: + addAttribute(d, attr, msgid, position, xml) + return d + +I18N_ATTRIBUTES_WARNING = ( + 'Space separated attributes in i18n:attributes' + ' are deprecated (i18n:attributes="value title"). Please use' + ' semicolon to separate attributes' + ' (i18n:attributes="value; title").' + '\nFile %s at row, column %s\nAttributes %s') + +"""Interpreter for a pre-compiled TAL program. + +""" +import cgi +import sys +import getopt +import re +from cgi import escape + +from StringIO import StringIO + + + +class ConflictError: + pass + +class MessageID: + pass + + + +BOOLEAN_HTML_ATTRS = [ + "compact", "nowrap", "ismap", "declare", "noshade", "checked", + "disabled", "readonly", "multiple", "selected", "noresize", + "defer" +] + +def _init(): + d = {} + for s in BOOLEAN_HTML_ATTRS: + d[s] = 1 + return d + +BOOLEAN_HTML_ATTRS = _init() + +_nulljoin = ''.join +_spacejoin = ' '.join + +def normalize(text): + return _spacejoin(text.split()) + + +NAME_RE = r"[a-zA-Z][a-zA-Z0-9_]*" +_interp_regex = re.compile(r'(?" + self.endlen = len(self.endsep) + self.macroStack = [] + self.position = None, None # (lineno, offset) + self.col = 0 + self.level = 0 + self.scopeLevel = 0 + self.sourceFile = None + self.i18nStack = [] + self.i18nInterpolate = i18nInterpolate + self.i18nContext = TranslationContext() + + def StringIO(self): + return FasterStringIO() + + def saveState(self): + return (self.position, self.col, self.stream, + self.scopeLevel, self.level, self.i18nContext) + + def restoreState(self, state): + (self.position, self.col, self.stream, + scopeLevel, level, i18n) = state + self._stream_write = self.stream.write + assert self.level == level + while self.scopeLevel > scopeLevel: + self.engine.endScope() + self.scopeLevel = self.scopeLevel - 1 + self.engine.setPosition(self.position) + self.i18nContext = i18n + + def restoreOutputState(self, state): + (dummy, self.col, self.stream, + scopeLevel, level, i18n) = state + self._stream_write = self.stream.write + assert self.level == level + assert self.scopeLevel == scopeLevel + + def pushMacro(self, macroName, slots, entering=1): + if len(self.macroStack) >= self.stackLimit: + raise METALError("macro nesting limit (%d) exceeded " + "by %s" % (self.stackLimit, `macroName`)) + self.macroStack.append([macroName, slots, entering, self.i18nContext]) + + def popMacro(self): + return self.macroStack.pop() + + def __call__(self): + assert self.level == 0 + assert self.scopeLevel == 0 + assert self.i18nContext.parent is None + self.interpret(self.program) + assert self.level == 0 + assert self.scopeLevel == 0 + assert self.i18nContext.parent is None + if self.col > 0: + self._stream_write("\n") + self.col = 0 + + def interpretWithStream(self, program, stream): + oldstream = self.stream + self.stream = stream + self._stream_write = stream.write + try: + self.interpret(program) + finally: + self.stream = oldstream + self._stream_write = oldstream.write + + def stream_write(self, s, + len=len): + self._stream_write(s) + i = s.rfind('\n') + if i < 0: + self.col = self.col + len(s) + else: + self.col = len(s) - (i + 1) + + bytecode_handlers = {} + + def interpret(self, program): + oldlevel = self.level + self.level = oldlevel + 1 + handlers = self.dispatch + try: + if self.debug: + for (opcode, args) in program: + s = "%sdo_%s(%s)\n" % (" "*self.level, opcode, + repr(args)) + if len(s) > 80: + s = s[:76] + "...\n" + sys.stderr.write(s) + handlers[opcode](self, args) + else: + for (opcode, args) in program: + handlers[opcode](self, args) + finally: + self.level = oldlevel + + def do_version(self, version): + assert version == TAL_VERSION + bytecode_handlers["version"] = do_version + + def do_mode(self, mode): + assert mode in ("html", "xml") + self.html = (mode == "html") + if self.html: + self.endsep = " />" + else: + self.endsep = "/>" + self.endlen = len(self.endsep) + bytecode_handlers["mode"] = do_mode + + def do_setSourceFile(self, source_file): + self.sourceFile = source_file + self.engine.setSourceFile(source_file) + bytecode_handlers["setSourceFile"] = do_setSourceFile + + def do_setPosition(self, position): + self.position = position + self.engine.setPosition(position) + bytecode_handlers["setPosition"] = do_setPosition + + def do_startEndTag(self, stuff): + self.do_startTag(stuff, self.endsep, self.endlen) + bytecode_handlers["startEndTag"] = do_startEndTag + + def do_startTag(self, (name, attrList), + end=">", endlen=1, _len=len): + self._currentTag = name + L = ["<", name] + append = L.append + col = self.col + _len(name) + 1 + wrap = self.wrap + align = col + 1 + if align >= wrap/2: + align = 4 # Avoid a narrow column far to the right + attrAction = self.dispatch[""] + try: + for item in attrList: + if _len(item) == 2: + name, s = item + else: + if item[2] in ('metal', 'tal', 'xmlns', 'i18n'): + if not self.showtal: + continue + ok, name, s = self.attrAction(item) + else: + ok, name, s = attrAction(self, item) + if not ok: + continue + slen = _len(s) + if (wrap and + col >= align and + col + 1 + slen > wrap): + append("\n") + append(" "*align) + col = align + slen + else: + append(" ") + col = col + 1 + slen + append(s) + append(end) + col = col + endlen + finally: + self._stream_write(_nulljoin(L)) + self.col = col + bytecode_handlers["startTag"] = do_startTag + + def attrAction(self, item): + name, value, action = item[:3] + if action == 'insert': + return 0, name, value + macs = self.macroStack + if action == 'metal' and self.metal and macs: + if len(macs) > 1 or not macs[-1][2]: + return 0, name, value + macs[-1][2] = 0 + i = name.rfind(":") + 1 + prefix, suffix = name[:i], name[i:] + if suffix == "define-macro": + name = prefix + "use-macro" + value = macs[-1][0] # Macro name + elif suffix == "define-slot": + name = prefix + "fill-slot" + elif suffix == "fill-slot": + pass + else: + return 0, name, value + + if value is None: + value = name + else: + value = '%s="%s"' % (name, attrEscape(value)) + return 1, name, value + + def attrAction_tal(self, item): + name, value, action = item[:3] + ok = 1 + expr, xlat, msgid = item[3:] + if self.html and name.lower() in BOOLEAN_HTML_ATTRS: + evalue = self.engine.evaluateBoolean(item[3]) + if evalue is self.Default: + if action == 'insert': # Cancelled insert + ok = 0 + elif evalue: + value = None + else: + ok = 0 + elif expr is not None: + evalue = self.engine.evaluateText(item[3]) + if evalue is self.Default: + if action == 'insert': # Cancelled insert + ok = 0 + else: + if evalue is None: + ok = 0 + value = evalue + else: + evalue = None + + if ok: + if xlat: + translated = self.translate(msgid or value, value, {}) + if translated is not None: + value = translated + if value is None: + value = name + elif evalue is self.Default: + value = attrEscape(value) + else: + value = escape(value, quote=1) + value = '%s="%s"' % (name, value) + return ok, name, value + bytecode_handlers[""] = attrAction + + def no_tag(self, start, program): + state = self.saveState() + self.stream = stream = self.StringIO() + self._stream_write = stream.write + self.interpret(start) + self.restoreOutputState(state) + self.interpret(program) + + def do_optTag(self, (name, cexpr, tag_ns, isend, start, program), + omit=0): + if tag_ns and not self.showtal: + return self.no_tag(start, program) + + self.interpret(start) + if not isend: + self.interpret(program) + s = '' % name + self._stream_write(s) + self.col = self.col + len(s) + + def do_optTag_tal(self, stuff): + cexpr = stuff[1] + if cexpr is not None and (cexpr == '' or + self.engine.evaluateBoolean(cexpr)): + self.no_tag(stuff[-2], stuff[-1]) + else: + self.do_optTag(stuff) + bytecode_handlers["optTag"] = do_optTag + + def do_rawtextBeginScope(self, (s, col, position, closeprev, dict)): + self._stream_write(s) + self.col = col + self.position = position + self.engine.setPosition(position) + if closeprev: + engine = self.engine + engine.endScope() + engine.beginScope() + else: + self.engine.beginScope() + self.scopeLevel = self.scopeLevel + 1 + + def do_rawtextBeginScope_tal(self, (s, col, position, closeprev, dict)): + self._stream_write(s) + self.col = col + engine = self.engine + self.position = position + engine.setPosition(position) + if closeprev: + engine.endScope() + engine.beginScope() + else: + engine.beginScope() + self.scopeLevel = self.scopeLevel + 1 + engine.setLocal("attrs", dict) + bytecode_handlers["rawtextBeginScope"] = do_rawtextBeginScope + + def do_beginScope(self, dict): + self.engine.beginScope() + self.scopeLevel = self.scopeLevel + 1 + + def do_beginScope_tal(self, dict): + engine = self.engine + engine.beginScope() + engine.setLocal("attrs", dict) + self.scopeLevel = self.scopeLevel + 1 + bytecode_handlers["beginScope"] = do_beginScope + + def do_endScope(self, notused=None): + self.engine.endScope() + self.scopeLevel = self.scopeLevel - 1 + bytecode_handlers["endScope"] = do_endScope + + def do_setLocal(self, notused): + pass + + def do_setLocal_tal(self, (name, expr)): + self.engine.setLocal(name, self.engine.evaluateValue(expr)) + bytecode_handlers["setLocal"] = do_setLocal + + def do_setGlobal_tal(self, (name, expr)): + self.engine.setGlobal(name, self.engine.evaluateValue(expr)) + bytecode_handlers["setGlobal"] = do_setLocal + + def do_beginI18nContext(self, settings): + get = settings.get + self.i18nContext = TranslationContext(self.i18nContext, + domain=get("domain"), + source=get("source"), + target=get("target")) + bytecode_handlers["beginI18nContext"] = do_beginI18nContext + + def do_endI18nContext(self, notused=None): + self.i18nContext = self.i18nContext.parent + assert self.i18nContext is not None + bytecode_handlers["endI18nContext"] = do_endI18nContext + + def do_insertText(self, stuff): + self.interpret(stuff[1]) + + def do_insertText_tal(self, stuff): + text = self.engine.evaluateText(stuff[0]) + if text is None: + return + if text is self.Default: + self.interpret(stuff[1]) + return + if isinstance(text, MessageID): + text = self.engine.translate(text.domain, text, text.mapping) + s = escape(text) + self._stream_write(s) + i = s.rfind('\n') + if i < 0: + self.col = self.col + len(s) + else: + self.col = len(s) - (i + 1) + bytecode_handlers["insertText"] = do_insertText + + def do_insertRawText_tal(self, stuff): + text = self.engine.evaluateText(stuff[0]) + if text is None: + return + if text is self.Default: + self.interpret(stuff[1]) + return + if isinstance(text, MessageID): + text = self.engine.translate(text.domain, text, text.mapping) + s = text + self._stream_write(s) + i = s.rfind('\n') + if i < 0: + self.col = self.col + len(s) + else: + self.col = len(s) - (i + 1) + + def do_i18nVariable(self, stuff): + varname, program, expression, structure = stuff + if expression is None: + state = self.saveState() + try: + tmpstream = self.StringIO() + self.interpretWithStream(program, tmpstream) + if self.html and self._currentTag == "pre": + value = tmpstream.getvalue() + else: + value = normalize(tmpstream.getvalue()) + finally: + self.restoreState(state) + else: + if structure: + value = self.engine.evaluateStructure(expression) + else: + value = self.engine.evaluate(expression) + + if isinstance(value, MessageID): + value = self.engine.translate(value.domain, value, + value.mapping) + + if not structure: + value = cgi.escape(ustr(value)) + + i18ndict, srepr = self.i18nStack[-1] + i18ndict[varname] = value + placeholder = '${%s}' % varname + srepr.append(placeholder) + self._stream_write(placeholder) + bytecode_handlers['i18nVariable'] = do_i18nVariable + + def do_insertTranslation(self, stuff): + i18ndict = {} + srepr = [] + obj = None + self.i18nStack.append((i18ndict, srepr)) + msgid = stuff[0] + currentTag = self._currentTag + tmpstream = self.StringIO() + self.interpretWithStream(stuff[1], tmpstream) + default = tmpstream.getvalue() + if not msgid: + if self.html and currentTag == "pre": + msgid = default + else: + msgid = normalize(default) + self.i18nStack.pop() + if len(stuff) > 2: + obj = self.engine.evaluate(stuff[2]) + xlated_msgid = self.translate(msgid, default, i18ndict, obj) + assert xlated_msgid is not None + self._stream_write(xlated_msgid) + bytecode_handlers['insertTranslation'] = do_insertTranslation + + def do_insertStructure(self, stuff): + self.interpret(stuff[2]) + + def do_insertStructure_tal(self, (expr, repldict, block)): + structure = self.engine.evaluateStructure(expr) + if structure is None: + return + if structure is self.Default: + self.interpret(block) + return + text = ustr(structure) + if not (repldict or self.strictinsert): + self.stream_write(text) + return + if self.html: + self.insertHTMLStructure(text, repldict) + else: + self.insertXMLStructure(text, repldict) + bytecode_handlers["insertStructure"] = do_insertStructure + + def insertHTMLStructure(self, text, repldict): + gen = AltTALGenerator(repldict, self.engine.getCompiler(), 0) + p = HTMLTALParser(gen) # Raises an exception if text is invalid + p.parseString(text) + program, macros = p.getCode() + self.interpret(program) + + def insertXMLStructure(self, text, repldict): + gen = AltTALGenerator(repldict, self.engine.getCompiler(), 0) + p = TALParser(gen) + gen.enable(0) + p.parseFragment('') + gen.enable(1) + p.parseFragment(text) # Raises an exception if text is invalid + gen.enable(0) + p.parseFragment('', 1) + program, macros = gen.getCode() + self.interpret(program) + + def do_loop(self, (name, expr, block)): + self.interpret(block) + + def do_loop_tal(self, (name, expr, block)): + iterator = self.engine.setRepeat(name, expr) + while iterator.next(): + self.interpret(block) + bytecode_handlers["loop"] = do_loop + + def translate(self, msgid, default, i18ndict, obj=None): + if obj: + i18ndict.update(obj) + if not self.i18nInterpolate: + return msgid + return self.engine.translate(self.i18nContext.domain, + msgid, i18ndict, default=default) + + def do_rawtextColumn(self, (s, col)): + self._stream_write(s) + self.col = col + bytecode_handlers["rawtextColumn"] = do_rawtextColumn + + def do_rawtextOffset(self, (s, offset)): + self._stream_write(s) + self.col = self.col + offset + bytecode_handlers["rawtextOffset"] = do_rawtextOffset + + def do_condition(self, (condition, block)): + if not self.tal or self.engine.evaluateBoolean(condition): + self.interpret(block) + bytecode_handlers["condition"] = do_condition + + def do_defineMacro(self, (macroName, macro)): + macs = self.macroStack + if len(macs) == 1: + entering = macs[-1][2] + if not entering: + macs.append(None) + self.interpret(macro) + assert macs[-1] is None + macs.pop() + return + self.interpret(macro) + bytecode_handlers["defineMacro"] = do_defineMacro + + def do_useMacro(self, (macroName, macroExpr, compiledSlots, block)): + if not self.metal: + self.interpret(block) + return + macro = self.engine.evaluateMacro(macroExpr) + if macro is self.Default: + macro = block + else: + if not isCurrentVersion(macro): + raise METALError("macro %s has incompatible version %s" % + (`macroName`, `getProgramVersion(macro)`), + self.position) + mode = getProgramMode(macro) + #if mode != (self.html and "html" or "xml"): + # raise METALError("macro %s has incompatible mode %s" % + # (`macroName`, `mode`), self.position) + + self.pushMacro(macroName, compiledSlots) + prev_source = self.sourceFile + self.interpret(macro) + if self.sourceFile != prev_source: + self.engine.setSourceFile(prev_source) + self.sourceFile = prev_source + self.popMacro() + bytecode_handlers["useMacro"] = do_useMacro + + def do_fillSlot(self, (slotName, block)): + self.interpret(block) + bytecode_handlers["fillSlot"] = do_fillSlot + + def do_defineSlot(self, (slotName, block)): + if not self.metal: + self.interpret(block) + return + macs = self.macroStack + if macs and macs[-1] is not None: + macroName, slots = self.popMacro()[:2] + slot = slots.get(slotName) + if slot is not None: + prev_source = self.sourceFile + self.interpret(slot) + if self.sourceFile != prev_source: + self.engine.setSourceFile(prev_source) + self.sourceFile = prev_source + self.pushMacro(macroName, slots, entering=0) + return + self.pushMacro(macroName, slots) + self.interpret(block) + bytecode_handlers["defineSlot"] = do_defineSlot + + def do_onError(self, (block, handler)): + self.interpret(block) + + def do_onError_tal(self, (block, handler)): + state = self.saveState() + self.stream = stream = self.StringIO() + self._stream_write = stream.write + try: + self.interpret(block) + except ConflictError: + raise + except: + exc = sys.exc_info()[1] + self.restoreState(state) + engine = self.engine + engine.beginScope() + error = engine.createErrorInfo(exc, self.position) + engine.setLocal('error', error) + try: + self.interpret(handler) + finally: + engine.endScope() + else: + self.restoreOutputState(state) + self.stream_write(stream.getvalue()) + bytecode_handlers["onError"] = do_onError + + bytecode_handlers_tal = bytecode_handlers.copy() + bytecode_handlers_tal["rawtextBeginScope"] = do_rawtextBeginScope_tal + bytecode_handlers_tal["beginScope"] = do_beginScope_tal + bytecode_handlers_tal["setLocal"] = do_setLocal_tal + bytecode_handlers_tal["setGlobal"] = do_setGlobal_tal + bytecode_handlers_tal["insertStructure"] = do_insertStructure_tal + bytecode_handlers_tal["insertText"] = do_insertText_tal + bytecode_handlers_tal["insertRaw"] = do_insertRawText_tal + bytecode_handlers_tal["loop"] = do_loop_tal + bytecode_handlers_tal["onError"] = do_onError_tal + bytecode_handlers_tal[""] = attrAction_tal + bytecode_handlers_tal["optTag"] = do_optTag_tal + + +class FasterStringIO(StringIO): + """Append-only version of StringIO. + + This let's us have a much faster write() method. + """ + def close(self): + if not self.closed: + self.write = _write_ValueError + StringIO.close(self) + + def seek(self, pos, mode=0): + raise RuntimeError("FasterStringIO.seek() not allowed") + + def write(self, s): + self.buflist.append(s) + self.len = self.pos = self.pos + len(s) + + +def _write_ValueError(s): + raise ValueError, "I/O operation on closed file" +""" +Parse XML and compile to TALInterpreter intermediate code. +""" + + +class TALParser(XMLParser): + + ordered_attributes = 1 + + def __init__(self, gen=None): # Override + XMLParser.__init__(self) + if gen is None: + gen = TALGenerator() + self.gen = gen + self.nsStack = [] + self.nsDict = {XML_NS: 'xml'} + self.nsNew = [] + + def getCode(self): + return self.gen.getCode() + + def getWarnings(self): + return () + + def StartNamespaceDeclHandler(self, prefix, uri): + self.nsStack.append(self.nsDict.copy()) + self.nsDict[uri] = prefix + self.nsNew.append((prefix, uri)) + + def EndNamespaceDeclHandler(self, prefix): + self.nsDict = self.nsStack.pop() + + def StartElementHandler(self, name, attrs): + if self.ordered_attributes: + attrlist = [] + for i in range(0, len(attrs), 2): + key = attrs[i] + value = attrs[i+1] + attrlist.append((key, value)) + else: + attrlist = attrs.items() + attrlist.sort() # For definiteness + name, attrlist, taldict, metaldict, i18ndict \ + = self.process_ns(name, attrlist) + attrlist = self.xmlnsattrs() + attrlist + self.gen.emitStartElement(name, attrlist, taldict, metaldict, i18ndict) + + def process_ns(self, name, attrlist): + taldict = {} + metaldict = {} + i18ndict = {} + fixedattrlist = [] + name, namebase, namens = self.fixname(name) + for key, value in attrlist: + key, keybase, keyns = self.fixname(key) + ns = keyns or namens # default to tag namespace + item = key, value + if ns == 'metal': + metaldict[keybase] = value + item = item + ("metal",) + elif ns == 'tal': + taldict[keybase] = value + item = item + ("tal",) + elif ns == 'i18n': + i18ndict[keybase] = value + item = item + ('i18n',) + fixedattrlist.append(item) + if namens in ('metal', 'tal', 'i18n'): + taldict['tal tag'] = namens + return name, fixedattrlist, taldict, metaldict, i18ndict + + def xmlnsattrs(self): + newlist = [] + for prefix, uri in self.nsNew: + if prefix: + key = "xmlns:" + prefix + else: + key = "xmlns" + if uri in (ZOPE_METAL_NS, ZOPE_TAL_NS, ZOPE_I18N_NS): + item = (key, uri, "xmlns") + else: + item = (key, uri) + newlist.append(item) + self.nsNew = [] + return newlist + + def fixname(self, name): + if ' ' in name: + uri, name = name.split(' ') + prefix = self.nsDict[uri] + prefixed = name + if prefix: + prefixed = "%s:%s" % (prefix, name) + ns = 'x' + if uri == ZOPE_TAL_NS: + ns = 'tal' + elif uri == ZOPE_METAL_NS: + ns = 'metal' + elif uri == ZOPE_I18N_NS: + ns = 'i18n' + return (prefixed, name, ns) + return (name, name, None) + + def EndElementHandler(self, name): + name = self.fixname(name)[0] + self.gen.emitEndElement(name) + + def DefaultHandler(self, text): + self.gen.emitRawText(text) + +"""Translation context object for the TALInterpreter's I18N support. + +The translation context provides a container for the information +needed to perform translation of a marked string from a page template. + +""" + +DEFAULT_DOMAIN = "default" + +class TranslationContext: + """Information about the I18N settings of a TAL processor.""" + + def __init__(self, parent=None, domain=None, target=None, source=None): + if parent: + if not domain: + domain = parent.domain + if not target: + target = parent.target + if not source: + source = parent.source + elif domain is None: + domain = DEFAULT_DOMAIN + + self.parent = parent + self.domain = domain + self.target = target + self.source = source +""" +Dummy TALES engine so that I can test out the TAL implementation. +""" + +import re +import sys +import stat +import os +import traceback + +class _Default: + pass +Default = _Default() + +name_match = re.compile(r"(?s)(%s):(.*)\Z" % NAME_RE).match + +class CompilerError(Exception): + pass + +class AthanaTALEngine: + + position = None + source_file = None + + __implements__ = ITALESCompiler, ITALESEngine + + def __init__(self, macros=None, context=None, webcontext=None, language=None, request=None): + if macros is None: + macros = {} + self.macros = macros + dict = {'nothing': None, 'default': Default} + if context is not None: + dict.update(context) + + self.locals = self.globals = dict + self.stack = [dict] + self.webcontext = webcontext + self.language = language + self.request = request + + def compilefile(self, file, mode=None): + assert mode in ("html", "xml", None) + #file = join_paths(GLOBAL_ROOT_DIR,join_paths(self.webcontext.root, file)) + if mode is None: + ext = os.path.splitext(file)[1] + if ext.lower() in (".html", ".htm"): + mode = "html" + else: + mode = "xml" + if mode == "html": + p = HTMLTALParser(TALGenerator(self)) + else: + p = TALParser(TALGenerator(self)) + p.parseFile(file) + return p.getCode() + + def getCompilerError(self): + return CompilerError + + def getCompiler(self): + return self + + def setSourceFile(self, source_file): + self.source_file = source_file + + def setPosition(self, position): + self.position = position + + def compile(self, expr): + return "$%s$" % expr + + def uncompile(self, expression): + assert (expression.startswith("$") and expression.endswith("$"), + expression) + return expression[1:-1] + + def beginScope(self): + self.stack.append(self.locals) + + def endScope(self): + assert len(self.stack) > 1, "more endScope() than beginScope() calls" + self.locals = self.stack.pop() + + def setLocal(self, name, value): + if self.locals is self.stack[-1]: + self.locals = self.locals.copy() + self.locals[name] = value + + def setGlobal(self, name, value): + self.globals[name] = value + + def evaluate(self, expression): + assert (expression.startswith("$") and expression.endswith("$"), + expression) + expression = expression[1:-1] + m = name_match(expression) + if m: + type, expr = m.group(1, 2) + else: + type = "path" + expr = expression + if type in ("string", "str"): + return expr + if type in ("path", "var", "global", "local"): + return self.evaluatePathOrVar(expr) + if type == "not": + return not self.evaluate(expr) + if type == "exists": + return self.locals.has_key(expr) or self.globals.has_key(expr) + if type == "python": + try: + return eval(expr, self.globals, self.locals) + except: + print "Error in python expression" + print sys.exc_info()[0], sys.exc_info()[1] + traceback.print_tb(sys.exc_info()[2]) + raise TALESError("evaluation error in %s" % `expr`) + + if type == "position": + if self.position: + lineno, offset = self.position + else: + lineno, offset = None, None + return '%s (%s,%s)' % (self.source_file, lineno, offset) + raise TALESError("unrecognized expression: " + `expression`) + + def evaluatePathOrVar(self, expr): + expr = expr.strip() + _expr=expr + _f=None + if expr.rfind("/")>0: + pos=expr.rfind("/") + _expr = expr[0:pos] + _f = expr[pos+1:] + if self.locals.has_key(_expr): + if _f: + return getattr(self.locals[_expr],_f) + else: + return self.locals[_expr] + elif self.globals.has_key(_expr): + if _f: + return getattr(self.globals[_expr], _f) + else: + return self.globals[_expr] + else: + raise TALESError("unknown variable: %s" % `_expr`) + + def evaluateValue(self, expr): + return self.evaluate(expr) + + def evaluateBoolean(self, expr): + return self.evaluate(expr) + + def evaluateText(self, expr): + text = self.evaluate(expr) + if text is not None and text is not Default: + text = ustr(text) + return text + + def evaluateStructure(self, expr): + return self.evaluate(expr) + + def evaluateSequence(self, expr): + return self.evaluate(expr) + + def evaluateMacro(self, macroName): + assert (macroName.startswith("$") and macroName.endswith("$"), + macroName) + macroName = macroName[1:-1] + file, localName = self.findMacroFile(macroName) + if not file: + macro = self.macros[localName] + else: + program, macros = self.compilefile(file) + macro = macros.get(localName) + if not macro: + raise TALESError("macro %s not found in file %s" % + (localName, file)) + return macro + + def findMacroDocument(self, macroName): + file, localName = self.findMacroFile(macroName) + if not file: + return file, localName + doc = parsefile(file) + return doc, localName + + def findMacroFile(self, macroName): + if not macroName: + raise TALESError("empty macro name") + i = macroName.rfind('/') + if i < 0: + print "NO Macro" + return None, macroName + else: + fileName = getMacroFile(macroName[:i]) + localName = macroName[i+1:] + return fileName, localName + + def setRepeat(self, name, expr): + seq = self.evaluateSequence(expr) + self.locals[name] = Iterator(name, seq, self) + return self.locals[name] + + def createErrorInfo(self, err, position): + return ErrorInfo(err, position) + + def getDefault(self): + return Default + + def translate(self, domain, msgid, mapping, default=None): + global translators + text = default or msgid + for f in translators: + text = f(msgid, language=self.language, request=self.request) + try: + text = f(msgid, language=self.language, request=self.request) + if text and text!=msgid: + break + except: + pass + def repl(m, mapping=mapping): + return ustr(mapping[m.group(m.lastindex).lower()]) + return VARIABLE.sub(repl, text) + + +class Iterator: + + def __init__(self, name, seq, engine): + self.name = name + self.seq = seq + self.engine = engine + self.nextIndex = 0 + + def next(self): + self.index = i = self.nextIndex + try: + item = self.seq[i] + except IndexError: + return 0 + self.nextIndex = i+1 + self.engine.setLocal(self.name, item) + return 1 + + def even(self): + print "-even-" + return not self.index % 2 + + def odd(self): + print "-odd-" + return self.index % 2 + + def number(self): + return self.nextIndex + + def parity(self): + if self.index % 2: + return 'odd' + return 'even' + + def first(self, name=None): + if self.start: return 1 + return not self.same_part(name, self._last, self.item) + + def last(self, name=None): + if self.end: return 1 + return not self.same_part(name, self.item, self._next) + + def length(self): + return len(self.seq) + + +VARIABLE = re.compile(r'\$(?:(%s)|\{(%s)\})' % (NAME_RE, NAME_RE)) + +parsed_files = {} +parsed_strings = {} + +def runTAL(writer, context=None, string=None, file=None, macro=None, language=None, request=None): + + if file: + file = getMacroFile(file) + + if context is None: + context = {} + + if string and not file: + if string in parsed_strings: + program,macros = parsed_strings[string] + else: + program,macros = None,None + elif file and not string: + if file in parsed_files: + (program,macros,mtime) = parsed_files[file] + mtime_file = os.stat(file)[stat.ST_MTIME] + if mtime != mtime_file: + program,macros = None,None + mtime = mtime_file + else: + program,macros,mtime = None,None,None + + if not (program and macros): + if file and file.endswith("xml"): + talparser = TALParser(TALGenerator(AthanaTALEngine())) + else: + talparser = HTMLTALParser(TALGenerator(AthanaTALEngine())) + if string: + talparser.parseString(string) + (program, macros) = talparser.getCode() + parsed_strings[string] = (program,macros) + else: + talparser.parseFile(file) + (program, macros) = talparser.getCode() + parsed_files[file] = (program,macros,mtime) + + if macro and macro in macros: + program = macros[macro] + engine = AthanaTALEngine(macros, context, language=language, request=request) + TALInterpreter(program, macros, engine, writer, wrap=0)() + +def processTAL(context=None, string=None, file=None, macro=None, language=None, request=None): + class STRWriter: + def __init__(self): + self.string = "" + def write(self,text): + if type(text) == type(u''): + self.string += text.encode("utf-8") + else: + self.string += text + def getvalue(self): + return self.string + wr = STRWriter() + runTAL(wr, context, string=string, file=file, macro=macro, language=language, request=request) + return wr.getvalue() + + +class MyWriter: + def write(self,s): + sys.stdout.write(s) + +def test(): + p = TALParser(TALGenerator(AthanaTALEngine())) + file = "test.xml" + if sys.argv[1:]: + file = sys.argv[1] + p.parseFile(file) + program, macros = p.getCode() + + class Node: + def getText(self): + return "TEST" + + engine = AthanaTALEngine(macros, {'node': Node()}) + TALInterpreter(program, macros, engine, MyWriter(), wrap=0)() + + +def ustr(v): + """Convert any object to a plain string or unicode string, + minimising the chance of raising a UnicodeError. This + even works with uncooperative objects like Exceptions + """ + if type(v) == type(""): #isinstance(v, basestring): + return v + else: + fn = getattr(v,'__str__',None) + if fn is not None: + v = fn() + if isinstance(v, basestring): + return v + else: + raise ValueError('__str__ returned wrong type') + return str(v) + + +# ================ MEDUSA =============== + +# python modules +import os +import re +import select +import socket +import string +import sys +import time +import stat +import string +import mimetypes +import glob +from cgi import escape +from urllib import unquote, splitquery + +# async modules +import asyncore +import socket + +class async_chat (asyncore.dispatcher): + """This is an abstract class. You must derive from this class, and add + the two methods collect_incoming_data() and found_terminator()""" + + # these are overridable defaults + + ac_in_buffer_size = 4096 + ac_out_buffer_size = 4096 + + def __init__ (self, conn=None): + self.ac_in_buffer = '' + self.ac_out_buffer = '' + self.producer_fifo = fifo() + asyncore.dispatcher.__init__ (self, conn) + + def collect_incoming_data(self, data): + raise NotImplementedError, "must be implemented in subclass" + + def found_terminator(self): + raise NotImplementedError, "must be implemented in subclass" + + def set_terminator (self, term): + "Set the input delimiter. Can be a fixed string of any length, an integer, or None" + self.terminator = term + + def get_terminator (self): + return self.terminator + + # grab some more data from the socket, + # throw it to the collector method, + # check for the terminator, + # if found, transition to the next state. + + def handle_read (self): + + try: + data = self.recv (self.ac_in_buffer_size) + except socket.error, why: + self.handle_error() + return + + self.ac_in_buffer = self.ac_in_buffer + data + + # Continue to search for self.terminator in self.ac_in_buffer, + # while calling self.collect_incoming_data. The while loop + # is necessary because we might read several data+terminator + # combos with a single recv(1024). + + while self.ac_in_buffer: + lb = len(self.ac_in_buffer) + terminator = self.get_terminator() + if terminator is None or terminator == '': + # no terminator, collect it all + self.collect_incoming_data (self.ac_in_buffer) + self.ac_in_buffer = '' + elif isinstance(terminator, int): + # numeric terminator + n = terminator + if lb < n: + self.collect_incoming_data (self.ac_in_buffer) + self.ac_in_buffer = '' + self.terminator = self.terminator - lb + else: + self.collect_incoming_data (self.ac_in_buffer[:n]) + self.ac_in_buffer = self.ac_in_buffer[n:] + self.terminator = 0 + self.found_terminator() + else: + # 3 cases: + # 1) end of buffer matches terminator exactly: + # collect data, transition + # 2) end of buffer matches some prefix: + # collect data to the prefix + # 3) end of buffer does not match any prefix: + # collect data + terminator_len = len(terminator) + index = self.ac_in_buffer.find(terminator) + if index != -1: + # we found the terminator + if index > 0: + # don't bother reporting the empty string (source of subtle bugs) + self.collect_incoming_data (self.ac_in_buffer[:index]) + self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:] + # This does the Right Thing if the terminator is changed here. + self.found_terminator() + else: + # check for a prefix of the terminator + index = find_prefix_at_end (self.ac_in_buffer, terminator) + if index: + if index != lb: + # we found a prefix, collect up to the prefix + self.collect_incoming_data (self.ac_in_buffer[:-index]) + self.ac_in_buffer = self.ac_in_buffer[-index:] + break + else: + # no prefix, collect it all + self.collect_incoming_data (self.ac_in_buffer) + self.ac_in_buffer = '' + + def handle_write (self): + self.initiate_send () + + def handle_close (self): + self.close() + + def push (self, data): + self.producer_fifo.push (simple_producer (data)) + self.initiate_send() + + def push_with_producer (self, producer): + self.producer_fifo.push (producer) + self.initiate_send() + + def readable (self): + "predicate for inclusion in the readable for select()" + return (len(self.ac_in_buffer) <= self.ac_in_buffer_size) + + def writable (self): + "predicate for inclusion in the writable for select()" + # return len(self.ac_out_buffer) or len(self.producer_fifo) or (not self.connected) + # this is about twice as fast, though not as clear. + return not ( + (self.ac_out_buffer == '') and + self.producer_fifo.is_empty() and + self.connected + ) + + def close_when_done (self): + "automatically close this channel once the outgoing queue is empty" + self.producer_fifo.push (None) + + # refill the outgoing buffer by calling the more() method + # of the first producer in the queue + def refill_buffer (self): + while 1: + if len(self.producer_fifo): + p = self.producer_fifo.first() + # a 'None' in the producer fifo is a sentinel, + # telling us to close the channel. + if p is None: + if not self.ac_out_buffer: + self.producer_fifo.pop() + self.close() + return + elif isinstance(p, str): + self.producer_fifo.pop() + self.ac_out_buffer = self.ac_out_buffer + p + return + data = p.more() + if data: + self.ac_out_buffer = self.ac_out_buffer + data + return + else: + self.producer_fifo.pop() + else: + return + + def initiate_send (self): + obs = self.ac_out_buffer_size + # try to refill the buffer + if (len (self.ac_out_buffer) < obs): + self.refill_buffer() + + if self.ac_out_buffer and self.connected: + # try to send the buffer + try: + num_sent = self.send (self.ac_out_buffer[:obs]) + if num_sent: + self.ac_out_buffer = self.ac_out_buffer[num_sent:] + + except socket.error, why: + self.handle_error() + return + + def discard_buffers (self): + # Emergencies only! + self.ac_in_buffer = '' + self.ac_out_buffer = '' + while self.producer_fifo: + self.producer_fifo.pop() + + +class simple_producer: + + def __init__ (self, data, buffer_size=512): + self.data = data + self.buffer_size = buffer_size + + def more (self): + if len (self.data) > self.buffer_size: + result = self.data[:self.buffer_size] + self.data = self.data[self.buffer_size:] + return result + else: + result = self.data + self.data = '' + return result + +class fifo: + def __init__ (self, list=None): + if not list: + self.list = [] + else: + self.list = list + + def __len__ (self): + return len(self.list) + + def is_empty (self): + return self.list == [] + + def first (self): + return self.list[0] + + def push (self, data): + self.list.append (data) + + def pop (self): + if self.list: + return (1, self.list.pop(0)) + else: + return (0, None) + +# Given 'haystack', see if any prefix of 'needle' is at its end. This +# assumes an exact match has already been checked. Return the number of +# characters matched. +# for example: +# f_p_a_e ("qwerty\r", "\r\n") => 1 +# f_p_a_e ("qwertydkjf", "\r\n") => 0 +# f_p_a_e ("qwerty\r\n", "\r\n") => + +# this could maybe be made faster with a computed regex? +# [answer: no; circa Python-2.0, Jan 2001] +# new python: 28961/s +# old python: 18307/s +# re: 12820/s +# regex: 14035/s + +def find_prefix_at_end (haystack, needle): + l = len(needle) - 1 + while l and not haystack.endswith(needle[:l]): + l -= 1 + return l + +class counter: + "general-purpose counter" + + def __init__ (self, initial_value=0): + self.value = initial_value + + def increment (self, delta=1): + result = self.value + try: + self.value = self.value + delta + except OverflowError: + self.value = long(self.value) + delta + return result + + def decrement (self, delta=1): + result = self.value + try: + self.value = self.value - delta + except OverflowError: + self.value = long(self.value) - delta + return result + + def as_long (self): + return long(self.value) + + def __nonzero__ (self): + return self.value != 0 + + def __repr__ (self): + return '' % (self.value, id(self)) + + def __str__ (self): + s = str(long(self.value)) + if s[-1:] == 'L': + s = s[:-1] + return s + + +# http_date +def concat (*args): + return ''.join (args) + +def join (seq, field=' '): + return field.join (seq) + +def group (s): + return '(' + s + ')' + +short_days = ['sun','mon','tue','wed','thu','fri','sat'] +long_days = ['sunday','monday','tuesday','wednesday','thursday','friday','saturday'] + +short_day_reg = group (join (short_days, '|')) +long_day_reg = group (join (long_days, '|')) + +daymap = {} +for i in range(7): + daymap[short_days[i]] = i + daymap[long_days[i]] = i + +hms_reg = join (3 * [group('[0-9][0-9]')], ':') + +months = ['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'] + +monmap = {} +for i in range(12): + monmap[months[i]] = i+1 + +months_reg = group (join (months, '|')) + +# From draft-ietf-http-v11-spec-07.txt/3.3.1 +# Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 +# Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 +# Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format + +# rfc822 format +rfc822_date = join ( + [concat (short_day_reg,','), # day + group('[0-9][0-9]?'), # date + months_reg, # month + group('[0-9]+'), # year + hms_reg, # hour minute second + 'gmt' + ], + ' ' + ) + +rfc822_reg = re.compile (rfc822_date) + +def unpack_rfc822 (m): + g = m.group + a = string.atoi + return ( + a(g(4)), # year + monmap[g(3)], # month + a(g(2)), # day + a(g(5)), # hour + a(g(6)), # minute + a(g(7)), # second + 0, + 0, + 0 + ) + +# rfc850 format +rfc850_date = join ( + [concat (long_day_reg,','), + join ( + [group ('[0-9][0-9]?'), + months_reg, + group ('[0-9]+') + ], + '-' + ), + hms_reg, + 'gmt' + ], + ' ' + ) + +rfc850_reg = re.compile (rfc850_date) +# they actually unpack the same way +def unpack_rfc850 (m): + g = m.group + a = string.atoi + return ( + a(g(4)), # year + monmap[g(3)], # month + a(g(2)), # day + a(g(5)), # hour + a(g(6)), # minute + a(g(7)), # second + 0, + 0, + 0 + ) + +# parsdate.parsedate - ~700/sec. +# parse_http_date - ~1333/sec. + +def build_http_date (when): + return time.strftime ('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(when)) + +time_offset = 0 + +def parse_http_date (d): + global time_offset + d = string.lower (d) + tz = time.timezone + m = rfc850_reg.match (d) + if m and m.end() == len(d): + retval = int (time.mktime (unpack_rfc850(m)) - tz) + else: + m = rfc822_reg.match (d) + if m and m.end() == len(d): + try: + retval = int (time.mktime (unpack_rfc822(m)) - tz) + except OverflowError: + return 0 + else: + return 0 + # Thanks to Craig Silverstein for pointing + # out the DST discrepancy + if time.daylight and time.localtime(retval)[-1] == 1: # DST correction + retval = retval + (tz - time.altzone) + return retval - time_offset + +def check_date(): + global time_offset + tmpfile = join_paths(GLOBAL_TEMP_DIR, "datetest"+str(random.random())+".tmp") + open(tmpfile,"wb").close() + time1 = os.stat(tmpfile)[stat.ST_MTIME] + os.unlink(tmpfile) + time2 = parse_http_date(build_http_date(time.time())) + time_offset = time2-time1 + print time_offset + +# producers + +class simple_producer: + "producer for a string" + def __init__ (self, data, buffer_size=1024): + self.data = data + self.buffer_size = buffer_size + + def more (self): + if len (self.data) > self.buffer_size: + result = self.data[:self.buffer_size] + self.data = self.data[self.buffer_size:] + return result + else: + result = self.data + self.data = '' + return result + +class file_producer: + "producer wrapper for file[-like] objects" + + # match http_channel's outgoing buffer size + out_buffer_size = 1<<16 + + def __init__ (self, file): + self.done = 0 + self.file = file + + def more (self): + if self.done: + return '' + else: + data = self.file.read (self.out_buffer_size) + if not data: + self.file.close() + del self.file + self.done = 1 + return '' + else: + return data + +# A simple output producer. This one does not [yet] have +# the safety feature builtin to the monitor channel: runaway +# output will not be caught. + +# don't try to print from within any of the methods +# of this object. + +class output_producer: + "Acts like an output file; suitable for capturing sys.stdout" + def __init__ (self): + self.data = '' + + def write (self, data): + lines = string.splitfields (data, '\n') + data = string.join (lines, '\r\n') + self.data = self.data + data + + def writeline (self, line): + self.data = self.data + line + '\r\n' + + def writelines (self, lines): + self.data = self.data + string.joinfields ( + lines, + '\r\n' + ) + '\r\n' + + def flush (self): + pass + + def softspace (self, *args): + pass + + def more (self): + if self.data: + result = self.data[:512] + self.data = self.data[512:] + return result + else: + return '' + +class composite_producer: + "combine a fifo of producers into one" + def __init__ (self, producers): + self.producers = producers + + def more (self): + while len(self.producers): + p = self.producers[0] + d = p.more() + if d: + return d + else: + self.producers.pop(0) + else: + return '' + + +class globbing_producer: + """ + 'glob' the output from a producer into a particular buffer size. + helps reduce the number of calls to send(). [this appears to + gain about 30% performance on requests to a single channel] + """ + + def __init__ (self, producer, buffer_size=1<<16): + self.producer = producer + self.buffer = '' + self.buffer_size = buffer_size + + def more (self): + while len(self.buffer) < self.buffer_size: + data = self.producer.more() + if data: + self.buffer = self.buffer + data + else: + break + r = self.buffer + self.buffer = '' + return r + + +class hooked_producer: + """ + A producer that will call when it empties,. + with an argument of the number of bytes produced. Useful + for logging/instrumentation purposes. + """ + + def __init__ (self, producer, function): + self.producer = producer + self.function = function + self.bytes = 0 + + def more (self): + if self.producer: + result = self.producer.more() + if not result: + self.producer = None + self.function (self.bytes) + else: + self.bytes = self.bytes + len(result) + return result + else: + return '' + +# HTTP 1.1 emphasizes that an advertised Content-Length header MUST be +# correct. In the face of Strange Files, it is conceivable that +# reading a 'file' may produce an amount of data not matching that +# reported by os.stat() [text/binary mode issues, perhaps the file is +# being appended to, etc..] This makes the chunked encoding a True +# Blessing, and it really ought to be used even with normal files. +# How beautifully it blends with the concept of the producer. + +class chunked_producer: + """A producer that implements the 'chunked' transfer coding for HTTP/1.1. + Here is a sample usage: + request['Transfer-Encoding'] = 'chunked' + request.push ( + producers.chunked_producer (your_producer) + ) + request.done() + """ + + def __init__ (self, producer, footers=None): + self.producer = producer + self.footers = footers + + def more (self): + if self.producer: + data = self.producer.more() + if data: + return '%x\r\n%s\r\n' % (len(data), data) + else: + self.producer = None + if self.footers: + return string.join ( + ['0'] + self.footers, + '\r\n' + ) + '\r\n\r\n' + else: + return '0\r\n\r\n' + else: + return '' + +class escaping_producer: + + "A producer that escapes a sequence of characters" + " Common usage: escaping the CRLF.CRLF sequence in SMTP, NNTP, etc..." + + def __init__ (self, producer, esc_from='\r\n.', esc_to='\r\n..'): + self.producer = producer + self.esc_from = esc_from + self.esc_to = esc_to + self.buffer = '' + self.find_prefix_at_end = find_prefix_at_end + + def more (self): + esc_from = self.esc_from + esc_to = self.esc_to + + buffer = self.buffer + self.producer.more() + + if buffer: + buffer = string.replace (buffer, esc_from, esc_to) + i = self.find_prefix_at_end (buffer, esc_from) + if i: + # we found a prefix + self.buffer = buffer[-i:] + return buffer[:-i] + else: + # no prefix, return it all + self.buffer = '' + return buffer + else: + return buffer + +class tail_logger: + "Keep track of the last log messages" + def __init__ (self, logger, size=500): + self.size = size + self.logger = logger + self.messages = [] + + def log (self, message): + self.messages.append (strip_eol (message)) + if len (self.messages) > self.size: + del self.messages[0] + self.logger.log (message) + + +def html_repr (object): + so = escape (repr (object)) + if hasattr (object, 'hyper_respond'): + return '%s' % (id (object), so) + else: + return so + +def html_reprs (list, front='', back=''): + reprs = map ( + lambda x,f=front,b=back: '%s%s%s' % (f,x,b), + map (lambda x: escape (html_repr(x)), list) + ) + reprs.sort() + return reprs + +# for example, tera, giga, mega, kilo +# p_d (n, (1024, 1024, 1024, 1024)) +# smallest divider goes first - for example +# minutes, hours, days +# p_d (n, (60, 60, 24)) + +def progressive_divide (n, parts): + result = [] + for part in parts: + n, rem = divmod (n, part) + result.append (rem) + result.append (n) + return result + +# b,k,m,g,t +def split_by_units (n, units, dividers, format_string): + divs = progressive_divide (n, dividers) + result = [] + for i in range(len(units)): + if divs[i]: + result.append (format_string % (divs[i], units[i])) + result.reverse() + if not result: + return [format_string % (0, units[0])] + else: + return result + +def english_bytes (n): + return split_by_units ( + n, + ('','K','M','G','T'), + (1024, 1024, 1024, 1024, 1024), + '%d %sB' + ) + +def english_time (n): + return split_by_units ( + n, + ('secs', 'mins', 'hours', 'days', 'weeks', 'years'), + ( 60, 60, 24, 7, 52), + '%d %s' + ) + +class file_logger: + + # pass this either a path or a file object. + def __init__ (self, file, flush=1, mode='a'): + if type(file) == type(''): + if (file == '-'): + self.file = sys.stdout + else: + self.file = open (file, mode) + else: + self.file = file + self.do_flush = flush + + def __repr__ (self): + return '' % self.file + + def write (self, data): + self.file.write (data) + self.maybe_flush() + + def writeline (self, line): + self.file.writeline (line) + self.maybe_flush() + + def writelines (self, lines): + self.file.writelines (lines) + self.maybe_flush() + + def maybe_flush (self): + if self.do_flush: + self.file.flush() + + def flush (self): + self.file.flush() + + def softspace (self, *args): + pass + + def log (self, message): + if message[-1] not in ('\r', '\n'): + self.write (message + '\n') + else: + self.write (message) + + def debug(self, message): + self.log(message) + +class unresolving_logger: + "Just in case you don't want to resolve" + def __init__ (self, logger): + self.logger = logger + + def log (self, ip, message): + self.logger.log ('%s:%s' % (ip, message)) + + +def strip_eol (line): + while line and line[-1] in '\r\n': + line = line[:-1] + return line + +VERSION_STRING = string.split(RCS_ID)[2] +ATHANA_VERSION = "0.2.1" + +# =========================================================================== +# Request Object +# =========================================================================== + +class http_request: + + # default reply code + reply_code = 200 + + request_counter = counter() + + # Whether to automatically use chunked encoding when + # + # HTTP version is 1.1 + # Content-Length is not set + # Chunked encoding is not already in effect + # + # If your clients are having trouble, you might want to disable this. + use_chunked = 1 + + # by default, this request object ignores user data. + collector = None + + def __init__ (self, *args): + # unpack information about the request + (self.channel, self.request, + self.command, self.uri, self.version, + self.header) = args + + self.outgoing = [] + self.reply_headers = { + 'Server' : 'Athana/%s' % ATHANA_VERSION, + 'Date' : build_http_date (time.time()), + 'Expires' : build_http_date (time.time()) + } + self.request_number = http_request.request_counter.increment() + self._split_uri = None + self._header_cache = {} + + # -------------------------------------------------- + # reply header management + # -------------------------------------------------- + def __setitem__ (self, key, value): + try: + if key=='Set-Cookie': + self.reply_headers[key] += [value] + else: + self.reply_headers[key] = [value] + except: + self.reply_headers[key] = [value] + + def __getitem__ (self, key): + return self.reply_headers[key][0] + + def has_key (self, key): + return self.reply_headers.has_key(key) + + def build_reply_header (self): + h = [] + for k,vv in self.reply_headers.items(): + if type(vv) != type([]): + h += ["%s: %s" % (k,vv)] + else: + for v in vv: + h += ["%s: %s" % (k,v)] + return string.join([self.response(self.reply_code)] + h, '\r\n') + '\r\n\r\n' + + # -------------------------------------------------- + # split a uri + # -------------------------------------------------- + + # ;?# + path_regex = re.compile ( + # path params query fragment + r'([^;?#]*)(;[^?#]*)?(\?[^#]*)?(#.*)?' + ) + + def split_uri (self): + if self._split_uri is None: + m = self.path_regex.match (self.uri) + if m.end() != len(self.uri): + raise ValueError, "Broken URI" + else: + self._split_uri = m.groups() + return self._split_uri + + def get_header_with_regex (self, head_reg, group): + for line in self.header: + m = head_reg.match (line) + if m.end() == len(line): + return m.group (group) + return '' + + def get_header (self, header): + header = string.lower (header) + hc = self._header_cache + if not hc.has_key (header): + h = header + ': ' + hl = len(h) + for line in self.header: + if string.lower (line[:hl]) == h: + r = line[hl:] + hc[header] = r + return r + hc[header] = None + return None + else: + return hc[header] + + # -------------------------------------------------- + # user data + # -------------------------------------------------- + + def collect_incoming_data (self, data): + if self.collector: + self.collector.collect_incoming_data (data) + else: + self.log_info( + 'Dropping %d bytes of incoming request data' % len(data), + 'warning' + ) + + def found_terminator (self): + if self.collector: + self.collector.found_terminator() + else: + self.log_info ( + 'Unexpected end-of-record for incoming request', + 'warning' + ) + + def push (self, thing): + if type(thing) == type(''): + self.outgoing.append(simple_producer (thing)) + else: + thing.more + self.outgoing.append(thing) + + def response (self, code=200): + message = self.responses[code] + self.reply_code = code + return 'HTTP/%s %d %s' % (self.version, code, message) + + def error (self, code, s=None): + self.reply_code = code + self.outgoing = [] + message = self.responses[code] + if s is None: + s = self.DEFAULT_ERROR_MESSAGE % { + 'code': code, + 'message': message, + } + self['Content-Length'] = len(s) + self['Content-Type'] = 'text/html' + # make an error reply + self.push (s) + self.done() + + # can also be used for empty replies + reply_now = error + + def done (self): + "finalize this transaction - send output to the http channel" + + if hasattr(self,"tempfiles"): + for f in self.tempfiles: + os.unlink(f) + + # ---------------------------------------- + # persistent connection management + # ---------------------------------------- + + # --- BUCKLE UP! ---- + + connection = string.lower (get_header (CONNECTION, self.header)) + + close_it = 0 + wrap_in_chunking = 0 + + if self.version == '1.0': + if connection == 'keep-alive': + if not self.has_key ('Content-Length'): + close_it = 1 + else: + self['Connection'] = 'Keep-Alive' + else: + close_it = 1 + elif self.version == '1.1': + if connection == 'close': + close_it = 1 + elif not self.has_key ('Content-Length'): + if self.has_key ('Transfer-Encoding'): + if not self['Transfer-Encoding'] == 'chunked': + close_it = 1 + elif self.use_chunked: + self['Transfer-Encoding'] = 'chunked' + wrap_in_chunking = 1 + else: + close_it = 1 + elif self.version is None: + # Although we don't *really* support http/0.9 (because we'd have to + # use \r\n as a terminator, and it would just yuck up a lot of stuff) + # it's very common for developers to not want to type a version number + # when using telnet to debug a server. + close_it = 1 + + outgoing_header = simple_producer (self.build_reply_header()) + + if close_it: + self['Connection'] = 'close' + + if wrap_in_chunking: + outgoing_producer = chunked_producer ( + composite_producer (list(self.outgoing)) + ) + # prepend the header + outgoing_producer = composite_producer( + [outgoing_header, outgoing_producer] + ) + else: + # prepend the header + self.outgoing.insert(0, outgoing_header) + outgoing_producer = composite_producer (list(self.outgoing)) + + # actually, this is already set to None by the handler: + self.channel.current_request = None + + # apply a few final transformations to the output + self.channel.push_with_producer ( + # globbing gives us large packets + globbing_producer ( + outgoing_producer + ) + ) + + if close_it: + self.channel.close_when_done() + + def log_date_string (self, when): + t = time.localtime(when) + return time.strftime ( '%d/%b/%Y:%H:%M:%S ', t) + + def log (self): + self.channel.server.logger.log ( + self.channel.addr[0], + '%d - - [%s] "%s"\n' % ( + self.channel.addr[1], + self.log_date_string (time.time()), + self.request, + ) + ) + + def write(self,text): + if type(text) == type(''): + self.push(text) + elif type(text) == type(u''): + self.push(text.encode("utf-8")) + else: + text.more + self.push(text) + + def setStatus(self,status): + self.reply_code = status + + def makeLink(self,page,params=None): + query = "" + if params is not None: + first = 1 + for k,v in params.items(): + if first: + query += "?" + else: + query += "&" + query += urllib.quote(k)+"="+urllib.quote(v) + first = 0 + return page+";"+self.sessionid+query + + def sendFile(self,path,content_type,force=0): + + try: + file_length = os.stat(path)[stat.ST_SIZE] + except OSError: + self.error (404) + return + + ims = get_header_match (IF_MODIFIED_SINCE, self.header) + length_match = 1 + if ims: + length = ims.group (4) + if length: + try: + length = string.atoi (length) + if length != file_length: + length_match = 0 + except: + pass + ims_date = 0 + if ims: + ims_date = parse_http_date (ims.group (1)) + + try: + mtime = os.stat (path)[stat.ST_MTIME] + except: + self.error (404) + return + if length_match and ims_date: + if mtime <= ims_date and not force: + print "File "+path+" was not modified since "+str(ims_date)+" (current filedate is "+str(mtime)+")-> 304" + self.reply_code = 304 + return + try: + file = open (path, 'rb') + except IOError: + self.error (404) + print "404" + return + + self.reply_headers['Last-Modified'] = build_http_date (mtime) + self.reply_headers['Content-Length'] = file_length + self.reply_headers['Content-Type'] = content_type + self.reply_headers['Connection'] = 'close'; + if self.command == 'GET': + self.push(file_producer(file)) + return + + def setCookie(self, name, value, expire=None): + if expire is None: + s = name+'='+value; + else: + datestr = time.strftime("%a, %d-%b-%Y %H:%M:%S GMT", time.gmtime(expire)) + s = name+'='+value+'; expires='+datestr; #+'; path=PATH; domain=DOMAIN_NAME; secure'; + + if 'Set-Cookie' not in self.reply_headers: + self.reply_headers['Set-Cookie'] = [s] + else: + self.reply_headers['Set-Cookie'] += [s] + + def makeSelfLink(self,params): + params2 = self.params.copy() + for k,v in params.items(): + if v is not None: + params2[k] = v + else: + try: del params2[k] + except: pass + ret = self.makeLink(self.fullpath, params2) + return ret + + def writeTAL(self,page,context,macro=None): + runTAL(self, context, file=page, macro=macro, request=self) + + def writeTALstr(self,string,context,macro=None): + runTAL(self, context, string=string, macro=macro, request=self) + + def getTAL(self,page,context,macro=None): + return processTAL(context,file=page, macro=macro, request=self) + + def getTALstr(self,string,context,macro=None): + return processTAL(context,string=string, macro=macro, request=self) + + + responses = { + 100: "Continue", + 101: "Switching Protocols", + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Non-Authoritative Information", + 204: "No Content", + 205: "Reset Content", + 206: "Partial Content", + 300: "Multiple Choices", + 301: "Moved Permanently", + 302: "Moved Temporarily", + 303: "See Other", + 304: "Not Modified", + 305: "Use Proxy", + 400: "Bad Request", + 401: "Unauthorized", + 402: "Payment Required", + 403: "Forbidden", + 404: "Not Found", + 405: "Method Not Allowed", + 406: "Not Acceptable", + 407: "Proxy Authentication Required", + 408: "Request Time-out", + 409: "Conflict", + 410: "Gone", + 411: "Length Required", + 412: "Precondition Failed", + 413: "Request Entity Too Large", + 414: "Request-URI Too Large", + 415: "Unsupported Media Type", + 500: "Internal Server Error", + 501: "Not Implemented", + 502: "Bad Gateway", + 503: "Service Unavailable", + 504: "Gateway Time-out", + 505: "HTTP Version not supported" + } + + # Default error message + DEFAULT_ERROR_MESSAGE = string.join ( + ['', + 'Error response', + '', + '', + '

    Error response

    ', + '

    Error code %(code)d.

    ', + '

    Message: %(message)s.

    ', + '', + '' + ], + '\r\n' + ) + +def getTAL(page,context,macro=None,language=None): + return processTAL(context,file=page, macro=macro, language=language) + +def getTALstr(string,context,macro=None,language=None): + return processTAL(context,string=string, macro=macro, language=language) + +# =========================================================================== +# HTTP Channel Object +# =========================================================================== + +class http_channel (async_chat): + + # use a larger default output buffer + ac_out_buffer_size = 1<<16 + + current_request = None + channel_counter = counter() + + def __init__ (self, server, conn, addr): + self.channel_number = http_channel.channel_counter.increment() + self.request_counter = counter() + async_chat.__init__ (self, conn) + self.server = server + self.addr = addr + self.set_terminator ('\r\n\r\n') + self.in_buffer = '' + self.creation_time = int (time.time()) + self.check_maintenance() + self.producer_lock = thread.allocate_lock() + + def initiate_send (self): + self.producer_lock.acquire() + try: + async_chat.initiate_send(self) + finally: + self.producer_lock.release() + + def push (self, data): + data.more + self.producer_lock.acquire() + try: + self.producer_fifo.push (simple_producer (data)) + finally: + self.producer_lock.release() + self.initiate_send() + + def push_with_producer (self, producer): + self.producer_lock.acquire() + try: + self.producer_fifo.push (producer) + finally: + self.producer_lock.release() + self.initiate_send() + + def close_when_done (self): + self.producer_lock.acquire() + try: + self.producer_fifo.push (None) + finally: + self.producer_lock.release() + + #results in select.error: (9, 'Bad file descriptor') if the socket map is poll'ed + #while this socket is being closed + #we do it anyway, and catch the select.error in the main loop + + #XXX on Ubuntu's 2.6.10-5-386, the socket won't be closed until the select finishes (or + #times out). We probably need to send a SIGINT signal or something. For now, we just + #set a very small timeout (0.01) in the main loop, so that select() will be called often + #enough. + + #it also results in a "NoneType has no attribute more" error if refill_buffer tries + #to run data = p.more() on the None terminator (which we catch) + try: + self.initiate_send() + except AttributeError: + pass + + def __repr__ (self): + ar = async_chat.__repr__(self)[1:-1] + return '<%s channel#: %s requests:%s>' % ( + ar, + self.channel_number, + self.request_counter + ) + + # Channel Counter, Maintenance Interval... + maintenance_interval = 500 + + def check_maintenance (self): + if not self.channel_number % self.maintenance_interval: + self.maintenance() + + def maintenance (self): + self.kill_zombies() + + # 30-minute zombie timeout. status_handler also knows how to kill zombies. + zombie_timeout = 30 * 60 + + def kill_zombies (self): + now = int (time.time()) + for channel in asyncore.socket_map.values(): + if channel.__class__ == self.__class__: + if (now - channel.creation_time) > channel.zombie_timeout: + channel.close() + + # -------------------------------------------------- + # send/recv overrides, good place for instrumentation. + # -------------------------------------------------- + + # this information needs to get into the request object, + # so that it may log correctly. + def send (self, data): + result = async_chat.send (self, data) + self.server.bytes_out.increment (len(data)) + return result + + def recv (self, buffer_size): + try: + result = async_chat.recv (self, buffer_size) + self.server.bytes_in.increment (len(result)) + return result + except MemoryError: + # --- Save a Trip to Your Service Provider --- + # It's possible for a process to eat up all the memory of + # the machine, and put it in an extremely wedged state, + # where medusa keeps running and can't be shut down. This + # is where MemoryError tends to get thrown, though of + # course it could get thrown elsewhere. + sys.exit ("Out of Memory!") + + def handle_error (self): + t, v = sys.exc_info()[:2] + if t is SystemExit: + raise t, v + else: + async_chat.handle_error (self) + + def log (self, *args): + pass + + # -------------------------------------------------- + # async_chat methods + # -------------------------------------------------- + + def collect_incoming_data (self, data): + if self.current_request: + # we are receiving data (probably POST data) for a request + self.current_request.collect_incoming_data (data) + else: + # we are receiving header (request) data + self.in_buffer = self.in_buffer + data + + def found_terminator (self): + if self.current_request: + self.current_request.found_terminator() + else: + header = self.in_buffer + self.in_buffer = '' + lines = string.split (header, '\r\n') + + # -------------------------------------------------- + # crack the request header + # -------------------------------------------------- + + while lines and not lines[0]: + # as per the suggestion of http-1.1 section 4.1, (and + # Eric Parker ), ignore a leading + # blank lines (buggy browsers tack it onto the end of + # POST requests) + lines = lines[1:] + + if not lines: + self.close_when_done() + return + + request = lines[0] + + command, uri, version = crack_request (request) + header = join_headers (lines[1:]) + + # unquote path if necessary (thanks to Skip Montanaro for pointing + # out that we must unquote in piecemeal fashion). + rpath, rquery = splitquery(uri) + if '%' in rpath: + if rquery: + uri = unquote (rpath) + '?' + rquery + else: + uri = unquote (rpath) + + r = http_request (self, request, command, uri, version, header) + self.request_counter.increment() + self.server.total_requests.increment() + + if command is None: + self.log_info ('Bad HTTP request: %s' % repr(request), 'error') + r.error (400) + return + + # -------------------------------------------------- + # handler selection and dispatch + # -------------------------------------------------- + for h in self.server.handlers: + if h.match (r): + try: + self.current_request = r + # This isn't used anywhere. + # r.handler = h # CYCLE + h.handle_request (r) + except: + self.server.exceptions.increment() + (file, fun, line), t, v, tbinfo = asyncore.compact_traceback() + self.log_info( + 'Server Error: %s, %s: file: %s line: %s' % (t,v,file,line), + 'error') + try: + r.error (500) + except: + pass + return + + # no handlers, so complain + r.error (404) + +# =========================================================================== +# HTTP Server Object +# =========================================================================== + +class http_server (asyncore.dispatcher): + + SERVER_IDENT = 'HTTP Server (V%s)' % VERSION_STRING + + channel_class = http_channel + + def __init__ (self, ip, port, resolver=None, logger_object=None): + self.ip = ip + self.port = port + asyncore.dispatcher.__init__ (self) + self.create_socket (socket.AF_INET, socket.SOCK_STREAM) + + self.handlers = [] + + if not logger_object: + logger_object = file_logger (sys.stdout) + + self.set_reuse_addr() + self.bind ((ip, port)) + + # lower this to 5 if your OS complains + self.listen (1024) + + host, port = self.socket.getsockname() + if not ip: + self.log_info('Computing default hostname', 'warning') + ip = socket.gethostbyname (socket.gethostname()) + try: + self.server_name = socket.gethostbyaddr (ip)[0] + except socket.error: + self.log_info('Cannot do reverse lookup', 'warning') + self.server_name = ip # use the IP address as the "hostname" + + self.server_port = port + self.total_clients = counter() + self.total_requests = counter() + self.exceptions = counter() + self.bytes_out = counter() + self.bytes_in = counter() + + if not logger_object: + logger_object = file_logger (sys.stdout) + + self.logger = unresolving_logger (logger_object) + + self.log_info ( + 'Athana (%s) started at %s' + '\n\n' + 'The server is running! You can now direct your browser to:\n' + '\thttp://%s:%d/' + '\n' % ( + ATHANA_VERSION, + time.ctime(time.time()), + self.server_name, + port, + ) + ) + + def writable (self): + return 0 + + def handle_read (self): + pass + + def readable (self): + return self.accepting + + def handle_connect (self): + pass + + def handle_accept (self): + self.total_clients.increment() + try: + conn, addr = self.accept() + except socket.error: + # linux: on rare occasions we get a bogus socket back from + # accept. socketmodule.c:makesockaddr complains that the + # address family is unknown. We don't want the whole server + # to shut down because of this. + self.log_info ('warning: server accept() threw an exception', 'warning') + return + except TypeError: + # unpack non-sequence. this can happen when a read event + # fires on a listening socket, but when we call accept() + # we get EWOULDBLOCK, so dispatcher.accept() returns None. + # Seen on FreeBSD3. + self.log_info ('warning: server accept() threw EWOULDBLOCK', 'warning') + return + + self.channel_class (self, conn, addr) + + def install_handler (self, handler, back=0): + if back: + self.handlers.append (handler) + else: + self.handlers.insert (0, handler) + + def remove_handler (self, handler): + self.handlers.remove (handler) + + +CONNECTION = re.compile ('Connection: (.*)', re.IGNORECASE) + +# merge multi-line headers +# [486dx2: ~500/sec] +def join_headers (headers): + r = [] + for i in range(len(headers)): + if headers[i][0] in ' \t': + r[-1] = r[-1] + headers[i][1:] + else: + r.append (headers[i]) + return r + +def get_header (head_reg, lines, group=1): + for line in lines: + m = head_reg.match (line) + if m and m.end() == len(line): + return m.group (group) + return '' + +def get_header_match (head_reg, lines): + for line in lines: + m = head_reg.match (line) + if m and m.end() == len(line): + return m + return '' + +REQUEST = re.compile ('([^ ]+) ([^ ]+)(( HTTP/([0-9.]+))$|$)') + +def crack_request (r): + m = REQUEST.match (r) + if m and m.end() == len(r): + if m.group(3): + version = m.group(5) + else: + version = None + return m.group(1), m.group(2), version + else: + return None, None, None + + +# This is the 'default' handler. it implements the base set of +# features expected of a simple file-delivering HTTP server. file +# services are provided through a 'filesystem' object, the very same +# one used by the FTP server. +# +# You can replace or modify this handler if you want a non-standard +# HTTP server. You can also derive your own handler classes from +# it. +# +# support for handling POST requests is available in the derived +# class , defined below. +# + +class default_handler: + + valid_commands = ['GET', 'HEAD'] + + IDENT = 'Default HTTP Request Handler' + + # Pathnames that are tried when a URI resolves to a directory name + directory_defaults = [ + 'index.html', + 'default.html' + ] + + default_file_producer = file_producer + + def __init__ (self, filesystem): + self.filesystem = filesystem + # count total hits + self.hit_counter = counter() + # count file deliveries + self.file_counter = counter() + # count cache hits + self.cache_counter = counter() + + hit_counter = 0 + + def __repr__ (self): + return '<%s (%s hits) at %x>' % ( + self.IDENT, + self.hit_counter, + id (self) + ) + + # always match, since this is a default + def match (self, request): + return 1 + + def can_handle(self, request): + path, params, query, fragment = request.split_uri() + if '%' in path: + path = unquote (path) + while path and path[0] == '/': + path = path[1:] + if self.filesystem.isdir (path): + if path and path[-1] != '/': + return 0 + found = 0 + if path and path[-1] != '/': + path = path + '/' + for default in self.directory_defaults: + p = path + default + if self.filesystem.isfile (p): + path = p + found = 1 + break + if not found: + return 0 + elif not self.filesystem.isfile (path): + return 0 + return 1 + + # handle a file request, with caching. + + def handle_request (self, request): + + if request.command not in self.valid_commands: + request.error (400) # bad request + return + + self.hit_counter.increment() + + path, params, query, fragment = request.split_uri() + + if '%' in path: + path = unquote (path) + + # strip off all leading slashes + while path and path[0] == '/': + path = path[1:] + + if self.filesystem.isdir (path): + if path and path[-1] != '/': + request['Location'] = 'http://%s/%s/' % ( + request.channel.server.server_name, + path + ) + request.error (301) + return + + # we could also generate a directory listing here, + # may want to move this into another method for that + # purpose + found = 0 + if path and path[-1] != '/': + path = path + '/' + for default in self.directory_defaults: + p = path + default + if self.filesystem.isfile (p): + path = p + found = 1 + break + if not found: + request.error (404) # Not Found + return + + elif not self.filesystem.isfile (path): + request.error (404) # Not Found + return + + file_length = self.filesystem.stat (path)[stat.ST_SIZE] + + ims = get_header_match (IF_MODIFIED_SINCE, request.header) + + length_match = 1 + if ims: + length = ims.group (4) + if length: + try: + length = string.atoi (length) + if length != file_length: + length_match = 0 + except: + pass + + ims_date = 0 + + if ims: + ims_date = parse_http_date (ims.group (1)) + + try: + mtime = self.filesystem.stat (path)[stat.ST_MTIME] + except: + request.error (404) + return + + if length_match and ims_date: + if mtime <= ims_date: + request.reply_code = 304 + request.done() + self.cache_counter.increment() + print "File "+path+" was not modified since "+str(ims_date)+" (current filedate is "+str(mtime)+")" + return + try: + file = self.filesystem.open (path, 'rb') + except IOError: + request.error (404) + return + + request['Last-Modified'] = build_http_date (mtime) + request['Content-Length'] = file_length + self.set_content_type (path, request) + + if request.command == 'GET': + request.push (self.default_file_producer (file)) + + self.file_counter.increment() + request.done() + + def set_content_type (self, path, request): + ext = string.lower (get_extension (path)) + typ, encoding = mimetypes.guess_type(path) + if typ is not None: + request['Content-Type'] = typ + else: + # TODO: test a chunk off the front of the file for 8-bit + # characters, and use application/octet-stream instead. + request['Content-Type'] = 'text/plain' + + def status (self): + return simple_producer ( + '
  • %s' % html_repr (self) + + '
      ' + + '
    • Total Hits: %s' % self.hit_counter + + '
    • Files Delivered: %s' % self.file_counter + + '
    • Cache Hits: %s' % self.cache_counter + + '
    ' + ) + +# HTTP/1.0 doesn't say anything about the "; length=nnnn" addition +# to this header. I suppose its purpose is to avoid the overhead +# of parsing dates... +IF_MODIFIED_SINCE = re.compile ( + 'If-Modified-Since: ([^;]+)((; length=([0-9]+)$)|$)', + re.IGNORECASE + ) + +USER_AGENT = re.compile ('User-Agent: (.*)', re.IGNORECASE) + +CONTENT_TYPE = re.compile ( + r'Content-Type: ([^;]+)((; boundary=([A-Za-z0-9\'\(\)+_,./:=?-]+)$)|$)', + re.IGNORECASE + ) + +get_header = get_header +get_header_match = get_header_match + +def get_extension (path): + dirsep = string.rfind (path, '/') + dotsep = string.rfind (path, '.') + if dotsep > dirsep: + return path[dotsep+1:] + else: + return '' + +class abstract_filesystem: + def __init__ (self): + pass + + def current_directory (self): + "Return a string representing the current directory." + pass + + def listdir (self, path, long=0): + """Return a listing of the directory at 'path' The empty string + indicates the current directory. If 'long' is set, instead + return a list of (name, stat_info) tuples + """ + pass + + def open (self, path, mode): + "Return an open file object" + pass + + def stat (self, path): + "Return the equivalent of os.stat() on the given path." + pass + + def isdir (self, path): + "Does the path represent a directory?" + pass + + def isfile (self, path): + "Does the path represent a plain file?" + pass + + def cwd (self, path): + "Change the working directory." + pass + + def cdup (self): + "Change to the parent of the current directory." + pass + + + def longify (self, path): + """Return a 'long' representation of the filename + [for the output of the LIST command]""" + pass + +# standard wrapper around a unix-like filesystem, with a 'false root' +# capability. + +# security considerations: can symbolic links be used to 'escape' the +# root? should we allow it? if not, then we could scan the +# filesystem on startup, but that would not help if they were added +# later. We will probably need to check for symlinks in the cwd method. + +# what to do if wd is an invalid directory? + +def safe_stat (path): + try: + return (path, os.stat (path)) + except: + return None + +class os_filesystem: + path_module = os.path + + # set this to zero if you want to disable pathname globbing. + # [we currently don't glob, anyway] + do_globbing = 1 + + def __init__ (self, root, wd='/'): + self.root = root + self.wd = wd + + def current_directory (self): + return self.wd + + def isfile (self, path): + p = self.normalize (self.path_module.join (self.wd, path)) + return self.path_module.isfile (self.translate(p)) + + def isdir (self, path): + p = self.normalize (self.path_module.join (self.wd, path)) + return self.path_module.isdir (self.translate(p)) + + def cwd (self, path): + p = self.normalize (self.path_module.join (self.wd, path)) + translated_path = self.translate(p) + if not self.path_module.isdir (translated_path): + return 0 + else: + old_dir = os.getcwd() + # temporarily change to that directory, in order + # to see if we have permission to do so. + try: + can = 0 + try: + os.chdir (translated_path) + can = 1 + self.wd = p + except: + pass + finally: + if can: + os.chdir (old_dir) + return can + + def cdup (self): + return self.cwd ('..') + + def listdir (self, path, long=0): + p = self.translate (path) + # I think we should glob, but limit it to the current + # directory only. + ld = os.listdir (p) + if not long: + return list_producer (ld, None) + else: + old_dir = os.getcwd() + try: + os.chdir (p) + # if os.stat fails we ignore that file. + result = filter (None, map (safe_stat, ld)) + finally: + os.chdir (old_dir) + return list_producer (result, self.longify) + + # TODO: implement a cache w/timeout for stat() + def stat (self, path): + p = self.translate (path) + return os.stat (p) + + def open (self, path, mode): + p = self.translate (path) + return open (p, mode) + + def unlink (self, path): + p = self.translate (path) + return os.unlink (p) + + def mkdir (self, path): + p = self.translate (path) + return os.mkdir (p) + + def rmdir (self, path): + p = self.translate (path) + return os.rmdir (p) + + # utility methods + def normalize (self, path): + # watch for the ever-sneaky '/+' path element + path = re.sub('/+', '/', path) + p = self.path_module.normpath (path) + # remove 'dangling' cdup's. + if len(p) > 2 and p[:3] == '/..': + p = '/' + return p + + def translate (self, path): + # we need to join together three separate + # path components, and do it safely. + # // + # use the operating system's path separator. + path = string.join (string.split (path, '/'), os.sep) + p = self.normalize (self.path_module.join (self.wd, path)) + p = self.normalize (self.path_module.join (self.root, p[1:])) + return p + + def longify (self, (path, stat_info)): + return unix_longify (path, stat_info) + + def __repr__ (self): + return '' % ( + self.root, + self.wd + ) + +# this matches the output of NT's ftp server (when in +# MSDOS mode) exactly. + +def msdos_longify (file, stat_info): + if stat.S_ISDIR (stat_info[stat.ST_MODE]): + dir = '' + else: + dir = ' ' + date = msdos_date (stat_info[stat.ST_MTIME]) + return '%s %s %8d %s' % ( + date, + dir, + stat_info[stat.ST_SIZE], + file + ) + +def msdos_date (t): + try: + info = time.gmtime (t) + except: + info = time.gmtime (0) + # year, month, day, hour, minute, second, ... + if info[3] > 11: + merid = 'PM' + info[3] = info[3] - 12 + else: + merid = 'AM' + return '%02d-%02d-%02d %02d:%02d%s' % ( + info[1], + info[2], + info[0]%100, + info[3], + info[4], + merid + ) + +months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + +mode_table = { + '0':'---', + '1':'--x', + '2':'-w-', + '3':'-wx', + '4':'r--', + '5':'r-x', + '6':'rw-', + '7':'rwx' + } + +def unix_longify (file, stat_info): + # for now, only pay attention to the lower bits + mode = ('%o' % stat_info[stat.ST_MODE])[-3:] + mode = string.join (map (lambda x: mode_table[x], mode), '') + if stat.S_ISDIR (stat_info[stat.ST_MODE]): + dirchar = 'd' + else: + dirchar = '-' + date = ls_date (long(time.time()), stat_info[stat.ST_MTIME]) + return '%s%s %3d %-8d %-8d %8d %s %s' % ( + dirchar, + mode, + stat_info[stat.ST_NLINK], + stat_info[stat.ST_UID], + stat_info[stat.ST_GID], + stat_info[stat.ST_SIZE], + date, + file + ) + +# Emulate the unix 'ls' command's date field. +# it has two formats - if the date is more than 180 +# days in the past, then it's like this: +# Oct 19 1995 +# otherwise, it looks like this: +# Oct 19 17:33 + +def ls_date (now, t): + try: + info = time.gmtime (t) + except: + info = time.gmtime (0) + # 15,600,000 == 86,400 * 180 + if (now - t) > 15600000: + return '%s %2d %d' % ( + months[info[1]-1], + info[2], + info[0] + ) + else: + return '%s %2d %02d:%02d' % ( + months[info[1]-1], + info[2], + info[3], + info[4] + ) + +class list_producer: + def __init__ (self, list, func=None): + self.list = list + self.func = func + + # this should do a pushd/popd + def more (self): + if not self.list: + return '' + else: + # do a few at a time + bunch = self.list[:50] + if self.func is not None: + bunch = map (self.func, bunch) + self.list = self.list[50:] + return string.joinfields (bunch, '\r\n') + '\r\n' + +class hooked_callback: + def __init__ (self, hook, callback): + self.hook, self.callback = hook, callback + + def __call__ (self, *args): + apply (self.hook, args) + apply (self.callback, args) + +# An extensible, configurable, asynchronous FTP server. +# +# All socket I/O is non-blocking, however file I/O is currently +# blocking. Eventually file I/O may be made non-blocking, too, if it +# seems necessary. Currently the only CPU-intensive operation is +# getting and formatting a directory listing. [this could be moved +# into another process/directory server, or another thread?] +# +# Only a subset of RFC 959 is implemented, but much of that RFC is +# vestigial anyway. I've attempted to include the most commonly-used +# commands, using the feature set of wu-ftpd as a guide. + + +# TODO: implement a directory listing cache. On very-high-load +# servers this could save a lot of disk abuse, and possibly the +# work of computing emulated unix ls output. + +# Potential security problem with the FTP protocol? I don't think +# there's any verification of the origin of a data connection. Not +# really a problem for the server (since it doesn't send the port +# command, except when in PASV mode) But I think a data connection +# could be spoofed by a program with access to a sniffer - it could +# watch for a PORT command to go over a command channel, and then +# connect to that port before the server does. + +# Unix user id's: +# In order to support assuming the id of a particular user, +# it seems there are two options: +# 1) fork, and seteuid in the child +# 2) carefully control the effective uid around filesystem accessing +# methods, using try/finally. [this seems to work] + +VERSION = string.split(RCS_ID)[2] + +class ftp_channel (async_chat): + + # defaults for a reliable __repr__ + addr = ('unknown','0') + + # unset this in a derived class in order + # to enable the commands in 'self.write_commands' + read_only = 1 + write_commands = ['appe','dele','mkd','rmd','rnfr','rnto','stor','stou'] + + restart_position = 0 + + # comply with (possibly troublesome) RFC959 requirements + # This is necessary to correctly run an active data connection + # through a firewall that triggers on the source port (expected + # to be 'L-1', or 20 in the normal case). + bind_local_minus_one = 0 + + def __init__ (self, server, conn, addr): + self.server = server + self.current_mode = 'a' + self.addr = addr + async_chat.__init__ (self, conn) + self.set_terminator ('\r\n') + + # client data port. Defaults to 'the same as the control connection'. + self.client_addr = (addr[0], 21) + + self.client_dc = None + self.in_buffer = '' + self.closing = 0 + self.passive_acceptor = None + self.passive_connection = None + self.filesystem = None + self.authorized = 0 + # send the greeting + self.respond ( + '220 %s FTP server (Medusa Async V%s [experimental]) ready.' % ( + self.server.hostname, + VERSION + ) + ) + +# def __del__ (self): +# print 'ftp_channel.__del__()' + + # -------------------------------------------------- + # async-library methods + # -------------------------------------------------- + + def handle_expt (self): + # this is handled below. not sure what I could + # do here to make that code less kludgish. + pass + + def collect_incoming_data (self, data): + self.in_buffer = self.in_buffer + data + if len(self.in_buffer) > 4096: + # silently truncate really long lines + # (possible denial-of-service attack) + self.in_buffer = '' + + def found_terminator (self): + + line = self.in_buffer + + if not len(line): + return + + sp = string.find (line, ' ') + if sp != -1: + line = [line[:sp], line[sp+1:]] + else: + line = [line] + + command = string.lower (line[0]) + # watch especially for 'urgent' abort commands. + if string.find (command, 'abor') != -1: + # strip off telnet sync chars and the like... + while command and command[0] not in string.letters: + command = command[1:] + fun_name = 'cmd_%s' % command + if command != 'pass': + self.log ('<== %s' % repr(self.in_buffer)[1:-1]) + else: + self.log ('<== %s' % line[0]+' ') + self.in_buffer = '' + if not hasattr (self, fun_name): + self.command_not_understood (line[0]) + return + fun = getattr (self, fun_name) + if (not self.authorized) and (command not in ('user', 'pass', 'help', 'quit')): + self.respond ('530 Please log in with USER and PASS') + elif (not self.check_command_authorization (command)): + self.command_not_authorized (command) + else: + try: + result = apply (fun, (line,)) + except: + self.server.total_exceptions.increment() + (file, fun, line), t,v, tbinfo = asyncore.compact_traceback() + if self.client_dc: + try: + self.client_dc.close() + except: + pass + self.respond ( + '451 Server Error: %s, %s: file: %s line: %s' % ( + t,v,file,line, + ) + ) + + closed = 0 + def close (self): + if not self.closed: + self.closed = 1 + if self.passive_acceptor: + self.passive_acceptor.close() + if self.client_dc: + self.client_dc.close() + self.server.closed_sessions.increment() + async_chat.close (self) + + # -------------------------------------------------- + # filesystem interface functions. + # override these to provide access control or perform + # other functions. + # -------------------------------------------------- + + def cwd (self, line): + return self.filesystem.cwd (line[1]) + + def cdup (self, line): + return self.filesystem.cdup() + + def open (self, path, mode): + return self.filesystem.open (path, mode) + + # returns a producer + def listdir (self, path, long=0): + return self.filesystem.listdir (path, long) + + def get_dir_list (self, line, long=0): + # we need to scan the command line for arguments to '/bin/ls'... + args = line[1:] + path_args = [] + for arg in args: + if arg[0] != '-': + path_args.append (arg) + else: + # ignore arguments + pass + if len(path_args) < 1: + dir = '.' + else: + dir = path_args[0] + return self.listdir (dir, long) + + # -------------------------------------------------- + # authorization methods + # -------------------------------------------------- + + def check_command_authorization (self, command): + if command in self.write_commands and self.read_only: + return 0 + else: + return 1 + + # -------------------------------------------------- + # utility methods + # -------------------------------------------------- + + def log (self, message): + self.server.logger.log ( + self.addr[0], + '%d %s' % ( + self.addr[1], message + ) + ) + + def respond (self, resp): + self.log ('==> %s' % resp) + self.push (resp + '\r\n') + + def command_not_understood (self, command): + self.respond ("500 '%s': command not understood." % command) + + def command_not_authorized (self, command): + self.respond ( + "530 You are not authorized to perform the '%s' command" % ( + command + ) + ) + + def make_xmit_channel (self): + # In PASV mode, the connection may or may _not_ have been made + # yet. [although in most cases it is... FTP Explorer being + # the only exception I've yet seen]. This gets somewhat confusing + # because things may happen in any order... + pa = self.passive_acceptor + if pa: + if pa.ready: + # a connection has already been made. + conn, addr = self.passive_acceptor.ready + cdc = xmit_channel (self, addr) + cdc.set_socket (conn) + cdc.connected = 1 + self.passive_acceptor.close() + self.passive_acceptor = None + else: + # we're still waiting for a connect to the PASV port. + cdc = xmit_channel (self) + else: + # not in PASV mode. + ip, port = self.client_addr + cdc = xmit_channel (self, self.client_addr) + cdc.create_socket (socket.AF_INET, socket.SOCK_STREAM) + if self.bind_local_minus_one: + cdc.bind (('', self.server.port - 1)) + try: + cdc.connect ((ip, port)) + except socket.error, why: + self.respond ("425 Can't build data connection") + self.client_dc = cdc + + # pretty much the same as xmit, but only right on the verge of + # being worth a merge. + def make_recv_channel (self, fd): + pa = self.passive_acceptor + if pa: + if pa.ready: + # a connection has already been made. + conn, addr = pa.ready + cdc = recv_channel (self, addr, fd) + cdc.set_socket (conn) + cdc.connected = 1 + self.passive_acceptor.close() + self.passive_acceptor = None + else: + # we're still waiting for a connect to the PASV port. + cdc = recv_channel (self, None, fd) + else: + # not in PASV mode. + ip, port = self.client_addr + cdc = recv_channel (self, self.client_addr, fd) + cdc.create_socket (socket.AF_INET, socket.SOCK_STREAM) + try: + cdc.connect ((ip, port)) + except socket.error, why: + self.respond ("425 Can't build data connection") + self.client_dc = cdc + + type_map = { + 'a':'ASCII', + 'i':'Binary', + 'e':'EBCDIC', + 'l':'Binary' + } + + type_mode_map = { + 'a':'t', + 'i':'b', + 'e':'b', + 'l':'b' + } + + # -------------------------------------------------- + # command methods + # -------------------------------------------------- + + def cmd_type (self, line): + 'specify data transfer type' + # ascii, ebcdic, image, local + t = string.lower (line[1]) + # no support for EBCDIC + # if t not in ['a','e','i','l']: + if t not in ['a','i','l']: + self.command_not_understood (string.join (line)) + elif t == 'l' and (len(line) > 2 and line[2] != '8'): + self.respond ('504 Byte size must be 8') + else: + self.current_mode = t + self.respond ('200 Type set to %s.' % self.type_map[t]) + + + def cmd_quit (self, line): + 'terminate session' + self.respond ('221 Goodbye.') + self.close_when_done() + + def cmd_port (self, line): + 'specify data connection port' + info = string.split (line[1], ',') + ip = string.join (info[:4], '.') + port = string.atoi(info[4])*256 + string.atoi(info[5]) + # how many data connections at a time? + # I'm assuming one for now... + # TODO: we should (optionally) verify that the + # ip number belongs to the client. [wu-ftpd does this?] + self.client_addr = (ip, port) + self.respond ('200 PORT command successful.') + + def new_passive_acceptor (self): + # ensure that only one of these exists at a time. + if self.passive_acceptor is not None: + self.passive_acceptor.close() + self.passive_acceptor = None + self.passive_acceptor = passive_acceptor (self) + return self.passive_acceptor + + def cmd_pasv (self, line): + 'prepare for server-to-server transfer' + pc = self.new_passive_acceptor() + port = pc.addr[1] + ip_addr = pc.control_channel.getsockname()[0] + self.respond ( + '227 Entering Passive Mode (%s,%d,%d)' % ( + string.replace(ip_addr, '.', ','), + port/256, + port%256 + ) + ) + self.client_dc = None + + def cmd_nlst (self, line): + 'give name list of files in directory' + # ncftp adds the -FC argument for the user-visible 'nlist' + # command. We could try to emulate ls flags, but not just yet. + if '-FC' in line: + line.remove ('-FC') + try: + dir_list_producer = self.get_dir_list (line, 0) + except os.error, why: + self.respond ('550 Could not list directory: %s' % why) + return + self.respond ( + '150 Opening %s mode data connection for file list' % ( + self.type_map[self.current_mode] + ) + ) + self.make_xmit_channel() + self.client_dc.push_with_producer (dir_list_producer) + self.client_dc.close_when_done() + + def cmd_list (self, line): + 'give a list of files in a directory' + try: + dir_list_producer = self.get_dir_list (line, 1) + except os.error, why: + self.respond ('550 Could not list directory: %s' % why) + return + self.respond ( + '150 Opening %s mode data connection for file list' % ( + self.type_map[self.current_mode] + ) + ) + self.make_xmit_channel() + self.client_dc.push_with_producer (dir_list_producer) + self.client_dc.close_when_done() + + def cmd_cwd (self, line): + 'change working directory' + if self.cwd (line): + self.respond ('250 CWD command successful.') + else: + self.respond ('550 No such directory.') + + def cmd_cdup (self, line): + 'change to parent of current working directory' + if self.cdup(line): + self.respond ('250 CDUP command successful.') + else: + self.respond ('550 No such directory.') + + def cmd_pwd (self, line): + 'print the current working directory' + self.respond ( + '257 "%s" is the current directory.' % ( + self.filesystem.current_directory() + ) + ) + + # modification time + # example output: + # 213 19960301204320 + def cmd_mdtm (self, line): + 'show last modification time of file' + filename = line[1] + if not self.filesystem.isfile (filename): + self.respond ('550 "%s" is not a file' % filename) + else: + mtime = time.gmtime(self.filesystem.stat(filename)[stat.ST_MTIME]) + self.respond ( + '213 %4d%02d%02d%02d%02d%02d' % ( + mtime[0], + mtime[1], + mtime[2], + mtime[3], + mtime[4], + mtime[5] + ) + ) + + def cmd_noop (self, line): + 'do nothing' + self.respond ('200 NOOP command successful.') + + def cmd_size (self, line): + 'return size of file' + filename = line[1] + if not self.filesystem.isfile (filename): + self.respond ('550 "%s" is not a file' % filename) + else: + self.respond ( + '213 %d' % (self.filesystem.stat(filename)[stat.ST_SIZE]) + ) + + def cmd_retr (self, line): + 'retrieve a file' + if len(line) < 2: + self.command_not_understood (string.join (line)) + else: + file = line[1] + if not self.filesystem.isfile (file): + self.log_info ('checking %s' % file) + self.respond ('550 No such file') + else: + try: + # FIXME: for some reason, 'rt' isn't working on win95 + mode = 'r'+self.type_mode_map[self.current_mode] + fd = self.open (file, mode) + except IOError, why: + self.respond ('553 could not open file for reading: %s' % (repr(why))) + return + self.respond ( + "150 Opening %s mode data connection for file '%s'" % ( + self.type_map[self.current_mode], + file + ) + ) + self.make_xmit_channel() + + if self.restart_position: + # try to position the file as requested, but + # give up silently on failure (the 'file object' + # may not support seek()) + try: + fd.seek (self.restart_position) + except: + pass + self.restart_position = 0 + + self.client_dc.push_with_producer ( + file_producer (fd) + ) + self.client_dc.close_when_done() + + def cmd_stor (self, line, mode='wb'): + 'store a file' + if len (line) < 2: + self.command_not_understood (string.join (line)) + else: + if self.restart_position: + restart_position = 0 + self.respond ('553 restart on STOR not yet supported') + return + file = line[1] + # todo: handle that type flag + try: + fd = self.open (file, mode) + except IOError, why: + self.respond ('553 could not open file for writing: %s' % (repr(why))) + return + self.respond ( + '150 Opening %s connection for %s' % ( + self.type_map[self.current_mode], + file + ) + ) + self.make_recv_channel (fd) + + def cmd_abor (self, line): + 'abort operation' + if self.client_dc: + self.client_dc.close() + self.respond ('226 ABOR command successful.') + + def cmd_appe (self, line): + 'append to a file' + return self.cmd_stor (line, 'ab') + + def cmd_dele (self, line): + if len (line) != 2: + self.command_not_understood (string.join (line)) + else: + file = line[1] + if self.filesystem.isfile (file): + try: + self.filesystem.unlink (file) + self.respond ('250 DELE command successful.') + except: + self.respond ('550 error deleting file.') + else: + self.respond ('550 %s: No such file.' % file) + + def cmd_mkd (self, line): + if len (line) != 2: + self.command_not_understood (string.join (line)) + else: + path = line[1] + try: + self.filesystem.mkdir (path) + self.respond ('257 MKD command successful.') + except: + self.respond ('550 error creating directory.') + + def cmd_rmd (self, line): + if len (line) != 2: + self.command_not_understood (string.join (line)) + else: + path = line[1] + try: + self.filesystem.rmdir (path) + self.respond ('250 RMD command successful.') + except: + self.respond ('550 error removing directory.') + + def cmd_user (self, line): + 'specify user name' + if len(line) > 1: + self.user = line[1] + self.respond ('331 Password required.') + else: + self.command_not_understood (string.join (line)) + + def cmd_pass (self, line): + 'specify password' + if len(line) < 2: + pw = '' + else: + pw = line[1] + result, message, fs = self.server.authorizer.authorize (self, self.user, pw) + if result: + self.respond ('230 %s' % message) + self.filesystem = fs + self.authorized = 1 + self.log_info('Successful login: Filesystem=%s' % repr(fs)) + else: + self.respond ('530 %s' % message) + + def cmd_rest (self, line): + 'restart incomplete transfer' + try: + pos = string.atoi (line[1]) + except ValueError: + self.command_not_understood (string.join (line)) + self.restart_position = pos + self.respond ( + '350 Restarting at %d. Send STORE or RETRIEVE to initiate transfer.' % pos + ) + + def cmd_stru (self, line): + 'obsolete - set file transfer structure' + if line[1] in 'fF': + # f == 'file' + self.respond ('200 STRU F Ok') + else: + self.respond ('504 Unimplemented STRU type') + + def cmd_mode (self, line): + 'obsolete - set file transfer mode' + if line[1] in 'sS': + # f == 'file' + self.respond ('200 MODE S Ok') + else: + self.respond ('502 Unimplemented MODE type') + +# The stat command has two personalities. Normally it returns status +# information about the current connection. But if given an argument, +# it is equivalent to the LIST command, with the data sent over the +# control connection. Strange. But wuftpd, ftpd, and nt's ftp server +# all support it. +# +## def cmd_stat (self, line): +## 'return status of server' +## pass + + def cmd_syst (self, line): + 'show operating system type of server system' + # Replying to this command is of questionable utility, because + # this server does not behave in a predictable way w.r.t. the + # output of the LIST command. We emulate Unix ls output, but + # on win32 the pathname can contain drive information at the front + # Currently, the combination of ensuring that os.sep == '/' + # and removing the leading slash when necessary seems to work. + # [cd'ing to another drive also works] + # + # This is how wuftpd responds, and is probably + # the most expected. The main purpose of this reply is so that + # the client knows to expect Unix ls-style LIST output. + self.respond ('215 UNIX Type: L8') + # one disadvantage to this is that some client programs + # assume they can pass args to /bin/ls. + # a few typical responses: + # 215 UNIX Type: L8 (wuftpd) + # 215 Windows_NT version 3.51 + # 215 VMS MultiNet V3.3 + # 500 'SYST': command not understood. (SVR4) + + def cmd_help (self, line): + 'give help information' + # find all the methods that match 'cmd_xxxx', + # use their docstrings for the help response. + attrs = dir(self.__class__) + help_lines = [] + for attr in attrs: + if attr[:4] == 'cmd_': + x = getattr (self, attr) + if type(x) == type(self.cmd_help): + if x.__doc__: + help_lines.append ('\t%s\t%s' % (attr[4:], x.__doc__)) + if help_lines: + self.push ('214-The following commands are recognized\r\n') + self.push_with_producer (lines_producer (help_lines)) + self.push ('214\r\n') + else: + self.push ('214-\r\n\tHelp Unavailable\r\n214\r\n') + +class ftp_server (asyncore.dispatcher): + # override this to spawn a different FTP channel class. + ftp_channel_class = ftp_channel + + SERVER_IDENT = 'FTP Server (V%s)' % VERSION + + def __init__ ( + self, + authorizer, + hostname =None, + ip ='', + port =21, + logger_object=file_logger (sys.stdout) + ): + self.ip = ip + self.port = port + self.authorizer = authorizer + + if hostname is None: + self.hostname = socket.gethostname() + else: + self.hostname = hostname + + # statistics + self.total_sessions = counter() + self.closed_sessions = counter() + self.total_files_out = counter() + self.total_files_in = counter() + self.total_bytes_out = counter() + self.total_bytes_in = counter() + self.total_exceptions = counter() + # + asyncore.dispatcher.__init__ (self) + self.create_socket (socket.AF_INET, socket.SOCK_STREAM) + + self.set_reuse_addr() + self.bind ((self.ip, self.port)) + self.listen (5) + + if not logger_object: + logger_object = sys.stdout + + self.logger = unresolving_logger (logger_object) + + self.log_info('FTP server started at %s\n\tAuthorizer:%s\n\tHostname: %s\n\tPort: %d' % ( + time.ctime(time.time()), + repr (self.authorizer), + self.hostname, + self.port) + ) + + def writable (self): + return 0 + + def handle_read (self): + pass + + def handle_connect (self): + pass + + def handle_accept (self): + conn, addr = self.accept() + self.total_sessions.increment() + self.log_info('Incoming connection from %s:%d' % (addr[0], addr[1])) + self.ftp_channel_class (self, conn, addr) + + # return a producer describing the state of the server + def status (self): + + def nice_bytes (n): + return string.join (english_bytes (n)) + + return lines_producer ( + ['

    %s

    ' % self.SERVER_IDENT, + '
    Listening on Host: %s' % self.hostname, + 'Port: %d' % self.port, + '
    Sessions', + 'Total: %s' % self.total_sessions, + 'Current: %d' % (self.total_sessions.as_long() - self.closed_sessions.as_long()), + '
    Files', + 'Sent: %s' % self.total_files_out, + 'Received: %s' % self.total_files_in, + '
    Bytes', + 'Sent: %s' % nice_bytes (self.total_bytes_out.as_long()), + 'Received: %s' % nice_bytes (self.total_bytes_in.as_long()), + '
    Exceptions: %s' % self.total_exceptions, + ] + ) + +# ====================================================================== +# Data Channel Classes +# ====================================================================== + +# This socket accepts a data connection, used when the server has been +# placed in passive mode. Although the RFC implies that we ought to +# be able to use the same acceptor over and over again, this presents +# a problem: how do we shut it off, so that we are accepting +# connections only when we expect them? [we can't] +# +# wuftpd, and probably all the other servers, solve this by allowing +# only one connection to hit this acceptor. They then close it. Any +# subsequent data-connection command will then try for the default +# port on the client side [which is of course never there]. So the +# 'always-send-PORT/PASV' behavior seems required. +# +# Another note: wuftpd will also be listening on the channel as soon +# as the PASV command is sent. It does not wait for a data command +# first. + +# --- we need to queue up a particular behavior: +# 1) xmit : queue up producer[s] +# 2) recv : the file object +# +# It would be nice if we could make both channels the same. Hmmm.. +# + +class passive_acceptor (asyncore.dispatcher): + ready = None + + def __init__ (self, control_channel): + # connect_fun (conn, addr) + asyncore.dispatcher.__init__ (self) + self.control_channel = control_channel + self.create_socket (socket.AF_INET, socket.SOCK_STREAM) + # bind to an address on the interface that the + # control connection is coming from. + self.bind (( + self.control_channel.getsockname()[0], + 0 + )) + self.addr = self.getsockname() + self.listen (1) + +# def __del__ (self): +# print 'passive_acceptor.__del__()' + + def log (self, *ignore): + pass + + def handle_accept (self): + conn, addr = self.accept() + dc = self.control_channel.client_dc + if dc is not None: + dc.set_socket (conn) + dc.addr = addr + dc.connected = 1 + self.control_channel.passive_acceptor = None + else: + self.ready = conn, addr + self.close() + + +class xmit_channel (async_chat): + + # for an ethernet, you want this to be fairly large, in fact, it + # _must_ be large for performance comparable to an ftpd. [64k] we + # ought to investigate automatically-sized buffers... + + ac_out_buffer_size = 16384 + bytes_out = 0 + + def __init__ (self, channel, client_addr=None): + self.channel = channel + self.client_addr = client_addr + async_chat.__init__ (self) + +# def __del__ (self): +# print 'xmit_channel.__del__()' + + def log (self, *args): + pass + + def readable (self): + return not self.connected + + def writable (self): + return 1 + + def send (self, data): + result = async_chat.send (self, data) + self.bytes_out = self.bytes_out + result + return result + + def handle_error (self): + # usually this is to catch an unexpected disconnect. + self.log_info ('unexpected disconnect on data xmit channel', 'error') + try: + self.close() + except: + pass + + # TODO: there's a better way to do this. we need to be able to + # put 'events' in the producer fifo. to do this cleanly we need + # to reposition the 'producer' fifo as an 'event' fifo. + + def close (self): + c = self.channel + s = c.server + c.client_dc = None + s.total_files_out.increment() + s.total_bytes_out.increment (self.bytes_out) + if not len(self.producer_fifo): + c.respond ('226 Transfer complete') + elif not c.closed: + c.respond ('426 Connection closed; transfer aborted') + del c + del s + del self.channel + async_chat.close (self) + +class recv_channel (asyncore.dispatcher): + def __init__ (self, channel, client_addr, fd): + self.channel = channel + self.client_addr = client_addr + self.fd = fd + asyncore.dispatcher.__init__ (self) + self.bytes_in = counter() + + def log (self, *ignore): + pass + + def handle_connect (self): + pass + + def writable (self): + return 0 + + def recv (*args): + result = apply (asyncore.dispatcher.recv, args) + self = args[0] + self.bytes_in.increment(len(result)) + return result + + buffer_size = 8192 + + def handle_read (self): + block = self.recv (self.buffer_size) + if block: + try: + self.fd.write (block) + except IOError: + self.log_info ('got exception writing block...', 'error') + + def handle_close (self): + s = self.channel.server + s.total_files_in.increment() + s.total_bytes_in.increment(self.bytes_in.as_long()) + self.fd.close() + self.channel.respond ('226 Transfer complete.') + self.close() + + +import getopt +import re, sys +import asyncore +import os +import random +import imp +import time +import thread +import stat +import urllib +import traceback +import logging +import zipfile + +HTTP_CONTINUE = 100 +HTTP_SWITCHING_PROTOCOLS = 101 +HTTP_PROCESSING = 102 +HTTP_OK = 200 +HTTP_CREATED = 201 +HTTP_ACCEPTED = 202 +HTTP_NON_AUTHORITATIVE = 203 +HTTP_NO_CONTENT = 204 +HTTP_RESET_CONTENT = 205 +HTTP_PARTIAL_CONTENT = 206 +HTTP_MULTI_STATUS = 207 +HTTP_MULTIPLE_CHOICES = 300 +HTTP_MOVED_PERMANENTLY = 301 +HTTP_MOVED_TEMPORARILY = 302 +HTTP_SEE_OTHER = 303 +HTTP_NOT_MODIFIED = 304 +HTTP_USE_PROXY = 305 +HTTP_TEMPORARY_REDIRECT = 307 +HTTP_BAD_REQUEST = 400 +HTTP_UNAUTHORIZED = 401 +HTTP_PAYMENT_REQUIRED = 402 +HTTP_FORBIDDEN = 403 +HTTP_NOT_FOUND = 404 +HTTP_METHOD_NOT_ALLOWED = 405 +HTTP_NOT_ACCEPTABLE = 406 +HTTP_PROXY_AUTHENTICATION_REQUIRED= 407 +HTTP_REQUEST_TIME_OUT = 408 +HTTP_CONFLICT = 409 +HTTP_GONE = 410 +HTTP_LENGTH_REQUIRED = 411 +HTTP_PRECONDITION_FAILED = 412 +HTTP_REQUEST_ENTITY_TOO_LARGE = 413 +HTTP_REQUEST_URI_TOO_LARGE = 414 +HTTP_UNSUPPORTED_MEDIA_TYPE = 415 +HTTP_RANGE_NOT_SATISFIABLE = 416 +HTTP_EXPECTATION_FAILED = 417 +HTTP_UNPROCESSABLE_ENTITY = 422 +HTTP_LOCKED = 423 +HTTP_FAILED_DEPENDENCY = 424 +HTTP_INTERNAL_SERVER_ERROR = 500 +HTTP_NOT_IMPLEMENTED = 501 +HTTP_BAD_GATEWAY = 502 +HTTP_SERVICE_UNAVAILABLE = 503 +HTTP_GATEWAY_TIME_OUT = 504 +HTTP_VERSION_NOT_SUPPORTED = 505 +HTTP_VARIANT_ALSO_VARIES = 506 +HTTP_INSUFFICIENT_STORAGE = 507 +HTTP_NOT_EXTENDED = 510 + +GLOBAL_TEMP_DIR="/tmp/" +GLOBAL_ROOT_DIR="no-root-dir-set" +verbose = 0 +multithreading_enabled = 0 +number_of_threads = 32 + +def qualify_path(p): + if p[-1] != '/': + return p + "/" + return p + +def join_paths(p1,p2): + if p1.endswith("/"): + if p2.startswith("/"): + return p1[:-1] + p2 + else: + return p1 + p2 + else: + if p2.startswith("/"): + return p1 + p2 + else: + return p1 + "/" + p2 + + +translators = [] +macroresolvers = [] +ftphandlers = [] +contexts = [] + +def getMacroFile(filename): + global macrofile_callback + for r in macroresolvers: + try: + f = r(filename) + if f is not None and os.path.isfile(f): + return f + except: + pass + if os.path.isfile(filename): + return filename + filename2 = join_paths(GLOBAL_ROOT_DIR,filename) + if os.path.isfile(filename2): + return filename2 + raise IOError("No such file: "+filename2) + + +global_modules={} + +def _make_inifiles(root, path): + dirs = path.split("/") + path = root + for dir in dirs: + path = join_paths(path, dir) + inifile = join_paths(path, "__init__.py") + # create missing __init__.py + if not os.path.isfile(inifile): + if lg: + lg.log("creating file "+inifile) + open(inifile, "wb").close() + +def _load_module(filename): + global global_modules + b = BASENAME.match(filename) + # filename e.g. /my/modules/test.py + # b.group(1) = /my/modules/ + # b.group(2) = test.py + if b is None: + raise "Internal error with filename "+filename + module = b.group(2) + if module is None: + raise "Internal error with filename "+filename + + while filename.startswith("./"): + filename = filename[2:] + + if filename in global_modules: + return global_modules[filename] + + dir = os.path.dirname(filename) + path = dir.replace("/",".") + + _make_inifiles(GLOBAL_ROOT_DIR, dir) + + # strip tailing/leading dots + while len(path) and path[0] == '.': + path = path[1:] + while len(path) and path[-1] != '.': + path = path + "." + + module2 = (path + module) + if lg: + lg.log("Loading module "+module2) + + m = __import__(module2) + try: + i = module2.index(".") + m = eval("m."+module2[i+1:]) + global_modules[filename] = m + except: + pass + return m + +system_modules = sys.modules.copy() +stdlib, x = os.path.split(os.__file__) +def _purge_all_modules(): + for m,mod in sys.modules.items(): + if m not in system_modules: + if hasattr(mod, "__file__"): + f = mod.__file__ + path, x = os.path.split(f) + if not path.startswith(stdlib): + del sys.modules[m] + +class WebContext: + def __init__(self, name, root=None): + self.name = name + self.files = [] + self.startupfile = None + if root: + self.root = qualify_path(root) + self.pattern_to_function = {} + self.id_to_function = {} + + def addFile(self, filename): + file = WebFile(self, filename) + self.files += [file] + return file + + def setRoot(self, root): + self.root = qualify_path(root) + while self.root.startswith("./"): + self.root = self.root[2:] + + def setStartupFile(self, startupfile): + self.startupfile = startupfile + lg.log(" executing startupfile") + self._load_module(self.startupfile) + + def getStartupFile(self): + return self.startupfile + + def match(self, path): + function = None + for pattern,call in self.pattern_to_function.items(): + if pattern.match(path): + function,desc = call + if verbose: + lg.log("Request %s matches (%s)" % (req.path, desc)) + if function is None: + for id,call in self.id_to_function.items(): + if path == id: + function,desc = call + if verbose: + lg.log("Request %s matches handler (%s)" % (req.path, desc)) + if not function: + return None + def call_and_close(f,req): + status = f(req) + if status is not None and type(1)==type(status) and status>10: + req.reply_code = status + if status == 404: + return req.error(status, "not found") + elif(status >= 400 and status <= 500): + return req.error(status) + return req.done() + return lambda req: call_and_close(function,req) + +class FileStore: + def __init__(self, name, root=None): + self.name = name + self.handlers = [] + if type(root) == type(""): + self.addRoot(root) + elif type(root) == type([]): + for dir in root: + self.addRoot(dir) + + def match(self, path): + return lambda req: self.findfile(req) + + def findfile(self, request): + for handler in self.handlers: + if handler.can_handle(request): + return handler.handle_request(request) + return request.error(404, "File "+request.path+" not found") + + def addRoot(self, dir): + dir = qualify_path(dir) + while dir.startswith("./"): + dir = dir[2:] + if zipfile.is_zipfile(GLOBAL_ROOT_DIR + dir[:-1]) and dir.lower().endswith("zip/"): + self.handlers += [default_handler (zip_filesystem (GLOBAL_ROOT_DIR + dir[:-1]))] + else: + self.handlers += [default_handler (os_filesystem (GLOBAL_ROOT_DIR + dir))] + +class WebFile: + def __init__(self, context, filename): + self.context = context + if filename[0] == '/': + filename = filename[1:] + self.filename = filename + self.m = _load_module(filename) + self.handlers = [] + + def addHandler(self, function): + handler = WebHandler(self, function) + self.handlers += [handler] + return handler + + def addFTPHandler(self, ftpclass): + global ftphandlers + m = self.m + try: + c = eval("m."+ftpclass) + if c is None: + raise + ftphandlers += [c] + except: + lgerr.log("Error in FTP Handler:" + str(sys.exc_info()[0]) + " " + str(sys.exc_info()[1])) + traceback.print_tb(sys.exc_info()[2],None,lgerr) + raise "No such function "+ftpclass+" in file "+self.filename + + def addMacroResolver(self, macroresolver): + global macroresolvers + m = self.m + try: + f = eval("m."+macroresolver) + if f is None: + raise + macroresolvers += [f] + except: + lgerr.log("Error in Macro Resolver:" + str(sys.exc_info()[0]) + " " + str(sys.exc_info()[1])) + traceback.print_tb(sys.exc_info()[2],None,lgerr) + raise "No such function "+macroresolver+" in file "+self.filename + + def addTranslator(self, handler): + global translators + m = self.m + try: + f = eval("m."+translator) + if f is None: + raise + translators += [f] + except: + lgerr.log("Error in Macro Resolver:" + str(sys.exc_info()[0]) + " " + str(sys.exc_info()[1])) + traceback.print_tb(sys.exc_info()[2],None,lgerr) + raise "No such function "+translator+" in file "+self.filename + + def getFileName(self): + return self.context.root + self.filename + +class WebHandler: + def __init__(self, file, function): + self.file = file + self.function = function + m = file.m + try: + self.f = eval("m."+function) + if self.f is None: + raise + except: + lgerr.log("Error in Handler:" + str(sys.exc_info()[0]) + " " + str(sys.exc_info()[1])) + traceback.print_tb(sys.exc_info()[2],None,lgerr) + raise "No such function "+function+" in file "+self.file.filename + + def addPattern(self, pattern): + p = WebPattern(self,pattern) + desc = "pattern %s, file %s, function %s" % (pattern,self.file.filename,self.function) + desc2 = "file %s, function %s" % (self.file.filename,self.function) + self.file.context.pattern_to_function[p.getPattern()] = (self.f,desc) + self.file.context.id_to_function["/"+self.function] = (self.f,desc2) + return p + +class WebPattern: + def __init__(self, handler, pattern): + self.handler = handler + self.pattern = pattern + if not pattern.endswith('$'): + pattern = pattern + "$" + self.compiled = re.compile(pattern) + def getPattern(self): + return self.compiled + def getPatternString(self): + return self.pattern + +def read_ini_file(filename): + global GLOBAL_TEMP_DIR,GLOBAL_ROOT_DIR,number_of_threads,multithreading_enabled,contexts + lineno = 0 + fi = open(filename, "rb") + file = None + function = None + context = None + GLOBAL_ROOT_DIR = '/' + for line in fi.readlines(): + lineno=lineno+1 + hashpos = line.find("#") + if hashpos>=0: + line = line[0:hashpos] + line = line.strip() + + if line == "": + continue #skip empty line + + equals = line.find(":") + if equals<0: + continue + key = line[0:equals].strip() + value = line[equals+1:].strip() + if key == "tempdir": + GLOBAL_TEMP_DIR = qualify_path(value) + elif key == "threads": + number_of_threads = int(value) + multithreading_enabled = 1 + elif key == "base": + GLOBAL_ROOT_DIR = qualify_path(value) + sys.path += [GLOBAL_ROOT_DIR] + elif key == "filestore": + if len(value) and value[0] != '/': + value = "/" + value + filestore = FileStore(value) + contexts += [filestore] + context = None + elif key == "context": + if len(value) and value[0] != '/': + value = "/" + value + contextname = value + context = WebContext(contextname) + contexts += [context] + filestore = None + elif key == "startupfile": + if context is not None: + context.setStartupFile(value) + else: + raise "Error: startupfile must be below a context" + elif key == "root": + if value.startswith('/'): + value = value[1:] + if context: + context.setRoot(value) + if filestore: + filestore.addRoot(value) + elif key == "file": + filename = value + context.addFile(filename) + elif key == "ftphandler": + file.addFTPHandler(value) + elif key == "handler": + function = value + file.addHandler(function) + elif key == "macroresolver": + file.addMacroResolver(value) + elif key == "translator": + file.addTranslator(value) + elif key == "pattern": + handler.addPattern(value) + else: + raise "Syntax error in line "+str(lineno)+" of file "+filename+":\n"+line + fi.close() + +def headers_to_map(mylist): + headers={} + for h in mylist: + try: + i = h.index(':') + except: + i = -1 + if i >= 0: + key = h[0:i].lower() + value = h[i+1:] + if len(value)>0 and value[0] == ' ': + value = value[1:] + headers[key] = value + else: + if len(h.strip())>0: + lg.log("invalid header: "+str(h)) + return headers + +class AthanaFile: + def __init__(self,fieldname, parammap,filename,content_type): + self.fieldname = fieldname + self.parammap = parammap + self.filename = filename + self.content_type = content_type + self.tempname = GLOBAL_TEMP_DIR+str(int(random.random()*999999))+os.path.splitext(filename)[1] + self.filesize = 0 + self.fi = open(self.tempname, "wb") + def adddata(self,data): + self.filesize += len(data) + self.fi.write(data) + def close(self): + self.fi.close() + # only append file to parameters if it contains some data + if self.filename or self.filesize: + self.parammap[self.fieldname] = self + del self.fieldname + del self.parammap + del self.fi + def __str__(self): + return "file %s (%s), %d bytes, content-type: %s" % (self.filename, self.tempname, self.filesize, self.content_type) + +class AthanaField: + def __init__(self,fieldname,parammap): + self.fieldname = fieldname + self.data = "" + self.parammap = parammap + def adddata(self,data): + self.data += data + def close(self): + try: + oldvalue = self.parammap[self.fieldname] + ";" + except KeyError: + oldvalue = "" + self.parammap[self.fieldname] = oldvalue + self.data + del self.data + del self.parammap + +class simple_input_collector: + def __init__ (self, handler, request, length): + self.request = request + self.length = length + self.handler = handler + request.channel.set_terminator(length) + self.data = "" + + def collect_incoming_data (self, data): + self.data += data + + def found_terminator(self): + self.request.channel.set_terminator('\r\n\r\n') + self.request.collector = None + d=self.data;del self.data + r=self.request;del self.request + parameters={} + data = d.split('&') + for e in data: + if '=' in e: + key,value = e.split('=') + key = urllib.unquote_plus(key) + try: + oldvalue = parameters[key]+";" + except KeyError: + oldvalue = "" + parameters[key] = oldvalue + urllib.unquote_plus(value) + else: + if len(e.strip())>0: + lg.log("Unknown parameter: "+e) + self.handler.continue_request(r,parameters) + +class upload_input_collector: + def __init__ (self, handler, request, length, boundary): + self.request = request + self.length = length + self.handler = handler + self.boundary = boundary + request.channel.set_terminator(length) + self.data = "" + self.pos = 0 + self.start_marker = "--"+boundary+"\r\n" + self.end_marker = "--"+boundary+"--\r\n" + self.prefix = "--"+boundary + self.marker = "\r\n--"+boundary + self.header_end_marker = "\r\n\r\n" + self.current_file = None + self.boundary = boundary + self.file = None + self.parameters = {} + self.files = [] + + def parse_semicolon_parameters(self,params): + params = params.split("; ") + parmap = {} + for a in params: + if '=' in a: + key,value = a.split('=') + if value.startswith('"') and value.endswith('"'): + value = value[1:-1] + parmap[key] = value + return parmap + + def startFile(self,headers): + fieldname = None + filename = None + if self.file is not None: + raise "Illegal state" + if "content-disposition" in headers: + cd = headers["content-disposition"] + l = self.parse_semicolon_parameters(cd) + if "name" in l: + fieldname = l["name"] + if "filename" in l: + filename = l["filename"] + if "content-type" in headers: + content_type = headers["content-type"] + self.file = AthanaFile(fieldname,self.parameters,filename,content_type) + self.files += [self.file] + else: + self.file = AthanaField(fieldname,self.parameters) + + def split_headers(self,string): + return string.split("\r\n") + + def collect_incoming_data (self, newdata): + self.pos += len(newdata) + self.data += newdata + + while len(self.data)>0: + if self.data.startswith(self.end_marker): + self.data = self.data[len(self.end_marker):] + if self.file is not None: + self.file.close() + self.file = None + return + elif self.data.startswith(self.start_marker): + try: + i = self.data.index(self.header_end_marker, len(self.start_marker)) + except: + i = -1 + if i>=0: + headerstr = self.data[len(self.start_marker):i+2] + headers = headers_to_map(self.split_headers(headerstr)) + self.startFile(headers) + self.data = self.data[i+len(self.header_end_marker):] + else: + return # wait for more data (inside headers) + elif self.data.startswith(self.prefix): + return + else: + try: + bindex = self.data.index(self.marker) + self.file.adddata(self.data[0:bindex]) + self.file.close() + self.file = None + self.data = self.data[bindex+2:] # cut to position after \r\n + except ValueError: #not found + if(len(self.data) <= len(self.marker)): + return #wait for more data before we make a decision or pass through data + else: + self.file.adddata(self.data[0:-len(self.marker)]) + self.data = self.data[-len(self.marker):] + + def found_terminator(self): + if len(self.data)>0:# and self.file is not None: + if self.file is not None: + self.file.close() + self.file = None + raise "Unfinished/malformed multipart request" + if self.file is not None: + self.file.close() + self.file = None + + self.request.collector = None + self.request.channel.set_terminator('\r\n\r\n') + d=self.data;del self.data + r=self.request;del self.request + r.tempfiles = [f.tempname for f in self.files] + self.handler.continue_request(r,self.parameters) + +class Session(dict): + def __init__(self, id): + self.id = id + def use(self): + self.lastuse = time.time() + +def exception_string(): + s = "Exception "+str(sys.exc_info()[0]) + info = sys.exc_info()[1] + if info: + s += " "+str(info) + s += "\n" + for l in traceback.extract_tb(sys.exc_info()[2]): + s += " File \"%s\", line %d, in %s\n" % (l[0],l[1],l[2]) + s += " %s\n" % l[3] + return s + +BASENAME = re.compile("([^/]*/)*([^/.]*)(.py)?") +MULTIPART = re.compile ('multipart/form-data.*boundary=([^ ]*)', re.IGNORECASE) +SESSION_PATTERN = re.compile("^;[a-z0-9]{6}-[a-z0-9]{6}-[a-z0-9]{6}$") + +use_cookies = 1 + +class AthanaHandler: + def __init__(self): + self.sessions = {} + self.queue = [] + self.queuelock = thread.allocate_lock() + + def match(self, request): + path, params, query, fragment = request.split_uri() + #lg.log("===== request:"+path+"=====") + return 1 + + def handle_request (self, request): + headers = headers_to_map(request.header) + request.request_headers = headers + + size=headers.get("content-length",None) + + if size and size != '0': + size=int(size) + ctype=headers.get("content-type",None) + b = MULTIPART.match(ctype) + if b is not None: + request.type = "MULTIPART" + boundary = b.group(1) + request.collector = upload_input_collector(self,request,size,boundary) + else: + request.type = "POST" + request.collector = simple_input_collector(self,request,size) + else: + request.type = "GET" + self.continue_request(request, {}) + + def create_session_id(self): + pid = abs((str(random.random())).__hash__()) + now = abs((str(time.time())).__hash__()) + rand = abs((str(random.random())).__hash__()) + x = "abcdefghijklmnopqrstuvwxyz0123456789" + result = "" + for a in range(0,6): + result += x[pid%36] + pid = pid / 36 + result += "-" + for a in range(0,6): + result += x[now%36] + now = now / 36 + result += "-" + for a in range(0,6): + result += x[rand%36] + rand = rand / 36 + return result + + def continue_request(self, request, parameters): + + path, params, query, fragment = request.split_uri() + + ip = request.request_headers.get("x-forwarded-for",None) + if ip is None: + try: ip = request.channel.addr[0] + except: pass + if ip: + request.channel.addr = (ip,request.channel.addr[1]) + + request.log() + + if query is not None: + if query[0] == '?': + query=query[1:] + query = query.split('&') + for e in query: + key,value = e.split('=') + key = urllib.unquote_plus(key) + try: + oldvalue = parameters[key]+";" + except KeyError: + oldvalue = "" + parameters[key] = oldvalue + urllib.unquote_plus(value) #_plus? + + cookies = {} + if "cookie" in request.request_headers: + cookiestr = request.request_headers["cookie"] + if cookiestr.rfind(";") == len(cookiestr)-1: + cookiestr = cookiestr[:-1] + items = cookiestr.split(';') + for a in items: + key,value = a.strip().split('=') + cookies[key] = value + + request.Cookies = cookies + + sessionid = None + if params is not None and SESSION_PATTERN.match(params): + sessionid = params + if sessionid[0] == ';': + sessionid = sessionid[1:] + elif use_cookies and "PSESSION" in cookies: + sessionid = cookies["PSESSION"] + + if sessionid is not None: + if sessionid in self.sessions: + session = self.sessions[sessionid] + session.use() + else: + session = Session(sessionid) + self.sessions[sessionid] = session + else: + sessionid = self.create_session_id() + session = Session(sessionid) + self.sessions[sessionid] = session + + + request['Connection'] = 'close'; + request['Content-Type'] = 'text/html; encoding=utf-8; charset=utf-8'; + + maxlen = -1 + context = None + global contexts + for c in contexts: + #lg.debug("Compare context "+c.name+" with request "+path) + if path.startswith(c.name) and len(c.name)>maxlen: + context = c + maxlen = len(context.name) + if context is None: + request.error (404) + return + + #print "Request ",'"'+path+'"',"maps to context",context.name + fullpath = path + path = path[len(context.name):] + if len(path)==0 or path[0] != '/': + path = "/" + path + + request.session = session + request.sessionid = sessionid + request.context = context + request.path = path + request.fullpath = fullpath + request.paramstring = params + request.query = query + request.fragment = fragment + request.params = parameters + request.request = request + request.ip = ip + request.uri = request.uri.replace(context.name, "/") + request._split_uri = None + + if use_cookies: + request.setCookie('PSESSION', sessionid, time.time()+3600*2) + + request.channel.current_request = None + + function = context.match(path) + + if function is not None: + if not multithreading_enabled: + self.callhandler(function, request) + else: + self.queuelock.acquire() + self.queue += [(function,request)] + self.queuelock.release() + return + else: + lg.log("Request %s matches no pattern (context: %s)" % (request.path,context.name)) + return request.error(404, "File %s not found" % request.path) + + def callhandler(self, function, req): + request = req.request + s = None + try: + status = function(req) + except: + lgerr.log("Error in page :" + str(sys.exc_info()[0]) + " " + str(sys.exc_info()[1])) + traceback.print_tb(sys.exc_info()[2],None,lgerr) + s = "
    "+exception_string()+"
    " + return request.error(500,s) + +def worker_thread(server): + while 1: + server.queuelock.acquire() + if len(server.queue) == 0: + server.queuelock.release() + time.sleep(0.01) + else: + function,req = server.queue.pop() + server.queuelock.release() + try: + server.callhandler(function,req) + except: + lgerr.log("Error while processing request:" + str(sys.exc_info()[0]) + " " + str(sys.exc_info()[1])) + traceback.print_tb(sys.exc_info()[2],None,lgerr) + +class fs: + pass + +class virtual_authorizer: + def __init__ (self): + pass + def authorize (self, channel, username, password): + channel.persona = -1, -1 + channel.read_only = 1 + #return 1, 'Ok.', fs() + return 1, 'Ok.', os_filesystem("/home/kramm") + + def __repr__(self): + return 'virtual' + +class logging_logger: + def __init__(self,name="athana"): + self.logger = logging.getLogger(name) + def log (self, message): + self.logger.info(message.rstrip()) + def debug (self, message): + self.logger.debug(message.rstrip()) + def write (self, message): + self.logger.info(message.rstrip()) + def error (self, message): + self.logger.error(message.rstrip()) + +lg = logging_logger() +lgerr = logging_logger("errors") + +class zip_filesystem: + def __init__(self, filename): + self.filename = filename + self.wd = '/' + self.m = {} + self.z = zipfile.ZipFile(filename) + self.lock = thread.allocate_lock() + for f in self.z.filelist: + self.m['/' + f.filename] = f + + def current_directory(self): + return self.wd + + def isfile(self, path): + if len(path) and path[-1]=='/': + return 0 + return (self.wd + path) in self.m + + def isdir (self, path): + if not (len(path) and path[-1]=='/'): + path += '/' + return path in self.m + + def cwd (self, path): + path = join_paths(self.wd, path) + if not self.isdir (path): + return 0 + else: + self.wd = path + return 1 + + def cdup (self): + try: + i = self.wd[:-1].rindex('/') + self.wd = self.wd[0:i+1] + except ValueError: + self.wd = '/' + return 1 + + def listdir (self, path, long=0): + raise "Not implemented" + + # TODO: implement a cache w/timeout for stat() + def stat (self, path): + fullpath = join_paths(self.wd, path) + if self.isfile(path): + size = self.m[fullpath].file_size + return (33188, 77396L, 10L, 1, 1000, 1000, size, 0,0,0) + elif self.isdir(path): + return (16895, 117481L, 10L, 20, 1000, 1000, 4096L, 0,0,0) + else: + raise "No such file or directory "+path + + def open (self, path, mode): + class zFile: + def __init__(self, content): + self.content = content + self.pos = 0 + self.len = len(content) + def read(self,l=None): + if l is None: + l = self.len - self.pos + if self.len < self.pos + l: + l = self.len - self.pos + s = self.content[self.pos : self.pos + l] + self.pos += l + return s + def close(self): + del self.content + del self.len + del self.pos + self.lock.acquire() + try: + data = self.z.read(path) + finally: + self.lock.release() + return zFile(data) + + def unlink (self, path): + raise "Not implemented" + def mkdir (self, path): + raise "Not implemented" + def rmdir (self, path): + raise "Not implemented" + + def longify (self, (path, stat_info)): + return unix_longify (path, stat_info) + + def __repr__ (self): + return '' % (self.filename, self.wd) + + +def setBase(base): + global GLOBAL_ROOT_DIR + GLOBAL_ROOT_DIR = qualify_path(base) + +def setTempDir(tempdir): + global GLOBAL_TEMP_DIR + GLOBAL_TEMP_DIR = qualify_path(tempdir) + +def addMacroResolver(m): + global macroresolvers + macroresolvers += [m] + +def addTranslator(m): + global translators + translators += [m] + +def addFTPHandler(m): + global ftphandlers + ftphandlers += [m] + +def addContext(webpath, localpath): + global contexts + c = WebContext(webpath, localpath) + contexts += [c] + return c + +def flush(): + global contexts,translators,ftphandlers,macroresolvers,global_modules + contexts[:] = [] + translators[:] = [] + ftphandlers[:] = [] + macroresolvers[:] = [] + global_modules.clear() + _purge_all_modules() + +def addFileStore(webpath, localpaths): + global contexts + if len(webpath) and webpath[0] != '/': + webpath = "/" + webpath + c = FileStore(webpath, localpaths) + contexts += [c] + return c + +def setThreads(number): + global number_of_threads + global multithreading_enabled + if number>1: + multithreading_enabled=1 + number_of_threads=number + else: + multithreading_enabled=0 + number_of_threads=1 + +def run(port=8081): + check_date() + ph = AthanaHandler() + hs = http_server ('', port, logger_object = lg) + hs.install_handler (ph) + + if len(ftphandlers) > 0: + ftp = ftp_server (virtual_authorizer(), port=8021, logger_object=lg) + + if multithreading_enabled: + threadlist = [] + for i in range(number_of_threads): + threadlist += [thread.start_new_thread(worker_thread, (ph,))] + + while 1: + try: + asyncore.loop(timeout=0.01) + except select.error: + continue + +""" +TODO: + * session clearup + * temp directory in .cfg file +""" + +def setTempDir(path): + global GLOBAL_TEMP_DIR + GLOBAL_TEMP_DIR = path + +def mainfunction(): + global verbose,port,init_file,log_file,temp_path,multithreading_enabled,number_of_threads,GLOBAL_TEMP_DIR,contexts,lg,lgerr + os.putenv('ATHANA_VERSION',ATHANA_VERSION) + + from optparse import OptionParser + + parser = OptionParser() + + parser.add_option("-v", "--verbose", dest="verbose", help="Be more verbose", action="store_true") + parser.add_option("-q", "--quiet", dest="quiet", help="Be quiet", action="store_true") + parser.add_option("-d", "--debug", dest="debug", help="Turn on debugging", action="store_true") + parser.add_option("-p", "--port", dest="port", help="Set the port number", action="store",type="string") + parser.add_option("-i", "--init-file", dest="init", help="Set the init file to use",action="store",type="string") + parser.add_option("-l", "--log-file", dest="log", help="Set the logging file to use",action="store",type="string") + parser.add_option("-t", "--temp-path", dest="temp", help="Set the temporary directory (default: /tmp/)",action="store",type="string") + parser.add_option("-m", "--multithread", dest="multithreading_enabled", help="Enable multithreading",action="store_true") + parser.add_option("-n", "--number-of-threads", dest="threads", help="Number of threads",action="store",type="int") + parser.add_option("-T", "--talfile", dest="talfile", help="execute TAL File",action="store",type="string") + + (options, args) = parser.parse_args() + + verbose = 0 + init_file="web.cfg" + log_file=None + temp_path="/tmp/" + port=8081 + + if options.verbose != None : verbose = 2 + if options.quiet != None : verbose = 0 + if options.debug != None : verbose = 3 + if options.port != None : port = int(options.port) + if options.init != None : init_file = options.init + if options.log != None : log_file = options.log + if options.temp != None : GLOBAL_TEMP_DIR = options.temp + if options.multithreading_enabled : multithreading_enabled = 1 + if options.threads != None : number_of_threads = options.threads + + if options.talfile: + print getTAL(options.talfile, {"mynone":None}) + sys.exit(0) + + if inifile: + contexts += read_ini_file(inifile) + + if logfile is not None: + fi = open(logfile, "wb") + lg = file_logger (fi) + lgerr = lg + + print "-"*72 + if multithreading_enabled: + print "Starting Athana (%d threads)..." % number_of_threads + else: + print "Starting Athana..." + print "Init-File:",init_file + print "Log-File:",log_file + print "Temp-Path:",GLOBAL_TEMP_DIR + print "-"*72 + + run(port) + +if __name__ == '__main__': + import athana + athana.mainfunction() diff -Nru swftools-0.9.2+ds1/rendertest/testpdfs.py swftools-0.9.1/rendertest/testpdfs.py --- swftools-0.9.2+ds1/rendertest/testpdfs.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/rendertest/testpdfs.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,353 @@ +import Image +import ImageChops +import ImageFilter +import sys +import os +import traceback +from athana import getTALstr +import random +import md5 + +filenames = [] +directories = ["pdfs"] + +SWFRENDER="swfrender" +PDFTOPPM="./pdftoppm" +CONVERT="convert" +PDF2SWF="pdf2swf" + +COMPARE=["xpdf", "xpdf -C"] +OUTPUTDIR = "results.clip/" + +#COMPARE=["xpdf", PDF2SWF+" -s convertgradients"] +#OUTPUTDIR = "results.pdf2swf/" + +#COMPARE=[PDF2SWF, PDF2SWF+" --flatten"] +#OUTPUTDIR = "results.flatten/" + +counter = 1 + +def randstr(): + return md5.md5(str(random.random())).hexdigest()[0:8] + +def unlink(file): + try: + os.unlink(file) + except: + pass + +def system(command): + if ">" not in command: + if os.system(command + " > /tmp/log.txt 2>&1") & 0xff00: + error = open("/tmp/log.txt", "rb").read() + print error + return error + else: + if os.system(command) & 0xff00: + return "Unknown error in "+command + +class ConversionError: + def __init__(self, msg): + self.msg = msg + def __str__(self): + return self.msg + +class TooComplexError: + def __init__(self, msg): + self.msg = msg + def __str__(self): + return self.msg + +class BadMatch: + def __init__(self, msg): + self.msg = msg + def __str__(self): + return self.msg + +def formatException(): + s = "Exception "+str(sys.exc_info()[0]) + info = sys.exc_info()[1] + if info: + s += " "+str(info) + s += "\n" + for l in traceback.extract_tb(sys.exc_info()[2]): + s += " File \"%s\", line %d, in %s\n" % (l[0],l[1],l[2]) + s += " %s\n" % l[3] + return s + + +class PDFPage: + def __init__(self, filename, page, width, height): + self.filename = filename + self.page = page + self.rating = None + self.message = None + self.htmlmessage = None + self.file1 = None + self.file2 = None + self.file12 = None + self.html12 = None + self.htmldiff = None + self.width,self.height = width,height + + def runtool(self, cmd, filename, page, file): + if cmd.startswith("xpdf"): + unlink("/tmp/test-%06d.ppm" % page) + args = cmd[4:] + error = system(PDFTOPPM + "%s -r 72 -f %d -l %d '%s' /tmp/test" % (args, page, page, filename)) + if error: + raise ConversionError(error) + unlink(file) + error = system(CONVERT + " /tmp/test-%06d.ppm %s" % (page, file)) + if error: + raise ConversionError(error) + unlink("/tmp/test-%06d.ppm" % page) + else: + unlink("/tmp/test.swf") + unlink("svp.ps") + error = system(COMPARE[0]+ " -Q 300 -p%d '%s' -o /tmp/test.swf" % (page, filename)) + #system("mv svp.ps %s.ps" % randstr()) + if error and "supports 65536" in error: + raise TooComplexError(error) + if error: + raise ConversionError(error) + unlink(file) + error = system(SWFRENDER + " /tmp/test.swf -o %s" % file) + if error: + raise ConversionError(error) + unlink("/tmp/test.swf") + + def runtools(self, filename, page, file1, file2, file12): + + badness = 0.0 + + self.runtool(COMPARE[0], filename, page, file2) + self.runtool(COMPARE[1], filename, page, file1) + + unlink(file12) + + pic1 = Image.open(file1) + pic1.load() + self.width1 = pic1.size[0] + self.height1 = pic1.size[1] + + pic2 = Image.open(file2) + pic2.load() + self.width2 = pic2.size[0] + self.height2 = pic2.size[1] + + if abs(self.width1-self.width2)>5 or abs(self.height1!=self.height2)>5: + badness += 65536*abs(self.width2-self.width1)*max(self.height1,self.height2)+65536*abs(self.height2-self.height1)*max(self.width1,self.width2) + + minx = min(self.width1,self.width2) + miny = min(self.height1,self.height2) + + pic1 = pic1.crop((0,0,minx,miny)) + pic1 = pic1.convert("RGB") + pic1 = pic1.filter(ImageFilter.BLUR) + pic2 = pic2.crop((0,0,minx,miny)) + pic2 = pic2.convert("RGB") + pic2 = pic2.filter(ImageFilter.BLUR) + + diffimage = ImageChops.difference(pic1,pic2) + diffimage.save(file12, "PNG") + + # compute quadratical difference + diff = diffimage.histogram() + for i in range(1,128): + badness += (diff[i] + diff[256-i])*float(i*i) + badness += (diff[256+i] + diff[256+256-i])*float(i*i) + badness += (diff[512+i] + diff[512+256-i])*float(i*i) + + badness /= (minx*miny)*3 + + return badness + + def compare(self): + try: + global counter + self.file1 = str(counter) + ".png" + counter = counter + 1 + self.file2 = str(counter) + ".png" + counter = counter + 1 + self.file12 = str(counter) + ".png" + counter = counter + 1 + self.rating = self.runtools(self.filename, self.page, OUTPUTDIR + self.file1, OUTPUTDIR + self.file2, OUTPUTDIR + self.file12) + except BadMatch: + self.rating = 65534.0 + self.message = formatException() + print self.message + except ConversionError: + self.rating = 65535.0 + self.message = formatException() + print self.message + except TooComplexError: + self.rating = 65536.0 + self.message = formatException() + print self.message + except: + self.rating = 65537.0 + self.message = formatException() + print self.message + + def getsizes(self): + if self.message: + return "" + if abs(self.width1 - self.width2) > 5 or \ + abs(self.height1 - self.height2) > 5: + return '%dx%d <-> %dx%d' % (self.width1, self.height1, self.width2, self.height2) + else: + return '%dx%d,%dx%d' % (self.width1, self.height1, self.width2, self.height2) + + def generatehtml(self): + global OUTPUTDIR + global counter + self.html12 = str(counter) + ".html" + counter = counter + 1 + self.htmldiff = str(counter) + ".html" + counter = counter + 1 + fi = open(OUTPUTDIR + self.html12, "wb") + fi.write(getTALstr(""" + + +
    +
    +
    +

    +
    + + + +
    pdf2swf Versionpdftoppm Version
    +
    + +""", {"self": self})) + fi.close() + + fi = open(OUTPUTDIR + self.htmldiff, "wb") + fi.write(getTALstr(""" + + +
    +
    +
    +

    +
    + +
    + +""", {"self": self})) + fi.close() + + if self.message: + self.htmlmessage = str(counter) + ".html" + counter = counter + 1 + fi = open(OUTPUTDIR + self.htmlmessage, "wb") + fi.write(getTALstr(""" + + +
    +
    + +""", {"self": self})) + fi.close() + + + +def compare_pages(page1,page2): + if page1.rating < page2.rating: + return 1 + elif page1.rating > page2.rating: + return -1 + else: + return 0 + + +def add_directory(directory): + if not os.path.isdir(directory): + print "bad directory:",directory + return + for file in os.listdir(directory): + global filenames + filename = os.path.join(directory, file) + if file.lower().endswith(".pdf"): + filenames += [filename] + print "+",filename + elif os.path.isdir(filename): + add_directory(filename) + +pages = [] +try: + os.mkdir(OUTPUTDIR) +except: pass + +for file in filenames: + print "+",file + +for dir in directories: + add_directory(dir) + +for filename in filenames: + try: + unlink("/tmp/test.txt") + error = system(PDF2SWF + " -I %s -o /tmp/test.txt" % filename) + if error: + raise ConversionError(error) + fi = open("/tmp/test.txt", "rb") + for line in fi.readlines(): + p = {} + for param in line.split(" "): + key,value = param.split("=") + p[key] = value + page = int(p["page"]) + width = int(float(p["width"])) + height = int(float(p["height"])) + print filename, page, "%dx%d" % (width, height) + pdfpage = PDFPage(filename, page, width, height) + pdfpage.compare() + + if width < 2000 and height < 2000: + pages += [pdfpage] + + # only consider the first 3 pages + if page > 3: + break + fi.close() + except KeyboardInterrupt: + break + except: + pdfpage = PDFPage(filename, -1, -1, -1) + pdfpage.rating = 65536.0 + pdfpage.message = formatException() + pages += [pdfpage] + +pages.sort(compare_pages) + +position = 1 +for page in pages: + page.generatehtml() + page.position = position + position = position + 1 + +fi = open(OUTPUTDIR + "index.html", "wb") +fi.write(getTALstr(""" + + + + + + + + + + +
    PositionRatingFileSizePageImagesDiffFurther Info
    + + + + +Side by SideDifferenceError message
    + +""", {"pages": pages})) +fi.close() + diff -Nru swftools-0.9.2+ds1/spec/circularfill.pdf swftools-0.9.1/spec/circularfill.pdf --- swftools-0.9.2+ds1/spec/circularfill.pdf 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/circularfill.pdf 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,265 @@ +%PDF-1.6 +%äãÏÒ +1 0 obj +[/PDF/ImageB/ImageC/ImageI/Text] +endobj +4 0 obj +<> +stream +BT +/F0 18 Tf +18 TL +0 0 Td +(\(0/0\))Tj +50 0 Td +(\(50/0\))Tj +50 0 Td +(\(100/0\))Tj +50 0 Td +(\(150/0\))Tj +50 0 Td +(\(200/0\))Tj +50 0 Td +(\(250/0\))Tj +50 0 Td +(\(300/0\))Tj +50 0 Td +(\(350/0\))Tj +50 0 Td +(\(400/0\))Tj +50 0 Td +(\(450/0\))Tj +50 0 Td +(\(500/0\))Tj +50 0 Td +(\(550/0\))Tj +50 0 Td +(\(600/0\))Tj +50 0 Td +(\(650/0\))Tj +50 0 Td +(\(700/0\))Tj +50 0 Td +(\(750/0\))Tj +50 0 Td +(\(800/0\))Tj +50 0 Td +(\(850/0\))Tj +50 0 Td +(\(900/0\))Tj +50 0 Td +(\(950/0\))Tj +-950 50 Td +(\(0/50\))Tj +0 50 Td +(\(0/100\))Tj +0 50 Td +(\(0/150\))Tj +0 50 Td +(\(0/200\))Tj +0 50 Td +(\(0/250\))Tj +0 50 Td +(\(0/300\))Tj +0 50 Td +(\(0/350\))Tj +0 50 Td +(\(0/400\))Tj +0 50 Td +(\(0/450\))Tj +0 50 Td +(\(0/500\))Tj +0 50 Td +(\(0/550\))Tj +0 50 Td +(\(0/600\))Tj +0 50 Td +(\(0/650\))Tj +0 50 Td +(\(0/700\))Tj +0 50 Td +(\(0/750\))Tj +1 0 0 rg +0 0 0 RG +ET +100 150 m +500 150 l +500 550 l +100 550 l +100 150 l +300 350 m +700 350 l +700 750 l +300 750 l +300 350 l +200 250 m +200 450 l +600 450 l +600 250 l +200 250 l +250 300 m +250 500 l +650 500 l +650 300 l +250 300 l +f +100 150 m +500 150 l +500 550 l +100 550 l +100 150 l +300 350 m +700 350 l +700 750 l +300 750 l +300 350 l +200 250 m +200 450 l +600 450 l +600 250 l +200 250 l +250 300 m +250 500 l +650 500 l +650 300 l +250 300 l +S + +endstream +endobj +5 0 obj +1212 +endobj +7 0 obj +<> +>> +endobj +8 0 obj +<> +endobj +6 0 obj +<> +endobj +10 0 obj +<> +endobj +9 0 obj +<> +endobj +3 0 obj +<> +endobj +2 0 obj +<> +endobj +11 0 obj +<> +endobj +xref +0 12 +0000000000 65535 f +0000000015 00000 n +0000003442 00000 n +0000003340 00000 n +0000000063 00000 n +0000001327 00000 n +0000001593 00000 n +0000001347 00000 n +0000001402 00000 n +0000003149 00000 n +0000002764 00000 n +0000003496 00000 n +trailer +<] +>> +startxref +3544 +%%EOF diff -Nru swftools-0.9.2+ds1/spec/circularfill.spec.rb swftools-0.9.1/spec/circularfill.spec.rb --- swftools-0.9.2+ds1/spec/circularfill.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/circularfill.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,30 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + + convert_file "circularfill.pdf" do + pixel_at(194,224).should_be_of_color 0xffffff + pixel_at(169,225).should_be_of_color 0xff0000 + pixel_at(138,225).should_be_of_color 0xffffff + pixel_at(72,162).should_be_of_color 0xff0000 + pixel_at(195,132).should_be_of_color 0xff0000 + pixel_at(69,132).should_be_of_color 0xffffff + pixel_at(310,289).should_be_of_color 0xff0000 + pixel_at(287,200).should_be_of_color 0xff0000 + pixel_at(309,161).should_be_of_color 0xff0000 + pixel_at(287,161).should_be_of_color 0xff0000 + pixel_at(109,336).should_be_of_color 0xff0000 + pixel_at(310,306).should_be_of_color 0xff0000 + pixel_at(282,340).should_be_of_color 0xff0000 + pixel_at(409,252).should_be_of_color 0xff0000 + pixel_at(139,310).should_be_of_color 0xffffff + pixel_at(312,343).should_be_of_color 0xffffff + pixel_at(311,248).should_be_of_color 0xff0000 + pixel_at(102,228).should_be_of_color 0xff0000 + pixel_at(374,281).should_be_of_color 0xff0000 + pixel_at(167,281).should_be_of_color 0xff0000 + pixel_at(409,285).should_be_of_color 0xffffff + pixel_at(166,190).should_be_of_color 0xffffff + pixel_at(138,191).should_be_of_color 0xff0000 + end +end diff -Nru swftools-0.9.2+ds1/spec/clip.pdf swftools-0.9.1/spec/clip.pdf --- swftools-0.9.2+ds1/spec/clip.pdf 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/clip.pdf 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,87 @@ +%PDF-1.6 +%äãÏÒ +1 0 obj +[/PDF/ImageB/ImageC/ImageI/Text] +endobj +4 0 obj +<> +stream +0 0 0 rg +100 100 m +300 100 l +300 300 l +100 300 l +100 100 l +200 200 m +400 200 l +400 400 l +200 400 l +200 200 l +S +0 1 0 rg +100 100 m +300 100 l +300 300 l +100 300 l +100 100 l +W n +200 200 m +400 200 l +400 400 l +200 400 l +200 200 l +f + +endstream +endobj +5 0 obj +226 +endobj +6 0 obj +<> +endobj +7 0 obj +<> +endobj +3 0 obj +<> +endobj +2 0 obj +<> +endobj +8 0 obj +<> +endobj +xref +0 9 +0000000000 65535 f +0000000015 00000 n +0000000604 00000 n +0000000503 00000 n +0000000063 00000 n +0000000341 00000 n +0000000360 00000 n +0000000395 00000 n +0000000658 00000 n +trailer +<<5B9C26B0AEF0EC3336ED3CECF52AC9D0>] +>> +startxref +705 +%%EOF diff -Nru swftools-0.9.2+ds1/spec/clip.py swftools-0.9.1/spec/clip.py --- swftools-0.9.2+ds1/spec/clip.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/clip.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,46 @@ +from sys import * +from pdflib_py import * +p = PDF_new() +PDF_open_file(p, "clip.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") +PDF_set_value(p, "compress", 0) + +width = 800 +height = 800 +PDF_begin_page(p, width, height) + +PDF_setcolor(p, "fill", "rgb", 0.0, 0.0, 0.0, 0.0) +x1,y1,x2,y2 = 100,100,300,300 +PDF_moveto(p, x1,y1) +PDF_lineto(p, x2,y1) +PDF_lineto(p, x2,y2) +PDF_lineto(p, x1,y2) +PDF_lineto(p, x1,y1) +x1,y1,x2,y2 = 200,200,400,400 +PDF_moveto(p, x1,y1) +PDF_lineto(p, x2,y1) +PDF_lineto(p, x2,y2) +PDF_lineto(p, x1,y2) +PDF_lineto(p, x1,y1) +PDF_stroke(p) + +PDF_setcolor(p, "fill", "rgb", 0.0, 1.0, 0.0, 1.0) +x1,y1,x2,y2 = 100,100,300,300 +PDF_moveto(p, x1,y1) +PDF_lineto(p, x2,y1) +PDF_lineto(p, x2,y2) +PDF_lineto(p, x1,y2) +PDF_lineto(p, x1,y1) +PDF_clip(p) +x1,y1,x2,y2 = 200,200,400,400 +PDF_moveto(p, x1,y1) +PDF_lineto(p, x2,y1) +PDF_lineto(p, x2,y2) +PDF_lineto(p, x1,y2) +PDF_lineto(p, x1,y1) +PDF_fill(p) + +PDF_end_page(p) +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/clip.spec.rb swftools-0.9.1/spec/clip.spec.rb --- swftools-0.9.2+ds1/spec/clip.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/clip.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,10 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + convert_file "clip.pdf" do + pixel_at(257,354).should_be_of_color 0xffffff + pixel_at(194,419).should_be_of_color 0x00ff00 + pixel_at(116,496).should_be_of_color 0xffffff + pixel_at(109,353).should_be_of_color 0xffffff + end +end diff -Nru swftools-0.9.2+ds1/spec/edit_spec.py swftools-0.9.1/spec/edit_spec.py --- swftools-0.9.2+ds1/spec/edit_spec.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/edit_spec.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,520 @@ +#!/usr/bin/env python +import wx +import wx.lib.scrolledpanel as scrolled +import os +import re +import sys +import time +import thread +import traceback +import math + +class Check: + def __init__(self, x,y): + self.x = x + self.y = y + def left(self): + return "pixel at (%d,%d)" % (self.x,self.y) + def right(self): + return "" + def verifies(self, model): + return True + +class PixelColorCheck(Check): + def __init__(self, x,y, color): + Check.__init__(self,x,y) + self.color = color + def right(self): + return "is of color 0x%06x" % self.color + def verifies(self, model): + p = model.getPixel(self.x,self.y) + val = p[0]<<16 | p[1]<<8 | p[2] + return val == self.color + +class TwoPixelCheck(Check): + def __init__(self, x,y, x2,y2): + Check.__init__(self,x,y) + self.x2,self.y2 = x2,y2 + def right(self): + return "pixel at (%d,%d)" % (self.x2,self.y2) + +class PixelBrighterThan(TwoPixelCheck): + def verifies(self, model): + p1 = model.getPixel(self.x,self.y) + p2 = model.getPixel(self.x2,self.y2) + val1 = p1[0] + p1[1] + p1[2] + val2 = p2[0] + p2[1] + p2[2] + return val1 > val2 + +class PixelDarkerThan(TwoPixelCheck): + pass + +class PixelEqualTo(TwoPixelCheck): + pass + +class AreaCheck(Check): + def __init__(self, x,y, x2,y2): + Check.__init__(self,x,y) + self.x2,self.y2 = x2,y2 + def left(self): + return "area at (%d,%d,%d,%d)" % (self.x,self.y,self.x2,self.y2) + +class AreaPlain(AreaCheck): + pass + +class AreaNotPlain(AreaCheck): + pass + +class AreaText(AreaCheck): + def __init__(self, x,y, x2, y2, text=""): + AreaCheck.__init__(self,x,y,x2,y2) + self.text = text + +checktypes = [PixelColorCheck,PixelBrighterThan,PixelDarkerThan,PixelEqualTo,AreaPlain,AreaNotPlain,AreaText] + +global TESTMODE + +def convert_to_ppm(pdf): + print pdf + f = os.popen("pdfinfo "+pdf, "rb") + info = f.read() + f.close() + width,heigth = re.compile(r"Page size:\s*([0-9]+) x ([0-9]+) pts").findall(info)[0] + dpi = int(72.0 * 612 / int(width)) + if TESTMODE: + os.system("pdf2swf -s poly2bitmap -s zoom="+str(dpi)+" -p1 "+pdf+" -o test.swf") + os.system("swfrender --legacy test.swf -o test.png") + os.unlink("test.swf") + return "test.png" + else: + os.system("pdftoppm -r "+str(dpi)+" -f 1 -l 1 "+pdf+" test") + return "test-000001.ppm" + + +class Model: + def __init__(self, specfile, docfile, checks): + self.specfile = specfile + self.docfile = docfile + self.imgfilename = convert_to_ppm(self.docfile) + self.bitmap = wx.Bitmap(self.imgfilename) + self.image = wx.ImageFromBitmap(self.bitmap) + self.width = self.bitmap.GetWidth() + self.height = self.bitmap.GetHeight() + self.checks = checks + self.xy2check = {} + self.appendListeners = [] + self.drawModeListeners = [] + self.drawmode = PixelColorCheck + + def close(self): + try: os.unlink(self.imgfilename) + except: pass + + def getPixel(self,x,y): + return (self.image.GetRed(x,y), self.image.GetGreen(x,y), self.image.GetBlue(x,y)) + + def setdrawmode(self, mode): + self.drawmode = mode + for f in self.drawModeListeners: + f() + + def find(self, x, y): + return self.xy2check.get((x,y),None) + + def delete(self, check): + i = self.checks.index(check) + del self.checks[i] + del self.xy2check[(check.x,check.y)] + for f in self.appendListeners: + f(check) + + def append(self, check): + self.checks += [check] + self.xy2check[(check.x,check.y)] = check + for f in self.appendListeners: + f(check) + + @staticmethod + def load(filename): + # convenience, allow to do "edit_spec.py file.pdf" + p,ext = os.path.splitext(filename) + if ext!=".rb": + path = p+".rb" + if not os.path.isfile(path): + path = p+".spec.rb" + if not os.path.isfile(path): + print "No file %s found, creating new..." % path + return Model(path, filename, []) + else: + path = filename + + fi = open(path, "rb") + r_file = re.compile(r"^convert_file \"([^\"]*)\"") + r_pixelcolor = re.compile(r"^pixel_at\(([0-9]+),([0-9]+)\).should_be_of_color (0x[0-9a-fA-F]+)") + r_pixelbrighter = re.compile(r"^pixel_at\(([0-9]+),([0-9]+)\).should_be_brighter_than pixel_at\(([0-9]+),([0-9]+)\)") + r_pixeldarker = re.compile(r"^pixel_at\(([0-9]+),([0-9]+)\).should_be_darker_than pixel_at\(([0-9]+),([0-9]+)\)") + r_pixelequalto = re.compile(r"^pixel_at\(([0-9]+),([0-9]+)\).should_be_the_same_as pixel_at\(([0-9]+),([0-9]+)\)") + r_areaplain = re.compile(r"^area_at\(([0-9]+),([0-9]+),([0-9]+),([0-9]+)\).should_be_plain_colored") + r_areanotplain = re.compile(r"^area_at\(([0-9]+),([0-9]+),([0-9]+),([0-9]+)\).should_not_be_plain_colored") + r_areatext = re.compile(r"^area_at\(([0-9]+),([0-9]+),([0-9]+),([0-9]+)\).should_contain_text '(.*)'") + r_width = re.compile(r"^width.should be ([0-9]+)") + r_height = re.compile(r"^height.should be ([0-9]+)") + r_describe = re.compile(r"^describe \"pdf conversion\"") + r_header = re.compile(r"^require File.dirname") + r_end = re.compile(r"^end$") + filename = None + checks = [] + for nr,line in enumerate(fi.readlines()): + line = line.strip() + if not line: + continue + m = r_file.match(line) + if m: + if filename: + raise Exception("can't load multi-file specs (in line %d)" % (nr+1)) + filename = m.group(1); + model = Model(path, filename, []) + continue + m = r_pixelcolor.match(line) + if m: model.append(PixelColorCheck(int(m.group(1)),int(m.group(2)),int(m.group(3),16)));continue + m = r_pixelbrighter.match(line) + if m: model.append(PixelBrighterThan(int(m.group(1)),int(m.group(2)),int(m.group(3)),int(m.group(4))));continue + m = r_pixeldarker.match(line) + if m: model.append(PixelDarkerThan(int(m.group(1)),int(m.group(2)),int(m.group(3)),int(m.group(4))));continue + m = r_pixelequalto.match(line) + if m: model.append(PixelEqualTo(int(m.group(1)),int(m.group(2)),int(m.group(3)),int(m.group(4))));continue + m = r_areaplain.match(line) + if m: model.append(AreaPlain(int(m.group(1)),int(m.group(2)),int(m.group(3)),int(m.group(4))));continue + m = r_areanotplain.match(line) + if m: model.append(AreaNotPlain(int(m.group(1)),int(m.group(2)),int(m.group(3)),int(m.group(4))));continue + m = r_areatext.match(line) + if m: model.append(AreaText(int(m.group(1)),int(m.group(2)),int(m.group(3)),int(m.group(4)),m.group(5)));continue + if r_width.match(line) or r_height.match(line): + continue # compatibility + if r_describe.match(line) or r_end.match(line) or r_header.match(line): + continue + print line + raise Exception("invalid file format: can't load this file (in line %d)" % (nr+1)) + + fi.close() + return model + + def save(self): + path = self.specfile + fi = open(path, "wb") + fi.write("require File.dirname(__FILE__) + '/spec_helper'\n\ndescribe \"pdf conversion\" do\n") + fi.write(" convert_file \"%s\" do\n" % self.docfile) + for check in self.checks: + c = check.__class__ + if c == PixelColorCheck: + fi.write(" pixel_at(%d,%d).should_be_of_color 0x%06x\n" % (check.x,check.y,check.color)) + elif c == PixelBrighterThan: + fi.write(" pixel_at(%d,%d).should_be_brighter_than pixel_at(%d,%d)\n" % (check.x,check.y,check.x2,check.y2)) + elif c == PixelDarkerThan: + fi.write(" pixel_at(%d,%d).should_be_darker_than pixel_at(%d,%d)\n" % (check.x,check.y,check.x2,check.y2)) + elif c == PixelEqualTo: + fi.write(" pixel_at(%d,%d).should_be_the_same_as pixel_at(%d,%d)\n" % (check.x,check.y,check.x2,check.y2)) + elif c == AreaPlain: + fi.write(" area_at(%d,%d,%d,%d).should_be_plain_colored\n" % (check.x,check.y,check.x2,check.y2)) + elif c == AreaNotPlain: + fi.write(" area_at(%d,%d,%d,%d).should_not_be_plain_colored\n" % (check.x,check.y,check.x2,check.y2)) + elif c == AreaText: + fi.write(" area_at(%d,%d,%d,%d).should_contain_text '%s'\n" % (check.x,check.y,check.x2,check.y2,check.text)) + fi.write(" end\n") + fi.write("end\n") + fi.close() + +class ZoomWindow(wx.Window): + def __init__(self, parent, model): + wx.Window.__init__(self, parent, pos=(0,0), size=(15*32,15*32)) + self.model = model + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.x = 0 + self.y = 0 + + def setpos(self,x,y): + self.x = x + self.y = y + self.Refresh() + + def OnPaint(self, event): + dc = wx.PaintDC(self) + self.Draw(dc) + + def Draw(self,dc=None): + if not dc: + dc = wx.ClientDC(self) + dc.SetBackground(wx.Brush((0,0,0))) + color = (0,255,0) + for yy in range(15): + y = self.y+yy-8 + for xx in range(15): + x = self.x+xx-8 + if 0<=x> +endobj +7 0 obj +<< +/Type /Encoding +/Differences [0 /.notdef /.notdef /.notdef 128 /.notdef 130 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 142 /.notdef 145 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 158 /.notdef /.notdef /space 173 /hyphen] +/BaseEncoding /WinAnsiEncoding +>> +endobj +5 0 obj +<< +/BaseFont /Courier +/Subtype /Type1 +/FontDescriptor 6 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +9 0 obj +<< +/FontName /Helvetica-BoldOblique +/StemV 166 +/Ascent 718 +/Flags 262240 +/XHeight 532 +/Descent -207 +/ItalicAngle -12 +/FontBBox [-560 -376 1157 1000] +/Type /FontDescriptor +/CapHeight 718 +>> +endobj +8 0 obj +<< +/BaseFont /Helvetica-BoldOblique +/Subtype /Type1 +/FontDescriptor 9 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +11 0 obj +<< +/FontName /Helvetica-Bold +/StemV 166 +/Ascent 718 +/Flags 262176 +/XHeight 532 +/Descent -207 +/ItalicAngle 0 +/FontBBox [-628 -376 2000 1010] +/Type /FontDescriptor +/CapHeight 718 +>> +endobj +10 0 obj +<< +/BaseFont /Helvetica-Bold +/Subtype /Type1 +/FontDescriptor 11 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +13 0 obj +<< +/FontName /Helvetica-Oblique +/StemV 88 +/Ascent 718 +/Flags 96 +/XHeight 523 +/Descent -207 +/ItalicAngle -12 +/FontBBox [-517 -325 1082 998] +/Type /FontDescriptor +/CapHeight 718 +>> +endobj +12 0 obj +<< +/BaseFont /Helvetica-Oblique +/Subtype /Type1 +/FontDescriptor 13 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +15 0 obj +<< +/FontName /Helvetica +/StemV 88 +/Ascent 718 +/Flags 32 +/XHeight 523 +/Descent -207 +/ItalicAngle 0 +/FontBBox [-665 -325 2028 1037] +/Type /FontDescriptor +/CapHeight 718 +>> +endobj +14 0 obj +<< +/BaseFont /Helvetica +/Subtype /Type1 +/FontDescriptor 15 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +17 0 obj +<< +/FontName /Times-BoldItalic +/StemV 166 +/Ascent 683 +/Flags 262240 +/XHeight 462 +/Descent -217 +/ItalicAngle -16 +/FontBBox [-547 -307 1206 1032] +/Type /FontDescriptor +/CapHeight 669 +>> +endobj +16 0 obj +<< +/BaseFont /Times-BoldItalic +/Subtype /Type1 +/FontDescriptor 17 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +19 0 obj +<< +/FontName /Times-Bold +/StemV 166 +/Ascent 683 +/Flags 262176 +/XHeight 461 +/Descent -217 +/ItalicAngle 0 +/FontBBox [-558 -307 2000 1026] +/Type /FontDescriptor +/CapHeight 676 +>> +endobj +18 0 obj +<< +/BaseFont /Times-Bold +/Subtype /Type1 +/FontDescriptor 19 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +21 0 obj +<< +/FontName /Times-Italic +/StemV 88 +/Ascent 683 +/Flags 96 +/XHeight 441 +/Descent -217 +/ItalicAngle -16 +/FontBBox [-498 -307 1120 1023] +/Type /FontDescriptor +/CapHeight 653 +>> +endobj +20 0 obj +<< +/BaseFont /Times-Italic +/Subtype /Type1 +/FontDescriptor 21 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +23 0 obj +<< +/FontName /Courier-BoldOblique +/StemV 166 +/Ascent 627 +/Flags 262243 +/XHeight 435 +/Descent -373 +/ItalicAngle -11 +/FontBBox [-48 -250 757 854] +/Type /FontDescriptor +/CapHeight 573 +>> +endobj +22 0 obj +<< +/BaseFont /Courier-BoldOblique +/Subtype /Type1 +/FontDescriptor 23 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +25 0 obj +<< +/FontName /Times-Roman +/StemV 88 +/Ascent 683 +/Flags 32 +/XHeight 450 +/Descent -217 +/ItalicAngle 0 +/FontBBox [-568 -307 2000 1007] +/Type /FontDescriptor +/CapHeight 662 +>> +endobj +24 0 obj +<< +/BaseFont /Times-Roman +/Subtype /Type1 +/FontDescriptor 25 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +27 0 obj +<< +/FontName /Courier-Bold +/StemV 166 +/Ascent 627 +/Flags 262179 +/XHeight 435 +/Descent -373 +/ItalicAngle 0 +/FontBBox [-88 -250 697 854] +/Type /FontDescriptor +/CapHeight 573 +>> +endobj +26 0 obj +<< +/BaseFont /Courier-Bold +/Subtype /Type1 +/FontDescriptor 27 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +30 0 obj [/PDF /ImageB /ImageC /ImageI /Text] +endobj +29 0 obj +<< +/ProcSet 30 0 R +>> +endobj +31 0 obj +<< +/Type /Encoding +/Differences [0 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /P /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /e /f /g /.notdef /i /.notdef /.notdef /l /.notdef /.notdef /o /p /.notdef /r /s /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /z /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef] +>> +endobj +33 0 obj +<< +/Length 247 +>> +stream +354 0 8 0 374 738 d1 +10 w +8 0 m +374 730 m +348 736 320 738 293 738 c +157 738 95 672 95 537 c +95 497 l +8 497 l +8 398 l +95 398 l +95 0 l +222 0 l +222 398 l +338 398 l +338 497 l +222 497 l +222 539 l +222 605 247 634 303 634 c +322 634 345 632 365 625 c +h +S + +endstream +endobj +34 0 obj +<< +/Length 145 +>> +stream +258 0 47 -12 210 152 d1 +10 w +47 0 m +129 152 m +84 152 47 115 47 70 c +47 25 84 -12 129 -12 c +174 -12 210 25 210 70 c +210 115 174 152 129 152 c +h +S + +endstream +endobj +35 0 obj +<< +/Length 319 +>> +stream +558 0 35 -11 488 730 d1 +10 w +35 0 m +488 0 m +488 730 l +361 730 l +361 502 l +339 505 319 506 298 506 c +133 506 35 390 35 222 c +35 80 95 -11 216 -11 c +292 -11 347 28 373 83 c +375 83 l +371 56 369 24 369 0 c +h +361 258 m +361 173 321 95 254 95 c +196 95 169 143 169 236 c +169 359 221 405 294 405 c +316 405 338 402 361 397 c +h +S + +endstream +endobj +36 0 obj +<< +/Length 266 +>> +stream +425 0 34 -9 394 506 d1 +10 w +34 0 m +394 14 m +384 123 l +357 109 320 102 286 102 c +201 102 168 160 168 245 c +168 339 209 399 290 399 c +322 399 353 391 380 381 c +393 492 l +361 501 325 506 291 506 c +115 506 34 387 34 232 c +34 63 120 -9 258 -9 c +311 -9 360 1 394 14 c +h +S + +endstream +endobj +37 0 obj +<< +/Length 338 +>> +stream +559 0 69 -10 523 730 d1 +10 w +69 0 m +523 274 m +523 421 459 507 340 507 c +271 507 215 473 190 419 c +189 419 l +194 445 197 486 197 516 c +197 730 l +69 730 l +69 14 l +126 -2 182 -10 254 -10 c +425 -10 523 106 523 274 c +h +389 261 m +389 138 336 92 264 92 c +236 92 215 95 197 101 c +197 241 l +197 324 237 401 304 401 c +362 401 389 354 389 261 c +h +S + +endstream +endobj +38 0 obj +<< +/Length 342 +>> +stream +796 0 9 0 786 497 d1 +10 w +9 0 m +786 497 m +655 497 l +599 303 l +584 254 574 210 564 159 c +562 159 l +552 208 540 252 522 309 c +461 497 l +338 497 l +278 303 l +264 259 252 214 242 159 c +241 159 l +229 210 215 260 202 309 c +149 497 l +9 497 l +161 0 l +293 0 l +356 207 l +369 248 380 286 390 332 c +391 332 l +400 290 408 255 419 221 c +491 0 l +630 0 l +h +S + +endstream +endobj +39 0 obj +<< +/Length 15 +>> +stream +0 0 0 0 0 0 d1 + +endstream +endobj +40 0 obj +<< +/Length 348 +>> +stream +559 0 69 -241 523 507 d1 +10 w +69 0 m +523 275 m +523 422 459 507 341 507 c +266 507 213 472 185 414 c +183 414 l +187 440 188 473 188 497 c +69 497 l +69 -241 l +197 -241 l +197 -3 l +218 -6 237 -7 261 -7 c +433 -7 523 102 523 275 c +h +389 261 m +389 138 336 92 264 92 c +238 92 217 95 197 101 c +197 239 l +197 324 237 402 304 402 c +362 402 389 354 389 261 c +h +S + +endstream +endobj +41 0 obj +<< +/Length 263 +>> +stream +553 0 33 -10 519 507 d1 +10 w +33 0 m +519 258 m +519 429 428 507 287 507 c +136 507 33 395 33 240 c +33 63 124 -10 265 -10 c +414 -10 519 102 519 258 c +h +387 251 m +387 150 339 99 276 99 c +202 99 165 151 165 253 c +165 355 221 399 278 399 c +353 399 387 347 387 251 c +h +S + +endstream +endobj +42 0 obj +<< +/Length 368 +>> +stream +866 0 69 0 797 508 d1 +10 w +69 0 m +797 0 m +797 342 l +797 455 744 508 648 508 c +564 508 509 457 486 408 c +474 456 437 508 349 508 c +275 508 215 469 185 408 c +183 408 l +188 437 190 474 190 497 c +69 497 l +69 0 l +197 0 l +197 238 l +197 331 252 401 311 401 c +360 401 370 364 370 315 c +370 0 l +496 0 l +496 238 l +496 335 554 401 610 401 c +657 401 669 368 669 315 c +669 0 l +h +S + +endstream +endobj +43 0 obj +<< +/Length 72 +>> +stream +266 0 69 0 197 730 d1 +10 w +69 0 m +197 0 m +197 730 l +69 730 l +69 0 l +h +S + +endstream +endobj +44 0 obj +<< +/Length 183 +>> +stream +266 0 54 0 213 716 d1 +10 w +54 0 m +213 639 m +213 682 177 716 133 716 c +89 716 54 681 54 639 c +54 596 89 561 133 561 c +177 561 213 596 213 639 c +h +197 0 m +197 497 l +69 497 l +69 0 l +h +S + +endstream +endobj +32 0 obj +<< +/i 33 0 R +/P 34 0 R +/g 35 0 R +/f 36 0 R +/e 37 0 R +/z 38 0 R +/.notdef 39 0 R +/s 40 0 R +/r 41 0 R +/p 42 0 R +/o 43 0 R +/l 44 0 R +>> +endobj +28 0 obj +<< +/FontMatrix [0.001 0 0 0.001 0 0] +/FirstChar 80 +/Resources 29 0 R +/Encoding 31 0 R +/Name /www.pdflib.com +/CharProcs 32 0 R +/Subtype /Type3 +/LastChar 122 +/FontBBox [0 -241 797 738] +/Type /Font +/Widths [258 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 559 425 558 0 354 0 0 266 0 0 266 866 0 553 559 0 0 0 0 0 0 796] +>> +endobj +46 0 obj +<< +/FontName /Courier-Oblique +/StemV 109 +/Ascent 627 +/Flags 99 +/XHeight 435 +/Descent -373 +/ItalicAngle -11 +/FontBBox [-48 -250 748 857] +/Type /FontDescriptor +/CapHeight 573 +>> +endobj +45 0 obj +<< +/BaseFont /Courier-Oblique +/Subtype /Type1 +/FontDescriptor 46 0 R +/Type /Font +/Encoding 7 0 R +>> +endobj +4 0 obj +<< +/Font +<< +/F9 5 0 R +/F8 8 0 R +/F7 10 0 R +/F6 12 0 R +/F5 14 0 R +/F4 16 0 R +/F3 18 0 R +/F2 20 0 R +/F1 24 0 R +/F12 22 0 R +/F0 28 0 R +/F11 26 0 R +/F10 45 0 R +>> +/ProcSet 30 0 R +>> +endobj +47 0 obj +<< +/Length 55139 +>> +stream +q +BT +/F4 14.3782 Tf +14.3782 TL +0 4.8109 Td +(mailie )Tj +/F4 10.2732 Tf +10.2732 TL +40.3453 2.0525 Td +(saxifragous )Tj +/F5 14.4485 Tf +14.4485 TL +52.2291 -2.0876 Td +(isoemodin )Tj +/F4 18.1148 Tf +18.1148 TL +69.8583 -1.8332 Td +(outflanking )Tj +/F4 13.7834 Tf +13.7834 TL +92.1139 2.1657 Td +(hypergol )Tj +/F4 18.5501 Tf +18.5501 TL +53.2177 -2.3833 Td +(correction )Tj +/F8 21.3124 Tf +21.3124 TL +82.956 -1.3811 Td +(putidly )Tj +/F1 13.4032 Tf +13.4032 TL +75.7868 3.9546 Td +(verbification )Tj +/F9 15.867 Tf +15.867 TL +71.8412 -1.2319 Td +(bronchus )Tj +/F10 22.8593 Tf +22.8593 TL +-538.3483 20.5039 Td +(trantlum )Tj +/F1 15.3823 Tf +15.3823 TL +123.4402 3.7385 Td +(arcuately )Tj +/F1 22.2612 Tf +22.2612 TL +60.2219 -3.4394 Td +(Episcopalianism )Tj +/F5 18.1517 Tf +18.1517 TL +152.7342 2.0548 Td +(blackwash )Tj +/F3 16.6152 Tf +16.6152 TL +89.7781 0.7682 Td +(semihexagon )Tj +/F1 22.1035 Tf +22.1035 TL +95.5376 -2.7441 Td +(sporangiferous )Tj +/F4 13.7163 Tf +13.7163 TL +-521.712 28.1936 Td +(sumptuosity )Tj +/F12 14.2424 Tf +14.2424 TL +71.2699 -0.2631 Td +(larcenic )Tj +/F9 20.5874 Tf +20.5874 TL +76.9091 -3.1725 Td +(Porokoto )Tj +/F11 15.4918 Tf +15.4918 TL +111.1718 2.5478 Td +(redound )Tj +/F2 15.0849 Tf +15.0849 TL +74.3608 0.2035 Td +(chloroplatinic )Tj +/F7 21.5262 Tf +21.5262 TL +89.2575 -3.2207 Td +(scerne )Tj +/F11 21.0694 Tf +21.0694 TL +75.3849 0.2284 Td +(carone )Tj +/F2 11.8468 Tf +11.8468 TL +88.4914 4.6113 Td +(hatching )Tj +/F1 16.6858 Tf +16.6858 TL +-586.8455 21.5805 Td +(animistic )Tj +/F10 18.9121 Tf +18.9121 TL +65.3584 -1.1131 Td +(techous )Tj +/F7 17.7284 Tf +17.7284 TL +90.7781 0.5918 Td +(orchesography )Tj +/F5 14.7378 Tf +14.7378 TL +132.9988 1.4953 Td +(nonbacterial )Tj +/F10 15.7752 Tf +15.7752 TL +84.3737 -0.5187 Td +(archprelatical )Tj +/F4 10.8735 Tf +10.8735 TL +141.9766 2.4508 Td +(indefective )Tj +/F1 22.0872 Tf +22.0872 TL +51.0294 -5.6068 Td +(knickknack )Tj +/F5 23.4895 Tf +23.4895 TL +-566.515 23.2988 Td +(septuagenarianism )Tj +/F1 15.3516 Tf +15.3516 TL +204.9697 4.069 Td +(disimmure )Tj +/F1 21.3073 Tf +21.3073 TL +69.512 -2.9778 Td +(Berberian )Tj +/F9 18.021 Tf +18.021 TL +89.3414 1.6431 Td +(hexis )Tj +/F7 11.2241 Tf +11.2241 TL +64.8755 3.3984 Td +(Ismailite )Tj +/F9 21.8417 Tf +21.8417 TL +48.0391 -5.3088 Td +(unappendaged )Tj +/F4 20.695 Tf +20.695 TL +-476.7376 24.5734 Td +(vrother )Tj +/F10 14.3478 Tf +14.3478 TL +67.2586 3.1736 Td +(ringtoss )Tj +/F5 11.4464 Tf +11.4464 TL +77.4779 1.4507 Td +(gillyflower )Tj +/F7 20.1892 Tf +20.1892 TL +53.4202 -4.3714 Td +(dumortierite )Tj +/F5 15.727 Tf +15.727 TL +123.3962 2.2311 Td +(actinozoon )Tj +/F2 12.156 Tf +12.156 TL +80.4276 1.7855 Td +(Polonia )Tj +/F8 15.4351 Tf +15.4351 TL +41.5369 -1.6396 Td +(magma )Tj +/F12 12.1788 Tf +12.1788 TL +58.3293 1.6282 Td +(unmedicinal )Tj +/F8 17.1513 Tf +17.1513 TL +87.6871 -2.4863 Td +(faunlike )Tj +/F8 17.4484 Tf +17.4484 TL +-589.5339 23.8514 Td +(pajahuello )Tj +/F9 18.3396 Tf +18.3396 TL +91.1507 -0.4456 Td +(unrecreating )Tj +/F5 19.3721 Tf +19.3721 TL +143.0492 -0.5162 Td +(flowerist )Tj +/F9 20.1012 Tf +20.1012 TL +76.423 -0.3646 Td +(Gonzalo )Tj +/F12 11.4439 Tf +11.4439 TL +96.4859 4.3287 Td +(Deuteronomical )Tj +/F9 23.7968 Tf +23.7968 TL +102.9953 -6.1764 Td +(hyperpurist )Tj +/F6 14.1282 Tf +14.1282 TL +-510.1041 28.8343 Td +(disproportionalness )Tj +/F2 11.9556 Tf +11.9556 TL +126.4191 1.0863 Td +(glycerinate )Tj +/F9 10.0702 Tf +10.0702 TL +56.7772 0.9427 Td +(nonlegal )Tj +/F5 23.1452 Tf +23.1452 TL +54.3791 -6.5375 Td +(repursue )Tj +/F10 10.6421 Tf +10.6421 TL +97.7654 6.2515 Td +(spareness )Tj +/F7 10.7309 Tf +10.7309 TL +63.8528 -0.0444 Td +(jacko )Tj +/F9 15.8468 Tf +15.8468 TL +30.4221 -2.558 Td +(ilmenorutile )Tj +/F10 16.0637 Tf +16.0637 TL +123.6052 -0.1085 Td +(nontextual )Tj +/F4 18.8217 Tf +18.8217 TL +-553.2208 22.621 Td +(Trachylinae )Tj +/F2 18.6107 Tf +18.6107 TL +98.814 0.1055 Td +(forwean )Tj +/F9 16.8599 Tf +16.8599 TL +65.6586 0.8754 Td +(monoptic )Tj +/F3 23.1234 Tf +23.1234 TL +91.0437 -3.1317 Td +(quintupliribbed )Tj +/F3 21.8652 Tf +21.8652 TL +162.5804 0.6291 Td +(debasedness )Tj +/F4 10.3957 Tf +10.3957 TL +119.6684 5.7348 Td +(cringing )Tj +/F3 11.4377 Tf +11.4377 TL +38.9942 -0.521 Td +(fortifyingly )Tj +/F4 13.7119 Tf +13.7119 TL +-576.7593 22.8629 Td +(Diadochian )Tj +/F12 13.6032 Tf +13.6032 TL +69.7115 0.0543 Td +(lutanist )Tj +/F4 14.8369 Tf +14.8369 TL +73.4575 -0.6168 Td +(arbitral )Tj +/F11 23.4953 Tf +23.4953 TL +49.8816 -4.3292 Td +(prefriendly )Tj +/F9 23.4155 Tf +23.4155 TL +169.1664 0.0399 Td +(Megachile )Tj +/F8 19.0183 Tf +19.0183 TL +140.4928 2.1986 Td +(lymphocytomatosis )Tj +/F9 18.471 Tf +18.471 TL +-502.7097 24.2737 Td +(irreparability )Tj +/F6 10.8041 Tf +10.8041 TL +166.2386 3.8334 Td +(azofy )Tj +/F11 23.6353 Tf +23.6353 TL +28.8252 -6.4156 Td +(multiengined )Tj +/F1 11.9967 Tf +11.9967 TL +184.3551 5.8193 Td +(incantatory )Tj +/F4 23.5625 Tf +23.5625 TL +56.9721 -5.7829 Td +(recurringly )Tj +/F10 18.0436 Tf +18.0436 TL +115.857 2.7595 Td +(bushmaker )Tj +/F8 17.8201 Tf +17.8201 TL +-552.2481 24.1118 Td +(bivittate )Tj +/F6 22.2513 Tf +22.2513 TL +73.2761 -2.2156 Td +(nevo )Tj +/F6 10.3122 Tf +10.3122 TL +54.4266 5.9695 Td +(sporting )Tj +/F5 20.8312 Tf +20.8312 TL +39.5472 -5.2595 Td +(permutational )Tj +/F7 11.7884 Tf +11.7884 TL +131.9863 4.5214 Td +(adenophthalmia )Tj +/F3 14.5035 Tf +14.5035 TL +93.6706 -1.3575 Td +(indignant )Tj +/F12 21.0729 Tf +21.0729 TL +63.2786 -3.2847 Td +(beguilingly )Tj +/F1 11.5395 Tf +11.5395 TL +151.7246 4.7667 Td +(locality )Tj +/F6 13.2095 Tf +13.2095 TL +-607.9101 23.165 Td +(yeukieness )Tj +/F1 12.3083 Tf +12.3083 TL +69.7464 0.4506 Td +(dashmaker )Tj +/F4 20.543 Tf +20.543 TL +56.3966 -4.1174 Td +(lymphangiectasis )Tj +/F11 21.5778 Tf +21.5778 TL +151.2379 -0.5174 Td +(paroemiac )Tj +/F7 14.5447 Tf +14.5447 TL +129.4669 3.5165 Td +(vermiformis )Tj +/F7 23.2277 Tf +23.2277 TL +87.2975 -4.3415 Td +(tyee )Tj +/F5 14.4508 Tf +14.4508 TL +52.936 4.3885 Td +(chartometer )Tj +/F10 22.7641 Tf +22.7641 TL +-547.0812 19.8433 Td +(gridelin )Tj +/F8 19.7225 Tf +19.7225 TL +122.9263 1.5208 Td +(Yezidi )Tj +/F6 16.8042 Tf +16.8042 TL +62.4809 1.4592 Td +(fendillation )Tj +/F4 22.502 Tf +22.502 TL +84.9954 -2.8489 Td +(sexualism )Tj +/F10 13.606 Tf +13.606 TL +98.1539 4.448 Td +(derogatory )Tj +/F8 18.6483 Tf +18.6483 TL +89.7994 -2.5212 Td +(uningenious )Tj +/F6 14.4391 Tf +14.4391 TL +116.0483 2.1046 Td +(bemaddening )Tj +/F6 20.1381 Tf +20.1381 TL +-574.4043 21.1505 Td +(cutin )Tj +/F1 12.0884 Tf +12.0884 TL +48.13 4.0248 Td +(boomless )Tj +/F6 14.8846 Tf +14.8846 TL +48.692 -1.3981 Td +(undisappointing )Tj +/F5 13.2836 Tf +13.2836 TL +108.3897 0.8005 Td +(setwork )Tj +/F6 18.8077 Tf +18.8077 TL +49.4549 -2.762 Td +(Strombidae )Tj +/F2 18.7695 Tf +18.7695 TL +101.3921 0.0191 Td +(unburden )Tj +/F11 20.5444 Tf +20.5444 TL +76.6358 -0.8875 Td +(uncram )Tj +/F5 21.6857 Tf +21.6857 TL +86.2867 -0.5706 Td +(overproductive )Tj +/F7 10.4408 Tf +10.4408 TL +-518.9812 29.6224 Td +(trapezial )Tj +/F5 14.6959 Tf +14.6959 TL +45.261 -2.1275 Td +(unrepentantly )Tj +/F8 17.649 Tf +17.649 TL +93.1279 -1.4765 Td +(antibody )Tj +/F1 10.4128 Tf +10.4128 TL +78.4497 3.6181 Td +(photosynthesize )Tj +/F5 16.7868 Tf +16.7868 TL +69.7034 -3.187 Td +(nonmental )Tj +/F1 18.2555 Tf +18.2555 TL +83.0444 -0.7343 Td +(narrow )Tj +/F8 13.9391 Tf +13.9391 TL +56.2635 2.1582 Td +(disinvigorate )Tj +/F1 20.936 Tf +20.936 TL +90.6322 -3.4985 Td +(auxiliator )Tj +/F6 17.752 Tf +17.752 TL +85.4818 1.592 Td +(dimethylamino )Tj +/F7 12.8677 Tf +12.8677 TL +-601.964 26.4422 Td +(venerational )Tj +/F4 18.8735 Tf +18.8735 TL +79.381 -3.0029 Td +(semifused )Tj +/F6 19.5648 Tf +19.5648 TL +82.3072 -0.3456 Td +(eudaemonism )Tj +/F11 15.4429 Tf +15.4429 TL +128.3058 2.0609 Td +(tranquillization )Tj +/F9 20.6041 Tf +20.6041 TL +157.518 -2.5806 Td +(Sabazios )Tj +/F5 14.5048 Tf +14.5048 TL +111.2623 3.0496 Td +(redictation )Tj +/F3 10.6075 Tf +10.6075 TL +-558.7743 25.9487 Td +(detrimentally )Tj +/F2 16.5422 Tf +16.5422 TL +63.9316 -2.9673 Td +(exoplasm )Tj +/F10 20.3362 Tf +20.3362 TL +66.6155 -1.897 Td +(learn )Tj +/F8 14.6686 Tf +14.6686 TL +73.2102 2.8338 Td +(merozoite )Tj +/F2 20.2352 Tf +20.2352 TL +73.3576 -2.7833 Td +(misthrift )Tj +/F2 18.3608 Tf +18.3608 TL +73.6563 0.9372 Td +(holomorphic )Tj +/F3 19.9976 Tf +19.9976 TL +98.4324 -0.8184 Td +(uninsulated )Tj +/F5 14.9828 Tf +14.9828 TL +105.0274 2.5074 Td +(erythrochroism )Tj +/F12 10.2373 Tf +10.2373 TL +-554.231 26.3728 Td +(benet )Tj +/F11 23.0183 Tf +23.0183 TL +36.8543 -6.3905 Td +(plastid )Tj +/F6 22.2963 Tf +22.2963 TL +110.4876 0.361 Td +(nasoethmoidal )Tj +/F11 19.2091 Tf +19.2091 TL +151.191 1.5436 Td +(unproportionableness )Tj +/F2 16.2711 Tf +16.2711 TL +242.0342 1.469 Td +(gaudless )Tj +/F7 22.7525 Tf +22.7525 TL +61.0165 -3.2407 Td +(backfatter )Tj +/F10 11.7162 Tf +11.7162 TL +-601.5835 29.5182 Td +(nonextortion )Tj +/F3 16.3524 Tf +16.3524 TL +91.386 -2.3181 Td +(runtee )Tj +/F9 13.1545 Tf +13.1545 TL +49.4988 1.5989 Td +(clochan )Tj +/F7 10.0172 Tf +10.0172 TL +63.1418 1.5687 Td +(marplotry )Tj +/F6 23.0242 Tf +23.0242 TL +48.984 -6.5035 Td +(taxiarch )Tj +/F12 15.7064 Tf +15.7064 TL +87.0083 3.6589 Td +(bradawl )Tj +/F7 17.0573 Tf +17.0573 TL +75.3905 -0.6755 Td +(sambal )Tj +/F8 10.6833 Tf +10.6833 TL +63.5214 3.187 Td +(orthopteron )Tj +/F5 10.5417 Tf +10.5417 TL +63.5013 0.0708 Td +(aptitude )Tj +/F3 17.6711 Tf +17.6711 TL +40.4381 -3.5647 Td +(soreheaded )Tj +/F9 14.9084 Tf +14.9084 TL +-582.8703 25.3813 Td +(convolvulinolic )Tj +/F6 10.93 Tf +10.93 TL +143.1208 1.9892 Td +(bumbarge )Tj +/F12 12.4611 Tf +12.4611 TL +52.2453 -0.7656 Td +(uncolonize )Tj +/F8 23.2811 Tf +23.2811 TL +82.2435 -5.41 Td +(castorite )Tj +/F12 12.1928 Tf +12.1928 TL +103.5076 5.5441 Td +(unsubjectlike )Tj +/F1 15.2943 Tf +15.2943 TL +102.4195 -1.5507 Td +(Geisenheimer )Tj +/F11 22.9033 Tf +22.9033 TL +88.7679 -3.8045 Td +(unjealoused )Tj +/F7 21.5597 Tf +21.5597 TL +-572.3046 24.6718 Td +(saccoderm )Tj +/F3 19.2421 Tf +19.2421 TL +119.8287 1.1588 Td +(Pseudechis )Tj +/F11 20.7097 Tf +20.7097 TL +94.6135 -0.7338 Td +(reafford )Tj +/F1 20.3324 Tf +20.3324 TL +111.8325 0.1887 Td +(holour )Tj +/F11 12.9625 Tf +12.9625 TL +58.171 3.685 Td +(jestproof )Tj +/F12 15.9659 Tf +15.9659 TL +77.7748 -1.5017 Td +(subhouse )Tj +/F11 11.789 Tf +11.789 TL +86.2161 2.0885 Td +(upsit )Tj +/F11 20.7082 Tf +20.7082 TL +42.4405 -4.4596 Td +(interfuse )Tj +/F10 13.2026 Tf +13.2026 TL +-590.8772 27.7528 Td +(thalassic )Tj +/F10 19.7599 Tf +19.7599 TL +79.2159 -3.2786 Td +(Pinna )Tj +/F2 19.8677 Tf +19.8677 TL +71.1358 -0.0539 Td +(Balthasar )Tj +/F10 16.2424 Tf +16.2424 TL +83.3449 1.8126 Td +(impeccably )Tj +/F9 13.6588 Tf +13.6588 TL +107.1997 1.2918 Td +(gigunu )Tj +/F9 20.9404 Tf +20.9404 TL +57.3668 -3.6408 Td +(bachelorhood )Tj +/F9 20.0018 Tf +20.0018 TL +163.3354 0.4693 Td +(Orakzai )Tj +/F7 12.432 Tf +12.432 TL +-561.5984 27.7849 Td +(soapbush )Tj +/F3 14.4708 Tf +14.4708 TL +62.1723 -1.0194 Td +(rota )Tj +/F1 16.8378 Tf +16.8378 TL +29.3324 -1.1835 Td +(reimmersion )Tj +/F12 11.3967 Tf +11.3967 TL +89.3243 2.7205 Td +(muddleproof )Tj +/F8 22.4429 Tf +22.4429 TL +82.0562 -5.5231 Td +(viscidize )Tj +/F2 18.5884 Tf +18.5884 TL +99.8037 1.9273 Td +(Geothlypis )Tj +/F8 10.6194 Tf +10.6194 TL +85.1906 3.9845 Td +(Nice )Tj +/F4 13.9043 Tf +13.9043 TL +25.3803 -1.6425 Td +(polypinnate )Tj +/F8 21.6554 Tf +21.6554 TL +70.6895 -3.8755 Td +(impenetrate )Tj +/F4 18.543 Tf +18.543 TL +-543.9492 25.5562 Td +(brambly )Tj +/F10 14.6981 Tf +14.6981 TL +67.4779 1.9224 Td +(disappointingness )Tj +/F12 12.4139 Tf +12.4139 TL +158.7398 1.1421 Td +(polycycly )Tj +/F6 14.8686 Tf +14.8686 TL +74.4832 -1.2273 Td +(flob )Tj +/F6 23.907 Tf +23.907 TL +28.1016 -4.5192 Td +(hepatorrhagia )Tj +/F9 13.5079 Tf +13.5079 TL +154.1522 5.1996 Td +(semiwarfare )Tj +/F9 13.7413 Tf +13.7413 TL +97.2567 -0.1167 Td +(blendure )Tj +/F11 20.1956 Tf +20.1956 TL +-580.2113 20.7728 Td +(reneague )Tj +/F12 20.6134 Tf +20.6134 TL +109.0561 -0.2089 Td +(foresaddle )Tj +/F11 15.7453 Tf +15.7453 TL +136.0482 2.434 Td +(anomalocephalus )Tj +/F3 18.5962 Tf +18.5962 TL +151.1552 -1.4254 Td +(philosophobia )Tj +/F4 22.8577 Tf +22.8577 TL +116.2818 -2.1307 Td +(palpation )Tj +/F8 17.8142 Tf +17.8142 TL +94.6307 2.5217 Td +(liltingness )Tj +/F10 15.3795 Tf +15.3795 TL +-607.172 25.2174 Td +(Barringtonia )Tj +/F12 15.6168 Tf +15.6168 TL +119.9601 -0.1186 Td +(lacunosity )Tj +/F6 23.2293 Tf +23.2293 TL +103.0708 -3.8063 Td +(foreutter )Tj +/F5 11.4616 Tf +11.4616 TL +92.9637 5.8839 Td +(wilily )Tj +/F12 11.3326 Tf +11.3326 TL +27.3702 0.0645 Td +(scomberoid )Tj +/F4 18.1894 Tf +18.1894 TL +74.7953 -3.4284 Td +(derangeable )Tj +/F12 19.4653 Tf +19.4653 TL +96.4949 -0.6379 Td +(brandyman )Tj +/F7 16.4287 Tf +16.4287 TL +-514.6549 25.5183 Td +(forkable )Tj +/F8 13.7998 Tf +13.7998 TL +68.475 1.3145 Td +(mnemonically )Tj +/F7 20.0991 Tf +20.0991 TL +95.8674 -3.1496 Td +(breaden )Tj +/F10 11.8532 Tf +11.8532 TL +83.7731 4.1229 Td +(rateless )Tj +/F10 15.3801 Tf +15.3801 TL +64.0075 -1.7634 Td +(parate )Tj +/F1 16.3227 Tf +16.3227 TL +64.5964 -0.4713 Td +(passingness )Tj +/F11 15.2386 Tf +15.2386 TL +81.1564 0.542 Td +(anticritique )Tj +/F10 18.6937 Tf +18.6937 TL +118.8611 -1.7276 Td +(droppy )Tj +/F7 15.4026 Tf +15.4026 TL +-576.7369 25.6456 Td +(rigging )Tj +/F12 13.0923 Tf +13.0923 TL +56.4812 1.1551 Td +(unthrown )Tj +/F2 20.5573 Tf +20.5573 TL +70.6985 -3.7325 Td +(explicatory )Tj +/F11 14.5955 Tf +14.5955 TL +97.6265 2.9809 Td +(cosmolabe )Tj +/F9 13.5506 Tf +13.5506 TL +87.5732 0.5225 Td +(pneumotherapeutics )Tj +/F1 19.8556 Tf +19.8556 TL +154.4772 -3.1525 Td +(sutural )Tj +/F2 16.1025 Tf +16.1025 TL +59.0109 1.8765 Td +(whoremonging )Tj +/F8 19.1601 Tf +19.1601 TL +-525.8675 22.4712 Td +(spirillar )Tj +/F9 12.4259 Tf +12.4259 TL +74.5518 3.3671 Td +(discolichen )Tj +/F10 10.8289 Tf +10.8289 TL +89.4665 0.7985 Td +(evenmete )Tj +/F2 19.3155 Tf +19.3155 TL +58.476 -4.2433 Td +(otorhinolaryngologist )Tj +/F5 15.2498 Tf +15.2498 TL +174.4001 2.0329 Td +(ophthalmodynia )Tj +/F6 15.2622 Tf +15.2622 TL +111.8874 -0.0062 Td +(Thiobacteria )Tj +/F8 11.2509 Tf +11.2509 TL +88.2157 2.0056 Td +(nonrefutation )Tj +/F5 21.2756 Tf +21.2756 TL +-596.9976 18.9877 Td +(prelature )Tj +/F10 13.9635 Tf +13.9635 TL +89.8679 3.656 Td +(myrmicine )Tj +/F8 17.6403 Tf +17.6403 TL +83.7807 -1.8384 Td +(bastide )Tj +/F6 18.3234 Tf +18.3234 TL +66.6629 -0.3415 Td +(venenation )Tj +/F7 16.7492 Tf +16.7492 TL +94.7319 0.7871 Td +(unobserved )Tj +/F12 23.5248 Tf +23.5248 TL +99.5906 -3.3878 Td +(foresign )Tj +/F3 18.2098 Tf +18.2098 TL +127.0337 2.6575 Td +(anagnorisis )Tj +/F2 17.6872 Tf +17.6872 TL +-561.6678 24.2613 Td +(corsaint )Tj +/F8 23.3342 Tf +23.3342 TL +62.4004 -2.8235 Td +(dandily )Tj +/F3 19.0196 Tf +19.0196 TL +88.18 2.1573 Td +(Newport )Tj +/F10 22.7663 Tf +22.7663 TL +75.5268 -1.8734 Td +(periwigpated )Tj +/F11 16.0565 Tf +16.0565 TL +177.5775 3.3549 Td +(incalescence )Tj +/F12 17.0064 Tf +17.0064 TL +125.2411 -0.4749 Td +(Bakutu )Tj +/F6 12.0033 Tf +12.0033 TL +71.4269 2.5016 Td +(spookiness )Tj +/F7 12.382 Tf +12.382 TL +-600.3526 23.8106 Td +(kineplasty )Tj +/F8 16.2662 Tf +16.2662 TL +64.0027 -1.9421 Td +(phthalan )Tj +/F7 21.814 Tf +21.814 TL +72.3033 -2.7739 Td +(Calorite )Tj +/F12 22.0924 Tf +22.0924 TL +87.278 -0.1392 Td +(fatefulness )Tj +/F9 17.5145 Tf +17.5145 TL +159.065 2.2889 Td +(unpondered )Tj +/F9 20.9143 Tf +20.9143 TL +115.5955 -1.6999 Td +(terebinthinate )Tj +/F9 12.6782 Tf +12.6782 TL +-498.2445 28.118 Td +(Potamonidae )Tj +/F8 13.8451 Tf +13.8451 TL +91.2833 -0.5834 Td +(whirling )Tj +/F8 22.1436 Tf +22.1436 TL +56.931 -4.1493 Td +(refectorial )Tj +/F3 18.6435 Tf +18.6435 TL +113.2204 1.75 Td +(reyouth )Tj +/F7 18.6564 Tf +18.6564 TL +66.7998 -0.0064 Td +(Frenchness )Tj +/F6 22.8835 Tf +22.8835 TL +109.9047 -2.1135 Td +(penicillin )Tj +/F2 16.0624 Tf +16.0624 TL +94.0968 3.4105 Td +(pendulate )Tj +/F5 22.0144 Tf +22.0144 TL +67.3657 -2.976 Td +(scratchcard )Tj +/F4 21.477 Tf +21.477 TL +-599.6018 24.2687 Td +(unsealer )Tj +/F9 11.3525 Tf +11.3525 TL +81.7413 5.0622 Td +(phonasthenia )Tj +/F10 19.5668 Tf +19.5668 TL +88.5496 -4.1072 Td +(gadwall )Tj +/F5 15.8742 Tf +15.8742 TL +93.9208 1.8463 Td +(Skoinolon )Tj +/F7 16.2772 Tf +16.2772 TL +74.1166 -0.2015 Td +(bossage )Tj +/F2 13.2545 Tf +13.2545 TL +70.5618 1.5114 Td +(paleography )Tj +/F7 12.5985 Tf +12.5985 TL +70.3149 0.328 Td +(Hippuritidae )Tj +/F2 20.8713 Tf +20.8713 TL +77.0021 -4.1364 Td +(scolytid )Tj +/F5 22.0663 Tf +22.0663 TL +-556.2071 23.4025 Td +(Chapanec )Tj +/F1 23.4582 Tf +23.4582 TL +106.7125 -0.696 Td +(thriftbox )Tj +/F8 21.7482 Tf +21.7482 TL +87.9684 0.855 Td +(calefactor )Tj +/F9 22.7418 Tf +22.7418 TL +108.7847 -0.4968 Td +(mica )Tj +/F7 13.1967 Tf +13.1967 TL +68.2253 4.7725 Td +(isolation )Tj +/F8 18.7281 Tf +18.7281 TL +57.9337 -2.7657 Td +(Dave )Tj +/F7 13.4219 Tf +13.4219 TL +49.9665 2.6531 Td +(bregmata )Tj +/F4 11.7077 Tf +11.7077 TL +64.1433 0.8571 Td +(forbearer )Tj +/F2 12.0382 Tf +12.0382 TL +48.4465 -0.1652 Td +(underpeopled )Tj +/F4 20.2878 Tf +20.2878 TL +-592.1808 19.8752 Td +(winy )Tj +/F4 16.3646 Tf +16.3646 TL +44.5316 1.9616 Td +(formaldehydesulphoxylate )Tj +/F12 16.0793 Tf +16.0793 TL +182.2852 0.1427 Td +(ethanediol )Tj +/F12 23.5656 Tf +23.5656 TL +106.1232 -3.7432 Td +(scotching )Tj +/F4 13.0841 Tf +13.0841 TL +141.3935 5.2407 Td +(ester )Tj +/F7 12.2896 Tf +12.2896 TL +28.7066 0.3973 Td +(effecter )Tj +/F12 20.1005 Tf +20.1005 TL +47.8064 -3.9055 Td +(dosadh )Tj +/F10 12.531 Tf +12.531 TL +-550.8464 27.7848 Td +(avania )Tj +/F10 20.5445 Tf +20.5445 TL +52.63 -4.0068 Td +(counterpull )Tj +/F1 13.3539 Tf +13.3539 TL +147.9202 3.5953 Td +(traversewise )Tj +/F4 19.723 Tf +19.723 TL +70.0811 -3.1846 Td +(unqualitied )Tj +/F10 20.501 Tf +20.501 TL +98.1022 -0.389 Td +(perduring )Tj +/F6 10.7835 Tf +10.7835 TL +123.0057 4.8587 Td +(setting )Tj +/F8 18.1004 Tf +18.1004 TL +34.766 -3.6584 Td +(laparorrhaphy )Tj +/F5 23.6358 Tf +23.6358 TL +-526.5053 21.2323 Td +(superoxygenation )Tj +/F8 12.8529 Tf +12.8529 TL +193.128 5.3914 Td +(ingrown )Tj +/F6 20.6429 Tf +20.6429 TL +53.558 -3.895 Td +(Ferrarese )Tj +/F5 11.0658 Tf +11.0658 TL +95.2049 4.7885 Td +(schiffli )Tj +/F12 21.5881 Tf +21.5881 TL +33.8172 -5.2611 Td +(eyrir )Tj +/F10 23.1229 Tf +23.1229 TL +77.7171 -0.7674 Td +(sultrily )Tj +/F9 19.6265 Tf +19.6265 TL +124.8636 1.7482 Td +(Saan )Tj +/F8 20.5321 Tf +20.5321 TL +-578.2889 23.5472 Td +(auramine )Tj +/F3 12.1008 Tf +12.1008 TL +96.9937 4.2157 Td +(raglet )Tj +/F3 18.9489 Tf +18.9489 TL +33.2651 -3.4241 Td +(anthradiquinone )Tj +/F8 10.4657 Tf +10.4657 TL +140.582 4.2416 Td +(getaway )Tj +/F9 20.7428 Tf +20.7428 TL +44.2071 -5.1385 Td +(chinkara )Tj +/F1 22.655 Tf +22.655 TL +112.011 -0.9561 Td +(decephalization )Tj +/F10 14.0329 Tf +14.0329 TL +147.8466 4.3111 Td +(pseudosymptomatic )Tj +/F11 22.7309 Tf +22.7309 TL +-574.9055 19.651 Td +(nonschismatic )Tj +/F5 15.9747 Tf +15.9747 TL +190.9395 3.3781 Td +(bandiness )Tj +/F2 19.8738 Tf +19.8738 TL +77.2538 -1.9496 Td +(unsenatorial )Tj +/F9 13.6427 Tf +13.6427 TL +105.4506 3.1156 Td +(merosymmetry )Tj +/F7 17.0957 Tf +17.0957 TL +106.4131 -1.7265 Td +(whiffer )Tj +/F4 21.4903 Tf +21.4903 TL +60.7925 -2.1973 Td +(hubmaking )Tj +/F6 13.6962 Tf +13.6962 TL +-540.8493 27.8971 Td +(decan )Tj +/F11 15.2129 Tf +15.2129 TL +41.1159 -0.7584 Td +(pyrogenetically )Tj +/F4 14.8002 Tf +14.8002 TL +146.0438 0.2063 Td +(sternways )Tj +/F8 12.9077 Tf +12.9077 TL +63.7297 0.9463 Td +(goetia )Tj +/F12 18.7315 Tf +18.7315 TL +41.6015 -2.9119 Td +(bordering )Tj +/F12 23.6455 Tf +23.6455 TL +112.3891 -2.457 Td +(reallocation )Tj +/F6 12.1827 Tf +12.1827 TL +184.4349 5.7314 Td +(aftaba )Tj +/F2 18.2492 Tf +18.2492 TL +-589.3149 20.9668 Td +(disinvestiture )Tj +/F8 12.6559 Tf +12.6559 TL +102.9074 2.7967 Td +(zirconate )Tj +/F3 17.8748 Tf +17.8748 TL +59.0779 -2.6094 Td +(unie )Tj +/F11 10.5717 Tf +10.5717 TL +37.2511 3.6515 Td +(omega )Tj +/F10 11.8088 Tf +11.8088 TL +38.0582 -0.6186 Td +(pseudoantique )Tj +/F7 11.9659 Tf +11.9659 TL +99.1942 -0.0785 Td +(phocodontic )Tj +/F1 13.7493 Tf +13.7493 TL +75.1219 -0.8917 Td +(latentness )Tj +/F11 11.7491 Tf +11.7491 TL +57.6647 1.0001 Td +(stingray )Tj +/F10 18.0764 Tf +18.0764 TL +63.4452 -3.1636 Td +(killeen )Tj +/F1 17.2956 Tf +17.2956 TL +-532.7205 24.3904 Td +(overparticularly )Tj +/F7 12.3491 Tf +12.3491 TL +114.791 2.4733 Td +(tetralemma )Tj +/F10 12.2848 Tf +12.2848 TL +69.3153 0.0321 Td +(Shalako )Tj +/F11 14.9893 Tf +14.9893 TL +58.9672 -1.3522 Td +(ripperman )Tj +/F10 20.1303 Tf +20.1303 TL +89.9356 -2.5705 Td +(Sirenoidei )Tj +/F4 13.6805 Tf +13.6805 TL +132.8597 3.2249 Td +(ultratotal )Tj +/F6 21.7503 Tf +21.7503 TL +55.8848 -4.0349 Td +(varicated )Tj +/F11 23.7568 Tf +23.7568 TL +-521.7536 22.9967 Td +(semisatiric )Tj +/F7 14.4395 Tf +14.4395 TL +171.0489 4.6587 Td +(stairhead )Tj +/F8 18.5477 Tf +18.5477 TL +68.2121 -2.0541 Td +(stuntiness )Tj +/F8 14.69 Tf +14.69 TL +97.9134 1.9289 Td +(unagonize )Tj +/F11 18.3103 Tf +18.3103 TL +76.7256 -1.8102 Td +(josephinite )Tj +/F7 15.299 Tf +15.299 TL +131.8344 1.5057 Td +(preimbibe )Tj +/F3 12.3604 Tf +12.3604 TL +-545.7344 25.4693 Td +(abutting )Tj +/F7 13.7645 Tf +13.7645 TL +47.7357 -0.7021 Td +(corticoefferent )Tj +/F9 23.8056 Tf +23.8056 TL +100.1916 -5.0206 Td +(enfester )Tj +/F4 22.9205 Tf +22.9205 TL +128.5503 0.4426 Td +(urethrorrhea )Tj +/F6 18.1913 Tf +18.1913 TL +129.2715 2.3646 Td +(jurara )Tj +/F11 14.5841 Tf +14.5841 TL +51.554 1.8036 Td +(admittible )Tj +/F11 18.6364 Tf +18.6364 TL +96.2551 -2.0262 Td +(Elihu )Tj +/F12 12.6655 Tf +12.6655 TL +-553.5583 26.9854 Td +(reclaim )Tj +/F2 10.6176 Tf +10.6176 TL +60.7945 1.0239 Td +(pregenerosity )Tj +/F7 17.676 Tf +17.676 TL +61.0408 -3.5292 Td +(Toriness )Tj +/F5 15.4913 Tf +15.4913 TL +78.5875 1.0923 Td +(lichenization )Tj +/F2 12.7831 Tf +12.7831 TL +89.54 1.3541 Td +(anukabiet )Tj +/F1 15.4326 Tf +15.4326 TL +53.6121 -1.3248 Td +(exponency )Tj +/F8 21.4633 Tf +21.4633 TL +70.7122 -3.0154 Td +(agminate )Tj +/F5 19.4304 Tf +19.4304 TL +100.1909 1.0165 Td +(rubiate )Tj +/F3 15.652 Tf +15.652 TL +64.8005 1.8892 Td +(keerogue )Tj +/F2 13.853 Tf +13.853 TL +-579.2785 24.8995 Td +(chthonian )Tj +/F4 12.8737 Tf +12.8737 TL +58.8754 0.4896 Td +(cardioneural )Tj +/F11 18.9866 Tf +18.9866 TL +71.887 -3.0564 Td +(felinophobe )Tj +/F9 20.3909 Tf +20.3909 TL +136.7034 -0.7021 Td +(pollenless )Tj +/F9 17.6068 Tf +17.6068 TL +134.5797 1.392 Td +(machicolation )Tj +/F8 13.3173 Tf +13.3173 TL +147.8972 2.1447 Td +(tarsoptosis )Tj +/F12 11.4769 Tf +11.4769 TL +-549.9426 24.9202 Td +(jacketing )Tj +/F2 10.9641 Tf +10.9641 TL +68.8614 0.2564 Td +(wiener )Tj +/F4 19.0805 Tf +19.0805 TL +32.5853 -4.0582 Td +(yomer )Tj +/F8 17.9757 Tf +17.9757 TL +53.5207 0.5524 Td +(steward )Tj +/F1 23.8212 Tf +23.8212 TL +72.9275 -2.9227 Td +(budmash )Tj +/F10 11.1781 Tf +11.1781 TL +91.9735 6.3215 Td +(ultravirtuous )Tj +/F12 20.7672 Tf +20.7672 TL +93.8961 -4.7946 Td +(satinlike )Tj +/F7 20.9271 Tf +20.9271 TL +124.6033 -0.0799 Td +(microcellular )Tj +/F7 18.8391 Tf +18.8391 TL +-538.3677 25.044 Td +(irreconciliableness )Tj +/F9 12.3435 Tf +12.3435 TL +175.9193 3.2478 Td +(archispore )Tj +/F5 11.9463 Tf +11.9463 TL +81.4672 0.1986 Td +(endosclerite )Tj +/F7 12.59 Tf +12.59 TL +67.7235 -0.3219 Td +(linteling )Tj +/F7 12.3622 Tf +12.3622 TL +51.77 0.1139 Td +(leucopyrite )Tj +/F2 13.4903 Tf +13.4903 TL +69.3888 -0.5641 Td +(acieration )Tj +/F3 14.1773 Tf +14.1773 TL +58.8311 -0.3435 Td +(physeterine )Tj +/F1 15.3811 Tf +15.3811 TL +73.6368 -0.6019 Td +(quipu )Tj +/F10 14.2303 Tf +14.2303 TL +-578.7368 24.5754 Td +(Pyrularia )Tj +/F5 19.0962 Tf +19.0962 TL +85.3819 -2.4329 Td +(paganistic )Tj +/F2 15.3296 Tf +15.3296 TL +91.2796 1.8833 Td +(apodosis )Tj +/F2 12.5172 Tf +12.5172 TL +58.3445 1.4062 Td +(calcaneonavicular )Tj +/F12 23.4996 Tf +23.4996 TL +96.2945 -5.4912 Td +(bothy )Tj +/F8 21.375 Tf +21.375 TL +84.5986 1.0623 Td +(Venezuelan )Tj +/F9 17.8584 Tf +17.8584 TL +123.5473 1.7583 Td +(overwade )Tj +/F4 21.2151 Tf +21.2151 TL +-539.4463 22.3216 Td +(fungo )Tj +/F2 16.411 Tf +16.411 TL +57.1748 2.4021 Td +(diverter )Tj +/F2 20.3534 Tf +20.3534 TL +56.0601 -1.9712 Td +(semitime )Tj +/F12 15.7231 Tf +15.7231 TL +77.4448 2.3152 Td +(campanular )Tj +/F2 13.3865 Tf +13.3865 TL +103.7721 1.1683 Td +(aggur )Tj +/F10 19.1689 Tf +19.1689 TL +35.3271 -2.8912 Td +(seemingness )Tj +/F3 15.5166 Tf +15.5166 TL +138.0164 1.8262 Td +(turpentine )Tj +/F4 21.7254 Tf +21.7254 TL +73.7037 -3.1044 Td +(beseechingly )Tj +/F11 11.3337 Tf +11.3337 TL +-541.499 29.1959 Td +(shanghaier )Tj +/F2 20.156 Tf +20.156 TL +74.8021 -4.4112 Td +(squalidity )Tj +/F9 20.243 Tf +20.243 TL +84.5542 -0.0435 Td +(epigonos )Tj +/F6 20.26 Tf +20.26 TL +109.3121 -0.0085 Td +(limous )Tj +/F8 23.2831 Tf +23.2831 TL +64.1633 -1.5116 Td +(neurogenetic )Tj +/F3 11.6071 Tf +11.6071 TL +152.6673 5.838 Td +(inrooted )Tj +/F1 21.7082 Tf +21.7082 TL +44.815 -5.0506 Td +(hydrocholecystis )Tj +/F11 18.6096 Tf +18.6096 TL +-530.3141 25.5493 Td +(Homeromastix )Tj +/F11 10.3765 Tf +10.3765 TL +145.1549 4.1166 Td +(pockwood )Tj +/F6 21.1877 Tf +21.1877 TL +56.033 -5.4056 Td +(unremediable )Tj +/F8 11.0203 Tf +11.0203 TL +134.2451 5.0837 Td +(insultation )Tj +/F8 13.479 Tf +13.479 TL +58.7821 -1.2294 Td +(unsized )Tj +/F12 14.5494 Tf +14.5494 TL +53.9296 -0.5352 Td +(buffle )Tj +/F4 13.3243 Tf +13.3243 TL +61.1074 0.6125 Td +(pasang )Tj +/F5 16.4498 Tf +16.4498 TL +42.5712 -1.5628 Td +(handhaving )Tj +/F12 13.9056 Tf +13.9056 TL +-551.8232 25.2721 Td +(carpentership )Tj +/F5 22.858 Tf +22.858 TL +116.807 -4.4762 Td +(pretravel )Tj +/F1 23.3678 Tf +23.3678 TL +95.2722 -0.2549 Td +(metapsychist )Tj +/F3 17.6449 Tf +17.6449 TL +127.8689 2.8615 Td +(lagopode )Tj +/F10 18.2525 Tf +18.2525 TL +72.0618 -0.3038 Td +(unstatesmanlike )Tj +/F12 10.6967 Tf +10.6967 TL +175.2242 3.7779 Td +(Baptist )Tj +/F12 11.8789 Tf +11.8789 TL +-587.234 23.4089 Td +(metate )Tj +/F1 20.9477 Tf +20.9477 TL +49.8912 -4.5344 Td +(indoles )Tj +/F10 12.3561 Tf +12.3561 TL +65.755 4.2958 Td +(vagrantlike )Tj +/F10 18.0975 Tf +18.0975 TL +88.9638 -2.8707 Td +(spectacularly )Tj +/F9 11.8266 Tf +11.8266 TL +152.0194 3.1355 Td +(judiciable )Tj +/F1 21.6924 Tf +21.6924 TL +78.0555 -4.9329 Td +(chalkiness )Tj +/F12 12.4287 Tf +12.4287 TL +95.7938 4.6319 Td +(disintegrationist )Tj +/F10 13.502 Tf +13.502 TL +-530.4786 23.4634 Td +(bedur )Tj +/F9 14.0877 Tf +14.0877 TL +48.6072 -0.2929 Td +(blustering )Tj +/F8 14.0253 Tf +14.0253 TL +92.979 0.0312 Td +(hiragana )Tj +/F10 19.0992 Tf +19.0992 TL +62.3565 -2.5369 Td +(intastable )Tj +/F4 13.559 Tf +13.559 TL +126.0545 2.7701 Td +(ichneumonoid )Tj +/F7 14.9443 Tf +14.9443 TL +84.0118 -0.6926 Td +(superrighteous )Tj +/F8 15.5859 Tf +15.5859 TL +112.9338 -0.3208 Td +(embracive )Tj +/F4 16.2558 Tf +16.2558 TL +81.4363 -0.335 Td +(chillagite )Tj +/F9 12.138 Tf +12.138 TL +-608.379 26.0589 Td +(semitonically )Tj +/F12 12.174 Tf +12.174 TL +101.9596 -0.018 Td +(text )Tj +/F9 20.2436 Tf +20.2436 TL +36.5221 -4.0348 Td +(transcendental )Tj +/F10 13.3409 Tf +13.3409 TL +182.1928 3.4514 Td +(panderous )Tj +/F3 13.7952 Tf +13.7952 TL +80.0456 -0.2271 Td +(incomprehensively )Tj +/F12 12.9631 Tf +12.9631 TL +113.81 0.416 Td +(trachelagra )Tj +/F12 23.0668 Tf +23.0668 TL +93.3342 -5.0519 Td +(mommy )Tj +/F5 16.2379 Tf +16.2379 TL +-607.8643 27.4144 Td +(Grammatophyllum )Tj +/F5 14.8567 Tf +14.8567 TL +137.1457 0.6906 Td +(unsurpassableness )Tj +/F6 21.8553 Tf +21.8553 TL +132.1203 -3.4993 Td +(unimposing )Tj +/F1 16.8879 Tf +16.8879 TL +117.8218 2.4837 Td +(excusingly )Tj +/F2 13.8904 Tf +13.8904 TL +77.3973 1.4987 Td +(turd )Tj +/F1 21.8985 Tf +21.8985 TL +26.6279 -4.0041 Td +(mastigophorous )Tj +/F2 17.9156 Tf +17.9156 TL +-491.113 25.9915 Td +(chondrotome )Tj +/F1 11.1192 Tf +11.1192 TL +99.0196 3.3982 Td +(harebrain )Tj +/F2 11.8048 Tf +11.8048 TL +44.7658 -0.3428 Td +(impletion )Tj +/F2 15.0898 Tf +15.0898 TL +47.5497 -1.6425 Td +(anthropoidean )Tj +/F1 15.9297 Tf +15.9297 TL +92.6362 -0.42 Td +(superregistration )Tj +/F2 19.1073 Tf +19.1073 TL +111.0461 -1.5888 Td +(Austroasiatic )Tj +/F3 15.7388 Tf +15.7388 TL +106.6954 1.6843 Td +(unrelievableness )Tj +/F7 19.1358 Tf +19.1358 TL +-501.7127 22.3015 Td +(nosewise )Tj +/F5 15.0255 Tf +15.0255 TL +91.469 2.0551 Td +(Aegialitis )Tj +/F3 18.614 Tf +18.614 TL +64.2941 -1.7943 Td +(Criniger )Tj +/F3 10.5628 Tf +10.5628 TL +72.8926 4.0256 Td +(pleurotonic )Tj +/F9 15.1592 Tf +15.1592 TL +54.282 -2.2982 Td +(stere )Tj +/F3 18.8424 Tf +18.8424 TL +54.573 -1.8416 Td +(nonprohibitive )Tj +/F3 10.2852 Tf +10.2852 TL +124.0775 4.2786 Td +(Cornaceae )Tj +/F10 13.7758 Tf +13.7758 TL +49.4101 -1.7453 Td +(viritrate )Tj +/F11 23.0468 Tf +23.0468 TL +82.655 -4.6355 Td +(myxoid )Tj +/F6 21.8767 Tf +21.8767 TL +-593.6533 24.5851 Td +(unpalatable )Tj +/F6 11.8137 Tf +11.8137 TL +119.1841 5.0315 Td +(superimpending )Tj +/F8 18.2889 Tf +18.2889 TL +87.3269 -3.2376 Td +(cogently )Tj +/F8 17.3496 Tf +17.3496 TL +80.2881 0.4696 Td +(undiademed )Tj +/F1 16.1501 Tf +16.1501 TL +107.0125 0.5997 Td +(pewless )Tj +/F2 15.1987 Tf +15.1987 TL +55.1689 0.4757 Td +(grizzled )Tj +/F11 12.0091 Tf +12.0091 TL +51.9339 1.5948 Td +(pseudolichen )Tj +/F5 22.679 Tf +22.679 TL +93.6713 -5.335 Td +(unaffixed )Tj +/F1 22.1621 Tf +22.1621 TL +-594.5856 24.2585 Td +(zaphrentoid )Tj +/F1 21.3389 Tf +21.3389 TL +110.168 0.4116 Td +(eczematosis )Tj +/F12 17.0328 Tf +17.0328 TL +108.4445 2.153 Td +(preinspection )Tj +/F2 15.4815 Tf +15.4815 TL +143.0759 0.7757 Td +(Saivism )Tj +/F2 23.4242 Tf +23.4242 TL +52.0333 -3.9714 Td +(drovy )Tj +/F10 21.9765 Tf +21.9765 TL +59.1931 0.7239 Td +(traumatize )Tj +/F12 20.183 Tf +20.183 TL +-472.9147 24.8967 Td +(conchologist )Tj +/F8 23.0101 Tf +23.0101 TL +157.4276 -1.4135 Td +(coryphylly )Tj +/F3 15.3554 Tf +15.3554 TL +121.4932 3.8273 Td +(bedside )Tj +/F11 19.1195 Tf +19.1195 TL +53.3294 -1.8821 Td +(overbowed )Tj +/F8 21.0278 Tf +21.0278 TL +114.7171 -0.9541 Td +(radiographic )Tj +/F12 22.8091 Tf +22.8091 TL +133.211 -0.8906 Td +(Premonstratensian )Tj +/F7 19.6616 Tf +19.6616 TL +-580.1783 25.5737 Td +(politzerization )Tj +/F1 18.926 Tf +18.926 TL +137.6508 0.3678 Td +(randir )Tj +/F9 15.2889 Tf +15.2889 TL +49.9267 1.8185 Td +(untrustworthiness )Tj +/F1 10.7615 Tf +10.7615 TL +165.1206 2.2637 Td +(overfar )Tj +/F3 12.3639 Tf +12.3639 TL +33.7589 -0.8012 Td +(sketchingly )Tj +/F1 11.4388 Tf +11.4388 TL +62.8582 0.4626 Td +(evaluable )Tj +/F7 21.2894 Tf +21.2894 TL +46.6932 -4.9253 Td +(unmissionized )Tj +/F10 14.7551 Tf +14.7551 TL +-496.0085 27.2671 Td +(precordium )Tj +/F8 11.4254 Tf +11.4254 TL +97.3838 1.6648 Td +(maintopman )Tj +/F8 16.9359 Tf +16.9359 TL +71.1006 -2.7552 Td +(shader )Tj +/F5 22.5758 Tf +22.5758 TL +60.2409 -2.82 Td +(Brevirostrines )Tj +/F11 16.0814 Tf +16.0814 TL +144.2595 3.2472 Td +(zimentwater )Tj +/F11 20.643 Tf +20.643 TL +115.7858 -2.2808 Td +(trenchlike )Tj +/F3 22.7891 Tf +22.7891 TL +-488.7706 22.927 Td +(menial )Tj +/F3 17.566 Tf +17.566 TL +71.535 2.6115 Td +(glazy )Tj +/F3 15.279 Tf +15.279 TL +43.4232 1.1435 Td +(Iguvine )Tj +/F10 10.0509 Tf +10.0509 TL +53.0638 2.614 Td +(roentgenometry )Tj +/F1 12.1239 Tf +12.1239 TL +90.4581 -1.0365 Td +(laggen )Tj +/F9 13.4092 Tf +13.4092 TL +35.3533 -0.6427 Td +(anakinetomeric )Tj +/F6 13.8121 Tf +13.8121 TL +120.6831 -0.2014 Td +(newfanglement )Tj +/F9 10.4332 Tf +10.4332 TL +97.4993 1.6895 Td +(homestead )Tj +/F6 12.7312 Tf +12.7312 TL +62.5989 -1.149 Td +(witherly )Tj +/F4 11.1153 Tf +11.1153 TL +-574.6146 24.8079 Td +(reiver )Tj +/F3 15.9399 Tf +15.9399 TL +29.3222 -2.4123 Td +(cuprobismutite )Tj +/F11 10.4758 Tf +10.4758 TL +107.5944 2.7321 Td +(spar )Tj +/F12 19.7127 Tf +19.7127 TL +31.4274 -4.6185 Td +(megalerg )Tj +/F6 14.6479 Tf +14.6479 TL +106.4487 2.5324 Td +(Culdee )Tj +/F7 19.0697 Tf +19.0697 TL +50.4767 -2.2109 Td +(superanimal )Tj +/F11 20.9244 Tf +20.9244 TL +117.6408 -0.9274 Td +(buttonholer )Tj +/F11 23.0601 Tf +23.0601 TL +150.6555 -1.0679 Td +(causational )Tj +/F1 21.9968 Tf +21.9968 TL +-593.5656 24.5316 Td +(wowser )Tj +/F8 13.9056 Tf +13.9056 TL +73.9093 4.0456 Td +(contour )Tj +/F8 11.6872 Tf +11.6872 TL +55.6224 1.1092 Td +(nonimpressionist )Tj +/F12 19.4086 Tf +19.4086 TL +100.6615 -3.8607 Td +(preceding )Tj +/F6 17.11 Tf +17.11 TL +116.4515 1.1493 Td +(methine )Tj +/F4 13.4354 Tf +13.4354 TL +65.6167 1.8373 Td +(chicky )Tj +/F12 19.4826 Tf +19.4826 TL +39.1776 -3.0236 Td +(confrater )Tj +/F7 13.8778 Tf +13.8778 TL +116.8958 2.8024 Td +(Chamicuro )Tj +/F3 11.9529 Tf +11.9529 TL +-568.3349 24.9624 Td +(monogynist )Tj +/F1 16.766 Tf +16.766 TL +62.0955 -2.4065 Td +(unbraid )Tj +/F2 14.0219 Tf +14.0219 TL +55.4115 1.372 Td +(determinably )Tj +/F7 18.5876 Tf +18.5876 TL +77.4991 -2.2828 Td +(ruffin )Tj +/F12 11.727 Tf +11.727 TL +52.6585 3.4303 Td +(goneoclinic )Tj +/F7 23.6941 Tf +23.6941 TL +84.4345 -5.9835 Td +(calamite )Tj +/F8 21.8844 Tf +21.8844 TL +101.4106 0.9048 Td +(Hydruntine )Tj +/F9 19.0103 Tf +19.0103 TL +121.5899 1.437 Td +(itonidid )Tj +/F11 11.8159 Tf +11.8159 TL +-555.0997 27.5972 Td +(semilichen )Tj +/F9 19.7472 Tf +19.7472 TL +77.9847 -3.9657 Td +(agamogenetic )Tj +/F9 14.839 Tf +14.839 TL +154.0279 2.4541 Td +(prestigious )Tj +/F4 10.2766 Tf +10.2766 TL +106.8409 2.2812 Td +(autobiology )Tj +/F9 22.5303 Tf +22.5303 TL +52.2465 -6.1268 Td +(Maba )Tj +/F1 20.8307 Tf +20.8307 TL +67.5909 0.8498 Td +(toru )Tj +/F3 10.4971 Tf +10.4971 TL +38.7659 5.1668 Td +(Chenopodium )Tj +/F6 15.0401 Tf +15.0401 TL +66.2054 -2.2715 Td +(rhomboidally )Tj +/F8 19.8904 Tf +19.8904 TL +-563.6621 21.5749 Td +(plap )Tj +/F11 18.0578 Tf +18.0578 TL +46.4242 0.9163 Td +(Protephemeroidea )Tj +/F6 14.5156 Tf +14.5156 TL +184.19 1.7711 Td +(osteocartilaginous )Tj +/F9 17.6048 Tf +17.6048 TL +121.0165 -1.5446 Td +(inequilobed )Tj +/F2 22.0607 Tf +22.0607 TL +126.7547 -2.228 Td +(bromacetic )Tj +/F6 15.2462 Tf +15.2462 TL +104.7665 3.4073 Td +(brutalize )Tj +/F11 19.4344 Tf +19.4344 TL +-583.152 21.9059 Td +(ornithodelphian )Tj +/F8 20.0923 Tf +20.0923 TL +186.5701 -0.329 Td +(pettifogger )Tj +/F11 22.8801 Tf +22.8801 TL +110.5077 -1.3939 Td +(tubulously )Tj +/F12 16.957 Tf +16.957 TL +151.0088 2.9615 Td +(stepniece )Tj +/F8 15.661 Tf +15.661 TL +101.7422 0.648 Td +(redistributor )Tj +/F2 21.5031 Tf +21.5031 TL +-549.8288 21.079 Td +(Mizpah )Tj +/F2 14.8233 Tf +14.8233 TL +69.8852 3.3399 Td +(Gnetaceae )Tj +/F1 13.6595 Tf +13.6595 TL +67.0901 0.5819 Td +(infusorium )Tj +/F6 10.6615 Tf +10.6615 TL +63.3663 1.499 Td +(Anomalon )Tj +/F12 11.5521 Tf +11.5521 TL +50.9618 -0.4453 Td +(cardiometric )Tj +/F5 20.2767 Tf +20.2767 TL +90.106 -4.3623 Td +(assessorial )Tj +/F1 16.1247 Tf +16.1247 TL +107.0408 2.076 Td +(egomaniacal )Tj +/F5 22.9891 Tf +22.9891 TL +85.5255 -3.4322 Td +(clogwood )Tj +/F2 17.9098 Tf +17.9098 TL +-533.9757 26.5396 Td +(lutelet )Tj +/F5 12.6644 Tf +12.6644 TL +49.252 2.6227 Td +(significavit )Tj +/F9 20.4673 Tf +20.4673 TL +61.9287 -3.9014 Td +(yearn )Tj +/F2 13.6821 Tf +13.6821 TL +73.6821 3.3926 Td +(smallage )Tj +/F8 19.9727 Tf +19.9727 TL +52.8266 -3.1453 Td +(cystoschisis )Tj +/F12 21.6166 Tf +21.6166 TL +125.4486 -0.8219 Td +(archaeologist )Tj +/F4 17.2195 Tf +17.2195 TL +181.5793 2.1985 Td +(gelatose )Tj +/F2 15.3141 Tf +15.3141 TL +61.6974 0.9527 Td +(urodele )Tj +/F11 19.5861 Tf +19.5861 TL +-606.4149 21.864 Td +(diminutiveness )Tj +/F1 19.5818 Tf +19.5818 TL +176.2745 0.0021 Td +(coappriser )Tj +/F2 18.7633 Tf +18.7633 TL +86.4537 0.4092 Td +(macronucleus )Tj +/F10 22.5633 Tf +22.5633 TL +109.953 -1.9 Td +(introflexion )Tj +/F7 21.6497 Tf +21.6497 TL +175.9936 0.4568 Td +(Condylopoda )Tj +/F3 15.1992 Tf +15.1992 TL +-548.6749 27.2253 Td +(Torosaurus )Tj +/F3 18.9975 Tf +18.9975 TL +78.9597 -1.8992 Td +(Bouvardia )Tj +/F5 10.6907 Tf +10.6907 TL +90.2571 4.1534 Td +(sheva )Tj +/F9 15.3465 Tf +15.3465 TL +31.4949 -2.3279 Td +(nonconsequence )Tj +/F7 15.6804 Tf +15.6804 TL +138.1181 -0.167 Td +(noninquiring )Tj +/F7 20.9088 Tf +20.9088 TL +100.182 -2.6142 Td +(luminificent )Tj +/F1 17.7713 Tf +17.7713 TL +123.1529 1.5687 Td +(cadism )Tj +/F5 14.8392 Tf +14.8392 TL +-562.1648 25.4661 Td +(monolayer )Tj +/F3 17.674 Tf +17.674 TL +73.3946 -1.4174 Td +(leucoencephalitis )Tj +/F2 16.3744 Tf +16.3744 TL +133.0497 0.6498 Td +(tauromachian )Tj +/F11 19.9281 Tf +19.9281 TL +95.9702 -1.7769 Td +(gade )Tj +/F2 23.3039 Tf +23.3039 TL +59.7844 -1.6879 Td +(bullbaiting )Tj +/F8 10.1319 Tf +10.1319 TL +108.1302 6.586 Td +(preadornment )Tj +/F1 17.1014 Tf +17.1014 TL +70.9331 -3.4848 Td +(selectly )Tj +/F4 10.5005 Tf +10.5005 TL +56.52 3.3005 Td +(Carpophaga )Tj +/F12 20.7854 Tf +20.7854 TL +-597.7823 18.8575 Td +(district )Tj +/F4 19.1608 Tf +19.1608 TL +112.241 0.8123 Td +(nonproductively )Tj +/F12 12.0332 Tf +12.0332 TL +132.5352 3.5638 Td +(scapulovertebral )Tj +/F2 17.6899 Tf +17.6899 TL +122.7391 -2.8283 Td +(brills )Tj +/F3 22.8271 Tf +22.8271 TL +41.7836 -2.5686 Td +(androgynism )Tj +/F2 10.7092 Tf +10.7092 TL +133.8125 6.0589 Td +(subcyaneous )Tj +/F12 20.0354 Tf +20.0354 TL +57.4015 -4.6631 Td +(unguled )Tj +/F7 13.0732 Tf +13.0732 TL +-600.513 27.4811 Td +(splenemphraxis )Tj +/F5 20.6414 Tf +20.6414 TL +103.1739 -3.7841 Td +(nonsynonymous )Tj +/F4 19.3187 Tf +19.3187 TL +156.0283 0.6614 Td +(crinkleroot )Tj +/F7 18.0586 Tf +18.0586 TL +92.8455 0.63 Td +(ejaculative )Tj +/F11 15.129 Tf +15.129 TL +97.372 1.4648 Td +(unctious )Tj +/F7 12.7622 Tf +12.7622 TL +81.6965 1.1834 Td +(valveless )Tj +/F11 14.6999 Tf +14.6999 TL +60.3141 -0.9689 Td +(Clunist )Tj +/F7 22.4283 Tf +22.4283 TL +-591.4303 20.1358 Td +(ocelliferous )Tj +/F6 17.3083 Tf +17.3083 TL +132.1249 2.56 Td +(distrain )Tj +/F9 19.0903 Tf +19.0903 TL +60.5963 -0.891 Td +(unmoldered )Tj +/F6 18.1952 Tf +18.1952 TL +125.9961 0.4476 Td +(arcade )Tj +/F9 23.0205 Tf +23.0205 TL +60.6809 -2.4127 Td +(skaffie )Tj +/F2 16.5445 Tf +16.5445 TL +110.4984 3.238 Td +(trochleary )Tj +/F12 14.8945 Tf +14.8945 TL +73.0606 0.825 Td +(prelogic )Tj +/F3 19.9829 Tf +19.9829 TL +-562.9573 21.4558 Td +(promulgation )Tj +/F11 16.2686 Tf +16.2686 TL +121.5759 1.8572 Td +(vinification )Tj +/F12 13.5332 Tf +13.5332 TL +126.8947 1.3677 Td +(neep )Tj +/F6 14.8315 Tf +14.8315 TL +40.5996 -0.6492 Td +(constrainer )Tj +/F1 21.7917 Tf +21.7917 TL +77.48 -3.4801 Td +(gentlewoman )Tj +/F11 17.6387 Tf +17.6387 TL +122.8616 2.0765 Td +(suasionist )Tj +/F5 11.0767 Tf +11.0767 TL +116.4156 3.281 Td +(farandole )Tj +/F10 14.3065 Tf +14.3065 TL +-605.8274 22.3851 Td +(unhorizontal )Tj +/F9 16.1654 Tf +16.1654 TL +111.591 -0.9294 Td +(gerrymanderer )Tj +/F11 11.1983 Tf +11.1983 TL +135.7894 2.4836 Td +(mittimus )Tj +/F3 23.9121 Tf +23.9121 TL +60.4706 -6.3569 Td +(sesquicentennial )Tj +/F4 22.1052 Tf +22.1052 TL +173.3867 0.9034 Td +(ipsedixitism )Tj +/F2 17.7327 Tf +17.7327 TL +113.6209 2.1863 Td +(unforthright )Tj +/F5 21.5093 Tf +21.5093 TL +-594.8586 22.1117 Td +(centrifugal )Tj +/F6 18.2247 Tf +18.2247 TL +105.2018 1.6423 Td +(bervie )Tj +/F6 15.8394 Tf +15.8394 TL +54.6923 1.1927 Td +(romancist )Tj +/F5 11.3996 Tf +11.3996 TL +73.0511 2.2199 Td +(previsor )Tj +/F9 16.1391 Tf +16.1391 TL +43.7062 -2.3697 Td +(zooecium )Tj +/F5 10.7082 Tf +10.7082 TL +87.1512 2.7154 Td +(antilynching )Tj +/F11 13.2705 Tf +13.2705 TL +59.5163 -1.2812 Td +(nonaromatic )Tj +/F5 18.459 Tf +18.459 TL +95.5479 -2.5942 Td +(resistlessly )Tj +/F4 23.2279 Tf +23.2279 TL +-518.8668 21.6155 Td +(spiraltail )Tj +/F9 20.5543 Tf +20.5543 TL +91.0069 1.3368 Td +(bleakly )Tj +/F12 23.9757 Tf +23.9757 TL +98.6607 -1.7107 Td +(systematization )Tj +/F8 15.5265 Tf +15.5265 TL +230.1669 4.2246 Td +(camphoronic )Tj +/F12 14.2195 Tf +14.2195 TL +101.8076 0.6535 Td +(studiousness )Tj +/F10 15.9782 Tf +15.9782 TL +-521.642 23.1207 Td +(rectococcygeal )Tj +/F2 10.837 Tf +10.837 TL +143.8041 2.5706 Td +(undragooned )Tj +/F10 11.0877 Tf +11.0877 TL +60.5032 -0.1253 Td +(thriftlessly )Tj +/F2 11.8168 Tf +11.8168 TL +86.484 -0.3646 Td +(overname )Tj +/F2 14.078 Tf +14.078 TL +49.548 -1.1306 Td +(imageless )Tj +/F1 12.5532 Tf +12.5532 TL +59.0432 0.7624 Td +(downstreet )Tj +/F10 16.6779 Tf +16.6779 TL +58.2216 -2.0624 Td +(antiluetin )Tj +/F9 19.0508 Tf +19.0508 TL +110.0739 -1.1865 Td +(compromiser )Tj +/F4 16.2809 Tf +16.2809 TL +-567.678 25.385 Td +(aoudad )Tj +/F7 15.7364 Tf +15.7364 TL +53.8247 0.2723 Td +(lough )Tj +/F7 15.6648 Tf +15.6648 TL +47.2092 0.0358 Td +(tummock )Tj +/F5 19.6225 Tf +19.6225 TL +73.9848 -1.9788 Td +(felsobanyite )Tj +/F8 10.1756 Tf +10.1756 TL +110.1605 4.7234 Td +(Encrinoidea )Tj +/F9 22.0864 Tf +22.0864 TL +61.0742 -5.9554 Td +(unvaluably )Tj +/F10 18.9525 Tf +18.9525 TL +145.7703 1.5669 Td +(hyperemphasize )Tj +/F10 15.0059 Tf +15.0059 TL +-492.0237 25.9733 Td +(lutist )Tj +/F7 19.638 Tf +19.638 TL +63.025 -2.316 Td +(unwashedness )Tj +/F10 15.3332 Tf +15.3332 TL +146.244 2.1524 Td +(unchurchlike )Tj +/F8 19.2236 Tf +19.2236 TL +119.5991 -1.9452 Td +(amidoketone )Tj +/F4 16.4651 Tf +16.4651 TL +123.9156 1.3793 Td +(brainward )Tj +/F7 12.7507 Tf +12.7507 TL +74.5703 1.8572 Td +(semireniform )Tj +/F8 20.6472 Tf +20.6472 TL +84.3203 -3.9482 Td +(Choloepus )Tj +/F3 20.8588 Tf +20.8588 TL +-611.6743 23.8942 Td +(televox )Tj +/F3 13.1478 Tf +13.1478 TL +67.7704 3.8555 Td +(formule )Tj +/F3 15.2602 Tf +15.2602 TL +47.8317 -1.0562 Td +(fimbrillate )Tj +/F9 20.076 Tf +20.076 TL +73.3253 -2.4079 Td +(Hamathite )Tj +/F12 20.1142 Tf +20.1142 TL +120.4559 -0.0191 Td +(whereby )Tj +/F6 14.259 Tf +14.259 TL +96.5482 2.9276 Td +(nongovernmental )Tj +/F6 18.4155 Tf +18.4155 TL +114.1289 -2.0782 Td +(tegumentary )Tj +/F1 17.8484 Tf +17.8484 TL +-520.0603 24.2835 Td +(scap )Tj +/F4 16.1194 Tf +16.1194 TL +36.1787 0.8645 Td +(flowing )Tj +/F10 17.6394 Tf +17.6394 TL +54.1933 -0.76 Td +(recorruption )Tj +/F8 21.2839 Tf +21.2839 TL +137.5876 -1.8222 Td +(quotidianness )Tj +/F5 13.2021 Tf +13.2021 TL +150.2001 4.0409 Td +(measled )Tj +/F4 22.2766 Tf +22.2766 TL +53.561 -4.5372 Td +(saxigenous )Tj +/F8 21.7733 Tf +21.7733 TL +108.3086 0.2516 Td +(mostness )Tj +/F2 14.6877 Tf +14.6877 TL +-540.0294 27.5428 Td +(sphingiform )Tj +/F6 14.1493 Tf +14.1493 TL +74.6721 0.2692 Td +(macrocornea )Tj +/F5 21.8378 Tf +21.8378 TL +86.4944 -3.8442 Td +(millile )Tj +/F9 12.0627 Tf +12.0627 TL +60.6434 4.8876 Td +(knoblike )Tj +/F5 14.1765 Tf +14.1765 TL +65.1383 -1.0569 Td +(scarlatiniform )Tj +/F4 12.645 Tf +12.645 TL +88.2201 0.7657 Td +(bediaper )Tj +/F11 19.2652 Tf +19.2652 TL +48.1143 -3.3101 Td +(mugwump )Tj +/F7 15.7218 Tf +15.7218 TL +92.4728 1.7717 Td +(palmicolous )Tj +/F7 16.7796 Tf +16.7796 TL +96.1074 -0.5289 Td +(benightedness )Tj +/F10 10.8494 Tf +10.8494 TL +-611.8628 26.9651 Td +(anisopterous )Tj +/F9 13.6353 Tf +13.6353 TL +84.6253 -1.393 Td +(khedival )Tj +/F10 14.7407 Tf +14.7407 TL +73.6307 -0.5527 Td +(paleotechnic )Tj +/F11 23.3576 Tf +23.3576 TL +114.9777 -4.3084 Td +(biomagnetism )Tj +/F1 14.5321 Tf +14.5321 TL +182.1892 4.4127 Td +(Chilcat )Tj +/F4 13.9841 Tf +13.9841 TL +45.6164 0.274 Td +(Japanophobe )Tj +/F12 14.6325 Tf +14.6325 TL +81.1916 -0.3242 Td +(oenanthate )Tj +/F10 10.608 Tf +10.608 TL +-582.2308 26.0123 Td +(anteroom )Tj +/F8 15.0636 Tf +15.0636 TL +57.2832 -2.2278 Td +(bibliological )Tj +/F1 14.4509 Tf +14.4509 TL +92.0838 0.3064 Td +(myodynamics )Tj +/F4 19.0513 Tf +19.0513 TL +84.6968 -2.3002 Td +(dysaphia )Tj +/F4 20.0575 Tf +20.0575 TL +74.6238 -0.5031 Td +(V )Tj +/F11 17.126 Tf +17.126 TL +18.3927 1.4657 Td +(familiarity )Tj +/F7 18.7452 Tf +18.7452 TL +123.3072 -0.8096 Td +(windproof )Tj +/F12 21.1317 Tf +21.1317 TL +95.8069 -1.1932 Td +(electromagnetical )Tj +/F6 18.0188 Tf +18.0188 TL +-546.1945 25.5565 Td +(dhabb )Tj +/F10 11.4778 Tf +11.4778 TL +55.1014 3.2705 Td +(spinsterly )Tj +/F12 23.6062 Tf +23.6062 TL +75.7532 -6.0642 Td +(herisson )Tj +/F11 17.454 Tf +17.454 TL +127.4737 3.0761 Td +(dryly )Tj +/F4 17.851 Tf +17.851 TL +62.8344 -0.1985 Td +(unsensually )Tj +/F10 21.4528 Tf +21.4528 TL +92.7539 -1.8009 Td +(europium )Tj +/F7 20.739 Tf +20.739 TL +115.8453 0.3569 Td +(volitient )Tj +/F3 12.1453 Tf +12.1453 TL +-529.7619 28.2969 Td +(violatory )Tj +/F1 10.8533 Tf +10.8533 TL +49.5891 0.646 Td +(becircled )Tj +/F11 10.3677 Tf +10.3677 TL +42.4906 0.2428 Td +(peritoneoscope )Tj +/F11 12.2548 Tf +12.2548 TL +93.3097 -0.9435 Td +(precision )Tj +/F8 14.8095 Tf +14.8095 TL +73.529 -1.2773 Td +(flatulent )Tj +/F7 11.9304 Tf +11.9304 TL +61.7112 1.4396 Td +(crassitude )Tj +/F12 11.0145 Tf +11.0145 TL +62.9924 0.4579 Td +(obeisance )Tj +/F3 10.4991 Tf +10.4991 TL +66.0873 0.2577 Td +(misanthropically )Tj +/F4 17.9018 Tf +17.9018 TL +78.46 -3.7013 Td +(anaphoric )Tj +/F7 21.3115 Tf +21.3115 TL +80.0746 -1.7049 Td +(therefor )Tj +/F6 17.1419 Tf +17.1419 TL +-608.2439 26.0848 Td +(saccharimetry )Tj +/F8 17.8258 Tf +17.8258 TL +111.4395 -0.3419 Td +(muscat )Tj +/F11 20.3795 Tf +20.3795 TL +67.3636 -1.2769 Td +(unlenient )Tj +/F8 19.0111 Tf +19.0111 TL +122.277 0.6842 Td +(Ephraimitish )Tj +/F9 19.2326 Tf +19.2326 TL +120.4352 -0.1108 Td +(decaffeinize )Tj +/F5 23.4959 Tf +23.4959 TL +150.0143 -2.1316 Td +(bourdon )Tj +/F5 22.3277 Tf +22.3277 TL +-571.5296 24.5841 Td +(shippage )Tj +/F1 23.3275 Tf +23.3275 TL +96.8131 -0.4999 Td +(raniform )Tj +/F7 23.1773 Tf +23.1773 TL +87.4547 0.0751 Td +(protohydrogen )Tj +/F5 17.2568 Tf +17.2568 TL +171.2572 2.9603 Td +(baselessly )Tj +/F1 13.3418 Tf +13.3418 TL +85.3519 1.9575 Td +(Podocarpus )Tj +/F9 19.4786 Tf +19.4786 TL +65.5881 -3.0684 Td +(pallidly )Tj +/F2 22.9727 Tf +22.9727 TL +105.1845 -1.7471 Td +(odalisk )Tj +/F1 21.2824 Tf +21.2824 TL +-611.6494 24.8452 Td +(Normanly )Tj +/F4 21.5264 Tf +21.5264 TL +91.6209 -0.122 Td +(disrealize )Tj +/F9 19.7236 Tf +19.7236 TL +89.0977 0.9014 Td +(isoperimetric )Tj +/F3 11.3875 Tf +11.3875 TL +165.6786 4.1681 Td +(hemlock )Tj +/F5 13.6222 Tf +13.6222 TL +43.9671 -1.1174 Td +(creosotic )Tj +/F12 21.6854 Tf +21.6854 TL +58.2894 -4.0316 Td +(bark )Tj +/F9 22.187 Tf +22.187 TL +65.0563 -0.2508 Td +(attingency )Tj +/F11 23.0086 Tf +23.0086 TL +-513.7099 23.5892 Td +(subprofitable )Tj +/F9 12.1527 Tf +12.1527 TL +193.2718 5.4279 Td +(naupathia )Tj +/F11 20.3485 Tf +20.3485 TL +72.9164 -4.0979 Td +(Lamaist )Tj +/F4 16.9771 Tf +16.9771 TL +97.673 1.6857 Td +(polyarticular )Tj +/F5 21.9033 Tf +21.9033 TL +94.8003 -2.4631 Td +(Pterostemonaceae )Tj +/F5 18.6596 Tf +18.6596 TL +-458.6616 25.6218 Td +(argyranthous )Tj +/F1 20.9854 Tf +20.9854 TL +114.085 -1.1629 Td +(suclat )Tj +/F4 12.3932 Tf +12.3932 TL +54.2054 4.2961 Td +(glucid )Tj +/F8 18.1307 Tf +18.1307 TL +34.7752 -2.8688 Td +(readaptiveness )Tj +/F9 21.2577 Tf +21.2577 TL +137.0497 -1.5635 Td +(uninterred )Tj +/F11 10.9625 Tf +10.9625 TL +140.301 5.1476 Td +(tutorship )Tj +/F6 10.879 Tf +10.879 TL +65.7753 0.0418 Td +(flagger )Tj +/F9 22.9612 Tf +22.9612 TL +36.2815 -6.0411 Td +(spile )Tj +/F4 20.8823 Tf +20.8823 TL +-582.4731 25.0394 Td +(intrametropolitan )Tj +/F2 13.3578 Tf +13.3578 TL +157.2438 3.7622 Td +(dethroner )Tj +/F11 20.8557 Tf +20.8557 TL +56.0227 -3.7489 Td +(litra )Tj +/F11 20.0679 Tf +20.0679 TL +75.0806 0.3939 Td +(triennially )Tj +/F12 17.9217 Tf +17.9217 TL +144.4886 1.0731 Td +(hyperpurist )Tj +/F10 13.333 Tf +13.333 TL +129.0365 2.2944 Td +(conchiolin )Tj +/F10 22.3101 Tf +22.3101 TL +-561.8722 19.5114 Td +(thoughtlet )Tj +/F6 20.8229 Tf +20.8229 TL +147.2469 0.7436 Td +(bevenom )Tj +/F11 19.6164 Tf +19.6164 TL +91.4335 0.6032 Td +(angelin )Tj +/F9 13.2784 Tf +13.2784 TL +94.1589 3.169 Td +(gastroenterocolostomy )Tj +/F6 20.2486 Tf +20.2486 TL +175.2744 -3.4851 Td +(antiplague )Tj +/F12 16.4208 Tf +16.4208 TL +99.0563 1.9139 Td +(prepupa )Tj +/F1 17.0399 Tf +17.0399 TL +-607.17 23.6904 Td +(prone )Tj +/F12 17.1285 Tf +17.1285 TL +43.0598 -0.0443 Td +(inconvincible )Tj +/F6 23.1156 Tf +23.1156 TL +143.8796 -2.9935 Td +(rehypothecation )Tj +/F9 23.2384 Tf +23.2384 TL +170.8933 -0.0614 Td +(ootocous )Tj +/F4 14.3204 Tf +14.3204 TL +125.4875 4.459 Td +(Cophetua )Tj +/F4 22.4497 Tf +22.4497 TL +60.8758 -4.0647 Td +(unborrowed )Tj +/F2 11.0113 Tf +11.0113 TL +-544.196 29.7192 Td +(vera )Tj +/F1 18.2352 Tf +18.2352 TL +22.3199 -3.612 Td +(jazzer )Tj +/F9 22.7881 Tf +22.7881 TL +48.0863 -2.2764 Td +(hydrophilism )Tj +/F3 22.9415 Tf +22.9415 TL +177.7471 -0.0767 Td +(uninverted )Tj +/F12 11.8894 Tf +11.8894 TL +112.8033 5.526 Td +(laurvikite )Tj +/F6 21.1483 Tf +21.1483 TL +78.4703 -4.6294 Td +(telephotograph )Tj +/F12 12.4796 Tf +12.4796 TL +146.9596 4.3344 Td +(Hampshire )Tj +/F12 15.7198 Tf +15.7198 TL +-586.3865 22.3799 Td +(Fingu )Tj +/F8 21.4842 Tf +21.4842 TL +56.5913 -2.8822 Td +(puparial )Tj +/F3 15.2796 Tf +15.2796 TL +89.5461 3.1023 Td +(plang )Tj +/F9 22.6847 Tf +22.6847 TL +40.3381 -3.7026 Td +(phototropy )Tj +/F7 10.238 Tf +10.238 TL +149.7193 6.2234 Td +(inoxidable )Tj +/F3 22.0546 Tf +22.0546 TL +53.4832 -5.9083 Td +(erepsin )Tj +/F5 12.1196 Tf +12.1196 TL +74.1255 4.9675 Td +(Melanochroid )Tj +/F6 15.9466 Tf +15.9466 TL +76.1108 -1.9135 Td +(archibenthic )Tj +/F12 15.2444 Tf +15.2444 TL +-539.9143 24.3511 Td +(Eupomatiaceae )Tj +/F2 12.5957 Tf +12.5957 TL +128.0527 1.3243 Td +(Kleinian )Tj +/F2 16.7644 Tf +16.7644 TL +46.5412 -2.0843 Td +(oscin )Tj +/F3 22.4382 Tf +22.4382 TL +39.5806 -2.8369 Td +(octennially )Tj +/F8 11.2929 Tf +11.2929 TL +110.3285 5.5726 Td +(peavy )Tj +/F2 11.7158 Tf +11.7158 TL +35.1547 -0.2114 Td +(insectiform )Tj +/F8 11.3335 Tf +11.3335 TL +55.6499 0.1911 Td +(indissuadable )Tj +/F12 13.7637 Tf +13.7637 TL +78.7342 -1.2151 Td +(superfunctional )Tj +/F9 12.8969 Tf +12.8969 TL +-494.0419 24.4334 Td +(dzeren )Tj +/F11 11.6794 Tf +11.6794 TL +54.1671 0.6087 Td +(harmonicalness )Tj +/F2 10.4387 Tf +10.4387 TL +105.1148 0.6204 Td +(Russine )Tj +/F3 15.8401 Tf +15.8401 TL +35.0845 -2.7007 Td +(herringbone )Tj +/F6 11.9366 Tf +11.9366 TL +87.5643 1.9518 Td +(colorless )Tj +/F6 18.7843 Tf +18.7843 TL +50.4083 -3.4238 Td +(astrosphere )Tj +/F4 23.1062 Tf +23.1062 TL +104.4031 -2.1609 Td +(Beguine )Tj +/F3 18.4423 Tf +18.4423 TL +85.3772 2.3319 Td +(pyopneumoperitonitis )Tj +/F8 10.118 Tf +10.118 TL +-522.1194 28.1622 Td +(Mystacocete )Tj +/F6 13.2725 Tf +13.2725 TL +63.5409 -1.5773 Td +(roof )Tj +/F5 11.2902 Tf +11.2902 TL +26.5584 0.9912 Td +(wid )Tj +/F8 18.1854 Tf +18.1854 TL +20.0739 -3.4476 Td +(capparidaceous )Tj +/F8 15.1247 Tf +15.1247 TL +143.5193 1.5304 Td +(tilmus )Tj +/F6 10.1087 Tf +10.1087 TL +48.7469 2.508 Td +(saltpan )Tj +/F7 13.0259 Tf +13.0259 TL +35.4006 -1.4586 Td +(indevoutness )Tj +/F7 13.8794 Tf +13.8794 TL +87.5862 -0.4268 Td +(diplospondylism )Tj +/F7 20.3881 Tf +20.3881 TL +114.1442 -3.2544 Td +(rectitis )Tj +/F4 15.4087 Tf +15.4087 TL +-539.5704 26.4897 Td +(overgreatness )Tj +/F1 16.2668 Tf +16.2668 TL +91.1579 -0.429 Td +(luting )Tj +/F12 21.8449 Tf +21.8449 TL +42.0334 -2.7891 Td +(appleberry )Tj +/F2 10.7182 Tf +10.7182 TL +144.1765 5.5634 Td +(diesinking )Tj +/F7 10.7782 Tf +10.7782 TL +46.7421 -0.03 Td +(Pyrausta )Tj +/F10 22.4764 Tf +22.4764 TL +48.5234 -5.8491 Td +(hod )Tj +/F4 21.4475 Tf +21.4475 TL +53.9434 0.5144 Td +(occipitohyoid )Tj +/F4 10.7589 Tf +10.7589 TL +123.3233 5.3443 Td +(syndactyl )Tj +/F8 16.1492 Tf +16.1492 TL +43.9286 -2.6951 Td +(Manvantara )Tj +/F2 15.9956 Tf +15.9956 TL +-593.8286 24.0768 Td +(swiveleye )Tj +/F5 17.5353 Tf +17.5353 TL +65.2939 -0.7699 Td +(hepatology )Tj +/F8 11.7266 Tf +11.7266 TL +90.6575 2.9044 Td +(ventriloquism )Tj +/F10 15.0013 Tf +15.0013 TL +80.1512 -1.6374 Td +(ithyphallic )Tj +/F11 11.622 Tf +11.622 TL +108.0095 1.6897 Td +(denaturization )Tj +/F12 20.4049 Tf +20.4049 TL +104.598 -4.3914 Td +(Aedes )Tj +/F6 23.0422 Tf +23.0422 TL +73.4575 -1.3187 Td +(cerebroma )Tj +/F12 19.2302 Tf +19.2302 TL +-522.1675 25.906 Td +(Uragoga )Tj +/F11 18.5029 Tf +18.5029 TL +92.3048 0.3636 Td +(trimetrical )Tj +/F7 20.094 Tf +20.094 TL +133.2208 -0.7956 Td +(weever )Tj +/F6 16.0077 Tf +16.0077 TL +73.7249 2.0432 Td +(Antedon )Tj +/F8 18.5364 Tf +18.5364 TL +64.0786 -1.2644 Td +(gyromele )Tj +/F4 19.0942 Tf +19.0942 TL +87.5659 -0.2789 Td +(numerableness )Tj +/F8 16.7529 Tf +16.7529 TL +123.5965 1.1706 Td +(overmarch )Tj +/F9 15.4326 Tf +15.4326 TL +-574.4915 24.6602 Td +(ultranice )Tj +/F3 19.7513 Tf +19.7513 TL +92.5954 -2.1594 Td +(punishability )Tj +/F5 20.9141 Tf +20.9141 TL +115.8216 -0.5814 Td +(anodontia )Tj +/F3 10.4621 Tf +10.4621 TL +97.669 5.226 Td +(Floridan )Tj +/F11 23.4154 Tf +23.4154 TL +41.5661 -6.4767 Td +(rovingly )Tj +/F9 10.7712 Tf +10.7712 TL +126.4434 6.3221 Td +(phragmocone )Tj +/F1 11.5577 Tf +11.5577 TL +77.5528 -0.3932 Td +(anicut )Tj +/F10 14.8199 Tf +14.8199 TL +31.1365 -1.6311 Td +(coenospecifically )Tj +/F1 13.943 Tf +13.943 TL +-582.7849 24.4385 Td +(snuff )Tj +/F6 16.2413 Tf +16.2413 TL +32.1386 -1.1491 Td +(arioso )Tj +/F6 10.4877 Tf +10.4877 TL +48.74 2.8768 Td +(endite )Tj +/F8 19.3024 Tf +19.3024 TL +31.484 -4.4074 Td +(frecken )Tj +/F2 21.393 Tf +21.393 TL +74.0246 -1.0453 Td +(personalia )Tj +/F9 12.3749 Tf +12.3749 TL +96.8674 4.5091 Td +(misinclination )Tj +/F11 18.3571 Tf +18.3571 TL +111.3737 -2.9911 Td +(calorimetry )Tj +/F6 22.4089 Tf +22.4089 TL +132.1711 -2.0259 Td +(advocator )Tj +/F7 21.2048 Tf +21.2048 TL +-526.7993 24.602 Td +(bulbilla )Tj +/F7 13.9517 Tf +13.9517 TL +80.133 3.6266 Td +(zeppelin )Tj +/F10 23.2613 Tf +23.2613 TL +59.6991 -4.6548 Td +(hasteless )Tj +/F7 16.6415 Tf +16.6415 TL +139.5678 3.3099 Td +(collyrium )Tj +/F2 21.7549 Tf +21.7549 TL +78.6147 -2.5567 Td +(copartnership )Tj +/F11 18.2914 Tf +18.2914 TL +127.5056 1.7317 Td +(monodram )Tj +/F11 12.1088 Tf +12.1088 TL +98.7737 3.0913 Td +(preballot )Tj +/F3 10.9615 Tf +10.9615 TL +-584.294 24.5737 Td +(alani )Tj +/F12 21.4327 Tf +21.4327 TL +25.891 -5.2356 Td +(parallelotropism )Tj +/F7 12.9842 Tf +12.9842 TL +218.6133 4.2242 Td +(cephalodiscid )Tj +/F5 23.976 Tf +23.976 TL +90.2013 -5.4959 Td +(subindices )Tj +/F12 18.5535 Tf +18.5535 TL +119.9278 2.7112 Td +(rivalize )Tj +/F8 23.4069 Tf +23.4069 TL +100.1891 -2.4267 Td +(damme )Tj +/F4 10.262 Tf +10.262 TL +-554.8225 30.5724 Td +(extravagancy )Tj +/F11 17.6412 Tf +17.6412 TL +58.9965 -3.6896 Td +(superpositive )Tj +/F8 12.8495 Tf +12.8495 TL +148.1865 2.3959 Td +(chiggak )Tj +/F12 22.7033 Tf +22.7033 TL +52.1305 -4.9269 Td +(conscriptional )Tj +/F9 20.7563 Tf +20.7563 TL +204.3294 0.9735 Td +(doomful )Tj +/F6 19.211 Tf +19.211 TL +99.6303 0.7727 Td +(ensorcelize )Tj +/F12 18.4285 Tf +18.4285 TL +-563.2733 24.3913 Td +(Hydroidea )Tj +/F7 17.9171 Tf +17.9171 TL +110.5708 0.2557 Td +(inofficiosity )Tj +/F3 14.5588 Tf +14.5588 TL +105.5316 1.6791 Td +(megachilid )Tj +/F9 12.3268 Tf +12.3268 TL +71.5858 1.116 Td +(rabbithearted )Tj +/F8 16.1862 Tf +16.1862 TL +103.5452 -1.9297 Td +(adawlut )Tj +/F12 18.1589 Tf +18.1589 TL +64.7609 -0.9864 Td +(cavalier )Tj +/F4 22.8732 Tf +22.8732 TL +98.058 -2.3572 Td +(tetramastia )Tj +/F10 19.0114 Tf +19.0114 TL +-554.0523 25.9309 Td +(Desmarestiaceae )Tj +/F11 22.0214 Tf +22.0214 TL +182.509 -1.505 Td +(vicegerency )Tj +/F2 17.0655 Tf +17.0655 TL +158.5544 2.478 Td +(predisregard )Tj +/F5 23.7085 Tf +23.7085 TL +93.3822 -3.3215 Td +(hoofless )Tj +/F5 10.2462 Tf +10.2462 TL +94.8815 6.7312 Td +(plunderess )Tj +/F8 20.5369 Tf +20.5369 TL +52.9624 -5.1453 Td +(forename )Tj +/F7 13.5301 Tf +13.5301 TL +-582.2895 27.5034 Td +(teller )Tj +/F3 15.794 Tf +15.794 TL +36.0983 -1.1319 Td +(unsobriety )Tj +/F9 14.6721 Tf +14.6721 TL +75.9059 0.5609 Td +(revisionary )Tj +/F1 15.889 Tf +15.889 TL +105.6393 -0.6084 Td +(intractableness )Tj +/F7 23.1779 Tf +23.1779 TL +98.4003 -3.6445 Td +(affordable )Tj +/F8 12.1882 Tf +12.1882 TL +118.4853 5.4948 Td +(hambroline )Tj +/F3 20.9647 Tf +20.9647 TL +69.0826 -4.3883 Td +(Cahuapana )Tj +/F1 23.4713 Tf +23.4713 TL +-503.6117 22.7467 Td +(distrustful )Tj +/F11 21.9872 Tf +21.9872 TL +101.0676 0.7421 Td +(druidess )Tj +/F4 14.2557 Tf +14.2557 TL +118.7311 3.8658 Td +(philocalic )Tj +/F1 23.1413 Tf +23.1413 TL +61.3849 -4.4428 Td +(phiz )Tj +/F12 20.2052 Tf +20.2052 TL +45.6346 1.468 Td +(Wappo )Tj +/F9 19.598 Tf +19.598 TL +72.7386 0.3036 Td +(Hadhramautian )Tj +/F7 14.8146 Tf +14.8146 TL +164.6229 2.3917 Td +(atrip )Tj +/F2 22.4411 Tf +22.4411 TL +36.2217 -3.8133 Td +(expropriate )Tj +/F12 17.1658 Tf +17.1658 TL +-600.4013 26.6376 Td +(fieldward )Tj +/F11 12.4539 Tf +12.4539 TL +102.995 2.356 Td +(Cycadofilices )Tj +/F9 11.2095 Tf +11.2095 TL +104.613 0.6222 Td +(Schrebera )Tj +/F5 16.7393 Tf +16.7393 TL +67.2568 -2.7649 Td +(cup )Tj +/F10 13.6034 Tf +13.6034 TL +31.6373 1.5679 Td +(unimpulsive )Tj +/F6 21.2249 Tf +21.2249 TL +97.9447 -3.8108 Td +(rauli )Tj +/F9 20.3561 Tf +20.3561 TL +45.9944 0.4344 Td +(kras )Tj +/F5 17.8963 Tf +17.8963 TL +61.0684 1.2299 Td +(lincloth )Tj +/F5 19.59 Tf +19.59 TL +60.6684 -0.8468 Td +(arabinose )Tj +/F3 20.4149 Tf +20.4149 TL +-572.1781 23.5876 Td +(shapingly )Tj +/F9 12.8709 Tf +12.8709 TL +89.07 3.772 Td +(siphonate )Tj +/F9 12.384 Tf +12.384 TL +77.2252 0.2434 Td +(Euphorbia )Tj +/F10 18.5343 Tf +18.5343 TL +74.3041 -3.0751 Td +(V )Tj +/F6 18.3745 Tf +18.3745 TL +22.2412 0.0799 Td +(epicoracoid )Tj +/F6 16.1168 Tf +16.1168 TL +99.0567 1.1288 Td +(quill )Tj +/F3 21.4985 Tf +21.4985 TL +33.1361 -2.6909 Td +(lunation )Tj +/F2 18.219 Tf +18.219 TL +81.8449 1.6397 Td +(corruptingly )Tj +/F2 14.8684 Tf +14.8684 TL +95.65 1.6753 Td +(beautied )Tj +/F12 23.5561 Tf +23.5561 TL +-572.5281 19.6561 Td +(wakeful )Tj +/F5 18.3539 Tf +18.3539 TL +113.0695 2.6011 Td +(trochleariform )Tj +/F7 23.1231 Tf +23.1231 TL +117.2814 -2.3846 Td +(honorworthy )Tj +/F2 13.2422 Tf +13.2422 TL +147.7334 4.9404 Td +(exactress )Tj +/F4 15.9398 Tf +15.9398 TL +52.5849 -1.3488 Td +(diaglyphic )Tj +/F10 21.7943 Tf +21.7943 TL +72.1753 -2.9273 Td +(propugnaculum )Tj +/F4 16.8 Tf +16.8 TL +-502.8446 26.4972 Td +(huffiness )Tj +/F10 14.999 Tf +14.999 TL +68.6111 0.9005 Td +(indecorousness )Tj +/F8 15.1197 Tf +15.1197 TL +134.9911 -0.0603 Td +(amimide )Tj +/F12 23.5512 Tf +23.5512 TL +65.5437 -4.2158 Td +(iambus )Tj +/F10 14.371 Tf +14.371 TL +98.9151 4.5901 Td +(preconcentratedly )Tj +/F3 20.6764 Tf +20.6764 TL +155.2072 -3.1527 Td +(salep )Tj +/F6 10.8967 Tf +10.8967 TL +49.9748 4.8898 Td +(culverineer )Tj +/F3 22.1215 Tf +22.1215 TL +-573.2429 18.3876 Td +(trisceptral )Tj +/F8 20.9153 Tf +20.9153 TL +103.8164 0.6031 Td +(unsuccessful )Tj +/F9 15.8948 Tf +15.8948 TL +139.4842 2.5103 Td +(tinchill )Tj +/F3 10.7349 Tf +10.7349 TL +85.832 2.5799 Td +(unslain )Tj +/F1 19.5539 Tf +19.5539 TL +36.1016 -4.4095 Td +(oathful )Tj +/F3 10.173 Tf +10.173 TL +60.2846 4.6904 Td +(unheelpieced )Tj +/F4 12.859 Tf +12.859 TL +59.0644 -1.343 Td +(clinopyroxene )Tj +/F11 19.0787 Tf +19.0787 TL +78.2216 -3.1098 Td +(cone )Tj +ET +Q +0.7163 0.6978 -0.6978 0.7163 60.0977 12.1894 cm +BT +/F0 103.1391 Tf +1 Tr +0 TL +0 0 Td +( )Tj +ET + +endstream +endobj +3 0 obj +<< +/Parent 1 0 R +/Resources 4 0 R +/MediaBox [0 0 612 600] +/pdftk_PageNum 1 +/Type /Page +/Contents 47 0 R +>> +endobj +1 0 obj +<< +/Kids [3 0 R] +/Count 1 +/Type /Pages +>> +endobj +48 0 obj +<< +/Pages 1 0 R +/Type /Catalog +>> +endobj +49 0 obj +<< +/Creator (þÿpdftk 1.41 - www.pdftk.com) +/Producer (itext-paulo-155 \(itextpdf.sf.net-lowagie.com\)) +/ModDate (D:20091006121825-07'00') +/CreationDate (D:20091006121825-07'00') +>> +endobj xref +0 50 +0000000000 65535 f +0000066099 00000 n +0000000000 65536 n +0000065975 00000 n +0000010583 00000 n +0000000594 00000 n +0000000015 00000 n +0000000198 00000 n +0000000908 00000 n +0000000702 00000 n +0000001228 00000 n +0000001030 00000 n +0000001542 00000 n +0000001345 00000 n +0000001850 00000 n +0000001662 00000 n +0000002164 00000 n +0000001962 00000 n +0000002477 00000 n +0000002283 00000 n +0000002783 00000 n +0000002590 00000 n +0000003100 00000 n +0000002898 00000 n +0000003412 00000 n +0000003222 00000 n +0000003719 00000 n +0000003526 00000 n +0000009937 00000 n +0000003888 00000 n +0000003834 00000 n +0000003928 00000 n +0000009787 00000 n +0000006223 00000 n +0000006525 00000 n +0000006725 00000 n +0000007099 00000 n +0000007420 00000 n +0000007813 00000 n +0000008210 00000 n +0000008279 00000 n +0000008682 00000 n +0000009000 00000 n +0000009423 00000 n +0000009549 00000 n +0000010465 00000 n +0000010271 00000 n +0000010779 00000 n +0000066158 00000 n +0000066210 00000 n +trailer + +<< +/Info 49 0 R +/Root 48 0 R +/Size 50 +/ID [<83763daa3b5c2c0ee12ec53a547b32f4>] +>> +startxref +66434 +%%EOF diff -Nru swftools-0.9.2+ds1/spec/fonts.py swftools-0.9.1/spec/fonts.py --- swftools-0.9.2+ds1/spec/fonts.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/fonts.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,47 @@ +from sys import * +from pdflib_py import * +import md5 +import random +p = PDF_new() +PDF_open_file(p, "fonts.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") + +PDF_set_info(p, "Creator", "smalltext.py") +PDF_begin_page(p, 612, 600) + +fonts = [] +fonts += [PDF_load_font(p, "Times-Roman", "host", "")] +fonts += [PDF_load_font(p, "Times-Italic", "host", "")] +fonts += [PDF_load_font(p, "Times-Bold", "host", "")] +fonts += [PDF_load_font(p, "Times-BoldItalic", "host", "")] +fonts += [PDF_load_font(p, "Helvetica", "host", "")] +fonts += [PDF_load_font(p, "Helvetica-Oblique", "host", "")] +fonts += [PDF_load_font(p, "Helvetica-Bold", "host", "")] +fonts += [PDF_load_font(p, "Helvetica-BoldOblique", "host", "")] +fonts += [PDF_load_font(p, "Courier", "host", "")] +fonts += [PDF_load_font(p, "Courier-Oblique", "host", "")] +fonts += [PDF_load_font(p, "Courier-Bold", "host", "")] +fonts += [PDF_load_font(p, "Courier-BoldOblique", "host", "")] +#fonts += [PDF_load_font(p, "Symbol", "host", "")] +#fonts += [PDF_load_font(p, "ZapfDingbats", "host", "")] + +words = list(open("/usr/share/dict/words", "rb").readlines()) + +i = 0 +# the idea is to overflow the placetext matrix once, so that +# we have at least two different ty values +for y in range(3000 / 24): + x = 0 + while x < 612: + font = fonts[random.randint(0,len(fonts)-1)] + fontsize = 10+14*random.random() + PDF_setfont(p, font, fontsize) + PDF_set_text_pos(p, x, y*24+(24-fontsize)/2); + text = words[random.randint(0,len(words)-1)] + x += PDF_stringwidth(p, text, font, fontsize) + PDF_show(p, text) + +PDF_end_page(p) +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/gradients.pdf swftools-0.9.1/spec/gradients.pdf --- swftools-0.9.2+ds1/spec/gradients.pdf 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/gradients.pdf 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,361 @@ +%PDF-1.6 +%äãÏÒ +1 0 obj +[/PDF/ImageB/ImageC/ImageI/Text] +endobj +4 0 obj +<> +stream +0 0 0 rg + +endstream +endobj +5 0 obj +9 +endobj +6 0 obj +<>>> +endobj +7 0 obj +<> +stream + +endstream +endobj +8 0 obj +0 +endobj +9 0 obj +<> +endobj +10 0 obj +<> +stream +/Pattern cs/P0 scn +0 0 m +80 80 80 240 0 320 c +80 240 240 240 320 320 c +240 240 240 80 320 0 c +240 80 80 80 0 0 c +f +0 0 m +80 80 80 240 0 320 c +80 240 240 240 320 320 c +240 240 240 80 320 0 c +240 80 80 80 0 0 c +S +0 0 0.4 rg + +endstream +endobj +11 0 obj +222 +endobj +12 0 obj +<>>> +endobj +13 0 obj +<> +stream + +endstream +endobj +14 0 obj +0 +endobj +15 0 obj +<> +endobj +16 0 obj +<> +stream +/Pattern cs/P1 scn +200 0 m +280 80 280 240 200 320 c +280 240 440 240 520 320 c +440 240 440 80 520 0 c +440 80 280 80 200 0 c +f +200 0 m +280 80 280 240 200 320 c +280 240 440 240 520 320 c +440 240 440 80 520 0 c +440 80 280 80 200 0 c +S +0 0 0.4 rg + +endstream +endobj +17 0 obj +242 +endobj +18 0 obj +<>>> +endobj +19 0 obj +<> +stream + +endstream +endobj +20 0 obj +0 +endobj +21 0 obj +<> +endobj +22 0 obj +<> +stream +/Pattern cs/P2 scn +580 80 m +580 640 l +660 640 l +660 80 l +580 80 l +f +580 80 m +580 640 l +660 640 l +660 80 l +580 80 l +S +0 0 0.4 rg + +endstream +endobj +23 0 obj +128 +endobj +24 0 obj +<>>> +endobj +25 0 obj +<> +stream + +endstream +endobj +26 0 obj +0 +endobj +27 0 obj +<> +endobj +28 0 obj +<> +stream +/Pattern cs/P3 scn +680 80 m +680 640 l +760 640 l +760 80 l +680 80 l +f +680 80 m +680 640 l +760 640 l +760 80 l +680 80 l +S +0 0 0.4 rg + +endstream +endobj +29 0 obj +128 +endobj +30 0 obj +<>>> +endobj +31 0 obj +<> +stream + +endstream +endobj +32 0 obj +0 +endobj +33 0 obj +<> +endobj +34 0 obj +<> +stream +/Pattern cs/P4 scn +130 380 m +130 460 l +450 460 l +450 380 l +130 380 l +f +130 380 m +130 460 l +450 460 l +450 380 l +130 380 l +S + +endstream +endobj +35 0 obj +123 +endobj +36 0 obj +[ 4 0 R 7 0 R 10 0 R 13 0 R 16 0 R 19 0 R 22 0 R 25 0 R 28 0 R 31 0 R 34 0 R] +endobj +37 0 obj +<> +/Shading<> +>> +endobj +38 0 obj +<> +endobj +3 0 obj +<> +endobj +2 0 obj +<> +endobj +39 0 obj +<> +endobj +xref +0 40 +0000000000 65535 f +0000000015 00000 n +0000003386 00000 n +0000003282 00000 n +0000000063 00000 n +0000000124 00000 n +0000000141 00000 n +0000000317 00000 n +0000000369 00000 n +0000000386 00000 n +0000000436 00000 n +0000000712 00000 n +0000000732 00000 n +0000000903 00000 n +0000000957 00000 n +0000000975 00000 n +0000001027 00000 n +0000001323 00000 n +0000001343 00000 n +0000001522 00000 n +0000001576 00000 n +0000001594 00000 n +0000001646 00000 n +0000001828 00000 n +0000001848 00000 n +0000002020 00000 n +0000002074 00000 n +0000002092 00000 n +0000002144 00000 n +0000002326 00000 n +0000002346 00000 n +0000002519 00000 n +0000002573 00000 n +0000002591 00000 n +0000002643 00000 n +0000002820 00000 n +0000002840 00000 n +0000002934 00000 n +0000003109 00000 n +0000003440 00000 n +trailer +<] +>> +startxref +3488 +%%EOF diff -Nru swftools-0.9.2+ds1/spec/gradients.py swftools-0.9.1/spec/gradients.py --- swftools-0.9.2+ds1/spec/gradients.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/gradients.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,114 @@ +from sys import * +from pdflib_py import * +p = PDF_new() +PDF_open_file(p, "gradients.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") +PDF_set_value(p, "compress", 0) + +PDF_set_info(p, "Author", "pdflib") +PDF_set_info(p, "Creator", "pdflib_py") +PDF_set_info(p, "Title", "gradients") + +width = 1024 +height = 800 +PDF_begin_page(p, width, height) + +type,x,params = "radial",0,"r0=0 r1=320" +y = 0 +PDF_setcolor(p, "fill", "rgb", 0.0, 0.0, 0.0, 1.0) +shading = PDF_shading(p, type, 160+x,160+y, 160+x, 160+y, 1.0, 1.0, 1.0, 1.0, params) #axial|radial +pattern = PDF_shading_pattern(p,shading,"") +PDF_setcolor(p, "fill", "pattern", pattern,0,0,0) +PDF_moveto(p, x,y) +PDF_curveto(p, x+80, y+80, x+80, y+240, x, y+320) +PDF_curveto(p, x+80, y+240, x+240, y+240, x+320, y+320) +PDF_curveto(p, x+240, y+240, x+240, y+80, x+320, y) +PDF_curveto(p, x+240, y+80, x+80, y+80, x, y) +PDF_fill(p) +PDF_moveto(p, x,y) +PDF_curveto(p, x+80, y+80, x+80, y+240, x, y+320) +PDF_curveto(p, x+80, y+240, x+240, y+240, x+320, y+320) +PDF_curveto(p, x+240, y+240, x+240, y+80, x+320, y) +PDF_curveto(p, x+240, y+80, x+80, y+80, x, y) +PDF_stroke(p) + +type,x,params = "axial",200,"" +y = 0 +PDF_setcolor(p, "fill", "rgb", 0.0, 0.0, 0.4, 1.0) +shading = PDF_shading(p, type, 0+x,0+y, 320+x,320+y, 1.0, 1.0, 1.0, 1.0, params) #axial|radial +pattern = PDF_shading_pattern(p,shading,"") +PDF_setcolor(p, "fill", "pattern", pattern,0,0,0) +PDF_moveto(p, x,y) +PDF_curveto(p, x+80, y+80, x+80, y+240, x, y+320) +PDF_curveto(p, x+80, y+240, x+240, y+240, x+320, y+320) +PDF_curveto(p, x+240, y+240, x+240, y+80, x+320, y) +PDF_curveto(p, x+240, y+80, x+80, y+80, x, y) +PDF_fill(p) +PDF_moveto(p, x,y) +PDF_curveto(p, x+80, y+80, x+80, y+240, x, y+320) +PDF_curveto(p, x+80, y+240, x+240, y+240, x+320, y+320) +PDF_curveto(p, x+240, y+240, x+240, y+80, x+320, y) +PDF_curveto(p, x+240, y+80, x+80, y+80, x, y) +PDF_stroke(p) + +type,x,params = "radial",500,"r0=0 r1=220" +y = 0 +PDF_setcolor(p, "fill", "rgb", 0.0, 0.0, 0.4, 1.0) +shading = PDF_shading(p, type, 120+x, 340+y, 120+x, 340+y, 1.0, 1.0, 1.0, 1.0, params) #axial|radial +pattern = PDF_shading_pattern(p,shading,"") +PDF_setcolor(p, "fill", "pattern", pattern,0,0,0) +PDF_moveto(p, x+80, y+80) +PDF_lineto(p, x+80, y+640) +PDF_lineto(p, x+160, y+640) +PDF_lineto(p, x+160, y+80) +PDF_lineto(p, x+80, y+80) +PDF_fill(p) +PDF_moveto(p, x+80, y+80) +PDF_lineto(p, x+80, y+640) +PDF_lineto(p, x+160, y+640) +PDF_lineto(p, x+160, y+80) +PDF_lineto(p, x+80, y+80) +PDF_stroke(p) + +type,x,params = "axial",600,"" +y = 0 +PDF_setcolor(p, "fill", "rgb", 0.0, 0.0, 0.4, 1.0) +shading = PDF_shading(p, type, 80+x, 80+y, 80+x, 640+y, 1.0, 1.0, 1.0, 1.0, params) #axial|radial +pattern = PDF_shading_pattern(p,shading,"") +PDF_setcolor(p, "fill", "pattern", pattern,0,0,0) +PDF_moveto(p, x+80, y+80) +PDF_lineto(p, x+80, y+640) +PDF_lineto(p, x+160, y+640) +PDF_lineto(p, x+160, y+80) +PDF_lineto(p, x+80, y+80) +PDF_fill(p) +PDF_moveto(p, x+80, y+80) +PDF_lineto(p, x+80, y+640) +PDF_lineto(p, x+160, y+640) +PDF_lineto(p, x+160, y+80) +PDF_lineto(p, x+80, y+80) +PDF_stroke(p) + +type,x,params = "axial",50,"" +y = 300 +PDF_setcolor(p, "fill", "rgb", 0.0, 0.0, 0.4, 1.0) +shading = PDF_shading(p, type, 80+x, 80+y, 400+x, 80+y, 1.0, 1.0, 1.0, 1.0, params) #axial|radial +pattern = PDF_shading_pattern(p,shading,"") +PDF_setcolor(p, "fill", "pattern", pattern,0,0,0) +PDF_moveto(p, x+80, y+80) +PDF_lineto(p, x+80, y+160) +PDF_lineto(p, x+400, y+160) +PDF_lineto(p, x+400, y+80) +PDF_lineto(p, x+80, y+80) +PDF_fill(p) +PDF_moveto(p, x+80, y+80) +PDF_lineto(p, x+80, y+160) +PDF_lineto(p, x+400, y+160) +PDF_lineto(p, x+400, y+80) +PDF_lineto(p, x+80, y+80) +PDF_stroke(p) + +PDF_end_page(p) +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/gradients.spec.rb swftools-0.9.1/spec/gradients.spec.rb --- swftools-0.9.2+ds1/spec/gradients.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/gradients.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,35 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + + convert_file "gradients.pdf" do + pixel_at(269,324).should_be_brighter_than pixel_at(155,438) + pixel_at(261,388).should_be_brighter_than pixel_at(209,434) + pixel_at(195,329).should_be_brighter_than pixel_at(164,367) + pixel_at(33,318).should_be_brighter_than pixel_at(92,381) + pixel_at(168,310).should_be_brighter_than pixel_at(108,381) + pixel_at(166,455).should_be_brighter_than pixel_at(109,401) + pixel_at(25,454).should_be_brighter_than pixel_at(89,396) + pixel_at(258,210).should_be_brighter_than pixel_at(90,215) + pixel_at(259,225).should_be_brighter_than pixel_at(95,227) + pixel_at(257,240).should_be_brighter_than pixel_at(102,240) + pixel_at(359,121).should_be_brighter_than pixel_at(360,270) + pixel_at(383,119).should_be_brighter_than pixel_at(385,181) + pixel_at(373,167).should_be_brighter_than pixel_at(373,239) + pixel_at(355,409).should_be_brighter_than pixel_at(356,349) + pixel_at(370,377).should_be_brighter_than pixel_at(369,316) + pixel_at(382,333).should_be_brighter_than pixel_at(383,286) + pixel_at(422,115).should_be_brighter_than pixel_at(422,411) + pixel_at(437,190).should_be_brighter_than pixel_at(436,318) + pixel_at(447,276).should_be_brighter_than pixel_at(446,413) + pixel_at(413,101).should_be_the_same_as pixel_at(448,101) + pixel_at(412,166).should_be_the_same_as pixel_at(449,166) + pixel_at(412,246).should_be_the_same_as pixel_at(450,246) + pixel_at(413,332).should_be_the_same_as pixel_at(450,332) + pixel_at(414,400).should_be_the_same_as pixel_at(451,400) + pixel_at(87,245).should_be_the_same_as pixel_at(87,212) + pixel_at(143,245).should_be_the_same_as pixel_at(143,209) + pixel_at(189,246).should_be_the_same_as pixel_at(189,210) + pixel_at(236,244).should_be_the_same_as pixel_at(236,208) + end +end Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/spec/imagematrix.pdf and /tmp/M5qDI_SGQH/swftools-0.9.1/spec/imagematrix.pdf differ diff -Nru swftools-0.9.2+ds1/spec/imagematrix.py swftools-0.9.1/spec/imagematrix.py --- swftools-0.9.2+ds1/spec/imagematrix.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/imagematrix.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,51 @@ +from sys import * +from pdflib_py import * +from math import sin,cos +p = PDF_new() +PDF_open_file(p, "imagematrix.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") + +width = 612 +height = 600 +PDF_begin_page(p, width, height) + +a=0.7 +b=-0.7 +matrices = [[1,0,0,1,100,200], + [cos(a),sin(a),-sin(a),cos(a),400,75], + [1,0,0,-1,100,350], + [-1,0,0,1,450,370], + [1.9,0.5,0.6,1.4,50,-200], + [cos(b),sin(b),sin(b),-cos(b),500,630], + [1.0,0,0,3,-90,-200], + ] + +i = PDF_load_image(p, "png", "karo.png", "") + +for m in matrices: + PDF_save(p) + PDF_setmatrix(p, m[0],m[1],m[2],m[3],m[4],m[5]) + + x,y = 100,100 + #PDF_fit_image(p, i, x, y, "") + PDF_place_image(p, i, x, y, 100/4) + w,h = 100,100 + + PDF_setrgbcolor_fill(p, 0.0, 1.0, 1.0) + PDF_moveto(p, x,y) + PDF_lineto(p, x+w,y) + PDF_lineto(p, x+w,y+h) + PDF_lineto(p, x,y+h) + PDF_lineto(p, x,y) + PDF_moveto(p, x-20,y-20) + PDF_lineto(p, x-20,y+20+h) + PDF_lineto(p, x+20+w,y+20+h) + PDF_lineto(p, x+20+w,y-20) + PDF_lineto(p, x-20,y-20) + PDF_fill(p); + PDF_restore(p) + +PDF_end_page(p) +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/imagematrix.spec.rb swftools-0.9.1/spec/imagematrix.spec.rb --- swftools-0.9.2+ds1/spec/imagematrix.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/imagematrix.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,119 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + + convert_file "imagematrix.pdf" do + pixel_at(22,239).should_be_of_color 0xff00ff + pixel_at(45,240).should_be_of_color 0x0000ff + pixel_at(72,239).should_be_of_color 0xffff00 + pixel_at(98,236).should_be_of_color 0xff0000 + pixel_at(99,312).should_be_of_color 0xffffff + pixel_at(80,312).should_be_of_color 0xff00ff + pixel_at(46,312).should_be_of_color 0x00ffff + pixel_at(26,314).should_be_of_color 0x0000ff + pixel_at(21,385).should_be_of_color 0xffff00 + pixel_at(46,384).should_be_of_color 0xff00ff + pixel_at(71,384).should_be_of_color 0x00ff00 + pixel_at(95,383).should_be_of_color 0x0000ff + pixel_at(97,459).should_be_of_color 0x00ffff + pixel_at(75,460).should_be_of_color 0x0000ff + pixel_at(50,460).should_be_of_color 0xffffff + pixel_at(23,461).should_be_of_color 0x00ff00 + pixel_at(216,436).should_be_of_color 0xff00ff + pixel_at(213,415).should_be_of_color 0x0000ff + pixel_at(214,386).should_be_of_color 0xffff00 + pixel_at(216,360).should_be_of_color 0x00ff00 + pixel_at(234,364).should_be_of_color 0xffffff + pixel_at(235,388).should_be_of_color 0xff00ff + pixel_at(233,416).should_be_of_color 0x00ffff + pixel_at(237,431).should_be_of_color 0x0000ff + pixel_at(260,433).should_be_of_color 0xffff00 + pixel_at(263,414).should_be_of_color 0xff00ff + pixel_at(261,393).should_be_of_color 0x00ff00 + pixel_at(263,365).should_be_of_color 0x0000ff + pixel_at(291,363).should_be_of_color 0x00ffff + pixel_at(288,390).should_be_of_color 0x0000ff + pixel_at(285,412).should_be_of_color 0xffffff + pixel_at(285,437).should_be_of_color 0xff0000 + pixel_at(286,287).should_be_of_color 0x00ffff + pixel_at(265,287).should_be_of_color 0x0000ff + pixel_at(244,290).should_be_of_color 0xffffff + pixel_at(219,290).should_be_of_color 0x00ff00 + pixel_at(209,270).should_be_of_color 0xffff00 + pixel_at(238,266).should_be_of_color 0xff00ff + pixel_at(266,265).should_be_of_color 0x00ff00 + pixel_at(283,265).should_be_of_color 0x0000ff + pixel_at(289,236).should_be_of_color 0xffffff + pixel_at(264,237).should_be_of_color 0xff00ff + pixel_at(238,241).should_be_of_color 0x00ffff + pixel_at(216,235).should_be_of_color 0x0000ff + pixel_at(210,213).should_be_of_color 0xff00ff + pixel_at(238,213).should_be_of_color 0x0000ff + pixel_at(267,211).should_be_of_color 0xffff00 + pixel_at(287,211).should_be_of_color 0xff0000 + pixel_at(257,118).should_be_of_color 0x00ffff + pixel_at(262,96).should_be_of_color 0x0000ff + pixel_at(263,69).should_be_of_color 0xffffff + pixel_at(262,43).should_be_of_color 0xff0000 + pixel_at(285,41).should_be_of_color 0xffff00 + pixel_at(290,67).should_be_of_color 0xff00ff + pixel_at(288,92).should_be_of_color 0x00ff00 + pixel_at(285,115).should_be_of_color 0x0000ff + pixel_at(312,120).should_be_of_color 0xffffff + pixel_at(311,94).should_be_of_color 0xff00ff + pixel_at(310,69).should_be_of_color 0x00ffff + pixel_at(311,45).should_be_of_color 0x0000ff + pixel_at(335,44).should_be_of_color 0xff00ff + pixel_at(335,67).should_be_of_color 0x0000ff + pixel_at(337,94).should_be_of_color 0xffff00 + pixel_at(337,119).should_be_of_color 0x00ff00 + pixel_at(367,310).should_be_of_color 0xff00ff + pixel_at(390,290).should_be_of_color 0x0000ff + pixel_at(406,277).should_be_of_color 0xffff00 + pixel_at(426,260).should_be_of_color 0xff0000 + pixel_at(438,280).should_be_of_color 0xffffff + pixel_at(418,296).should_be_of_color 0xff00ff + pixel_at(404,308).should_be_of_color 0x00ffff + pixel_at(380,324).should_be_of_color 0x0000ff + pixel_at(401,344).should_be_of_color 0xffff00 + pixel_at(415,330).should_be_of_color 0xff00ff + pixel_at(434,314).should_be_of_color 0x00ff00 + pixel_at(451,301).should_be_of_color 0x0000ff + pixel_at(472,316).should_be_of_color 0x00ffff + pixel_at(452,333).should_be_of_color 0x0000ff + pixel_at(434,349).should_be_of_color 0xffffff + pixel_at(415,362).should_be_of_color 0x00ff00 + pixel_at(375,484).should_be_of_color 0xff00ff + pixel_at(360,518).should_be_of_color 0x0000ff + pixel_at(343,552).should_be_of_color 0xffff00 + pixel_at(334,585).should_be_of_color 0x00ff00 + pixel_at(379,574).should_be_of_color 0xffffff + pixel_at(392,538).should_be_of_color 0xff00ff + pixel_at(406,505).should_be_of_color 0x00ffff + pixel_at(420,472).should_be_of_color 0x0000ff + pixel_at(468,456).should_be_of_color 0xffff00 + pixel_at(455,496).should_be_of_color 0xff00ff + pixel_at(438,527).should_be_of_color 0x00ff00 + pixel_at(427,558).should_be_of_color 0x0000ff + pixel_at(515,443).should_be_of_color 0xff0000 + pixel_at(504,480).should_be_of_color 0xffffff + pixel_at(489,512).should_be_of_color 0x0000ff + pixel_at(477,547).should_be_of_color 0x00ffff + pixel_at(520,238).should_be_of_color 0xff0000 + pixel_at(503,222).should_be_of_color 0xffff00 + pixel_at(486,204).should_be_of_color 0x0000ff + pixel_at(463,187).should_be_of_color 0xff00ff + pixel_at(478,168).should_be_of_color 0x0000ff + pixel_at(500,148).should_be_of_color 0xffff00 + pixel_at(516,130).should_be_of_color 0x00ff00 + pixel_at(536,146).should_be_of_color 0xffffff + pixel_at(517,165).should_be_of_color 0xff00ff + pixel_at(501,187).should_be_of_color 0x00ffff + pixel_at(518,198).should_be_of_color 0xff00ff + pixel_at(533,183).should_be_of_color 0x00ff00 + pixel_at(551,163).should_be_of_color 0x0000ff + pixel_at(572,178).should_be_of_color 0x00ffff + pixel_at(553,197).should_be_of_color 0x0000ff + pixel_at(538,216).should_be_of_color 0xffffff + end +end Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/spec/layers2.pdf and /tmp/M5qDI_SGQH/swftools-0.9.1/spec/layers2.pdf differ diff -Nru swftools-0.9.2+ds1/spec/layers2.py swftools-0.9.1/spec/layers2.py --- swftools-0.9.2+ds1/spec/layers2.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/layers2.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,64 @@ +from sys import * +from pdflib_py import * +import random + +p = PDF_new() +PDF_open_file(p, "layers2.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") +PDF_set_info(p, "Creator", "layer2.py") + +width=400 +height=400 + +PDF_begin_page(p, width, height) + +PDF_setrgbcolor_fill(p, 0, 0, 1.0) +PDF_moveto(p, 10, 10) +PDF_lineto(p, 100, 10) +PDF_lineto(p, 10, 100) + +PDF_moveto(p, 20, 110) +PDF_lineto(p, 110, 110) +PDF_lineto(p, 110, 20) +PDF_fill(p) + +for i in range(100): + x = random.randint(10,110) + y = random.randint(200,300) + PDF_moveto(p, x, y) + PDF_lineto(p, x+5, y) + PDF_stroke(p) + +PDF_setrgbcolor_fill(p, 0.5, 0.5, 1.0) +x,y = 100,100 +def rect(x,y): + PDF_moveto(p, x,y) + PDF_lineto(p, x+50,y) + PDF_lineto(p, x+50,y+50) + PDF_lineto(p, x,y+50) + PDF_lineto(p, x,y) + PDF_fill(p) + +rect(200,100) +rect(250,170) +rect(300,240) + +PDF_setrgbcolor_fill(p, 0, 1.0, 0) +rect(200,300) + +x,y = 230,330 +PDF_moveto(p, x+25,y) +PDF_lineto(p, x+50,y) +PDF_lineto(p, x+50,y+50) +PDF_lineto(p, x,y+50) +PDF_lineto(p, x,y+25) +PDF_lineto(p, x+25,y+25) +PDF_lineto(p, x+25,y) +PDF_fill(p) + + +PDF_end_page(p) + +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/layers.pdf swftools-0.9.1/spec/layers.pdf --- swftools-0.9.2+ds1/spec/layers.pdf 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/layers.pdf 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,147 @@ +%PDF-1.6 +%äãÏÒ +1 0 obj +[/PDF/ImageB/ImageC/ImageI/Text] +endobj +4 0 obj +<> +stream +xœUŽÍ +Â0„ïó{Ô“kmü96E½xÒ}­ -…ÐÇw'QAÉ·3Ìf¢aqPÙªXÞ'¨,ý½bÇ”ÆAìöJs{P÷s>Âí'öæ‚Ê€  ¨ô¸ PѾ +cÓ« R÷ê]†>Æ@ëÙêÀ¯”¹h¨}[U*5¥ÈúSðoj9y­7…Õ+× +endstream +endobj +5 0 obj +136 +endobj +7 0 obj +<> +>> +endobj +8 0 obj +<> +endobj +6 0 obj +<> +endobj +10 0 obj +<> +endobj +9 0 obj +<> +endobj +3 0 obj +<> +endobj +2 0 obj +<> +endobj +11 0 obj +<> +endobj +xref +0 12 +0000000000 65535 f +0000000015 00000 n +0000002308 00000 n +0000002207 00000 n +0000000063 00000 n +0000000271 00000 n +0000000460 00000 n +0000000290 00000 n +0000000345 00000 n +0000002016 00000 n +0000001631 00000 n +0000002362 00000 n +trailer +<] +>> +startxref +2410 +%%EOF diff -Nru swftools-0.9.2+ds1/spec/layers.py swftools-0.9.1/spec/layers.py --- swftools-0.9.2+ds1/spec/layers.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/layers.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,41 @@ +from sys import * +from pdflib_py import * + +p = PDF_new() +PDF_open_file(p, "layers.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") +PDF_begin_page(p, 500, 200) + +font = PDF_load_font(p, "Helvetica-Bold", "host", "") +PDF_setfont(p, font, 80.0) +PDF_set_text_pos(p, 0, 10) +PDF_show(p, "Bottom Text") + +PDF_setrgbcolor_stroke(p, 0, 1.0, 1.0) +PDF_setlinewidth(p, 10) +PDF_moveto(p, 0, 0) +PDF_lineto(p, 500, 100) +PDF_stroke(p) +PDF_moveto(p, 0, 100) +PDF_lineto(p, 500, 0) +PDF_stroke(p) + +PDF_setrgbcolor_fill(p, 0, 0, 1.0) +PDF_moveto(p, 350, 25) +PDF_lineto(p, 490, 25) +PDF_lineto(p, 490, 75) +PDF_lineto(p, 350, 75) +PDF_lineto(p, 350, 25) +PDF_fill(p) + +PDF_setrgbcolor_fill(p, 1, 1, 0) +PDF_set_text_pos(p, 400, 20);PDF_show(p, "A") +PDF_set_text_pos(p, 400, 80);PDF_show(p, "B") +PDF_set_text_pos(p, 400, 140);PDF_show(p, "C") + + +PDF_end_page(p) + +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/layers.spec.rb swftools-0.9.1/spec/layers.spec.rb --- swftools-0.9.2+ds1/spec/layers.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/layers.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,26 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + convert_file "layers.pdf" do + pixel_at(67,134).should_be_of_color 0x00ffff + pixel_at(299,182).should_be_of_color 0x00ffff + pixel_at(144,215).should_be_of_color 0x00ffff + pixel_at(206,203).should_be_of_color 0x00ffff + pixel_at(243,196).should_be_of_color 0x00ffff + pixel_at(270,190).should_be_of_color 0x00ffff + pixel_at(114,220).should_be_of_color 0x00ffff + pixel_at(406,161).should_be_of_color 0x00ffff + pixel_at(398,201).should_be_of_color 0x00ffff + pixel_at(438,211).should_be_of_color 0x0000ff + pixel_at(499,216).should_be_of_color 0xffff00 + pixel_at(498,223).should_be_of_color 0x00ffff + pixel_at(515,175).should_be_of_color 0xffff00 + pixel_at(458,185).should_be_of_color 0x0000ff + pixel_at(541,138).should_be_of_color 0xffff00 + pixel_at(433,158).should_be_of_color 0x0000ff + area_at(431,155,485,212).should_be_plain_colored + pixel_at(103,184).should_be_of_color 0x000000 + pixel_at(505,84).should_be_of_color 0xffff00 + pixel_at(314,149).should_be_of_color 0xffffff + end +end Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/spec/links.pdf and /tmp/M5qDI_SGQH/swftools-0.9.1/spec/links.pdf differ diff -Nru swftools-0.9.2+ds1/spec/links.py swftools-0.9.1/spec/links.py --- swftools-0.9.2+ds1/spec/links.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/links.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,26 @@ +from sys import * +from pdflib_py import * +p = PDF_new() +PDF_open_file(p, "links.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") +PDF_set_info(p, "Creator", "links.py") + +width=200 +height=200 + +PDF_begin_page(p, width, height) +def draw_link(x1,y1,x2,y2,url): + action = PDF_create_action(p, "URI", "url="+url); + optlist = "action={activate "+str(action)+"} linewidth=5" + PDF_create_annotation(p, x1,y1,x2,y2, "Link", optlist); +draw_link(0, 0, 100, 100, "http://www.swftools.org") +draw_link(0, 100, 100, 200, "http://www.quiss.org") +PDF_end_page(p) + +PDF_begin_page(p, width, height) +draw_link(0, 0, 100, 100, "http://www.pdf2swf.org") +PDF_end_page(p) + +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/links.spec.rb swftools-0.9.1/spec/links.spec.rb --- swftools-0.9.2+ds1/spec/links.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/links.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,9 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + + convert_file "links.pdf" do + area_at(0,0,200,200).should_contain_link("http://www.swftools.org") + area_at(0,0,200,200).should_contain_link("http://www.quiss.org") + end +end Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/spec/miterlimit.pdf and /tmp/M5qDI_SGQH/swftools-0.9.1/spec/miterlimit.pdf differ diff -Nru swftools-0.9.2+ds1/spec/miterlimit.spec.rb swftools-0.9.1/spec/miterlimit.spec.rb --- swftools-0.9.2+ds1/spec/miterlimit.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/miterlimit.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,22 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + + convert_file "miterlimit.pdf" do + pixel_at(451,153).should_be_of_color 0x999999 + pixel_at(492,154).should_be_of_color 0x666666 + pixel_at(523,153).should_be_of_color 0x666666 + pixel_at(386,151).should_be_of_color 0x666666 + pixel_at(86,65).should_be_of_color 0x666666 + pixel_at(80,77).should_be_of_color 0x999999 + pixel_at(77,86).should_be_of_color 0x666666 + pixel_at(474,380).should_be_of_color 0xffffff + pixel_at(492,380).should_be_of_color 0xffffff + pixel_at(452,381).should_be_of_color 0x999999 + pixel_at(450,369).should_be_of_color 0x666666 + pixel_at(376,382).should_be_of_color 0x666666 + pixel_at(89,319).should_be_of_color 0x666666 + pixel_at(119,314).should_be_of_color 0x999999 + pixel_at(142,305).should_be_of_color 0x666666 + end +end Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/spec/pattern.pdf and /tmp/M5qDI_SGQH/swftools-0.9.1/spec/pattern.pdf differ diff -Nru swftools-0.9.2+ds1/spec/pattern.py swftools-0.9.1/spec/pattern.py --- swftools-0.9.2+ds1/spec/pattern.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/pattern.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,41 @@ +from sys import * +from pdflib_py import * +p = PDF_new() +PDF_open_file(p, "pattern.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") +PDF_set_info(p, "Creator", "pattern.py") + +width=595 +height=842 + +PDF_begin_page(p, width, height) + +PDF_setrgbcolor_stroke(p, 0, 0, 0.9) +PDF_setrgbcolor_fill(p, 0.7, 0.7, 0.0) +pattern = PDF_begin_pattern(p, 4, 4, 4, 4, 2) +PDF_moveto(p, 0, 0) +PDF_lineto(p, 4, 4) +PDF_moveto(p, 4, 0) +PDF_lineto(p, 0, 4) +PDF_stroke(p) +PDF_moveto(p, 0, 2) +PDF_lineto(p, 0, 4) +PDF_lineto(p, 4, 4) +PDF_lineto(p, 4, 2) +PDF_lineto(p, 0, 2) +PDF_fill(p) +PDF_end_pattern(p) + +PDF_setcolor(p, "fill", "pattern", pattern, 0.0, 0.9, 0.0) +PDF_moveto(p, 0, 0) +PDF_lineto(p, width-100, 0) +PDF_lineto(p, width-100, height) +PDF_lineto(p, 0, height) +PDF_lineto(p, 0, 0) +PDF_fill(p) + +PDF_end_page(p) + +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/pattern.spec.rb swftools-0.9.1/spec/pattern.spec.rb --- swftools-0.9.2+ds1/spec/pattern.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/pattern.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,9 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + + convert_file "pattern.pdf" do + area_at(425,190,500,224).should_not_be_plain_colored + area_at(517,192,583,225).should_be_plain_colored + end +end Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/spec/simpletext.pdf and /tmp/M5qDI_SGQH/swftools-0.9.1/spec/simpletext.pdf differ diff -Nru swftools-0.9.2+ds1/spec/simpletext.spec.rb swftools-0.9.1/spec/simpletext.spec.rb --- swftools-0.9.2+ds1/spec/simpletext.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/simpletext.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,14 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + + convert_file "simpletext.pdf" do + pixel_at(109,133).should_be_of_color 0x000000 + pixel_at(154,139).should_be_brighter_than pixel_at(151,139) + pixel_at(53,136).should_be_darker_than pixel_at(58,166) + pixel_at(97,164).should_be_the_same_as pixel_at(208,256) + area_at(215,80,333,156).should_be_plain_colored + area_at(46,126,180,158).should_not_be_plain_colored + area_at(38,118,170,152).should_contain_text 'Hello World' + end +end Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/spec/smalltext.pdf and /tmp/M5qDI_SGQH/swftools-0.9.1/spec/smalltext.pdf differ diff -Nru swftools-0.9.2+ds1/spec/smalltext.py swftools-0.9.1/spec/smalltext.py --- swftools-0.9.2+ds1/spec/smalltext.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/smalltext.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,26 @@ +from sys import * +from pdflib_py import * +p = PDF_new() +PDF_open_file(p, "smalltext.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") + +PDF_set_info(p, "Creator", "smalltext.py") +PDF_begin_page(p, 612, 200) +font = PDF_load_font(p, "Helvetica", "host", "") + +PDF_setfont(p, font, 6.0) +PDF_set_text_pos(p, 40, 100);PDF_show(p, "'") +PDF_set_text_pos(p, 80, 100);PDF_show(p, "i") +PDF_set_text_pos(p, 120, 100);PDF_show(p, "l") +PDF_set_text_pos(p, 160, 100);PDF_show(p, "-") + +PDF_setfont(p, font, 9.0) +PDF_set_text_pos(p, 40, 50);PDF_show(p, "|") +PDF_set_text_pos(p, 80, 50);PDF_show(p, "i") +PDF_set_text_pos(p, 120, 50);PDF_show(p, "l") +PDF_set_text_pos(p, 160, 50);PDF_show(p, "-") + +PDF_end_page(p) +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/smalltext.spec.rb swftools-0.9.1/spec/smalltext.spec.rb --- swftools-0.9.2+ds1/spec/smalltext.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/smalltext.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,16 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + + convert_file "smalltext.pdf" do + area_at(37,93,44,103).should_not_be_plain_colored + area_at(77,94,86,104).should_not_be_plain_colored + area_at(117,94,123,104).should_not_be_plain_colored + area_at(157,94,165,103).should_not_be_plain_colored + area_at(37,139,45,155).should_not_be_plain_colored + area_at(76,139,85,154).should_not_be_plain_colored + area_at(116,142,125,152).should_not_be_plain_colored + area_at(155,145,167,151).should_not_be_plain_colored + area_at(27,110,180,115).should_be_plain_colored + end +end diff -Nru swftools-0.9.2+ds1/spec/spec_helper.rb swftools-0.9.1/spec/spec_helper.rb --- swftools-0.9.2+ds1/spec/spec_helper.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/spec_helper.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,199 @@ +require 'spec' +require 'rubygems' +require 'RMagick' + +class WrongColor < Exception + def initialize(pixel, is_color, desired_color) + @pixel = pixel + @is_color = is_color + @desired_color = desired_color + end + def to_s + "Wrong color at %s (is: %06x should be: %06x)" % [@pixel.to_s, @is_color, @desired_color] + end +end +class AreaError < Exception + def initialize(area,problem) + @area,@problem = area,problem + end + def to_s + "Area at #{@area} #{@problem}" + end +end +class PixelError < Exception + def initialize(p1, relation,p2) + @p1,@p2,@relation = p1,p2,relation + end + def to_s + "Pixel #{@p1} #{@relation} #{@p2}" + end +end +class ConversionFailed < Exception + def initialize(output,file) + @output = output + @file = file + @exists = File.exists?(file) + end + def to_s + puts "-"*26+" Conversion failed "+"-"*27 + (puts @output) if @output + puts "file #{@file} doesn't exist" if not @exists + puts "-"*72 + end +end + +class Area + def initialize(x1,y1,x2,y2,file) + @x1,@y1,@x2,@y2,@file = x1,y1,x2,y2,file + end + def should_be_plain_colored + @rgb = @file.get_area(@x1,@y1,@x2,@y2) unless @rgb + @rgb.min == @rgb.max or raise AreaError.new(self,"is not plain colored: colors go from %06x to %06x" % [rgb_to_int(@rgb.min), rgb_to_int(@rgb.max)]) + end + def should_not_be_plain_colored + @rgb = @file.get_area(@x1,@y1,@x2,@y2) unless @rgb + @rgb.min != @rgb.max or raise AreaError.new(self,"is plain colored") + end + def should_contain_text(text) + text2 = @file.get_text(@x1,@y1,@x2,@y2) + text2 == text or raise AreaError.new(self, "doesn't contain text \"#{text}\" (found: \"#{text2}\")") + end + def should_contain_link(url) + links = @file.get_links(@x1,@y1,@x2,@y2) + (links & [url]).empty? and raise AreaError.new(self, "doesn't contain url \"#{url}\"") + end + def to_s + "(#{@x1},#{@y1},#{@x2},#{@y2})" + end +end + +def rgb_to_int(rgb) + # ImageMagick rgb triples are 16 bit + (rgb.reverse+[0]).map {|c| c>>8}.pack("CCCC").unpack("i")[0] +end + +class Pixel + attr :rgb + def initialize(x,y,rgb) + @x,@y,@rgb = x,y,rgb + end + def should_be_of_color(color2) + color1 = rgb_to_int(@rgb) + color1 == color2 or raise WrongColor.new(self, color1, color2) + end + def should_be_brighter_than(pixel) + gray1 = @rgb.inject(0) {|sum,e| sum+e} + gray2 = pixel.rgb.inject(0) {|sum,e| sum+e} + gray1 > gray2 or raise PixelError.new(self,"is not brighter than",pixel) + end + def should_be_darker_than(pixel) + gray1 = @rgb.inject(0) {|sum,e| sum+e} + gray2 = pixel.rgb.inject(0) {|sum,e| sum+e} + gray1 < gray2 or raise PixelError.new(self,"is not less bright than",pixel) + end + def should_be_the_same_as(pixel) + @rgb == pixel.rgb or raise PixelError.new(self,"is not the same as",pixel) + end + def to_s + "(#{@x},#{@y})" + end +end + +$tempfiles = [] +Kernel.at_exit do + $tempfiles.each do |file| + `rm -f #{file}` + end +end + +class DocFile + def initialize(filename, page) + @filename = filename + @page = page + end + def convert() + return if @swfname + @swfname = @filename.gsub(/.pdf$/i,"")+".swf" + $tempfiles += [@swfname] + `pdfinfo #{@filename}` =~ /Page size:\s*([0-9]+) x ([0-9]+) pts/ + width,height = $1,$2 + dpi = (72.0 * 612 / width.to_i).to_i + output = `pdf2swf -f -s poly2bitmap -s zoom=#{dpi} -p #{@page} #{@filename} -o #{@swfname} 2>&1` + #output = `pdf2swf -s zoom=#{dpi} --flatten -p #{@page} #{@filename} -o #{@swfname} 2>&1` + raise ConversionFailed.new(output,@swfname) unless File.exists?(@swfname) + end + def render() + return if @img + convert() + @pngname = @filename.gsub(/.pdf$/i,"")+".png" + begin + output = `swfrender #{@swfname} -o #{@pngname} 2>&1` + raise ConversionFailed.new(output,@pngname) unless File.exists?(@pngname) + @img = Magick::Image.read(@pngname).first + ensure + `rm -f #{@pngname}` + end + end + def get_text(x1,y1,x2,y2) + self.convert() + #puts "swfstrings -x #{x1} -y #{y1} -W #{x2-x1} -H #{y2-y1} #{@swfname}" + #puts `swfstrings -x #{x1} -y #{y1} -W #{x2-x1} -H #{y2-y1} #{@swfname}` + `swfstrings -x #{x1} -y #{y1} -W #{x2-x1} -H #{y2-y1} #{@swfname}`.chomp + end + def get_links(x1,y1,x2,y2) + self.convert() + t = `swfdump -a #{@swfname}` + links = t.scan(/GetUrl2? URL:"([^"]*)"/).inject([]) do |a,u| a + u end + t.scan(/name "url:([^"]*)"/).inject(links) do |a,u| a + u end + end + def get_area(x1,y1,x2,y2) + self.render() + data = @img.export_pixels(x1, y1, x2-x1, y2-y1, "RGB") + Array.new(data.size/3) { |i| data.slice(i*3,3) } + end + def area_at(x1,y1,x2,y2) + return Area.new(x1,y1,x2,y2,self) + end + def width() + self.render() + return @img.columns + end + def height() + self.render() + return @img.rows + end + def pixel_at(x,y) + self.render() + data = @img.export_pixels(x, y, 1, 1, "RGB") + return Pixel.new(x,y,data) + end +end + +module Spec::Example::ExampleGroupMethods + alias :convert_file :example +end + +class FileExampleGroup < Spec::Example::ExampleGroup + def area_at(x1,y1,x2,y2) + @file.area_at(x1,y1,x2,y2) + end + def width + @file.width + end + def height + @file.height + end + def pixel_at(x,y) + @file.pixel_at(x,y) + end +end + +Spec::Example::ExampleGroupFactory.default(FileExampleGroup) + +Spec::Runner.configure do |config| + config.before do + input_file = File.join(File.dirname(__FILE__), description) + raise "Cannot find input file #{input_file}" unless File.exists?(input_file) + @file = DocFile.new(input_file, 1) + end +end Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/spec/textarea3.pdf and /tmp/M5qDI_SGQH/swftools-0.9.1/spec/textarea3.pdf differ diff -Nru swftools-0.9.2+ds1/spec/textarea3.py swftools-0.9.1/spec/textarea3.py --- swftools-0.9.2+ds1/spec/textarea3.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/textarea3.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,49 @@ +from sys import * +from pdflib_py import * +import md5 +import Image +import math + +img = Image.open("baboon.png") +width, height = img.size +img.load() + +p = PDF_new() +PDF_open_file(p, "textarea3.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") + +PDF_set_info(p, "Creator", "smalltext.py") +PDF_begin_page(p, width, height) +font = PDF_load_font(p, "Courier", "host", "") + +PDF_setrgbcolor_fill(p, 0.0, 0.0, 0.0) +PDF_moveto(p, 0, 0) +PDF_lineto(p, width, 0) +PDF_lineto(p, width, height) +PDF_lineto(p, 0, height) +PDF_lineto(p, 0, 0) +PDF_fill(p) + +PDF_setfont(p, font, 4.0) +i = 0 +for y in range(height / 6): + text = "".join([md5.md5(str(i+j*732849)).hexdigest() for j in range(9)]) + for x in range(width / 6): + r,g,b = img.getpixel((x*6, height-1-y*6)) + l = math.sqrt(r*r+g*g+b*b) + if not r and not g and not b: + continue + white = (l / 444.0)*5 + PDF_setfont(p, font, 0.5+int(white)*4) + r = 0.3 + 0.3 * int((r/l)*3) + g = 0.3 + 0.3 * int((g/l)*3) + b = 0.3 + 0.3 * int((b/l)*3) + PDF_setrgbcolor_fill(p, r, g, b) + PDF_set_text_pos(p, x*6, y*6); + PDF_show(p, text[x]) + i = i + 1 + +PDF_end_page(p) +PDF_close(p) +PDF_delete(p); Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/spec/textarea.pdf and /tmp/M5qDI_SGQH/swftools-0.9.1/spec/textarea.pdf differ diff -Nru swftools-0.9.2+ds1/spec/textarea.py swftools-0.9.1/spec/textarea.py --- swftools-0.9.2+ds1/spec/textarea.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/textarea.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,26 @@ +from sys import * +from pdflib_py import * +import md5 +p = PDF_new() +PDF_open_file(p, "textarea.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") + +PDF_set_info(p, "Creator", "smalltext.py") +PDF_begin_page(p, 612, 3000) +font = PDF_load_font(p, "Courier", "host", "") + +PDF_setfont(p, font, 12.0) +i = 0 +# the idea is to overflow the placetext matrix once, so that +# we have at least two different ty values +for y in range(3000 / 9): + PDF_set_text_pos(p, 0, y*9); + text = "".join([md5.md5(str(i+j*732849)).hexdigest() for j in range(3)]) + print text + PDF_show(p, text) + i = i + 1 + +PDF_end_page(p) +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/textarea.spec.rb swftools-0.9.1/spec/textarea.spec.rb --- swftools-0.9.2+ds1/spec/textarea.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/textarea.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,11 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + + convert_file "textarea.pdf" do + area_at(460,94,610,106).should_contain_text '97924ff65f9dfc75450ba' + area_at(467,373,525,384).should_contain_text '29cf24e47' + area_at(474,592,543,601).should_contain_text '0afa27099a' + area_at(59,798,131,808).should_contain_text '4c28e489b4' + end +end diff -Nru swftools-0.9.2+ds1/spec/textposition.pdf swftools-0.9.1/spec/textposition.pdf --- swftools-0.9.2+ds1/spec/textposition.pdf 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/textposition.pdf 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,146 @@ +%PDF-1.6 +%äãÏÒ +1 0 obj +[/PDF/ImageB/ImageC/ImageI/Text] +endobj +4 0 obj +<> +stream +xœÕTÍ ¾÷)zÔ 6¸g<,@3³æû,?ºèR íW’æûÊ-‰RTd·D +½°°;RÒb!î",Z¸ÃæÔ{?àu¸øÃ6> +>> +endobj +8 0 obj +<> +endobj +6 0 obj +<> +endobj +10 0 obj +<> +endobj +9 0 obj +<> +endobj +3 0 obj +<> +endobj +2 0 obj +<> +endobj +11 0 obj +<> +endobj +xref +0 12 +0000000000 65535 f +0000000015 00000 n +0000002385 00000 n +0000002284 00000 n +0000000063 00000 n +0000000348 00000 n +0000000537 00000 n +0000000367 00000 n +0000000422 00000 n +0000002093 00000 n +0000001708 00000 n +0000002439 00000 n +trailer +<<2E2949BF0CCA717C9B1FEA7F231B3F97>] +>> +startxref +2487 +%%EOF diff -Nru swftools-0.9.2+ds1/spec/textposition.py swftools-0.9.1/spec/textposition.py --- swftools-0.9.2+ds1/spec/textposition.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/textposition.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,54 @@ +from sys import * +from pdflib_py import * +from math import sin,cos +p = PDF_new() +PDF_open_file(p, "textposition.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") + +width = 612 +height = 500 +PDF_begin_page(p, width, height) + +font = PDF_load_font(p, "Helvetica-Bold", "host", "") + +PDF_setfont(p, font, 18.0) + +a=0.7 +b=-0.7 +matrices = [[1,0,0,1,100,200], + [cos(a),sin(a),-sin(a),cos(a),400,75], + [1,0,0,-1,100,350], + [-1,0,0,1,450,270], + [1.9,0.5,0.6,1.4,50,-140], + [cos(b),sin(b),sin(b),-cos(b),100,300], + [1.0,0,0,5,-90,-200], + ] + +for m in matrices: + PDF_save(p) + PDF_setmatrix(p, m[0],m[1],m[2],m[3],m[4],m[5]) + x,y = 100,100 + PDF_set_text_pos(p, x,y) + w = PDF_stringwidth(p, "HELLO WORLD", font, 18.0) + h = 18.0 - 4 + PDF_setrgbcolor_fill(p, 0.0, 0.0, 0.0) + PDF_show(p, "HELLO WORLD") + + PDF_setrgbcolor_fill(p, 0.0, 0.0, 1.0) + PDF_moveto(p, x,y) + PDF_lineto(p, x+w,y) + PDF_lineto(p, x+w,y+h) + PDF_lineto(p, x,y+h) + PDF_lineto(p, x,y) + PDF_moveto(p, x-20,y-20) + PDF_lineto(p, x-20,y+20+h) + PDF_lineto(p, x+20+w,y+20+h) + PDF_lineto(p, x+20+w,y-20) + PDF_lineto(p, x-20,y-20) + PDF_fill(p); + PDF_restore(p) + +PDF_end_page(p) +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/textposition.spec.rb swftools-0.9.1/spec/textposition.spec.rb --- swftools-0.9.2+ds1/spec/textposition.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/textposition.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,125 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + convert_file "textposition.pdf" do + pixel_at(109,352).should_be_of_color 0xffffff + pixel_at(115,346).should_be_of_color 0xffffff + pixel_at(132,368).should_be_of_color 0xffffff + pixel_at(141,375).should_be_of_color 0xffffff + pixel_at(149,380).should_be_of_color 0xffffff + pixel_at(156,386).should_be_of_color 0xffffff + pixel_at(176,403).should_be_of_color 0xffffff + pixel_at(189,409).should_be_of_color 0xffffff + pixel_at(196,421).should_be_of_color 0xffffff + pixel_at(204,428).should_be_of_color 0xffffff + pixel_at(16,164).should_be_of_color 0x000000 + pixel_at(28,167).should_be_of_color 0x000000 + pixel_at(30,152).should_be_of_color 0xffffff + pixel_at(29,139).should_be_of_color 0x000000 + pixel_at(42,194).should_be_of_color 0x000000 + pixel_at(42,182).should_be_of_color 0xffffff + pixel_at(28,196).should_be_of_color 0x000000 + pixel_at(31,183).should_be_of_color 0xffffff + pixel_at(50,193).should_be_of_color 0x000000 + pixel_at(52,183).should_be_of_color 0xffffff + pixel_at(63,194).should_be_of_color 0x000000 + pixel_at(63,178).should_be_of_color 0xffffff + pixel_at(63,149).should_be_of_color 0xffffff + pixel_at(62,139).should_be_of_color 0x000000 + pixel_at(99,141).should_be_of_color 0x000000 + pixel_at(98,171).should_be_of_color 0xffffff + pixel_at(99,194).should_be_of_color 0x000000 + pixel_at(113,168).should_be_of_color 0x000000 + pixel_at(113,152).should_be_of_color 0xffffff + pixel_at(113,189).should_be_of_color 0xffffff + pixel_at(126,169).should_be_of_color 0xffffff + pixel_at(136,167).should_be_of_color 0xffffff + pixel_at(135,195).should_be_of_color 0x000000 + pixel_at(125,194).should_be_of_color 0x000000 + pixel_at(135,141).should_be_of_color 0x000000 + pixel_at(113,141).should_be_of_color 0x000000 + pixel_at(74,169).should_be_of_color 0xffffff + pixel_at(310,437).should_be_of_color 0x000000 + pixel_at(313,442).should_be_of_color 0xffffff + pixel_at(320,430).should_be_of_color 0xffffff + pixel_at(363,423).should_be_of_color 0xffffff + pixel_at(383,419).should_be_of_color 0xffffff + pixel_at(405,413).should_be_of_color 0xffffff + pixel_at(416,407).should_be_of_color 0x000000 + pixel_at(435,404).should_be_of_color 0x000000 + pixel_at(458,403).should_be_of_color 0xffffff + pixel_at(474,394).should_be_of_color 0xffffff + pixel_at(489,385).should_be_of_color 0xffffff + pixel_at(499,393).should_be_of_color 0xffffff + pixel_at(525,381).should_be_of_color 0xffffff + pixel_at(545,376).should_be_of_color 0xffffff + pixel_at(409,271).should_be_of_color 0xffffff + pixel_at(432,256).should_be_of_color 0xffffff + pixel_at(440,250).should_be_of_color 0xffffff + pixel_at(449,243).should_be_of_color 0xffffff + pixel_at(458,237).should_be_of_color 0xffffff + pixel_at(472,228).should_be_of_color 0xffffff + pixel_at(476,221).should_be_of_color 0xffffff + pixel_at(489,214).should_be_of_color 0xffffff + pixel_at(497,202).should_be_of_color 0xffffff + pixel_at(504,196).should_be_of_color 0xffffff + pixel_at(243,262).should_be_of_color 0xffffff + pixel_at(242,255).should_be_of_color 0xffffff + pixel_at(253,257).should_be_of_color 0xffffff + pixel_at(129,370).should_be_of_color 0xffffff + pixel_at(367,419).should_be_of_color 0xffffff + pixel_at(387,412).should_be_of_color 0xffffff + pixel_at(232,188).should_be_of_color 0xffffff + pixel_at(233,262).should_be_of_color 0xffffff + pixel_at(207,253).should_be_of_color 0xffffff + pixel_at(264,254).should_be_of_color 0xffffff + pixel_at(290,256).should_be_of_color 0xffffff + pixel_at(303,252).should_be_of_color 0xffffff + pixel_at(317,256).should_be_of_color 0xffffff + pixel_at(326,256).should_be_of_color 0xffffff + pixel_at(317,188).should_be_of_color 0xffffff + pixel_at(325,193).should_be_of_color 0xffffff + pixel_at(289,193).should_be_of_color 0xffffff + pixel_at(252,194).should_be_of_color 0xffffff + pixel_at(206,197).should_be_of_color 0xffffff + pixel_at(206,188).should_be_of_color 0xffffff + pixel_at(222,123).should_be_of_color 0xffffff + pixel_at(231,118).should_be_of_color 0xffffff + pixel_at(245,128).should_be_of_color 0xffffff + pixel_at(260,124).should_be_of_color 0xffffff + pixel_at(285,124).should_be_of_color 0xffffff + pixel_at(295,123).should_be_of_color 0xffffff + pixel_at(305,118).should_be_of_color 0xffffff + pixel_at(316,118).should_be_of_color 0xffffff + pixel_at(343,128).should_be_of_color 0xffffff + pixel_at(343,118).should_be_of_color 0xffffff + pixel_at(303,198).should_be_of_color 0xffffff + pixel_at(43,136).should_be_of_color 0xffffff + pixel_at(53,135).should_be_of_color 0xffffff + area_at(17,177,76,197).should_not_be_plain_colored + area_at(74,134,141,162).should_not_be_plain_colored + area_at(77,173,141,196).should_not_be_plain_colored + area_at(219,119,346,128).should_not_be_plain_colored + area_at(110,347,117,354).should_not_be_plain_colored + area_at(129,366,138,373).should_not_be_plain_colored + area_at(139,373,149,381).should_not_be_plain_colored + area_at(166,396,176,403).should_not_be_plain_colored + area_at(187,413,197,420).should_not_be_plain_colored + area_at(199,422,208,429).should_not_be_plain_colored + area_at(317,430,347,434).should_not_be_plain_colored + area_at(353,420,382,425).should_not_be_plain_colored + area_at(396,408,427,414).should_not_be_plain_colored + area_at(430,400,461,404).should_not_be_plain_colored + area_at(478,389,503,395).should_not_be_plain_colored + area_at(513,381,539,385).should_not_be_plain_colored + area_at(203,189,330,197).should_not_be_plain_colored + area_at(204,253,331,261).should_not_be_plain_colored + area_at(410,271,415,277).should_not_be_plain_colored + area_at(423,261,428,266).should_not_be_plain_colored + area_at(440,246,445,257).should_not_be_plain_colored + area_at(460,228,465,235).should_not_be_plain_colored + area_at(475,217,483,223).should_not_be_plain_colored + area_at(489,206,493,212).should_not_be_plain_colored + area_at(502,197,505,202).should_not_be_plain_colored + end +end diff -Nru swftools-0.9.2+ds1/spec/textselectspaces.pdf swftools-0.9.1/spec/textselectspaces.pdf --- swftools-0.9.2+ds1/spec/textselectspaces.pdf 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/textselectspaces.pdf 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,147 @@ +%PDF-1.6 +%äãÏÒ +1 0 obj +[/PDF/ImageB/ImageC/ImageI/Text] +endobj +4 0 obj +<> +stream +xœm»Â0 EwEFâÄNÛµLŒþ +A‚Ï')µªK9º9¾r#°Ú8ƒ•‘òÜ¥gtFö°ãa)g`´É|Ùýyj/™FŸ¨ÿÑÝ£ÝZ²]ÿάÀ*eÉa¢%U˪–U-kÚà5-UëæÚµ€·œXºÃ0Û+4M9݃–•=éï|գ쿾–çõ£Z¿Të“ZÿZépi +endstream +endobj +5 0 obj +166 +endobj +7 0 obj +<> +>> +endobj +8 0 obj +<> +endobj +6 0 obj +<> +endobj +10 0 obj +<> +endobj +9 0 obj +<> +endobj +3 0 obj +<> +endobj +2 0 obj +<> +endobj +11 0 obj +<> +endobj +xref +0 12 +0000000000 65535 f +0000000015 00000 n +0000002348 00000 n +0000002247 00000 n +0000000063 00000 n +0000000301 00000 n +0000000514 00000 n +0000000320 00000 n +0000000375 00000 n +0000002066 00000 n +0000001681 00000 n +0000002402 00000 n +trailer +<<8F26BB647D55ECD56991EB3EFE624E02>] +>> +startxref +2450 +%%EOF diff -Nru swftools-0.9.2+ds1/spec/textselectspaces.py swftools-0.9.1/spec/textselectspaces.py --- swftools-0.9.2+ds1/spec/textselectspaces.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/textselectspaces.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,63 @@ +from sys import * +from pdflib_py import * +p = PDF_new() +PDF_open_file(p, "textselectspaces.pdf") + +PDF_set_parameter(p, "usercoordinates", "true") + +PDF_set_info(p, "Creator", "smalltext.py") +PDF_begin_page(p, 612, 200) +font = PDF_load_font(p, "Helvetica", "host", "") + +PDF_setfont(p, font, 18.0) + +x = 40 +y = 100 +def write_word(s, d): + global x,y + w = PDF_stringwidth(p, s, font, 18.0) + PDF_show(p, s) + x+=w+d + PDF_set_text_pos(p, x, y) + +x,y = 40,160 +PDF_set_text_pos(p, x, y) +write_word("The", 20) +write_word("quick", 20) +write_word("brown", 20) +write_word("fox", 20) + +x,y = 40,130 +PDF_set_text_pos(p, x, y) +write_word("The", 10) +write_word("quick", 10) +write_word("brown", 10) +write_word("fox", 10) + +x,y = 40,100 +PDF_set_text_pos(p, x, y) +write_word("The", 1) +write_word("quick", 1) +write_word("brown", 1) +write_word("fox", 1) + +PDF_setmatrix(p, 2.5, 0, 0, 1.0, 0, 0) +x,y = 16,70 +PDF_set_text_pos(p, x, y) +write_word("The", 0.5) +write_word("quick", 0.5) +write_word("brown", 0.5) +write_word("fox", 0.5) + +PDF_setmatrix(p, 2.5, 0, 0, 1.0, 0, 0) +x,y = 16,40 +PDF_set_text_pos(p, x, y) +write_word("The", 5) +write_word("quick", 5) +write_word("brown", 5) +write_word("fox", 5) + + +PDF_end_page(p) +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/textselectspaces.spec.rb swftools-0.9.1/spec/textselectspaces.spec.rb --- swftools-0.9.2+ds1/spec/textselectspaces.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/textselectspaces.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,12 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + + convert_file "textselectspaces.pdf" do + area_at(32,22,257,46).should_contain_text 'The quick brown fox' + area_at(32,53,226,77).should_contain_text 'The quick brown fox' + area_at(31,84,198,108).should_contain_text 'Thequickbrownfox' + area_at(33,111,423,137).should_contain_text 'Thequickbrownfox' + area_at(35,141,455,167).should_contain_text 'The quick brown fox' + end +end Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/spec/transparency.pdf and /tmp/M5qDI_SGQH/swftools-0.9.1/spec/transparency.pdf differ diff -Nru swftools-0.9.2+ds1/spec/transparency.py swftools-0.9.1/spec/transparency.py --- swftools-0.9.2+ds1/spec/transparency.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/transparency.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,82 @@ +import sys +from pdflib_py import * +from math import sin,cos +import Image +import ImageDraw + +img = Image.new("L", (3, 3)) +draw = ImageDraw.Draw(img) +draw.point((0,1), fill=255) +draw.point((0,2), fill=255) +draw.point((1,0), fill=255) +draw.point((1,2), fill=255) +draw.point((2,0), fill=255) +draw.point((2,1), fill=255) +img.save("/tmp/mask1.png") + +img = Image.new("L", (16, 1)) +draw = ImageDraw.Draw(img) +for i in range(16): + draw.point((i,0), fill=i*16) +img.save("/tmp/mask2.png") + +img = Image.new("RGB", (3, 3)) +draw = ImageDraw.Draw(img) +draw.point((0,1), fill=(0,0,0)) +draw.point((0,2), fill=(255,0,0)) +draw.point((1,0), fill=(0,255,0)) +draw.point((1,2), fill=(0,0,255)) +draw.point((2,0), fill=(255,255,0)) +draw.point((2,1), fill=(0,255,255)) +img.save("/tmp/img1.png") + +img = Image.new("RGB", (16, 1)) +draw = ImageDraw.Draw(img) +for i in range(16): + draw.point((i,0), fill=(0,255,0)) +img.save("/tmp/img2.png") + +p = PDF_new() +PDF_open_file(p, "transparency.pdf") +font = PDF_load_font(p, "Helvetica", "host", "") + +PDF_set_parameter(p, "usercoordinates", "true") + +width = 400 +height = 400 +PDF_begin_page(p, width, height) + +PDF_setcolor(p, "fill", "rgb", 0.0,0.0,0.0,1.0) +PDF_moveto(p, 0,0) +PDF_lineto(p, width, 0) +PDF_lineto(p, width, height) +PDF_lineto(p, 0, height) +PDF_lineto(p, 0, 0) +PDF_fill(p) + +PDF_setfont(p, font, 10.0) +PDF_setcolor(p, "fill", "rgb", 1.0,1.0,1.0,1.0) +PDF_set_text_pos(p, 50, 205);PDF_show(p, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz") +PDF_set_text_pos(p, 50, 105);PDF_show(p, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz") + +mask = PDF_load_image(p, "png", "/tmp/mask1.png", "mask") +i = PDF_load_image(p, "png", "/tmp/img1.png", "masked "+str(mask)) +PDF_place_image(p, i, 100, 300, 20) + +mask2 = PDF_load_image(p, "png", "/tmp/mask2.png", "mask") +i2 = PDF_load_image(p, "png", "/tmp/img2.png", "masked "+str(mask2)) +PDF_place_image(p, i2, 0, 200, 25) + +PDF_setcolor(p, "fill", "rgb", 1.0,1.0,1.0,1.0) +gstate = PDF_create_gstate(p, "opacityfill 0.25") # blendmode multiply opacityfill 0.5") +PDF_set_gstate(p, gstate) +PDF_moveto(p, 50, 75) +PDF_lineto(p, 50+300, 75) +PDF_lineto(p, 50+300, 150) +PDF_lineto(p, 50, 150) +PDF_lineto(p, 50, 75) +PDF_fill(p) + +PDF_end_page(p) +PDF_close(p) +PDF_delete(p); diff -Nru swftools-0.9.2+ds1/spec/transparency.spec.rb swftools-0.9.1/spec/transparency.spec.rb --- swftools-0.9.2+ds1/spec/transparency.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/transparency.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,27 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + convert_file "transparency.pdf" do + pixel_at(174,135).should_be_of_color 0xff0000 + pixel_at(167,112).should_be_of_color 0x000000 + pixel_at(172,75).should_be_of_color 0x000000 + pixel_at(199,108).should_be_of_color 0x000000 + pixel_at(234,141).should_be_of_color 0x000000 + pixel_at(202,142).should_be_of_color 0x0000ff + pixel_at(233,111).should_be_of_color 0x00ffff + pixel_at(233,71).should_be_of_color 0xffff00 + pixel_at(199,71).should_be_of_color 0x00ff00 + pixel_at(594,277).should_be_brighter_than pixel_at(439,279) + pixel_at(552,284).should_be_brighter_than pixel_at(361,285) + pixel_at(474,294).should_be_brighter_than pixel_at(325,277) + pixel_at(283,276).should_be_brighter_than pixel_at(94,277) + area_at(86,290,107,301).should_not_be_plain_colored + area_at(158,287,186,300).should_not_be_plain_colored + area_at(234,288,262,300).should_not_be_plain_colored + area_at(312,287,337,300).should_not_be_plain_colored + area_at(162,438,244,455).should_not_be_plain_colored + pixel_at(201,400).should_be_brighter_than pixel_at(174,345) + pixel_at(299,477).should_be_brighter_than pixel_at(237,555) + area_at(407,400,435,422).should_be_plain_colored + end +end diff -Nru swftools-0.9.2+ds1/spec/transpstack.pdf swftools-0.9.1/spec/transpstack.pdf --- swftools-0.9.2+ds1/spec/transpstack.pdf 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/transpstack.pdf 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,90 @@ +%PDF-1.4 +%ê~ +1 0 obj << +/Type /Catalog +/Pages 4 0 R +>> endobj +2 0 obj << +/Contents 3 0 R +/Parent 4 0 R +/Type /Page +/Resources 7 0 R +/MediaBox [0 0 612 100] +>> endobj +3 0 obj << +/Length 107 +>> stream +q + +1.0 0.0 0.0 rg + +0 40 m 612 40 l 612 60 l 0 60 l 0 40 l f +q /gs0 gs 1.0 0 0 1.0 0 0 cm /mygroup Do Q + +Qendstream +endobj +4 0 obj << +/Kids [2 0 R] +/Type /Pages +/Count 1 +>> endobj +5 0 obj << +/Length 337 +/Type /XObject +/BBox [0 0 100 100] +/Group << +/K true +/CS /DeviceRGB +/S /Transparency +/I true +>> +/Subtype /Form +>> stream + +0.0 1.0 0.0 rg +0.0 0.0 0.0 RG +10 10 m 70 10 l 70 70 l 10 70 l 10 10 l f +10 10 m 70 10 l 70 70 l 10 70 l 10 10 l s +0.0 0.0 1.0 rg +0.0 0.0 0.0 RG +30 30 m 90 30 l 90 90 l 30 90 l 30 30 l f +30 30 m 90 30 l 90 90 l 30 90 l 30 30 l s +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +endstream +endobj +6 0 obj << +/CA 1.0 +/ca 1.0 +/Type /ExtGState +/BM /Normal +>> endobj +7 0 obj << +/XObject << +/mygroup 5 0 R +>> +/Type /Resources +/ExtGState << +/gs0 6 0 R +>> +>> endobj +xref +0 8 +0000000000 65535 f +0000000013 00000 n +0000000062 00000 n +0000000166 00000 n +0000000323 00000 n +0000000380 00000 n +0000000878 00000 n +0000000944 00000 n +trailer +<< +/Size 8 +/Root 1 0 R +>> +startxref +1040 +%%EOF \ No newline at end of file diff -Nru swftools-0.9.2+ds1/spec/transpstack.py swftools-0.9.1/spec/transpstack.py --- swftools-0.9.2+ds1/spec/transpstack.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/transpstack.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,58 @@ +#!/usr/bin/python +import sys +sys.path += ["../scripts/"] +import pdf + +# a test for transparency groups: +# form xobjects used for doing transparency groups can do savestate (q) +# without ever needing to do a corresponding restorestate (Q) because +# their content stream is self-contained. +# +# Test that this doesn't confuse the pdf reader. + +file = pdf.PDF() + +page = file.add_page(612,100) + +group1 = file.create_object("/XObject", "/Form") +group1.stream = """ +0.0 1.0 0.0 rg +0.0 0.0 0.0 RG +10 10 m 70 10 l 70 70 l 10 70 l 10 10 l f +10 10 m 70 10 l 70 70 l 10 70 l 10 10 l s +0.0 0.0 1.0 rg +0.0 0.0 0.0 RG +30 30 m 90 30 l 90 90 l 30 90 l 30 30 l f +30 30 m 90 30 l 90 90 l 30 90 l 30 30 l s +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +1.0 0 0 1.0 1000 1000 cm q +""" +isolated = "true" +knockout = "true" +group1["/Group"] = pdf.PDFDict({"/S": "/Transparency", "/CS": "/DeviceRGB", "/I": isolated, "/K": knockout}) +group1["/BBox"] = pdf.PDFArray([0, 0, 100, 100]) + +gs = file.create_object("/ExtGState") +gs["/BM"] = "/Normal" +gs["/CA"] = "1.0" # stroke alpha +gs["/ca"] = "1.0" # fill alpha + +resources = file.create_object("/Resources") +resources["/XObject"] = pdf.PDFDict({"/mygroup": group1}) +resources["/ExtGState"] = pdf.PDFDict({"/gs0": gs}) + +page.header["/Resources"] = resources + +page.stream = """q + +1.0 0.0 0.0 rg + +0 40 m 612 40 l 612 60 l 0 60 l 0 40 l f +q /gs0 gs 1.0 0 0 1.0 0 0 cm /mygroup Do Q + +Q""" + +file.write("transpstack.pdf") + diff -Nru swftools-0.9.2+ds1/spec/transpstack.spec.rb swftools-0.9.1/spec/transpstack.spec.rb --- swftools-0.9.2+ds1/spec/transpstack.spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/spec/transpstack.spec.rb 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,14 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pdf conversion" do + + convert_file "transpstack.pdf" do + pixel_at(15,15).should_be_of_color 0xffffff + pixel_at(4,50).should_be_of_color 0xff0000 + pixel_at(21,52).should_be_of_color 0x00ff00 + pixel_at(49,51).should_be_of_color 0x0000ff + pixel_at(80,49).should_be_of_color 0x0000ff + pixel_at(23,77).should_be_of_color 0x00ff00 + pixel_at(70,20).should_be_of_color 0x0000ff + end +end diff -Nru swftools-0.9.2+ds1/src/as3compile.1 swftools-0.9.1/src/as3compile.1 --- swftools-0.9.2+ds1/src/as3compile.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/as3compile.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH as3compile "1" "February 2012" "as3compile" "swftools" +.TH as3compile "1" "April 2012" "as3compile" "swftools" .SH NAME as3compile \- Compile .as ActionScript 3.0 files to swf. diff -Nru swftools-0.9.2+ds1/src/as3compile.doc swftools-0.9.1/src/as3compile.doc --- swftools-0.9.2+ds1/src/as3compile.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/as3compile.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,72 @@ +Usage: %s file.as [-o file.swf] + +Compile .as ActionScript 3.0 files to swf. + +Compiles a file written in ActionScript 3.0 to a SWF file. + +-h, --help + Print short help message and exit +-V, --version + Print version info and exit +-v, --verbose + Increase verbosity +-q, --quiet + Decrease verbosity +-C, --cgi + Output to stdout (for use in CGI environments) +-R, --resolve + Try to resolve undefined classes automatically. + This flag will cause the compiler to try filenames like "FooBar.as" for classes named "FooBar". +-D, --define + Set a compile time variable (for doing conditional compilation) +-X, --width + Set target SWF width +-Y, --height + Set target SWF width +-r, --rate + Set target SWF framerate +-M, --mainclass + Set the name of the main class (extending flash.display.MovieClip) +-l, --library + Include library file . can be an .abc or .swf file. +-I, --include + Add additional include dir . +-N, --local-with-network + Make output file "local with networking" +-L, --local-with-filesystem + Make output file "local with filesystem" +-T, --flashversion + Set target SWF flash version to . + must be >= 9. +-o, --output + Set output file to . + +.SH EXAMPLE + + The following is a basic as3 file that can be compiled e.g. + with \fBas3compile -X 400 -Y 400 smiley.as\fR + + // smiley.as + package + { + import flash.display.MovieClip + + public class Main extends MovieClip + { + function Main() + { + this.graphics.beginFill(0xcccc00) + this.graphics.drawCircle(200,200,200) + this.graphics.endFill() + this.graphics.beginFill(0x000000) + this.graphics.drawCircle(140,150,50) + this.graphics.drawCircle(260,150,50) + this.graphics.drawRoundRect(140,270,120,10,20); + this.graphics.endFill() + } + } + } + +.SH AUTHOR + +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/font2swf.1 swftools-0.9.1/src/font2swf.1 --- swftools-0.9.2+ds1/src/font2swf.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/font2swf.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH font2swf "1" "February 2012" "font2swf" "swftools" +.TH font2swf "1" "April 2012" "font2swf" "swftools" .SH NAME font2swf \- Converts a font to SWF. diff -Nru swftools-0.9.2+ds1/src/font2swf.doc swftools-0.9.1/src/font2swf.doc --- swftools-0.9.2+ds1/src/font2swf.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/font2swf.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,26 @@ +Usage: %s + +Converts a font to SWF. + +Takes a font file (.ttf, .afm, .pfa, .pfb and all other types +supported by FreeType) and converts it into a SWF file. +.PP +The SWF will contain the Font in SWF format (that is, a +DefineFont2 Tag) as well as a textfield containing all the +characters the font has. This means the resulting SWF will +be viewable. + +-h, --help + Print short help message and exit +-v, --verbose + Be verbose. Use more than one -v for greater effect. +-o, --output + Write output to file . + Write output to file . (If not given, the output will go + to a file called "output.swf") +-V, --version + Print version info and exit + +.SH AUTHOR + +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/gfx2gfx.c swftools-0.9.1/src/gfx2gfx.c --- swftools-0.9.2+ds1/src/gfx2gfx.c 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/gfx2gfx.c 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,297 @@ +/* pdf2swf.c + main routine for pdf2swf(1) + + Part of the swftools package. + + Copyright (c) 2001,2002,2003 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 "../../swftools/config.h" +#include "../../swftools/lib/args.h" +#include "../../swftools/lib/os.h" +#include "../../swftools/lib/gfxsource.h" +#include "../../swftools/lib/gfxdevice.h" +#include "../../swftools/lib/gfxpoly.h" +#include "../../swftools/lib/devices/pdf.h" +#include "../../swftools/lib/devices/swf.h" +#include "../../swftools/lib/devices/text.h" +#include "../../swftools/lib/devices/render.h" +#include "../../swftools/lib/devices/file.h" +#include "../../swftools/lib/devices/bbox.h" +#ifdef HAVE_LRF +#include "../../swftools/lib/devices/lrf.h" +#endif +#include "../../swftools/lib/devices/ocr.h" +#include "../../swftools/lib/devices/rescale.h" +#include "../../swftools/lib/devices/record.h" +#include "../../swftools/lib/readers/image.h" +#include "../../swftools/lib/readers/swf.h" +#include "../../swftools/lib/pdf/pdf.h" +#include "../../swftools/lib/log.h" + +static gfxsource_t*driver = 0; + +static char * outputname = 0; +static int loglevel = 3; +static char * pagerange = 0; +static char * filename = 0; +static const char * format = 0; + +int args_callback_option(char*name,char*val) { + if (!strcmp(name, "o")) + { + outputname = val; + return 1; + } + else if (!strcmp(name, "v")) + { + loglevel ++; + setConsoleLogging(loglevel); + return 0; + } + else if (!strcmp(name, "f")) + { + format = val; + return 1; + } + else if (!strcmp(name, "q")) + { + loglevel --; + setConsoleLogging(loglevel); + return 0; + } + else if (name[0]=='p') + { + do { + name++; + } while(*name == 32 || *name == 13 || *name == 10 || *name == '\t'); + + if(*name) { + pagerange = name; + return 0; + } + pagerange = val; + return 1; + } + else if (!strcmp(name, "s")) + { + if(!driver) { + fprintf(stderr, "Specify input file before -s\n"); + exit(1); + } + char*s = strdup(val); + char*c = strchr(s, '='); + if(c && *c && c[1]) { + *c = 0; + c++; + driver->setparameter(driver, s,c); + } else { + driver->setparameter(driver, s,"1"); + } + free(s); + return 1; + } + else if (!strcmp(name, "V")) + { + printf("pdf2swf - part of %s %s\n", PACKAGE, VERSION); + exit(0); + } + else + { + fprintf(stderr, "Unknown option: -%s\n", name); + exit(1); + } + return 0; +} + +struct options_t options[] = +{{"o","output"}, + {"q","quiet"}, + {"V","version"}, + {"s","set"}, + {"p","pages"}, + {0,0} +}; + +int args_callback_longoption(char*name,char*val) { + return args_long2shortoption(options, name, val); +} + +int args_callback_command(char*name, char*val) { + if (!filename) { + + filename = name; + + if(strstr(filename, ".pdf") || strstr(filename, ".PDF")) { + msg(" Treating file as PDF"); + driver = gfxsource_pdf_create(); + } else if(strstr(filename, ".swf") || strstr(filename, ".SWF")) { + msg(" Treating file as SWF"); + driver = gfxsource_swf_create(); + } else if(strstr(filename, ".jpg") || strstr(filename, ".JPG") || + strstr(filename, ".png") || strstr(filename, ".PNG")) { + msg(" Treating file as Image"); + driver = gfxsource_image_create(); + } + } else { + if(outputname) + { + fprintf(stderr, "Error: Do you want the output to go to %s or to %s?", + outputname, name); + exit(1); + } + outputname = name; + } + return 0; +} + +void args_callback_usage(char*name) +{ +} + +int main(int argn, char *argv[]) +{ + processargs(argn, argv); + initLog(0,-1,0,0,-1,loglevel); + + if(!filename) { + fprintf(stderr, "Please specify an input file\n"); + exit(1); + } + + if(!outputname) + { + if(filename) { + outputname = stripFilename(filename, ".out"); + msg(" Output filename not given. Writing to %s", outputname); + } + } + if(!outputname) + { + fprintf(stderr, "Please use -o to specify an output file\n"); + exit(1); + } + is_in_range(0x7fffffff, pagerange); + if(pagerange) + driver->setparameter(driver, "pages", pagerange); + + if(!filename) { + args_callback_usage(argv[0]); + exit(0); + } + + gfxdocument_t* doc = driver->open(driver, filename); + if(!doc) { + msg(" Couldn't open %s", filename); + exit(1); + } + + if(!format) { + char*x = strrchr(outputname, '.'); + if(x) + format = x+1; + } + + + gfxresult_t*result = 0; +#ifdef HAVE_LRF + if(!strcasecmp(format, "lrf")) { + gfxdevice_t lrf; + gfxdevice_lrf_init(&lrf); + + gfxdevice_t rescale; + gfxdevice_rescale_init(&rescale, &lrf, 592, 732, 0); + + gfxdevice_t*out = &rescale; + out->setparameter(out, "keepratio", "1"); + out->setparameter(out, "pagepattern", outputname); + + gfxdevice_t bbox2,*bbox=&bbox2; + gfxdevice_bbox_init(bbox); + bbox->setparameter(bbox, "graphics", "0"); + + int pagenr; + + for(pagenr = 1; pagenr <= doc->num_pages; pagenr++) + { + if(is_in_range(pagenr, pagerange)) { + gfxpage_t* page = doc->getpage(doc, pagenr); + bbox->startpage(bbox,-1,-1); + page->render(page, bbox); + gfxbbox_t b = gfxdevice_bbox_getbbox(bbox); + + out->startpage(out, b.xmax-b.xmin, b.ymax-b.ymin); + page->rendersection(page, out, -b.xmin, -b.ymin, 0,0,b.xmax-b.xmin,b.ymax-b.ymin); + out->endpage(out); + + page->destroy(page); + } + } + result = out->finish(out); + } else +#endif + { + gfxdevice_t _out,*out=&_out; + if(!strcasecmp(format, "ocr")) { + gfxdevice_ocr_init(out); + } else if(!strcasecmp(format, "swf")) { + gfxdevice_swf_init(out); + } else if(!strcasecmp(format, "img") || !strcasecmp(format, "png")) { + gfxdevice_render_init(out); + out->setparameter(out, "antialize", "4"); + } else if(!strcasecmp(format, "txt")) { + gfxdevice_text_init(out); + } else if(!strcasecmp(format, "log")) { + gfxdevice_file_init(out, "/tmp/device.log"); + } else if(!strcasecmp(format, "pdf")) { + gfxdevice_pdf_init(out); + } else { + msg(" Invalid output format: %s", format); + exit(1); + } + + int pagenr; + for(pagenr = 1; pagenr <= doc->num_pages; pagenr++) + { + if(is_in_range(pagenr, pagerange)) { + gfxpage_t* page = doc->getpage(doc, pagenr); + out->startpage(out, page->width, page->height); + page->render(page, out); + out->endpage(out); + page->destroy(page); + } + } + result = out->finish(out); + } + + if(result) { + if(result->save(result, outputname) < 0) { + exit(1); + } + result->destroy(result); + } + + doc->destroy(doc); + + driver->destroy(driver); + return 0; +} + diff -Nru swftools-0.9.2+ds1/src/gif2swf.1 swftools-0.9.1/src/gif2swf.1 --- swftools-0.9.2+ds1/src/gif2swf.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/gif2swf.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH gif2swf "1" "February 2012" "gif2swf" "swftools" +.TH gif2swf "1" "April 2012" "gif2swf" "swftools" .SH NAME gif2swf \- Takes a number of gif files and converts them to a swf movie, one picture per frame. diff -Nru swftools-0.9.2+ds1/src/gif2swf.doc swftools-0.9.1/src/gif2swf.doc --- swftools-0.9.2+ds1/src/gif2swf.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/gif2swf.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,31 @@ +Usage: %s [-X width] [-Y height] [-o file.swf] [-r rate] file1.gif [file2.gif ...] + +Takes a number of gif files and converts them to a swf movie, one +picture per frame. + +This tools converts gif image files into an SWF animation. It takes any +number of input pictures, and converts them to SWF one-by-one, where every +converted picture is a seperate frame in the target SWF. + +-r, --rate + Set movie framerate (frames per second) +-o, --output + Set name for SWF output file. + Explicitly specify output file. (Otherwise, output will go to stdout / output.swf) +-z, --zlib + Enable Flash 6 (MX) Zlib Compression + Use Flash MX (SWF 6) Zlib encoding for the output. The resulting SWF will be + smaller, but not playable in Flash Plugins of Version 5 and below. +-l, --loop + Set loop count. (default: 0 [=infinite loop]) +-X, --pixel + Force movie width to (default: autodetect) +-Y, --pixel + Force movie height to (default: autodetect) +-v, --verbose + Set verbose level (0=quiet, 1=default, 2=debug) +-C, --cgi + For use as CGI- prepend http header, write to stdout +-V, --version + Print version information and exit + diff -Nru swftools-0.9.2+ds1/src/jpeg2swf.1 swftools-0.9.1/src/jpeg2swf.1 --- swftools-0.9.2+ds1/src/jpeg2swf.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/jpeg2swf.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH jpeg2swf "1" "February 2012" "jpeg2swf" "swftools" +.TH jpeg2swf "1" "April 2012" "jpeg2swf" "swftools" .SH NAME jpeg2swf \- Converts jpeg images to SWF. diff -Nru swftools-0.9.2+ds1/src/jpeg2swf.doc swftools-0.9.1/src/jpeg2swf.doc --- swftools-0.9.2+ds1/src/jpeg2swf.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/jpeg2swf.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,47 @@ +Usage: %s [-options [value]] imagefiles[.jpg]|[.jpeg] [...] + +Converts jpeg images to SWF. + +This tool converts jpeg image files into an SWF animation. It takes any +number of input pictures, and converts them to SWF one-by-one, where every +converted picture is a seperate frame in the target SWF. + +-o --output + Explicitly specify output file. (otherwise, output.swf will be used) + Explicitly specify output file. (Otherwise, output will go to stdout / output.swf) +-q --quality + Set compression quality (1-100, 1=worst, 100=best) + Set compression quality (1-100, 1=worst, 100=best). + This option can be set independently for each image. +-r --rate + Set movie framerate (frames per second) +-z --zlib + Enable Flash 6 (MX) Zlib Compression + Use Flash MX (SWF 6) Zlib encoding for the output. The resulting SWF will be + smaller, but not playable in Flash Plugins of Version 5 and below. +-M --mx + Use Flash MX H.263 compression (use for correlated images) +-x --xoffset + horizontally offset images by +-y --yoffset + vertically offset images by +-X --width + Force movie width to (default: autodetect) +-Y --height + Force movie height to (default: autodetect) +-T --flashversion + Set flash file version to +-v --verbose + Set verbose level to (0=quiet, 1=default, 2=debug) +-V --version + Print version information and exit +-f --fit-to-movie + Fit images to movie size +-e --export + Make importable as asset with + +.SH AUTHORS + +Rainer Böhme +.TP +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/pdf2pdf.1 swftools-0.9.1/src/pdf2pdf.1 --- swftools-0.9.2+ds1/src/pdf2pdf.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/pdf2pdf.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH pdf2pdf "1" "February 2012" "pdf2pdf" "swftools" +.TH pdf2pdf "1" "April 2012" "pdf2pdf" "swftools" .SH NAME pdf2pdf \- Runs a pdf through the pdf2swf conversion engine, and writes it back to a pdf. diff -Nru swftools-0.9.2+ds1/src/pdf2pdf.doc swftools-0.9.1/src/pdf2pdf.doc --- swftools-0.9.2+ds1/src/pdf2pdf.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/pdf2pdf.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,29 @@ +Usage: %s + +Runs a pdf through the pdf2swf conversion engine, and writes it back to a pdf. + +Runs a pdf through the pdf2swf conversion engine, and writes it +back to a pdf. + +-h, --help + Print short help message and exit +-v, --verbose + Be verbose. Use more than one -v for greater effect. +-p, --pages + Pages to convert +-X, --width + Make sure the output pdf is pixels wide +-Y, --height + Make sure the output pdf is pixels high +-s, --set = + Set to +-o, --output + Write output to file . + Write output to file . (If not given, the output will go + to a file with the extension .print.pdf) +-V, --version + Print version info and exit + +.SH AUTHOR + +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/png2swf.1 swftools-0.9.1/src/png2swf.1 --- swftools-0.9.2+ds1/src/png2swf.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/png2swf.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH png2swf "1" "February 2012" "png2swf" "swftools" +.TH png2swf "1" "April 2012" "png2swf" "swftools" .SH NAME png2swf \- Takes a number of png files and converts them to a swf movie, one picture per frame. diff -Nru swftools-0.9.2+ds1/src/png2swf.c swftools-0.9.1/src/png2swf.c --- swftools-0.9.2+ds1/src/png2swf.c 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/png2swf.c 2012-06-20 15:37:18.000000000 +0000 @@ -777,7 +777,7 @@ printf("-q , --quiet Omit normal log messages, only log errors\n"); printf("-C , --cgi For use as CGI- prepend http header, write to stdout\n"); printf("-V , --version Print version information and exit\n"); - printf("-s , --scale Scale image to % size.\n"); + printf("-s , --scale Scale image to %% size.\n"); printf("\n"); } diff -Nru swftools-0.9.2+ds1/src/png2swf.doc swftools-0.9.1/src/png2swf.doc --- swftools-0.9.2+ds1/src/png2swf.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/png2swf.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,44 @@ +Usage: %s [-X width] [-Y height] [-o file.swf] [-r rate] file1.png [file2.png...] + +Takes a number of png files and converts them to a swf movie, one +picture per frame. + +This tools converts png image files into an SWF animation. It takes any +number of input pictures, and converts them to SWF one-by-one, where every +converted picture is a seperate frame in the target SWF. +.PP +The way the +images are encoded in SWF is very similar to PNG (in that a zlib-based, lossless +compression algorithm is used). + +-r, --rate + Set movie framerate (frames per second) +-o, --output + Set name for SWF output file. + Explicitly specify output file. (Otherwise, output will go to stdout / output.swf) +-j, --jpeg + Generate a lossy jpeg bitmap inside the SWF, with a given quality (1-100) +-z --zlib + Enable Flash 6 (MX) Zlib Compression + Use Flash MX (SWF 6) Zlib encoding for the output. The resulting SWF will be + smaller, but not playable in Flash Plugins of Version 5 and below. +-T, --flashversion + Set the flash version to generate +-X, --pixel + Force movie width to (default: autodetect) +-Y, --pixel + Force movie height to (default: autodetect) +-v, --verbose + Set verbose level (0=quiet, 1=default, 2=debug) +-q, --quiet + Omit normal log messages, only log errors +-C, --cgi + For use as CGI- prepend http header, write to stdout +-V, --version + Print version information and exit +-s, --scale + Scale image to % size. + +.SH AUTHOR + +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/swfbbox.1 swftools-0.9.1/src/swfbbox.1 --- swftools-0.9.2+ds1/src/swfbbox.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/swfbbox.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH swfbbox "1" "February 2012" "swfbbox" "swftools" +.TH swfbbox "1" "April 2012" "swfbbox" "swftools" .SH NAME swfbbox \- Tool for playing around with SWF bounding boxes. diff -Nru swftools-0.9.2+ds1/src/swfbbox.doc swftools-0.9.1/src/swfbbox.doc --- swftools-0.9.2+ds1/src/swfbbox.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/swfbbox.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,33 @@ +Usage: %s [-OS] file.swf + +Tool for playing around with SWF bounding boxes. + +This tool can, among others, recalculate some bounding boxes of SWFs +in order to speed them up or make them smaller. +.PP +It can also dump the corners of the bounding boxes of all frames of a movie. + +-h, --help + Print help and exit +-b, --bbox + Show movie bounding box (default) +-B, --newbbox + Show recalculated (optimized/expanded) bounding box +-e, --expand + Write out a new file using the recalculated header bounding box +-O, --optimize + Recalculate all object bounding boxes (except for the header) +-S, --swifty + Print out transformed bounding boxes +-c, --clip + Clip bounding boxes to movie size +-o, --output + Set output filename to (for -O) +-v, --verbose + Be more verbose +-V, --version + Print program version and exit + +.SH AUTHOR + +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/swfbytes.1 swftools-0.9.1/src/swfbytes.1 --- swftools-0.9.2+ds1/src/swfbytes.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/swfbytes.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH swfbytes "1" "February 2012" "swfbytes" "swftools" +.TH swfbytes "1" "April 2012" "swfbytes" "swftools" .SH NAME swfbytes \- Tool for simplifying the hex-editing of SWF files. diff -Nru swftools-0.9.2+ds1/src/swfbytes.doc swftools-0.9.1/src/swfbytes.doc --- swftools-0.9.2+ds1/src/swfbytes.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/swfbytes.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,18 @@ +Usage: %s [-v] file.swf > file.hexdump +OR: %s file.hexdump + +Tool for simplifying the hex-editing of SWF files. + +With this tool and a text editor, you can perform some basic +editing operations on SWF files. + +-h, --help + Print help and exit +-v, --verbose + Be more verbose +-V, --version + Print program version and exit + +.SH AUTHOR + +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/swfc.1 swftools-0.9.1/src/swfc.1 --- swftools-0.9.2+ds1/src/swfc.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/swfc.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH swfc "1" "February 2012" "swfc" "swftools" +.TH swfc "1" "April 2012" "swfc" "swftools" .SH NAME swfc \- compile .sc files to swf. diff -Nru swftools-0.9.2+ds1/src/swfc.doc swftools-0.9.1/src/swfc.doc --- swftools-0.9.2+ds1/src/swfc.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/swfc.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,24 @@ +Usage: %s [-o file.swf] file.sc + +compile .sc files to swf. + +Compiles a file written in sc (SWF Script) into a number of SWF files. + +-h, --help + Print short help message and exit +-V, --version + Print version info and exit +-C, --cgi + Output to stdout (for use in CGI environments) +-v, --verbose + Increase verbosity. + Increase verbosity. Use more than one \fB-v\fR for greater effect. +-o, --output + Set output file to . + Specify output file (Default: output.swf). + This affects only the parts of the .sc file which haven't + specified an output file themselves. + +.SH AUTHOR + +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/swfcombine.1 swftools-0.9.1/src/swfcombine.1 --- swftools-0.9.2+ds1/src/swfcombine.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/swfcombine.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH swfcombine "1" "February 2012" "swfcombine" "swftools" +.TH swfcombine "1" "April 2012" "swfcombine" "swftools" .SH NAME swfcombine \- a tool for combining swf (flash) files diff -Nru swftools-0.9.2+ds1/src/swfcombine.c swftools-0.9.1/src/swfcombine.c --- swftools-0.9.2+ds1/src/swfcombine.c 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/swfcombine.c 2012-06-20 15:37:18.000000000 +0000 @@ -321,7 +321,7 @@ printf("-f , --frame The following identifier is a frame or framelabel, not an id or objectname\n"); printf("-x , --movex x Adjust position of slave by pixels\n"); printf("-y , --movey y Adjust position of slave by pixels\n"); - printf("-s , --scale Adjust size of slave by percent (e.g. 100% = original size)\n"); + printf("-s , --scale Adjust size of slave by percent (e.g. 100%% = original size)\n"); printf("-r , --rate Set movie framerate to (frames/sec)\n"); printf("-X , --width Force movie bbox width to (default: use master width (not with -t))\n"); printf("-Y , --height Force movie bbox height to (default: use master height (not with -t))\n"); diff -Nru swftools-0.9.2+ds1/src/swfcombine.doc swftools-0.9.1/src/swfcombine.doc --- swftools-0.9.2+ds1/src/swfcombine.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/swfcombine.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,107 @@ +Usage: %s [-rXYomlcv] [-f] masterfile [-xysf] [(name1|#id1)=]slavefile1 .. [-xysf] [(nameN|#idN)=]slavefileN +OR: %s [-rXYomv] --stack[1] [-xysf] [(name1|#id1)=]slavefile1 .. [-xysf] [(nameN|#idN)=]slavefileN +OR: %s [-rXYov] --cat [-xysf] [(name1|#id1)=]slavefile1 .. [-xysf] [(nameN|#idN)=]slavefileN +OR: %s [-rXYomlcv] --dummy [-xys] [file] + +a tool for combining swf (flash) files + +Take two or more SWF files, and combine them into a new SWF. SWFs can either +be stacked (no masterfile is present) or inserted (into the masterfile). +.PP +SWF files are animation files which can be displayed in Web Browsers using +the Flash Plugin. +.LP +For template mechanisms, it's often convenient to separate the processes +of generating small animation fragments and merging them into a big +movie. swfcombine can be used to perform the latter. + +-o --output + explicitly specify output file. (otherwise, output.swf will be used) +-t --stack + place each slave in a seperate frame (no master movie) + Don't assume the first file is a master file. Instead, store each + file in a seperate frame. +-T --stack1 + place each slave in the first frame (no master movie) +-m --merge + Don't store the slaves in Sprites/MovieClips + Do not store the slave files in a sprite/MovieClip. Instead, merge the files frame by frame. +-a --cat + concatenate all slave files (no master movie) +-l --overlay + Don't remove any master objects, only overlay new objects +-c --clip + Clip the slave objects by the corresponding master objects +-v --verbose + Be verbose. Use more than one -v for greater effect +-F --flashversion + Set the flash version of the output file. +-d --dummy + Don't require slave objects (for changing movie attributes) + Don't require the presence of slave objects. Usually used together with \fB\-X\fR, \fB\-Y\fR or \fB\-r\fR. +-f --frame + The following identifier is a frame or framelabel, not an id or objectname + The next slave replaces a frame, not an object. Therefore the slave identifier is a + frame number (#frame=) or frame label (framelabel=). +-x --movex + x Adjust position of slave by pixels +-y --movey + y Adjust position of slave by pixels +-s --scale + Adjust size of slave by percent (e.g. 100% = original size) +-r --rate + Set movie framerate to (frames/sec) + Force the output to have the framerate . (Otherwise, the framerate of the master file will be used) +-X --width + Force movie bbox width to (default: use master width (not with -t)) +-Y --height + Force movie bbox height to (default: use master height (not with -t)) +-N --local-with-networking + Make output file "local-with-networking" +-G --hardware-gpu + Set the "use hardware gpu" bit in the output file +-B --accelerated-blit + Set the "use accelerated blit" bit in the output file +-L --local-with-filesystem + Make output file "local-with-filesystem" +-z --zlib + Enable Flash 6 (MX) Zlib Compression + Use Flash MX (SWF 6) Zlib encoding for the output. The resulting SWF will be + smaller, but not playable in Flash Plugins of Version 5 and below. + +.PP +.SH Combining two or more .swf files using a master file +Of the flash files to be combined, all except one will be packed into a sprite +structure (Movieclip) which will then be inserted into the master .swf file. +This means that, in terms of trees, when combining several flash files, +one will form the root of the tree, while the others will be +appended to the root as a subnode. +The user has to specify which of the files will become the root +of the tree ("master") and which will be the appended nodes ("slaves"). +The slave files must all have a name, which is then used to determine +their exact position inside the master file. +The slave files will then be converted into sprites, inserted into the +master file, and all PlaceObject tags in the master file which match the +name of the slave file will be updated to correctly display the slave sprite. +The slave name may also be the object id, preceded by '#', in which case +the object to be replaced is referenced by id and not by instance name. +.SH Combining (stacking) one or more .swf files without a master +The flash files will be inserted in seperate frames. They will still be +packed into Movieclips, therefore the outputfile will have exactly as many +frames as there were inputfiles. Also, the files don't need to have names. +If you want to access the Movieclips, their names are frameXX, where XX is +the decimal number of the file, starting by zero (00). + +.SH EXAMPLES + +Create two flash movies. Insert some rectangle into one of them, and give +it a name. (E.g. "foo") Now call + +swfcombine -o combined.swf master.swf foo=slave.swf + +As a result, the slave movie should be visible inside the master movie +at the position where the rectangle used to be. + +.SH AUTHOR + +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/swfdump.1 swftools-0.9.1/src/swfdump.1 --- swftools-0.9.2+ds1/src/swfdump.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/swfdump.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH swfdump "1" "February 2012" "swfdump" "swftools" +.TH swfdump "1" "April 2012" "swfdump" "swftools" .SH NAME swfdump \- Display an SWF file's content. diff -Nru swftools-0.9.2+ds1/src/swfdump.doc swftools-0.9.1/src/swfdump.doc --- swftools-0.9.2+ds1/src/swfdump.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/swfdump.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,54 @@ +Usage: %s [-atpdu] file.swf + +Display an SWF file's content. + +A tool for displaying information about flash files +.PP +swfdump shows ids, names and depths of objects defined in the SWF file. +It can furthermore also disassemble Actionscript, extract texts, and +display placement information about objects. + +-h, --help + Print short help message and exit +-D, --full + Show everything. Same as -atp +-V, --version + Print version info and exit +-e, --html + Print out html code for embedding the file +-E, --xhtml + Print out xhtml code for embedding the file +-a, --action + Disassemble action tags +-t, --text + Show text fields (like swfstrings). +-s, --shapes + Show shape coordinates/styles +-F, --fonts + Show font information +-p, --placements + Show placement information +-B, --buttons + Show button information +-b, --bbox + Print tag's bounding boxes +-X, --width + Prints out a string of the form "-X width". + Print out the horizontal dimension of the movie, in a string of the form "-X width" +-Y, --height + Prints out a string of the form "-Y height". + Print out the vertical dimension of the movie, in a string of the form "-Y height" +-r, --rate + Prints out a string of the form "-r rate". + Print out the frame rate of the movie, in a string of the form "-r rate". +-f, --frames + Prints out a string of the form "-f framenum". + Print out the number of frames in the movie, in a string of the form "-f frames" +-d, --hex + Print hex output of tag data, too. +-u, --used + Show referred IDs for each Tag. + +.SH AUTHOR + +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/swfstrings.doc swftools-0.9.1/src/swfstrings.doc --- swftools-0.9.2+ds1/src/swfstrings.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/swfstrings.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,25 @@ +Usage: %s [options] file.swf + +Extracts strings from SWF files. + +This tool extracts strings from SWF files. It parses SWF font records +and text records and prints unicode-encoded characters to stdout. + +-f --fonts + Print out font information for each text block +-x --xpos + Set bounding box x coordinate +-y --ypos + Set bounding box y coordinate +-W --width + Set bounding box width +-H --height + Set bounding box height +-V --version + Print version information and exit + +.SH AUTHORS + +Rainer Böhme +.TP +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/testswfc swftools-0.9.1/src/testswfc --- swftools-0.9.2+ds1/src/testswfc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/testswfc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,159 @@ +#!/bin/sh +exec 3>&2 4>&1 5>output 2>&5 >&5 6>/dev/null +testswffile() { + echo -n "testing $1 for existence..." + test -f $1 || (touch failed;echo -n "not there" >&5;return;) + echo + echo -n "testing $1 for wellformedness..." + ./swfdump $1 | tail -n 1 | grep '\b0 END\b' >&6 2>&6 || (touch failed;echo -n "wrong end";return;) + ./swfdump $1 | grep 'rfxswf|warning|error|bounds' >&6 2>&6 && (touch failed;echo -n "error";return;) + ./swfdump $1 2>&1 >&6 | grep '^.*$' >&6 2>&6 && (touch failed;echo -n "swfdump stderr";./swfdump $1 >&6 2>&5;return;) + echo +} +showresult() { + test -f failed || echo ' succeeded' >&4 + test -f failed && echo ' failed' >&4 +} +showfile() { + echo '===========================' >&5 + cat $1 >&5 + echo '===========================' >&5 +} +starttest() { + test=$1 + echo -n "Test \"${test}\"..." >&4 + echo "================== starting test ${test} ===================" >&5 + rm -f failed +} +swfc() { + file=$1 + echo "running ${swfc} ${file}...">&5 + shift + catchsegv ${swfc} $file $@ >test.s 2>test.s2 + test -s test.s2 && (touch failed;cat test.s2 >&5) + grep 'Segmentation fault' test.s && (touch failed) + rm -f test.s test.s2 2>&6 +} + +swfc=./swfc + +starttest sprite1 +rm -f output.swf +cat > test.sc < test.sc < test.sc < test.sc < test.sc < test.sc <&6 2>&6 || touch failed +showresult + +starttest nostart2 +rm -f output.swf +cat > test.sc < test.sc < test.sc <&5 +test -f output.swf && touch failed +showresult + +echo -n '' >&4 +rm -f test.sc failed file1.swf file2.swf output.swf diff -Nru swftools-0.9.2+ds1/src/ttftool.doc swftools-0.9.1/src/ttftool.doc --- swftools-0.9.2+ds1/src/ttftool.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/ttftool.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,18 @@ +Usage: %s [-n] fontfile.ttf + +Displays information about TrueType (ttf) font files. + +This tool converts jpeg image files into an SWF animation. It takes any +number of input pictures, and converts them to SWF one-by-one, where every +converted picture is a seperate frame in the target SWF. + +-n --name + Display the font name. +-v --verbose + Increase verbosity. +-V --version + Print version information and exit + +.SH AUTHORS + +Matthias Kramm diff -Nru swftools-0.9.2+ds1/src/wav2swf.1 swftools-0.9.1/src/wav2swf.1 --- swftools-0.9.2+ds1/src/wav2swf.1 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/src/wav2swf.1 2012-06-20 15:37:18.000000000 +0000 @@ -1,4 +1,4 @@ -.TH wav2swf "1" "February 2012" "wav2swf" "swftools" +.TH wav2swf "1" "April 2012" "wav2swf" "swftools" .SH NAME wav2swf \- convert a WAV file to an SWF animation. diff -Nru swftools-0.9.2+ds1/src/wav2swf.doc swftools-0.9.1/src/wav2swf.doc --- swftools-0.9.2+ds1/src/wav2swf.doc 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/src/wav2swf.doc 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,41 @@ +Usage: %s [-o filename] file.wav + +convert a WAV file to an SWF animation. + +Takes a wav file and converts it to a swf movie. + +-h, --help + Print short help message and exit +-V, --version + Print version info and exit +-o, --output + Explicitly specify output file. (Otherwise, output will go to output.swf) +-r, --framerate + Set file framerate to frames per second. +-s , --samplerate + Set samplerate to frames per second (default: 11025). +-d, --definesound + Generate a DefineSound tag instead of streaming sound. + Store the sound as DEFINESOUND tag, not as streaming sound. Allows for + looping. +-l, --loop n + (Only used with -d) + Loop the sound n times. +-C --cgi + For use as CGI- prepend http header, write to stdout. +-S, --stop + Stop the movie at frame 0 + Stop the movie at frame 0, and start the sound at 1, so that the + sound will not play until a "GotoFrame(1)" is issued. + (For use with flashsound.js). +-E, --end + Stop the movie at the end frame +-b --bitrate + Set mp3 bitrate to (default: 32) +-v --verbose + Be more verbose + Be more verbose. (Use more than one -v for greater effect) + +.SH AUTHOR + +Matthias Kramm diff -Nru swftools-0.9.2+ds1/swfs/Makefile.in swftools-0.9.1/swfs/Makefile.in --- swftools-0.9.2+ds1/swfs/Makefile.in 2012-04-08 17:25:26.000000000 +0000 +++ swftools-0.9.1/swfs/Makefile.in 2012-06-20 15:37:18.000000000 +0000 @@ -41,9 +41,9 @@ $(INSTALL_DATA) ./PreLoaderTemplate.swf $(pkgdatadir)/swfs/PreLoaderTemplate.swf $(INSTALL_DATA) ./tessel_loader.swf $(pkgdatadir)/swfs/tessel_loader.swf $(INSTALL_DATA) ./swft_loader.swf $(pkgdatadir)/swfs/swft_loader.swf - rm -f $(pkgdatadir)/swfs/default_viewer.swf -o -L $(pkgdatadir)/swfs/default_viewer.swf + rm -f $(pkgdatadir)/swfs/default_viewer.swf $(LN_S) $(pkgdatadir)/swfs/simple_viewer.swf $(pkgdatadir)/swfs/default_viewer.swf - rm -f $(pkgdatadir)/swfs/default_loader.swf -o -L $(pkgdatadir)/swfs/default_loader.swf + rm -f $(pkgdatadir)/swfs/default_loader.swf $(LN_S) $(pkgdatadir)/swfs/tessel_loader.swf $(pkgdatadir)/swfs/default_loader.swf uninstall: Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/wx/ArialBold.ttf and /tmp/M5qDI_SGQH/swftools-0.9.1/wx/ArialBold.ttf differ Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/wx/Arial.ttf and /tmp/M5qDI_SGQH/swftools-0.9.1/wx/Arial.ttf differ Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/wx/Courier.ttf and /tmp/M5qDI_SGQH/swftools-0.9.1/wx/Courier.ttf differ Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/wx/gpdf2swf.ico and /tmp/M5qDI_SGQH/swftools-0.9.1/wx/gpdf2swf.ico differ diff -Nru swftools-0.9.2+ds1/wx/gpdf2swf.py swftools-0.9.1/wx/gpdf2swf.py --- swftools-0.9.2+ds1/wx/gpdf2swf.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gpdf2swf.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +from __future__ import division +import __builtin__ +import os +import sys +#import imp + +#def main_is_frozen(): +# return (hasattr(sys, "frozen") or # new py2exe +# hasattr(sys, "importers") # old py2exe +# or imp.is_frozen("__main__")) # tools/freeze +# +##if not main_is_frozen(): +## try: +## import wxversion +## wxversion.select("2.6") +## except: +## wxversion.select("2.8") +# +#def get_main_dir(): +# if main_is_frozen(): +# return os.path.dirname(sys.executable) +# return os.path.dirname(os.path.abspath(__file__)) +#__builtin__.get_main_dir = get_main_dir +#__builtin__.GPDF2SWF_BASEDIR = get_main_dir() +# +#pyver = "".join(map(str, sys.version_info[0:2])) +##print >>sys.stderr, pyver +#if main_is_frozen(): +# sys.path.insert(0, os.path.join("..", "python%s" % pyver)) +#else: +# sys.path.insert(0, os.path.join("..", "lib", "python")) +# sys.path.insert(1, os.path.join("..", "python%s" % pyver)) + +import wx +#print >>sys.stderr, wx.VERSION +from lib.app import Pdf2Swf + +__builtin__.GPDF2SWF_BASEDIR = os.path.dirname(os.path.abspath(sys.argv[0])) + +if __name__ == "__main__": + #print "sys.argv[0]", sys.argv[0] + #print "abspath sys.argv[0]", + #print "sys.executable", sys.executable + #print "abspath sys.executable", os.path.abspath(sys.executable) + #print "GPDF2SWF_BASEDIR", GPDF2SWF_BASEDIR + app = wx.App(False) + app.SetAppName(u"gpdf2swf") + Pdf2Swf() + app.MainLoop() + diff -Nru swftools-0.9.2+ds1/wx/gui/boldstatictext.py swftools-0.9.1/wx/gui/boldstatictext.py --- swftools-0.9.2+ds1/wx/gui/boldstatictext.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gui/boldstatictext.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +import wx + +class BoldStaticText(wx.StaticText): + def __init__(self, *args, **kwargs): + wx.StaticText.__init__(self, *args, **kwargs) + font = self.GetFont() + font.SetWeight(wx.BOLD) + self.SetFont(font) + diff -Nru swftools-0.9.2+ds1/wx/gui/choicetext.py swftools-0.9.1/wx/gui/choicetext.py --- swftools-0.9.2+ds1/wx/gui/choicetext.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gui/choicetext.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +import wx +import wx.lib.intctrl + +class ChoiceInt(wx.Panel): + def __init__(self, parent, choices=[], editselection=None): + wx.Panel.__init__(self, parent) + choices = choices + self.editselection = editselection + + s = wx.BoxSizer(wx.HORIZONTAL) + + self.choice = choice = wx.Choice(self, choices=choices) + self.text = text = wx.lib.intctrl.IntCtrl(self) + s.Add(choice, 1, wx.EXPAND) + s.Add(text, 1, wx.EXPAND) + + self.SetSizer(s) + + choice.Bind(wx.EVT_CHOICE, self.__OnChoice) + + def IsEditableSelection(self, n): + return n == self.editselection + + def GetValue(self): + return self.text.GetValue() + + def SetValue(self, value): + self.text.SetValue(value) + + def GetSelectionAndValue(self): + return self.choice.GetSelection(), self.text.GetValue() + + def SetSelectionAndValue(self, n, value): + self.SetSelection(n) + self.text.SetValue(value) + + def GetSelection(self): + return self.choice.GetSelection() + + def SetSelection(self, n): + self.choice.SetSelection(n) + self.EnableText(self.IsEditableSelection(n)) + + def EnableText(self, enable): + self.text.Enable(enable) + + def __OnChoice(self, event): + self.EnableText(self.IsEditableSelection(event.GetSelection())) + diff -Nru swftools-0.9.2+ds1/wx/gui/dialogs.py swftools-0.9.1/wx/gui/dialogs.py --- swftools-0.9.2+ds1/wx/gui/dialogs.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gui/dialogs.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,141 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +from __future__ import division +import os +import gfx +import wx +from lib.wordwrap import wordwrap + +from gui.options import Quality, ViewerBook + + +class _ProgressDialog(wx.ProgressDialog): + def __init__(self, title, message, maximum=100, parent=None, + style=wx.PD_AUTO_HIDE|wx.PD_APP_MODAL): + wx.ProgressDialog.__init__(self, title, message, maximum=maximum, + parent=parent, style=style) + + +if wx.VERSION[:2] == (2, 6): + ProgressDialog = _ProgressDialog +else: + class ProgressDialog(_ProgressDialog): + def Update(self, *args, **kwargs): + return wx.ProgressDialog.Update(self, *args, **kwargs)[0] + +class OptionsDialog(wx.Dialog): + def __init__(self, parent): + wx.Dialog.__init__(self, parent) + + app_name = wx.GetApp().GetAppName() + self.SetTitle(u"%s options" % app_name) + + p = wx.Notebook(self) + self.__quality = Quality(p) + self.__viewers = ViewerBook(p) + p.AddPage(self.__quality, u"Quality") + p.AddPage(self.__viewers, u"Viewer") + + sizer = wx.BoxSizer(wx.VERTICAL) + btnsizer = wx.StdDialogButtonSizer() + + btn = wx.Button(self, wx.ID_OK) + btn.SetDefault() + btnsizer.AddButton(btn) + btnsizer.Realize() + + + sizer.Add(p, 0, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) + sizer.Add(btnsizer, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) + + self.SetSizer(sizer) + sizer.Fit(self) + + def __get_quality(self): + return self.__quality + quality_panel = property(__get_quality) + + def __get_viewers(self): + return self.__viewers + viewers_panel = property(__get_viewers) + + def __get_quality_options(self): + return self.__quality.options + quality = property(__get_quality_options) + + def __get_viewers_options(self): + return self.__viewers.options + viewers = property(__get_viewers_options) + + +from gui.info import InfoList +class InfoDialog(wx.Dialog): + def __init__(self, parent): + wx.Dialog.__init__(self, parent, + style=wx.DEFAULT_DIALOG_STYLE + |wx.RESIZE_BORDER + ) + + app_name = wx.GetApp().GetAppName() + self.SetTitle(u"Document info - %s" % app_name) + + self.info = InfoList(self) + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.info, 1, wx.EXPAND, 0) + + + btnsizer = wx.BoxSizer(wx.HORIZONTAL) + + btn = wx.Button(self, wx.ID_OK) + btn.SetDefault() + #self.SetAffirmativeId(wx.ID_CLOSE) + btnsizer.Add(btn) + sizer.Add(btnsizer, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) + + self.SetSizer(sizer) + + +class AboutDialog: + def __init__(self, parent): + appname = wx.GetApp().GetAppName() + version = " - part of SWFTools %s" % gfx.VERSION + copyright = (u"Copyright (c) 2008,2009,2010\n" + u"Matthias Kramm ") + description = u"A graphical user interface for pdf2swf" + developers = (u"Developers:\nMatthias Kramm \n" + u"Ricardo Pedroso ") + + + message = ("%(appname)s %(version)s\n\n" + "%(description)s\n\n" + "%(developers)s\n\n" + "%(copyright)s" % locals()) + caption = "About %s" % appname + + #wx.MessageBox(message, caption) + + wx.MessageDialog(parent, message, caption, style=wx.OK | wx.CENTRE).ShowModal() + diff -Nru swftools-0.9.2+ds1/wx/gui/fields.py swftools-0.9.1/wx/gui/fields.py --- swftools-0.9.2+ds1/wx/gui/fields.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gui/fields.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,195 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +import wx +from choicetext import ChoiceInt + +class Option(object): + def __init__(self, name, label, data, selection): + self.name = name + self.label = label + self.data = data + self.selection = selection + + def _Update(self): + self.value = self.ctrl.GetValue() + + def _SetControlValue(self, value): + self.value = value + self.ctrl.SetValue(value) + + def _OnUpdate(self, event): + self._Update() + event.Skip() + + def SetValue(self, value): + self._SetControlValue(value) + +class Hidden: + def __init__(self, name, value): + self.name = name + self.value = value + + def draw(self, parent): + return None, None + + def SetValue(self, value): + self.value = value + +class Choose(Option): + klass = wx.Choice + def __init__(self, name, label, data, selection): + Option.__init__(self, name, label, data, selection) + self.choices = data[0::2] + self.data = data[1::2] + + def draw(self, parent): + label = wx.StaticText(parent, label=self.label) + self.ctrl = ctrl = self.klass(parent, choices=self.choices) + ctrl.Bind(wx.EVT_CHOICE, self._OnUpdate) + self._SetControlValue(self.selection) + return label, ctrl + + def _Update(self): + n = self.ctrl.GetSelection() + self.value = self.data[n] + + def _SetControlValue(self, n): + self.ctrl.SetSelection(n) + self.value = self.data[n] + + def SetValue(self, value): + # in python < 2.6 tuples doesnt have the index method + # be sure that we are using a list + tmp = list(self.data) + try: + n = tmp.index(value) + except ValueError: + n = self.selection + self._SetControlValue(n) + +class ChooseAndInt(Choose): + klass = ChoiceInt + def __init__(self, name, label, data, selection, editselection, editvalue): + Choose.__init__(self, name, label, data, selection) + self.editselection = editselection + self.editvalue = editvalue + + def draw(self, parent): + label = wx.StaticText(parent, label=self.label) + self.ctrl = ctrl = self.klass(parent, choices=self.choices, + editselection=self.editselection) + ctrl.choice.Bind(wx.EVT_CHOICE, self._OnUpdate) + ctrl.text.Bind(wx.EVT_TEXT, self._OnUpdate) + self._SetControlValue(self.selection) + return label, ctrl + + def _Update(self): + n = self.ctrl.GetSelection() + if self.ctrl.IsEditableSelection(n): + self.value = self.ctrl.GetValue() + else: + self.value = self.data[n] + + def _SetControlValue(self, n): + self.ctrl.SetSelectionAndValue(n, self.editvalue) + self.value = self.data[n] + + def SetValue(self, value): + # in python < 2.6 tuples doesnt have the index method + # be sure that we are using a list + tmp = list(self.data) + try: + n = tmp.index(value) + except ValueError: + n = self.editselection + self.editvalue = value + self._SetControlValue(n) + +class Radio(Option): + klass = wx.RadioBox + def __init__(self, name, label, data, selection): + Option.__init__(self, name, label, data, selection) + self.choices = data[0::2] + self.data = data[1::2] + self.selection = selection + + def draw(self, parent): + self.ctrl = ctrl = self.klass(parent, label=self.label, + choices=self.choices, + majorDimension=1, + style=wx.RA_SPECIFY_COLS) + ctrl.Bind(wx.EVT_RADIOBOX, self._OnUpdate) + self._SetControlValue(self.selection) + return ctrl + + def _Update(self): + n = self.ctrl.GetSelection() + self.value = self.data[n] + + def _SetControlValue(self, n): + self.ctrl.SetSelection(n) + self.value = self.data[n] + + def SetValue(self, value): + # in python < 2.6 tuples doesnt have the index method + # be sure that we are using a list + tmp = list(self.data) + try: + n = tmp.index(value) + except ValueError: + n = self.selection + self._SetControlValue(n) + +class Spinner(Option): + klass = wx.SpinCtrl + def __init__(self, name, label, data, selection): + Option.__init__(self, name, label, data, selection) + self.min = data[0] + self.max = data[1] + + def draw(self, parent): + label = wx.StaticText(parent, label=self.label) + self.ctrl = ctrl = self.klass(parent, min=self.min, max=self.max, + initial=self.selection) + ctrl.Bind(wx.EVT_SPINCTRL, self._OnUpdate) + self._SetControlValue(self.selection) + return label, ctrl + +class Slider(Option): + klass = wx.Slider + def __init__(self, name, label, data, selection): + Option.__init__(self, name, label, data, selection) + self.min = data[0] + self.max = data[1] + + def draw(self, parent): + label = wx.StaticText(parent, label=self.label) + self.ctrl = ctrl = self.klass(parent, minValue=self.min, + maxValue=self.max, + value=self.selection, + style=wx.SL_LABELS) + ctrl.Bind(wx.EVT_SCROLL, self._OnUpdate) + self._SetControlValue(self.selection) + return label, ctrl diff -Nru swftools-0.9.2+ds1/wx/gui/gmain.py swftools-0.9.1/wx/gui/gmain.py --- swftools-0.9.2+ds1/wx/gui/gmain.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gui/gmain.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,411 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +from __future__ import division +import os +import wx +from wx.lib.pubsub import Publisher +from lib.embeddedimage import PyEmbeddedImage +import thread +import time +import lib.images as images + +ICON_SIZE = 64 + +ID_INVERT_SELECTION = wx.NewId() +ID_SELECT_ODD = wx.NewId() +ID_SELECT_EVEN = wx.NewId() +ID_ONE_PAGE_PER_FILE = wx.NewId() + +ID_DOC_INFO = wx.NewId() +ID_PREVIEW_TYPE = wx.NewId() + +lock = thread.allocate_lock() + +class _AppendThumbnailThread: + def __init__(self, win, thumbs): + self.__win = win + self.__thumbs = thumbs + + def Start(self): + self.__keep_running = self.running = True + thread.start_new_thread(self.Run, ()) + + def IsRunning(self): + return self.running + + def Stop(self): + self.__keep_running = False + + def Run(self): + thumbs = self.__thumbs + different_sizes = False + for pos, thumb in enumerate(thumbs): + if pos == 0: + width, height = thumb.width, thumb.height + else: + if not different_sizes: + if abs(width - thumb.width) > 2 or \ + abs(height - thumb.height) > 2: + different_sizes = True + wx.CallAfter(Publisher.sendMessage, "DIFF_SIZES") + + lock.acquire() + img_str = thumb.asImage(ICON_SIZE, ICON_SIZE, allow_threads=True) + lock.release() + wx.CallAfter(self.__win.AppendThumbnail, pos, img_str, thumb) + wx.CallAfter(Publisher.sendMessage, "THUMBNAIL_ADDED", + {'pagenr':pos+1,}) + #time.sleep(.01) + if not self.__keep_running: + break + + wx.CallAfter(Publisher.sendMessage, "THUMBNAIL_DONE") + #time.sleep(.10) + + self.running = False + +class FileDropTarget(wx.FileDropTarget): + def __init__(self, window): + wx.FileDropTarget.__init__(self) + self.window = window + + def OnDropFiles(self, x, y, filenames): + if len(filenames) == 1: + Publisher.sendMessage("FILE_DROPED", + {'filename': filenames[0]} + ) + else: + Publisher.sendMessage("FILES_DROPED", + {'filenames': filenames} + ) + +from Queue import Queue, Full as QueueFull + +class _DisplayPageThread: + def __init__(self, win, q): + self.win = win + self.q = q + thread.start_new_thread(self.Run, ()) + + def Run(self): + for page in iter(self.q.get, None): + w = page['width'] + h = page['height'] + #time.sleep(.02) + lock.acquire() + page = page["page"].asImage(w, h, allow_threads=True) + lock.release() + wx.CallAfter(self.win._DisplayPage, w, h, page) + +class PagePreviewWindow(wx.ScrolledWindow): + def __init__(self, parent): + wx.ScrolledWindow.__init__(self, parent) + self.SetBackgroundColour('grey') + self.__bg_brush = wx.Brush(self.GetBackgroundColour()) + self.SetScrollRate(20, 20) + + self.__page = None + + self.put_in_queue_timer = None + self.__buffer = wx.EmptyBitmap(1, 1) + self.q = Queue(1) + + _DisplayPageThread(self, self.q) + + self.Bind(wx.EVT_PAINT, self.__OnPaint) + self.Bind(wx.EVT_SIZE, self.__OnSize) + + def __del__(self): + if self.put_in_queue_timer: + self.put_in_queue.timer.Stop() + self.q.put(None, block=True) + + def DisplayPage(self, page): + if self.put_in_queue_timer: + self.put_in_queue_timer.Stop() + + self.put_in_queue_timer = wx.FutureCall(300, self.__PutInQueue, page) + + def __PutInQueue(self, page): + try: + self.q.put(page, block=False) + except QueueFull: + pass + + def Clear(self): + self.__buffer = wx.EmptyBitmap(1, 1) + self.Refresh() + + def __OnSize(self, event): + if self.__page: + self.__DisplayPage() + event.Skip() + + def __OnPaint(self, event): + dc = wx.BufferedPaintDC(self, self.__buffer, wx.BUFFER_VIRTUAL_AREA) + + def _DisplayPage(self, w, h, page): + self.__page = page + self.__page_size = (w, h) + self.SetVirtualSize((w, h)) + self.__DisplayPage() + + def __DisplayPage(self): + w, h = self.__page_size + page = self.__page + cw, ch = self.GetClientSize() + x = max(0, (cw - w) / 2) + w2 = w + 2 + h2 = h + 2 + self.__buffer = wx.EmptyBitmap(max(cw,w2), h2) + dc = wx.BufferedDC(None, self.__buffer) + dc.SetBackground(self.__bg_brush) + dc.Clear() + dc.DrawRectangle(x, 0, w2, h2) + #dc.DrawBitmap(wx.BitmapFromBuffer(w, h, page), 1, 1, True) + dc.DrawBitmap(wx.BitmapFromImage( + wx.ImageFromData(w, h, page)), x, 0, True) + + self.Refresh() + + +class PageListCtrl(wx.ListView): + def __init__(self, parent): + wx.ListView.__init__(self, parent, style=wx.LC_ICON) + self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu) + + def OnContextMenu(self, event): + if self.GetItemCount(): + menu = wx.Menu() + menu.Append(wx.ID_SELECTALL, u"Select All\tCTRL-A") + menu.AppendSeparator() + menu.Append(wx.ID_SAVE, u"Save SWF (all pages)\tCTRL-W") + menu.Append(wx.ID_SAVEAS, u"Save SWF (selected pages)\tCTRL-S") + self.PopupMenu(menu) + menu.Destroy() + + def DisplayEmptyThumbnails(self, pages): + self.DeleteAllItems() + self.imglist = wx.ImageList(ICON_SIZE, ICON_SIZE, mask=True) + self.AssignImageList(self.imglist, wx.IMAGE_LIST_NORMAL) + bmp = images.getblankBitmap() + for pos in range(pages): + self.imglist.Add(bmp) + self.InsertImageStringItem(pos, u"Page %s" % (pos+1), pos) + + def DisplayThumbnails(self, thumbs): + t = _AppendThumbnailThread(self, thumbs) + t.Start() + return t + + def AppendThumbnail(self, pos, thumb, page): + #bmp = wx.BitmapFromBuffer(ICON_SIZE, ICON_SIZE, thumb) + bmp = wx.BitmapFromImage( + wx.ImageFromData(ICON_SIZE, ICON_SIZE, + thumb)) + self.imglist.Replace(pos, bmp) + self.SetItemText(pos, u"Page %s\n(%sx%s)" % (pos+1, + page.width, page.height)) + if pos == 0: + wx.CallAfter(self.Select, 0) + self.RefreshItem(pos) + + +class StatusBar(wx.StatusBar): + def __init__(self, parent): + wx.StatusBar.__init__(self, parent, -1) + + self.sizeChanged = False + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_IDLE, self.OnIdle) + + self.gauge = wx.Gauge(self) + + bmp = images.getstopBitmap() + self.btn_cancel = wx.BitmapButton(self, bitmap=bmp, + style = wx.NO_BORDER) + self.gauge.Hide() + self.btn_cancel.Hide() + + self.Reposition() + + def SetGaugeValue(self, value): + if value == 0: + self.gauge.Hide() + self.btn_cancel.Hide() + self.gauge.SetValue(value) + + def SetGaugeRange(self, pages): + self.gauge.Show() + self.btn_cancel.Show() + self.gauge.SetRange(pages) + + def OnSize(self, evt): + self.Reposition() + self.sizeChanged = True + + def OnIdle(self, evt): + if self.sizeChanged: + self.Reposition() + + def Reposition(self): + rect = self.GetFieldRect(0) + of = rect.width // 1.5 + self.gauge.SetPosition((rect.x+of , rect.y+2)) + self.gauge.SetSize((rect.width-of-24, rect.height-4)) + self.btn_cancel.SetPosition((rect.width-22, rect.y+1)) + self.btn_cancel.SetSize((22, rect.height-2)) + self.sizeChanged = False + + +class PdfFrame(wx.Frame): + def __init__(self): + wx.Frame.__init__(self, None, size=(750,550), title=u"gpdf2swf") + + icon = self.__MakeIcon() + self.SetIcon(icon) + self.__CreateMenu() + self.__CreateToolbar() + self.statusbar = StatusBar(self) + self.SetStatusBar(self.statusbar) + + dt = FileDropTarget(self) + self.SetDropTarget(dt) + + hsplit = wx.SplitterWindow(self, style=wx.SP_3D|wx.SP_LIVE_UPDATE) + self.page_list = PageListCtrl(hsplit) + self.page_preview = PagePreviewWindow(hsplit) + hsplit.SplitVertically(self.page_list, self.page_preview, + sashPosition=ICON_SIZE*2) + hsplit.SetMinimumPaneSize(ICON_SIZE*2) + + def __MakeIcon(self): + img = images.getgpdf2swfImage() + if "wxMSW" in wx.PlatformInfo: + img = img.Scale(16, 16) + #elif "wxGTK" in wx.PlatformInfo: + # img = img.Scale(22, 22) + # wxMac and wxGTK???? can be any size up to 128x128, + # so leave the source img alone.... + icon = wx.IconFromBitmap(img.ConvertToBitmap()) + return icon + + def __CreateMenu(self): + menubar = wx.MenuBar() + + menu_recent = wx.Menu() + menu_save = wx.Menu() + menu_save.AppendCheckItem(ID_ONE_PAGE_PER_FILE, u"One Page Per File") + menu_save.AppendSeparator() + menu_save.Append(wx.ID_SAVE, u"All Pages\tCTRL-W", + u"Save all pages") + menu_save.Append(wx.ID_SAVEAS, u"Selected Pages\tCTRL-S", + u"Save selected pages") + + menu = wx.Menu() + menu.Append(wx.ID_OPEN, u"Open PDF\tCTRL-O", u"Open a PDF document") + menu.AppendMenu(wx.ID_ANY, u"Save SWF", menu_save) + menu.AppendSeparator() + menu.AppendMenu(wx.ID_ANY, u"Recent", menu_recent) + menu.AppendSeparator() + menu.Append(wx.ID_EXIT, u"Exit\tCTRL-Q") + menubar.Append(menu, u"&File") + + self.filehistory = wx.FileHistory() + self.filehistory.UseMenu(menu_recent) + + menu = wx.Menu() + menu.Append(wx.ID_SELECTALL, u"Select All\tCTRL-A", + u"Select all pages") + menu.Append(ID_INVERT_SELECTION, u"Invert Selection", + u"Invert current selection") + menu.Append(ID_SELECT_ODD, u"Select Odd", + u"Select odd pages") + menu.Append(ID_SELECT_EVEN, u"Select Even", + u"Select even pages") + menu.AppendSeparator() + menu.Append(wx.ID_PREFERENCES, u"Options\tCTRL-R", + u"Show options dialog") + menubar.Append(menu, u"&Edit") + + menu = wx.Menu() + menu.Append(wx.ID_ZOOM_IN, u"Zoom In\tCTRL-+") + menu.Append(wx.ID_ZOOM_OUT, u"Zoom Out\tCTRL--") + menu.Append(wx.ID_ZOOM_100, u"Normal Size\tCTRL-0") + menu.Append(wx.ID_ZOOM_FIT, u"Fit\tCTRL-1") + menu.AppendSeparator() + menu.Append(ID_DOC_INFO, u"Document Info\tCTRL-I") + menubar.Append(menu, u"&View") + + menu = wx.Menu() + menu.Append(wx.ID_ABOUT, u"About") + menubar.Append(menu, u"&Help") + self.SetMenuBar(menubar) + + def __CreateToolbar(self): + tsize = (16,16) + wxart = wx.ArtProvider.GetBitmap + self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL | + wx.NO_BORDER | wx.TB_FLAT) + self.toolbar.AddSimpleTool(wx.ID_OPEN, + wxart(wx.ART_FILE_OPEN, + wx.ART_TOOLBAR, tsize), + u"Open") + self.toolbar.AddSimpleTool(wx.ID_SAVE, + wxart(wx.ART_FILE_SAVE, + wx.ART_TOOLBAR, tsize), + u"Save SWF (all pages)") + self.toolbar.AddSeparator() + + self.toolbar.AddSimpleTool(wx.ID_PREFERENCES, + wxart(wx.ART_LIST_VIEW, + wx.ART_TOOLBAR, tsize), + u"Options") + self.toolbar.AddSeparator() + + self.toolbar.AddSimpleTool(ID_DOC_INFO, + wxart(wx.ART_TIP, + wx.ART_TOOLBAR, tsize), + u"Document Info") + + self.toolbar.AddSeparator() + + self.toolbar.AddControl(wx.StaticText(self.toolbar, + label="Rendering mode:")) + self.toolbar_preview_type = wx.Choice( + self.toolbar, ID_PREVIEW_TYPE, + choices=["convert everything to bitmaps", + "convert fonts to fonts, everything else to bitmaps", + "convert polygons to polygons and fonts to fonts", + "convert text only" + ], + size=(350,-1) + ) + # I'm not sure about the utility of this, so Show False + self.toolbar_preview_type.Show(True) + self.toolbar.AddControl(self.toolbar_preview_type) + + self.toolbar.Realize() + diff -Nru swftools-0.9.2+ds1/wx/gui/info.py swftools-0.9.1/wx/gui/info.py --- swftools-0.9.2+ds1/wx/gui/info.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gui/info.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,46 @@ +import wx +from lib.document import PDF_INFO +import lib.utils as utils +#from wx.lib.mixins import listctrl as listmix + +#class InfoList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin): +class InfoList(wx.ListCtrl): + def __init__(self, parent): + wx.ListCtrl.__init__(self, parent, + style=wx.LC_REPORT + | wx.LC_VIRTUAL + | wx.BORDER_SUNKEN + #| wx.BORDER_NONE + #| wx.LC_EDIT_LABELS + #| wx.LC_SORT_ASCENDING + #| wx.LC_NO_HEADER + | wx.LC_VRULES + | wx.LC_HRULES + | wx.LC_SINGLE_SEL + ) + #listmix.ListCtrlAutoWidthMixin.__init__(self) + #self.setResizeColumn("LAST") + + self.InsertColumn(0, "Property") + self.InsertColumn(1, "Value", wx.LIST_FORMAT_LEFT) + self.SetColumnWidth(0, 120) + self.SetColumnWidth(1, 400) + + self.__data = [] + + def append(self, data): + self.__data.append(data) + self.SetItemCount(len(self.__data)) + self.RefreshItem(len(self.__data)-1) + + def OnGetItemText(self, item, col): + data_row = self.__data[item] + return data_row[col] + + def display(self, doc): + self.__data = [] + for item in PDF_INFO: + val = getattr(doc, item) + sane_val = utils.force_unicode(val) + self.append([item, sane_val]) + diff -Nru swftools-0.9.2+ds1/wx/gui/__init__.py swftools-0.9.1/wx/gui/__init__.py --- swftools-0.9.2+ds1/wx/gui/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gui/__init__.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + diff -Nru swftools-0.9.2+ds1/wx/gui/options/__init__.py swftools-0.9.1/wx/gui/options/__init__.py --- swftools-0.9.2+ds1/wx/gui/options/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gui/options/__init__.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +from quality import * +from viewer import * diff -Nru swftools-0.9.2+ds1/wx/gui/options/quality.py swftools-0.9.1/wx/gui/options/quality.py --- swftools-0.9.2+ds1/wx/gui/options/quality.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gui/options/quality.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +import wx +from gui import fields + +class Quality(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent) + self.__options = [] + + sizer = wx.BoxSizer(wx.VERTICAL) + obj = fields.Radio( + ("bitmap", "poly2bitmap", "bitmapfonts", "textonly"), + u"Rendering mode", + [u"Convert polygons to polygons and fonts to fonts", + (0, 0, 0, 0), + u"Convert fonts to fonts, everything else to bitmaps", + (0, 1, 0, 0), + u"Convert everthing to bitmaps", (1, 0, 1, 0), + u"Convert text only", (0, 0, 0, 1), + ], 0) + + ra = obj.draw(self) + self.__options.append(obj) + sizer.Add(ra, 0, wx.EXPAND|wx.ALL, 5) + + quality = [ + ('Spinner', 'zoom', u'Resolution (in dpi):', (0, 100), 72), + ('Slider', 'fontquality', u'Font quality:', (0, 100), 20), + ('Choose', 'storeallcharacters', u'Insert full fonts in SWF file:', + (u'no', 0, u'yes', 1), 0), + ('Choose', 'local-with-filesystem', u'Make SWF local-with-filesystem (instead of local-with-network)', + (u'no', 0, u'yes', 1), 0), + ('Slider', 'splinequality', u'Polygon quality:', (0, 100), 100), + ('Slider', 'jpegquality', u'JPEG quality:', (0, 100), 75), + ('Choose', 'jpegsubpixels', u'JPEG image resolution:', + (u'same as in PDF', 0, u'1x', 1, u'2x', 2, u'4x', 4), 0), + ('Choose', 'ppmsubpixels', u'non-JPEG image resolution:', + (u'same as in PDF', 0, u'1x', 1, u'2x', 2, u'4x', 4), 0), + ] + + box = wx.StaticBox(self, label=u"Quality") + bsizer = wx.StaticBoxSizer(box, wx.VERTICAL) + + flex = wx.FlexGridSizer(cols=2, hgap=0, vgap=0) + flex.AddGrowableCol(0) + flex.AddGrowableCol(1) + for ctrl, opt, label, range, value in quality: + wxobj = getattr(fields, ctrl) + optobj = wxobj(opt, label, range, value) + lb, sp = optobj.draw(self) + flex.Add(lb, 0, wx.TOP|wx.ALIGN_CENTER_VERTICAL, 5) + flex.Add(sp, 0, wx.TOP|wx.EXPAND, 5) + self.__options.append(optobj) + + bsizer.Add(flex, 0, wx.EXPAND) + sizer.Add(bsizer, 0, wx.EXPAND|wx.ALL, 5) + + self.SetSizer(sizer) + + def __get_options(self): + return self.__options + options = property(__get_options) + + def pickle(self): + data = {} + for opt in self.__options: + data[opt.name] = opt.value + return data + + def unpickle(self, data): + fields = {} + for opt in self.__options: + fields[opt.name] = opt + + for k, v in data.items(): + fields[k].SetValue(v) diff -Nru swftools-0.9.2+ds1/wx/gui/options/viewer.py swftools-0.9.1/wx/gui/options/viewer.py --- swftools-0.9.2+ds1/wx/gui/options/viewer.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gui/options/viewer.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,226 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +import os +import wx +import operator +import imp +from lib.wordwrap import wordwrap +from gui.boldstatictext import BoldStaticText +import viewers +import gui.fields + +# this two are only to satisfy some plugins requirements +import gui.plugin +import shutil + +import wx.html +#import viewers.raw +#import viewers.simple +#import viewers.rfx +#import viewers.flexpaper +#import viewers.technoargia + +class Viewers: + def __init__(self): + #self.viewers = [ + # 'raw', + # 'simple', + # 'rfx', + # 'flexpaper', + # 'technoargia', + #] + self.viewers = [] + #self.modules = [ + # viewers.raw, + # viewers.simple, + # viewers.rfx, + # viewers.flexpaper, + # viewers.technoargia, + #] + self.modules = [] + + self.list_viewers() + self.import_viewers() + + def list_viewers(self): + for file in os.listdir('viewers'): + if (file.startswith('.') or file.startswith('_') + or file.endswith(".pyc") or not file.endswith('.py')): + continue + self.viewers.append(os.path.splitext(file)[0]) + + def import_viewers(self): + for file in self.viewers: + try: + _temp = imp.load_source("viewers.%s" % file, os.path.join(os.getcwdu(), "viewers/%s.py" % file)) + self.modules.append(_temp) + except Exception, e: + print "Could not load %s (%s)" % (file, e) + + +class HtmlWindow(wx.html.HtmlWindow): + def __init__(self, parent, text=""): + wx.html.HtmlWindow.__init__(self, parent, size=(-1, 100)) + self.SetFonts("arial", "courier", [7,8,9,10,11,12,13]) + self.SetPage(text) + #self.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.OnLinkClicked) + + def OnLinkClicked(self, event): + if 'gtk2' in wx.PlatformInfo: + os.system('xdg-open "%s"' % event.GetHref()) + elif 'msw' in wx.PlatformInfo(): + os.system('start "%s"' % event.GetHref()) + else: # MAC ??? + pass + +class ViewerBook(wx.Listbook): + def __init__(self, parent): + wx.Listbook.__init__(self, parent, wx.ID_ANY, style= + wx.LB_DEFAULT + ) + + self.__mod = [] + self.__viewers = viewers = Viewers() + + # make an image list + il = wx.ImageList(102, 102) + self.AssignImageList(il) + + # Sort viewers by attribute order. + # The attribute order must be an int from 0..n + viewers.modules.sort(key=operator.attrgetter('order')) + + # Make a bunch of panels for the list book + for idx, mod in enumerate(viewers.modules): + bmp = mod.preview.GetBitmap() + il.Add(bmp) + + win = self.makePanel(mod) + self.AddPage(win, mod, imageId=idx) + if hasattr(mod, "default"): + self.SetSelection(idx) + + + def makePanel(self, mod): + p = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + + nameCtrl = BoldStaticText(p, label=mod.name) + sizer.Add(nameCtrl, 0, wx.EXPAND|wx.TOP, 5) + + descCtrl = HtmlWindow(p, mod.desc) + sizer.Add(descCtrl, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) + + #swf_options = [] + + # Avoid showing an empty StaticBox + if (len(mod.swf_options) == 1 + and isinstance(mod.swf_options[0], gui.fields.Hidden) + ): + hidden = True + else: + hidden = False + + if mod.swf_options and not hidden: + box = wx.StaticBox(p, label=u"SWF") + bsizer = wx.StaticBoxSizer(box, wx.VERTICAL) + + flex = wx.FlexGridSizer(rows=len(mod.swf_options), cols=2, hgap=0, vgap=0) + flex.AddGrowableCol(1) + + for option in mod.swf_options: + #swf_options.append(option) + label, ctrl = option.draw(p) + if label and ctrl: + flex.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 4) + flex.Add(ctrl, 0, wx.EXPAND|wx.ALL, 4) + + bsizer.Add(flex, 0, wx.EXPAND) + sizer.Add(bsizer, 0, wx.EXPAND) + + #vie_options = [] + if mod.viewer_options: + box = wx.StaticBox(p, label=u"Viewer") + bsizer = wx.StaticBoxSizer(box, wx.VERTICAL) + + flex = wx.FlexGridSizer(rows=len(mod.viewer_options), + cols=2, hgap=0, vgap=0) + flex.AddGrowableCol(1) + + for option in mod.viewer_options: + #vie_options.append(option) + label, ctrl = option.draw(p) + if label and ctrl: + flex.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 4) + flex.Add(ctrl, 0, wx.EXPAND|wx.ALL, 4) + + bsizer.Add(flex, 0, wx.EXPAND) + sizer.Add(bsizer, 0, wx.EXPAND) + + p.SetSizer(sizer) + return p + + def AddPage(self, win, mod, select=False, imageId=-1): + wx.Listbook.AddPage(self, win, mod.name, select, imageId) + self.__mod.append(mod) + + def __get_options(self): + page = self.GetSelection() + return self.__mod[page] + + options = property(__get_options) + + def pickle(self): + data = {} + data['selected_viewer'] = self.GetSelection() + + for viewer, module in zip(self.__viewers.viewers, self.__viewers.modules): + data[viewer] = {} + for opt in module.swf_options: + data[viewer][opt.name] = opt.value + for opt in module.viewer_options: + data[viewer][opt.name] = opt.value + + return data + + def unpickle(self, data): + if not data: + return + + selected_viewer = data.pop('selected_viewer') + self.SetSelection(selected_viewer) + + _fields = {} + for viewer, module in zip(self.__viewers.viewers, self.__viewers.modules): + _fields[viewer] = {} + + all_opts = module.swf_options + module.viewer_options + for field in all_opts: + _fields[viewer][field.name] = field + + for modname, opts in data.items(): + for k, v in opts.items(): + _fields[modname][k].SetValue(v) + diff -Nru swftools-0.9.2+ds1/wx/gui/plugin.py swftools-0.9.1/wx/gui/plugin.py --- swftools-0.9.2+ds1/wx/gui/plugin.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/gui/plugin.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +import os +import time +import wx +from wx.lib.pubsub import Publisher +from subprocess import Popen, PIPE + +class Plugin: + one_page_per_file = False + + def before_render(self): + pass + + def before_save(self, page): + pass + + def after_save(self, page): + pass + + def _swap_extension(self, filename, newext, flashversion=""): + name, ext = os.path.splitext(filename) + return u"%s%s.%s" % (name, flashversion, newext) + + def __find_swfcombine(self): + found = False + if "wxMSW" in wx.PlatformInfo: + prog = "swfcombine.exe" + else: + prog = "swfcombine" + #basedir = os.path.dirname(__file__) + basedir = GPDF2SWF_BASEDIR + #print 'basedir', basedir + + opj = os.path.join + locations = [ + os.path.normpath(opj(basedir, prog)), + os.path.normpath(opj(basedir, "..", "src", prog)), + ] + if "wxMSW" in wx.PlatformInfo: + try: + system_drive = os.environ['SYSTEMDRIVE'] + except KeyError: + system_drive = 'c:' + try: + program_files = os.environ['PROGRAMFILES'] + except KeyError: + program_files = '' + locations.extend([ + opj("c:", os.sep, "swftools", prog), + opj("c:", os.sep, "Program Files", "SWFTools", prog), + opj(system_drive, os.sep, program_files, "SWFTools", prog), + ]) + else: + locations.extend([ + opj("/usr", "local", "bin", prog), + opj("/usr", "bin", prog), + opj(basedir, '..', 'src', prog), + ]) + #print locations + + exe = prog + for e in locations: + #print e + if os.path.isfile(e): + exe = e + found = True + break + #print exe, found + return exe, found + + def swfcombine(self, *args): + try: + self.__swfcombine(*args) + except Exception, e: + wx.CallAfter(Publisher.sendMessage, + "SWF_COMBINE_ERROR", unicode(e)) + time.sleep(0.05) + + def __swfcombine(self, *args): + exe, found = self.__find_swfcombine() + # uncoment to test a failed swfcombine find + #found = False + + if not found: + raise Exception(u"Could not execute %s: %s not found" % (exe, exe)) + + # Create a command line + cmd = [exe,] + cmd.extend(args) + + if "wxMSW" in wx.PlatformInfo: + try: + import win32process + # To avoid an ugly "DOS Window" to show up + flags = win32process.CREATE_NO_WINDOW + except ImportError: + # See http://msdn.microsoft.com/en-us/library/ms684863(VS.85).aspx + # for this flag (CREATE_NO_WINDOW) value + flags = 0x08000000 + else: + flags = 0 + output = Popen(cmd, stdin=PIPE, stdout=PIPE, + stderr=PIPE, creationflags=flags).communicate()[0] + + # Check the process output + if output: + raise Exception(u"Error executing %s:%s%s" % + (u" ".join(cmd), os.linesep, output)) + diff -Nru swftools-0.9.2+ds1/wx/lib/app.py swftools-0.9.1/wx/lib/app.py --- swftools-0.9.2+ds1/wx/lib/app.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/lib/app.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,533 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +from __future__ import division +import os, sys +import wx +import time +import pickle + +from lib.wordwrap import wordwrap +from wx.lib.pubsub import Publisher + +from document import Document +from gui.dialogs import (ProgressDialog, OptionsDialog, AboutDialog, InfoDialog) +from gui.gmain import (PdfFrame, + ID_INVERT_SELECTION, ID_SELECT_ODD, + ID_ONE_PAGE_PER_FILE, + ID_SELECT_EVEN, ID_DOC_INFO, + ) +from lib import error +from lib import utils + + +def GetDataDir(): + """ + Return the standard location on this platform for application data + """ + sp = wx.StandardPaths.Get() + return sp.GetUserDataDir() + +def GetConfig(): + if not os.path.exists(GetDataDir()): + os.makedirs(GetDataDir()) + + config = wx.FileConfig( + localFilename=os.path.join(GetDataDir(), "options")) + return config + + +class Pdf2Swf: + def __init__(self): + self.__doc = Document() + + self.__threads = {} + + self.__busy = None + self.__progress = None + + self.__can_save = False + self.__can_viewinfo = False + + self.view = PdfFrame() + wx.GetApp().SetTopWindow(self.view) + sys.excepthook = error.ErrorFrame(self.view) + + # Call Show after the current and pending event + # handlers have been completed. Otherwise on MSW + # we see the frame been draw and after that we saw + # the menubar appear + wx.CallAfter(self.Show) + + self.options = OptionsDialog(self.view) + self.__ReadConfigurationFile() + + self.view.toolbar_preview_type.SetSelection(0) + + Publisher.subscribe(self.OnPageChanged, "PAGE_CHANGED") + Publisher.subscribe(self.OnFileLoaded, "FILE_LOADED") + Publisher.subscribe(self.OnFileNotLoaded, "FILE_NOT_LOADED") + Publisher.subscribe(self.OnDiffSizes, "DIFF_SIZES") + Publisher.subscribe(self.OnThumbnailAdded, "THUMBNAIL_ADDED") + Publisher.subscribe(self.OnThumbnailDone, "THUMBNAIL_DONE") + Publisher.subscribe(self.OnProgressBegin, "SWF_BEGIN_SAVE") + Publisher.subscribe(self.OnProgressUpdate, "SWF_PAGE_SAVED") + Publisher.subscribe(self.OnProgressDone, "SWF_FILE_SAVED") + Publisher.subscribe(self.OnCombineError, "SWF_COMBINE_ERROR") + Publisher.subscribe(self.OnFileDroped, "FILE_DROPED") + Publisher.subscribe(self.OnFilesDroped, "FILES_DROPED") + Publisher.subscribe(self.OnPluginOnePagePerFileNotSupported, + "PLUGIN_ONE_PAGE_PER_FILE_NOT_SUPPORTED") + Publisher.subscribe(self.OnPluginError, "PLUGIN_ERROR") + + self.view.Bind(wx.EVT_MENU, self.OnMenuOpen, id=wx.ID_OPEN) + self.view.Bind(wx.EVT_MENU, self.OnMenuSave, id=wx.ID_SAVE) + self.view.Bind(wx.EVT_MENU, self.OnMenuSaveSelected, id=wx.ID_SAVEAS) + self.view.Bind(wx.EVT_MENU, self.OnMenuExit, id=wx.ID_EXIT) + self.view.Bind(wx.EVT_MENU_RANGE, self.OnFileHistory, + id=wx.ID_FILE1, id2=wx.ID_FILE9) + + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_SAVE) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_SAVEAS) + + self.view.Bind(wx.EVT_MENU, self.OnMenuSelectAll, id=wx.ID_SELECTALL) + self.view.Bind(wx.EVT_MENU, + self.OnMenuInvertSelection, id=ID_INVERT_SELECTION) + self.view.Bind(wx.EVT_MENU, self.OnMenuSelectOdd, id=ID_SELECT_ODD) + self.view.Bind(wx.EVT_MENU, self.OnMenuSelectEven, id=ID_SELECT_EVEN) + self.view.Bind(wx.EVT_MENU, self.OnMenuOptions, id=wx.ID_PREFERENCES) + + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_SELECTALL) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=ID_INVERT_SELECTION) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=ID_SELECT_ODD) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=ID_SELECT_EVEN) + + self.view.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT) + + self.view.Bind(wx.EVT_MENU, self.OnZoom, id=wx.ID_ZOOM_IN) + self.view.Bind(wx.EVT_MENU, self.OnZoom, id=wx.ID_ZOOM_OUT) + self.view.Bind(wx.EVT_MENU, self.OnZoom, id=wx.ID_ZOOM_100) + self.view.Bind(wx.EVT_MENU, self.OnFit, id=wx.ID_ZOOM_FIT) + self.view.Bind(wx.EVT_MENU, self.OnShowDocInfo, id=ID_DOC_INFO) + + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_IN) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_OUT) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_100) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_FIT) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUIInfo, id=ID_DOC_INFO) + + self.view.page_list.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelectItem) + self.view.Bind(wx.EVT_CLOSE, self.OnMenuExit) + + self.view.toolbar_preview_type.Bind(wx.EVT_CHOICE, + self.OnPreviewType) + + # statusbar cancel thumbanails generation button + self.view.statusbar.btn_cancel.Bind(wx.EVT_BUTTON, + self.OnThumbnailCancel) + + # Don't know where the problem is (python/xpython or wxwidgets/wxpython) + # but I found that this hack was necessary to avoid the app enter in a + # idle state. We must, for example, move the mouse inside the app + # for threads continue their job. + # There is no need for this when freezing with other utils, like + # py2exe, pyinstaller, cxfreeze + if "wxMSW" in wx.PlatformInfo: + self.timer = wx.Timer(self.view) + self.view.Bind(wx.EVT_TIMER, lambda evt: None) + self.timer.Start(50) + + def OnFilesDroped(self, evt): + dlg = wx.MessageDialog(self.view, + u"You must drop only one file.", + u"Notice", + style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + + def OnFileDroped(self, message): + self.__Load(message.data["filename"]) + + def OnPluginOnePagePerFileNotSupported(self, message): + self.Message(u"Selected viewer does not support " + u"one page per file. ") + + def OnPluginError(self, message): + self.Message(u"Error applying selected viewer") + + def OnFileHistory(self, evt): + # get the file based on the menu ID + fileNum = evt.GetId() - wx.ID_FILE1 + filename = self.view.filehistory.GetHistoryFile(fileNum) + + self.__Load(filename) + + def OnProgressBegin(self, message): + pages = message.data["pages"] + style = ( + wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME| + wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT| + wx.PD_AUTO_HIDE + ) + if self.__progress: + self.__progress.Destroy() + self.__progress = ProgressDialog(u"Saving...", + u"Start saving SWF pages", + maximum=pages, + parent=self.view, style=style) + self.__progress.Show() + self.view.SetStatusText(u"Saving document...") + + def OnProgressUpdate(self, message): + pagenr = message.data["pagenr"] + pages = message.data["pages"] + + keep_running = self.__progress.Update( + pagenr, + u"Saving SWF page %d of %d" % (pagenr, pages) + ) + + if not keep_running and self.__threads.has_key("progress"): + self.view.SetStatusText(u"Cancelling...") + self.__threads.pop("progress").Stop() + self.__progress.Hide() + + + def OnProgressDone(self, message): + if self.__threads.has_key("progress"): # it goes all the way? + self.__threads.pop("progress") + self.view.SetStatusText(u"SWF document saved successfully.") + else: + self.view.SetStatusText(u"") + + def OnCombineError(self, message): + from wx.lib.dialogs import ScrolledMessageDialog + ScrolledMessageDialog(self.view, message.data, u"Notice").ShowModal() + + + def OnThumbnailAdded(self, message): + self.view.statusbar.SetGaugeValue(message.data['pagenr']) + tot = self.view.page_list.GetItemCount() + self.view.SetStatusText(u"Generating thumbnails %s/%d" % + (message.data['pagenr'], tot), 0) + + def OnThumbnailDone(self, message): + self.view.statusbar.SetGaugeValue(0) + self.view.SetStatusText(u"", 0) + if self.__threads.has_key("thumbnails"): + self.__threads.pop("thumbnails") + self.view.SendSizeEvent() + + def OnThumbnailCancel(self, event): + if self.__threads.has_key("thumbnails"): + self.__threads["thumbnails"].Stop() + + def OnSelectItem(self, event): + self.__doc.ChangePage(event.GetIndex() + 1) + + def OnPreviewType(self, event): + filename = self.__doc.filename + if filename: + self.__Load(filename) + + def OnPageChanged(self, message): + # ignore if we have more than one item selected + if self.view.page_list.GetSelectedItemCount() > 1: + return + + self.view.page_preview.DisplayPage(message.data) + + def SetTitle(self): + name = wx.GetApp().GetAppName() + filename = os.path.basename(self.__doc.filename) + if self.__doc.title != "n/a": + t = u"%s - %s (%s)" % (name, filename, self.__doc.title) + else: + t = u"%s - %s" % (name, filename) + self.view.SetTitle(t) + + def OnFileLoaded(self, message): + if self.__progress: + self.__progress.Destroy() + self.__progress = None + + self.__can_viewinfo = True + del self.__busy + + self.SetTitle() + + if self.__doc.oktocopy == 'no': + self.__can_save = False + self.view.page_list.DisplayEmptyThumbnails(0) + self.view.page_preview.Clear() + self.view.SetStatusText(u"") + self.Message( + u"This PDF disallows copying, cannot be converted." + ) + return + + #if not self.__doc.oktoprint: + self.view.SetStatusText(u"Document loaded successfully.") + + self.view.page_list.DisplayEmptyThumbnails(message.data["pages"]) + thumbs = self.__doc.GetThumbnails() + t = self.view.page_list.DisplayThumbnails(thumbs) + self.__threads["thumbnails"] = t + self.view.statusbar.SetGaugeRange(message.data["pages"]) + #del self.__busy + + def OnFileNotLoaded(self, message): + self.__can_save = False + self.__can_viewinfo = False + del self.__busy + self.view.SetStatusText(u"") + self.Message( + u"Could not open file %s" % message.data['filename'] + ) + + def OnDiffSizes(self, message): + # just let the user know- for now, we can't handle this properly + self.Message( + u"In this PDF, width or height are not the same for " + u"each page. This might cause problems if you export " + u"pages of different dimensions into the same SWF file." + ) + + def OnMenuOpen(self, event): + dlg = wx.FileDialog(self.view, u"Choose PDF File:", + style=wx.OPEN|wx.CHANGE_DIR, + wildcard = u"PDF files (*.pdf)|*.pdf|all files (*.*)|*.*") + + if dlg.ShowModal() == wx.ID_OK: + filename = dlg.GetPath() + self.__Load(filename) + + def OnMenuSave(self, event, pages=None): + defaultFile = self.__doc.lastsavefile + if "wxMSW" in wx.PlatformInfo: + allFiles = "*.*" + else: + allFiles = "*" + self.view.SetStatusText(u"") + dlg = wx.FileDialog(self.view, u"Choose Save Filename:", + style = wx.SAVE | wx.OVERWRITE_PROMPT, + defaultFile=os.path.basename(defaultFile), + wildcard=u"SWF files (*.swf)|*.swf" + "|all files (%s)|%s" % (allFiles, allFiles)) + + + if dlg.ShowModal() == wx.ID_OK: + menubar = self.view.GetMenuBar() + one_file_per_page = menubar.IsChecked(ID_ONE_PAGE_PER_FILE) + + self.__threads["progress"] = self.__doc.SaveSWF(dlg.GetPath(), + one_file_per_page, + pages, self.options) + + def OnUpdateUI(self, event): + menubar = self.view.GetMenuBar() + menubar.Enable(event.GetId(), self.__can_save) + + self.view.GetToolBar().EnableTool(event.GetId(), self.__can_save) + + def OnUpdateUIInfo(self, event): + menubar = self.view.GetMenuBar() + menubar.Enable(event.GetId(), self.__can_viewinfo) + + self.view.GetToolBar().EnableTool(event.GetId(), self.__can_viewinfo) + + def OnMenuSaveSelected(self, event): + pages = [] + page = self.view.page_list.GetFirstSelected() + pages.append(page+1) + + while True: + page = self.view.page_list.GetNextSelected(page) + if page == -1: + break + pages.append(page+1) + + self.OnMenuSave(event, pages) + + def OnMenuExit(self, event): + self.view.SetStatusText(u"Cleaning up...") + + # Stop any running thread + self.__StopThreads() + + config = GetConfig() + self.view.filehistory.Save(config) + config.Flush() + # A little extra cleanup is required for the FileHistory control + del self.view.filehistory + + # Save quality options + dirpath = GetDataDir() + data = self.options.quality_panel.pickle() + try: + f = file(os.path.join(dirpath, 'quality.pkl'), 'wb') + pickle.dump(data, f) + f.close() + except Exception: + pass + + # Save viewer options + try: + f = file(os.path.join(dirpath, 'viewers.pkl'), 'wb') + data = self.options.viewers_panel.pickle() + pickle.dump(data, f) + f.close() + except Exception: + pass + + self.view.Destroy() + + def OnMenuSelectAll(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, True) + + def OnMenuInvertSelection(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, not self.view.page_list.IsSelected(i)) + + def OnMenuSelectOdd(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, not bool(i%2)) + + def OnMenuSelectEven(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, bool(i%2)) + + def OnMenuOptions(self, event): + self.options.ShowModal() + + def OnFit(self, event): + self.__doc.Fit(self.view.page_preview.GetClientSize()) + + def OnZoom(self, event): + zoom = { + wx.ID_ZOOM_IN: .1, + wx.ID_ZOOM_OUT: -.1, + wx.ID_ZOOM_100: 1, + } + self.__doc.Zoom(zoom[event.GetId()]) + + def OnShowDocInfo(self, event): + info = InfoDialog(self.view) + info.info.display(self.__doc) + info.Show() + + def OnAbout(self, evt): + AboutDialog(self.view) + + def __Load(self, filename): + self.__can_save = True + self.__StopThreads() + self.view.SetStatusText(u"Loading document...") + self.__busy = wx.BusyInfo(u"One moment please, " + u"opening pdf document...") + + self.view.filehistory.AddFileToHistory(filename) + try: + # I dont care if this, for some reason, + # give some error. I just swallow it + os.chdir(os.path.dirname(filename)) + except: + pass + + # Need to delay the file load a little bit + # for the BusyInfo get a change to repaint itself + #wx.FutureCall(150, self.__doc.Load, filename) + sel = self.view.toolbar_preview_type.GetSelection() + #print sel + PREV_TYPE = { + 0 : [('bitmap', '1'), ('poly2bitmap', '0'), ('bitmapfonts', '1'), + ('textonly', '0')], + 1 : [('bitmap', '0'), ('poly2bitmap', '1'), ('bitmapfonts', '0'), + ('textonly', '0')], + 2 : [('bitmap', '0'), ('poly2bitmap', '0'), ('bitmapfonts', '0'), + ('textonly', '0')], + 3 : [('bitmap', '0'), ('poly2bitmap', '0'), ('bitmapfonts', '0'), + ('textonly', '1')], + } + self.__doc.preview_parameters = PREV_TYPE[sel] + wx.CallAfter(self.__doc.Load, filename) + + def __StopThreads(self): + for n, t in self.__threads.items(): + t.Stop() + + running = True + while running: + running = False + for n, t in self.__threads.items(): + running = running + t.IsRunning() + time.sleep(0.1) + + def __ReadConfigurationFile(self): + config = GetConfig() + self.view.filehistory.Load(config) + + dirpath = GetDataDir() + try: + f = file(os.path.join(dirpath, 'quality.pkl'), 'rb') + #try: + if 1: + data = pickle.load(f) + self.options.quality_panel.unpickle(data) + #except: + # self.Message( + # u"Error loading quality settings. " + # u"They will be reset to defaults. ") + f.close() + except Exception: + pass + + try: + f = file(os.path.join(dirpath, 'viewers.pkl'), 'rb') + #try: + if 1: + data = pickle.load(f) + self.options.viewers_panel.unpickle(data) + #except: + # self.Message( + # u"Error loading viewers settings. " + # u"They will be reset to defaults. ") + f.close() + except Exception: + pass + #d = pickle.load(f) + + def Show(self): + self.view.Show() + if len(sys.argv) == 2: + self.__Load(utils.force_unicode(sys.argv[1])) + + def Message(self, message): + dlg = wx.MessageDialog(self.view, + message, + style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + diff -Nru swftools-0.9.2+ds1/wx/lib/document.py swftools-0.9.1/wx/lib/document.py --- swftools-0.9.2+ds1/wx/lib/document.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/lib/document.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,257 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + +from __future__ import division +import os, sys +import time +import thread +import gfx +import wx +from wx.lib.pubsub import Publisher +from subprocess import Popen, PIPE +import lib.utils as utils + +class _SaveSWFThread: + def __init__(self, pdffilename, filename, one_page_per_file, doc, pages, options): + #self.__doc = doc + filename = filename.encode(sys.getfilesystemencoding()) + self.__filename = filename + self.__pdffilename = pdffilename + self.__pages = pages or range(1, doc.pages+1) + self.__options = options + self.__one_page_per_file = one_page_per_file + + def Start(self): + self.__keep_running = self.__running = True + thread.start_new_thread(self.Run, ()) + #self.Run() + + def Stop(self): + self.__keep_running = False + + def IsRunning(self): + return self.__running + + def Run(self): + swf = gfx.SWF() + + try: + plugin = self.__options.viewers.init(swf, self.__filename) + except Exception, e: + wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR") + self.__running = False + return + + if self.__one_page_per_file and not plugin.one_page_per_file: + wx.CallAfter(Publisher.sendMessage, + "PLUGIN_ONE_PAGE_PER_FILE_NOT_SUPPORTED", + {'plugin': plugin,}) + self.__running = False + return + + pages = len(self.__pages) + wx.CallAfter(Publisher.sendMessage, "SWF_BEGIN_SAVE", + {'pages': pages,}) + + self.setparameters(gfx) + self.__doc = gfx.open("pdf", self.__pdffilename) + + self.setparameters(swf) + + try: + plugin.before_render() + except Exception, e: + wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR") + self.__running = False + return + + for pagenr in self.__pages: + page = self.__doc.getPage(pagenr) + swf.startpage(page.width, page.height) + page.render(swf) + swf.endpage() + wx.CallAfter(Publisher.sendMessage, "SWF_PAGE_SAVED", + {'pagenr': pagenr, + 'pages': pages,}) + + if self.__one_page_per_file: + form = '.%%0%dd.swf' % len(str(len(self.__pages))) + filename = self.__filename.replace('.swf', form % pagenr) + swf.save(filename) + swf = gfx.SWF() + + try: + plugin = self.__options.viewers.init(swf, self.__filename) + except Exception, e: + wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR") + self.__running = False + return + + self.setparameters(swf) + + if not self.__keep_running: + break + else: + # This will not run if we break the for loop + if not self.__one_page_per_file: + try: + plugin.before_save(page) + except Exception, e: + wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR") + self.__running = False + return + swf.save(self.__filename) + try: + plugin.after_save(page) + except Exception, e: + wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR") + self.__running = False + return + + # No need. But to be sure that it's clean up + # as soon as possible + del swf + + wx.CallAfter(Publisher.sendMessage, "SWF_FILE_SAVED") + + self.__running = False + + def setparameters(self, swf): + #print "driver", swf + for opt in self.__options.quality: + if type(opt.name) in (tuple, list): + for name, value in ( + # Example to better understand the list comprehension: + # opt.name = ['a', 'b', 'c'] + # opt.value = [1, 2, 3] + # zip them = [('a',1), ('b', 2), ('c', 3)] + # pair will be in this example ('a', 1) due to + # the if pair[1] condition + pair for pair in zip(opt.name, opt.value) #if pair[1] == 1 + ): + #print "1.swf.setparameter(%s, %s)" % (name, value) + swf.setparameter(str(name), str(value)) + else: + #print "2.swf.setparameter(%s, %s)" % (opt.name, str(opt.value)) + swf.setparameter(opt.name, str(opt.value)) + + #swf.setparameter('noclips', '1') + #swf.setparameter('reordertags', '1') + #swf.setparameter('animate', '1') + +PDF_INFO = [ + "title", "subject", "keywords", "author", + "creator", "producer", "creationdate", "moddate", + "linearized", "tagged", "encrypted", "oktoprint", + "oktocopy", "oktochange", "oktoaddnotes", "version", +] + +class Document(object): + def __init__(self): + self.__page = None + self.__zoom = 1 + self.__lastsavefile = "output.swf" + self.__pdffilename = None + self.__preview_parameters = [] + + def __getattr__(self, name): + if name in PDF_INFO: + return utils.force_unicode(self.__pdf.getInfo(name)) or "n/a" + raise AttributeError, name + + def filename(self): + return unicode(self.__pdffilename or "", sys.getfilesystemencoding()) + filename = property(filename) + + def __get_lastsavefile(self): + return self.__lastsavefile + def __set_lastsavefile(self, lastsavefile): + self.__lastsavefile = lastsavefile + lastsavefile = property(__get_lastsavefile, __set_lastsavefile) + + def __SwapExtension(self, filename, newext): + basename, ext = os.path.splitext(filename) + return "%s.%s" % (basename, newext) + + def __Reload(self): + Publisher.sendMessage("PAGE_CHANGED", + {'page': self.__page, + 'width': int(self.__page.width * self.__zoom), + 'height': int(self.__page.height * self.__zoom)}) + + def __get_preview_parameters(self): + return self.__preview_parameters + def __set_preview_parameters(self, parameters): + self.__preview_parameters = parameters + preview_parameters = property(__get_preview_parameters, + __set_preview_parameters) + + def Load(self, filename): + self.__lastsavefile = self.__SwapExtension(filename, "swf") + try: + filename = filename.encode(sys.getfilesystemencoding()) + except LookupError: + pass + self.__pdffilename = filename + + #print 'Load',self.__preview_parameters + for parameter, value in self.__preview_parameters: + gfx.setparameter(parameter, value) + + try: + self.__pdf = gfx.open("pdf", filename) + except: + Publisher.sendMessage("FILE_NOT_LOADED", {'filename': filename}) + else: + Publisher.sendMessage("FILE_LOADED", {'pages': self.__pdf.pages}) + + def ChangePage(self, pagenr=1, size=None): + self.__page = page = self.__pdf.getPage(pagenr) + self.__Reload() + + def Fit(self, size): + w = size[0] / self.__page.width + h = size[1] / self.__page.height + self.__zoom = min(w, h) + self.__Reload() + + def Zoom(self, zoom): + if zoom == 1: + self.__zoom = 1 + else: + self.__zoom += zoom + self.__Reload() + + def GetThumbnails(self): + for pagenr in range(1, self.__pdf.pages + 1): + page = self.__pdf.getPage(pagenr) + yield page + + def SaveSWF(self, filename, one_page_per_file, pages, options): + self.__lastsavefile = filename + t = _SaveSWFThread(self.__pdffilename, filename, one_page_per_file, self.__pdf, pages, options) + t.Start() + return t + + diff -Nru swftools-0.9.2+ds1/wx/lib/embeddedimage.py swftools-0.9.1/wx/lib/embeddedimage.py --- swftools-0.9.2+ds1/wx/lib/embeddedimage.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/lib/embeddedimage.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,74 @@ +#---------------------------------------------------------------------- +# Name: wx.lib.embeddedimage +# Purpose: Defines a class used for embedding PNG images in Python +# code. The primary method of using this module is via +# the code generator in wx.tools.img2py. +# +# Author: Anthony Tuininga +# +# Created: 26-Nov-2007 +# RCS-ID: $Id: embeddedimage.py 59672 2009-03-20 20:59:42Z RD $ +# Copyright: (c) 2007 by Anthony Tuininga +# Licence: wxWindows license +#---------------------------------------------------------------------- + +import base64 +import cStringIO +import wx + +try: + b64decode = base64.b64decode +except AttributeError: + b64decode = base64.decodestring + + +class PyEmbeddedImage(object): + """ + PyEmbeddedImage is primarily intended to be used by code generated + by img2py as a means of embedding image data in a python module so + the image can be used at runtime without needing to access the + image from an image file. This makes distributing icons and such + that an application uses simpler since tools like py2exe will + automatically bundle modules that are imported, and the + application doesn't have to worry about how to locate the image + files on the user's filesystem. + + The class can also be used for image data that may be acquired + from some other source at runtime, such as over the network or + from a database. In this case pass False for isBase64 (unless the + data actually is base64 encoded.) Any image type that + wx.ImageFromStream can handle should be okay. + """ + + def __init__(self, data, isBase64=True): + self.data = data + self.isBase64 = isBase64 + + def GetBitmap(self): + return wx.BitmapFromImage(self.GetImage()) + + def GetData(self): + if self.isBase64: + data = b64decode(self.data) + return data + + def GetIcon(self): + icon = wx.EmptyIcon() + icon.CopyFromBitmap(self.GetBitmap()) + return icon + + def GetImage(self): + stream = cStringIO.StringIO(self.GetData()) + return wx.ImageFromStream(stream) + + # added for backwards compatibility + getBitmap = GetBitmap + getData = GetData + getIcon = GetIcon + getImage = GetImage + + # define properties, for convenience + Bitmap = property(GetBitmap) + Icon = property(GetIcon) + Image = property(GetImage) + diff -Nru swftools-0.9.2+ds1/wx/lib/error.py swftools-0.9.1/wx/lib/error.py --- swftools-0.9.2+ds1/wx/lib/error.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/lib/error.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,138 @@ +import os, sys +import wx +import wx.lib.mixins.listctrl as listmix +import traceback + + +class BoldedStaticText(wx.StaticText): + def __init__(self, *args, **kwargs): + wx.StaticText.__init__(self, *args, **kwargs) + font = self.GetFont() + font.SetWeight(wx.BOLD) + self.SetFont(font) + + +class ListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin): + def __init__(self, parent, size=wx.DefaultSize, style=0): + wx.ListCtrl.__init__(self, parent, size=size, style=style) + listmix.ListCtrlAutoWidthMixin.__init__(self) + + +class ErrorPanel(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent) + + self.box = wx.BoxSizer(wx.VERTICAL) + + # Main Label + self.box.Add(BoldedStaticText(self, label="An error has occurred") + , 0, wx.ALIGN_CENTER | wx.ALL, 10) + + # Exception Information + boxInfoGrid = wx.FlexGridSizer(2, 2, 0, 0) + textFlags = wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP + + boxInfoGrid.Add(BoldedStaticText(self, label="Type: "), 0, textFlags, 5 ) + self.error_type = wx.StaticText(self, label="") + boxInfoGrid.Add(self.error_type, 0, textFlags, 5 ) + + textFlags = wx.ALIGN_LEFT | wx.ALL + boxInfoGrid.Add(BoldedStaticText(self, label="Value: ") , 0, textFlags, 5 ) + self.error_details = wx.StaticText(self, label="") + boxInfoGrid.Add(self.error_details , 0, textFlags, 5 ) + + bbox = wx.BoxSizer(wx.HORIZONTAL) + self.copy = wx.Button(self, label="Copy to Clipboard") + self.close = wx.Button(self, label="&Close") + bbox.Add(self.copy) + bbox.Add(self.close) + + # Set up the traceback list + # This one automatically resizes last column to take up remaining space + self.__list = ListCtrl(self, style=wx.LC_REPORT | wx.SUNKEN_BORDER) + self.__list.InsertColumn(0, "Filename") + self.__list.InsertColumn(1, "Line", wx.LIST_FORMAT_RIGHT) + self.__list.InsertColumn(2, "Function") + self.__list.InsertColumn(3, "Code") + + self.box.Add(boxInfoGrid) + self.box.Add((-1,10)) + self.box.Add(BoldedStaticText(self, label="Traceback:") + , 0, wx.ALIGN_LEFT | wx.LEFT | wx.TOP, 5) + self.box.Add(self.__list, 1, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, 5) + self.box.Add(bbox, 0, wx.ALIGN_RIGHT | wx.ALL, 5) + + self.box.Fit(self) + self.SetSizer(self.box) + + self.tb_info = [] + + self.copy.Bind(wx.EVT_BUTTON, self.OnCopy) + + + def repr_(self, val): + return repr(val)[1:-1] + + def show(self, type_, value, tb): + sys.__excepthook__(type_, value, tb) + + self.error_type.SetLabel(self.repr_(type_)) + self.error_details.SetLabel(repr(value)) + + self.tb_info = traceback.format_exception(type_, value, tb) + x = 0 + self.__list.DeleteAllItems() + for filename, line, func, text in traceback.extract_tb(tb): + self.__list.InsertStringItem(x, + self.repr_(os.path.basename(filename))) # Filename + self.__list.SetStringItem(x, 1, unicode(line)) # Line + self.__list.SetStringItem(x, 2, unicode(func)) # Function + self.__list.SetStringItem(x, 3, self.repr_(text)) # Code + + x += 1 + self.Show() + + def OnCopy(self, event): + data = wx.TextDataObject() + data.SetText(''.join(self.tb_info)) + if wx.TheClipboard.Open(): + wx.TheClipboard.SetData(data) + wx.TheClipboard.Close() + event.GetEventObject().Enable(False) + else: + wx.MessageBox("Unable to open the clipboard", "Error") + + +class ErrorFrame: + def __init__(self, parent=None): + self.frame = None + self.parent = parent + + def __call__(self, type_, value, tb): + if not self.frame: + self.frame = wx.Frame(self.parent, size=(600,400)) + self.error_panel = ErrorPanel(self.frame) + + self.error_panel.close.Bind(wx.EVT_BUTTON, self.OnClose) + self.frame.Bind(wx.EVT_CLOSE, self.OnClose) + + self.error_panel.show(type_, value, tb) + + self.frame.CenterOnParent() + self.frame.Show() + + def OnClose(self, event): + self.frame.Hide() + #event.Skip() + + +if __name__ == '__main__': + def raise_(): + raise Exception("Teste") + + app = wx.App() + f = wx.Frame(None) + sys.excepthook = ErrorFrame(f) + f.Show() + wx.FutureCall(500, raise_) + app.MainLoop() diff -Nru swftools-0.9.2+ds1/wx/lib/images.py swftools-0.9.1/wx/lib/images.py --- swftools-0.9.2+ds1/wx/lib/images.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/lib/images.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,107 @@ +#---------------------------------------------------------------------- +# This file was generated by /usr/bin/img2py +# +from embeddedimage import PyEmbeddedImage + +blank = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAAZiS0dE" + "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kHDAscKjCK/4UAAABo" + "SURBVHja7dABAcBAEAIgXf/Ofo8dRKDblqPa5stxAgQIECBAgAABAgQIECBAgAABAgQIECBA" + "gAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEPALTbLLAQ8OIAV9" + "8WNeKwAAAABJRU5ErkJggg==") +getblankData = blank.GetData +getblankImage = blank.GetImage +getblankBitmap = blank.GetBitmap +getblankIcon = blank.GetIcon + +#---------------------------------------------------------------------- +stop = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAAAZiS0dE" + "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kHGAEINtjJMYEAAADV" + "SURBVBjTPc8xTgJBAEbh988sLFkDXEAvgB338AhauI3EUqOVVhR6gq0s9Do2WpDVipaOLCZL" + "LGZ+G+IJ3ve0KssBUo3UWAJANtgL7JcCqXZVNcxmKXVdBBMn06S2bdT3xOvh8D3P50nPTyF2" + "O3xyjG9vpI/PrM3mrHAI/PZ9PHp79Xi5VAZ+7u7t7TY6BAI2g/2ehDAgBXSwABTKmWIyTr44" + "D93Do0FQX6Kv76T1Omo1Gl25qhqdzlLqdtE5E6fTpLaN6vuFVmU5kFQTQmMdMjn/b/4BTeBh" + "NrAp1ecAAAAASUVORK5CYII=") +getstopData = stop.GetData +getstopImage = stop.GetImage +getstopBitmap = stop.GetBitmap +getstopIcon = stop.GetIcon + +#---------------------------------------------------------------------- +gpdf2swf = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABHNCSVQICAgIfAhkiAAADlJJ" + "REFUeJzlW0twFNcVPT3/GY00rR/CcaoE8YLgOCUMC2xwlSAki0BWgiwisxrDhs9GMRs7XijY" + "rqJMvDGwgdImQlkYlA3CGxuHKllxqjCfKiKHBb9UmUhYSBrBaP7TWZx+8173dPf0gHClKreq" + "S+qe7tfv3nfvuZ93W9Pw/02hH+pFBmA0c78G/CBr89wE0JDh/gj/5g0gpgG/MM9vlYHvqmi9" + "FzGW7j+p3f7cBKKt4AEyzaM3KP8fjBkYShjojxiWe7yOvpCBlFY7X7NmjQHAWMn5agC0lRBr" + "bbX7I8BLQeB2BbheAnbHgPeTwOoAMF0GrpeBS0VgJFc/SEoD3ooDqYDzSy4VgctF3pfh61ZE" + "K1Zk1QeiBk60coVTmoHhpIHJDl4biPJaSuPvw0l5781OXk/HpXYMRA2MpgxUe+qPdJz3KJr0" + "zPN/JsZ7g1RvMaGUZmBzWDI8EDVwLElGBRPzq3j/snl+LMlxqj0GHnTLcyGYK51WIQzGpKAU" + "k/lBBVBjVrXz3qDUBPukxbHcQ+btv68LUjPUazc7KYCUZqAnwHEfdPO3d1rkOyc7KPSnFUIz" + "RmQARt+2DbixcBO4UQYGosBAjAi+2sV2BeUB/HoBONkKvGxzPlMlYNcC8G2X8zhjeWA8D4wX" + "5DsXq8Chx/x9OAl0asChx03jgm8BGICR2taFzJ4CXzyUAL4pOzNkJy/mBb39mON92e4+zkyV" + "gjidA+5VeG1NkH/1APBBEnhjvjkh+FWVH297keomVE+o9Oaw1cbth7B5r3vEWCnNwDnd+z5x" + "jKakmxSYk9KIIU2Yg3+bv6DLF55ps058c5i/+7V5L6Z6gxSa01gXdOJCT0CC7FCiPoboCfgX" + "QiNdMQADkx3AwSWqnR4A7nbV37hviVgwGLNeS8eBLeEGb1Fo+wKwKQQcb2Xs8Lci8GmBMUBf" + "CNgRIQaIMadKcm4bwsSGG+XacI3MwdN4DcDAaAr4OMsAZ9GgnTnRmTYyfLsCvNciBeLEfB7A" + "1ZI8X6zS/gG+5+Nl4HyB13dEgP1x4C8pd6DVA8BEG4H0qw7O890nwOUiDGqCqxBcNcAADAwn" + "gdkK8FWJk/ho2Xn1VTq0BEwUOfkNYcb6M1XgfkXek9L4G8DfXwwAfeb5bAU4lQN6g/QKsfpX" + "WGjRANZ+DyysAo5mgbEccM18bvsCYl+HkS9k3TXBzeZT27ok0Nzpom26RWjCfvtC1lh+soPH" + "nS5/GFDtob8XwKoGTF4HIP/vjzBYEnMCjPWv/dwVD1ydd2ZfCdiboUpNmeo6aFuOPOij185R" + "5Y60MB8YNs1kPE8TEK7KD53OAYcTdJcnW+k+p8uNnxP0WTswUeC8BmNAbxDfRm+5Z6eOiC/i" + "d7Hi9tVf7mHkltK40uK3B91cjQfdPNQx/BwiN1BXXXgSLzeqakC1h1qX0vjMcNLAQJQa7eAZ" + "6gSwevWLZHgowcHOtFlj9cGYTGwmO6wvHk4a2BmxMgQ0jgHEMZSQ6uvkTt3GsQtAmFJvkC6Y" + "YO7sGlVkqKnJzghwwYzI1s4BuyJU95Ec3dqBBLDRwYGsnaPa7ozKa2N54K0McLe7cbjs9Lwg" + "r2gyMAtUe+qf2bNoPmsAmyO1lFoFxPoZ9YWAMyna/dEs0ftsnr896Ka7c2J+qkTkt09+MAYc" + "THDyeQ/mLxb414l5gKj+WTtw8LF/TBjV6V5jGl35/njdLTUNsICEcFPXTfD7z6rG7mjfEqBr" + "DGCcSKzGOf3pnhfkpAntD93nOF0GXnnE/0dT6D3egX9fv1vTgHoBqKrU/pDSO5BgcOM1qcQs" + "NcRNzfMAXn8EbA0DJ9qaf95+/95FRoSDMUaPHyTdI85Ty0zg+iOMOcbyNTOovW3NmjXWh6ZK" + "jLDO68CHTxjMuNFYjqbjNXmhwmfz9SUxP8/bxzqn06bH8rRxLzqQYBp9uQiss5pvCODq37t3" + "z/rQF0WGoVvCwJtxRnhu6vvJMmOARrQ6wLjilUfAa2Gpwn/OO9pnQxLh97/K0lzdKB0nT2pE" + "CtMEDMDAUIIxuDCBVx+RqcEYVe6Fh8BEe72aTZeBrfP+cELQWJ4JzLdmWP2j74HlnsbPz1SB" + "OxXJiCi+ZgyGzo0CrnsVPtcfqXkDqQ8bFcbyMCs+5oxioI29manPBT7Msvrrl3mAQr1aIpht" + "DVM91eeny5zsN2XgH0UgC6pvb5BatDPKRCsd5OrvW+JzXsUUgEB8v8KE6zIvSQ2Y7ADemKcG" + "jOSo1tc6rQO8+ohCUQGx/SHwRYeza2xEexZZ5toZIZMilV0XBH4WYoK0KWTdOLHTviUKb6LI" + "RbKH6yoFZvn3nRbgw6yHBkyV5OqrdNJMOffHuRJjeQKlX+ZFfn+pyNUV9vhdlWPrWuPymkoi" + "OHvQDWwpMh9xE8DFAjXofsVixhJ21ecEANppS5jqfshUudM54EjCfYJTJbqgPYvUlDcztOF0" + "HPh7B/8ORLnqzTIPMNkS3kMwPuYSbY0XgN1mkKUr3qaWAImY+oqZkHjV+ESSA1jLV5MdLFmL" + "fYL+iIEDcZay7GmtqAFe6ZRxu5/UVz36Qtby3GiK5TCne0UJneZeywvqHe/XRQKTG+kabWhv" + "hir1/hPg9Xna17tPgKhGjKj2EJROtBG07Jo5nidqbwzRT28KMbjxSzMmXgwq7nMwRrywxxlX" + "y8SXLUoRxqR6nTudc/fpeXPiF4vy2k+C1hqdXzqds/r+UR1YP0eTOeBhVoKOZ2lCdsEeSTCu" + "SCtjf20z6ZhMAes14Ea5HnEvFoi2iVngoyzwW9OWdkSAR0bzzM9U6dbSCqMxABM6Q1Y/yc55" + "c5PETukEY4MpJTD6tOAM6nASQE9A7ua+/RiIzzID0zWi7bVOuUJn2hhbCz/sl07n6n0/QBA8" + "lgR2LT595hgDMNRCcwRYM7xcdHWjUgDihasDwAvfM7pbNOjj73YxS3OK1UXZuxkhnFq2qqhK" + "R1r4nkMe443lJaI70WFFCy4WGFeoc1fyGokBoky9aAB/avUOKOyUjtOu9izSlr0enSoRhNzy" + "fgD4soOht32fAZB1yAfd7s/rmtSCl4JWoASAf0oTk2IRe222ZME3DcaAPyYbFz5GcmyE8KIY" + "mHccXKrHA9X3e9GRFmrBeQdtUXiUo1xSkH1vprlKrKCXQ9QeNyHkAZzNuau/SlvCXMXdNjw4" + "+sRf5nmnLPcl7AHWbScBnM+zEpTSuJpb571rAG60URGC0+r9NOQ/4nuvBVgdBPZleD5TBW5V" + "3GuGwlsJDLteco4LlLpgADD3zzIGA5OMQfV6K95Ynd1oY8i5fmf3/X5IrfML36+bfny6TEDd" + "vkAX/e4T/nZeZ6qdMfhX1DcdyFoSG4gyZu4NEvm96nhulViVRP3ugyQDJr95v51EA4UeoD0v" + "GsxXxN6hU5PG0SxwoyTnPpa3NGgJDbDqoh4AoiBIzFSJ6K/OMR5oVKx0ohiAv+p8/naF4DVV" + "tERi+Kpo1bKCQbsVm6WijxDmvCYKwK4ocDblHoDlwSrwhFIfGIzVcE4ti9cEoAGaMZIzkI5T" + "SuN5BjxfdnDzcWO4OddYm4zJkChoHM1amRL5ftQ8j5o4pO5Cf6W0yB1ONA6VP8kSAFUBTZeJ" + "czaq3xgRAuiPyAqLKC3f7JQA1sgE8gD+8JhltnSczI/kGu8uO42zfo4x/oYwTaFR+W3tnLU4" + "Isp2Dv2FFmeqARpGzArtZUU1Xw4Boyl/niEPrvILD6nGYjNFVJHc8nU3+vUC7fxAgiu6I9I4" + "SgTqmTdrAPZtcu9oYlyZ7GCMnmH7vLuPP5oF2mdpaxPt1CAVmI4kWGrzS28/BmYq1n2E461U" + "5SmXKvAny7JIM10GNj2i5rgVTF17gmgO9YWFgSg3QNUNyWNJ9w1TpyLI5+2Nix2iN0H0BqrH" + "Oy0shtivi13h+VVyd1oUTVx6hrw1wAE0MKqzhgfI3oBTObniXqlxDNSiRmYwXWYYPNHuHPK+" + "bwKk3beLMDum0XQA4GQbeke7XDtEvFtkAGCygx7gaon5wu0KTUM0Ig1E3TdMnGimynjAbRtM" + "bKHZq892sjdXinFvdrL2eKPMuX+cBcYLzQsAUIQgNktfUury10ssXkRBie+OsXnST5grUucz" + "bfW//WaB4/kR6r4lYsSFdv6/WGWmd6tC0Da7ST07xRr00f0SgIEonG27P8KmhitKX29vkDbq" + "ZLviuOLQCSIaLPpCzn2CXphyTpeNkuL7BKXw6XX4apLUdZ0D2xuaBdCowrmgy07u/gjBzKna" + "K1rn1edEW0szleETrbJbtC8kO0l8Nkr67xRVu7/U1RWr5rQ6J1pl51g6bu0mvaDL1hvRG+TU" + "bWoX+GQH3ym+MRCr3heS/UpNtMr62o/WiBW/AkD7XD8nkVwAlR2RY2Dwcq2TgKdrzA7js/Tv" + "wi9/lCVoDbXINHe6zNT2aJaYsH2Bkefr88DvzQ7x3qBMdwEC9I4IsDfTsDvUzlwzBzFB+P10" + "nCv9ebu7z3by1aLRSmhV1DQXoS3rzG8PhpPUCnvcIN4/lOA9QsOe5psB/6KSZPlG6F6F5eyR" + "XON2d0EXC2bCVWDYDfjbG5ypAr/LyO+RREoMABmjuZU3yWdLhpUsL9odlT0410uyZG2nmSpV" + "v/0hTaEvLMvsm8IUpBfzp5ZpepeLTGq+KVHlM8ZTMy+YeeoDQoUHovI7nygk6i/3MAwVe4Xp" + "uHsYnI47N1Xe6bJ+brc5zPvEB1TP+uHU04nNSnVtqGKP7ry5/zcYAw63+Os0U0vhp5ZZ5soY" + "NLf9cceqzrPQighAkGs/rr19pVOT3eHiXHSPH1wio+IbAVFBvl3hOVaGcUErKgBBlhB6R4TM" + "pwIMpdcErd8HAEBGORd9PIBsaBCTXUHGa2M+DwGo5KoVPul5MG0Z/3kL4H+d/guSgjllU02h" + "fQAAAABJRU5ErkJggg==") +getgpdf2swfData = gpdf2swf.GetData +getgpdf2swfImage = gpdf2swf.GetImage +getgpdf2swfBitmap = gpdf2swf.GetBitmap +getgpdf2swfIcon = gpdf2swf.GetIcon + diff -Nru swftools-0.9.2+ds1/wx/lib/utils.py swftools-0.9.1/wx/lib/utils.py --- swftools-0.9.2+ds1/wx/lib/utils.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/lib/utils.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,53 @@ +# coding: utf-8 +import wx + +def blank_bmp(w, h, color="white"): + bmp = wx.EmptyBitmap(max(w,1) , max(h,1)) + clear_bmp(bmp, color) + return bmp + +def clear_bmp(bmp, color): + dc = wx.MemoryDC() + dc.SelectObject(bmp) + dc.SetBackground(wx.Brush(color)) + dc.Clear() + +encodings = [ +'UTF-8', # +#'US-ASCII', # (basic English) +#'ISO-8859-1', # (Western Europe) +#'ISO-8859-2', # (Central Europe) +#'ISO-8859-3', # (Southern Europe) +#'ISO-8859-4', # (Baltic) +#'ISO-8859-5', # (Cyrillic) +#'ISO-8859-6', # (Arabic) +#'ISO-8859-7', # (Greek) +#'ISO-8859-8', # (Hebrew) +#'ISO-8859-9', # (Turkish) +'ISO-8859-15', # (Latin 9) +#'Windows-1250', # (Central Europe) +#'Windows-1251', # (Cyrillic) +'Windows-1252', # (Western Europe) +#'Windows-1253', # (Greek) +#'Windows-1254', # (Turkish) +#'Windows-1255', # (Hebrew) +#'Windows-1256', # (Arabic) +#'Windows-1257', # (Baltic Rim) +#'Windows-1258', # (Vietnam) +#'SHIFT_JIS', # (Japanese, Win/Mac) +#'BIG5', # (Traditional Chinese) +#'GB18030', # (Simplified Chinese) +] + +def force_unicode(s): + if isinstance(s, unicode): + return s + + sane = repr(s)[1:-2] + for enc in encodings: + try: + sane = s.decode(enc) + break + except UnicodeDecodeError: + continue + return sane diff -Nru swftools-0.9.2+ds1/wx/lib/wordwrap.py swftools-0.9.1/wx/lib/wordwrap.py --- swftools-0.9.2+ds1/wx/lib/wordwrap.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/lib/wordwrap.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,97 @@ +#---------------------------------------------------------------------- +# Name: wx.lib.wordwrap +# Purpose: Contains a function to aid in word-wrapping some text +# +# Author: Robin Dunn +# +# Created: 15-Oct-2006 +# RCS-ID: $Id: wordwrap.py 54718 2008-07-19 18:57:26Z RD $ +# Copyright: (c) 2006 by Total Control Software +# Licence: wxWindows license +#---------------------------------------------------------------------- + +def wordwrap(text, width, dc, breakLongWords=True, margin=0): + """ + Returns a copy of text with newline characters inserted where long + lines should be broken such that they will fit within the given + width, with the given margin left and right, on the given `wx.DC` + using its current font settings. By default words that are wider + than the margin-adjusted width will be broken at the nearest + character boundary, but this can be disabled by passing ``False`` + for the ``breakLongWords`` parameter. + """ + + wrapped_lines = [] + text = text.split('\n') + for line in text: + pte = dc.GetPartialTextExtents(line) + wid = ( width - (2*margin+1)*dc.GetTextExtent(' ')[0] + - max([0] + [pte[i]-pte[i-1] for i in range(1,len(pte))]) ) + idx = 0 + start = 0 + startIdx = 0 + spcIdx = -1 + while idx < len(pte): + # remember the last seen space + if line[idx] == ' ': + spcIdx = idx + + # have we reached the max width? + if pte[idx] - start > wid and (spcIdx != -1 or breakLongWords): + if spcIdx != -1: + idx = spcIdx + 1 + wrapped_lines.append(' '*margin + line[startIdx : idx] + ' '*margin) + start = pte[idx] + startIdx = idx + spcIdx = -1 + + idx += 1 + + wrapped_lines.append(' '*margin + line[startIdx : idx] + ' '*margin) + + return '\n'.join(wrapped_lines) + + + +if __name__ == '__main__': + import wx + class TestPanel(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent) + + self.tc = wx.TextCtrl(self, -1, "", (20,20), (150,150), wx.TE_MULTILINE) + self.Bind(wx.EVT_TEXT, self.OnDoUpdate, self.tc) + self.Bind(wx.EVT_SIZE, self.OnSize) + + + def OnSize(self, evt): + wx.CallAfter(self.OnDoUpdate, None) + + + def OnDoUpdate(self, evt): + WIDTH = self.GetSize().width - 220 + HEIGHT = 200 + bmp = wx.EmptyBitmap(WIDTH, HEIGHT) + mdc = wx.MemoryDC(bmp) + mdc.SetBackground(wx.Brush("white")) + mdc.Clear() + mdc.SetPen(wx.Pen("black")) + mdc.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL)) + mdc.DrawRectangle(0,0, WIDTH, HEIGHT) + + text = wordwrap(self.tc.GetValue(), WIDTH-2, mdc, False) + #print repr(text) + mdc.DrawLabel(text, (1,1, WIDTH-2, HEIGHT-2)) + + del mdc + dc = wx.ClientDC(self) + dc.DrawBitmap(bmp, 200, 20) + + + app = wx.App(False) + frm = wx.Frame(None, title="Test wordWrap") + pnl = TestPanel(frm) + frm.Show() + app.MainLoop() + + diff -Nru swftools-0.9.2+ds1/wx/Makefile swftools-0.9.1/wx/Makefile --- swftools-0.9.2+ds1/wx/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/Makefile 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,22 @@ +top_builddir = ../.. +srcdir = . +top_srcdir = .. +include ../Makefile.common + +all: pdf2swf_gui.exe + +pdf2swf_gui.exe: gpdf2swf.py gui/*.py viewers/*.py + cp -a ../installer/swftools.ico /xpython/xpython.ico + cp -a gpdf2swf.py /xpython/main.py + cp -a -R viewers gui lib /xpython/ + rm -f /xpython/swftools/lib/python/gfx.a + rm -f /xpython/swftools/lib/python/gfx.lib + cd /xpython/swftools;git pull + cd /xpython;make xpython.exe + ln -f /xpython/xpython.exe ./gpdf2swf.exe + #ln -f gpdf2swf.exe ../win32_gui/ + ln -f gpdf2swf.exe ../win32/ + cp -R viewers/* ../win32/viewers/ + rm -rf ../win32/viewers/flexpaper* # we're not distributing flexpaper + +.PHONY: exe diff -Nru swftools-0.9.2+ds1/wx/pdf2swf.gui.old.py swftools-0.9.1/wx/pdf2swf.gui.old.py --- swftools-0.9.2+ds1/wx/pdf2swf.gui.old.py 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/pdf2swf.gui.old.py 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,1465 @@ +#!/usr/bin/env python +# -*- coding: ISO-8859-15 -*- +# +# pdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# 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 */ + + +import sys +import wx +import os +sys.path+=["../lib/python"] +import gfx +import images +import stat + +basedir = os.getcwd() + +gfx.verbose(3) + +#try: +# gfx.setparameter("wxwindowparams", "1") +#except: +# gfx.setoption("wxwindowparams", "1") + +class StaticData: + def __init__(self): + self.simpleviewer_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.simpleviewer_width,images.simpleviewer_height,images.simpleviewer_data)) + self.raw_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.raw_width,images.raw_height,images.raw_data)) + self.motionpaper_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.motionpaper_width,images.motionpaper_height,images.motionpaper_data)) + self.rfxview_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.rfxview_width,images.rfxview_height,images.rfxview_data)) +staticdata = None + +HTMLTEMPLATE = """ + + + + + + + + + + + + +""" + +def error(msg): + dlg = wx.MessageDialog(None, msg, "Error", style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + +def savefilestatus(msg): + dlg = wx.MessageDialog(None, msg, "Save file status", style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + +def swfcombine(params): + exe = "swfcombine" + if os.path.sep == '/': + locations = [os.path.join(basedir, "swfcombine"), + "/usr/local/bin/swfcombine", + "/usr/bin/swfcombine" + ] + else: + locations = [os.path.join(basedir, "swfcombine.exe"), + "c:\\swftools\\swfcombine.exe"] + params = ['"'+p+'"' for p in params] + + for e in locations: + if os.path.isfile(e): + exe = e + break + + if hasattr(os,"spawnv"): + print "spawnv",exe,params + ret = -1 + try: + ret = os.spawnv(os.P_WAIT, exe, ["swfcombine"]+params) + except: + ret = -1 + if not ret: + return + + cmd = '"' + exe + '"' + " " + (" ".join(params)) + print "system",cmd + ret = os.system(cmd) + if ret&0xff00: + error("Couldn't execute swfcombine.exe- error code "+str(ret)) + +ICON_SIZE = 64 + +EVENT_PAGE_CHANGE = 1 +EVENT_FILE_CHANGE = 2 +EVENT_STATUS_TEXT = 4 + +class ProgressFrame(wx.Dialog): + def __init__(self, parent, message=""): + wx.Dialog.__init__(self, parent, -1, "Progress", size=(350, 150)) + panel = wx.Panel(self, -1) + self.count = 0 + + self.msg = wx.StaticText(panel, -1, message, (20,25)) + self.gauge = wx.Gauge(panel, -1, 100, (20, 50), (250, 25)) + + self.gauge.SetBezelFace(3) + self.gauge.SetShadowWidth(3) + + self.Bind(wx.EVT_WINDOW_DESTROY, self.close, id=wx.ID_CLOSE) + + def setProgress(self, num): + self.gauge.SetValue(int(num)) + + def close(self, event): + print "close" + + +def swapextension(filename,newext): + basename,ext = os.path.splitext(filename) + return basename + "." + newext + +def has_different_size_pages(doc): + width,height = 0,0 + for i in range(1,doc.pages+1): + page = doc.getPage(i) + if i==1: + width,height = page.width,page.height + else: + if abs(width-page.width)>2 or \ + abs(height-page.height)>2: + return 1 + return 0 + + +options = [] +gfx_options = {} + +class Option: + def __init__(self, parameter, text, options, default, mapping=None): + self.parameter = parameter + self.text = text + self.options = options + self.default = default + self.mapping = mapping + self.control = None + self.enabled = 1 + self.register() + + def generateControl(self, panel): + if type(self.options) == type((0,)): + control = wx.Choice(panel, -1, choices=self.options) + control.SetSelection(self.default) + elif self.options == "slider": + control = wx.Slider(panel, -1, self.default, 0, 100, size=(100, -1), style=wx.SL_HORIZONTAL|wx.SL_LABELS|wx.SL_TOP) + elif self.options == "spinner": + control = wx.SpinCtrl(panel, -1, str(self.default)) + else: + control = wx.Choice(panel, -1, choices=["broken"]) + control.SetSelection(0) + + self.control = control + return self.control + + def getSettings(self): + value = "" + if type(self.options) == type((0,)): + value = self.options[self.control.GetCurrentSelection()] + if self.mapping and value in self.mapping: + value = str(self.mapping[value]) + if value == "yes": + value = "1" + elif value == "no": + value = "0" + return {self.parameter:value} + elif self.options == "slider" or self.options == "spinner": + value = str(self.control.GetValue()) + return {self.parameter:value} + + def register(self): + global options + options += [self] + +class Option2(Option): + + def __init__(self, parameter, text, options, default, mapping=None): + Option.__init__(self, parameter, text, options, default, mapping) + self.enabled = 0 + + def generateControl(self, panel): + p = wx.Panel(panel, -1) + #p.SetOwnBackgroundColour('#ff0000') + h = wx.BoxSizer(wx.HORIZONTAL) + control = wx.Choice(p, -1, choices=self.options) + control.SetSelection(self.default) + text = wx.StaticText(p, -1, self.text) + h.Add(text,1,wx.EXPAND|wx.ALIGN_LEFT|wx.TOP, 5) + h.Add(control,1,wx.EXPAND|wx.ALIGN_RIGHT|wx.ALIGN_TOP) + self.control = control + if self.enabled: + control.Enable() + else: + control.Disable() + p.SetSizer(h) + p.Fit() + return p + + def Disable(self): + self.enabled=0 + if self.control: + self.control.Disable() + + def Enable(self): + self.enabled=1 + if self.control: + self.control.Enable() + + def getSettings(self): + if not self.enabled: + return {} + return Option.getSettings(self) + +class ChooseAndText(Option): + def __init__(self, parameter, text, options, default, editselection, textvalue=""): + Option.__init__(self, parameter, text, options, default) + self.editselection = editselection + self.selection = default + self.textvalue = textvalue + self.enabled = 0 + self.choice = None + + def generateControl(self, panel): + p = wx.Panel(panel, -1) + h = wx.BoxSizer(wx.HORIZONTAL) + control = wx.Choice(p, -1, choices=self.options) + p.Bind(wx.EVT_CHOICE, self.OnChoice, control) + control.SetSelection(self.default) + text = wx.StaticText(p, -1, self.text) + if self.selection == self.editselection: + edittext = wx.TextCtrl(p, -1, self.textvalue) + self.textvalue = "" + else: + edittext = wx.TextCtrl(p, -1, "") + edittext.Disable() + p.Bind(wx.EVT_TEXT, self.OnText, edittext) + h.Add(text,1,wx.EXPAND|wx.ALIGN_LEFT|wx.TOP, 5) + h.Add(control,1,wx.EXPAND|wx.ALIGN_RIGHT) + h.Add(edittext,1,wx.EXPAND|wx.ALIGN_RIGHT) + self.choice = control + self.edittext = edittext + if self.enabled: + control.Enable() + else: + control.Disable() + p.SetSizer(h) + p.Fit() + return p + + def OnText(self, event): + text = self.edittext.GetValue() + text2 = "".join(c for c in text if c.isdigit()) + if text2!=text: + self.edittext.SetValue(text2) + + def OnChoice(self, event): + self.selection = self.choice.GetCurrentSelection() + if self.selection != self.editselection: + if not self.textvalue and self.edittext.GetValue(): + self.textvalue = self.edittext.GetValue() + self.edittext.SetValue("") + self.edittext.Disable() + else: + if self.textvalue and not self.edittext.GetValue(): + self.edittext.SetValue(self.textvalue) + self.textvalue = "" + self.edittext.Enable() + + def Disable(self): + self.enabled=0 + if not self.choice: + return + self.choice.Disable() + self.edittext.Disable() + + def Enable(self): + self.enabled=1 + if not self.choice: + return + self.choice.Enable() + if self.choice.GetCurrentSelection() == self.editselection: + if self.textvalue and not self.edittext.GetValue(): + self.edittext.SetValue(self.textvalue) + self.textvalue = "" + self.edittext.Enable() + else: + self.edittext.Disable() + + def getSettings(self): + if not self.enabled: + return {} + if self.choice.GetCurrentSelection() != self.editselection: + value = self.options[self.choice.GetCurrentSelection()] + else: + value = self.edittext.GetValue().strip() + return {self.parameter:value} + +class TextOption: + def __init__(self, parameter, label, default=""): + self.parameter = parameter + self.label = label + self.default = default + self.register() + + def generateControl(self, panel): + v = wx.BoxSizer(wx.VERTICAL) + self.control = wx.TextCtrl(panel, -1, self.default, size=(250, -1)) + self.control.Fit() + return self.control + + def getSettings(self): + settings = {} + for items in self.control.GetValue().split(" "): + if "=" in items: + l = items.split("=") + if len(l) == 2: + settings[l[0]] = l[1] + return settings + + def register(self): + global options + options += [self] + +class RadioOption(Option): + def __init__(self, text, options): + self.text = text + self.options = options + self.selected = "==nothing==" + self.radios = [] + self.register() + + def generateControl(self, panel): + control = wx.Panel(panel, -1) + vsplit = wx.BoxSizer(wx.VERTICAL) + for i in range(len(self.options)/2): + text = self.options[i*2] + if i == 0: + c = wx.RadioButton(control, -1, text, style=wx.RB_GROUP) + else: + c = wx.RadioButton(control, -1, text) + control.Bind(wx.EVT_RADIOBUTTON, self.OnRadio, c) + self.radios += [c] + vsplit.Add(c) + control.SetSizer(vsplit) + control.Fit() + self.control = control + return control + + def OnRadio(self, event): + self.selected = event.GetEventObject().GetLabel() + + def getSettings(self): + for i in range(len(self.options)/2): + if self.options[i*2] == self.selected: + return self.options[i*2+1] + return self.options[1] + +class BitmapWindow(wx.Window): + def __init__(self, parent, image): + wx.Window.__init__(self, parent, -1) + self.image = image + self.SetMinSize((image.GetWidth()+2, image.GetHeight()+2)) + self.SetMaxSize((image.GetWidth()+2, image.GetHeight()+2)) + self.SetSize((image.GetWidth()+2, image.GetHeight()+2)) + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Update() + def OnPaint(self, event): + dc = wx.PaintDC(self) + self.Draw(dc) + def Draw(self,dc=None): + if not dc: + dc = wx.ClientDC(self) + dc.DrawRectangleRect((0, 0, self.image.GetWidth()+2, self.image.GetHeight()+2)) + dc.DrawBitmap(self.image, 1, 1, False) + +class ImageRadioOption(Option): + def __init__(self, text, options): + self.text = text + self.options = options + self.selected = "==nothing==" + self.radios = [] + self.register() + self.ids = [] + + def generateControl(self, panel): + control = wx.Panel(panel, -1) + vsplit = wx.BoxSizer(wx.VERTICAL) + first = 1 + for image,text,params,selected,extraoptions in self.options: + hsplit = wx.BoxSizer(wx.HORIZONTAL) + + v = wx.BoxSizer(wx.VERTICAL) + + name,text = text.split("- ") + + c = wx.CheckBox(control, -1, name) + control.Bind(wx.EVT_CHECKBOX, self.OnRadio, c) + + # radio buttons crash windows when clicked on- even without event bindings. + # This is caused by the subpanel which is created for extra options + # (I tried this with a empty Panel(), and even that crashed) + #if first: + # c = wx.RadioButton(control, -1, name, style=wx.RB_GROUP) + #else: + # c = wx.RadioButton(control, -1, name) + #control.Bind(wx.EVT_RADIOBUTTON, self.OnRadio, c) + + self.ids += [c.GetId()] + + first = 0 + + if "disable" in text: + c.Enable(False) + if selected: + self.selected = c.GetId() + c.SetValue(True) + else: + c.SetValue(False) + self.radios += [c] + + bitmap = BitmapWindow(control, image) + t = wx.StaticText(control, -1, text, size=(400,50)) + + v.Add(c, 0, wx.EXPAND) + v.Add(t, 0, wx.EXPAND|wx.LEFT, 20) + + for o in extraoptions: + cx = o.generateControl(control) + if selected: + o.Enable() + else: + o.Disable() + v.Add(cx, 0, wx.EXPAND|wx.LEFT, 20) + + v.SetMinSize((330,170)) + + hsplit.Add(bitmap, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.ALIGN_TOP, 5) + hsplit.Add(v, 0, wx.EXPAND) + vsplit.Add(hsplit, 0, wx.EXPAND) + + control.SetSizer(vsplit) + control.Fit() + self.control = control + return vsplit + + def OnRadio(self, event): + self.selected = event.GetEventObject().GetId() + for c in self.radios: + if c.GetId() == self.selected: + c.SetValue(1) + else: + c.SetValue(0) + i = 0 + for image,text,params,selected,extraoptions in self.options: + if self.ids[i] == self.selected: + for xo in extraoptions: + xo.Enable() + pass + else: + for xo in extraoptions: + xo.Disable() + pass + i = i + 1 + event.ResumePropagation(0) + + def getSettings(self): + i = 0 + for image,text,params,s,extraoptions in self.options: + id = self.ids[i] + i = i + 1 + if id == self.selected: + return params + return {} + + +class OptionFrame(wx.Dialog): + + def __init__(self, parent): + wx.Dialog.__init__(self, parent, -1, "Options") + + #self.nb = wx.Notebook(self, -1)#, wx.Point(0,0), wx.Size(0,0), wxNB_FIXEDWIDTH) + self.nb = wx.Notebook(self, -1) + + self.needreload = 0 + + options0 = [RadioOption('Rendering mode', + ["Convert polygons to polygons and fonts to fonts", {}, + "Convert fonts to fonts, everything else to bitmaps", {"poly2bitmap":"1"}, + "Convert everthing to bitmaps", {"poly2bitmap":"1", "bitmapfonts":"1"} + ])] + + mp_options = [] + sv_options = [Option2('flashversion', 'Flash version:', ('4','5','6','7','8'), 2), + Option2('transparent', 'Make SWF file transparent:', ('no','yes'), 0), + ] + + raw_options = [Option2('flashversion', 'Flash version:', ('4','5','6','7','8','9'), 2), + Option2('insertstop', 'Insert stop after each frame:', ('no','yes'), 0), + Option2('transparent', 'Make SWF file transparent:', ('no','yes'), 0), + ] + rfxview_options = [ChooseAndText('rfxwidth', 'Width:', ('same as PDF','fullscreen','custom'),1,2,"600"), + ChooseAndText('rfxheight', 'Height:', ('same as PDF','fullscreen','custom'),1,2,"800"), + Option2('rfxzoomtype', 'Initial zoom level:', ('Original resolution','Show all','Maximum width/height'),2), + ] + + options4 = [ImageRadioOption('Select Paging GUI', + [(staticdata.raw_bitmap, "No Viewer- The SWF will be in \"raw\" format, with each page a seperate frame. Use this if you want to add a viewer yourself afterwards.", {}, 0, raw_options), + (staticdata.simpleviewer_bitmap, "SimpleViewer- A tiny viewer, which attaches directly to the SWF, and provides small previous/next buttons in the upper left corner", {"simpleviewer":"1", "insertstop":"1"}, 0, sv_options), + (staticdata.rfxview_bitmap, "rfxView- A more sophisticated viewer with zooming and scrolling.", {"rfxview":"1", "flashversion":"8"}, 1, rfxview_options), + #(staticdata.motionpaper_bitmap, "MotionPaper- A highly sophisticated viewer with page flipping. (disabled in this evaluation version)", {}, 0, mp_options), + #(staticdata.motionpaper_bitmap, "Your advertisement here- Are you are company who developed a viewer for pdf2swf, or who offers commercial PDF hosting service? Place your advertisement or demo viewer here, or allow pdf2swf to upload SWFs directly to your site! contact sales@swftools.org for details.", {}, 0, mp_options), + ])] + + options1 = [Option('zoom', 'Resolution (in dpi):', "spinner", 72), + Option('fontquality', 'Font quality:', "slider", 20), + Option('storeallcharacters', 'Insert full fonts in SWF file:', ('no','yes'), 0), + Option('splinequality', 'Polygon quality:', "slider", 100), + Option('jpegquality', 'JPEG quality:', "slider", 75), + Option('jpegsubpixels', 'JPEG image resolution:', ('same as in PDF', '1x', '2x', '4x'), 0, {"same as in PDF": 0, "1x": 1, "2x": 2, "3x": 3}), + Option('ppmsubpixels', 'non-JPEG image resolution:', ('same as in PDF', '1x', '2x', '4x'), 0, {"same as in PDF": 0, "1x": 1, "2x": 2, "3x": 3}), + ] + + + options3 = [TextOption('_additional_', 'Additional options')] + + panel1 = [('Rendering options', options0,''), + ('Quality',options1,'v')] + panel3 = [('Select paging GUI', options4,'')] + panel4 = [('Additional options', options3,'')] + + panels = [('Quality', panel1), + ('Viewer', panel3), + ('Advanced', panel4)] + + for name,poptions in panels: + panel = wx.Panel(self.nb, -1) + self.nb.AddPage(panel, name) + + vsplit = wx.BoxSizer(wx.VERTICAL) + + for name,options,align in poptions: + optiongroup = wx.StaticBox(panel, -1, name) + optiongroupsizer= wx.StaticBoxSizer(optiongroup, wx.VERTICAL) + optiongroup.SetSizer(optiongroupsizer) + + if align == 'v': + grid = wx.GridSizer(rows=len(options), cols=2, hgap=3, vgap=3) + optiongroupsizer.Add(grid, 1, wx.EXPAND, 0) + else: + grid = wx.GridSizer(rows=len(options), cols=1, hgap=3, vgap=3) + optiongroupsizer.Add(grid, 1, wx.EXPAND, 0) + + for option in options: + if align=='v': + t = wx.StaticText(panel, -1, option.text) + grid.Add(t, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + optionbox = option.generateControl(panel) + grid.Add(optionbox, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + + vsplit.Add(optiongroupsizer, 0, wx.EXPAND, 0) + + #hs = wx.BoxSizer(wx.HORIZONTAL) + #hs.Add(gobutton, 0, wx.ALIGN_CENTER, 0) + gobutton = wx.Button(panel, -1, "Apply") + self.Bind(wx.EVT_BUTTON, self.Apply, gobutton) + + vsplit.Add(gobutton, 0, wx.ALIGN_CENTER|wx.ALL, 0) + + panel.SetSizer(vsplit) + panel.Fit() + + self.nb.Fit() + + self.Fit() + + + def updateOptions(self): + global options,gfx_options + a = [] + + # FIXME: we clear *our* options- but gfx will still have + # stored the old ones. Critical for options in the "imageradio" section. + gfx_options.clear() + i = 0 + print "----- options ------" + for option in options: + for k,v in option.getSettings().items(): + gfx_options[k] = v + gfx.setparameter(k,v) + print k,v + i = i + 1 + + # TODO: filter out "global" options, and do this only if + # pdf layer is affected + + def Apply(self, event): + self.updateOptions() + self.Hide() + self.needreload = 1 + + +class State: + def __init__(self): + self.pdf = None + self.page = None + self.pagenr = 1 + self.pagebitmap = None + self.bitmap_width = 0 + self.bitmap_height = 0 + self.bitmap_page = 0 + self.filename = None + self.status_text = None + self.lastsavefile = "output.swf" + self.lasthtmlfile = "index.html" + + self.listeners = [] + + def onEvent(self,event_type, function): + self.listeners += [(event_type,function)] + def loadPDF(self,filename): + self.filename = filename + self.lastsavefile = swapextension(filename,"swf") + self.lasthtmlfile = swapextension(filename,"html") + + self.pdf = gfx.open("pdf",filename) + if(has_different_size_pages(self.pdf)): + # just let the user know- for now, we can't handle this properly + dlg = wx.MessageDialog(app.frame, """In this PDF, width or height are not the same for each page. This might cause problems if you export pages of different dimensions into the same SWF file.""", "Notice", style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + + self.changePage(1) + + for type,f in self.listeners: + if type&EVENT_PAGE_CHANGE or type&EVENT_FILE_CHANGE: + f() + self.setStatus("File loaded successfully.") + + def saveSWF(self, filename, progress, pages=None, html=0): + if html: + basename,ext = os.path.splitext(filename) + if not ext: + html = basename + ".html" + filename = basename + ".swf" + elif ext.lower() != ".swf": + html = filename + filename = basename + ".swf" + else: + html = basename + ".html" + filename = filename + + steps = 100.0 / (self.pdf.pages*2 + 3) + pos = [0] + + self.lastsavefile = filename + if html: + self.lasthtmlfile = html + + swf = gfx.SWF() + for k,v in gfx_options.items(): + swf.setparameter(k,v) + if pages is None: + pages = range(1,self.pdf.pages+1) + pdfwidth,pdfheight=0,0 + for pagenr in pages: + page = self.pdf.getPage(pagenr) + pdfwidth = page.width + pdfheight = page.height + swf.startpage(page.width, page.height) + page.render(swf) + swf.endpage() + swf.save(filename) + if not os.path.isfile(filename): + error("Couldn't create file "+filename) + + if gfx_options.get("rfxview",None): + rfxview = os.path.join(basedir, "rfxview.swf") + if not os.path.isfile(rfxview): + error("File rfxview.swf not found in working directory") + else: + size1 = os.stat(filename)[stat.ST_SIZE] + swfcombine([rfxview,"viewport="+filename,"-o",filename]) + size2 = os.stat(filename)[stat.ST_SIZE] + if size1 == size2: + error("Couldn't add viewer to file "+filename) + + if html: + version = int(gfx_options.get("flashversion", "8")) + swf = gfx.open("swf", filename) + page1 = swf.getPage(1) + + width,height = str(page1.width),str(page1.height) + + + w = gfx_options.get("rfxwidth","") + if w == "fullscreen": width = "100%" + elif w == "same as PDF": width = pdfwidth+40 + elif w.isdigit(): width = w + else: width = pdfwidth + + h = gfx_options.get("rfxheight","") + if h == "fullscreen": height = "100%" + elif h == "same as PDF": height = pdfheight+70 + elif h.isdigit(): height = h + else: height = pdfwidth + + flashvars = "" + zoomtype = gfx_options.get("rfxzoomtype","") + if zoomtype=="Original resolution": + flashvars = "zoomtype=1" + elif zoomtype=="Show all": + flashvars = "zoomtype=2" + elif zoomtype=="Maximum width/height": + flashvars = "zoomtype=3" + + swffilename = os.path.basename(filename) + fi = open(html, "wb") + fi.write(HTMLTEMPLATE % locals()) + fi.close() + + + def changePage(self,page): + self.pagenr = page + self.page = self.pdf.getPage(self.pagenr) + for type,f in self.listeners: + if type&EVENT_PAGE_CHANGE: + f() + + def getPageIcon(self,pagenr): + page = self.pdf.getPage(pagenr) + return wx.BitmapFromImage(wx.ImageFromData(ICON_SIZE,ICON_SIZE,page.asImage(ICON_SIZE,ICON_SIZE))) + #return wx.BitmapFromImage(wx.ImageFromData(8,8,"0"*(64*3))) + + def getPageImage(self, width, height): + if self.bitmap_width == width and self.bitmap_height == height and self.bitmap_page == self.pagenr: + return self.pagebitmap + else: + self.bitmap_width = width + self.bitmap_height = height + self.bitmap_page = self.pagenr + self.pagebitmap = wx.BitmapFromImage(wx.ImageFromData(width,height,self.page.asImage(width,height))) + #self.pagebitmap = wx.BitmapFromImage(wx.ImageFromData(8,8,"0"*(64*3))) + return self.pagebitmap + + def setStatus(self,text): + self.status_text = text + for type,f in self.listeners: + if type&EVENT_STATUS_TEXT: + f() + +state = State() + +class PageListWidget(wx.ListCtrl): + def __init__(self,parent): + wx.ListCtrl.__init__(self,parent,style=wx.LC_ICON|wx.LC_AUTOARRANGE) + #self.SetMinSize((ICON_SIZE+8,-1)) + #self.SetMaxSize((ICON_SIZE+8,-1)) + #self.SetSize((ICON_SIZE+8,-1)) + self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.SelectItem) + state.onEvent(EVENT_FILE_CHANGE, self.reload) + state.onEvent(EVENT_PAGE_CHANGE, self.switchPage) + self.reload() + self.dontcare = 0 + #self.Bind(wx.EVT_IDLE, self.OnIdle) + #print dir(self) + + def processFiles(self): + if self.filepos >= 0 and self.filepos < state.pdf.pages: + icon = state.getPageIcon(self.filepos+1) + self.imglist.Add(icon) + self.InsertImageStringItem(self.filepos, str(self.filepos+1), self.filepos) + self.filepos = self.filepos + 1 + self.Update() + + def OnIdle(self,event): + self.processFiles() + event.ResumePropagation(0) + + def reload(self): + self.filepos = -1 + self.DeleteAllItems() + self.imglist = wx.ImageList(ICON_SIZE,ICON_SIZE,mask=False) + self.AssignImageList(self.imglist,wx.IMAGE_LIST_NORMAL) + self.filepos = 0 + while state.pdf and self.filepos < state.pdf.pages: + self.processFiles() + + def switchPage(self): + if self.dontcare: + self.dontcare = 0 + return + for i in range(0,self.GetItemCount()): + self.Select(i, False) + self.Select(state.pagenr-1, True) + self.Focus(state.pagenr-1) + self.Update() + + def SelectItem(self,event): + self.dontcare = 1 #ignore next change event + state.changePage(event.GetIndex()+1) + + +helptxt = """ +This is the SWF preview window. +Here, you will see how the SWF file generated from +the PDF file will look like. Changing parameters in +the configuration which affect the appeareance of +the final SWF will affect this preview, too, so you +can always evaluate the final output beforehand. +""" + + +class OnePageWidget(wx.Window): + def __init__(self,parent): + wx.Window.__init__(self, parent) + self.SetSize((160,100)) + self.SetMinSize((160,100)) + self.Fit() + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_KEY_DOWN, self.key_down) + state.onEvent(EVENT_PAGE_CHANGE, self.OnPageChange) + + def key_down(self, event): + if state.pdf: + if event.GetKeyCode() == 312 and state.pagenr>1: + state.changePage(state.pagenr-1) + elif event.GetKeyCode() == 313 and state.pagenr state.page.height * window_width: + width = window_width + height = window_width * state.page.height / state.page.width + posy = (window_height - height) / 2 + else: + width = window_height * state.page.width / state.page.height + height = window_height + posx = (window_width - width) / 2 + + dc.DrawBitmap(state.getPageImage(width,height), posx,posy, False) + #state.getPageImage( + + def OnPaint(self, event): + dc = wx.PaintDC(self) + self.Draw(dc) + +class Pdf2swfFrame(wx.Frame): + #def __init__(self): + #wx.Window.__init__(self, None, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize) + def __init__(self,application): + wx.Frame.__init__(self, None, -1, style = wx.DEFAULT_FRAME_STYLE) + self.application = application + + self.SetTitle("pdf2swf") + self.createMenu() + self.createToolbar() + self.createStatusBar() + self.createMainFrame() + + self.SetSize((800,600)) + + self.options = OptionFrame(None) + self.options.Show(False) + self.options.updateOptions() + + state.onEvent(EVENT_STATUS_TEXT, self.status_change) + self.html = 0 + + #self.table = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), 333),]) + #self.SetAcceleratorTable(self.table) + + self.Bind(wx.EVT_IDLE, self.OnIdle) + self.Bind(wx.EVT_CLOSE, self.menu_exit) + return + + def menu_open(self,event): + global state + if state.filename: + dlg = wx.FileDialog(self, "Choose PDF File:", style = wx.DD_DEFAULT_STYLE, defaultFile = state.filename, wildcard = "PDF files (*.pdf)|*.pdf|all files (*.*)|*.*") + else: + dlg = wx.FileDialog(self, "Choose PDF File:", style = wx.DD_DEFAULT_STYLE, wildcard = "PDF files (*.pdf)|*.pdf|all files (*.*)|*.*") + + if dlg.ShowModal() == wx.ID_OK: + self.filename = dlg.GetFilename() + state.loadPDF(self.filename) + + def menu_save(self,event,pages=None): + html,self.html = self.html,0 + global state + if not state.pdf: + return + print "html",html + if not html: + defaultFile = state.lastsavefile + else: + defaultFile = state.lasthtmlfile + dlg = wx.FileDialog(self, "Choose Save Filename:", style = wx.SAVE | wx.OVERWRITE_PROMPT, defaultFile = defaultFile, wildcard = "all files (*.*)|*.*|SWF files (*.swf)|*.swf|HTML template (*.html)|*.html") + + if dlg.ShowModal() == wx.ID_OK: + filename = os.path.join(dlg.GetDirectory(),dlg.GetFilename()) + + #progress = ProgressFrame(self, "Saving %s File '%s'..." % (html and "HTML" or "SWF", filename)) + #progress.Show(True) + progress = None + state.saveSWF(filename, progress, pages, html) + #progress.Destroy() + + def menu_save_selected(self,event): + if not state.pdf: + return + p = [] + for i in range(0,self.pagelist.GetItemCount()): + if self.pagelist.IsSelected(i): + p += [i+1] + self.menu_save(event, pages=p) + + def menu_save_html(self,event): + self.html = 1 + return self.menu_save(event) + + def menu_save_selected_html(self,event): + self.html = 1 + return self.menu_save_selected(event) + + def menu_exit(self,event): + self.application.Exit() + + def menu_selectall(self,event): + for i in range(0,self.pagelist.GetItemCount()): + self.pagelist.Select(i, True) + def menu_options(self,event): + self.options.Show(True) + + def status_change(self): + self.statusbar.SetStatusText(state.status_text) + + def OnIdle(self,event): + if self.options.needreload: + self.options.needreload = 0 + if state.pdf: + # reload + state.loadPDF(state.filename) + + def createMenu(self): + menubar = wx.MenuBar() + + menu = wx.Menu();menubar.Append(menu, "&File") + menu.Append(wx.ID_OPEN, "Open PDF\tCTRL-O");self.Bind(wx.EVT_MENU, self.menu_open, id=wx.ID_OPEN) + menu.AppendSeparator() + menu.Append(wx.ID_SAVE, "Save SWF (all pages)\tCTRL-W");self.Bind(wx.EVT_MENU, self.menu_save, id=wx.ID_SAVE) + menu.Append(wx.ID_SAVEAS, "Save SWF (selected pages)\tCTRL-S");self.Bind(wx.EVT_MENU, self.menu_save_selected, id=wx.ID_SAVEAS) + menu.AppendSeparator() + menu.Append(2001, "Save HTML template (all pages)\tCTRL-H");self.Bind(wx.EVT_MENU, self.menu_save_html, id=2001) + menu.Append(2002, "Save HTML template (selected pages)");self.Bind(wx.EVT_MENU, self.menu_save_selected_html, id=2002) + menu.AppendSeparator() + menu.Append(wx.ID_EXIT, "Exit\tCTRL-Q");self.Bind(wx.EVT_MENU, self.menu_exit, id=wx.ID_EXIT) + + menu = wx.Menu();menubar.Append(menu, "&Edit") + menu.Append(wx.ID_SELECTALL, "Select All\tCTRL-A");self.Bind(wx.EVT_MENU, self.menu_selectall, id=wx.ID_SELECTALL) + menu.AppendSeparator() + menu.Append(wx.ID_PREFERENCES, "Options\tCTRL-R");self.Bind(wx.EVT_MENU, self.menu_options, id=wx.ID_PREFERENCES) + + menu = wx.Menu();menubar.Append(menu, "&Help") + + self.SetMenuBar(menubar) + + + def createToolbar(self): + + tsize = (16,16) + self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT) + + self.toolbar.AddSimpleTool(wx.ID_OPEN, + wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, tsize), + "Open") + self.toolbar.AddSimpleTool(wx.ID_SAVE, + wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR, tsize), + "Save selected pages") + self.toolbar.AddSimpleTool(wx.ID_PREFERENCES, + wx.ArtProvider.GetBitmap(wx.ART_LIST_VIEW, wx.ART_TOOLBAR, tsize), + "Options") + #self.toolbar.AddSeparator() + self.toolbar.Realize() + + def createStatusBar(self): + self.statusbar = self.CreateStatusBar(1) + + def createMainFrame(self): + + if 0: + self.pagelist = PageListWidget(self) + self.onepage = OnePageWidget(self) + hsplit = wx.BoxSizer(wx.HORIZONTAL) + pagelistbox = wx.StaticBox(self, -1, "Pages") + pagelistboxsizer= wx.StaticBoxSizer(pagelistbox, wx.VERTICAL) + pagelistboxsizer.Add(self.pagelist, proportion=1, flag=wx.EXPAND) + onepagebox = wx.StaticBox(self, -1, "Page 1") + onepageboxsizer= wx.StaticBoxSizer(onepagebox, wx.VERTICAL) + onepageboxsizer.Add(self.onepage, proportion=1, flag=wx.EXPAND) + hsplit.Add(pagelistboxsizer, 0, wx.EXPAND, 0) + hsplit.Add(onepageboxsizer, 1, wx.EXPAND, 0) + self.SetAutoLayout(True) + self.SetSizer(hsplit) + hsplit.Fit(self) + hsplit.SetSizeHints(self) + else: + hsplit = wx.SplitterWindow(self, style=wx.SP_3D|wx.SP_LIVE_UPDATE) + #p1 = wx.Panel(hsplit,-1, style=wx.SUNKEN_BORDER) + #p2 = wx.Panel(hsplit,-1, style=wx.SUNKEN_BORDER) + self.pagelist = PageListWidget(hsplit) + self.onepage = OnePageWidget(hsplit) + #hsplit.SplitVertically(p1,p2, sashPosition=64) + hsplit.SplitVertically(self.pagelist, self.onepage, sashPosition=ICON_SIZE*3/2) + hsplit.SetMinimumPaneSize(10) + +class MyApp(wx.App): + def __init__(self): + wx.App.__init__(self, redirect=False, filename=None, useBestVisual=False) + + #state.loadPDF("sitis2007.pdf") + #state.loadPDF("wxPython-Advanced-OSCON2004.pdf") + global staticdata + staticdata = StaticData() + + self.frame = Pdf2swfFrame(self) + self.SetTopWindow(self.frame) + self.frame.Show(True) + + #self.frame = TestFrame(self) + #self.frame.Show(True) + + def OnInit(self): + return True + + +raw_width=100 +raw_height=100 +raw_data="""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfa\xfa\xff\xff\xffQQQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"""+\ +"""\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"""+\ +"""\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfa\xfa\xff\xff\xffJJJ]]]\xc5\xc5\xc5\xc1\xc1\xc1\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc4"""+\ +"""\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc3\xc3\xc3\xc2\xc2\xc2\xc1\xc1\xc1\xc1\xc1\xc1\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4"""+\ +"""\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc1\xc1\xc1\xc4\xc4\xc4\x96\x96\x96"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfa\xfa\xff\xff\xffHHH\x81\x81\x81\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd0\xd0\xd0"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfa\xfa\xff\xff\xffIIIxxx\xfc\xfc\xfc\xf8\xf8\xf8\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfc"""+\ +"""\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xf9\xf9\xf9\xc2\xc2\xc2\xb2\xb2\xb2\xaf\xaf\xaf\xe9\xe9\xe9\xfb\xfb\xfb\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfa\xfa\xfa\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfa\xfa\xfa\xfd\xfd\xfd\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc"""+\ +"""\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xf9\xf9\xf9\xfc\xfc\xfc\xc2\xc2\xc2"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfa\xfa\xff\xff\xffIII\x7a\x7a\x7a\xff\xff\xff\xfb\xfb\xfb\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff"""+\ +"""\xff\xff\xfc\xfc\xfc\xff\xff\xff\xdd\xdd\xdd\x22\x22\x22\x83\x83\x83\x7d\x7d\x7d\xdd\xdd\xdd\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xf9\xf9\xf9\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff"""+\ +"""\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4"""+\ +"""\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xf9\xf9\xf9\xfe\xfe\xfeIII\x79\x79\x79\xfe\xfe\xfe\xfa\xfa\xfa\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe"""+\ +"""\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xd8\xd8\xd8TTT\xff\xff\xff\xff\xff\xff\xe3\xe3\xe3gggnnn\xb4\xb4\xb4\xa6\xa6\xa6\x5c\x5c\x5ciii\xe1\xe1\xe1\xf0\xf0\xf0\x7b\x7b\x7bqqqZZZ\xb3\xb3\xb3oooooo\xec\xec\xec\xfc\xfc\xfc\x92\x92\x92WWWooo\xed\xed\xed\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe"""+\ +"""\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc4\xc4\xc4"""+\ +"""\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xf9\xf9\xf9\xfe\xfe\xfeIII\x79\x79\x79\xfe\xfe\xfe\xfa\xfa\xfa\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe"""+\ +"""\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xe0\xe0\xe0%%%lll\x86\x86\x86\xc3\xc3\xc3&&&\xdf\xdf\xdf\xff\xff\xff\xeb\xeb\xeb\xe0\xe0\xe0ccc\x79\x79\x79\xfb\xfb\xfb---\xd6\xd6\xd6\xab\xab\xab,,,\xed\xed\xed\x83\x83\x83\xa4\xa4\xa4\xc2\xc2\xc2III\xf3\xf3\xf3sss\x7e\x7e\x7e\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe"""+\ +"""\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfa\xfa\xff\xff\xffIII\x7a\x7a\x7a\xff\xff\xff\xfb\xfb\xfb\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff"""+\ +"""\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd9\xd9\xd9LLL\xea\xea\xea\xee\xee\xee\xcb\xcb\xcbccc\xff\xff\xff\xf6\xf6\xf6xxx\x8c\x8c\x8c\x7d\x7d\x7dkkk\xee\xee\xeefff\xff\xff\xff\xcb\xcb\xcbppp\xff\xff\xff\xa4\xa4\xa4\x8d\x8d\x8d\xa2\xa2\xa2@@@\x92\x92\x92\x79\x79\x79\xa5\xa5\xa5\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff"""+\ +"""\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4"""+\ +"""\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xf9\xf9\xf9\xfe\xfe\xfeHHH\x79\x79\x79\xfe\xfe\xfe\xfa\xfa\xfa\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe"""+\ +"""\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xd5\xd5\xd5JJJ\xff\xff\xff\xff\xff\xff\xcc\xcc\xccWWW\xfd\xfd\xfd\xe4\xe4\xe4FFF\xe9\xe9\xe9mmm___\xed\xed\xed[[[\xfa\xfa\xfa\xc4\xc4\xc4ggg\xfe\xfe\xfe\x9b\x9b\x9b\x86\x86\x86\xd4\xd4\xd4GGG\xdc\xdc\xdc\xe7\xe7\xe7\xe6\xe6\xe6\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe"""+\ +"""\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfa\xfa\xff\xff\xffIII\x7a\x7a\x7a\xff\xff\xff\xfb\xfb\xfb\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff"""+\ +"""\xff\xff\xfd\xfd\xfd\xff\xff\xff\xe7\xe7\xe7\x93\x93\x93\xfd\xfd\xfd\xfd\xfd\xfd\xe0\xe0\xe0\x9c\x9c\x9c\xfe\xfe\xfe\xfe\xfe\xfe\xa7\xa7\xa7nnn\x8d\x8d\x8d\xa9\xa9\xa9\xf3\xf3\xf3\x9f\x9f\x9f\xfd\xfd\xfd\xdd\xdd\xdd\xa5\xa5\xa5\xfe\xfe\xfe\xc6\xc6\xc6\xaf\xaf\xaf\xff\xff\xff\xa7\xa7\xa7cccooo\xcd\xcd\xcd\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff"""+\ +"""\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4"""+\ +"""\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xf9\xf9\xf9\xfe\xfe\xfeHHH\x79\x79\x79\xfe\xfe\xfe\xfa\xfa\xfa\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe"""+\ +"""\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe"""+\ +"""\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xff\xff\xffLLL\x7c\x7c\x7c\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf2\xf2\xf2\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xee\xee\xee\xf3\xf3\xf3<<>>\xfe\xfe\xfefff\xba\xba\xba\xff\xff\xffFFF\xe4\xe4\xe4\xe9\xe9\xe9mmm\xcb\xcb\xcb;;;\xa6\xa6\xa6\x94\x94\x94JJJ\xee\xee\xee\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfeUUU\xe1\xe1\xe1\xff\xff\xff\xfa\xfa\xfaccc\xe2\xe2\xe2\xfc\xfc\xfcooo\x9c\x9c\x9c\xcd\xcd\xcd000\xff\xff\xffiii\xcc\xcc\xcc\xfc\xfc\xfceee\xe9\xe9\xe9\xe0\xe0\xe0mmm\xcf\xcf\xcf;;;\xb8\xb8\xb8\xd0\xd0\xd0\xd8\xd8\xd8\xfa\xfa\xfa\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe[[[\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff]]]\xd4\xd4\xd4\xfc\xfc\xfc\xf5\xf5\xf5iii\xe1\xe1\xe1\xff\xff\xff\x94\x94\x94xxx\x83\x83\x83999\xfc\xfc\xfcooo\xcb\xcb\xcb\xfe\xfe\xfehhh\xe9\xe9\xe9\xe4\xe4\xe4kkk\xfe\xfe\xfe\x88\x88\x88sss\x98\x98\x98\xad\xad\xad\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xe1\xe1\xe1\xf8\xf8\xf8\xfe\xfe\xfe\xfd\xfd\xfd\xe4\xe4\xe4\xf9\xf9\xf9\xfe\xfe\xfe\xfd\xfd\xfd\xbe\xbe\xbe\xd2\xd2\xd2\xe9\xe9\xe9\xfd\xfd\xfd\xe5\xe5\xe5\xf6\xf6\xf6\xfe\xfe\xfe\xe4\xe4\xe4\xfb\xfb\xfb\xfa\xfa\xfa\xe5\xe5\xe5\xfd\xfd\xfd\xff\xff\xff\xc4\xc4\xc4\xb0\xb0\xb0\xdc\xdc\xdc\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe[[[\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x90\x90\x90\xae\xae\xae\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\x5c\x5c\x5c\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe[[[\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe[[[\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe[[[\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe[[[\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe[[[\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe[[[\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe[[[\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe[[[\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x90\x90\x90\xae\xae\xae\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\x5c\x5c\x5c\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe[[[\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc3\xc3\xc3\x00\x00\x00\xc4\xc4\xc4\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x90\x90\x90\xae\xae\xae\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\x5c\x5c\x5c\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\x5c\x5c\x5c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc4\xc4\xc4\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff[[[\xef\xef\xef\xfb\xfb\xfb\xfa\xfa\xfa\xfb\xfb\xfb\xfa\xfa\xfa\xfb\xfb\xfb\xfa\xfa\xfa\xfb\xfb\xfb\xfb\xfb\xfb\xf8\xf8\xf8\xfb\xfb\xfb\xc1\xc1\xc1\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff^^^\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd3\xd3\xd3\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xffLLLooo\x7c\x7c\x7c\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x79\x79\x79\x7e\x7e\x7eYYY\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xffDDDDDDJJJHHHIIIHHHIIIHHHIIIIIIIIIIIIJJJ\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xffYYY\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfeVVV\xee\xee\xee\xfa\xfa\xfa\xf9\xf9\xf9\xfa\xfa\xfa\xf9\xf9\xf9\xfa\xfa\xfa\xf9\xf9\xf9\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xf9\xf9\xf9\xfa\xfa\xfa\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfeVVV\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xffWWW\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xffWWW\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfeVVV\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xffWWW\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x90\x90\x90\xae\xae\xae\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xffWWW\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\x8f\x8f\x8f\xad\xad\xad\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfeVVV\xf3\xf3\xf3\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\x90\x90\x90\xaf\xaf\xaf\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffWWW\xf2\xf2\xf2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\x8f\x8f\x8f\xab\xab\xab\xff\xff\xff\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfdYYY\xf3\xf3\xf3\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\x8d\x8d\x8d###222......//////...//////......///---\x19\x19\x19\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfa\xfa\xfa\xff\xff\xff\x7e\x7e\x7e000\xb6\xb6\xb6\xb2\xb2\xb2\xb5\xb5\xb5\xb6\xb6\xb6\xb6\xb6\xb6\xb5\xb5\xb5\xb6\xb6\xb6\xb6\xb6\xb6\xb5\xb5\xb5\xb5\xb5\xb5\xb6\xb6\xb6\xb6\xb6\xb6\xc3\xc3\xc3\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfb\xfb\xfb\xff\xff\xffxxxNNN\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc4\xc4\xc4\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfa\xfa\xfa\xfe\xfe\xfe\x7a\x7a\x7aHHH\xfb\xfb\xfb\xf6\xf6\xf6\xfa\xfa\xfa\xfb\xfb\xfb\xfb\xfb\xfb\xfa\xfa\xfa\xfb\xfb\xfb\xfb\xfb\xfb\xfa\xfa\xfa\xfa\xfa\xfa\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfa\xfa\xfa\xfe\xfe\xfe\x79\x79\x79HHH\xfe\xfe\xfe\xf9\xf9\xf9\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\x7a\x7a\x7aIII\xff\xff\xff\xfa\xfa\xfa\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfa\xfa\xfa\xfe\xfe\xfe\x79\x79\x79HHH\xfe\xfe\xfe\xf9\xf9\xf9\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\x7a\x7a\x7aIII\xff\xff\xff\xfa\xfa\xfa\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc3\xc3\xc3\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfa\xfa\xfa\xfe\xfe\xfe\x79\x79\x79III\xfe\xfe\xfe\xf9\xf9\xf9\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\x7a\x7a\x7aIII\xff\xff\xff\xfa\xfa\xfa\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\x7a\x7a\x7aIII\xff\xff\xff\xfa\xfa\xfa\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xc2\xc2\xc2\xfc\xfc\xfc\xf9\xf9\xf9\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xf8\xf8\xf8\xfc\xfc\xfcxxxIII\xff\xff\xff\xfa\xfa\xfa\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\x00\x00\x00\xd0\xd0\xd0\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x81\x81\x81HHH\xfe\xfe\xfe\xf9\xf9\xf9\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\x00\x00\x00\x96\x96\x96\xc4\xc4\xc4\xc1\xc1\xc1\xc4\xc4\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc3\xc3\xc3\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4\xc4\xc1\xc1\xc1\xc5\xc5\xc5]]]JJJ\xff\xff\xff\xfa\xfa\xfa\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff""" + +simpleviewer_width=100 +simpleviewer_height=100 +simpleviewer_data="""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d"""+\ +"""\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d"""+\ +"""\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0d\x0d\x0d\x84\x84\x84\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb5\xb5\xb5\xb6\xb6\xb6\xb5\xb5\xb5\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7"""+\ +"""\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7"""+\ +"""\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\x84\x84\x84\x0d\x0d\x0d\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0d\x0d\x0d\xb7\xb7\xb7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf9\xf9\xf9\x79\x8b\x79ftf\xf7\xf7\xf7&2&\xbd\xc1\xbd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xb7\xb7\xb7\x0d\x0d\x0d\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0d\x0d\x0d\xb7\xb7\xb7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xaa\xb2\xaa2Z2+\xca+PgP\xf6\xf6\xf6*k**\x8c*JdJ\xe1\xe1\xe1\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xb7\xb7\xb7\x0d\x0d\x0d\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0d\x0d\x0d\xb7\xb7\xb7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd4\xd6\xd4?\x5c?*\x9d*2\xfe22\xff2OgO\xf4\xf4\xf4-r-2\xff2-\xe8-*j*o\x81o\xf6"""+\ +"""\xf6\xf6\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xb7\xb7\xb7\x0d\x0d\x0d\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0d\x0d\x0d\xb7\xb7\xb7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xef\xef\xef^s^)s)/\xef/2\xff22\xff22\xff2NgN\xf3\xf3\xf3.t.2\xff22\xff22\xff2)\xc9)."""+\ +"""U.\xa0\xa9\xa0\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xb7\xb7\xb7\x0d\x0d\x0d\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"""+\ +"""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0d\x0d\x0d\xb7\xb7\xb7\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\x8c\x98\x8c,[,+\xd6+2\xff22\xff22\xff22\xff22\xff2NgN\xf2\xf2\xf2.u.2\xff22\xff22\xff22\xff22"""+\ +"""\xfe2)\xa2)?\xa2\xa2\xa2\x7c\x7c\x7chhh\xff\xff\xff\xed\xed\xed\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1"""+\ +"""\xf0\xf0\xf0\xf0\xf0\xf0\xef\xef\xef\xf0\xf0\xf0\xef\xef\xef\xf0\xf0\xf0\xee\xee\xee\xe6\xe5\xe5\xf0\xf0\xf0\xdd\xe2\xde\xd6\xdd\xd7\xd6\xdc\xd6\xe4\xea\xe5\xe7\xea\xe7\xd5\xda\xd6\xdb\xe2\xdc\xd5\xdb\xd6\xda\xe0\xdb\xdf\xe4\xe0\xf9\xfd\xfa\xed\xf2\xee\xdd\xe4\xde\xe5\xec\xe6\xe4\xeb\xe5\xdb\xe1\xdb\xe5\xec\xe6\xd9\xe1\xda\xd2\xda\xd3\xe1\xe7\xe2\xe8\xef\xe9\xe1\xe8\xe2\xdd\xe4\xdd\xf8\xfa\xf8\xe6"""+\ +"""\xf7\xe4\xe8\xf7\xe7\xff\xff\xff\xfd\xfe\xfe\xfd\xfe\xfe\xfe\xfe\xff\xfd\xfe\xfe\xf9\xff\xfb\xf5\xfd\xf7\xf9\xff\xfb\xdb\xed\xde\x84Q\x7a\xd9\x82\xca\xef\xff\xf3\xf5\xfb\xf7\xf5\xfd\xf7\xff\xff\xff\xdc\xe0\xdd\xbd\xc4\xbe\xcb\xd2\xcc\xd6\xdc\xd7\xc8\xd8\xca\x7cQs\xccx\xbd\xe8\xf7\xea\xf1\xf6\xf2\xf4\xfa\xf5\xf7\xfe\xf8\xfa\xff\xfb\xfc\xfe\xfe\xfd\xff\xfe\xfe\xff\xff\xfe\xff\xfe\xfe\xfe"""+\ +"""\xfe\xfe\xfe\xfe\xfe\xff\xff\xfe\xff\xff\xfe\xff\xff\xfe\xff\xff\xfe\xfe\xfe\xfe\xff\xff\xfe\xff\xff\xfe\xff\xff\xfe\xfe\xfe\xfd\xfe\xfe\xff\xff\xff\xec\xf0\xed\xd6\xde\xd7\xd6\xdd\xd7\xdb\xe1\xdc\xe9\xee\xea\xc9\xcf\xca\xb3\xb9\xb4\xa2\xa7\xa3\x8d\x92\x8e\x80\x83\x80v\x79wX]Wpro\xf4\xf3\xf3222ttt\xff\xff\xff\xec\xec\xec\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf0"""+\ +"""\xef\xef\xef\xef\xef\xef\xee\xee\xee\xef\xef\xef\xee\xee\xee\xee\xee\xee\xef\xef\xef\xd9\xda\xd8\xe4\xd4\xe1\xc5\xa3\xbe\xbe\x9c\xb7\xb7\x95\xb0\xcb\xaa\xc5\xcc\xae\xc6\xb8\x98\xb1\xc6\xa2\xc0\xc0\x9d\xb9\xbe\x9e\xb8\xc1\x9e\xba\xe9\xc8\xe3\xdf\xbc\xd8\xc1\x9d\xba\xc8\xa4\xc1\xc2\x9e\xbb\xbd\x99\xb6\xc2\x9e\xbb\xc5\xa1\xbe\xbf\x9b\xb8\xbd\x98\xb5\xca\xa6\xc3\xc4\xa0\xbd\xc8\xa2\xc1\xd5\xbb\xcc\xdb"""+\ +"""\xc6\xd1\xfe\xda\xf8\xfd\xda\xf7\xfd\xda\xf7\xfd\xda\xf7\xfe\xdb\xf8\xfd\xd9\xf7\xf9\xd6\xf3\xf5\xd3\xef\xf8\xd4\xf1\xe1\xc8\xdc\xa4X\x95\xdf\x79\xce\xf0\xd8\xec\xf5\xd5\xf0\xf5\xd8\xf0\xff\xe2\xfa\xdc\xc2\xd8\xbc\xa2\xb8\xca\xaf\xc6\xd4\xb7\xd0\xcb\xb6\xc7\x97U\x8b\xd0o\xbf\xe5\xce\xe1\xec\xce\xe7\xef\xd2\xea\xf4\xd5\xef\xf8\xd7\xf2\xf8\xd8\xf3\xfc\xd9\xf6\xfc\xda\xf6\xfc\xd9\xf6\xfb\xda"""+\ +"""\xf5\xfb\xda\xf5\xfb\xda\xf6\xfd\xda\xf7\xfd\xda\xf7\xfb\xda\xf6\xf8\xdb\xf3\xfb\xdb\xf5\xfb\xdb\xf6\xfc\xda\xf7\xfc\xda\xf6\xfc\xd9\xf6\xff\xdf\xfc\xdf\xbc\xd9\xbe\x9c\xb7\xbd\x9b\xb6\xbc\x9c\xb5\xd1\xb0\xcb\xa7\x8c\xa2\x99\x7d\x94\x8as\x86wariXfSGOVRR\xcb\xca\xcb\xc4\xc4\xc4\x00\x00\x00\x7f\x7f\x7f\xff\xff\xff\xeb\xeb\xeb\xee\xee\xee\xef\xef\xef\xef\xef\xef"""+\ +"""\xf0\xf0\xf0\xf0\xf0\xf0\xef\xef\xef\xf0\xf0\xf0\xef\xef\xef\xef\xef\xef\xf2\xef\xf1\xd2\xe0\xd3\xe0\x7f\xcf\xd9$\xba\xd41\xb8\xd14\xb6\xcf1\xb4\xd1-\xb4\xd9/\xbc\xd71\xba\xd32\xb7\xd31\xb7\xca-\xb0\xc5+\xaa\xe5)\xc8\xff*\xe6\xfe)\xe1\xfe)\xe2\xfe+\xe4\xfe*\xe3\xff*\xe3\xff,\xe4\xfe+\xe4\xfe%\xde\xfe$\xdd\xfe%\xde\xfa\x1d\xd5\xfe"""+\ +"""\x1f\xda\xfc\x1d\xd6\xfc\x1d\xd6\xfc\x1d\xd6\xfd\x1e\xd7\xfc\x1d\xd6\xfd\x1f\xd8\xfb\x1f\xd5\xf7 \xd2\xf5\x22\xd1\xf6%\xd3\xf96\xd8\xf03\xd0\xf1,\xcf\xf23\xd1\xf47\xd3\xfdD\xdd\xda9\xbf\xbb\x13\x9e\xc8\x1d\xac\xd2\x1f\xb4\xc8(\xad\xb4D\xa0\xb7@\xa2\xba5\xa3\xc56\xac\xc36\xaa\xc25\xa9\xd12\xb6\xca1\xaf\xcd.\xb1\xc1+\xa7\xc4'\xa9\xc9&"""+\ +"""\xac\xc5&\xa9\xd0$\xb2\xbe%\xa3\xc4%\xa8\xd1#\xb3\xc2$\xa6\xc0$\xa4\xc5#\xa8\xd2\x22\xb4\xc3$\xa7\xd2\x22\xb3\xc5\x22\xa9\xc6(\xaa\xcc,\xb0\xd4,\xb8\xcb-\xaf\xbd&\xa3\xaf&\x97\xa7!\x90\x91\x1d\x7c\x7d\x1alm\x16^O\x0bC\xa2\x90\x9f\xec\xee\xeb\x8a\x89\x89\x00\x00\x00\x87\x87\x87\xff\xff\xff\xec\xec\xec\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf0"""+\ +"""\xf0\xf0\xf0\xf0\xf0\xf0\xef\xef\xef\xf0\xf0\xf0\xef\xef\xef\xef\xef\xef\xf2\xf1\xf2\xd2\xd2\xd1\xdf\xd7\xdd\xf0\xdf\xed\xef\xe0\xec\xe4\xd4\xe1\xe1\xd2\xde\xed\xdc\xea\xf2\xe2\xef\xe1\xd3\xde\xe4\xd5\xe1\xe7\xd6\xe4\xf5\xe7\xf3\xe8\xd9\xe5\xe7\xd8\xe4\xe8\xd7\xe5\xe8\xd7\xe5\xeb\xd9\xe7\xe6\xd5\xe3\xe6\xd5\xe3\xe8\xd7\xe4\xe4\xd2\xe0\xe6\xd5\xe2\xf8\xe8\xf5\xfd\xec\xfa\xfc\xeb\xf9\xfd\xed\xfb\xfd"""+\ +"""\xed\xfa\xfe\xee\xfb\xfb\xeb\xf8\xfd\xec\xfa\xf7\xe7\xf4\xfd\xec\xfa\xef\xde\xec\xe9\xd8\xe6\xe6\xd6\xe3\xe3\xd3\xe0\xe2\xd3\xe0\xee\xdd\xeb\xf1\xe0\xee\xf1\xe3\xef\xf5\xe7\xf3\xf5\xe7\xf3\xff\xf1\xfd\xdc\xd0\xda\xbc\xb0\xba\xcb\xbe\xc9\xd2\xc6\xd0\xd7\xc2\xd4\xd8\xab\xd0\xe3\xb0\xda\xeb\xb9\xe3\xf0\xbe\xe8\xf2\xc3\xea\xf7\xc9\xef\xf9\xcd\xf2\xfc\xd1\xf5\xfd\xd4\xf6\xfe\xd7\xf7\xfe\xdb\xfa\xfe\xdc"""+\ +"""\xfa\xfd\xdf\xf9\xfd\xe2\xfa\xfe\xe6\xfb\xfd\xe7\xf9\xfb\xe7\xf7\xfd\xe9\xfa\xfc\xec\xf9\xfb\xec\xf8\xfb\xed\xf8\xfc\xed\xfa\xfc\xed\xf9\xfb\xee\xf9\xf9\xec\xf7\xfa\xeb\xf7\xfb\xeb\xf9\xf9\xe9\xf7\xe6\xd8\xe3\xd1\xc3\xce\xba\xaf\xb8\xa5\x9b\xa3\x91\x88\x8fskq\x92\x8d\x91\xcc\xce\xcc\xe9\xe8\xe8MMM\x00\x00\x00\x89\x89\x89\xff\xff\xff\xec\xec\xec\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf0"""+\ +"""\xef\xef\xef\xef\xef\xef\xee\xee\xee\xef\xef\xef\xee\xee\xee\xef\xef\xef\xed\xed\xed\xe5\xe4\xe4\xef\xf0\xef\xde\xe1\xde\xe2\xe3\xe2\xdd\xe1\xdd\xd8\xdc\xd8\xe4\xe6\xe3\xe5\xe7\xe5\xdd\xe0\xdd\xdb\xde\xdb\xdd\xe1\xdd\xed\xed\xed\xde\xe1\xde\xdc\xdf\xdb\xdc\xe0\xdc\xdb\xdf\xdb\xdd\xe0\xdd\xde\xe2\xde\xdb\xdf\xdb\xda\xde\xda\xd8\xdc\xd8\xd9\xdd\xd9\xf5\xf6\xf5\xff\xff\xff\xfe\xfe\xfe\xfe\xff\xff\xfe"""+\ +"""\xfe\xfe\xff\xff\xff\xee\xee\xee\xfa\xfa\xfa\xcb\xcd\xca\xfc\xfc\xfc\xe3\xe6\xe2\xd6\xd9\xd5\xce\xd2\xce\xce\xd1\xcd\xd6\xd9\xd6\xf4\xf8\xf4\xf2\xf6\xf3\xe9\xed\xe9\xf7\xfb\xf7\xf6\xf9\xf6\xff\xff\xff\xdd\xde\xdd\xbd\xc0\xbd\xcc\xcd\xcc\xd2\xe0\xd4\xd8\xa7\xd0\xd29\xb8\xd8.\xba\xbe,\xa4\xca8\xb0\xdbD\xc0\xc3I\xad\xcfT\xb9\xd5_\xc0\xd0f\xbd\xcal\xb8\xc7s\xb7\xd2\x85"""+\ +"""\xc3\xd3\x91\xc6\xcb\x96\xc1\xc1\x9a\xb9\xda\xb8\xd3\xff\xea\xff\xfe\xf8\xfe\xfe\xff\xfe\xff\xfe\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xfe\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xff\xff\xff\xf9\xfb\xf9\xe3\xe7\xe3\xcd\xd0\xcd\xb7\xba\xb7\xa1\xa4\xa2\x86\x89\x87\x86\x89\x87\xc1\xc2\xc1\xc7\xc6\xc6\xcf\xcf\xcf\x15\x15\x15\x05\x05\x05\x89\x89\x89\xfd\xfd\xfe\xeb\xeb\xeb\xee\xee\xee\xef\xef\xef\xef\xef\xef"""+\ +"""\xee\xee\xee\xee\xee\xee\xed\xed\xed\xee\xee\xee\xed\xed\xed\xee\xee\xee\xed\xec\xec\xe6\xe5\xe5\xf4\xf4\xf4\xf9\xf8\xf9\xee\xed\xee\xff\xff\xff\xff\xff\xff\xf7\xf6\xf7\xef\xee\xee\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xf0\xef\xef\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfd\xfe\xfd\xfc\xfd\xfe\xfd\xfe\xfe\xfd\xfe\xfd"""+\ +"""\xfc\xfd\xff\xff\xff\xe6\xe5\xe6\xd5\xd4\xd4\xd0\xce\xcf\xde\xe1\xe0\xd2\xd7\xd7\xf2\xf3\xf4\xf9\xf8\xf9\xea\xeb\xec\xc8\xcd\xcc\xdf\xe1\xe1\xd6\xd5\xd5\xe7\xe7\xe7\xf6\xf6\xf6\xf5\xf5\xf5\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xca\xcb\xd1\xd4\xd2\xd8\xcc\xd6\xc2\x95\xba\xba\x8f\xb2\xc4\x9d\xbd\xcb\xa4\xc4\xc6\x9f\xbf\xcc\xaa\xc5\xc7\xa6\xc0\xd3\xb4\xcd\xce\xb1\xc8\xd2\xb8\xcd\xcf\xba\xcb\xcc\xb7"""+\ +"""\xc8\xcd\xba\xc9\xd2\xc3\xce\xce\xc3\xcc\xdb\xd0\xd8\xe1\xd8\xde\xda\xd6\xd9\xdf\xde\xdf\xd5\xd3\xd4\xea\xe9\xe9\xff\xff\xff\xfe\xfd\xfe\xfd\xfd\xfd\xfa\xf9\xfa\xfa\xf9\xfa\xfb\xfa\xfb\xed\xec\xed\xd7\xd6\xd7\xc2\xc1\xc2\xad\xac\xad\x98\x97\x98\x83\x83\x83\xb8\xb8\xb8\xb2\xb1\xb1\xe1\xe2\xe2\x98\x98\x98\x00\x00\x00\x0f\x0f\x0f\x8a\x8a\x8a\xfc\xfc\xfc\xea\xea\xea\xed\xed\xed\xee\xee\xee\xee\xee\xee"""+\ +"""\xef\xef\xef\xef\xef\xef\xee\xee\xee\xef\xef\xef\xee\xee\xee\xee\xee\xee\xf0\xf0\xf0\xd6\xd4\xd4\xe8\xe8\xe8\xfa\xfa\xfa\xed\xed\xed\xff\xff\xff\xfe\xfe\xfe\xf6\xf6\xf6\xee\xee\xee\xff\xff\xff\xfa\xfa\xfa\xfd\xfd\xfd\xf0\xef\xef\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd"""+\ +"""\xfd\xfd\xff\xff\xff\xe3\xe2\xe2\xcc\xcc\xcc\xcf\xce\xce\x9d\xa6\xa3\x99\xa4\xa2\xcf\xd5\xd5\xed\xed\xed\xc4\xca\xc9\x8c\x99\x96\xaa\xb1\xaf\xbe\xbc\xbc\xe7\xe6\xe6\xf6\xf6\xf6\xf5\xf5\xf5\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd2\xd1\xd2\xd6\xd8\xd6\xc9\xd3\xcb\xce\xd7\xcf\xd8\xdf\xd9\xd0\xd7\xd1\xdc\xe3\xdd\xe8\xef\xe9\xec\xf2\xec\xe1\xe7\xe2\xd9\xdf\xda\xe2\xe7\xe3\xe4\xe7\xe4\xe0\xe4"""+\ +"""\xe1\xdf\xe3\xe0\xe6\xe8\xe6\xd9\xdb\xd9\xb5\xb6\xb4\xb2\xb3\xb1\xb4\xb4\xb3\xb5\xb4\xb4\xad\xac\xab\xc7\xc6\xc6\xc3\xc3\xc3\xbc\xbc\xbc\xc8\xc8\xc7\xeb\xeb\xeb\xe7\xe7\xe7\xe5\xe5\xe5\xd6\xd5\xd5\xc0\xc0\xc0\xaa\xa9\xa9\x92\x91\x91ppp\xa6\xa7\xa6\xc4\xc3\xc3\xb8\xb9\xb9\xf6\xf1\xf0MCE\x04\x01\x04\x13\x13\x13\x8d\x8d\x8d\xfd\xfd\xfd\xeb\xeb\xeb\xee\xee\xee\xef\xef\xef\xef\xef\xef"""+\ +"""\xee\xee\xee\xee\xee\xee\xed\xed\xed\xee\xee\xee\xed\xed\xed\xed\xed\xed\xf0\xf0\xf0\xd2\xd1\xd1\xe6\xe5\xe5\xfc\xfc\xfc\xee\xee\xee\xff\xff\xff\xff\xff\xff\xf7\xf7\xf7\xef\xef\xef\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xf0\xf0\xf0\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfd\xfe\xfe\xfe\xfc"""+\ +"""\xfc\xfc\xff\xff\xff\xe2\xe2\xe2\xcc\xcc\xcb\xd8\xd7\xd7\xed\xee\xee\xe0\xe3\xe2\xf7\xf9\xf8\xf9\xf8\xf8\xf0\xf1\xf0\xd6\xda\xd9\xee\xef\xee\xdb\xda\xda\xea\xea\xea\xf7\xf7\xf7\xf6\xf6\xf6\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd1\xd1\xd1\xde\xdd\xde\xce\xca\xcd\xa5\xa1\xa3\xbe\xb9\xbb\xe6\xe3\xe4\xe4\xe2\xe4\xe3\xe1\xe2\xe3\xe1\xe3\xe3\xe1\xe2\xeb\xea\xeb\xfb\xf9\xfa\xca\xc9\xc9\xdd\xdc"""+\ +"""\xdd\xf8\xf8\xf8\xbb\xba\xba\xe6\xe5\xe5\xe4\xe1\xe2\xaa\xa6\xa7\xef\xec\xed\xd2\xd1\xd1\xb5\xb3\xb3\xf9\xf7\xf8\xc0\xbd\xbe\xc1\xbe\xbf\xf8\xf5\xf6\xbb\xb9\xb9\xdb\xda\xda\xed\xed\xed\xa1\xa1\xa0\xb8\xb8\xb8\xaf\xaf\xae\x88\x87\x87\x9c\x9c\x9c\xcd\xcc\xcc\xc3\xc3\xc3\xdf\xdd\xdd\xd8\xc9\xc8\x15\x15\x14\x13\x13\x13\x16\x15\x16\x8f\x8f\x8f\xfb\xfb\xfb\xea\xea\xea\xed\xed\xed\xee\xee\xee\xee\xee\xee"""+\ +"""\xef\xef\xef\xef\xef\xef\xee\xee\xee\xef\xef\xef\xee\xee\xee\xee\xee\xee\xf2\xf2\xf2\xce\xcd\xcd\xe2\xe1\xe1\xfa\xfa\xfa\xeb\xec\xec\xff\xff\xff\xff\xff\xff\xf5\xf5\xf5\xe2\xe2\xe1\xe5\xe5\xe5\xd1\xd1\xd0\xe3\xe2\xe2\xe7\xe6\xe6\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"""+\ +"""\xfe\xfe\xff\xff\xff\xe2\xe1\xe1\xcd\xcc\xcc\xcb\xca\xc9\xe4\xe2\xe2\xe5\xe3\xe3\xdd\xda\xda\xd8\xd8\xd8\xd6\xd5\xd5\xd9\xd9\xd8\xd7\xd6\xd6\xd3\xd3\xd3\xe3\xe3\xe3\xf9\xf9\xf9\xf6\xf6\xf6\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd3\xd3\xd3\xd3\xd5\xd5\xc3\xcb\xc8\xb3\xba\xb7\xc3\xcc\xc8\xcf\xd5\xd2\xd2\xd1\xd1\xb2\xb1\xb1\xb6\xb5\xb5\xd6\xd5\xd5\xe4\xe4\xe4\xf2\xf2\xf2\xd0\xd0\xd0\xe0\xe0"""+\ +"""\xe0\xf1\xef\xf0\xcc\xc8\xc9\xe8\xe6\xe6\xe2\xeb\xe7\xcf\xda\xd5\xe6\xf0\xec\xc7\xcb\xc9\xc2\xc9\xc6\xe9\xf3\xee\xd1\xda\xd6\xd0\xdb\xd6\xe5\xf1\xec\xc2\xc9\xc6\xe1\xe0\xe0\xe1\xe1\xe1\xad\xac\xac\xb5\xb5\xb5\x9f\x9e\x9e\x8f\x91\x90\xd2\xd2\xd2\xb7\xb6\xb6\xcb\xcb\xcb\xef\xdd\xdd\x9c\x99\x98\x00\x00\x00 \x1e\x1e\x1e\x92\x92\x92\xfc\xfc\xfc\xeb\xeb\xeb\xee\xee\xee\xef\xef\xef\xef\xef\xef"""+\ +"""\xee\xee\xee\xee\xee\xee\xed\xed\xed\xee\xee\xee\xed\xed\xed\xee\xee\xee\xed\xed\xed\xe0\xdd\xde\xe9\xef\xea\xec\xd1\xe5\xe1\xc6\xda\xe6\xec\xe7\xdf\xde\xdf\xe4\xe3\xe3\xdb\xdb\xdb\xd1\xd1\xd1\xbe\xbd\xbd\xd4\xd4\xd4\xdc\xdc\xdc\xca\xc9\xc9\xcc\xcb\xcb\xc9\xc8\xc8\xcb\xca\xca\xcd\xcc\xcc\xd2\xd2\xd2\xcb\xcb\xcb\xcc\xcb\xcb\xc8\xc8\xc7\xca\xca\xc9\xd0\xd0\xcf\xd3\xd2\xd2\xd2\xd1\xd1\xd3\xd3\xd3\xcc"""+\ +"""\xcb\xcb\xdb\xd9\xd9\xd5\xdc\xda\xb4\xc2\xbd\xcc\xd1\xcf\xb1\xca\xc2\xb1\xca\xc1\xae\xc4\xbc\xc5\xc5\xc4\xc1\xc0\xc0\xc2\xc1\xc1\xc3\xc2\xc2\xbf\xbe\xbe\xe2\xe2\xe2\xf9\xf9\xf9\xf6\xf6\xf6\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd4\xd3\xd3\xd1\xd6\xd4\xba\xce\xc7\xd0\xe5\xdd\xd3\xea\xe1\xc6\xd6\xcf\xe1\xe0\xe0\xb5\xb4\xb4\xc1\xc0\xc0\xe2\xe2\xe2\xdc\xdc\xdc\xed\xed\xec\xdb\xdb\xda\xe5\xe4"""+\ +"""\xe4\xde\xe8\xe3\xd5\xe3\xdd\xda\xe8\xe2\xcc\xe3\xda\xbd\xce\xc7\xc5\xdb\xd2\xc2\xd6\xce\xc9\xde\xd5\xcd\xe6\xdd\xd0\xe6\xde\xde\xe8\xe4\xde\xe8\xe4\xd4\xda\xd8\xe6\xe5\xe5\xd7\xd7\xd7\xb6\xb6\xb6\xaf\xae\xae\x97\x97\x97\xcb\xcb\xcb\xba\xb9\xb9\xb1\xb1\xb1\xcb\xc8\xc8\xf3\xea\xeaSUU\x01\x01\x01%%%$$$\x94\x94\x94\xfb\xfb\xfb\xea\xea\xea\xed\xed\xed\xee\xee\xee\xee\xee\xee"""+\ +"""\xee\xee\xee\xee\xee\xee\xed\xed\xed\xee\xee\xee\xed\xed\xed\xee\xee\xee\xec\xec\xec\xe7\xe5\xe6\xf5\xfe\xf7\xf6\xcc\xeb\xee\xc6\xe5\xdb\xe2\xdb\xce\xca\xcb\xf4\xf7\xf7\xb4\xb4\xb4\xb1\xb1\xb1\xc3\xc3\xc3\xda\xda\xda\xdf\xde\xde\x9c\x9a\x9a\xab\xaa\xaa\xab\xaa\xa9\xaa\xa9\xa8\xa5\xa4\xa3\xaf\xae\xad\xaa\xa9\xa8\xaf\xad\xad\xa8\xa6\xa6\xa5\xa4\xa4\xa3\xa2\xa1\xab\xaa\xa9\xab\xaa\xa9\xb3\xb2\xb2\xb6"""+\ +"""\xb4\xb4\xb9\xba\xb8\xd3\xc8\xcf\xb3\xa1\xab\xd7\xd0\xd4\xce\xa8\xc1\xce\xab\xc2\xcb\xab\xc0\xd0\xcf\xcf\xcd\xcd\xcc\xce\xcd\xcd\xcc\xcb\xcb\xd5\xd5\xd5\xe9\xe9\xe9\xf6\xf6\xf6\xf5\xf5\xf5\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd2\xd2\xd2\xd3\xd5\xd4\xcc\xd2\xd0\xd1\xd7\xd5\xd7\xdd\xdb\xd9\xdc\xdb\xe6\xe5\xe5\xe0\xdf\xdf\xe4\xe4\xe4\xeb\xeb\xeb\xed\xed\xed\xf1\xf0\xf0\xe6\xe6\xe6\xeb\xeb"""+\ +"""\xeb\xe5\xec\xe9\xe3\xec\xe8\xe3\xeb\xe8\xe3\xe9\xe7\xd6\xd9\xd8\xe0\xe5\xe3\xe8\xf0\xec\xe5\xec\xe9\xe4\xeb\xe8\xe3\xe9\xe7\xec\xea\xeb\xf0\xed\xee\xe9\xe7\xe8\xe6\xe6\xe6\xd3\xd3\xd3\xba\xba\xba\xa4\xa4\xa4\xc2\xc2\xc2\xdb\xda\xda\xb1\xb1\xb1\xc9\xc9\xc9\xdc\xdc\xdc\xd3\xd5\xd5\x18\x18\x18\x11\x11\x11&%%$$$\x97\x97\x97\xfa\xfa\xfa\xeb\xeb\xeb\xed\xed\xed\xee\xee\xee\xee\xee\xee"""+\ +"""\xee\xee\xee\xee\xee\xee\xed\xed\xed\xee\xee\xee\xed\xed\xed\xed\xed\xed\xef\xee\xee\xd9\xd6\xd8\xe6\xed\xe7\xd2\xad\xcb\xee\xb8\xd4\xf9\x8a\x7c\xf7wp\xff\xef\xef\xc4\xc7\xc7\xc0\xbf\xbf\xe1\xe1\xe1\xf0\xf1\xf1\xe8\xe8\xe8\xb2\xb1\xb0\xb2\xb1\xb1\xb5\xb4\xb4\xb4\xb3\xb3\xaa\xa9\xa9\xaf\xae\xae\xb2\xb1\xb0\xbb\xba\xba\xb8\xb7\xb6\xb3\xb2\xb1\xb2\xb0\xb0\xb2\xb2\xb1\xb2\xb1\xb1\xb7\xb6\xb6\xcb"""+\ +"""\xca\xca\xf4\xf6\xf4\xd5\xcb\xd2\xb2\xa0\xac\xd5\xce\xd3\xc1\xa0\xb9\xc1\xa1\xb9\xbe\xa2\xb7\xce\xcd\xce\xcb\xcc\xcb\xcc\xcc\xcc\xd0\xd0\xd0\xe6\xe5\xe5\xeb\xeb\xeb\xf7\xf7\xf7\xf6\xf6\xf6\xff\xff\xff\xdc\xdc\xdc\xbd\xbd\xbd\xcc\xcc\xcc\xd2\xd2\xd2\xda\xda\xda\xd9\xd8\xd9\xdb\xda\xdb\xe0\xdf\xdf\xeb\xea\xea\xe9\xe9\xe9\xef\xef\xef\xf1\xf1\xf1\xf1\xf1\xf1\xef\xef\xef\xf8\xf8\xf8\xff\xff\xff\xfe\xfe"""+\ +"""\xfe\xfe\xff\xfe\xff\xfe\xff\xff\xfe\xff\xff\xff\xff\xff\xfe\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xf4\xf4\xf4\xdf\xdf\xdf\xc5\xc6\xc6\xbe\xbf\xbf\xe8\xe7\xe7\xd9\xd8\xd8\xbd\xbd\xbd\xbe\xbe\xbe\xe7\xe7\xe7\x9b\x9b\x9b\x00\x00\x00\x1d\x1d\x1d((('''\x99\x99\x99\xfa\xfa\xfa\xeb\xeb\xeb\xed\xed\xed\xee\xee\xee\xee\xee\xee"""+\ +"""\xed\xed\xed\xed\xed\xed\xec\xec\xec\xed\xed\xed\xec\xec\xec\xec\xec\xec\xf0\xf0\xf0\xd0\xcd\xce\xdd\xe4\xdd\xcc\xa6\xc4\xf0\xbc\xd9\xf6\x90\x83\xf2mf\xf7\xe6\xe4\xde\xe2\xe2\xce\xcd\xcd\xc6\xc5\xc5\xe5\xe5\xe5\xdc\xdc\xdc\x9d\x9c\x9b\xa0\x9e\x9e\xa9\xa8\xa7\xa4\xa3\xa3\xae\xad\xad\xa8\xa7\xa7\xa6\xa5\xa4\xae\xac\xac\xa6\xa5\xa5\xa4\xa3\xa3\xb3\xb2\xb2\xb2\xb1\xb1\xb2\xb1\xb1\xb0\xaf\xaf\xb6"""+\ +"""\xb5\xb4\xfc\xfe\xfd\xe1\xd7\xde\xb8\xa5\xb2\xd3\xce\xd2\xc3\xa5\xbb\xca\xac\xc3\xc9\xab\xc0\xd2\xcd\xcf\xcf\xcb\xcc\xca\xca\xca\xe5\xe5\xe5\xf4\xf4\xf4\xe8\xe8\xe8\xf7\xf7\xf7\xf6\xf6\xf6\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd3\xd3\xd3\xd6\xd6\xd6\xbe\xbe\xbe\xc1\xc0\xc0\xc5\xc4\xc4\xc2\xc2\xc2\xc8\xc8\xc8\xcd\xcc\xcc\xcc\xcc\xcb\xca\xca\xc9\xc6\xc5\xc5\xdc\xdc\xdc\xf1\xf1\xf1\xed\xed"""+\ +"""\xed\xeb\xeb\xeb\xf2\xf2\xf2\xe7\xe6\xe6\xd3\xd3\xd3\xd9\xd8\xd8\xd4\xd4\xd4\xd6\xd6\xd6\xd6\xd5\xd5\xdc\xdb\xdb\xdb\xdb\xdb\xd7\xd7\xd7\xda\xda\xda\xf1\xf1\xf1\xdc\xdb\xdb\xc4\xc3\xc3\xb4\xb4\xb4\xdd\xdd\xdd\xd7\xd6\xd6\xd1\xd1\xd1\x96\x95\x95\xa9\xa9\xa9\xe8\xe8\xe8PPP\x02\x02\x02###.---,,\x9b\x9b\x9b\xf8\xf8\xf8\xea\xea\xea\xec\xec\xec\xed\xed\xed\xed\xed\xed\xee\xee\xee\xee\xee\xee\xed\xed\xed\xee\xee\xee\xed\xed\xed\xed\xed\xed\xf1\xf1\xf1\xcd\xca\xcb\xdc\xe4\xdd\xd0\xa6\xc4\xe6\xc1\xdf\xf2\xfa\xf4\xf2\xf1\xf2\xea\xed\xed\xe4\xe3\xe3\xf0\xf0\xf0\xd9\xd8\xd8\xed\xed\xed\xda\xda\xda\xb7\xb6\xb6\xb7\xb6\xb5\xba\xb9\xb8\xb5\xb4\xb4\xbe\xbd\xbd\xbf\xbe\xbe\xbb\xb9\xb9\xb8\xb7\xb7\xbf\xbe\xbe\xb3\xb2\xb1\xc6\xc5\xc5\xdf\xde\xde\xdf\xdf\xdf\xdd\xdc\xdc\xda\xda\xda\xf2\xf0\xf1\xd4\xd9\xd6\xb6\xc2\xbb\xda\xd9\xd9\xce\xcb\xca\xdb\xda\xd8\xc3\xd4\xca\xc0\xd4\xca\xbe\xd0\xc7\xd0\xd1\xd0\xd9\xd8\xd8\xdc\xdc\xdc\xe6\xe6\xe6\xf8\xf8\xf8\xf6\xf6\xf6\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd2\xd2\xd2\xdc\xdc\xdc\xcf\xd0\xcf\xbe\xbe\xbd\xce\xce\xcd\xe2\xe2\xe1\xef\xef\xef\xf7\xf7\xf7\xfb\xfb\xfb\xed\xed\xec\xe8\xe8\xe8\xf4\xf4\xf4\xd4\xd4\xd4\xde\xde\xde\xee\xee\xee\xcd\xcd\xcc\xde\xdf\xde\xc6\xc6\xc5\xa0\xa0\x9f\xce\xce\xcd\xbb\xbb\xba\xa5\xa6\xa4\xde\xdf\xdd\xb7\xb7\xb6\xb4\xb3\xb2\xdb\xdb\xdb\xca\xc9\xc9\xc7\xc6\xc6\xbb\xbb\xbb\xd3\xd3\xd3\xd1\xd0\xd0\xc5\xc4\xc4\xa8\xa7\xa7\x94\x93\x93\xcf\xce\xce\xdd\xdd\xdd\x1a\x1a\x1a\x10\x10\x10&&&444988\x9d\x9d\x9d\xf9\xf9\xf9\xeb\xeb\xeb\xed\xed\xed\xee\xee\xee\xee\xee\xee\xed\xed\xed\xed\xed\xed\xec\xec\xec\xed\xed\xed\xec\xec\xec\xed\xed\xed\xed\xed\xed\xdf\xdc\xde\xe9\xf1\xea\xd0\xa7\xc5\xef\xc6\xe3\xfe\xff\xff\xfd\xfc\xfd\xf5\xf4\xf3\xed\xed\xed\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xe1\xe1\xe1\xa7\xa6\xa5\xb9\xb8\xb8\xaf\xae\xae\xb2\xb1\xb1\xba\xb9\xb9\xb9\xb8\xb8\xac\xab\xaa\xb6\xb5\xb5\xb9\xb8\xb8\xb2\xb0\xb0\xa9\xa8\xa8\xb1\xb0\xaf\xc2\xc1\xc0\xdc\xdc\xdc\xd5\xd4\xd4\xee\xee\xed\xdd\xd9\xde\xb2\xac\xb4\xdd\xdd\xdc\xd9\xd9\xd8\xd5\xd4\xd5\xc1\xb5\xc5\xc1\xb4\xc5\xbe\xb2\xc2\xce\xcc\xce\xce\xce\xce\xce\xcd\xcd\xe6\xe6\xe6\xf6\xf6\xf6\xf5\xf5\xf5\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd1\xd1\xd1\xd8\xd7\xd8\xcc\xc8\xcb\xa0\x9c\x9e\xba\xb5\xb8\xdb\xd8\xda\xcf\xce\xce\xb9\xb9\xb9\xb9\xb8\xb8\xd2\xd2\xd1\xe9\xe9\xe9\xf8\xf8\xf8\xc7\xc6\xc6\xdd\xdc\xdc\xf6\xf8\xf5\xb9\xb7\xb8\xe8\xe3\xe7\xf4\xef\xf4\xc4\xbe\xc2\xf7\xf3\xf7\xd9\xd6\xd8\xc8\xc1\xc6\xff\xf8\xff\xcf\xc9\xce\xd1\xd0\xd0\xff\xff\xff\xb3\xb2\xb2\xb8\xb7\xb7\xd4\xd4\xd4\xde\xdd\xdd\xc9\xc8\xc8\xe8\xe7\xe7\xa7\xa6\xa6\xb9\xb8\xb8\xe0\xe0\xe0\x94\x93\x93\x00\x00\x00\x1d\x1d\x1d*)):::???\x9f\x9f\x9f\xf8\xf8\xf8\xea\xea\xea\xec\xec\xec\xed\xed\xed\xed\xed\xed\xee\xee\xee\xee\xee\xee\xed\xed\xed\xee\xee\xee\xed\xed\xed\xee\xee\xee\xec\xec\xec\xea\xe7\xe8\xf0\xf8\xf2\xcb\xa1\xbf\xf2\xcc\xe9\xd3\xd1\xca\xc2\xb7\xb8\xe7\xea\xeb\xf2\xf1\xf1\xfd\xfd\xfd\xf9\xf9\xf9\xff\xff\xff\xe2\xe2\xe2\xa7\xa6\xa6\xad\xac\xac\xb5\xb4\xb4\xb7\xb6\xb6\xb0\xae\xae\xba\xb9\xb9\xaf\xae\xae\xb5\xb4\xb4\xbc\xbb\xbb\xb5\xb4\xb3\xb1\xb0\xaf\xb3\xb3\xb2\xb7\xb6\xb5\xc2\xc1\xc1\xb5\xb4\xb3\xc0\xc2\xc0\xcd\xbf\xc6\xb7\x9c\xaa\xd7\xd8\xd7\xd2\xd3\xd2\xd3\xcd\xcf\xc7\x9d\xb4\xc7\x9b\xb3\xc3\x9b\xb1\xcb\xc6\xc8\xcb\xcb\xca\xe0\xdf\xdf\xec\xec\xec\xf6\xf6\xf6\xf6\xf6\xf6\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd3\xd4\xd3\xd7\xcf\xd6\xc8\xa9\xc6\xe6\xc5\xe4\xed\xc9\xeb\xd7\xbf\xd5\xdf\xe0\xdf\xb5\xb4\xb4\xc0\xbf\xbf\xe2\xe2\xe2\xde\xdd\xdd\xed\xed\xed\xdc\xdc\xdb\xe5\xe5\xe5\xea\xe4\xe9\xe1\xcc\xdf\xe7\xc0\xe5\xde\xbd\xdb\xee\xc8\xeb\xd7\xb7\xd5\xc8\xae\xc5\xe9\xcc\xe7\xea\xce\xe8\xde\xc6\xdc\xe2\xe1\xe1\xea\xea\xea\xcc\xcb\xcb\xc5\xc5\xc5\xe5\xe5\xe5\xe6\xe5\xe5\xf3\xf3\xf3\xe8\xe8\xe8\xd8\xd8\xd8\xcc\xcc\xcc\xe4\xe4\xe4VVV\x00\x00\x00!!!,,,;;;>>>\xa2\xa3\xa3\xf8\xf8\xf8\xeb\xeb\xeb\xed\xed\xed\xee\xee\xee\xee\xee\xee\xed\xed\xed\xed\xed\xed\xec\xec\xec\xed\xed\xed\xec\xec\xec\xec\xec\xec\xed\xed\xed\xdc\xd9\xda\xe6\xee\xe7\xcb\xa5\xc4\xef\xb6\xd3\xf2wh\xee_X\xfd\xe8\xe7\xc6\xca\xcb\xa1\xa0\xa0\xac\xac\xac\xcf\xcf\xcf\xdf\xde\xde\xb4\xb3\xb3\xb3\xb2\xb2\xbc\xbb\xbb\xb1\xb0\xb0\xb3\xb2\xb1\xaa\xa9\xa9\xbd\xbc\xbb\xb6\xb5\xb4\xb3\xb2\xb2\xb3\xb2\xb2\xb2\xb0\xb0\xb4\xb3\xb3\xb2\xb1\xb1\xb4\xb3\xb2\xb9\xb8\xb8\xf9\xfa\xf9\xdc\xd3\xda\xb2\x9e\xae\xda\xda\xd9\xd5\xd4\xd4\xd3\xcf\xd1\xbd\xa1\xb9\xbd\xa0\xb9\xbb\xa0\xb6\xc9\xc6\xc8\xe2\xe3\xe2\xf2\xf2\xf2\xe6\xe5\xe5\xf6\xf6\xf6\xf5\xf5\xf5\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd2\xd3\xd2\xd5\xd0\xd5\xcc\xb6\xca\xd6\xc0\xd5\xde\xc6\xdd\xd6\xc5\xd4\xdd\xde\xdc\xc5\xc4\xc4\xcd\xcd\xcc\xe1\xe1\xe1\xe1\xe0\xe0\xec\xec\xec\xdd\xdd\xdc\xe5\xe4\xe4\xe9\xd2\xe7\xe9\xce\xe8\xe2\xca\xe1\xc7\xb9\xc5\xe0\xc8\xde\xec\xd2\xea\xe7\xcd\xe6\xe3\xdf\xe2\xeb\xed\xec\xdf\xdf\xde\xe2\xe2\xe2\xe8\xe7\xe7\xc4\xc4\xc4\xda\xda\xda\xda\xd9\xd9\xf1\xf0\xf0\xf6\xf6\xf6\xdc\xdc\xdc\xd3\xd5\xd5\xdd\xd6\xd6\xda\xcd\xcd\x1c\x1f\x1f\x10\x10\x0f%%%555????>>\xa5\xa5\xa5\xf7\xf7\xf7\xea\xea\xea\xec\xec\xec\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xec\xec\xec\xed\xed\xed\xec\xec\xec\xec\xec\xec\xf0\xf0\xf0\xce\xcb\xcc\xd9\xe1\xda\xcc\xa5\xc2\xef\xc0\xdd\xf7\x9f\x93\xf3\x7cv\xfe\xf0\xef\xc9\xcc\xcc\xbc\xbb\xbb\xe3\xe3\xe3\xe8\xe8\xe8\xe8\xe8\xe8\xaa\xa9\xa9\xba\xb9\xb9\xb6\xb5\xb5\xb7\xb6\xb6\xc4\xc3\xc2\xb4\xb3\xb3\xb4\xb3\xb2\xaf\xae\xae\xad\xac\xab\xb1\xb0\xb0\xb0\xaf\xaf\xb5\xb4\xb3\xac\xab\xaa\xab\xaa\xaa\xaa\xa9\xa9\xbf\xbf\xbe\xda\xd5\xd6\xc1\xb7\xba\xda\xdb\xdb\xd7\xd7\xd6\xd7\xd5\xd6\xd4\xc5\xca\xd3\xc4\xca\xd1\xc2\xc7\xce\xcc\xcc\xde\xde\xde\xe6\xe6\xe6\xe1\xe1\xe1\xf7\xf7\xf7\xf5\xf5\xf5\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd1\xd1\xd1\xd8\xd8\xd8\xe0\xe2\xe0\xe6\xe8\xe6\xea\xec\xeb\xf0\xf2\xf1\xf5\xf5\xf5\xfd\xfd\xfd\xfd\xfd\xfd\xfa\xfa\xfa\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfd\xfc\xfe\xfc\xfd\xfe\xfd\xff\xfe\xff\xfc\xfe\xfc\xfc\xfe\xfc\xfc\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfe\xfe\xfe\xee\xee\xee\xdf\xdf\xdf\xd6\xd5\xd5\xd4\xd3\xd3\xff\xff\xff\xec\xec\xec\xd9\xd9\xd9\xd1\xd0\xd0\xeb\xd9\xd8\xac\xab\xaa\x00\x00\x00\x1b\x17\x1a)))999DDDEDD\xa7\xa8\xa7\xf6\xf6\xf6\xea\xea\xea\xec\xec\xec\xed\xed\xed\xed\xed\xed\xee\xee\xee\xee\xee\xee\xed\xed\xed\xee\xee\xee\xed\xed\xed\xed\xed\xed\xf1\xf1\xf1\xcf\xcc\xcd\xdf\xe7\xe1\xe9\xc0\xde\xef\xc7\xe5\xff\xff\xff\xff\xfd\xfe\xfa\xfa\xfa\xe0\xdf\xdf\xc3\xc3\xc3\xd1\xd1\xd1\xeb\xeb\xeb\xe3\xe2\xe2\xaa\xa9\xa8\xb2\xb1\xb1\xad\xab\xab\xaf\xae\xae\xb6\xb5\xb5\xaa\xa9\xa8\xae\xad\xac\xb4\xb3\xb2\xb3\xb2\xb2\xb8\xb7\xb6\xbc\xbb\xbb\xbe\xbd\xbc\xc0\xbf\xbf\xb9\xb8\xb8\xb6\xb5\xb5\xc8\xc7\xc6\xdb\xdc\xdb\xf7\xf9\xf8\xfb\xfb\xfb\xfa\xfa\xfa\xfa\xfa\xfa\xf6\xf8\xf7\xf2\xf5\xf4\xf1\xf3\xf2\xf0\xef\xf0\xef\xee\xee\xea\xea\xea\xe8\xe8\xe8\xf7\xf7\xf7\xf6\xf6\xf6\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd3\xd3\xd3\xd8\xd8\xd8\xc2\xc1\xc1\xbf\xbe\xbe\xcd\xcc\xcc\xc7\xc7\xc7\xc8\xc7\xc7\xc9\xc9\xc8\xe7\xe7\xe7\xf5\xf5\xf5\xf7\xf7\xf7\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf8\xf7\xf8\xf9\xf9\xf9\xf8\xf8\xf8\xf8\xf8\xf8\xfb\xfb\xfb\xfa\xf9\xf9\xfa\xf9\xfa\xfa\xfa\xfa\xf9\xf9\xf9\xfa\xfa\xfa\xf9\xf8\xf9\xe4\xe5\xe4\xdd\xdc\xdc\xc3\xc2\xc1\xfa\xfa\xfa\xfd\xfd\xfd\xe4\xe3\xe3\xd6\xd9\xd9\xd1\xbe\xbe\xf5\xef\xeebcd\x00\x00\x00 \x10\x1d.0/?>>LLLRRR\xa9\xa9\xa9\xf7\xf7\xf7\xeb\xeb\xeb\xed\xed\xed\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xed\xed\xed\xee\xee\xee\xed\xed\xed\xed\xee\xee\xee\xee\xee\xdb\xd8\xd9\xea\xf1\xeb\xf4\xcc\xe9\xe6\xbe\xda\xf7\xff\xf8\xf5\xf3\xf4\xef\xed\xed\xe1\xe0\xe0\xe6\xe6\xe5\xc8\xc7\xc7\xe2\xe2\xe2\xe0\xe0\xe0\xe2\xe1\xe1\xdd\xdd\xdd\xe0\xe0\xe0\xe3\xe2\xe2\xdd\xdd\xdd\xdd\xdd\xdc\xdf\xdf\xdf\xda\xd9\xd9\xdf\xde\xde\xf9\xf8\xf9\xf8\xf8\xf8\xf8\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf9\xf9\xf9\xe5\xe5\xe4\xf6\xf7\xf6\xfb\xfa\xfb\xfa\xfa\xfa\xf9\xf9\xf9\xf3\xf4\xf4\xf0\xf4\xf1\xef\xf1\xee\xee\xef\xed\xee\xef\xee\xeb\xeb\xeb\xe7\xe7\xe7\xf6\xf6\xf6\xf5\xf5\xf5\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd2\xd2\xd2\xd7\xd7\xd7\xca\xc9\xc9\xcc\xcb\xcb\xd5\xd4\xd4\xd1\xd0\xd0\xe2\xe2\xe2\xea\xea\xe9\xf4\xf4\xf4\xe8\xe8\xe8\xde\xdd\xdd\xe9\xe9\xe8\xe4\xe3\xe3\xe5\xe4\xe4\xe7\xe6\xe6\xe6\xe5\xe5\xdc\xdb\xdb\xb7\xb6\xb5\xaf\xae\xad\xba\xb8\xb8\xb5\xb4\xb4\xad\xab\xab\xcb\xca\xca\xba\xb8\xb8\xb8\xb8\xb7\xe7\xe7\xe7\xd8\xd7\xd7\xce\xcd\xcd\xff\xff\xff\xf4\xf4\xf4\xde\xe1\xe1\xd2\xc5\xc5\xda\xcc\xcb\xe4\xe7\xe8\x22!!\x0c\x0b\x0c\x22!\x22111???PPP[[[\xab\xab\xab\xf7\xf7\xf7\xeb\xeb\xeb\xed\xed\xed\xee\xee\xee\xee\xee\xee\xed\xed\xed\xed\xed\xed\xec\xec\xec\xed\xed\xed\xed\xed\xed\xed\xed\xed\xeb\xeb\xeb\xe9\xe7\xe8\xee\xf6\xf1\xea\xc5\xdc\xe1\xbc\xd3\xf8\xfe\xf9\xf9\xf5\xf6\xeb\xeb\xeb\xe3\xe3\xe3\xf4\xf4\xf4\xf1\xf0\xf0\xf5\xf4\xf4\xdb\xdb\xdb\xbb\xba\xba\xc1\xc1\xc1\xbe\xbd\xbd\xbd\xbc\xbc\xc6\xc5\xc5\xd1\xd0\xd0\xd9\xd9\xd9\xd6\xd5\xd5\xd1\xd1\xd0\xd0\xcf\xcf\xd0\xcf\xcf\xd2\xd1\xd1\xd1\xd0\xd0\xd2\xd2\xd2\xd7\xd7\xd6\xd4\xd2\xd2\xca\xcf\xce\xb1\xbd\xbb\xda\xd9\xd9\xd6\xd5\xd5\xd3\xd5\xd4\xb6\xcb\xc2\xb4\xc1\xc0\xb3\xc2\xc1\xb4\xc3\xc2\xb3\xcc\xc3\xc4\xca\xc7\xe5\xe3\xe4\xf8\xf8\xf8\xf6\xf6\xf6\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd1\xd1\xd1\xdd\xdd\xdd\xcc\xce\xce\x9d\x9e\x9e\xb8\xb9\xb9\xe4\xe6\xe6\xde\xdd\xdd\xd8\xd8\xd8\xd6\xd5\xd5\xdd\xdc\xdc\xeb\xeb\xeb\xfa\xfb\xfb\xc6\xc5\xc5\xdb\xdb\xda\xf8\xf8\xf8\xb5\xb4\xb4\xe6\xe5\xe5\xe9\xe8\xe8\xae\xae\xad\xf4\xf7\xf6\xd2\xd4\xd4\xb5\xb7\xb6\xfd\xff\xff\xc9\xc9\xc9\xcf\xce\xce\xd8\xd7\xd7\xc6\xc5\xc5\xf9\xf9\xf9\xff\xff\xff\xed\xef\xef\xd8\xd3\xd3\xd0\xb9\xb8\xec\xef\xef\xb0\xaf\xaf\x00\x00\x00\x1c\x1c\x1c)))777GGGSRRXXX\xae\xae\xae\xf5\xf5\xf5\xea\xea\xea\xed\xed\xed\xec\xec\xec\xed\xed\xed\xed\xed\xed\xed\xed\xed\xee\xee\xee\xec\xec\xec\xed\xed\xed\xee\xee\xee\xee\xee\xee\xdb\xd9\xda\xf0\xf8\xf3\xe7\xc0\xd8\xea\xc2\xda\xe8\xf8\xf3\xda\xdf\xe0\xec\xec\xec\xf1\xf1\xf1\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xe2\xe1\xe1\x9c\x9b\x9b\xa5\xa4\xa3\xab\xaa\xaa\xac\xab\xab\xb3\xb2\xb1\xbf\xbe\xbe\xcd\xcc\xcc\xd5\xd4\xd4\xcb\xca\xca\xc6\xc5\xc5\xcf\xcf\xce\xcf\xce\xce\xc8\xc7\xc7\xc9\xc8\xc8\xc9\xc8\xc8\xdd\xdf\xdd\xd5\xc7\xcf\xb8\x9c\xac\xd9\xdb\xda\xd4\xd3\xd4\xd5\xd5\xd4\xcf\xcd\xcf\xce\xb6\xcd\xca\x9e\xb9\xcb\x9c\xb9\xc8\xae\xb7\xd6\xd2\xd2\xe7\xe8\xe8\xf6\xf6\xf6\xf5\xf5\xf5\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd2\xd3\xd3\xd4\xcf\xd0\xcb\xb6\xb9\xc8\xb3\xb6\xd6\xbe\xc1\xd4\xc3\xc6\xd5\xd6\xd5\xb2\xb1\xb1\xb9\xb8\xb8\xd9\xd9\xd9\xe2\xe2\xe1\xf0\xf0\xf0\xd5\xd5\xd4\xe3\xe3\xe2\xed\xed\xec\xd2\xd1\xd1\xe7\xe9\xe8\xe9\xec\xec\xd2\xc3\xc5\xeb\xd0\xd4\xe6\xcc\xcf\xdf\xc5\xc9\xe6\xcc\xcf\xda\xd4\xd4\xdc\xdd\xdd\xbe\xbd\xbd\xed\xed\xec\xff\xff\xff\xfb\xfb\xfb\xe5\xe6\xe6\xd4\xba\xb8\xd2\xcf\xcf\xf6\xf7\xf7ggg\x00\x00\x00! !,*+<<TWTWVV]\x5c\x5c\xb4\xb5\xb5\xf5\xf5\xf5\xec\xec\xec\xf2\xf2\xf2\xed\xed\xed\xee\xee\xee\xee\xee\xee\xed\xed\xed\xf1\xf1\xf1\xe2\xe2\xe2\xed\xed\xed\xee\xee\xee\xf0\xf0\xf0\xd3\xd1\xd1\xd1\xd7\xd2\xa9\x87\x9d\xe9\xb1\xc7\xfase\xf6RI\xf9\xde\xdc\xe0\xe2\xe5\x9b\x7d\x8e\x98\x83\x8f\xc1\xbc\xbe\xde\xdf\xde\xb2\xb0\xb0\xad\xac\xab\xb2\xb1\xb1\xaf\xae\xad\xb6\xb5\xb5\xb2\xb1\xb0\xac\xab\xab\xab\xaa\xaa\xb0\xae\xae\xb8\xb8\xb7\xb1\xb0\xb0\xb2\xb1\xb0\xbb\xbb\xba\xbd\xbc\xbc\xb6\xb5\xb5\xb4\xb5\xb4\xca\xc1\xc6\xb8\xa6\xb1\xd5\xd6\xd5\xd1\xd0\xd0\xd1\xd2\xd1\xcc\xc9\xca\xcb\xae\xbc\xc8\xae\xbc\xc8\xc8\xc9\xe3\xe7\xe6\xf2\xf2\xf2\xe7\xe7\xe7\xf7\xf7\xf7\xf6\xf6\xf6\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd3\xd3\xd3\xd6\xd5\xd5\xd6\xd0\xd1\xdb\xd5\xd6\xe0\xda\xdb\xe2\xdd\xde\xe9\xea\xea\xea\xea\xea\xee\xee\xee\xf0\xf0\xf0\xf1\xf1\xf1\xf5\xf5\xf5\xf1\xf1\xf1\xf3\xf2\xf2\xf5\xf5\xf5\xf0\xf0\xf0\xf4\xec\xed\xf2\xe7\xe8\xf2\xea\xeb\xf2\xeb\xec\xeb\xe7\xe8\xe3\xde\xde\xe4\xe3\xe3\xdb\xda\xda\xe8\xe8\xe7\xff\xff\xff\xfc\xfb\xfb\xff\xff\xff\xed\xde\xdd\xd7\xc0\xbf\xd2\xd6\xd7\xea\xea\xea\xb4\xb5\xb5\x01\x00\x01\x18\x14\x17%\x1e$4'2D@CVWVSRRhgg\xb6\xb6\xb6\xf6\xf6\xf6\xeb\xeb\xeb\xe2\xe2\xe2\xf1\xf1\xf1\xed\xed\xed\xed\xed\xed\xed\xed\xed\xf0\xf0\xf0\xc0\xc0\xc0\xe4\xe4\xe4\xef\xef\xef\xef\xef\xef\xd5\xd3\xd4\xc8\xcf\xca\xc1\x9b\xb1\xe6\xc1\xd8\xfb\xc9\xc0\xf4\xa5\xa1\xff\xfb\xfa\xc6\xbd\xc3\xa9\x98\xa1\xe6\xec\xe9\xe6\xe6\xe6\xe8\xe7\xe7\xac\xab\xab\xaa\xa8\xa8\xad\xac\xab\xbb\xba\xba\xb7\xb6\xb6\xb7\xb6\xb6\xb0\xaf\xae\xb1\xb0\xaf\xae\xad\xac\xb4\xb3\xb3\xbc\xbb\xbb\xae\xad\xad\xac\xab\xaa\xb6\xb5\xb5\xb3\xb2\xb2\xe1\xe1\xe0\xe5\xe5\xe4\xda\xda\xd9\xeb\xea\xea\xe8\xe7\xe7\xe8\xe7\xe7\xe4\xe4\xe3\xe1\xe3\xe2\xdf\xe0\xdf\xdf\xde\xde\xe1\xe0\xe0\xe2\xe2\xe2\xe6\xe6\xe6\xf8\xf8\xf8\xf6\xf6\xf6\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd2\xd2\xd2\xda\xda\xda\xd3\xd5\xd4\xd5\xd6\xd6\xdd\xdf\xdf\xe5\xe6\xe6\xe7\xe6\xe6\xea\xe9\xe9\xeb\xeb\xeb\xf0\xef\xef\xf3\xf3\xf3\xf0\xf0\xf0\xef\xef\xef\xf1\xf0\xf0\xee\xed\xed\xef\xef\xef\xee\xf0\xef\xf7\xf9\xf8\xf6\xf7\xf6\xf6\xf7\xf7\xf4\xf5\xf5\xe8\xea\xea\xe3\xe2\xe2\xef\xee\xee\xff\xff\xff\xfd\xfd\xfd\xfe\xff\xff\xfc\xf5\xf5\xe3\xc4\xc2\xd6\xd8\xd8\xd2\xd2\xd1\xf6\xf6\xf6lll\x00\x00\x00!!!,-,;<;IIIYYYYXXtss\xb8\xb8\xb8\xf7\xf7\xf7\xe2\xe2\xe2\xc0\xc0\xc0\xf0\xf0\xf0\xed\xed\xed\xed\xed\xed\xee\xee\xee\xeb\xeb\xeb\xef\xef\xef\xea\xea\xea\xee\xee\xee\xed\xec\xec\xe7\xe4\xe5\xd6\xde\xd9\xe7\xbc\xd6\xeb\xc1\xda\xff\xff\xff\xff\xfd\xfe\xfa\xf9\xfa\xdc\xd8\xdb\xcf\xc9\xcd\xd0\xcd\xcf\xe8\xe5\xe8\xe2\xdf\xe1\xb4\xb1\xb3\xb7\xb3\xb5\xb4\xb1\xb2\xb2\xae\xb0\xb9\xb6\xb8\xb7\xb4\xb6\xb8\xb5\xb7\xb7\xb4\xb5\xb3\xb0\xb2\xb4\xb0\xb2\xbe\xba\xbc\xb9\xb5\xb7\xb2\xae\xb0\xb1\xae\xb0\xb6\xb2\xb4\xe0\xdd\xdf\xe8\xe7\xe8\xfb\xfb\xfb\xff\xff\xff\xfe\xfe\xfe\xff\xfe\xff\xfd\xfb\xfd\xfa\xf7\xfa\xf8\xf5\xf8\xf7\xf5\xf7\xf7\xf4\xf6\xf2\xef\xf1\xe8\xe6\xe8\xf6\xf4\xf6\xf5\xf3\xf5\xff\xfd\xff\xdc\xdb\xdc\xbd\xbd\xbd\xcc\xcc\xcc\xd3\xd3\xd3\xd5\xd5\xd5\xbf\xbe\xbe\xc2\xc1\xc1\xca\xc9\xc9\xc3\xc2\xc2\xcb\xca\xca\xcd\xcc\xcc\xce\xcd\xcd\xca\xca\xc9\xcf\xcf\xcf\xcf\xce\xce\xd0\xd0\xd0\xd2\xd1\xd1\xd0\xcf\xcf\xd2\xd2\xd2\xc6\xc5\xc5\xbe\xbd\xbd\xc7\xc6\xc6\xbf\xbd\xbd\xcd\xcd\xcd\xde\xdd\xdc\xe5\xe4\xe4\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xf4\xd2\xd1\xde\xd7\xd7\xd4\xd6\xd6\xda\xda\xda\xe8\xe8\xe8))(\x0b\x0e\x0c%(%374AGBQSQddd\x5c[[kjj\xbc\xbc\xbc\xf5\xf5\xf5\xe9\xe9\xe9\xef\xef\xef\xeb\xeb\xeb\xee\xee\xee\xee\xee\xee\xed\xed\xed\xef\xef\xef\xda\xda\xda\xee\xee\xee\xed\xed\xed\xef\xef\xef\xd7\xd3\xd5\xc1\xce\xc4\xf3\xdd\xe8\xe6\xd1\xdb\xf6\xff\xf8\xf4\xfd\xf2\xed\xf8\xee\xe5\xf0\xe7\xe8\xf5\xeb\xcf\xdc\xd0\xe7\xf4\xe9\xdf\xec\xe1\xc9\xd6\xca\xd0\xdd\xd1\xc9\xd6\xca\xc8\xd5\xc9\xd0\xde\xd2\xd2\xde\xd3\xd0\xde\xd2\xd4\xe1\xd6\xcc\xd8\xce\xc8\xd4\xc9\xc9\xd6\xca\xcb\xd8\xcc\xcf\xdc\xd1\xcb\xd9\xcd\xc4\xd2\xc5\xed\xf6\xef\xe8\xf3\xea\xee\xfa\xf0\xf4\xff\xf6\xf3\xfe\xf5\xf3\xfe\xf5\xee\xfc\xf0\xeb\xf8\xee\xe9\xf6\xeb\xe8\xf5\xeb\xe9\xf5\xeb\xe6\xf1\xe7\xea\xf3\xeb\xf7\xff\xf9\xf6\xfd\xf8\xff\xff\xff\xdc\xdd\xdd\xbc\xbc\xbc\xcb\xcb\xcb\xd0\xd0\xd0\xdc\xdc\xdc\xd1\xd1\xd0\xbb\xbb\xba\xcc\xcc\xcb\xe3\xe3\xe2\xed\xed\xed\xf4\xf4\xf4\xf7\xf7\xf7\xeb\xeb\xeb\xe7\xe7\xe6\xf7\xf7\xf6\xd4\xd3\xd2\xe3\xe3\xe2\xf4\xf4\xf3\xcf\xcf\xce\xe3\xe2\xe1\xca\xca\xc9\xa2\xa1\xa0\xc3\xc3\xc2\xe2\xe1\xe1\xdd\xdc\xdc\xf1\xf1\xf1\xff\xff\xff\xfd\xfc\xfc\xfe\xff\xff\xfd\xe2\xe1\xed\xda\xd9\xda\xdf\xdf\xd1\xd1\xd1\xe9\xe9\xe9\xb8\xac\xab\x03\x00\x01\x18\x07\x15!\x0b\x1d0\x11*G\x0f=TCQgkhmlmrqq\xbe\xbe\xbe\xf5\xf5\xf5\xeb\xeb\xeb\xda\xda\xda\xf0\xf0\xf0\xed\xed\xed\xee\xee\xee\xef\xef\xef\xeb\xeb\xeb\xcc\xcc\xcc\xea\xea\xea\xef\xef\xef\xf1\xf0\xf1\xd0\xd4\xd0\xd6\xaf\xce\xec\x9e\xdf\xe7\xa0\xdb\xe4\xa0\xd8\xe8\x9f\xdb\xe7\x9f\xdb\xe6\xa0\xda\xec\xa1\xdf\xec\xa5\xdf\xeb\xa1\xdf\xe8\xa1\xdc\xec\xa5\xe0\xed\xa4\xe0\xec\xa6\xe0\xf0\xa6\xe3\xef\xa5\xe2\xec\xa6\xe0\xf0\xa5\xe3\xec\xa5\xe0\xeb\xa6\xdf\xec\xa7\xe0\xf0\xa6\xe4\xef\xa6\xe3\xef\xa6\xe2\xf1\xa5\xe4\xf0\xa7\xe3\xe9\xa1\xdc\xe9\xa0\xdc\xe7\xa0\xdb\xe7\xa0\xda\xe6\xa0\xda\xe5\xa0\xd9\xe7\x9c\xda\xe0\x9c\xd4\xe0\x9b\xd4\xdd\x9a\xd1\xdb\x9a\xd0\xda\x9c\xcf\xe5\xa6\xda\xf5\xaa\xe9\xf4\xad\xe8\xfe\xb2\xf1\xdc\xb9\xd6\xbd\xc2\xbe\xcc\xcb\xcc\xd3\xd3\xd2\xd8\xd7\xd8\xc4\xc3\xc5\xa0\x9e\xa1\xb9\xb7\xbb\xd9\xd8\xda\xd1\xd0\xd0\xb9\xb8\xb8\xb9\xb8\xb8\xd4\xd3\xd3\xe7\xe6\xe9\xf3\xf2\xf6\xbc\xba\xbe\xd4\xd2\xd6\xf1\xf0\xf4\xb1\xaf\xb3\xe2\xe1\xe5\xe6\xe5\xe8\xb5\xb4\xb6\xe7\xe7\xe7\xe4\xe3\xe3\xf1\xf0\xf0\xff\xff\xff\xfd\xfd\xfd\xfe\xff\xff\xfd\xef\xee\xfa\xdb\xda\xe7\xeb\xec\xd5\xd5\xd4\xd3\xd4\xd4\xf6\xea\xeaqkj\x00\x00\x00 \x0e\x1c'\x10#6\x170K\x16BXIVlolqppvuu\xc1\xc1\xc1\xf6\xf6\xf6\xe6\xe6\xe6\xcd\xcd\xcd\xed\xed\xed\xef\xef\xef\xed\xed\xed\xee\xee\xee\xee\xed\xed\xec\xec\xec\xea\xeb\xea\xee\xee\xee\xf0\xed\xf0\xd2\xde\xd3\xe2\x8c\xd3\xde3\xc1\xddA\xc3\xdf@\xc4\xe4>\xc8\xe5>\xca\xdf?\xc4\xe8=\xcc\xe0=\xc5\xe7>\xcb\xde?\xc3\xdd>\xc2\xe5>\xca\xdb;\xc0\xe08\xc3\xda9\xbe\xd39\xb8\xde7\xc1\xde7\xc1\xd67\xba\xd37\xb8\xdd6\xc0\xdb6\xbf\xdb6\xbe\xe05\xc2\xd47\xb9\xd87\xbc\xdb7\xbf\xdd7\xc0\xd78\xbc\xd79\xbc\xdb7\xbf\xdc6\xbf\xd66\xba\xd38\xb8\xd7@\xbd\xd7J\xbf\xd3K\xbc\xd7B\xbe\xf4D\xd6\xf3K\xd7\xfdJ\xde\xdb\x8a\xcd\xbd\xc8\xbf\xcb\xc9\xcb\xd5\xd5\xd4\xce\xcd\xd1\xac\xa8\xb6\xc6\xc1\xd1\xc8\xc2\xd3\xc0\xbc\xc8\xde\xdf\xde\xc3\xc2\xc2\xcd\xcc\xcc\xe0\xdf\xe0\xc9\xc4\xd5\xd0\xca\xde\xd3\xce\xe1\xd1\xcc\xdf\xce\xc9\xdc\xd5\xd0\xe3\xce\xc9\xdb\xb6\xb2\xbe\xcf\xce\xd3\xe6\xe5\xe4\xeb\xea\xea\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfa\xf9\xfc\xd8\xd7\xf7\xf6\xf6\xde\xdf\xdf\xda\xd6\xd8\xcd\xcc\xcc\xd9\xd6\xd6//0\x09\x0a\x09#%#/20?C?KSL[][jjjvuu\x81\x80\x80\xc2\xc2\xc2\xf4\xf4\xf4\xe9\xea\xea\xed\xed\xed\xed\xed\xed\xee\xee\xee\xef\xef\xef\xee\xee\xee\xf2\xf1\xf1\xd5\xda\xd9\xd6\xdb\xda\xf2\xf1\xf1\xf0\xed\xf0\xd3\xde\xd4\xe0\x8d\xd1\xf3M\xd8\xe4G\xc9\xd5N\xbd\xeb[\xd3\xdda\xc8\xdcj\xc8\xddt\xcb\xe1\x7e\xd0\xdc\x86\xcc\xdd\x8e\xce\xdf\x98\xd2\xd5\x9b\xca\xee\xb6\xe5\xff\xcf\xfa\xfd\xd9\xfa\xff\xe6\xfd\xfe\xf3\xfe\xfe\xfd\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xfe\xfe\xfe\xfe\xff\xfe\xff\xfe\xff\xfe\xfe\xfe\xfc\xfe\xfd\xfa\xff\xfb\xfb\xfd\xfb\xee\xe2\xea\xd0\xb2\xc7\xd2\xa8\xc4\xf9\xfe\xfa\xf5\xfe\xf6\xf7\xfd\xf7\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd2\xd2\xd2\xd9\xd9\xd9\xe1\xe1\xe1\xe4\xe4\xe4\xeb\xeb\xea\xf1\xf1\xf1\xf3\xf3\xf3\xfa\xfa\xfa\xfd\xfd\xfd\xfa\xfa\xfa\xfb\xfc\xfb\xfc\xfc\xfc\xfb\xfb\xfa\xfb\xfb\xfb\xfc\xfc\xfc\xfa\xfa\xfa\xfe\xfe\xfd\xec\xec\xec\xdf\xdf\xde\xe6\xe5\xe5\xf9\xf9\xf9\xff\xff\xff\xfd\xfc\xfc\xfd\xff\xff\xfb\xdb\xd9\xfe\xf0\xf0\xef\xf1\xf2\xdc\xdb\xda\xc3\xd2\xc9\xc7\xca\xc9\xa6\xa6\xa6\x05\x07\x05\x19\x1a\x19(((767GFGVTVeeeuuu\x81\x80\x81\x91\x90\x90\xc3\xc4\xc3\xf8\xf7\xf7\xd4\xd9\xd8\xda\xdf\xde\xf2\xf1\xf1\xee\xee\xee\xef\xef\xef\xef\xef\xef\xee\xee\xee\xef\xef\xef\xef\xef\xef\xef\xef\xef\xee\xeb\xed\xe5\xef\xe7\xee\xaa\xe2\xea`\xd2\xdfi\xca\xd8m\xc5\xe0n\xcb\xd8u\xc7\xd5\x7d\xc5\xd8\x85\xc9\xd6\x8a\xc8\xd0\x8d\xc3\xd4\x95\xc8\xdf\xa8\xd5\xe4\xb5\xdb\xf2\xc5\xeb\xff\xd7\xfa\xfc\xdc\xf7\xfc\xe3\xf7\xfc\xec\xfa\xfd\xf7\xfc\xfb\xfb\xfb\xf4\xf1\xf3\xf4\xf0\xf3\xf5\xf5\xf5\xf3\xf3\xf3\xf5\xf4\xf5\xf4\xf3\xf3\xf1\xf1\xf1\xef\xee\xee\xee\xed\xee\xf0\xf0\xf0\xfc\xfc\xfc\xfe\xfe\xfe\xfc\xfd\xfc\xf3\xeb\xf1\xb6\x7b\xa5\xb8t\xa4\xbd\x94\xb1\xdb\xc8\xd5\xf4\xf4\xf4\xf4\xf3\xf4\xf6\xf5\xf6\xff\xfe\xff\xdc\xdc\xdc\xbd\xbd\xbd\xcc\xcc\xcc\xd3\xd3\xd3\xd8\xd8\xd8\xc2\xc1\xc1\xc6\xc5\xc5\xc9\xc8\xc8\xc7\xc6\xc6\xcd\xcd\xcd\xca\xca\xca\xcb\xca\xca\xdb\xdb\xdb\xfa\xfa\xfa\xf8\xf8\xf8\xf9\xf9\xf9\xf9\xf9\xf9\xf8\xf8\xf8\xfa\xfa\xfa\xf2\xf3\xf2\xe3\xe2\xe2\xda\xd8\xd8\xf0\xef\xef\xff\xff\xff\xfd\xfc\xfc\xfe\xff\xff\xfe\xe9\xe8\xfb\xe3\xe2\xfc\xff\xff\xe7\xe8\xe6\xd9\xd1\xdb\x9d\x97\xac\xd4\xe4\xdcuqs\x00\x00\x00 \x1a\x1f-.-<;;LLLZZZjji\x79\x79\x79\x86\x85\x85\x95\x95\x95\xc6\xc6\xc6\xf4\xf4\xf4\xed\xed\xed\xee\xee\xee\xef\xee\xee\xee\xef\xef\xef\xef\xef\xef\xef\xef\xee\xee\xee\xef\xef\xef\xee\xef\xef\xef\xef\xef\xed\xed\xed\xe6\xe5\xe5\xec\xee\xec\xc1\xd7\xc4\xc1\xd9\xc5\xd1\xdd\xd2\xdb\xed\xde\xdc\xea\xde\xd8\xe0\xd9\xdf\xe7\xe0\xd9\xdf\xda\xda\xdf\xdb\xdd\xe2\xdd\xeb\xef\xeb\xf3\xf7\xf3\xf0\xf3\xf0\xec\xf1\xec\xf8\xfa\xf9\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xf8\xf8\xf8\xc4\xcf\xc5\xbf\xcc\xc0\xca\xca\xc9\xc0\xbf\xbf\xbe\xbd\xbd\xc8\xc7\xc6\xda\xda\xda\xd2\xd1\xd1\xd5\xd4\xd4\xdd\xdc\xdc\xf3\xf2\xf2\xe9\xe9\xe9\xe9\xe9\xe9\xe0\xdc\xdf\xe4\xd7\xe0\xf9\xfa\xf9\xfc\xff\xfd\xf7\xfa\xf8\xf2\xf2\xf2\xf5\xf5\xf5\xf6\xf6\xf6\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd2\xd2\xd2\xd7\xd7\xd7\xca\xc9\xca\xcf\xce\xce\xd4\xd3\xd4\xd0\xcf\xcf\xe3\xe3\xe3\xec\xec\xec\xf0\xf0\xf0\xe4\xe4\xe4\xde\xdd\xdd\xe8\xe7\xe7\xe6\xe5\xe6\xe5\xe5\xe5\xe6\xe6\xe6\xe3\xe3\xe3\xde\xde\xde\xe4\xe2\xe3\xef\xee\xee\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xef\xf0\xf0\xdc\xd2\xd1\xff\xff\xff\xf6\xf6\xf6\xe0\xe4\xe3\xb8\x94\x95\xc1\x9a\xb4\xdf\xe1\xdf.,.\x0a\x00\x07$\x1a\x22343AAARRR```ppp\x80\x80\x80\x89\x89\x88\x95\x95\x95\xc9\xc9\xc9\xf4\xf4\xf4\xed\xee\xee\xef\xef\xef\xee\xee\xee\xef\xef\xef\xef\xef\xef\xef\xef\xef\xee\xee\xee\xef\xef\xef\xee\xee\xee\xef\xef\xef\xee\xed\xee\xe1\xe0\xdf\xee\xee\xee\xe3\x87\xd6\xd8l\xc6\xdc\xac\xd6\xe8\x7c\xdb\xf8\xc4\xf2\xff\xff\xff\xff\xff\xff\xed\xec\xed\xde\xdc\xdd\xde\xdd\xde\xdf\xde\xdf\xd5\xd3\xd4\xd8\xd7\xd8\xd5\xd3\xd4\xe2\xe0\xe1\xec\xeb\xeb\xe6\xe5\xe5\xfc\xfb\xfc\xfd\xff\xfe\xec\xa6\xe4\xde\x87\xd0\xe8\xe1\xe7\xe7\xe9\xe7\xe7\xe7\xe7\xea\xe9\xe9\xff\xff\xff\xed\xed\xed\xde\xde\xde\xde\xdd\xdd\xe0\xe0\xe0\xd9\xd9\xd9\xd8\xd7\xd7\xd6\xd6\xd5\xe1\xe3\xe1\xe2\xe1\xe1\xdb\xd9\xda\xf0\xef\xf0\xf3\xf3\xf3\xf4\xf4\xf4\xf6\xf6\xf6\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd0\xd0\xd0\xdc\xdd\xdd\xcc\xce\xcd\x9c\x9e\x9c\xb8\xba\xb8\xe4\xe6\xe5\xde\xdd\xdd\xd8\xd8\xd8\xd8\xd7\xd7\xde\xde\xde\xeb\xed\xec\xfa\xfd\xfc\xc3\xc6\xc4\xde\xdf\xde\xf8\xf8\xf8\xd3\xd3\xd2\xe8\xe7\xe7\xea\xe9\xe9\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xbc\xbb\xbb\x9c\x9c\x9c\xc7\xc6\xc6\xee\xee\xee\xdf\xe0\xe1\xc6\xbb\xb7\xce\xd0\xca\xb7\xb7\xb8\x07\x07\x07\x16\x17\x16$%$333AAAPPP^]]lll\x7b\x7a\x7a\x89\x89\x89\x9a\x99\x99\xcb\xcc\xcb\xf3\xf3\xf3\xed\xed\xed\xee\xee\xee\xef\xef\xef\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf0\xef\xef\xef\xf0\xf0\xf0\xef\xef\xef\xf0\xf0\xf0\xf0\xef\xf0\xdc\xdf\xdc\xe8\xd7\xe5\xeb+\xcd\xedJ\xd4\xef\x81\xe0\xd7\x1a\xbd\xf3\xb1\xeb\xff\xff\xff\xff\xfe\xff\xdd\xdd\xdd\xa9\xa8\xa7\xae\xac\xac\xb1\xb0\xb0\xb5\xb3\xb4\xb9\xba\xb7\xbc\xbe\xb8\xad\xad\xab\xb1\xb0\xb0\xbb\xba\xba\xfa\xfc\xfa\xfe\xf6\xfd\xf3\x22\xd3\xec0\xcc\xff\xfc\xff\xfe\xff\xfe\xff\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xdd\xdd\xdd\xaa\xa9\xa9\xad\xac\xac\xb3\xb1\xb1\xb2\xb1\xb1\xac\xab\xab\xac\xab\xab\xaa\xa9\xa9\xa7\xa6\xa6\xb7\xb6\xb6\xf0\xf0\xf0\xf3\xf3\xf3\xf4\xf4\xf4\xf6\xf6\xf6\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd2\xd3\xd3\xd5\xcf\xd2\xcd\xb6\xc2\xc9\xb2\xbd\xd6\xbd\xc9\xd4\xc3\xcc\xd5\xd6\xd5\xb7\xb5\xb5\xbc\xbc\xbb\xd8\xd7\xd7\xe3\xcb\xd7\xf2\xd5\xe3\xde\xc3\xd0\xce\xb9\xc3\xd7\xcf\xd3\xdf\xdf\xdf\xd7\xd6\xd6\xf9\xf9\xf9\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xd3\xd2\xd2\xae\xad\xad\xcc\xcb\xca\xb6\xb5\xb5\xa2\xa1\xa0\xc9\xc9\xc9\xd9\xdc\xdd\xf2\xf2\xf3uuu\x00\x00\x00\x1e\x1e\x1e-.-<>=OPO[ZZjjjxxx\x87\x87\x86\x96\x96\x96\xa1\xa1\xa0\xb3\xb2\xb2\xd9\xd9\xd9\xf4\xf4\xf4\xf0\xf0\xf0\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1\xf2\xf2\xf2\xf2\xf2\xf2\xf1\xf1\xf1\xf2\xf2\xf2\xf1\xf1\xf1\xf2\xf2\xf2\xf2\xf2\xf2\xdc\xda\xda\xe8\xe9\xe8\xd7\xe3\xd8\xce\xd5\xcf\xda\xe1\xda\xdb\xe6\xdc\xfd\xfd\xfd\xff\xff\xff\xe9\xe8\xe8\xd1\xd0\xd0\xae\xae\xad\xab\xaa\xaa\xbb\xbc\xb7\xea\xee\xe7\xe3\xe9\xde\xcd\xd4\xc5\xad\xad\xac\xa3\xa2\xa2\xc1\xc0\xc0\xdc\xdb\xdb\xf0\xf2\xf0\xd7\xe8\xd9\xd4\xde\xd5\xdf\xdf\xdf\xd8\xd8\xd7\xe2\xe1\xe1\xff\xff\xff\xe3\xe2\xe2\xd3\xd3\xd2\xac\xaa\xaa\xac\xaf\xa7\xdb\xe0\xd6\xec\xed\xed\xd7\xdb\xd3\xa2\xa2\xa0\xa8\xa7\xa7\xa0\x9f\x9f\xba\xb9\xb9\xd1\xd1\xd0\xe8\xe8\xe8\xf7\xf7\xf7\xf5\xf5\xf5\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd1\xd1\xd0\xdc\xdc\xdc\xd1\xd1\xd1\xbf\xbe\xbe\xcf\xce\xce\xe2\xe2\xe2\xf0\xef\xef\xf8\xf8\xf8\xfb\xfb\xfb\xea\xea\xea\xdd\xdd\xdd\xe5\xe5\xe5\xc9\xc7\xc7\xe0\xe0\xe0\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xf1\xf1\xf1\xda\xda\xda\xd4\xd4\xd4\xe8\xe8\xe8\xc4\xc4\xc4\x09\x09\x09\x16\x16\x16 \x1f+++>>>TTTddduuu\x83\x83\x83\x93\x93\x93\xa4\xa3\xa3\xac\xac\xac\xc0\xbf\xbf\xda\xdb\xda\xf5\xf5\xf5\xf1\xf1\xf1\xf1\xf1\xf1\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf1\xf1\xf1\xf2\xf2\xf2\xf1\xf1\xf1\xf2\xf2\xf2\xf0\xef\xf0\xe4\xe3\xe3\xef\xee\xef\xdb\x8d\xd1\xd5s\xc9\xee\xdf\xec\xfa\xfb\xfa\xfe\xfc\xfe\xff\xff\xff\xee\xee\xee\xd7\xd6\xd6\xae\xad\xac\xa7\xa6\xa5\xc3\xc2\xc2\xf3\xf4\xf1\xc9\xd1\xc2\xa4\xa8\xa0\xae\xad\xad\xaa\xa9\xa8\xb9\xb8\xb8\xde\xde\xde\xf4\xf5\xf4\xf1e\xe0\xe9G\xd1\xf1\xe5\xef\xf2\xf5\xf2\xf3\xf2\xf3\xff\xff\xff\xed\xec\xec\xd8\xd8\xd8\xb1\xb0\xaf\xd1\xd8\xca\xdf\xe0\xdd\xe1\xe7\xdb\xd3\xdd\xcb\xa0\xa1\x9e\xac\xaa\xab\xa4\xa3\xa3\xb5\xb4\xb4\xd3\xd3\xd3\xed\xed\xed\xf6\xf6\xf6\xf5\xf5\xf5\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd1\xd1\xd1\xd7\xd7\xd7\xc5\xc5\xc4\x9f\x9e\x9e\xb9\xb8\xb8\xda\xda\xda\xcf\xcf\xcf\xb7\xb6\xb5\xb7\xb6\xb5\xd4\xd4\xd4\xe1\xe1\xe1\xd2\xd1\xd1\xd2\xd1\xd1\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xe9\xe9\xe9\xd7\xd7\xd7\xd1\xd1\xd1\xf3\xf3\xf3\x87\x87\x87\x00\x00\x00 ++*565<\x073H\x07>>\x05\x05\x05###222?>?I.DW5Qieh\x7c\x7b\x7b\x89\x87\x88\x99\x97\x98\xa8\xa6\xa7\xb4\xb3\xb3\xcc\xcb\xcb\xdf\xdf\xdf\xf4\xf4\xf4\xf1\xf1\xf1\xf1\xf1\xf1\xf2\xf2\xf2\xf2\xf2\xf2\xf3\xf3\xf3\xf3\xf3\xf3\xf2\xf2\xf2\xf3\xf3\xf3\xf2\xf2\xf2\xf3\xf3\xf3\xf1\xf1\xf1\xe6\xe5\xe5\xf5\xf3\xf4\xf2\xe4\xef\xea\xdf\xe8\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xdf\xdf\xdf\xac\xac\xab\xb0\xaf\xaf\xae\xac\xac\xab\xab\xa9\xab\xac\xa9\xab\xab\xaa\xb1\xaf\xaf\xad\xac\xac\xb9\xb8\xb8\xf3\xf3\xf3\xff\xff\xff\xf1\xf1\xf0\xe9\xe8\xe8\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xdf\xdf\xdf\xb0\xaf\xaf\xdf\xe0\xdd\xd0\xd6\xc7\xb6\xba\xae\xa5\xa3\xa2\xac\xab\xab\xaa\xaa\xa9\xa5\xa4\xa4\xb5\xb5\xb4\xea\xea\xea\xf4\xf4\xf4\xf4\xf4\xf4\xf6\xf6\xf6\xff\xff\xff\xdc\xdc\xdc\xbc\xbc\xbc\xcb\xcb\xcb\xd1\xd1\xd1\xd8\xd8\xd8\xd3\xd3\xd3\xd6\xd6\xd6\xdb\xdb\xdb\xe2\xe2\xe2\xe4\xe3\xe3\xea\xe9\xe9\xed\xee\xee\xf5\xf5\xf5\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xf2\xf2\xf2\xdb\xdb\xdb\xd2\xd2\xd2\xe4\xe4\xe4\xcd\xcd\xcd\x0d\x0d\x0d\x16\x18\x16%'%+-+:>;IQJXcYv\x7cw\x84\x8a\x85\x94\x9a\x95\xa3\xaa\xa4\xb3\xbb\xb4\xb0\xb1\xaf\xbd\xbb\xbb\xe5\xe5\xe5\xf4\xf4\xf4\xf2\xf2\xf2\xf2\xf2\xf2\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf2\xf2\xf2\xf3\xf3\xf3\xf2\xf2\xf2\xf3\xf3\xf3\xf3\xf3\xf3\xd8\xd7\xd7\xe9\xe8\xe8\xff\xff\xff\xfd\xfd\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xdd\xdd\xdd\xa8\xa6\xa6\xad\xac\xac\xad\xab\xab\xae\xad\xad\xac\xaa\xab\xad\xac\xac\xad\xac\xab\xaa\xa8\xa8\xb5\xb4\xb4\xee\xed\xed\xff\xff\xff\xfe\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xdf\xdf\xdf\xa9\xa7\xa8\xae\xb1\xaa\xbe\xc5\xb7\xab\xac\xa7\xa7\xa6\xa6\xa8\xa7\xa6\xa8\xa7\xa6\xa1\xa0\xa0\xb4\xb3\xb2\xe5\xe5\xe5\xf5\xf5\xf5\xf5\xf5\xf5\xf7\xf7\xf7\xff\xff\xff\xdd\xdd\xdd\xbd\xbd\xbd\xcc\xcc\xcc\xd2\xd2\xd2\xd9\xd9\xd9\xcb\xcb\xcb\xcf\xce\xce\xcf\xcf\xcf\xd7\xd7\xd7\xd8\xd7\xd7\xd2\xd1\xd1\xe7\xe8\xe8\xff\xff\xff\xf9\xf9\xf9\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xe9\xe9\xe9\xd7\xd7\xd7\xd1\xd1\xd1\xf3\xf3\xf3\x8c\x8c\x8c\x00\x00\x00\x1e\x18\x1d(\x1f'5(2F5CR + + +gpdf2swf Program + + + + + + +""" + +class Target(object): + """ A simple class that holds information on our executable file. """ + def __init__(self, **kw): + """ Default class constructor. Update as you need. """ + self.__dict__.update(kw) + + +# Ok, let's explain why I am doing that. +# Often, data_files, excludes and dll_excludes (but also resources) +# can be very long list of things, and this will clutter too much +# the setup call at the end of this file. So, I put all the big lists +# here and I wrap them using the textwrap module. + +data_files = [('viewers', ['viewers/__init__.py', + 'viewers/raw.py', + 'viewers/rfx.py', + 'viewers/rfx7.swf', + 'viewers/rfx8.swf', + 'viewers/simple.py']), + #('.', ['dll/msvcp71.dll', + # ]), + #('images', ['images/stop.png', + # 'images/pdf2swf_gui.ico']) + ] + +includes = [] +excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger', + 'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl', + 'Tkconstants', 'Tkinter'] +packages = ['viewers'] +dll_excludes = ['libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll', 'tcl84.dll', + 'tk84.dll'] +icon_resources = [(1, 'gpdf2swf.ico')] +bitmap_resources = [] +other_resources = [(24, 1, manifest_template)] + + +# This is a place where the user custom code may go. You can do almost +# whatever you want, even modify the data_files, includes and friends +# here as long as they have the same variable name that the setup call +# below is expecting. + +# No custom code added + + +# Ok, now we are going to build our target class. +# I chose this building strategy as it works perfectly for me :-D + + +GUI2Exe_Target_1 = Target( + # what to build + script = "gpdf2swf.py", + icon_resources = icon_resources, + bitmap_resources = bitmap_resources, + other_resources = other_resources, + dest_base = "gpdf2swf", + version = "0.9.0", + company_name = "swftools", + copyright = "swftools", + name = "gpdf2exe" + ) + + + +# That's serious now: we have all (or almost all) the options py2exe +# supports. I put them all even if some of them are usually defaulted +# and not used. Some of them I didn't even know about. + +setup( + + data_files = data_files, + + options = {"py2exe": {"compressed": 0, + "optimize": 2, + "includes": includes, + "excludes": excludes, + "packages": packages, + "dll_excludes": dll_excludes, + "bundle_files": 3, + "dist_dir": "dist", + "xref": False, + "skip_archive": False, + "ascii": False, + "custom_boot_script": '', + } + }, + + zipfile = None, + console = [], + windows = [GUI2Exe_Target_1] + ) + +# This is a place where any post-compile code may go. +# You can add as much code as you want, which can be used, for example, +# to clean up your folders or to do some particular post-compilation +# actions. + +# No post-compilation code added + + +# And we are done. That's a setup script :-D + +# Run setup standalone... +if __name__ == "__main__": + setup() diff -Nru swftools-0.9.2+ds1/wx/viewers/flexpaper/FlexPaperViewer.html swftools-0.9.1/wx/viewers/flexpaper/FlexPaperViewer.html --- swftools-0.9.2+ds1/wx/viewers/flexpaper/FlexPaperViewer.html 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/viewers/flexpaper/FlexPaperViewer.html 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + +
    +
    +

    + To view this page ensure that Adobe Flash Player version + 9.0.124 or greater is installed. +

    + +
    +
    + Can't see the document? Running FlexPaper from your local directory? Make sure you have added FlexPaper as trusted. You can do that at Adobe's website. +
    +
    + + diff -Nru swftools-0.9.2+ds1/wx/viewers/flexpaper/js/jquery.js swftools-0.9.1/wx/viewers/flexpaper/js/jquery.js --- swftools-0.9.2+ds1/wx/viewers/flexpaper/js/jquery.js 1970-01-01 00:00:00.000000000 +0000 +++ swftools-0.9.1/wx/viewers/flexpaper/js/jquery.js 2012-06-20 15:37:18.000000000 +0000 @@ -0,0 +1,5999 @@ +/*! + * jQuery JavaScript Library v1.4 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://docs.jquery.com/License + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Wed Jan 13 15:23:05 2010 -0500 + */ +(function( window, undefined ) { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/, + + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The functions to execute on DOM ready + readyList = [], + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwnProperty = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + indexOf = Array.prototype.indexOf; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; + } + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + if ( elem ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $("TAG") + } else if ( !context && /^\w+$/.test( selector ) ) { + this.selector = selector; + this.context = document; + selector = document.getElementsByTagName( selector ); + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return jQuery( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.isArray( selector ) ? + this.setArray( selector ) : + jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.4", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = jQuery( elems || null ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Force the current matched set of elements to become + // the specified array of elements (destroying the stack in the process) + // You should use pushStack() in order to do this, but maintain the stack + setArray: function( elems ) { + // Resetting the length to 0, then using the native Array push + // is a super-fast way to populate an object with array-like properties + this.length = 0; + push.apply( this, elems ); + + return this; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // If the DOM is already ready + if ( jQuery.isReady ) { + // Execute the function immediately + fn.call( document, jQuery ); + + // Otherwise, remember the function for later + } else if ( readyList ) { + // Add the function to the wait list + readyList.push( fn ); + } + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || jQuery(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging object literal values or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) { + var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src + : jQuery.isArray(copy) ? [] : {}; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // Handle when the DOM is ready + ready: function() { + // Make sure that the DOM is not already loaded + if ( !jQuery.isReady ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 13 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If there are functions bound, to execute + if ( readyList ) { + // Execute all of them + var fn, i = 0; + while ( (fn = readyList[ i++ ]) ) { + fn.call( document, jQuery ); + } + + // Reset the list of functions + readyList = null; + } + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + return jQuery.ready(); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return toString.call(obj) === "[object Function]"; + }, + + isArray: function( obj ) { + return toString.call(obj) === "[object Array]"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor + && !hasOwnProperty.call(obj, "constructor") + && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwnProperty.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + + if ( jQuery.support.scriptEval ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + trim: function( text ) { + return (text || "").replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = []; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + if ( !inv !== !callback( elems[ i ], i ) ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + var ret = { browser: "" }; + + ua = ua.toLowerCase(); + + if ( /webkit/.test( ua ) ) { + ret = { browser: "webkit", version: /webkit[\/ ]([\w.]+)/ }; + + } else if ( /opera/.test( ua ) ) { + ret = { browser: "opera", version: /version/.test( ua ) ? /version[\/ ]([\w.]+)/ : /opera[\/ ]([\w.]+)/ }; + + } else if ( /msie/.test( ua ) ) { + ret = { browser: "msie", version: /msie ([\w.]+)/ }; + + } else if ( /mozilla/.test( ua ) && !/compatible/.test( ua ) ) { + ret = { browser: "mozilla", version: /rv:([\w.]+)/ }; + } + + ret.version = (ret.version && ret.version.exec( ua ) || [0, "0"])[1]; + + return ret; + }, + + browser: {} +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch( error ) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +function evalScript( i, elem ) { + if ( elem.src ) { + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + } else { + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } +} + +// Mutifunctional method to get and set values to a collection +// The value/s can be optionally by executed if its a function +function access( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : null; +} + +function now() { + return (new Date).getTime(); +} +(function() { + + jQuery.support = {}; + + var root = document.documentElement, + script = document.createElement("script"), + div = document.createElement("div"), + id = "script" + now(); + + div.style.display = "none"; + div.innerHTML = "
    a"; + + var all = div.getElementsByTagName("*"), + a = div.getElementsByTagName("a")[0]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return; + } + + jQuery.support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText insted) + style: /red/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: div.getElementsByTagName("input")[0].value === "on", + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected, + + // Will be defined later + scriptEval: false, + noCloneEvent: true, + boxModel: null + }; + + script.type = "text/javascript"; + try { + script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); + } catch(e) {} + + root.insertBefore( script, root.firstChild ); + + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) + if ( window[ id ] ) { + jQuery.support.scriptEval = true; + delete window[ id ]; + } + + root.removeChild( script ); + + if ( div.attachEvent && div.fireEvent ) { + div.attachEvent("onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + jQuery.support.noCloneEvent = false; + div.detachEvent("onclick", click); + }); + div.cloneNode(true).fireEvent("onclick"); + } + + // Figure out if the W3C box model works as expected + // document.body must exist before we can do this + // TODO: This timeout is temporary until I move ready into core.js. + jQuery(function() { + var div = document.createElement("div"); + div.style.width = div.style.paddingLeft = "1px"; + + document.body.appendChild( div ); + jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; + document.body.removeChild( div ).style.display = 'none'; + div = null; + }); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + var eventSupported = function( eventName ) { + var el = document.createElement("div"); + eventName = "on" + eventName; + + var isSupported = (eventName in el); + if ( !isSupported ) { + el.setAttribute(eventName, "return;"); + isSupported = typeof el[eventName] === "function"; + } + el = null; + + return isSupported; + }; + + jQuery.support.submitBubbles = eventSupported("submit"); + jQuery.support.changeBubbles = eventSupported("change"); + + // release memory in IE + root = script = div = all = a = null; +})(); + +jQuery.props = { + "for": "htmlFor", + "class": "className", + readonly: "readOnly", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + tabindex: "tabIndex", + usemap: "useMap", + frameborder: "frameBorder" +}; +var expando = "jQuery" + now(), uuid = 0, windowData = {}; +var emptyObject = {}; + +jQuery.extend({ + cache: {}, + + expando:expando, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + "object": true, + "applet": true + }, + + data: function( elem, name, data ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ], cache = jQuery.cache, thisCache; + + // Handle the case where there's no name immediately + if ( !name && !id ) { + return null; + } + + // Compute a unique ID for the element + if ( !id ) { + id = ++uuid; + } + + // Avoid generating a new cache unless none exists and we + // want to manipulate it. + if ( typeof name === "object" ) { + elem[ expando ] = id; + thisCache = cache[ id ] = jQuery.extend(true, {}, name); + } else if ( cache[ id ] ) { + thisCache = cache[ id ]; + } else if ( typeof data === "undefined" ) { + thisCache = emptyObject; + } else { + thisCache = cache[ id ] = {}; + } + + // Prevent overriding the named cache with undefined values + if ( data !== undefined ) { + elem[ expando ] = id; + thisCache[ name ] = data; + } + + return typeof name === "string" ? thisCache[ name ] : thisCache; + }, + + removeData: function( elem, name ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ]; + + // If we want to remove a specific section of the element's data + if ( name ) { + if ( thisCache ) { + // Remove the section of cache data + delete thisCache[ name ]; + + // If we've removed all the data, remove the element's cache + if ( jQuery.isEmptyObject(thisCache) ) { + jQuery.removeData( elem ); + } + } + + // Otherwise, we want to remove all of the element's data + } else { + // Clean up the element expando + try { + delete elem[ expando ]; + } catch( e ) { + // IE has trouble directly removing the expando + // but it's ok with using removeAttribute + if ( elem.removeAttribute ) { + elem.removeAttribute( expando ); + } + } + + // Completely remove the data cache + delete cache[ id ]; + } + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + if ( typeof key === "undefined" && this.length ) { + return jQuery.data( this[0] ); + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + } + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + } else { + return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() { + jQuery.data( this, key, value ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); +jQuery.extend({ + queue: function( elem, type, data ) { + if ( !elem ) { + return; + } + + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( !data ) { + return q || []; + } + + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data) ); + + } else { + q.push( data ); + } + + return q; + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), fn = queue.shift(); + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function( i, elem ) { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + } +}); +var rclass = /[\n\t]/g, + rspace = /\s+/, + rreturn = /\r/g, + rspecialurl = /href|src|style/, + rtype = /(button|input)/i, + rfocusable = /(button|input|object|select|textarea)/i, + rclickable = /^(a|area)$/i, + rradiocheck = /radio|checkbox/; + +jQuery.fn.extend({ + attr: function( name, value ) { + return access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name, fn ) { + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspace ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " "; + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + elem.className += " " + classNames[c]; + } + } + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split(rspace); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = className.substring(1, className.length - 1); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, i = 0, self = jQuery(this), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery.data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + if ( value === undefined ) { + var elem = this[0]; + + if ( elem ) { + if ( jQuery.nodeName( elem, "option" ) ) { + return (elem.attributes.value || {}).specified ? elem.value : elem.text; + } + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + if ( option.selected ) { + // Get the specifc value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + } + + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { + return elem.getAttribute("value") === null ? "on" : elem.value; + } + + + // Everything else, we just grab the value + return (elem.value || "").replace(rreturn, ""); + + } + + return undefined; + } + + var isFunction = jQuery.isFunction(value); + + return this.each(function(i) { + var self = jQuery(this), val = value; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call(this, i, self.val()); + } + + // Typecast each time if the value is a Function and the appended + // value is therefore different each time. + if ( typeof val === "number" ) { + val += ""; + } + + if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { + this.checked = jQuery.inArray( self.val(), val ) >= 0; + + } else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(val); + + jQuery( "option", this ).each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + this.selectedIndex = -1; + } + + } else { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + // don't set attributes on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery(elem)[name](value); + } + + var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), + // Whether we are setting (or getting) + set = value !== undefined; + + // Try to normalize/fix the name + name = notxml && jQuery.props[ name ] || name; + + // Only do all the following if this is a node (faster for style) + if ( elem.nodeType === 1 ) { + // These attributes require special treatment + var special = rspecialurl.test( name ); + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( name === "selected" && !jQuery.support.optSelected ) { + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + + // If applicable, access the attribute via the DOM 0 way + if ( name in elem && notxml && !special ) { + if ( set ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { + throw "type property can't be changed"; + } + + elem[ name ] = value; + } + + // browsers index elements by id/name on forms, give priority to attributes. + if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { + return elem.getAttributeNode( name ).nodeValue; + } + + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + if ( name === "tabIndex" ) { + var attributeNode = elem.getAttributeNode( "tabIndex" ); + + return attributeNode && attributeNode.specified ? + attributeNode.value : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + + return elem[ name ]; + } + + if ( !jQuery.support.style && notxml && name === "style" ) { + if ( set ) { + elem.style.cssText = "" + value; + } + + return elem.style.cssText; + } + + if ( set ) { + // convert the value to a string (all browsers do this but IE) see #1070 + elem.setAttribute( name, "" + value ); + } + + var attr = !jQuery.support.hrefNormalized && notxml && special ? + // Some attributes require a special call on IE + elem.getAttribute( name, 2 ) : + elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return attr === null ? undefined : attr; + } + + // elem is actually elem.style ... set the style + // Using attr for specific style information is now deprecated. Use style insead. + return jQuery.style( elem, name, value ); + } +}); +var fcleanup = function( nm ) { + return nm.replace(/[^\w\s\.\|`]/g, function( ch ) { + return "\\" + ch; + }); +}; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) { + elem = window; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // if data is passed, bind to handler + if ( data !== undefined ) { + // Create temporary function pointer to original handler + var fn = handler; + + // Create unique handler function, wrapped around original handler + handler = jQuery.proxy( fn ); + + // Store data in unique handler + handler.data = data; + } + + // Init the element's event structure + var events = jQuery.data( elem, "events" ) || jQuery.data( elem, "events", {} ), + handle = jQuery.data( elem, "handle" ), eventHandle; + + if ( !handle ) { + eventHandle = function() { + // Handle the second event of a trigger and when + // an event is called after a page has unloaded + return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + + handle = jQuery.data( elem, "handle", eventHandle ); + } + + // If no handle is found then we must be trying to bind to one of the + // banned noData elements + if ( !handle ) { + return; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native + // event in IE. + handle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split( /\s+/ ); + var type, i=0; + while ( (type = types[ i++ ]) ) { + // Namespaced event handlers + var namespaces = type.split("."); + type = namespaces.shift(); + handler.type = namespaces.slice(0).sort().join("."); + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = this.special[ type ] || {}; + + + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = {}; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, handler) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, handle, false ); + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, handle ); + } + } + } + + if ( special.add ) { + var modifiedHandler = special.add.call( elem, handler, data, namespaces, handlers ); + if ( modifiedHandler && jQuery.isFunction( modifiedHandler ) ) { + modifiedHandler.guid = modifiedHandler.guid || handler.guid; + handler = modifiedHandler; + } + } + + // Add the function to the element's handler list + handlers[ handler.guid ] = handler; + + // Keep track of which events have been used, for global triggering + this.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + var events = jQuery.data( elem, "events" ), ret, type, fn; + + if ( events ) { + // Unbind all events for the element + if ( types === undefined || (typeof types === "string" && types.charAt(0) === ".") ) { + for ( type in events ) { + this.remove( elem, type + (types || "") ); + } + } else { + // types is actually an event object here + if ( types.type ) { + handler = types.handler; + types = types.type; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(/\s+/); + var i = 0; + while ( (type = types[ i++ ]) ) { + // Namespaced event handlers + var namespaces = type.split("."); + type = namespaces.shift(); + var all = !namespaces.length, + cleaned = jQuery.map( namespaces.slice(0).sort(), fcleanup ), + namespace = new RegExp("(^|\\.)" + cleaned.join("\\.(?:.*\\.)?") + "(\\.|$)"), + special = this.special[ type ] || {}; + + if ( events[ type ] ) { + // remove the given handler for the given type + if ( handler ) { + fn = events[ type ][ handler.guid ]; + delete events[ type ][ handler.guid ]; + + // remove all handlers for the given type + } else { + for ( var handle in events[ type ] ) { + // Handle the removal of namespaced events + if ( all || namespace.test( events[ type ][ handle ].type ) ) { + delete events[ type ][ handle ]; + } + } + } + + if ( special.remove ) { + special.remove.call( elem, namespaces, fn); + } + + // remove generic event handler if no more handlers exist + for ( ret in events[ type ] ) { + break; + } + if ( !ret ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, jQuery.data( elem, "handle" ), false ); + } else if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, jQuery.data( elem, "handle" ) ); + } + } + ret = null; + delete events[ type ]; + } + } + } + } + + // Remove the expando if it's no longer used + for ( ret in events ) { + break; + } + if ( !ret ) { + var handle = jQuery.data( elem, "handle" ); + if ( handle ) { + handle.elem = null; + } + jQuery.removeData( elem, "events" ); + jQuery.removeData( elem, "handle" ); + } + } + }, + + // bubbling is internal + trigger: function( event, data, elem /*, bubbling */ ) { + // Event object or event type + var type = event.type || event, + bubbling = arguments[3]; + + if ( !bubbling ) { + event = typeof event === "object" ? + // jQuery.Event object + event[expando] ? event : + // Object literal + jQuery.extend( jQuery.Event(type), event ) : + // Just the event type (string) + jQuery.Event(type); + + if ( type.indexOf("!") >= 0 ) { + event.type = type = type.slice(0, -1); + event.exclusive = true; + } + + // Handle a global trigger + if ( !elem ) { + // Don't bubble custom events when global (to avoid too much overhead) + event.stopPropagation(); + + // Only trigger if we've ever bound an event for it + if ( this.global[ type ] ) { + jQuery.each( jQuery.cache, function() { + if ( this.events && this.events[type] ) { + jQuery.event.trigger( event, data, this.handle.elem ); + } + }); + } + } + + // Handle triggering a single element + + // don't do events on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + // Clean up in case it is reused + event.result = undefined; + event.target = elem; + + // Clone the incoming data, if any + data = jQuery.makeArray( data ); + data.unshift( event ); + } + + event.currentTarget = elem; + + // Trigger the event, it is assumed that "handle" is a function + var handle = jQuery.data( elem, "handle" ); + if ( handle ) { + handle.apply( elem, data ); + } + + var nativeFn, nativeHandler; + try { + if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { + nativeFn = elem[ type ]; + nativeHandler = elem[ "on" + type ]; + } + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (e) {} + + var isClick = jQuery.nodeName(elem, "a") && type === "click"; + + // Trigger the native events (except for clicks on links) + if ( !bubbling && nativeFn && !event.isDefaultPrevented() && !isClick ) { + this.triggered = true; + try { + elem[ type ](); + // prevent IE from throwing an error for some hidden elements + } catch (e) {} + + // Handle triggering native .onfoo handlers + } else if ( nativeHandler && elem[ "on" + type ].apply( elem, data ) === false ) { + event.result = false; + } + + this.triggered = false; + + if ( !event.isPropagationStopped() ) { + var parent = elem.parentNode || elem.ownerDocument; + if ( parent ) { + jQuery.event.trigger( event, data, parent, true ); + } + } + }, + + handle: function( event ) { + // returned undefined or false + var all, handlers; + + event = arguments[0] = jQuery.event.fix( event || window.event ); + event.currentTarget = this; + + // Namespaced event handlers + var namespaces = event.type.split("."); + event.type = namespaces.shift(); + + // Cache this now, all = true means, any handler + all = !namespaces.length && !event.exclusive; + + var namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)"); + + handlers = ( jQuery.data(this, "events") || {} )[ event.type ]; + + for ( var j in handlers ) { + var handler = handlers[ j ]; + + // Filter the functions by class + if ( all || namespace.test(handler.type) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handler; + event.data = handler.data; + + var ret = handler.apply( this, arguments ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + + } + } + + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var doc = document.documentElement, body = document.body; + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) { + event.which = event.charCode || event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( proxy, data, namespaces, live ) { + jQuery.extend( proxy, data || {} ); + + proxy.guid += data.selector + data.live; + jQuery.event.add( this, data.live, liveHandler, data ); + + }, + + remove: function( namespaces ) { + if ( namespaces.length ) { + var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)"); + + jQuery.each( (jQuery.data(this, "events").live || {}), function() { + if ( name.test(this.type) ) { + remove++; + } + }); + + if ( remove < 1 ) { + jQuery.event.remove( this, namespaces[0], liveHandler ); + } + } + }, + special: {} + }, + beforeunload: { + setup: function( data, namespaces, fn ) { + // We only want to do this special case on windows + if ( this.setInterval ) { + this.onbeforeunload = fn; + } + + return false; + }, + teardown: function( namespaces, fn ) { + if ( this.onbeforeunload === fn ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.Event = function( src ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + // Event type + } else { + this.type = src; + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = now(); + + // Mark it as fixed + this[ expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + } + // otherwise set the returnValue property of the original event to false (IE) + e.returnValue = false; + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // Traverse up the tree + while ( parent && parent !== this ) { + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + parent = parent.parentNode; + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { + break; + } + } + + if ( parent !== this ) { + // set the correct event type + event.type = event.data; + + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + +jQuery.event.special.submit = { + setup: function( data, namespaces, fn ) { + if ( this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit." + fn.guid, function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + return trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit." + fn.guid, function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + return trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + remove: function( namespaces, fn ) { + jQuery.event.remove( this, "click.specialSubmit" + (fn ? "."+fn.guid : "") ); + jQuery.event.remove( this, "keypress.specialSubmit" + (fn ? "."+fn.guid : "") ); + } +}; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + +var formElems = /textarea|input|select/i; + +function getVal( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; +} + +function testChange( e ) { + var elem = e.target, data, val; + + if ( !formElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery.data( elem, "_change_data" ); + val = getVal(elem); + + if ( val === data ) { + return; + } + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery.data( elem, "_change_data", val ); + } + + if ( elem.type !== "select" && (data != null || val) ) { + e.type = "change"; + return jQuery.event.trigger( e, arguments[1], this ); + } +} + +jQuery.event.special.change = { + filters: { + focusout: testChange, + + click: function( e ) { + var elem = e.target, type = elem.type; + + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + return testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; + + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + return testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information/focus[in] is not needed anymore + beforeactivate: function( e ) { + var elem = e.target; + + if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" ) { + jQuery.data( elem, "_change_data", getVal(elem) ); + } + } + }, + setup: function( data, namespaces, fn ) { + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] ); + } + + return formElems.test( this.nodeName ); + }, + remove: function( namespaces, fn ) { + for ( var type in changeFilters ) { + jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] ); + } + + return formElems.test( this.nodeName ); + } +}; + +var changeFilters = jQuery.event.special.change.filters; + +} + +function trigger( type, elem, args ) { + args[0].type = type; + return jQuery.event.handle.apply( elem, args ); +} + +// Create "bubbling" focus and blur events +if ( document.addEventListener ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.event.special[ fix ] = { + setup: function() { + this.addEventListener( orig, handler, true ); + }, + teardown: function() { + this.removeEventListener( orig, handler, true ); + } + }; + + function handler( e ) { + e = jQuery.event.fix( e ); + e.type = fix; + return jQuery.event.handle.call( this, e ); + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( jQuery.isFunction( data ) ) { + thisObject = fn; + fn = data; + data = undefined; + } + + var handler = name === "one" ? jQuery.proxy( fn, function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }) : fn; + + return type === "unload" && name !== "one" ? + this.one( type, data, fn, thisObject ) : + this.each(function() { + jQuery.event.add( this, type, handler, data ); + }); + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + return this; + } + + return this.each(function() { + jQuery.event.remove( this, type, fn ); + }); + }, + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + var event = jQuery.Event( type ); + event.preventDefault(); + event.stopPropagation(); + jQuery.event.trigger( event, data, this[0] ); + return event.result; + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, i = 1; + + // link all the functions, so any of them can unbind this click handler + while ( i < args.length ) { + jQuery.proxy( fn, args[ i++ ] ); + } + + return this.click( jQuery.proxy( fn, function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + })); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + }, + + live: function( type, data, fn ) { + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + jQuery( this.context ).bind( liveConvert( type, this.selector ), { + data: data, selector: this.selector, live: type + }, fn ); + + return this; + }, + + die: function( type, fn ) { + jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null ); + return this; + } +}); + +function liveHandler( event ) { + var stop = true, elems = [], selectors = [], args = arguments, + related, match, fn, elem, j, i, data, + live = jQuery.extend({}, jQuery.data( this, "events" ).live); + + for ( j in live ) { + fn = live[j]; + if ( fn.live === event.type || + fn.altLive && jQuery.inArray(event.type, fn.altLive) > -1 ) { + + data = fn.data; + if ( !(data.beforeFilter && data.beforeFilter[event.type] && + !data.beforeFilter[event.type](event)) ) { + selectors.push( fn.selector ); + } + } else { + delete live[j]; + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + for ( j in live ) { + fn = live[j]; + elem = match[i].elem; + related = null; + + if ( match[i].selector === fn.selector ) { + // Those two events require additional checking + if ( fn.live === "mouseenter" || fn.live === "mouseleave" ) { + related = jQuery( event.relatedTarget ).closest( fn.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, fn: fn }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + event.currentTarget = match.elem; + event.data = match.fn.data; + if ( match.fn.apply( match.elem, args ) === false ) { + stop = false; + break; + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "&")].join("."); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( fn ) { + return fn ? this.bind( name, fn ) : this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + +// Prevent memory leaks in IE +// Window isn't included so as not to unbind existing unload events +// More info: +// - http://isaacschlueter.com/2006/10/msie-memory-leaks/ +if ( window.attachEvent && !window.addEventListener ) { + window.attachEvent("onunload", function() { + for ( var id in jQuery.cache ) { + if ( jQuery.cache[ id ].handle ) { + // Try/Catch is to handle iframes being unloaded, see #4280 + try { + jQuery.event.remove( jQuery.cache[ id ].handle.elem ); + } catch(e) {} + } + } + }); +} +/*! + * Sizzle CSS Selector Engine - v1.0 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function(){ + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function(selector, context, results, seed) { + results = results || []; + var origContext = context = context || document; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context), + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + var ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; + } + + if ( context ) { + var ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray(set); + } else { + prune = false; + } + + while ( parts.length ) { + var cur = parts.pop(), pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + throw "Syntax error, unrecognized expression: " + (cur || selector); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + } else if ( context && context.nodeType === 1 ) { + for ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + } else { + for ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function(results){ + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort(sortOrder); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[i-1] ) { + results.splice(i--, 1); + } + } + } + } + + return results; +}; + +Sizzle.matches = function(expr, set){ + return Sizzle(expr, null, null, set); +}; + +Sizzle.find = function(expr, context, isXML){ + var set, match; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var type = Expr.order[i], match; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice(1,1); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace(/\\/g, ""); + set = Expr.find[ type ]( match, context, isXML ); + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = context.getElementsByTagName("*"); + } + + return {set: set, expr: expr}; +}; + +Sizzle.filter = function(expr, set, inplace, not){ + var old = expr, result = [], curLoop = set, match, anyFound, + isXMLFilter = set && set[0] && isXML(set[0]); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var filter = Expr.filter[ type ], found, item, left = match[1]; + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + } else { + curLoop[i] = false; + } + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + throw "Syntax error, unrecognized expression: " + expr; + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + match: { + ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + leftMatch: {}, + attrMap: { + "class": "className", + "for": "htmlFor" + }, + attrHandle: { + href: function(elem){ + return elem.getAttribute("href"); + } + }, + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !/\W/.test(part), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + ">": function(checkSet, part){ + var isPartStr = typeof part === "string"; + + if ( isPartStr && !/\W/.test(part) ) { + part = part.toLowerCase(); + + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + } else { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + "": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + var nodeCheck = part = part.toLowerCase(); + checkFn = dirNodeCheck; + } + + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); + }, + "~": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + var nodeCheck = part = part.toLowerCase(); + checkFn = dirNodeCheck; + } + + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); + } + }, + find: { + ID: function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? [m] : []; + } + }, + NAME: function(match, context){ + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], results = context.getElementsByName(match[1]); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + TAG: function(match, context){ + return context.getElementsByTagName(match[1]); + } + }, + preFilter: { + CLASS: function(match, curLoop, inplace, result, not, isXML){ + match = " " + match[1].replace(/\\/g, "") + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + ID: function(match){ + return match[1].replace(/\\/g, ""); + }, + TAG: function(match, curLoop){ + return match[1].toLowerCase(); + }, + CHILD: function(match){ + if ( match[1] === "nth" ) { + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + ATTR: function(match, curLoop, inplace, result, not, isXML){ + var name = match[1].replace(/\\/g, ""); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + PSEUDO: function(match, curLoop, inplace, result, not){ + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + if ( !inplace ) { + result.push.apply( result, ret ); + } + return false; + } + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + POS: function(match){ + match.unshift( true ); + return match; + } + }, + filters: { + enabled: function(elem){ + return elem.disabled === false && elem.type !== "hidden"; + }, + disabled: function(elem){ + return elem.disabled === true; + }, + checked: function(elem){ + return elem.checked === true; + }, + selected: function(elem){ + // Accessing this property makes selected-by-default + // options in Safari work properly + elem.parentNode.selectedIndex; + return elem.selected === true; + }, + parent: function(elem){ + return !!elem.firstChild; + }, + empty: function(elem){ + return !elem.firstChild; + }, + has: function(elem, i, match){ + return !!Sizzle( match[3], elem ).length; + }, + header: function(elem){ + return /h\d/i.test( elem.nodeName ); + }, + text: function(elem){ + return "text" === elem.type; + }, + radio: function(elem){ + return "radio" === elem.type; + }, + checkbox: function(elem){ + return "checkbox" === elem.type; + }, + file: function(elem){ + return "file" === elem.type; + }, + password: function(elem){ + return "password" === elem.type; + }, + submit: function(elem){ + return "submit" === elem.type; + }, + image: function(elem){ + return "image" === elem.type; + }, + reset: function(elem){ + return "reset" === elem.type; + }, + button: function(elem){ + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + input: function(elem){ + return /input|select|textarea|button/i.test(elem.nodeName); + } + }, + setFilters: { + first: function(elem, i){ + return i === 0; + }, + last: function(elem, i, match, array){ + return i === array.length - 1; + }, + even: function(elem, i){ + return i % 2 === 0; + }, + odd: function(elem, i){ + return i % 2 === 1; + }, + lt: function(elem, i, match){ + return i < match[3] - 0; + }, + gt: function(elem, i, match){ + return i > match[3] - 0; + }, + nth: function(elem, i, match){ + return match[3] - 0 === i; + }, + eq: function(elem, i, match){ + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function(elem, match, i, array){ + var name = match[1], filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + } else if ( name === "not" ) { + var not = match[3]; + + for ( var i = 0, l = not.length; i < l; i++ ) { + if ( not[i] === elem ) { + return false; + } + } + + return true; + } else { + throw "Syntax error, unrecognized expression: " + name; + } + }, + CHILD: function(elem, match){ + var type = match[1], node = elem; + switch (type) { + case 'only': + case 'first': + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + if ( type === "first" ) { + return true; + } + node = elem; + case 'last': + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + return true; + case 'nth': + var first = match[2], last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + if ( first === 0 ) { + return diff === 0; + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + ID: function(elem, match){ + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + TAG: function(elem, match){ + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + CLASS: function(elem, match){ + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + ATTR: function(elem, match){ + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + POS: function(elem, match, i, array){ + var name = match[2], filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){ + return "\\" + (num - 0 + 1); + })); +} + +var makeArray = function(array, results) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 ); + +// Provide a fallback method if it does not work +} catch(e){ + makeArray = function(array, results) { + var ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + } else { + if ( typeof array.length === "number" ) { + for ( var i = 0, l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + } else { + for ( var i = 0; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.compareDocumentPosition ? -1 : 1; + } + + var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( "sourceIndex" in document.documentElement ) { + sortOrder = function( a, b ) { + if ( !a.sourceIndex || !b.sourceIndex ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.sourceIndex ? -1 : 1; + } + + var ret = a.sourceIndex - b.sourceIndex; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( document.createRange ) { + sortOrder = function( a, b ) { + if ( !a.ownerDocument || !b.ownerDocument ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.ownerDocument ? -1 : 1; + } + + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +function getText( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += getText( elem.childNodes ); + } + } + + return ret; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date).getTime(); + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + var root = document.documentElement; + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; + } + }; + + Expr.filter.ID = function(elem, match){ + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + root = form = null; // release memory in IE +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function(match, context){ + var results = context.getElementsByTagName(match[1]); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } + + div = null; // release memory in IE +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, div = document.createElement("div"); + div.innerHTML = "

    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function(query, context, extra, seed){ + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && context.nodeType === 9 && !isXML(context) ) { + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(e){} + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + div = null; // release memory in IE + })(); +} + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function(match, context, isXML) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + div = null; // release memory in IE +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +var contains = document.compareDocumentPosition ? function(a, b){ + return a.compareDocumentPosition(b) & 16; +} : function(a, b){ + return a !== b && (a.contains ? a.contains(b) : true); +}; + +var isXML = function(elem){ + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function(selector, context){ + var tmpSet = [], later = "", match, + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.getText = getText; +jQuery.isXMLDoc = isXML; +jQuery.contains = contains; + +return; + +window.Sizzle = Sizzle; + +})(); +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + slice = Array.prototype.slice; + +// Implement the identical functionality for filter and not +var winnow = function( elements, qualifier, keep ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, elements ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var ret = this.pushStack( "", "find", selector ), length = 0; + + for ( var i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( var n = length; n < ret.length; n++ ) { + for ( var r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && jQuery.filter( selector, this ).length > 0; + }, + + closest: function( selectors, context ) { + if ( jQuery.isArray( selectors ) ) { + var ret = [], cur = this[0], match, matches = {}, selector; + + if ( cur && selectors.length ) { + for ( var i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[selector] ) { + matches[selector] = jQuery.expr.match.POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[selector]; + + if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { + ret.push({ selector: selector, elem: cur }); + delete matches[selector]; + } + } + cur = cur.parentNode; + } + } + + return ret; + } + + var pos = jQuery.expr.match.POS.test( selectors ) ? + jQuery( selectors, context || this.context ) : null; + + return this.map(function( i, cur ) { + while ( cur && cur.ownerDocument && cur !== context ) { + if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) { + return cur; + } + cur = cur.parentNode; + } + return null; + }); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context || this.context ) : + jQuery.makeArray( selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call(arguments).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], cur = elem[dir]; + while ( cur && cur.nodeType !== 9 && (until === undefined || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g, + rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i, + rtagName = /<([\w:]+)/, + rtbody = /"; + }, + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
    ", "
    " ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + col: [ 2, "", "
    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and