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