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