Procházet zdrojové kódy

* X11 driver improvements courtesy of Ben Wiley Sittler. Reworked them a

bit myself, too.
tags/v0.99.beta14
Sam Hocevar sam před 17 roky
rodič
revize
8ed49158e8
1 změnil soubory, kde provedl 263 přidání a 133 odebrání
  1. +263
    -133
      caca/driver_x11.c

+ 263
- 133
caca/driver_x11.c Zobrazit soubor

@@ -1,6 +1,7 @@
/*
* libcaca Colour ASCII-Art library
* Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
* Copyright (c) 2002-2007 Sam Hocevar <sam@zoy.org>
* 2007 Ben Wiley Sittler <bsittler@gmail.com>
* All Rights Reserved
*
* $Id$
@@ -30,6 +31,7 @@

#include <stdio.h> /* BUFSIZ */
#include <stdlib.h>
#include <string.h>

#include "caca.h"
#include "caca_internals.h"
@@ -40,6 +42,8 @@
* Local functions
*/
static int x11_error_handler(Display *, XErrorEvent *);
static void x11_put_glyph(caca_display_t *, int, int, int, int, int,
uint32_t, uint32_t);

struct driver_private
{
@@ -59,8 +63,12 @@ struct driver_private
#if defined(HAVE_X11_XKBLIB_H)
Bool autorepeat;
#endif
uint32_t max_char;
};

#define UNICODE_XLFD_SUFFIX "-iso10646-1"
#define LATIN_1_XLFD_SUFFIX "-iso8859-1"

static int x11_init_graphics(caca_display_t *dp)
{
Colormap colormap;
@@ -99,6 +107,8 @@ static int x11_init_graphics(caca_display_t *dp)
/* Parse our font list */
for( ; ; parser++)
{
unsigned int font_max_char;

if(!*parser)
{
XSetErrorHandler(old_error_handler);
@@ -117,13 +127,47 @@ static int x11_init_graphics(caca_display_t *dp)
continue;
}

if((strlen(*parser) > sizeof(UNICODE_XLFD_SUFFIX))
&& !strcasecmp(*parser + strlen(*parser)
- strlen(UNICODE_XLFD_SUFFIX), UNICODE_XLFD_SUFFIX))
dp->drv.p->max_char = 0xffff;
else if((strlen(*parser) > sizeof(LATIN_1_XLFD_SUFFIX))
&& !strcasecmp(*parser + strlen(*parser)
- strlen(LATIN_1_XLFD_SUFFIX), LATIN_1_XLFD_SUFFIX))
dp->drv.p->max_char = 0xff;
else
dp->drv.p->max_char = 0x7f;

font_max_char =
(((unsigned int)dp->drv.p->font_struct->max_byte1) << 8)
| dp->drv.p->font_struct->max_char_or_byte2;
if(font_max_char && (font_max_char < dp->drv.p->max_char))
dp->drv.p->max_char = font_max_char;

break;
}

/* Reset the default X11 error handler */
XSetErrorHandler(old_error_handler);
dp->drv.p->font_width = 0;
if(dp->drv.p->font_struct->per_char
&& !dp->drv.p->font_struct->min_byte1
&& dp->drv.p->font_struct->min_char_or_byte2 <= 0x21
&& dp->drv.p->font_struct->max_char_or_byte2 >= 0x7e)
{
for(i = 0x21; i < 0x7f; i++)
{
int cw = dp->drv.p->font_struct->per_char[i
- dp->drv.p->font_struct->min_char_or_byte2].width;
if(cw > dp->drv.p->font_width)
dp->drv.p->font_width = cw;
}
}

if(!dp->drv.p->font_width)
dp->drv.p->font_width = dp->drv.p->font_struct->max_bounds.width;

dp->drv.p->font_width = dp->drv.p->font_struct->max_bounds.width;
dp->drv.p->font_height = dp->drv.p->font_struct->max_bounds.ascent
+ dp->drv.p->font_struct->max_bounds.descent;
dp->drv.p->font_offset = dp->drv.p->font_struct->max_bounds.descent;
@@ -173,7 +217,7 @@ static int x11_init_graphics(caca_display_t *dp)
{
XEvent xevent;
XNextEvent(dp->drv.p->dpy, &xevent);
if (xevent.type == MapNotify)
if(xevent.type == MapNotify)
break;
}

@@ -258,8 +302,10 @@ static void x11_display(caca_display_t *dp)
XSetForeground(dp->drv.p->dpy, dp->drv.p->gc,
dp->drv.p->colors[bg]);
XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap, dp->drv.p->gc,
x * dp->drv.p->font_width, y * dp->drv.p->font_height,
len * dp->drv.p->font_width, dp->drv.p->font_height);
x * dp->drv.p->font_width,
y * dp->drv.p->font_height,
len * dp->drv.p->font_width,
dp->drv.p->font_height);
}
}

@@ -269,139 +315,17 @@ static void x11_display(caca_display_t *dp)
unsigned int yoff = (y + 1) * dp->drv.p->font_height
- dp->drv.p->font_offset;
uint32_t *chars = dp->cv->chars + y * dp->cv->width;
uint32_t *attrs = dp->cv->attrs + y * dp->cv->width;

for(x = 0; x < dp->cv->width; x++, chars++)
for(x = 0; x < dp->cv->width; x++, chars++, attrs++)
{
uint32_t *attrs = dp->cv->attrs + x + y * dp->cv->width;

/* Underline */
if(*attrs & CUCUL_UNDERLINE)
XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap,
dp->drv.p->gc,
x * dp->drv.p->font_width,
(y + 1) * dp->drv.p->font_height - 1,
dp->drv.p->font_width, 1);

/* Skip spaces */
if(*chars <= 0x00000020)
continue;

if(*chars == CUCUL_MAGIC_FULLWIDTH)
continue;

XSetForeground(dp->drv.p->dpy, dp->drv.p->gc,
dp->drv.p->colors[_cucul_attr_to_rgb12fg(*attrs)]);

/* Plain ASCII, no problem. */
if(*chars > 0x00000020 && *chars < 0x00000080)
{
char ch = (uint8_t)*chars;
XDrawString(dp->drv.p->dpy, dp->drv.p->pixmap, dp->drv.p->gc,
x * dp->drv.p->font_width, yoff, &ch, 1);
continue;
}

/* We want to be able to print a few special Unicode characters
* such as the CP437 gradients and half blocks. For unknown
* characters, just print '?'. */
switch(*chars)
{
case 0x000000b7: /* · */
XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap,
dp->drv.p->gc,
x * dp->drv.p->font_width
+ dp->drv.p->font_width / 2,
y * dp->drv.p->font_height
+ dp->drv.p->font_height / 2, 2, 2);
break;
case 0x00002500: /* ─ */
XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap,
dp->drv.p->gc,
x * dp->drv.p->font_width,
y * dp->drv.p->font_height
+ dp->drv.p->font_height / 2 + 1,
dp->drv.p->font_width, 1);
break;
case 0x00002580: /* ▀ */
XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap,
dp->drv.p->gc,
x * dp->drv.p->font_width,
y * dp->drv.p->font_height,
dp->drv.p->font_width,
dp->drv.p->font_height / 2);
break;
case 0x00002584: /* ▄ */
XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap,
dp->drv.p->gc,
x * dp->drv.p->font_width,
(y + 1) * dp->drv.p->font_height
- dp->drv.p->font_height / 2,
dp->drv.p->font_width,
dp->drv.p->font_height / 2);
break;
case 0x00002588: /* █ */
XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap,
dp->drv.p->gc,
x * dp->drv.p->font_width,
y * dp->drv.p->font_height,
dp->drv.p->font_width,
dp->drv.p->font_height);
break;
case 0x0000258c: /* ▌ */
XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap,
dp->drv.p->gc,
x * dp->drv.p->font_width,
y * dp->drv.p->font_height,
dp->drv.p->font_width / 2,
dp->drv.p->font_height);
break;
case 0x00002590: /* ▐ */
XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap,
dp->drv.p->gc,
(x + 1) * dp->drv.p->font_width
- dp->drv.p->font_width / 2,
y * dp->drv.p->font_height,
dp->drv.p->font_width / 2,
dp->drv.p->font_height);
break;
case 0x000025a0: /* ■ */
XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap,
dp->drv.p->gc,
x * dp->drv.p->font_width,
y * dp->drv.p->font_height
+ dp->drv.p->font_height / 4,
dp->drv.p->font_width,
dp->drv.p->font_height / 2);
break;
case 0x00002593: /* ▓ */
case 0x00002592: /* ▒ */
case 0x00002591: /* ░ */
{
/* FIXME: this sucks utterly */
int i, j, k = *chars - 0x00002591;
for(j = dp->drv.p->font_height; j--; )
for(i = dp->drv.p->font_width; i--; )
{
if(((i + 2 * (j & 1)) & 3) > k)
continue;

XDrawPoint(dp->drv.p->dpy, dp->drv.p->pixmap,
dp->drv.p->gc,
x * dp->drv.p->font_width + i,
y * dp->drv.p->font_height + j);
}
break;
}
default:
{
char ch;
ch = '?';
XDrawString(dp->drv.p->dpy, dp->drv.p->pixmap,
dp->drv.p->gc,
x * dp->drv.p->font_width, yoff, &ch, 1);
break;
}
}
x11_put_glyph(dp, x * dp->drv.p->font_width,
y * dp->drv.p->font_height, yoff,
dp->drv.p->font_width, dp->drv.p->font_height,
*attrs, *chars);
}
}

@@ -622,6 +546,212 @@ static int x11_error_handler(Display *dpy, XErrorEvent *xevent)
return 0;
}

static void x11_put_glyph(caca_display_t *dp, int x, int y, int yoff,
int w, int h, uint32_t attr, uint32_t ch)
{
Display *dpy = dp->drv.p->dpy;
Pixmap px = dp->drv.p->pixmap;
GC gc = dp->drv.p->gc;
int fw;
XChar2b ch16;

/* Underline */
if(attr & CUCUL_UNDERLINE)
XFillRectangle(dpy, px, gc, x, y + h - 1, w, 1);

/* Skip spaces and magic stuff */
if(ch <= 0x00000020)
return;

if(ch == CUCUL_MAGIC_FULLWIDTH)
return;

fw = w;
if(cucul_utf32_is_fullwidth(ch))
fw *= 2;

/* We want to be able to print a few special Unicode characters
* such as the CP437 gradients and half blocks. For unknown
* characters, print what cucul_utf32_to_ascii() returns. */

if(ch >= 0x2500 && ch <= 0x256c)
{
static uint8_t const udlr[] =
{
/* 0x2500 - 0x250f: ─ . │ . . . . . . . . . ┌ . . . */
0x05, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
/* 0x2510 - 0x251f: ┐ . . . └ . . . ┘ . . . ├ . . . */
0x14, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
0x44, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
/* 0x2520 - 0x252f: . . . . ┤ . . . . . . . ┬ . . . */
0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
/* 0x2530 - 0x253f: . . . . ┴ . . . . . . . ┼ . . . */
0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00,
/* 0x2540 - 0x254f: . . . . . . . . . . . . . . . . */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x2550 - 0x255f: ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟ */
0x0a, 0xa0, 0x12, 0x21, 0x22, 0x18, 0x24, 0x28,
0x42, 0x81, 0x82, 0x48, 0x84, 0x88, 0x52, 0xa1,
/* 0x2560 - 0x256c: ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ */
0xa2, 0x58, 0xa4, 0xa8, 0x1a, 0x25, 0x2a, 0x4a,
0x85, 0x8a, 0x5a, 0xa5, 0xaa,
};

uint16_t D = udlr[ch - 0x2500];

if(!D)
goto next_try;

if(D & 0x04)
XFillRectangle(dpy, px, gc, x, y + h / 2, fw / 2 + 1, 1);

if(D & 0x01)
XFillRectangle(dpy, px, gc,
x + fw / 2, y + h / 2, (fw + 1) / 2, 1);

if(D & 0x40)
XFillRectangle(dpy, px, gc, x + fw / 2, y, 1, h / 2 + 1);

if(D & 0x10)
XFillRectangle(dpy, px, gc, x + fw / 2, y + h / 2, 1, (h + 1) / 2);

#define STEPIF(a,b) (D&(a)?-1:(D&(b))?1:0)

if(D & 0x08)
{
XFillRectangle(dpy, px, gc, x, y - 1 + h / 2,
fw / 2 + 1 + STEPIF(0xc0,0x20), 1);
XFillRectangle(dpy, px, gc, x, y + 1 + h / 2,
fw / 2 + 1 + STEPIF(0x30,0x80), 1);
}

if(D & 0x02)
{
XFillRectangle(dpy, px, gc, x - STEPIF(0xc0,0x20) + fw / 2,
y - 1 + h / 2, (fw + 1) / 2 + STEPIF(0xc0,0x20), 1);
XFillRectangle(dpy, px, gc, x - STEPIF(0x30,0x80) + fw / 2,
y + 1 + h / 2, (fw + 1) / 2 + STEPIF(0x30,0x80), 1);
}

if(D & 0x80)
{
XFillRectangle(dpy, px, gc, x - 1 + fw / 2, y,
1, h / 2 + 1 + STEPIF(0x0c,0x02));
XFillRectangle(dpy, px, gc, x + 1 + fw / 2, y,
1, h / 2 + 1 + STEPIF(0x03,0x08));
}

if(D & 0x20)
{
XFillRectangle(dpy, px, gc, x - 1 + fw / 2,
y - STEPIF(0x0c,0x02) + h / 2,
1, (h + 1) / 2 + STEPIF(0x0c,0x02));
XFillRectangle(dpy, px, gc, x + 1 + fw / 2,
y - STEPIF(0x03,0x08) + h / 2,
1, (h + 1) / 2 + STEPIF(0x03,0x08));
}

return;
}
next_try:

switch(ch)
{
case 0x000000b7: /* · */
case 0x00002219: /* ∙ */
case 0x000030fb: /* ・ */
XFillRectangle(dpy, px, gc, x + fw / 2 - 1, y + h / 2 - 1, 2, 2);
return;

case 0x00002261: /* ≡ */
XFillRectangle(dpy, px, gc, x + 1, y - 2 + h / 2, fw - 1, 1);
XFillRectangle(dpy, px, gc, x + 1, y + h / 2, fw - 1, 1);
XFillRectangle(dpy, px, gc, x + 1, y + 2 + h / 2, fw - 1, 1);
return;

case 0x00002580: /* ▀ */
XFillRectangle(dpy, px, gc, x, y, fw, h / 2);
return;

case 0x00002584: /* ▄ */
XFillRectangle(dpy, px, gc, x, y + h - h / 2, fw, h / 2);
return;

case 0x00002588: /* █ */
case 0x000025ae: /* ▮ */
XFillRectangle(dpy, px, gc, x, y, fw, h);
return;

case 0x0000258c: /* ▌ */
XFillRectangle(dpy, px, gc, x, y, fw / 2, h);
return;

case 0x00002590: /* ▐ */
XFillRectangle(dpy, px, gc, x + fw - fw / 2, y, fw / 2, h);
return;

case 0x000025a0: /* ■ */
case 0x000025ac: /* ▬ */
XFillRectangle(dpy, px, gc, x, y + h / 4, fw, h / 2);
return;

case 0x00002593: /* ▓ */
case 0x00002592: /* ▒ */
case 0x00002591: /* ░ */
{
/* FIXME: this sucks utterly */
int i, j, k = ch - 0x00002591;
for(j = h; j--; )
for(i = fw; i--; )
{
if(((i + 2 * (j & 1)) & 3) > k)
continue;

XDrawPoint(dpy, px, gc, x + i, y + j);
}
return;
}

case 0x000025cb: /* ○ */
case 0x00002022: /* • */
case 0x000025cf: /* ● */
{
int d, xo, yo;

d = fw;
if(h < fw)
d = h;
if(d < 1)
d = 1;
xo = (fw - d) / 2;
yo = (h - d) / 2;
if(ch == 0x000025cb)
XDrawArc(dpy, px, gc, x + xo, y + yo, d, d, 0, 64 * 360);
else
XFillArc(dpy, px, gc, x + xo, y + yo, d, d, 0, 64 * 360);
return;
}
}

if(ch >= 0x00000020 && ch <= dp->drv.p->max_char)
{
/* ascii, latin-1 or unicode font (might draw a blank square) */
ch16.byte1 = (ch) >> 8;
ch16.byte2 = (ch) & 0xff;
}
else
{
ch16.byte1 = 0;
ch16.byte2 = cucul_utf32_to_ascii(ch);
}

XDrawString16(dpy, px, gc, x + (ch16.byte1 ? 0 : (fw - w) / 2), yoff, &ch16, 1);
}

/*
* Driver initialisation
*/


Načítá se…
Zrušit
Uložit