1 //========================================================================
5 // Copyright 2001-2002 Glyph & Cog, LLC
7 //========================================================================
10 #pragma implementation
24 //------------------------------------------------------------------------
26 T1FontEngine::T1FontEngine(Display *displayA, Visual *visualA, int depthA,
27 Colormap colormapA, GBool aaA, GBool aaHighA):
28 SFontEngine(displayA, visualA, depthA, colormapA)
30 static unsigned long grayVals[17] = {
31 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
36 if (!T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE |
43 T1_AASetBitsPerPixel(8);
45 T1_AASetLevel(T1_AA_HIGH);
46 T1_AAHSetGrayValues(grayVals);
48 T1_AASetLevel(T1_AA_LOW);
49 T1_AASetGrayValues(0, 1, 2, 3, 4);
52 T1_AANSetGrayValues(0, 1);
57 T1FontEngine::~T1FontEngine() {
61 //------------------------------------------------------------------------
63 T1FontFile::T1FontFile(T1FontEngine *engineA, char *fontFileName,
64 char **fontEnc, double *bboxA) {
73 for (i = 0; i < 4; ++i) {
78 if ((id = T1_AddFont(fontFileName)) < 0) {
85 for (i = 0; i < 256; ++i) {
87 encStrSize += strlen(fontEnc[i]) + 1;
90 enc = (char **)gmalloc(257 * sizeof(char *));
91 encStr = (char *)gmalloc(encStrSize * sizeof(char));
93 for (i = 0; i < 256; ++i) {
95 strcpy(encPtr, fontEnc[i]);
97 encPtr += strlen(encPtr) + 1;
103 T1_ReencodeFont(id, enc);
108 T1FontFile::~T1FontFile() {
116 //------------------------------------------------------------------------
118 T1Font::T1Font(T1FontFile *fontFileA, double *m) {
119 T1FontEngine *engine;
122 double bbx0, bby0, bbx1, bby1;
123 int x, y, xMin, xMax, yMin, yMax;
127 fontFile = fontFileA;
128 engine = fontFile->engine;
130 id = T1_CopyFont(fontFile->id);
133 size = (float)sqrt(m[2]*m[2] + m[3]*m[3]);
135 // transform the four corners of the font bounding box -- the min
136 // and max values form the bounding box of the transformed font
137 bbx0 = fontFile->bbox[0];
138 bby0 = fontFile->bbox[1];
139 bbx1 = fontFile->bbox[2];
140 bby1 = fontFile->bbox[3];
141 // some fonts in PDF files have bboxes which are just plain wrong,
142 // so we check the font file's bbox too
143 bbox = T1_GetFontBBox(id);
144 if (0.001 * bbox.llx < bbx0) {
145 bbx0 = 0.001 * bbox.llx;
147 if (0.001 * bbox.lly < bby0) {
148 bby0 = 0.001 * bbox.lly;
150 if (0.001 * bbox.urx > bbx1) {
151 bbx1 = 0.001 * bbox.urx;
153 if (0.001 * bbox.ury > bby1) {
154 bby1 = 0.001 * bbox.ury;
156 // some fonts are completely broken, so we fake it (with values
157 // large enough that most glyphs should fit)
158 if (bbx0 == 0 && bby0 == 0 && bbx1 == 0 && bby1 == 0) {
162 x = (int)(m[0] * bbx0 + m[2] * bby0);
164 y = (int)(m[1] * bbx0 + m[3] * bby0);
166 x = (int)(m[0] * bbx0 + m[2] * bby1);
169 } else if (x > xMax) {
172 y = (int)(m[1] * bbx0 + m[3] * bby1);
175 } else if (y > yMax) {
178 x = (int)(m[0] * bbx1 + m[2] * bby0);
181 } else if (x > xMax) {
184 y = (int)(m[1] * bbx1 + m[3] * bby0);
187 } else if (y > yMax) {
190 x = (int)(m[0] * bbx1 + m[2] * bby1);
193 } else if (x > xMax) {
196 y = (int)(m[1] * bbx1 + m[3] * bby1);
199 } else if (y > yMax) {
202 // This is a kludge: some buggy PDF generators embed fonts with
203 // zero bounding boxes.
210 yMax = (int)(1.2 * size);
212 // Another kludge: an unusually large xMin or yMin coordinate is
220 // Another kludge: t1lib doesn't correctly handle fonts with
221 // real (non-integer) bounding box coordinates.
222 if (xMax - xMin > 5000) {
226 if (yMax - yMin > 5000) {
228 yMax = (int)(1.2 * size);
230 // this should be (max - min + 1), but we add some padding to
231 // deal with rounding errors
232 glyphW = xMax - xMin + 3;
233 glyphH = yMax - yMin + 3;
235 glyphSize = glyphW * glyphH;
237 glyphSize = ((glyphW + 7) >> 3) * glyphH;
240 // set up the glyph pixmap cache
242 if (glyphSize <= 256) {
244 } else if (glyphSize <= 512) {
246 } else if (glyphSize <= 1024) {
251 cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
252 cacheTags = (T1FontCacheTag *)gmalloc(cacheSets * cacheAssoc *
253 sizeof(T1FontCacheTag));
254 for (i = 0; i < cacheSets * cacheAssoc; ++i) {
255 cacheTags[i].mru = i & (cacheAssoc - 1);
259 if (!(image = XCreateImage(engine->display, engine->visual, engine->depth,
260 ZPixmap, 0, NULL, glyphW, glyphH, 8, 0))) {
263 image->data = (char *)gmalloc(glyphH * image->bytes_per_line);
265 // transform the font
266 matrix.cxx = m[0] / size;
267 matrix.cxy = m[1] / size;
268 matrix.cyx = m[2] / size;
269 matrix.cyy = m[3] / size;
270 T1_TransformFont(id, &matrix);
281 XDestroyImage(image);
286 GBool T1Font::drawChar(Drawable d, int w, int h, GC gc,
287 int x, int y, int r, int g, int b,
288 CharCode c, Unicode u) {
289 T1FontEngine *engine;
294 int xOffset, yOffset, x0, y0, x1, y1, gw, gh, w0, h0;
299 engine = fontFile->engine;
301 // generate the glyph pixmap
302 if (!(p = getGlyphPixmap(c, &xOffset, &yOffset, &gw, &gh))) {
306 // compute: (x0,y0) = position in destination drawable
307 // (x1,y1) = position in glyph image
308 // (w0,h0) = size of image transfer
339 XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1,
340 ZPixmap, image, x1, y1);
344 // compute the colors
345 xcolor.pixel = XGetPixel(image, x1 + w0/2, y1 + h0/2);
346 XQueryColor(engine->display, engine->colormap, &xcolor);
350 if (engine->aaHigh) {
352 for (i = 1; i <= 16; ++i) {
353 colors[i] = engine->findColor((i * r + (16 - i) * bgR) / 16,
354 (i * g + (16 - i) * bgG) / 16,
355 (i * b + (16 - i) * bgB) / 16);
359 colors[1] = engine->findColor((r + 3*bgR) / 4,
362 colors[2] = engine->findColor((r + bgR) / 2,
365 colors[3] = engine->findColor((3*r + bgR) / 4,
368 colors[4] = engine->findColor(r, g, b);
371 // stuff the glyph pixmap into the X image
372 for (yy = 0; yy < gh; ++yy) {
373 for (xx = 0; xx < gw; ++xx) {
379 XPutPixel(image, xx, yy, colors[pix]);
387 colors[1] = engine->findColor(r, g, b);
389 // stuff the glyph bitmap into the X image
390 for (yy = 0; yy < gh; ++yy) {
391 for (xx = 0; xx < gw; xx += 8) {
393 for (xx1 = xx; xx1 < xx + 8 && xx1 < gw; ++xx1) {
395 XPutPixel(image, xx1, yy, colors[1]);
405 XPutImage(engine->display, d, gc, image, x1, y1, x0, y0, w0, h0);
410 Guchar *T1Font::getGlyphPixmap(CharCode c, int *x, int *y, int *w, int *h) {
411 T1FontEngine *engine;
417 engine = fontFile->engine;
420 i = (c & (cacheSets - 1)) * cacheAssoc;
421 for (j = 0; j < cacheAssoc; ++j) {
422 if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) {
423 *x = cacheTags[i+j].x;
424 *y = cacheTags[i+j].y;
425 *w = cacheTags[i+j].w;
426 *h = cacheTags[i+j].h;
427 for (k = 0; k < cacheAssoc; ++k) {
429 (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) {
430 ++cacheTags[i+k].mru;
433 cacheTags[i+j].mru = 0x8000;
434 return cache + (i+j) * glyphSize;
438 // generate the glyph pixmap
440 glyph = T1_AASetChar(id, c, size, NULL);
442 glyph = T1_SetChar(id, c, size, NULL);
447 *x = -glyph->metrics.leftSideBearing;
448 *y = glyph->metrics.ascent;
449 *w = glyph->metrics.rightSideBearing - glyph->metrics.leftSideBearing;
450 *h = glyph->metrics.ascent - glyph->metrics.descent;
451 if (*w > glyphW || *h > glyphH) {
453 fprintf(stderr, "Weird t1lib glyph size: %d > %d or %d > %d\n",
454 *w, glyphW, *h, glyphH);
459 // store glyph pixmap in cache
461 for (j = 0; j < cacheAssoc; ++j) {
462 if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {
463 cacheTags[i+j].mru = 0x8000;
464 cacheTags[i+j].code = c;
465 cacheTags[i+j].x = *x;
466 cacheTags[i+j].y = *y;
467 cacheTags[i+j].w = *w;
468 cacheTags[i+j].h = *h;
472 gSize = ((*w + 7) >> 3) * *h;
474 ret = cache + (i+j) * glyphSize;
476 memcpy(ret, glyph->bits, gSize);
478 memset(ret, 0, gSize);
481 ++cacheTags[i+j].mru;
487 GBool T1Font::getCharPath(CharCode c, Unicode u, GfxState *state) {
490 T1_BEZIERSEGMENT *bez;
493 outline = T1_GetCharOutline(id, c, size, NULL);
496 for (seg = outline; seg; seg = seg->link) {
498 case T1_PATHTYPE_MOVE:
499 x += seg->dest.x / 65536.0;
500 y += seg->dest.y / 65536.0;
503 case T1_PATHTYPE_LINE:
504 x += seg->dest.x / 65536.0;
505 y += seg->dest.y / 65536.0;
508 case T1_PATHTYPE_BEZIER:
509 bez = (T1_BEZIERSEGMENT *)seg;
510 x1 = x + bez->dest.x / 65536.0;
511 y1 = y + bez->dest.y / 65536.0;
512 state->curveTo(x + bez->B.x / 65536.0, y + bez->B.y / 65536.0,
513 x + bez->C.x / 65536.0, y + bez->C.y / 65536.0,
520 T1_FreeOutline(outline);
524 #endif // HAVE_T1LIB_H