#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef FONTMODULE
#include <string.h>
#ifdef _XOPEN_SOURCE
#include <math.h>
#else
#define _XOPEN_SOURCE
#include <math.h>
#undef _XOPEN_SOURCE
#endif
#include "X11/Xfuncs.h"
#ifdef USE_MMAP
#include <sys/types.h>
#include <sys/mman.h>
#endif
#else
#include "Xmd.h"
#include "Xdefs.h"
#endif
#ifdef FONTMODULE
#include "os.h"
#include "xf86_ansic.h"
#endif
#include <X11/fonts/fntfilst.h>
#include <X11/fonts/fontutil.h>
#include <X11/fonts/FSproto.h>
#include <X11/fonts/fontenc.h>
#include "t1unicode.h"
#include "objects.h"
#include "spaces.h"
#include "paths.h"
#include "regions.h"
#include "t1stdio.h"
#include "util.h"
#include "fontfcn.h"
#include "t1intf.h"
static int Type1GetGlyphs ( FontPtr pFont, unsigned long count,
unsigned char *chars, FontEncoding charEncoding,
unsigned long *glyphCount, CharInfoPtr *glyphs );
static int Type1GetMetrics ( FontPtr pFont, unsigned long count,
unsigned char *chars,
FontEncoding charEncoding,
unsigned long *glyphCount,
xCharInfo **glyphs );
#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8))
#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8))
static void fillrun ( char *p, pel x0, pel x1, int bit );
extern psfont *FontP;
extern psobj *ISOLatin1EncArrayP;
static void fill ( char *dest, int h, int w, struct region *area, int byte,
int bit, int wordsize );
static int
Type1ReturnCodeToXReturnCode(int rc)
{
switch(rc) {
case SCAN_OK:
return Successful;
case SCAN_FILE_EOF:
case SCAN_ERROR:
return BadFontFormat;
case SCAN_OUT_OF_MEMORY:
return AllocError;
case SCAN_FILE_OPEN_ERROR:
return BadFontName;
case SCAN_TRUE:
case SCAN_FALSE:
case SCAN_END:
default:
ErrorF("Type1 return code not convertable to X return code: %d\n", rc);
return rc;
}
}
int
Type1OpenScalable (FontPathElementPtr fpe,
FontPtr *ppFont,
int flags,
FontEntryPtr entry,
char *fileName,
FontScalablePtr vals,
fsBitmapFormat format,
fsBitmapFormatMask fmask,
FontPtr non_cachable_font)
{
FontPtr pFont;
int bit,
byte,
glyph,
scan,
image;
int pad,wordsize;
long *pool;
int size;
struct XYspace *S;
struct region *area;
CharInfoRec *glyphs;
int len, rc, count = 0, i = 0;
struct type1font *type1;
char *p;
FontMapPtr mapping = NULL;
int no_mapping;
psobj *fontmatrix;
long x0, total_width = 0, total_raw_width = 0;
double x1, y1, t1 = .001, t2 = 0.0, t3 = 0.0, t4 = .001;
double sxmult;
if (hypot(vals->pixel_matrix[0], vals->pixel_matrix[1]) < 1.0 ||
hypot(vals->pixel_matrix[2], vals->pixel_matrix[3]) < 1.0)
return BadFontName;
FontDefaultFormat(&bit, &byte, &glyph, &scan);
rc = CheckFSFormat(format, fmask, &bit, &byte, &scan, &glyph, &image);
if (rc != Successful)
return rc;
pad = glyph * 8;
wordsize = scan * 8;
#define PAD(bits, pad) (((bits)+(pad)-1)&-(pad))
pFont = CreateFontRec();
if (pFont == NULL)
return AllocError;
type1 = (struct type1font *)xalloc(sizeof(struct type1font));
if (type1 == NULL) {
DestroyFontRec(pFont);
return AllocError;
}
bzero(type1, sizeof(struct type1font));
size = 200000 + 600 *
(int)hypot(vals->pixel_matrix[2], vals->pixel_matrix[3])
* sizeof(short);
if (size < 0 || NULL == (pool = (long *) xalloc(size))) {
xfree(type1);
DestroyFontRec(pFont);
return AllocError;
}
addmemory(pool, size);
glyphs = type1->glyphs;
if (!fontfcnA(fileName, &rc)) {
delmemory();
xfree(type1);
DestroyFontRec(pFont);
xfree(pool);
return Type1ReturnCodeToXReturnCode(rc);
}
fontmatrix = &FontP->fontInfoP[FONTMATRIX].value;
if (objPIsArray(fontmatrix) && fontmatrix->len == 6)
{
#define assign(n,d,f) if (objPIsInteger(fontmatrix->data.arrayP + n)) \
d = fontmatrix->data.arrayP[n].data.integer; \
else if (objPIsReal(fontmatrix->data.arrayP + n)) \
d = fontmatrix->data.arrayP[n].data.real; \
else d = f;
assign(0, t1, .001);
assign(1, t2, 0.0);
assign(2, t3, 0.0);
assign(3, t4, .001);
}
S = (struct XYspace *) t1_Transform((struct xobject *)IDENTITY,
t1, t2, t3, t4);
S = (struct XYspace *) Permanent(t1_Transform((struct xobject *)S,
vals->pixel_matrix[0],
-vals->pixel_matrix[1],
vals->pixel_matrix[2],
-vals->pixel_matrix[3]));
sxmult = hypot(vals->pixel_matrix[0], vals->pixel_matrix[1]);
if (sxmult > EPS) sxmult = 1000.0 / sxmult;
no_mapping=0;
p = FontEncFromXLFD(entry->name.name, entry->name.length);
if(p==0) {
mapping=0;
no_mapping=2;
}
if(!strcmp(p, "adobe-fontspecific")) {
mapping=0;
no_mapping=1;
}
pFont->info.firstCol = 255;
pFont->info.lastCol = 0;
if(!no_mapping) {
mapping = FontEncMapFind(p,
FONT_ENCODING_POSTSCRIPT, -1, -1,
fileName);
if(!mapping)
mapping = FontEncMapFind(p,
FONT_ENCODING_UNICODE, -1, -1,
fileName);
if(!mapping)
goto NoEncoding;
else
no_mapping=0;
}
for (i=0; i < 256; i++) {
long h,w;
long paddedW;
int j;
char *codename;
if(no_mapping == 1) {
codename = FontP->fontInfoP[ENCODING].
value.data.arrayP[i].data.valueP;
len = FontP->fontInfoP[ENCODING].
value.data.arrayP[i].len;
} else if(no_mapping) {
codename = unicodetoPSname(i);
len = codename ? strlen(codename) : 0;
} else {
if(mapping->type == FONT_ENCODING_UNICODE) {
codename = unicodetoPSname(FontEncRecode(i, mapping));
} else
codename = FontEncName(i, mapping);
len=codename?strlen(codename):0;
}
if(len==7 && !strncmp(codename, ".notdef", 7)) {
len=0;
codename=0;
}
if(len==0) {
if(i==0) {
codename=".notdef";
len=7;
} else
continue;
}
if(i!=0) {
for (j = 0; j < vals->nranges; j++)
if (i >= minchar(vals->ranges[j]) &&
i <= maxchar(vals->ranges[j]))
break;
if (vals->nranges && j == vals->nranges)
continue;
}
rc = 0;
area = (struct region *)fontfcnB(S, (unsigned char *)codename,
&len, &rc);
if (rc < 0) {
rc = Type1ReturnCodeToXReturnCode(rc);
break;
}
else if (rc > 0)
continue;
if (area == NULL)
continue;
if (pFont->info.firstCol > i)
pFont->info.firstCol = i;
if (pFont->info.lastCol < i)
pFont->info.lastCol = i;
h = area->ymax - area->ymin;
w = area->xmax - area->xmin;
paddedW = PAD(w, pad);
if (h > 0 && w > 0) {
size = h * paddedW / 8;
glyphs[i].bits = (char *)xalloc(size);
if (glyphs[i].bits == NULL) {
rc = AllocError;
break;
}
}
else {
size = 0;
h = w = 0;
area->xmin = area->xmax = 0;
area->ymax = area->ymax = 0;
}
glyphs[i].metrics.leftSideBearing = area->xmin;
x1 = (double)(x0 = area->ending.x - area->origin.x);
y1 = (double)(area->ending.y - area->origin.y);
glyphs[i].metrics.characterWidth =
(x0 + (x0 > 0 ? FPHALF : -FPHALF)) / (1 << FRACTBITS);
if (!glyphs[i].metrics.characterWidth && size == 0)
{
h = w = 1;
size = paddedW = PAD(w, pad);
glyphs[i].bits = (char *)xalloc(size);
if (glyphs[i].bits == NULL) {
rc = AllocError;
break;
}
}
glyphs[i].metrics.attributes =
NEARESTPEL((long)(hypot(x1, y1) * sxmult));
total_width += glyphs[i].metrics.attributes;
total_raw_width += abs((int)(INT16)glyphs[i].metrics.attributes);
count++;
glyphs[i].metrics.rightSideBearing = w + area->xmin;
glyphs[i].metrics.descent = area->ymax - NEARESTPEL(area->origin.y);
glyphs[i].metrics.ascent = h - glyphs[i].metrics.descent;
bzero(glyphs[i].bits, size);
if (h > 0 && w > 0) {
fill(glyphs[i].bits, h, paddedW, area, byte, bit, wordsize );
}
Destroy(area);
}
NoEncoding:
delmemory();
xfree(pool);
if (pFont->info.firstCol > pFont->info.lastCol)
{
xfree(type1);
DestroyFontRec(pFont);
return BadFontName;
}
if (i != 256) {
for (i--; i >= 0; i--)
if (glyphs[i].bits != NULL)
xfree(glyphs[i].bits);
xfree(type1);
DestroyFontRec(pFont);
return rc;
}
type1->pDefault = NULL;
pFont->format = format;
pFont->bit = bit;
pFont->byte = byte;
pFont->glyph = glyph;
pFont->scan = scan;
pFont->info.firstRow = 0;
pFont->info.lastRow = 0;
pFont->get_metrics = Type1GetMetrics;
pFont->get_glyphs = Type1GetGlyphs;
pFont->unload_font = Type1CloseFont;
pFont->unload_glyphs = NULL;
pFont->refcnt = 0;
pFont->fontPrivate = (unsigned char *) type1;
if (count)
{
total_raw_width = (total_raw_width * 10 + count / 2) / count;
if (total_width < 0)
{
total_raw_width = -total_raw_width;
}
vals->width = (int)((double)total_raw_width *
vals->pixel_matrix[0] / 1000.0 +
(vals->pixel_matrix[0] > 0 ? .5 : -.5));
}
T1FillFontInfo(pFont, vals, fileName, entry->name.name, total_raw_width);
*ppFont = pFont;
return Successful;
}
static int
Type1GetGlyphs(FontPtr pFont,
unsigned long count,
unsigned char *chars,
FontEncoding charEncoding,
unsigned long *glyphCount,
CharInfoPtr *glyphs)
{
unsigned int firstRow;
unsigned int numRows;
CharInfoPtr *glyphsBase;
register unsigned int c;
register CharInfoPtr pci;
unsigned int r;
CharInfoPtr pDefault;
register struct type1font *type1Font;
register int firstCol;
type1Font = (struct type1font *) pFont->fontPrivate;
firstCol = pFont->info.firstCol;
pDefault = type1Font->pDefault;
glyphsBase = glyphs;
switch (charEncoding) {
#define EXIST(pci) \
((pci)->metrics.attributes || \
(pci)->metrics.ascent != -(pci)->metrics.descent || \
(pci)->metrics.leftSideBearing != (pci)->metrics.rightSideBearing)
case Linear8Bit:
case TwoD8Bit:
if (pFont->info.firstRow > 0)
break;
while (count--) {
c = (*chars++);
if (c >= firstCol &&
(pci = &type1Font->glyphs[c]) &&
EXIST(pci))
*glyphs++ = pci;
else if (pDefault)
*glyphs++ = pDefault;
}
break;
case Linear16Bit:
while (count--) {
c = *chars++ << 8;
c = (c | *chars++);
if (c < 256 && c >= firstCol &&
(pci = &type1Font->glyphs[c]) &&
EXIST(pci))
*glyphs++ = pci;
else if (pDefault)
*glyphs++ = pDefault;
}
break;
case TwoD16Bit:
firstRow = pFont->info.firstRow;
numRows = pFont->info.lastRow - firstRow + 1;
while (count--) {
r = (*chars++) - firstRow;
c = (*chars++);
if (r < numRows && c < 256 && c >= firstCol &&
(pci = &type1Font->glyphs[(r << 8) + c]) &&
EXIST(pci))
*glyphs++ = pci;
else if (pDefault)
*glyphs++ = pDefault;
}
break;
}
*glyphCount = glyphs - glyphsBase;
return Successful;
#undef EXIST
}
static int
Type1GetMetrics(FontPtr pFont,
unsigned long count,
unsigned char *chars,
FontEncoding charEncoding,
unsigned long *glyphCount,
xCharInfo **glyphs)
{
static CharInfoRec nonExistantChar;
int ret;
struct type1font *type1Font;
CharInfoPtr oldDefault;
type1Font = (struct type1font *) pFont->fontPrivate;
oldDefault = type1Font->pDefault;
type1Font->pDefault = &nonExistantChar;
ret = Type1GetGlyphs(pFont, count, chars, charEncoding, glyphCount, (CharInfoPtr *) glyphs);
type1Font->pDefault = oldDefault;
return ret;
}
void
Type1CloseFont(FontPtr pFont)
{
register int i;
struct type1font *type1;
type1 = (struct type1font *) pFont->fontPrivate;
for (i=0; i < 256; i++)
if (type1->glyphs[i].bits != NULL)
xfree(type1->glyphs[i].bits);
xfree(type1);
if (pFont->info.props)
xfree(pFont->info.props);
if (pFont->info.isStringProp)
xfree(pFont->info.isStringProp);
DestroyFontRec(pFont);
}
static void
fill(char *dest,
int h, int w,
struct region *area,
int byte, int bit,
int wordsize)
{
register struct edgelist *edge;
register char *p;
register int y;
register int wbytes = w / 8;
register pel *leftP,*rightP;
int xmin = area->xmin;
int ymin = area->ymin;
for (edge = area->anchor; VALIDEDGE(edge); edge = edge->link->link) {
p = dest + (edge->ymin - ymin) * wbytes;
leftP = edge->xvalues;
rightP = edge->link->xvalues;
for (y = edge->ymin; y < edge->ymax; y++) {
fillrun(p, *leftP++ - xmin, *rightP++ - xmin, bit);
p += wbytes;
}
}
if (byte == LSBFirst && wordsize != 8) {
register int i;
switch (wordsize) {
case 16:
{
register unsigned short data,*p;
p = (unsigned short *) dest;
for (i = h * w /16; --i >= 0;) {
data = *p;
*p++ = (data << 8) + (data >> 8);
}
break;
}
case 64:
case 32:
{
register unsigned long data,*p;
p = (unsigned long *) dest;
for (i = h * w / 32; --i >= 0;) {
data = *p;
*p++ = (data << 24) + (data >> 24)
+ (0xFF00 & (data >> 8))
+ (0xFF0000 & (data << 8));
}
if (wordsize == 64) {
p = (unsigned long *) dest;
for (i = h * w / 64; --i >= 0;) {
data = *p++;
p[-1] = p[0];
*p++ = data;
}
}
break;
}
default:
Abort("xiFill: unknown format");
}
}
}
#define ALLONES 0xFF
static void
fillrun(char *p,
pel x0, pel x1,
int bit)
{
register int startmask,endmask;
register int middle;
if (x1 <= x0)
return;
middle = x1/8 - x0/8;
p += x0/8;
x0 &= 7; x1 &= 7;
if (bit == LSBFirst) {
startmask = ALLONES << x0;
endmask = ~(ALLONES << x1);
}
else {
startmask = ALLONES >> x0;
endmask = ~(ALLONES >> x1);
}
if (middle == 0)
*p++ |= startmask & endmask;
else {
*p++ |= startmask;
while (--middle > 0)
*p++ = (char)ALLONES;
*p |= endmask;
}
}
#define CAPABILITIES (CAP_MATRIX | CAP_CHARSUBSETTING)
static FontRendererRec renderers[] = {
{ ".pfa", 4, NULL, Type1OpenScalable,
NULL, Type1GetInfoScalable, 0, CAPABILITIES },
{ ".pfb", 4, NULL, Type1OpenScalable,
NULL, Type1GetInfoScalable, 0, CAPABILITIES }
};
void
Type1RegisterFontFileFunctions(void)
{
int i;
T1InitStdProps();
for (i=0; i < sizeof(renderers) / sizeof(FontRendererRec); i++)
FontFilePriorityRegisterRenderer(&renderers[i], -10);
}