1 //========================================================================
5 //========================================================================
17 #include "FontEncoding.h"
20 //------------------------------------------------------------------------
22 T1FontEngine::T1FontEngine(Display *display, Visual *visual, int depth,
23 Colormap colormap, GBool aa, GBool aaHigh):
24 SFontEngine(display, visual, depth, colormap)
26 static unsigned long grayVals[17] = {
27 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
32 if (!T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE |
37 this->aaHigh = aaHigh;
39 T1_AASetBitsPerPixel(8);
41 T1_AASetLevel(T1_AA_HIGH);
42 T1_AAHSetGrayValues(grayVals);
44 T1_AASetLevel(T1_AA_LOW);
45 T1_AASetGrayValues(0, 1, 2, 3, 4);
48 T1_AANSetGrayValues(0, 1);
53 T1FontEngine::~T1FontEngine() {
57 //------------------------------------------------------------------------
59 T1FontFile::T1FontFile(T1FontEngine *engine, char *fontFileName,
60 FontEncoding *fontEnc) {
66 this->engine = engine;
69 if ((id = T1_AddFont(fontFileName)) < 0) {
76 for (i = 0; i < 256 && i < fontEnc->getSize(); ++i) {
77 if (fontEnc->getCharName(i)) {
78 encStrSize += strlen(fontEnc->getCharName(i)) + 1;
81 enc = (char **)gmalloc(257 * sizeof(char *));
82 encStr = (char *)gmalloc(encStrSize * sizeof(char));
84 for (i = 0; i < 256 && i < fontEnc->getSize(); ++i) {
85 if (fontEnc->getCharName(i)) {
86 strcpy(encPtr, fontEnc->getCharName(i));
88 encPtr += strlen(encPtr) + 1;
93 for (; i < 256; ++i) {
97 T1_ReencodeFont(id, enc);
102 T1FontFile::~T1FontFile() {
108 //------------------------------------------------------------------------
110 T1Font::T1Font(T1FontFile *fontFile, double *m) {
111 T1FontEngine *engine;
114 int x, y, xMin, xMax, yMin, yMax;
118 engine = fontFile->engine;
119 this->fontFile = fontFile;
121 id = T1_CopyFont(fontFile->id);
124 size = (float)sqrt(m[2]*m[2] + m[3]*m[3]);
126 // transform the four corners of the font bounding box -- the min
127 // and max values form the bounding box of the transformed font
128 bbox = T1_GetFontBBox(id);
129 x = (int)((m[0] * bbox.llx + m[2] * bbox.lly) * 0.001);
131 y = (int)((m[1] * bbox.llx + m[3] * bbox.lly) * 0.001);
133 x = (int)((m[0] * bbox.llx + m[2] * bbox.ury) * 0.001);
136 } else if (x > xMax) {
139 y = (int)((m[1] * bbox.llx + m[3] * bbox.ury) * 0.001);
142 } else if (y > yMax) {
145 x = (int)((m[0] * bbox.urx + m[2] * bbox.lly) * 0.001);
148 } else if (x > xMax) {
151 y = (int)((m[1] * bbox.urx + m[3] * bbox.lly) * 0.001);
154 } else if (y > yMax) {
157 x = (int)((m[0] * bbox.urx + m[2] * bbox.ury) * 0.001);
160 } else if (x > xMax) {
163 y = (int)((m[1] * bbox.urx + m[3] * bbox.ury) * 0.001);
166 } else if (y > yMax) {
170 //~ This is a kludge: some buggy PDF generators embed fonts with
171 //~ zero bounding boxes.
178 yMax = (int)(1.2 * size);
181 // this should be (max - min + 1), but we add some padding to
182 // deal with rounding errors
183 glyphW = xMax - xMin + 3;
184 glyphH = yMax - yMin + 3;
186 glyphSize = glyphW * glyphH;
188 glyphSize = ((glyphW + 7) >> 3) * glyphH;
191 // set up the glyph pixmap cache
193 if (glyphSize <= 256) {
195 } else if (glyphSize <= 512) {
197 } else if (glyphSize <= 1024) {
202 cache = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
203 cacheTags = (T1FontCacheTag *)gmalloc(cacheSets * cacheAssoc *
204 sizeof(T1FontCacheTag));
205 for (i = 0; i < cacheSets * cacheAssoc; ++i) {
206 cacheTags[i].mru = i & (cacheAssoc - 1);
210 if (!(image = XCreateImage(engine->display, engine->visual, engine->depth,
211 ZPixmap, 0, NULL, glyphW, glyphH, 8, 0))) {
214 image->data = (char *)gmalloc(glyphH * image->bytes_per_line);
216 // transform the font
217 matrix.cxx = m[0] / size;
218 matrix.cxy = m[1] / size;
219 matrix.cyx = m[2] / size;
220 matrix.cyy = m[3] / size;
221 T1_TransformFont(id, &matrix);
232 XDestroyImage(image);
237 GBool T1Font::drawChar(Drawable d, int w, int h, GC gc,
238 int x, int y, int r, int g, int b, Gushort c) {
239 T1FontEngine *engine;
244 int xOffset, yOffset, x0, y0, x1, y1, gw, gh, w0, h0;
249 engine = fontFile->engine;
251 // generate the glyph pixmap
252 if (!(p = getGlyphPixmap(c, &xOffset, &yOffset, &gw, &gh))) {
256 // compute: (x0,y0) = position in destination drawable
257 // (x1,y1) = position in glyph image
258 // (w0,h0) = size of image transfer
289 XGetSubImage(engine->display, d, x0, y0, w0, h0, (1 << engine->depth) - 1,
290 ZPixmap, image, x1, y1);
294 // compute the colors
295 xcolor.pixel = XGetPixel(image, x1, y1);
296 XQueryColor(engine->display, engine->colormap, &xcolor);
300 if (engine->aaHigh) {
302 for (i = 1; i <= 16; ++i) {
303 colors[i] = engine->findColor((i * r + (16 - i) * bgR) / 16,
304 (i * g + (16 - i) * bgG) / 16,
305 (i * b + (16 - i) * bgB) / 16);
309 colors[1] = engine->findColor((r + 3*bgR) / 4,
312 colors[2] = engine->findColor((r + bgR) / 2,
315 colors[3] = engine->findColor((3*r + bgR) / 4,
318 colors[4] = engine->findColor(r, g, b);
321 // stuff the glyph pixmap into the X image
322 for (yy = 0; yy < gh; ++yy) {
323 for (xx = 0; xx < gw; ++xx) {
329 XPutPixel(image, xx, yy, colors[pix]);
337 colors[1] = engine->findColor(r, g, b);
339 // stuff the glyph bitmap into the X image
340 for (yy = 0; yy < gh; ++yy) {
341 for (xx = 0; xx < gw; xx += 8) {
343 for (xx1 = xx; xx1 < xx + 8 && xx1 < gw; ++xx1) {
345 XPutPixel(image, xx1, yy, colors[1]);
355 XPutImage(engine->display, d, gc, image, x1, y1, x0, y0, w0, h0);
360 Guchar *T1Font::getGlyphPixmap(Gushort c, int *x, int *y, int *w, int *h) {
361 T1FontEngine *engine;
367 engine = fontFile->engine;
370 i = (c & (cacheSets - 1)) * cacheAssoc;
371 for (j = 0; j < cacheAssoc; ++j) {
372 if ((cacheTags[i+j].mru & 0x8000) && cacheTags[i+j].code == c) {
373 *x = cacheTags[i+j].x;
374 *y = cacheTags[i+j].y;
375 *w = cacheTags[i+j].w;
376 *h = cacheTags[i+j].h;
377 for (k = 0; k < cacheAssoc; ++k) {
379 (cacheTags[i+k].mru & 0x7fff) < (cacheTags[i+j].mru & 0x7fff)) {
380 ++cacheTags[i+k].mru;
383 cacheTags[i+j].mru = 0x8000;
384 return cache + (i+j) * glyphSize;
388 // generate the glyph pixmap
390 glyph = T1_AASetChar(id, c, size, NULL);
392 glyph = T1_SetChar(id, c, size, NULL);
397 *x = -glyph->metrics.leftSideBearing;
398 *y = glyph->metrics.ascent;
399 *w = glyph->metrics.rightSideBearing - glyph->metrics.leftSideBearing;
400 *h = glyph->metrics.ascent - glyph->metrics.descent;
401 if (*w > glyphW || *h > glyphH) {
403 fprintf(stderr, "Weird t1lib glyph size: %d > %d or %d > %d\n",
404 *w, glyphW, *h, glyphH);
409 // store glyph pixmap in cache
411 for (j = 0; j < cacheAssoc; ++j) {
412 if ((cacheTags[i+j].mru & 0x7fff) == cacheAssoc - 1) {
413 cacheTags[i+j].mru = 0x8000;
414 cacheTags[i+j].code = c;
415 cacheTags[i+j].x = *x;
416 cacheTags[i+j].y = *y;
417 cacheTags[i+j].w = *w;
418 cacheTags[i+j].h = *h;
422 gSize = ((*w + 7) >> 3) * *h;
424 ret = cache + (i+j) * glyphSize;
426 memcpy(ret, glyph->bits, gSize);
428 memset(ret, 0, gSize);
431 ++cacheTags[i+j].mru;
437 #endif // HAVE_T1LIB_H