examples/PIPS/antiword/src/fonts.c

00001 /*
00002  * fonts.c
00003  * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
00004  *
00005  * Description:
00006  * Functions to deal with fonts (generic)
00007  */
00008 
00009 #include <ctype.h>
00010 #include <string.h>
00011 #include "antiword.h"
00012 
00013 /* Maximum line length in the font file */
00014 #define FONT_LINE_LENGTH        81
00015 
00016 /* Pitch */
00017 #define PITCH_UNKNOWN           0
00018 #define PITCH_FIXED             1
00019 #define PITCH_VARIABLE          2
00020 
00021 /* Font Family */
00022 #define FAMILY_UNKNOWN          0
00023 #define FAMILY_ROMAN            1
00024 #define FAMILY_SWISS            2
00025 #define FAMILY_MODERN           3
00026 #define FAMILY_SCRIPT           4
00027 #define FAMILY_DECORATIVE       5
00028 
00029 /* Font Translation Table */
00030 static size_t           tFontTableRecords = 0;
00031 static font_table_type  *pFontTable = NULL;
00032 
00033 /*
00034  * Find the given font in the font table
00035  *
00036  * returns the index into the FontTable, -1 if not found
00037  */
00038 int
00039 iGetFontByNumber(UCHAR ucWordFontNumber, USHORT usFontStyle)
00040 {
00041         int     iIndex;
00042 
00043         for (iIndex = 0; iIndex < (int)tFontTableRecords; iIndex++) {
00044                 if (ucWordFontNumber == pFontTable[iIndex].ucWordFontNumber &&
00045                     usFontStyle == pFontTable[iIndex].usFontStyle &&
00046                     pFontTable[iIndex].szOurFontname[0] != '\0') {
00047                         return iIndex;
00048                 }
00049         }
00050         DBG_DEC(ucWordFontNumber);
00051         DBG_HEX(usFontStyle);
00052         return -1;
00053 } /* end of iGetFontByNumber */
00054 
00055 /*
00056  * szGetOurFontname - Get our font name
00057  *
00058  * return our font name from the given index, NULL if not found
00059  */
00060 const char *
00061 szGetOurFontname(int iIndex)
00062 {
00063         if (iIndex < 0 || iIndex >= (int)tFontTableRecords) {
00064                 return NULL;
00065         }
00066         return pFontTable[iIndex].szOurFontname;
00067 } /* end of szGetOurFontname */
00068 
00069 /*
00070  * Find the given font in the font table
00071  *
00072  * returns the Word font number, -1 if not found
00073  */
00074 int
00075 iFontname2Fontnumber(const char *szOurFontname, USHORT usFontStyle)
00076 {
00077         int     iIndex;
00078 
00079         for (iIndex = 0; iIndex < (int)tFontTableRecords; iIndex++) {
00080                 if (pFontTable[iIndex].usFontStyle == usFontStyle &&
00081                     STREQ(pFontTable[iIndex].szOurFontname, szOurFontname)) {
00082                         return (int)pFontTable[iIndex].ucWordFontNumber;
00083                 }
00084         }
00085         return -1;
00086 } /* end of iFontname2Fontnumber */
00087 
00088 /*
00089  * szGetDefaultFont - get the default font that matches the parameters
00090  */
00091 static const char *
00092 szGetDefaultFont(UCHAR ucFFN, int iEmphasis)
00093 {
00094         UCHAR   ucPrq, ucFf;
00095 
00096         fail(iEmphasis < 0 || iEmphasis > 3);
00097 
00098         ucPrq = ucFFN & 0x03;
00099         ucFf = (ucFFN & 0x70) >> 4;
00100         NO_DBG_DEC(ucPrq);
00101         NO_DBG_DEC(ucFf);
00102         if (ucPrq == PITCH_FIXED) {
00103                 /* Set to the default monospaced font */
00104                 switch (iEmphasis) {
00105                 case 1: return FONT_MONOSPACED_BOLD;
00106                 case 2: return FONT_MONOSPACED_ITALIC;
00107                 case 3: return FONT_MONOSPACED_BOLDITALIC;
00108                 default: return FONT_MONOSPACED_PLAIN;
00109                 }
00110         } else if (ucFf == FAMILY_ROMAN) {
00111                 /* Set to the default serif font */
00112                 switch (iEmphasis) {
00113                 case 1: return FONT_SERIF_BOLD;
00114                 case 2: return FONT_SERIF_ITALIC;
00115                 case 3: return FONT_SERIF_BOLDITALIC;
00116                 default: return FONT_SERIF_PLAIN;
00117                 }
00118         } else if (ucFf == FAMILY_SWISS) {
00119                 /* Set to the default sans serif font */
00120                 switch (iEmphasis) {
00121                 case 1: return FONT_SANS_SERIF_BOLD;
00122                 case 2: return FONT_SANS_SERIF_ITALIC;
00123                 case 3: return FONT_SANS_SERIF_BOLDITALIC;
00124                 default: return FONT_SANS_SERIF_PLAIN;
00125                 }
00126         } else {
00127                 /* Set to the default default font */
00128                 switch (iEmphasis) {
00129                 case 1: return FONT_SERIF_BOLD;
00130                 case 2: return FONT_SERIF_ITALIC;
00131                 case 3: return FONT_SERIF_BOLDITALIC;
00132                 default: return FONT_SERIF_PLAIN;
00133                 }
00134         }
00135 } /* end of szGetDefaultFont */
00136 
00137 /*
00138  * See if the fontname from the Word file matches the fontname from the
00139  * font translation file.
00140  * If iBytesPerChar is one than aucWord is in ISO-8859-x (Word 2/6/7),
00141  * if iBytesPerChar is two than aucWord is in Unicode (Word 8/9/10).
00142  */
00143 static BOOL
00144 bFontEqual(const UCHAR *aucWord, const char *szTable, int iBytesPerChar)
00145 {
00146         const UCHAR     *pucTmp;
00147         const char      *pcTmp;
00148 
00149         fail(aucWord == NULL || szTable == NULL);
00150         fail(iBytesPerChar != 1 && iBytesPerChar != 2);
00151 
00152         for (pucTmp = aucWord, pcTmp = szTable;
00153              *pucTmp != 0;
00154              pucTmp += iBytesPerChar, pcTmp++) {
00155                 if (ulToUpper((ULONG)*pucTmp) !=
00156                     ulToUpper((ULONG)(UCHAR)*pcTmp)) {
00157                         return FALSE;
00158                 }
00159         }
00160         return *pcTmp == '\0';
00161 } /* end of bFontEqual */
00162 
00163 /*
00164  * vFontname2Table - add fontnames to the font table
00165  */
00166 static void
00167 vFontname2Table(const UCHAR *aucFont, const UCHAR *aucAltFont,
00168         int iBytesPerChar, int iEmphasis, UCHAR ucFFN,
00169         const char *szWordFont, const char *szOurFont,
00170         font_table_type *pFontTableRecord)
00171 {
00172         BOOL    bMatchFound;
00173 
00174         fail(aucFont == NULL || aucFont[0] == 0);
00175         fail(aucAltFont != NULL && aucAltFont[0] == 0);
00176         fail(iBytesPerChar != 1 && iBytesPerChar != 2);
00177         fail(iEmphasis < 0 || iEmphasis > 3);
00178         fail(szWordFont == NULL || szWordFont[0] == '\0');
00179         fail(szOurFont == NULL || szOurFont[0] == '\0');
00180         fail(pFontTableRecord == NULL);
00181 
00182         bMatchFound = bFontEqual(aucFont, szWordFont, iBytesPerChar);
00183 
00184         if (!bMatchFound && aucAltFont != NULL) {
00185                 bMatchFound = bFontEqual(aucAltFont, szWordFont, iBytesPerChar);
00186         }
00187 
00188         if (!bMatchFound &&
00189             pFontTableRecord->szWordFontname[0] == '\0' &&
00190             szWordFont[0] == '*' &&
00191             szWordFont[1] == '\0') {
00192                 /*
00193                  * szWordFont contains a "*", so szOurFont will contain the
00194                  * "default default" font. See if we can do better than that.
00195                  */
00196                 szOurFont = szGetDefaultFont(ucFFN, iEmphasis);
00197                 bMatchFound = TRUE;
00198         }
00199 
00200         if (bMatchFound) {
00201                 switch (iBytesPerChar) {
00202                 case 1:
00203                         (void)strncpy(pFontTableRecord->szWordFontname,
00204                                 (const char *)aucFont,
00205                                 sizeof(pFontTableRecord->szWordFontname) - 1);
00206                         break;
00207                 case 2:
00208                         (void)unincpy(pFontTableRecord->szWordFontname,
00209                                 aucFont,
00210                                 sizeof(pFontTableRecord->szWordFontname) - 1);
00211                         break;
00212                 default:
00213                         DBG_FIXME();
00214                         pFontTableRecord->szWordFontname[0] = '\0';
00215                         break;
00216                 }
00217                 pFontTableRecord->szWordFontname[
00218                         sizeof(pFontTableRecord->szWordFontname) - 1] = '\0';
00219                 (void)strncpy(pFontTableRecord->szOurFontname, szOurFont,
00220                         sizeof(pFontTableRecord->szOurFontname) - 1);
00221                 pFontTableRecord->szOurFontname[
00222                         sizeof(pFontTableRecord->szOurFontname) - 1] = '\0';
00223                 NO_DBG_MSG(pFontTableRecord->szWordFontname);
00224                 NO_DBG_MSG(pFontTableRecord->szOurFontname);
00225                 pFontTableRecord->ucFFN = ucFFN;
00226                 pFontTableRecord->ucEmphasis = (UCHAR)iEmphasis;
00227         }
00228 } /* end of vFontname2Table */
00229 
00230 /*
00231  * vCreateFontTable - Create and initialize the internal font table
00232  */
00233 static void
00234 vCreateFontTable(void)
00235 {
00236         font_table_type *pTmp;
00237         int     iNbr;
00238 
00239         if (tFontTableRecords == 0) {
00240                 pFontTable = xfree(pFontTable);
00241                 return;
00242         }
00243 
00244         /* Create the font table */
00245         pFontTable = xcalloc(tFontTableRecords, sizeof(*pFontTable));
00246 
00247         /* Initialize the font table */
00248         for (iNbr = 0, pTmp = pFontTable;
00249              pTmp < pFontTable + tFontTableRecords;
00250              iNbr++, pTmp++) {
00251                 pTmp->ucWordFontNumber = (UCHAR)(iNbr / 4);
00252                 switch (iNbr % 4) {
00253                 case 0:
00254                         pTmp->usFontStyle = FONT_REGULAR;
00255                         break;
00256                 case 1:
00257                         pTmp->usFontStyle = FONT_BOLD;
00258                         break;
00259                 case 2:
00260                         pTmp->usFontStyle = FONT_ITALIC;
00261                         break;
00262                 case 3:
00263                         pTmp->usFontStyle = FONT_BOLD|FONT_ITALIC;
00264                         break;
00265                 default:
00266                         DBG_DEC(iNbr);
00267                         break;
00268                 }
00269         }
00270 } /* end of vCreateFontTable */
00271 
00272 /*
00273  * vMinimizeFontTable - make the font table as small as possible
00274  */
00275 static void
00276 vMinimizeFontTable(void)
00277 {
00278         font_block_type         tFontNext;
00279         const style_block_type  *pStyle;
00280         const font_block_type   *pFont;
00281         font_table_type         *pTmp;
00282         int     iUnUsed;
00283         BOOL    bMustAddTableFont;
00284 
00285         NO_DBG_MSG("vMinimizeFontTable");
00286 
00287         if (tFontTableRecords == 0) {
00288                 pFontTable = xfree(pFontTable);
00289                 return;
00290         }
00291 
00292         /* See if we must add a font for our tables */
00293         bMustAddTableFont = TRUE;
00294 
00295 #if 0
00296         DBG_MSG("Before");
00297         DBG_DEC(tFontTableRecords);
00298         for (pTmp = pFontTable;
00299              pTmp < pFontTable + tFontTableRecords;
00300              pTmp++) {
00301                 DBG_DEC(pTmp->ucWordFontNumber);
00302                 DBG_HEX(pTmp->usFontStyle);
00303                 DBG_MSG(pTmp->szWordFontname);
00304                 DBG_MSG(pTmp->szOurFontname);
00305         }
00306 #endif /* DEBUG */
00307 
00308         /* See which fonts/styles we really need */
00309 
00310         /* Default font/style is by definition in use */
00311         pFontTable[0].ucInUse = 1;
00312 
00313         /* Make InUse 1 for all the fonts/styles that WILL be used */
00314         pFont = NULL;
00315         while((pFont = pGetNextFontInfoListItem(pFont)) != NULL) {
00316                 pTmp = pFontTable + 4 * (int)pFont->ucFontNumber;
00317                 if (bIsBold(pFont->usFontStyle)) {
00318                         pTmp++;
00319                 }
00320                 if (bIsItalic(pFont->usFontStyle)) {
00321                         pTmp += 2;
00322                 }
00323                 if (pTmp >= pFontTable + tFontTableRecords) {
00324                         continue;
00325                 }
00326                 if (STREQ(pTmp->szOurFontname, TABLE_FONT)) {
00327                         /* The table font is already present */
00328                         bMustAddTableFont = FALSE;
00329                 }
00330                 pTmp->ucInUse = 1;
00331         }
00332 
00333         /* Make InUse 1 for all the fonts/styles that MIGHT be used */
00334         pStyle = NULL;
00335         while((pStyle = pGetNextStyleInfoListItem(pStyle)) != NULL) {
00336                 vFillFontFromStylesheet(pStyle->usIstdNext, &tFontNext);
00337                 vCorrectFontValues(&tFontNext);
00338                 pTmp = pFontTable + 4 * (int)tFontNext.ucFontNumber;
00339                 if (bIsBold(tFontNext.usFontStyle)) {
00340                         pTmp++;
00341                 }
00342                 if (bIsItalic(tFontNext.usFontStyle)) {
00343                         pTmp += 2;
00344                 }
00345                 if (pTmp >= pFontTable + tFontTableRecords) {
00346                         continue;
00347                 }
00348                 if (STREQ(pTmp->szOurFontname, TABLE_FONT)) {
00349                         /* The table font is already present */
00350                         bMustAddTableFont = FALSE;
00351                 }
00352                 pTmp->ucInUse = 1;
00353         }
00354 
00355         /* Remove the unused font entries from the font table */
00356         iUnUsed = 0;
00357         for (pTmp = pFontTable;
00358              pTmp < pFontTable + tFontTableRecords;
00359              pTmp++) {
00360                 if (pTmp->ucInUse == 0) {
00361                         iUnUsed++;
00362                         continue;
00363                 }
00364                 if (iUnUsed > 0) {
00365                         fail(pTmp - iUnUsed <= pFontTable);
00366                         *(pTmp - iUnUsed) = *pTmp;
00367                 }
00368         }
00369         fail(iUnUsed < 0);
00370         fail(tFontTableRecords <= (size_t)iUnUsed);
00371         tFontTableRecords -= (size_t)iUnUsed;
00372 
00373         if (bMustAddTableFont) {
00374                 pTmp = pFontTable + tFontTableRecords;
00375                 fail(pTmp <= pFontTable);
00376                 pTmp->ucWordFontNumber = (pTmp - 1)->ucWordFontNumber + 1;
00377                 pTmp->usFontStyle = FONT_REGULAR;
00378                 pTmp->ucInUse = 1;
00379                 strcpy(pTmp->szWordFontname, "Extra Table Font");
00380                 strcpy(pTmp->szOurFontname, TABLE_FONT);
00381                 tFontTableRecords++;
00382                 iUnUsed--;
00383         }
00384         if (iUnUsed > 0) {
00385                 /* Resize the font table */
00386                 pFontTable = xrealloc(pFontTable,
00387                                 tFontTableRecords * sizeof(*pFontTable));
00388         }
00389 #if defined(DEBUG)
00390         DBG_MSG("After");
00391         DBG_DEC(tFontTableRecords);
00392         for (pTmp = pFontTable;
00393              pTmp < pFontTable + tFontTableRecords;
00394              pTmp++) {
00395                 DBG_DEC(pTmp->ucWordFontNumber);
00396                 DBG_HEX(pTmp->usFontStyle);
00397                 DBG_MSG(pTmp->szWordFontname);
00398                 DBG_MSG(pTmp->szOurFontname);
00399         }
00400 #endif /* DEBUG */
00401 } /* end of vMinimizeFontTable */
00402 
00403 /*
00404  * bReadFontFile - read and check a line from the font translation file
00405  *
00406  * returns TRUE when a correct line has been read, otherwise FALSE
00407  */
00408 static BOOL
00409 bReadFontFile(FILE *pFontTableFile, char *szWordFont,
00410         int *piItalic, int *piBold, char *szOurFont, int *piSpecial)
00411 {
00412         char    *pcTmp;
00413         int     iFields;
00414         char    szLine[FONT_LINE_LENGTH];
00415 
00416         fail(szWordFont == NULL || szOurFont == NULL);
00417         fail(piItalic == NULL || piBold == NULL || piSpecial == NULL);
00418 
00419         while (fgets(szLine, (int)sizeof(szLine), pFontTableFile) != NULL) {
00420                 if (szLine[0] == '#' ||
00421                     szLine[0] == '\n' ||
00422                     szLine[0] == '\r') {
00423                         continue;
00424                 }
00425                 iFields = sscanf(szLine, "%[^,],%d,%d,%1s%[^,],%d",
00426                         szWordFont, piItalic, piBold,
00427                         &szOurFont[0], &szOurFont[1], piSpecial);
00428                 if (iFields != 6) {
00429                         pcTmp = strchr(szLine, '\r');
00430                         if (pcTmp != NULL) {
00431                                 *pcTmp = '\0';
00432                         }
00433                         pcTmp = strchr(szLine, '\n');
00434                         if (pcTmp != NULL) {
00435                                 *pcTmp = '\0';
00436                         }
00437                         DBG_DEC(iFields);
00438                         werr(0, "Syntax error in: '%s'", szLine);
00439                         continue;
00440                 }
00441                 if (strlen(szWordFont) >=
00442                                 sizeof(pFontTable[0].szWordFontname)) {
00443                         werr(0, "Word fontname too long: '%s'", szWordFont);
00444                         continue;
00445                 }
00446                 if (strlen(szOurFont) >=
00447                                 sizeof(pFontTable[0].szOurFontname)) {
00448                         werr(0, "Local fontname too long: '%s'", szOurFont);
00449                         continue;
00450                 }
00451                 /* The current line passed all the tests */
00452                 return TRUE;
00453         }
00454         return FALSE;
00455 } /* end of bReadFontFile */
00456 
00457 /*
00458  * vCreate0FontTable - create a font table from Word for DOS
00459  */
00460 void
00461 vCreate0FontTable(void)
00462 {
00463         FILE    *pFontTableFile;
00464         font_table_type *pTmp;
00465         UCHAR   *aucFont;
00466         int     iBold, iItalic, iSpecial, iEmphasis, iFtc;
00467         UCHAR   ucPrq, ucFf, ucFFN;
00468         char    szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
00469 
00470         tFontTableRecords = 0;
00471         pFontTable = xfree(pFontTable);
00472 
00473         pFontTableFile = pOpenFontTableFile();
00474         if (pFontTableFile == NULL) {
00475                 /* No translation table file, no translation table */
00476                 return;
00477         }
00478 
00479         /* Get the maximum number of entries in the font table */
00480         tFontTableRecords = 64;
00481         tFontTableRecords *= 4; /* Plain, Bold, Italic and Bold/italic */
00482         tFontTableRecords++;    /* One extra for the table-font */
00483         vCreateFontTable();
00484 
00485         /* Read the font translation file */
00486         iItalic = 0;
00487         iBold = 0;
00488         iSpecial = 0;
00489         while (bReadFontFile(pFontTableFile, szWordFont,
00490                         &iItalic, &iBold, szOurFont, &iSpecial)) {
00491                 iEmphasis = 0;
00492                 if (iBold != 0) {
00493                         iEmphasis++;
00494                 }
00495                 if (iItalic != 0) {
00496                         iEmphasis += 2;
00497                 }
00498                 for (iFtc = 0, pTmp = pFontTable + iEmphasis;
00499                      pTmp < pFontTable + tFontTableRecords;
00500                      iFtc++, pTmp += 4) {
00501                         if (iFtc >= 16 && iFtc <= 55) {
00502                                 ucPrq = PITCH_VARIABLE;
00503                                 ucFf = FAMILY_ROMAN;
00504                                 aucFont = (UCHAR *)"Times";
00505                         } else {
00506                                 ucPrq = PITCH_FIXED;
00507                                 ucFf = FAMILY_MODERN;
00508                                 aucFont = (UCHAR *)"Courier";
00509                         }
00510                         ucFFN = (ucFf << 4) | ucPrq;
00511                         vFontname2Table(aucFont, NULL, 1, iEmphasis,
00512                                         ucFFN, szWordFont, szOurFont, pTmp);
00513                 }
00514         }
00515         (void)fclose(pFontTableFile);
00516         vMinimizeFontTable();
00517 } /* end of vCreate0FontTable */
00518 
00519 /*
00520  * vCreate2FontTable - create a font table from WinWord 1/2
00521  */
00522 void
00523 vCreate2FontTable(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
00524 {
00525         FILE    *pFontTableFile;
00526         font_table_type *pTmp;
00527         UCHAR   *aucFont;
00528         UCHAR   *aucBuffer;
00529         ULONG   ulBeginFontInfo;
00530         size_t  tFontInfoLen;
00531         int     iPos, iOff, iRecLen;
00532         int     iBold, iItalic, iSpecial, iEmphasis;
00533         UCHAR   ucFFN;
00534         char    szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
00535 
00536         fail(pFile == NULL || aucHeader == NULL);
00537         fail(iWordVersion != 1 && iWordVersion != 2);
00538 
00539         tFontTableRecords = 0;
00540         pFontTable = xfree(pFontTable);
00541 
00542         pFontTableFile = pOpenFontTableFile();
00543         if (pFontTableFile == NULL) {
00544                 /* No translation table file, no translation table */
00545                 return;
00546         }
00547 
00548         ulBeginFontInfo = ulGetLong(0xb2, aucHeader); /* fcSttbfffn */
00549         DBG_HEX(ulBeginFontInfo);
00550         tFontInfoLen = (size_t)usGetWord(0xb6, aucHeader); /* cbSttbfffn */
00551         DBG_DEC(tFontInfoLen);
00552 
00553         if (ulBeginFontInfo > (ULONG)LONG_MAX || tFontInfoLen == 0) {
00554                 /* Don't ask me why this is needed */
00555                 DBG_HEX_C(tFontInfoLen != 0, ulBeginFontInfo);
00556                 (void)fclose(pFontTableFile);
00557                 return;
00558         }
00559 
00560         aucBuffer = xmalloc(tFontInfoLen);
00561         if (!bReadBytes(aucBuffer, tFontInfoLen, ulBeginFontInfo, pFile)) {
00562                 aucBuffer = xfree(aucBuffer);
00563                 (void)fclose(pFontTableFile);
00564                 return;
00565         }
00566         NO_DBG_PRINT_BLOCK(aucBuffer, tFontInfoLen);
00567         DBG_DEC(usGetWord(0, aucBuffer));
00568 
00569         /* Compute the maximum number of entries in the font table */
00570         if (iWordVersion == 1) {
00571                 fail(tFontInfoLen < 2);
00572                 /* WinWord 1 has three implicit fonts */
00573                 tFontTableRecords = 3;
00574                 iOff = 2;
00575         } else {
00576                 fail(tFontInfoLen < 6);
00577                 /* WinWord 2 and up have no implicit fonts */
00578                 tFontTableRecords = 0;
00579                 iOff = 3;
00580         }
00581         iPos = 2;
00582         while (iPos + iOff < (int)tFontInfoLen) {
00583                 iRecLen = (int)ucGetByte(iPos, aucBuffer);
00584                 NO_DBG_DEC(iRecLen);
00585                 NO_DBG_MSG(aucBuffer + iPos + iOff);
00586                 iPos += iRecLen + 1;
00587                 tFontTableRecords++;
00588         }
00589         tFontTableRecords *= 4; /* Plain, Bold, Italic and Bold/Italic */
00590         tFontTableRecords++;    /* One extra for the table-font */
00591         vCreateFontTable();
00592 
00593         /* Add the tree implicit fonts (in four variations) */
00594         if (iWordVersion == 1) {
00595                 fail(tFontTableRecords < 13);
00596                 vFontname2Table((UCHAR *)"Tms Rmn", NULL, 1, 0,
00597                         (UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
00598                         "*", "Times-Roman", pFontTable + 0);
00599                 vFontname2Table((UCHAR *)"Tms Rmn", NULL, 1, 1,
00600                         (UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
00601                         "*", "Times-Bold", pFontTable + 1);
00602                 vFontname2Table((UCHAR *)"Tms Rmn", NULL, 1, 2,
00603                         (UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
00604                         "*", "Times-Italic", pFontTable + 2);
00605                 vFontname2Table((UCHAR *)"Tms Rmn", NULL, 1, 3,
00606                         (UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
00607                         "*", "Times-BoldItalic", pFontTable + 3);
00608                 vFontname2Table((UCHAR *)"Symbol", NULL, 1, 0,
00609                         (UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
00610                         "*", "Times-Roman", pFontTable + 4);
00611                 vFontname2Table((UCHAR *)"Symbol", NULL, 1, 1,
00612                         (UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
00613                         "*", "Times-Bold", pFontTable + 5);
00614                 vFontname2Table((UCHAR *)"Symbol", NULL, 1, 2,
00615                         (UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
00616                         "*", "Times-Italic", pFontTable + 6);
00617                 vFontname2Table((UCHAR *)"Symbol", NULL, 1, 3,
00618                         (UCHAR)((FAMILY_ROMAN << 4) | PITCH_VARIABLE),
00619                         "*", "Times-BoldItalic", pFontTable + 7);
00620                 vFontname2Table((UCHAR *)"Helv", NULL, 1, 0,
00621                         (UCHAR)((FAMILY_SWISS << 4) | PITCH_VARIABLE),
00622                         "*", "Helvetica", pFontTable + 8);
00623                 vFontname2Table((UCHAR *)"Helv", NULL, 1, 1,
00624                         (UCHAR)((FAMILY_SWISS << 4) | PITCH_VARIABLE),
00625                         "*", "Helvetica-Bold", pFontTable + 9);
00626                 vFontname2Table((UCHAR *)"Helv", NULL, 1, 2,
00627                         (UCHAR)((FAMILY_SWISS << 4) | PITCH_VARIABLE),
00628                         "*", "Helvetica-Oblique", pFontTable + 10);
00629                 vFontname2Table((UCHAR *)"Helv", NULL, 1, 3,
00630                         (UCHAR)((FAMILY_SWISS << 4) | PITCH_VARIABLE),
00631                         "*", "Helvetica-BoldOblique", pFontTable + 11);
00632         }
00633 
00634         /* Read the font translation file */
00635         iItalic = 0;
00636         iBold = 0;
00637         iSpecial = 0;
00638         while (bReadFontFile(pFontTableFile, szWordFont,
00639                         &iItalic, &iBold, szOurFont, &iSpecial)) {
00640                 iEmphasis = 0;
00641                 if (iBold != 0) {
00642                         iEmphasis++;
00643                 }
00644                 if (iItalic != 0) {
00645                         iEmphasis += 2;
00646                 }
00647                 pTmp = pFontTable + iEmphasis;
00648                 iPos = 2;
00649                 while (iPos + iOff < (int)tFontInfoLen) {
00650                         iRecLen = (int)ucGetByte(iPos, aucBuffer);
00651                         ucFFN = ucGetByte(iPos + 1, aucBuffer);
00652                         aucFont = aucBuffer + iPos + iOff;
00653                         vFontname2Table(aucFont, NULL, 1, iEmphasis,
00654                                         ucFFN, szWordFont, szOurFont, pTmp);
00655                         pTmp += 4;
00656                         iPos += iRecLen + 1;
00657                 }
00658         }
00659         (void)fclose(pFontTableFile);
00660         aucBuffer = xfree(aucBuffer);
00661         vMinimizeFontTable();
00662 } /* end of vCreate2FontTable */
00663 
00664 /*
00665  * vCreate6FontTable - create a font table from Word 6/7
00666  */
00667 void
00668 vCreate6FontTable(FILE *pFile, ULONG ulStartBlock,
00669         const ULONG *aulBBD, size_t tBBDLen,
00670         const UCHAR *aucHeader)
00671 {
00672         FILE    *pFontTableFile;
00673         font_table_type *pTmp;
00674         UCHAR   *aucFont, *aucAltFont;
00675         UCHAR   *aucBuffer;
00676         ULONG   ulBeginFontInfo;
00677         size_t  tFontInfoLen;
00678         int     iPos, iRecLen, iOffsetAltName;
00679         int     iBold, iItalic, iSpecial, iEmphasis;
00680         UCHAR   ucFFN;
00681         char    szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
00682 
00683         fail(pFile == NULL || aucHeader == NULL);
00684         fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
00685         fail(aulBBD == NULL);
00686 
00687         tFontTableRecords = 0;
00688         pFontTable = xfree(pFontTable);
00689 
00690         pFontTableFile = pOpenFontTableFile();
00691         if (pFontTableFile == NULL) {
00692                 /* No translation table file, no translation table */
00693                 return;
00694         }
00695 
00696         ulBeginFontInfo = ulGetLong(0xd0, aucHeader); /* fcSttbfffn */
00697         DBG_HEX(ulBeginFontInfo);
00698         tFontInfoLen = (size_t)ulGetLong(0xd4, aucHeader); /* lcbSttbfffn */
00699         DBG_DEC(tFontInfoLen);
00700         fail(tFontInfoLen < 9);
00701 
00702         aucBuffer = xmalloc(tFontInfoLen);
00703         if (!bReadBuffer(pFile, ulStartBlock,
00704                         aulBBD, tBBDLen, BIG_BLOCK_SIZE,
00705                         aucBuffer, ulBeginFontInfo, tFontInfoLen)) {
00706                 aucBuffer = xfree(aucBuffer);
00707                 (void)fclose(pFontTableFile);
00708                 return;
00709         }
00710         DBG_DEC(usGetWord(0, aucBuffer));
00711 
00712         /* Compute the maximum number of entries in the font table */
00713         tFontTableRecords = 0;
00714         iPos = 2;
00715         while (iPos + 6 < (int)tFontInfoLen) {
00716                 iRecLen = (int)ucGetByte(iPos, aucBuffer);
00717                 NO_DBG_DEC(iRecLen);
00718                 iOffsetAltName = (int)ucGetByte(iPos + 5, aucBuffer);
00719                 NO_DBG_MSG(aucBuffer + iPos + 6);
00720                 NO_DBG_MSG_C(iOffsetAltName > 0,
00721                                 aucBuffer + iPos + 6 + iOffsetAltName);
00722                 iPos += iRecLen + 1;
00723                 tFontTableRecords++;
00724         }
00725         tFontTableRecords *= 4; /* Plain, Bold, Italic and Bold/italic */
00726         tFontTableRecords++;    /* One extra for the table-font */
00727         vCreateFontTable();
00728 
00729         /* Read the font translation file */
00730         iItalic = 0;
00731         iBold = 0;
00732         iSpecial = 0;
00733         while (bReadFontFile(pFontTableFile, szWordFont,
00734                         &iItalic, &iBold, szOurFont, &iSpecial)) {
00735                 iEmphasis = 0;
00736                 if (iBold != 0) {
00737                         iEmphasis++;
00738                 }
00739                 if (iItalic != 0) {
00740                         iEmphasis += 2;
00741                 }
00742                 pTmp = pFontTable + iEmphasis;
00743                 iPos = 2;
00744                 while (iPos + 6 < (int)tFontInfoLen) {
00745                         iRecLen = (int)ucGetByte(iPos, aucBuffer);
00746                         ucFFN = ucGetByte(iPos + 1, aucBuffer);
00747                         aucFont = aucBuffer + iPos + 6;
00748                         iOffsetAltName = (int)ucGetByte(iPos + 5, aucBuffer);
00749                         if (iOffsetAltName <= 0) {
00750                                 aucAltFont = NULL;
00751                         } else {
00752                                 aucAltFont = aucFont + iOffsetAltName;
00753                                 NO_DBG_MSG(aucFont);
00754                                 NO_DBG_MSG(aucAltFont);
00755                         }
00756                         vFontname2Table(aucFont, aucAltFont, 1, iEmphasis,
00757                                         ucFFN, szWordFont, szOurFont, pTmp);
00758                         pTmp += 4;
00759                         iPos += iRecLen + 1;
00760                 }
00761         }
00762         (void)fclose(pFontTableFile);
00763         aucBuffer = xfree(aucBuffer);
00764         vMinimizeFontTable();
00765 } /* end of vCreate6FontTable */
00766 
00767 /*
00768  * vCreate8FontTable - create a font table from Word 8/9/10
00769  */
00770 void
00771 vCreate8FontTable(FILE *pFile, const pps_info_type *pPPS,
00772         const ULONG *aulBBD, size_t tBBDLen,
00773         const ULONG *aulSBD, size_t tSBDLen,
00774         const UCHAR *aucHeader)
00775 {
00776         FILE    *pFontTableFile;
00777         font_table_type *pTmp;
00778         const ULONG     *aulBlockDepot;
00779         UCHAR   *aucFont, *aucAltFont;
00780         UCHAR   *aucBuffer;
00781         ULONG   ulBeginFontInfo;
00782         size_t  tFontInfoLen, tBlockDepotLen, tBlockSize;
00783         int     iPos, iRecLen, iOffsetAltName;
00784         int     iBold, iItalic, iSpecial, iEmphasis;
00785         UCHAR   ucFFN;
00786         char    szWordFont[FONT_LINE_LENGTH], szOurFont[FONT_LINE_LENGTH];
00787 
00788         fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
00789         fail(aulBBD == NULL || aulSBD == NULL);
00790 
00791         tFontTableRecords = 0;
00792         pFontTable = xfree(pFontTable);
00793 
00794         pFontTableFile = pOpenFontTableFile();
00795         if (pFontTableFile == NULL) {
00796                 /* No translation table file, no translation table */
00797                 return;
00798         }
00799 
00800         ulBeginFontInfo = ulGetLong(0x112, aucHeader); /* fcSttbfffn */
00801         DBG_HEX(ulBeginFontInfo);
00802         tFontInfoLen = (size_t)ulGetLong(0x116, aucHeader); /* lcbSttbfffn */
00803         DBG_DEC(tFontInfoLen);
00804         fail(tFontInfoLen < 46);
00805 
00806         DBG_DEC(pPPS->tTable.ulSB);
00807         DBG_HEX(pPPS->tTable.ulSize);
00808         if (pPPS->tTable.ulSize == 0) {
00809                 DBG_MSG("No fontname table");
00810                 (void)fclose(pFontTableFile);
00811                 return;
00812         }
00813 
00814         if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
00815                 /* Use the Small Block Depot */
00816                 aulBlockDepot = aulSBD;
00817                 tBlockDepotLen = tSBDLen;
00818                 tBlockSize = SMALL_BLOCK_SIZE;
00819         } else {
00820                 /* Use the Big Block Depot */
00821                 aulBlockDepot = aulBBD;
00822                 tBlockDepotLen = tBBDLen;
00823                 tBlockSize = BIG_BLOCK_SIZE;
00824         }
00825         aucBuffer = xmalloc(tFontInfoLen);
00826         if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
00827                         aulBlockDepot, tBlockDepotLen, tBlockSize,
00828                         aucBuffer, ulBeginFontInfo, tFontInfoLen)) {
00829                 aucBuffer = xfree(aucBuffer);
00830                 (void)fclose(pFontTableFile);
00831                 return;
00832         }
00833         NO_DBG_PRINT_BLOCK(aucBuffer, tFontInfoLen);
00834 
00835         /* Get the maximum number of entries in the font table */
00836         tFontTableRecords = (size_t)usGetWord(0, aucBuffer);
00837         tFontTableRecords *= 4; /* Plain, Bold, Italic and Bold/italic */
00838         tFontTableRecords++;    /* One extra for the table-font */
00839         vCreateFontTable();
00840 
00841         /* Read the font translation file */
00842         iItalic = 0;
00843         iBold = 0;
00844         iSpecial = 0;
00845         while (bReadFontFile(pFontTableFile, szWordFont,
00846                         &iItalic, &iBold, szOurFont, &iSpecial)) {
00847                 iEmphasis = 0;
00848                 if (iBold != 0) {
00849                         iEmphasis++;
00850                 }
00851                 if (iItalic != 0) {
00852                         iEmphasis += 2;
00853                 }
00854                 pTmp = pFontTable + iEmphasis;
00855                 iPos = 4;
00856                 while (iPos + 40 < (int)tFontInfoLen) {
00857                         iRecLen = (int)ucGetByte(iPos, aucBuffer);
00858                         ucFFN = ucGetByte(iPos + 1, aucBuffer);
00859                         aucFont = aucBuffer + iPos + 40;
00860                         iOffsetAltName = (int)unilen(aucFont);
00861                         if (iPos + 40 + iOffsetAltName + 4 >= iRecLen) {
00862                                 aucAltFont = NULL;
00863                         } else {
00864                                 aucAltFont = aucFont + iOffsetAltName + 2;
00865                                 NO_DBG_UNICODE(aucFont);
00866                                 NO_DBG_UNICODE(aucAltFont);
00867                         }
00868                         vFontname2Table(aucFont, aucAltFont, 2, iEmphasis,
00869                                         ucFFN, szWordFont, szOurFont, pTmp);
00870                         pTmp += 4;
00871                         iPos += iRecLen + 1;
00872                 }
00873         }
00874         (void)fclose(pFontTableFile);
00875         aucBuffer = xfree(aucBuffer);
00876         vMinimizeFontTable();
00877 } /* end of vCreate8FontTable */
00878 
00879 /*
00880  * Destroy the internal font table by freeing its memory
00881  */
00882 void
00883 vDestroyFontTable(void)
00884 {
00885         DBG_MSG("vDestroyFontTable");
00886 
00887         tFontTableRecords = 0;
00888         pFontTable = xfree(pFontTable);
00889 } /* end of vDestroyFontTable */
00890 
00891 /*
00892  * pGetNextFontTableRecord
00893  *
00894  * returns the next record in the table or NULL if there is no next record
00895  */
00896 const font_table_type *
00897 pGetNextFontTableRecord(const font_table_type *pRecordCurr)
00898 {
00899         size_t  tIndexCurr;
00900 
00901         if (pRecordCurr == NULL) {
00902                 /* No current record, so start with the first one */
00903                 return &pFontTable[0];
00904         }
00905 
00906         if (pRecordCurr < pFontTable ||
00907             pRecordCurr >= pFontTable + tFontTableRecords) {
00908                 /* Not a pointer in the array */
00909                 DBG_HEX(pRecordCurr);
00910                 DBG_HEX(pFontTable);
00911                 return NULL;
00912         }
00913 
00914         tIndexCurr = (size_t)(pRecordCurr - pFontTable);
00915         if (tIndexCurr + 1 < tFontTableRecords) {
00916                 /* There is a next record, so return it */
00917                 return &pFontTable[tIndexCurr + 1];
00918         }
00919         /* There is no next record */
00920         return NULL;
00921 } /* end of pGetNextFontTableRecord */
00922 
00923 /*
00924  * tGetFontTableLength
00925  *
00926  * returns the number of records in the internal font table
00927  */
00928 size_t
00929 tGetFontTableLength(void)
00930 {
00931         return tFontTableRecords;
00932 } /* end of tGetFontTableLength */
00933 
00934 #if !defined(__riscos)
00935 /*
00936  * vCorrect4PDF - only include PDF default fonts
00937  */
00938 static void
00939 vCorrect4PDF(void)
00940 {
00941         font_table_type *pTmp;
00942         const char      *szOurFont;
00943 
00944         for (pTmp = pFontTable; pTmp < pFontTable + tFontTableRecords; pTmp++) {
00945                 if (STRCEQ(pTmp->szOurFontname, FONT_MONOSPACED_PLAIN) ||
00946                     STRCEQ(pTmp->szOurFontname, FONT_MONOSPACED_BOLD) ||
00947                     STRCEQ(pTmp->szOurFontname, FONT_MONOSPACED_ITALIC) ||
00948                     STRCEQ(pTmp->szOurFontname, FONT_MONOSPACED_BOLDITALIC) ||
00949                     STRCEQ(pTmp->szOurFontname, FONT_SERIF_PLAIN) ||
00950                     STRCEQ(pTmp->szOurFontname, FONT_SERIF_BOLD) ||
00951                     STRCEQ(pTmp->szOurFontname, FONT_SERIF_ITALIC) ||
00952                     STRCEQ(pTmp->szOurFontname, FONT_SERIF_BOLDITALIC) ||
00953                     STRCEQ(pTmp->szOurFontname, FONT_SANS_SERIF_PLAIN) ||
00954                     STRCEQ(pTmp->szOurFontname, FONT_SANS_SERIF_BOLD) ||
00955                     STRCEQ(pTmp->szOurFontname, FONT_SANS_SERIF_ITALIC) ||
00956                     STRCEQ(pTmp->szOurFontname, FONT_SANS_SERIF_BOLDITALIC)) {
00957                         /* Already a default font */
00958                         continue;
00959                 }
00960                 szOurFont =
00961                         szGetDefaultFont(pTmp->ucFFN, (int)pTmp->ucEmphasis);
00962                 (void)strncpy(pTmp->szOurFontname, szOurFont,
00963                         sizeof(pTmp->szOurFontname) - 1);
00964                 pTmp->szOurFontname[sizeof(pTmp->szOurFontname) - 1] = '\0';
00965         }
00966 } /* end of vCorrect4PDF */
00967 
00968 /*
00969  * vCorrect4CyrPS - only include monospaced fonts
00970  */
00971 static void
00972 vCorrect4CyrPS(void)
00973 {
00974         font_table_type *pTmp;
00975         const char      *szOurFont;
00976         UCHAR   ucFFN;
00977 
00978         ucFFN = (FAMILY_UNKNOWN << 4) | PITCH_FIXED;
00979         for (pTmp = pFontTable; pTmp < pFontTable + tFontTableRecords; pTmp++) {
00980                 szOurFont = szGetDefaultFont(ucFFN, (int)pTmp->ucEmphasis);
00981                 (void)strncpy(pTmp->szOurFontname, szOurFont,
00982                         sizeof(pTmp->szOurFontname) - 1);
00983                 pTmp->szOurFontname[sizeof(pTmp->szOurFontname) - 1] = '\0';
00984         }
00985 } /* end of vCorrect4CyrPS */
00986 #endif /* __riscos */
00987 
00988 /*
00989  * vCorrectFontTable - correct the font table in special cases
00990  */
00991 void
00992 vCorrectFontTable(conversion_type eConversionType, encoding_type eEncoding)
00993 {
00994 #if !defined(__riscos)
00995         if (eConversionType == conversion_pdf) {
00996                 vCorrect4PDF();
00997         }
00998         if (eConversionType == conversion_ps &&
00999             eEncoding == encoding_cyrillic) {
01000                 vCorrect4CyrPS();
01001         }
01002 #endif /* __riscos */
01003 } /* end of vCorrectFontTable */
01004 
01005 /*
01006  * lComputeSpaceWidth - compute the width of a space character
01007  *
01008  * Returns the space width in millipoints
01009  */
01010 long
01011 lComputeSpaceWidth(drawfile_fontref tFontRef, USHORT usFontSize)
01012 {
01013         char    szSpace[] = " ";
01014 
01015         fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
01016 
01017         return lComputeStringWidth(szSpace, 1, tFontRef, usFontSize);
01018 } /* end of lComputeSpaceWidth */

Generated by  doxygen 1.6.2