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