1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright 2017 Toomas Soome <tsoome@me.com>
  29  */
  30 
  31 /*
  32  * Generic font related data and functions shared by early boot console
  33  * in dboot, kernel startup and full kernel.
  34  */
  35 #include <sys/types.h>
  36 #include <sys/systm.h>
  37 #include <sys/font.h>
  38 #include <sys/sysmacros.h>
  39 
  40 /*
  41  * Fonts are statically linked with this module. At some point an
  42  * RFE might be desireable to allow dynamic font loading.  The
  43  * original intention to facilitate dynamic fonts can be seen
  44  * by examining the data structures and set_font().  As much of
  45  * the original code is retained but modified to be suited for
  46  * traversing a list of static fonts.
  47  */
  48 
  49 /*
  50  * Must be sorted by font size in descending order
  51  */
  52 struct fontlist fonts[] = {
  53         {  &font_data_12x22,        NULL  },
  54         {  &font_data_8x16, NULL  },
  55         {  &font_data_7x14, NULL  },
  56         {  &font_data_6x10, NULL  },
  57         {  NULL, NULL  }
  58 };
  59 
  60 void
  61 set_font(struct font *f, short *rows, short *cols, short height, short width)
  62 {
  63         bitmap_data_t   *font_selected = NULL;
  64         struct fontlist *fl;
  65         int i;
  66 
  67         /*
  68          * Find best font for these dimensions, or use default
  69          *
  70          * A 1 pixel border is the absolute minimum we could have
  71          * as a border around the text window (BORDER_PIXELS = 2),
  72          * however a slightly larger border not only looks better
  73          * but for the fonts currently statically built into the
  74          * emulator causes much better font selection for the
  75          * normal range of screen resolutions.
  76          */
  77         for (fl = fonts; fl->data; fl++) {
  78                 if ((((*rows * fl->data->height) + BORDER_PIXELS) <= height) &&
  79                     (((*cols * fl->data->width) + BORDER_PIXELS) <= width)) {
  80                         font_selected = fl->data;
  81                         break;
  82                 }
  83         }
  84         /*
  85          * The minus 2 is to make sure we have at least a 1 pixel
  86          * border around the entire screen.
  87          */
  88         if (font_selected == NULL) {
  89                 if (((*rows * DEFAULT_FONT_DATA.height) > height) ||
  90                     ((*cols * DEFAULT_FONT_DATA.width) > width)) {
  91                         *rows = (height - 2) / DEFAULT_FONT_DATA.height;
  92                         *cols = (width - 2) / DEFAULT_FONT_DATA.width;
  93                 }
  94                 font_selected = &DEFAULT_FONT_DATA;
  95         }
  96 
  97         f->width = font_selected->width;
  98         f->height = font_selected->height;
  99 
 100         for (i = 0; i < ENCODED_CHARS; i++)
 101                 f->char_ptr[i] = font_selected->encoding[i];
 102 
 103         f->image_data = font_selected->image;
 104 
 105 }
 106 
 107 /*
 108  * bit_to_pix4 is for 4-bit frame buffers.  It will write one output byte
 109  * for each 2 bits of input bitmap.  It inverts the input bits before
 110  * doing the output translation, for reverse video.
 111  *
 112  * Assuming foreground is 0001 and background is 0000...
 113  * An input data byte of 0x53 will output the bit pattern
 114  * 00000001 00000001 00000000 00010001.
 115  */
 116 
 117 void
 118 font_bit_to_pix4(
 119     struct font *f,
 120     uint8_t *dest,
 121     uint8_t c,
 122     uint8_t fg_color,
 123     uint8_t bg_color)
 124 {
 125         int     row;
 126         int     byte;
 127         int     i;
 128         uint8_t *cp;
 129         uint8_t data;
 130         uint8_t nibblett;
 131         int     bytes_wide;
 132 
 133         cp = f->char_ptr[c];
 134         bytes_wide = (f->width + 7) / 8;
 135 
 136         for (row = 0; row < f->height; row++) {
 137                 for (byte = 0; byte < bytes_wide; byte++) {
 138                         data = *cp++;
 139                         for (i = 0; i < 4; i++) {
 140                                 nibblett = (data >> ((3-i) * 2)) & 0x3;
 141                                 switch (nibblett) {
 142                                 case 0x0:
 143                                         *dest++ = bg_color << 4 | bg_color;
 144                                         break;
 145                                 case 0x1:
 146                                         *dest++ = bg_color << 4 | fg_color;
 147                                         break;
 148                                 case 0x2:
 149                                         *dest++ = fg_color << 4 | bg_color;
 150                                         break;
 151                                 case 0x3:
 152                                         *dest++ = fg_color << 4 | fg_color;
 153                                         break;
 154                                 }
 155                         }
 156                 }
 157         }
 158 }
 159 
 160 /*
 161  * bit_to_pix8 is for 8-bit frame buffers.  It will write one output byte
 162  * for each bit of input bitmap.  It inverts the input bits before
 163  * doing the output translation, for reverse video.
 164  *
 165  * Assuming foreground is 00000001 and background is 00000000...
 166  * An input data byte of 0x53 will output the bit pattern
 167  * 0000000 000000001 00000000 00000001 00000000 00000000 00000001 00000001.
 168  */
 169 
 170 void
 171 font_bit_to_pix8(
 172     struct font *f,
 173     uint8_t *dest,
 174     uint8_t c,
 175     uint8_t fg_color,
 176     uint8_t bg_color)
 177 {
 178         int     row;
 179         int     byte;
 180         int     i;
 181         uint8_t *cp;
 182         uint8_t data;
 183         int     bytes_wide;
 184         uint8_t mask;
 185         int     bitsleft, nbits;
 186 
 187         cp = f->char_ptr[c];
 188         bytes_wide = (f->width + 7) / 8;
 189 
 190         for (row = 0; row < f->height; row++) {
 191                 bitsleft = f->width;
 192                 for (byte = 0; byte < bytes_wide; byte++) {
 193                         data = *cp++;
 194                         mask = 0x80;
 195                         nbits = MIN(8, bitsleft);
 196                         bitsleft -= nbits;
 197                         for (i = 0; i < nbits; i++) {
 198                                 *dest++ = (data & mask ? fg_color: bg_color);
 199                                 mask = mask >> 1;
 200                         }
 201                 }
 202         }
 203 }
 204 
 205 /*
 206  * bit_to_pix24 is for 24-bit frame buffers.  It will write four output bytes
 207  * for each bit of input bitmap.  It inverts the input bits before
 208  * doing the output translation, for reverse video.  Note that each
 209  * 24-bit RGB value is finally stored in a 32-bit unsigned int, with the
 210  * high-order byte set to zero.
 211  *
 212  * Assuming foreground is 00000000 11111111 11111111 11111111
 213  * and background is 00000000 00000000 00000000 00000000
 214  * An input data byte of 0x53 will output the bit pattern
 215  *
 216  * 00000000 00000000 00000000 00000000
 217  * 00000000 11111111 11111111 11111111
 218  * 00000000 00000000 00000000 00000000
 219  * 00000000 11111111 11111111 11111111
 220  * 00000000 00000000 00000000 00000000
 221  * 00000000 00000000 00000000 00000000
 222  * 00000000 11111111 11111111 11111111
 223  * 00000000 11111111 11111111 11111111
 224  *
 225  */
 226 
 227 void
 228 font_bit_to_pix24(
 229     struct font *f,
 230     uint32_t *dest,
 231     uint8_t c,
 232     uint32_t fg_color32,
 233     uint32_t bg_color32)
 234 {
 235         int     row;
 236         int     byte;
 237         int     i;
 238         uint8_t *cp;
 239         uint32_t data;
 240         int     bytes_wide;
 241         int     bitsleft, nbits;
 242 
 243         cp = f->char_ptr[c];
 244         bytes_wide = (f->width + 7) / 8;
 245 
 246         for (row = 0; row < f->height; row++) {
 247                 bitsleft = f->width;
 248                 for (byte = 0; byte < bytes_wide; byte++) {
 249                         data = *cp++;
 250                         nbits = MIN(8, bitsleft);
 251                         bitsleft -= nbits;
 252                         for (i = 0; i < nbits; i++) {
 253                                 *dest++ = ((data << i) & 0x80 ?
 254                                     fg_color32 : bg_color32);
 255                         }
 256                 }
 257         }
 258 }