fixed bug in cfb32_fill_rectangle use c99 syntax for new style struct initializers instead of gcc specific simplified tolower unsigned char hacks fixed various sparse warnings
352 lines
9 KiB
C
352 lines
9 KiB
C
/*
|
|
* Frame buffer low level functions for QEmacs
|
|
*
|
|
* Copyright (c) 2001, 2002 Fabrice Bellard.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "qe.h"
|
|
#include "cfb.h"
|
|
#include "fbfrender.h"
|
|
|
|
static unsigned int cfb15_get_color(unsigned int color)
|
|
{
|
|
unsigned int r, g, b;
|
|
|
|
r = (color >> 16) & 0xff;
|
|
g = (color >> 8) & 0xff;
|
|
b = (color) & 0xff;
|
|
return ((((r) >> 3) << 10) | (((g) >> 3) << 5) | ((b) >> 3));
|
|
}
|
|
|
|
static unsigned int cfb16_get_color(unsigned int color)
|
|
{
|
|
unsigned int r, g, b;
|
|
|
|
r = (color >> 16) & 0xff;
|
|
g = (color >> 8) & 0xff;
|
|
b = (color) & 0xff;
|
|
return ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3));
|
|
}
|
|
|
|
static unsigned int cfb24_get_color(unsigned int color)
|
|
{
|
|
return color & 0xffffff;
|
|
}
|
|
|
|
static void cfb16_fill_rectangle(QEditScreen *s,
|
|
int x1, int y1, int w, int h, QEColor color)
|
|
{
|
|
CFBContext *cfb = s->private;
|
|
unsigned char *dest, *d;
|
|
int y, n;
|
|
unsigned int col;
|
|
|
|
col = cfb->get_color(color);
|
|
col = (col << 16) | col;
|
|
|
|
dest = cfb->base + y1 * cfb->wrap + x1 * 2;
|
|
if (color == QECOLOR_XOR) {
|
|
/* XXX: suppress this mess */
|
|
for (y = 0; y < h; y++) {
|
|
d = dest;
|
|
for (n = w; n != 0; n--) {
|
|
((short *)d)[0] ^= 0xffff;
|
|
d += 2;
|
|
}
|
|
dest += cfb->wrap;
|
|
}
|
|
} else {
|
|
for (y = 0; y < h; y++) {
|
|
d = dest;
|
|
n = w;
|
|
|
|
if (((int)d & 3) != 0) {
|
|
((short *)d)[0] = col;
|
|
d += 2;
|
|
n--;
|
|
}
|
|
|
|
while (n >= 8) {
|
|
((int *)d)[0] = col;
|
|
((int *)d)[1] = col;
|
|
((int *)d)[2] = col;
|
|
((int *)d)[3] = col;
|
|
d += 16;
|
|
n -= 8;
|
|
}
|
|
while (n > 0) {
|
|
((short *)d)[0] = col;
|
|
d += 2;
|
|
n--;
|
|
}
|
|
dest += cfb->wrap;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void cfb32_fill_rectangle(QEditScreen *s,
|
|
int x1, int y1, int w, int h, QEColor color)
|
|
{
|
|
CFBContext *cfb = s->private;
|
|
unsigned char *dest, *d;
|
|
int y, n;
|
|
unsigned int col;
|
|
col = cfb->get_color(color);
|
|
|
|
dest = cfb->base + y1 * cfb->wrap + x1 * 4;
|
|
if (color == QECOLOR_XOR) {
|
|
/* XXX: suppress this mess */
|
|
for (y = 0; y < h; y++) {
|
|
d = dest;
|
|
for (n = w; n != 0; n--) {
|
|
((int *)d)[0] ^= 0x00ffffff;
|
|
d += 4;
|
|
}
|
|
dest += cfb->wrap;
|
|
}
|
|
} else {
|
|
for (y = 0; y < h; y++) {
|
|
d = dest;
|
|
n = w;
|
|
while (n >= 4) {
|
|
((int *)d)[0] = col;
|
|
((int *)d)[1] = col;
|
|
((int *)d)[2] = col;
|
|
((int *)d)[3] = col;
|
|
d += 16;
|
|
n -= 4;
|
|
}
|
|
while (n > 0) {
|
|
((int *)d)[0] = col;
|
|
d += 4;
|
|
n--;
|
|
}
|
|
dest += cfb->wrap;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void cfb16_draw_glyph(QEditScreen *s1,
|
|
int x1, int y1, int w, int h, QEColor color,
|
|
unsigned char *glyph, int glyph_wrap)
|
|
{
|
|
CFBContext *cfb = s1->private;
|
|
unsigned char *dest, *d, *s, *src;
|
|
int n;
|
|
unsigned int col;
|
|
|
|
col = cfb->get_color(color);
|
|
dest = cfb->base + y1 * cfb->wrap + x1 * 2;
|
|
src = glyph;
|
|
|
|
while (h > 0) {
|
|
n = w;
|
|
s = src;
|
|
d = dest;
|
|
while (n >= 4) {
|
|
if (s[0] >= 0x80)
|
|
((short *)d)[0] = col;
|
|
if (s[1] >= 0x80)
|
|
((short *)d)[1] = col;
|
|
if (s[2] >= 0x80)
|
|
((short *)d)[2] = col;
|
|
if (s[3] >= 0x80)
|
|
((short *)d)[3] = col;
|
|
s += 4;
|
|
d += 4 * 2;
|
|
n -= 4;
|
|
}
|
|
while (n > 0) {
|
|
if (s[0] >= 0x80)
|
|
((short *)d)[0] = col;
|
|
s++;
|
|
d += 2;
|
|
n--;
|
|
}
|
|
|
|
h--;
|
|
src += glyph_wrap;
|
|
dest += cfb->wrap;
|
|
}
|
|
}
|
|
|
|
static void cfb32_draw_glyph(QEditScreen *s1,
|
|
int x1, int y1, int w, int h, QEColor color,
|
|
unsigned char *glyph, int glyph_wrap)
|
|
{
|
|
CFBContext *cfb = s1->private;
|
|
unsigned char *dest, *d, *s, *src;
|
|
int n;
|
|
unsigned int col;
|
|
|
|
col = cfb->get_color(color);
|
|
dest = cfb->base + y1 * cfb->wrap + x1 * 4;
|
|
src = glyph;
|
|
|
|
while (h > 0) {
|
|
n = w;
|
|
s = src;
|
|
d = dest;
|
|
while (n >= 4) {
|
|
if (s[0] >= 0x80)
|
|
((int *)d)[0] = col;
|
|
if (s[1] >= 0x80)
|
|
((int *)d)[1] = col;
|
|
if (s[2] >= 0x80)
|
|
((int *)d)[2] = col;
|
|
if (s[3] >= 0x80)
|
|
((int *)d)[3] = col;
|
|
s += 4;
|
|
d += 4 * 4;
|
|
n -= 4;
|
|
}
|
|
while (n > 0) {
|
|
if (s[0] >= 0x80)
|
|
((int *)d)[0] = col;
|
|
s++;
|
|
d += 4;
|
|
n--;
|
|
}
|
|
|
|
h--;
|
|
src += glyph_wrap;
|
|
dest += cfb->wrap;
|
|
}
|
|
}
|
|
|
|
static void cfb_draw_text(QEditScreen *s, QEFont *font,
|
|
int x_start, int y, const unsigned int *str, int len,
|
|
QEColor color)
|
|
{
|
|
CFBContext *cfb = s->private;
|
|
GlyphCache *g;
|
|
unsigned char *glyph_ptr;
|
|
int i, x1, y1, x2, y2, wrap, x;
|
|
unsigned int cc;
|
|
|
|
x = x_start;
|
|
for (i = 0;i < len; i++) {
|
|
cc = str[i];
|
|
g = decode_cached_glyph(s, font, cc);
|
|
if (!g)
|
|
continue;
|
|
|
|
x1 = x + g->x;
|
|
x2 = x1 + g->w;
|
|
y2 = y - g->y;
|
|
y1 = y2 - g->h;
|
|
glyph_ptr = g->data;
|
|
wrap = g->w;
|
|
|
|
if (x1 >= s->clip_x1 && y1 >= s->clip_y1 &&
|
|
x2 <= s->clip_x2 && y2 <= s->clip_y2)
|
|
goto draw;
|
|
|
|
if (x2 <= s->clip_x1 || y2 <= s->clip_y1 ||
|
|
x1 >= s->clip_x2 || y1 >= s->clip_y2)
|
|
goto nodraw;
|
|
|
|
if (x1 < s->clip_x1) {
|
|
glyph_ptr += s->clip_x1 - x1;
|
|
x1 = s->clip_x1;
|
|
}
|
|
if (x2 > s->clip_x2)
|
|
x2 = s->clip_x2;
|
|
if (y1 < s->clip_y1) {
|
|
glyph_ptr += (s->clip_y1 - y1) * wrap;
|
|
y1 = s->clip_y1;
|
|
}
|
|
if (y2 > s->clip_y2)
|
|
y2 = s->clip_y2;
|
|
draw:
|
|
cfb->draw_glyph(s, x1, y1,
|
|
x2 - x1, y2 - y1,
|
|
color, glyph_ptr, wrap);
|
|
nodraw:
|
|
x += g->xincr;
|
|
}
|
|
|
|
/* underline synthesis */
|
|
if (font->style & (QE_STYLE_UNDERLINE | QE_STYLE_LINE_THROUGH)) {
|
|
int dy, h, w;
|
|
h = (font->descent + 2) / 4;
|
|
if (h < 1)
|
|
h = 1;
|
|
w = x - x_start;
|
|
if (font->style & QE_STYLE_UNDERLINE) {
|
|
dy = (font->descent + 1) / 3;
|
|
fill_rectangle(s, x_start, y + dy, w, h, color);
|
|
}
|
|
if (font->style & QE_STYLE_LINE_THROUGH) {
|
|
dy = -(font->ascent / 2 - 1);
|
|
fill_rectangle(s, x_start, y + dy, w, h, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void cfb_set_clip(__unused__ QEditScreen *s,
|
|
__unused__ int x, __unused__ int y,
|
|
__unused__ int w, __unused__ int h)
|
|
{
|
|
}
|
|
|
|
int cfb_init(QEditScreen *s,
|
|
void *base, int wrap, int depth, const char *font_path)
|
|
{
|
|
CFBContext *cfb = s->private;
|
|
|
|
cfb->base = base;
|
|
cfb->wrap = wrap;
|
|
cfb->depth = depth;
|
|
cfb->bpp = (depth + 7) / 8;
|
|
|
|
switch (depth) {
|
|
case 15:
|
|
cfb->get_color = cfb15_get_color;
|
|
break;
|
|
case 16:
|
|
cfb->get_color = cfb16_get_color;
|
|
break;
|
|
case 24:
|
|
default:
|
|
cfb->get_color = cfb24_get_color;
|
|
break;
|
|
}
|
|
|
|
switch (cfb->bpp) {
|
|
case 2:
|
|
s->dpy.dpy_fill_rectangle = cfb16_fill_rectangle;
|
|
cfb->draw_glyph = cfb16_draw_glyph;
|
|
break;
|
|
default:
|
|
case 4:
|
|
s->dpy.dpy_fill_rectangle = cfb32_fill_rectangle;
|
|
cfb->draw_glyph = cfb32_draw_glyph;
|
|
break;
|
|
}
|
|
|
|
s->dpy.dpy_set_clip = cfb_set_clip;
|
|
s->dpy.dpy_draw_text = cfb_draw_text;
|
|
|
|
/* fbf font handling init */
|
|
s->dpy.dpy_text_metrics = fbf_text_metrics;
|
|
s->dpy.dpy_open_font = fbf_open_font;
|
|
s->dpy.dpy_close_font = fbf_close_font;
|
|
|
|
return fbf_render_init(font_path);
|
|
}
|