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