Line data Source code
1 : /* Copyright (C) 2000-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include "gpsdrawP.h"
28 : #include "colorP.h"
29 :
30 0 : static void InitFilter(GPSWindow ps) {
31 0 : ps->ascii85encode = 0;
32 0 : ps->ascii85n = 0;
33 0 : ps->ascii85bytes_per_line = 0;
34 0 : }
35 :
36 0 : static void Filter(GPSWindow ps,uint8 ch) {
37 0 : ps->ascii85encode = (ps->ascii85encode<<8) | ch;
38 0 : if ( ++ps->ascii85n == 4 ) {
39 : int c5, c4, c3, c2, c1;
40 0 : uint32 val = ps->ascii85encode;
41 0 : if ( val==0 ) {
42 0 : putc('z',ps->output_file);
43 0 : ps->ascii85n = 0;
44 0 : if ( ++ps->ascii85bytes_per_line >= 76 ) {
45 0 : putc('\n',ps->output_file);
46 0 : ps->ascii85bytes_per_line = 0;
47 : }
48 : } else {
49 0 : c5 = val%85; val /= 85;
50 0 : c4 = val%85; val /= 85;
51 0 : c3 = val%85; val /= 85;
52 0 : c2 = val%85;
53 0 : c1 = val/85;
54 0 : fprintf(ps->output_file, "%c%c%c%c%c",
55 : c1+'!', c2+'!', c3+'!', c4+'!', c5+'!' );
56 0 : ps->ascii85encode = 0;
57 0 : ps->ascii85n = 0;
58 0 : if (( ps->ascii85bytes_per_line+=5) >= 80 ) {
59 0 : putc('\n',ps->output_file);
60 0 : ps->ascii85bytes_per_line = 0;
61 : }
62 : }
63 : }
64 0 : }
65 :
66 0 : static void FlushFilter(GPSWindow ps) {
67 0 : uint32 val = ps->ascii85encode;
68 0 : int n = ps->ascii85n;
69 0 : if ( n!=0 ) {
70 : int c5, c4, c3, c2, c1;
71 0 : while ( n++<4 )
72 0 : val<<=8;
73 0 : c5 = val%85; val /= 85;
74 0 : c4 = val%85; val /= 85;
75 0 : c3 = val%85; val /= 85;
76 0 : c2 = val%85;
77 0 : c1 = val/85;
78 0 : putc(c1+'!',ps->output_file);
79 0 : putc(c2+'!',ps->output_file);
80 0 : if ( ps->ascii85n>=2 )
81 0 : putc(c3+'!',ps->output_file);
82 0 : if ( ps->ascii85n>=3 )
83 0 : putc(c4+'!',ps->output_file);
84 : }
85 0 : putc('~',ps->output_file);
86 0 : putc('>',ps->output_file);
87 0 : putc('\n',ps->output_file);
88 0 : }
89 :
90 0 : static int IsImageStringable(struct _GImage *base,int size,int do_color) {
91 0 : if ( base->image_type==it_true ) {
92 0 : if ( size>(do_color?21000:65000) )
93 0 : return( false );
94 0 : } else if ( base->image_type == it_index ) {
95 0 : if ( size>65000 )
96 0 : return( false );
97 : } else {
98 0 : if ( size>65000*8 )
99 0 : return( false );
100 : }
101 0 : return( true );
102 : }
103 :
104 0 : static void PSBuildImageMonoString(GPSWindow ps,struct _GImage *base,
105 : GRect *src) {
106 : register int j,jj;
107 : int i;
108 : register uint8 *pt;
109 : register int val, res, resbit;
110 :
111 0 : InitFilter(ps);
112 0 : for ( i=src->y; i<src->y+src->height; ++i ) {
113 0 : pt = (uint8 *) (base->data + i*base->bytes_per_line);
114 0 : jj = 1<<(7-(src->x&7)); res=0; resbit=0x80;
115 0 : res=0; resbit = 0x80;
116 0 : for ( j=src->width-1; j>=0; ) {
117 0 : val = *pt++;
118 0 : for ( ; jj!=0 &&j>=0; jj>>=1, --j ) {
119 0 : if ( val&jj )
120 0 : res |= resbit;
121 0 : if (( resbit>>=1 )==0 ) {
122 0 : Filter(ps,res);
123 0 : res = 0; resbit=0x80;
124 : }
125 : }
126 0 : jj = 0x80;
127 : }
128 0 : if ( resbit!=0x80 ) {
129 0 : Filter(ps,res);
130 : }
131 : }
132 0 : FlushFilter(ps);
133 0 : }
134 :
135 0 : static void PSDrawMonoImg(GPSWindow ps,struct _GImage *base,GRect *src, int usefile) {
136 : int width, height;
137 0 : Color col0=0, col1 = COLOR_CREATE(0xff,0xff,0xff);
138 :
139 0 : if ( base->clut!=NULL ) {
140 0 : col0 = base->clut->clut[0];
141 0 : col1 = base->clut->clut[1];
142 : }
143 0 : if ( base->trans==0 )
144 0 : _GPSDraw_SetColor(ps,col1);
145 0 : else if ( base->trans==1 )
146 0 : _GPSDraw_SetColor(ps,col0);
147 :
148 0 : width = src->width;
149 0 : height = src->height;
150 :
151 0 : if ( base->trans==COLOR_UNKNOWN && ps->display->do_color ) {
152 : /* I can't get image to work with the RGB colorspace, but I can */
153 : /* get it to work with an Indexed space. Ghostview crashes when */
154 : /* given a 6 element decode matrix and my printer gives up in */
155 : /* the middle of the blt */
156 0 : fprintf( ps->output_file, "[/Indexed /DeviceRGB 1 < %06X %06X >] setcolorspace\n",
157 : (int) col0, (int) col1 );
158 : }
159 0 : fprintf(ps->output_file, "<<\n" );
160 0 : fprintf(ps->output_file, " /ImageType 1\n" );
161 0 : fprintf(ps->output_file, " /Width %d\n", (int) src->width );
162 0 : fprintf(ps->output_file, " /Height %d\n", (int) src->height );
163 0 : fprintf(ps->output_file, " /ImageMatrix [%d 0 0 %d 0 %d]\n",
164 0 : (int) src->width, (int) -src->height, (int) src->height);
165 0 : fprintf(ps->output_file, " /MultipleDataSources false\n" );
166 0 : fprintf(ps->output_file, " /BitsPerComponent 1\n" );
167 0 : if ( base->trans != COLOR_UNKNOWN ) {
168 0 : if ( base->trans==0 )
169 0 : fprintf(ps->output_file, " /Decode [1 0]\n" );
170 : else
171 0 : fprintf(ps->output_file, " /Decode [0 1]\n" );
172 0 : } else if ( !ps->display->do_color ) {
173 0 : fprintf(ps->output_file, " /Decode [%g %g]\n",
174 0 : COLOR2GREYR(col0), COLOR2GREYR(col1));
175 : } else {
176 0 : fprintf(ps->output_file, " /Decode [0 1]\n" );
177 : }
178 0 : fprintf(ps->output_file, " /Interpolate true\n" );
179 0 : fprintf(ps->output_file, " /DataSource " );
180 0 : if ( usefile ) {
181 0 : fprintf(ps->output_file, "currentfile /ASCII85Decode filter\n" );
182 0 : fprintf(ps->output_file, ">> %s\n",
183 0 : base->trans==COLOR_UNKNOWN?"image":"imagemask" );
184 0 : PSBuildImageMonoString(ps,base,src);
185 : } else {
186 0 : fprintf(ps->output_file, "<~\n" );
187 0 : PSBuildImageMonoString(ps,base,src);
188 0 : fprintf(ps->output_file, ">> %s\n",
189 0 : base->trans==COLOR_UNKNOWN?"image":"imagemask" );
190 : }
191 0 : }
192 :
193 0 : static void PSSetIndexColors(GPSWindow ps,GClut *clut) {
194 : int i;
195 :
196 0 : fprintf( ps->output_file, "[/Indexed /DeviceRGB %d <\n", clut->clut_len-1 );
197 0 : for ( i=0; i<clut->clut_len; ++i )
198 0 : fprintf(ps->output_file, "%02X%02X%02X%s",
199 0 : (unsigned int) COLOR_RED(clut->clut[i]),
200 0 : (unsigned int) COLOR_GREEN(clut->clut[i]),
201 0 : (unsigned int) COLOR_BLUE(clut->clut[i]),
202 0 : i%11==10?"\n":" ");
203 0 : fprintf(ps->output_file,">\n] setcolorspace\n");
204 0 : }
205 :
206 0 : static void PSBuildImageIndexString(GPSWindow ps,struct _GImage *base,GRect *src) {
207 : GCol clut[256];
208 : register int i,val;
209 : register uint8 *pt, *end;
210 0 : int do_color = ps->display->do_color;
211 0 : int clut_len = base->clut->clut_len;
212 :
213 0 : if ( base->clut->is_grey )
214 0 : do_color = false;
215 :
216 0 : for ( i=0; i<256; ++i ) {
217 0 : clut[i].red = COLOR_RED(base->clut->clut[i]);
218 0 : clut[i].green = COLOR_GREEN(base->clut->clut[i]);
219 0 : clut[i].blue = COLOR_BLUE(base->clut->clut[i]);
220 0 : if ( i==base->trans )
221 0 : clut[i].red = clut[i].green = clut[i].blue = 0xff;
222 0 : if ( !do_color )
223 0 : clut[i].red = RGB2GREY(clut[i].red,clut[i].green,clut[i].blue);
224 : }
225 :
226 0 : InitFilter(ps);
227 0 : for ( i=src->y; i<src->y+src->height; ++i ) {
228 0 : pt = (uint8 *) (base->data + i*base->bytes_per_line) + src->x;
229 0 : end = pt + src->width;
230 0 : while ( pt<end ) {
231 0 : val = *pt++;
232 0 : if ( do_color ) {
233 0 : if ( val>=clut_len )
234 0 : val = clut_len-1;
235 0 : Filter(ps,val);
236 : } else {
237 0 : Filter(ps,clut[val].red);
238 : }
239 : }
240 : }
241 0 : FlushFilter(ps);
242 0 : }
243 :
244 0 : static void PSBuildImageIndexDict(GPSWindow ps,struct _GImage *base,GRect *src, int usefile) {
245 0 : fprintf(ps->output_file, "<<\n" );
246 0 : fprintf(ps->output_file, " /ImageType 1\n" );
247 0 : fprintf(ps->output_file, " /Width %d\n", (int) src->width );
248 0 : fprintf(ps->output_file, " /Height %d\n", (int) src->height );
249 0 : fprintf(ps->output_file, " /ImageMatrix [%d 0 0 %d 0 %d]\n",
250 0 : (int) src->width, (int) -src->height, (int) src->height);
251 0 : fprintf(ps->output_file, " /MultipleDataSources false\n" );
252 0 : fprintf(ps->output_file, " /BitsPerComponent 8\n" );
253 0 : fprintf(ps->output_file, " /Decode [0 255]\n" );
254 0 : fprintf(ps->output_file, " /Interpolate false\n" );
255 0 : fprintf(ps->output_file, " /DataSource " );
256 0 : if ( usefile ) {
257 0 : fprintf(ps->output_file, "currentfile /ASCII85Decode filter\n" );
258 0 : fprintf(ps->output_file, ">> image\n" );
259 0 : PSBuildImageIndexString(ps,base,src);
260 : } else {
261 0 : fprintf(ps->output_file, "<~\n" );
262 0 : PSBuildImageIndexString(ps,base,src);
263 0 : fprintf(ps->output_file, "\n>> image\n" );
264 : }
265 0 : }
266 :
267 0 : static void PSBuildImage24String(GPSWindow ps,struct _GImage *base,GRect *src) {
268 : int i;
269 0 : register long val, trans = base->trans;
270 : register uint32 *pt, *end;
271 0 : int do_color = ps->display->do_color;
272 :
273 0 : InitFilter(ps);
274 0 : for ( i=src->y; i<src->y+src->height; ++i ) {
275 0 : pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
276 0 : end = pt + src->width;
277 0 : while ( pt<end ) {
278 0 : if ((val = *pt++)==trans ) val = COLOR_CREATE(0xff,0xff,0xff);
279 0 : if ( do_color ) {
280 0 : Filter(ps,COLOR_RED(val));
281 0 : Filter(ps,COLOR_GREEN(val));
282 0 : Filter(ps,COLOR_BLUE(val));
283 : } else {
284 0 : Filter(ps,COLOR2GREY(val));
285 : }
286 : }
287 : }
288 0 : FlushFilter(ps);
289 0 : }
290 :
291 0 : static void PSBuildImageClutMaskString(GPSWindow ps,struct _GImage *base,GRect *src) {
292 : int i;
293 0 : int trans = base->trans;
294 : register uint8 *pt, *end;
295 : register int res,val, resbit;
296 :
297 0 : InitFilter(ps);
298 0 : for ( i=src->y; i<src->y+src->height; ++i ) {
299 0 : pt = (uint8 *) (base->data + i*base->bytes_per_line) + src->x;
300 0 : end = pt + src->width;
301 0 : res=0; resbit = 0x80;
302 0 : while ( pt<end ) {
303 0 : val = *pt++;
304 0 : if ( val!=trans ) /* Want to draw non transparent bits */
305 0 : res |= resbit;
306 0 : if (( resbit>>=1 )==0 ) {
307 0 : Filter(ps,res);
308 0 : res = 0; resbit=0x80;
309 : }
310 : }
311 0 : if ( resbit!=0x80 ) {
312 0 : Filter(ps,res);
313 : }
314 : }
315 0 : FlushFilter(ps);
316 0 : }
317 :
318 0 : static void PSBuildImage24MaskString(GPSWindow ps,struct _GImage *base,GRect *src) {
319 : int i;
320 0 : register Color val, trans = base->trans;
321 : register uint32 *pt, *end;
322 : register int res, resbit;
323 :
324 0 : InitFilter(ps);
325 0 : for ( i=src->y; i<src->y+src->height; ++i ) {
326 0 : pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
327 0 : end = pt + src->width;
328 0 : res=0; resbit = 0x80;
329 0 : while ( pt<end ) {
330 0 : val = *pt++;
331 0 : if ( val!=trans ) /* Want to draw non transparent bits */
332 0 : res |= resbit;
333 0 : if (( resbit>>=1 )==0 ) {
334 0 : Filter(ps,res);
335 0 : res = 0; resbit=0x80;
336 : }
337 : }
338 0 : if ( resbit!=0x80 ) {
339 0 : Filter(ps,res);
340 : }
341 : }
342 0 : FlushFilter(ps);
343 0 : }
344 :
345 0 : static void PSDrawImg(GPSWindow ps,struct _GImage *base,GRect *src, int usefile) {
346 : short width, height;
347 : /* when building up a pattern we put the image into a string rather than */
348 : /* trying to read from a file (file is long past that point). This */
349 : /* doesn't work normally as the string can get too long. We limit */
350 : /* the images that we are willing to display transparently... */
351 0 : int do_color = ps->display->do_color;
352 0 : int usedict = false;
353 :
354 0 : if ( base->image_type == it_index && GImageGreyClut(base->clut))
355 0 : do_color = false;
356 0 : if ( base->image_type == it_index && do_color )
357 0 : usedict = true;
358 :
359 0 : width = src->width;
360 0 : height = src->height;
361 :
362 0 : if ( usedict ) {
363 0 : PSSetIndexColors(ps,base->clut);
364 0 : PSBuildImageIndexDict(ps,base,src,usefile);
365 0 : fprintf(ps->output_file, "[/DeviceRGB] setcolorspace\n" );
366 0 : ps->cur_fg = COLOR_CREATE(0,0,0);
367 : } else {
368 0 : fprintf(ps->output_file, "%d %d 8 [%d 0 0 %d 0 %d] ",
369 : width, height, width, -height, height);
370 0 : if ( !usefile )
371 0 : fprintf(ps->output_file, "<~\n" ); /* start a string */
372 : else {
373 0 : fprintf(ps->output_file, "currentfile /ASCII85Decode filter " );
374 0 : if ( do_color )
375 0 : fprintf(ps->output_file, "false 3 colorimage\n" );
376 : else
377 0 : fprintf(ps->output_file, "image\n" );
378 : }
379 0 : if ( base->image_type==it_index )
380 0 : PSBuildImageIndexString(ps,base,src);
381 : else
382 0 : PSBuildImage24String(ps,base,src);
383 0 : if ( !usefile ) {
384 0 : if ( ps->display->do_color )
385 0 : fprintf(ps->output_file, "false 3 colorimage\n" );
386 : else
387 0 : fprintf(ps->output_file, "image\n" );
388 : }
389 : }
390 0 : }
391 :
392 0 : static void PSDrawImage(GPSWindow ps,GImage *image, GRect *dest, GRect *src) {
393 0 : struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
394 0 : Color trans = base->trans;
395 : short width, height;
396 :
397 0 : _GPSDraw_SetClip(ps);
398 :
399 0 : width = src->width;
400 0 : height = src->height;
401 :
402 0 : if ( trans!=COLOR_UNKNOWN ) {
403 : /* We don't try to get tranparent images to work if they are bigger */
404 : /* than 64k. Strings are limited to that amount and we use strings */
405 : /* for our masks. (well, mono images are a special case) */
406 0 : if ( !ps->display->do_transparent )
407 0 : trans = COLOR_UNKNOWN;
408 0 : else if ( !IsImageStringable(base,width*height,ps->display->do_color) )
409 0 : trans = COLOR_UNKNOWN;
410 : }
411 :
412 0 : fprintf( ps->output_file, " gsave %g %g translate %g %g scale\n",
413 0 : _GSPDraw_XPos(ps,dest->x), _GSPDraw_YPos(ps,dest->y+dest->height),
414 : _GSPDraw_Distance(ps,dest->width),_GSPDraw_Distance(ps,dest->height) );
415 0 : if ( base->image_type==it_mono ) {
416 0 : PSDrawMonoImg(ps,base,src,true);
417 0 : } else if ( trans==COLOR_UNKNOWN ) {
418 : /* Just draw the image, don't worry about if it's transparent */
419 0 : PSDrawImg(ps,base,src,true);
420 : } else {
421 0 : fprintf( ps->output_file, " save mark\t%% Create a temporary pattern for trans image\n");
422 0 : fprintf( ps->output_file, "<< /PatternType 1\n" );
423 0 : fprintf( ps->output_file, " /PaintType 1\n" ); /* coloured pattern */
424 0 : fprintf( ps->output_file, " /TilingType 2\n" ); /* Allow PS to distort pattern to make it fit */
425 0 : fprintf( ps->output_file, " /BBox [0 0 1 1]\n" );
426 0 : fprintf( ps->output_file, " /XStep 1 /YStep 1\n" );
427 0 : fprintf( ps->output_file, " /PaintProc { pop " );
428 0 : PSDrawImg(ps,base,src,false);
429 0 : fprintf( ps->output_file, "} >> matrix makepattern /TransPattern exch def\n" );
430 0 : fprintf( ps->output_file, " TransPattern setpattern\n");
431 0 : fprintf(ps->output_file, "%d %d true [%d 0 0 %d 0 %d] currentfile /ASCII85Decode filter imagemask\n",
432 0 : (int) base->width, (int) base->height, (int) base->width, (int) -base->height, (int) base->height);
433 0 : if ( base->image_type==it_index )
434 0 : PSBuildImageClutMaskString(ps,base,src);
435 : else
436 0 : PSBuildImage24MaskString(ps,base,src);
437 0 : fprintf( ps->output_file, " /TransPattern /Pattern undefineresource cleartomark restore\n");
438 : }
439 0 : fprintf( ps->output_file, " grestore\n" );
440 0 : }
441 :
442 0 : static int PSBuildImagePattern(GPSWindow ps,struct _GImage *base, char *pattern_name) {
443 0 : GPSDisplay *gdisp = ps->display;
444 : GRect src;
445 0 : int factor = gdisp->scale_screen_by;
446 :
447 0 : if ( !IsImageStringable(base,base->width*base->height,gdisp->do_color))
448 0 : return( false );
449 0 : src.x = src.y = 0; src.width = base->width; src.height = base->height;
450 :
451 0 : fprintf( ps->output_file, " gsave %g %g scale\n",
452 0 : base->width*factor*72.0/ps->res,
453 0 : base->height*factor*72.0/ps->res );
454 :
455 0 : if ( base->image_type!=it_mono && base->trans!=(Color)-1 ) {
456 : /* Must build a secondary pattern through which the primary pattern */
457 : /* will mask */
458 0 : fprintf( ps->output_file, "<< /PatternType 1\n" );
459 0 : fprintf( ps->output_file, " /PaintType 1\n" ); /* coloured pattern */
460 0 : fprintf( ps->output_file, " /TilingType 2\n" ); /* Allow PS to distort pattern to make it fit */
461 0 : fprintf( ps->output_file, " /BBox [0 0 1 1]\n" );
462 0 : fprintf( ps->output_file, " /XStep 1 /YStep 1\n" );
463 0 : fprintf( ps->output_file, " /PaintProc { pop " );
464 0 : PSDrawImg(ps,base,&src,false);
465 0 : fprintf( ps->output_file, "} >> matrix makepattern /%s_Secondary exch def\n", pattern_name );
466 : }
467 0 : fprintf( ps->output_file, "<< /PatternType 1\n" );
468 0 : fprintf( ps->output_file, " /PaintType 1\n" ); /* coloured pattern */
469 0 : fprintf( ps->output_file, " /TilingType 2\n" ); /* Allow PS to distort pattern to make it fit */
470 0 : fprintf( ps->output_file, " /BBox [0 0 1 1]\n" );
471 0 : fprintf( ps->output_file, " /XStep 1 /YStep 1\n" );
472 0 : fprintf( ps->output_file, " /PaintProc { pop " );
473 0 : if ( base->image_type==it_mono ) {
474 0 : PSDrawMonoImg(ps,base,&src,false);
475 0 : } else if ( base->trans==COLOR_UNKNOWN || !gdisp->do_transparent ) {
476 : /* Just draw the image, don't worry about if it's transparent */
477 0 : PSDrawImg(ps,base,&src,false);
478 : } else {
479 0 : fprintf( ps->output_file, " %s_Secondary setpattern\n", pattern_name);
480 0 : fprintf(ps->output_file, "%d %d true [%d 0 0 %d 0 %d] <~",
481 0 : (int) base->width, (int) base->height, (int) base->width, (int) -base->height, (int) base->height);
482 0 : if ( base->image_type==it_index )
483 0 : PSBuildImageClutMaskString(ps,base,&src);
484 : else
485 0 : PSBuildImage24MaskString(ps,base,&src);
486 0 : fprintf(ps->output_file, "imagemask \n" );
487 : }
488 0 : fprintf( ps->output_file, "} >> matrix makepattern /%s exch def\n", pattern_name );
489 0 : fprintf( ps->output_file, " grestore\n" );
490 0 : return( true );
491 : }
492 :
493 0 : void _GPSDraw_InitPatterns(GPSWindow ps) {
494 :
495 : /* Need to output pattern defn for dotted filling, background fill pattern??? */
496 0 : fprintf( ps->init_file, "\n%%Global Patterns\n" );
497 0 : fprintf( ps->init_file, "%% Dithering pattern\n" );
498 0 : fprintf( ps->init_file, "<< /PatternType 1\n" );
499 0 : fprintf( ps->init_file, " /PaintType 2\n" ); /* Uncoloured pattern */
500 0 : fprintf( ps->init_file, " /TilingType 3\n" ); /* Allow PS to distort pattern to make it fit */
501 0 : fprintf( ps->init_file, " /BBox [0 0 2 2]\n" );
502 0 : fprintf( ps->init_file, " /XStep 2 /YStep 2\n" );
503 0 : fprintf( ps->init_file, " /PaintProc { pop 0 0 moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto closepath fill\n" );
504 0 : fprintf( ps->init_file, "\t\t 1 1 moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto closepath fill }\n" );
505 0 : fprintf( ps->init_file, ">> matrix makepattern /DotPattern exch def\n\n" );
506 0 : }
507 :
508 0 : static int PSTileImage(GPSWindow ps,struct _GImage *base, long x, long y,
509 : int repeatx, int repeaty ) {
510 0 : char *pattern_name = NULL;
511 0 : int factor = ps->display->scale_screen_by;
512 :
513 0 : _GPSDraw_SetClip(ps);
514 : {
515 0 : if ( !IsImageStringable(base,base->width*base->height,ps->display->do_color) )
516 0 : return( false );
517 0 : if ( repeatx==1 && repeaty==1 )
518 0 : return( false ); /* Not worth it for just one drawing */
519 0 : fprintf( ps->output_file, " save mark\t%% Create a temporary pattern for tiling the background\n");
520 0 : pattern_name = "g_background_pattern";
521 0 : PSBuildImagePattern(ps,base, pattern_name);
522 : }
523 :
524 0 : fprintf( ps->output_file, " %s setpattern\n", pattern_name );
525 0 : _GPSDraw_FlushPath(ps);
526 0 : fprintf( ps->output_file, " %g %g %g %g %g %g %g %g g_quad fill\n",
527 0 : _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y+repeaty*base->height*factor),
528 0 : _GSPDraw_XPos(ps,x+repeatx*base->width*factor), _GSPDraw_YPos(ps,y+repeaty*base->height*factor),
529 0 : _GSPDraw_XPos(ps,x+repeatx*base->width*factor), _GSPDraw_YPos(ps,y),
530 : _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y));
531 0 : if ( base->image_type!=it_mono && base->trans!=COLOR_UNKNOWN &&
532 0 : ps->display->do_transparent )
533 0 : fprintf( ps->output_file, " /g_background_pattern_Secondary /Pattern undefineresource\n" );
534 0 : fprintf( ps->output_file, " /g_background_pattern /Pattern undefineresource cleartomark restore\n" );
535 0 : return( true );
536 : }
537 :
538 0 : void _GPSDraw_Image(GWindow w, GImage *image, GRect *src, int32 x, int32 y) {
539 0 : GPSWindow ps = (GPSWindow) w;
540 : GRect dest;
541 0 : int factor = ps->display->scale_screen_by;
542 :
543 0 : dest.x = x; dest.y = y;
544 0 : dest.width = src->width*factor;
545 0 : dest.height = src->height*factor;
546 0 : PSDrawImage(ps,image,&dest,src);
547 0 : }
548 :
549 0 : void _GPSDraw_ImageMagnified(GWindow w, GImage *image, GRect *dest, int32 x, int32 y, int32 width, int32 height) {
550 0 : GPSWindow ps = (GPSWindow) w;
551 0 : struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
552 : GRect src,temp;
553 :
554 0 : src.width = (dest->width/(double) width)*base->width;
555 0 : src.height = (dest->height/(double) height)*base->height;
556 0 : src.x = dest->x * (base->width/(double) width);
557 0 : src.y = dest->y * (base->height/(double) height);
558 0 : temp.x = x; temp.y = y; temp.width = dest->width; temp.height = dest->height;
559 0 : PSDrawImage(ps,image,&temp,&src);
560 0 : }
561 :
562 0 : void _GPSDraw_TileImage(GWindow w, GImage *image, GRect *dest, int32 x, int32 y) {
563 0 : GPSWindow ps = (GPSWindow) w;
564 0 : struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
565 : int xstart, ystart, xend, yend;
566 0 : int factor = ps->display->scale_screen_by;
567 0 : int width = factor*base->width, height = factor*base->height;
568 : int i,j;
569 :
570 0 : xstart = (dest->x-x)/width; ystart = (dest->y-y)/height;
571 0 : xend = (dest->x+dest->width-x)/width; yend = (dest->y+dest->height-y)/height;
572 0 : if ( !PSTileImage(ps,base,
573 0 : x+xstart*width,y+ystart*height,
574 0 : xend-xstart+1,yend-ystart+1)) {
575 0 : GRect src; src.x = src.y = 0; src.width = base->width; src.height = height;
576 0 : for ( j=ystart; j<=yend; ++j ) for ( i=xstart; i<=xend; ++i ) {
577 : GRect dest;
578 0 : dest.x = x+i*width; dest.y = y+j*height;
579 0 : dest.width = width; dest.height = height;
580 0 : PSDrawImage(ps,image, &dest, &src);
581 : }
582 : }
583 0 : }
|