3 * Copyright (C) 1999-2002 A.J. van Os; Released under GPL
6 * Functions to deal with the PostScript format
8 *================================================================
9 * The function vImagePrologue is based on:
10 * jpeg2ps - convert JPEG compressed images to PostScript Level 2
11 * Copyright (C) 1994-99 Thomas Merz (tm@muc.de)
12 *================================================================
13 * The credit should go to him, but all the bugs are mine.
24 /* The output must be in PostScript */
25 static BOOL bUsePostScript
= FALSE
;
26 /* The character set */
27 static encoding_type eEncoding
= encoding_neutral
;
29 static image_level_enum eImageLevel
= level_default
;
30 /* The output must use landscape orientation */
31 static BOOL bUseLandscape
= FALSE
;
32 /* The height of a PostScript page (in DrawUnits) */
33 static long lPageHeight
= LONG_MAX
;
34 /* Current time for a PS header */
35 static const char *szCreationDate
= NULL
;
36 /* Current creator for a PS header */
37 static const char *szCreator
= NULL
;
38 /* Current font information */
39 static draw_fontref tFontRefCurr
= (draw_fontref
)-1;
40 static short sFontsizeCurr
= -1;
41 static int iColorCurr
= -1;
42 /* Current vertical position information */
43 static long lYtopCurr
= -1;
44 /* PostScript page counter */
45 static int iPageCount
= 0;
47 static int iImageCount
= 0;
48 /* Local representation of the non-breaking space */
49 static UCHAR ucNbsp
= 0;
51 static char iso_8859_1_data
[] = { "\
52 /newcodes % ISO-8859-1 character encodings\n\
54 160/space 161/exclamdown 162/cent 163/sterling 164/currency\n\
55 165/yen 166/brokenbar 167/section 168/dieresis 169/copyright\n\
56 170/ordfeminine 171/guillemotleft 172/logicalnot 173/hyphen 174/registered\n\
57 175/macron 176/degree 177/plusminus 178/twosuperior 179/threesuperior\n\
58 180/acute 181/mu 182/paragraph 183/periodcentered 184/cedilla\n\
59 185/onesuperior 186/ordmasculine 187/guillemotright 188/onequarter\n\
60 189/onehalf 190/threequarters 191/questiondown 192/Agrave 193/Aacute\n\
61 194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla\n\
62 200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute\n\
63 206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute\n\
64 212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash\n\
65 217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn\n\
66 223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde\n\
67 228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute\n\
68 234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex\n\
69 239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex\n\
70 245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute\n\
71 251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis\n\
74 /reencdict 12 dict def\n\
78 static char iso_8859_2_data
[] = { "\
79 /newcodes % ISO-8859-2 character encodings\n\
81 160/space 161/Aogonek 162/breve 163/Lslash 164/currency 165/Lcaron\n\
82 166/Sacute 167/section 168/dieresis 169/Scaron 170/Scommaaccent\n\
83 171/Tcaron 172/Zacute 173/hyphen 174/Zcaron 175/Zdotaccent 176/degree\n\
84 177/aogonek 178/ogonek 179/lslash 180/acute 181/lcaron 182/sacute\n\
85 183/caron 184/cedilla 185/scaron 186/scommaaccent 187/tcaron\n\
86 188/zacute 189/hungarumlaut 190/zcaron 191/zdotaccent 192/Racute\n\
87 193/Aacute 194/Acircumflex 195/Abreve 196/Adieresis 197/Lacute\n\
88 198/Cacute 199/Ccedilla 200/Ccaron 201/Eacute 202/Eogonek\n\
89 203/Edieresis 204/Ecaron 205/Iacute 206/Icircumflex 207/Dcaron\n\
90 208/Dcroat 209/Nacute 210/Ncaron 211/Oacute 212/Ocircumflex\n\
91 213/Ohungarumlaut 214/Odieresis 215/multiply 216/Rcaron 217/Uring\n\
92 218/Uacute 219/Uhungarumlaut 220/Udieresis 221/Yacute 222/Tcommaaccent\n\
93 223/germandbls 224/racute 225/aacute 226/acircumflex 227/abreve\n\
94 228/adieresis 229/lacute 230/cacute 231/ccedilla 232/ccaron 233/eacute\n\
95 234/eogonek 235/edieresis 236/ecaron 237/iacute 238/icircumflex\n\
96 239/dcaron 240/dcroat 241/nacute 242/ncaron 243/oacute 244/ocircumflex\n\
97 245/ohungarumlaut 246/odieresis 247/divide 248/rcaron 249/uring\n\
98 250/uacute 251/uhungarumlaut 252/udieresis 253/yacute 254/tcommaaccent\n\
102 /reencdict 12 dict def\n\
106 static char iso_8859_x_func
[] = { "\
107 % change fonts using ISO-8859-x characters\n\
108 /ChgFnt % size psname natname => font\n\
110 dup FontDirectory exch known % is re-encoded name known?\n\
111 { exch pop } % yes, get rid of long name\n\
112 { dup 3 1 roll ReEncode } ifelse % no, re-encode it\n\
113 findfont exch scalefont setfont\n\
120 /basename exch def\n\
121 /basedict basename findfont def\n\
122 /newfont basedict maxlength dict def\n\
124 { exch dup /FID ne\n\
125 { dup /Encoding eq\n\
126 { exch dup length array copy newfont 3 1 roll put }\n\
127 { exch newfont 3 1 roll put } ifelse\n\
129 { pop pop } ifelse\n\
131 newfont /FontName newname put\n\
132 newcodes aload pop newcodes length 2 idiv\n\
133 { newfont /Encoding get 3 1 roll put } repeat\n\
134 newname newfont definefont pop\n\
140 static char misc_func
[] = { "\
141 % draw a line and show the string\n\
142 /LineShow % string linewidth movement\n\
154 % begin an EPS file (level 2 and up)\n\
157 /b4_Inc_state save def\n\
158 /dict_count countdictstack def\n\
159 /op_count count 1 sub def\n\
162 0 setgray 0 setlinecap\n\
163 1 setlinewidth 0 setlinejoin\n\
164 10 setmiterlimit [ ] 0 setdash newpath\n\
165 false setstrokeadjust false setoverprint\n\
170 count op_count sub { pop } repeat\n\
171 countdictstack dict_count sub { end } repeat\n\
172 b4_Inc_state restore\n\
179 * vAddPageSetup - add the page setup
182 vAddPageSetup(FILE *pOutFile
)
185 fprintf(pOutFile
, "%%%%BeginPageSetup\n");
186 fprintf(pOutFile
, "90 rotate\n");
187 fprintf(pOutFile
, "0.00 %.2f translate\n",
188 -dDrawUnits2Points(lPageHeight
));
189 fprintf(pOutFile
, "%%%%EndPageSetup\n");
191 } /* end of vAddPageSetup */
194 * vMove2NextPage - move to the start of the next page
197 vMove2NextPage(diagram_type
*pDiag
)
200 fail(!bUsePostScript
);
202 fprintf(pDiag
->pOutFile
, "showpage\n");
204 fprintf(pDiag
->pOutFile
, "%%%%Page: %d %d\n", iPageCount
, iPageCount
);
205 vAddPageSetup(pDiag
->pOutFile
);
206 pDiag
->lYtop
= lPageHeight
- PS_TOP_MARGIN
;
208 } /* end of vMove2NextPage */
211 * vMoveToPS - move to the given X,Y coordinates (Postscript)
213 * Move the current position of the given diagram to its X,Y coordinates,
214 * start on a new page if needed
217 vMoveToPS(diagram_type
*pDiag
, long lLastVerticalMovement
)
220 fail(pDiag
->pOutFile
== NULL
);
222 if (pDiag
->lYtop
< PS_BOTTOM_MARGIN
) {
223 vMove2NextPage(pDiag
);
224 /* Repeat the last vertical movement on the new page */
225 pDiag
->lYtop
-= lLastVerticalMovement
;
227 fail(pDiag
->lYtop
< PS_BOTTOM_MARGIN
);
229 if (pDiag
->lYtop
!= lYtopCurr
) {
230 fprintf(pDiag
->pOutFile
, "%.2f %.2f moveto\n",
231 dDrawUnits2Points(pDiag
->lXleft
+ PS_LEFT_MARGIN
),
232 dDrawUnits2Points(pDiag
->lYtop
));
233 lYtopCurr
= pDiag
->lYtop
;
235 } /* end of vMoveToPS */
238 * vPrologue - set options and perform the PostScript initialization
241 vPrologue(FILE *pOutFile
, const char *szTask
, const char *szFilename
)
243 options_type tOptions
;
247 fail(pOutFile
== NULL
);
248 fail(szTask
== NULL
|| szTask
[0] == '\0');
250 vGetOptions(&tOptions
);
251 if (tOptions
.iPageHeight
== INT_MAX
) {
252 lPageHeight
= LONG_MAX
;
254 lPageHeight
= lPoints2DrawUnits(tOptions
.iPageHeight
);
256 DBG_DEC(lPageHeight
);
257 bUsePostScript
= tOptions
.bUseOutlineFonts
;
258 bUseLandscape
= tOptions
.bUseLandscape
;
259 eEncoding
= tOptions
.eEncoding
;
260 eImageLevel
= tOptions
.eImageLevel
;
261 tFontRefCurr
= (draw_fontref
)-1;
267 if (!bUsePostScript
) {
273 fprintf(pOutFile
, "%%!PS-Adobe-2.0\n");
274 fprintf(pOutFile
, "%%%%Title: %s\n", szBasename(szFilename
));
275 fprintf(pOutFile
, "%%%%Creator: %s %s\n", szCreator
, VERSIONSTRING
);
276 szTmp
= getenv("LOGNAME");
277 if (szTmp
== NULL
|| szTmp
[0] == '\0') {
278 szTmp
= getenv("USER");
279 if (szTmp
== NULL
|| szTmp
[0] == '\0') {
283 fprintf(pOutFile
, "%%%%For: %.50s\n", szTmp
);
286 if (tTime
== (time_t)-1 && errno
!= 0) {
287 szCreationDate
= NULL
;
289 szCreationDate
= ctime(&tTime
);
291 if (szCreationDate
== NULL
|| szCreationDate
[0] == '\0') {
292 szCreationDate
= "unknown\n";
294 fprintf(pOutFile
, "%%%%CreationDate: %s", szCreationDate
);
296 fprintf(pOutFile
, "%%%%Orientation: Landscape\n");
297 fprintf(pOutFile
, "%%%%BoundingBox: 0 0 %d %d\n",
298 tOptions
.iPageHeight
, tOptions
.iPageWidth
);
300 fprintf(pOutFile
, "%%%%Orientation: Portrait\n");
301 fprintf(pOutFile
, "%%%%BoundingBox: 0 0 %d %d\n",
302 tOptions
.iPageWidth
, tOptions
.iPageHeight
);
304 } /* end of vPrologue */
307 * vEpilogue - clean up after everything is done
310 vEpilogue(FILE *pFile
)
312 if (!bUsePostScript
) {
313 fprintf(pFile
, "\n");
317 fprintf(pFile
, "%%%%Trailer\n");
318 fprintf(pFile
, "%%%%Pages: %d\n", iPageCount
);
319 fprintf(pFile
, "%%%%EOF\n");
320 szCreationDate
= NULL
;
322 } /* end of vEpilogue */
325 * vPrintPalette - print a postscript palette
328 vPrintPalette(FILE *pOutFile
, const imagedata_type
*pImg
)
332 fail(pOutFile
== NULL
);
334 fail(pImg
->iColorsUsed
< 2);
335 fail(pImg
->iColorsUsed
> 256);
337 fprintf(pOutFile
, "[ /Indexed\n");
338 fprintf(pOutFile
, "\t/Device%s %d\n",
339 pImg
->bColorImage
? "RGB" : "Gray", pImg
->iColorsUsed
- 1);
340 fprintf(pOutFile
, "<");
341 for (iIndex
= 0; iIndex
< pImg
->iColorsUsed
; iIndex
++) {
342 fprintf(pOutFile
, "%02x",
343 (unsigned int)pImg
->aucPalette
[iIndex
][0]);
344 if (pImg
->bColorImage
) {
345 fprintf(pOutFile
, "%02x%02x",
346 (unsigned int)pImg
->aucPalette
[iIndex
][1],
347 (unsigned int)pImg
->aucPalette
[iIndex
][2]);
349 if (iIndex
% 8 == 7) {
350 fprintf(pOutFile
, "\n");
352 fprintf(pOutFile
, " ");
355 fprintf(pOutFile
, ">\n");
356 fprintf(pOutFile
, "] setcolorspace\n");
357 } /* end of vPrintPalette */
360 * vImagePrologue - perform the Encapsulated PostScript initialization
363 vImagePrologue(diagram_type
*pDiag
, const imagedata_type
*pImg
)
368 fail(pDiag
->pOutFile
== NULL
);
371 if (!bUsePostScript
) {
375 if (pImg
->iVerSizeScaled
<= 0 || pImg
->iHorSizeScaled
<= 0) {
379 fail(szCreationDate
== NULL
);
380 fail(szCreator
== NULL
);
381 fail(eImageLevel
== level_no_images
);
385 DBG_DEC_C(pDiag
->lXleft
!= 0, pDiag
->lXleft
);
387 pDiag
->lYtop
-= lPoints2DrawUnits(pImg
->iVerSizeScaled
);
388 vMoveToPS(pDiag
, lPoints2DrawUnits(pImg
->iVerSizeScaled
));
390 pOutFile
= pDiag
->pOutFile
;
392 fprintf(pOutFile
, "BeginEPSF\n");
393 fprintf(pOutFile
, "%%%%BeginDocument: image%03d.eps\n", iImageCount
);
394 fprintf(pOutFile
, "%%!PS-Adobe-2.0 EPSF-2.0\n");
395 fprintf(pOutFile
, "%%%%Creator: %s %s\n", szCreator
, VERSIONSTRING
);
396 fprintf(pOutFile
, "%%%%Title: Image %03d\n", iImageCount
);
397 fprintf(pOutFile
, "%%%%CreationDate: %s", szCreationDate
);
398 fprintf(pOutFile
, "%%%%BoundingBox: 0 0 %d %d\n",
399 pImg
->iHorSizeScaled
, pImg
->iVerSizeScaled
);
400 fprintf(pOutFile
, "%%%%DocumentData: Clean7Bit\n");
401 fprintf(pOutFile
, "%%%%LanguageLevel: 2\n");
402 fprintf(pOutFile
, "%%%%EndComments\n");
403 fprintf(pOutFile
, "%%%%BeginProlog\n");
404 fprintf(pOutFile
, "%%%%EndProlog\n");
405 fprintf(pOutFile
, "%%%%Page: 1 1\n");
407 fprintf(pOutFile
, "save\n");
409 switch (pImg
->eImageType
) {
410 case imagetype_is_jpeg
:
411 fprintf(pOutFile
, "/Data1 currentfile ");
412 fprintf(pOutFile
, "/ASCII85Decode filter def\n");
413 fprintf(pOutFile
, "/Data Data1 << ");
414 fprintf(pOutFile
, ">> /DCTDecode filter def\n");
415 switch (pImg
->iComponents
) {
417 fprintf(pOutFile
, "/DeviceGray setcolorspace\n");
420 fprintf(pOutFile
, "/DeviceRGB setcolorspace\n");
423 fprintf(pOutFile
, "/DeviceCMYK setcolorspace\n");
426 DBG_DEC(pImg
->iComponents
);
430 case imagetype_is_png
:
431 if (eImageLevel
== level_gs_special
) {
433 "/Data2 currentfile /ASCII85Decode filter def\n");
435 "/Data1 Data2 << >> /FlateDecode filter def\n");
436 fprintf(pOutFile
, "/Data Data1 <<\n");
437 fprintf(pOutFile
, "\t/Colors %d\n", pImg
->iComponents
);
438 fprintf(pOutFile
, "\t/BitsPerComponent %d\n",
439 pImg
->iBitsPerComponent
);
440 fprintf(pOutFile
, "\t/Columns %d\n", pImg
->iWidth
);
442 ">> /PNGPredictorDecode filter def\n");
445 "/Data1 currentfile /ASCII85Decode filter def\n");
447 "/Data Data1 << >> /FlateDecode filter def\n");
449 if (pImg
->iComponents
== 3) {
450 fprintf(pOutFile
, "/DeviceRGB setcolorspace\n");
451 } else if (pImg
->iColorsUsed
> 0) {
452 vPrintPalette(pOutFile
, pImg
);
454 fprintf(pOutFile
, "/DeviceGray setcolorspace\n");
457 case imagetype_is_dib
:
458 fprintf(pOutFile
, "/Data currentfile ");
459 fprintf(pOutFile
, "/ASCII85Decode filter def\n");
460 if (pImg
->iBitsPerComponent
<= 8) {
461 vPrintPalette(pOutFile
, pImg
);
463 fprintf(pOutFile
, "/DeviceRGB setcolorspace\n");
467 fprintf(pOutFile
, "/Data currentfile ");
468 fprintf(pOutFile
, "/ASCIIHexDecode filter def\n");
469 fprintf(pOutFile
, "/Device%s setcolorspace\n",
470 pImg
->bColorImage
? "RGB" : "Gray");
474 /* Translate to lower left corner of image */
475 fprintf(pOutFile
, "%.2f %.2f translate\n",
476 dDrawUnits2Points(pDiag
->lXleft
+ PS_LEFT_MARGIN
),
477 dDrawUnits2Points(pDiag
->lYtop
));
479 fprintf(pOutFile
, "%d %d scale\n",
480 pImg
->iHorSizeScaled
, pImg
->iVerSizeScaled
);
482 fprintf(pOutFile
, "{ <<\n");
483 fprintf(pOutFile
, "\t/ImageType 1\n");
484 fprintf(pOutFile
, "\t/Width %d\n", pImg
->iWidth
);
485 fprintf(pOutFile
, "\t/Height %d\n", pImg
->iHeight
);
486 if (pImg
->eImageType
== imagetype_is_dib
) {
487 /* Scanning from left to right and bottom to top */
488 fprintf(pOutFile
, "\t/ImageMatrix [ %d 0 0 %d 0 0 ]\n",
489 pImg
->iWidth
, pImg
->iHeight
);
491 /* Scanning from left to right and top to bottom */
492 fprintf(pOutFile
, "\t/ImageMatrix [ %d 0 0 %d 0 %d ]\n",
493 pImg
->iWidth
, -pImg
->iHeight
, pImg
->iHeight
);
495 fprintf(pOutFile
, "\t/DataSource Data\n");
497 switch (pImg
->eImageType
) {
498 case imagetype_is_jpeg
:
499 fprintf(pOutFile
, "\t/BitsPerComponent 8\n");
500 switch (pImg
->iComponents
) {
502 fprintf(pOutFile
, "\t/Decode [0 1]\n");
505 fprintf(pOutFile
, "\t/Decode [0 1 0 1 0 1]\n");
510 * Adobe-conforming CMYK file
511 * applying workaround for color inversion
514 "\t/Decode [1 0 1 0 1 0 1 0]\n");
517 "\t/Decode [0 1 0 1 0 1 0 1]\n");
521 DBG_DEC(pImg
->iComponents
);
525 case imagetype_is_png
:
526 if (pImg
->iComponents
== 3) {
527 fprintf(pOutFile
, "\t/BitsPerComponent 8\n");
528 fprintf(pOutFile
, "\t/Decode [0 1 0 1 0 1]\n");
529 } else if (pImg
->iColorsUsed
> 0) {
530 fail(pImg
->iBitsPerComponent
> 8);
531 fprintf(pOutFile
, "\t/BitsPerComponent %d\n",
532 pImg
->iBitsPerComponent
);
533 fprintf(pOutFile
, "\t/Decode [0 %d]\n",
534 (1 << pImg
->iBitsPerComponent
) - 1);
536 fprintf(pOutFile
, "\t/BitsPerComponent 8\n");
537 fprintf(pOutFile
, "\t/Decode [0 1]\n");
540 case imagetype_is_dib
:
541 fprintf(pOutFile
, "\t/BitsPerComponent 8\n");
542 if (pImg
->iBitsPerComponent
<= 8) {
543 fprintf(pOutFile
, "\t/Decode [0 255]\n");
545 fprintf(pOutFile
, "\t/Decode [0 1 0 1 0 1]\n");
549 fprintf(pOutFile
, "\t/BitsPerComponent 8\n");
550 if (pImg
->bColorImage
) {
551 fprintf(pOutFile
, "\t/Decode [0 1 0 1 0 1]\n");
553 fprintf(pOutFile
, "\t/Decode [0 1]\n");
558 fprintf(pOutFile
, " >> image\n");
559 fprintf(pOutFile
, " Data closefile\n");
560 fprintf(pOutFile
, " showpage\n");
561 fprintf(pOutFile
, " restore\n");
562 fprintf(pOutFile
, "} exec\n");
563 } /* end of vImagePrologue */
566 * vImageEpilogue - clean up after Encapsulated PostScript
569 vImageEpilogue(diagram_type
*pDiag
)
573 if (!bUsePostScript
) {
578 fail(pDiag
->pOutFile
== NULL
);
580 pOutFile
= pDiag
->pOutFile
;
582 fprintf(pOutFile
, "%%%%EOF\n");
583 fprintf(pOutFile
, "%%%%EndDocument\n");
584 fprintf(pOutFile
, "EndEPSF\n");
587 } /* end of vImageEpilogue */
590 * bAddDummyImage - add a dummy image
592 * return TRUE when successful, otherwise FALSE
595 bAddDummyImage(diagram_type
*pDiag
, const imagedata_type
*pImg
)
600 fail(pDiag
->pOutFile
== NULL
);
603 if (!bUsePostScript
) {
607 if (pImg
->iVerSizeScaled
<= 0 || pImg
->iHorSizeScaled
<= 0) {
613 DBG_DEC_C(pDiag
->lXleft
!= 0, pDiag
->lXleft
);
615 pDiag
->lYtop
-= lPoints2DrawUnits(pImg
->iVerSizeScaled
);
616 vMoveToPS(pDiag
, lPoints2DrawUnits(pImg
->iVerSizeScaled
));
618 pOutFile
= pDiag
->pOutFile
;
620 fprintf(pOutFile
, "gsave %% Image %03d\n", iImageCount
);
621 fprintf(pOutFile
, "\tnewpath\n");
622 fprintf(pOutFile
, "\t%.2f %.2f moveto\n",
623 dDrawUnits2Points(pDiag
->lXleft
+ PS_LEFT_MARGIN
),
624 dDrawUnits2Points(pDiag
->lYtop
));
625 fprintf(pOutFile
, "\t1.0 setlinewidth\n");
626 fprintf(pOutFile
, "\t0.3 setgray\n");
627 fprintf(pOutFile
, "\t0 %d rlineto\n", pImg
->iVerSizeScaled
);
628 fprintf(pOutFile
, "\t%d 0 rlineto\n", pImg
->iHorSizeScaled
);
629 fprintf(pOutFile
, "\t0 %d rlineto\n", -pImg
->iVerSizeScaled
);
630 fprintf(pOutFile
, "\tclosepath\n");
631 fprintf(pOutFile
, "\tstroke\n");
632 fprintf(pOutFile
, "grestore\n");
637 } /* end of bAddDummyImage */
640 * pCreateDiagram - create and initialize a diagram
642 * remark: does not return if the diagram can't be created
645 pCreateDiagram(const char *szTask
, const char *szFilename
)
649 fail(szTask
== NULL
|| szTask
[0] == '\0');
650 DBG_MSG("pCreateDiagram");
652 /* Get the necessary memory */
653 pDiag
= xmalloc(sizeof(diagram_type
));
655 pDiag
->pOutFile
= stdout
;
656 vPrologue(pDiag
->pOutFile
, szTask
, szFilename
);
659 if (bUsePostScript
) {
660 pDiag
->lYtop
= lPageHeight
- PS_TOP_MARGIN
;
666 } /* end of pCreateDiagram */
669 * vDestroyDiagram - remove a diagram by freeing the memory it uses
672 vDestroyDiagram(diagram_type
*pDiag
)
674 DBG_MSG("vDestroyDiagram");
681 if (bUsePostScript
&& pDiag
->lYtop
< lPageHeight
- PS_TOP_MARGIN
) {
682 fprintf(pDiag
->pOutFile
, "showpage\n");
684 vEpilogue(pDiag
->pOutFile
);
685 pDiag
= xfree(pDiag
);
686 } /* end of vDestroyDiagram */
689 * vAddFonts2Diagram - add the list of fonts and complete the prologue
692 vAddFonts2Diagram(diagram_type
*pDiag
)
695 const font_table_type
*pTmp
, *pTmp2
;
700 fail(pDiag
->pOutFile
== NULL
);
702 if (!bUsePostScript
) {
706 pOutFile
= pDiag
->pOutFile
;
707 iLineLen
= fprintf(pOutFile
, "%%%%DocumentFonts:");
709 if (tGetFontTableLength() == 0) {
710 iLineLen
+= fprintf(pOutFile
, " Courier");
713 while ((pTmp
= pGetNextFontTableRecord(pTmp
)) != NULL
) {
714 /* Print the document fonts */
717 while ((pTmp2
= pGetNextFontTableRecord(pTmp2
))
718 != NULL
&& pTmp2
< pTmp
) {
719 bFound
= STREQ(pTmp2
->szOurFontname
,
720 pTmp
->szOurFontname
);
728 if (iLineLen
+ (int)strlen(pTmp
->szOurFontname
) > 78) {
729 fprintf(pOutFile
, "\n%%%%+");
732 iLineLen
+= fprintf(pOutFile
,
733 " %s", pTmp
->szOurFontname
);
736 fprintf(pOutFile
, "\n");
737 fprintf(pOutFile
, "%%%%Pages: (atend)\n");
738 fprintf(pOutFile
, "%%%%EndComments\n");
739 fprintf(pOutFile
, "%%%%BeginProlog\n");
742 case encoding_iso_8859_1
:
743 fprintf(pOutFile
, "%s\n%s", iso_8859_1_data
, iso_8859_x_func
);
745 case encoding_iso_8859_2
:
746 fprintf(pOutFile
, "%s\n%s", iso_8859_2_data
, iso_8859_x_func
);
753 /* The rest of the functions */
754 fprintf(pOutFile
, "%s", misc_func
);
755 fprintf(pOutFile
, "%%%%EndProlog\n");
757 fprintf(pDiag
->pOutFile
, "%%%%Page: %d %d\n", iPageCount
, iPageCount
);
758 vAddPageSetup(pDiag
->pOutFile
);
759 } /* end of vAddFonts2Diagram */
762 * vPrintPS - print a PostScript string
765 vPrintPS(FILE *pFile
, const char *szString
, int iStringLength
,
768 const UCHAR
*ucBytes
;
771 fail(szString
== NULL
|| iStringLength
< 0);
773 if (szString
== NULL
|| szString
[0] == '\0' || iStringLength
<= 0) {
777 ucBytes
= (UCHAR
*)szString
;
778 (void)putc('(', pFile
);
779 for (iCount
= 0; iCount
< iStringLength
; iCount
++) {
780 switch (ucBytes
[iCount
]) {
784 (void)putc('\\', pFile
);
785 (void)putc(szString
[iCount
], pFile
);
788 if ((int)ucBytes
[iCount
] < 0x20 ||
789 ((int)ucBytes
[iCount
] >= 0x7f &&
790 (int)ucBytes
[iCount
] < 0xa0)) {
791 DBG_HEX(ucBytes
[iCount
]);
792 (void)putc(' ', pFile
);
793 } else if ((int)ucBytes
[iCount
] >= 0x80) {
794 fprintf(pFile
, "\\%03o",
795 (unsigned int)ucBytes
[iCount
]);
797 (void)putc(szString
[iCount
], pFile
);
802 fprintf(pFile
, ") ");
803 if ((bIsStrike(ucFontstyle
) || bIsMarkDel(ucFontstyle
)) &&
805 fprintf(pFile
, "%.2f %.2f LineShow\n",
806 sFontsizeCurr
* 0.02, sFontsizeCurr
* 0.12);
807 } else if (bIsUnderline(ucFontstyle
) && sFontsizeCurr
> 0) {
808 fprintf(pFile
, "%.2f %.2f LineShow\n",
809 sFontsizeCurr
* 0.02, sFontsizeCurr
* -0.06);
811 fprintf(pFile
, "show\n");
813 } /* end of vPrintPS */
816 * vPrintTXT - print a Text string
819 vPrintTXT(FILE *pFile
, const char *szString
, int iStringLength
)
821 const UCHAR
*ucBytes
;
824 fail(szString
== NULL
|| iStringLength
< 0);
826 if (szString
== NULL
|| szString
[0] == '\0' || iStringLength
<= 0) {
830 if (eEncoding
== encoding_utf8
) {
831 fprintf(pFile
, "%.*s", iStringLength
, szString
);
836 ucNbsp
= ucGetNbspValue();
837 DBG_HEX_C(ucNbsp
!= 0xa0, ucNbsp
);
840 ucBytes
= (UCHAR
*)szString
;
841 for (iCount
= 0; iCount
< iStringLength
; iCount
++) {
842 if (ucBytes
[iCount
] == ucNbsp
) {
843 (void)putc(' ', pFile
);
845 (void)putc(szString
[iCount
], pFile
);
848 } /* end of vPrintTXT */
851 * vSetColor - move to the given color
854 vSetColor(FILE *pFile
, int iColor
)
856 ULONG ulTmp
, ulRed
, ulGreen
, ulBlue
;
858 ulTmp
= ulColor2Color(iColor
);
859 ulRed
= (ulTmp
& 0x0000ff00) >> 8;
860 ulGreen
= (ulTmp
& 0x00ff0000) >> 16;
861 ulBlue
= (ulTmp
& 0xff000000) >> 24;
862 fprintf(pFile
, "%.3f %.3f %.3f setrgbcolor\n",
863 ulRed
/ 255.0, ulGreen
/ 255.0, ulBlue
/ 255.0);
864 } /* end of vSetColor */
867 * vMoveToTXT - move to the given X,Y coordinates (Text)
869 * Move the current position of the given diagram to its X,Y coordinates,
870 * start on a new page if needed
873 vMoveToTXT(diagram_type
*pDiag
)
878 fail(pDiag
->pOutFile
== NULL
);
880 if (pDiag
->lYtop
!= lYtopCurr
) {
881 iNbr
= iDrawUnits2Char(pDiag
->lXleft
);
882 for (iCount
= 0; iCount
< iNbr
; iCount
++) {
883 (void)putc(FILLER_CHAR
, pDiag
->pOutFile
);
885 lYtopCurr
= pDiag
->lYtop
;
887 } /* end of vMoveToTXT */
890 * vMove2NextLine - move to the next line
893 vMove2NextLine(diagram_type
*pDiag
, draw_fontref tFontRef
, short sFontsize
)
896 fail(pDiag
->pOutFile
== NULL
);
897 fail(sFontsize
< MIN_FONT_SIZE
|| sFontsize
> MAX_FONT_SIZE
);
899 pDiag
->lYtop
-= lComputeLeading(sFontsize
);
900 if (!bUsePostScript
) {
901 (void)fprintf(pDiag
->pOutFile
, "\n");
903 } /* end of vMove2NextLine */
906 * vSubstring2Diagram - put a sub string into a diagram
909 vSubstring2Diagram(diagram_type
*pDiag
,
910 char *szString
, int iStringLength
, long lStringWidth
,
911 int iColor
, UCHAR ucFontstyle
, draw_fontref tFontRef
,
912 short sFontsize
, short sMaxFontsize
)
914 const char *szOurFontname
;
916 fail(pDiag
== NULL
|| szString
== NULL
);
917 fail(pDiag
->pOutFile
== NULL
);
918 fail(pDiag
->lXleft
< 0);
919 fail(iStringLength
< 0);
920 fail((size_t)iStringLength
!= strlen(szString
));
921 fail(sFontsize
< MIN_FONT_SIZE
|| sFontsize
> MAX_FONT_SIZE
);
922 fail(sMaxFontsize
< MIN_FONT_SIZE
|| sMaxFontsize
> MAX_FONT_SIZE
);
923 fail(sFontsize
> sMaxFontsize
);
925 if (szString
[0] == '\0' || iStringLength
<= 0) {
929 if (bUsePostScript
) {
930 if (tFontRef
!= tFontRefCurr
|| sFontsize
!= sFontsizeCurr
) {
931 szOurFontname
= szGetFontname(tFontRef
);
932 fail(szOurFontname
== NULL
);
933 fprintf(pDiag
->pOutFile
,
934 "%.1f /%s /%s-ISO-8859-x ChgFnt\n",
935 (double)sFontsize
/ 2.0,
936 szOurFontname
, szOurFontname
);
937 tFontRefCurr
= tFontRef
;
938 sFontsizeCurr
= sFontsize
;
940 if (iColor
!= iColorCurr
) {
941 vSetColor(pDiag
->pOutFile
, iColor
);
944 vMoveToPS(pDiag
, lComputeLeading(sMaxFontsize
));
945 vPrintPS(pDiag
->pOutFile
, szString
, iStringLength
, ucFontstyle
);
948 vPrintTXT(pDiag
->pOutFile
, szString
, iStringLength
);
950 pDiag
->lXleft
+= lStringWidth
;
951 } /* end of vSubstring2Diagram */
954 * Create an start of paragraph by moving the y-top mark
957 vStartOfParagraph2Diagram(diagram_type
*pDiag
,
958 draw_fontref tFontRef
, short sFontsize
, long lBeforeIndentation
)
961 fail(pDiag
->pOutFile
== NULL
);
962 fail(sFontsize
< MIN_FONT_SIZE
|| sFontsize
> MAX_FONT_SIZE
);
963 fail(lBeforeIndentation
< 0);
965 if (bUsePostScript
) {
967 pDiag
->lYtop
-= lMilliPoints2DrawUnits(lBeforeIndentation
);
969 if (lBeforeIndentation
>= lTwips2MilliPoints(HEADING_GAP
)) {
970 /* A large gap is replaced by an empty line */
971 vMove2NextLine(pDiag
, tFontRef
, sFontsize
);
974 } /* end of vStartOfParagraph2Diagram */
977 * Create an end of paragraph by moving the y-top mark
980 vEndOfParagraph2Diagram(diagram_type
*pDiag
,
981 draw_fontref tFontRef
, short sFontsize
, long lAfterIndentation
)
984 fail(pDiag
->pOutFile
== NULL
);
985 fail(sFontsize
< MIN_FONT_SIZE
|| sFontsize
> MAX_FONT_SIZE
);
986 fail(lAfterIndentation
< 0);
988 if (pDiag
->lXleft
> 0) {
989 /* To the start of the line */
990 vMove2NextLine(pDiag
, tFontRef
, sFontsize
);
993 if (bUsePostScript
) {
995 pDiag
->lYtop
-= lMilliPoints2DrawUnits(lAfterIndentation
);
997 if (lAfterIndentation
>= lTwips2MilliPoints(HEADING_GAP
)) {
998 /* A large gap is replaced by an empty line */
999 vMove2NextLine(pDiag
, tFontRef
, sFontsize
);
1002 } /* end of vEndOfParagraph2Diagram */
1005 * Create an end of page
1008 vEndOfPage2Diagram(diagram_type
*pDiag
,
1009 draw_fontref tFontRef
, short sFontsize
, long lAfterIndentation
)
1011 if (bUsePostScript
) {
1012 vMove2NextPage(pDiag
);
1014 vEndOfParagraph2Diagram(pDiag
,
1019 } /* end of vEndOfPage2Diagram */