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