efl/legacy/evas/src/evas_x11_routines.c

2035 lines
48 KiB
C

#include "evas_x11_routines.h"
#include "evas_fileless_image.h"
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <assert.h>
#define CLIP(x, y, w, h, xx, yy, ww, hh) \
if (x < (xx)) {w += (x - (xx)); x = (xx);} \
if (y < (yy)) {h += (y - (yy)); y = (yy);} \
if ((x + w) > ((xx) + (ww))) {w = (ww) - (x - xx);} \
if ((y + h) > ((yy) + (hh))) {h = (hh) - (y - yy);}
#define INTERSECTS(x, y, w, h, xx, yy, ww, hh) \
((x < (xx + ww)) && \
(y < (yy + hh)) && \
((x + w) > xx) && \
((y + h) > yy))
#define CLIP_TO(_x, _y, _w, _h, _cx, _cy, _cw, _ch) \
{ \
if (INTERSECTS(_x, _y, _w, _h, _cx, _cy, _cw, _ch)) \
{ \
if (_x < _cx) \
{ \
_w += _x - _cx; \
_x = _cx; \
if (_w < 0) _w = 0; \
} \
if ((_x + _w) > (_cx + _cw)) \
_w = _cx + _cw - _x; \
if (_y < _cy) \
{ \
_h += _y - _cy; \
_y = _cy; \
if (_h < 0) _h = 0; \
} \
if ((_y + _h) > (_cy + _ch)) \
_h = _cy + _ch - _y; \
} \
else \
{ \
_w = 0; _h = 0; \
} \
}
static void __evas_x11_image_cache_flush(Display *disp);
static int __evas_anti_alias = 1;
static Evas_List drawable_list = NULL;
static Visual *__evas_visual = NULL;
static Colormap __evas_cmap = 0;
static Evas_List __evas_images = NULL;
static int __evas_image_cache = 0;
static int __evas_image_cache_max = 512 * 1024;
/* the current clip region and color */
static int __evas_clip = 0;
static int __evas_clip_x = 0;
static int __evas_clip_y = 0;
static int __evas_clip_w = 0;
static int __evas_clip_h = 0;
static int __evas_clip_r = 0;
static int __evas_clip_g = 0;
static int __evas_clip_b = 0;
static int __evas_clip_a = 0;
/*****************************************************************************/
/* image internals ***********************************************************/
/*****************************************************************************/
static void
__evas_x11_image_cache_flush(Display *disp)
{
Evas_X11_Image *im, *im_last;
Evas_List l;
while (__evas_image_cache > __evas_image_cache_max)
{
for (l = __evas_images; l; l = l->next)
{
im = l->data;
if (im->references == 0) im_last = im;
}
if (im_last)
{
im = im_last;
__evas_images = evas_list_remove(__evas_images, im);
if (im->pmap) imlib_free_pixmap_and_mask(im->pmap);
if (im->gc) XFreeGC(im->disp, im->gc);
if (im->file) free(im->file);
if (im->image)
{
imlib_context_set_image(im->image);
imlib_free_image_and_decache();
}
__evas_image_cache -= im->pw * im->ph * 4;
free(im);
}
}
}
/*****************************************************************************/
/* image externals ***********************************************************/
/*****************************************************************************/
Evas_X11_Image *
__evas_x11_image_new_from_file(Display *disp, char *file)
{
Evas_X11_Image *im;
Evas_List l;
for (l = __evas_images; l; l = l->next)
{
im = l->data;
if ((!strcmp(im->file, file)) && (im->disp == disp))
{
if (l != __evas_images)
{
__evas_images = evas_list_remove(__evas_images, im);
__evas_images = evas_list_prepend(__evas_images, im);
}
if (im->references == 0)
{
__evas_image_cache -= im->pw * im->ph * 4;
}
im->references++;
return im;
}
}
im = malloc(sizeof(Evas_X11_Image));
memset(im, 0, sizeof(Evas_X11_Image));
im->image = _evas_find_fileless_image(file);
if (!im->image)
im->image = imlib_load_image(file);
if (!im->image)
{
free(im);
return NULL;
}
im->disp = disp;
im->file = malloc(strlen(file) + 1);
strcpy(im->file, file);
im->references = 1;
imlib_context_set_image(im->image);
imlib_image_set_changes_on_disk();
im->w = imlib_image_get_width();
im->h = imlib_image_get_height();
im->has_alpha = imlib_image_has_alpha();
__evas_images = evas_list_prepend(__evas_images, im);
return im;
}
void
__evas_x11_image_free(Evas_X11_Image *im)
{
im->references--;
if (im->references == 0)
{
/* flush */
__evas_image_cache += im->pw * im->ph * 4;
__evas_x11_image_cache_flush(im->disp);
}
}
void
__evas_x11_image_cache_empty(Display *disp)
{
int size;
size = imlib_get_cache_size();
imlib_set_cache_size(0);
imlib_set_cache_size(size);
size = __evas_image_cache_max;
__evas_image_cache_max = 0;
__evas_x11_image_cache_flush(disp);
__evas_image_cache_max = size;
}
void
__evas_x11_image_cache_set_size(Display *disp, int size)
{
__evas_image_cache_max = size;
imlib_set_cache_size(size * 2);
__evas_x11_image_cache_flush(disp);
}
int
__evas_x11_image_cache_get_size(Display *disp)
{
return __evas_image_cache_max;
}
void
__evas_x11_image_draw(Evas_X11_Image *im,
Display *disp, Imlib_Image dstim, Window w, int win_w, int win_h,
int src_x, int src_y, int src_w, int src_h,
int dst_x, int dst_y, int dst_w, int dst_h,
int cr, int cg, int cb, int ca)
{
Evas_List l;
Imlib_Color_Modifier cm = NULL;
if (ca == 0) return;
if ((src_w == 0) || (src_h == 0) || (dst_w == 0) || (dst_w == 0)) return;
if (__evas_clip)
{
cr = (cr * __evas_clip_r) / 255;
cg = (cg * __evas_clip_g) / 255;
cb = (cb * __evas_clip_b) / 255;
ca = (ca * __evas_clip_a) / 255;
}
if (ca < 128) return;
if ((cr != 255) || (cg != 255) || (cb != 255) || (ca != 255))
{
DATA8 r[256], g[256], b[256], a[256];
int i;
cm = imlib_create_color_modifier();
imlib_context_set_color_modifier(cm);
for (i = 0; i < 256; i++)
{
r[i] = (i * cr) / 255;
g[i] = (i * cg) / 255;
b[i] = (i * cb) / 255;
a[i] = (i * ca) / 255;
}
imlib_set_color_modifier_tables(r, g, b, a);
}
else
imlib_context_set_color_modifier(NULL);
imlib_context_set_display(disp);
imlib_context_set_visual(__evas_visual);
imlib_context_set_colormap(__evas_cmap);
imlib_context_set_drawable(w);
imlib_context_set_dither_mask(0);
imlib_context_set_anti_alias(0);
if (imlib_get_visual_depth(disp, __evas_visual) <= 8)
imlib_context_set_dither(__evas_anti_alias);
else imlib_context_set_dither(0);
imlib_context_set_blend(0);
imlib_context_set_angle(0.0);
imlib_context_set_operation(IMLIB_OP_COPY);
imlib_context_set_direction(IMLIB_TEXT_TO_RIGHT);
for(l = drawable_list; l; l = l->next)
{
Evas_X11_Drawable *dr;
dr = l->data;
if ((dr->win == w) && (dr->disp == disp))
{
Evas_List ll;
for (ll = dr->tmp_images; ll; ll = ll->next)
{
Evas_X11_Update *up;
up = ll->data;
/* if image intersects image update - render */
if (RECTS_INTERSECT(up->x, up->y, up->w, up->h,
dst_x, dst_y, dst_w, dst_h))
{
int xx, yy, ww, hh, iw, ih, dx, dy, dw, dh;
if (!up->p)
up->p = XCreatePixmap(disp, w, up->w, up->h, dr->depth);
dx = dst_x;
dy = dst_y;
dw = dst_w;
dh = dst_h;
iw = im->w;
ih = im->h;
ww = (iw * dw) / src_w;
hh = (ih * dh) / src_h;
xx = (src_x * dw) / src_w;
yy = (src_y * dh) / src_h;
if (__evas_clip)
{
int px, py;
px = dx;
py = dy;
CLIP_TO(dx, dy, dw, dh,
__evas_clip_x, __evas_clip_y,
__evas_clip_w, __evas_clip_h);
xx += dx - px;
yy += dy - py;
}
if ((dw > 1) && (dh > 1))
{
if ((ww != im->pw) || (hh != im->ph) ||
(cr != im->pr) || (cg != im->pg) ||
(cb != im->pb) || (ca != im->pa))
{
if (im->pmap) imlib_free_pixmap_and_mask(im->pmap);
if (im->gc) XFreeGC(im->disp, im->gc);
im->pmap = 0;
im->mask = 0;
im->gc = 0;
im->pw = 0;
im->ph = 0;
}
if (!im->pmap)
{
XGCValues gcv;
imlib_context_set_image(im->image);
im->pw = ww;
im->ph = hh;
im->pr = cr;
im->pg = cg;
im->pb = cb;
im->pa = ca;
imlib_render_pixmaps_for_whole_image_at_size(&im->pmap, &im->mask,
ww, hh);
gcv.graphics_exposures = False;
im->gc = XCreateGC(disp, w,
GCGraphicsExposures, &gcv);
im->win = w;
if (im->mask)
XSetClipMask(disp, im->gc, im->mask);
}
if (im->mask)
XSetClipOrigin(disp, im->gc,
dst_x - up->x - src_x,
dst_y - up->y - src_y);
if (im->pmap)
XCopyArea(disp,
im->pmap, up->p,
im->gc,
xx, yy,
dw, dh,
dx - up->x, dy - up->y);
}
}
}
}
}
if (cm)
{
imlib_free_color_modifier();
imlib_context_set_color_modifier(NULL);
}
}
int
__evas_x11_image_get_width(Evas_X11_Image *im)
{
return im->w;
}
int
__evas_x11_image_get_height(Evas_X11_Image *im)
{
return im->h;
}
void
__evas_x11_image_set_borders(Evas_X11_Image *im, int left, int right,
int top, int bottom)
{
Imlib_Border bd;
imlib_context_set_image(im->image);
imlib_image_get_border(&bd);
if ((bd.left != left) || (bd.right != right) ||
(bd.top != top) || (bd.bottom != bottom))
{
if (im->pmap) imlib_free_pixmap_and_mask(im->pmap);
if (im->gc) XFreeGC(im->disp, im->gc);
im->pmap = 0;
im->mask = 0;
im->gc = 0;
im->pw = 0;
im->ph = 0;
bd.left = left;
bd.right = right;
bd.top = top;
bd.bottom = bottom;
imlib_image_set_border(&bd);
}
}
void
__evas_x11_image_set_smooth_scaling(int on)
{
__evas_anti_alias = on;
}
/*****************************************************************************/
/* font internals ************************************************************/
/*****************************************************************************/
#define TT_VALID( handle ) ( ( handle ).z != NULL )
static Evas_List __evas_fonts = NULL;
static char **__evas_fpath = NULL;
static int __evas_fpath_num = 0;
static int __evas_font_cache = 0;
static int __evas_font_cache_max = 512 * 1024;
static int __evas_have_tt_engine = 0;
static TT_Engine __evas_tt_engine;
static Evas_X11_Glyph *
__evas_x11_text_font_get_glyph(Evas_X11_Font *fn, int glyph)
{
Evas_X11_Glyph *g;
Evas_List l;
int hash;
int code;
hash = glyph & 0xff;
for (l = fn->glyphs[hash]; l; l = l->next)
{
g = l->data;
if (g->glyph_id == glyph)
{
if (l != fn->glyphs[hash])
{
fn->glyphs[hash] = evas_list_remove(fn->glyphs[hash], g);
fn->glyphs[hash] = evas_list_prepend(fn->glyphs[hash], g);
}
return g;
}
}
g = malloc(sizeof(Evas_X11_Glyph));
g->glyph_id = glyph;
TT_New_Glyph(fn->face, &(g->glyph));
code = TT_Char_Index(fn->char_map, glyph);
TT_Load_Glyph(fn->instance, g->glyph, code, TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH);
TT_Get_Glyph_Metrics(g->glyph, &(g->metrics));
g->pw = 0;
g->ph = 0;
g->pmap = 0;
fn->glyphs[hash] = evas_list_prepend(fn->glyphs[hash], g);
return g;
}
static TT_Raster_Map *
__evas_x11_text_font_raster_new(int width, int height)
{
TT_Raster_Map *rmap;
rmap = malloc(sizeof(TT_Raster_Map));
if (!rmap) return NULL;
rmap->width = (width + 3) & -4;
rmap->rows = height;
rmap->flow = TT_Flow_Up;
rmap->cols = rmap->width;
rmap->size = rmap->rows * rmap->width;
if (rmap->size <= 0)
{
free(rmap);
return NULL;
}
rmap->bitmap = malloc(rmap->size);
if (!rmap->bitmap)
{
free(rmap);
return NULL;
}
memset(rmap->bitmap, 0, rmap->size);
return rmap;
}
static void
__evas_x11_text_font_raster_free(TT_Raster_Map * rmap)
{
if (rmap->bitmap) free(rmap->bitmap);
free(rmap);
}
static void
__evas_x11_text_font_render_glyph(Window win, Evas_X11_Font *fn, Evas_X11_Glyph *g)
{
int tw, th, xmin, ymin, xmax, ymax;
TT_Raster_Map *rmap;
if (g->pmap) return;
xmin = g->metrics.bbox.xMin & -64;
ymin = g->metrics.bbox.yMin & -64;
xmax = (g->metrics.bbox.xMax + 63) & -64;
ymax = (g->metrics.bbox.yMax + 63) & -64;
tw = ((xmax - xmin) / 64) + 1;
th = ((ymax - ymin) / 64) + 1;
g->pmap = XCreatePixmap(fn->disp, win, tw, th, 1);
g->pw = tw;
g->ph = th;
fn->mem_use += (((g->pw -1) | 0x7) + 1) * g->ph / 8;
rmap = __evas_x11_text_font_raster_new(tw, th);
if (rmap)
{
int x, y;
XImage *xim;
XGCValues gcv;
GC gc;
xim = XCreateImage(fn->disp, __evas_visual, 1, ZPixmap, 0, NULL, tw, th, 8, 0);
xim->data = malloc(xim->bytes_per_line * xim->height);
TT_Get_Glyph_Bitmap(g->glyph, rmap, -xmin, -ymin);
for (y = 0; y < th; y++)
{
for (x = 0; x < tw; x++)
{
DATA8 rval;
rval = (DATA8)(((unsigned char *)(rmap->bitmap))[((rmap->rows - y - 1) * rmap->cols) + (x >> 3)]);
rval >>= (7 - (x - ((x >> 3) << 3)));
XPutPixel(xim, x, y, rval);
}
}
gc = XCreateGC(fn->disp, g->pmap, 0, &gcv);
XPutImage(fn->disp, g->pmap, gc, xim, 0, 0, 0, 0, tw, th);
XDestroyImage(xim);
XFreeGC(fn->disp, gc);
__evas_x11_text_font_raster_free(rmap);
}
}
__evas_x11_is_file(char *file)
{
struct stat st;
if (stat(file, &st) < 0)
return 0;
return 1;
}
static char *
__evas_x11_font_find(char *font)
{
char buf[4096];
char *ext[] = {".ttf", ".TTF", ""
};
int i, j;
for (i = 0; i < 3; i++)
{
sprintf(buf, "%s%s", font, ext[i]);
if (__evas_x11_is_file(buf))
{
char *f;
f = malloc(strlen(buf) + 1);
strcpy(f, buf);
return f;
}
}
for (j = 0; j < __evas_fpath_num; j++)
{
for (i = 0; i < 3; i++)
{
sprintf(buf, "%s/%s%s", __evas_fpath[j], font, ext[i]);
if (__evas_x11_is_file(buf))
{
char *f;
f = malloc(strlen(buf) + 1);
strcpy(f, buf);
return f;
}
}
}
return NULL;
}
static Evas_X11_Font *
__evas_x11_font_load(char *font, int size)
{
Evas_X11_Font *fn;
char *file;
TT_Error error;
int i, num_cmap, upm;
const int dpi = 96;
file = __evas_x11_font_find(font);
if (!file) return NULL;
if (!__evas_have_tt_engine)
{
error = TT_Init_FreeType(&__evas_tt_engine);
if (error) return NULL;
__evas_have_tt_engine = 1;
}
fn = malloc(sizeof(Evas_X11_Font));
fn->font = malloc(strlen(font) + 1);
strcpy(fn->font, font);
fn->size = size;
fn->engine = __evas_tt_engine;
fn->mem_use = 0;
error = TT_Open_Face(fn->engine, file, &fn->face);
if (error)
{
free(fn->font);
free(fn);
free(file);
return NULL;
}
free(file);
error = TT_Get_Face_Properties(fn->face, &fn->properties);
if (error)
{
TT_Close_Face(fn->face);
free(fn->font);
free(fn);
return NULL;
}
error = TT_New_Instance(fn->face, &fn->instance);
if (error)
{
TT_Close_Face(fn->face);
free(fn->font);
free(fn);
return NULL;
}
TT_Set_Instance_Resolutions(fn->instance, dpi, dpi);
TT_Set_Instance_CharSize(fn->instance, size * 64);
TT_Get_Instance_Metrics(fn->instance, &fn->metrics);
upm = fn->properties.header->Units_Per_EM;
fn->ascent = (fn->properties.horizontal->Ascender * fn->metrics.y_ppem) / upm;
fn->descent = (fn->properties.horizontal->Descender * fn->metrics.y_ppem) / upm;
if (fn->descent < 0) fn->descent = -fn->descent;
num_cmap = fn->properties.num_CharMaps;
for (i = 0; i < num_cmap; i++)
{
unsigned short platform, encoding;
TT_Get_CharMap_ID(fn->face, i, &platform, &encoding);
if ((platform == 3 && encoding == 1) ||
(platform == 0 && encoding == 0))
{
TT_Get_CharMap(fn->face, i, &fn->char_map);
break;
}
}
if (i == num_cmap)
TT_Get_CharMap(fn->face, 0, &fn->char_map);
fn->max_descent = 0;
fn->max_ascent = 0;
memset(fn->glyphs, 0, sizeof(Evas_List) * 256);
fn->references = 1;
/* go thru the first 256 glyps to calculate max ascent/descent */
{
Evas_X11_Glyph *g;
for (i = 0; i < 256; i++)
{
g = __evas_x11_text_font_get_glyph(fn, i);
if (!g) continue;
if (!TT_VALID(g->glyph)) continue;
if ((g->metrics.bbox.yMin & -64) < fn->max_descent)
fn->max_descent = (g->metrics.bbox.yMin & -64);
if (((g->metrics.bbox.yMax + 63) & -64) > fn->max_ascent)
fn->max_ascent = ((g->metrics.bbox.yMax + 63) & -64);
}
}
if (((fn->ascent == 0) && (fn->descent == 0)) || (fn->ascent == 0))
{
fn->ascent = fn->max_ascent / 64;
fn->descent = -fn->max_descent / 64;
}
TT_Flush_Face(fn->face);
return fn;
}
static void
__evas_x11_text_font_cache_flush(void)
{
Evas_List l;
Evas_X11_Font *fn_last;
Evas_X11_Font *fn;
while (__evas_font_cache > __evas_font_cache_max)
{
fn_last = NULL;
for (l = __evas_fonts; l; l = l->next)
{
fn = l->data;
if (fn->references == 0) fn_last = fn;
}
if (fn_last)
{
int i;
__evas_font_cache -= fn->mem_use;
TT_Done_Instance(fn_last->instance);
TT_Close_Face(fn_last->face);
if (fn_last->font) free(fn_last->font);
for (i = 0; i < 256; i++)
{
if (fn_last->glyphs[i])
{
for (l = fn_last->glyphs[i]; l; l = l->next)
{
Evas_X11_Glyph *g;
Evas_List ll;
g = l->data;
if (g->pmap)
XFreePixmap(fn->disp, g->pmap);
free(g);
}
evas_list_free(fn_last->glyphs[i]);
}
}
__evas_fonts = evas_list_remove(__evas_fonts, fn_last);
free(fn_last);
}
}
}
/*****************************************************************************/
/* font externals ************************************************************/
/*****************************************************************************/
Evas_X11_Font *
__evas_x11_text_font_new(Display *disp, char *font, int size)
{
Evas_List l;
Evas_X11_Font *fn;
if (!font) return NULL;
for (l = __evas_fonts; l; l = l->next)
{
Evas_X11_Font *fn;
fn = l->data;
if (!strcmp(fn->font, font) && (size == fn->size))
{
if (l != __evas_fonts)
{
__evas_fonts = evas_list_remove(__evas_fonts, fn);
__evas_fonts = evas_list_prepend(__evas_fonts, fn);
}
if (fn->references == 0)
__evas_font_cache -= fn->mem_use;
fn->references++;
return fn;
}
}
fn = __evas_x11_font_load(font, size);
if (!fn) return NULL;
__evas_fonts = evas_list_prepend(__evas_fonts, fn);
return fn;
}
void
__evas_x11_text_font_free(Evas_X11_Font *fn)
{
if (!fn) return;
if (fn->references >= 0)
{
fn->references--;
if (fn->references == 0)
__evas_font_cache += fn->mem_use;
}
__evas_x11_text_font_cache_flush();
}
int
__evas_x11_text_font_get_ascent(Evas_X11_Font *fn)
{
if (!fn) return 0;
return fn->ascent / 64;
}
int
__evas_x11_text_font_get_descent(Evas_X11_Font *fn)
{
if (!fn) return 0;
return fn->descent / 64;
}
int
__evas_x11_text_font_get_max_ascent(Evas_X11_Font *fn)
{
if (!fn) return 0;
return fn->max_ascent / 64;
}
int
__evas_x11_text_font_get_max_descent(Evas_X11_Font *fn)
{
if (!fn) return 0;
return fn->max_descent / 64;
}
void
__evas_x11_text_font_get_advances(Evas_X11_Font *fn, char *text,
int *advance_horiz,
int *advance_vert)
{
int i, ascent, descent, pw, ph;
if (advance_horiz) *advance_horiz = 0;
if (advance_horiz) *advance_vert = 0;
if (!fn) return;
if (!text) return;
if (text[0] == 0) return;
ascent = fn->ascent;
descent = fn->descent;
pw = 0;
ph = ascent + descent;
for (i = 0; text[i]; i++)
{
Evas_X11_Glyph *g;
int glyph;
glyph = ((unsigned char *)text)[i];
g = __evas_x11_text_font_get_glyph(fn, glyph);
if (!g) continue;
if (!TT_VALID(g->glyph)) continue;
if (i == 0)
pw += ((-g->metrics.bearingX) / 64);
pw += g->metrics.advance / 64;
}
*advance_horiz = pw;
*advance_vert = ph;
}
int
__evas_x11_text_font_get_first_inset(Evas_X11_Font *fn, char *text)
{
int i;
if (!fn) return 0;
if (!text) return 0;
if (text[0] == 0) return 0;
for (i = 0; text[i]; i++)
{
Evas_X11_Glyph *g;
int glyph;
glyph = ((unsigned char *)text)[i];
g = __evas_x11_text_font_get_glyph(fn, glyph);
if (!g) continue;
if (!TT_VALID(g->glyph)) continue;
return ((-g->metrics.bearingX) / 64);
}
return 0;
}
void
__evas_x11_text_font_add_path(char *path)
{
int i;
for (i = 0; i < __evas_fpath_num; i++)
{
if (!strcmp(path, __evas_fpath[i])) return;
}
__evas_fpath_num++;
if (!__evas_fpath) __evas_fpath = malloc(sizeof(char *));
else __evas_fpath = realloc(__evas_fpath,
(__evas_fpath_num * sizeof(char *)));
__evas_fpath[__evas_fpath_num - 1] = malloc(strlen(path) + 1);
strcpy(__evas_fpath[__evas_fpath_num - 1], path);
}
void
__evas_x11_text_font_del_path(char *path)
{
int i, j;
for (i = 0; i < __evas_fpath_num; i++)
{
if (!strcmp(path, __evas_fpath[i]))
{
__evas_fpath_num--;
for (j = i; j < __evas_fpath_num; j++)
__evas_fpath[j] = __evas_fpath[j + 1];
if (__evas_fpath_num > 0)
__evas_fpath = realloc(__evas_fpath,
__evas_fpath_num * sizeof(char *));
else
{
free(__evas_fpath);
__evas_fpath = NULL;
}
}
}
}
char **
__evas_x11_text_font_list_paths(int *count)
{
*count = __evas_fpath_num;
return __evas_fpath;
}
void
__evas_x11_text_cache_empty(Display *disp)
{
int prev_cache;
prev_cache = __evas_font_cache_max;
__evas_font_cache_max = 0;
__evas_x11_text_font_cache_flush();
__evas_font_cache_max = prev_cache;
}
void
__evas_x11_text_cache_set_size(Display *disp, int size)
{
__evas_font_cache_max = size;
__evas_x11_text_font_cache_flush();
}
int
__evas_x11_text_cache_get_size(Display *disp)
{
return __evas_font_cache_max;
}
void
__evas_x11_text_draw(Evas_X11_Font *fn, Display *disp, Imlib_Image dstim, Window win,
int win_w, int win_h, int x, int y, char *text,
int cr, int cg, int cb, int ca)
{
Evas_List l;
DATA32 pixel;
int w, h;
if (__evas_clip)
{
cr = (cr * __evas_clip_r) / 255;
cg = (cg * __evas_clip_g) / 255;
cb = (cb * __evas_clip_b) / 255;
ca = (ca * __evas_clip_a) / 255;
}
if (ca < 128) return;
imlib_context_set_display(disp);
imlib_context_set_visual(__evas_visual);
imlib_context_set_colormap(__evas_cmap);
imlib_context_set_drawable(win);
imlib_context_set_color(cr, cg, cb, ca);
pixel = imlib_render_get_pixel_color();
imlib_context_set_dither_mask(0);
imlib_context_set_anti_alias(0);
imlib_context_set_dither(0);
imlib_context_set_blend(0);
imlib_context_set_angle(0.0);
imlib_context_set_operation(IMLIB_OP_COPY);
imlib_context_set_direction(IMLIB_TEXT_TO_RIGHT);
imlib_context_set_color_modifier(NULL);
__evas_x11_text_get_size(fn, text, &w, &h);
fn->disp = disp;
for(l = drawable_list; l; l = l->next)
{
Evas_X11_Drawable *dr;
dr = l->data;
if ((dr->win == win) && (dr->disp == disp))
{
Evas_List ll;
for (ll = dr->tmp_images; ll; ll = ll->next)
{
Evas_X11_Update *up;
up = ll->data;
/* if image intersects image update - render */
if (RECTS_INTERSECT(up->x, up->y, up->w, up->h,
x, y, w, h))
{
if (!up->p)
up->p = XCreatePixmap(disp, win, up->w, up->h, dr->depth);
XSetForeground(disp, dr->gc, pixel);
XSetClipMask(disp, dr->gc, None);
XSetClipOrigin(disp, dr->gc, 0, 0);
XSetFillStyle(disp, dr->gc, FillStippled);
{
int xx, yy, ww, hh;
XRectangle rect;
xx = up->x;
yy = up->y;
ww = up->w;
hh = up->h;
if (__evas_clip)
{
CLIP_TO(xx, yy, ww, hh,
__evas_clip_x, __evas_clip_y,
__evas_clip_w, __evas_clip_h);
}
rect.x = xx - up->x;
rect.y = yy - up->y;
rect.width = ww;
rect.height = hh;
XSetClipRectangles(disp, dr->gc, 0, 0,
&rect, 1, Unsorted);
{
int i;
int x_offset, y_offset;
int glyph, rows;
Evas_X11_Glyph *g;
if (text[0] == 0) return;
glyph = ((unsigned char *)text)[0];
g = __evas_x11_text_font_get_glyph(fn, glyph);
if (!TT_VALID(g->glyph)) continue;
x_offset = 0;
if (g) x_offset = - (g->metrics.bearingX / 64);
y_offset = -(fn->max_descent / 64);
rows = h;
for (i = 0; text[i]; i++)
{
int xmin, ymin, xmax, ymax, off, adj;
/* for internationalization this here wouldnt just use */
/* the char value of the text[i] but translate form utf-8 */
/* or whetever and incriment i appropriately and set g to */
/* the glyph index */
glyph = ((unsigned char *)text)[i];
g = __evas_x11_text_font_get_glyph(fn, glyph);
__evas_x11_text_font_render_glyph(win, fn, g);
if (!g) continue;
if (!TT_VALID(g->glyph)) continue;
xmin = g->metrics.bbox.xMin & -64;
ymin = g->metrics.bbox.yMin & -64;
xmax = (g->metrics.bbox.xMax + 63) & -64;
ymax = (g->metrics.bbox.yMax + 63) & -64;
xmin = (xmin >> 6) + x_offset;
ymin = (ymin >> 6) + y_offset;
xmax = (xmax >> 6) + x_offset;
ymax = (ymax >> 6) + y_offset;
if (ymin < 0) off = 0;
else off = rows - ymin - 1;
adj = (rows - ymax) -
((fn->max_ascent - fn->max_descent) >> 6);
if (g->pmap)
{
XSetStipple(disp, dr->gc, g->pmap);
XSetTSOrigin(disp, dr->gc,
x + xmin - up->x,
y + ymin + off + adj - up->y);
XFillRectangle(disp, up->p, dr->gc,
x + xmin - up->x,
y + ymin + off + adj - up->y,
xmax - xmin + 1,
ymax - ymin + 1);
x_offset += g->metrics.advance / 64;
}
}
}
}
}
}
}
}
}
void
__evas_x11_text_get_size(Evas_X11_Font *fn, char *text, int *w, int *h)
{
int i, pw, ph;
Evas_X11_Glyph *g;
int glyph;
if (!fn) return;
if (!text) return;
if (text[0] == 0) return;
pw = 0;
ph = (fn->max_ascent - fn->max_descent) / 64;
for (i = 0; text[i]; i++)
{
/* for internationalization this here wouldnt just use */
/* the char value of the text[i] but translate form utf-8 */
/* or whetever and incriment i appropriately and set g to */
/* the glyph index */
glyph = ((unsigned char *)text)[i];
g = __evas_x11_text_font_get_glyph(fn, glyph);
if (!g) continue;
if (!TT_VALID(g->glyph)) continue;
if (i == 0)
pw += ((-g->metrics.bearingX) / 64);
if (text[i + 1] == 0) /* last char - ineternationalization issue */
{
if ((g->metrics.bbox.xMax / 64) == 0)
pw += (g->metrics.advance / 64);
else
pw += (g->metrics.bbox.xMax / 64);
}
else
pw += g->metrics.advance / 64;
}
if (w) *w = pw;
if (h) *h = ph;
}
int
__evas_x11_text_get_character_at_pos(Evas_X11_Font *fn, char *text,
int x, int y,
int *cx, int *cy, int *cw, int *ch)
{
int i, px, ppx;
if (cx) *cx = 0;
if (cy) *cy = 0;
if (cw) *cw = 0;
if (ch) *ch = 0;
if (!fn) return -1;
if (!text) return -1;
if (text[0] == 0) return -1;
if ((y < 0) || (y > (fn->ascent + fn->descent))) return -1;
if (cy) *cy = 0;
if (ch) *ch = fn->ascent + fn->descent;
ppx = 0;
px = 0;
for (i = 0; text[i]; i++)
{
Evas_X11_Glyph *g;
int glyph;
glyph = ((unsigned char *)text)[i];
g = __evas_x11_text_font_get_glyph(fn, glyph);
if (!g) continue;
if (!TT_VALID(g->glyph)) continue;
if (i == 0)
px += ((-g->metrics.bearingX) / 64);
if (text[i + 1] == 0)
px += (g->metrics.bbox.xMax / 64);
else
px += g->metrics.advance / 64;
if ((x >= ppx) && (x < px))
{
if (cx)
*cx = ppx;
if (cw)
*cw = px - ppx;
return i;
}
}
return -1;
}
void
__evas_x11_text_get_character_number(Evas_X11_Font *fn, char *text,
int num,
int *cx, int *cy, int *cw, int *ch)
{
int i, px, ppx;
if (cx) *cx = 0;
if (cy) *cy = 0;
if (cw) *cw = 0;
if (ch) *ch = 0;
if (!fn) return;
if (!text) return;
if (text[0] == 0) return;
if (cy) *cy = 0;
if (ch) *ch = fn->ascent + fn->descent;
ppx = 0;
px = 0;
for (i = 0; text[i]; i++)
{
Evas_X11_Glyph *g;
int glyph;
glyph = ((unsigned char *)text)[i];
g = __evas_x11_text_font_get_glyph(fn, glyph);
if (!g) continue;
if (!TT_VALID(g->glyph)) continue;
ppx = px;
if (i == 0)
px += ((-g->metrics.bearingX) / 64);
if (text[i + 1] == 0)
px += (g->metrics.bbox.xMax / 64);
else
px += g->metrics.advance / 64;
if (i == num)
{
if (cx) *cx = ppx;
if (cw) *cw = px - ppx;
return;
}
}
}
/*****************************************************************************/
/* rectangle externals *******************************************************/
/*****************************************************************************/
void __evas_x11_rectangle_draw(Display *disp, Imlib_Image dstim, Window win,
int win_w, int win_h,
int x, int y, int w, int h,
int cr, int cg, int cb, int ca)
{
Evas_List l;
DATA32 pixel;
if (__evas_clip)
{
cr = (cr * __evas_clip_r) / 255;
cg = (cg * __evas_clip_g) / 255;
cb = (cb * __evas_clip_b) / 255;
ca = (ca * __evas_clip_a) / 255;
}
if (ca < 128) return;
imlib_context_set_display(disp);
imlib_context_set_visual(__evas_visual);
imlib_context_set_colormap(__evas_cmap);
imlib_context_set_drawable(win);
imlib_context_set_color(cr, cg, cb, ca);
pixel = imlib_render_get_pixel_color();
imlib_context_set_dither_mask(0);
imlib_context_set_anti_alias(0);
imlib_context_set_dither(0);
imlib_context_set_blend(0);
imlib_context_set_angle(0.0);
imlib_context_set_operation(IMLIB_OP_COPY);
imlib_context_set_direction(IMLIB_TEXT_TO_RIGHT);
imlib_context_set_color_modifier(NULL);
for(l = drawable_list; l; l = l->next)
{
Evas_X11_Drawable *dr;
dr = l->data;
if ((dr->win == win) && (dr->disp == disp))
{
Evas_List ll;
for (ll = dr->tmp_images; ll; ll = ll->next)
{
Evas_X11_Update *up;
up = ll->data;
/* if image intersects image update - render */
if (RECTS_INTERSECT(up->x, up->y, up->w, up->h,
x, y, w, h))
{
if (!up->p)
up->p = XCreatePixmap(disp, win, up->w, up->h, dr->depth);
XSetForeground(disp, dr->gc, pixel);
XSetClipMask(disp, dr->gc, None);
XSetClipOrigin(disp, dr->gc, 0, 0);
XSetFillStyle(disp, dr->gc, FillSolid);
{
int xx, yy, ww, hh;
xx = x;
yy = y;
ww = w;
hh = h;
CLIP_TO(xx, yy, ww, hh, up->x, up->y, up->w, up->h);
if (__evas_clip)
{
CLIP_TO(xx, yy, ww, hh,
__evas_clip_x, __evas_clip_y,
__evas_clip_w, __evas_clip_h);
}
if ((w > 1) && (h > 1))
XFillRectangle(disp, up->p, dr->gc,
xx - up->x, yy - up->y, ww, hh);
}
}
}
}
}
}
/*****************************************************************************/
/* rectangle externals *******************************************************/
/*****************************************************************************/
void __evas_x11_line_draw(Display *disp, Imlib_Image dstim, Window win,
int win_w, int win_h,
int x1, int y1, int x2, int y2,
int cr, int cg, int cb, int ca)
{
Evas_List l;
int x, y, w, h;
DATA32 pixel;
if (__evas_clip)
{
cr = (cr * __evas_clip_r) / 255;
cg = (cg * __evas_clip_g) / 255;
cb = (cb * __evas_clip_b) / 255;
ca = (ca * __evas_clip_a) / 255;
}
if (ca < 128) return;
imlib_context_set_display(disp);
imlib_context_set_visual(__evas_visual);
imlib_context_set_colormap(__evas_cmap);
imlib_context_set_drawable(win);
imlib_context_set_color(cr, cg, cb, ca);
pixel = imlib_render_get_pixel_color();
imlib_context_set_dither_mask(0);
imlib_context_set_anti_alias(0);
imlib_context_set_dither(0);
imlib_context_set_blend(0);
imlib_context_set_angle(0.0);
imlib_context_set_operation(IMLIB_OP_COPY);
imlib_context_set_direction(IMLIB_TEXT_TO_RIGHT);
imlib_context_set_color_modifier(NULL);
w = x2 - x1;
if (w < 0) w = -w;
h = y2 - y1;
if (h < 0) h = -h;
if (x1 < x2) x = x1;
else x = x2;
if (y1 < y2) y = y1;
else y = y2;
w++; h++;
for(l = drawable_list; l; l = l->next)
{
Evas_X11_Drawable *dr;
dr = l->data;
if ((dr->win == win) && (dr->disp == disp))
{
Evas_List ll;
for (ll = dr->tmp_images; ll; ll = ll->next)
{
Evas_X11_Update *up;
up = ll->data;
/* if image intersects image update - render */
if (RECTS_INTERSECT(up->x, up->y, up->w, up->h,
x, y, w, h))
{
if (!up->p)
up->p = XCreatePixmap(disp, win, up->w, up->h, dr->depth);
XSetForeground(disp, dr->gc, pixel);
XSetClipMask(disp, dr->gc, None);
XSetClipOrigin(disp, dr->gc, 0, 0);
XSetFillStyle(disp, dr->gc, FillSolid);
{
int xx, yy, ww, hh;
XRectangle rect;
xx = up->x;
yy = up->y;
ww = up->w;
hh = up->h;
if (__evas_clip)
{
CLIP_TO(xx, yy, ww, hh,
__evas_clip_x, __evas_clip_y,
__evas_clip_w, __evas_clip_h);
}
rect.x = xx - up->x;
rect.y = yy - up->y;
rect.width = ww;
rect.height = hh;
XSetClipRectangles(disp, dr->gc, 0, 0,
&rect, 1, Unsorted);
XDrawLine(disp, up->p, dr->gc,
x1 - up->x, y1 - up->y,
x2 - up->x, y2 - up->y);
}
}
}
}
}
}
/*****************************************************************************/
/* gradient externals ********************************************************/
/*****************************************************************************/
Evas_X11_Graident *
__evas_x11_gradient_new(Display *disp)
{
Evas_X11_Graident *gr;
gr = malloc(sizeof(Evas_X11_Graident));
gr->colors = NULL;
}
void
__evas_x11_gradient_free(Evas_X11_Graident *gr)
{
Evas_List l;
if (gr->colors)
{
for (l = gr->colors; l; l = l->next)
{
free(l->data);
}
evas_list_free(gr->colors);
}
free(gr);
}
void
__evas_x11_gradient_color_add(Evas_X11_Graident *gr, int r, int g, int b, int a, int dist)
{
Evas_X11_Color *cl;
cl = malloc(sizeof(Evas_X11_Color));
cl->r = r;
cl->g = g;
cl->b = b;
cl->a = a;
cl->dist = dist;
gr->colors = evas_list_append(gr->colors, cl);
}
void
__evas_x11_gradient_draw(Evas_X11_Graident *gr, Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, int x, int y, int w, int h, double angle)
{
Evas_List l;
imlib_context_set_display(disp);
imlib_context_set_visual(__evas_visual);
imlib_context_set_colormap(__evas_cmap);
imlib_context_set_drawable(win);
imlib_context_set_dither_mask(0);
imlib_context_set_anti_alias(0);
imlib_context_set_dither(0);
imlib_context_set_blend(0);
imlib_context_set_angle(0.0);
imlib_context_set_operation(IMLIB_OP_COPY);
imlib_context_set_direction(IMLIB_TEXT_TO_RIGHT);
imlib_context_set_color_modifier(NULL);
/* oops - math was rotated 180 derees - fixup here */
angle += 180;
while (angle < 0.0) angle += 360.0;
while (angle > 360.0) angle -= 360.0;
for (l = drawable_list; l; l = l->next)
{
Evas_X11_Drawable *dr;
dr = l->data;
if ((dr->win == win) && (dr->disp == disp))
{
Evas_List ll;
for (ll = dr->tmp_images; ll; ll = ll->next)
{
Evas_X11_Update *up;
up = ll->data;
if (RECTS_INTERSECT(up->x, up->y, up->w, up->h,
x, y, w, h))
{
int i, p, tot;
int xx, yy, ww, hh;
XRectangle rect;
Evas_List l2;
if (!up->p)
up->p = XCreatePixmap(disp, win, up->w, up->h, dr->depth);
XSetClipMask(disp, dr->gc, None);
XSetClipOrigin(disp, dr->gc, 0, 0);
XSetFillStyle(disp, dr->gc, FillSolid);
xx = x;
yy = y;
ww = w;
hh = h;
if (__evas_clip)
{
CLIP_TO(xx, yy, ww, hh,
__evas_clip_x, __evas_clip_y,
__evas_clip_w, __evas_clip_h);
}
tot = 0;
for (l2 = gr->colors; l2; l2 = l2->next)
{
Evas_X11_Color *c1;
c1 = l2->data;
if (l2 != gr->colors) tot += c1->dist;
}
tot <<= 2;
if ((ww > 1) && (hh > 1))
{
rect.x = xx - up->x;
rect.y = yy - up->y;
rect.width = ww;
rect.height = hh;
XSetClipRectangles(disp, dr->gc, 0, 0,
&rect, 1, Unsorted);
p = 0;
for (l2 = gr->colors; l2; l2 = l2->next)
{
int r, g, b, a;
int dist;
Evas_X11_Color *c1, *c2;
XPoint xpoints[4];
DATA32 pixel;
double x1, y1, x2, y2, x3, y3, per1, per2;
c1 = l2->data;
if (!l2->next) break;;
c2 = l2->next->data;
dist = c2->dist;
for (i = 0; i < (dist << 2); i++)
{
r = ((c1->r * ((dist << 2) - i)) + (c2->r * i)) / (dist << 2);
g = ((c1->g * ((dist << 2) - i)) + (c2->g * i)) / (dist << 2);
b = ((c1->b * ((dist << 2) - i)) + (c2->b * i)) / (dist << 2);
a = ((c1->a * ((dist << 2) - i)) + (c2->a * i)) / (dist << 2);
if (__evas_clip)
{
r = (r * __evas_clip_r) / 255;
g = (g * __evas_clip_g) / 255;
b = (b * __evas_clip_b) / 255;
a = (a * __evas_clip_a) / 255;
}
if (a >= 128)
{
/* | 0/x2 */
/* |_ / */
/* |a/ */
/* -_|/ */
/* |-_ */
/* x3 1/| x1 */
x1 = cos((angle * 2.0 * 3.141592654) / 360.0);
y1 = sin((angle * 2.0 * 3.141592654) / 360.0);
x2 = cos(((angle - 90) * 2.0 * 3.141592654) / 360.0);
y2 = sin(((angle - 90) * 2.0 * 3.141592654) / 360.0);
if ((angle > 0.0) && (angle <= 90.0)) {x3 = -1.0; y3 = 1.0;}
else if ((angle > 90.0) && (angle <= 180.0)) {x3 = -1.0; y3 = -1.0;}
else if ((angle > 180.0) && (angle <= 270.0)) {x3 = 1.0; y3 = -1.0;}
else {x3 = 1.0; y3 = 1.0;}
if ((angle > 315.0) || (angle <= 45.0)) {x2 *= -1.0 / y2; y2 = -1.0;}
else if ((angle > 45.0) && (angle <= 135.0)) {y2 *= 1.0 / x2; x2 = 1.0;}
else if ((angle > 135.0) && (angle <= 225.0)) {x2 *= 1.0 / y2; y2 = 1.0;}
else {y2 *= -1.0 / x2; x2 = -1.0;}
x3 = (x3 + 1.0) / 2.0;
y3 = (y3 + 1.0) / 2.0;
x2 *= 0.5;
y2 *= 0.5;
per1 = (-1.0 + ((((double)(tot - p - 1) / (double)tot) - 0.5) * 2.0));
per2 = (-1.0 + ((((double)(tot - p) / (double)tot) - 0.5) * 2.0));
xpoints[0].x = x - up->x + (int)
((x3 + (2.0 * x1) + (-x2 * per2)) * (double)w);
xpoints[0].y = y - up->y + (int)
((y3 + (2.0 * y1) + (-y2 * per2)) * (double)h);
xpoints[1].x = x - up->x + (int)
((x3 + (2.0 * x1) + (-x2 * per1)) * (double)w);
xpoints[1].y = y - up->y + (int)
((y3 + (2.0 * y1) + (-y2 * per1)) * (double)h);
xpoints[2].x = x - up->x + (int)
((x3 - (2.0 * x1) + (-x2 * per1)) * (double)w);
xpoints[2].y = y - up->y + (int)
((y3 - (2.0 * y1) + (-y2 * per1)) * (double)h);
xpoints[3].x = x - up->x + (int)
((x3 - (2.0 * x1) + (-x2 * per2)) * (double)w);
xpoints[3].y = y - up->y + (int)
((y3 - (2.0 * y1) + (-y2 * per2)) * (double)h);
imlib_context_set_color(r, g, b, a);
pixel = 0;
pixel = imlib_render_get_pixel_color();
XSetForeground(disp, dr->gc, pixel);
XFillPolygon(disp, up->p, dr->gc,
xpoints, 4,
Convex, CoordModeOrigin);
}
p++;
}
}
}
}
}
}
}
}
/************/
/* polygons */
/************/
void
__evas_x11_poly_draw (Display *disp, Imlib_Image dstim, Window win,
int win_w, int win_h,
Evas_List points,
int cr, int cg, int cb, int ca)
{
Evas_List l, l2;
DATA32 pixel;
int x, y, w, h;
if (__evas_clip)
{
cr = (cr * __evas_clip_r) / 255;
cg = (cg * __evas_clip_g) / 255;
cb = (cb * __evas_clip_b) / 255;
ca = (ca * __evas_clip_a) / 255;
}
if (ca < 128) return;
imlib_context_set_display(disp);
imlib_context_set_visual(__evas_visual);
imlib_context_set_colormap(__evas_cmap);
imlib_context_set_drawable(win);
imlib_context_set_color(cr, cg, cb, ca);
pixel = imlib_render_get_pixel_color();
imlib_context_set_dither_mask(0);
imlib_context_set_anti_alias(0);
imlib_context_set_dither(0);
imlib_context_set_blend(0);
imlib_context_set_angle(0.0);
imlib_context_set_operation(IMLIB_OP_COPY);
imlib_context_set_direction(IMLIB_TEXT_TO_RIGHT);
imlib_context_set_color_modifier(NULL);
x = y = w = h = 0;
if (points)
{
Evas_Point p;
p = points->data;
x = p->x;
y = p->y;
w = 1;
h = 1;
}
for (l2 = points; l2; l2 = l2->next)
{
Evas_Point p;
p = l2->data;
if (p->x < x)
{
w += x - p->x;
x = p->x;
}
if (p->x > (x + w))
w = p->x - x;
if (p->y < y)
{
h += y - p->y;
y = p->y;
}
if (p->y > (y + h))
h = p->y - y;
}
for(l = drawable_list; l; l = l->next)
{
Evas_X11_Drawable *dr;
dr = l->data;
if ((dr->win == win) && (dr->disp == disp))
{
Evas_List ll;
for (ll = dr->tmp_images; ll; ll = ll->next)
{
Evas_X11_Update *up;
up = ll->data;
if (RECTS_INTERSECT(up->x, up->y, up->w, up->h,
x, y, w, h))
{
if (!up->p)
up->p = XCreatePixmap(disp, win, up->w, up->h, dr->depth);
XSetForeground(disp, dr->gc, pixel);
XSetClipMask(disp, dr->gc, None);
XSetClipOrigin(disp, dr->gc, 0, 0);
XSetFillStyle(disp, dr->gc, FillSolid);
{
XPoint *xpoints;
int point_count, i;
int xx, yy, ww, hh;
XRectangle rect;
xx = up->x;
yy = up->y;
ww = up->w;
hh = up->h;
if (__evas_clip)
{
CLIP_TO(xx, yy, ww, hh,
__evas_clip_x, __evas_clip_y,
__evas_clip_w, __evas_clip_h);
}
rect.x = xx - up->x;
rect.y = yy - up->y;
rect.width = ww;
rect.height = hh;
XSetClipRectangles(disp, dr->gc, 0, 0,
&rect, 1, Unsorted);
point_count = 0;
for (l2 = points; l2; l2 = l2->next) point_count++;
xpoints = malloc(point_count * sizeof(XPoint));
for (l2 = points, i = 0; l2; l2 = l2->next, i++)
{
Evas_Point p;
p = l2->data;
xpoints[i].x = p->x - up->x;
xpoints[i].y = p->y - up->y;
}
XFillPolygon(disp, up->p, dr->gc, xpoints,
point_count, Complex,
CoordModeOrigin);
free(xpoints);
}
}
}
}
}
}
/*****************************************************************************/
/* general externals *********************************************************/
/*****************************************************************************/
void
__evas_x11_set_clip_rect(int on, int x, int y, int w, int h, int r, int g, int b, int a)
{
__evas_clip = on;
__evas_clip_x = x;
__evas_clip_y = y;
__evas_clip_w = w;
__evas_clip_h = h;
__evas_clip_r = r;
__evas_clip_g = g;
__evas_clip_b = b;
__evas_clip_a = a;
}
void
__evas_x11_sync(Display *disp)
{
XSync(disp, False);
}
void
__evas_x11_flush_draw(Display *disp, Imlib_Image dstim, Window win)
{
Evas_List l;
for(l = drawable_list; l; l = l->next)
{
Evas_X11_Drawable *dr;
dr = l->data;
XSetClipMask(disp, dr->gc, None);
XSetClipOrigin(disp, dr->gc, 0, 0);
XSetFillStyle(disp, dr->gc, FillSolid);
if ((dr->win == win) && (dr->disp == disp))
{
Evas_List ll;
for (ll = dr->tmp_images; ll; ll = ll->next)
{
Evas_X11_Update *up;
up = ll->data;
if (up->p)
{
XCopyArea(disp, up->p, win, dr->gc,
0, 0, up->w, up->h, up->x, up->y);
XFreePixmap(disp, up->p);
}
free(up);
}
if (dr->tmp_images)
dr->tmp_images = evas_list_free(dr->tmp_images);
}
XFreeGC(disp, dr->gc);
free(dr);
}
if (drawable_list)
drawable_list = evas_list_free(drawable_list);
drawable_list = NULL;
}
void
__evas_x11_set_vis_cmap(Visual *vis, Colormap cmap)
{
__evas_visual = vis;
__evas_cmap = cmap;
}
int
__evas_x11_capable(Display *disp)
{
return 1;
}
Visual *
__evas_x11_get_visual(Display *disp, int screen)
{
int depth;
__evas_visual = imlib_get_best_visual(disp, screen, &depth);
return __evas_visual;
}
XVisualInfo *
__evas_x11_get_visual_info(Display *disp, int screen)
{
static XVisualInfo *vi = NULL;
XVisualInfo vi_template;
int n;
if (vi) return vi;
vi_template.visualid = (__evas_x11_get_visual(disp, screen))->visualid;
vi_template.screen = screen;
vi = XGetVisualInfo(disp, VisualIDMask | VisualScreenMask, &vi_template ,&n);
return vi;
}
Colormap
__evas_x11_get_colormap(Display *disp, int screen)
{
Visual *v;
if (__evas_cmap) return __evas_cmap;
v = __evas_x11_get_visual(disp, screen);
__evas_cmap = DefaultColormap(disp, screen);
return __evas_cmap;
__evas_cmap = XCreateColormap(disp, RootWindow(disp, screen), v, AllocNone);
return __evas_cmap;
}
void
__evas_x11_init(Display *disp, int screen, int colors)
{
static int initted = 0;
if (!initted)
{
imlib_set_color_usage(216);
imlib_set_font_cache_size(1024 * 1024);
imlib_set_cache_size(8 * 1024 * 1024);
initted = 1;
}
imlib_set_color_usage(colors);
}
void
__evas_x11_draw_add_rect(Display *disp, Imlib_Image dstim, Window win,
int x, int y, int w, int h)
{
Evas_List l;
for(l = drawable_list; l; l = l->next)
{
Evas_X11_Drawable *dr;
dr = l->data;
if ((dr->win == win) && (dr->disp == disp))
{
Evas_X11_Update *up;
up = malloc(sizeof(Evas_X11_Update));
up->x = x;
up->y = y;
up->w = w;
up->h = h;
up->p = 0;
dr->tmp_images = evas_list_append(dr->tmp_images, up);
}
return;
}
{
Evas_X11_Drawable *dr;
Evas_X11_Update *up;
GC gc;
XGCValues gcv;
XWindowAttributes att;
gc = XCreateGC(disp, win, 0, &gcv);
XGetWindowAttributes(disp, win, &att);
dr = malloc(sizeof(Evas_X11_Drawable));
dr->win = win;
dr->disp = disp;
dr->tmp_images = NULL;
dr->gc = gc;
dr->depth = att.depth;
up = malloc(sizeof(Evas_X11_Update));
up->x = x;
up->y = y;
up->w = w;
up->h = h;
up->p = 0;
drawable_list = evas_list_append(drawable_list, dr);
dr->tmp_images = evas_list_append(dr->tmp_images, up);
}
}