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>
| 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 $");
| 31__FBSDID("$FreeBSD: stable/10/sys/dev/vt/vt_font.c 262861 2014-03-06 18:30:56Z jhb $");
|
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. */
| 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
| 44#define VTFONT_MAXMAPPINGS 8192 45#define VTFONT_MAXGLYPHSIZE 1048576
|
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;
| 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 unsigned int normal_map; 90 unsigned int bold_map;
|
89
| 91
|
| 92 /* 93 * No support for printing right hand sides for CJK fullwidth 94 * characters. Simply print a space and assume that the left 95 * hand side describes the entire character. 96 */
|
90 src = TCHAR_CHARACTER(c);
| 97 src = TCHAR_CHARACTER(c);
|
| 98 if (TCHAR_FORMAT(c) & TF_CJK_RIGHT) { 99 normal_map = VFNT_MAP_NORMAL_RIGHT; 100 bold_map = VFNT_MAP_BOLD_RIGHT; 101 } else { 102 normal_map = VFNT_MAP_NORMAL; 103 bold_map = VFNT_MAP_BOLD; 104 } 105
|
91 if (TCHAR_FORMAT(c) & TF_BOLD) {
| 106 if (TCHAR_FORMAT(c) & TF_BOLD) {
|
92 dst = vtfont_bisearch(vf->vf_bold, vf->vf_bold_length, src);
| 107 dst = vtfont_bisearch(vf->vf_map[bold_map], 108 vf->vf_map_count[bold_map], src);
|
93 if (dst != 0) 94 goto found; 95 }
| 109 if (dst != 0) 110 goto found; 111 }
|
96 dst = vtfont_bisearch(vf->vf_normal, vf->vf_normal_length, src);
| 112 dst = vtfont_bisearch(vf->vf_map[normal_map], 113 vf->vf_map_count[normal_map], 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 115found: 116 stride = howmany(vf->vf_width, 8) * vf->vf_height; 117 return (&vf->vf_bytes[dst * stride]); 118} 119 120struct vt_font * 121vtfont_ref(struct vt_font *vf) 122{ 123 124 refcount_acquire(&vf->vf_refcount); 125 return (vf); 126} 127 128void 129vtfont_unref(struct vt_font *vf) 130{
|
| 131 unsigned int i;
|
114 115 if (refcount_release(&vf->vf_refcount)) {
| 132 133 if (refcount_release(&vf->vf_refcount)) {
|
116 free(vf->vf_normal, M_VTFONT); 117 free(vf->vf_bold, M_VTFONT);
| 134 for (i = 0; i < VFNT_MAPS; i++) 135 free(vf->vf_map[i], 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,
| 136 free(vf->vf_bytes, M_VTFONT); 137 free(vf, M_VTFONT); 138 } 139} 140 141static int 142vtfont_validate_map(struct vt_font_map *vfm, unsigned int length,
|
125 unsigned int nglyphs)
| 143 unsigned int glyph_count)
|
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 */
| 144{ 145 unsigned int i, last = 0; 146 147 for (i = 0; i < length; i++) { 148 /* Not ordered. */ 149 if (i > 0 && vfm[i].vfm_src <= last) 150 return (EINVAL); 151 /* 152 * Destination extends amount of glyphs. 153 */
|
136 if (vfm[i].vfm_dst >= nglyphs || 137 vfm[i].vfm_dst + vfm[i].vfm_len >= nglyphs)
| 154 if (vfm[i].vfm_dst >= glyph_count || 155 vfm[i].vfm_dst + vfm[i].vfm_len >= glyph_count)
|
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{
| 156 return (EINVAL); 157 last = vfm[i].vfm_src + vfm[i].vfm_len; 158 } 159 160 return (0); 161} 162 163int 164vtfont_load(vfnt_t *f, struct vt_font **ret) 165{
|
148 size_t glyphsize;
| 166 size_t glyphsize, mapsize;
|
149 struct vt_font *vf; 150 int error;
| 167 struct vt_font *vf; 168 int error;
|
| 169 unsigned int i;
|
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. */
| 170 171 /* Make sure the dimensions are valid. */ 172 if (f->width < 1 || f->height < 1) 173 return (EINVAL); 174 if (f->width > VTFONT_MAXDIMENSION || f->height > VTFONT_MAXDIMENSION) 175 return (E2BIG); 176 177 /* Not too many mappings. */
|
159 if (f->nnormal > VTFONT_MAXMAPPINGS || f->nbold > VTFONT_MAXMAPPINGS) 160 return (E2BIG);
| 178 for (i = 0; i < VFNT_MAPS; i++) 179 if (f->map_count[i] > VTFONT_MAXMAPPINGS) 180 return (E2BIG);
|
161 162 /* Character 0 must always be present. */
| 181 182 /* Character 0 must always be present. */
|
163 if (f->nglyphs < 1)
| 183 if (f->glyph_count < 1)
|
164 return (EINVAL); 165
| 184 return (EINVAL); 185
|
166 glyphsize = howmany(f->width, 8) * f->height * f->nglyphs;
| 186 glyphsize = howmany(f->width, 8) * f->height * f->glyph_count;
|
167 if (glyphsize > VTFONT_MAXGLYPHSIZE) 168 return (E2BIG); 169 170 /* Allocate new font structure. */
| 187 if (glyphsize > VTFONT_MAXGLYPHSIZE) 188 return (E2BIG); 189 190 /* 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);
| 191 vf = malloc(sizeof *vf, M_VTFONT, M_WAITOK | M_ZERO);
|
176 vf->vf_bytes = malloc(glyphsize, M_VTFONT, M_WAITOK); 177 vf->vf_height = f->height; 178 vf->vf_width = f->width;
| 192 vf->vf_bytes = malloc(glyphsize, M_VTFONT, M_WAITOK); 193 vf->vf_height = f->height; 194 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
| 195 vf->vf_refcount = 1; 196
|
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;
| 197 /* Allocate, copy in, and validate mappings. */ 198 for (i = 0; i < VFNT_MAPS; i++) { 199 vf->vf_map_count[i] = f->map_count[i]; 200 if (f->map_count[i] == 0) 201 continue; 202 mapsize = f->map_count[i] * sizeof(struct vt_font_map); 203 vf->vf_map[i] = malloc(mapsize, M_VTFONT, M_WAITOK); 204 error = copyin(f->map[i], vf->vf_map[i], mapsize); 205 if (error) 206 goto bad; 207 error = vtfont_validate_map(vf->vf_map[i], vf->vf_map_count[i], 208 f->glyph_count); 209 if (error) 210 goto bad; 211 } 212 213 /* Copy in glyph data. */
|
192 error = copyin(f->glyphs, vf->vf_bytes, glyphsize); 193 if (error) 194 goto bad; 195
| 214 error = copyin(f->glyphs, vf->vf_bytes, glyphsize); 215 if (error) 216 goto bad; 217
|
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}
| 218 /* Success. */ 219 *ret = vf; 220 return (0); 221 222bad: vtfont_unref(vf); 223 return (error); 224}
|