home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 110 / EnigmaAmiga110CD.iso / indispensabili / utility / apdf / xpdf-0.80 / xpdf / fontoutputdev.cc < prev    next >
C/C++ Source or Header  |  1999-06-20  |  10KB  |  389 lines

  1. //========================================================================
  2. //
  3. // FontOutputDev.cc
  4. //
  5. // Copyright 1999 Emmanuel Lesueur
  6. //
  7. //========================================================================
  8.  
  9. #ifdef __GNUC__
  10. #pragma implementation
  11. #endif
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <stddef.h>
  16. #include <ctype.h>
  17. #define Object ZZObject
  18. #include <graphics/gfx.h>
  19. #include <graphics/text.h>
  20. #undef Object
  21. #include "GString.h"
  22. #include "gmem.h"
  23. #include "config.h"
  24. #include "Error.h"
  25. #include "GfxState.h"
  26. #include "GfxFont.h"
  27. #include "FontOutputDev.h"
  28. #include "XOutputFontInfo.h"
  29.  
  30. static GfxFontEncoding* enc[]={
  31.     &isoLatin1Encoding,
  32.     &isoLatin2Encoding,
  33.     &symbolEncoding,
  34.     &zapfDingbatsEncoding
  35. };
  36.  
  37. //------------------------------------------------------------------------
  38. // Font map
  39. //------------------------------------------------------------------------
  40.  
  41. static FontMapEntry fontMap[] = {
  42.   {"Courier",               "courier.font",100,FS_NORMAL,0},
  43.   {"Courier-Bold",          "courier.font",100,FSF_BOLD,0},
  44.   {"Courier-BoldOblique",   "courier.font",100,FSF_BOLD|FSF_ITALIC,0},
  45.   {"Courier-Oblique",       "courier.font",100,FSF_ITALIC,0},
  46.   {"Helvetica",             "helvetica.font",100,FS_NORMAL,0},
  47.   {"Helvetica-Bold",        "helvetica.font",100,FSF_BOLD,0},
  48.   {"Helvetica-BoldOblique", "helvetica.font",100,FSF_BOLD|FSF_ITALIC,0},
  49.   {"Helvetica-Oblique",     "helvetica.font",100,FSF_ITALIC,0},
  50.   {"Symbol",                "StandardSymL.font",100,FS_NORMAL,2},
  51.   {"Times-Bold",            "times.font",100,FSF_BOLD,0},
  52.   {"Times-BoldItalic",      "times.font",100,FSF_BOLD|FSF_ITALIC,0},
  53.   {"Times-Italic",          "times.font",100,FSF_ITALIC,0},
  54.   {"Times-Roman",           "times.font",100,FS_NORMAL,0},
  55.   {"ZapfDingbats",          "Dingbats.font",100,FS_NORMAL,3},
  56.   {NULL}
  57. };
  58. static const int fontMapSize=sizeof(fontMap)/sizeof(fontMap[0])-1;
  59.  
  60. FontMapEntry *userFontMap;
  61.  
  62.  
  63. //------------------------------------------------------------------------
  64. // Font substitutions
  65. //------------------------------------------------------------------------
  66.  
  67. const char* defFontsNames[] = {
  68.     "« Sans-serif »",
  69.     "« Sans-serif Italic »",
  70.     "« Sans-serif Bold »",
  71.     "« Sans-serif Italic Bold »",
  72.     "« Serif »",
  73.     "« Serif Italic »",
  74.     "« Serif Bold »",
  75.     "« Serif Italic Bold »",
  76.     "« Fixed »",
  77.     "« Fixed Italic »",
  78.     "« Fixed Bold »",
  79.     "« Fixed Italic Bold »",
  80. /*    "« Symbolic »",
  81.     "« Symbolic Italic »",
  82.     "« Symbolic Bold »",
  83.     "« Symbolic Italic Bold »",*/
  84. };
  85.  
  86. struct FontSubst {
  87.   char *xFont;
  88.   int style;
  89.   double mWidth;
  90. };
  91.  
  92. // index: {symbolic:12, fixed:8, serif:4, sans-serif:0} + bold*2 + italic
  93. static FontSubst fontSubst[] = {
  94.   {"helvetica.font",   FS_NORMAL,           0.833},
  95.   {"helvetica.font",   FSF_ITALIC,          0.833},
  96.   {"helvetica.font",   FSF_BOLD,            0.889},
  97.   {"helvetica.font",   FSF_BOLD|FSF_ITALIC, 0.889},
  98.   {"times.font",       FS_NORMAL,           0.788},
  99.   {"times.font",       FSF_ITALIC,          0.722},
  100.   {"times.font",       FSF_BOLD,            0.833},
  101.   {"times.font",       FSF_BOLD|FSF_ITALIC, 0.778},
  102.   {"courier.font",     FS_NORMAL,           0.600},
  103.   {"courier.font",     FSF_ITALIC,          0.600},
  104.   {"courier.font",     FSF_BOLD,            0.600},
  105.   {"courier.font",     FSF_BOLD|FSF_ITALIC, 0.600},
  106. /*  {"StandardSymL.font",FS_NORMAL,           0.576},
  107.   {"StandardSymL.font",FSF_ITALIC,          0.576},
  108.   {"StandardSymL.font",FSF_BOLD,            0.576},
  109.   {"StandardSymL.font",FSF_BOLD|FSF_ITALIC, 0.576},*/
  110. };
  111. static const int fontSubstSize=sizeof(fontSubst)/sizeof(fontSubst[0]);
  112.  
  113. const char* getAFont(GfxFont* gfxFont,GfxFontEncoding*& encoding,
  114.              int& style,double& m1, double& m2) {
  115.  
  116.   encoding = &isoLatin1Encoding;
  117.   style = 0;
  118.   m1 = 1;
  119.   m2 = 1;
  120.  
  121.   if(gfxFont->is16Bit())
  122.     return fontSubst[0].xFont;
  123.   else {
  124.  
  125.     GString* pdfFont = gfxFont->getName();
  126.     FontMapEntry* p = NULL;
  127.  
  128.     if (pdfFont) {
  129.       for (p = userFontMap; p->pdfFont; ++p) {
  130.     if (!pdfFont->cmp(p->pdfFont))
  131.       break;
  132.       }
  133.       if (!p->pdfFont) {
  134.     for (p = fontMap; p->pdfFont; ++p) {
  135.       if (!pdfFont->cmp(p->pdfFont))
  136.         break;
  137.     }
  138.       }
  139.     }
  140.  
  141.     if (p && p->pdfFont) {
  142.       m1 = m2 = p->mWidth / 100.0;
  143.       style = p->style;
  144.       encoding = enc[p->encoding];
  145.       return p->xFont;
  146.     } else {
  147. //~ Some non-symbolic fonts are tagged as symbolic.
  148. //      if (gfxFont->isSymbolic()) {
  149. //        index = 12;
  150. //        encoding = symbolEncoding;
  151. //      } else
  152.       int index;
  153.       if (gfxFont->isFixedWidth()) {
  154.     index = 8;
  155.       } else if (gfxFont->isSerif()) {
  156.     index = 4;
  157.       } else {
  158.     index = 0;
  159.       }
  160.       if (gfxFont->isBold())
  161.     index += 2;
  162.       if (gfxFont->isItalic())
  163.     index += 1;
  164.  
  165.       const char* defFontName = defFontsNames[index];
  166.  
  167.       for (p = userFontMap; p->pdfFont; ++p) {
  168.     if (!strcmp(p->pdfFont, defFontName))
  169.       break;
  170.       }
  171.  
  172.       if (p && p->pdfFont) {
  173.     m1 = m2 = p->mWidth / 100.0;
  174.     style = p->style;
  175.     encoding = enc[p->encoding];
  176.     return p->xFont;
  177.       } else {
  178.  
  179.     double w1, w2, v;
  180.     int code;
  181.  
  182.     if ((code = gfxFont->getCharCode("m")) >= 0)
  183.       w1 = gfxFont->getWidth(code);
  184.     else
  185.       w1 = 0;
  186.     w2 = fontSubst[index].mWidth;
  187.     if (gfxFont->getType() == fontType3) {
  188.       // This is a hack which makes it possible to substitute for some
  189.       // Type 3 fonts.  The problem is that it's impossible to know what
  190.       // the base coordinate system used in the font is without actually
  191.       // rendering the font.  This code tries to guess by looking at the
  192.       // width of the character 'm' (which breaks if the font is a
  193.       // subset that doesn't contain 'm').
  194.       if (w1 > 0 && (w1 > 1.1 * w2 || w1 < 0.9 * w2)) {
  195.         w1 /= w2;
  196.         m1 = m2 = w1;
  197.       }
  198.       double* fm = gfxFont->getFontMatrix();
  199.       v = (fm[0] == 0) ? 1 : (fm[3] / fm[0]);
  200.       m2 *= v;
  201.       m2 *= v;
  202.     } else if (!gfxFont->isSymbolic()) {
  203.       if (w1 > 0.01 && w1 < 0.9 * w2) {
  204.         w1 /= w2;
  205.         if (w1 < 0.8)
  206.           w1 = 0.8;
  207.         m1 = m2 = w1;
  208.       }
  209.     }
  210.     style = fontSubst[index].style;
  211.     return fontSubst[index].xFont;
  212.       }
  213.     }
  214.   }
  215. }
  216.  
  217. #if 0
  218. void clearUserFontMap() {
  219.   if(userFontMap) {
  220.     gfree(userFontMap);
  221.     userFontMap = NULL;
  222.   }
  223. }
  224.  
  225. void resetUserFontMap() {
  226.   clearUserFontMap();
  227.  
  228.   for (n = 0; devFontMap[n].pdfFont; ++n) ;
  229.   userFontMap = (FontMapEntry *)gmalloc((n+1) * sizeof(FontMapEntry));
  230.   for (i = 0; i < n; ++i) {
  231.     char* s = devFontMap[i].devFont;
  232.     int style = FS_NORMAL;
  233.     GfxFontEncoding* encoding = &isoLatin1Encoding;
  234.     double m = 1;
  235.     if(*s=='[') {
  236.       ++s;
  237.       bool ok=true;
  238.       do {
  239.     switch(*s++) {
  240.       case '\0':
  241.         error(-1, "Unterminated font option.\n");
  242.         ok = false;
  243.         s = devFontMap[i].devFont;
  244.         break;
  245.       case '1':
  246.         encoding = &isoLatin1Encoding;
  247.         break;
  248.       case '2':
  249.         encoding = &isoLatin2Encoding;
  250.         break;
  251.       case 'z':
  252.         encoding = &zapfDingbatsEncoding;
  253.         break;
  254.       case 's':
  255.         encoding = &symbolEncoding;
  256.         break;
  257.       case 'B':
  258.         style |= FSF_BOLD;
  259.         break;
  260.       case 'I':
  261.         style |= FSF_ITALIC;
  262.         break;
  263.       case ']':
  264.         ok = false;
  265.         break;
  266.       default:
  267.         error(-1, "Invalid font flag : %c\n", s[-1]);
  268.         break;
  269.     }
  270.       } while(ok);
  271.     }
  272.     userFontMap[i].pdfFont = devFontMap[i].pdfFont;
  273.     userFontMap[i].xFont = s;
  274.     userFontMap[i].mWidth = m;
  275.     userFontMap[i].style = style;
  276.     userFontMap[i].encoding = encoding;
  277.   }
  278.   userFontMap[n].pdfFont = NULL;
  279. }
  280. #endif
  281.  
  282.  
  283. FontOutputDev::FontOutputDev() : beg(NULL),cur(NULL),end(NULL) {
  284. }
  285.  
  286. FontOutputDev::~FontOutputDev() {
  287.   Entry *p = cur;
  288.   if (p != beg)
  289.     do {
  290.       --p;
  291.       delete p->pdfFont;
  292.     } while (p != beg);
  293.   gfree(beg);
  294. }
  295.  
  296. void FontOutputDev::updateFont(GfxState *state) {
  297.   if (GfxFont* gfxFont = state->getFont()) {
  298.     unsigned n = cur - beg;
  299.     Entry *p = beg;
  300.     while (n > 0) {
  301.       unsigned k = n / 2;
  302.       Entry *q = p + k;
  303.       int cmp = gfxFont->getName()->cmp(q->pdfFont);
  304.       if (cmp > 0) {
  305.     p = q + 1;
  306.     n -= k + 1;
  307.       } else if(cmp != 0)
  308.     n = k;
  309.       else {
  310.     p = q;
  311.     break;
  312.       }
  313.     }
  314.     if (n == 0) {
  315.       if (cur == end) {
  316.     unsigned sz = ((end - beg) * 3) / 2 + 16;
  317.     ptrdiff_t k = cur - beg;
  318.     ptrdiff_t l = p - beg;
  319.     beg = (Entry*)grealloc(beg, sz * sizeof(*beg));
  320.     end = beg + sz;
  321.     cur = beg + k;
  322.     p = beg + l;
  323.       }
  324.  
  325.       double m1, m2;
  326.       int style;
  327.       GfxFontEncoding* encoding;
  328.       GString* pdfFont = new GString(gfxFont->getName());
  329.       const char* xFont = getAFont(gfxFont, encoding, style, m1, m2);
  330.  
  331.       // move entries after the two preceding lines to avoid leaving
  332.       // the object in an incoherent state in case of an exception.
  333.       if (p != cur)
  334.     memmove(p + 1, p, (cur - p) * sizeof(*p));
  335.       p->pdfFont = pdfFont;
  336.       p->xFont = xFont;
  337.       p->style = style;
  338.       p->encoding = encoding == &isoLatin1Encoding ? 0 :
  339.             encoding == &isoLatin2Encoding ? 1 :
  340.             encoding == &symbolEncoding ? 2 : 3;
  341.       p->m = int(100 * m1 + 0.5);
  342.       ++cur;
  343.     }
  344.   }
  345. }
  346.  
  347.  
  348. DefaultFontOutputDev::DefaultFontOutputDev() {
  349.   beg = (Entry*)gmalloc((numDefFonts + fontMapSize) * sizeof(*beg));
  350.   end = beg + numDefFonts + fontMapSize;
  351.   Entry* p = beg;
  352.   for (int k = 0; k < fontMapSize; ++k) {
  353.     p->pdfFont = new GString(fontMap[k].pdfFont);
  354.     FontMapEntry* q;
  355.     for (q = userFontMap; q->pdfFont; ++q) {
  356.       if (!strcmp(q->pdfFont, p->pdfFont->getCString()))
  357.     break;
  358.     }
  359.     if (!q || !q->pdfFont)
  360.       q = fontMap + k;
  361.     p->xFont = q->xFont;
  362.     p->m = q->mWidth;
  363.     p->style = q->style;
  364.     p->encoding = q->encoding;
  365.     cur = ++p;
  366.   }
  367.   for (int k = 0; k < numDefFonts; ++k) {
  368.     p->pdfFont = new GString((char*)defFontsNames[k]);
  369.     FontMapEntry* q;
  370.     for (q = userFontMap; q->pdfFont; ++q) {
  371.       if (!strcmp(q->pdfFont, p->pdfFont->getCString()))
  372.     break;
  373.     }
  374.     if (q && q->pdfFont) {
  375.       p->xFont = q->xFont;
  376.       p->m = q->mWidth;
  377.       p->style = q->style;
  378.       p->encoding = q->encoding;
  379.     } else {
  380.       p->xFont = fontSubst[k].xFont;
  381.       p->m = (int)(fontSubst[k].mWidth * 100 + 0.5);
  382.       p->style = fontSubst[k].style;
  383.       p->encoding = /*k >= 12 ? 2 :*/ 0;
  384.     }
  385.     cur = ++p;
  386.   }
  387. }
  388.  
  389.