📄 fonts.c
字号:
/* * fonts.c * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL * * Description: * Functions to deal with fonts (generic) */#include <ctype.h>#include <string.h>#include "antiword.h"/* Maximum line length in the font file */#define FONT_LINE_LENGTH 81/* Pitch */#define PITCH_UNKNOWN 0#define PITCH_FIXED 1#define PITCH_VARIABLE 2/* Font Family */#define FAMILY_UNKNOWN 0#define FAMILY_ROMAN 1#define FAMILY_SWISS 2#define FAMILY_MODERN 3#define FAMILY_SCRIPT 4#define FAMILY_DECORATIVE 5/* Font Translation Table */static size_t tFontTableRecords = 0;static font_table_type *pFontTable = NULL;/* * Find the given font in the font table * * returns the index into the FontTable, -1 if not found */intiGetFontByNumber(UCHAR ucWordFontNumber, USHORT usFontStyle){ int iIndex; for (iIndex = 0; iIndex < (int)tFontTableRecords; iIndex++) { if (ucWordFontNumber == pFontTable[iIndex].ucWordFontNumber && usFontStyle == pFontTable[iIndex].usFontStyle && pFontTable[iIndex].szOurFontname[0] != '\0') { return iIndex; } } DBG_DEC(ucWordFontNumber); DBG_HEX(usFontStyle); return -1;} /* end of iGetFontByNumber *//* * szGetOurFontname - Get our font name * * return our font name from the given index, NULL if not found */const char *szGetOurFontname(int iIndex){ if (iIndex < 0 || iIndex >= (int)tFontTableRecords) { return NULL; } return pFontTable[iIndex].szOurFontname;} /* end of szGetOurFontname *//* * Find the given font in the font table * * returns the Word font number, -1 if not found */intiFontname2Fontnumber(const char *szOurFontname, USHORT usFontStyle){ int iIndex; for (iIndex = 0; iIndex < (int)tFontTableRecords; iIndex++) { if (pFontTable[iIndex].usFontStyle == usFontStyle && STREQ(pFontTable[iIndex].szOurFontname, szOurFontname)) { return (int)pFontTable[iIndex].ucWordFontNumber; } } return -1;} /* end of iFontname2Fontnumber *//* * szGetDefaultFont - get the default font that matches the parameters */static const char *szGetDefaultFont(UCHAR ucFFN, int iEmphasis){ UCHAR ucPrq, ucFf; fail(iEmphasis < 0 || iEmphasis > 3); ucPrq = ucFFN & 0x03; ucFf = (ucFFN & 0x70) >> 4; NO_DBG_DEC(ucPrq); NO_DBG_DEC(ucFf); if (ucPrq == PITCH_FIXED) { /* Set to the default monospaced font */ switch (iEmphasis) { case 1: return FONT_MONOSPACED_BOLD; case 2: return FONT_MONOSPACED_ITALIC; case 3: return FONT_MONOSPACED_BOLDITALIC; default: return FONT_MONOSPACED_PLAIN; } } else if (ucFf == FAMILY_ROMAN) { /* Set to the default serif font */ switch (iEmphasis) { case 1: return FONT_SERIF_BOLD; case 2: return FONT_SERIF_ITALIC; case 3: return FONT_SERIF_BOLDITALIC; default: return FONT_SERIF_PLAIN; } } else if (ucFf == FAMILY_SWISS) { /* Set to the default sans serif font */ switch (iEmphasis) { case 1: return FONT_SANS_SERIF_BOLD; case 2: return FONT_SANS_SERIF_ITALIC; case 3: return FONT_SANS_SERIF_BOLDITALIC; default: return FONT_SANS_SERIF_PLAIN; } } else { /* Set to the default default font */ switch (iEmphasis) { case 1: return FONT_SERIF_BOLD; case 2: return FONT_SERIF_ITALIC; case 3: return FONT_SERIF_BOLDITALIC; default: return FONT_SERIF_PLAIN; } }} /* end of szGetDefaultFont *//* * See if the fontname from the Word file matches the fontname from the * font translation file. * If iBytesPerChar is one than aucWord is in ISO-8859-x (Word 2/6/7), * if iBytesPerChar is two than aucWord is in Unicode (Word 8/9/10). */static BOOLbFontEqual(const UCHAR *aucWord, const char *szTable, int iBytesPerChar){ const UCHAR *pucTmp; const char *pcTmp; fail(aucWord == NULL || szTable == NULL); fail(iBytesPerChar != 1 && iBytesPerChar != 2); for (pucTmp = aucWord, pcTmp = szTable; *pucTmp != 0; pucTmp += iBytesPerChar, pcTmp++) { if (ulToUpper((ULONG)*pucTmp) != ulToUpper((ULONG)(UCHAR)*pcTmp)) { return FALSE; } } return *pcTmp == '\0';} /* end of bFontEqual *//* * vFontname2Table - add fontnames to the font table */static voidvFontname2Table(const UCHAR *aucFont, const UCHAR *aucAltFont, int iBytesPerChar, int iEmphasis, UCHAR ucFFN, const char *szWordFont, const char *szOurFont, font_table_type *pFontTableRecord){ BOOL bMatchFound; fail(aucFont == NULL || aucFont[0] == 0); fail(aucAltFont != NULL && aucAltFont[0] == 0); fail(iBytesPerChar != 1 && iBytesPerChar != 2); fail(iEmphasis < 0 || iEmphasis > 3); fail(szWordFont == NULL || szWordFont[0] == '\0'); fail(szOurFont == NULL || szOurFont[0] == '\0'); fail(pFontTableRecord == NULL); bMatchFound = bFontEqual(aucFont, szWordFont, iBytesPerChar); if (!bMatchFound && aucAltFont != NULL) { bMatchFound = bFontEqual(aucAltFont, szWordFont, iBytesPerChar); } if (!bMatchFound && pFontTableRecord->szWordFontname[0] == '\0' && szWordFont[0] == '*' && szWordFont[1] == '\0') { /* * szWordFont contains a "*", so szOurFont will contain the * "default default" font. See if we can do better than that. */ szOurFont = szGetDefaultFont(ucFFN, iEmphasis); bMatchFound = TRUE; } if (bMatchFound) { switch (iBytesPerChar) { case 1: (void)strncpy(pFontTableRecord->szWordFontname, (const char *)aucFont, sizeof(pFontTableRecord->szWordFontname) - 1); break; case 2: (void)unincpy(pFontTableRecord->szWordFontname, aucFont, sizeof(pFontTableRecord->szWordFontname) - 1); break; default: DBG_FIXME(); pFontTableRecord->szWordFontname[0] = '\0'; break; } pFontTableRecord->szWordFontname[ sizeof(pFontTableRecord->szWordFontname) - 1] = '\0'; (void)strncpy(pFontTableRecord->szOurFontname, szOurFont, sizeof(pFontTableRecord->szOurFontname) - 1); pFontTableRecord->szOurFontname[ sizeof(pFontTableRecord->szOurFontname) - 1] = '\0'; NO_DBG_MSG(pFontTableRecord->szWordFontname); NO_DBG_MSG(pFontTableRecord->szOurFontname); pFontTableRecord->ucFFN = ucFFN; pFontTableRecord->ucEmphasis = (UCHAR)iEmphasis; }} /* end of vFontname2Table *//* * vCreateFontTable - Create and initialize the internal font table */static voidvCreateFontTable(void){ font_table_type *pTmp; int iNbr; if (tFontTableRecords == 0) { pFontTable = xfree(pFontTable); return; } /* Create the font table */ pFontTable = xcalloc(tFontTableRecords, sizeof(*pFontTable)); /* Initialize the font table */ for (iNbr = 0, pTmp = pFontTable; pTmp < pFontTable + tFontTableRecords; iNbr++, pTmp++) { pTmp->ucWordFontNumber = (UCHAR)(iNbr / 4); switch (iNbr % 4) { case 0: pTmp->usFontStyle = FONT_REGULAR; break; case 1: pTmp->usFontStyle = FONT_BOLD; break; case 2: pTmp->usFontStyle = FONT_ITALIC; break; case 3: pTmp->usFontStyle = FONT_BOLD|FONT_ITALIC; break; default: DBG_DEC(iNbr); break; } }} /* end of vCreateFontTable *//* * vMinimizeFontTable - make the font table as small as possible */static voidvMinimizeFontTable(void){ font_block_type tFontNext; const style_block_type *pStyle; const font_block_type *pFont; font_table_type *pTmp; int iUnUsed; BOOL bMustAddTableFont; NO_DBG_MSG("vMinimizeFontTable"); if (tFontTableRecords == 0) { pFontTable = xfree(pFontTable); return; } /* See if we must add a font for our tables */ bMustAddTableFont = TRUE;#if 0 DBG_MSG("Before"); DBG_DEC(tFontTableRecords); for (pTmp = pFontTable; pTmp < pFontTable + tFontTableRecords; pTmp++) { DBG_DEC(pTmp->ucWordFontNumber); DBG_HEX(pTmp->usFontStyle); DBG_MSG(pTmp->szWordFontname); DBG_MSG(pTmp->szOurFontname); }#endif /* DEBUG */ /* See which fonts/styles we really need */ /* Default font/style is by definition in use */ pFontTable[0].ucInUse = 1; /* Make InUse 1 for all the fonts/styles that WILL be used */ pFont = NULL; while((pFont = pGetNextFontInfoListItem(pFont)) != NULL) { pTmp = pFontTable + 4 * (int)pFont->ucFontNumber; if (bIsBold(pFont->usFontStyle)) { pTmp++; } if (bIsItalic(pFont->usFontStyle)) { pTmp += 2; } if (pTmp >= pFontTable + tFontTableRecords) { continue; } if (STREQ(pTmp->szOurFontname, TABLE_FONT)) { /* The table font is already present */ bMustAddTableFont = FALSE; } pTmp->ucInUse = 1; } /* Make InUse 1 for all the fonts/styles that MIGHT be used */ pStyle = NULL; while((pStyle = pGetNextStyleInfoListItem(pStyle)) != NULL) { vFillFontFromStylesheet(pStyle->usIstdNext, &tFontNext); vCorrectFontValues(&tFontNext); pTmp = pFontTable + 4 * (int)tFontNext.ucFontNumber; if (bIsBold(tFontNext.usFontStyle)) { pTmp++; } if (bIsItalic(tFontNext.usFontStyle)) { pTmp += 2; } if (pTmp >= pFontTable + tFontTableRecords) { continue; } if (STREQ(pTmp->szOurFontname, TABLE_FONT)) { /* The table font is already present */ bMustAddTableFont = FALSE; } pTmp->ucInUse = 1; } /* Remove the unused font entries from the font table */ iUnUsed = 0; for (pTmp = pFontTable; pTmp < pFontTable + tFontTableRecords; pTmp++) { if (pTmp->ucInUse == 0) { iUnUsed++; continue; } if (iUnUsed > 0) { fail(pTmp - iUnUsed <= pFontTable); *(pTmp - iUnUsed) = *pTmp; } } fail(iUnUsed < 0); fail(tFontTableRecords <= (size_t)iUnUsed); tFontTableRecords -= (size_t)iUnUsed; if (bMustAddTableFont) { pTmp = pFontTable + tFontTableRecords; fail(pTmp <= pFontTable); pTmp->ucWordFontNumber = (pTmp - 1)->ucWordFontNumber + 1; pTmp->usFontStyle = FONT_REGULAR; pTmp->ucInUse = 1; strcpy(pTmp->szWordFontname, "Extra Table Font"); strcpy(pTmp->szOurFontname, TABLE_FONT); tFontTableRecords++; iUnUsed--; } if (iUnUsed > 0) { /* Resize the font table */ pFontTable = xrealloc(pFontTable, tFontTableRecords * sizeof(*pFontTable)); }#if defined(DEBUG) DBG_MSG("After"); DBG_DEC(tFontTableRecords); for (pTmp = pFontTable; pTmp < pFontTable + tFontTableRecords; pTmp++) { DBG_DEC(pTmp->ucWordFontNumber); DBG_HEX(pTmp->usFontStyle); DBG_MSG(pTmp->szWordFontname); DBG_MSG(pTmp->szOurFontname); }#endif /* DEBUG */} /* end of vMinimizeFontTable *//* * bReadFontFile - read and check a line from the font translation file * * returns TRUE when a correct line has been read, otherwise FALSE */static BOOLbReadFontFile(FILE *pFontTableFile, char *szWordFont, int *piItalic, int *piBold, char *szOurFont, int *piSpecial){ char *pcTmp; int iFields; char szLine[FONT_LINE_LENGTH]; fail(szWordFont == NULL || szOurFont == NULL); fail(piItalic == NULL || piBold == NULL || piSpecial == NULL); while (fgets(szLine, (int)sizeof(szLine), pFontTableFile) != NULL) { if (szLine[0] == '#' || szLine[0] == '\n' || szLine[0] == '\r') { continue; } iFields = sscanf(szLine, "%[^,],%d,%d,%1s%[^,],%d", szWordFont, piItalic, piBold, &szOurFont[0], &szOurFont[1], piSpecial); if (iFields != 6) { pcTmp = strchr(szLine, '\r'); if (pcTmp != NULL) { *pcTmp = '\0'; } pcTmp = strchr(szLine, '\n'); if (pcTmp != NULL) { *pcTmp = '\0'; } DBG_DEC(iFields); werr(0, "Syntax error in: '%s'", szLine); continue; } if (strlen(szWordFont) >= sizeof(pFontTable[0].szWordFontname)) { werr(0, "Word fontname too long: '%s'", szWordFont); continue; } if (strlen(szOurFont) >= sizeof(pFontTable[0].szOurFontname)) { werr(0, "Local fontname too long: '%s'", szOurFont); continue; } /* The current line passed all the tests */ return TRUE; } return FALSE;} /* end of bReadFontFile *//* * vCreate0FontTable - create a font table from Word for DOS */voidvCreate0FontTable(void){ FILE *pFontTableFile; font_table_type *pTmp; UCHAR *aucFont; int iBold, iItalic, iSpecial, iEmphasis, iFtc; UCHAR ucPrq, ucFf, ucFFN; char szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH]; tFontTableRecords = 0; pFontTable = xfree(pFontTable); pFontTableFile = pOpenFontTableFile(); if (pFontTableFile == NULL) { /* No translation table file, no translation table */ return; } /* Get the maximum number of entries in the font table */ tFontTableRecords = 64; tFontTableRecords *= 4; /* Plain, Bold, Italic and Bold/italic */ tFontTableRecords++; /* One extra for the table-font */ vCreateFontTable(); /* Read the font translation file */ iItalic = 0; iBold = 0; iSpecial = 0; while (bReadFontFile(pFontTableFile, szWordFont, &iItalic, &iBold, szOurFont, &iSpecial)) { iEmphasis = 0; if (iBold != 0) { iEmphasis++; } if (iItalic != 0) { iEmphasis += 2; } for (iFtc = 0, pTmp = pFontTable + iEmphasis; pTmp < pFontTable + tFontTableRecords; iFtc++, pTmp += 4) { if (iFtc >= 16 && iFtc <= 55) { ucPrq = PITCH_VARIABLE; ucFf = FAMILY_ROMAN; aucFont = (UCHAR *)"Times"; } else { ucPrq = PITCH_FIXED; ucFf = FAMILY_MODERN; aucFont = (UCHAR *)"Courier"; } ucFFN = (ucFf << 4) | ucPrq;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -