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