00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <stdarg.h>
00011 #include <string.h>
00012 #include "version.h"
00013 #include "antiword.h"
00014
00015
00016
00017 #define INITIAL_LOCATION_SIZE 20
00018 #define INITIAL_PAGEOBJECT_SIZE 5
00019 #if defined(DEBUG)
00020 #define EXTENSION_ARRAY_SIZE 10
00021 #else
00022 #define EXTENSION_ARRAY_SIZE 30
00023 #endif
00024
00025
00026 static encoding_type eEncoding = encoding_neutral;
00027
00028 static const char *szProducer = NULL;
00029
00030 static long lPageHeight = LONG_MAX;
00031 static long lPageWidth = LONG_MAX;
00032
00033 static long lFooterHeight = 0;
00034
00035 static BOOL bInFtrSpace = FALSE;
00036
00037 static drawfile_fontref tFontRefCurr = (drawfile_fontref)-1;
00038 static USHORT usFontSizeCurr = 0;
00039 static int iFontColorCurr = -1;
00040
00041 static long lYtopCurr = -1;
00042
00043 static int iImageCount = 0;
00044
00045 static int iSectionIndex = 0;
00046
00047 static BOOL bFirstInSection = TRUE;
00048
00049 static long lFilePosition = 0;
00050 static long *alLocation = NULL;
00051 static size_t tLocations = 0;
00052 static int iMaxLocationNumber = 0;
00053
00054 static long lStreamStart = -1;
00055
00056 static int *aiPageObject = NULL;
00057 static int iPageCount = 0;
00058 static size_t tMaxPageObjects = 0;
00059
00060
00061 static int iObjectNumberCurr = 17;
00062
00063 static void vMoveTo(diagram_type *, long);
00064
00065 static const struct {
00066 const char *szPDFname;
00067 const char *szPSname;
00068 } atFontname[] = {
00069 { "Courier", FONT_MONOSPACED_PLAIN },
00070 { "Courier-Bold", FONT_MONOSPACED_BOLD },
00071 { "Courier-Oblique", FONT_MONOSPACED_ITALIC },
00072 { "Courier-BoldOblique", FONT_MONOSPACED_BOLDITALIC },
00073 { "Helvetica", FONT_SANS_SERIF_PLAIN },
00074 { "Helvetica-Bold", FONT_SANS_SERIF_BOLD },
00075 { "Helvetica-Oblique", FONT_SANS_SERIF_ITALIC },
00076 { "Helvetica-BoldOblique", FONT_SANS_SERIF_BOLDITALIC },
00077 { "Times-Roman", FONT_SERIF_PLAIN },
00078 { "Times-Bold", FONT_SERIF_BOLD },
00079 { "Times-Italic", FONT_SERIF_ITALIC },
00080 { "Times-BoldItalic", FONT_SERIF_BOLDITALIC },
00081 };
00082
00083 static const char *iso_8859_1[] = {
00084 "128 /Euro",
00085 "140 /ellipsis /trademark /perthousand /bullet",
00086 " /quoteleft /quoteright /guilsinglleft /guilsinglright",
00087 " /quotedblleft /quotedblright /quotedblbase /endash /emdash",
00088 " /minus /OE /oe /dagger /daggerdbl /fi /fl",
00089 "160 /space /exclamdown /cent /sterling /currency",
00090 " /yen /brokenbar /section /dieresis /copyright",
00091 " /ordfeminine /guillemotleft /logicalnot /hyphen /registered",
00092 " /macron /degree /plusminus /twosuperior /threesuperior",
00093 " /acute /mu /paragraph /periodcentered /cedilla",
00094 " /onesuperior /ordmasculine /guillemotright /onequarter",
00095 " /onehalf /threequarters /questiondown /Agrave /Aacute",
00096 " /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla",
00097 " /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute",
00098 " /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute",
00099 " /Ocircumflex /Otilde /Odieresis /multiply /Oslash",
00100 " /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn",
00101 " /germandbls /agrave /aacute /acircumflex /atilde",
00102 " /adieresis /aring /ae /ccedilla /egrave /eacute",
00103 " /ecircumflex /edieresis /igrave /iacute /icircumflex",
00104 " /idieresis /eth /ntilde /ograve /oacute /ocircumflex",
00105 " /otilde /odieresis /divide /oslash /ugrave /uacute",
00106 " /ucircumflex /udieresis /yacute /thorn /ydieresis",
00107 };
00108
00109 static const char *iso_8859_2[] = {
00110 "160 /space /Aogonek /breve /Lslash /currency /Lcaron",
00111 " /Sacute /section /dieresis /Scaron /Scommaaccent",
00112 " /Tcaron /Zacute /hyphen /Zcaron /Zdotaccent /degree",
00113 " /aogonek /ogonek /lslash /acute /lcaron /sacute",
00114 " /caron /cedilla /scaron /scommaaccent /tcaron",
00115 " /zacute /hungarumlaut /zcaron /zdotaccent /Racute",
00116 " /Aacute /Acircumflex /Abreve /Adieresis /Lacute",
00117 " /Cacute /Ccedilla /Ccaron /Eacute /Eogonek",
00118 " /Edieresis /Ecaron /Iacute /Icircumflex /Dcaron",
00119 " /.notdef /Nacute /Ncaron /Oacute /Ocircumflex",
00120 " /Ohungarumlaut /Odieresis /multiply /Rcaron /Uring",
00121 " /Uacute /Uhungarumlaut /Udieresis /Yacute /Tcommaaccent",
00122 " /germandbls /racute /aacute /acircumflex /abreve",
00123 " /adieresis /lacute /cacute /ccedilla /ccaron /eacute",
00124 " /eogonek /edieresis /ecaron /iacute /icircumflex",
00125 " /dcaron /.notdef /nacute /ncaron /oacute /ocircumflex",
00126 " /ohungarumlaut /odieresis /divide /rcaron /uring",
00127 " /uacute /uhungarumlaut /udieresis /yacute /tcommaaccent",
00128 " /dotaccent",
00129 };
00130
00131
00132
00133
00134
00135 static size_t
00136 tGetFontIndex(drawfile_fontref tFontRef)
00137 {
00138 const char *szFontname;
00139 size_t tIndex;
00140
00141
00142 szFontname = szGetFontname(tFontRef);
00143 fail(szFontname == NULL);
00144 if (szFontname == NULL) {
00145 return 0;
00146 }
00147
00148
00149 for (tIndex = 0; tIndex < elementsof(atFontname); tIndex++) {
00150 if (STRCEQ(atFontname[tIndex].szPSname, szFontname)) {
00151 return tIndex;
00152 }
00153 }
00154
00155 DBG_DEC(tFontRef);
00156 DBG_MSG(szFontname);
00157 return 0;
00158 }
00159
00160
00161
00162
00163 static void
00164 vSetLocation(int iLocationNumber)
00165 {
00166 fail(iLocationNumber <= 0);
00167
00168 if ((size_t)iLocationNumber >= tLocations) {
00169
00170 tLocations += EXTENSION_ARRAY_SIZE;
00171 alLocation = xrealloc(alLocation, tLocations * sizeof(long));
00172 memset(alLocation + tLocations - EXTENSION_ARRAY_SIZE,
00173 0,
00174 EXTENSION_ARRAY_SIZE * sizeof(long));
00175 DBG_DEC(tLocations);
00176 }
00177 if (iLocationNumber > iMaxLocationNumber) {
00178 iMaxLocationNumber = iLocationNumber;
00179 }
00180
00181 DBG_DEC_C((size_t)iLocationNumber >= tLocations, iLocationNumber);
00182 DBG_DEC_C((size_t)iLocationNumber >= tLocations, tLocations);
00183 fail((size_t)iLocationNumber >= tLocations);
00184
00185 alLocation[iLocationNumber] = lFilePosition;
00186 }
00187
00188
00189
00190
00191 static void
00192 vFillNextPageObject(void)
00193 {
00194 iPageCount++;
00195 if ((size_t)iPageCount >= tMaxPageObjects) {
00196
00197 tMaxPageObjects += EXTENSION_ARRAY_SIZE;
00198 aiPageObject = xrealloc(aiPageObject,
00199 tMaxPageObjects * sizeof(int));
00200 DBG_DEC(tMaxPageObjects);
00201 }
00202 aiPageObject[iPageCount] = iObjectNumberCurr;
00203 }
00204
00205
00206
00207
00208
00209
00210 static void
00211 vFPprintf(FILE *pOutFile, const char *szFormat, ...)
00212 {
00213 va_list tArg;
00214
00215 va_start(tArg, szFormat);
00216 lFilePosition += vfprintf(pOutFile, szFormat, tArg);
00217 va_end(tArg);
00218 }
00219
00220
00221
00222
00223 void
00224 vCreateInfoDictionary(diagram_type *pDiag, int iWordVersion)
00225 {
00226 FILE *pOutFile;
00227 const char *szTitle, *szAuthor, *szSubject, *szCreator;
00228 const char *szCreationDate, *szModDate;
00229
00230 fail(pDiag == NULL);
00231 fail(pDiag->pOutFile == NULL);
00232 fail(iWordVersion < 0);
00233 fail(szProducer == NULL || szProducer[0] == '\0');
00234
00235 szTitle = szGetTitle();
00236 szAuthor = szGetAuthor();
00237 szSubject = szGetSubject();
00238 szCreationDate = szGetCreationDate();
00239 szModDate = szGetModDate();
00240
00241 switch (iWordVersion) {
00242 case 0: szCreator = "Word for DOS"; break;
00243 case 1: szCreator = "WinWord 1.x"; break;
00244 case 2: szCreator = "WinWord 2.0"; break;
00245 case 4: szCreator = "MacWord 4"; break;
00246 case 5: szCreator = "MacWord 5"; break;
00247 case 6: szCreator = "Word 6"; break;
00248 case 7: szCreator = "Word 7/95"; break;
00249 case 8: szCreator = "Word 97 or later"; break;
00250 default: szCreator = NULL; break;
00251 }
00252
00253 pOutFile = pDiag->pOutFile;
00254
00255 vSetLocation(2);
00256 vFPprintf(pOutFile, "2 0 obj\n");
00257 vFPprintf(pOutFile, "<<\n");
00258 if (szTitle != NULL && szTitle[0] != '\0') {
00259 vFPprintf(pOutFile, "/Title (%s)\n", szTitle);
00260 }
00261 if (szAuthor != NULL && szAuthor[0] != '\0') {
00262 vFPprintf(pOutFile, "/Author (%s)\n", szAuthor);
00263 }
00264 if (szSubject != NULL && szSubject[0] != '\0') {
00265 vFPprintf(pOutFile, "/Subject (%s)\n", szSubject);
00266 }
00267 if (szCreator != NULL && szCreator[0] != '\0') {
00268 vFPprintf(pOutFile, "/Creator (%s)\n", szCreator);
00269 }
00270 vFPprintf(pOutFile, "/Producer (%s %s)\n", szProducer, VERSIONSTRING);
00271 if (szCreationDate != NULL && szCreationDate[0] != '\0') {
00272 vFPprintf(pOutFile, "/CreationDate (%s)\n", szCreationDate);
00273 }
00274 if (szModDate != NULL && szModDate[0] != '\0') {
00275 vFPprintf(pOutFile, "/ModDate (%s)\n", szModDate);
00276 }
00277 vFPprintf(pOutFile, ">>\n");
00278 vFPprintf(pOutFile, "endobj\n");
00279 }
00280
00281
00282
00283
00284 static void
00285 vAddHdrFtr(diagram_type *pDiag, const hdrftr_block_type *pHdrFtrInfo)
00286 {
00287 output_type *pStart, *pPrev, *pNext;
00288
00289 fail(pDiag == NULL);
00290 fail(pHdrFtrInfo == NULL);
00291
00292 vStartOfParagraphPDF(pDiag, 0);
00293 pStart = pHdrFtrInfo->pText;
00294 while (pStart != NULL) {
00295 pNext = pStart;
00296 while (pNext != NULL &&
00297 (pNext->tNextFree != 1 ||
00298 (pNext->szStorage[0] != PAR_END &&
00299 pNext->szStorage[0] != HARD_RETURN))) {
00300 pNext = pNext->pNext;
00301 }
00302 if (pNext == NULL) {
00303 if (bOutputContainsText(pStart)) {
00304 vAlign2Window(pDiag, pStart,
00305 lChar2MilliPoints(DEFAULT_SCREEN_WIDTH),
00306 ALIGNMENT_LEFT);
00307 } else {
00308 vMove2NextLinePDF(pDiag, pStart->usFontSize);
00309 }
00310 break;
00311 }
00312 fail(pNext->tNextFree != 1);
00313 fail(pNext->szStorage[0] != PAR_END &&
00314 pNext->szStorage[0] != HARD_RETURN);
00315
00316 if (pStart != pNext) {
00317
00318 pPrev = pNext->pPrev;
00319 fail(pPrev->pNext != pNext);
00320
00321 pPrev->pNext = NULL;
00322 if (bOutputContainsText(pStart)) {
00323
00324 vAlign2Window(pDiag, pStart,
00325 lChar2MilliPoints(DEFAULT_SCREEN_WIDTH),
00326 ALIGNMENT_LEFT);
00327 } else {
00328
00329 vMove2NextLinePDF(pDiag, pStart->usFontSize);
00330 }
00331
00332 pPrev->pNext = pNext;
00333 }
00334 if (pNext->szStorage[0] == PAR_END) {
00335 vEndOfParagraphPDF(pDiag, pNext->usFontSize,
00336 (long)pNext->usFontSize * 200);
00337 }
00338 pStart = pNext->pNext;
00339 }
00340 }
00341
00342
00343
00344
00345 static void
00346 vAddHeader(diagram_type *pDiag)
00347 {
00348 const hdrftr_block_type *pHdrInfo;
00349 const hdrftr_block_type *pFtrInfo;
00350
00351 fail(pDiag == NULL);
00352
00353 NO_DBG_MSG("vAddHeader");
00354
00355 pHdrInfo = pGetHdrFtrInfo(iSectionIndex, TRUE,
00356 odd(iPageCount), bFirstInSection);
00357 pFtrInfo = pGetHdrFtrInfo(iSectionIndex, FALSE,
00358 odd(iPageCount), bFirstInSection);
00359
00360 lFooterHeight = pFtrInfo == NULL ? 0 : pFtrInfo->lHeight;
00361 fail(lFooterHeight < 0);
00362
00363 if (pHdrInfo == NULL ||
00364 pHdrInfo->pText == NULL ||
00365 pHdrInfo->lHeight <= 0) {
00366 fail(pHdrInfo != NULL && pHdrInfo->lHeight < 0);
00367 fail(pHdrInfo != NULL &&
00368 pHdrInfo->pText != NULL &&
00369 pHdrInfo->lHeight == 0);
00370 return;
00371 }
00372
00373 vAddHdrFtr(pDiag, pHdrInfo);
00374
00375 DBG_DEC_C(pHdrInfo->lHeight !=
00376 lPageHeight - PS_TOP_MARGIN - pDiag->lYtop,
00377 pHdrInfo->lHeight);
00378 DBG_DEC_C(pHdrInfo->lHeight !=
00379 lPageHeight - PS_TOP_MARGIN - pDiag->lYtop,
00380 lPageHeight - PS_TOP_MARGIN - pDiag->lYtop);
00381 }
00382
00383
00384
00385
00386 static void
00387 vAddFooter(diagram_type *pDiag)
00388 {
00389 const hdrftr_block_type *pFtrInfo;
00390
00391 fail(pDiag == NULL);
00392
00393 NO_DBG_MSG("vAddFooter");
00394
00395 pFtrInfo = pGetHdrFtrInfo(iSectionIndex, FALSE,
00396 odd(iPageCount), bFirstInSection);
00397 bFirstInSection = FALSE;
00398 if (pFtrInfo == NULL ||
00399 pFtrInfo->pText == NULL ||
00400 pFtrInfo->lHeight <= 0) {
00401 fail(pFtrInfo != NULL && pFtrInfo->lHeight < 0);
00402 fail(pFtrInfo != NULL &&
00403 pFtrInfo->pText != NULL &&
00404 pFtrInfo->lHeight == 0);
00405 return;
00406 }
00407
00408 bInFtrSpace = TRUE;
00409
00410 DBG_DEC_C(pFtrInfo->lHeight != lFooterHeight, pFtrInfo->lHeight);
00411 DBG_DEC_C(pFtrInfo->lHeight != lFooterHeight, lFooterHeight);
00412 DBG_DEC_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
00413 pDiag->lYtop);
00414 DBG_DEC_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
00415 lFooterHeight + PS_BOTTOM_MARGIN);
00416
00417 if (pDiag->lYtop > lFooterHeight + PS_BOTTOM_MARGIN) {
00418
00419 pDiag->lYtop = lFooterHeight + PS_BOTTOM_MARGIN;
00420 vMoveTo(pDiag, 0);
00421 } else if (pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN / 2) {
00422 DBG_FIXME();
00423
00424
00425
00426
00427 pDiag->lYtop = lFooterHeight + PS_BOTTOM_MARGIN;
00428 vMoveTo(pDiag, 0);
00429 }
00430
00431 DBG_FLT_C(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN,
00432 dDrawUnits2Points(lFooterHeight + PS_BOTTOM_MARGIN - pDiag->lYtop));
00433
00434 vAddHdrFtr(pDiag, pFtrInfo);
00435 bInFtrSpace = FALSE;
00436 }
00437
00438
00439
00440
00441 static void
00442 vEndPageObject(FILE *pOutFile)
00443 {
00444 long lStreamEnd;
00445
00446 if (lStreamStart < 0) {
00447
00448 return;
00449 }
00450
00451 vFPprintf(pOutFile, "ET\n");
00452 lStreamEnd = lFilePosition;
00453 vFPprintf(pOutFile, "endstream\n");
00454 vFPprintf(pOutFile, "endobj\n");
00455
00456 iObjectNumberCurr++;
00457 vSetLocation(iObjectNumberCurr);
00458 vFPprintf(pOutFile, "%d 0 obj\n", iObjectNumberCurr);
00459 vFPprintf(pOutFile, "%lu\n", lStreamEnd - lStreamStart);
00460 vFPprintf(pOutFile, "endobj\n");
00461 }
00462
00463
00464
00465
00466 static void
00467 vMove2NextPage(diagram_type *pDiag, BOOL bNewSection)
00468 {
00469 FILE *pOutFile;
00470
00471 fail(pDiag == NULL);
00472 fail(pDiag->pOutFile == NULL);
00473
00474 pOutFile = pDiag->pOutFile;
00475
00476 vAddFooter(pDiag);
00477
00478 vEndPageObject(pOutFile);
00479 if (bNewSection) {
00480 iSectionIndex++;
00481 bFirstInSection = TRUE;
00482 }
00483
00484
00485 iObjectNumberCurr++;
00486 vSetLocation(iObjectNumberCurr);
00487 vFillNextPageObject();
00488 vFPprintf(pOutFile, "%d 0 obj\n", iObjectNumberCurr);
00489 vFPprintf(pOutFile, "<<\n");
00490 vFPprintf(pOutFile, "/Type /Page\n");
00491 vFPprintf(pOutFile, "/Parent 3 0 R\n");
00492 vFPprintf(pOutFile, "/Resources 17 0 R\n");
00493 vFPprintf(pOutFile, "/Contents %d 0 R\n", iObjectNumberCurr + 1);
00494 vFPprintf(pOutFile, ">>\n");
00495 vFPprintf(pOutFile, "endobj\n");
00496
00497
00498 iObjectNumberCurr++;
00499 vSetLocation(iObjectNumberCurr);
00500 vFPprintf(pOutFile, "%d 0 obj\n", iObjectNumberCurr);
00501 vFPprintf(pOutFile, "<<\n");
00502 vFPprintf(pOutFile, "/Length %d 0 R\n", iObjectNumberCurr + 1);
00503 vFPprintf(pOutFile, ">>\n");
00504 vFPprintf(pOutFile, "stream\n");
00505 lStreamStart = lFilePosition;
00506 vFPprintf(pOutFile, "BT\n");
00507
00508
00509 pDiag->lYtop = lPageHeight - PS_TOP_MARGIN;
00510 tFontRefCurr = (drawfile_fontref)-1;
00511 usFontSizeCurr = 0;
00512 iFontColorCurr = -1;
00513 lYtopCurr = -1;
00514 vAddHeader(pDiag);
00515 }
00516
00517
00518
00519
00520
00521
00522
00523 static void
00524 vMoveTo(diagram_type *pDiag, long lLastVerticalMovement)
00525 {
00526 fail(pDiag == NULL);
00527 fail(pDiag->pOutFile == NULL);
00528
00529 if (pDiag->lYtop <= lFooterHeight + PS_BOTTOM_MARGIN && !bInFtrSpace) {
00530 vMove2NextPage(pDiag, FALSE);
00531
00532 pDiag->lYtop -= lLastVerticalMovement;
00533 }
00534
00535 fail(pDiag->lYtop < lFooterHeight + PS_BOTTOM_MARGIN && !bInFtrSpace);
00536 DBG_DEC_C(pDiag->lYtop < PS_BOTTOM_MARGIN, pDiag->lYtop);
00537 fail(pDiag->lYtop < PS_BOTTOM_MARGIN / 3);
00538
00539 if (pDiag->lYtop != lYtopCurr) {
00540 vFPprintf(pDiag->pOutFile, "1 0 0 1 %.2f %.2f Tm\n",
00541 dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
00542 dDrawUnits2Points(pDiag->lYtop));
00543 lYtopCurr = pDiag->lYtop;
00544 }
00545 }
00546
00547
00548
00549
00550 void
00551 vProloguePDF(diagram_type *pDiag,
00552 const char *szTask, const options_type *pOptions)
00553 {
00554 FILE *pOutFile;
00555
00556 fail(pDiag == NULL);
00557 fail(pDiag->pOutFile == NULL);
00558 fail(pOptions == NULL);
00559
00560 pOutFile = pDiag->pOutFile;
00561
00562 eEncoding = pOptions->eEncoding;
00563
00564
00565 tLocations = INITIAL_LOCATION_SIZE;
00566 alLocation = xcalloc(tLocations, sizeof(long));
00567
00568
00569 tMaxPageObjects = INITIAL_PAGEOBJECT_SIZE;
00570 aiPageObject = xcalloc(tMaxPageObjects, sizeof(int));
00571
00572 if (pOptions->iPageHeight == INT_MAX) {
00573 lPageHeight = LONG_MAX;
00574 } else {
00575 lPageHeight = lPoints2DrawUnits(pOptions->iPageHeight);
00576 }
00577 DBG_DEC(lPageHeight);
00578 if (pOptions->iPageWidth == INT_MAX) {
00579 lPageWidth = LONG_MAX;
00580 } else {
00581 lPageWidth = lPoints2DrawUnits(pOptions->iPageWidth);
00582 }
00583 DBG_DEC(lPageWidth);
00584 lFooterHeight = 0;
00585 bInFtrSpace = FALSE;
00586
00587 tFontRefCurr = (drawfile_fontref)-1;
00588 usFontSizeCurr = 0;
00589 iFontColorCurr = -1;
00590 lYtopCurr = -1;
00591 iPageCount = 0;
00592 iImageCount = 0;
00593 iSectionIndex = 0;
00594 bFirstInSection = TRUE;
00595 lFilePosition = 0;
00596 iMaxLocationNumber = 0;
00597 lStreamStart = -1;
00598 iObjectNumberCurr = 17;
00599 pDiag->lXleft = 0;
00600 pDiag->lYtop = 0;
00601
00602 szProducer = szTask;
00603
00604 vFPprintf(pOutFile, "%%PDF-1.3\n");
00605 vFPprintf(pOutFile, "%%%c%c%c%c\n", 0xe2, 0xe3, 0xcf, 0xd3);
00606
00607
00608 vSetLocation(1);
00609 vFPprintf(pOutFile, "1 0 obj\n");
00610 vFPprintf(pOutFile, "<<\n");
00611 vFPprintf(pOutFile, "/Type /Catalog\n");
00612 vFPprintf(pOutFile, "/Pages 3 0 R\n");
00613 vFPprintf(pOutFile, ">>\n");
00614 vFPprintf(pOutFile, "endobj\n");
00615 }
00616
00617
00618
00619
00620 void
00621 vEpiloguePDF(diagram_type *pDiag)
00622 {
00623 FILE *pOutFile;
00624 long lXref;
00625 int iIndex;
00626
00627 fail(pDiag == NULL);
00628 fail(pDiag->pOutFile == NULL);
00629
00630 pOutFile = pDiag->pOutFile;
00631
00632 vAddFooter(pDiag);
00633
00634 vEndPageObject(pOutFile);
00635
00636 vSetLocation(3);
00637 vFPprintf(pOutFile, "3 0 obj\n");
00638 vFPprintf(pOutFile, "<<\n");
00639 vFPprintf(pOutFile, "/Type /Pages\n");
00640 vFPprintf(pOutFile, "/Count %d\n", iPageCount);
00641 vFPprintf(pOutFile, "/MediaBox [ 0 0 %.0f %.0f ]\n",
00642 dDrawUnits2Points(lPageWidth),
00643 dDrawUnits2Points(lPageHeight));
00644 vFPprintf(pOutFile, "/Kids [ ");
00645 for (iIndex = 1; iIndex <= iPageCount; iIndex++) {
00646 vFPprintf(pOutFile, "\t%d 0 R\n", aiPageObject[iIndex]);
00647 }
00648 vFPprintf(pOutFile, "]\n");
00649 vFPprintf(pOutFile, ">>\n");
00650 vFPprintf(pOutFile, "endobj\n");
00651
00652 lXref = lFilePosition;
00653
00654 vFPprintf(pOutFile, "xref\n");
00655 vFPprintf(pOutFile, "0 %d\n", iMaxLocationNumber + 1);
00656 vFPprintf(pOutFile, "0000000000 65535 f \n");
00657 for (iIndex = 1; iIndex <= iMaxLocationNumber; iIndex++) {
00658 vFPprintf(pOutFile, "%.10ld 00000 n \n", alLocation[iIndex]);
00659 }
00660
00661 vFPprintf(pOutFile, "trailer\n");
00662 vFPprintf(pOutFile, "<<\n");
00663 vFPprintf(pOutFile, "/Size %d\n", iMaxLocationNumber + 1);
00664 vFPprintf(pOutFile, "/Root 1 0 R\n");
00665 vFPprintf(pOutFile, "/Info 2 0 R\n");
00666 vFPprintf(pOutFile, ">>\n");
00667
00668 vFPprintf(pOutFile, "startxref\n");
00669 vFPprintf(pOutFile, "%ld\n", lXref);
00670 vFPprintf(pOutFile, "%%%%EOF\n");
00671
00672 szProducer = NULL;
00673 aiPageObject = xfree(aiPageObject);
00674 alLocation = xfree(alLocation);
00675 }
00676
00677
00678
00679
00680 static void
00681 vPrintPalette(FILE *pOutFile, const imagedata_type *pImg)
00682 {
00683 int iIndex;
00684
00685 fail(pOutFile == NULL);
00686 fail(pImg == NULL);
00687 fail(pImg->iColorsUsed < 2);
00688 fail(pImg->iColorsUsed > 256);
00689
00690 vFPprintf(pOutFile, "\t/ColorSpace [ /Indexed\n");
00691 vFPprintf(pOutFile, "\t/Device%s %d\n",
00692 pImg->bColorImage ? "RGB" : "Gray", pImg->iColorsUsed - 1);
00693 vFPprintf(pOutFile, "<");
00694 for (iIndex = 0; iIndex < pImg->iColorsUsed; iIndex++) {
00695 vFPprintf(pOutFile, "%02x",
00696 (unsigned int)pImg->aucPalette[iIndex][0]);
00697 if (pImg->bColorImage) {
00698 vFPprintf(pOutFile, "%02x%02x",
00699 (unsigned int)pImg->aucPalette[iIndex][1],
00700 (unsigned int)pImg->aucPalette[iIndex][2]);
00701 }
00702 if (iIndex % 8 == 7) {
00703 vFPprintf(pOutFile, "\n");
00704 } else {
00705 vFPprintf(pOutFile, " ");
00706 }
00707 }
00708 vFPprintf(pOutFile, "> ]\n");
00709 }
00710
00711
00712
00713
00714 void
00715 vImageProloguePDF(diagram_type *pDiag, const imagedata_type *pImg)
00716 {
00717 FILE *pOutFile;
00718
00719 fail(pDiag == NULL);
00720 fail(pDiag->pOutFile == NULL);
00721 fail(pImg == NULL);
00722
00723 if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
00724 return;
00725 }
00726
00727 iImageCount++;
00728
00729 DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
00730
00731 pDiag->lYtop -= lPoints2DrawUnits(pImg->iVerSizeScaled);
00732 vMoveTo(pDiag, lPoints2DrawUnits(pImg->iVerSizeScaled));
00733
00734 pOutFile = pDiag->pOutFile;
00735
00736 vFPprintf(pOutFile, "ET\n");
00737 vFPprintf(pOutFile, "q %% Image %03d\n", iImageCount);
00738 if (pImg->eImageType == imagetype_is_dib) {
00739
00740 vFPprintf(pOutFile, "%d 0 0 %d %.2f %.2f cm\n",
00741 pImg->iHorSizeScaled, -pImg->iVerSizeScaled,
00742 dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
00743 dDrawUnits2Points(pDiag->lYtop) + pImg->iVerSizeScaled);
00744 } else {
00745
00746 vFPprintf(pOutFile, "%d 0 0 %d %.2f %.2f cm\n",
00747 pImg->iHorSizeScaled, pImg->iVerSizeScaled,
00748 dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
00749 dDrawUnits2Points(pDiag->lYtop));
00750 }
00751 vFPprintf(pOutFile, "BI\n");
00752 vFPprintf(pOutFile, "\t/Width %d\n", pImg->iWidth);
00753 vFPprintf(pOutFile, "\t/Height %d\n", pImg->iHeight);
00754 switch (pImg->eImageType) {
00755 case imagetype_is_jpeg:
00756 switch (pImg->iComponents) {
00757 case 1:
00758 vFPprintf(pOutFile, "\t/ColorSpace /DeviceGray\n");
00759 break;
00760 case 3:
00761 vFPprintf(pOutFile, "\t/ColorSpace /DeviceRGB\n");
00762 break;
00763 case 4:
00764 vFPprintf(pOutFile, "\t/ColorSpace /DeviceCMYK\n");
00765 if (pImg->bAdobe) {
00766
00767
00768
00769
00770 vFPprintf(pOutFile,
00771 "\t/Decode [1 0 1 0 1 0 1 0]\n");
00772 }
00773 break;
00774 default:
00775 DBG_DEC(pImg->iComponents);
00776 break;
00777 }
00778 vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
00779 vFPprintf(pOutFile,
00780 "\t/Filter [ /ASCII85Decode /DCTDecode ]\n");
00781 break;
00782 case imagetype_is_png:
00783 if (pImg->iComponents == 3 || pImg->iComponents == 4) {
00784 vFPprintf(pOutFile, "\t/ColorSpace /DeviceRGB\n");
00785 vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
00786 } else if (pImg->iColorsUsed > 0) {
00787 vPrintPalette(pOutFile, pImg);
00788 fail(pImg->uiBitsPerComponent > 8);
00789 vFPprintf(pOutFile, "\t/BitsPerComponent %u\n",
00790 pImg->uiBitsPerComponent);
00791 } else {
00792 vFPprintf(pOutFile, "\t/ColorSpace /DeviceGray\n");
00793 vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
00794 }
00795 vFPprintf(pOutFile,
00796 "\t/Filter [ /ASCII85Decode /FlateDecode ]\n");
00797 vFPprintf(pOutFile, "\t/DecodeParms [ null <<\n");
00798 vFPprintf(pOutFile, "\t\t/Predictor 10\n");
00799 vFPprintf(pOutFile, "\t\t/Colors %d\n", pImg->iComponents);
00800 vFPprintf(pOutFile, "\t\t/BitsPerComponent %u\n",
00801 pImg->uiBitsPerComponent);
00802 vFPprintf(pOutFile, "\t\t/Columns %d\n", pImg->iWidth);
00803 vFPprintf(pOutFile, "\t\t>> ]\n");
00804 break;
00805 case imagetype_is_dib:
00806 if (pImg->uiBitsPerComponent <= 8) {
00807 vPrintPalette(pOutFile, pImg);
00808 } else {
00809 vFPprintf(pOutFile, "\t/ColorSpace /DeviceRGB\n");
00810 }
00811 vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
00812 vFPprintf(pOutFile, "\t/Filter /ASCII85Decode\n");
00813 break;
00814 default:
00815 vFPprintf(pOutFile, "\t/ColorSpace /Device%s\n",
00816 pImg->bColorImage ? "RGB" : "Gray");
00817 vFPprintf(pOutFile, "\t/BitsPerComponent 8\n");
00818 vFPprintf(pOutFile, "\t/Filter /ASCIIHexDecode\n");
00819 break;
00820 }
00821 vFPprintf(pOutFile, "ID\n");
00822 }
00823
00824
00825
00826
00827 void
00828 vImageEpiloguePDF(diagram_type *pDiag)
00829 {
00830 FILE *pOutFile;
00831
00832 fail(pDiag == NULL);
00833 fail(pDiag->pOutFile == NULL);
00834
00835 pOutFile = pDiag->pOutFile;
00836
00837
00838 lFilePosition = ftell(pOutFile);
00839
00840 vFPprintf(pOutFile, "EI\n");
00841 vFPprintf(pOutFile, "Q\n");
00842 vFPprintf(pOutFile, "BT\n");
00843
00844 pDiag->lXleft = 0;
00845 }
00846
00847
00848
00849
00850
00851
00852 BOOL
00853 bAddDummyImagePDF(diagram_type *pDiag, const imagedata_type *pImg)
00854 {
00855 FILE *pOutFile;
00856
00857 fail(pDiag == NULL);
00858 fail(pDiag->pOutFile == NULL);
00859 fail(pImg == NULL);
00860
00861 if (pImg->iVerSizeScaled <= 0 || pImg->iHorSizeScaled <= 0) {
00862 return FALSE;
00863 }
00864
00865 iImageCount++;
00866
00867 DBG_DEC_C(pDiag->lXleft != 0, pDiag->lXleft);
00868
00869 pDiag->lYtop -= lPoints2DrawUnits(pImg->iVerSizeScaled);
00870 vMoveTo(pDiag, lPoints2DrawUnits(pImg->iVerSizeScaled));
00871
00872 pOutFile = pDiag->pOutFile;
00873
00874 vFPprintf(pOutFile, "ET\n");
00875 vFPprintf(pOutFile, "q %% Image %03d\n", iImageCount);
00876 vFPprintf(pOutFile, "\t1.0 w\n");
00877 vFPprintf(pOutFile, "\t0.3 G\n");
00878 vFPprintf(pOutFile, "\t%.2f %.2f %d %d re\n",
00879 dDrawUnits2Points(pDiag->lXleft + PS_LEFT_MARGIN),
00880 dDrawUnits2Points(pDiag->lYtop),
00881 pImg->iHorSizeScaled,
00882 pImg->iVerSizeScaled);
00883 vFPprintf(pOutFile, "\tS\n");
00884 vFPprintf(pOutFile, "Q\n");
00885 vFPprintf(pOutFile, "BT\n");
00886
00887 pDiag->lXleft = 0;
00888
00889 return TRUE;
00890 }
00891
00892
00893
00894
00895 void
00896 vAddFontsPDF(diagram_type *pDiag)
00897 {
00898 FILE *pOutFile;
00899 size_t tIndex;
00900
00901 fail(pDiag == NULL);
00902 fail(pDiag->pOutFile == NULL);
00903
00904 pOutFile = pDiag->pOutFile;
00905
00906
00907 vSetLocation(4);
00908 vFPprintf(pOutFile, "4 0 obj\n");
00909 vFPprintf(pOutFile, "<<\n");
00910 vFPprintf(pOutFile, "/Type /Encoding\n");
00911 vFPprintf(pOutFile, "/BaseEncoding /StandardEncoding\n");
00912 vFPprintf(pOutFile, "/Differences [\n");
00913 switch (eEncoding) {
00914 case encoding_latin_1:
00915 for (tIndex = 0;
00916 tIndex < elementsof(iso_8859_1);
00917 tIndex++) {
00918 vFPprintf(pOutFile, "%s\n", iso_8859_1[tIndex]);
00919 }
00920 break;
00921 case encoding_latin_2:
00922 for (tIndex = 0;
00923 tIndex < elementsof(iso_8859_2);
00924 tIndex++) {
00925 vFPprintf(pOutFile, "%s\n", iso_8859_2[tIndex]);
00926 }
00927 break;
00928 case encoding_cyrillic:
00929 werr(1,
00930 "The combination PDF and Cyrillic is not supported");
00931 break;
00932 case encoding_utf_8:
00933 werr(1,
00934 "The combination PDF and UTF-8 is not supported");
00935 break;
00936 default:
00937 DBG_DEC(eEncoding);
00938 break;
00939 }
00940 vFPprintf(pOutFile, "]\n");
00941 vFPprintf(pOutFile, ">>\n");
00942 vFPprintf(pOutFile, "endobj\n");
00943
00944
00945 for (tIndex = 0; tIndex < 12; tIndex++) {
00946 vSetLocation(5 + tIndex);
00947 vFPprintf(pOutFile, "%u 0 obj\n", 5 + tIndex);
00948 vFPprintf(pOutFile, "<<\n");
00949 vFPprintf(pOutFile, "/Type /Font\n");
00950 vFPprintf(pOutFile, "/Subtype /Type1\n");
00951 vFPprintf(pOutFile, "/Name /F%u\n", 1 + tIndex);
00952 vFPprintf(pOutFile, "/BaseFont /%s\n",
00953 atFontname[tIndex].szPDFname);
00954 vFPprintf(pOutFile, "/Encoding 4 0 R\n");
00955 vFPprintf(pOutFile, ">>\n");
00956 vFPprintf(pOutFile, "endobj\n");
00957 }
00958
00959
00960 vSetLocation(17);
00961 vFPprintf(pOutFile, "17 0 obj\n");
00962 vFPprintf(pOutFile, "<<\n");
00963 vFPprintf(pOutFile, "/ProcSet [ /PDF /Text ]\n");
00964 vFPprintf(pOutFile, "/Font <<\n");
00965 for (tIndex = 0; tIndex < 12; tIndex++) {
00966 vFPprintf(pOutFile, "\t/F%u %u 0 R\n", 1 + tIndex, 5 + tIndex);
00967 }
00968 vFPprintf(pOutFile, "\t>>\n");
00969 vFPprintf(pOutFile, ">>\n");
00970 vFPprintf(pOutFile, "endobj\n");
00971 vAddHeader(pDiag);
00972 }
00973
00974
00975
00976
00977 static void
00978 vPrintPDF(FILE *pFile, const char *szString, size_t tStringLength,
00979 USHORT usFontstyle)
00980 {
00981 const UCHAR *aucBytes;
00982 double dMove;
00983 size_t tCount;
00984
00985 fail(szString == NULL);
00986
00987 if (szString == NULL || szString[0] == '\0' || tStringLength == 0) {
00988 return;
00989 }
00990 DBG_DEC_C(usFontSizeCurr < MIN_FONT_SIZE, usFontSizeCurr);
00991
00992 dMove = 0.0;
00993
00994
00995 if (bIsSuperscript(usFontstyle) && usFontSizeCurr != 0) {
00996 dMove = (double)((usFontSizeCurr + 1) / 2) * 0.375;
00997 vFPprintf(pFile, "%.2f Ts\n", dMove);
00998 }
00999
01000
01001 if (bIsSubscript(usFontstyle) && usFontSizeCurr != 0) {
01002 dMove = (double)usFontSizeCurr * 0.125;
01003 vFPprintf(pFile, "%.2f Ts\n", -dMove);
01004 }
01005
01006
01007 aucBytes = (UCHAR *)szString;
01008 vFPprintf(pFile, "(");
01009 for (tCount = 0; tCount < tStringLength ; tCount++) {
01010 switch (aucBytes[tCount]) {
01011 case '(':
01012 case ')':
01013 case '\\':
01014 vFPprintf(pFile, "\\%c", szString[tCount]);
01015 break;
01016 default:
01017 if (aucBytes[tCount] < 0x20 ||
01018 aucBytes[tCount] == 0x7f ||
01019 (aucBytes[tCount] >= 0x81 &&
01020 aucBytes[tCount] < 0x8c)) {
01021 DBG_HEX(aucBytes[tCount]);
01022 vFPprintf(pFile, " ");
01023 } else if (aucBytes[tCount] >= 0x80) {
01024 vFPprintf(pFile, "\\%03o",
01025 (UINT)aucBytes[tCount]);
01026 } else {
01027 vFPprintf(pFile, "%c", szString[tCount]);
01028 }
01029 break;
01030 }
01031 }
01032 vFPprintf(pFile, ") Tj\n");
01033
01034
01035 if (dMove != 0.0) {
01036 vFPprintf(pFile, "0 Ts\n");
01037 }
01038 }
01039
01040
01041
01042
01043 static void
01044 vSetColor(FILE *pFile, UCHAR ucFontColor)
01045 {
01046 ULONG ulTmp, ulRed, ulGreen, ulBlue;
01047
01048 ulTmp = ulColor2Color(ucFontColor);
01049 ulRed = (ulTmp & 0x0000ff00) >> 8;
01050 ulGreen = (ulTmp & 0x00ff0000) >> 16;
01051 ulBlue = (ulTmp & 0xff000000) >> 24;
01052 vFPprintf(pFile, "%.3f %.3f %.3f rg\n",
01053 ulRed / 255.0, ulGreen / 255.0, ulBlue / 255.0);
01054 }
01055
01056
01057
01058
01059 void
01060 vMove2NextLinePDF(diagram_type *pDiag, USHORT usFontSize)
01061 {
01062 fail(pDiag == NULL);
01063 fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
01064
01065 pDiag->lYtop -= lComputeLeading(usFontSize);
01066 }
01067
01068
01069
01070
01071 void
01072 vSubstringPDF(diagram_type *pDiag,
01073 char *szString, size_t tStringLength, long lStringWidth,
01074 UCHAR ucFontColor, USHORT usFontstyle, drawfile_fontref tFontRef,
01075 USHORT usFontSize, USHORT usMaxFontSize)
01076 {
01077 size_t tFontIndex;
01078
01079 fail(pDiag == NULL || szString == NULL);
01080 fail(pDiag->pOutFile == NULL);
01081 fail(pDiag->lXleft < 0);
01082 fail(tStringLength != strlen(szString));
01083 fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
01084 fail(usMaxFontSize < MIN_FONT_SIZE || usMaxFontSize > MAX_FONT_SIZE);
01085 fail(usFontSize > usMaxFontSize);
01086
01087 if (szString[0] == '\0' || tStringLength == 0) {
01088 return;
01089 }
01090
01091 vMoveTo(pDiag, lComputeLeading(usMaxFontSize));
01092 if (tFontRef != tFontRefCurr || usFontSize != usFontSizeCurr) {
01093 tFontIndex = tGetFontIndex(tFontRef);
01094 vFPprintf(pDiag->pOutFile, "/F%u %.1f Tf\n",
01095 1 + tFontIndex, (double)usFontSize / 2.0);
01096 tFontRefCurr = tFontRef;
01097 usFontSizeCurr = usFontSize;
01098 }
01099 if ((int)ucFontColor != iFontColorCurr) {
01100 vSetColor(pDiag->pOutFile, ucFontColor);
01101 iFontColorCurr = (int)ucFontColor;
01102 }
01103 vPrintPDF(pDiag->pOutFile, szString, tStringLength, usFontstyle);
01104 pDiag->lXleft += lStringWidth;
01105 }
01106
01107
01108
01109
01110 void
01111 vStartOfParagraphPDF(diagram_type *pDiag, long lBeforeIndentation)
01112 {
01113 fail(pDiag == NULL);
01114 fail(lBeforeIndentation < 0);
01115
01116 pDiag->lXleft = 0;
01117 pDiag->lYtop -= lMilliPoints2DrawUnits(lBeforeIndentation);
01118 }
01119
01120
01121
01122
01123 void
01124 vEndOfParagraphPDF(diagram_type *pDiag,
01125 USHORT usFontSize, long lAfterIndentation)
01126 {
01127 fail(pDiag == NULL);
01128 fail(pDiag->pOutFile == NULL);
01129 fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
01130 fail(lAfterIndentation < 0);
01131
01132 if (pDiag->lXleft > 0) {
01133
01134 vMove2NextLinePDF(pDiag, usFontSize);
01135 }
01136
01137 pDiag->lXleft = 0;
01138 pDiag->lYtop -= lMilliPoints2DrawUnits(lAfterIndentation);
01139 }
01140
01141
01142
01143
01144 void
01145 vEndOfPagePDF(diagram_type *pDiag, BOOL bNewSection)
01146 {
01147 vMove2NextPage(pDiag, bNewSection);
01148 }