#ifdef BUILDCID
#ifndef FONTMODULE
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#ifdef USE_MMAP
#include <sys/mman.h>
#ifndef MAP_FAILED
#define MAP_FAILED ((caddr_t)(-1))
#endif
#endif
#else
#include "Xmd.h"
#include "Xdefs.h"
#include "xf86_ansic.h"
#endif
#ifndef FONTMODULE
#ifdef _XOPEN_SOURCE
#include <math.h>
#else
#define _XOPEN_SOURCE
#include <math.h>
#undef _XOPEN_SOURCE
#endif
#endif
#include "fntfilst.h"
#include "objects.h"
#include "spaces.h"
#include "range.h"
#include "util.h"
#include "fontfcn.h"
#include "blues.h"
#include "AFM.h"
#include "t1intf.h"
#define BSIZE 4096
extern cidfont *CIDFontP;
extern psfont *FDArrayP;
extern psfont *FontP;
static unsigned char sd[] = "StartData";
CharInfoPtr
CIDGetGlyphInfo(FontPtr pFont, unsigned int cidcode, CharInfoPtr pci, int *rc)
{
CharInfoPtr cp = NULL;
#ifdef USE_MMAP
int fd;
unsigned char *buf;
long total_len = 0;
#else
FILE *fp;
unsigned char buf[BSIZE];
unsigned int count = 0;
#endif
cidglyphs *cid;
unsigned char *p1 = NULL;
#ifndef USE_MMAP
unsigned char *p2;
#endif
register int i = 0, j;
long byteoffset;
int FDindex, FDBytes, GDBytes, SDBytes, SubrCount, CIDMapOffset, len;
psobj *arrayP;
psobj charstring;
long *subroffsets = NULL, cstringoffset, nextcstringoffset;
struct blues_struct *blues;
cid = (cidglyphs *)pFont->fontPrivate;
#ifdef USE_MMAP
if (!cid->CIDdata) {
if (!(fd = open(cid->CIDFontName, O_RDONLY, 0))) {
*rc = BadFontName;
return(cp);
}
cid->CIDsize = lseek(fd, 0, SEEK_END);
cid->CIDdata = (unsigned char *)
mmap(0, (size_t)cid->CIDsize, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
if (cid->CIDdata == (unsigned char *)MAP_FAILED) {
*rc = AllocError;
cid->CIDdata = NULL;
return (cp);
}
}
#else
if (!(fp = fopen(cid->CIDFontName,"rb"))) {
*rc = BadFontName;
return(cp);
}
#endif
#ifdef USE_MMAP
if (cid->dataoffset == 0) {
if ((p1 = (unsigned char *)strstr((char *)cid->CIDdata, (char *)sd))
!= NULL) {
cid->dataoffset = (p1 - cid->CIDdata) + strlen((char *)sd);
}
else {
*rc = BadFontFormat;
return(cp);
}
}
#else
if (cid->dataoffset == 0) {
p2 = sd;
while (*p2) {
cid->dataoffset += count;
if ((count = fread(buf, 1, BSIZE, fp)) == 0)
break;
p1 = buf;
for (i=0; i < count && *p2; i++) {
if (*p1 == *p2)
p2++;
else {
p2 = sd;
if (*p1 == *p2)
p2++;
}
p1++;
}
}
if (*p2 || count == 0) {
*rc = BadFontFormat;
fclose(fp);
return(cp);
}
if (i >= count) {
cid->dataoffset += count;
count = fread(buf, 1, BSIZE, fp);
p1 = buf;
} else {
cid->dataoffset += p1 - buf;
count = count - (p1 - buf);
}
} else {
if (fseek(fp, cid->dataoffset, SEEK_SET)) {
*rc = BadFontFormat;
fclose(fp);
return(cp);
}
if ((count = fread(buf, 1, BSIZE, fp)) == 0) {
*rc = BadFontFormat;
fclose(fp);
return(cp);
}
p1 = buf;
}
if (count == 0 || (CIDFontP->binarydata && (*p1 != ' '))) {
*rc = BadFontFormat;
fclose(fp);
return(cp);
}
#endif
FDBytes = CIDFontP->CIDfontInfoP[CIDFDBYTES].value.data.integer;
GDBytes = CIDFontP->CIDfontInfoP[CIDGDBYTES].value.data.integer;
CIDMapOffset = CIDFontP->CIDfontInfoP[CIDMAPOFFSET].value.data.integer;
byteoffset = cid->dataoffset + 1 + CIDMapOffset +
cidcode * (FDBytes + GDBytes);
#ifdef USE_MMAP
buf = &cid->CIDdata[byteoffset];
#else
if (fseek(fp, byteoffset, SEEK_SET)) {
*rc = BadFontFormat;
fclose(fp);
return(cp);
}
if ((count = fread(buf, 1, BSIZE, fp)) < 2*(FDBytes + GDBytes)) {
*rc = BadFontFormat;
fclose(fp);
return(cp);
}
#endif
if (FDBytes == 0)
FDindex = 0;
else {
FDindex = 0;
for (i = 0; i < FDBytes; i++)
FDindex += (unsigned char)buf[i] << (8 * (FDBytes - 1 - i));
}
if (FDindex >= CIDFontP->CIDfontInfoP[CIDFDARRAY].value.len) {
*rc = BadFontFormat;
#ifndef USE_MMAP
fclose(fp);
#endif
return(cp);
}
cstringoffset = 0;
for (i = 0; i < GDBytes; i++)
cstringoffset += (unsigned char)buf[FDBytes + i] <<
(8 * (GDBytes - 1 - i));
nextcstringoffset = 0;
for (i = 0; i < GDBytes; i++)
nextcstringoffset += (unsigned char)buf[2*FDBytes + GDBytes + i] <<
(8 * (GDBytes - 1 - i));
len = nextcstringoffset - cstringoffset;
if (len <= 0) {
*rc = BadFontFormat;
#ifndef USE_MMAP
fclose(fp);
#endif
return(cp);
}
FontP = &FDArrayP[FDindex];
charstring.type = OBJ_INTEGER;
charstring.len = len;
#ifndef USE_MMAP
if (!(charstring.data.stringP = (unsigned char *)xalloc(len))) {
*rc = AllocError;
fclose(fp);
return(cp);
}
#endif
byteoffset = cid->dataoffset + 1 + cstringoffset;
#ifdef USE_MMAP
charstring.data.stringP = &cid->CIDdata[byteoffset];
#else
if (fseek(fp, byteoffset, SEEK_SET)) {
*rc = BadFontFormat;
xfree(charstring.data.stringP);
fclose(fp);
return(cp);
}
if ((count = fread(charstring.data.stringP, 1, len, fp)) != len) {
*rc = BadFontFormat;
xfree(charstring.data.stringP);
fclose(fp);
return(cp);
}
#endif
if (FontP->Subrs.data.arrayP == NULL) {
byteoffset = cid->dataoffset + 1 +
FDArrayP[FDindex].Private[CIDT1SUBMAPOFF].value.data.integer;
SDBytes = FDArrayP[FDindex].Private[CIDT1SDBYTES].value.data.integer;
SubrCount = FDArrayP[FDindex].Private[CIDT1SUBRCNT].value.data.integer;
#ifdef USE_MMAP
buf = &cid->CIDdata[byteoffset];
#else
if (fseek(fp, byteoffset, SEEK_SET)) {
*rc = BadFontFormat;
fclose(fp);
return(cp);
}
if ((count = fread(buf, 1, BSIZE, fp)) < SDBytes * (SubrCount + 1)) {
*rc = BadFontFormat;
fclose(fp);
return(cp);
}
#endif
arrayP = (psobj *)vm_alloc(SubrCount*sizeof(psobj));
if (!arrayP) {
*rc = AllocError;
#ifndef USE_MMAP
fclose(fp);
#endif
return(cp);
}
if (!(subroffsets = (long *)xalloc((SubrCount + 1)*sizeof(long)))) {
*rc = AllocError;
#ifndef USE_MMAP
fclose(fp);
#endif
return(cp);
}
for (i = 0; i <= SubrCount; i++) {
subroffsets[i] = 0;
for (j = 0; j < SDBytes; j++)
subroffsets[i] += (unsigned char)buf[i * SDBytes + j] <<
(8 * (SDBytes - 1 - j));
}
byteoffset = cid->dataoffset + 1 + subroffsets[0];
#ifndef USE_MMAP
if (fseek(fp, byteoffset, SEEK_SET)) {
*rc = BadFontFormat;
xfree(subroffsets);
fclose(fp);
return(cp);
}
#else
total_len = byteoffset;
#endif
for (i = 0; i < SubrCount; i++) {
len = subroffsets[i + 1] - subroffsets[i];
#ifndef USE_MMAP
arrayP[i].data.valueP = vm_alloc(len);
if (!arrayP[i].data.valueP) {
*rc = AllocError;
xfree(subroffsets);
fclose(fp);
return(cp);
}
#endif
arrayP[i].len = len;
#ifdef USE_MMAP
arrayP[i].data.valueP = (char *)&cid->CIDdata[total_len];
total_len += len;
#else
if ((count = fread(arrayP[i].data.valueP, 1, len, fp)) != len) {
*rc = BadFontFormat;
xfree(subroffsets);
fclose(fp);
return(cp);
}
#endif
}
FontP->Subrs.len = SubrCount;
FontP->Subrs.data.arrayP = arrayP;
xfree(subroffsets);
}
if (FontP->BluesP == NULL) {
blues = (struct blues_struct *) vm_alloc(sizeof(struct blues_struct));
if (!blues) {
*rc = AllocError;
#ifndef USE_MMAP
xfree(subroffsets);
fclose(fp);
#endif
return(cp);
}
bzero(blues, sizeof(struct blues_struct));
blues->numBlueValues =
FDArrayP[FDindex].Private[CIDT1BLUEVALUES].value.len;
for (i = 0; i < blues->numBlueValues; i++)
blues->BlueValues[i] =
FDArrayP[FDindex].Private[CIDT1BLUEVALUES].value.data.arrayP[i].data.integer;
blues->numOtherBlues =
FDArrayP[FDindex].Private[CIDT1OTHERBLUES].value.len;
for (i = 0; i < blues->numOtherBlues; i++)
blues->OtherBlues[i] =
FDArrayP[FDindex].Private[CIDT1OTHERBLUES].value.data.arrayP[i].data.integer;
blues->numFamilyBlues =
FDArrayP[FDindex].Private[CIDT1FAMBLUES].value.len;
for (i = 0; i < blues->numFamilyBlues; i++)
blues->FamilyBlues[i] =
FDArrayP[FDindex].Private[CIDT1FAMBLUES].value.data.arrayP[i].data.integer;
blues->numFamilyOtherBlues =
FDArrayP[FDindex].Private[CIDT1FAMOTHERBLUES].value.len;
for (i = 0; i < blues->numFamilyOtherBlues; i++)
blues->FamilyOtherBlues[i] =
FDArrayP[FDindex].Private[CIDT1FAMOTHERBLUES].value.data.arrayP[i].data.integer;
blues->BlueScale = FDArrayP[FDindex].Private[CIDT1BLUESCALE].value.data.real;
blues->BlueShift = FDArrayP[FDindex].Private[CIDT1BLUESHIFT].value.data.integer;
blues->BlueFuzz = FDArrayP[FDindex].Private[CIDT1BLUEFUZZ].value.data.integer;
blues->StdHW = (double)FDArrayP[FDindex].Private[CIDT1STDHW].value.data.arrayP[0].data.integer;
blues->StdVW = (double)FDArrayP[FDindex].Private[CIDT1STDVW].value.data.arrayP[0].data.integer;
blues->numStemSnapH =
FDArrayP[FDindex].Private[CIDT1STEMSNAPH].value.len;
for (i = 0; i < blues->numStemSnapH; i++)
blues->StemSnapH[i] =
FDArrayP[FDindex].Private[CIDT1STEMSNAPH].value.data.arrayP[i].data.integer;
blues->numStemSnapV =
FDArrayP[FDindex].Private[CIDT1STEMSNAPV].value.len;
for (i = 0; i < blues->numStemSnapV; i++)
blues->StemSnapV[i] =
FDArrayP[FDindex].Private[CIDT1STEMSNAPV].value.data.arrayP[i].data.integer;
blues->ForceBold =
FDArrayP[FDindex].Private[CIDT1FORCEBOLD].value.data.boolean;
blues->LanguageGroup =
FDArrayP[FDindex].Private[CIDT1LANGGROUP].value.data.integer;
blues->RndStemUp =
FDArrayP[FDindex].Private[CIDT1RNDSTEMUP].value.data.boolean;
blues->lenIV =
FDArrayP[FDindex].Private[CIDT1LENIV].value.data.integer;
blues->ExpansionFactor =
FDArrayP[FDindex].Private[CIDT1EXPFACTOR].value.data.real;
FontP->BluesP = blues;
}
cp = CIDRenderGlyph(pFont, &charstring, &FontP->Subrs, FontP->BluesP, pci, rc);
#ifndef USE_MMAP
xfree(charstring.data.stringP);
fclose(fp);
#endif
return(cp);
}
static int
node_compare(const void *node1, const void *node2)
{
return (((Metrics *)node1)->code - ((Metrics *)node2)->code);
}
static CharInfoRec *
CIDGetCharMetrics(FontPtr pFont, FontInfo *fi, unsigned int charcode, double sxmult)
{
CharInfoPtr cp;
Metrics *p, node;
unsigned int cidcode;
cidcode = node.code = getCID(pFont, charcode);
if ((cidcode < fi->nChars) && (cidcode == fi->metrics[cidcode].code))
p = &fi->metrics[cidcode];
else
p = (Metrics *)bsearch(&node, fi->metrics, fi->nChars, sizeof(Metrics), node_compare);
if (!p)
p = &fi->metrics[0];
if (!(cp = (CharInfoRec *)Xalloc(sizeof(CharInfoRec))))
return NULL;
bzero(cp, sizeof(CharInfoRec));
cp->bits = (char *)CID_BITMAP_UNDEFINED;
cp->metrics.leftSideBearing =
floor(p->charBBox.llx / sxmult + 0.5);
cp->metrics.rightSideBearing =
floor(p->charBBox.urx / sxmult + 0.5);
cp->metrics.characterWidth = floor(p->wx / sxmult + 0.5);
cp->metrics.ascent = floor(p->charBBox.ury / sxmult + 0.5);
cp->metrics.descent = -floor(p->charBBox.lly / sxmult + 0.5);
cp->metrics.attributes = p->wx;
return cp;
}
int
CIDGetAFM(FontPtr pFont, unsigned long count, unsigned char *chars, FontEncoding charEncoding, unsigned long *glyphCount, CharInfoPtr *glyphs, char *cidafmfile)
{
FILE *fp;
FontInfo *fi = NULL;
cidglyphs *cid;
CharInfoPtr *glyphsBase;
register unsigned int c;
register CharInfoPtr pci;
CharInfoPtr pDefault;
unsigned int firstCol, code, char_row, char_col;
double sxmult;
cid = (cidglyphs *)pFont->fontPrivate;
if (cid->AFMinfo == NULL) {
if (!(fp = fopen(cidafmfile, "rb")))
return(BadFontName);
if (CIDAFM(fp, &fi) != 0) {
fprintf(stderr,
"There is something wrong with Adobe Font Metric file %s.\n",
cidafmfile);
fclose(fp);
return(BadFontName);
}
fclose(fp);
cid->AFMinfo = fi;
}
fi = cid->AFMinfo;
firstCol = pFont->info.firstCol;
pDefault = cid->pDefault;
glyphsBase = glyphs;
sxmult = hypot(cid->pixel_matrix[0], cid->pixel_matrix[1]);
if (sxmult > EPS) sxmult = 1000.0 / sxmult;
if (sxmult == 0.0) return(0);
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 && c <= pFont->info.lastCol) {
code = c - firstCol;
if (!(pci = (CharInfoRec *)cid->glyphs[code]))
pci = CIDGetCharMetrics(pFont, fi, c, sxmult);
if (pci && EXIST(pci)) {
*glyphs++ = pci;
cid->glyphs[code] = pci;
}
} else if (pDefault)
*glyphs++ = pDefault;
}
break;
case Linear16Bit:
while (count--) {
char_row = *chars++;
char_col = *chars++;
c = char_row << 8;
c = (c | char_col);
if (pFont->info.firstRow <= char_row && char_row <=
pFont->info.lastRow && pFont->info.firstCol <= char_col &&
char_col <= pFont->info.lastCol) {
code = pFont->info.lastCol - pFont->info.firstCol + 1;
char_row = char_row - pFont->info.firstRow;
char_col = char_col - pFont->info.firstCol;
code = char_row * code + char_col;
if (!(pci = (CharInfoRec *)cid->glyphs[code]))
pci = CIDGetCharMetrics(pFont, fi, c, sxmult);
if (pci && EXIST(pci)) {
*glyphs++ = pci;
cid->glyphs[code] = pci;
} else if (pDefault) {
*glyphs++ = pDefault;
cid->glyphs[code] = pDefault;
}
} else if (pDefault)
*glyphs++ = pDefault;
}
break;
case TwoD16Bit:
while (count--) {
char_row = (*chars++);
char_col = (*chars++);
c = char_row << 8;
c = (c | char_col);
if (pFont->info.firstRow <= char_row && char_row <=
pFont->info.lastRow && pFont->info.firstCol <= char_col &&
char_col <= pFont->info.lastCol) {
code = pFont->info.lastCol - pFont->info.firstCol + 1;
char_row = char_row - pFont->info.firstRow;
char_col = char_col - pFont->info.firstCol;
code = char_row * code + char_col;
if (!(pci = (CharInfoRec *)cid->glyphs[code]))
pci = CIDGetCharMetrics(pFont, fi, c, sxmult);
if (pci && EXIST(pci)) {
*glyphs++ = pci;
cid->glyphs[code] = pci;
} else if (pDefault) {
*glyphs++ = pDefault;
cid->glyphs[code] = pDefault;
}
} else if (pDefault)
*glyphs++ = pDefault;
}
break;
}
*glyphCount = glyphs - glyphsBase;
#undef EXIST
return Successful;
}
#endif