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