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