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