The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/vt/vt_font.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: b859a95f9ddd1e0c13bde6712217ee76


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.