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