Deleted Added
sdiff udiff text old ( 259016 ) new ( 262861 )
full compact
1/*-
2 * Copyright (c) 2009 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Ed Schouten under sponsorship from the
6 * FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/dev/vt/vt_font.c 256145 2013-10-08 12:40:04Z ray $");
32
33#include <sys/param.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/refcount.h>
37#include <sys/systm.h>
38
39#include <dev/vt/vt.h>
40
41static MALLOC_DEFINE(M_VTFONT, "vtfont", "vt font");
42
43/* Some limits to prevent abnormal fonts from being loaded. */
44#define VTFONT_MAXMAPPINGS 1024
45#define VTFONT_MAXGLYPHSIZE 262144
46#define VTFONT_MAXDIMENSION 128
47
48static uint16_t
49vtfont_bisearch(const struct vt_font_map *map, unsigned int len, uint32_t src)
50{
51 int min, mid, max;
52
53 min = 0;
54 max = len - 1;
55
56 /* Empty font map. */
57 if (len == 0)
58 return (0);
59 /* Character below minimal entry. */
60 if (src < map[0].vfm_src)
61 return (0);
62 /* Optimization: ASCII characters occur very often. */
63 if (src <= map[0].vfm_src + map[0].vfm_len)
64 return (src - map[0].vfm_src + map[0].vfm_dst);
65 /* Character above maximum entry. */
66 if (src > map[max].vfm_src + map[max].vfm_len)
67 return (0);
68
69 /* Binary search. */
70 while (max >= min) {
71 mid = (min + max) / 2;
72 if (src < map[mid].vfm_src)
73 max = mid - 1;
74 else if (src > map[mid].vfm_src + map[mid].vfm_len)
75 min = mid + 1;
76 else
77 return (src - map[mid].vfm_src + map[mid].vfm_dst);
78 }
79
80 return (0);
81}
82
83const uint8_t *
84vtfont_lookup(const struct vt_font *vf, term_char_t c)
85{
86 uint32_t src;
87 uint16_t dst;
88 size_t stride;
89
90 src = TCHAR_CHARACTER(c);
91 if (TCHAR_FORMAT(c) & TF_BOLD) {
92 dst = vtfont_bisearch(vf->vf_bold, vf->vf_bold_length, src);
93 if (dst != 0)
94 goto found;
95 }
96 dst = vtfont_bisearch(vf->vf_normal, vf->vf_normal_length, src);
97
98found:
99 stride = howmany(vf->vf_width, 8) * vf->vf_height;
100 return (&vf->vf_bytes[dst * stride]);
101}
102
103struct vt_font *
104vtfont_ref(struct vt_font *vf)
105{
106
107 refcount_acquire(&vf->vf_refcount);
108 return (vf);
109}
110
111void
112vtfont_unref(struct vt_font *vf)
113{
114
115 if (refcount_release(&vf->vf_refcount)) {
116 free(vf->vf_normal, M_VTFONT);
117 free(vf->vf_bold, M_VTFONT);
118 free(vf->vf_bytes, M_VTFONT);
119 free(vf, M_VTFONT);
120 }
121}
122
123static int
124vtfont_validate_map(struct vt_font_map *vfm, unsigned int length,
125 unsigned int nglyphs)
126{
127 unsigned int i, last = 0;
128
129 for (i = 0; i < length; i++) {
130 /* Not ordered. */
131 if (i > 0 && vfm[i].vfm_src <= last)
132 return (EINVAL);
133 /*
134 * Destination extends amount of glyphs.
135 */
136 if (vfm[i].vfm_dst >= nglyphs ||
137 vfm[i].vfm_dst + vfm[i].vfm_len >= nglyphs)
138 return (EINVAL);
139 last = vfm[i].vfm_src + vfm[i].vfm_len;
140 }
141
142 return (0);
143}
144
145int
146vtfont_load(vfnt_t *f, struct vt_font **ret)
147{
148 size_t glyphsize;
149 struct vt_font *vf;
150 int error;
151
152 /* Make sure the dimensions are valid. */
153 if (f->width < 1 || f->height < 1)
154 return (EINVAL);
155 if (f->width > VTFONT_MAXDIMENSION || f->height > VTFONT_MAXDIMENSION)
156 return (E2BIG);
157
158 /* Not too many mappings. */
159 if (f->nnormal > VTFONT_MAXMAPPINGS || f->nbold > VTFONT_MAXMAPPINGS)
160 return (E2BIG);
161
162 /* Character 0 must always be present. */
163 if (f->nglyphs < 1)
164 return (EINVAL);
165
166 glyphsize = howmany(f->width, 8) * f->height * f->nglyphs;
167 if (glyphsize > VTFONT_MAXGLYPHSIZE)
168 return (E2BIG);
169
170 /* Allocate new font structure. */
171 vf = malloc(sizeof *vf, M_VTFONT, M_WAITOK);
172 vf->vf_normal = malloc(f->nnormal * sizeof(struct vt_font_map),
173 M_VTFONT, M_WAITOK);
174 vf->vf_bold = malloc(f->nbold * sizeof(struct vt_font_map),
175 M_VTFONT, M_WAITOK);
176 vf->vf_bytes = malloc(glyphsize, M_VTFONT, M_WAITOK);
177 vf->vf_height = f->height;
178 vf->vf_width = f->width;
179 vf->vf_normal_length = f->nnormal;
180 vf->vf_bold_length = f->nbold;
181 vf->vf_refcount = 1;
182
183 /* Copy in data. */
184 error = copyin(f->normal, vf->vf_normal,
185 vf->vf_normal_length * sizeof(struct vt_font_map));
186 if (error)
187 goto bad;
188 error = copyin(f->bold, vf->vf_bold,
189 vf->vf_bold_length * sizeof(struct vt_font_map));
190 if (error)
191 goto bad;
192 error = copyin(f->glyphs, vf->vf_bytes, glyphsize);
193 if (error)
194 goto bad;
195
196 /* Validate mappings. */
197 error = vtfont_validate_map(vf->vf_normal, vf->vf_normal_length,
198 f->nglyphs);
199 if (error)
200 goto bad;
201 error = vtfont_validate_map(vf->vf_bold, vf->vf_bold_length,
202 f->nglyphs);
203 if (error)
204 goto bad;
205
206 /* Success. */
207 *ret = vf;
208 return (0);
209
210bad: vtfont_unref(vf);
211 return (error);
212}