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