Fixed GetOpenFileName and GetSaveFileName dialogs.
[wine/testsucceed.git] / graphics / psdrv / ps.c
blobd301c36082ba073d36f4f66ed20f59c8b629c4d4
1 /*
2 * PostScript output functions
4 * Copyright 1998 Huw D M Davies
6 */
8 #include <ctype.h>
9 #include <string.h>
10 #include "windows.h"
11 #include "psdrv.h"
12 #include "print.h"
13 #include "debug.h"
15 static char psheader[] = /* title llx lly urx ury orientation */
16 "%%!PS-Adobe-3.0\n"
17 "%%%%Creator: Wine PostScript Driver\n"
18 "%%%%Title: %s\n"
19 "%%%%BoundingBox: %d %d %d %d\n"
20 "%%%%Pages: (atend)\n"
21 "%%%%Orientation: %s\n"
22 "%%%%EndComments\n";
24 static char psbeginprolog[] =
25 "%%BeginProlog\n";
27 static char psendprolog[] =
28 "%%EndProlog\n";
30 static char psvectorstart[] =
31 "/ANSIEncoding [\n";
33 static char psvectorend[] =
34 "] def\n";
36 static char psprolog[] = /* output ANSIEncoding vector first */
37 "/reencodefont {\n"
38 "findfont\n"
39 "dup length dict begin\n"
40 "{1 index /FID ne {def} {pop pop} ifelse} forall\n"
41 "/Encoding ANSIEncoding def\n"
42 "currentdict\n"
43 "end\n"
44 "definefont pop\n"
45 "} bind def\n"
46 "/tmpmtrx matrix def\n";
48 static char psbeginsetup[] =
49 "%%BeginSetup\n";
51 static char psendsetup[] =
52 "%%EndSetup\n";
54 static char psbeginfeature[] = /* feature, value */
55 "mark {\n"
56 "%%%%BeginFeature: %s %s\n";
58 static char psendfeature[] =
59 "\n%%EndFeature\n"
60 "} stopped cleartomark\n";
62 static char psnewpage[] = /* name, number, xres, yres, xtrans, ytrans, rot */
63 "%%%%Page: %s %d\n"
64 "%%%%BeginPageSetup\n"
65 "/pgsave save def\n"
66 "72 %d div 72 %d div scale\n"
67 "%d %d translate\n"
68 "1 -1 scale\n"
69 "%d rotate\n"
70 "%%%%EndPageSetup\n";
72 static char psendpage[] =
73 "pgsave restore\n"
74 "showpage\n";
76 static char psfooter[] = /* pages */
77 "%%%%Trailer\n"
78 "%%%%Pages: %d\n"
79 "%%%%EOF\n";
81 static char psmoveto[] = /* x, y */
82 "%d %d moveto\n";
84 static char pslineto[] = /* x, y */
85 "%d %d lineto\n";
87 static char psstroke[] =
88 "stroke\n";
90 static char psrectangle[] = /* x, y, width, height, -width */
91 "%d %d moveto\n"
92 "%d 0 rlineto\n"
93 "0 %d rlineto\n"
94 "%d 0 rlineto\n"
95 "closepath\n";
97 static char psshow[] = /* string */
98 "(%s) show\n";
100 static char pssetfont[] = /* fontname, xscale, yscale, ascent, escapement */
101 "/%s findfont\n"
102 "[%d 0 0 %d 0 0]\n"
103 "%d 10 div matrix rotate\n"
104 "matrix concatmatrix\n"
105 "makefont setfont\n";
107 static char pssetlinewidth[] = /* width */
108 "%d setlinewidth\n";
110 static char pssetdash[] = /* dash, offset */
111 "[%s] %d setdash\n";
113 static char pssetgray[] = /* gray */
114 "%.2f setgray\n";
116 static char pssetrgbcolor[] = /* r, g, b */
117 "%.2f %.2f %.2f setrgbcolor\n";
119 static char psellipse[] = /* x, y, a, b */
120 "tmpmtrx currentmatrix pop\n"
121 "%d %d translate\n"
122 "%d %d scale\n"
123 "0 0 1 0 360 arc\n"
124 "tmpmtrx setmatrix\n";
126 static char psgsave[] =
127 "gsave\n";
129 static char psgrestore[] =
130 "grestore\n";
132 static char psfill[] =
133 "fill\n";
135 char *PSDRV_ANSIVector[256] = {
136 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
137 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
138 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
139 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
140 "space", "exclam", "quotedbl", "numbersign",
141 "dollar", "percent", "ampersand", "quotesingle",
142 "parenleft", "parenright", "asterisk", "plus",
143 "comma", "hyphen", "period", "slash",
144 "zero", "one", "two", "three",
145 "four", "five", "six", "seven",
146 "eight", "nine", "colon", "semicolon",
147 "less", "equal", "greater", "question",
148 "at", "A", "B", "C",
149 "D", "E", "F", "G",
150 "H", "I", "J", "K",
151 "L", "M", "N", "O",
152 "P", "Q", "R", "S",
153 "T", "U", "V", "W",
154 "X", "Y", "Z", "bracketleft",
155 "backslash", "bracketright", "asciicircum", "underscore",
156 "grave", "a", "b", "c",
157 "d", "e", "f", "g",
158 "h", "i", "j", "k",
159 "l", "m", "n", "o",
160 "p", "q", "r", "s",
161 "t", "u", "v", "w",
162 "x", "y", "z", "braceleft",
163 "bar", "braceright", "asciitilde", NULL,
164 NULL, NULL, NULL, NULL,
165 NULL, NULL, NULL, NULL,
166 NULL, NULL, NULL, NULL,
167 NULL, NULL, NULL, NULL,
168 NULL, "quoteleft", "quoteright", NULL,
169 NULL, NULL, NULL, NULL,
170 NULL, NULL, NULL, NULL,
171 NULL, NULL, NULL, NULL,
172 NULL, "exclamdown", "cent", "sterling",
173 "currency", "yen", "brokenbar", "section",
174 "dieresis", "copyright", "ordfeminine", "guillemotleft",
175 "logicalnot", "hyphen", "registered", "macron",
176 "degree", "plusminus", "twosuperior", "threesuperior",
177 "acute", "mu", "paragraph", "periodcentered",
178 "cedilla", "onesuperior", "ordmasculine", "guillemotright",
179 "onequarter", "onehalf", "threequarters","questiondown",
180 "Agrave", "Aacute", "Acircumflex", "Atilde",
181 "Adieresis", "Aring", "AE", "Ccedilla",
182 "Egrave", "Eacute", "Ecircumflex", "Edieresis",
183 "Igrave", "Iacute", "Icircumflex", "Idieresis",
184 "Eth", "Ntilde", "Ograve", "Oacute",
185 "Ocircumflex", "Otilde", "Odieresis", "multiply",
186 "Oslash", "Ugrave", "Uacute", "Ucircumflex",
187 "Udieresis", "Yacute", "Thorn", "germandbls",
188 "agrave", "aacute", "acircumflex", "atilde",
189 "adieresis", "aring", "ae", "ccedilla",
190 "egrave", "eacute", "ecircumflex", "edieresis",
191 "igrave", "iacute", "icircumflex", "idieresis",
192 "eth", "ntilde", "ograve", "oacute",
193 "ocircumflex", "otilde", "odieresis", "divide",
194 "oslash", "ugrave", "uacute", "ucircumflex",
195 "udieresis", "yacute", "thorn", "ydieresis"
199 char psreencodefont[] = /* newfontname basefontname*/
200 "/%s /%s reencodefont\n";
203 int PSDRV_WriteSpool(DC *dc, LPSTR lpData, WORD cch)
205 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
207 if(physDev->job.NeedPageHeader) {
208 physDev->job.PageNo++;
209 if( !PSDRV_WriteNewPage(dc) )
210 return FALSE;
211 physDev->job.NeedPageHeader = FALSE;
213 return WriteSpool( physDev->job.hJob, lpData, cch );
217 INT32 PSDRV_WriteFeature(HANDLE16 hJob, char *feature, char *value,
218 char *invocation)
221 char *buf = (char *)HeapAlloc( PSDRV_Heap, 0, sizeof(psheader) +
222 strlen(feature) + strlen(value));
225 sprintf(buf, psbeginfeature, feature, value);
226 WriteSpool( hJob, buf, strlen(buf) );
228 WriteSpool( hJob, invocation, strlen(invocation) );
230 WriteSpool( hJob, psendfeature, strlen(psendfeature) );
232 HeapFree( PSDRV_Heap, 0, buf );
233 return 1;
238 INT32 PSDRV_WriteHeader( DC *dc, char *title, int len )
240 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
241 char *buf, *titlebuf, *orient, vectbuf[256];
242 INPUTSLOT *slot;
243 PAGESIZE *page;
244 int urx, ury, i, j;
246 titlebuf = (char *)HeapAlloc( PSDRV_Heap, 0, len+1 );
247 if(!titlebuf) {
248 WARN(psdrv, "HeapAlloc failed\n");
249 return 0;
251 memcpy(titlebuf, title, len);
252 titlebuf[len] = '\0';
254 buf = (char *)HeapAlloc( PSDRV_Heap, 0, sizeof(psheader) + len + 30);
255 if(!buf) {
256 WARN(psdrv, "HeapAlloc failed\n");
257 HeapFree( PSDRV_Heap, 0, titlebuf );
258 return 0;
261 if(physDev->Devmode->dmPublic.dmOrientation == DMORIENT_LANDSCAPE) {
262 /* BBox co-ords are in default user co-ord system so urx < ury even in
263 landscape mode */
264 urx = (int) (dc->w.devCaps->vertSize * 72.0 / 25.4);
265 ury = (int) (dc->w.devCaps->horzSize * 72.0 / 25.4);
266 orient = "Landscape";
267 } else {
268 urx = (int) (dc->w.devCaps->horzSize * 72.0 / 25.4);
269 ury = (int) (dc->w.devCaps->vertSize * 72.0 / 25.4);
270 orient = "Portrait";
273 /* FIXME should do something better with BBox */
275 sprintf(buf, psheader, title, 0, 0, urx, ury, orient);
277 if( WriteSpool( physDev->job.hJob, buf, strlen(buf) ) !=
278 strlen(buf) ) {
279 WARN(psdrv, "WriteSpool error\n");
280 HeapFree( PSDRV_Heap, 0, titlebuf );
281 HeapFree( PSDRV_Heap, 0, buf );
282 return 0;
284 HeapFree( PSDRV_Heap, 0, titlebuf );
285 HeapFree( PSDRV_Heap, 0, buf );
287 WriteSpool( physDev->job.hJob, psbeginprolog, strlen(psbeginprolog) );
288 WriteSpool( physDev->job.hJob, psvectorstart, strlen(psvectorstart) );
290 for(i = 0; i < 256; i += 8) {
291 vectbuf[0] = '\0';
292 for(j = 0; j < 8; j++) {
293 strcat(vectbuf, "/");
294 if(PSDRV_ANSIVector[i+j]) {
295 strcat(vectbuf, PSDRV_ANSIVector[i+j]);
296 strcat(vectbuf, " ");
297 } else {
298 strcat(vectbuf, ".notdef ");
301 strcat(vectbuf, "\n");
302 WriteSpool( physDev->job.hJob, vectbuf, strlen(vectbuf) );
305 WriteSpool( physDev->job.hJob, psvectorend, strlen(psvectorend) );
306 WriteSpool( physDev->job.hJob, psprolog, strlen(psprolog) );
307 WriteSpool( physDev->job.hJob, psendprolog, strlen(psendprolog) );
310 WriteSpool( physDev->job.hJob, psbeginsetup, strlen(psbeginsetup) );
312 for(slot = physDev->pi->ppd->InputSlots; slot; slot = slot->next) {
313 if(slot->WinBin == physDev->Devmode->dmPublic.dmDefaultSource) {
314 if(slot->InvocationString) {
315 PSDRV_WriteFeature(physDev->job.hJob, "*InputSlot", slot->Name,
316 slot->InvocationString);
317 break;
322 for(page = physDev->pi->ppd->PageSizes; page; page = page->next) {
323 if(page->WinPage == physDev->Devmode->dmPublic.dmPaperSize) {
324 if(page->InvocationString) {
325 PSDRV_WriteFeature(physDev->job.hJob, "*PageSize", page->Name,
326 page->InvocationString);
327 break;
332 WriteSpool( physDev->job.hJob, psendsetup, strlen(psendsetup) );
335 return 1;
339 INT32 PSDRV_WriteFooter( DC *dc )
341 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
342 char *buf;
344 buf = (char *)HeapAlloc( PSDRV_Heap, 0, sizeof(psfooter) + 100 );
345 if(!buf) {
346 WARN(psdrv, "HeapAlloc failed\n");
347 return 0;
350 sprintf(buf, psfooter, physDev->job.PageNo);
352 if( WriteSpool( physDev->job.hJob, buf, strlen(buf) ) !=
353 strlen(buf) ) {
354 WARN(psdrv, "WriteSpool error\n");
355 HeapFree( PSDRV_Heap, 0, buf );
356 return 0;
358 HeapFree( PSDRV_Heap, 0, buf );
359 return 1;
364 INT32 PSDRV_WriteEndPage( DC *dc )
366 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
368 if( WriteSpool( physDev->job.hJob, psendpage, sizeof(psendpage)-1 ) !=
369 sizeof(psendpage)-1 ) {
370 WARN(psdrv, "WriteSpool error\n");
371 return 0;
373 return 1;
379 INT32 PSDRV_WriteNewPage( DC *dc )
381 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
382 char *buf;
383 char name[100];
384 signed int xtrans, ytrans, rotation;
386 sprintf(name, "%d", physDev->job.PageNo);
388 buf = (char *)HeapAlloc( PSDRV_Heap, 0, sizeof(psnewpage) + 200 );
389 if(!buf) {
390 WARN(psdrv, "HeapAlloc failed\n");
391 return 0;
394 if(physDev->Devmode->dmPublic.dmOrientation == DMORIENT_LANDSCAPE) {
395 if(physDev->pi->ppd->LandscapeOrientation == -90) {
396 xtrans = dc->w.devCaps->vertRes;
397 ytrans = dc->w.devCaps->horzRes;
398 rotation = 90;
399 } else {
400 xtrans = ytrans = 0;
401 rotation = -90;
403 } else {
404 xtrans = 0;
405 ytrans = dc->w.devCaps->vertRes;
406 rotation = 0;
409 sprintf(buf, psnewpage, name, physDev->job.PageNo,
410 dc->w.devCaps->logPixelsX, dc->w.devCaps->logPixelsY,
411 xtrans, ytrans, rotation);
413 if( WriteSpool( physDev->job.hJob, buf, strlen(buf) ) !=
414 strlen(buf) ) {
415 WARN(psdrv, "WriteSpool error\n");
416 HeapFree( PSDRV_Heap, 0, buf );
417 return 0;
419 HeapFree( PSDRV_Heap, 0, buf );
420 return 1;
424 BOOL32 PSDRV_WriteMoveTo(DC *dc, INT32 x, INT32 y)
426 char buf[100];
428 sprintf(buf, psmoveto, x, y);
429 return PSDRV_WriteSpool(dc, buf, strlen(buf));
432 BOOL32 PSDRV_WriteLineTo(DC *dc, INT32 x, INT32 y)
434 char buf[100];
436 sprintf(buf, pslineto, x, y);
437 return PSDRV_WriteSpool(dc, buf, strlen(buf));
441 BOOL32 PSDRV_WriteStroke(DC *dc)
443 return PSDRV_WriteSpool(dc, psstroke, sizeof(psstroke)-1);
448 BOOL32 PSDRV_WriteRectangle(DC *dc, INT32 x, INT32 y, INT32 width,
449 INT32 height)
451 char buf[100];
453 sprintf(buf, psrectangle, x, y, width, height, -width);
454 return PSDRV_WriteSpool(dc, buf, strlen(buf));
457 BOOL32 PSDRV_WriteEllispe(DC *dc, INT32 x, INT32 y, INT32 a, INT32 b)
459 char buf[256];
461 sprintf(buf, psellipse, x, y, a, b);
462 return PSDRV_WriteSpool(dc, buf, strlen(buf));
465 static char encodingext[] = "-ANSI";
467 BOOL32 PSDRV_WriteSetFont(DC *dc, BOOL32 UseANSI)
469 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
470 char *buf, *newbuf;
472 buf = (char *)HeapAlloc( PSDRV_Heap, 0,
473 sizeof(pssetfont) + strlen(physDev->font.afm->FontName) + 40);
475 if(!buf) {
476 WARN(psdrv, "HeapAlloc failed\n");
477 return FALSE;
480 newbuf = (char *)HeapAlloc( PSDRV_Heap, 0,
481 strlen(physDev->font.afm->FontName) + sizeof(encodingext));
483 if(!newbuf) {
484 WARN(psdrv, "HeapAlloc failed\n");
485 HeapFree(PSDRV_Heap, 0, buf);
486 return FALSE;
489 if(UseANSI)
490 sprintf(newbuf, "%s%s", physDev->font.afm->FontName, encodingext);
491 else
492 strcpy(newbuf, physDev->font.afm->FontName);
494 sprintf(buf, pssetfont, newbuf,
495 physDev->font.size, -physDev->font.size,
496 -physDev->font.escapement);
498 PSDRV_WriteSpool(dc, buf, strlen(buf));
499 HeapFree(PSDRV_Heap, 0, buf);
500 return TRUE;
503 BOOL32 PSDRV_WriteSetColor(DC *dc, PSCOLOR *color)
505 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
506 char buf[256];
508 if(PSDRV_CmpColor(&physDev->inkColor, color))
509 return TRUE;
511 PSDRV_CopyColor(&physDev->inkColor, color);
512 switch(color->type) {
513 case PSCOLOR_RGB:
514 sprintf(buf, pssetrgbcolor, color->value.rgb.r, color->value.rgb.g,
515 color->value.rgb.b);
516 return PSDRV_WriteSpool(dc, buf, strlen(buf));
518 case PSCOLOR_GRAY:
519 sprintf(buf, pssetgray, color->value.gray.i);
520 return PSDRV_WriteSpool(dc, buf, strlen(buf));
522 default:
523 ERR(psdrv, "Unkonwn colour type %d\n", color->type);
524 break;
527 return FALSE;
530 BOOL32 PSDRV_WriteSetPen(DC *dc)
532 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
533 char buf[256];
535 sprintf(buf, pssetlinewidth, physDev->pen.width);
536 PSDRV_WriteSpool(dc, buf, strlen(buf));
538 if(physDev->pen.dash) {
539 sprintf(buf, pssetdash, physDev->pen.dash, 0);
540 PSDRV_WriteSpool(dc, buf, strlen(buf));
543 return TRUE;
546 BOOL32 PSDRV_WriteReencodeFont(DC *dc)
548 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
549 char *buf, *newbuf;
551 buf = (char *)HeapAlloc( PSDRV_Heap, 0,
552 sizeof(psreencodefont) + 2 * strlen(physDev->font.afm->FontName)
553 + sizeof(encodingext));
555 if(!buf) {
556 WARN(psdrv, "HeapAlloc failed\n");
557 return FALSE;
560 newbuf = (char *)HeapAlloc( PSDRV_Heap, 0,
561 strlen(physDev->font.afm->FontName) + sizeof(encodingext));
563 if(!newbuf) {
564 WARN(psdrv, "HeapAlloc failed\n");
565 HeapFree(PSDRV_Heap, 0, buf);
566 return FALSE;
569 sprintf(newbuf, "%s%s", physDev->font.afm->FontName, encodingext);
570 sprintf(buf, psreencodefont, newbuf, physDev->font.afm->FontName);
572 PSDRV_WriteSpool(dc, buf, strlen(buf));
574 HeapFree(PSDRV_Heap, 0, newbuf);
575 HeapFree(PSDRV_Heap, 0, buf);
576 return TRUE;
579 BOOL32 PSDRV_WriteShow(DC *dc, char *str, INT32 count)
581 char *buf, *buf1;
582 INT32 buflen = count + 10, i, done;
584 buf = (char *)HeapAlloc( PSDRV_Heap, 0, buflen );
586 for(i = done = 0; i < count; i++) {
587 if(!isprint(str[i])) {
588 if(done + 4 >= buflen)
589 buf = HeapReAlloc( PSDRV_Heap, 0, buf, buflen += 10 );
590 sprintf(buf + done, "\\%03o", (int)(unsigned char)str[i] );
591 done += 4;
592 } else if(str[i] == '\\' || str[i] == '(' || str[i] == ')' ) {
593 if(done + 2 >= buflen)
594 buf = HeapReAlloc( PSDRV_Heap, 0, buf, buflen += 10 );
595 buf[done++] = '\\';
596 buf[done++] = str[i];
597 } else {
598 if(done + 1 >= buflen)
599 buf = HeapReAlloc( PSDRV_Heap, 0, buf, buflen += 10 );
600 buf[done++] = str[i];
603 buf[done] = '\0';
605 buf1 = (char *)HeapAlloc( PSDRV_Heap, 0, sizeof(psshow) + done);
607 sprintf(buf1, psshow, buf);
609 PSDRV_WriteSpool(dc, buf1, strlen(buf1));
610 HeapFree(PSDRV_Heap, 0, buf);
611 HeapFree(PSDRV_Heap, 0, buf1);
613 return TRUE;
616 BOOL32 PSDRV_WriteFill(DC *dc)
618 return PSDRV_WriteSpool(dc, psfill, sizeof(psfill)-1);
621 BOOL32 PSDRV_Writegsave(DC *dc)
623 return PSDRV_WriteSpool(dc, psgsave, sizeof(psgsave)-1);
626 BOOL32 PSDRV_Writegrestore(DC *dc)
628 return PSDRV_WriteSpool(dc, psgrestore, sizeof(psgrestore)-1);