1 /*
2 * Copyright (C) 1997 and 1998 WIDE Project. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the project nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28 /*
29 * $Id: tfont.c,v 1.45 2007/11/24 17:29:40 nishida Exp $
30 */
31
32 #include "mgp.h"
33
34 #ifdef FREETYPE
35
36 int tfcachesize = 3000; /*XXX*/
37 #define TFFONT_NUM 128
38 #define TFHASH_SIZE 255
39 #define TFCACHE_HASH(c, siz) ((c ^ siz) % TFHASH_SIZE)
40
41 static TT_Raster_Map bitmap;
42 static TT_Face_Properties properties[TFFONT_NUM];
43 static TT_Face face[TFFONT_NUM];
44 static TT_Glyph glyph[TFFONT_NUM];
45 static TT_Instance instance[TFFONT_NUM];
46 static TT_Glyph_Metrics metrics;
47 static TT_Error error;
48 static TT_Engine engine;
49 static XImage *xim;
50
51 static char *tf_curname[4]; /* contains iso8859-[2-4] fonts */
52 static char *tf_mcurname = NULL;
53 static int tfcinitdone;
54 static int tfcachecnt;
55 static struct tfont tfclru;
56 static struct tfont tfcache[TFHASH_SIZE];
57 static int tffontcnt = 0;
58 static int tfcachehit = 0;
59 static int tfcachemiss = 0;
60 static int tfcuridx = -1;
61 static char tfloadedfont[1024][TFFONT_NUM];
62 static int tfloadedregistry[TFFONT_NUM];
63
64 #define TFC_INSHASH(tfc) { \
65 struct tfont *h, *n; \
66 h = &tfcache[TFCACHE_HASH(tfc->code, tfc->size)]; \
67 n = h->next; tfc->next = n; n->prev = tfc; \
68 h->next = tfc; tfc->prev = h; \
69 }
70 #define TFC_DELHASH(tfc) { \
71 struct tfont *n, *p; \
72 n = tfc->next; p = tfc->prev; \
73 n->prev = p; p->next = n; \
74 }
75 #define TFC_INSLRU(tfc) { \
76 struct tfont *p; \
77 p = tfclru.lruprev; tfc->lruprev = p; p->lrunext = tfc; \
78 tfclru.lruprev = tfc; tfc->lrunext = &tfclru; \
79 }
80 #define TFC_DELLRU(tfc) { \
81 struct tfont *n, *p; \
82 n = tfc->lrunext; p = tfc->lruprev; \
83 n->lruprev = p; p->lrunext = n; \
84 }
85
86 static void tfc_init __P((void));
87 static void tfc_free __P((struct tfont *));
88 static struct tfont *tfc_lookup __P((u_int, u_int, char*, int));
89 static struct tfont *tfc_alloc __P((u_int, u_int, char *, char *));
90 static short CharToUnicode __P((u_int, char *));
91 static short jistosjis __P((u_int));
92 static TT_Error LoadTrueTypeChar __P((int, int));
93
94 #define TTFLOOR(x) ((x) & -64)
95 #define TTCEIL(x) (((x) + 63) & -64)
96
97 static void
tfc_init()98 tfc_init()
99 {
100 u_int i;
101 struct tfont *tfc;
102
103 /* Initialize engine */
104 if ((error = TT_Init_FreeType(&engine))) {
105 fprintf(stderr, "Error while initializing engine, code = %d.\n",
106 (int)error);
107 cleanup(-1);
108 }
109
110 tfc = tfcache;
111 for (tfc = tfcache, i = 0; i < TFHASH_SIZE; tfc++, i++)
112 tfc->next = tfc->prev = tfc;
113 tfclru.lrunext = tfclru.lruprev = &tfclru;
114 tfcinitdone ++;
115
116 latin_unicode_map_init();
117 #ifdef FREETYPE_CHARSET16
118 unicode_map_init();
119 #endif
120 }
121
122 static void
tfc_free(tfc)123 tfc_free(tfc)
124 struct tfont *tfc;
125 {
126 TFC_DELHASH(tfc);
127 TFC_DELLRU(tfc);
128 free(tfc->fontname);
129 free(tfc->dbitmap);
130 free(tfc);
131 tfcachecnt--;
132 }
133
134 int
tfc_setsize(char_size)135 tfc_setsize(char_size)
136 u_int char_size;
137 {
138 if (!tfcinitdone)
139 return -1;
140
141 if (tfcuridx < 0 || tffontcnt <= tfcuridx) {
142 if (verbose)
143 fprintf(stderr, "tfc_setsize: font index out of bound\n");
144 return -1;
145 }
146
147 error = TT_Set_Instance_CharSize(instance[tfcuridx],
148 (char_size * 0.75) * 64);
149 if (error) {
150 fprintf(stderr,
151 "Could not set device resolutions for \"%s\".\n",
152 tfloadedfont[tfcuridx]);
153 return -1;
154 }
155 return 0;
156 }
157
158 struct tfont *
tfc_get(code,size,force,registry,charset16)159 tfc_get(code, size, force, registry, charset16)
160 u_int code, size;
161 int force;
162 char *registry;
163 int charset16;
164 {
165 struct tfont *tfc, *ntfc;
166 int regid;
167
168 if (!tfcinitdone)
169 tfc_init();
170
171 if (charset16)
172 tfc = tfc_lookup(code, size, tf_mcurname, 0);
173 else {
174 if (code >= 0xa0 && ((!registry || !registry[0]) && mgp_charset)){
175 regid = get_regid(mgp_charset);
176 } else
177 regid = get_regid(registry);
178 tfc = tfc_lookup(code, size, tf_curname[regid], regid);
179 }
180
181 if (tfc == NULL) {
182 /* XXX */
183 if (tfcachecnt >= tfcachesize) {
184 if (!force)
185 return NULL;
186 tfc = tfclru.lrunext;
187 while (tfcachecnt >= tfcachesize) {
188 if (tfc == &tfclru)
189 break;
190 ntfc = tfc->lrunext;
191 if (tfc->ref == 0)
192 tfc_free(tfc);
193 tfc = ntfc;
194 }
195 }
196
197 if (charset16)
198 tfc = tfc_alloc(code, size, tf_mcurname, registry);
199 else
200 tfc = tfc_alloc(code, size, tf_curname[regid], registry);
201 }
202 return tfc;
203 }
204
205 void
tfc_setfont(name,charset16,registry)206 tfc_setfont(name, charset16, registry)
207 char *name;
208 int charset16; /*2-octet charset?*/
209 char *registry;
210 {
211 char *fontname = NULL;
212 u_int i, regid = 0;
213 int res = 96; /* XXX */
214 char pathname[MAXPATHLEN];
215 int trial;
216 TT_Face tface;
217
218 if (!tfcinitdone)
219 tfc_init();
220
221 if (TFFONT_NUM <= tffontcnt) {
222 fprintf(stderr, "internal error: "
223 "too many fonts opened (increase TFFONT_NUM)\n");
224 cleanup(-1);
225 }
226
227 if (!name || !name[0]) {
228 if (freetypefont0 && freetypefont0[0]) {
229 if (verbose) {
230 fprintf(stderr, "tfc_setfont: "
231 "font name not given, "
232 "using last resort (%s)\n",
233 freetypefont0);
234 }
235 name = freetypefont0;
236 } else {
237 if (verbose) {
238 fprintf(stderr, "tfc_setfont: "
239 "font name not given, fail\n");
240 }
241 goto fail;
242 }
243 }
244
245 /* check font cache first */
246 for (trial = 0; trial < 2; trial++) {
247 switch (trial) {
248 case 0:
249 fontname = name;
250 break;
251 case 1:
252 snprintf(pathname, sizeof(pathname),
253 "%s/%s", freetypefontdir, name);
254 fontname = pathname;
255 break;
256 }
257
258 for (i = 0; i < tffontcnt; i ++) {
259 if (!strcmp(fontname, tfloadedfont[i])) {
260 /* already loaded */
261 #if 0
262 if (verbose) {
263 fprintf(stderr,
264 "font cache hit for \"%s\"\n",
265 fontname);
266 }
267 #endif
268 tfcuridx = i;
269 if (charset16)
270 tf_mcurname = tfloadedfont[i];
271 else {
272 regid = get_regid(registry);
273 tf_curname[regid] = tfloadedfont[i];
274 }
275 #if 0
276 tfc_setsize(char_size);
277 #endif
278 return;
279 }
280 }
281 }
282
283 /* try to load font */
284 for (trial = 0; trial < 3; trial++) {
285 switch (trial) {
286 case 0:
287 fontname = name;
288 break;
289 case 1:
290 snprintf(pathname, sizeof(pathname),
291 "%s/%s", freetypefontdir, name);
292 fontname = pathname;
293 break;
294 case 2:
295 if (!freetypefont0 || !freetypefont0[0])
296 continue;
297 fontname = freetypefont0;
298 /* already loaded? */
299 for (i = 0; i < tffontcnt; i ++) {
300 if (!strcmp(fontname, tfloadedfont[i])){
301 tfcuridx = i;
302 if (verbose)
303 fprintf(stderr, "font \"%s\" already loaded: %d\n",
304 fontname, tffontcnt);
305 goto cached;
306 }
307 }
308 break;
309 }
310
311 /* Load face */
312 if (verbose) fprintf(stderr, "trying to open font \"%s\"\n", fontname);
313 error = TT_Open_Face(engine, fontname, &tface);
314 if (!error)
315 break;
316 }
317 if (trial == 2) {
318 if (verbose) {
319 fprintf(stderr, "font \"%s\" not found, "
320 "last resort font \"%s\" was used\n",
321 name, freetypefont0);
322 }
323 } else if (trial == 3) {
324 if (verbose) {
325 fprintf(stderr, "could not load font \"%s\", "
326 "using other rendering engine\n", name);
327 }
328 goto fail;
329 }
330 if (verbose) {
331 fprintf(stderr, "font \"%s\" opened successfully\n",
332 fontname);
333 }
334
335 /* get registry id */
336 if ((regid = get_regid(registry)) < 0){
337 fprintf(stderr, "font \"%s\" has irregal registry\n", fontname);
338 goto fail2;
339 }
340
341 tfloadedregistry[tffontcnt] = regid;
342 strcpy(tfloadedfont[tffontcnt], fontname);
343 tfcuridx = tffontcnt;
344 face[tfcuridx] = tface;
345 tffontcnt++;
346
347 /* get face properties and allocate preload arrays */
348 error = TT_Get_Face_Properties(face[tfcuridx], &properties[tfcuridx]);
349 if (error) {
350 fprintf(stderr, "Could not create face property for "
351 "\"%s\" (err 0x%04x).\n", fontname, (int)error);
352 goto fail2;
353 }
354
355 /* create glyph */
356 error = TT_New_Glyph(face[tfcuridx], &glyph[tfcuridx]);
357 if (error) {
358 fprintf(stderr, "Could not create glyph container for "
359 "\"%s\" (err 0x%04x).\n", fontname, (int)error);
360 goto fail2;
361 }
362
363 /* create instance */
364 error = TT_New_Instance(face[tfcuridx], &instance[tfcuridx]);
365 if (error) {
366 fprintf(stderr, "Could not create instance for "
367 "\"%s\" (err 0x%04x).\n", fontname, (int)error);
368 goto fail2;
369 }
370
371 error = TT_Set_Instance_Resolutions(instance[tfcuridx], res, res);
372 if (error) {
373 fprintf(stderr, "Could not set device resolutions for "
374 "\"%s\" (err 0x%04x).\n", fontname, (int)error);
375 goto fail2;
376 }
377
378 cached:
379 if (charset16)
380 tf_mcurname = tfloadedfont[tfcuridx];
381 else {
382 if (registry)
383 tf_curname[regid] = tfloadedfont[tfcuridx];
384 else {
385 /* this should be default font */
386 for (i = 0; i < 4; i ++)
387 tf_curname[i] = tfloadedfont[tfcuridx];
388 }
389 }
390 if (tfc_setsize(char_size[caching]) < 0)
391 goto fail2;
392
393 /* success */
394 return;
395
396 fail2:
397 TT_Close_Face(tface);
398 tffontcnt--;
399 fail:
400 if (!charset16){
401 tf_curname[regid] = "";
402 tfcuridx = -1;
403 } else
404 tf_mcurname = "";
405 return;
406 }
407
408 static struct tfont *
tfc_lookup(code,size,fontname,regid)409 tfc_lookup(code, size, fontname, regid)
410 u_int code, size;
411 char *fontname;
412 int regid;
413 {
414 u_int i;
415 struct tfont *tfc, *htfc;
416
417 if (!fontname)
418 return NULL;
419
420 for (i = 0; i < tffontcnt; i ++) {
421 if (!strcmp(fontname, tfloadedfont[i]))
422 tfcuridx = i;
423 }
424
425 htfc = &tfcache[TFCACHE_HASH(code, size)];
426 for (tfc = htfc->next; tfc != htfc; tfc = tfc->next) {
427 if (tfc->code == code
428 && tfc->size == size
429 && tfc->regid == regid
430 && strcmp(tfc->fontname, fontname) == 0) {
431 tfcachehit++;
432 TFC_DELLRU(tfc);
433 TFC_INSLRU(tfc);
434 return tfc;
435 }
436 }
437 tfcachemiss++;
438
439 return NULL;
440 }
441
442 static struct tfont *
tfc_alloc(code,size,fontname,registry)443 tfc_alloc(code, size, fontname, registry)
444 u_int code, size;
445 char *fontname;
446 char *registry;
447 {
448 struct tfont *tfc;
449 short unicode;
450
451 /* if no font was ever loaded, try loading the last resort font */
452 if (!tffontcnt) {
453 if (verbose)
454 fprintf(stderr, "no fontcount\n");
455 tfc_setfont(NULL, 0, NULL);
456 }
457
458 /* font out of bounds, suggests no font was available */
459 if (tfcuridx < 0 || tffontcnt <= tfcuridx) {
460 if (verbose)
461 fprintf(stderr, "tfc_alloc: font index out of bound\n");
462 return NULL;
463 }
464
465 if (fontname == NULL)
466 return NULL;
467
468
469 /* This is required! */
470 if (tfc_setsize(char_size[caching]) < 0)
471 return NULL;
472
473 tfc = (struct tfont *)malloc(sizeof(*tfc));
474 if (tfc == NULL) {
475 fprintf(stderr, "tfc_alloc: malloc failed\n");
476 return NULL;
477 }
478
479 #if 1
480 unicode = CharToUnicode(code, registry);
481 #else
482 unicode = code;
483 #endif
484 if (!unicode)
485 return NULL;
486 if ((error = LoadTrueTypeChar(unicode, 0))) {
487 fprintf(stderr, "LoadTrueTypeChar fail %d\n", (int)error);
488 fprintf(stderr, "fontfile: \"%s\" char: '%c' (0x%04x)\n",
489 tfloadedfont[tfcuridx],
490 isprint(unicode) ? unicode : '?',
491 unicode);
492 return NULL;
493 }
494
495 TT_Get_Glyph_Metrics(glyph[tfcuridx], &metrics);
496
497 /*
498 * TT_Get_Glyph_Pixmap generates pixmap starting from FreeType
499 * origin (leftmost side, baseline). Because of this 3rd and 4th
500 * arguments are necessary.
501 * For X axis (3rd argument), we have to take metrics.bearingX as
502 * offset. Y axis must be shifted if there's descent box (image
503 * below the baseline). 4th argument is specified for that.
504 */
505 bitmap.rows = (metrics.bbox.yMax - metrics.bbox.yMin) >> 6;
506 bitmap.rows += 2; /* insurance to cope with number-round error */
507 bitmap.width = metrics.bbox.xMax - metrics.bbox.xMin;
508 bitmap.width >>= 6;
509 bitmap.width += 2; /* insurance to cope with number-round error */
510 bitmap.cols = (bitmap.width+3) & -4;
511 bitmap.flow = TT_Flow_Down;
512 bitmap.size = (long)bitmap.cols * bitmap.rows;
513 bitmap.bitmap = (void *)malloc((int)bitmap.size);
514 memset(bitmap.bitmap, 0, bitmap.size);
515
516 /* be very careful about CEIL/FLOOR. */
517 TT_Get_Glyph_Pixmap(glyph[tfcuridx], &bitmap,
518 TTCEIL(-metrics.bearingX),
519 TTCEIL(metrics.bbox.yMax - metrics.bbox.yMin - metrics.bearingY));
520
521 tfc->code = code;
522 tfc->size = size;
523 tfc->width = bitmap.width;
524 tfc->bwidth = bitmap.cols;
525 tfc->height = bitmap.rows;
526 /*
527 * ascent must be derived from descent, to avoid number-rounding
528 * errors.
529 */
530 tfc->descent =
531 TTCEIL(metrics.bbox.yMax - metrics.bbox.yMin - metrics.bearingY) >> 6;
532 tfc->ascent = bitmap.rows - tfc->descent;
533 tfc->xoff = metrics.bearingX >> 6;
534 tfc->fontname = strdup(fontname);
535 tfc->charlen = metrics.advance >> 6;
536 tfc->xmax = metrics.bbox.xMax >> 6;
537 tfc->ref = 0;
538 tfc->dbitmap = bitmap.bitmap;
539 tfc->regid = get_regid(registry);
540 if (!tfc->charlen) tfc->charlen = 1;
541
542 TFC_INSHASH(tfc);
543 TFC_INSLRU(tfc);
544 tfcachecnt++;
545
546 return tfc;
547 }
548
549 static short
CharToUnicode(code,registry)550 CharToUnicode(code, registry)
551 u_int code;
552 char *registry;
553 {
554 TT_CharMap char_map;
555 unsigned short i, n;
556 unsigned short platform, encoding;
557 unsigned int regid;
558 char p;
559
560 /* First, look for a Unicode charmap */
561 #ifdef HAVE_TT_FACE_PROPERTIES_CHARMAPS
562 n = properties[tfcuridx].num_CharMaps;
563 #else
564 n = TT_Get_CharMap_Count(face[tfcuridx]);
565 #endif
566
567 #if 1
568 if (verbose) {
569 fprintf(stderr, "%d charmaps for font %s code %04x\n",
570 n, tfloadedfont[tfcuridx], code & 0xffff);
571 }
572 #endif
573
574 for (i = 0; i < n; i++) {
575 TT_Get_CharMap_ID(face[tfcuridx], i, &platform, &encoding);
576 if ((platform == 3 && encoding == 1)
577 || (platform == 0 && encoding == 0)) {
578 TT_Get_CharMap(face[tfcuridx], i, &char_map);
579 #ifdef FREETYPE_CHARSET16
580 if (code > 256 && strncmp(registry, "jisx0208.1983-", 14) != 0) {
581 /*
582 * unicode_map assumes JIS X0208.
583 * it is not usable for other encodings.
584 * try the next CharMap available.
585 */
586 continue;
587 }
588 if (code > 256)
589 code = unicode_map[code];
590 #endif /* FREETYPE_CHARSET16 */
591
592 #if 1 /* latin2-4 encoding processing */
593 if (code > 0xa0 && code < 256) {
594 int tempregid;
595 if (registry)
596 tempregid = get_regid(registry) -1;
597 else {
598 if (mgp_charset)
599 tempregid = get_regid(mgp_charset)-1;
600 }
601 if (tempregid >= 0) {
602 regid = tempregid;
603 if (latin_unicode_map[regid][code])
604 code = latin_unicode_map[regid][code];
605 }
606 }
607 #endif
608
609 /*
610 * For freetype 1.4, suggested by mituharu@math.s.chiba-u.ac.jp
611 */
612 #if TT_FREETYPE_MAJOR == 1 && TT_FREETYPE_MINOR == 4
613 return TT_Char_Index(char_map, (u_short) code);
614 #else
615 return TT_Char_Index(char_map, (short) code);
616 #endif
617 }
618 #ifdef FREETYPE_CHARSET16
619 else {
620 /*
621 * very adhoc processing for truetype fonts generated by cb2ttj.
622 */
623 if ((platform == 3 && encoding == 2)
624 || (platform == 1 && encoding == 1)) {
625 if (code < 256) continue;
626 TT_Get_CharMap(face[tfcuridx], i, &char_map);
627 return TT_Char_Index(char_map, (u_short) jistosjis(code));
628 } else {
629 if (platform == 1 && encoding == 0) {
630 if (code >= 0xa0) continue;
631 TT_Get_CharMap(face[tfcuridx], i, &char_map);
632 return TT_Char_Index(char_map, (short) code);
633 }
634 #endif
635 else {
636 /* symbol font */
637 if (platform == 3 && encoding == 0) {
638 code |= 0xf000;
639 TT_Get_CharMap(face[tfcuridx],
640 i, &char_map);
641 return TT_Char_Index(char_map,
642 code);
643 }
644 }
645 #ifdef FREETYPE_CHARSET16
646 }
647 }
648 #endif
649 }
650
651 fprintf(stderr, "Sorry, but the fontfile \"%s\" doesn't "
652 "contain any Unicode mapping table\n", tfloadedfont[tfcuridx]);
653 return 0;
654 }
655
656 static TT_Error
LoadTrueTypeChar(int idx,int hint)657 LoadTrueTypeChar(int idx, int hint)
658 {
659 int flags;
660
661 flags = TTLOAD_SCALE_GLYPH;
662 if (hint)
663 flags |= TTLOAD_HINT_GLYPH;
664
665 return TT_Load_Glyph(instance[tfcuridx], glyph[tfcuridx], idx, flags);
666 }
667
668 /*
669 * NOTE: this is upper-layer's responsibility to adjust the (bx, by)
670 * so that the font bitmap fits into the given XImage.
671 * see draw_onechar_tf() for the code.
672 */
673 XImage *
tfc_image(tfc,fore,back,xim,bx,by)674 tfc_image(tfc, fore, back, xim, bx, by)
675 struct tfont *tfc;
676 long fore, back;
677 XImage *xim;
678 int bx, by;
679 {
680 int x, y;
681 static XColor col[5];
682 u_char d, *s;
683 u_long p;
684 XColor *bcol = NULL, *bc;
685 u_int charlen;
686
687 charlen = tfc->charlen;
688
689 if (back == -1) {
690 u_long r, g, b;
691 int dots;
692
693 dots = charlen * tfc->height;
694 bcol = malloc(sizeof(XColor) * dots);
695 if (bcol == NULL)
696 return NULL;
697 bc = bcol;
698 for (y = 0; y < tfc->height; y++) {
699 for (x = 0; x < charlen; x++, bc++) {
700 bc->pixel = XGetPixel(xim, bx + tfc->xoff + x,
701 by - tfc->ascent + y);
702 bc->flags = DoRed|DoGreen|DoBlue;
703 }
704 }
705 XQueryColors(display, colormap, bcol, dots);
706 r = g = b = 0;
707 for (y = 0; y < tfc->height; y++) {
708 for (x = 0; x < charlen; x++) {
709 r += bcol[x].red;
710 g += bcol[x].green;
711 b += bcol[x].blue;
712 }
713 }
714 r /= dots; g /= dots; b /= dots;
715 bc = &col[0];
716 if (bc->red == r && bc->green == g && bc->blue == b)
717 bc->pixel = back;
718 else {
719 bc->pixel = ~back;
720 bc->red = r; bc->green = g; bc->blue = b;
721 }
722 }
723 if (fore != col[4].pixel || back != col[0].pixel) {
724 col[4].pixel = fore;
725 col[4].flags = DoRed|DoGreen|DoBlue;
726 if (back != -1) {
727 col[3].pixel = back;
728 col[3].flags = DoRed|DoGreen|DoBlue;
729 XQueryColors(display, colormap, &col[3], 2);
730 col[0] = col[3];
731 } else {
732 XQueryColor(display, colormap, &col[4]);
733 }
734 for (x = 3; x > 0; x--) {
735 col[x].red = (col[4].red *x + col[0].red *(4-x)) /4;
736 col[x].green = (col[4].green*x + col[0].green*(4-x)) /4;
737 col[x].blue = (col[4].blue *x + col[0].blue *(4-x)) /4;
738 if (!XAllocColor(display, colormap, &col[x])) {
739 if (verbose)
740 printf("tfc_image: cannot allocate color for level %d (using %d)\n", x, x + 1);
741 col[x].pixel = col[x + 1].pixel;
742 }
743 else regist_alloc_colors(&font_clr, &col[x].pixel, 1);
744 }
745 }
746
747 /* XXX: need optimization */
748 s = tfc->dbitmap;
749 bc = bcol;
750 for (y = 0; y < tfc->height; y++) {
751 for (x = 0; x < tfc->bwidth; x++) {
752 d = *s++;
753 if (d && x < tfc->width) {
754 p = col[d].pixel;
755 XPutPixel(xim, bx + tfc->xoff + x,
756 by - tfc->ascent + y, p);
757 }
758 }
759 }
760 if (mgp_flag & FL_GLYPHEDGE) {
761 /*
762 * for debugging treatment of font metrics, for 16bpp displays
763 */
764 /* pixmap bounding box */
765 for (y = 0; y < tfc->height; y++) {
766 XPutPixel(xim, bx + tfc->xoff, by - tfc->ascent + y,
767 0xffff);
768 XPutPixel(xim, bx + tfc->xoff + tfc->width - 1,
769 by - tfc->ascent + y, 0xffff);
770 }
771 for (x = 0; x < tfc->width; x++) {
772 XPutPixel(xim, bx + tfc->xoff + x, by - tfc->ascent,
773 0xffff);
774 XPutPixel(xim, bx + tfc->xoff + x,
775 by - tfc->ascent + tfc->height - 1, 0xffff);
776 }
777 /* origin */
778 XPutPixel(xim, bx, by, 0xaaaa);
779 /* baseline */
780 for (x = 0; x < tfc->width; x++)
781 XPutPixel(xim, bx + tfc->xoff + x, by, 0xaaaa);
782 }
783 if (bcol)
784 free(bcol);
785 return xim;
786 }
787
788 static short
jistosjis(code)789 jistosjis(code)
790 u_int code;
791 {
792 u_char c1 = code >> 8;
793 u_char c2 = code % 256;
794 int rowOffset = c1 < 95 ? 112: 176;
795 int cellOffset = c1 % 2 ? (c2 > 95 ? 32 : 31) : 126;
796
797 return (((c1 + 1) >> 1) + rowOffset) * 256 + c2 + cellOffset;
798 }
799
800 #endif /* FRRETYPE */
801