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