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