summaryrefslogtreecommitdiff
path: root/src/Type1/cidchar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Type1/cidchar.c')
-rw-r--r--src/Type1/cidchar.c617
1 files changed, 617 insertions, 0 deletions
diff --git a/src/Type1/cidchar.c b/src/Type1/cidchar.c
new file mode 100644
index 0000000..e70d371
--- /dev/null
+++ b/src/Type1/cidchar.c
@@ -0,0 +1,617 @@
+/* Copyright (c) 1994-1999 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * The contents of this file are subject to the CID Font Code Public Licence
+ * Version 1.0 (the "License"). You may not use this file except in compliance
+ * with the Licence. You may obtain a copy of the License at Silicon Graphics,
+ * Inc., attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA
+ * 94043 or at http://www.sgi.com/software/opensource/cid/license.html.
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis.
+ * ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE OR OF
+ * NON-INFRINGEMENT. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Software is CID font code that was developed by Silicon
+ * Graphics, Inc.
+ */
+/* $XFree86: xc/lib/font/Type1/cidchar.c,v 1.9 2001/10/28 03:32:44 tsi Exp $ */
+
+#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" /* For INT32 declaration */
+#include "Xdefs.h" /* For Bool */
+#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 /* USE_MMAP */
+ if (cid->dataoffset == 0) {
+ p2 = sd;
+
+ /* find "StartData" */
+ 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 "StartData" not found, or end of file */
+ 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 "StartData" not found, or "Binary" data and the next character */
+ /* is not the space character (0x20) */
+
+ if (count == 0 || (CIDFontP->binarydata && (*p1 != ' '))) {
+ *rc = BadFontFormat;
+ fclose(fp);
+ return(cp);
+ }
+#endif /* USE_MMAP */
+
+ 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 is equal to 0, the CIDMap contains no FD indices, and the */
+ /* FD index of 0 is assumed. */
+ 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) { /* empty interval, missing glyph */
+ *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) {
+ /* get subroutine data */
+ 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];
+
+ /* get subroutine info */
+#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));
+
+ /* indicate that character bitmap is not defined */
+ cp->bits = (char *)CID_BITMAP_UNDEFINED;
+
+
+ /* get metric data for this CID code from the CID AFM file */
+ 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)
+{
+ int rc;
+ FILE *fp;
+ FontInfo *fi = NULL;
+ cidglyphs *cid;
+ CharInfoPtr *glyphsBase;
+ register unsigned int c;
+
+ register CharInfoPtr pci;
+ CharInfoPtr pDefault;
+ unsigned int firstRow, firstCol, numRows, code, char_row, char_col;
+ double sxmult;
+
+ cid = (cidglyphs *)pFont->fontPrivate;
+
+ if (cid->AFMinfo == NULL) {
+ if (!(fp = fopen(cidafmfile, "rb")))
+ return(BadFontName);
+
+ if ((rc = 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;
+
+ /* multiplier for computation of raw values */
+ 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:
+ firstRow = pFont->info.firstRow;
+ numRows = pFont->info.lastRow - firstRow + 1;
+ 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