postscript.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171
  1. /*
  2. * postscript.c
  3. * Copyright (C) 1999-2005 A.J. van Os; Released under GNU GPL
  4. *
  5. * Description:
  6. * Functions to deal with the PostScript format
  7. *
  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.
  14. */
  15. #include <stdlib.h>
  16. #include <errno.h>
  17. #include <time.h>
  18. #include <string.h>
  19. #include "version.h"
  20. #include "antiword.h"
  21. /* The character set */
  22. static encoding_type eEncoding = encoding_neutral;
  23. /* The image level */
  24. static image_level_enum eImageLevel = level_default;
  25. /* The output must use landscape orientation */
  26. static BOOL bUseLandscape = FALSE;
  27. /* The height and width of a PostScript page (in DrawUnits) */
  28. static long lPageHeight = LONG_MAX;
  29. static long lPageWidth = LONG_MAX;
  30. /* The height of the footer on the current page (in DrawUnits) */
  31. static long lFooterHeight = 0;
  32. /* Inside a footer (to prevent an infinite loop when the footer is too big) */
  33. static BOOL bInFtrSpace = FALSE;
  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 drawfile_fontref tFontRefCurr = (drawfile_fontref)-1;
  40. static USHORT usFontSizeCurr = 0;
  41. static int iFontColorCurr = -1;
  42. /* Current vertical position information */
  43. static long lYtopCurr = -1;
  44. /* PostScript page counter */
  45. static int iPageCount = 0;
  46. /* Image counter */
  47. static int iImageCount = 0;
  48. /* Section index */
  49. static int iSectionIndex = 0;
  50. /* Are we on the first page of the section? */
  51. static BOOL bFirstInSection = TRUE;
  52. static void vMoveTo(diagram_type *, long);
  53. static const char *iso_8859_1_data[] = {
  54. "/newcodes % ISO-8859-1 character encodings",
  55. "[",
  56. "140/ellipsis 141/trademark 142/perthousand 143/bullet",
  57. "144/quoteleft 145/quoteright 146/guilsinglleft 147/guilsinglright",
  58. "148/quotedblleft 149/quotedblright 150/quotedblbase 151/endash 152/emdash",
  59. "153/minus 154/OE 155/oe 156/dagger 157/daggerdbl 158/fi 159/fl",
  60. "160/space 161/exclamdown 162/cent 163/sterling 164/currency",
  61. "165/yen 166/brokenbar 167/section 168/dieresis 169/copyright",
  62. "170/ordfeminine 171/guillemotleft 172/logicalnot 173/hyphen 174/registered",
  63. "175/macron 176/degree 177/plusminus 178/twosuperior 179/threesuperior",
  64. "180/acute 181/mu 182/paragraph 183/periodcentered 184/cedilla",
  65. "185/onesuperior 186/ordmasculine 187/guillemotright 188/onequarter",
  66. "189/onehalf 190/threequarters 191/questiondown 192/Agrave 193/Aacute",
  67. "194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla",
  68. "200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute",
  69. "206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute",
  70. "212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash",
  71. "217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn",
  72. "223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde",
  73. "228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute",
  74. "234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex",
  75. "239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex",
  76. "245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute",
  77. "251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis",
  78. "] bind def",
  79. "",
  80. "/reencdict 12 dict def",
  81. "",
  82. };
  83. static const char *iso_8859_2_data[] = {
  84. "/newcodes % ISO-8859-2 character encodings",
  85. "[",
  86. "160/space 161/Aogonek 162/breve 163/Lslash 164/currency 165/Lcaron",
  87. "166/Sacute 167/section 168/dieresis 169/Scaron 170/Scommaaccent",
  88. "171/Tcaron 172/Zacute 173/hyphen 174/Zcaron 175/Zdotaccent 176/degree",
  89. "177/aogonek 178/ogonek 179/lslash 180/acute 181/lcaron 182/sacute",
  90. "183/caron 184/cedilla 185/scaron 186/scommaaccent 187/tcaron",
  91. "188/zacute 189/hungarumlaut 190/zcaron 191/zdotaccent 192/Racute",
  92. "193/Aacute 194/Acircumflex 195/Abreve 196/Adieresis 197/Lacute",
  93. "198/Cacute 199/Ccedilla 200/Ccaron 201/Eacute 202/Eogonek",
  94. "203/Edieresis 204/Ecaron 205/Iacute 206/Icircumflex 207/Dcaron",
  95. "208/Dcroat 209/Nacute 210/Ncaron 211/Oacute 212/Ocircumflex",
  96. "213/Ohungarumlaut 214/Odieresis 215/multiply 216/Rcaron 217/Uring",
  97. "218/Uacute 219/Uhungarumlaut 220/Udieresis 221/Yacute 222/Tcommaaccent",
  98. "223/germandbls 224/racute 225/aacute 226/acircumflex 227/abreve",
  99. "228/adieresis 229/lacute 230/cacute 231/ccedilla 232/ccaron 233/eacute",
  100. "234/eogonek 235/edieresis 236/ecaron 237/iacute 238/icircumflex",
  101. "239/dcaron 240/dcroat 241/nacute 242/ncaron 243/oacute 244/ocircumflex",
  102. "245/ohungarumlaut 246/odieresis 247/divide 248/rcaron 249/uring",
  103. "250/uacute 251/uhungarumlaut 252/udieresis 253/yacute 254/tcommaaccent",
  104. "255/dotaccent",
  105. "] bind def",
  106. "",
  107. "/reencdict 12 dict def",
  108. "",
  109. };
  110. static const char *iso_8859_5_data[] = {
  111. "/newcodes % ISO-8859-5 character encodings",
  112. "[",
  113. "160/space 161/afii10023 162/afii10051 163/afii10052 164/afii10053",
  114. "165/afii10054 166/afii10055 167/afii10056 168/afii10057 169/afii10058",
  115. "170/afii10059 171/afii10060 172/afii10061 173/hyphen 174/afii10062",
  116. "175/afii10145 176/afii10017 177/afii10018 178/afii10019 179/afii10020",
  117. "180/afii10021 181/afii10022 182/afii10024 183/afii10025 184/afii10026",
  118. "185/afii10027 186/afii10028 187/afii10029 188/afii10030 189/afii10031",
  119. "190/afii10032 191/afii10033 192/afii10034 193/afii10035 194/afii10036",
  120. "195/afii10037 196/afii10038 197/afii10039 198/afii10040 199/afii10041",
  121. "200/afii10042 201/afii10043 202/afii10044 203/afii10045 204/afii10046",
  122. "205/afii10047 206/afii10048 207/afii10049 208/afii10065 209/afii10066",
  123. "210/afii10067 211/afii10068 212/afii10069 213/afii10070 214/afii10072",
  124. "215/afii10073 216/afii10074 217/afii10075 218/afii10076 219/afii10077",
  125. "220/afii10078 221/afii10079 222/afii10080 223/afii10081 224/afii10082",
  126. "225/afii10083 226/afii10084 227/afii10085 228/afii10086 229/afii10087",
  127. "230/afii10088 231/afii10089 232/afii10090 233/afii10091 234/afii10092",
  128. "235/afii10093 236/afii10094 237/afii10095 238/afii10096 239/afii10097",
  129. "240/afii61352 241/afii10071 242/afii10099 243/afii10100 244/afii10101",
  130. "245/afii10102 246/afii10103 247/afii10104 248/afii10105 249/afii10106",
  131. "250/afii10107 251/afii10108 252/afii10109 253/section 254/afii10110",
  132. "255/afii10193",
  133. "] bind def",
  134. "",
  135. "/reencdict 12 dict def",
  136. "",
  137. };
  138. static const char *iso_8859_x_func[] = {
  139. "% change fonts using ISO-8859-x characters",
  140. "/ChgFnt % size psname natname => font",
  141. "{",
  142. " dup FontDirectory exch known % is re-encoded name known?",
  143. " { exch pop } % yes, get rid of long name",
  144. " { dup 3 1 roll ReEncode } ifelse % no, re-encode it",
  145. " findfont exch scalefont setfont",
  146. "} bind def",
  147. "",
  148. "/ReEncode",
  149. "{",
  150. "reencdict begin",
  151. " /newname exch def",
  152. " /basename exch def",
  153. " /basedict basename findfont def",
  154. " /newfont basedict maxlength dict def",
  155. " basedict",
  156. " { exch dup /FID ne",
  157. " { dup /Encoding eq",
  158. " { exch dup length array copy newfont 3 1 roll put }",
  159. " { exch newfont 3 1 roll put } ifelse",
  160. " }",
  161. " { pop pop } ifelse",
  162. " } forall",
  163. " newfont /FontName newname put",
  164. " newcodes aload pop newcodes length 2 idiv",
  165. " { newfont /Encoding get 3 1 roll put } repeat",
  166. " newname newfont definefont pop",
  167. "end",
  168. "} bind def",
  169. "",
  170. };
  171. static const char *misc_func[] = {
  172. "% draw a line and show the string",
  173. "/LineShow % string linewidth movement",
  174. "{",
  175. " gsave",
  176. " 0 exch rmoveto",
  177. " setlinewidth",
  178. " dup",
  179. " stringwidth pop",
  180. " 0 rlineto stroke",
  181. " grestore",
  182. " show",
  183. "} bind def",
  184. "",
  185. "% begin an EPS file (level 2 and up)",
  186. "/BeginEPSF",
  187. "{",
  188. " /b4_Inc_state save def",
  189. " /dict_count countdictstack def",
  190. " /op_count count 1 sub def",
  191. " userdict begin",
  192. " /showpage { } def",
  193. " 0 setgray 0 setlinecap",
  194. " 1 setlinewidth 0 setlinejoin",
  195. " 10 setmiterlimit [ ] 0 setdash newpath",
  196. " false setstrokeadjust false setoverprint",
  197. "} bind def",
  198. "",
  199. "% end an EPS file",
  200. "/EndEPSF {",
  201. " count op_count sub { pop } repeat",
  202. " countdictstack dict_count sub { end } repeat",
  203. " b4_Inc_state restore",
  204. "} bind def",
  205. "",
  206. };
  207. /*
  208. * vAddPageSetup - add the page setup
  209. */
  210. static void
  211. vAddPageSetup(FILE *pOutFile)
  212. {
  213. if (bUseLandscape) {
  214. fprintf(pOutFile, "%%%%BeginPageSetup\n");
  215. fprintf(pOutFile, "90 rotate\n");
  216. fprintf(pOutFile, "0.00 %.2f translate\n",
  217. -dDrawUnits2Points(lPageHeight));
  218. fprintf(pOutFile, "%%%%EndPageSetup\n");
  219. }
  220. } /* end of vAddPageSetup */
  221. /*
  222. * vAddHdrFtr - add a header or footer
  223. */
  224. static void
  225. vAddHdrFtr(diagram_type *pDiag, const hdrftr_block_type *pHdrFtrInfo)
  226. {
  227. output_type *pStart, *pPrev, *pNext;
  228. fail(pDiag == NULL);
  229. fail(pHdrFtrInfo == NULL);
  230. vStartOfParagraphPS(pDiag, 0);
  231. pStart = pHdrFtrInfo->pText;
  232. while (pStart != NULL) {
  233. pNext = pStart;
  234. while (pNext != NULL &&
  235. (pNext->tNextFree != 1 ||
  236. (pNext->szStorage[0] != PAR_END &&
  237. pNext->szStorage[0] != HARD_RETURN))) {
  238. pNext = pNext->pNext;
  239. }
  240. if (pNext == NULL) {
  241. if (bOutputContainsText(pStart)) {
  242. vAlign2Window(pDiag, pStart,
  243. lChar2MilliPoints(DEFAULT_SCREEN_WIDTH),
  244. ALIGNMENT_LEFT);
  245. } else {
  246. vMove2NextLinePS(pDiag, pStart->usFontSize);
  247. }
  248. break;
  249. }
  250. fail(pNext->tNextFree != 1);
  251. fail(pNext->szStorage[0] != PAR_END &&
  252. pNext->szStorage[0] != HARD_RETURN);
  253. if (pStart != pNext) {
  254. /* There is something to print */
  255. pPrev = pNext->pPrev;
  256. fail(pPrev->pNext != pNext);
  257. /* Cut the chain */
  258. pPrev->pNext = NULL;
  259. if (bOutputContainsText(pStart)) {
  260. /* Print it */
  261. vAlign2Window(pDiag, pStart,
  262. lChar2MilliPoints(DEFAULT_SCREEN_WIDTH),
  263. ALIGNMENT_LEFT);
  264. } else {
  265. /* Just an empty line */
  266. vMove2NextLinePS(pDiag, pStart->usFontSize);
  267. }
  268. /* Repair the chain */
  269. pPrev->pNext = pNext;
  270. }
  271. if (pNext->szStorage[0] == PAR_END) {
  272. vEndOfParagraphPS(pDiag, pNext->usFontSize,
  273. (long)pNext->usFontSize * 200);
  274. }
  275. pStart = pNext->pNext;
  276. }
  277. } /* end of vAddHdrFtr */
  278. /*
  279. * vAddHeader - add a page header
  280. */
  281. static void
  282. vAddHeader(diagram_type *pDiag)
  283. {
  284. const hdrftr_block_type *pHdrInfo;
  285. const hdrftr_block_type *pFtrInfo;
  286. fail(pDiag == NULL);
  287. NO_DBG_MSG("vAddHeader");
  288. pHdrInfo = pGetHdrFtrInfo(iSectionIndex, TRUE,
  289. odd(iPageCount), bFirstInSection);
  290. pFtrInfo = pGetHdrFtrInfo(iSectionIndex, FALSE,
  291. odd(iPageCount), bFirstInSection);
  292. /* Set the height of the footer of this page */
  293. lFooterHeight = pFtrInfo == NULL ? 0 : pFtrInfo->lHeight;
  294. fail(lFooterHeight < 0);
  295. if (pHdrInfo == NULL ||
  296. pHdrInfo->pText == NULL ||
  297. pHdrInfo->lHeight <= 0) {
  298. fail(pHdrInfo != NULL && pHdrInfo->lHeight < 0);
  299. fail(pHdrInfo != NULL &&
  300. pHdrInfo->pText != NULL &&
  301. pHdrInfo->lHeight == 0);
  302. return;
  303. }
  304. vAddHdrFtr(pDiag, pHdrInfo);
  305. DBG_DEC_C(pHdrInfo->lHeight !=
  306. lPageHeight - PS_TOP_MARGIN - pDiag->lYtop,
  307. pHdrInfo->lHeight);
  308. DBG_DEC_C(pHdrInfo->lHeight !=
  309. lPageHeight - PS_TOP_MARGIN - pDiag->lYtop,
  310. lPageHeight - PS_TOP_MARGIN - pDiag->lYtop);
  311. #if 0 /* defined(DEBUG) */
  312. fprintf(pDiag->pOutFile,
  313. "(HEADER: FileOffset 0x%04lx-0x%04lx; Height %ld-%ld) show\n",
  314. ulCharPos2FileOffset(pHdrInfo->ulCharPosStart),
  315. ulCharPos2FileOffset(pHdrInfo->ulCharPosNext),
  316. pHdrInfo->lHeight,
  317. lPageHeight - PS_TOP_MARGIN - pDiag->lYtop);
  318. #endif
  319. } /* end of vAddHeader */
  320. /*
  321. * vAddFooter - add a page footer
  322. */
  323. static void
  324. vAddFooter(diagram_type *pDiag)
  325. {
  326. const hdrftr_block_type *pFtrInfo;
  327. fail(pDiag == NULL);
  328. NO_DBG_MSG("vAddFooter");
  329. pFtrInfo = pGetHdrFtrInfo(iSectionIndex, FALSE,
  330. odd(iPageCount), bFirstInSection);
  331. bFirstInSection = FALSE;
  332. if (pFtrInfo == NULL ||
  333. pFtrInfo->pText == NULL ||
  334. pFtrInfo->lHeight <= 0) {
  335. fail(pFtrInfo != NULL && pFtrInfo->lHeight < 0);
  336. fail(pFtrInfo != NULL &&
  337. pFtrInfo->pText != NULL &&
  338. pFtrInfo->lHeight == 0);
  339. return;
  340. }
  341. bInFtrSpace = TRUE;
  342. DBG_DEC_C(pFtrInfo->lHeight != lFooterHeight, pFtrInfo->lHeight);
  343. DBG_DEC_C(pFtrInfo->lHeight != lFooterHeight, lFooterHeight);
  344. DBG_DEC_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
  345. pDiag->lYtop);
  346. DBG_DEC_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
  347. lFooterHeight + PS_BOTTOM_MARGIN);
  348. if (pDiag->lYtop > lFooterHeight + PS_BOTTOM_MARGIN) {
  349. /* Move down to the start of the footer */
  350. pDiag->lYtop = lFooterHeight + PS_BOTTOM_MARGIN;
  351. vMoveTo(pDiag, 0);
  352. } else if (pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN / 2) {
  353. DBG_FIXME();
  354. /*
  355. * Move up to the start of the footer, to prevent moving
  356. * of the bottom edge of the paper
  357. */
  358. pDiag->lYtop = lFooterHeight + PS_BOTTOM_MARGIN;
  359. vMoveTo(pDiag, 0);
  360. }
  361. DBG_FLT_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
  362. dDrawUnits2Points(lFooterHeight + PS_BOTTOM_MARGIN - pDiag->lYtop));
  363. #if 0 /* defined(DEBUG) */
  364. fprintf(pDiag->pOutFile,
  365. "(FOOTER: FileOffset 0x%04lx-0x%04lx; Bottom %ld-%ld) show\n",
  366. ulCharPos2FileOffset(pFtrInfo->ulCharPosStart),
  367. ulCharPos2FileOffset(pFtrInfo->ulCharPosNext),
  368. pDiag->lYtop,
  369. pFtrInfo->lHeight + PS_BOTTOM_MARGIN);
  370. #endif
  371. vAddHdrFtr(pDiag, pFtrInfo);
  372. bInFtrSpace = FALSE;
  373. } /* end of vAddFooter */
  374. /*
  375. * vMove2NextPage - move to the start of the next page
  376. */
  377. static void
  378. vMove2NextPage(diagram_type *pDiag, BOOL bNewSection)
  379. {
  380. fail(pDiag == NULL);
  381. vAddFooter(pDiag);
  382. fprintf(pDiag->pOutFile, "showpage\n");
  383. iPageCount++;
  384. fprintf(pDiag->pOutFile, "%%%%Page: %d %d\n", iPageCount, iPageCount);
  385. if (bNewSection) {
  386. iSectionIndex++;
  387. bFirstInSection = TRUE;
  388. }
  389. vAddPageSetup(pDiag->pOutFile);
  390. pDiag->lYtop = lPageHeight - PS_TOP_MARGIN;
  391. lYtopCurr = -1;
  392. vAddHeader(pDiag);
  393. } /* end of vMove2NextPage */
  394. /*
  395. * vMoveTo - move to the specified X,Y coordinates
  396. *
  397. * Move the current position of the specified diagram to its X,Y coordinates,
  398. * start on a new page if needed
  399. */
  400. static void
  401. vMoveTo(diagram_type *pDiag, long lLastVerticalMovement)
  402. {
  403. fail(pDiag == NULL);
  404. fail(pDiag->pOutFile == NULL);
  405. if (pDiag->lYtop <= lFooterHeight + PS_BOTTOM_MARGIN && !bInFtrSpace) {
  406. vMove2NextPage(pDiag, FALSE);
  407. /* Repeat the last vertical movement on the new page */
  408. pDiag->lYtop -= lLastVerticalMovement;
  409. }
  410. fail(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN && !bInFtrSpace);
  411. DBG_DEC_C(pDiag->lYtop < PS_BOTTOM_MARGIN, pDiag->lYtop);
  412. fail(pDiag->lYtop < PS_BOTTOM_MARGIN / 3);
  413. if (pDiag->lYtop != lYtopCurr) {
  414. fprintf(pDiag->pOutFile, "%.2f %.2f moveto\n",
  415. dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
  416. dDrawUnits2Points(pDiag->lYtop));
  417. lYtopCurr = pDiag->lYtop;
  418. }
  419. } /* end of vMoveTo */
  420. /*
  421. * vProloguePS - set options and perform the PostScript initialization
  422. */
  423. void
  424. vProloguePS(diagram_type *pDiag,
  425. const char *szTask, const char *szFilename,
  426. const options_type *pOptions)
  427. {
  428. FILE *pOutFile;
  429. const char *szTmp;
  430. time_t tTime;
  431. fail(pDiag == NULL);
  432. fail(pDiag->pOutFile == NULL);
  433. fail(szTask == NULL || szTask[0] == '\0');
  434. fail(pOptions == NULL);
  435. pOutFile = pDiag->pOutFile;
  436. bUseLandscape = pOptions->bUseLandscape;
  437. eEncoding = pOptions->eEncoding;
  438. eImageLevel = pOptions->eImageLevel;
  439. if (pOptions->iPageHeight == INT_MAX) {
  440. lPageHeight = LONG_MAX;
  441. } else {
  442. lPageHeight = lPoints2DrawUnits(pOptions->iPageHeight);
  443. }
  444. DBG_DEC(lPageHeight);
  445. if (pOptions->iPageWidth == INT_MAX) {
  446. lPageWidth = LONG_MAX;
  447. } else {
  448. lPageWidth = lPoints2DrawUnits(pOptions->iPageWidth);
  449. }
  450. DBG_DEC(lPageWidth);
  451. lFooterHeight = 0;
  452. bInFtrSpace = FALSE;
  453. tFontRefCurr = (drawfile_fontref)-1;
  454. usFontSizeCurr = 0;
  455. iFontColorCurr = -1;
  456. lYtopCurr = -1;
  457. iPageCount = 0;
  458. iImageCount = 0;
  459. iSectionIndex = 0;
  460. bFirstInSection = TRUE;
  461. pDiag->lXleft = 0;
  462. pDiag->lYtop = lPageHeight - PS_TOP_MARGIN;
  463. szCreator = szTask;
  464. fprintf(pOutFile, "%%!PS-Adobe-2.0\n");
  465. fprintf(pOutFile, "%%%%Title: %s\n", szBasename(szFilename));
  466. fprintf(pOutFile, "%%%%Creator: %s %s\n", szCreator, VERSIONSTRING);
  467. szTmp = getenv("LOGNAME");
  468. if (szTmp == NULL || szTmp[0] == '\0') {
  469. szTmp = getenv("USER");
  470. if (szTmp == NULL || szTmp[0] == '\0') {
  471. szTmp = "unknown";
  472. }
  473. }
  474. fprintf(pOutFile, "%%%%For: %.50s\n", szTmp);
  475. errno = 0;
  476. tTime = time(NULL);
  477. if (tTime == (time_t)-1 && errno != 0) {
  478. szCreationDate = NULL;
  479. } else {
  480. szCreationDate = ctime(&tTime);
  481. }
  482. if (szCreationDate == NULL || szCreationDate[0] == '\0') {
  483. szCreationDate = "unknown\n";
  484. }
  485. fprintf(pOutFile, "%%%%CreationDate: %s", szCreationDate);
  486. if (bUseLandscape) {
  487. fprintf(pOutFile, "%%%%Orientation: Landscape\n");
  488. fprintf(pOutFile, "%%%%BoundingBox: 0 0 %.0f %.0f\n",
  489. dDrawUnits2Points(lPageHeight),
  490. dDrawUnits2Points(lPageWidth));
  491. } else {
  492. fprintf(pOutFile, "%%%%Orientation: Portrait\n");
  493. fprintf(pOutFile, "%%%%BoundingBox: 0 0 %.0f %.0f\n",
  494. dDrawUnits2Points(lPageWidth),
  495. dDrawUnits2Points(lPageHeight));
  496. }
  497. } /* end of vProloguePS */
  498. /*
  499. * vEpiloguePS - clean up after everything is done
  500. */
  501. void
  502. vEpiloguePS(diagram_type *pDiag)
  503. {
  504. fail(pDiag == NULL);
  505. fail(pDiag->pOutFile == NULL);
  506. if (pDiag->lYtop < lPageHeight - PS_TOP_MARGIN) {
  507. vAddFooter(pDiag);
  508. fprintf(pDiag->pOutFile, "showpage\n");
  509. }
  510. fprintf(pDiag->pOutFile, "%%%%Trailer\n");
  511. fprintf(pDiag->pOutFile, "%%%%Pages: %d\n", iPageCount);
  512. fprintf(pDiag->pOutFile, "%%%%EOF\n");
  513. szCreationDate = NULL;
  514. szCreator = NULL;
  515. } /* end of vEpiloguePS */
  516. /*
  517. * vPrintPalette - print a postscript palette
  518. */
  519. static void
  520. vPrintPalette(FILE *pOutFile, const imagedata_type *pImg)
  521. {
  522. int iIndex;
  523. fail(pOutFile == NULL);
  524. fail(pImg == NULL);
  525. fail(pImg->iColorsUsed < 2);
  526. fail(pImg->iColorsUsed > 256);
  527. fprintf(pOutFile, "[ /Indexed\n");
  528. fprintf(pOutFile, "\t/Device%s %d\n",
  529. pImg->bColorImage ? "RGB" : "Gray", pImg->iColorsUsed - 1);
  530. fprintf(pOutFile, "<");
  531. for (iIndex = 0; iIndex < pImg->iColorsUsed; iIndex++) {
  532. fprintf(pOutFile, "%02x",
  533. (unsigned int)pImg->aucPalette[iIndex][0]);
  534. if (pImg->bColorImage) {
  535. fprintf(pOutFile, "%02x%02x",
  536. (unsigned int)pImg->aucPalette[iIndex][1],
  537. (unsigned int)pImg->aucPalette[iIndex][2]);
  538. }
  539. if (iIndex % 8 == 7) {
  540. fprintf(pOutFile, "\n");
  541. } else {
  542. fprintf(pOutFile, " ");
  543. }
  544. }
  545. fprintf(pOutFile, ">\n");
  546. fprintf(pOutFile, "] setcolorspace\n");
  547. } /* end of vPrintPalette */
  548. /*
  549. * vImageProloguePS - perform the Encapsulated PostScript initialization
  550. */
  551. void
  552. vImageProloguePS(diagram_type *pDiag, const imagedata_type *pImg)
  553. {
  554. FILE *pOutFile;
  555. fail(pDiag == NULL);
  556. fail(pDiag->pOutFile == NULL);
  557. fail(pImg == NULL);
  558. if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
  559. return;
  560. }
  561. fail(szCreationDate == NULL);
  562. fail(szCreator == NULL);
  563. fail(eImageLevel == level_no_images);
  564. iImageCount++;
  565. DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
  566. pDiag->lYtop -= lPoints2DrawUnits(pImg->iVerSizeScaled);
  567. vMoveTo(pDiag, lPoints2DrawUnits(pImg->iVerSizeScaled));
  568. pOutFile = pDiag->pOutFile;
  569. fprintf(pOutFile, "BeginEPSF\n");
  570. fprintf(pOutFile, "%%%%BeginDocument: image%03d.eps\n", iImageCount);
  571. fprintf(pOutFile, "%%!PS-Adobe-2.0 EPSF-2.0\n");
  572. fprintf(pOutFile, "%%%%Creator: %s %s\n", szCreator, VERSIONSTRING);
  573. fprintf(pOutFile, "%%%%Title: Image %03d\n", iImageCount);
  574. fprintf(pOutFile, "%%%%CreationDate: %s", szCreationDate);
  575. fprintf(pOutFile, "%%%%BoundingBox: 0 0 %d %d\n",
  576. pImg->iHorSizeScaled, pImg->iVerSizeScaled);
  577. fprintf(pOutFile, "%%%%DocumentData: Clean7Bit\n");
  578. fprintf(pOutFile, "%%%%LanguageLevel: 2\n");
  579. fprintf(pOutFile, "%%%%EndComments\n");
  580. fprintf(pOutFile, "%%%%BeginProlog\n");
  581. fprintf(pOutFile, "%%%%EndProlog\n");
  582. fprintf(pOutFile, "%%%%Page: 1 1\n");
  583. fprintf(pOutFile, "save\n");
  584. switch (pImg->eImageType) {
  585. case imagetype_is_jpeg:
  586. fprintf(pOutFile, "/Data1 currentfile ");
  587. fprintf(pOutFile, "/ASCII85Decode filter def\n");
  588. fprintf(pOutFile, "/Data Data1 << ");
  589. fprintf(pOutFile, ">> /DCTDecode filter def\n");
  590. switch (pImg->iComponents) {
  591. case 1:
  592. fprintf(pOutFile, "/DeviceGray setcolorspace\n");
  593. break;
  594. case 3:
  595. fprintf(pOutFile, "/DeviceRGB setcolorspace\n");
  596. break;
  597. case 4:
  598. fprintf(pOutFile, "/DeviceCMYK setcolorspace\n");
  599. break;
  600. default:
  601. DBG_DEC(pImg->iComponents);
  602. break;
  603. }
  604. break;
  605. case imagetype_is_png:
  606. if (eImageLevel == level_gs_special) {
  607. fprintf(pOutFile,
  608. "/Data2 currentfile /ASCII85Decode filter def\n");
  609. fprintf(pOutFile,
  610. "/Data1 Data2 << >> /FlateDecode filter def\n");
  611. fprintf(pOutFile, "/Data Data1 <<\n");
  612. fprintf(pOutFile, "\t/Colors %d\n", pImg->iComponents);
  613. fprintf(pOutFile, "\t/BitsPerComponent %u\n",
  614. pImg->uiBitsPerComponent);
  615. fprintf(pOutFile, "\t/Columns %d\n", pImg->iWidth);
  616. fprintf(pOutFile,
  617. ">> /PNGPredictorDecode filter def\n");
  618. } else {
  619. fprintf(pOutFile,
  620. "/Data1 currentfile /ASCII85Decode filter def\n");
  621. fprintf(pOutFile,
  622. "/Data Data1 << >> /FlateDecode filter def\n");
  623. }
  624. if (pImg->iComponents == 3 || pImg->iComponents == 4) {
  625. fprintf(pOutFile, "/DeviceRGB setcolorspace\n");
  626. } else if (pImg->iColorsUsed > 0) {
  627. vPrintPalette(pOutFile, pImg);
  628. } else {
  629. fprintf(pOutFile, "/DeviceGray setcolorspace\n");
  630. }
  631. break;
  632. case imagetype_is_dib:
  633. fprintf(pOutFile, "/Data currentfile ");
  634. fprintf(pOutFile, "/ASCII85Decode filter def\n");
  635. if (pImg->uiBitsPerComponent <= 8) {
  636. vPrintPalette(pOutFile, pImg);
  637. } else {
  638. fprintf(pOutFile, "/DeviceRGB setcolorspace\n");
  639. }
  640. break;
  641. default:
  642. fprintf(pOutFile, "/Data currentfile ");
  643. fprintf(pOutFile, "/ASCIIHexDecode filter def\n");
  644. fprintf(pOutFile, "/Device%s setcolorspace\n",
  645. pImg->bColorImage ? "RGB" : "Gray");
  646. break;
  647. }
  648. /* Translate to lower left corner of image */
  649. fprintf(pOutFile, "%.2f %.2f translate\n",
  650. dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
  651. dDrawUnits2Points(pDiag->lYtop));
  652. fprintf(pOutFile, "%d %d scale\n",
  653. pImg->iHorSizeScaled, pImg->iVerSizeScaled);
  654. fprintf(pOutFile, "{ <<\n");
  655. fprintf(pOutFile, "\t/ImageType 1\n");
  656. fprintf(pOutFile, "\t/Width %d\n", pImg->iWidth);
  657. fprintf(pOutFile, "\t/Height %d\n", pImg->iHeight);
  658. if (pImg->eImageType == imagetype_is_dib) {
  659. /* Scanning from left to right and bottom to top */
  660. fprintf(pOutFile, "\t/ImageMatrix [ %d 0 0 %d 0 0 ]\n",
  661. pImg->iWidth, pImg->iHeight);
  662. } else {
  663. /* Scanning from left to right and top to bottom */
  664. fprintf(pOutFile, "\t/ImageMatrix [ %d 0 0 %d 0 %d ]\n",
  665. pImg->iWidth, -pImg->iHeight, pImg->iHeight);
  666. }
  667. fprintf(pOutFile, "\t/DataSource Data\n");
  668. switch (pImg->eImageType) {
  669. case imagetype_is_jpeg:
  670. fprintf(pOutFile, "\t/BitsPerComponent 8\n");
  671. switch (pImg->iComponents) {
  672. case 1:
  673. fprintf(pOutFile, "\t/Decode [0 1]\n");
  674. break;
  675. case 3:
  676. fprintf(pOutFile, "\t/Decode [0 1 0 1 0 1]\n");
  677. break;
  678. case 4:
  679. if (pImg->bAdobe) {
  680. /*
  681. * Adobe-conforming CMYK file
  682. * applying workaround for color inversion
  683. */
  684. fprintf(pOutFile,
  685. "\t/Decode [1 0 1 0 1 0 1 0]\n");
  686. } else {
  687. fprintf(pOutFile,
  688. "\t/Decode [0 1 0 1 0 1 0 1]\n");
  689. }
  690. break;
  691. default:
  692. DBG_DEC(pImg->iComponents);
  693. break;
  694. }
  695. break;
  696. case imagetype_is_png:
  697. if (pImg->iComponents == 3) {
  698. fprintf(pOutFile, "\t/BitsPerComponent 8\n");
  699. fprintf(pOutFile, "\t/Decode [0 1 0 1 0 1]\n");
  700. } else if (pImg->iColorsUsed > 0) {
  701. fail(pImg->uiBitsPerComponent > 8);
  702. fprintf(pOutFile, "\t/BitsPerComponent %u\n",
  703. pImg->uiBitsPerComponent);
  704. fprintf(pOutFile, "\t/Decode [0 %d]\n",
  705. (1 << pImg->uiBitsPerComponent) - 1);
  706. } else {
  707. fprintf(pOutFile, "\t/BitsPerComponent 8\n");
  708. fprintf(pOutFile, "\t/Decode [0 1]\n");
  709. }
  710. break;
  711. case imagetype_is_dib:
  712. fprintf(pOutFile, "\t/BitsPerComponent 8\n");
  713. if (pImg->uiBitsPerComponent <= 8) {
  714. fprintf(pOutFile, "\t/Decode [0 255]\n");
  715. } else {
  716. fprintf(pOutFile, "\t/Decode [0 1 0 1 0 1]\n");
  717. }
  718. break;
  719. default:
  720. fprintf(pOutFile, "\t/BitsPerComponent 8\n");
  721. if (pImg->bColorImage) {
  722. fprintf(pOutFile, "\t/Decode [0 1 0 1 0 1]\n");
  723. } else {
  724. fprintf(pOutFile, "\t/Decode [0 1]\n");
  725. }
  726. break;
  727. }
  728. fprintf(pOutFile, " >> image\n");
  729. fprintf(pOutFile, " Data closefile\n");
  730. fprintf(pOutFile, " showpage\n");
  731. fprintf(pOutFile, " restore\n");
  732. fprintf(pOutFile, "} exec\n");
  733. } /* end of vImageProloguePS */
  734. /*
  735. * vImageEpiloguePS - clean up after Encapsulated PostScript
  736. */
  737. void
  738. vImageEpiloguePS(diagram_type *pDiag)
  739. {
  740. FILE *pOutFile;
  741. fail(pDiag == NULL);
  742. fail(pDiag->pOutFile == NULL);
  743. pOutFile = pDiag->pOutFile;
  744. fprintf(pOutFile, "%%%%EOF\n");
  745. fprintf(pOutFile, "%%%%EndDocument\n");
  746. fprintf(pOutFile, "EndEPSF\n");
  747. pDiag->lXleft = 0;
  748. } /* end of vImageEpiloguePS */
  749. /*
  750. * bAddDummyImagePS - add a dummy image
  751. *
  752. * return TRUE when successful, otherwise FALSE
  753. */
  754. BOOL
  755. bAddDummyImagePS(diagram_type *pDiag, const imagedata_type *pImg)
  756. {
  757. FILE *pOutFile;
  758. fail(pDiag == NULL);
  759. fail(pDiag->pOutFile == NULL);
  760. fail(pImg == NULL);
  761. if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
  762. return FALSE;
  763. }
  764. iImageCount++;
  765. DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
  766. pDiag->lYtop -= lPoints2DrawUnits(pImg->iVerSizeScaled);
  767. vMoveTo(pDiag, lPoints2DrawUnits(pImg->iVerSizeScaled));
  768. pOutFile = pDiag->pOutFile;
  769. fprintf(pOutFile, "gsave %% Image %03d\n", iImageCount);
  770. fprintf(pOutFile, "\tnewpath\n");
  771. fprintf(pOutFile, "\t%.2f %.2f moveto\n",
  772. dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
  773. dDrawUnits2Points(pDiag->lYtop));
  774. fprintf(pOutFile, "\t1.0 setlinewidth\n");
  775. fprintf(pOutFile, "\t0.3 setgray\n");
  776. fprintf(pOutFile, "\t0 %d rlineto\n", pImg->iVerSizeScaled);
  777. fprintf(pOutFile, "\t%d 0 rlineto\n", pImg->iHorSizeScaled);
  778. fprintf(pOutFile, "\t0 %d rlineto\n", -pImg->iVerSizeScaled);
  779. fprintf(pOutFile, "\tclosepath\n");
  780. fprintf(pOutFile, "\tstroke\n");
  781. fprintf(pOutFile, "grestore\n");
  782. pDiag->lXleft = 0;
  783. return TRUE;
  784. } /* end of bAddDummyImagePS */
  785. /*
  786. * vAddFontsPS - add the list of fonts and complete the prologue
  787. */
  788. void
  789. vAddFontsPS(diagram_type *pDiag)
  790. {
  791. FILE *pOutFile;
  792. const font_table_type *pTmp, *pTmp2;
  793. size_t tIndex;
  794. int iLineLen, iOurFontnameLen;
  795. BOOL bFound;
  796. fail(pDiag == NULL);
  797. fail(pDiag->pOutFile == NULL);
  798. pOutFile = pDiag->pOutFile;
  799. iLineLen = fprintf(pOutFile, "%%%%DocumentFonts:");
  800. if (tGetFontTableLength() == 0) {
  801. iLineLen += fprintf(pOutFile, " Courier");
  802. } else {
  803. pTmp = NULL;
  804. while ((pTmp = pGetNextFontTableRecord(pTmp)) != NULL) {
  805. /* Print the document fonts */
  806. bFound = FALSE;
  807. pTmp2 = NULL;
  808. while ((pTmp2 = pGetNextFontTableRecord(pTmp2))
  809. != NULL && pTmp2 < pTmp) {
  810. bFound = STREQ(pTmp2->szOurFontname,
  811. pTmp->szOurFontname);
  812. if (bFound) {
  813. break;
  814. }
  815. }
  816. iOurFontnameLen = (int)strlen(pTmp->szOurFontname);
  817. if (bFound || iOurFontnameLen <= 0) {
  818. continue;
  819. }
  820. if (iLineLen + iOurFontnameLen > 76) {
  821. fprintf(pOutFile, "\n%%%%+");
  822. iLineLen = 3;
  823. }
  824. iLineLen += fprintf(pOutFile,
  825. " %s", pTmp->szOurFontname);
  826. }
  827. }
  828. fprintf(pOutFile, "\n");
  829. fprintf(pOutFile, "%%%%Pages: (atend)\n");
  830. fprintf(pOutFile, "%%%%EndComments\n");
  831. fprintf(pOutFile, "%%%%BeginProlog\n");
  832. switch (eEncoding) {
  833. case encoding_latin_1:
  834. for (tIndex = 0;
  835. tIndex < elementsof(iso_8859_1_data);
  836. tIndex++) {
  837. fprintf(pOutFile, "%s\n", iso_8859_1_data[tIndex]);
  838. }
  839. fprintf(pOutFile, "\n");
  840. for (tIndex = 0;
  841. tIndex < elementsof(iso_8859_x_func);
  842. tIndex++) {
  843. fprintf(pOutFile, "%s\n", iso_8859_x_func[tIndex]);
  844. }
  845. break;
  846. case encoding_latin_2:
  847. for (tIndex = 0;
  848. tIndex < elementsof(iso_8859_2_data);
  849. tIndex++) {
  850. fprintf(pOutFile, "%s\n", iso_8859_2_data[tIndex]);
  851. }
  852. fprintf(pOutFile, "\n");
  853. for (tIndex = 0;
  854. tIndex < elementsof(iso_8859_x_func);
  855. tIndex++) {
  856. fprintf(pOutFile, "%s\n", iso_8859_x_func[tIndex]);
  857. }
  858. break;
  859. case encoding_cyrillic:
  860. for (tIndex = 0;
  861. tIndex < elementsof(iso_8859_5_data);
  862. tIndex++) {
  863. fprintf(pOutFile, "%s\n", iso_8859_5_data[tIndex]);
  864. }
  865. fprintf(pOutFile, "\n");
  866. for (tIndex = 0;
  867. tIndex < elementsof(iso_8859_x_func);
  868. tIndex++) {
  869. fprintf(pOutFile, "%s\n", iso_8859_x_func[tIndex]);
  870. }
  871. break;
  872. case encoding_utf_8:
  873. werr(1,
  874. "The combination PostScript and UTF-8 is not supported");
  875. break;
  876. default:
  877. DBG_DEC(eEncoding);
  878. break;
  879. }
  880. /* The rest of the functions */
  881. for (tIndex = 0; tIndex < elementsof(misc_func); tIndex++) {
  882. fprintf(pOutFile, "%s\n", misc_func[tIndex]);
  883. }
  884. fprintf(pOutFile, "%%%%EndProlog\n");
  885. iPageCount = 1;
  886. fprintf(pDiag->pOutFile, "%%%%Page: %d %d\n", iPageCount, iPageCount);
  887. vAddPageSetup(pDiag->pOutFile);
  888. vAddHeader(pDiag);
  889. } /* end of vAddFontsPS */
  890. /*
  891. * vPrintPS - print a PostScript string
  892. */
  893. static void
  894. vPrintPS(FILE *pFile, const char *szString, size_t tStringLength,
  895. USHORT usFontstyle)
  896. {
  897. double dSuperscriptMove, dSubscriptMove;
  898. const UCHAR *ucBytes;
  899. size_t tCount;
  900. fail(szString == NULL);
  901. if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
  902. return;
  903. }
  904. DBG_DEC_C(usFontSizeCurr < MIN_FONT_SIZE, usFontSizeCurr);
  905. dSuperscriptMove = 0.0;
  906. dSubscriptMove = 0.0;
  907. /* Up for superscript */
  908. if (bIsSuperscript(usFontstyle) && usFontSizeCurr != 0) {
  909. dSuperscriptMove = (double)((usFontSizeCurr + 1) / 2) * 0.375;
  910. fprintf(pFile, "0 %.2f rmoveto\n", dSuperscriptMove);
  911. }
  912. /* Down for subscript */
  913. if (bIsSubscript(usFontstyle) && usFontSizeCurr != 0) {
  914. dSubscriptMove = (double)usFontSizeCurr * 0.125;
  915. fprintf(pFile, "0 %.2f rmoveto\n", -dSubscriptMove);
  916. }
  917. /* Generate and print the PostScript output */
  918. ucBytes = (UCHAR *)szString;
  919. (void)putc('(', pFile);
  920. for (tCount = 0; tCount < tStringLength ; tCount++) {
  921. switch (ucBytes[tCount]) {
  922. case '(':
  923. case ')':
  924. case '\\':
  925. (void)putc('\\', pFile);
  926. (void)putc(szString[tCount], pFile);
  927. break;
  928. default:
  929. if (ucBytes[tCount] < 0x20 ||
  930. (ucBytes[tCount] >= 0x7f &&
  931. ucBytes[tCount] < 0x8c)) {
  932. DBG_HEX(ucBytes[tCount]);
  933. (void)putc(' ', pFile);
  934. } else if (ucBytes[tCount] >= 0x80) {
  935. fprintf(pFile, "\\%03o", (UINT)ucBytes[tCount]);
  936. } else {
  937. (void)putc(szString[tCount], pFile);
  938. }
  939. break;
  940. }
  941. }
  942. fprintf(pFile, ") ");
  943. if ((bIsStrike(usFontstyle) || bIsMarkDel(usFontstyle)) &&
  944. usFontSizeCurr != 0) {
  945. fprintf(pFile, "%.2f %.2f LineShow\n",
  946. (double)usFontSizeCurr * 0.02,
  947. (double)usFontSizeCurr * 0.12);
  948. } else if (bIsUnderline(usFontstyle) && usFontSizeCurr != 0) {
  949. fprintf(pFile, "%.2f %.2f LineShow\n",
  950. (double)usFontSizeCurr * 0.02,
  951. (double)usFontSizeCurr * -0.06);
  952. } else {
  953. fprintf(pFile, "show\n");
  954. }
  955. /* Undo the superscript move */
  956. if (bIsSuperscript(usFontstyle) && usFontSizeCurr != 0) {
  957. fprintf(pFile, "0 %.2f rmoveto\n", -dSuperscriptMove);
  958. }
  959. /* Undo the subscript move */
  960. if (bIsSubscript(usFontstyle) && usFontSizeCurr != 0) {
  961. fprintf(pFile, "0 %.2f rmoveto\n", dSubscriptMove);
  962. }
  963. } /* end of vPrintPS */
  964. /*
  965. * vSetColor - move to the specified color
  966. */
  967. static void
  968. vSetColor(FILE *pFile, UCHAR ucFontColor)
  969. {
  970. ULONG ulTmp, ulRed, ulGreen, ulBlue;
  971. ulTmp = ulColor2Color(ucFontColor);
  972. ulRed = (ulTmp & 0x0000ff00) >> 8;
  973. ulGreen = (ulTmp & 0x00ff0000) >> 16;
  974. ulBlue = (ulTmp & 0xff000000) >> 24;
  975. fprintf(pFile, "%.3f %.3f %.3f setrgbcolor\n",
  976. ulRed / 255.0, ulGreen / 255.0, ulBlue / 255.0);
  977. } /* end of vSetColor */
  978. /*
  979. * vMove2NextLinePS - move to the next line
  980. */
  981. void
  982. vMove2NextLinePS(diagram_type *pDiag, USHORT usFontSize)
  983. {
  984. fail(pDiag == NULL);
  985. fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
  986. pDiag->lYtop -= lComputeLeading(usFontSize);
  987. } /* end of vMove2NextLinePS */
  988. /*
  989. * vSubstringPS - print a sub string
  990. */
  991. void
  992. vSubstringPS(diagram_type *pDiag,
  993. char *szString, size_t tStringLength, long lStringWidth,
  994. UCHAR ucFontColor, USHORT usFontstyle, drawfile_fontref tFontRef,
  995. USHORT usFontSize, USHORT usMaxFontSize)
  996. {
  997. const char *szOurFontname;
  998. fail(pDiag == NULL || szString == NULL);
  999. fail(pDiag->pOutFile == NULL);
  1000. fail(pDiag->lXleft < 0);
  1001. fail(tStringLength != strlen(szString));
  1002. fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
  1003. fail(usMaxFontSize < MIN_FONT_SIZE || usMaxFontSize > MAX_FONT_SIZE);
  1004. fail(usFontSize > usMaxFontSize);
  1005. if (szString[0] == '\0' || tStringLength == 0) {
  1006. return;
  1007. }
  1008. if (tFontRef != tFontRefCurr || usFontSize != usFontSizeCurr) {
  1009. szOurFontname = szGetFontname(tFontRef);
  1010. fail(szOurFontname == NULL);
  1011. fprintf(pDiag->pOutFile,
  1012. "%.1f /%s /%s-ISO-8859-x ChgFnt\n",
  1013. (double)usFontSize / 2.0,
  1014. szOurFontname, szOurFontname);
  1015. tFontRefCurr = tFontRef;
  1016. usFontSizeCurr = usFontSize;
  1017. }
  1018. if ((int)ucFontColor != iFontColorCurr) {
  1019. vSetColor(pDiag->pOutFile, ucFontColor);
  1020. iFontColorCurr = (int)ucFontColor;
  1021. }
  1022. vMoveTo(pDiag, lComputeLeading(usMaxFontSize));
  1023. vPrintPS(pDiag->pOutFile, szString, tStringLength, usFontstyle);
  1024. pDiag->lXleft += lStringWidth;
  1025. } /* end of vSubstringPS */
  1026. /*
  1027. * Create an start of paragraph by moving the y-top mark
  1028. */
  1029. void
  1030. vStartOfParagraphPS(diagram_type *pDiag, long lBeforeIndentation)
  1031. {
  1032. fail(pDiag == NULL);
  1033. fail(lBeforeIndentation < 0);
  1034. pDiag->lXleft = 0;
  1035. pDiag->lYtop -= lMilliPoints2DrawUnits(lBeforeIndentation);
  1036. } /* end of vStartOfParagraphPS */
  1037. /*
  1038. * Create an end of paragraph by moving the y-top mark
  1039. */
  1040. void
  1041. vEndOfParagraphPS(diagram_type *pDiag,
  1042. USHORT usFontSize, long lAfterIndentation)
  1043. {
  1044. fail(pDiag == NULL);
  1045. fail(pDiag->pOutFile == NULL);
  1046. fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
  1047. fail(lAfterIndentation < 0);
  1048. if (pDiag->lXleft > 0) {
  1049. /* To the start of the line */
  1050. vMove2NextLinePS(pDiag, usFontSize);
  1051. }
  1052. pDiag->lXleft = 0;
  1053. pDiag->lYtop -= lMilliPoints2DrawUnits(lAfterIndentation);
  1054. } /* end of vEndOfParagraphPS */
  1055. /*
  1056. * Create an end of page
  1057. */
  1058. void
  1059. vEndOfPagePS(diagram_type *pDiag, BOOL bNewSection)
  1060. {
  1061. vMove2NextPage(pDiag, bNewSection);
  1062. } /* end of vEndOfPagePS */