1*25b329d5SDavid du Colombier /*
2*25b329d5SDavid du Colombier * pdf.c
3*25b329d5SDavid du Colombier * Copyright (C) 2003-2005 A.J. van Os; Released under GNU GPL
4*25b329d5SDavid du Colombier *
5*25b329d5SDavid du Colombier * Description:
6*25b329d5SDavid du Colombier * Functions to deal with the Adobe Portable Document Format (pdf)
7*25b329d5SDavid du Colombier *
8*25b329d5SDavid du Colombier */
9*25b329d5SDavid du Colombier
10*25b329d5SDavid du Colombier #include <stdarg.h>
11*25b329d5SDavid du Colombier #include <string.h>
12*25b329d5SDavid du Colombier #include "version.h"
13*25b329d5SDavid du Colombier #include "antiword.h"
14*25b329d5SDavid du Colombier
15*25b329d5SDavid du Colombier
16*25b329d5SDavid du Colombier /* Constants for the file positions */
17*25b329d5SDavid du Colombier #define INITIAL_LOCATION_SIZE 20
18*25b329d5SDavid du Colombier #define INITIAL_PAGEOBJECT_SIZE 5
19*25b329d5SDavid du Colombier #if defined(DEBUG)
20*25b329d5SDavid du Colombier #define EXTENSION_ARRAY_SIZE 10
21*25b329d5SDavid du Colombier #else
22*25b329d5SDavid du Colombier #define EXTENSION_ARRAY_SIZE 30
23*25b329d5SDavid du Colombier #endif /* DEBUG */
24*25b329d5SDavid du Colombier
25*25b329d5SDavid du Colombier /* The character set */
26*25b329d5SDavid du Colombier static encoding_type eEncoding = encoding_neutral;
27*25b329d5SDavid du Colombier /* Current creator for a PDF header */
28*25b329d5SDavid du Colombier static const char *szProducer = NULL;
29*25b329d5SDavid du Colombier /* The height and width of a PDF page (in DrawUnits) */
30*25b329d5SDavid du Colombier static long lPageHeight = LONG_MAX;
31*25b329d5SDavid du Colombier static long lPageWidth = LONG_MAX;
32*25b329d5SDavid du Colombier /* The height of the footer on the current page (in DrawUnits) */
33*25b329d5SDavid du Colombier static long lFooterHeight = 0;
34*25b329d5SDavid du Colombier /* Inside a footer (to prevent an infinite loop when the footer is too big) */
35*25b329d5SDavid du Colombier static BOOL bInFtrSpace = FALSE;
36*25b329d5SDavid du Colombier /* Current font information */
37*25b329d5SDavid du Colombier static drawfile_fontref tFontRefCurr = (drawfile_fontref)-1;
38*25b329d5SDavid du Colombier static USHORT usFontSizeCurr = 0;
39*25b329d5SDavid du Colombier static int iFontColorCurr = -1;
40*25b329d5SDavid du Colombier /* Current vertical position information */
41*25b329d5SDavid du Colombier static long lYtopCurr = -1;
42*25b329d5SDavid du Colombier /* Image counter */
43*25b329d5SDavid du Colombier static int iImageCount = 0;
44*25b329d5SDavid du Colombier /* Section index */
45*25b329d5SDavid du Colombier static int iSectionIndex = 0;
46*25b329d5SDavid du Colombier /* Are we on the first page of the section? */
47*25b329d5SDavid du Colombier static BOOL bFirstInSection = TRUE;
48*25b329d5SDavid du Colombier /* File positions */
49*25b329d5SDavid du Colombier static long lFilePosition = 0;
50*25b329d5SDavid du Colombier static long *alLocation = NULL;
51*25b329d5SDavid du Colombier static size_t tLocations = 0;
52*25b329d5SDavid du Colombier static int iMaxLocationNumber = 0;
53*25b329d5SDavid du Colombier /* File position at the start of a page */
54*25b329d5SDavid du Colombier static long lStreamStart = -1;
55*25b329d5SDavid du Colombier /* Page objects */
56*25b329d5SDavid du Colombier static int *aiPageObject = NULL;
57*25b329d5SDavid du Colombier static int iPageCount = 0;
58*25b329d5SDavid du Colombier static size_t tMaxPageObjects = 0;
59*25b329d5SDavid du Colombier /* Current object number */
60*25b329d5SDavid du Colombier /* 1 = root; 2 = info; 3 = pages; 4 = encoding; 5-16 = fonts; 17 = resources */
61*25b329d5SDavid du Colombier static int iObjectNumberCurr = 17;
62*25b329d5SDavid du Colombier
63*25b329d5SDavid du Colombier static void vMoveTo(diagram_type *, long);
64*25b329d5SDavid du Colombier
65*25b329d5SDavid du Colombier static const struct {
66*25b329d5SDavid du Colombier const char *szPDFname;
67*25b329d5SDavid du Colombier const char *szPSname;
68*25b329d5SDavid du Colombier } atFontname[] = {
69*25b329d5SDavid du Colombier { "Courier", FONT_MONOSPACED_PLAIN },
70*25b329d5SDavid du Colombier { "Courier-Bold", FONT_MONOSPACED_BOLD },
71*25b329d5SDavid du Colombier { "Courier-Oblique", FONT_MONOSPACED_ITALIC },
72*25b329d5SDavid du Colombier { "Courier-BoldOblique", FONT_MONOSPACED_BOLDITALIC },
73*25b329d5SDavid du Colombier { "Helvetica", FONT_SANS_SERIF_PLAIN },
74*25b329d5SDavid du Colombier { "Helvetica-Bold", FONT_SANS_SERIF_BOLD },
75*25b329d5SDavid du Colombier { "Helvetica-Oblique", FONT_SANS_SERIF_ITALIC },
76*25b329d5SDavid du Colombier { "Helvetica-BoldOblique", FONT_SANS_SERIF_BOLDITALIC },
77*25b329d5SDavid du Colombier { "Times-Roman", FONT_SERIF_PLAIN },
78*25b329d5SDavid du Colombier { "Times-Bold", FONT_SERIF_BOLD },
79*25b329d5SDavid du Colombier { "Times-Italic", FONT_SERIF_ITALIC },
80*25b329d5SDavid du Colombier { "Times-BoldItalic", FONT_SERIF_BOLDITALIC },
81*25b329d5SDavid du Colombier };
82*25b329d5SDavid du Colombier
83*25b329d5SDavid du Colombier static const char *iso_8859_1[] = {
84*25b329d5SDavid du Colombier "128 /Euro",
85*25b329d5SDavid du Colombier "140 /ellipsis /trademark /perthousand /bullet",
86*25b329d5SDavid du Colombier " /quoteleft /quoteright /guilsinglleft /guilsinglright",
87*25b329d5SDavid du Colombier " /quotedblleft /quotedblright /quotedblbase /endash /emdash",
88*25b329d5SDavid du Colombier " /minus /OE /oe /dagger /daggerdbl /fi /fl",
89*25b329d5SDavid du Colombier "160 /space /exclamdown /cent /sterling /currency",
90*25b329d5SDavid du Colombier " /yen /brokenbar /section /dieresis /copyright",
91*25b329d5SDavid du Colombier " /ordfeminine /guillemotleft /logicalnot /hyphen /registered",
92*25b329d5SDavid du Colombier " /macron /degree /plusminus /twosuperior /threesuperior",
93*25b329d5SDavid du Colombier " /acute /mu /paragraph /periodcentered /cedilla",
94*25b329d5SDavid du Colombier " /onesuperior /ordmasculine /guillemotright /onequarter",
95*25b329d5SDavid du Colombier " /onehalf /threequarters /questiondown /Agrave /Aacute",
96*25b329d5SDavid du Colombier " /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla",
97*25b329d5SDavid du Colombier " /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute",
98*25b329d5SDavid du Colombier " /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute",
99*25b329d5SDavid du Colombier " /Ocircumflex /Otilde /Odieresis /multiply /Oslash",
100*25b329d5SDavid du Colombier " /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn",
101*25b329d5SDavid du Colombier " /germandbls /agrave /aacute /acircumflex /atilde",
102*25b329d5SDavid du Colombier " /adieresis /aring /ae /ccedilla /egrave /eacute",
103*25b329d5SDavid du Colombier " /ecircumflex /edieresis /igrave /iacute /icircumflex",
104*25b329d5SDavid du Colombier " /idieresis /eth /ntilde /ograve /oacute /ocircumflex",
105*25b329d5SDavid du Colombier " /otilde /odieresis /divide /oslash /ugrave /uacute",
106*25b329d5SDavid du Colombier " /ucircumflex /udieresis /yacute /thorn /ydieresis",
107*25b329d5SDavid du Colombier };
108*25b329d5SDavid du Colombier
109*25b329d5SDavid du Colombier static const char *iso_8859_2[] = {
110*25b329d5SDavid du Colombier "160 /space /Aogonek /breve /Lslash /currency /Lcaron",
111*25b329d5SDavid du Colombier " /Sacute /section /dieresis /Scaron /Scommaaccent",
112*25b329d5SDavid du Colombier " /Tcaron /Zacute /hyphen /Zcaron /Zdotaccent /degree",
113*25b329d5SDavid du Colombier " /aogonek /ogonek /lslash /acute /lcaron /sacute",
114*25b329d5SDavid du Colombier " /caron /cedilla /scaron /scommaaccent /tcaron",
115*25b329d5SDavid du Colombier " /zacute /hungarumlaut /zcaron /zdotaccent /Racute",
116*25b329d5SDavid du Colombier " /Aacute /Acircumflex /Abreve /Adieresis /Lacute",
117*25b329d5SDavid du Colombier " /Cacute /Ccedilla /Ccaron /Eacute /Eogonek",
118*25b329d5SDavid du Colombier " /Edieresis /Ecaron /Iacute /Icircumflex /Dcaron",
119*25b329d5SDavid du Colombier " /.notdef /Nacute /Ncaron /Oacute /Ocircumflex",
120*25b329d5SDavid du Colombier " /Ohungarumlaut /Odieresis /multiply /Rcaron /Uring",
121*25b329d5SDavid du Colombier " /Uacute /Uhungarumlaut /Udieresis /Yacute /Tcommaaccent",
122*25b329d5SDavid du Colombier " /germandbls /racute /aacute /acircumflex /abreve",
123*25b329d5SDavid du Colombier " /adieresis /lacute /cacute /ccedilla /ccaron /eacute",
124*25b329d5SDavid du Colombier " /eogonek /edieresis /ecaron /iacute /icircumflex",
125*25b329d5SDavid du Colombier " /dcaron /.notdef /nacute /ncaron /oacute /ocircumflex",
126*25b329d5SDavid du Colombier " /ohungarumlaut /odieresis /divide /rcaron /uring",
127*25b329d5SDavid du Colombier " /uacute /uhungarumlaut /udieresis /yacute /tcommaaccent",
128*25b329d5SDavid du Colombier " /dotaccent",
129*25b329d5SDavid du Colombier };
130*25b329d5SDavid du Colombier
131*25b329d5SDavid du Colombier
132*25b329d5SDavid du Colombier /*
133*25b329d5SDavid du Colombier * tGetFontIndex - get the font index
134*25b329d5SDavid du Colombier */
135*25b329d5SDavid du Colombier static size_t
tGetFontIndex(drawfile_fontref tFontRef)136*25b329d5SDavid du Colombier tGetFontIndex(drawfile_fontref tFontRef)
137*25b329d5SDavid du Colombier {
138*25b329d5SDavid du Colombier const char *szFontname;
139*25b329d5SDavid du Colombier size_t tIndex;
140*25b329d5SDavid du Colombier
141*25b329d5SDavid du Colombier /* Get the font name */
142*25b329d5SDavid du Colombier szFontname = szGetFontname(tFontRef);
143*25b329d5SDavid du Colombier fail(szFontname == NULL);
144*25b329d5SDavid du Colombier if (szFontname == NULL) {
145*25b329d5SDavid du Colombier return 0;
146*25b329d5SDavid du Colombier }
147*25b329d5SDavid du Colombier
148*25b329d5SDavid du Colombier /* Find the name in the table */
149*25b329d5SDavid du Colombier for (tIndex = 0; tIndex < elementsof(atFontname); tIndex++) {
150*25b329d5SDavid du Colombier if (STRCEQ(atFontname[tIndex].szPSname, szFontname)) {
151*25b329d5SDavid du Colombier return tIndex;
152*25b329d5SDavid du Colombier }
153*25b329d5SDavid du Colombier }
154*25b329d5SDavid du Colombier /* Not found */
155*25b329d5SDavid du Colombier DBG_DEC(tFontRef);
156*25b329d5SDavid du Colombier DBG_MSG(szFontname);
157*25b329d5SDavid du Colombier return 0;
158*25b329d5SDavid du Colombier } /* end of tGetFontIndex */
159*25b329d5SDavid du Colombier
160*25b329d5SDavid du Colombier /*
161*25b329d5SDavid du Colombier * vSetLocation - store the location of objects
162*25b329d5SDavid du Colombier */
163*25b329d5SDavid du Colombier static void
vSetLocation(int iLocationNumber)164*25b329d5SDavid du Colombier vSetLocation(int iLocationNumber)
165*25b329d5SDavid du Colombier {
166*25b329d5SDavid du Colombier fail(iLocationNumber <= 0);
167*25b329d5SDavid du Colombier
168*25b329d5SDavid du Colombier if ((size_t)iLocationNumber >= tLocations) {
169*25b329d5SDavid du Colombier /* Extend and set to zero */
170*25b329d5SDavid du Colombier tLocations += EXTENSION_ARRAY_SIZE;
171*25b329d5SDavid du Colombier alLocation = xrealloc(alLocation, tLocations * sizeof(long));
172*25b329d5SDavid du Colombier memset(alLocation + tLocations - EXTENSION_ARRAY_SIZE,
173*25b329d5SDavid du Colombier 0,
174*25b329d5SDavid du Colombier EXTENSION_ARRAY_SIZE * sizeof(long));
175*25b329d5SDavid du Colombier DBG_DEC(tLocations);
176*25b329d5SDavid du Colombier }
177*25b329d5SDavid du Colombier if (iLocationNumber > iMaxLocationNumber) {
178*25b329d5SDavid du Colombier iMaxLocationNumber = iLocationNumber;
179*25b329d5SDavid du Colombier }
180*25b329d5SDavid du Colombier
181*25b329d5SDavid du Colombier DBG_DEC_C((size_t)iLocationNumber >= tLocations, iLocationNumber);
182*25b329d5SDavid du Colombier DBG_DEC_C((size_t)iLocationNumber >= tLocations, tLocations);
183*25b329d5SDavid du Colombier fail((size_t)iLocationNumber >= tLocations);
184*25b329d5SDavid du Colombier
185*25b329d5SDavid du Colombier alLocation[iLocationNumber] = lFilePosition;
186*25b329d5SDavid du Colombier } /* end of vSetLocation */
187*25b329d5SDavid du Colombier
188*25b329d5SDavid du Colombier /*
189*25b329d5SDavid du Colombier * vFillNextPageObject - fil the next page object with the current object number
190*25b329d5SDavid du Colombier */
191*25b329d5SDavid du Colombier static void
vFillNextPageObject(void)192*25b329d5SDavid du Colombier vFillNextPageObject(void)
193*25b329d5SDavid du Colombier {
194*25b329d5SDavid du Colombier iPageCount++;
195*25b329d5SDavid du Colombier if ((size_t)iPageCount >= tMaxPageObjects) {
196*25b329d5SDavid du Colombier /* Extend the array */
197*25b329d5SDavid du Colombier tMaxPageObjects += EXTENSION_ARRAY_SIZE;
198*25b329d5SDavid du Colombier aiPageObject = xrealloc(aiPageObject,
199*25b329d5SDavid du Colombier tMaxPageObjects * sizeof(int));
200*25b329d5SDavid du Colombier DBG_DEC(tMaxPageObjects);
201*25b329d5SDavid du Colombier }
202*25b329d5SDavid du Colombier aiPageObject[iPageCount] = iObjectNumberCurr;
203*25b329d5SDavid du Colombier } /* end of vFillNextPageObject */
204*25b329d5SDavid du Colombier
205*25b329d5SDavid du Colombier /*
206*25b329d5SDavid du Colombier * vFPprintf - printf and update the fileposition
207*25b329d5SDavid du Colombier *
208*25b329d5SDavid du Colombier * called with arguments like fprintf(3)
209*25b329d5SDavid du Colombier */
210*25b329d5SDavid du Colombier static void
vFPprintf(FILE * pOutFile,const char * szFormat,...)211*25b329d5SDavid du Colombier vFPprintf(FILE *pOutFile, const char *szFormat, ...)
212*25b329d5SDavid du Colombier {
213*25b329d5SDavid du Colombier va_list tArg;
214*25b329d5SDavid du Colombier
215*25b329d5SDavid du Colombier va_start(tArg, szFormat);
216*25b329d5SDavid du Colombier lFilePosition += vfprintf(pOutFile, szFormat, tArg);
217*25b329d5SDavid du Colombier va_end(tArg);
218*25b329d5SDavid du Colombier } /* end of vFPprintf */
219*25b329d5SDavid du Colombier
220*25b329d5SDavid du Colombier /*
221*25b329d5SDavid du Colombier * vCreateInfoDictionary - create the document information dictionary
222*25b329d5SDavid du Colombier */
223*25b329d5SDavid du Colombier void
vCreateInfoDictionary(diagram_type * pDiag,int iWordVersion)224*25b329d5SDavid du Colombier vCreateInfoDictionary(diagram_type *pDiag, int iWordVersion)
225*25b329d5SDavid du Colombier {
226*25b329d5SDavid du Colombier FILE *pOutFile;
227*25b329d5SDavid du Colombier const char *szTitle, *szAuthor, *szSubject, *szCreator;
228*25b329d5SDavid du Colombier const char *szCreationDate, *szModDate;
229*25b329d5SDavid du Colombier
230*25b329d5SDavid du Colombier fail(pDiag == NULL);
231*25b329d5SDavid du Colombier fail(pDiag->pOutFile == NULL);
232*25b329d5SDavid du Colombier fail(iWordVersion < 0);
233*25b329d5SDavid du Colombier fail(szProducer == NULL || szProducer[0] == '\0');
234*25b329d5SDavid du Colombier
235*25b329d5SDavid du Colombier szTitle = szGetTitle();
236*25b329d5SDavid du Colombier szAuthor = szGetAuthor();
237*25b329d5SDavid du Colombier szSubject = szGetSubject();
238*25b329d5SDavid du Colombier szCreationDate = szGetCreationDate();
239*25b329d5SDavid du Colombier szModDate = szGetModDate();
240*25b329d5SDavid du Colombier
241*25b329d5SDavid du Colombier switch (iWordVersion) {
242*25b329d5SDavid du Colombier case 0: szCreator = "Word for DOS"; break;
243*25b329d5SDavid du Colombier case 1: szCreator = "WinWord 1.x"; break;
244*25b329d5SDavid du Colombier case 2: szCreator = "WinWord 2.0"; break;
245*25b329d5SDavid du Colombier case 4: szCreator = "MacWord 4"; break;
246*25b329d5SDavid du Colombier case 5: szCreator = "MacWord 5"; break;
247*25b329d5SDavid du Colombier case 6: szCreator = "Word 6"; break;
248*25b329d5SDavid du Colombier case 7: szCreator = "Word 7/95"; break;
249*25b329d5SDavid du Colombier case 8: szCreator = "Word 97 or later"; break;
250*25b329d5SDavid du Colombier default: szCreator = NULL; break;
251*25b329d5SDavid du Colombier }
252*25b329d5SDavid du Colombier
253*25b329d5SDavid du Colombier pOutFile = pDiag->pOutFile;
254*25b329d5SDavid du Colombier
255*25b329d5SDavid du Colombier vSetLocation(2);
256*25b329d5SDavid du Colombier vFPprintf(pOutFile, "2 0 obj\n");
257*25b329d5SDavid du Colombier vFPprintf(pOutFile, "<<\n");
258*25b329d5SDavid du Colombier if (szTitle != NULL && szTitle[0] != '\0') {
259*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Title (%s)\n", szTitle);
260*25b329d5SDavid du Colombier }
261*25b329d5SDavid du Colombier if (szAuthor != NULL && szAuthor[0] != '\0') {
262*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Author (%s)\n", szAuthor);
263*25b329d5SDavid du Colombier }
264*25b329d5SDavid du Colombier if (szSubject != NULL && szSubject[0] != '\0') {
265*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Subject (%s)\n", szSubject);
266*25b329d5SDavid du Colombier }
267*25b329d5SDavid du Colombier if (szCreator != NULL && szCreator[0] != '\0') {
268*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Creator (%s)\n", szCreator);
269*25b329d5SDavid du Colombier }
270*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Producer (%s %s)\n", szProducer, VERSIONSTRING);
271*25b329d5SDavid du Colombier if (szCreationDate != NULL && szCreationDate[0] != '\0') {
272*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/CreationDate (%s)\n", szCreationDate);
273*25b329d5SDavid du Colombier }
274*25b329d5SDavid du Colombier if (szModDate != NULL && szModDate[0] != '\0') {
275*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/ModDate (%s)\n", szModDate);
276*25b329d5SDavid du Colombier }
277*25b329d5SDavid du Colombier vFPprintf(pOutFile, ">>\n");
278*25b329d5SDavid du Colombier vFPprintf(pOutFile, "endobj\n");
279*25b329d5SDavid du Colombier } /* end of vCreateInfoDictionary */
280*25b329d5SDavid du Colombier
281*25b329d5SDavid du Colombier /*
282*25b329d5SDavid du Colombier * vAddHdrFtr - add a header or footer
283*25b329d5SDavid du Colombier */
284*25b329d5SDavid du Colombier static void
vAddHdrFtr(diagram_type * pDiag,const hdrftr_block_type * pHdrFtrInfo)285*25b329d5SDavid du Colombier vAddHdrFtr(diagram_type *pDiag, const hdrftr_block_type *pHdrFtrInfo)
286*25b329d5SDavid du Colombier {
287*25b329d5SDavid du Colombier output_type *pStart, *pPrev, *pNext;
288*25b329d5SDavid du Colombier
289*25b329d5SDavid du Colombier fail(pDiag == NULL);
290*25b329d5SDavid du Colombier fail(pHdrFtrInfo == NULL);
291*25b329d5SDavid du Colombier
292*25b329d5SDavid du Colombier vStartOfParagraphPDF(pDiag, 0);
293*25b329d5SDavid du Colombier pStart = pHdrFtrInfo->pText;
294*25b329d5SDavid du Colombier while (pStart != NULL) {
295*25b329d5SDavid du Colombier pNext = pStart;
296*25b329d5SDavid du Colombier while (pNext != NULL &&
297*25b329d5SDavid du Colombier (pNext->tNextFree != 1 ||
298*25b329d5SDavid du Colombier (pNext->szStorage[0] != PAR_END &&
299*25b329d5SDavid du Colombier pNext->szStorage[0] != HARD_RETURN))) {
300*25b329d5SDavid du Colombier pNext = pNext->pNext;
301*25b329d5SDavid du Colombier }
302*25b329d5SDavid du Colombier if (pNext == NULL) {
303*25b329d5SDavid du Colombier if (bOutputContainsText(pStart)) {
304*25b329d5SDavid du Colombier vAlign2Window(pDiag, pStart,
305*25b329d5SDavid du Colombier lChar2MilliPoints(DEFAULT_SCREEN_WIDTH),
306*25b329d5SDavid du Colombier ALIGNMENT_LEFT);
307*25b329d5SDavid du Colombier } else {
308*25b329d5SDavid du Colombier vMove2NextLinePDF(pDiag, pStart->usFontSize);
309*25b329d5SDavid du Colombier }
310*25b329d5SDavid du Colombier break;
311*25b329d5SDavid du Colombier }
312*25b329d5SDavid du Colombier fail(pNext->tNextFree != 1);
313*25b329d5SDavid du Colombier fail(pNext->szStorage[0] != PAR_END &&
314*25b329d5SDavid du Colombier pNext->szStorage[0] != HARD_RETURN);
315*25b329d5SDavid du Colombier
316*25b329d5SDavid du Colombier if (pStart != pNext) {
317*25b329d5SDavid du Colombier /* There is something to print */
318*25b329d5SDavid du Colombier pPrev = pNext->pPrev;
319*25b329d5SDavid du Colombier fail(pPrev->pNext != pNext);
320*25b329d5SDavid du Colombier /* Cut the chain */
321*25b329d5SDavid du Colombier pPrev->pNext = NULL;
322*25b329d5SDavid du Colombier if (bOutputContainsText(pStart)) {
323*25b329d5SDavid du Colombier /* Print it */
324*25b329d5SDavid du Colombier vAlign2Window(pDiag, pStart,
325*25b329d5SDavid du Colombier lChar2MilliPoints(DEFAULT_SCREEN_WIDTH),
326*25b329d5SDavid du Colombier ALIGNMENT_LEFT);
327*25b329d5SDavid du Colombier } else {
328*25b329d5SDavid du Colombier /* Just an empty line */
329*25b329d5SDavid du Colombier vMove2NextLinePDF(pDiag, pStart->usFontSize);
330*25b329d5SDavid du Colombier }
331*25b329d5SDavid du Colombier /* Repair the chain */
332*25b329d5SDavid du Colombier pPrev->pNext = pNext;
333*25b329d5SDavid du Colombier }
334*25b329d5SDavid du Colombier if (pNext->szStorage[0] == PAR_END) {
335*25b329d5SDavid du Colombier vEndOfParagraphPDF(pDiag, pNext->usFontSize,
336*25b329d5SDavid du Colombier (long)pNext->usFontSize * 200);
337*25b329d5SDavid du Colombier }
338*25b329d5SDavid du Colombier pStart = pNext->pNext;
339*25b329d5SDavid du Colombier }
340*25b329d5SDavid du Colombier } /* end of vAddHdrFtr */
341*25b329d5SDavid du Colombier
342*25b329d5SDavid du Colombier /*
343*25b329d5SDavid du Colombier * vAddHeader - add a page header
344*25b329d5SDavid du Colombier */
345*25b329d5SDavid du Colombier static void
vAddHeader(diagram_type * pDiag)346*25b329d5SDavid du Colombier vAddHeader(diagram_type *pDiag)
347*25b329d5SDavid du Colombier {
348*25b329d5SDavid du Colombier const hdrftr_block_type *pHdrInfo;
349*25b329d5SDavid du Colombier const hdrftr_block_type *pFtrInfo;
350*25b329d5SDavid du Colombier
351*25b329d5SDavid du Colombier fail(pDiag == NULL);
352*25b329d5SDavid du Colombier
353*25b329d5SDavid du Colombier NO_DBG_MSG("vAddHeader");
354*25b329d5SDavid du Colombier
355*25b329d5SDavid du Colombier pHdrInfo = pGetHdrFtrInfo(iSectionIndex, TRUE,
356*25b329d5SDavid du Colombier odd(iPageCount), bFirstInSection);
357*25b329d5SDavid du Colombier pFtrInfo = pGetHdrFtrInfo(iSectionIndex, FALSE,
358*25b329d5SDavid du Colombier odd(iPageCount), bFirstInSection);
359*25b329d5SDavid du Colombier /* Set the height of the footer of this page */
360*25b329d5SDavid du Colombier lFooterHeight = pFtrInfo == NULL ? 0 : pFtrInfo->lHeight;
361*25b329d5SDavid du Colombier fail(lFooterHeight < 0);
362*25b329d5SDavid du Colombier
363*25b329d5SDavid du Colombier if (pHdrInfo == NULL ||
364*25b329d5SDavid du Colombier pHdrInfo->pText == NULL ||
365*25b329d5SDavid du Colombier pHdrInfo->lHeight <= 0) {
366*25b329d5SDavid du Colombier fail(pHdrInfo != NULL && pHdrInfo->lHeight < 0);
367*25b329d5SDavid du Colombier fail(pHdrInfo != NULL &&
368*25b329d5SDavid du Colombier pHdrInfo->pText != NULL &&
369*25b329d5SDavid du Colombier pHdrInfo->lHeight == 0);
370*25b329d5SDavid du Colombier return;
371*25b329d5SDavid du Colombier }
372*25b329d5SDavid du Colombier
373*25b329d5SDavid du Colombier vAddHdrFtr(pDiag, pHdrInfo);
374*25b329d5SDavid du Colombier
375*25b329d5SDavid du Colombier DBG_DEC_C(pHdrInfo->lHeight !=
376*25b329d5SDavid du Colombier lPageHeight - PS_TOP_MARGIN - pDiag->lYtop,
377*25b329d5SDavid du Colombier pHdrInfo->lHeight);
378*25b329d5SDavid du Colombier DBG_DEC_C(pHdrInfo->lHeight !=
379*25b329d5SDavid du Colombier lPageHeight - PS_TOP_MARGIN - pDiag->lYtop,
380*25b329d5SDavid du Colombier lPageHeight - PS_TOP_MARGIN - pDiag->lYtop);
381*25b329d5SDavid du Colombier } /* end of vAddHeader */
382*25b329d5SDavid du Colombier
383*25b329d5SDavid du Colombier /*
384*25b329d5SDavid du Colombier * vAddFooter - add a page footer
385*25b329d5SDavid du Colombier */
386*25b329d5SDavid du Colombier static void
vAddFooter(diagram_type * pDiag)387*25b329d5SDavid du Colombier vAddFooter(diagram_type *pDiag)
388*25b329d5SDavid du Colombier {
389*25b329d5SDavid du Colombier const hdrftr_block_type *pFtrInfo;
390*25b329d5SDavid du Colombier
391*25b329d5SDavid du Colombier fail(pDiag == NULL);
392*25b329d5SDavid du Colombier
393*25b329d5SDavid du Colombier NO_DBG_MSG("vAddFooter");
394*25b329d5SDavid du Colombier
395*25b329d5SDavid du Colombier pFtrInfo = pGetHdrFtrInfo(iSectionIndex, FALSE,
396*25b329d5SDavid du Colombier odd(iPageCount), bFirstInSection);
397*25b329d5SDavid du Colombier bFirstInSection = FALSE;
398*25b329d5SDavid du Colombier if (pFtrInfo == NULL ||
399*25b329d5SDavid du Colombier pFtrInfo->pText == NULL ||
400*25b329d5SDavid du Colombier pFtrInfo->lHeight <= 0) {
401*25b329d5SDavid du Colombier fail(pFtrInfo != NULL && pFtrInfo->lHeight < 0);
402*25b329d5SDavid du Colombier fail(pFtrInfo != NULL &&
403*25b329d5SDavid du Colombier pFtrInfo->pText != NULL &&
404*25b329d5SDavid du Colombier pFtrInfo->lHeight == 0);
405*25b329d5SDavid du Colombier return;
406*25b329d5SDavid du Colombier }
407*25b329d5SDavid du Colombier
408*25b329d5SDavid du Colombier bInFtrSpace = TRUE;
409*25b329d5SDavid du Colombier
410*25b329d5SDavid du Colombier DBG_DEC_C(pFtrInfo->lHeight != lFooterHeight, pFtrInfo->lHeight);
411*25b329d5SDavid du Colombier DBG_DEC_C(pFtrInfo->lHeight != lFooterHeight, lFooterHeight);
412*25b329d5SDavid du Colombier DBG_DEC_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
413*25b329d5SDavid du Colombier pDiag->lYtop);
414*25b329d5SDavid du Colombier DBG_DEC_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
415*25b329d5SDavid du Colombier lFooterHeight + PS_BOTTOM_MARGIN);
416*25b329d5SDavid du Colombier
417*25b329d5SDavid du Colombier if (pDiag->lYtop > lFooterHeight + PS_BOTTOM_MARGIN) {
418*25b329d5SDavid du Colombier /* Move down to the start of the footer */
419*25b329d5SDavid du Colombier pDiag->lYtop = lFooterHeight + PS_BOTTOM_MARGIN;
420*25b329d5SDavid du Colombier vMoveTo(pDiag, 0);
421*25b329d5SDavid du Colombier } else if (pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN / 2) {
422*25b329d5SDavid du Colombier DBG_FIXME();
423*25b329d5SDavid du Colombier /*
424*25b329d5SDavid du Colombier * Move up to the start of the footer, to prevent moving
425*25b329d5SDavid du Colombier * of the bottom edge of the paper
426*25b329d5SDavid du Colombier */
427*25b329d5SDavid du Colombier pDiag->lYtop = lFooterHeight + PS_BOTTOM_MARGIN;
428*25b329d5SDavid du Colombier vMoveTo(pDiag, 0);
429*25b329d5SDavid du Colombier }
430*25b329d5SDavid du Colombier
431*25b329d5SDavid du Colombier DBG_FLT_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
432*25b329d5SDavid du Colombier dDrawUnits2Points(lFooterHeight + PS_BOTTOM_MARGIN - pDiag->lYtop));
433*25b329d5SDavid du Colombier
434*25b329d5SDavid du Colombier vAddHdrFtr(pDiag, pFtrInfo);
435*25b329d5SDavid du Colombier bInFtrSpace = FALSE;
436*25b329d5SDavid du Colombier } /* end of vAddFooter */
437*25b329d5SDavid du Colombier
438*25b329d5SDavid du Colombier /*
439*25b329d5SDavid du Colombier * vEndPageObject - end the current page object
440*25b329d5SDavid du Colombier */
441*25b329d5SDavid du Colombier static void
vEndPageObject(FILE * pOutFile)442*25b329d5SDavid du Colombier vEndPageObject(FILE *pOutFile)
443*25b329d5SDavid du Colombier {
444*25b329d5SDavid du Colombier long lStreamEnd;
445*25b329d5SDavid du Colombier
446*25b329d5SDavid du Colombier if (lStreamStart < 0) {
447*25b329d5SDavid du Colombier /* There is no current page object */
448*25b329d5SDavid du Colombier return;
449*25b329d5SDavid du Colombier }
450*25b329d5SDavid du Colombier
451*25b329d5SDavid du Colombier vFPprintf(pOutFile, "ET\n");
452*25b329d5SDavid du Colombier lStreamEnd = lFilePosition;
453*25b329d5SDavid du Colombier vFPprintf(pOutFile, "endstream\n");
454*25b329d5SDavid du Colombier vFPprintf(pOutFile, "endobj\n");
455*25b329d5SDavid du Colombier
456*25b329d5SDavid du Colombier iObjectNumberCurr++;
457*25b329d5SDavid du Colombier vSetLocation(iObjectNumberCurr);
458*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%d 0 obj\n", iObjectNumberCurr);
459*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%lu\n", lStreamEnd - lStreamStart);
460*25b329d5SDavid du Colombier vFPprintf(pOutFile, "endobj\n");
461*25b329d5SDavid du Colombier } /* end of vEndPageObject */
462*25b329d5SDavid du Colombier
463*25b329d5SDavid du Colombier /*
464*25b329d5SDavid du Colombier * vMove2NextPage - move to the start of the next page
465*25b329d5SDavid du Colombier */
466*25b329d5SDavid du Colombier static void
vMove2NextPage(diagram_type * pDiag,BOOL bNewSection)467*25b329d5SDavid du Colombier vMove2NextPage(diagram_type *pDiag, BOOL bNewSection)
468*25b329d5SDavid du Colombier {
469*25b329d5SDavid du Colombier FILE *pOutFile;
470*25b329d5SDavid du Colombier
471*25b329d5SDavid du Colombier fail(pDiag == NULL);
472*25b329d5SDavid du Colombier fail(pDiag->pOutFile == NULL);
473*25b329d5SDavid du Colombier
474*25b329d5SDavid du Colombier pOutFile = pDiag->pOutFile;
475*25b329d5SDavid du Colombier
476*25b329d5SDavid du Colombier vAddFooter(pDiag);
477*25b329d5SDavid du Colombier /* End the old page object */
478*25b329d5SDavid du Colombier vEndPageObject(pOutFile);
479*25b329d5SDavid du Colombier if (bNewSection) {
480*25b329d5SDavid du Colombier iSectionIndex++;
481*25b329d5SDavid du Colombier bFirstInSection = TRUE;
482*25b329d5SDavid du Colombier }
483*25b329d5SDavid du Colombier
484*25b329d5SDavid du Colombier /* Start the new page object */
485*25b329d5SDavid du Colombier iObjectNumberCurr++;
486*25b329d5SDavid du Colombier vSetLocation(iObjectNumberCurr);
487*25b329d5SDavid du Colombier vFillNextPageObject();
488*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%d 0 obj\n", iObjectNumberCurr);
489*25b329d5SDavid du Colombier vFPprintf(pOutFile, "<<\n");
490*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Type /Page\n");
491*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Parent 3 0 R\n");
492*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Resources 17 0 R\n");
493*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Contents %d 0 R\n", iObjectNumberCurr + 1);
494*25b329d5SDavid du Colombier vFPprintf(pOutFile, ">>\n");
495*25b329d5SDavid du Colombier vFPprintf(pOutFile, "endobj\n");
496*25b329d5SDavid du Colombier
497*25b329d5SDavid du Colombier /* Start the new text object */
498*25b329d5SDavid du Colombier iObjectNumberCurr++;
499*25b329d5SDavid du Colombier vSetLocation(iObjectNumberCurr);
500*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%d 0 obj\n", iObjectNumberCurr);
501*25b329d5SDavid du Colombier vFPprintf(pOutFile, "<<\n");
502*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Length %d 0 R\n", iObjectNumberCurr + 1);
503*25b329d5SDavid du Colombier vFPprintf(pOutFile, ">>\n");
504*25b329d5SDavid du Colombier vFPprintf(pOutFile, "stream\n");
505*25b329d5SDavid du Colombier lStreamStart = lFilePosition;
506*25b329d5SDavid du Colombier vFPprintf(pOutFile, "BT\n");
507*25b329d5SDavid du Colombier
508*25b329d5SDavid du Colombier /* Set variables to their start of page values */
509*25b329d5SDavid du Colombier pDiag->lYtop = lPageHeight - PS_TOP_MARGIN;
510*25b329d5SDavid du Colombier tFontRefCurr = (drawfile_fontref)-1;
511*25b329d5SDavid du Colombier usFontSizeCurr = 0;
512*25b329d5SDavid du Colombier iFontColorCurr = -1;
513*25b329d5SDavid du Colombier lYtopCurr = -1;
514*25b329d5SDavid du Colombier vAddHeader(pDiag);
515*25b329d5SDavid du Colombier } /* end of vMove2NextPage */
516*25b329d5SDavid du Colombier
517*25b329d5SDavid du Colombier /*
518*25b329d5SDavid du Colombier * vMoveTo - move to the specified X,Y coordinates
519*25b329d5SDavid du Colombier *
520*25b329d5SDavid du Colombier * Move the current position of the specified diagram to its X,Y coordinates,
521*25b329d5SDavid du Colombier * start on a new page if needed
522*25b329d5SDavid du Colombier */
523*25b329d5SDavid du Colombier static void
vMoveTo(diagram_type * pDiag,long lLastVerticalMovement)524*25b329d5SDavid du Colombier vMoveTo(diagram_type *pDiag, long lLastVerticalMovement)
525*25b329d5SDavid du Colombier {
526*25b329d5SDavid du Colombier fail(pDiag == NULL);
527*25b329d5SDavid du Colombier fail(pDiag->pOutFile == NULL);
528*25b329d5SDavid du Colombier
529*25b329d5SDavid du Colombier if (pDiag->lYtop <= lFooterHeight + PS_BOTTOM_MARGIN && !bInFtrSpace) {
530*25b329d5SDavid du Colombier vMove2NextPage(pDiag, FALSE);
531*25b329d5SDavid du Colombier /* Repeat the last vertical movement on the new page */
532*25b329d5SDavid du Colombier pDiag->lYtop -= lLastVerticalMovement;
533*25b329d5SDavid du Colombier }
534*25b329d5SDavid du Colombier
535*25b329d5SDavid du Colombier fail(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN && !bInFtrSpace);
536*25b329d5SDavid du Colombier DBG_DEC_C(pDiag->lYtop < PS_BOTTOM_MARGIN, pDiag->lYtop);
537*25b329d5SDavid du Colombier fail(pDiag->lYtop < PS_BOTTOM_MARGIN / 3);
538*25b329d5SDavid du Colombier
539*25b329d5SDavid du Colombier if (pDiag->lYtop != lYtopCurr) {
540*25b329d5SDavid du Colombier vFPprintf(pDiag->pOutFile, "1 0 0 1 %.2f %.2f Tm\n",
541*25b329d5SDavid du Colombier dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
542*25b329d5SDavid du Colombier dDrawUnits2Points(pDiag->lYtop));
543*25b329d5SDavid du Colombier lYtopCurr = pDiag->lYtop;
544*25b329d5SDavid du Colombier }
545*25b329d5SDavid du Colombier } /* end of vMoveTo */
546*25b329d5SDavid du Colombier
547*25b329d5SDavid du Colombier /*
548*25b329d5SDavid du Colombier * vProloguePDF - set options and perform the PDF initialization
549*25b329d5SDavid du Colombier */
550*25b329d5SDavid du Colombier void
vProloguePDF(diagram_type * pDiag,const char * szTask,const options_type * pOptions)551*25b329d5SDavid du Colombier vProloguePDF(diagram_type *pDiag,
552*25b329d5SDavid du Colombier const char *szTask, const options_type *pOptions)
553*25b329d5SDavid du Colombier {
554*25b329d5SDavid du Colombier FILE *pOutFile;
555*25b329d5SDavid du Colombier
556*25b329d5SDavid du Colombier fail(pDiag == NULL);
557*25b329d5SDavid du Colombier fail(pDiag->pOutFile == NULL);
558*25b329d5SDavid du Colombier fail(pOptions == NULL);
559*25b329d5SDavid du Colombier
560*25b329d5SDavid du Colombier pOutFile = pDiag->pOutFile;
561*25b329d5SDavid du Colombier
562*25b329d5SDavid du Colombier eEncoding = pOptions->eEncoding;
563*25b329d5SDavid du Colombier
564*25b329d5SDavid du Colombier /* Create an empty location array */
565*25b329d5SDavid du Colombier tLocations = INITIAL_LOCATION_SIZE;
566*25b329d5SDavid du Colombier alLocation = xcalloc(tLocations, sizeof(long));
567*25b329d5SDavid du Colombier
568*25b329d5SDavid du Colombier /* Create an empty pageobject array */
569*25b329d5SDavid du Colombier tMaxPageObjects = INITIAL_PAGEOBJECT_SIZE;
570*25b329d5SDavid du Colombier aiPageObject = xcalloc(tMaxPageObjects, sizeof(int));
571*25b329d5SDavid du Colombier
572*25b329d5SDavid du Colombier if (pOptions->iPageHeight == INT_MAX) {
573*25b329d5SDavid du Colombier lPageHeight = LONG_MAX;
574*25b329d5SDavid du Colombier } else {
575*25b329d5SDavid du Colombier lPageHeight = lPoints2DrawUnits(pOptions->iPageHeight);
576*25b329d5SDavid du Colombier }
577*25b329d5SDavid du Colombier DBG_DEC(lPageHeight);
578*25b329d5SDavid du Colombier if (pOptions->iPageWidth == INT_MAX) {
579*25b329d5SDavid du Colombier lPageWidth = LONG_MAX;
580*25b329d5SDavid du Colombier } else {
581*25b329d5SDavid du Colombier lPageWidth = lPoints2DrawUnits(pOptions->iPageWidth);
582*25b329d5SDavid du Colombier }
583*25b329d5SDavid du Colombier DBG_DEC(lPageWidth);
584*25b329d5SDavid du Colombier lFooterHeight = 0;
585*25b329d5SDavid du Colombier bInFtrSpace = FALSE;
586*25b329d5SDavid du Colombier
587*25b329d5SDavid du Colombier tFontRefCurr = (drawfile_fontref)-1;
588*25b329d5SDavid du Colombier usFontSizeCurr = 0;
589*25b329d5SDavid du Colombier iFontColorCurr = -1;
590*25b329d5SDavid du Colombier lYtopCurr = -1;
591*25b329d5SDavid du Colombier iPageCount = 0;
592*25b329d5SDavid du Colombier iImageCount = 0;
593*25b329d5SDavid du Colombier iSectionIndex = 0;
594*25b329d5SDavid du Colombier bFirstInSection = TRUE;
595*25b329d5SDavid du Colombier lFilePosition = 0;
596*25b329d5SDavid du Colombier iMaxLocationNumber = 0;
597*25b329d5SDavid du Colombier lStreamStart = -1;
598*25b329d5SDavid du Colombier iObjectNumberCurr = 17;
599*25b329d5SDavid du Colombier pDiag->lXleft = 0;
600*25b329d5SDavid du Colombier pDiag->lYtop = 0;
601*25b329d5SDavid du Colombier
602*25b329d5SDavid du Colombier szProducer = szTask;
603*25b329d5SDavid du Colombier
604*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%%PDF-1.3\n");
605*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%%%c%c%c%c\n", 0xe2, 0xe3, 0xcf, 0xd3);
606*25b329d5SDavid du Colombier
607*25b329d5SDavid du Colombier /* Root catalog */
608*25b329d5SDavid du Colombier vSetLocation(1);
609*25b329d5SDavid du Colombier vFPprintf(pOutFile, "1 0 obj\n");
610*25b329d5SDavid du Colombier vFPprintf(pOutFile, "<<\n");
611*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Type /Catalog\n");
612*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Pages 3 0 R\n");
613*25b329d5SDavid du Colombier vFPprintf(pOutFile, ">>\n");
614*25b329d5SDavid du Colombier vFPprintf(pOutFile, "endobj\n");
615*25b329d5SDavid du Colombier } /* end of vProloguePDF */
616*25b329d5SDavid du Colombier
617*25b329d5SDavid du Colombier /*
618*25b329d5SDavid du Colombier * vEpiloguePDF - clean up after everything is done
619*25b329d5SDavid du Colombier */
620*25b329d5SDavid du Colombier void
vEpiloguePDF(diagram_type * pDiag)621*25b329d5SDavid du Colombier vEpiloguePDF(diagram_type *pDiag)
622*25b329d5SDavid du Colombier {
623*25b329d5SDavid du Colombier FILE *pOutFile;
624*25b329d5SDavid du Colombier long lXref;
625*25b329d5SDavid du Colombier int iIndex;
626*25b329d5SDavid du Colombier
627*25b329d5SDavid du Colombier fail(pDiag == NULL);
628*25b329d5SDavid du Colombier fail(pDiag->pOutFile == NULL);
629*25b329d5SDavid du Colombier
630*25b329d5SDavid du Colombier pOutFile = pDiag->pOutFile;
631*25b329d5SDavid du Colombier
632*25b329d5SDavid du Colombier vAddFooter(pDiag);
633*25b329d5SDavid du Colombier /* End the old page object */
634*25b329d5SDavid du Colombier vEndPageObject(pOutFile);
635*25b329d5SDavid du Colombier
636*25b329d5SDavid du Colombier vSetLocation(3);
637*25b329d5SDavid du Colombier vFPprintf(pOutFile, "3 0 obj\n");
638*25b329d5SDavid du Colombier vFPprintf(pOutFile, "<<\n");
639*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Type /Pages\n");
640*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Count %d\n", iPageCount);
641*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/MediaBox [ 0 0 %.0f %.0f ]\n",
642*25b329d5SDavid du Colombier dDrawUnits2Points(lPageWidth),
643*25b329d5SDavid du Colombier dDrawUnits2Points(lPageHeight));
644*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Kids [ ");
645*25b329d5SDavid du Colombier for (iIndex = 1; iIndex <= iPageCount; iIndex++) {
646*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t%d 0 R\n", aiPageObject[iIndex]);
647*25b329d5SDavid du Colombier }
648*25b329d5SDavid du Colombier vFPprintf(pOutFile, "]\n");
649*25b329d5SDavid du Colombier vFPprintf(pOutFile, ">>\n");
650*25b329d5SDavid du Colombier vFPprintf(pOutFile, "endobj\n");
651*25b329d5SDavid du Colombier
652*25b329d5SDavid du Colombier lXref = lFilePosition;
653*25b329d5SDavid du Colombier
654*25b329d5SDavid du Colombier vFPprintf(pOutFile, "xref\n");
655*25b329d5SDavid du Colombier vFPprintf(pOutFile, "0 %d\n", iMaxLocationNumber + 1);
656*25b329d5SDavid du Colombier vFPprintf(pOutFile, "0000000000 65535 f \n");
657*25b329d5SDavid du Colombier for (iIndex = 1; iIndex <= iMaxLocationNumber; iIndex++) {
658*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%.10ld 00000 n \n", alLocation[iIndex]);
659*25b329d5SDavid du Colombier }
660*25b329d5SDavid du Colombier
661*25b329d5SDavid du Colombier vFPprintf(pOutFile, "trailer\n");
662*25b329d5SDavid du Colombier vFPprintf(pOutFile, "<<\n");
663*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Size %d\n", iMaxLocationNumber + 1);
664*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Root 1 0 R\n");
665*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Info 2 0 R\n");
666*25b329d5SDavid du Colombier vFPprintf(pOutFile, ">>\n");
667*25b329d5SDavid du Colombier
668*25b329d5SDavid du Colombier vFPprintf(pOutFile, "startxref\n");
669*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%ld\n", lXref);
670*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%%%%EOF\n");
671*25b329d5SDavid du Colombier
672*25b329d5SDavid du Colombier szProducer = NULL;
673*25b329d5SDavid du Colombier aiPageObject = xfree(aiPageObject);
674*25b329d5SDavid du Colombier alLocation = xfree(alLocation);
675*25b329d5SDavid du Colombier } /* end of vEpiloguePDF */
676*25b329d5SDavid du Colombier
677*25b329d5SDavid du Colombier /*
678*25b329d5SDavid du Colombier * vPrintPalette - print a pdf color space (palette)
679*25b329d5SDavid du Colombier */
680*25b329d5SDavid du Colombier static void
vPrintPalette(FILE * pOutFile,const imagedata_type * pImg)681*25b329d5SDavid du Colombier vPrintPalette(FILE *pOutFile, const imagedata_type *pImg)
682*25b329d5SDavid du Colombier {
683*25b329d5SDavid du Colombier int iIndex;
684*25b329d5SDavid du Colombier
685*25b329d5SDavid du Colombier fail(pOutFile == NULL);
686*25b329d5SDavid du Colombier fail(pImg == NULL);
687*25b329d5SDavid du Colombier fail(pImg->iColorsUsed < 2);
688*25b329d5SDavid du Colombier fail(pImg->iColorsUsed > 256);
689*25b329d5SDavid du Colombier
690*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/ColorSpace [ /Indexed\n");
691*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/Device%s %d\n",
692*25b329d5SDavid du Colombier pImg->bColorImage ? "RGB" : "Gray", pImg->iColorsUsed - 1);
693*25b329d5SDavid du Colombier vFPprintf(pOutFile, "<");
694*25b329d5SDavid du Colombier for (iIndex = 0; iIndex < pImg->iColorsUsed; iIndex++) {
695*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%02x",
696*25b329d5SDavid du Colombier (unsigned int)pImg->aucPalette[iIndex][0]);
697*25b329d5SDavid du Colombier if (pImg->bColorImage) {
698*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%02x%02x",
699*25b329d5SDavid du Colombier (unsigned int)pImg->aucPalette[iIndex][1],
700*25b329d5SDavid du Colombier (unsigned int)pImg->aucPalette[iIndex][2]);
701*25b329d5SDavid du Colombier }
702*25b329d5SDavid du Colombier if (iIndex % 8 == 7) {
703*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\n");
704*25b329d5SDavid du Colombier } else {
705*25b329d5SDavid du Colombier vFPprintf(pOutFile, " ");
706*25b329d5SDavid du Colombier }
707*25b329d5SDavid du Colombier }
708*25b329d5SDavid du Colombier vFPprintf(pOutFile, "> ]\n");
709*25b329d5SDavid du Colombier } /* end of vPrintPalette */
710*25b329d5SDavid du Colombier
711*25b329d5SDavid du Colombier /*
712*25b329d5SDavid du Colombier * vImageProloguePDF - perform the image initialization
713*25b329d5SDavid du Colombier */
714*25b329d5SDavid du Colombier void
vImageProloguePDF(diagram_type * pDiag,const imagedata_type * pImg)715*25b329d5SDavid du Colombier vImageProloguePDF(diagram_type *pDiag, const imagedata_type *pImg)
716*25b329d5SDavid du Colombier {
717*25b329d5SDavid du Colombier FILE *pOutFile;
718*25b329d5SDavid du Colombier
719*25b329d5SDavid du Colombier fail(pDiag == NULL);
720*25b329d5SDavid du Colombier fail(pDiag->pOutFile == NULL);
721*25b329d5SDavid du Colombier fail(pImg == NULL);
722*25b329d5SDavid du Colombier
723*25b329d5SDavid du Colombier if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
724*25b329d5SDavid du Colombier return;
725*25b329d5SDavid du Colombier }
726*25b329d5SDavid du Colombier
727*25b329d5SDavid du Colombier iImageCount++;
728*25b329d5SDavid du Colombier
729*25b329d5SDavid du Colombier DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
730*25b329d5SDavid du Colombier
731*25b329d5SDavid du Colombier pDiag->lYtop -= lPoints2DrawUnits(pImg->iVerSizeScaled);
732*25b329d5SDavid du Colombier vMoveTo(pDiag, lPoints2DrawUnits(pImg->iVerSizeScaled));
733*25b329d5SDavid du Colombier
734*25b329d5SDavid du Colombier pOutFile = pDiag->pOutFile;
735*25b329d5SDavid du Colombier
736*25b329d5SDavid du Colombier vFPprintf(pOutFile, "ET\n");
737*25b329d5SDavid du Colombier vFPprintf(pOutFile, "q %% Image %03d\n", iImageCount);
738*25b329d5SDavid du Colombier if (pImg->eImageType == imagetype_is_dib) {
739*25b329d5SDavid du Colombier /* Scanning from left to right and bottom to top */
740*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%d 0 0 %d %.2f %.2f cm\n",
741*25b329d5SDavid du Colombier pImg->iHorSizeScaled, -pImg->iVerSizeScaled,
742*25b329d5SDavid du Colombier dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
743*25b329d5SDavid du Colombier dDrawUnits2Points(pDiag->lYtop) + pImg->iVerSizeScaled);
744*25b329d5SDavid du Colombier } else {
745*25b329d5SDavid du Colombier /* Scanning from left to right and top to bottom */
746*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%d 0 0 %d %.2f %.2f cm\n",
747*25b329d5SDavid du Colombier pImg->iHorSizeScaled, pImg->iVerSizeScaled,
748*25b329d5SDavid du Colombier dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
749*25b329d5SDavid du Colombier dDrawUnits2Points(pDiag->lYtop));
750*25b329d5SDavid du Colombier }
751*25b329d5SDavid du Colombier vFPprintf(pOutFile, "BI\n");
752*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/Width %d\n", pImg->iWidth);
753*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/Height %d\n", pImg->iHeight);
754*25b329d5SDavid du Colombier switch (pImg->eImageType) {
755*25b329d5SDavid du Colombier case imagetype_is_jpeg:
756*25b329d5SDavid du Colombier switch (pImg->iComponents) {
757*25b329d5SDavid du Colombier case 1:
758*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/ColorSpace /DeviceGray\n");
759*25b329d5SDavid du Colombier break;
760*25b329d5SDavid du Colombier case 3:
761*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/ColorSpace /DeviceRGB\n");
762*25b329d5SDavid du Colombier break;
763*25b329d5SDavid du Colombier case 4:
764*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/ColorSpace /DeviceCMYK\n");
765*25b329d5SDavid du Colombier if (pImg->bAdobe) {
766*25b329d5SDavid du Colombier /*
767*25b329d5SDavid du Colombier * Adobe-conforming CMYK file
768*25b329d5SDavid du Colombier * applying workaround for color inversion
769*25b329d5SDavid du Colombier */
770*25b329d5SDavid du Colombier vFPprintf(pOutFile,
771*25b329d5SDavid du Colombier "\t/Decode [1 0 1 0 1 0 1 0]\n");
772*25b329d5SDavid du Colombier }
773*25b329d5SDavid du Colombier break;
774*25b329d5SDavid du Colombier default:
775*25b329d5SDavid du Colombier DBG_DEC(pImg->iComponents);
776*25b329d5SDavid du Colombier break;
777*25b329d5SDavid du Colombier }
778*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
779*25b329d5SDavid du Colombier vFPprintf(pOutFile,
780*25b329d5SDavid du Colombier "\t/Filter [ /ASCII85Decode /DCTDecode ]\n");
781*25b329d5SDavid du Colombier break;
782*25b329d5SDavid du Colombier case imagetype_is_png:
783*25b329d5SDavid du Colombier if (pImg->iComponents == 3 || pImg->iComponents == 4) {
784*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/ColorSpace /DeviceRGB\n");
785*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
786*25b329d5SDavid du Colombier } else if (pImg->iColorsUsed > 0) {
787*25b329d5SDavid du Colombier vPrintPalette(pOutFile, pImg);
788*25b329d5SDavid du Colombier fail(pImg->uiBitsPerComponent > 8);
789*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/BitsPerComponent %u\n",
790*25b329d5SDavid du Colombier pImg->uiBitsPerComponent);
791*25b329d5SDavid du Colombier } else {
792*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/ColorSpace /DeviceGray\n");
793*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
794*25b329d5SDavid du Colombier }
795*25b329d5SDavid du Colombier vFPprintf(pOutFile,
796*25b329d5SDavid du Colombier "\t/Filter [ /ASCII85Decode /FlateDecode ]\n");
797*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/DecodeParms [ null <<\n");
798*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t\t/Predictor 10\n");
799*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t\t/Colors %d\n", pImg->iComponents);
800*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t\t/BitsPerComponent %u\n",
801*25b329d5SDavid du Colombier pImg->uiBitsPerComponent);
802*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t\t/Columns %d\n", pImg->iWidth);
803*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t\t>> ]\n");
804*25b329d5SDavid du Colombier break;
805*25b329d5SDavid du Colombier case imagetype_is_dib:
806*25b329d5SDavid du Colombier if (pImg->uiBitsPerComponent <= 8) {
807*25b329d5SDavid du Colombier vPrintPalette(pOutFile, pImg);
808*25b329d5SDavid du Colombier } else {
809*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/ColorSpace /DeviceRGB\n");
810*25b329d5SDavid du Colombier }
811*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
812*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/Filter /ASCII85Decode\n");
813*25b329d5SDavid du Colombier break;
814*25b329d5SDavid du Colombier default:
815*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/ColorSpace /Device%s\n",
816*25b329d5SDavid du Colombier pImg->bColorImage ? "RGB" : "Gray");
817*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
818*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/Filter /ASCIIHexDecode\n");
819*25b329d5SDavid du Colombier break;
820*25b329d5SDavid du Colombier }
821*25b329d5SDavid du Colombier vFPprintf(pOutFile, "ID\n");
822*25b329d5SDavid du Colombier } /* end of vImageProloguePDF */
823*25b329d5SDavid du Colombier
824*25b329d5SDavid du Colombier /*
825*25b329d5SDavid du Colombier * vImageEpiloguePDF - clean up after the image
826*25b329d5SDavid du Colombier */
827*25b329d5SDavid du Colombier void
vImageEpiloguePDF(diagram_type * pDiag)828*25b329d5SDavid du Colombier vImageEpiloguePDF(diagram_type *pDiag)
829*25b329d5SDavid du Colombier {
830*25b329d5SDavid du Colombier FILE *pOutFile;
831*25b329d5SDavid du Colombier
832*25b329d5SDavid du Colombier fail(pDiag == NULL);
833*25b329d5SDavid du Colombier fail(pDiag->pOutFile == NULL);
834*25b329d5SDavid du Colombier
835*25b329d5SDavid du Colombier pOutFile = pDiag->pOutFile;
836*25b329d5SDavid du Colombier
837*25b329d5SDavid du Colombier /* Correction for the image bytes */
838*25b329d5SDavid du Colombier lFilePosition = ftell(pOutFile);
839*25b329d5SDavid du Colombier
840*25b329d5SDavid du Colombier vFPprintf(pOutFile, "EI\n");
841*25b329d5SDavid du Colombier vFPprintf(pOutFile, "Q\n");
842*25b329d5SDavid du Colombier vFPprintf(pOutFile, "BT\n");
843*25b329d5SDavid du Colombier
844*25b329d5SDavid du Colombier pDiag->lXleft = 0;
845*25b329d5SDavid du Colombier } /* end of vImageEpiloguePDF */
846*25b329d5SDavid du Colombier
847*25b329d5SDavid du Colombier /*
848*25b329d5SDavid du Colombier * bAddDummyImagePDF - add a dummy image
849*25b329d5SDavid du Colombier *
850*25b329d5SDavid du Colombier * return TRUE when successful, otherwise FALSE
851*25b329d5SDavid du Colombier */
852*25b329d5SDavid du Colombier BOOL
bAddDummyImagePDF(diagram_type * pDiag,const imagedata_type * pImg)853*25b329d5SDavid du Colombier bAddDummyImagePDF(diagram_type *pDiag, const imagedata_type *pImg)
854*25b329d5SDavid du Colombier {
855*25b329d5SDavid du Colombier FILE *pOutFile;
856*25b329d5SDavid du Colombier
857*25b329d5SDavid du Colombier fail(pDiag == NULL);
858*25b329d5SDavid du Colombier fail(pDiag->pOutFile == NULL);
859*25b329d5SDavid du Colombier fail(pImg == NULL);
860*25b329d5SDavid du Colombier
861*25b329d5SDavid du Colombier if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
862*25b329d5SDavid du Colombier return FALSE;
863*25b329d5SDavid du Colombier }
864*25b329d5SDavid du Colombier
865*25b329d5SDavid du Colombier iImageCount++;
866*25b329d5SDavid du Colombier
867*25b329d5SDavid du Colombier DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
868*25b329d5SDavid du Colombier
869*25b329d5SDavid du Colombier pDiag->lYtop -= lPoints2DrawUnits(pImg->iVerSizeScaled);
870*25b329d5SDavid du Colombier vMoveTo(pDiag, lPoints2DrawUnits(pImg->iVerSizeScaled));
871*25b329d5SDavid du Colombier
872*25b329d5SDavid du Colombier pOutFile = pDiag->pOutFile;
873*25b329d5SDavid du Colombier
874*25b329d5SDavid du Colombier vFPprintf(pOutFile, "ET\n");
875*25b329d5SDavid du Colombier vFPprintf(pOutFile, "q %% Image %03d\n", iImageCount);
876*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t1.0 w\n");
877*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t0.3 G\n");
878*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t%.2f %.2f %d %d re\n",
879*25b329d5SDavid du Colombier dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
880*25b329d5SDavid du Colombier dDrawUnits2Points(pDiag->lYtop),
881*25b329d5SDavid du Colombier pImg->iHorSizeScaled,
882*25b329d5SDavid du Colombier pImg->iVerSizeScaled);
883*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\tS\n");
884*25b329d5SDavid du Colombier vFPprintf(pOutFile, "Q\n");
885*25b329d5SDavid du Colombier vFPprintf(pOutFile, "BT\n");
886*25b329d5SDavid du Colombier
887*25b329d5SDavid du Colombier pDiag->lXleft = 0;
888*25b329d5SDavid du Colombier
889*25b329d5SDavid du Colombier return TRUE;
890*25b329d5SDavid du Colombier } /* end of bAddDummyImagePDF */
891*25b329d5SDavid du Colombier
892*25b329d5SDavid du Colombier /*
893*25b329d5SDavid du Colombier * vAddFontsPDF - add the font information
894*25b329d5SDavid du Colombier */
895*25b329d5SDavid du Colombier void
vAddFontsPDF(diagram_type * pDiag)896*25b329d5SDavid du Colombier vAddFontsPDF(diagram_type *pDiag)
897*25b329d5SDavid du Colombier {
898*25b329d5SDavid du Colombier FILE *pOutFile;
899*25b329d5SDavid du Colombier size_t tIndex;
900*25b329d5SDavid du Colombier
901*25b329d5SDavid du Colombier fail(pDiag == NULL);
902*25b329d5SDavid du Colombier fail(pDiag->pOutFile == NULL);
903*25b329d5SDavid du Colombier
904*25b329d5SDavid du Colombier pOutFile = pDiag->pOutFile;
905*25b329d5SDavid du Colombier
906*25b329d5SDavid du Colombier /* The font encoding */
907*25b329d5SDavid du Colombier vSetLocation(4);
908*25b329d5SDavid du Colombier vFPprintf(pOutFile, "4 0 obj\n");
909*25b329d5SDavid du Colombier vFPprintf(pOutFile, "<<\n");
910*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Type /Encoding\n");
911*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/BaseEncoding /StandardEncoding\n");
912*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Differences [\n");
913*25b329d5SDavid du Colombier switch (eEncoding) {
914*25b329d5SDavid du Colombier case encoding_latin_1:
915*25b329d5SDavid du Colombier for (tIndex = 0;
916*25b329d5SDavid du Colombier tIndex < elementsof(iso_8859_1);
917*25b329d5SDavid du Colombier tIndex++) {
918*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%s\n", iso_8859_1[tIndex]);
919*25b329d5SDavid du Colombier }
920*25b329d5SDavid du Colombier break;
921*25b329d5SDavid du Colombier case encoding_latin_2:
922*25b329d5SDavid du Colombier for (tIndex = 0;
923*25b329d5SDavid du Colombier tIndex < elementsof(iso_8859_2);
924*25b329d5SDavid du Colombier tIndex++) {
925*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%s\n", iso_8859_2[tIndex]);
926*25b329d5SDavid du Colombier }
927*25b329d5SDavid du Colombier break;
928*25b329d5SDavid du Colombier case encoding_cyrillic:
929*25b329d5SDavid du Colombier werr(1,
930*25b329d5SDavid du Colombier "The combination PDF and Cyrillic is not supported");
931*25b329d5SDavid du Colombier break;
932*25b329d5SDavid du Colombier case encoding_utf_8:
933*25b329d5SDavid du Colombier werr(1,
934*25b329d5SDavid du Colombier "The combination PDF and UTF-8 is not supported");
935*25b329d5SDavid du Colombier break;
936*25b329d5SDavid du Colombier default:
937*25b329d5SDavid du Colombier DBG_DEC(eEncoding);
938*25b329d5SDavid du Colombier break;
939*25b329d5SDavid du Colombier }
940*25b329d5SDavid du Colombier vFPprintf(pOutFile, "]\n");
941*25b329d5SDavid du Colombier vFPprintf(pOutFile, ">>\n");
942*25b329d5SDavid du Colombier vFPprintf(pOutFile, "endobj\n");
943*25b329d5SDavid du Colombier
944*25b329d5SDavid du Colombier /* Twelve of the standard type 1 fonts */
945*25b329d5SDavid du Colombier for (tIndex = 0; tIndex < 12; tIndex++) {
946*25b329d5SDavid du Colombier vSetLocation(5 + tIndex);
947*25b329d5SDavid du Colombier vFPprintf(pOutFile, "%u 0 obj\n", 5 + tIndex);
948*25b329d5SDavid du Colombier vFPprintf(pOutFile, "<<\n");
949*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Type /Font\n");
950*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Subtype /Type1\n");
951*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Name /F%u\n", 1 + tIndex);
952*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/BaseFont /%s\n",
953*25b329d5SDavid du Colombier atFontname[tIndex].szPDFname);
954*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Encoding 4 0 R\n");
955*25b329d5SDavid du Colombier vFPprintf(pOutFile, ">>\n");
956*25b329d5SDavid du Colombier vFPprintf(pOutFile, "endobj\n");
957*25b329d5SDavid du Colombier }
958*25b329d5SDavid du Colombier
959*25b329d5SDavid du Colombier /* The Resources */
960*25b329d5SDavid du Colombier vSetLocation(17);
961*25b329d5SDavid du Colombier vFPprintf(pOutFile, "17 0 obj\n");
962*25b329d5SDavid du Colombier vFPprintf(pOutFile, "<<\n");
963*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/ProcSet [ /PDF /Text ]\n");
964*25b329d5SDavid du Colombier vFPprintf(pOutFile, "/Font <<\n");
965*25b329d5SDavid du Colombier for (tIndex = 0; tIndex < 12; tIndex++) {
966*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t/F%u %u 0 R\n", 1 + tIndex, 5 + tIndex);
967*25b329d5SDavid du Colombier }
968*25b329d5SDavid du Colombier vFPprintf(pOutFile, "\t>>\n");
969*25b329d5SDavid du Colombier vFPprintf(pOutFile, ">>\n");
970*25b329d5SDavid du Colombier vFPprintf(pOutFile, "endobj\n");
971*25b329d5SDavid du Colombier vAddHeader(pDiag);
972*25b329d5SDavid du Colombier } /* end of vAddFontsPDF */
973*25b329d5SDavid du Colombier
974*25b329d5SDavid du Colombier /*
975*25b329d5SDavid du Colombier * vPrintPDF - print a PDF string
976*25b329d5SDavid du Colombier */
977*25b329d5SDavid du Colombier static void
vPrintPDF(FILE * pFile,const char * szString,size_t tStringLength,USHORT usFontstyle)978*25b329d5SDavid du Colombier vPrintPDF(FILE *pFile, const char *szString, size_t tStringLength,
979*25b329d5SDavid du Colombier USHORT usFontstyle)
980*25b329d5SDavid du Colombier {
981*25b329d5SDavid du Colombier const UCHAR *aucBytes;
982*25b329d5SDavid du Colombier double dMove;
983*25b329d5SDavid du Colombier size_t tCount;
984*25b329d5SDavid du Colombier
985*25b329d5SDavid du Colombier fail(szString == NULL);
986*25b329d5SDavid du Colombier
987*25b329d5SDavid du Colombier if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
988*25b329d5SDavid du Colombier return;
989*25b329d5SDavid du Colombier }
990*25b329d5SDavid du Colombier DBG_DEC_C(usFontSizeCurr < MIN_FONT_SIZE, usFontSizeCurr);
991*25b329d5SDavid du Colombier
992*25b329d5SDavid du Colombier dMove = 0.0;
993*25b329d5SDavid du Colombier
994*25b329d5SDavid du Colombier /* Up for superscript */
995*25b329d5SDavid du Colombier if (bIsSuperscript(usFontstyle) && usFontSizeCurr != 0) {
996*25b329d5SDavid du Colombier dMove = (double)((usFontSizeCurr + 1) / 2) * 0.375;
997*25b329d5SDavid du Colombier vFPprintf(pFile, "%.2f Ts\n", dMove);
998*25b329d5SDavid du Colombier }
999*25b329d5SDavid du Colombier
1000*25b329d5SDavid du Colombier /* Down for subscript */
1001*25b329d5SDavid du Colombier if (bIsSubscript(usFontstyle) && usFontSizeCurr != 0) {
1002*25b329d5SDavid du Colombier dMove = (double)usFontSizeCurr * 0.125;
1003*25b329d5SDavid du Colombier vFPprintf(pFile, "%.2f Ts\n", -dMove);
1004*25b329d5SDavid du Colombier }
1005*25b329d5SDavid du Colombier
1006*25b329d5SDavid du Colombier /* Generate and print the PDF output */
1007*25b329d5SDavid du Colombier aucBytes = (UCHAR *)szString;
1008*25b329d5SDavid du Colombier vFPprintf(pFile, "(");
1009*25b329d5SDavid du Colombier for (tCount = 0; tCount < tStringLength ; tCount++) {
1010*25b329d5SDavid du Colombier switch (aucBytes[tCount]) {
1011*25b329d5SDavid du Colombier case '(':
1012*25b329d5SDavid du Colombier case ')':
1013*25b329d5SDavid du Colombier case '\\':
1014*25b329d5SDavid du Colombier vFPprintf(pFile, "\\%c", szString[tCount]);
1015*25b329d5SDavid du Colombier break;
1016*25b329d5SDavid du Colombier default:
1017*25b329d5SDavid du Colombier if (aucBytes[tCount] < 0x20 ||
1018*25b329d5SDavid du Colombier aucBytes[tCount] == 0x7f ||
1019*25b329d5SDavid du Colombier (aucBytes[tCount] >= 0x81 &&
1020*25b329d5SDavid du Colombier aucBytes[tCount] < 0x8c)) {
1021*25b329d5SDavid du Colombier DBG_HEX(aucBytes[tCount]);
1022*25b329d5SDavid du Colombier vFPprintf(pFile, " ");
1023*25b329d5SDavid du Colombier } else if (aucBytes[tCount] >= 0x80) {
1024*25b329d5SDavid du Colombier vFPprintf(pFile, "\\%03o",
1025*25b329d5SDavid du Colombier (UINT)aucBytes[tCount]);
1026*25b329d5SDavid du Colombier } else {
1027*25b329d5SDavid du Colombier vFPprintf(pFile, "%c", szString[tCount]);
1028*25b329d5SDavid du Colombier }
1029*25b329d5SDavid du Colombier break;
1030*25b329d5SDavid du Colombier }
1031*25b329d5SDavid du Colombier }
1032*25b329d5SDavid du Colombier vFPprintf(pFile, ") Tj\n");
1033*25b329d5SDavid du Colombier
1034*25b329d5SDavid du Colombier /* Undo the superscript/subscript move */
1035*25b329d5SDavid du Colombier if (dMove != 0.0) {
1036*25b329d5SDavid du Colombier vFPprintf(pFile, "0 Ts\n");
1037*25b329d5SDavid du Colombier }
1038*25b329d5SDavid du Colombier } /* end of vPrintPDF */
1039*25b329d5SDavid du Colombier
1040*25b329d5SDavid du Colombier /*
1041*25b329d5SDavid du Colombier * vSetColor - move to the specified color
1042*25b329d5SDavid du Colombier */
1043*25b329d5SDavid du Colombier static void
vSetColor(FILE * pFile,UCHAR ucFontColor)1044*25b329d5SDavid du Colombier vSetColor(FILE *pFile, UCHAR ucFontColor)
1045*25b329d5SDavid du Colombier {
1046*25b329d5SDavid du Colombier ULONG ulTmp, ulRed, ulGreen, ulBlue;
1047*25b329d5SDavid du Colombier
1048*25b329d5SDavid du Colombier ulTmp = ulColor2Color(ucFontColor);
1049*25b329d5SDavid du Colombier ulRed = (ulTmp & 0x0000ff00) >> 8;
1050*25b329d5SDavid du Colombier ulGreen = (ulTmp & 0x00ff0000) >> 16;
1051*25b329d5SDavid du Colombier ulBlue = (ulTmp & 0xff000000) >> 24;
1052*25b329d5SDavid du Colombier vFPprintf(pFile, "%.3f %.3f %.3f rg\n",
1053*25b329d5SDavid du Colombier ulRed / 255.0, ulGreen / 255.0, ulBlue / 255.0);
1054*25b329d5SDavid du Colombier } /* end of vSetColor */
1055*25b329d5SDavid du Colombier
1056*25b329d5SDavid du Colombier /*
1057*25b329d5SDavid du Colombier * vMove2NextLinePDF - move to the next line
1058*25b329d5SDavid du Colombier */
1059*25b329d5SDavid du Colombier void
vMove2NextLinePDF(diagram_type * pDiag,USHORT usFontSize)1060*25b329d5SDavid du Colombier vMove2NextLinePDF(diagram_type *pDiag, USHORT usFontSize)
1061*25b329d5SDavid du Colombier {
1062*25b329d5SDavid du Colombier fail(pDiag == NULL);
1063*25b329d5SDavid du Colombier fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
1064*25b329d5SDavid du Colombier
1065*25b329d5SDavid du Colombier pDiag->lYtop -= lComputeLeading(usFontSize);
1066*25b329d5SDavid du Colombier } /* end of vMove2NextLinePDF */
1067*25b329d5SDavid du Colombier
1068*25b329d5SDavid du Colombier /*
1069*25b329d5SDavid du Colombier * vSubstringPDF - print a sub string
1070*25b329d5SDavid du Colombier */
1071*25b329d5SDavid du Colombier void
vSubstringPDF(diagram_type * pDiag,char * szString,size_t tStringLength,long lStringWidth,UCHAR ucFontColor,USHORT usFontstyle,drawfile_fontref tFontRef,USHORT usFontSize,USHORT usMaxFontSize)1072*25b329d5SDavid du Colombier vSubstringPDF(diagram_type *pDiag,
1073*25b329d5SDavid du Colombier char *szString, size_t tStringLength, long lStringWidth,
1074*25b329d5SDavid du Colombier UCHAR ucFontColor, USHORT usFontstyle, drawfile_fontref tFontRef,
1075*25b329d5SDavid du Colombier USHORT usFontSize, USHORT usMaxFontSize)
1076*25b329d5SDavid du Colombier {
1077*25b329d5SDavid du Colombier size_t tFontIndex;
1078*25b329d5SDavid du Colombier
1079*25b329d5SDavid du Colombier fail(pDiag == NULL || szString == NULL);
1080*25b329d5SDavid du Colombier fail(pDiag->pOutFile == NULL);
1081*25b329d5SDavid du Colombier fail(pDiag->lXleft < 0);
1082*25b329d5SDavid du Colombier fail(tStringLength != strlen(szString));
1083*25b329d5SDavid du Colombier fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
1084*25b329d5SDavid du Colombier fail(usMaxFontSize < MIN_FONT_SIZE || usMaxFontSize > MAX_FONT_SIZE);
1085*25b329d5SDavid du Colombier fail(usFontSize > usMaxFontSize);
1086*25b329d5SDavid du Colombier
1087*25b329d5SDavid du Colombier if (szString[0] == '\0' || tStringLength == 0) {
1088*25b329d5SDavid du Colombier return;
1089*25b329d5SDavid du Colombier }
1090*25b329d5SDavid du Colombier
1091*25b329d5SDavid du Colombier vMoveTo(pDiag, lComputeLeading(usMaxFontSize));
1092*25b329d5SDavid du Colombier if (tFontRef != tFontRefCurr || usFontSize != usFontSizeCurr) {
1093*25b329d5SDavid du Colombier tFontIndex = tGetFontIndex(tFontRef);
1094*25b329d5SDavid du Colombier vFPprintf(pDiag->pOutFile, "/F%u %.1f Tf\n",
1095*25b329d5SDavid du Colombier 1 + tFontIndex, (double)usFontSize / 2.0);
1096*25b329d5SDavid du Colombier tFontRefCurr = tFontRef;
1097*25b329d5SDavid du Colombier usFontSizeCurr = usFontSize;
1098*25b329d5SDavid du Colombier }
1099*25b329d5SDavid du Colombier if ((int)ucFontColor != iFontColorCurr) {
1100*25b329d5SDavid du Colombier vSetColor(pDiag->pOutFile, ucFontColor);
1101*25b329d5SDavid du Colombier iFontColorCurr = (int)ucFontColor;
1102*25b329d5SDavid du Colombier }
1103*25b329d5SDavid du Colombier vPrintPDF(pDiag->pOutFile, szString, tStringLength, usFontstyle);
1104*25b329d5SDavid du Colombier pDiag->lXleft += lStringWidth;
1105*25b329d5SDavid du Colombier } /* end of vSubstringPDF */
1106*25b329d5SDavid du Colombier
1107*25b329d5SDavid du Colombier /*
1108*25b329d5SDavid du Colombier * Create an start of paragraph by moving the y-top mark
1109*25b329d5SDavid du Colombier */
1110*25b329d5SDavid du Colombier void
vStartOfParagraphPDF(diagram_type * pDiag,long lBeforeIndentation)1111*25b329d5SDavid du Colombier vStartOfParagraphPDF(diagram_type *pDiag, long lBeforeIndentation)
1112*25b329d5SDavid du Colombier {
1113*25b329d5SDavid du Colombier fail(pDiag == NULL);
1114*25b329d5SDavid du Colombier fail(lBeforeIndentation < 0);
1115*25b329d5SDavid du Colombier
1116*25b329d5SDavid du Colombier pDiag->lXleft = 0;
1117*25b329d5SDavid du Colombier pDiag->lYtop -= lMilliPoints2DrawUnits(lBeforeIndentation);
1118*25b329d5SDavid du Colombier } /* end of vStartOfParagraphPDF */
1119*25b329d5SDavid du Colombier
1120*25b329d5SDavid du Colombier /*
1121*25b329d5SDavid du Colombier * Create an end of paragraph by moving the y-top mark
1122*25b329d5SDavid du Colombier */
1123*25b329d5SDavid du Colombier void
vEndOfParagraphPDF(diagram_type * pDiag,USHORT usFontSize,long lAfterIndentation)1124*25b329d5SDavid du Colombier vEndOfParagraphPDF(diagram_type *pDiag,
1125*25b329d5SDavid du Colombier USHORT usFontSize, long lAfterIndentation)
1126*25b329d5SDavid du Colombier {
1127*25b329d5SDavid du Colombier fail(pDiag == NULL);
1128*25b329d5SDavid du Colombier fail(pDiag->pOutFile == NULL);
1129*25b329d5SDavid du Colombier fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
1130*25b329d5SDavid du Colombier fail(lAfterIndentation < 0);
1131*25b329d5SDavid du Colombier
1132*25b329d5SDavid du Colombier if (pDiag->lXleft > 0) {
1133*25b329d5SDavid du Colombier /* To the start of the line */
1134*25b329d5SDavid du Colombier vMove2NextLinePDF(pDiag, usFontSize);
1135*25b329d5SDavid du Colombier }
1136*25b329d5SDavid du Colombier
1137*25b329d5SDavid du Colombier pDiag->lXleft = 0;
1138*25b329d5SDavid du Colombier pDiag->lYtop -= lMilliPoints2DrawUnits(lAfterIndentation);
1139*25b329d5SDavid du Colombier } /* end of vEndOfParagraphPDF */
1140*25b329d5SDavid du Colombier
1141*25b329d5SDavid du Colombier /*
1142*25b329d5SDavid du Colombier * Create an end of page
1143*25b329d5SDavid du Colombier */
1144*25b329d5SDavid du Colombier void
vEndOfPagePDF(diagram_type * pDiag,BOOL bNewSection)1145*25b329d5SDavid du Colombier vEndOfPagePDF(diagram_type *pDiag, BOOL bNewSection)
1146*25b329d5SDavid du Colombier {
1147*25b329d5SDavid du Colombier vMove2NextPage(pDiag, bNewSection);
1148*25b329d5SDavid du Colombier } /* end of vEndOfPagePDF */
1149