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