wsfont.c revision 1.60 1 /* $NetBSD: wsfont.c,v 1.60 2016/11/20 15:44:40 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.60 2016/11/20 15:44:40 macallan Exp $");
34
35 #include "opt_wsfont.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/time.h>
40 #include <sys/malloc.h>
41 #include <sys/queue.h>
42
43 #include <dev/wscons/wsdisplayvar.h>
44 #include <dev/wscons/wsconsio.h>
45 #include <dev/wsfont/wsfont.h>
46
47 #include "wsfont_glue.h" /* NRASOPS_ROTATION */
48
49 #undef HAVE_FONT
50
51 #ifdef FONT_QVSS8x15
52 #define HAVE_FONT 1
53 #include <dev/wsfont/qvss8x15.h>
54 #endif
55
56 #ifdef FONT_GALLANT12x22
57 #define HAVE_FONT 1
58 #include <dev/wsfont/gallant12x22.h>
59 #endif
60
61 #ifdef FONT_LUCIDA16x29
62 #define HAVE_FONT 1
63 #include <dev/wsfont/lucida16x29.h>
64 #endif
65
66 #ifdef FONT_VT220L8x8
67 #define HAVE_FONT 1
68 #include <dev/wsfont/vt220l8x8.h>
69 #endif
70
71 #ifdef FONT_VT220L8x10
72 #define HAVE_FONT 1
73 #include <dev/wsfont/vt220l8x10.h>
74 #endif
75
76 #ifdef FONT_VT220L8x16
77 #define HAVE_FONT 1
78 #include <dev/wsfont/vt220l8x16.h>
79 #endif
80
81 #ifdef FONT_VT220ISO8x8
82 #define HAVE_FONT 1
83 #include <dev/wsfont/vt220iso8x8.h>
84 #endif
85
86 #ifdef FONT_VT220ISO8x16
87 #define HAVE_FONT 1
88 #include <dev/wsfont/vt220iso8x16.h>
89 #endif
90
91 #ifdef FONT_VT220KOI8x10_KOI8_R
92 #define HAVE_FONT 1
93 #include <dev/wsfont/vt220koi8x10.h>
94 #endif
95
96 #ifdef FONT_VT220KOI8x10_KOI8_U
97 #define HAVE_FONT 1
98 #define KOI8_U
99 #include <dev/wsfont/vt220koi8x10.h>
100 #undef KOI8_U
101 #endif
102
103 #ifdef FONT_SONY8x16
104 #define HAVE_FONT 1
105 #include <dev/wsfont/sony8x16.h>
106 #endif
107
108 #ifdef FONT_SONY12x24
109 #define HAVE_FONT 1
110 #include <dev/wsfont/sony12x24.h>
111 #endif
112
113 #ifdef FONT_OMRON12x20
114 #define HAVE_FONT 1
115 #include <dev/wsfont/omron12x20.h>
116 #endif
117
118 #ifdef FONT_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 int score = 20000;
574
575 /* first weed out fonts the caller doesn't claim support for */
576 if (FONT_IS_ALPHA(font)) {
577 if (flags & WSFONT_PREFER_ALPHA)
578 score++;
579 if ((flags & WSFONT_FIND_ALPHA) == 0)
580 return 0;
581 } else {
582 if ((flags & WSFONT_FIND_BITMAP) == 0)
583 return 0;
584 }
585
586 if (height != 0 && font->fontheight != height)
587 return (0);
588
589 if (width != 0) {
590 if ((flags & WSFONT_FIND_BESTWIDTH) == 0) {
591 if (font->fontwidth != width)
592 return (0);
593 } else {
594 if (font->fontwidth > width)
595 score -= 10000 + min(font->fontwidth - width, 9999);
596 else
597 score -= min(width - font->fontwidth, 9999);
598 }
599 }
600
601 if (stride != 0 && font->stride != stride)
602 return (0);
603
604 if (name != NULL && strcmp(font->name, name) != 0)
605 return (0);
606
607 return (score);
608 }
609
610 int
611 wsfont_find(const char *name, int width, int height, int stride, int bito, int byteo, int flags)
612 {
613 struct font *ent, *bestent = NULL;
614 int score, bestscore = 0;
615
616 TAILQ_FOREACH(ent, &list, chain) {
617 score = wsfont_matches(ent->font, name,
618 width, height, stride, flags);
619 if (score > bestscore) {
620 bestscore = score;
621 bestent = ent;
622 }
623 }
624
625 if (bestent != NULL)
626 return (wsfont_make_cookie(bestent->cookie, bito, byteo));
627
628 return (-1);
629 }
630
631 void
632 wsfont_walk(void (*matchfunc)(struct wsdisplay_font *, void *, int), void *cookie)
633 {
634 struct font *ent;
635
636 TAILQ_FOREACH(ent, &list, chain) {
637 matchfunc(ent->font, cookie, ent->cookie);
638 }
639 }
640
641 static struct font *
642 wsfont_add0(struct wsdisplay_font *font, int copy)
643 {
644 struct font *ent;
645 size_t size;
646
647 ent = malloc(sizeof(struct font), M_DEVBUF, M_WAITOK | M_ZERO);
648
649 /* Is this font statically allocated? */
650 if (!copy) {
651 ent->font = font;
652 ent->flags = WSFONT_STATIC;
653 } else {
654 void *data;
655 char *name;
656
657 ent->font = malloc(sizeof(struct wsdisplay_font), M_DEVBUF,
658 M_WAITOK);
659 memcpy(ent->font, font, sizeof(*ent->font));
660
661 size = font->fontheight * font->numchars * font->stride;
662 data = malloc(size, M_DEVBUF, M_WAITOK);
663 memcpy(data, font->data, size);
664 ent->font->data = data;
665
666 name = malloc(strlen(font->name) + 1, M_DEVBUF, M_WAITOK);
667 strlcpy(name, font->name, strlen(font->name) + 1);
668 ent->font->name = name;
669 }
670
671 TAILQ_INSERT_TAIL(&list, ent, chain);
672 return (ent);
673 }
674
675 int
676 wsfont_add(struct wsdisplay_font *font, int copy)
677 {
678 struct font *ent;
679
680 /* Don't allow exact duplicates */
681 if (wsfont_find(font->name, font->fontwidth, font->fontheight,
682 font->stride, 0, 0, WSFONT_FIND_ALL) >= 0)
683 return (EEXIST);
684
685 ent = wsfont_add0(font, copy);
686
687 ident += (1 << WSFONT_IDENT_SHIFT);
688 ent->cookie = wsfont_make_cookie(ident, font->bitorder,
689 font->byteorder);
690
691 return (0);
692 }
693
694 int
695 wsfont_remove(int cookie)
696 {
697 struct font *ent;
698
699 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
700 return (ENOENT);
701
702 if ((ent->flags & WSFONT_BUILTIN) != 0 || ent->lockcount != 0)
703 return (EBUSY);
704
705 if ((ent->flags & WSFONT_STATIC) == 0) {
706 free(ent->font->data, M_DEVBUF);
707 free(__UNCONST(ent->font->name), M_DEVBUF); /*XXXUNCONST*/
708 free(ent->font, M_DEVBUF);
709 }
710
711 TAILQ_REMOVE(&list, ent, chain);
712 free(ent, M_DEVBUF);
713
714 return (0);
715 }
716
717 int
718 wsfont_lock(int cookie, struct wsdisplay_font **ptr)
719 {
720 struct font *ent, *neu;
721 int bito, byteo;
722
723 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) {
724 if ((ent = wsfont_find0(cookie, WSFONT_IDENT_MASK)) == NULL)
725 return (ENOENT);
726
727 bito = (cookie & WSFONT_BITO_MASK) >> WSFONT_BITO_SHIFT;
728 byteo = (cookie & WSFONT_BYTEO_MASK) >> WSFONT_BYTEO_SHIFT;
729
730 if (ent->lockcount != 0) {
731 neu = wsfont_add0(ent->font, 1);
732 neu->flags |= WSFONT_COPY;
733
734 aprint_debug("wsfont: font '%s' bito %d byteo %d "
735 "copied to bito %d byteo %d\n",
736 ent->font->name,
737 ent->font->bitorder, ent->font->byteorder,
738 bito, byteo);
739
740 ent = neu;
741 }
742
743 if (bito && bito != ent->font->bitorder) {
744 wsfont_revbit(ent->font);
745 ent->font->bitorder = bito;
746 }
747
748 if (byteo && byteo != ent->font->byteorder) {
749 wsfont_revbyte(ent->font);
750 ent->font->byteorder = byteo;
751 }
752
753 ent->cookie = cookie;
754 }
755
756 ent->lockcount++;
757 *ptr = ent->font;
758 return (0);
759 }
760
761 int
762 wsfont_unlock(int cookie)
763 {
764 struct font *ent;
765
766 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
767 return (ENOENT);
768
769 if (ent->lockcount == 0)
770 panic("wsfont_unlock: font not locked");
771
772 if (--ent->lockcount == 0 && (ent->flags & WSFONT_COPY) != 0)
773 wsfont_remove(cookie);
774
775 return (0);
776 }
777
778 /*
779 * Unicode to font encoding mappings
780 */
781
782 /*
783 * To save memory, font encoding tables use a two level lookup. First the
784 * high byte of the Unicode is used to lookup the level 2 table, then the
785 * low byte indexes that table. Level 2 tables that are not needed are
786 * omitted (NULL), and both level 1 and level 2 tables have base and size
787 * attributes to keep their size down.
788 */
789
790 struct wsfont_level1_glyphmap {
791 const struct wsfont_level2_glyphmap **level2;
792 int base; /* High byte for first level2 entry */
793 int size; /* Number of level2 entries */
794 };
795
796 struct wsfont_level2_glyphmap {
797 int base; /* Low byte for first character */
798 int size; /* Number of characters */
799 const void *chars; /* Pointer to character number entries */
800 int width; /* Size of each entry in bytes (1,2,4) */
801 };
802
803 #define null16 \
804 NULL, NULL, NULL, NULL, \
805 NULL, NULL, NULL, NULL, \
806 NULL, NULL, NULL, NULL, \
807 NULL, NULL, NULL, NULL
808
809 /*
810 * IBM 437 maps
811 */
812
813 static const u_int8_t ibm437_chars_0[] = {
814 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
815 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
816 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
817 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
818 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
819 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
820 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
821 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
822 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
823 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
824 255,173,155,156, 0, 157, 0, 0, 0, 0, 166,174,170, 0, 0, 0,
825 0, 241,253, 0, 0, 0, 0, 249, 0, 0, 167,175,172,171, 0, 168,
826 0, 0, 0, 0, 142,143,146,128, 0, 144, 0, 0, 0, 0, 0, 0,
827 0, 165, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 154, 0, 0, 0,
828 133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
829 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0, 0, 152
830 };
831
832 static const u_int8_t ibm437_chars_1[] = {
833 159
834 };
835
836 static const u_int8_t ibm437_chars_3[] = {
837 226, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
838 228, 0, 0, 232, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 224,225,
839 0, 235,238, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 227, 0, 0,
840 229,231
841 };
842
843 static const u_int8_t ibm437_chars_32[] = {
844 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
845 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
846 0, 0, 0, 0, 0, 0, 0, 0, 158
847 };
848
849 static const u_int8_t ibm437_chars_34[] = {
850 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
851 0, 0, 0, 248,250,251, 0, 0, 0, 236, 0, 0, 0, 0, 0, 0,
852 0, 0, 0, 0, 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
853 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
854 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
855 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 0, 0,243,
856 242
857 };
858
859 static const u_int8_t ibm437_chars_35[] = {
860 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
861 244,245
862 };
863
864 static const u_int8_t ibm437_chars_37[] = {
865 196,205,179,186, 0, 0, 0, 0, 0, 0, 0, 0, 218,213,214,201,
866 191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0, 0,
867 199, 0, 0, 204,180,181, 0, 0, 182, 0, 0, 185,194, 0, 0, 209,
868 210, 0, 0, 203,193, 0, 0, 207,208, 0, 0, 202,197, 0, 0, 216,
869 0, 0, 215, 0, 0, 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, 0,
870 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
871 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
872 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
873 223, 0, 0, 0, 220, 0, 0, 0, 219, 0, 0, 0, 221, 0, 0, 0,
874 222,176,177,178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
875 254
876 };
877
878 static const struct wsfont_level2_glyphmap ibm437_level2_0 =
879 { 0, 256, ibm437_chars_0, 1 };
880
881 static const struct wsfont_level2_glyphmap ibm437_level2_1 =
882 { 146, 1, ibm437_chars_1, 1 };
883
884 static const struct wsfont_level2_glyphmap ibm437_level2_3 =
885 { 147, 50, ibm437_chars_3, 1 };
886
887 static const struct wsfont_level2_glyphmap ibm437_level2_32 =
888 { 127, 41, ibm437_chars_32, 1 };
889
890 static const struct wsfont_level2_glyphmap ibm437_level2_34 =
891 { 5, 97, ibm437_chars_34, 1 };
892
893 static const struct wsfont_level2_glyphmap ibm437_level2_35 =
894 { 16, 18, ibm437_chars_35, 1 };
895
896 static const struct wsfont_level2_glyphmap ibm437_level2_37 =
897 { 0, 161, ibm437_chars_37, 1 };
898
899 static const struct wsfont_level2_glyphmap *ibm437_level1[] = {
900 &ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
901 NULL, NULL, NULL, NULL,
902 NULL, NULL, NULL, NULL,
903 NULL, NULL, NULL, NULL,
904 NULL, NULL, NULL, NULL,
905 NULL, NULL, NULL, NULL,
906 NULL, NULL, NULL, NULL,
907 NULL, NULL, NULL, NULL,
908 &ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
909 NULL, &ibm437_level2_37
910 };
911
912 /*
913 * ISO-8859-7 maps
914 */
915 static const u_int8_t iso7_chars_0[] = {
916 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
917 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
918 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
919 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
920 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
921 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
922 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
923 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
924 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
925 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
926 160, 0, 0, 163, 0, 0, 166,167,168,169, 0, 171,172,173, 0, 0,
927 176,177,178,179,180, 0, 0, 183, 0, 0, 0, 187, 0, 189
928 };
929
930 static const u_int8_t iso7_chars_3[] = {
931 182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197,
932 198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213,
933 214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
934 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
935 246,247,248,249,250,251,252,253,254, 0, 0, 0, 0, 0, 0, 0,
936 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
937 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181
938 };
939
940 /*
941 * map all variants of the box drawing characters to the same basic shapes for
942 * now, encoded like this:
943 *
944 * 1
945 * 1
946 * 888 222
947 * 4
948 * 4
949 *
950 * so an upright line would be 0x05
951 */
952 #define FL |WSFONT_FLAG_OPT
953 static const u_int32_t netbsd_boxes[] = {
954 /*00*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
955 /*08*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x06 FL,
956 /*10*/ 0x0c FL, 0x0c FL, 0x0c FL, 0x0c FL, 0x03 FL, 0x03 FL, 0x03 FL, 0x03 FL,
957 /*18*/ 0x09 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL,
958 /*20*/ 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL,
959 /*28*/ 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL,
960 /*30*/ 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL,
961 /*38*/ 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
962 /*40*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
963 /*48*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
964 /*50*/ 0x0a FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x0c FL, 0x0c FL, 0x0c FL,
965 /*58*/ 0x03 FL, 0x03 FL, 0x03 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL,
966 /*60*/ 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL,
967 /*68*/ 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x06 FL, 0x0c FL, 0x09 FL,
968 /*70*/ 0x03 FL, 0 FL, 0 FL, 0 FL, 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL,
969 /*78*/ 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL, 0x0a FL, 0x05 FL, 0x0a FL, 0x05 FL
970 };
971 #undef FL
972
973 static const u_int8_t iso7_chars_32[] = {
974 175, 0, 0, 0, 0, 162, 0, 161
975 };
976
977 static const struct wsfont_level2_glyphmap iso7_level2_0 =
978 { 0, 190, iso7_chars_0, 1 };
979
980 static const struct wsfont_level2_glyphmap iso7_level2_3 =
981 { 134, 111, iso7_chars_3, 1 };
982
983 static const struct wsfont_level2_glyphmap iso7_level2_32 =
984 { 20, 8, iso7_chars_32, 1 };
985
986 static const struct wsfont_level2_glyphmap netbsd_box_drawing =
987 { 0, 128, netbsd_boxes, 4 };
988
989 static const struct wsfont_level2_glyphmap *iso7_level1[] = {
990 &iso7_level2_0, NULL, NULL, &iso7_level2_3,
991 NULL, NULL, NULL, NULL,
992 NULL, NULL, NULL, NULL,
993 NULL, NULL, NULL, NULL,
994 NULL, NULL, NULL, NULL,
995 NULL, NULL, NULL, NULL,
996 NULL, NULL, NULL, NULL,
997 NULL, NULL, NULL, NULL,
998 &iso7_level2_32, NULL, NULL, NULL,
999 NULL, &netbsd_box_drawing
1000 };
1001
1002 static const struct wsfont_level2_glyphmap *iso_level1[] = {
1003 NULL, NULL, NULL, NULL,
1004 NULL, NULL, NULL, NULL,
1005 NULL, NULL, NULL, NULL,
1006 NULL, NULL, NULL, NULL,
1007 NULL, NULL, NULL, NULL,
1008 NULL, NULL, NULL, NULL,
1009 NULL, NULL, NULL, NULL,
1010 NULL, NULL, NULL, NULL,
1011 NULL, NULL, NULL, NULL,
1012 NULL, &netbsd_box_drawing
1013 };
1014
1015 static const struct wsfont_level1_glyphmap encodings[] = {
1016 { iso_level1, 0, 0x26 }, /* WSDISPLAY_FONTENC_ISO */
1017 { ibm437_level1, 0, 38 }, /* WSDISPLAY_FONTENC_IBM */
1018 { NULL, 0, 0 }, /* WSDISPLAY_FONTENC_PCVT */
1019 { iso7_level1, 0, 0x26 }, /* WSDISPLAY_FONTENC_ISO7 */
1020 };
1021
1022 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0]))
1023
1024 /*
1025 * Remap Unicode character to glyph
1026 */
1027 int
1028 wsfont_map_unichar(struct wsdisplay_font *font, int c)
1029 {
1030 const struct wsfont_level1_glyphmap *map1;
1031 const struct wsfont_level2_glyphmap *map2;
1032 int hi, lo;
1033
1034 if (font->encoding < 0 || font->encoding >= MAX_ENCODING)
1035 return (-1);
1036
1037 hi = (c >> 8);
1038 lo = c & 255;
1039 map1 = &encodings[font->encoding];
1040
1041 if (hi < map1->base || hi >= map1->base + map1->size)
1042 return (-1);
1043
1044 map2 = map1->level2[hi - map1->base];
1045
1046 /* so we don't need an identical level 2 table for hi == 0 */
1047 if (hi == 0 && font->encoding == WSDISPLAY_FONTENC_ISO)
1048 return lo;
1049
1050 if (map2 == NULL || lo < map2->base || lo >= map2->base + map2->size)
1051 return (-1);
1052
1053 lo -= map2->base;
1054
1055 switch(map2->width) {
1056 case 1:
1057 c = (((const u_int8_t *)map2->chars)[lo]);
1058 break;
1059 case 2:
1060 c = (((const u_int16_t *)map2->chars)[lo]);
1061 break;
1062 case 4:
1063 c = (((const u_int32_t *)map2->chars)[lo]);
1064 break;
1065 }
1066
1067 if (c == 0 && lo != 0)
1068 return (-1);
1069
1070 return (c);
1071 }
1072