#include <sys/types.h>
#include <sys/systm.h>
#include <sys/tem_impl.h>
#include <sys/rgb.h>
#include <sys/font.h>
#include <sys/sysmacros.h>
const uint8_t dim_xlate[XLATE_NCOLORS] = { 1, 5, 3, 7, 2, 6, 4, 8 };
const uint8_t brt_xlate[XLATE_NCOLORS] = { 9, 13, 11, 15, 10, 14, 12, 0 };
const uint8_t solaris_color_to_pc_color[16] = {
pc_brt_white,
pc_black,
pc_blue,
pc_green,
pc_cyan,
pc_red,
pc_magenta,
pc_brown,
pc_white,
pc_grey,
pc_brt_blue,
pc_brt_green,
pc_brt_cyan,
pc_brt_red,
pc_brt_magenta,
pc_yellow
};
const uint8_t pc_color_to_solaris_color[16] = {
sun_black,
sun_blue,
sun_green,
sun_cyan,
sun_red,
sun_magenta,
sun_brown,
sun_white,
sun_grey,
sun_brt_blue,
sun_brt_green,
sun_brt_cyan,
sun_brt_red,
sun_brt_magenta,
sun_yellow,
sun_brt_white
};
const text_cmap_t cmap4_to_24 = {
.red = {
0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff
},
.green = {
0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff
},
.blue = {
0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00
}
};
rgb_t rgb_info = {
.red = { .size = 8, .pos = 16 },
.green = { .size = 8, .pos = 8 },
.blue = { .size = 8, .pos = 0 }
};
uint32_t
rgb_to_color(const rgb_t *rgb, uint32_t a, uint32_t r, uint32_t g, uint32_t b)
{
uint32_t color;
int pos, size;
color = 0;
if (a != 0) {
if (rgb->red.pos != 0 &&
rgb->green.pos != 0 &&
rgb->blue.pos != 0) {
pos = 0;
size = MIN(rgb->red.pos,
MIN(rgb->green.pos, rgb->blue.pos));
} else {
pos = 24;
size = (rgb->red.size + rgb->green.size +
rgb->blue.size) / 3;
}
color = ((a * ((1 << size) - 1)) / 0xff) << pos;
}
pos = rgb->red.pos;
size = rgb->red.size;
color |= ((r * ((1 << size) - 1)) / 0xff) << pos;
pos = rgb->green.pos;
size = rgb->green.size;
color |= (((g * ((1 << size) - 1)) / 0xff) << pos);
pos = rgb->blue.pos;
size = rgb->blue.size;
color |= (((b * ((1 << size) - 1)) / 0xff) << pos);
return (color);
}
uint32_t
rgb_color_map(const rgb_t *rgb, uint8_t index, uint8_t alpha)
{
uint32_t color, code, gray, level;
if (index < 16) {
color = rgb_to_color(rgb, alpha, cmap4_to_24.red[index],
cmap4_to_24.green[index], cmap4_to_24.blue[index]);
return (color);
}
if (index > 15 && index < 232) {
uint32_t red, green, blue;
for (red = 0; red < 6; red++) {
for (green = 0; green < 6; green++) {
for (blue = 0; blue < 6; blue++) {
code = 16 + (red * 36) +
(green * 6) + blue;
if (code != index)
continue;
red = red ? (red * 40 + 55) : 0;
green = green ? (green * 40 + 55) : 0;
blue = blue ? (blue * 40 + 55) : 0;
color = rgb_to_color(rgb, alpha,
red, green, blue);
return (color);
}
}
}
}
for (gray = 0; gray < 24; gray++) {
level = (gray * 10) + 8;
code = 232 + gray;
if (code == index)
break;
}
return (rgb_to_color(rgb, alpha, level, level, level));
}
font_list_t fonts = STAILQ_HEAD_INITIALIZER(fonts);
void
reset_font_flags(void)
{
struct fontlist *fl;
STAILQ_FOREACH(fl, &fonts, font_next) {
fl->font_flags = FONT_AUTO;
}
}
__weak_symbol bitmap_data_t *
gfx_get_font(short rows __unused, short cols __unused, short height __unused,
short width __unused)
{
return (NULL);
}
bitmap_data_t *
set_font(short *rows, short *cols, short h, short w)
{
bitmap_data_t *font = NULL;
struct fontlist *fl;
unsigned height = h;
unsigned width = w;
STAILQ_FOREACH(fl, &fonts, font_next) {
if (fl->font_flags == FONT_MANUAL ||
fl->font_flags == FONT_BOOT) {
font = fl->font_data;
if (font->font == NULL && fl->font_load != NULL &&
fl->font_name != NULL) {
font = fl->font_load(fl->font_name);
}
if (font == NULL || font->font == NULL)
font = NULL;
break;
}
}
if (font == NULL)
font = gfx_get_font(*rows, *cols, h, w);
if (font != NULL) {
*rows = (height - BORDER_PIXELS) / font->height;
*cols = (width - BORDER_PIXELS) / font->width;
return (font);
}
STAILQ_FOREACH(fl, &fonts, font_next) {
font = fl->font_data;
if ((((*rows * font->height) + BORDER_PIXELS) <= height) &&
(((*cols * font->width) + BORDER_PIXELS) <= width)) {
if (font->font == NULL ||
fl->font_flags == FONT_RELOAD) {
if (fl->font_load != NULL &&
fl->font_name != NULL) {
font = fl->font_load(fl->font_name);
}
if (font == NULL)
continue;
}
*rows = (height - BORDER_PIXELS) / font->height;
*cols = (width - BORDER_PIXELS) / font->width;
break;
}
font = NULL;
}
if (font == NULL) {
fl = STAILQ_LAST(&fonts, fontlist, font_next);
if (fl != NULL && fl->font_load != NULL &&
fl->font_name != NULL) {
font = fl->font_load(fl->font_name);
}
if (font == NULL)
font = &DEFAULT_FONT_DATA;
*rows = (height - BORDER_PIXELS) / font->height;
*cols = (width - BORDER_PIXELS) / font->width;
}
return (font);
}
static uint16_t
font_bisearch(const struct font_map *map, uint32_t len, uint32_t src)
{
unsigned min, mid, max;
min = 0;
max = len - 1;
if (len == 0)
return (0);
if (src < map[0].font_src)
return (0);
if (src <= map[0].font_src + map[0].font_len)
return (src - map[0].font_src + map[0].font_dst);
if (src > map[max].font_src + map[max].font_len)
return (0);
while (max >= min) {
mid = (min + max) / 2;
if (src < map[mid].font_src)
max = mid - 1;
else if (src > map[mid].font_src + map[mid].font_len)
min = mid + 1;
else
return (src - map[mid].font_src + map[mid].font_dst);
}
return (0);
}
const uint8_t *
font_lookup(const struct font *vf, uint32_t c)
{
uint32_t src;
uint16_t dst;
size_t stride;
src = TEM_CHAR(c);
if (TEM_CHAR_ATTR(c) & TEM_ATTR_BOLD) {
dst = font_bisearch(vf->vf_map[VFNT_MAP_BOLD],
vf->vf_map_count[VFNT_MAP_BOLD], src);
if (dst != 0)
goto found;
}
dst = font_bisearch(vf->vf_map[VFNT_MAP_NORMAL],
vf->vf_map_count[VFNT_MAP_NORMAL], src);
found:
stride = howmany(vf->vf_width, 8) * vf->vf_height;
return (&vf->vf_bytes[dst * stride]);
}
void
font_bit_to_pix4(
struct font *f,
uint8_t *dest,
uint32_t c,
uint32_t fg_color,
uint32_t bg_color)
{
uint32_t row;
int byte;
int i;
const uint8_t *cp, *ul;
uint8_t data;
uint8_t nibblett;
int bytes_wide;
if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE)
ul = font_lookup(f, 0x0332);
else
ul = NULL;
cp = font_lookup(f, c);
bytes_wide = (f->vf_width + 7) / 8;
for (row = 0; row < f->vf_height; row++) {
for (byte = 0; byte < bytes_wide; byte++) {
if (ul == NULL)
data = *cp++;
else
data = *cp++ | *ul++;
for (i = 0; i < 4; i++) {
nibblett = (data >> ((3-i) * 2)) & 0x3;
switch (nibblett) {
case 0x0:
*dest++ = bg_color << 4 | bg_color;
break;
case 0x1:
*dest++ = bg_color << 4 | fg_color;
break;
case 0x2:
*dest++ = fg_color << 4 | bg_color;
break;
case 0x3:
*dest++ = fg_color << 4 | fg_color;
break;
}
}
}
}
}
void
font_bit_to_pix8(
struct font *f,
uint8_t *dest,
uint32_t c,
uint32_t fg_color,
uint32_t bg_color)
{
uint32_t row;
int byte;
int i;
const uint8_t *cp, *ul;
uint8_t data;
int bytes_wide;
uint8_t mask;
int bitsleft, nbits;
if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE)
ul = font_lookup(f, 0x0332);
else
ul = NULL;
cp = font_lookup(f, c);
bytes_wide = (f->vf_width + 7) / 8;
for (row = 0; row < f->vf_height; row++) {
bitsleft = f->vf_width;
for (byte = 0; byte < bytes_wide; byte++) {
if (ul == NULL)
data = *cp++;
else
data = *cp++ | *ul++;
mask = 0x80;
nbits = MIN(8, bitsleft);
bitsleft -= nbits;
for (i = 0; i < nbits; i++) {
*dest++ = (data & mask ? fg_color: bg_color);
mask = mask >> 1;
}
}
}
}
void
font_bit_to_pix16(
struct font *f,
uint16_t *dest,
uint32_t c,
uint32_t fg_color16,
uint32_t bg_color16)
{
uint32_t row;
int byte;
int i;
const uint8_t *cp, *ul;
uint16_t data, d;
int bytes_wide;
int bitsleft, nbits;
if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE)
ul = font_lookup(f, 0x0332);
else
ul = NULL;
cp = font_lookup(f, c);
bytes_wide = (f->vf_width + 7) / 8;
for (row = 0; row < f->vf_height; row++) {
bitsleft = f->vf_width;
for (byte = 0; byte < bytes_wide; byte++) {
if (ul == NULL)
data = *cp++;
else
data = *cp++ | *ul++;
nbits = MIN(8, bitsleft);
bitsleft -= nbits;
for (i = 0; i < nbits; i++) {
d = ((data << i) & 0x80 ?
fg_color16 : bg_color16);
*dest++ = d;
}
}
}
}
void
font_bit_to_pix24(
struct font *f,
uint8_t *dest,
uint32_t c,
uint32_t fg_color32,
uint32_t bg_color32)
{
uint32_t row;
int byte;
int i;
const uint8_t *cp, *ul;
uint32_t data, d;
int bytes_wide;
int bitsleft, nbits;
if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE)
ul = font_lookup(f, 0x0332);
else
ul = NULL;
cp = font_lookup(f, c);
bytes_wide = (f->vf_width + 7) / 8;
for (row = 0; row < f->vf_height; row++) {
bitsleft = f->vf_width;
for (byte = 0; byte < bytes_wide; byte++) {
if (ul == NULL)
data = *cp++;
else
data = *cp++ | *ul++;
nbits = MIN(8, bitsleft);
bitsleft -= nbits;
for (i = 0; i < nbits; i++) {
d = ((data << i) & 0x80 ?
fg_color32 : bg_color32);
*dest++ = d & 0xff;
*dest++ = (d >> 8) & 0xff;
*dest++ = (d >> 16) & 0xff;
}
}
}
}
void
font_bit_to_pix32(
struct font *f,
uint32_t *dest,
uint32_t c,
uint32_t fg_color32,
uint32_t bg_color32)
{
uint32_t row;
int byte;
int i;
const uint8_t *cp, *ul;
uint32_t data;
int bytes_wide;
int bitsleft, nbits;
if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE)
ul = font_lookup(f, 0x0332);
else
ul = NULL;
cp = font_lookup(f, c);
bytes_wide = (f->vf_width + 7) / 8;
for (row = 0; row < f->vf_height; row++) {
bitsleft = f->vf_width;
for (byte = 0; byte < bytes_wide; byte++) {
if (ul == NULL)
data = *cp++;
else
data = *cp++ | *ul++;
nbits = MIN(8, bitsleft);
bitsleft -= nbits;
for (i = 0; i < nbits; i++) {
*dest++ = ((data << i) & 0x80 ?
fg_color32 : bg_color32);
}
}
}
}