wsfont.c revision 1.72 1 /* $NetBSD: wsfont.c,v 1.72 2021/11/19 23:50: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.72 2021/11/19 23:50: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 if (origfont == NULL)
567 return (-1);
568
569 switch (rotate) {
570 case WSFONT_ROTATE_CW:
571 font = wsfont_rotate_cw_internal(origfont->font);
572 if (font == NULL)
573 return (-1);
574 break;
575
576 case WSFONT_ROTATE_CCW:
577 font = wsfont_rotate_ccw_internal(origfont->font);
578 if (font == NULL)
579 return (-1);
580 break;
581
582 case WSFONT_ROTATE_UD:
583 default:
584 return (-1);
585 }
586 /* rotation works only with bitmap fonts so far */
587 ncookie = wsfont_find(font->name, font->fontwidth, font->fontheight,
588 font->stride, 0, 0, WSFONT_FIND_BITMAP);
589
590 return (ncookie);
591 }
592
593 #endif /* NRASOPS_ROTATION */
594
595 void
596 wsfont_init(void)
597 {
598 struct font *ent;
599 static int again;
600 int i;
601
602 if (again != 0)
603 return;
604 again = 1;
605
606 TAILQ_INIT(&list);
607 ent = builtin_fonts;
608
609 for (i = 0; builtin_fonts[i].font != NULL; i++, ent++) {
610 ident += (1 << WSFONT_IDENT_SHIFT);
611 ent->cookie = wsfont_make_cookie(ident,
612 ent->font->bitorder, ent->font->byteorder);
613 TAILQ_INSERT_TAIL(&list, ent, chain);
614 }
615 }
616
617 static struct font *
618 wsfont_find0(int cookie, int mask)
619 {
620 struct font *ent;
621
622 TAILQ_FOREACH(ent, &list, chain) {
623 if ((ent->cookie & mask) == (cookie & mask))
624 return (ent);
625 }
626
627 return (NULL);
628 }
629
630 int
631 wsfont_matches(struct wsdisplay_font *font, const char *name,
632 int width, int height, int stride, int flags)
633 {
634 int score = 20000;
635
636 /* first weed out fonts the caller doesn't claim support for */
637 if (FONT_IS_ALPHA(font)) {
638 if (flags & WSFONT_PREFER_ALPHA)
639 score++;
640 if ((flags & WSFONT_FIND_ALPHA) == 0)
641 return 0;
642 } else {
643 if ((flags & WSFONT_FIND_BITMAP) == 0)
644 return 0;
645 }
646
647 if (height != 0 && font->fontheight != height)
648 return (0);
649
650 if (width != 0) {
651 if ((flags & WSFONT_FIND_BESTWIDTH) == 0) {
652 if (font->fontwidth != width)
653 return (0);
654 } else {
655 if (font->fontwidth > width)
656 score -= 10000 + uimin(font->fontwidth - width, 9999);
657 else
658 score -= uimin(width - font->fontwidth, 9999);
659 }
660 }
661
662 if (stride != 0 && font->stride != stride)
663 return (0);
664
665 if (name != NULL && strcmp(font->name, name) != 0)
666 return (0);
667
668 return (score);
669 }
670
671 int
672 wsfont_find(const char *name, int width, int height, int stride, int bito, int byteo, int flags)
673 {
674 struct font *ent, *bestent = NULL;
675 int score, bestscore = 0;
676
677 TAILQ_FOREACH(ent, &list, chain) {
678 score = wsfont_matches(ent->font, name,
679 width, height, stride, flags);
680 if (score > bestscore) {
681 bestscore = score;
682 bestent = ent;
683 }
684 }
685
686 if (bestent != NULL)
687 return (wsfont_make_cookie(bestent->cookie, bito, byteo));
688
689 return (-1);
690 }
691
692 void
693 wsfont_walk(void (*matchfunc)(struct wsdisplay_font *, void *, int), void *cookie)
694 {
695 struct font *ent;
696
697 TAILQ_FOREACH(ent, &list, chain) {
698 matchfunc(ent->font, cookie, ent->cookie);
699 }
700 }
701
702 static struct font *
703 wsfont_add0(struct wsdisplay_font *font, int copy)
704 {
705 struct font *ent;
706 size_t size;
707
708 ent = malloc(sizeof(struct font), M_DEVBUF, M_WAITOK | M_ZERO);
709
710 /* Is this font statically allocated? */
711 if (!copy) {
712 ent->font = font;
713 ent->flags = WSFONT_STATIC;
714 } else {
715 void *data;
716 char *name;
717
718 ent->font = malloc(sizeof(struct wsdisplay_font), M_DEVBUF,
719 M_WAITOK);
720 memcpy(ent->font, font, sizeof(*ent->font));
721
722 size = font->fontheight * font->numchars * font->stride;
723 data = malloc(size, M_DEVBUF, M_WAITOK);
724 memcpy(data, font->data, size);
725 ent->font->data = data;
726
727 name = malloc(strlen(font->name) + 1, M_DEVBUF, M_WAITOK);
728 strlcpy(name, font->name, strlen(font->name) + 1);
729 ent->font->name = name;
730 }
731
732 TAILQ_INSERT_TAIL(&list, ent, chain);
733 return (ent);
734 }
735
736 int
737 wsfont_add(struct wsdisplay_font *font, int copy)
738 {
739 struct font *ent;
740
741 /* Don't allow exact duplicates */
742 if (wsfont_find(font->name, font->fontwidth, font->fontheight,
743 font->stride, 0, 0, WSFONT_FIND_ALL) >= 0)
744 return (EEXIST);
745
746 ent = wsfont_add0(font, copy);
747
748 ident += (1 << WSFONT_IDENT_SHIFT);
749 ent->cookie = wsfont_make_cookie(ident, font->bitorder,
750 font->byteorder);
751
752 return (0);
753 }
754
755 int
756 wsfont_remove(int cookie)
757 {
758 struct font *ent;
759
760 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
761 return (ENOENT);
762
763 if ((ent->flags & WSFONT_BUILTIN) != 0 || ent->lockcount != 0)
764 return (EBUSY);
765
766 if ((ent->flags & WSFONT_STATIC) == 0) {
767 free(ent->font->data, M_DEVBUF);
768 free(__UNCONST(ent->font->name), M_DEVBUF); /*XXXUNCONST*/
769 free(ent->font, M_DEVBUF);
770 }
771
772 TAILQ_REMOVE(&list, ent, chain);
773 free(ent, M_DEVBUF);
774
775 return (0);
776 }
777
778 int
779 wsfont_lock(int cookie, struct wsdisplay_font **ptr)
780 {
781 struct font *ent, *neu;
782 int bito, byteo;
783
784 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) {
785 if ((ent = wsfont_find0(cookie, WSFONT_IDENT_MASK)) == NULL)
786 return (ENOENT);
787
788 bito = (cookie & WSFONT_BITO_MASK) >> WSFONT_BITO_SHIFT;
789 byteo = (cookie & WSFONT_BYTEO_MASK) >> WSFONT_BYTEO_SHIFT;
790
791 if (ent->lockcount != 0) {
792 neu = wsfont_add0(ent->font, 1);
793 neu->flags |= WSFONT_COPY;
794
795 aprint_debug("wsfont: font '%s' bito %d byteo %d "
796 "copied to bito %d byteo %d\n",
797 ent->font->name,
798 ent->font->bitorder, ent->font->byteorder,
799 bito, byteo);
800
801 ent = neu;
802 }
803
804 if (bito && bito != ent->font->bitorder) {
805 wsfont_revbit(ent->font);
806 ent->font->bitorder = bito;
807 }
808
809 if (byteo && byteo != ent->font->byteorder) {
810 wsfont_revbyte(ent->font);
811 ent->font->byteorder = byteo;
812 }
813
814 ent->cookie = cookie;
815 }
816
817 ent->lockcount++;
818 *ptr = ent->font;
819 return (0);
820 }
821
822 int
823 wsfont_unlock(int cookie)
824 {
825 struct font *ent;
826
827 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
828 return (ENOENT);
829
830 if (ent->lockcount == 0)
831 panic("wsfont_unlock: font not locked");
832
833 if (--ent->lockcount == 0 && (ent->flags & WSFONT_COPY) != 0)
834 wsfont_remove(cookie);
835
836 return (0);
837 }
838
839 /*
840 * Unicode to font encoding mappings
841 */
842
843 /*
844 * To save memory, font encoding tables use a two level lookup. First the
845 * high byte of the Unicode is used to lookup the level 2 table, then the
846 * low byte indexes that table. Level 2 tables that are not needed are
847 * omitted (NULL), and both level 1 and level 2 tables have base and size
848 * attributes to keep their size down.
849 */
850
851 struct wsfont_level1_glyphmap {
852 const struct wsfont_level2_glyphmap **level2;
853 int base; /* High byte for first level2 entry */
854 int size; /* Number of level2 entries */
855 };
856
857 struct wsfont_level2_glyphmap {
858 int base; /* Low byte for first character */
859 int size; /* Number of characters */
860 const void *chars; /* Pointer to character number entries */
861 int width; /* Size of each entry in bytes (1,2,4) */
862 };
863
864 #define null16 \
865 NULL, NULL, NULL, NULL, \
866 NULL, NULL, NULL, NULL, \
867 NULL, NULL, NULL, NULL, \
868 NULL, NULL, NULL, NULL
869
870 /*
871 * IBM 437 maps
872 */
873
874 static const u_int8_t ibm437_chars_0[] = {
875 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
876 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
877 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
878 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
879 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
880 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
881 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
882 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
883 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
884 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
885 255,173,155,156, 0, 157, 0, 0, 0, 0, 166,174,170, 0, 0, 0,
886 0, 241,253, 0, 0, 0, 0, 249, 0, 0, 167,175,172,171, 0, 168,
887 0, 0, 0, 0, 142,143,146,128, 0, 144, 0, 0, 0, 0, 0, 0,
888 0, 165, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 154, 0, 0, 0,
889 133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
890 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0, 0, 152
891 };
892
893 static const u_int8_t ibm437_chars_1[] = {
894 159
895 };
896
897 static const u_int8_t ibm437_chars_3[] = {
898 226, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
899 228, 0, 0, 232, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 224,225,
900 0, 235,238, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 227, 0, 0,
901 229,231
902 };
903
904 static const u_int8_t ibm437_chars_32[] = {
905 252, 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 0, 0, 0, 0, 0, 0, 0, 0, 158
908 };
909
910 static const u_int8_t ibm437_chars_34[] = {
911 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
912 0, 0, 0, 248,250,251, 0, 0, 0, 236, 0, 0, 0, 0, 0, 0,
913 0, 0, 0, 0, 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
914 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
915 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
916 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 0, 0,243,
917 242
918 };
919
920 static const u_int8_t ibm437_chars_35[] = {
921 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
922 244,245
923 };
924
925 static const u_int8_t ibm437_chars_37[] = {
926 196,205,179,186, 0, 0, 0, 0, 0, 0, 0, 0, 218,213,214,201,
927 191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0, 0,
928 199, 0, 0, 204,180,181, 0, 0, 182, 0, 0, 185,194, 0, 0, 209,
929 210, 0, 0, 203,193, 0, 0, 207,208, 0, 0, 202,197, 0, 0, 216,
930 0, 0, 215, 0, 0, 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, 0,
931 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
932 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
933 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
934 223, 0, 0, 0, 220, 0, 0, 0, 219, 0, 0, 0, 221, 0, 0, 0,
935 222,176,177,178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
936 254
937 };
938
939 static const struct wsfont_level2_glyphmap ibm437_level2_0 =
940 { 0, 256, ibm437_chars_0, 1 };
941
942 static const struct wsfont_level2_glyphmap ibm437_level2_1 =
943 { 146, 1, ibm437_chars_1, 1 };
944
945 static const struct wsfont_level2_glyphmap ibm437_level2_3 =
946 { 147, 50, ibm437_chars_3, 1 };
947
948 static const struct wsfont_level2_glyphmap ibm437_level2_32 =
949 { 127, 41, ibm437_chars_32, 1 };
950
951 static const struct wsfont_level2_glyphmap ibm437_level2_34 =
952 { 5, 97, ibm437_chars_34, 1 };
953
954 static const struct wsfont_level2_glyphmap ibm437_level2_35 =
955 { 16, 18, ibm437_chars_35, 1 };
956
957 static const struct wsfont_level2_glyphmap ibm437_level2_37 =
958 { 0, 161, ibm437_chars_37, 1 };
959
960 static const struct wsfont_level2_glyphmap *ibm437_level1[] = {
961 &ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
962 NULL, NULL, NULL, NULL,
963 NULL, NULL, NULL, NULL,
964 NULL, NULL, NULL, NULL,
965 NULL, NULL, NULL, NULL,
966 NULL, NULL, NULL, NULL,
967 NULL, NULL, NULL, NULL,
968 NULL, NULL, NULL, NULL,
969 &ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
970 NULL, &ibm437_level2_37
971 };
972
973 /*
974 * ISO-8859-7 maps
975 */
976 static const u_int8_t iso7_chars_0[] = {
977 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
978 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
979 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
980 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
981 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
982 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
983 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
984 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
985 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
986 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
987 160, 0, 0, 163, 0, 0, 166,167,168,169, 0, 171,172,173, 0, 0,
988 176,177,178,179,180, 0, 0, 183, 0, 0, 0, 187, 0, 189
989 };
990
991 static const u_int8_t iso7_chars_3[] = {
992 182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197,
993 198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213,
994 214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
995 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
996 246,247,248,249,250,251,252,253,254, 0, 0, 0, 0, 0, 0, 0,
997 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
998 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181
999 };
1000
1001 /*
1002 * map all variants of the box drawing characters to the same basic shapes for
1003 * now, encoded like this:
1004 *
1005 * 1
1006 * 1
1007 * 888 222
1008 * 4
1009 * 4
1010 *
1011 * so an upright line would be 0x05
1012 */
1013 #define FL |WSFONT_FLAG_OPT
1014 static const u_int32_t netbsd_boxes[] = {
1015 /*00*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
1016 /*08*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x06 FL,
1017 /*10*/ 0x0c FL, 0x0c FL, 0x0c FL, 0x0c FL, 0x03 FL, 0x03 FL, 0x03 FL, 0x03 FL,
1018 /*18*/ 0x09 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL,
1019 /*20*/ 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL,
1020 /*28*/ 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL,
1021 /*30*/ 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL,
1022 /*38*/ 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
1023 /*40*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
1024 /*48*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
1025 /*50*/ 0x0a FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x0c FL, 0x0c FL, 0x0c FL,
1026 /*58*/ 0x03 FL, 0x03 FL, 0x03 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL,
1027 /*60*/ 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL,
1028 /*68*/ 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x06 FL, 0x0c FL, 0x09 FL,
1029 /*70*/ 0x03 FL, 0 FL, 0 FL, 0 FL, 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL,
1030 /*78*/ 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL, 0x0a FL, 0x05 FL, 0x0a FL, 0x05 FL
1031 };
1032 #undef FL
1033
1034 static const u_int8_t iso7_chars_32[] = {
1035 175, 0, 0, 0, 0, 162, 0, 161
1036 };
1037
1038 static const struct wsfont_level2_glyphmap iso7_level2_0 =
1039 { 0, 190, iso7_chars_0, 1 };
1040
1041 static const struct wsfont_level2_glyphmap iso7_level2_3 =
1042 { 134, 111, iso7_chars_3, 1 };
1043
1044 static const struct wsfont_level2_glyphmap iso7_level2_32 =
1045 { 20, 8, iso7_chars_32, 1 };
1046
1047 static const struct wsfont_level2_glyphmap netbsd_box_drawing =
1048 { 0, 128, netbsd_boxes, 4 };
1049
1050 static const struct wsfont_level2_glyphmap *iso7_level1[] = {
1051 &iso7_level2_0, NULL, NULL, &iso7_level2_3,
1052 NULL, NULL, NULL, NULL,
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 &iso7_level2_32, NULL, NULL, NULL,
1060 NULL, &netbsd_box_drawing
1061 };
1062
1063 static const struct wsfont_level2_glyphmap *iso_level1[] = {
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, NULL, NULL, NULL,
1071 NULL, NULL, NULL, NULL,
1072 NULL, NULL, NULL, NULL,
1073 NULL, &netbsd_box_drawing
1074 };
1075
1076 static const struct wsfont_level1_glyphmap encodings[] = {
1077 { iso_level1, 0, 0x26 }, /* WSDISPLAY_FONTENC_ISO */
1078 { ibm437_level1, 0, 38 }, /* WSDISPLAY_FONTENC_IBM */
1079 { NULL, 0, 0 }, /* WSDISPLAY_FONTENC_PCVT */
1080 { iso7_level1, 0, 0x26 }, /* WSDISPLAY_FONTENC_ISO7 */
1081 };
1082
1083 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0]))
1084
1085 /*
1086 * Remap Unicode character to glyph
1087 */
1088 int
1089 wsfont_map_unichar(struct wsdisplay_font *font, int c)
1090 {
1091 const struct wsfont_level1_glyphmap *map1;
1092 const struct wsfont_level2_glyphmap *map2;
1093 int hi, lo;
1094
1095 if (font->encoding < 0 || font->encoding >= MAX_ENCODING)
1096 return (-1);
1097
1098 hi = (c >> 8);
1099 lo = c & 255;
1100 map1 = &encodings[font->encoding];
1101
1102 if (hi < map1->base || hi >= map1->base + map1->size)
1103 return (-1);
1104
1105 map2 = map1->level2[hi - map1->base];
1106
1107 /* so we don't need an identical level 2 table for hi == 0 */
1108 if (hi == 0 && font->encoding == WSDISPLAY_FONTENC_ISO)
1109 return lo;
1110
1111 if (map2 == NULL || lo < map2->base || lo >= map2->base + map2->size)
1112 return (-1);
1113
1114 lo -= map2->base;
1115
1116 switch(map2->width) {
1117 case 1:
1118 c = (((const u_int8_t *)map2->chars)[lo]);
1119 break;
1120 case 2:
1121 c = (((const u_int16_t *)map2->chars)[lo]);
1122 break;
1123 case 4:
1124 c = (((const u_int32_t *)map2->chars)[lo]);
1125 break;
1126 }
1127
1128 if (c == 0 && lo != 0)
1129 return (-1);
1130
1131 return (c);
1132 }
1133