home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pdflb302.zip / pdf / pdflib-3.0.2 / pdflib / p_pfm.c < prev    next >
C/C++ Source or Header  |  2000-08-21  |  10KB  |  279 lines

  1. /*---------------------------------------------------------------------------*
  2.  |        PDFlib - A library for dynamically generating PDF documents        |
  3.  +---------------------------------------------------------------------------+
  4.  |        Copyright (c) 1997-2000 Thomas Merz. All rights reserved.          |
  5.  +---------------------------------------------------------------------------+
  6.  |    This software is NOT in the public domain.  It can be used under two   |
  7.  |    substantially different licensing terms:                               |
  8.  |                                                                           |
  9.  |    The commercial license is available for a fee, and allows you to       |
  10.  |    - ship a commercial product based on PDFlib                            |
  11.  |    - implement commercial Web services with PDFlib                        |
  12.  |    - distribute (free or commercial) software when the source code is     |
  13.  |      not made available                                                   |
  14.  |    Details can be found in the file PDFlib-license.pdf.                   |
  15.  |                                                                           |
  16.  |    The "Aladdin Free Public License" doesn't require any license fee,     |
  17.  |    and allows you to                                                      |
  18.  |    - develop and distribute PDFlib-based software for which the complete  |
  19.  |      source code is made available                                        |
  20.  |    - redistribute PDFlib non-commercially under certain conditions        |
  21.  |    - redistribute PDFlib on digital media for a fee if the complete       |
  22.  |      contents of the media are freely redistributable                     |
  23.  |    Details can be found in the file aladdin-license.pdf.                  |
  24.  |                                                                           |
  25.  |    These conditions extend to ports to other programming languages.       |
  26.  |    PDFlib is distributed with no warranty of any kind. Commercial users,  |
  27.  |    however, will receive warranty and support statements in writing.      |
  28.  *---------------------------------------------------------------------------*/
  29.  
  30. /* p_pfm.c
  31.  *
  32.  * PDFlib routines for fast reading of PFM font metrics files
  33.  *
  34.  */
  35.  
  36. #include <string.h>
  37.  
  38. #include "p_intern.h"
  39. #include "p_font.h"
  40.  
  41. /* read data types from the PFM */
  42. #define PFM_BYTE(offset)  pfm[offset]
  43. #define PFM_WORD(offset)  ((unsigned int) ((pfm[offset+1] << 8) + pfm[offset]))
  44. #define PFM_SHORT(offset) ((int) ((((char*) pfm)[offset+1] << 8) + pfm[offset]))
  45. #define PFM_DWORD(offset) ((unsigned long) ((PFM_WORD(offset+2)<<16) + PFM_WORD(offset)))
  46.  
  47. /* Offsets in the buffer containing the various PFM structures */
  48. #define header_base        0
  49. #define header_dfVersion    (PFM_WORD(header_base + 0))
  50. #define header_dfSize        (PFM_DWORD(header_base + 2))
  51. #define header_dfAscent        (PFM_WORD(header_base + 74))
  52. #define header_dfItalic        (PFM_BYTE(header_base + 80))
  53. #define header_dfWeight        (PFM_WORD(header_base + 83))
  54. #define header_dfCharSet    (PFM_BYTE(header_base + 85))
  55. #define header_dfPitchAndFamily    (PFM_BYTE(header_base + 90))
  56. #define header_dfMaxWidth    (PFM_WORD(header_base + 93))
  57. #define header_dfFirstChar    (PFM_BYTE(header_base + 95))
  58. #define header_dfLastChar    (PFM_BYTE(header_base + 96))
  59. #define header_dfDefaultChar    (PFM_BYTE(header_base + 97))
  60.  
  61. #define ext_base        117
  62. #define ext_dfExtentTable    (PFM_DWORD(ext_base + 6))
  63. #define ext_dfDriverInfo    (PFM_DWORD(ext_base + 22))
  64.  
  65. #define etm_base        147
  66. #define etmCapHeight        (PFM_SHORT(etm_base + 14))
  67. #define etmXHeight        (PFM_SHORT(etm_base + 16))
  68. #define etmLowerCaseAscent    (PFM_SHORT(etm_base + 18))
  69. #define etmLowerCaseDescent    (PFM_SHORT(etm_base + 20))
  70. #define etmSlant        (PFM_SHORT(etm_base + 22))
  71. #define etmUnderlineOffset    (PFM_SHORT(etm_base + 32))
  72. #define etmUnderlineWidth    (PFM_SHORT(etm_base + 34))
  73.  
  74. #define dfDevice        199
  75.  
  76. /* Windows font descriptor flags */
  77. #define PDF_FIXED_PITCHi    0x01  /* Fixed width font -- unused */
  78.  
  79. #define PDF_DONTCARE        0x00  /* Don't care or don't know. */
  80. #define PDF_ROMAN        0x10  /* Variable stroke width, serifed */
  81. #define PDF_SWISS        0x20  /* Variable stroke width, sans-serifed */
  82. #define PDF_MODERN        0x30  /* fixed pitch */
  83. #define PDF_SCRIPT        0x40  /* Cursive, etc. */
  84. #define PDF_DECORATIVE        0x50  /* Old English, etc. */
  85.  
  86. /* Windows character set flags */
  87. #define PFM_ANSI_CHARSET        0    /* seems to imply codepage 1250/1252 */
  88. #define PFM_SYMBOL_CHARSET      2
  89. #define PFM_SHIFTJIS_CHARSET    128
  90. #define PFM_OEM_CHARSET         255
  91.  
  92. /* Windows font weights */
  93. #define PDF_SEMIBOLD        600
  94. #define PDF_BOLD        700
  95.  
  96. /* default missing width */
  97. #define POSTSCRIPT_DEFAULT_WIDTH    250
  98.  
  99. #define PDF_STRING_PostScript    ((const char*) "\120\157\163\164\123\143\162\151\160\164")
  100.  
  101. /*
  102.  * Currently we do not populate the following fields correctly:
  103.  * - familyName
  104.  * - fullName
  105.  * - serif flag
  106.  */
  107.  
  108. static pdf_bool
  109. pdf_parse_pfm(PDF *p, FILE *fp, pdf_font *font)
  110. {
  111.     size_t length;
  112.     long file_length;
  113.     unsigned char *pfm;
  114.     int i, dfFirstChar, dfLastChar, default_width;
  115.     unsigned long dfExtentTable;
  116.  
  117.     if (fseek(fp, 0, SEEK_END) || (file_length = ftell(fp)) == -1 ||
  118.     fseek(fp, 0, SEEK_SET))
  119.     return pdf_false;
  120.  
  121.     length = (size_t) file_length;
  122.  
  123.     pfm = (unsigned char *) p->malloc(p, (size_t) length, "pdf_parse_pfm");
  124.  
  125.     /* check whether this is really a valid PostScript PFM file */
  126.     if (fread(pfm, (size_t) length, 1, fp) != 1 || 
  127.     (header_dfVersion != 0x100 && header_dfVersion != 0x200) ||
  128.     dfDevice > length ||
  129.     strncmp((const char *) pfm + dfDevice, PDF_STRING_PostScript, 10) ||
  130.     ext_dfDriverInfo > length ||
  131.     ext_dfExtentTable + 2 * (header_dfLastChar - header_dfFirstChar) + 1 > length) {
  132.         p->free(p, pfm);
  133.         pdf_error(p, PDF_RuntimeError, "Corrupt PFM file");
  134.     }
  135.  
  136.     if (header_dfSize != length) {
  137.     pdf_error(p, PDF_NonfatalError, "Corrupt PFM file, proceeding anyway");
  138.     }
  139.  
  140.     /* initialize font struct */
  141.     pdf_init_font_struct(p, font);
  142.  
  143.     /* fetch relevant data from the PFM */
  144.  
  145.     font->afm             = pdf_false;
  146.  
  147. #define PDF_STRING_Bold        "\102\157\154\144"
  148. #define PDF_STRING_Semibold    "\123\145\155\151\142\157\154\144"
  149. #define PDF_STRING_Medium    "\115\145\144\151\165\155"
  150.  
  151.     /* heuristic for estimating the stem width from the weight */
  152.     if (header_dfWeight >= PDF_BOLD) {
  153.     font->weight    = pdf_strdup(p, PDF_STRING_Bold);
  154.     font->StdVW    = DEFAULT_STEMWIDTH_BOLD;
  155.     } else if (header_dfWeight >= PDF_SEMIBOLD) {
  156.     font->weight    = pdf_strdup(p, PDF_STRING_Semibold);
  157.     font->StdVW    = DEFAULT_STEMWIDTH_SEMI;
  158.     } else {
  159.     font->weight    = pdf_strdup(p, PDF_STRING_Medium);
  160.     font->StdVW    = DEFAULT_STEMWIDTH;
  161.     }
  162.  
  163.     switch (header_dfPitchAndFamily & 0xF0) {
  164.     case PDF_ROMAN:
  165.         font->flags |= SERIF;
  166.         break;
  167.     case PDF_MODERN:
  168.         /* Has to be ignored, contrary to MS's specs */
  169.         break;
  170.     case PDF_SCRIPT:
  171.         font->flags |= SCRIPT;
  172.         break;
  173.     case PDF_DECORATIVE:
  174.         /* the dfCharSet flag lies in this case... */
  175.         header_dfCharSet = PFM_SYMBOL_CHARSET;
  176.         break;
  177.     case PDF_SWISS:
  178.     case PDF_DONTCARE:
  179.     default:
  180.         break;
  181.     }
  182.     
  183.     switch (header_dfCharSet) {
  184.     case PFM_ANSI_CHARSET:
  185.         font->encoding    = winansi;
  186.         font->encodingScheme= pdf_strdup(p, "AdobeStandardEncoding");
  187.         break;
  188.     case PFM_SYMBOL_CHARSET:
  189.         font->encoding    = builtin;
  190.         font->encodingScheme= pdf_strdup(p, "FontSpecific");
  191.         break;
  192.     default:
  193.         return pdf_false;
  194.     }
  195.  
  196.     font->name         = pdf_strdup(p, (const char *)pfm + ext_dfDriverInfo);
  197.     font->fullName    = pdf_strdup(p, font->name);    /* fake */
  198.     font->familyName    = pdf_strdup(p, font->name);    /* fake */
  199.  
  200.     dfFirstChar = header_dfFirstChar;
  201.     dfLastChar  = header_dfLastChar;
  202.     dfExtentTable = ext_dfExtentTable;
  203.  
  204.     /* default values -- don't take the width of the default character */
  205.     default_width = POSTSCRIPT_DEFAULT_WIDTH;
  206.  
  207.     for (i = 0; i < 256; i++)
  208.     font->widths[i] = default_width;
  209.  
  210.     for (i = dfFirstChar; i <= dfLastChar; i++)
  211.     font->widths[i] = (int) PFM_WORD(dfExtentTable + 2 * (i - dfFirstChar));
  212.  
  213.     /* check for monospaced font (the fixed pitch flag lies at us) */
  214.     default_width = font->widths[dfFirstChar];
  215.  
  216.     for (i = dfFirstChar+1; i <= dfLastChar; i++)
  217.     if (default_width != font->widths[i])
  218.         break;
  219.  
  220.     if (i == dfLastChar + 1)
  221.     font->isFixedPitch = pdf_true;
  222.  
  223.     font->italicAngle        = (header_dfItalic ? etmSlant/((float) 10.0) : (float) 0.0);
  224.     font->capHeight        = etmCapHeight;
  225.     font->xHeight        = etmXHeight;
  226.     font->descender        = -etmLowerCaseDescent;
  227.     font->ascender        = (int) header_dfAscent;
  228.  
  229.     font->underlinePosition    = -etmUnderlineOffset;
  230.     font->underlineThickness    = etmUnderlineWidth;
  231.  
  232.     font->llx            = (float) -200;
  233.     font->lly            = (float) font->descender;
  234.     font->urx            = (float) header_dfMaxWidth;
  235.     font->ury            = (float) font->ascender;
  236.  
  237.     p->free(p, pfm);
  238.  
  239.     return pdf_true;
  240. }
  241.  
  242. pdf_bool
  243. pdf_get_metrics_pfm(PDF *p, pdf_font *font, const char *fontname, int enc, const char *filename)
  244. {
  245.     FILE    *pfmfile;
  246.  
  247.     /* open PFM file */
  248.     if ((pfmfile = fopen(filename, READMODE)) == NULL) {
  249.     return pdf_false;
  250.     }
  251.  
  252.     /* Read PFM metrics */
  253.     if (pdf_parse_pfm(p, pfmfile, font) == pdf_false) {
  254.     fclose(pfmfile);
  255.     pdf_error(p, PDF_RuntimeError, "Error parsing PFM file %s", filename);
  256.     }
  257.  
  258.     fclose(pfmfile);
  259.  
  260.     if (enc != winansi && font->encoding == winansi) {
  261.     pdf_error(p, PDF_NonfatalError,
  262.         "Can't reencode Windows font '%s' (using winansi)", font->name);
  263.     enc = winansi;
  264.     }
  265.     if (enc != builtin && font->encoding == builtin) {
  266.     pdf_error(p, PDF_NonfatalError,
  267.         "Can't reencode Symbol font '%s' (using builtin)", font->name);
  268.     }
  269.  
  270.     if (fontname && strcmp(font->name, fontname)) {
  271.     pdf_error(p, PDF_NonfatalError,
  272.         "Font name mismatch in PFM file %s", filename);
  273.     }
  274.  
  275.     pdf_make_fontflags(p, font);
  276.  
  277.     return pdf_true;
  278. }
  279.