polygon intersector: added horizontal line reconstruction
[swftools.git] / lib / devices / file.c
1 /* gfxdevice_file.cc
2
3    Part of the swftools package.
4
5    Copyright (c) 2005 Matthias Kramm <kramm@quiss.org> 
6  
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #ifndef WIN32
24 #include <unistd.h>
25 #endif
26 #include <string.h>
27 #include <memory.h>
28 #include "../gfxdevice.h"
29
30 typedef struct _internal {
31     char*filename;
32     FILE*fi;
33 } internal_t;
34
35 int file_setparameter(struct _gfxdevice*dev, const char*key, const char*value)
36 {
37     internal_t*i = (internal_t*)dev->internal;
38     fprintf(i->fi, "setparameter %s=%s\n", key, value);
39     return 1;
40 }
41
42 void file_startpage(struct _gfxdevice*dev, int width, int height)
43 {
44     internal_t*i = (internal_t*)dev->internal;
45     fprintf(i->fi, "startpage %d %d\n", width, height);
46 }
47
48 static void dumpline(FILE*fi, gfxline_t*line)
49 {
50     while(line) {
51         if(line->type == gfx_moveTo) {
52             fprintf(fi, "\tmoveTo %f %f\n", line->x, line->y);
53         } else if(line->type == gfx_lineTo) {
54             fprintf(fi, "\tlineTo %f %f\n", line->x, line->y);
55         } else if(line->type == gfx_splineTo) {
56             fprintf(fi, "\tsplineTo %f %f %f %f\n", line->sx, line->sy, line->x, line->y);
57         }
58         line = line->next;
59     }
60 }
61
62 static void dumpmatrix (FILE*fi, gfxmatrix_t*matrix)
63 {
64     fprintf(fi, "| %5.2f %5.2f %5.2f\n", matrix->m00, matrix->m10, matrix->tx);
65     fprintf(fi, "| %5.2f %5.2f %5.2f\n", matrix->m01, matrix->m11, matrix->ty);
66 }
67
68 static void dumpgradient (FILE*fi, gfxgradient_t*gradient)
69 {
70     while(gradient) {
71         fprintf(fi, "pos %f: %02x%02x%02x%02x\n", gradient->pos, gradient->color.r, gradient->color.g, gradient->color.b, gradient->color.a);
72         gradient = gradient->next;
73     }
74 }
75
76 void file_startclip(struct _gfxdevice*dev, gfxline_t*line)
77 {
78     internal_t*i = (internal_t*)dev->internal;
79     fprintf(i->fi, "startclip\n");
80     dumpline(i->fi, line);
81 }
82
83 void file_endclip(struct _gfxdevice*dev)
84 {
85     internal_t*i = (internal_t*)dev->internal;
86     fprintf(i->fi, "endclip\n");
87 }
88
89 void file_stroke(struct _gfxdevice*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit)
90 {
91     internal_t*i = (internal_t*)dev->internal;
92     char* jointTypes[] = {"joinMiter", "joinRound", "joinBevel"};
93     char* capTypes[] = {"capButt", "capRound", "capSquare"};
94
95     fprintf(i->fi, "stroke %f %f %s %s %02x%02x%02x%02x\n", width, miterLimit, capTypes[cap_style], jointTypes[joint_style],
96                 color->r, color->g, color->b, color->a
97             );
98     dumpline(i->fi, line);
99 }
100
101 void file_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color)
102 {
103     internal_t*i = (internal_t*)dev->internal;
104     fprintf(i->fi, "fill %02x%02x%02x%02x\n", color->r, color->g, color->b, color->a);
105     dumpline(i->fi, line);
106 }
107
108 void file_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
109 {
110     internal_t*i = (internal_t*)dev->internal;
111     fprintf(i->fi, "fillbitmap\n");
112     dumpmatrix(i->fi, matrix);
113     dumpline(i->fi, line);
114 }
115
116 void file_fillgradient(struct _gfxdevice*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
117 {
118     internal_t*i = (internal_t*)dev->internal;
119     fprintf(i->fi, "fillgradient\n");
120     dumpmatrix(i->fi, matrix);
121     dumpgradient(i->fi, gradient);
122     dumpline(i->fi, line);
123 }
124
125 void file_addfont(struct _gfxdevice*dev, gfxfont_t*font)
126 {
127     internal_t*i = (internal_t*)dev->internal;
128     fprintf(i->fi, "addfont %s\n", font->id);
129 }
130
131 void file_drawchar(struct _gfxdevice*dev, gfxfont_t*font, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix)
132 {
133     internal_t*i = (internal_t*)dev->internal;
134 }
135
136 void file_drawlink(struct _gfxdevice*dev, gfxline_t*line, const char*action)
137 {
138     internal_t*i = (internal_t*)dev->internal;
139     fprintf(i->fi, "drawlink %s\n", action);
140     dumpline(i->fi, line);
141 }
142
143 void file_endpage(struct _gfxdevice*dev)
144 {
145     internal_t*i = (internal_t*)dev->internal;
146     fprintf(i->fi, "endpage\n");
147 }
148
149 typedef struct gfxresult_internal
150 {
151     FILE*fi;
152     char*filename;
153 } gfxresult_internal_t;
154     
155 void fileresult_destroy(struct _gfxresult*gfx)
156 {
157     gfxresult_internal_t*i = (gfxresult_internal_t*)gfx->internal;
158     unlink(i->filename);
159     free(i->filename);i->filename = 0;
160 }
161
162 int fileresult_save(struct _gfxresult*gfx, const char*filename)
163 {
164     gfxresult_internal_t*i = (gfxresult_internal_t*)gfx->internal;
165     FILE*fi,*fo;
166     fi = fopen(i->filename, "rb");
167     if(!fi) {
168         perror(i->filename);
169         return 0;
170     }
171     fo = fopen(filename, "wb");
172     if(!fo) {
173         perror(filename);
174         return 0;
175     }
176
177     char buf[4096];
178     while(!feof(fi)) {
179         int l = fread(buf, 1, 4096, fi);
180         if(l>0) {
181             fwrite(buf, 1, l, fo);
182         } else {
183             break;
184         }
185     }
186
187     fclose(fi);
188     fclose(fo);
189     return 0;
190 }
191
192 void* fileresult_get(struct _gfxresult*gfx, const char*name)
193 {
194     return 0; 
195 }
196
197 gfxresult_t* file_finish(struct _gfxdevice*dev)
198 {
199     internal_t*i = (internal_t*)dev->internal;
200     char*filename = strdup(i->filename);
201     gfxresult_t*result = (gfxresult_t*)malloc(sizeof(gfxresult_t));
202     fclose(i->fi);
203     i->fi = 0;
204     if(i->filename) {
205         free(i->filename);
206         i->filename = 0;
207     }
208     free(dev->internal);
209     dev->internal = 0;
210
211     memset(result, 0, sizeof(gfxresult_t));
212     result->save = fileresult_save;
213     result->get = fileresult_get;
214     result->destroy = fileresult_destroy;
215     result->internal = malloc(sizeof(gfxresult_internal_t));
216     ((gfxresult_internal_t*)result->internal)->filename = filename;
217
218     return result;
219 }
220
221 void gfxdevice_file_init(gfxdevice_t*dev, char*filename)
222 {
223     internal_t*i = (internal_t*)malloc(sizeof(internal_t));
224     memset(dev, 0, sizeof(gfxdevice_t));
225
226     dev->name = "file";
227
228     dev->internal = i;
229
230     dev->setparameter = file_setparameter;
231     dev->startpage = file_startpage;
232     dev->startclip = file_startclip;
233     dev->endclip = file_endclip;
234     dev->stroke = file_stroke;
235     dev->fill = file_fill;
236     dev->fillbitmap = file_fillbitmap;
237     dev->fillgradient = file_fillgradient;
238     dev->addfont = file_addfont;
239     dev->drawchar = file_drawchar;
240     dev->drawlink = file_drawlink;
241     dev->endpage = file_endpage;
242     dev->finish = file_finish;
243
244     i->fi = fopen(filename, "wb");
245     i->filename = strdup(filename);
246     if(!i->fi) {
247         fprintf(stderr, "Couldn't open file %s\n", filename);
248         exit(1);
249     }
250 }
251