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