wsfont.c revision 1.52 1 /* $NetBSD: wsfont.c,v 1.52 2011/12/28 18:29:48 macallan Exp $ */
2
3 /*-
4 * Copyright (c) 1999, 2000, 2001, 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: wsfont.c,v 1.52 2011/12/28 18:29:48 macallan Exp $");
34
35 #include "opt_wsfont.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/time.h>
40 #include <sys/malloc.h>
41 #include <sys/queue.h>
42
43 #include <dev/wscons/wsdisplayvar.h>
44 #include <dev/wscons/wsconsio.h>
45 #include <dev/wsfont/wsfont.h>
46
47 #include "wsfont_glue.h" /* NRASOPS_ROTATION */
48
49 #undef HAVE_FONT
50
51 #ifdef FONT_QVSS8x15
52 #define HAVE_FONT 1
53 #include <dev/wsfont/qvss8x15.h>
54 #endif
55
56 #ifdef FONT_GALLANT12x22
57 #define HAVE_FONT 1
58 #include <dev/wsfont/gallant12x22.h>
59 #endif
60
61 #ifdef FONT_LUCIDA16x29
62 #define HAVE_FONT 1
63 #include <dev/wsfont/lucida16x29.h>
64 #endif
65
66 #ifdef FONT_VT220L8x8
67 #define HAVE_FONT 1
68 #include <dev/wsfont/vt220l8x8.h>
69 #endif
70
71 #ifdef FONT_VT220L8x10
72 #define HAVE_FONT 1
73 #include <dev/wsfont/vt220l8x10.h>
74 #endif
75
76 #ifdef FONT_VT220L8x16
77 #define HAVE_FONT 1
78 #include <dev/wsfont/vt220l8x16.h>
79 #endif
80
81 #ifdef FONT_VT220ISO8x8
82 #define HAVE_FONT 1
83 #include <dev/wsfont/vt220iso8x8.h>
84 #endif
85
86 #ifdef FONT_VT220ISO8x16
87 #define HAVE_FONT 1
88 #include <dev/wsfont/vt220iso8x16.h>
89 #endif
90
91 #ifdef FONT_VT220KOI8x10_KOI8_R
92 #define HAVE_FONT 1
93 #include <dev/wsfont/vt220koi8x10.h>
94 #endif
95
96 #ifdef FONT_VT220KOI8x10_KOI8_U
97 #define HAVE_FONT 1
98 #define KOI8_U
99 #include <dev/wsfont/vt220koi8x10.h>
100 #undef KOI8_U
101 #endif
102
103 #ifdef FONT_SONY8x16
104 #define HAVE_FONT 1
105 #include <dev/wsfont/sony8x16.h>
106 #endif
107
108 #ifdef FONT_SONY12x24
109 #define HAVE_FONT 1
110 #include <dev/wsfont/sony12x24.h>
111 #endif
112
113 #ifdef FONT_OMRON12x20
114 #define HAVE_FONT 1
115 #include <dev/wsfont/omron12x20.h>
116 #endif
117
118 #ifdef FONT_DEJAVU_SANS_MONO12x22
119 #include <dev/wsfont/DejaVu_Sans_Mono_12x22.h>
120 #endif
121
122 #ifdef FONT_DROID_SANS_MONO12x22
123 #include <dev/wsfont/Droid_Sans_Mono_12x22.h>
124 #endif
125
126 #ifdef FONT_DROID_SANS_MONO9x18
127 #include <dev/wsfont/Droid_Sans_Mono_9x18.h>
128 #endif
129
130 #ifdef FONT_FREEMONO12x22
131 #include <dev/wsfont/FreeMono_12x22.h>
132 #endif
133
134 /* Make sure we always have at least one font. */
135 #ifndef HAVE_FONT
136 #define HAVE_FONT 1
137 #define FONT_BOLD8x16 1
138 #endif
139
140 #ifdef FONT_BOLD8x16
141 #include <dev/wsfont/bold8x16.h>
142 #endif
143
144 #define WSFONT_IDENT_MASK 0xffffff00
145 #define WSFONT_IDENT_SHIFT 8
146 #define WSFONT_BITO_MASK 0x000000f0
147 #define WSFONT_BITO_SHIFT 4
148 #define WSFONT_BYTEO_MASK 0x0000000f
149 #define WSFONT_BYTEO_SHIFT 0
150
151 #define WSFONT_BUILTIN 0x01 /* In wsfont.c */
152 #define WSFONT_STATIC 0x02 /* Font structures not malloc()ed */
153 #define WSFONT_COPY 0x04 /* Copy of existing font in table */
154
155 /* Placeholder struct used for linked list */
156 struct font {
157 TAILQ_ENTRY(font) chain;
158 struct wsdisplay_font *font;
159 u_int lockcount;
160 u_int cookie;
161 u_int flags;
162 };
163
164 /* Our list of built-in fonts */
165 static struct font builtin_fonts[] = {
166 #ifdef FONT_BOLD8x16
167 { { NULL, NULL }, &bold8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
168 #endif
169 #ifdef FONT_ISO8x16
170 { { NULL, NULL }, &iso8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
171 #endif
172 #ifdef FONT_COURIER11x18
173 { { NULL, NULL }, &courier11x18, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
174 #endif
175 #ifdef FONT_GALLANT12x22
176 { { NULL, NULL }, &gallant12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
177 #endif
178 #ifdef FONT_LUCIDA16x29
179 { { NULL, NULL }, &lucida16x29, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
180 #endif
181 #ifdef FONT_QVSS8x15
182 { { NULL, NULL }, &qvss8x15, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
183 #endif
184 #ifdef FONT_VT220L8x8
185 { { NULL, NULL }, &vt220l8x8, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
186 #endif
187 #ifdef FONT_VT220L8x10
188 { { NULL, NULL }, &vt220l8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
189 #endif
190 #ifdef FONT_VT220L8x16
191 { { NULL, NULL }, &vt220l8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
192 #endif
193 #ifdef FONT_VT220ISO8x8
194 { { NULL, NULL }, &vt220iso8x8, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
195 #endif
196 #ifdef FONT_VT220ISO8x16
197 { { NULL, NULL }, &vt220iso8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
198 #endif
199 #ifdef FONT_VT220KOI8x10_KOI8_R
200 { { NULL, NULL }, &vt220kr8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
201 #endif
202 #ifdef FONT_VT220KOI8x10_KOI8_U
203 { { NULL, NULL }, &vt220ku8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
204 #endif
205 #ifdef FONT_SONY8x16
206 { { NULL, NULL }, &sony8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
207 #endif
208 #ifdef FONT_SONY12x24
209 { { NULL, NULL }, &sony12x24, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
210 #endif
211 #ifdef FONT_OMRON12x20
212 { { NULL, NULL }, &omron12x20, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
213 #endif
214 { { NULL, NULL }, NULL, 0, 0, 0 },
215 };
216 static struct font builtin_aa_fonts[] = {
217 #ifdef FONT_DEJAVU_SANS_MONO12x22
218 { { NULL, NULL }, &DejaVu_Sans_Mono_12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
219 #endif
220 #ifdef FONT_DROID_SANS_MONO12x22
221 { { NULL, NULL }, &Droid_Sans_Mono_12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
222 #endif
223 #ifdef FONT_DROID_SANS_MONO9x18
224 { { NULL, NULL }, &Droid_Sans_Mono_9x18, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
225 #endif
226 #ifdef FONT_FREEMONO12x22
227 { { NULL, NULL }, &FreeMono_12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
228 #endif
229 { { NULL, NULL }, NULL, 0, 0, 0 },
230 };
231
232 static TAILQ_HEAD(,font) list;
233 static TAILQ_HEAD(,font) aa_list;
234 static int ident;
235
236 /* Reverse the bit order in a byte */
237 static const u_char reverse[256] = {
238 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
239 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
240 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
241 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
242 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
243 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
244 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
245 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
246 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
247 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
248 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
249 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
250 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
251 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
252 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
253 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
254 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
255 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
256 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
257 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
258 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
259 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
260 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
261 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
262 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
263 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
264 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
265 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
266 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
267 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
268 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
269 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
270 };
271
272 static struct font *wsfont_find0(int, int);
273 static struct font *wsfont_add0(struct wsdisplay_font *, int);
274 static void wsfont_revbit(struct wsdisplay_font *);
275 static void wsfont_revbyte(struct wsdisplay_font *);
276 static inline int wsfont_make_cookie(int, int, int);
277
278 static inline int
279 wsfont_make_cookie(int cident, int bito, int byteo)
280 {
281
282 return ((cident & WSFONT_IDENT_MASK) |
283 (bito << WSFONT_BITO_SHIFT) |
284 (byteo << WSFONT_BYTEO_SHIFT));
285 }
286
287 static void
288 wsfont_revbit(struct wsdisplay_font *font)
289 {
290 u_char *p, *m;
291
292 p = (u_char *)font->data;
293 m = p + font->stride * font->numchars * font->fontheight;
294
295 for (; p < m; p++)
296 *p = reverse[*p];
297 }
298
299 static void
300 wsfont_revbyte(struct wsdisplay_font *font)
301 {
302 int x, l, r, nr;
303 u_char *rp;
304
305 if (font->stride == 1)
306 return;
307
308 rp = (u_char *)font->data;
309 nr = font->numchars * font->fontheight;
310
311 while (nr--) {
312 l = 0;
313 r = font->stride - 1;
314
315 while (l < r) {
316 x = rp[l];
317 rp[l] = rp[r];
318 rp[r] = x;
319 l++, r--;
320 }
321
322 rp += font->stride;
323 }
324 }
325
326 void
327 wsfont_enum(void (*cb)(const char *, int, int, int))
328 {
329 struct wsdisplay_font *f;
330 struct font *ent;
331
332 TAILQ_FOREACH(ent, &list, chain) {
333 f = ent->font;
334 cb(f->name, f->fontwidth, f->fontheight, f->stride);
335 }
336 }
337
338 #if NRASOPS_ROTATION > 0
339
340 struct wsdisplay_font *wsfont_rotate_cw_internal(struct wsdisplay_font *);
341 struct wsdisplay_font *wsfont_rotate_ccw_internal(struct wsdisplay_font *);
342
343 struct wsdisplay_font *
344 wsfont_rotate_cw_internal(struct wsdisplay_font *font)
345 {
346 int b, n, r, namelen, newstride;
347 struct wsdisplay_font *newfont;
348 char *newname, *newbits;
349
350 /* Duplicate the existing font... */
351 newfont = malloc(sizeof(*font), M_DEVBUF, M_WAITOK);
352 if (newfont == NULL)
353 return (NULL);
354
355 *newfont = *font;
356
357 namelen = strlen(font->name) + 4;
358 newname = malloc(namelen, M_DEVBUF, M_WAITOK);
359 strlcpy(newname, font->name, namelen);
360 strlcat(newname, "cw", namelen);
361 newfont->name = newname;
362
363 /* Allocate a buffer big enough for the rotated font. */
364 newstride = (font->fontheight + 7) / 8;
365 newbits = malloc(newstride * font->fontwidth * font->numchars,
366 M_DEVBUF, M_WAITOK|M_ZERO);
367 if (newbits == NULL) {
368 free(newfont, M_DEVBUF);
369 return (NULL);
370 }
371
372 /* Rotate the font a bit at a time. */
373 for (n = 0; n < font->numchars; n++) {
374 unsigned char *ch = (unsigned char *)font->data +
375 (n * font->stride * font->fontheight);
376
377 for (r = 0; r < font->fontheight; r++) {
378 for (b = 0; b < font->fontwidth; b++) {
379 unsigned char *rb;
380
381 rb = ch + (font->stride * r) + (b / 8);
382 if (*rb & (0x80 >> (b % 8))) {
383 unsigned char *rrb;
384
385 rrb = newbits + newstride - 1 - (r / 8)
386 + (n * newstride * font->fontwidth)
387 + (newstride * b);
388 *rrb |= (1 << (r % 8));
389 }
390 }
391 }
392 }
393
394 newfont->data = newbits;
395
396 /* Update font sizes. */
397 newfont->stride = newstride;
398 newfont->fontwidth = font->fontheight;
399 newfont->fontheight = font->fontwidth;
400
401 if (wsfont_add(newfont, 0) != 0) {
402 /*
403 * If we seem to have rotated this font already, drop the
404 * new one...
405 */
406 free(newbits, M_DEVBUF);
407 free(newfont, M_DEVBUF);
408 newfont = NULL;
409 }
410
411 return (newfont);
412 }
413
414 struct wsdisplay_font *
415 wsfont_rotate_ccw_internal(struct wsdisplay_font *font)
416 {
417 int b, n, r, namelen, newstride;
418 struct wsdisplay_font *newfont;
419 char *newname, *newbits;
420
421 /* Duplicate the existing font... */
422 newfont = malloc(sizeof(*font), M_DEVBUF, M_WAITOK);
423 if (newfont == NULL)
424 return (NULL);
425
426 *newfont = *font;
427
428 namelen = strlen(font->name) + 4;
429 newname = malloc(namelen, M_DEVBUF, M_WAITOK);
430 strlcpy(newname, font->name, namelen);
431 strlcat(newname, "ccw", namelen);
432 newfont->name = newname;
433
434 /* Allocate a buffer big enough for the rotated font. */
435 newstride = (font->fontheight + 7) / 8;
436 newbits = malloc(newstride * font->fontwidth * font->numchars,
437 M_DEVBUF, M_WAITOK|M_ZERO);
438 if (newbits == NULL) {
439 free(newfont, M_DEVBUF);
440 return (NULL);
441 }
442
443 /* Rotate the font a bit at a time. */
444 for (n = 0; n < font->numchars; n++) {
445 unsigned char *ch = (unsigned char *)font->data +
446 (n * font->stride * font->fontheight);
447
448 for (r = 0; r < font->fontheight; r++) {
449 for (b = 0; b < font->fontwidth; b++) {
450 unsigned char *rb;
451
452 rb = ch + (font->stride * r) + (b / 8);
453 if (*rb & (0x80 >> (b % 8))) {
454 unsigned char *rrb;
455 int w = font->fontwidth;
456
457 rrb = newbits + (r / 8)
458 + (n * newstride * w)
459 + (newstride * (w - 1 - b));
460 *rrb |= (0x80 >> (r % 8));
461 }
462 }
463 }
464 }
465
466 newfont->data = newbits;
467
468 /* Update font sizes. */
469 newfont->stride = newstride;
470 newfont->fontwidth = font->fontheight;
471 newfont->fontheight = font->fontwidth;
472
473 if (wsfont_add(newfont, 0) != 0) {
474 /*
475 * If we seem to have rotated this font already, drop the
476 * new one...
477 */
478 free(newbits, M_DEVBUF);
479 free(newfont, M_DEVBUF);
480 newfont = NULL;
481 }
482
483 return (newfont);
484 }
485
486 int
487 wsfont_rotate(int cookie, int rotate)
488 {
489 int s, ncookie;
490 struct wsdisplay_font *font;
491 struct font *origfont;
492
493 s = splhigh();
494 origfont = wsfont_find0(cookie, 0xffffffff);
495 splx(s);
496
497 switch (rotate) {
498 case WSFONT_ROTATE_CW:
499 font = wsfont_rotate_cw_internal(origfont->font);
500 if (font == NULL)
501 return (-1);
502 break;
503
504 case WSFONT_ROTATE_CCW:
505 font = wsfont_rotate_ccw_internal(origfont->font);
506 if (font == NULL)
507 return (-1);
508 break;
509
510 case WSFONT_ROTATE_UD:
511 default:
512 return (-1);
513 }
514
515 ncookie = wsfont_find(font->name, font->fontwidth, font->fontheight,
516 font->stride, 0, 0);
517
518 return (ncookie);
519 }
520
521 #endif /* NRASOPS_ROTATION */
522
523 void
524 wsfont_init(void)
525 {
526 struct font *ent;
527 static int again;
528 int i;
529
530 if (again != 0)
531 return;
532 again = 1;
533
534 TAILQ_INIT(&list);
535 ent = builtin_fonts;
536
537 for (i = 0; builtin_fonts[i].font != NULL; i++, ent++) {
538 ident += (1 << WSFONT_IDENT_SHIFT);
539 ent->cookie = wsfont_make_cookie(ident,
540 ent->font->bitorder, ent->font->byteorder);
541 TAILQ_INSERT_TAIL(&list, ent, chain);
542 }
543
544 TAILQ_INIT(&aa_list);
545 ent = builtin_aa_fonts;
546
547 for (i = 0; builtin_aa_fonts[i].font != NULL; i++, ent++) {
548 ident += (1 << WSFONT_IDENT_SHIFT);
549 ent->cookie = wsfont_make_cookie(ident,
550 ent->font->bitorder, ent->font->byteorder);
551 TAILQ_INSERT_TAIL(&aa_list, ent, chain);
552 }
553 }
554
555 static struct font *
556 wsfont_find0(int cookie, int mask)
557 {
558 struct font *ent;
559
560 TAILQ_FOREACH(ent, &list, chain) {
561 if ((ent->cookie & mask) == (cookie & mask))
562 return (ent);
563 }
564
565 TAILQ_FOREACH(ent, &aa_list, chain) {
566 if ((ent->cookie & mask) == (cookie & mask))
567 return (ent);
568 }
569
570 return (NULL);
571 }
572
573 int
574 wsfont_matches(struct wsdisplay_font *font, const char *name,
575 int width, int height, int stride)
576 {
577
578 if (height != 0 && font->fontheight != height)
579 return (0);
580
581 if (width != 0 && font->fontwidth != width)
582 return (0);
583
584 if (stride != 0 && font->stride != stride)
585 return (0);
586
587 if (name != NULL && strcmp(font->name, name) != 0)
588 return (0);
589
590 return (1);
591 }
592
593 int
594 wsfont_find(const char *name, int width, int height, int stride, int bito, int byteo)
595 {
596 struct font *ent;
597
598 TAILQ_FOREACH(ent, &list, chain) {
599 if (wsfont_matches(ent->font, name, width, height, stride))
600 return (wsfont_make_cookie(ent->cookie, bito, byteo));
601 }
602
603 return (-1);
604 }
605
606 int
607 wsfont_find_aa(const char *name, int width, int height, int stride, int bito, int byteo)
608 {
609 struct font *ent;
610
611 TAILQ_FOREACH(ent, &aa_list, chain) {
612 if (wsfont_matches(ent->font, name, width, height, stride))
613 return (wsfont_make_cookie(ent->cookie, bito, byteo));
614 }
615
616 return (-1);
617 }
618
619 static struct font *
620 wsfont_add0(struct wsdisplay_font *font, int copy)
621 {
622 struct font *ent;
623 size_t size;
624
625 ent = malloc(sizeof(struct font), M_DEVBUF, M_WAITOK | M_ZERO);
626
627 /* Is this font statically allocated? */
628 if (!copy) {
629 ent->font = font;
630 ent->flags = WSFONT_STATIC;
631 } else {
632 void *data;
633 char *name;
634
635 ent->font = malloc(sizeof(struct wsdisplay_font), M_DEVBUF,
636 M_WAITOK);
637 memcpy(ent->font, font, sizeof(*ent->font));
638
639 size = font->fontheight * font->numchars * font->stride;
640 data = malloc(size, M_DEVBUF, M_WAITOK);
641 memcpy(data, font->data, size);
642 ent->font->data = data;
643
644 name = malloc(strlen(font->name) + 1, M_DEVBUF, M_WAITOK);
645 strlcpy(name, font->name, strlen(font->name) + 1);
646 ent->font->name = name;
647 }
648
649 TAILQ_INSERT_TAIL(&list, ent, chain);
650 return (ent);
651 }
652
653 int
654 wsfont_add(struct wsdisplay_font *font, int copy)
655 {
656 struct font *ent;
657
658 /* Don't allow exact duplicates */
659 if (wsfont_find(font->name, font->fontwidth, font->fontheight,
660 font->stride, 0, 0) >= 0)
661 return (EEXIST);
662
663 ent = wsfont_add0(font, copy);
664
665 ident += (1 << WSFONT_IDENT_SHIFT);
666 ent->cookie = wsfont_make_cookie(ident, font->bitorder,
667 font->byteorder);
668
669 return (0);
670 }
671
672 int
673 wsfont_remove(int cookie)
674 {
675 struct font *ent;
676
677 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
678 return (ENOENT);
679
680 if ((ent->flags & WSFONT_BUILTIN) != 0 || ent->lockcount != 0)
681 return (EBUSY);
682
683 if ((ent->flags & WSFONT_STATIC) == 0) {
684 free(ent->font->data, M_DEVBUF);
685 free(__UNCONST(ent->font->name), M_DEVBUF); /*XXXUNCONST*/
686 free(ent->font, M_DEVBUF);
687 }
688
689 TAILQ_REMOVE(&list, ent, chain);
690 free(ent, M_DEVBUF);
691
692 return (0);
693 }
694
695 int
696 wsfont_lock(int cookie, struct wsdisplay_font **ptr)
697 {
698 struct font *ent, *neu;
699 int bito, byteo;
700
701 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) {
702 if ((ent = wsfont_find0(cookie, WSFONT_IDENT_MASK)) == NULL)
703 return (ENOENT);
704
705 bito = (cookie & WSFONT_BITO_MASK) >> WSFONT_BITO_SHIFT;
706 byteo = (cookie & WSFONT_BYTEO_MASK) >> WSFONT_BYTEO_SHIFT;
707
708 if (ent->lockcount != 0) {
709 neu = wsfont_add0(ent->font, 1);
710 neu->flags |= WSFONT_COPY;
711
712 aprint_debug("wsfont: font '%s' bito %d byteo %d "
713 "copied to bito %d byteo %d\n",
714 ent->font->name,
715 ent->font->bitorder, ent->font->byteorder,
716 bito, byteo);
717
718 ent = neu;
719 }
720
721 if (bito && bito != ent->font->bitorder) {
722 wsfont_revbit(ent->font);
723 ent->font->bitorder = bito;
724 }
725
726 if (byteo && byteo != ent->font->byteorder) {
727 wsfont_revbyte(ent->font);
728 ent->font->byteorder = byteo;
729 }
730
731 ent->cookie = cookie;
732 }
733
734 ent->lockcount++;
735 *ptr = ent->font;
736 return (0);
737 }
738
739 int
740 wsfont_unlock(int cookie)
741 {
742 struct font *ent;
743
744 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
745 return (ENOENT);
746
747 if (ent->lockcount == 0)
748 panic("wsfont_unlock: font not locked");
749
750 if (--ent->lockcount == 0 && (ent->flags & WSFONT_COPY) != 0)
751 wsfont_remove(cookie);
752
753 return (0);
754 }
755
756 /*
757 * Unicode to font encoding mappings
758 */
759
760 /*
761 * To save memory, font encoding tables use a two level lookup. First the
762 * high byte of the Unicode is used to lookup the level 2 table, then the
763 * low byte indexes that table. Level 2 tables that are not needed are
764 * omitted (NULL), and both level 1 and level 2 tables have base and size
765 * attributes to keep their size down.
766 */
767
768 struct wsfont_level1_glyphmap {
769 const struct wsfont_level2_glyphmap **level2;
770 int base; /* High byte for first level2 entry */
771 int size; /* Number of level2 entries */
772 };
773
774 struct wsfont_level2_glyphmap {
775 int base; /* Low byte for first character */
776 int size; /* Number of characters */
777 const void *chars; /* Pointer to character number entries */
778 int width; /* Size of each entry in bytes (1,2,4) */
779 };
780
781 #define null16 \
782 NULL, NULL, NULL, NULL, \
783 NULL, NULL, NULL, NULL, \
784 NULL, NULL, NULL, NULL, \
785 NULL, NULL, NULL, NULL
786
787 /*
788 * IBM 437 maps
789 */
790
791 static const u_int8_t ibm437_chars_0[] = {
792 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
793 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
794 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
795 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
796 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
797 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
798 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
799 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
800 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
801 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
802 255,173,155,156, 0, 157, 0, 0, 0, 0, 166,174,170, 0, 0, 0,
803 0, 241,253, 0, 0, 0, 0, 249, 0, 0, 167,175,172,171, 0, 168,
804 0, 0, 0, 0, 142,143,146,128, 0, 144, 0, 0, 0, 0, 0, 0,
805 0, 165, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 154, 0, 0, 0,
806 133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
807 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0, 0, 152
808 };
809
810 static const u_int8_t ibm437_chars_1[] = {
811 159
812 };
813
814 static const u_int8_t ibm437_chars_3[] = {
815 226, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
816 228, 0, 0, 232, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 224,225,
817 0, 235,238, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 227, 0, 0,
818 229,231
819 };
820
821 static const u_int8_t ibm437_chars_32[] = {
822 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
823 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
824 0, 0, 0, 0, 0, 0, 0, 0, 158
825 };
826
827 static const u_int8_t ibm437_chars_34[] = {
828 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
829 0, 0, 0, 248,250,251, 0, 0, 0, 236, 0, 0, 0, 0, 0, 0,
830 0, 0, 0, 0, 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
831 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
832 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
833 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 0, 0,243,
834 242
835 };
836
837 static const u_int8_t ibm437_chars_35[] = {
838 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
839 244,245
840 };
841
842 static const u_int8_t ibm437_chars_37[] = {
843 196,205,179,186, 0, 0, 0, 0, 0, 0, 0, 0, 218,213,214,201,
844 191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0, 0,
845 199, 0, 0, 204,180,181, 0, 0, 182, 0, 0, 185,194, 0, 0, 209,
846 210, 0, 0, 203,193, 0, 0, 207,208, 0, 0, 202,197, 0, 0, 216,
847 0, 0, 215, 0, 0, 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, 0,
848 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
849 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
850 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
851 223, 0, 0, 0, 220, 0, 0, 0, 219, 0, 0, 0, 221, 0, 0, 0,
852 222,176,177,178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
853 254
854 };
855
856 static const struct wsfont_level2_glyphmap ibm437_level2_0 =
857 { 0, 256, ibm437_chars_0, 1 };
858
859 static const struct wsfont_level2_glyphmap ibm437_level2_1 =
860 { 146, 1, ibm437_chars_1, 1 };
861
862 static const struct wsfont_level2_glyphmap ibm437_level2_3 =
863 { 147, 50, ibm437_chars_3, 1 };
864
865 static const struct wsfont_level2_glyphmap ibm437_level2_32 =
866 { 127, 41, ibm437_chars_32, 1 };
867
868 static const struct wsfont_level2_glyphmap ibm437_level2_34 =
869 { 5, 97, ibm437_chars_34, 1 };
870
871 static const struct wsfont_level2_glyphmap ibm437_level2_35 =
872 { 16, 18, ibm437_chars_35, 1 };
873
874 static const struct wsfont_level2_glyphmap ibm437_level2_37 =
875 { 0, 161, ibm437_chars_37, 1 };
876
877 static const struct wsfont_level2_glyphmap *ibm437_level1[] = {
878 &ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
879 NULL, NULL, NULL, NULL,
880 NULL, NULL, NULL, NULL,
881 NULL, NULL, NULL, NULL,
882 NULL, NULL, NULL, NULL,
883 NULL, NULL, NULL, NULL,
884 NULL, NULL, NULL, NULL,
885 NULL, NULL, NULL, NULL,
886 &ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
887 NULL, &ibm437_level2_37
888 };
889
890 /*
891 * ISO-8859-7 maps
892 */
893 static const u_int8_t iso7_chars_0[] = {
894 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
895 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
896 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
897 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
898 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
899 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
900 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
901 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
902 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
903 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
904 160, 0, 0, 163, 0, 0, 166,167,168,169, 0, 171,172,173, 0, 0,
905 176,177,178,179,180, 0, 0, 183, 0, 0, 0, 187, 0, 189
906 };
907
908 static const u_int8_t iso7_chars_3[] = {
909 182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197,
910 198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213,
911 214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
912 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
913 246,247,248,249,250,251,252,253,254, 0, 0, 0, 0, 0, 0, 0,
914 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
915 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181
916 };
917
918 /*
919 * map all variants of the box drawing characters to the same basic shapes for
920 * now, encoded like this:
921 *
922 * 1
923 * 1
924 * 888 222
925 * 4
926 * 4
927 *
928 * so an upright line would be 0x05
929 */
930 #define FL |WSFONT_FLAG_OPT
931 static const u_int32_t netbsd_boxes[] = {
932 /*00*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
933 /*08*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x06 FL,
934 /*10*/ 0x0c FL, 0x0c FL, 0x0c FL, 0x0c FL, 0x03 FL, 0x03 FL, 0x03 FL, 0x03 FL,
935 /*18*/ 0x09 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL,
936 /*20*/ 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL,
937 /*28*/ 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL,
938 /*30*/ 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL,
939 /*38*/ 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
940 /*40*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
941 /*48*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
942 /*50*/ 0x0a FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x0c FL, 0x0c FL, 0x0c FL,
943 /*58*/ 0x03 FL, 0x03 FL, 0x03 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL,
944 /*60*/ 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL,
945 /*68*/ 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x06 FL, 0x0c FL, 0x09 FL,
946 /*70*/ 0x03 FL, 0 FL, 0 FL, 0 FL, 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL,
947 /*78*/ 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL, 0x0a FL, 0x05 FL, 0x0a FL, 0x05 FL
948 };
949 #undef FL
950
951 static const u_int8_t iso7_chars_32[] = {
952 175, 0, 0, 0, 0, 162, 0, 161
953 };
954
955 static const struct wsfont_level2_glyphmap iso7_level2_0 =
956 { 0, 190, iso7_chars_0, 1 };
957
958 static const struct wsfont_level2_glyphmap iso7_level2_3 =
959 { 134, 111, iso7_chars_3, 1 };
960
961 static const struct wsfont_level2_glyphmap iso7_level2_32 =
962 { 20, 8, iso7_chars_32, 1 };
963
964 static const struct wsfont_level2_glyphmap netbsd_box_drawing =
965 { 0, 128, netbsd_boxes, 4 };
966
967 static const struct wsfont_level2_glyphmap *iso7_level1[] = {
968 &iso7_level2_0, NULL, NULL, &iso7_level2_3,
969 NULL, NULL, NULL, NULL,
970 NULL, NULL, NULL, NULL,
971 NULL, NULL, NULL, NULL,
972 NULL, NULL, NULL, NULL,
973 NULL, NULL, NULL, NULL,
974 NULL, NULL, NULL, NULL,
975 NULL, NULL, NULL, NULL,
976 &iso7_level2_32, NULL, NULL, NULL,
977 NULL, &netbsd_box_drawing
978 };
979
980 static const struct wsfont_level2_glyphmap *iso_level1[] = {
981 NULL, NULL, NULL, NULL,
982 NULL, NULL, NULL, NULL,
983 NULL, NULL, NULL, NULL,
984 NULL, NULL, NULL, NULL,
985 NULL, NULL, NULL, NULL,
986 NULL, NULL, NULL, NULL,
987 NULL, NULL, NULL, NULL,
988 NULL, NULL, NULL, NULL,
989 NULL, NULL, NULL, NULL,
990 NULL, &netbsd_box_drawing
991 };
992
993 static const struct wsfont_level1_glyphmap encodings[] = {
994 { iso_level1, 0, 0x26 }, /* WSDISPLAY_FONTENC_ISO */
995 { ibm437_level1, 0, 38 }, /* WSDISPLAY_FONTENC_IBM */
996 { NULL, 0, 0 }, /* WSDISPLAY_FONTENC_PCVT */
997 { iso7_level1, 0, 0x26 }, /* WSDISPLAY_FONTENC_ISO7 */
998 };
999
1000 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0]))
1001
1002 /*
1003 * Remap Unicode character to glyph
1004 */
1005 int
1006 wsfont_map_unichar(struct wsdisplay_font *font, int c)
1007 {
1008 const struct wsfont_level1_glyphmap *map1;
1009 const struct wsfont_level2_glyphmap *map2;
1010 int hi, lo;
1011
1012 if (font->encoding < 0 || font->encoding >= MAX_ENCODING)
1013 return (-1);
1014
1015 hi = (c >> 8);
1016 lo = c & 255;
1017 map1 = &encodings[font->encoding];
1018
1019 if (hi < map1->base || hi >= map1->base + map1->size)
1020 return (-1);
1021
1022 map2 = map1->level2[hi - map1->base];
1023
1024 /* so we don't need an identical level 2 table for hi == 0 */
1025 if (hi == 0 && font->encoding == WSDISPLAY_FONTENC_ISO)
1026 return lo;
1027
1028 if (map2 == NULL || lo < map2->base || lo >= map2->base + map2->size)
1029 return (-1);
1030
1031 lo -= map2->base;
1032
1033 switch(map2->width) {
1034 case 1:
1035 c = (((const u_int8_t *)map2->chars)[lo]);
1036 break;
1037 case 2:
1038 c = (((const u_int16_t *)map2->chars)[lo]);
1039 break;
1040 case 4:
1041 c = (((const u_int32_t *)map2->chars)[lo]);
1042 break;
1043 }
1044
1045 if (c == 0 && lo != 0)
1046 return (-1);
1047
1048 return (c);
1049 }
1050