home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 110
/
EnigmaAmiga110CD.iso
/
indispensabili
/
utility
/
apdf
/
xpdf-0.80
/
xpdf
/
fontoutputdev.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1999-06-20
|
10KB
|
389 lines
//========================================================================
//
// FontOutputDev.cc
//
// Copyright 1999 Emmanuel Lesueur
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#define Object ZZObject
#include <graphics/gfx.h>
#include <graphics/text.h>
#undef Object
#include "GString.h"
#include "gmem.h"
#include "config.h"
#include "Error.h"
#include "GfxState.h"
#include "GfxFont.h"
#include "FontOutputDev.h"
#include "XOutputFontInfo.h"
static GfxFontEncoding* enc[]={
&isoLatin1Encoding,
&isoLatin2Encoding,
&symbolEncoding,
&zapfDingbatsEncoding
};
//------------------------------------------------------------------------
// Font map
//------------------------------------------------------------------------
static FontMapEntry fontMap[] = {
{"Courier", "courier.font",100,FS_NORMAL,0},
{"Courier-Bold", "courier.font",100,FSF_BOLD,0},
{"Courier-BoldOblique", "courier.font",100,FSF_BOLD|FSF_ITALIC,0},
{"Courier-Oblique", "courier.font",100,FSF_ITALIC,0},
{"Helvetica", "helvetica.font",100,FS_NORMAL,0},
{"Helvetica-Bold", "helvetica.font",100,FSF_BOLD,0},
{"Helvetica-BoldOblique", "helvetica.font",100,FSF_BOLD|FSF_ITALIC,0},
{"Helvetica-Oblique", "helvetica.font",100,FSF_ITALIC,0},
{"Symbol", "StandardSymL.font",100,FS_NORMAL,2},
{"Times-Bold", "times.font",100,FSF_BOLD,0},
{"Times-BoldItalic", "times.font",100,FSF_BOLD|FSF_ITALIC,0},
{"Times-Italic", "times.font",100,FSF_ITALIC,0},
{"Times-Roman", "times.font",100,FS_NORMAL,0},
{"ZapfDingbats", "Dingbats.font",100,FS_NORMAL,3},
{NULL}
};
static const int fontMapSize=sizeof(fontMap)/sizeof(fontMap[0])-1;
FontMapEntry *userFontMap;
//------------------------------------------------------------------------
// Font substitutions
//------------------------------------------------------------------------
const char* defFontsNames[] = {
"« Sans-serif »",
"« Sans-serif Italic »",
"« Sans-serif Bold »",
"« Sans-serif Italic Bold »",
"« Serif »",
"« Serif Italic »",
"« Serif Bold »",
"« Serif Italic Bold »",
"« Fixed »",
"« Fixed Italic »",
"« Fixed Bold »",
"« Fixed Italic Bold »",
/* "« Symbolic »",
"« Symbolic Italic »",
"« Symbolic Bold »",
"« Symbolic Italic Bold »",*/
};
struct FontSubst {
char *xFont;
int style;
double mWidth;
};
// index: {symbolic:12, fixed:8, serif:4, sans-serif:0} + bold*2 + italic
static FontSubst fontSubst[] = {
{"helvetica.font", FS_NORMAL, 0.833},
{"helvetica.font", FSF_ITALIC, 0.833},
{"helvetica.font", FSF_BOLD, 0.889},
{"helvetica.font", FSF_BOLD|FSF_ITALIC, 0.889},
{"times.font", FS_NORMAL, 0.788},
{"times.font", FSF_ITALIC, 0.722},
{"times.font", FSF_BOLD, 0.833},
{"times.font", FSF_BOLD|FSF_ITALIC, 0.778},
{"courier.font", FS_NORMAL, 0.600},
{"courier.font", FSF_ITALIC, 0.600},
{"courier.font", FSF_BOLD, 0.600},
{"courier.font", FSF_BOLD|FSF_ITALIC, 0.600},
/* {"StandardSymL.font",FS_NORMAL, 0.576},
{"StandardSymL.font",FSF_ITALIC, 0.576},
{"StandardSymL.font",FSF_BOLD, 0.576},
{"StandardSymL.font",FSF_BOLD|FSF_ITALIC, 0.576},*/
};
static const int fontSubstSize=sizeof(fontSubst)/sizeof(fontSubst[0]);
const char* getAFont(GfxFont* gfxFont,GfxFontEncoding*& encoding,
int& style,double& m1, double& m2) {
encoding = &isoLatin1Encoding;
style = 0;
m1 = 1;
m2 = 1;
if(gfxFont->is16Bit())
return fontSubst[0].xFont;
else {
GString* pdfFont = gfxFont->getName();
FontMapEntry* p = NULL;
if (pdfFont) {
for (p = userFontMap; p->pdfFont; ++p) {
if (!pdfFont->cmp(p->pdfFont))
break;
}
if (!p->pdfFont) {
for (p = fontMap; p->pdfFont; ++p) {
if (!pdfFont->cmp(p->pdfFont))
break;
}
}
}
if (p && p->pdfFont) {
m1 = m2 = p->mWidth / 100.0;
style = p->style;
encoding = enc[p->encoding];
return p->xFont;
} else {
//~ Some non-symbolic fonts are tagged as symbolic.
// if (gfxFont->isSymbolic()) {
// index = 12;
// encoding = symbolEncoding;
// } else
int index;
if (gfxFont->isFixedWidth()) {
index = 8;
} else if (gfxFont->isSerif()) {
index = 4;
} else {
index = 0;
}
if (gfxFont->isBold())
index += 2;
if (gfxFont->isItalic())
index += 1;
const char* defFontName = defFontsNames[index];
for (p = userFontMap; p->pdfFont; ++p) {
if (!strcmp(p->pdfFont, defFontName))
break;
}
if (p && p->pdfFont) {
m1 = m2 = p->mWidth / 100.0;
style = p->style;
encoding = enc[p->encoding];
return p->xFont;
} else {
double w1, w2, v;
int code;
if ((code = gfxFont->getCharCode("m")) >= 0)
w1 = gfxFont->getWidth(code);
else
w1 = 0;
w2 = fontSubst[index].mWidth;
if (gfxFont->getType() == fontType3) {
// This is a hack which makes it possible to substitute for some
// Type 3 fonts. The problem is that it's impossible to know what
// the base coordinate system used in the font is without actually
// rendering the font. This code tries to guess by looking at the
// width of the character 'm' (which breaks if the font is a
// subset that doesn't contain 'm').
if (w1 > 0 && (w1 > 1.1 * w2 || w1 < 0.9 * w2)) {
w1 /= w2;
m1 = m2 = w1;
}
double* fm = gfxFont->getFontMatrix();
v = (fm[0] == 0) ? 1 : (fm[3] / fm[0]);
m2 *= v;
m2 *= v;
} else if (!gfxFont->isSymbolic()) {
if (w1 > 0.01 && w1 < 0.9 * w2) {
w1 /= w2;
if (w1 < 0.8)
w1 = 0.8;
m1 = m2 = w1;
}
}
style = fontSubst[index].style;
return fontSubst[index].xFont;
}
}
}
}
#if 0
void clearUserFontMap() {
if(userFontMap) {
gfree(userFontMap);
userFontMap = NULL;
}
}
void resetUserFontMap() {
clearUserFontMap();
for (n = 0; devFontMap[n].pdfFont; ++n) ;
userFontMap = (FontMapEntry *)gmalloc((n+1) * sizeof(FontMapEntry));
for (i = 0; i < n; ++i) {
char* s = devFontMap[i].devFont;
int style = FS_NORMAL;
GfxFontEncoding* encoding = &isoLatin1Encoding;
double m = 1;
if(*s=='[') {
++s;
bool ok=true;
do {
switch(*s++) {
case '\0':
error(-1, "Unterminated font option.\n");
ok = false;
s = devFontMap[i].devFont;
break;
case '1':
encoding = &isoLatin1Encoding;
break;
case '2':
encoding = &isoLatin2Encoding;
break;
case 'z':
encoding = &zapfDingbatsEncoding;
break;
case 's':
encoding = &symbolEncoding;
break;
case 'B':
style |= FSF_BOLD;
break;
case 'I':
style |= FSF_ITALIC;
break;
case ']':
ok = false;
break;
default:
error(-1, "Invalid font flag : %c\n", s[-1]);
break;
}
} while(ok);
}
userFontMap[i].pdfFont = devFontMap[i].pdfFont;
userFontMap[i].xFont = s;
userFontMap[i].mWidth = m;
userFontMap[i].style = style;
userFontMap[i].encoding = encoding;
}
userFontMap[n].pdfFont = NULL;
}
#endif
FontOutputDev::FontOutputDev() : beg(NULL),cur(NULL),end(NULL) {
}
FontOutputDev::~FontOutputDev() {
Entry *p = cur;
if (p != beg)
do {
--p;
delete p->pdfFont;
} while (p != beg);
gfree(beg);
}
void FontOutputDev::updateFont(GfxState *state) {
if (GfxFont* gfxFont = state->getFont()) {
unsigned n = cur - beg;
Entry *p = beg;
while (n > 0) {
unsigned k = n / 2;
Entry *q = p + k;
int cmp = gfxFont->getName()->cmp(q->pdfFont);
if (cmp > 0) {
p = q + 1;
n -= k + 1;
} else if(cmp != 0)
n = k;
else {
p = q;
break;
}
}
if (n == 0) {
if (cur == end) {
unsigned sz = ((end - beg) * 3) / 2 + 16;
ptrdiff_t k = cur - beg;
ptrdiff_t l = p - beg;
beg = (Entry*)grealloc(beg, sz * sizeof(*beg));
end = beg + sz;
cur = beg + k;
p = beg + l;
}
double m1, m2;
int style;
GfxFontEncoding* encoding;
GString* pdfFont = new GString(gfxFont->getName());
const char* xFont = getAFont(gfxFont, encoding, style, m1, m2);
// move entries after the two preceding lines to avoid leaving
// the object in an incoherent state in case of an exception.
if (p != cur)
memmove(p + 1, p, (cur - p) * sizeof(*p));
p->pdfFont = pdfFont;
p->xFont = xFont;
p->style = style;
p->encoding = encoding == &isoLatin1Encoding ? 0 :
encoding == &isoLatin2Encoding ? 1 :
encoding == &symbolEncoding ? 2 : 3;
p->m = int(100 * m1 + 0.5);
++cur;
}
}
}
DefaultFontOutputDev::DefaultFontOutputDev() {
beg = (Entry*)gmalloc((numDefFonts + fontMapSize) * sizeof(*beg));
end = beg + numDefFonts + fontMapSize;
Entry* p = beg;
for (int k = 0; k < fontMapSize; ++k) {
p->pdfFont = new GString(fontMap[k].pdfFont);
FontMapEntry* q;
for (q = userFontMap; q->pdfFont; ++q) {
if (!strcmp(q->pdfFont, p->pdfFont->getCString()))
break;
}
if (!q || !q->pdfFont)
q = fontMap + k;
p->xFont = q->xFont;
p->m = q->mWidth;
p->style = q->style;
p->encoding = q->encoding;
cur = ++p;
}
for (int k = 0; k < numDefFonts; ++k) {
p->pdfFont = new GString((char*)defFontsNames[k]);
FontMapEntry* q;
for (q = userFontMap; q->pdfFont; ++q) {
if (!strcmp(q->pdfFont, p->pdfFont->getCString()))
break;
}
if (q && q->pdfFont) {
p->xFont = q->xFont;
p->m = q->mWidth;
p->style = q->style;
p->encoding = q->encoding;
} else {
p->xFont = fontSubst[k].xFont;
p->m = (int)(fontSubst[k].mWidth * 100 + 0.5);
p->style = fontSubst[k].style;
p->encoding = /*k >= 12 ? 2 :*/ 0;
}
cur = ++p;
}
}