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