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