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