📄 pdf.c
字号:
/* * pdf.c * Copyright (C) 2003-2005 A.J. van Os; Released under GNU GPL * * Description: * Functions to deal with the Adobe Portable Document Format (pdf) * */#include <stdarg.h>#include <string.h>#include "version.h"#include "antiword.h"/* Constants for the file positions */#define INITIAL_LOCATION_SIZE 20#define INITIAL_PAGEOBJECT_SIZE 5#if defined(DEBUG)#define EXTENSION_ARRAY_SIZE 10#else#define EXTENSION_ARRAY_SIZE 30#endif /* DEBUG *//* The character set */static encoding_type eEncoding = encoding_neutral;/* Current creator for a PDF header */static const char *szProducer = NULL;/* The height and width of a PDF page (in DrawUnits) */static long lPageHeight = LONG_MAX;static long lPageWidth = LONG_MAX;/* The height of the footer on the current page (in DrawUnits) */static long lFooterHeight = 0;/* Inside a footer (to prevent an infinite loop when the footer is too big) */static BOOL bInFtrSpace = FALSE;/* Current font information */static drawfile_fontref tFontRefCurr = (drawfile_fontref)-1;static USHORT usFontSizeCurr = 0;static int iFontColorCurr = -1;/* Current vertical position information */static long lYtopCurr = -1;/* Image counter */static int iImageCount = 0;/* Section index */static int iSectionIndex = 0;/* Are we on the first page of the section? */static BOOL bFirstInSection = TRUE;/* File positions */static long lFilePosition = 0;static long *alLocation = NULL;static size_t tLocations = 0;static int iMaxLocationNumber = 0;/* File position at the start of a page */static long lStreamStart = -1;/* Page objects */static int *aiPageObject = NULL;static int iPageCount = 0;static size_t tMaxPageObjects = 0;/* Current object number *//* 1 = root; 2 = info; 3 = pages; 4 = encoding; 5-16 = fonts; 17 = resources */static int iObjectNumberCurr = 17;static void vMoveTo(diagram_type *, long);static const struct { const char *szPDFname; const char *szPSname;} atFontname[] = { { "Courier", FONT_MONOSPACED_PLAIN }, { "Courier-Bold", FONT_MONOSPACED_BOLD }, { "Courier-Oblique", FONT_MONOSPACED_ITALIC }, { "Courier-BoldOblique", FONT_MONOSPACED_BOLDITALIC }, { "Helvetica", FONT_SANS_SERIF_PLAIN }, { "Helvetica-Bold", FONT_SANS_SERIF_BOLD }, { "Helvetica-Oblique", FONT_SANS_SERIF_ITALIC }, { "Helvetica-BoldOblique", FONT_SANS_SERIF_BOLDITALIC }, { "Times-Roman", FONT_SERIF_PLAIN }, { "Times-Bold", FONT_SERIF_BOLD }, { "Times-Italic", FONT_SERIF_ITALIC }, { "Times-BoldItalic", FONT_SERIF_BOLDITALIC },};static const char *iso_8859_1[] = {"128 /Euro","140 /ellipsis /trademark /perthousand /bullet"," /quoteleft /quoteright /guilsinglleft /guilsinglright"," /quotedblleft /quotedblright /quotedblbase /endash /emdash"," /minus /OE /oe /dagger /daggerdbl /fi /fl","160 /space /exclamdown /cent /sterling /currency"," /yen /brokenbar /section /dieresis /copyright"," /ordfeminine /guillemotleft /logicalnot /hyphen /registered"," /macron /degree /plusminus /twosuperior /threesuperior"," /acute /mu /paragraph /periodcentered /cedilla"," /onesuperior /ordmasculine /guillemotright /onequarter"," /onehalf /threequarters /questiondown /Agrave /Aacute"," /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla"," /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute"," /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute"," /Ocircumflex /Otilde /Odieresis /multiply /Oslash"," /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn"," /germandbls /agrave /aacute /acircumflex /atilde"," /adieresis /aring /ae /ccedilla /egrave /eacute"," /ecircumflex /edieresis /igrave /iacute /icircumflex"," /idieresis /eth /ntilde /ograve /oacute /ocircumflex"," /otilde /odieresis /divide /oslash /ugrave /uacute"," /ucircumflex /udieresis /yacute /thorn /ydieresis",};static const char *iso_8859_2[] = {"160 /space /Aogonek /breve /Lslash /currency /Lcaron"," /Sacute /section /dieresis /Scaron /Scommaaccent"," /Tcaron /Zacute /hyphen /Zcaron /Zdotaccent /degree"," /aogonek /ogonek /lslash /acute /lcaron /sacute"," /caron /cedilla /scaron /scommaaccent /tcaron"," /zacute /hungarumlaut /zcaron /zdotaccent /Racute"," /Aacute /Acircumflex /Abreve /Adieresis /Lacute"," /Cacute /Ccedilla /Ccaron /Eacute /Eogonek"," /Edieresis /Ecaron /Iacute /Icircumflex /Dcaron"," /.notdef /Nacute /Ncaron /Oacute /Ocircumflex"," /Ohungarumlaut /Odieresis /multiply /Rcaron /Uring"," /Uacute /Uhungarumlaut /Udieresis /Yacute /Tcommaaccent"," /germandbls /racute /aacute /acircumflex /abreve"," /adieresis /lacute /cacute /ccedilla /ccaron /eacute"," /eogonek /edieresis /ecaron /iacute /icircumflex"," /dcaron /.notdef /nacute /ncaron /oacute /ocircumflex"," /ohungarumlaut /odieresis /divide /rcaron /uring"," /uacute /uhungarumlaut /udieresis /yacute /tcommaaccent"," /dotaccent",};/* * tGetFontIndex - get the font index */static size_ttGetFontIndex(drawfile_fontref tFontRef){ const char *szFontname; size_t tIndex; /* Get the font name */ szFontname = szGetFontname(tFontRef); fail(szFontname == NULL); if (szFontname == NULL) { return 0; } /* Find the name in the table */ for (tIndex = 0; tIndex < elementsof(atFontname); tIndex++) { if (STRCEQ(atFontname[tIndex].szPSname, szFontname)) { return tIndex; } } /* Not found */ DBG_DEC(tFontRef); DBG_MSG(szFontname); return 0;} /* end of tGetFontIndex *//* * vSetLocation - store the location of objects */static voidvSetLocation(int iLocationNumber){ fail(iLocationNumber <= 0); if ((size_t)iLocationNumber >= tLocations) { /* Extend and set to zero */ tLocations += EXTENSION_ARRAY_SIZE; alLocation = xrealloc(alLocation, tLocations * sizeof(long)); memset(alLocation + tLocations - EXTENSION_ARRAY_SIZE, 0, EXTENSION_ARRAY_SIZE * sizeof(long)); DBG_DEC(tLocations); } if (iLocationNumber > iMaxLocationNumber) { iMaxLocationNumber = iLocationNumber; } DBG_DEC_C((size_t)iLocationNumber >= tLocations, iLocationNumber); DBG_DEC_C((size_t)iLocationNumber >= tLocations, tLocations); fail((size_t)iLocationNumber >= tLocations); alLocation[iLocationNumber] = lFilePosition;} /* end of vSetLocation *//* * vFillNextPageObject - fil the next page object with the current object number */static voidvFillNextPageObject(void){ iPageCount++; if ((size_t)iPageCount >= tMaxPageObjects) { /* Extend the array */ tMaxPageObjects += EXTENSION_ARRAY_SIZE; aiPageObject = xrealloc(aiPageObject, tMaxPageObjects * sizeof(int)); DBG_DEC(tMaxPageObjects); } aiPageObject[iPageCount] = iObjectNumberCurr;} /* end of vFillNextPageObject *//* * vFPprintf - printf and update the fileposition * * called with arguments like fprintf(3) */static voidvFPprintf(FILE *pOutFile, const char *szFormat, ...){ va_list tArg; va_start(tArg, szFormat); lFilePosition += vfprintf(pOutFile, szFormat, tArg); va_end(tArg);} /* end of vFPprintf *//* * vCreateInfoDictionary - create the document information dictionary */voidvCreateInfoDictionary(diagram_type *pDiag, int iWordVersion){ FILE *pOutFile; const char *szTitle, *szAuthor, *szSubject, *szCreator; const char *szCreationDate, *szModDate; fail(pDiag == NULL); fail(pDiag->pOutFile == NULL); fail(iWordVersion < 0); fail(szProducer == NULL || szProducer[0] == '\0'); szTitle = szGetTitle(); szAuthor = szGetAuthor(); szSubject = szGetSubject(); szCreationDate = szGetCreationDate(); szModDate = szGetModDate(); switch (iWordVersion) { case 0: szCreator = "Word for DOS"; break; case 1: szCreator = "WinWord 1.x"; break; case 2: szCreator = "WinWord 2.0"; break; case 4: szCreator = "MacWord 4"; break; case 5: szCreator = "MacWord 5"; break; case 6: szCreator = "Word 6"; break; case 7: szCreator = "Word 7/95"; break; case 8: szCreator = "Word 97 or later"; break; default: szCreator = NULL; break; } pOutFile = pDiag->pOutFile; vSetLocation(2); vFPprintf(pOutFile, "2 0 obj\n"); vFPprintf(pOutFile, "<<\n"); if (szTitle != NULL && szTitle[0] != '\0') { vFPprintf(pOutFile, "/Title (%s)\n", szTitle); } if (szAuthor != NULL && szAuthor[0] != '\0') { vFPprintf(pOutFile, "/Author (%s)\n", szAuthor); } if (szSubject != NULL && szSubject[0] != '\0') { vFPprintf(pOutFile, "/Subject (%s)\n", szSubject); } if (szCreator != NULL && szCreator[0] != '\0') { vFPprintf(pOutFile, "/Creator (%s)\n", szCreator); } vFPprintf(pOutFile, "/Producer (%s %s)\n", szProducer, VERSIONSTRING); if (szCreationDate != NULL && szCreationDate[0] != '\0') { vFPprintf(pOutFile, "/CreationDate (%s)\n", szCreationDate); } if (szModDate != NULL && szModDate[0] != '\0') { vFPprintf(pOutFile, "/ModDate (%s)\n", szModDate); } vFPprintf(pOutFile, ">>\n"); vFPprintf(pOutFile, "endobj\n");} /* end of vCreateInfoDictionary *//* * vAddHdrFtr - add a header or footer */static voidvAddHdrFtr(diagram_type *pDiag, const hdrftr_block_type *pHdrFtrInfo){ output_type *pStart, *pPrev, *pNext; fail(pDiag == NULL); fail(pHdrFtrInfo == NULL); vStartOfParagraphPDF(pDiag, 0); pStart = pHdrFtrInfo->pText; while (pStart != NULL) { pNext = pStart; while (pNext != NULL && (pNext->tNextFree != 1 || (pNext->szStorage[0] != PAR_END && pNext->szStorage[0] != HARD_RETURN))) { pNext = pNext->pNext; } if (pNext == NULL) { if (bOutputContainsText(pStart)) { vAlign2Window(pDiag, pStart, lChar2MilliPoints(DEFAULT_SCREEN_WIDTH), ALIGNMENT_LEFT); } else { vMove2NextLinePDF(pDiag, pStart->usFontSize); } break; } fail(pNext->tNextFree != 1); fail(pNext->szStorage[0] != PAR_END && pNext->szStorage[0] != HARD_RETURN); if (pStart != pNext) { /* There is something to print */ pPrev = pNext->pPrev; fail(pPrev->pNext != pNext); /* Cut the chain */ pPrev->pNext = NULL; if (bOutputContainsText(pStart)) { /* Print it */ vAlign2Window(pDiag, pStart, lChar2MilliPoints(DEFAULT_SCREEN_WIDTH), ALIGNMENT_LEFT); } else { /* Just an empty line */ vMove2NextLinePDF(pDiag, pStart->usFontSize); } /* Repair the chain */ pPrev->pNext = pNext; } if (pNext->szStorage[0] == PAR_END) { vEndOfParagraphPDF(pDiag, pNext->usFontSize, (long)pNext->usFontSize * 200); } pStart = pNext->pNext; }} /* end of vAddHdrFtr *//* * vAddHeader - add a page header */static voidvAddHeader(diagram_type *pDiag){ const hdrftr_block_type *pHdrInfo; const hdrftr_block_type *pFtrInfo; fail(pDiag == NULL); NO_DBG_MSG("vAddHeader"); pHdrInfo = pGetHdrFtrInfo(iSectionIndex, TRUE, odd(iPageCount), bFirstInSection); pFtrInfo = pGetHdrFtrInfo(iSectionIndex, FALSE, odd(iPageCount), bFirstInSection); /* Set the height of the footer of this page */ lFooterHeight = pFtrInfo == NULL ? 0 : pFtrInfo->lHeight; fail(lFooterHeight < 0); if (pHdrInfo == NULL || pHdrInfo->pText == NULL || pHdrInfo->lHeight <= 0) { fail(pHdrInfo != NULL && pHdrInfo->lHeight < 0); fail(pHdrInfo != NULL && pHdrInfo->pText != NULL && pHdrInfo->lHeight == 0); return; } vAddHdrFtr(pDiag, pHdrInfo); DBG_DEC_C(pHdrInfo->lHeight != lPageHeight - PS_TOP_MARGIN - pDiag->lYtop, pHdrInfo->lHeight); DBG_DEC_C(pHdrInfo->lHeight != lPageHeight - PS_TOP_MARGIN - pDiag->lYtop, lPageHeight - PS_TOP_MARGIN - pDiag->lYtop);} /* end of vAddHeader *//*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -