From ce2f4fe9f15af05cdaf568066a4a7b5a70d267c5 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Wed, 27 Dec 2000 20:51:39 +0000 Subject: [PATCH] * rewrote GL engine for evas - vast speed improvements and cleanliness improvements - MUCH better * fixed imlib and x11 engines - much faster x11 engine. much better imlib engine * added clipping ability to evas (you can clip one object by another for now only rectangles are supported) * you will need to use cvs imlib2 - i fixed the clipping in it to apply to images, text and gradients too. * almost done with x11 engine - just fonts to go (mostly done) * clipping rects rgba color modifies what they clip * gl, imlib and x11 engines modified to do clipping * still need to add border scaling supporty to gl engine * maybe some other stuff i don't remember - i've been sick over christmas SVN revision: 4039 --- legacy/evas/src/Evas.h | 8 +- legacy/evas/src/Evas_private.h | 40 + legacy/evas/src/evas_events.c | 63 +- legacy/evas/src/evas_gl_routines.c | 4282 ++++++++++++------------ legacy/evas/src/evas_gl_routines.h | 237 +- legacy/evas/src/evas_image_routines.c | 25 + legacy/evas/src/evas_image_routines.h | 1 + legacy/evas/src/evas_imlib_routines.c | 160 +- legacy/evas/src/evas_imlib_routines.h | 15 +- legacy/evas/src/evas_object.c | 171 +- legacy/evas/src/evas_render.c | 105 +- legacy/evas/src/evas_render_routines.c | 26 + legacy/evas/src/evas_render_routines.h | 1 + legacy/evas/src/evas_x11_routines.c | 1360 ++++++-- legacy/evas/src/evas_x11_routines.h | 78 +- legacy/evas/test/evas_test.c | 1 + legacy/evas/test/evas_test_old.c | 42 +- 17 files changed, 3954 insertions(+), 2661 deletions(-) diff --git a/legacy/evas/src/Evas.h b/legacy/evas/src/Evas.h index d979008ddb..6b6718a900 100644 --- a/legacy/evas/src/Evas.h +++ b/legacy/evas/src/Evas.h @@ -99,7 +99,13 @@ void evas_set_output_size(Evas e, int w, int h); void evas_set_output_viewport(Evas e, double x, double y, double w, double h); void evas_set_output_method(Evas e, Evas_Render_Method method); void evas_set_scale_smoothness(Evas e, int smooth); - + +/* clipping - for now you can only use rectangles as clip objects */ +void evas_set_clip(Evas e, Evas_Object o, Evas_Object clip); +void evas_unset_clip(Evas e, Evas_Object o); +Evas_Object evas_get_clip_object(Evas e, Evas_Object o); +Evas_List evas_get_clip_list(Evas e, Evas_Object o); + /* deleting objects */ void evas_del_object(Evas e, Evas_Object o); diff --git a/legacy/evas/src/Evas_private.h b/legacy/evas/src/Evas_private.h index 2087955cd7..0a3c5a834e 100644 --- a/legacy/evas/src/Evas_private.h +++ b/legacy/evas/src/Evas_private.h @@ -34,6 +34,40 @@ typedef struct _Evas_Object_Poly * Evas_Object_Poly; #define IF_OBJ(_o, _t) if (((Evas_Object)_o)->type != _t) +#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; \ + } \ + } + + #include "Evas.h" struct _Evas_Render_Data { @@ -151,6 +185,12 @@ struct _Evas_Object_Any Evas_List callbacks; Evas_List data; + struct { + Evas_List list; + Evas_Object object; + int changed; + } clip; + Evas_Render_Data renderer_data; char *name; diff --git a/legacy/evas/src/evas_events.c b/legacy/evas/src/evas_events.c index b2b6b53614..5b69e7dce0 100644 --- a/legacy/evas/src/evas_events.c +++ b/legacy/evas/src/evas_events.c @@ -5,71 +5,24 @@ #include #include -int -_evas_point_in_object(Evas e, Evas_Object o, int x, int y) -{ - int ox, oy, ow, oh; - - if (o->delete_me) return 0; - _evas_object_get_current_translated_coords(e, o, &ox, &oy, &ow, &oh); - if ((x >= ox) && (x < (ox + ow)) && (y >= oy) && (y < (oy + oh))) - return 1; - return 0; -} - Evas_Object _evas_highest_object_at_point(Evas e, int x, int y) { - Evas_List l, ll; - Evas_Layer layer; - Evas_Object o; + double cx, cy; - o = NULL; - for (l = e->layers; l ; l = l->next) - { - layer = l->data; - - for (ll = layer->objects; ll; ll = ll->next) - { - Evas_Object ob; - - ob = ll->data; - if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me)) - { - if (_evas_point_in_object(e, ob, x, y)) - { - o = ob; - } - } - } - } - return o; + cx = evas_screen_x_to_world(e, x); + cy = evas_screen_x_to_world(e, y); + return evas_object_at_position(e, cx, cy); } Evas_List _evas_objects_at_point(Evas e, int x, int y) { - Evas_List l, ll, objs; - Evas_Layer layer; + double cx, cy; - objs = NULL; - for (l = e->layers; l ; l = l->next) - { - layer = l->data; - - for (ll = layer->objects; ll; ll = ll->next) - { - Evas_Object ob; - - ob = ll->data; - if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me)) - { - if (_evas_point_in_object(e, ll->data, x, y)) - objs = evas_list_prepend(objs, ll->data); - } - } - } - return objs; + cx = evas_screen_x_to_world(e, x); + cy = evas_screen_x_to_world(e, y); + return evas_objects_at_position(e, cx, cy); } void diff --git a/legacy/evas/src/evas_gl_routines.c b/legacy/evas/src/evas_gl_routines.c index 4fc6d3fafa..8643191828 100644 --- a/legacy/evas/src/evas_gl_routines.c +++ b/legacy/evas/src/evas_gl_routines.c @@ -2,6 +2,48 @@ #include #include #include +#include + +/* uncomment this is partial buffer swaps fail - problem with glcopypixels? */ +#define GLSWB 1 +/* uncomment if your GL implimentation is CRAP at clipping */ +/* #define GLNOCLIP 1 */ + +#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; \ + } \ + } + + +#define TT_VALID( handle ) ( ( handle ).z != NULL ) #ifdef HAVE_GL @@ -15,1090 +57,809 @@ static int __evas_gl_configuration[] = None }; -static void __evas_gl_image_copy_image_rect_to_texture(Evas_GL_Image *im, int x, int y, int w, int h, int tw, int th, GLuint texture); -static void __evas_gl_image_move_state_data_to_texture(Evas_GL_Image *im); -static void __evas_gl_image_calc_tex_and_poly(Evas_GL_Image *im, int x, double *x1, double *x2, int *tx, int *txx, double *dtx, double *dtxx, int tw, int w, int edge); -static Evas_GL_Image *__evas_gl_create_image(void); -static Evas_GL_Image *__evas_gl_image_create_from_file(Display *disp, char *file); -static void __evas_gl_image_free_textures(Evas_GL_Image *im); -static void __evas_gl_image_destroy(Evas_GL_Image *im); -static void __evas_gl_image_cache_flush(Display *disp); +static Evas_GL_Window *__evas_current = NULL; -static void __evas_gl_text_font_render_textures(Evas_GL_Font *f); -static TT_Raster_Map *__evas_gl_text_font_raster_new(int width, int height); -static void __evas_gl_text_font_raster_free(TT_Raster_Map * rmap); -static void __evas_gl_text_font_path_add(const char *path); -static void __evas_gl_text_font_path_del(const char *path); -static char **__evas_gl_text_font_path_list(int *num_ret); -static int __evas_gl_is_file(char *file); -static Evas_GL_Font *__evas_gl_text_font_load(char *font, int size); -static void __evas_gl_text_calc_size(Evas_GL_Font *f, int *width, int *height, char *text); -static void __evas_gl_text_font_destroy(Evas_GL_Font *font); -static void __evas_gl_text_paste(Evas_GL_Font *f, char *text, Display *disp, Window w, int win_w, int win_h, int x, int y, int r, int g, int b, int a); -static void __evas_gl_text_cache_flush(void); +static Evas_List __evas_windows = NULL; +static Evas_List __evas_contexts = NULL; +static Evas_List __evas_images = NULL; +static Evas_List __evas_fonts = NULL; +static int __evas_image_cache = 0; +static int __evas_image_cache_max = 512 * 1024; -static XVisualInfo *__evas_vi = NULL; -static GLXContext __evas_gl_cx = 0; -static Window __evas_context_window = 0; -static Evas_List __evas_images = NULL; -static int __evas_image_cache_max = 16 *1024 * 1024; -static int __evas_image_cache_used = 0; +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 Display *__evas_current_disp = NULL; -static Window __evas_current_win = 0; +static int __evas_rend_lut[9] = { 0, 64, 128, 192, 255, 255, 255, 255, 255}; -static Evas_List __evas_fonts = NULL; -static int __evas_fpath_num = 0; -static char **__evas_fpath = NULL; -static TT_Engine __evas_engine; -static char __evas_have_engine = 0; -static int __evas_font_cache_max = 512 * 1024; -static int __evas_font_cache_used = 0; +static int __evas_have_tt_engine = 0; +static TT_Engine __evas_tt_engine; -static int __evas_anti_alias = 1; +/* smooth (linear interp / supersample/mipmap scaling or "nearest" sampling */ +static int __evas_smooth = 1; +/* 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; -const int __evas_rend_lut[9] = { 0, 64, 128, 192, 255, 255, 255, 255, 255}; - -#define TT_VALID( handle ) ( ( handle ).z != NULL ) - -/* -#ifdef HAVE_GLU -#undef HAVE_GLU -#endif -*/ - - - - - - - - - - - - - - - - - - - - - -/*****************************************************************************/ -/* image internals ***********************************************************/ -/*****************************************************************************/ - -static void -__evas_gl_image_copy_image_rect_to_texture(Evas_GL_Image *im, int x, int y, - int w, int h, int tw, int th, - GLuint texture) +static Evas_GL_Context * +__evas_gl_context_new(Display *disp, int screen) { - int tx, ty; - DATA32 *data, *p1, *p2; + Evas_GL_Context *c; + XSetWindowAttributes att; + int eb, evb; - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); -#if 0 -#ifdef HAVE_GLU - if (__evas_anti_alias) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - else -#else - if (__evas_anti_alias) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - else -#endif - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } -#endif - data = malloc(tw * th * 4); - for (ty = 0; ty < h; ty++) - { - p1 = im->data + ((y + ty) * im->w) + x; - p2 = data + (ty * tw); - for (tx = 0; tx < w; tx++) - { -#ifndef WORDS_BIGENDIAN - *p2 = - ((*p1 & 0xff000000)) | - ((*p1 & 0x00ff0000) >> 16) | - ((*p1 & 0x0000ff00)) | - ((*p1 & 0x000000ff) << 16); -#else - *p2 = - ((*p1 & 0xff000000) >> 24) | - ((*p1 & 0x00ff0000) << 8) | - ((*p1 & 0x0000ff00) << 8) | - ((*p1 & 0x000000ff) << 8); -#endif - p2++; p1++; - } - if (tx < tw) - *p2 = p2[-1]; - } - if (ty < th) - { - p1 = data + ((ty - 1) * tw); - p2 = data + (ty * tw); - for (tx = 0; tx < w; tx++) - { - *p2 = *p1; - p2++; p1++; - } - if (tx < tw) - *p2 = p2[-1]; - } -#ifdef HAVE_GLU - if (__evas_anti_alias) - { - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, tw, th, GL_RGBA, - GL_UNSIGNED_BYTE, data); - if (glGetError() == GL_OUT_OF_MEMORY) - { - __evas_gl_image_cache_empty(im->buffer.display); - __evas_gl_text_cache_empty(im->buffer.display); - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, tw, th, GL_RGBA, - GL_UNSIGNED_BYTE, data); - } - } - else -#endif - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tw, th, 0, - GL_RGBA, GL_UNSIGNED_BYTE, data); - if (glGetError() == GL_OUT_OF_MEMORY) - { - __evas_gl_image_cache_empty(im->buffer.display); - __evas_gl_text_cache_empty(im->buffer.display); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tw, th, 0, - GL_RGBA, GL_UNSIGNED_BYTE, data); - } - } - free(data); + if (!glXQueryExtension(disp, &eb, &evb)) return NULL; + c = malloc(sizeof(Evas_GL_Context)); + c->disp = disp; + c->screen = screen; + c->visualinfo = glXChooseVisual(c->disp, c->screen, __evas_gl_configuration); + c->visual = c->visualinfo->visual; + c->context = glXCreateContext(c->disp, c->visualinfo, NULL, GL_TRUE); + c->root = RootWindow(c->disp, c->screen); + c->colormap = XCreateColormap(c->disp, c->root, c->visual, 0); + att.colormap = c->colormap; + att.border_pixel = 0; + att.event_mask = 0; + c->win = XCreateWindow(c->disp, c->root, 0, 0, 1, 1, 0, + c->visualinfo->depth, InputOutput, + c->visual, CWColormap | CWBorderPixel | CWEventMask, + &att); + glXMakeCurrent(c->disp, c->win, c->context); + glShadeModel(GL_FLAT); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glEnable(GL_LINE_SMOOTH); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + c->texture = 0; + glDisable(GL_TEXTURE_2D); + c->dither = 0; + glDisable(GL_DITHER); + c->blend = 1; + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + c->color = 0xffffffff; + glColor4f(1.0, 1.0, 1.0, 1.0); + + c->clip.active = 0; + c->clip.x = 0; + c->clip.y = 0; + c->clip.w = 0; + c->clip.h = 0; + glDisable(GL_SCISSOR_TEST); + + c->read_buf = GL_BACK; + glReadBuffer(GL_BACK); + c->write_buf = GL_FRONT; + glDrawBuffer(GL_BACK); + + c->bound_texture = NULL; + + /* FIXME: need to determine these */ + c->max_texture_depth = 32; + c->max_texture_size = 256; + + return c; } -static void -__evas_gl_image_move_state_data_to_texture(Evas_GL_Image *im) +static Evas_GL_Context * +__evas_gl_context_lookup(Display *disp, int screen) { - int i, x, y; - int image_data = 0; - Imlib_Image image = NULL; + Evas_List l; + Evas_GL_Context *c; - if ((!im->data) && (im->file)) + for (l = __evas_contexts; l; l = l->next) { - image = imlib_load_image(im->file); - if (image) + c = l->data; + if ((c->disp == disp) && (c->screen == screen)) { - imlib_context_set_image(image); - im->data = imlib_image_get_data_for_reading_only(); - image_data = 1; + if (l != __evas_contexts) + { + __evas_contexts = evas_list_remove(__evas_contexts, c); + __evas_contexts = evas_list_prepend(__evas_contexts, c); + } + return c; } } - if (!im->data) return; + c = __evas_gl_context_new(disp, screen); + if (!c) return NULL; + __evas_contexts = evas_list_prepend(__evas_contexts, c); + return c; +} + +static Evas_GL_Window * +__evas_gl_window_new(Display *disp, Window win) +{ + Evas_GL_Context *c; + Evas_GL_Window *w; + Window root; + int screen, i; + XWindowAttributes att; + + XGetWindowAttributes(disp, win, &att); + root = att.root; + screen = 0; + for (i = 0; i < ScreenCount(disp); i++) + { + if (RootWindow(disp, i) == root) + { + screen = i; + break; + } + } + c = __evas_gl_context_lookup(disp, screen); + if (!c) return NULL; + w = malloc(sizeof(Evas_GL_Window)); + w->disp = disp; + w->win = win; + w->context = c; + w->root = root; + w->screen = screen; + w->updates = NULL; + w->w = 0; + w->h = 0; + return w; +} + +static Evas_GL_Window * +__evas_gl_window_lookup(Display *disp, Window win) +{ + Evas_List l; + Evas_GL_Window *w; + + for (l = __evas_windows; l; l = l->next) + { + w = l->data; + if ((w->win == win) && (w->disp == disp)) + { + if (l != __evas_windows) + { + __evas_windows = evas_list_remove(__evas_windows, w); + __evas_windows = evas_list_prepend(__evas_windows, w); + } + return w; + } + } + w = __evas_gl_window_new(disp, win); + if (!w) return NULL; + __evas_windows = evas_list_prepend(__evas_windows, w); + return w; +} + +static Evas_GL_Window * +__evas_gl_window_current(Display *disp, Window win, int w, int h) +{ + Evas_GL_Window *glw; + + glw = __evas_gl_window_lookup(disp, win); + if (!glw) return NULL; + if (glw != __evas_current) + { + double dr, dg, db, da; - im->texture.w = im->w / (im->texture.max_size - 2); - if (im->w > ((im->texture.max_size - 2) * im->texture.w)) - { - int shift = 0; + __evas_current = glw; + glw->w = w; + glw->h = h; + glXMakeCurrent(glw->disp, glw->win, glw->context->context); + glShadeModel(GL_FLAT); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glEnable(GL_LINE_SMOOTH); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ALIGNMENT, 1); - im->texture.edge_w = im->w - (im->texture.w * (im->texture.max_size - 2)); - while (im->texture.edge_w < (im->texture.max_size >> shift)) shift++; - im->texture.edge_w = im->texture.max_size >> (shift - 1); - im->texture.w++; - } - else - im->texture.edge_w = im->texture.max_size; - im->texture.h = im->h / (im->texture.max_size - 2); - if (im->h > ((im->texture.max_size - 2) * im->texture.h)) - { - int shift = 0; - - im->texture.edge_h = im->h - (im->texture.h * (im->texture.max_size - 2)); - while (im->texture.edge_h < (im->texture.max_size >> shift)) shift++; - im->texture.edge_h = im->texture.max_size >> (shift - 1); - im->texture.h++; - } - else - im->texture.edge_h = im->texture.max_size; - - if (!__evas_context_window) - { - XSetWindowAttributes att; - att.colormap = im->buffer.colormap; - att.border_pixel = 0; - att.event_mask = 0; - __evas_context_window = XCreateWindow(im->buffer.display, - RootWindow(im->buffer.display, DefaultScreen(im->buffer.display)), - 0, 0, 32, 32, 0, - im->buffer.visual_info->depth, - InputOutput, - im->buffer.visual_info->visual, - CWColormap | CWBorderPixel | CWEventMask, - &att); - im->buffer.window = __evas_context_window; - im->texture.textures = malloc(sizeof(GLuint) * im->texture.w * im->texture.h); - glXMakeCurrent(im->buffer.display, im->buffer.window, im->context); - __evas_current_disp = im->buffer.display; - __evas_current_win = im->buffer.window; - } - else - { - im->buffer.window = __evas_context_window; - im->texture.textures = malloc(sizeof(GLuint) * im->texture.w * im->texture.h); - glXMakeCurrent(im->buffer.display, im->buffer.window, im->context); - __evas_current_disp = im->buffer.display; - __evas_current_win = im->buffer.window; - } - glGenTextures(im->texture.w * im->texture.h, im->texture.textures); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glEnable(GL_TEXTURE_2D); - - for (i = 0, y = 0; y < im->texture.h; y++) - { - for (x = 0; x < im->texture.w; x++, i++) + glViewport(0, 0, glw->w, h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, glw->w, 0, glw->h, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glScalef(1, -1, 1); + glTranslatef(0, - glw->h, 0); + if (glw->context->dither) glEnable(GL_DITHER); + else glDisable(GL_DITHER); + if (glw->context->blend) { - int xx, yy, ww, hh, tw, th; - - if (x == (im->texture.w - 1)) tw = im->texture.edge_w; - else tw = im->texture.max_size; - if (y == (im->texture.h - 1)) th = im->texture.edge_h; - else th = im->texture.max_size; - - if (x == 0) xx = 0; - else xx = x * (im->texture.max_size - 2) - 1; - if (x == (im->texture.w - 1)) ww = im->w - (x * (im->texture.max_size- 2)); - else ww = im->texture.max_size - 2; - ww += 2; - if (x == 0) ww--; - if (x == (im->texture.w - 1)) ww--; - - if (y == 0) yy = 0; - else yy = y * (im->texture.max_size - 2) - 1; - if (y == (im->texture.h - 1)) hh = im->h - (y * (im->texture.max_size- 2)); - else hh = im->texture.max_size - 2; - hh += 2; - if (y == 0) hh--; - if (y == (im->texture.h - 1)) hh--; - - __evas_gl_image_copy_image_rect_to_texture(im, xx, yy, ww, hh, tw, th, - im->texture.textures[i]); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - } - /* done - set the actual image state to textured */ - im->state = EVAS_STATE_TEXTURE; - if (image_data) - { - imlib_context_set_image(image); - imlib_image_put_back_data(im->data); - im->data = NULL; - imlib_free_image(); - } -} - -static void -__evas_gl_image_calc_tex_and_poly(Evas_GL_Image *im, int x, double *x1, double *x2, - int *tx, int *txx, double *dtx, double *dtxx, int tw, int w, int edge) -{ - if ((x == 0) && (tw > 1)) - { - *tx = 0; - *txx = im->texture.max_size - 2; - *dtx = (double)*tx / (im->texture.max_size); - *dtxx = (double)*txx / (im->texture.max_size); - } - else if (x < (tw - 1)) - { - *tx = 1; - *txx = im->texture.max_size - 1; - *dtx = (double)*tx / (im->texture.max_size); - *dtxx = (double)*txx / (im->texture.max_size); - } - else if ((x == 0) && (tw == 1)) - { - *tx = 0; - *txx = w - (x * (im->texture.max_size - 2)); - *dtx = (double)*tx / (double)edge; - *dtxx = (double)*txx / (double)edge; - } - else - { - *tx = 1; - *txx = w - (x * (im->texture.max_size - 2)); - *dtx = (double)*tx / (double)edge; - *dtxx = (double)*txx / (double)edge; - } - - if (x == 0) - *x1 = 0.0; - else - *x1 = (double)(x * (im->texture.max_size - 2)); - - if (x < (tw - 1)) - *x2 = (double)((x + 1) * (im->texture.max_size - 2)); - else - *x2 = (double)w; -} - -static Evas_GL_Image * -__evas_gl_create_image(void) -{ - Evas_GL_Image *im; - - im = malloc(sizeof(Evas_GL_Image)); - memset(im, 0, sizeof(Evas_GL_Image)); - return im; -} - -static Evas_GL_Image * -__evas_gl_image_create_from_file(Display *disp, char *file) -{ - Evas_GL_Image *im; - Imlib_Image i; - - if (!file) return NULL; - im = __evas_gl_create_image(); - im->file = strdup(file); - i = imlib_load_image(file); - if (i) - { - imlib_context_set_image(i); - im->w = imlib_image_get_width(); - im->h = imlib_image_get_height(); - im->alpha = imlib_image_has_alpha(); - imlib_free_image(); - } - else - { - im->w = 0; - im->h = 0; - } - im->data = NULL; - im->texture.max_size = 256; - im->texture.w = 0; - im->texture.h = 0; - im->texture.edge_w = 0; - im->texture.edge_h = 0; - im->texture.textures = NULL; - - im->context = __evas_gl_cx; - im->buffer.display = disp; - im->buffer.colormap = __evas_gl_get_colormap(disp, 0); - im->buffer.visual_info = __evas_vi; - im->buffer.window = 0; - im->buffer.dest = 0; - im->buffer.dest_w = 0; - im->buffer.dest_h = 0; - - im->references = 1; - - return im; -} - -static void -__evas_gl_image_free_textures(Evas_GL_Image *im) -{ - if ((__evas_current_win != im->buffer.dest) || - (__evas_current_disp != im->buffer.display)) - { - glXMakeCurrent(im->buffer.display, im->buffer.dest, im->context); - __evas_current_disp = im->buffer.display; - __evas_current_win = im->buffer.dest; - } - if (im->texture.textures) - { - __evas_image_cache_used -= - ((((im->texture.w - 1) * im->texture.max_size) * - ((im->texture.h - 1) * im->texture.max_size)) + - ((im->texture.w - 1) * im->texture.edge_h) + - ((im->texture.h - 1) * im->texture.edge_w) + - (im->texture.edge_w * im->texture.edge_h)) * 4; - glDeleteTextures(im->texture.w * im->texture.h, im->texture.textures); - free(im->texture.textures); - im->texture.textures = NULL; - } - im->state = EVAS_STATE_DATA; -} - -static void -__evas_gl_image_destroy(Evas_GL_Image *im) -{ - if (im->file) free(im->file); - if (im->data) free(im->data); - __evas_gl_image_free_textures(im); - free(im); -} - -static void -__evas_gl_image_cache_flush(Display *disp) -{ - while (__evas_image_cache_used > __evas_image_cache_max) - { - Evas_GL_Image *im = NULL, *im_last; - Evas_List l; - - im_last = NULL; - for (l = __evas_images; l; l = l->next) - { - im = l->data; - - if (im->references <= 0) - im_last = im; - } - if (im_last) + else glDisable(GL_BLEND); + if (glw->context->texture) glEnable(GL_TEXTURE_2D); + else glDisable(GL_TEXTURE_2D); + glColor4d((double)((glw->context->color >> 24) & 0xff) / 255.0, + (double)((glw->context->color >> 16) & 0xff) / 255.0, + (double)((glw->context->color >> 8) & 0xff) / 255.0, + (double)((glw->context->color ) & 0xff) / 255.0); + if (glw->context->clip.active) { - __evas_images = evas_list_remove(__evas_images, im_last); - __evas_gl_image_destroy(im_last); + glEnable(GL_SCISSOR_TEST); + glScissor(glw->context->clip.x, + glw->h - glw->context->clip.y - glw->context->clip.h, + glw->context->clip.w, + glw->context->clip.h); } + else + glDisable(GL_SCISSOR_TEST); + if (glw->context->bound_texture) + glBindTexture(GL_TEXTURE_2D, glw->context->bound_texture->texture); } - disp = NULL; + return glw; } -/*****************************************************************************/ -/* image externals ***********************************************************/ -/*****************************************************************************/ - -void -__evas_gl_image_draw(Evas_GL_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) +static void +__evas_gl_window_dither(Evas_GL_Window *w, int onoff) { - int x, y, i; - double dx, dy, dw, dh; + if (!w) return; + if (w->context->dither == onoff) return; - if (ca == 0) return; - if ((src_w <= 0) || (src_h <= 0) || (dst_w <= 0) || (dst_h <= 0)) return; - if (im->state != EVAS_STATE_TEXTURE) - __evas_gl_image_move_state_data_to_texture(im); - if ((__evas_current_win != w) || (__evas_current_disp != disp)) - { - glXMakeCurrent(disp, w, im->context); - __evas_current_disp = disp; - __evas_current_win = w; - im->buffer.dest = w; - } - if (im->alpha) + w->context->dither = onoff; + if (w->context->dither) glEnable(GL_DITHER); + else glDisable(GL_DITHER); +} + +static void +__evas_gl_window_blend(Evas_GL_Window *w, int onoff) +{ + if (!w) return; + if (w->context->blend == onoff) return; + + w->context->blend = onoff; + if (w->context->blend) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - else - { - glDisable(GL_BLEND); - } - - src_y = im->h - src_h - src_y; - - dw = (((double)dst_w * (double)im->w)/ (double)src_w); - dx = (double)dst_x - (((double)dst_w * (double)src_x)/ (double)src_w); - dh = (((double)dst_h * (double)im->h)/ (double)src_h); - dy = (double)dst_y - (((double)dst_h * (double)src_y)/ (double)src_h); - - glEnable(GL_DITHER); - glEnable(GL_TEXTURE_2D); - glShadeModel(GL_FLAT); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - - glViewport(dst_x, win_h - dst_y - dst_h, dst_w, dst_h); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, dst_w, 0, dst_h, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glScalef(1, -1, 1); - glTranslatef((double)(-dst_x), (dst_y - dy) -dy - dh - , 0); - im->buffer.dest_w = win_w; - im->buffer.dest_h = win_h; + else glDisable(GL_BLEND); +} - glColor4d(((double)cr) / 255.0, - ((double)cg) / 255.0, - ((double)cb) / 255.0, - ((double)ca) / 255.0); - /* project src and dst rects to overall dest rect */ - if ((im->direct) || - ((im->bl == 0) && (im->br == 0) && (im->bt == 0) && (im->bb == 0))) +static void +__evas_gl_window_texture(Evas_GL_Window *w, int onoff) +{ + if (!w) return; + if (w->context->texture == onoff) return; + + w->context->texture = onoff; + if (w->context->texture) glEnable(GL_TEXTURE_2D); + else glDisable(GL_TEXTURE_2D); +} + +static void +__evas_gl_window_color(Evas_GL_Window *w, int r, int g, int b, int a) +{ + DATA32 col; + + if (!w) return; + col = (r << 24) | (g << 16) | (b << 8) | (a); + if (w->context->color == col) return; + + w->context->color = col; + glColor4d((double)r / 255.0, + (double)g / 255.0, + (double)b / 255.0, + (double)a / 255.0); +} + +static void +__evas_gl_window_clip(Evas_GL_Window *w, int c, int cx, int cy, int cw, int ch) +{ + if (!w) return; + if (w->context->clip.active == c) + { + if ((c) && + (w->context->clip.x == cx) && (w->context->clip.y == cy) && + (w->context->clip.w == cw) && (w->context->clip.h == ch)) + return; + } + w->context->clip.active = c; + w->context->clip.x = cx; + w->context->clip.y = cy; + w->context->clip.w = cw; + w->context->clip.h = ch; + if (w->context->clip.active) + { + glEnable(GL_SCISSOR_TEST); + glScissor(w->context->clip.x, + w->h - w->context->clip.y - w->context->clip.h, + w->context->clip.w, + w->context->clip.h); + } + else + glDisable(GL_SCISSOR_TEST); +} + +static void +__evas_gl_window_write_buf(Evas_GL_Window *w, GLenum buf) +{ + if (!w) return; + if (w->context->write_buf != buf) + { + w->context->write_buf = buf; + glDrawBuffer(buf); + } +} + +static void +__evas_gl_window_read_buf(Evas_GL_Window *w, GLenum buf) +{ + if (!w) return; + if (w->context->read_buf != buf) + { + w->context->read_buf = buf; + glReadBuffer(buf); + } +} + +static void +__evas_gl_window_swap_rect(Evas_GL_Window *w, int rx, int ry, int rw, int rh) +{ + if (!w) return; + + __evas_gl_window_read_buf(w, GL_BACK); + __evas_gl_window_write_buf(w, GL_FRONT); + __evas_gl_window_blend(w, 0); + __evas_gl_window_clip(w, 0, 0, 0, 0, 0); + __evas_gl_window_dither(w, 0); + glRasterPos2i(rx, w->h - ry); + glCopyPixels(rx, ry, rw, rh, GL_COLOR); +} + +static void +__evas_gl_window_use_texture(Evas_GL_Window *w, Evas_GL_Texture *tex, int smooth) +{ + if (!w) return; + if (w->context->bound_texture != tex) + { + glBindTexture(GL_TEXTURE_2D, tex->texture); + w->context->bound_texture = tex; + } + if (smooth != tex->smooth) { - if ((im->bl == 0) && (im->br == 0) && (im->bt == 0) && (im->bb == 0)) - { #ifdef HAVE_GLU - if (__evas_anti_alias) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - else -#else - if (__evas_anti_alias) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - else -#endif - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } + if (smooth) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else - { - if (__evas_anti_alias) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - } - for (y = 0, i = 0; y < im->texture.h; y++) - { - for (x = 0; x < im->texture.w; x++, i++) - { - int tx, ty, txx, tyy; - double x1, y1, x2, y2; - double dtx, dtxx, dty, dtyy; - - - __evas_gl_image_calc_tex_and_poly(im, x, &x1, &x2, - &tx, &txx, - &dtx, &dtxx, - im->texture.w, im->w, - im->texture.edge_w); - __evas_gl_image_calc_tex_and_poly(im, y, &y1, &y2, - &ty, &tyy, - &dty, &dtyy, - im->texture.h, im->h, - im->texture.edge_h); - x1 = dx + ((x1 * dw) / (double)im->w); - y1 = dy + ((y1 * dh) / (double)im->h); - x2 = dx + ((x2 * dw) / (double)im->w); - y2 = dy + ((y2 * dh) / (double)im->h); - glBindTexture(GL_TEXTURE_2D, im->texture.textures[i]); - if ((im->bl == 0) && (im->br == 0) && (im->bt == 0) && (im->bb == 0)) - { -#ifdef HAVE_GLU - if (__evas_anti_alias) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - else #else - if (__evas_anti_alias) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - else + if (smooth) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + else #endif - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - } - else - { - if (__evas_anti_alias) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - } - glBegin(GL_QUADS); - glTexCoord2d(dtx, dty); glVertex2d(x1, y1); - glTexCoord2d(dtxx, dty); glVertex2d(x2, y1); - glTexCoord2d(dtxx, dtyy); glVertex2d(x2, y2); - glTexCoord2d(dtx, dtyy); glVertex2d(x1, y2); - glEnd(); + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + tex->smooth = smooth; + } +} + +static Evas_GL_Texture * +__evas_gl_texture_new(Evas_GL_Window *w, Imlib_Image im, int ix, int iy, int iw, int ih) +{ + Evas_GL_Texture *tex; + int tx, ty, tw, th, im_w, im_h; + DATA32 *data, *p1, *p2, *im_data; + int shift; + Imlib_Image prev_im; + + if (!w) return NULL; + tex = malloc(sizeof(Evas_GL_Texture)); + shift = 1; while (iw > shift) shift = shift << 1; tw = shift; + shift = 1; while (ih > shift) shift = shift << 1; th = shift; + tex->w = tw; + tex->h = th; + glGenTextures(1, &(tex->texture)); + glBindTexture(GL_TEXTURE_2D, tex->texture); + w->context->bound_texture = tex; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + tex->smooth = 0; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + prev_im = imlib_context_get_image(); + imlib_context_set_image(im); + data = malloc(tw * th * 4); + im_data = imlib_image_get_data_for_reading_only(); + im_w = imlib_image_get_width(); + im_h = imlib_image_get_height(); + for (ty = 0; ty < ih; ty++) + { + p1 = im_data + ((iy + ty) * im_w) + ix; + p2 = data + (ty * tw); + for (tx = 0; tx < iw; tx++) + { +#ifndef WORDS_BIGENDIAN + *p2 = + ((*p1 & 0xff000000)) | + ((*p1 & 0x00ff0000) >> 16) | + ((*p1 & 0x0000ff00)) | + ((*p1 & 0x000000ff) << 16); +#else + *p2 = + ((*p1 & 0xff000000) >> 24) | + ((*p1 & 0x00ff0000) << 8) | + ((*p1 & 0x0000ff00) << 8) | + ((*p1 & 0x000000ff) << 8); +#endif + p2++; p1++; + } + if (tx < tw) + { + for (; tx < tw; tx++) *p2 = p2[-1]; + } + } + if (ty < th) + { + for (; ty < th; ty++) + { + p1 = data + ((ty - 1) * tw); + p2 = data + (ty * tw); + for (tx = 0; tx < tw; tx++) + { + *p2 = *p1; p2++; p1++; } } } +#ifdef HAVE_GLU + if (imlib_image_has_alpha()) + { + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, tw, th, GL_RGBA, + GL_UNSIGNED_BYTE, data); + } else { - int bl, br, bt, bb; - - im->direct = 1; - bl = im->bl; - br = im->br; - bt = im->bt; - bb = im->bb; - if ((bl + br) > (int)dw) - { - bl = (int)dw / 2; - br = (int)dw - bl; - } - if ((bt + bb) > (int)dh) - { - bt = (int)dh / 2; - bb = (int)dh - bt; - } - __evas_gl_image_draw(im, disp, dstim, w, win_w, win_h, - 0, 0, bl, bt, - dx, dy, bl, bt, cr, cg, cb, ca); - __evas_gl_image_draw(im, disp, dstim, w, win_w, win_h, - bl, 0, im->w - bl - br, bt, - dx + bl, dy, dw - bl - br, bt, cr, cg, cb, ca); - __evas_gl_image_draw(im, disp, dstim, w, win_w, win_h, - im->w - br, 0, br, bt, - dx + dw - br, dy, br, bt, cr, cg, cb, ca); - - __evas_gl_image_draw(im, disp, dstim, w, win_w, win_h, - 0, bt, bl, im->h - bt - bb, - dx, dy + bt, bl, dh - bt - bb, cr, cg, cb, ca); - __evas_gl_image_draw(im, disp, dstim, w, win_w, win_h, - bl, bt, im->w - bl - br, im->h - bt - bb, - dx + bl, dy + bt, dw - bl - br, dh - bt - bb, cr, cg, cb, ca); - __evas_gl_image_draw(im, disp, dstim, w, win_w, win_h, - im->w - br, bt, br, im->h - bt - bb, - dx + dw - br, dy + bt, br, dh - bt - bb, cr, cg, cb, ca); - - __evas_gl_image_draw(im, disp, dstim, w, win_w, win_h, - 0, im->h - bb, bl, bb, - dx, dy + dh - bb, bl, bb, cr, cg, cb, ca); - __evas_gl_image_draw(im, disp, dstim, w, win_w, win_h, - bl, im->h - bb, im->w - bl - br, bb, - dx + bl, dy + dh - bb, dw - bl - br, bb, cr, cg, cb, ca); - __evas_gl_image_draw(im, disp, dstim, w, win_w, win_h, - im->w - br, im->h - bb, br, bb, - dx + dw - br, dy + dh - bb, br, bb, cr, cg, cb, ca); - im->direct = 0; + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, tw, th, GL_RGBA, + GL_UNSIGNED_BYTE, data); } +#else + if (imlib_image_has_alpha()) + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tw, th, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); + } + else + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, tw, th, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); + } +#endif + free(data); + imlib_image_put_back_data(im_data); + imlib_context_set_image(prev_im); + return tex; } -Evas_GL_Image * -__evas_gl_image_new_from_file(Display *disp, char *file) -{ - Evas_GL_Image *im; +static void +__evas_gl_texture_free(Evas_GL_Window *w, Evas_GL_Texture *tex) +{ + if (!w) return; + glDeleteTextures(1, &tex->texture); + if (w->context->bound_texture == tex) w->context->bound_texture = NULL; + free(tex); +} + +static Evas_GL_Texmesh * +__evas_gl_make_image_textures(Evas_GL_Window *w, Evas_GL_Image *image) +{ Evas_List l; + Evas_GL_Texmesh *tm; + int tx, ty, ex, ey, tw, th, ix, iy, iw, ih; + int i, shift; + Imlib_Image prev_im; - for (l = __evas_images; l; l = l->next) + for (l = image->textures; l; l = l->next) { - im = l->data; - - if (((im->file) && (im->buffer.display == disp)) && - (!strcmp(im->file, file))) + tm = l->data; + if (tm->context == w->context) return tm; + } + tm = malloc(sizeof(Evas_GL_Texmesh)); + tm->window = w; + tm->context = w->context; + + image->textures = evas_list_prepend(image->textures, tm); + + if ((!image->im) && (image->file)) + image->im = imlib_load_image(image->file); + + tx = (image->w - 2) / (w->context->max_texture_size - 2); + ex = (image->w - 1) - (tx * (w->context->max_texture_size - 2)); + if (tx == 0) ex = image->w; + tm->tiles.x_left = ex; + shift = 1; while (ex > shift) shift = shift << 1; ex = shift; + + ty = (image->h - 2) / (w->context->max_texture_size - 2); + ey = (image->h - 1) - (ty * (w->context->max_texture_size - 2)); + if (ty == 0) ey = image->h; + tm->tiles.y_left = ey; + shift = 1; while (ey > shift) shift = shift << 1; ey = shift; + + tm->tiles.x = tx; + tm->tiles.y = ty; + tm->tiles.x_edge = ex; + tm->tiles.y_edge = ey; + tm->textures = malloc(sizeof(Evas_GL_Texmesh *) * (tm->tiles.x + 1) * (tm->tiles.y + 1)); + i = 0; + for (ty = 0; ty <= tm->tiles.y; ty++) + { + /* figure out image y,h */ + /* texture is only an edge size */ + if ((ty == 0) && (tm->tiles.y == 0)) { - if (l != __evas_images) + iy = 0; + ih = image->h; + } + /* start edge */ + else if (ty == 0) + { + iy = 0; + ih = w->context->max_texture_size; + } + /* end edge */ + else if (ty == tm->tiles.y) + { + iy = ty * (w->context->max_texture_size - 2) + 1; + ih = image->h - iy; + } + /* middle tex */ + else + { + iy = ty * (w->context->max_texture_size - 2) + 1; + ih = w->context->max_texture_size; + } + for (tx = 0; tx <= tm->tiles.x; tx++) + { + /* figure out image x,w */ + /* texture is only an edge size */ + if ((tx == 0) && (tm->tiles.x == 0)) { - __evas_images = evas_list_remove(__evas_images, im); - __evas_images = evas_list_prepend(__evas_images, im); + ix = 0; + iw = image->w; } - if (im->references == 0) - __evas_image_cache_used -= - ((((im->texture.w - 1) * im->texture.max_size) * - ((im->texture.h - 1) * im->texture.max_size)) + - ((im->texture.w - 1) * im->texture.edge_h) + - ((im->texture.h - 1) * im->texture.edge_w) + - (im->texture.edge_w * im->texture.edge_h)) * 4; - im->references++; - return im; + /* start edge */ + else if (tx == 0) + { + ix = 0; + iw = w->context->max_texture_size; + } + /* end edge */ + else if (tx == tm->tiles.x) + { + ix = tx * (w->context->max_texture_size - 2) + 1; + iw = image->w - ix; + } + /* middle tex */ + else + { + ix = tx * (w->context->max_texture_size - 2) + 1; + iw = w->context->max_texture_size; + } + if (image->im) + tm->textures[i] = __evas_gl_texture_new(w, image->im, + ix, iy, iw, ih); + i++; } } - - im = __evas_gl_image_create_from_file(disp, file); - if (im) - __evas_images = evas_list_prepend(__evas_images, im); - - return im; -} - -void -__evas_gl_image_free(Evas_GL_Image *im) -{ - im->references--; - if (im->references == 0) + if ((image->file) && (image->im)) { - __evas_image_cache_used += - ((((im->texture.w - 1) * im->texture.max_size) * - ((im->texture.h - 1) * im->texture.max_size)) + - ((im->texture.w - 1) * im->texture.edge_h) + - ((im->texture.h - 1) * im->texture.edge_w) + - (im->texture.edge_w * im->texture.edge_h)) * 4; + prev_im = imlib_context_get_image(); + imlib_context_set_image(image->im); + imlib_free_image_and_decache(); + image->im = NULL; + imlib_context_set_image(prev_im); } - if (im->references <= 0) - __evas_gl_image_cache_flush(im->buffer.display); + return tm; } -void -__evas_gl_image_cache_empty(Display *disp) +static void +__evas_gl_free_image_textures(Evas_GL_Image *image) { - Evas_GL_Image *im = NULL, *im_last; Evas_List l; - int size; - - im_last = (Evas_GL_Image *)1; - while (im_last) + + if (image->textures) { + for (l = image->textures; l; l = l->next) + { + Evas_GL_Texmesh *tm; + Evas_GL_Window *w; + int i; + + tm = l->data; + w = __evas_gl_window_current(tm->window->disp, tm->window->win, + tm->window->w, tm->window->h); + for (i = 0; i < (tm->tiles.x + 1) * (tm->tiles.y + 1); i++) + __evas_gl_texture_free(w, tm->textures[i]); + free(tm->textures); + tm->tiles.x = 0; + tm->tiles.y = 0; + tm->tiles.x_edge = 0; + tm->tiles.y_edge = 0; + free(tm); + } + evas_list_free(image->textures); + } + image->textures = NULL; +} + +static Evas_GL_Image * +__evas_gl_image_alloc(char *file) +{ + Evas_GL_Image *image; + Imlib_Image im, prev_im; + + im = imlib_load_image(file); + if (!im) return NULL; + image = malloc(sizeof(Evas_GL_Image)); + image->file = strdup(file); + image->im = im; + prev_im = imlib_context_get_image(); + imlib_context_set_image(im); + image->w = imlib_image_get_width(); + image->h = imlib_image_get_height(); + image->has_alpha = imlib_image_has_alpha(); + image->border.l = 0; + image->border.r = 0; + image->border.t = 0; + image->border.b = 0; + image->references = 1; + image->textures = NULL; + imlib_context_set_image(prev_im); + return image; +} + +static void +__evas_gl_image_dealloc(Evas_GL_Image *image) +{ + Imlib_Image prev_im; + + if (image->file) free(image->file); + if (image->im) + { + prev_im = imlib_context_get_image(); + imlib_context_set_image(image->im); + imlib_free_image(); + imlib_context_set_image(prev_im); + } + if (image->textures) + __evas_gl_free_image_textures(image); + free(image); +} + +static void +__evas_gl_image_cache_flush(void) +{ + while (__evas_image_cache > __evas_image_cache_max) + { + Evas_GL_Image *im, *im_last; + Evas_List l; + im_last = NULL; for (l = __evas_images; l; l = l->next) { im = l->data; - - __evas_gl_image_free_textures(im); - if (im->references <= 0) - im_last = im; + if (im->references == 0) im_last = im; } if (im_last) { + __evas_image_cache -= im_last->w * im_last->h * 4; __evas_images = evas_list_remove(__evas_images, im_last); - __evas_gl_image_destroy(im_last); + __evas_gl_image_dealloc(im_last); } } - size = imlib_get_cache_size(); - imlib_set_cache_size(0); - imlib_set_cache_size(size); - disp = NULL; } -void -__evas_gl_image_cache_set_size(Display *disp, int size) +static Evas_GL_Graident_Texture * +__evas_gl_gradient_texture_new(Evas_GL_Window *w, Evas_GL_Graident *gr) { - __evas_image_cache_max = size; - __evas_gl_image_cache_flush(disp); -} - -int -__evas_gl_image_cache_get_size(Display *disp) -{ - return __evas_image_cache_max; - disp = NULL; -} - -int -__evas_gl_image_get_width(Evas_GL_Image *im) -{ - return im->w; -} - -int -__evas_gl_image_get_height(Evas_GL_Image *im) -{ - return im->h; -} - -void -__evas_gl_image_set_borders(Evas_GL_Image *im, int left, int right, - int top, int bottom) -{ - im->bl = left; - im->br = right; - im->bt = top; - im->bb = bottom; - if ((im->bl + im->br) > im->w) + Evas_List l; + Evas_GL_Graident_Texture *tg; + + for (l = gr->textures; l; l = l->next) { - im->bl = im->w / 2; - im->br = im->w - im->bl; - } - if ((im->bt + im->bb) > im->h) - { - im->bt = im->h / 2; - im->bb = im->h - im->bt; + tg = l->data; + if (tg->context == w->context) return tg; } + tg = malloc(sizeof(Evas_GL_Graident_Texture)); + tg->window = w; + tg->context = w->context; + tg->texture = NULL; + gr->textures = evas_list_prepend(gr->textures, tg); + return tg; } -void -__evas_gl_image_set_smooth_scaling(int on) -{ - if (on != __evas_anti_alias) - __evas_gl_image_cache_empty(__evas_current_disp); - __evas_anti_alias = on; -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/*****************************************************************************/ -/* font internals ************************************************************/ -/*****************************************************************************/ - - - static void -__evas_gl_text_paste(Evas_GL_Font *f, char *text, - Display *disp, Window win, int win_w, int win_h, - int x, int y, int r, int g, int b, int a) +__evas_gl_gradient_texture_free(Evas_GL_Graident_Texture *tg) { - int i, j, off, rows, adj, w, h; - int x_offset, y_offset; - TT_F26Dot6 xx, yy, xmin, ymin, xmax, ymax; - TT_Glyph_Metrics metrics; - float rr, gg, bb, aa; - GLuint last_tex; - - j = text[0]; - TT_Get_Glyph_Metrics(f->glyphs[j], &metrics); - x_offset = (-metrics.bearingX) / 64; - y_offset = -(f->max_descent / 64); - - if ((__evas_current_win != win) || (__evas_current_disp != disp)) - { - glXMakeCurrent(disp, win, f->context); - __evas_current_disp = disp; - __evas_current_win = win; - f->buffer.dest = win; - } - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_DITHER); - glShadeModel(GL_FLAT); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - rr = (float)r / 255; - gg = (float)g / 255; - bb = (float)b / 255; - aa = (float)a / 255; - glColor4f(rr, gg, bb, aa); - glViewport(0, 0, win_w, win_h); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, win_w, 0, win_h, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glScalef(1, -1, 1); - glTranslatef(0, -win_h, 0); - f->buffer.dest_w = win_w; - f->buffer.dest_h = win_h; - - __evas_gl_text_calc_size(f, &w, &h, text); - rows = h; - glBindTexture(GL_TEXTURE_2D, f->glyphinfo[j].texture); - last_tex = f->glyphinfo[j].texture; + if (tg->texture) + __evas_gl_texture_free(tg->window, tg->texture); + free(tg); +} +static Evas_GL_Texture * +__evas_gl_texture_alpha_new(Evas_GL_Window *w) +{ + Evas_GL_Texture *tex; + DATA8 *data; + + if (!w) return NULL; + tex = malloc(sizeof(Evas_GL_Texture)); + tex->w = w->context->max_texture_size; + tex->h = w->context->max_texture_size; + glGenTextures(1, &(tex->texture)); + glBindTexture(GL_TEXTURE_2D, tex->texture); + w->context->bound_texture = tex; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + tex->smooth = 0; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - for (i = 0; text[i]; i++) - { - j = text[i]; - if (!TT_VALID(f->glyphs[j])) - continue; - - TT_Get_Glyph_Metrics(f->glyphs[j], &metrics); - - xmin = metrics.bbox.xMin & -64; - ymin = metrics.bbox.yMin & -64; - xmax = (metrics.bbox.xMax + 63) & -64; - ymax = (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 (last_tex != f->glyphinfo[j].texture) - { - glBindTexture(GL_TEXTURE_2D, f->glyphinfo[j].texture); -/* if i don't have these 2 lines.. it screwes up*/ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - last_tex = f->glyphinfo[j].texture; - } - if (ymin < 0) off = 0; - else off = rows - ymin - 1; - adj = (rows - ymax) - ((f->max_ascent - f->max_descent) >> 6); - - glBegin(GL_QUADS); - glTexCoord2d(f->glyphinfo[j].x1, f->glyphinfo[j].y1); - glVertex2i(x + xmin, y + ymin + off + adj); - glTexCoord2d(f->glyphinfo[j].x2, f->glyphinfo[j].y1); - glVertex2i(x + xmax + 1, y + ymin + off + adj); - glTexCoord2d(f->glyphinfo[j].x2, f->glyphinfo[j].y2); - glVertex2i(x + xmax + 1, y + ymax + off + adj + 1); - glTexCoord2d(f->glyphinfo[j].x1, f->glyphinfo[j].y2); - glVertex2i(x + xmin, y + ymax + off + adj + 1); - glEnd(); - - x_offset += metrics.advance / 64; - } + data = malloc(w->context->max_texture_size * w->context->max_texture_size); + memset(data, 0, w->context->max_texture_size * w->context->max_texture_size); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA4, + w->context->max_texture_size, w->context->max_texture_size, 0, + GL_ALPHA, GL_UNSIGNED_BYTE, data); + free(data); + return tex; } static void -__evas_gl_text_font_render_textures(Evas_GL_Font *f) +__evas_gl_texture_paste_data(Evas_GL_Window *w, Evas_GL_Texture *tex, int x, int y, DATA8 *data, int iw, int ih) { - int i, maxw, maxh, cols, rows, pop, j, k, c, r, x, y; - int didlast = 0; - unsigned char *data = NULL; + __evas_gl_window_use_texture(w, tex, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, iw, ih, + GL_ALPHA, GL_UNSIGNED_BYTE, data); +} + +static Evas_GL_Glyph * +__evas_gl_text_font_get_glyph(Evas_GL_Font *fn, int glyph) +{ + Evas_GL_Glyph *g; + Evas_List l; + int hash; + int code; - maxw = 0; - maxh = 0; - for (i = 0; i < f->num_glyph; i++) + hash = glyph & 0xff; + for (l = fn->glyphs[hash]; l; l = l->next) { - int w, h; - char text[2]; - - text[0] = (char)i; - text[1] = 0; - __evas_gl_text_calc_size(f, &w, &h, text); - if (w > maxw) maxw = w; - if (h > maxh) maxh = h; - } - if ((maxw == 0) || (maxh == 0)) return; - maxw++; - maxh++; - cols = f->max_texture_size / maxw; - rows = f->max_texture_size / maxh; - if ((cols < 1) || (rows < 1)) return; - i = f->num_glyph; - pop = 0; - while (i > 0) - { - pop++; - i -= cols * rows; - } - f->num_textures = pop; - f->textures = malloc(f->num_textures * sizeof(GLuint)); - glGenTextures(f->num_textures, f->textures); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glEnable(GL_TEXTURE_2D); - j = 0; - c = 0; - r = 0; - - data = malloc(256 * 256); - for (j = 0, k = 0, i = 0; i < f->num_glyph; i++) - { - TT_F26Dot6 xmin, ymin, xmax, ymax; - int w, h; - TT_Raster_Map *rtmp; - - if (TT_VALID(f->glyphs[i])) + g = l->data; + if (g->glyph_id == glyph) { - TT_Glyph_Metrics metrics; - - TT_Get_Glyph_Metrics(f->glyphs[i], &metrics); - xmin = metrics.bbox.xMin & -64; - ymin = metrics.bbox.yMin & -64; - xmax = (metrics.bbox.xMax + 63) & -64; - ymax = (metrics.bbox.yMax + 63) & -64; - w = ((xmax - xmin) / 64) + 1; - h = ((ymax - ymin) / 64) + 1; - rtmp = __evas_gl_text_font_raster_new(((xmax - xmin) / 64) + 1, - ((ymax - ymin) / 64) + 1); - if (rtmp) + if (l != fn->glyphs[hash]) { - TT_Get_Glyph_Pixmap(f->glyphs[i], rtmp, -xmin, -ymin); - f->glyphinfo[i].texture = f->textures[j]; - f->glyphinfo[i].px = c * maxw; - f->glyphinfo[i].py = r * maxh; - f->glyphinfo[i].pw = w; - f->glyphinfo[i].ph = h; - f->glyphinfo[i].x1 = ((double)f->glyphinfo[i].px / - (double)f->max_texture_size); - f->glyphinfo[i].y1 = ((double)f->glyphinfo[i].py / - (double)f->max_texture_size); - f->glyphinfo[i].x2 = ((double)(f->glyphinfo[i].px + w) / - (double)f->max_texture_size); - f->glyphinfo[i].y2 = ((double)(f->glyphinfo[i].py + h) / - (double)f->max_texture_size); - - for (y = 0; y < h; y++) - { - for (x = 0; x < w; x++) - { - int val, rval; - - rval = (int)(((unsigned char *)(rtmp->bitmap))[((rtmp->rows - y -1) * rtmp->cols) + x]); - val = __evas_rend_lut[rval]; - data[(((f->glyphinfo[i].py + y) << 8) + f->glyphinfo[i].px + x)] = val; - } - } - __evas_gl_text_font_raster_free(rtmp); - } - } - - k++; - /* last char done */ - if (k == (cols * rows)) - { - glBindTexture(GL_TEXTURE_2D, f->textures[j]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA4, f->max_texture_size, f->max_texture_size, 0, - GL_ALPHA, GL_UNSIGNED_BYTE, data); - j++; - if (j >= f->num_textures) didlast = 1; - k = 0; - r = 0; - c = 0; - } - else - { - c++; - if (c == cols) - { - c = 0; - r++; + fn->glyphs[hash] = evas_list_remove(fn->glyphs[hash], g); + fn->glyphs[hash] = evas_list_prepend(fn->glyphs[hash], g); } + return g; } } - if (!didlast) - { - glBindTexture(GL_TEXTURE_2D, f->textures[j]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA4, f->max_texture_size, f->max_texture_size, 0, - GL_ALPHA, GL_UNSIGNED_BYTE, data); - j++; - } - if (data) - { - free(data); - data = NULL; - } + g = malloc(sizeof(Evas_GL_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->texture = NULL; + g->textures = NULL; + g->tex.x1 = 0.0; + g->tex.x2 = 0.0; + g->tex.y1 = 0.0; + g->tex.y2 = 0.0; + fn->glyphs[hash] = evas_list_prepend(fn->glyphs[hash], g); + return g; } static TT_Raster_Map * @@ -1127,25 +888,767 @@ __evas_gl_text_font_raster_new(int width, int height) memset(rmap->bitmap, 0, rmap->size); return rmap; } - + static void __evas_gl_text_font_raster_free(TT_Raster_Map * rmap) -{ +{ if (rmap->bitmap) free(rmap->bitmap); free(rmap); } static void -__evas_gl_text_font_path_add(const char *path) +__evas_gl_text_font_render_glyph(Evas_GL_Window *glw, Evas_GL_Font *fn, Evas_GL_Glyph *g) { - __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] = strdup(path); + Evas_List l; + Evas_GL_Font_Texture *ft; + Evas_GL_Glyph_Texture *gt; + Evas_GL_Texture *tex; + int tx, ty, tw, th, xmin, ymin, xmax, ymax; + TT_Raster_Map *rmap; + + if ((g->texture) && (g->texture->context == glw->context)) return; + for (l = g->textures; l; l = l->next) + { + gt = l->data; + if (gt->context == glw->context) + { + g->texture = gt; + g->tex.x1 = gt->tex.x1; + g->tex.x2 = gt->tex.x2; + g->tex.y1 = gt->tex.y1; + g->tex.y2 = gt->tex.y2; + 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; + /* could never fit glyph into max texture size tile */ + if ((tw > glw->context->max_texture_size) || + (th > glw->context->max_texture_size)) + { + g->texture = NULL; + return; + } + + /* find a new texture with space */ + ft = NULL; + tex = NULL; + tx = 0; + ty = 0; + for (l = fn->textures; l; l = l->next) + { + ft = l->data; + if (ft->context == glw->context) + { + tex = ft->texture; + + if ((tex->h - ft->cursor.y) >= th) + { + if ((tex->w - ft->cursor.x) >= tw) + { + if (ft->cursor.row_h < th) ft->cursor.row_h = th; + tx = ft->cursor.x; + ty = ft->cursor.y; + ft->cursor.x += tw; + goto done; + } + else + { + ty = ft->cursor.y + ft->cursor.row_h; + if ((tex->h - ty) >= th) + { + ft->cursor.y += ft->cursor.row_h; + ft->cursor.row_h = th; + ft->cursor.x = tw; + tx = 0; + ty = ft->cursor.y; + goto done; + } + } + } + } + ft = NULL; + } + done: + if (!ft) + { + /* make a new texture with space */ + tex = __evas_gl_texture_alpha_new(glw); + ft = malloc(sizeof(Evas_GL_Font_Texture)); + ft->cursor.x = tw; + ft->cursor.y = 0; + ft->cursor.row_h = th; + ft->window = glw; + ft->context = glw->context; + ft->texture = tex; + + fn->textures = evas_list_prepend(fn->textures, ft); + tx = 0; + ty = 0; + } + /* paste glyph in free spot in texture */ + gt = malloc(sizeof(Evas_GL_Glyph_Texture)); + + rmap = __evas_gl_text_font_raster_new(tw, th); + if (rmap) + { + int x, y; + DATA8 *data; + + TT_Get_Glyph_Pixmap(g->glyph, rmap, -xmin, -ymin); + data = malloc(tw * th * sizeof(DATA8)); + for (y = 0; y < th; y++) + { + for (x = 0; x < tw; x++) + { + int rval; + + rval = (int)(((unsigned char *)(rmap->bitmap))[((rmap->rows - y - 1) * rmap->cols) + x]); + data[(y * tw) + x] = __evas_rend_lut[rval]; + } + } + __evas_gl_texture_paste_data(glw, tex, tx, ty, data, tw, th); + free(data); + __evas_gl_text_font_raster_free(rmap); + } + gt->texture = tex; + gt->window = glw; + gt->context = glw->context; + gt->tex.x1 = (double)tx / (double)glw->context->max_texture_size; + gt->tex.x2 = (double)(tx + tw) / (double)glw->context->max_texture_size; + gt->tex.y1 = (double)ty / (double)glw->context->max_texture_size; + gt->tex.y2 = (double)(ty + th) / (double)glw->context->max_texture_size; + g->textures = evas_list_prepend(g->textures, gt); + + g->texture = gt; + g->tex.x1 = gt->tex.x1; + g->tex.x2 = gt->tex.x2; + g->tex.y1 = gt->tex.y1; + g->tex.y2 = gt->tex.y2; +} + +static int +__evas_gl_is_file(char *file) +{ + struct stat st; + + if (stat(file, &st) < 0) + return 0; + return 1; +} + +static char * +__evas_gl_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_gl_is_file(buf)) return strdup(buf); + } + 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_gl_is_file(buf)) return strdup(buf); + } + } + return NULL; +} + +static Evas_GL_Font * +__evas_gl_font_load(char *font, int size) +{ + Evas_GL_Font *fn; + char *file; + TT_Error error; + int i, num_cmap, upm; + const int dpi = 96; + + file = __evas_gl_font_find(font); + if (!file) return; + 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_GL_Font)); + fn->font = strdup(font); + fn->size = size; + fn->engine = __evas_tt_engine; + 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->textures = NULL; + fn->references = 1; + + /* go thru the first 256 glyps to calculate max ascent/descent */ + { + Evas_GL_Glyph *g; + + for (i = 0; i < 256; i++) + { + g = __evas_gl_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_gl_text_font_path_del(const char *path) +__evas_gl_text_font_cache_flush(void) +{ + Evas_List l; + Evas_GL_Font *fn_last; + Evas_GL_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; + + for (l = fn_last->textures; l; l = l->next) + { + Evas_GL_Font_Texture *ft; + + ft = l->data; + __evas_font_cache -= ft->texture->w * ft->texture->h; + } + 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_GL_Glyph *g; + Evas_List ll; + + g = l->data; + if (g->textures) + { + for (ll = g->textures; ll; ll = ll->next) + { + Evas_GL_Glyph_Texture *gt; + + gt = ll->data; + free(gt); + } + evas_list_free(g->textures); + } + free(g); + } + evas_list_free(fn_last->glyphs[i]); + } + } + if (fn_last->textures) + { + for (l = fn_last->textures; l; l = l->next) + { + Evas_GL_Font_Texture *ft; + + ft = l->data; + __evas_gl_texture_free(ft->window, ft->texture); + free(ft); + } + evas_list_free(fn_last->textures); + } + __evas_fonts = evas_list_remove(__evas_fonts, fn_last); + free(fn_last); + } + } +} + +/*****************************************************************************/ +/* image externals ***********************************************************/ +/*****************************************************************************/ + +void +__evas_gl_image_draw(Evas_GL_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_GL_Window *glw; + Evas_List l; + Evas_GL_Texmesh *tm; + + double scx, scy; + double x0, y0, w0, h0; + int go; + + 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 <= 0) return; + if (src_w < 1) src_w = 1; + if (src_h < 1) src_h = 1; + if (dst_w < 1) return; + if (dst_h < 1) return; + glw = __evas_gl_window_current(disp, w, win_w, win_h); + if (!glw) return; + __evas_gl_window_texture(glw, 1); + __evas_gl_window_blend(glw, im->has_alpha); + __evas_gl_window_write_buf(glw, GL_BACK); + __evas_gl_window_read_buf(glw, GL_BACK); + __evas_gl_window_color(glw, cr, cg, cb, ca); + __evas_gl_window_dither(glw, 1); + + tm = __evas_gl_make_image_textures(glw, im); + scx = (double)dst_w / (double)src_w; + scy = (double)dst_h / (double)src_h; + + x0 = (double)dst_x - ((double)src_x * scx); + y0 = (double)dst_y - ((double)src_y * scy); + w0 = (double)im->w * scx; + h0 = (double)im->h * scy; + +#ifndef GLNOCLIP + for (l = glw->updates; l; l = l->next) + { + Evas_GL_Rect *rect; + + go = 1; + rect = l->data; + { + int rx, ry, rw, rh; + + rx = dst_x; + ry = dst_y; + rw = dst_w; + rh = dst_h; + CLIP_TO(rx, ry, rw, rh, rect->x, rect->y, rect->w, rect->h); + if (__evas_clip) + { + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); + } + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; + } +#else + go = 1; + { + int rx, ry, rw, rh; + + rx = dst_x; + ry = dst_y; + rw = dst_w; + rh = dst_h; + if (__evas_clip) + { + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; + } + else + { + if (!((src_x != 0) || (src_w != im->w) || + (src_y != 0) || (src_h != im->h))) + __evas_gl_window_clip(glw, 0, 0, 0, 0, 0); + } + } +#endif + /* render image here */ + if (go) + { + int tx, ty, t; + double ty1, ty2, tx1, tx2; + double x1, x2, y1, y2; + int smooth = 0; + + if (__evas_smooth) + { + if ((dst_w == src_w) && (dst_h == src_h)) + smooth = 0; + else smooth = __evas_smooth; + } + else + smooth = 0; + t = 0; + for (ty = 0; ty <= tm->tiles.y; ty++) + { + if ((ty == 0) && (ty < tm->tiles.y)) + { + y1 = y0; + y2 = y1 + ((double)(glw->context->max_texture_size - 1) * scy); + ty1 = 0.0; + ty2 = (double)(glw->context->max_texture_size - 1) / (double)glw->context->max_texture_size; + } + else if (ty < tm->tiles.y) + { + y1 = y0 + (((double)(glw->context->max_texture_size - 1) + ((double)(ty - 1) * (double)(glw->context->max_texture_size - 2))) * scy); + y2 = y1 + ((double)(glw->context->max_texture_size - 2) * scy); + ty1 = 1.0 / (double)glw->context->max_texture_size; + ty2 = (double)(glw->context->max_texture_size - 1) / (double)glw->context->max_texture_size; + } + else + { + if (ty == 0) y1 = y0; + else + y1 = y0 + h0 - ((double)tm->tiles.y_left * scy); + y2 = y0 + h0; + if (ty == 0) ty1 = 0; + else ty1 = 1 / (double)tm->tiles.y_edge; + ty2 = (double)tm->tiles.y_left / (double)tm->tiles.y_edge; + } + for (tx = 0; tx <= tm->tiles.x; tx++) + { + if ((tx == 0) && (tx < tm->tiles.x)) + { + x1 = x0; + x2 = x1 + (255 * scx); + tx1 = 0.0; + tx2 = (double)(glw->context->max_texture_size - 1) / (double)glw->context->max_texture_size; + } + else if (tx < tm->tiles.x) + { + x1 = x0 + (((double)(glw->context->max_texture_size - 1) + ((double)(tx - 1) * (double)(glw->context->max_texture_size - 2))) * scx); + x2 = x1 + ((double)(glw->context->max_texture_size - 2) * scx); + tx1 = 1.0 / (double)glw->context->max_texture_size; + tx2 = (double)(glw->context->max_texture_size - 1) / (double)glw->context->max_texture_size; + } + else + { + if (tx == 0) x1 = x0; + else + x1 = x0 + w0 - ((double)tm->tiles.x_left * scx); + x2 = x0 + w0; + if (tx == 0) tx1 = 0; + else tx1 = 1 / (double)tm->tiles.x_edge; + tx2 = (double)tm->tiles.x_left / (double)tm->tiles.x_edge; + } + __evas_gl_window_use_texture(glw, tm->textures[t++], smooth); + glBegin(GL_QUADS); + glTexCoord2d(tx1, ty1); glVertex2d(x1, y1); + glTexCoord2d(tx2, ty1); glVertex2d(x2, y1); + glTexCoord2d(tx2, ty2); glVertex2d(x2, y2); + glTexCoord2d(tx1, ty2); glVertex2d(x1, y2); + glEnd(); + } + } + } +#ifndef GLNOCLIP + } +#endif +} + +Evas_GL_Image * +__evas_gl_image_new_from_file(Display *disp, char *file) +{ + Evas_List l; + Evas_GL_Image *image; + + for (l = __evas_images; l; l = l->next) + { + + image = l->data; + + if ((image->file) && (!strcmp(image->file, file))) + { + if (image->references == 0) + { + __evas_image_cache -= image->w * image->h * 4; + } + image->references++; + if (l != __evas_images) + { + __evas_images = evas_list_remove(__evas_images, image); + __evas_images = evas_list_prepend(__evas_images, image); + } + return image; + } + } + image = __evas_gl_image_alloc(file); + if (image) __evas_images = evas_list_prepend(__evas_images, image); + return image; +} + +void +__evas_gl_image_free(Evas_GL_Image *im) +{ + if (im->references > 0) + im->references--; + if (im->references == 0) + { + __evas_image_cache += im->w * im->h * 4; + __evas_gl_image_cache_flush(); + } +} + +void +__evas_gl_image_cache_empty(Display *disp) +{ + int prev_cache; + + prev_cache = __evas_image_cache_max; + __evas_image_cache_max = 0; + __evas_gl_image_cache_flush(); + __evas_image_cache_max = prev_cache; +} + +void +__evas_gl_image_cache_set_size(Display *disp, int size) +{ + __evas_image_cache_max = size; + __evas_gl_image_cache_flush(); +} + +int +__evas_gl_image_cache_get_size(Display *disp) +{ + return __evas_image_cache_max; +} + +int +__evas_gl_image_get_width(Evas_GL_Image *im) +{ + return im->w; +} + +int +__evas_gl_image_get_height(Evas_GL_Image *im) +{ + return im->h; +} + +void +__evas_gl_image_set_borders(Evas_GL_Image *im, int left, int right, + int top, int bottom) +{ + im->border.l = left; + im->border.r = right; + im->border.t = top; + im->border.b = bottom; +} + +void +__evas_gl_image_set_smooth_scaling(int on) +{ + __evas_smooth = on; +} + +/*****************************************************************************/ +/* font externals ************************************************************/ +/*****************************************************************************/ + +Evas_GL_Font * +__evas_gl_text_font_new(Display *disp, char *font, int size) +{ + Evas_List l; + Evas_GL_Font *fn; + + if (!font) return NULL; + for (l = __evas_fonts; l; l = l->next) + { + Evas_GL_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) + { + for (l = fn->textures; l; l = l->next) + { + Evas_GL_Font_Texture *ft; + + ft = l->data; + __evas_font_cache -= ft->texture->w * ft->texture->h; + } + } + fn->references++; + return fn; + } + } + fn = __evas_gl_font_load(font, size); + if (!fn) return NULL; + __evas_fonts = evas_list_prepend(__evas_fonts, fn); + return fn; +} + +void +__evas_gl_text_font_free(Evas_GL_Font *fn) +{ + if (!fn) return; + if (fn->references >= 0) + { + fn->references--; + if (fn->references == 0) + { + Evas_List l; + + for (l = fn->textures; l; l = l->next) + { + Evas_GL_Font_Texture *ft; + + ft = l->data; + __evas_font_cache += ft->texture->w * ft->texture->h; + } + } + } + __evas_gl_text_font_cache_flush(); +} + +int +__evas_gl_text_font_get_ascent(Evas_GL_Font *fn) +{ + if (!fn) return 0; + return fn->ascent; +} + +int +__evas_gl_text_font_get_descent(Evas_GL_Font *fn) +{ + if (!fn) return 0; + return fn->descent; +} + +int +__evas_gl_text_font_get_max_ascent(Evas_GL_Font *fn) +{ + if (!fn) return 0; + return fn->max_ascent; +} + +int +__evas_gl_text_font_get_max_descent(Evas_GL_Font *fn) +{ + if (!fn) return 0; + return fn->max_descent; +} + +void +__evas_gl_text_font_get_advances(Evas_GL_Font *fn, char *text, + int *advance_horiz, + int *advance_vert) +{ + if (advance_horiz) *advance_horiz = 0; + if (advance_horiz) *advance_vert = 0; + if (!fn) return; + if (!text) return; + if (text[0] == 0) return; +} + +int +__evas_gl_text_font_get_first_inset(Evas_GL_Font *fn, char *text) +{ + if (!fn) return 0; + if (!text) return 0; + if (text[0] == 0) return 0; +} + +void +__evas_gl_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] = strdup(path); +} + +void +__evas_gl_text_font_del_path(char *path) { int i, j; @@ -1154,8 +1657,11 @@ __evas_gl_text_font_path_del(const char *path) 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 *)); + 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); @@ -1165,490 +1671,29 @@ __evas_gl_text_font_path_del(const char *path) } } -static char ** -__evas_gl_text_font_path_list(int *num_ret) -{ - *num_ret = __evas_fpath_num; - return __evas_fpath; -} - -static int -__evas_gl_is_file(char *file) -{ - struct stat st; - - if (stat(file, &st) < 0) - return 0; - return 1; -} - -static Evas_GL_Font * -__evas_gl_text_font_load(char *font, int size) -{ - Evas_GL_Font *f; - TT_Error error; - TT_CharMap char_map; - TT_Glyph_Metrics metrics; - TT_Instance_Metrics imetrics; - int dpi = 96; - unsigned short i, n, code, load_flags; - unsigned short num_glyphs = 0, no_cmap = 0; - unsigned short platform, encoding; - int j, upm, ascent, descent; - char *name, *file = NULL, *tmp; - - if (!__evas_have_engine) - { - error = TT_Init_FreeType(&__evas_engine); - if (error) - return NULL; - __evas_have_engine = 1; - } - tmp = malloc(strlen(font) + 4 + 1); - if (!tmp) - return NULL; - sprintf(tmp, "%s.ttf", font); - if (__evas_gl_is_file(tmp)) - file = strdup(tmp); - else - { - sprintf(tmp, "%s.TTF", font); - if (__evas_gl_is_file(tmp)) - file = strdup(tmp); - else - { - sprintf(tmp, "%s", font); - if (__evas_gl_is_file(tmp)) - file = strdup(tmp); - } - } - free(tmp); - if (!file) - { - for (j = 0; (j < __evas_fpath_num) && (!file); j++) - { - tmp = malloc(strlen(__evas_fpath[j]) + 1 + strlen(font) + 4 + 1); - if (!tmp) - return NULL; - else - { - sprintf(tmp, "%s/%s.ttf", __evas_fpath[j], font); - if (__evas_gl_is_file(tmp)) - file = strdup(tmp); - else - { - sprintf(tmp, "%s/%s.TTF", __evas_fpath[j], font); - if (__evas_gl_is_file(tmp)) - file = strdup(tmp); - else - { - sprintf(tmp, "%s/%s", __evas_fpath[j], font); - if (__evas_gl_is_file(tmp)) - file = strdup(tmp); - } - } - } - free(tmp); - } - } - /* didnt find a file? abort */ - if (!file) - return NULL; - /* allocate */ - f = malloc(sizeof(Evas_GL_Font)); - /* put in name and references */ - f->file = strdup(font); - f->size = size; - f->references = 1; - /* remember engine */ - f->engine = __evas_engine; - f->mem_use = 0; - error = TT_Open_Face(f->engine, file, &f->face); - if (error) - { - free(f->file); - free(f); - /* fprintf(stderr, "Unable to open font\n"); */ - return NULL; - } - free(file); - error = TT_Get_Face_Properties(f->face, &f->properties); - if (error) - { - TT_Close_Face(f->face); - free(f->file); - free(f); - /* fprintf(stderr, "Unable to get face properties\n"); */ - return NULL; - } - - error = TT_New_Instance(f->face, &f->instance); - if (error) - { - TT_Close_Face(f->face); - free(f->file); - free(f); - /* fprintf(stderr, "Unable to create instance\n"); */ - return NULL; - } - - TT_Set_Instance_Resolutions(f->instance, dpi, dpi); - TT_Set_Instance_CharSize(f->instance, size * 64); - n = f->properties.num_CharMaps; - - /* get ascent & descent */ - TT_Get_Instance_Metrics(f->instance, &imetrics); - upm = f->properties.header->Units_Per_EM; - ascent = (f->properties.horizontal->Ascender * imetrics.y_ppem) / upm; - descent = (f->properties.horizontal->Descender * imetrics.y_ppem) / upm; - if (descent < 0) - descent = -descent; - f->ascent = ascent; - f->descent = descent; - - for (i = 0; i < n; i++) - { - TT_Get_CharMap_ID(f->face, i, &platform, &encoding); - if ((platform == 3 && encoding == 1) || - (platform == 0 && encoding == 0)) - { - TT_Get_CharMap(f->face, i, &char_map); - break; - } - } - if (i == n) - TT_Get_CharMap(f->face, 0, &char_map); - f->num_glyph = 256; - f->glyphs = (TT_Glyph *)malloc(f->num_glyph * sizeof(TT_Glyph)); - memset(f->glyphs, 0, f->num_glyph * sizeof(TT_Glyph)); - f->glyphinfo = (Evas_GL_Glyph_Info *)malloc(sizeof(Evas_GL_Glyph_Info) * f->num_glyph); - f->textures = NULL; - f->num_textures = 0; - - load_flags = TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH; - f->max_descent = 0; - f->max_ascent = 0; - for (i = 0; i < f->num_glyph; ++i) - { - if (TT_VALID(f->glyphs[i])) - continue; - - if (no_cmap) - { - code = (i - ' ' + 1) < 0 ? 0 : (i - ' ' + 1); - if (code >= num_glyphs) - code = 0; - } - else - code = TT_Char_Index(char_map, i); - - TT_New_Glyph(f->face, &f->glyphs[i]); - TT_Load_Glyph(f->instance, f->glyphs[i], code, load_flags); - TT_Get_Glyph_Metrics(f->glyphs[i], &metrics); - if ((metrics.bbox.yMin & -64) < f->max_descent) - f->max_descent = (metrics.bbox.yMin & -64); - if (((metrics.bbox.yMax + 63) & -64) > f->max_ascent) - f->max_ascent = ((metrics.bbox.yMax + 63) & -64); - } - /* work around broken fonts - some just have wrong ascent and */ - /* descent members */ - if (((f->ascent == 0) && (f->descent == 0)) || (f->ascent == 0)) - { - f->ascent = f->max_ascent / 64; - f->descent = -f->max_descent / 64; - } - /* all ent well in loading, so add to head of font list and return */ - /* we dont need the file handle hanging around so flush it out */ - TT_Flush_Face(f->face); - return f; -} - -static void -__evas_gl_text_calc_size(Evas_GL_Font *f, int *width, int *height, char *text) -{ - int i, ascent, descent, pw, ph; - TT_Glyph_Metrics gmetrics; - - ascent = f->ascent; - descent = f->descent; - pw = 0; - ph = ((f->max_ascent) - f->max_descent) / 64; - - for (i = 0; text[i]; i++) - { - unsigned char j; - - j = text[i]; - if (!TT_VALID(f->glyphs[j])) - continue; - TT_Get_Glyph_Metrics(f->glyphs[j], &gmetrics); - if (i == 0) - pw += ((-gmetrics.bearingX) / 64); - if (text[i + 1] == 0) - pw += (gmetrics.bbox.xMax / 64); - else - pw += gmetrics.advance / 64; - } - *width = pw; - *height = ph; -} - -static void -__evas_gl_text_font_destroy(Evas_GL_Font *font) -{ - int i; - - __evas_font_cache_used -= 256 * 128 * font->num_textures; - /* free freetype instance stuff */ - TT_Done_Instance(font->instance); - TT_Close_Face(font->face); - /* free all cached glyphs */ - for (i = 0; i < font->num_glyph; i++) - { - if (!TT_VALID(font->glyphs[i])) - TT_Done_Glyph(font->glyphs[i]); - } - /* free glyph info */ - free(font->glyphs); - free(font->glyphinfo); - if (font->textures) - { - glDeleteTextures(font->num_textures, font->textures); - free(font->textures); - } - /* free font struct & name */ - free(font->file); - free(font); -} - -static void -__evas_gl_text_cache_flush(void) -{ - while (__evas_font_cache_used > __evas_font_cache_max) - { - Evas_List l; - Evas_GL_Font *last_f; - - last_f = NULL; - for (l = __evas_fonts; l; l = l->next) - { - Evas_GL_Font *f; - - f = l->data; - if (f->references == 0) - last_f = f; - } - if (last_f) - { - __evas_fonts = evas_list_remove(__evas_fonts, last_f); - __evas_gl_text_font_destroy(last_f); - } - } -} - - -/*****************************************************************************/ -/* font externals ************************************************************/ -/*****************************************************************************/ - -Evas_GL_Font * -__evas_gl_text_font_new(Display *disp, char *font, int size) -{ - Evas_GL_Font *f; - Evas_List l; - - for (l = __evas_fonts; l; l = l->next) - { - f = l->data; - if ((f->buffer.display == disp) && (!strcmp(font, f->file)) && - (f->size == size)) - { - if (f->references == 0) - __evas_font_cache_used -= 256 * 128 * f->num_textures; - f->references++; - if (l != __evas_fonts) - { - __evas_fonts = evas_list_remove(__evas_fonts, f); - __evas_fonts = evas_list_prepend(__evas_fonts, f); - } - return f; - } - } - f = __evas_gl_text_font_load(font, size); - if (!f) return NULL; - f->context = __evas_gl_cx; - f->max_texture_size = 256; - f->buffer.display = disp; - f->buffer.colormap = __evas_gl_get_colormap(disp, 0); - f->buffer.visual_info = __evas_vi; - f->buffer.window = 0; - f->buffer.dest = 0; - f->buffer.dest_w = 0; - f->buffer.dest_h = 0; - f->buffer.display = disp; - if (!__evas_context_window) - { - XSetWindowAttributes att; - - att.colormap = f->buffer.colormap; - att.border_pixel = 0; - att.event_mask = 0; - __evas_context_window = XCreateWindow(f->buffer.display, - RootWindow(f->buffer.display, DefaultScreen(f->buffer.display)), - 0, 0, 32, 32, 0, - f->buffer.visual_info->depth, - InputOutput, - f->buffer.visual_info->visual, - CWColormap | CWBorderPixel | CWEventMask, - &att); - f->buffer.window = __evas_context_window; - glXMakeCurrent(f->buffer.display, f->buffer.window, f->context); - __evas_current_disp = f->buffer.display; - __evas_current_win = f->buffer.window; - } - else - { - f->buffer.window = __evas_context_window; - glXMakeCurrent(f->buffer.display, f->buffer.window, f->context); - __evas_current_disp = f->buffer.display; - __evas_current_win = f->buffer.window; - } - __evas_gl_text_font_render_textures(f); - __evas_fonts = evas_list_prepend(__evas_fonts, f); - return f; -} - -void -__evas_gl_text_font_free(Evas_GL_Font *fn) -{ - fn->references--; - if (fn->references == 0) - __evas_font_cache_used += 256 * 128 * fn->num_textures; - if (fn->references >= 0) - __evas_gl_text_cache_flush(); -} - -int -__evas_gl_text_font_get_ascent(Evas_GL_Font *fn) -{ - return fn->ascent; -} - -int -__evas_gl_text_font_get_descent(Evas_GL_Font *fn) -{ - return fn->descent; -} - -int -__evas_gl_text_font_get_max_ascent(Evas_GL_Font *fn) -{ - return fn->max_ascent / 64; -} - -int -__evas_gl_text_font_get_max_descent(Evas_GL_Font *fn) -{ - return fn->max_descent / 64; -} - -void -__evas_gl_text_font_get_advances(Evas_GL_Font *fn, char *text, - int *advance_horiz, - int *advance_vert) -{ - int i, ascent, descent, pw, ph; - TT_Glyph_Metrics gmetrics; - - ascent = fn->ascent; - descent = fn->descent; - pw = 0; - ph = ascent + descent; - - for (i = 0; text[i]; i++) - { - unsigned char j; - - j = text[i]; - if (!TT_VALID(fn->glyphs[j])) - continue; - TT_Get_Glyph_Metrics(fn->glyphs[j], &gmetrics); - if (i == 0) - pw += ((-gmetrics.bearingX) / 64); - pw += gmetrics.advance / 64; - } - *advance_horiz = pw; - *advance_vert = ph; -} - -int -__evas_gl_text_font_get_first_inset(Evas_GL_Font *fn, char *text) -{ - int i; - TT_Glyph_Metrics gmetrics; - - for (i = 0; text[i]; i++) - { - unsigned char j; - - j = text[i]; - if (!TT_VALID(fn->glyphs[j])) - continue; - TT_Get_Glyph_Metrics(fn->glyphs[j], &gmetrics); - return ((-gmetrics.bearingX) / 64); - } - return 0; -} - -void -__evas_gl_text_font_add_path(char *path) -{ - __evas_gl_text_font_path_add(path); -} - -void -__evas_gl_text_font_del_path(char *path) -{ - __evas_gl_text_font_path_del(path); -} - char ** __evas_gl_text_font_list_paths(int *count) { - return __evas_gl_text_font_path_list(count); + *count = __evas_fpath_num; + return __evas_fpath; } void __evas_gl_text_cache_empty(Display *disp) { - Evas_List l; - Evas_GL_Font *last_f; + int prev_cache; - last_f = (Evas_GL_Font *)1; - while (last_f) - { - last_f = NULL; - for (l = __evas_fonts; l; l = l->next) - { - Evas_GL_Font *f; - - f = l->data; - if (f->references == 0) - last_f = f; - } - if (last_f) - { - __evas_fonts = evas_list_remove(__evas_fonts, last_f); - __evas_gl_text_font_destroy(last_f); - } - } + prev_cache = __evas_font_cache_max; + __evas_font_cache_max = 0; + __evas_gl_text_font_cache_flush(); + __evas_font_cache_max = prev_cache; } void __evas_gl_text_cache_set_size(Display *disp, int size) { - __evas_font_cache_max = size; - __evas_gl_text_cache_flush(); + __evas_font_cache_max = size; + __evas_gl_text_font_cache_flush(); } int @@ -1660,133 +1705,267 @@ __evas_gl_text_cache_get_size(Display *disp) void __evas_gl_text_draw(Evas_GL_Font *fn, Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, int x, int y, char *text, - int r, int g, int b, int a) + int cr, int cg, int cb, int ca) { - if ((!fn) || (!text)) return; - __evas_gl_text_paste(fn, text, disp, win, win_w, win_h, x, y, r, g, b, a); + Evas_GL_Window *glw; + Evas_List l; + int go; + + 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 <= 0) return; + glw = __evas_gl_window_current(disp, win, win_w, win_h); + if (!glw) return; + __evas_gl_window_texture(glw, 1); + __evas_gl_window_blend(glw, 1); + __evas_gl_window_write_buf(glw, GL_BACK); + __evas_gl_window_read_buf(glw, GL_BACK); + __evas_gl_window_color(glw, cr, cg, cb, ca); + __evas_gl_window_dither(glw, 1); + +#ifndef GLNOCLIP + for (l = glw->updates; l; l = l->next) + { + Evas_GL_Rect *rect; + + go = 1; + rect = l->data; + { + int rx, ry, rw, rh; + + rx = 0; + ry = 0; + rw = win_w; + rh = win_h; + CLIP_TO(rx, ry, rw, rh, rect->x, rect->y, rect->w, rect->h); + if (__evas_clip) + { + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); + } + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; + } +#else + go = 1; + { + int rx, ry, rw, rh; + + rx = 0; + ry = 0; + rw = win_w; + rh = win_h; + if (__evas_clip) + { + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; + } + else + __evas_gl_window_clip(glw, 0, 0, 0, 0, 0); + } +#endif + /* render string here */ + if (go) + { + int i; + int x_offset, y_offset; + int glyph, rows; + Evas_GL_Glyph *g; + + if (text[0] == 0) return; + glyph = ((unsigned char *)text)[0]; + g = __evas_gl_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); + __evas_gl_text_get_size(fn, text, NULL, &rows); + 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_gl_text_font_get_glyph(fn, glyph); + __evas_gl_text_font_render_glyph(glw, 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->texture) && (g->texture->texture)) + { + __evas_gl_window_texture(glw, 1); + __evas_gl_window_use_texture(glw, + g->texture->texture, + 0); + } + else + __evas_gl_window_texture(glw, 0); + glBegin(GL_QUADS); + glTexCoord2d(g->tex.x1, g->tex.y1); + glVertex2i(x + xmin, y + ymin + off + adj); + glTexCoord2d(g->tex.x2, g->tex.y1); + glVertex2i(x + xmax + 1, y + ymin + off + adj); + glTexCoord2d(g->tex.x2, g->tex.y2); + glVertex2i(x + xmax + 1, y + ymax + off + adj + 1); + glTexCoord2d(g->tex.x1, g->tex.y2); + glVertex2i(x + xmin, y + ymax + off + adj + 1); + glEnd(); + x_offset += g->metrics.advance / 64; + } + } +#ifndef GLNOCLIP + } +#endif } void __evas_gl_text_get_size(Evas_GL_Font *fn, char *text, int *w, int *h) { - if ((!fn) || (!text)) - { - *w = 0; *h = 0; - return; - } - __evas_gl_text_calc_size(fn, w, h, text); + int i, pw, ph; + Evas_GL_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_gl_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 */ + pw += (g->metrics.bbox.xMax / 64); + else + pw += g->metrics.advance / 64; + } + if (w) *w = pw + 1; + if (h) *h = ph + 1; } int __evas_gl_text_get_character_at_pos(Evas_GL_Font *fn, char *text, int x, int y, int *cx, int *cy, int *cw, int *ch) { int i, px, ppx; - TT_Glyph_Metrics gmetrics; - if ((y < 0) || (y > (fn->ascent + fn->descent))) - return -1; - if (cy) - *cy = 0; - if (ch) - *ch = fn->ascent + fn->descent; + 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++) { - unsigned char j; + Evas_GL_Glyph *g; + int glyph; - j = text[i]; - if (!TT_VALID(fn->glyphs[j])) - continue; - TT_Get_Glyph_Metrics(fn->glyphs[j], &gmetrics); - ppx = px; - if (i == 0) - px += ((-gmetrics.bearingX) / 64); + glyph = ((unsigned char *)text)[i]; + g = __evas_gl_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 += (gmetrics.bbox.xMax / 64); + px += (g->metrics.bbox.xMax / 64); else - px += gmetrics.advance / 64; + px += g->metrics.advance / 64; if ((x >= ppx) && (x < px)) { if (cx) - *cx = ppx; + *cx = ppx; if (cw) - *cw = px - ppx; + *cw = px - ppx; return i; } } - *cw = 0; - *ch = 0; - *cx = 0; - *cy = 0; - return -1; + return -1; } void __evas_gl_text_get_character_number(Evas_GL_Font *fn, char *text, int num, int *cx, int *cy, int *cw, int *ch) { int i, px, ppx; - TT_Glyph_Metrics gmetrics; - if (cy) - *cy = 0; - if (ch) - *ch = fn->ascent + fn->descent; + 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++) { - unsigned char j; + Evas_GL_Glyph *g; + int glyph; - j = text[i]; - if (!TT_VALID(fn->glyphs[j])) - continue; - TT_Get_Glyph_Metrics(fn->glyphs[j], &gmetrics); + glyph = ((unsigned char *)text)[i]; + g = __evas_gl_text_font_get_glyph(fn, glyph); + if (!g) continue; + if (!TT_VALID(g->glyph)) continue; ppx = px; if (i == 0) - px += ((-gmetrics.bearingX) / 64); + px += ((-g->metrics.bearingX) / 64); if (text[i + 1] == 0) - px += (gmetrics.bbox.xMax / 64); + px += (g->metrics.bbox.xMax / 64); else - px += gmetrics.advance / 64; + px += g->metrics.advance / 64; if (i == num) { - if (cx) - *cx = ppx; - if (cw) - *cw = px - ppx; + if (cx) *cx = ppx; + if (cw) *cw = px - ppx; return; } } - *cw = 0; - *ch = 0; - *cx = 0; - *cy = 0; } - - - - - - - - - - - - - - - - - - - - - - - /*****************************************************************************/ /* rectangle externals *******************************************************/ /*****************************************************************************/ @@ -1794,75 +1973,100 @@ __evas_gl_text_get_character_number(Evas_GL_Font *fn, char *text, int num, int * void __evas_gl_rectangle_draw(Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, int x, int y, int w, int h, - int r, int g, int b, int a) + int cr, int cg, int cb, int ca) { - float rr, gg, bb, aa; - static int dest_w = 0, dest_h = 0; + Evas_GL_Window *glw; + Evas_List l; + int go; - if ((__evas_current_win != win) || (__evas_current_disp != disp)) + if (__evas_clip) { - glXMakeCurrent(disp, win, __evas_gl_cx); - __evas_current_disp = disp; - __evas_current_win = win; + cr = (cr * __evas_clip_r) / 255; + cg = (cg * __evas_clip_g) / 255; + cb = (cb * __evas_clip_b) / 255; + ca = (ca * __evas_clip_a) / 255; } - rr = (float)r / 255; - gg = (float)g / 255; - bb = (float)b / 255; - aa = (float)a / 255; - glColor4f(rr, gg, bb, aa); - glViewport(0, 0, win_w, win_h); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, win_w, 0, win_h, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glScalef(1, -1, 1); - glTranslatef(0, -win_h, 0); - dest_w = win_w; - dest_h = win_h; - if (a < 255) + if (ca <= 0) return; + if (w < 1) return; + if (h < 1) return; + glw = __evas_gl_window_current(disp, win, win_w, win_h); + if (!glw) return; + __evas_gl_window_texture(glw, 0); + if (ca < 255) __evas_gl_window_blend(glw, 1); + else __evas_gl_window_blend(glw, 0); + __evas_gl_window_write_buf(glw, GL_BACK); + __evas_gl_window_read_buf(glw, GL_BACK); + __evas_gl_window_color(glw, cr, cg, cb, ca); + __evas_gl_window_dither(glw, 1); + +#ifndef GLNOCLIP + for (l = glw->updates; l; l = l->next) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + Evas_GL_Rect *rect; + + go = 1; + rect = l->data; + { + int rx, ry, rw, rh; + + rx = x; + ry = y; + rw = w; + rh = h; + CLIP_TO(rx, ry, rw, rh, rect->x, rect->y, rect->w, rect->h); + if (__evas_clip) + { + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); + } + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; + } +#else + go = 1; + { + int rx, ry, rw, rh; + + rx = x; + ry = y; + rw = w; + rh = h; + if (__evas_clip) + { + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; + } + else + __evas_gl_window_clip(glw, 0, 0, 0, 0, 0); + } +#endif + /* render rect here */ + if (go) + { + double x1, x2, y1, y2; + + x1 = (double)x; + y1 = (double)y; + x2 = (double)(x + w); + y2 = (double)(y + h); + glBegin(GL_QUADS); + glVertex2d(x1, y1); + glVertex2d(x2, y1); + glVertex2d(x2, y2); + glVertex2d(x1, y2); + glEnd(); + } +#ifndef GLNOCLIP } - else - glDisable(GL_BLEND); - glEnable(GL_DITHER); - glDisable(GL_TEXTURE_2D); - glShadeModel(GL_FLAT); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - - glBegin(GL_QUADS); - glVertex2i(x, y); - glVertex2i(x + w, y); - glVertex2i(x + w, y + h); - glVertex2i(x, y + h); - glEnd(); - - glEnable(GL_TEXTURE_2D); +#endif } - - - - - - - - - - - - - - - - - - - /*****************************************************************************/ /* line externals ************************************************************/ /*****************************************************************************/ @@ -1870,235 +2074,88 @@ void __evas_gl_rectangle_draw(Display *disp, Imlib_Image dstim, Window void __evas_gl_line_draw(Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, int x1, int y1, int x2, int y2, - int r, int g, int b, int a) + int cr, int cg, int cb, int ca) { - float rr, gg, bb, aa; - static int dest_w = 0, dest_h = 0; + Evas_GL_Window *glw; + Evas_List l; + int go; - if ((__evas_current_win != win) || (__evas_current_disp != disp)) + if (__evas_clip) { - glXMakeCurrent(disp, win, __evas_gl_cx); - __evas_current_disp = disp; - __evas_current_win = win; + cr = (cr * __evas_clip_r) / 255; + cg = (cg * __evas_clip_g) / 255; + cb = (cb * __evas_clip_b) / 255; + ca = (ca * __evas_clip_a) / 255; } - rr = (float)r / 255; - gg = (float)g / 255; - bb = (float)b / 255; - aa = (float)a / 255; - glColor4f(rr, gg, bb, aa); - glViewport(0, 0, win_w, win_h); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, win_w, 0, win_h, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glScalef(1, -1, 1); - glTranslatef(0, -win_h, 0); - dest_w = win_w; - dest_h = win_h; + if (ca <= 0) return; + glw = __evas_gl_window_current(disp, win, win_w, win_h); + if (!glw) return; + __evas_gl_window_texture(glw, 0); + if (ca < 255) __evas_gl_window_blend(glw, 1); + else __evas_gl_window_blend(glw, 0); + __evas_gl_window_write_buf(glw, GL_BACK); + __evas_gl_window_read_buf(glw, GL_BACK); + __evas_gl_window_color(glw, cr, cg, cb, ca); + __evas_gl_window_dither(glw, 1); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_DITHER); - glDisable(GL_TEXTURE_2D); - glShadeModel(GL_FLAT); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glEnable(GL_LINE_SMOOTH); - - glBegin(GL_LINES); - glVertex2d((double)x1 + 0.5, (double)y1 + 0.5); - glVertex2d((double)x2 + 0.5, (double)y2 + 0.5); - glEnd(); - - glEnable(GL_TEXTURE_2D); -} - - - - - - - - - - - - - - - - - -/*****************************************************************************/ -/* gradient internals ********************************************************/ -/*****************************************************************************/ - -static void -__evas_gl_gradient_free_texture(Evas_GL_Graident *gr) -{ - if (gr->texture_w > 0) - glDeleteTextures(1, &(gr->texture)); - gr->texture_w = 0; -} - -static void -__evas_gl_gradient_gen_texture(Evas_GL_Graident *gr) -{ - Evas_List p; - unsigned char *map; - unsigned int *pmap; - int i, ll, v1, v2, j, inc, r, g, b, a, rr, gg, bb, aa, v, vv, l; - - if (!gr->colors) return; - if (!gr->colors->next) return; - ll = 1; - for (p = gr->colors; p; p = p->next) +#ifndef GLNOCLIP + for (l = glw->updates; l; l = l->next) { - Evas_GL_Graident_Color *cl; + Evas_GL_Rect *rect; - cl = p->data; - ll += cl->dist; - } - pmap = malloc(ll * 4); - map = malloc(gr->max_texture_size * 4); - i = 0; - for (p = gr->colors; p; p = p->next) - { - Evas_GL_Graident_Color *cl, *cl2; - - cl = p->data; - if (p->next) - cl2 = p->next->data; - if (p->next) + go = 1; + rect = l->data; { - for (j = 0; j < cl2->dist; j++) + int rx, ry, rw, rh; + + rx = 0; + ry = 0; + rw = win_w; + rh = win_h; + CLIP_TO(rx, ry, rw, rh, rect->x, rect->y, rect->w, rect->h); + if (__evas_clip) { - v1 = (j << 16) / cl2->dist; - v2 = 65536 - v1; - r = ((cl->r * v2) + (cl2->r * v1)) >> 16; - g = ((cl->g * v2) + (cl2->g * v1)) >> 16; - b = ((cl->b * v2) + (cl2->b * v1)) >> 16; - a = ((cl->a * v2) + (cl2->a * v1)) >> 16; - pmap[i++] = (a << 24) | (r << 16) | (g << 8) | b; + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); } + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; } - else +#else + go = 1; { - r = cl->r; - g = cl->g; - b = cl->b; - a = cl->a; - pmap[i++] = (a << 24) | (r << 16) | (g << 8) | b; - } - } - inc = ((ll - 1) << 16) / (gr->max_texture_size); - l = 0; - j = 0; - if (ll > gr->max_texture_size) - { - for (i = 0; i < gr->max_texture_size; i++) - { - v = pmap[l >> 16]; - if ((l >> 16) < ll) - vv = pmap[(l >> 16) + 1]; + int rx, ry, rw, rh; + + rx = 0; + ry = 0; + rw = win_w; + rh = win_h; + if (__evas_clip) + { + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; + } else - vv = pmap[(l >> 16)]; - v1 = l - ((l >> 16) << 16); - v2 = 65536 - v1; - b = ((v) ) & 0xff; - g = ((v) >> 8 ) & 0xff; - r = ((v) >> 16) & 0xff; - a = ((v) >> 24) & 0xff; - bb = ((vv) ) & 0xff; - gg = ((vv) >> 8 ) & 0xff; - rr = ((vv) >> 16) & 0xff; - aa = ((vv) >> 24) & 0xff; - r = ((r * v2) + (rr * v1)) >> 16; - g = ((g * v2) + (gg * v1)) >> 16; - b = ((b * v2) + (bb * v1)) >> 16; - a = ((a * v2) + (aa * v1)) >> 16; - map[j++] = r; - map[j++] = g; - map[j++] = b; - map[j++] = a; - l += inc; + __evas_gl_window_clip(glw, 0, 0, 0, 0, 0); } - } - else - { - for (i = 0; i < ll; i++) - { - v = pmap[i]; - b = ((v) ) & 0xff; - g = ((v) >> 8 ) & 0xff; - r = ((v) >> 16) & 0xff; - a = ((v) >> 24) & 0xff; - map[j++] = r; - map[j++] = g; - map[j++] = b; - map[j++] = a; - } - for (i = ll; i < gr->max_texture_size; i++) +#endif + /* render rect here */ + if (go) { - map[j++] = r; - map[j++] = g; - map[j++] = b; - map[j++] = a; + glBegin(GL_LINES); + glVertex2d((double)x1 + 0.5, (double)y1 + 0.5); + glVertex2d((double)x2 + 0.5, (double)y2 + 0.5); + glEnd(); } +#ifndef GLNOCLIP } - if (!__evas_context_window) - { - XSetWindowAttributes att; - att.colormap = gr->buffer.colormap; - att.border_pixel = 0; - att.event_mask = 0; - __evas_context_window = XCreateWindow(gr->buffer.display, - RootWindow(gr->buffer.display, DefaultScreen(gr->buffer.display)), - 0, 0, 32, 32, 0, - gr->buffer.visual_info->depth, - InputOutput, - gr->buffer.visual_info->visual, - CWColormap | CWBorderPixel | CWEventMask, - &att); - gr->buffer.window = __evas_context_window; - glXMakeCurrent(gr->buffer.display, gr->buffer.window, gr->context); - __evas_current_disp = gr->buffer.display; - __evas_current_win = gr->buffer.window; - } - else - { - gr->buffer.window = __evas_context_window; - glXMakeCurrent(gr->buffer.display, gr->buffer.window, gr->context); - __evas_current_disp = gr->buffer.display; - __evas_current_win = gr->buffer.window; - } - /* the texture */ - /***************************************/ - /*c1....c2.......c3......c4.....c5...c6*/ - /***************************************/ - glGenTextures(1, &(gr->texture)); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, gr->texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gr->max_texture_size, 1, 0, - GL_RGBA, GL_UNSIGNED_BYTE, map); - if (glGetError() == GL_OUT_OF_MEMORY) - { - __evas_gl_image_cache_empty(gr->buffer.display); - __evas_gl_text_cache_empty(gr->buffer.display); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gr->max_texture_size, 1, 0, - GL_RGBA, GL_UNSIGNED_BYTE, map); - } - gr->texture_w = ll; - gr->texture_h = 1; - free(pmap); - free(map); +#endif } /*****************************************************************************/ @@ -2111,49 +2168,42 @@ __evas_gl_gradient_new(Display *disp) Evas_GL_Graident *gr; gr = malloc(sizeof(Evas_GL_Graident)); - gr->colors = NULL; - gr->context = __evas_gl_cx; - gr->max_texture_size = 256; - gr->texture_w = 0; - gr->texture_h = 0; - gr->texture = 0; - gr->buffer.display = disp; - gr->buffer.colormap = __evas_gl_get_colormap(disp, 0); - gr->buffer.visual_info = __evas_vi; - gr->buffer.window = 0; - gr->buffer.dest = 0; - gr->buffer.dest_w = 0; - gr->buffer.dest_h = 0; - gr->buffer.display = disp; - return gr; + gr->col_range = NULL; + gr->textures = NULL; } void __evas_gl_gradient_free(Evas_GL_Graident *gr) { - Evas_List l; - - __evas_gl_gradient_free_texture(gr); - for (l = gr->colors; l; l = l->next) - free(l->data); - evas_list_free(gr->colors); + if (gr->col_range) + { + imlib_context_set_color_range(gr->col_range); + imlib_free_color_range(); + } + if (gr->textures); + { + Evas_List l; + + for (l = gr->textures; l; l = l->next) + { + Evas_GL_Graident_Texture *tg; + + tg = l->data; + __evas_gl_gradient_texture_free(tg); + } + evas_list_free(gr->textures); + } + free(gr); } void __evas_gl_gradient_color_add(Evas_GL_Graident *gr, int r, int g, int b, int a, int dist) { - Evas_GL_Graident_Color *cl; - - cl = malloc(sizeof(Evas_GL_Graident_Color)); - cl->r = r; - cl->g = g; - cl->b = b; - cl->a = a; - if (gr->colors) cl->dist = dist; - else cl->dist = 0; - gr->colors = evas_list_append(gr->colors, cl); - __evas_gl_gradient_free_texture(gr); + if (!gr->col_range) gr->col_range = imlib_create_color_range(); + imlib_context_set_color_range(gr->col_range); + imlib_context_set_color(r, g, b, a); + imlib_add_color_to_color_range(dist); } void @@ -2161,141 +2211,173 @@ __evas_gl_gradient_draw(Evas_GL_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) { - int i; - static int dest_w = 0, dest_h = 0; - double max, t[8]; + Evas_GL_Window *glw; + Evas_List l; + int go; + int cr, cg, cb, ca; + Evas_GL_Graident_Texture *tg; - - if (gr->texture_w == 0) - __evas_gl_gradient_gen_texture(gr); - if ((__evas_current_win != win) || (__evas_current_disp != disp)) + if (__evas_clip) { - glXMakeCurrent(disp, win, __evas_gl_cx); - __evas_current_disp = disp; - __evas_current_win = win; + cr = __evas_clip_r; + cg = __evas_clip_g; + cb = __evas_clip_b; + ca = __evas_clip_a; } - glColor4f(1.0, 1.0, 1.0, 1.0); - glViewport(0, 0, win_w, win_h); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, win_w, 0, win_h, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glScalef(1, -1, 1); - glTranslatef(0, -win_h, 0); - dest_w = win_w; - dest_h = win_h; - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_DITHER); - glEnable(GL_TEXTURE_2D); - glShadeModel(GL_FLAT); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glBindTexture(GL_TEXTURE_2D, gr->texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - t[0] = cos(((-angle + 45 + 90) * 2 * 3.141592654) / 360); - t[1] = sin(((-angle + 45 + 90) * 2 * 3.141592654) / 360); - - t[2] = cos(((-angle + 45 + 180) * 2 * 3.141592654) / 360); - t[3] = sin(((-angle + 45 + 180) * 2 * 3.141592654) / 360); - - t[4] = cos(((-angle + 45 + 270) * 2 * 3.141592654) / 360); - t[5] = sin(((-angle + 45 + 270) * 2 * 3.141592654) / 360); - - t[6] = cos(((-angle + 45 + 0) * 2 * 3.141592654) / 360); - t[7] = sin(((-angle + 45 + 0) * 2 * 3.141592654) / 360); - max = 0; - for (i = 0; i < 8; i++) + else { - if ((t[i] < 0) && (-t[i] > max)) max = -t[i]; - else if ((t[i] > max)) max = t[i]; + cr = 255; + cg = 255; + cb = 255; + ca = 255; } - if (max > 0) + if (ca <= 0) return; + if (w < 1) return; + if (h < 1) return; + glw = __evas_gl_window_current(disp, win, win_w, win_h); + if (!glw) return; + __evas_gl_window_texture(glw, 1); + __evas_gl_window_blend(glw, 1); + __evas_gl_window_write_buf(glw, GL_BACK); + __evas_gl_window_read_buf(glw, GL_BACK); + __evas_gl_window_color(glw, cr, cg, cb, ca); + __evas_gl_window_dither(glw, 1); + +#ifndef GLNOCLIP + for (l = glw->updates; l; l = l->next) { - for (i = 0; i < 8; i++) t[i] *= 1 / max; + Evas_GL_Rect *rect; + + go = 1; + rect = l->data; + { + int rx, ry, rw, rh; + + rx = x; + ry = y; + rw = w; + rh = h; + CLIP_TO(rx, ry, rw, rh, rect->x, rect->y, rect->w, rect->h); + if (__evas_clip) + { + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); + } + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; + } +#else + go = 1; + { + int rx, ry, rw, rh; + + rx = x; + ry = y; + rw = w; + rh = h; + if (__evas_clip) + { + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; + } + else + __evas_gl_window_clip(glw, 0, 0, 0, 0, 0); + } +#endif + /* render gradient here */ + if (go) + { + double x1, x2, y1, y2; + double max, t[8]; + int i; + + tg = __evas_gl_gradient_texture_new(glw, gr); + if (!tg->texture) + { + Imlib_Image prev_im, im; + DATA32 *data; + int tw, th; + + tw = glw->context->max_texture_size; + th = 4; + im = imlib_create_image(tw, th); + prev_im = imlib_context_get_image(); + imlib_context_set_image(im); + imlib_image_set_has_alpha(1); + data = imlib_image_get_data(); + memset(data, 0, tw * th * sizeof(DATA32)); + imlib_image_put_back_data(data); + imlib_context_set_color_range(gr->col_range); + imlib_image_fill_color_range_rectangle(1, 1, tw - 2, th - 2, + 270.0); + data = imlib_image_get_data(); + memcpy(&(data[(1) + (0 * tw)]), &(data[(1) + (1 * tw)]), + (tw - 2) * sizeof(DATA32)); + memcpy(&(data[(1) + (3 * tw)]), &(data[(1) + (2 * tw)]), + (tw - 2) * sizeof(DATA32)); + data[(0) + (0 * tw)] = data[(1) + (0 * tw)]; + data[(0) + (1 * tw)] = data[(1) + (1 * tw)]; + data[(0) + (2 * tw)] = data[(1) + (2 * tw)]; + data[(0) + (3 * tw)] = data[(1) + (3 * tw)]; + data[(tw - 1) + (0 * tw)] = data[(tw - 2) + (0 * tw)]; + data[(tw - 1) + (1 * tw)] = data[(tw - 2) + (1 * tw)]; + data[(tw - 1) + (2 * tw)] = data[(tw - 2) + (2 * tw)]; + data[(tw - 1) + (3 * tw)] = data[(tw - 2) + (3 * tw)]; + imlib_image_put_back_data(data); + tg->texture = __evas_gl_texture_new(glw, im, 0, 0, tw, th); + imlib_free_image(); + } + __evas_gl_window_use_texture(glw, tg->texture, 1); + t[0] = cos(((-angle + 45 + 90) * 2 * 3.141592654) / 360); + t[1] = sin(((-angle + 45 + 90) * 2 * 3.141592654) / 360); + + t[2] = cos(((-angle + 45 + 180) * 2 * 3.141592654) / 360); + t[3] = sin(((-angle + 45 + 180) * 2 * 3.141592654) / 360); + + t[4] = cos(((-angle + 45 + 270) * 2 * 3.141592654) / 360); + t[5] = sin(((-angle + 45 + 270) * 2 * 3.141592654) / 360); + + t[6] = cos(((-angle + 45 + 0) * 2 * 3.141592654) / 360); + t[7] = sin(((-angle + 45 + 0) * 2 * 3.141592654) / 360); + max = 0; + for (i = 0; i < 8; i++) + { + if ((t[i] < 0) && (-t[i] > max)) max = -t[i]; + else if ((t[i] > max)) max = t[i]; + } + if (max > 0) + { + for (i = 0; i < 8; i++) t[i] *= 1 / max; + } + for (i = 0; i < 8; i+=2) + { + t[i] = (1.0 + + ((((0.5) + (t[i] / 2.0)) * + ((double)glw->context->max_texture_size - 2.0)))) / + (double)glw->context->max_texture_size; + t[i + 1] = (1.0 + ((((0.5) - (t[i + 1] / 2.0))) * 2.0)) / 4.0; + } + x1 = (double)x; + y1 = (double)y; + x2 = (double)(x + w); + y2 = (double)(y + h); + glBegin(GL_QUADS); + glTexCoord2d(t[0], t[1]); glVertex2d(x1, y1); + glTexCoord2d(t[2], t[3]); glVertex2d(x2, y1); + glTexCoord2d(t[4], t[5]); glVertex2d(x2, y2); + glTexCoord2d(t[6], t[7]); glVertex2d(x1, y2); + glEnd(); + } +#ifndef GLNOCLIP } - for (i = 0; i < 8; i+=2) - { - t[i] = (((0.5) + (t[i] / 2)) * (double)gr->texture_w) / (double)gr->max_texture_size; - t[i + 1] = ((0.5) - (t[i + 1] / 2)); - } - - glBegin(GL_QUADS); - glTexCoord2d(t[0], t[1]); glVertex2i(x, y); - glTexCoord2d(t[2], t[3]); glVertex2i(x + w, y); - glTexCoord2d(t[4], t[5]); glVertex2i(x + w, y + h); - glTexCoord2d(t[6], t[7]); glVertex2i(x, y + h); - glEnd(); -} - - - - - - - - - - - - - -/* something is wrong here - GL experts? the polys dont get tesselated */ -/* correctly */ -/* -#ifdef HAVE_GLU -static void -__evas_gl_tess_begin_cb(GLenum which) -{ - glBegin(which); -} - -static void -__evas_gl_tess_end_cb(void) -{ - glEnd(); -} - -static void -__evas_gl_tess_error_cb(GLenum errorcode) -{ -} - -static void -__evas_gl_tess_vertex_cb(GLvoid *vertex) -{ - glVertex2dv(vertex); -} - -static void -__evas_gl_tess_combine_cb(GLdouble coords[3], - GLdouble *vertex_data[4], - GLfloat weight[4], GLdouble **data_out) -{ - GLdouble *vertex; - int i; - - vertex = (GLdouble *) malloc(6 * sizeof(GLdouble)); - vertex[0] = coords[0]; - vertex[1] = coords[1]; - vertex[2] = coords[2]; - for (i = 3; i < 6; i++) - vertex[i] = - weight[0] * vertex_data[0][i] + - weight[1] * vertex_data[1][i] + - weight[2] * vertex_data[2][i] + - weight[3] * vertex_data[3][i]; - *data_out = vertex; -} #endif -*/ +} /************/ /* polygons */ @@ -2304,115 +2386,119 @@ void __evas_gl_poly_draw (Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, Evas_List points, - int r, int g, int b, int a) + int cr, int cg, int cb, int ca) { - Evas_List l2; - float rr, gg, bb, aa; - static int dest_w = 0, dest_h = 0; + Evas_GL_Window *glw; + Evas_List l; + int go; - if ((__evas_current_win != win) || (__evas_current_disp != disp)) + if (__evas_clip) { - glXMakeCurrent(disp, win, __evas_gl_cx); - __evas_current_disp = disp; - __evas_current_win = win; + cr = (cr * __evas_clip_r) / 255; + cg = (cg * __evas_clip_g) / 255; + cb = (cb * __evas_clip_b) / 255; + ca = (ca * __evas_clip_a) / 255; } - rr = (float)r / 255; - gg = (float)g / 255; - bb = (float)b / 255; - aa = (float)a / 255; - glColor4f(rr, gg, bb, aa); - glViewport(0, 0, win_w, win_h); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, win_w, 0, win_h, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glScalef(1, -1, 1); - glTranslatef(0, -win_h, 0); - dest_w = win_w; - dest_h = win_h; - if (a < 255) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - else - glDisable(GL_BLEND); - glEnable(GL_DITHER); - glDisable(GL_TEXTURE_2D); - glShadeModel(GL_FLAT); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + if (ca <= 0) return; + glw = __evas_gl_window_current(disp, win, win_w, win_h); + if (!glw) return; + __evas_gl_window_texture(glw, 0); + if (ca < 255) __evas_gl_window_blend(glw, 1); + else __evas_gl_window_blend(glw, 0); + __evas_gl_window_write_buf(glw, GL_BACK); + __evas_gl_window_read_buf(glw, GL_BACK); + __evas_gl_window_color(glw, cr, cg, cb, ca); + __evas_gl_window_dither(glw, 1); -/* -#ifdef HAVE_GLU +#ifndef GLNOCLIP + for (l = glw->updates; l; l = l->next) { - static void *tess = NULL; + Evas_GL_Rect *rect; - if (!tess) + go = 1; + rect = l->data; { - tess = gluNewTess(); + int rx, ry, rw, rh; - gluTessCallback(tess, GLU_TESS_BEGIN, __evas_gl_tess_begin_cb); - gluTessCallback(tess, GLU_TESS_END, __evas_gl_tess_end_cb); - gluTessCallback(tess, GLU_TESS_ERROR, __evas_gl_tess_error_cb); - gluTessCallback(tess, GLU_TESS_VERTEX, __evas_gl_tess_vertex_cb); - gluTessCallback(tess, GLU_TESS_COMBINE, __evas_gl_tess_combine_cb); - gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); + rx = 0; + ry = 0; + rw = win_w; + rh = win_h; + CLIP_TO(rx, ry, rw, rh, rect->x, rect->y, rect->w, rect->h); + if (__evas_clip) + { + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); + } + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; } - gluTessBeginPolygon(tess, NULL); - gluTessBeginContour(tess); - for (l2 = points; l2; l2 = l2->next) +#else + go = 1; { - Evas_Point p; - GLdouble glp[3]; + int rx, ry, rw, rh; - p = l2->data; - glp[0] = p->x; - glp[1] = p->y; - glp[2] = 0; - gluTessVertex(tess, glp, glp); + rx = 0; + ry = 0; + rw = win_w; + rh = win_h; + if (__evas_clip) + { + CLIP_TO(rx, ry, rw, rh, + __evas_clip_x, __evas_clip_y, + __evas_clip_w, __evas_clip_h); + if ((rw > 0) && (rh > 0)) + __evas_gl_window_clip(glw, 1, rx, ry, rw, rh); + else go = 0; + } + else + __evas_gl_window_clip(glw, 0, 0, 0, 0, 0); } - gluTessEndContour(tess); - gluTessEndPolygon(tess); +#endif + /* render poly here */ + if (go) + { + Evas_List l; + + glBegin(GL_POLYGON); + for (l = points; l; l = l->next) + { + Evas_Point p; + + p = l->data; + glVertex2d(p->x, p->y); + } + glEnd(); + } +#ifndef GLNOCLIP } -#else -*/ -/* -#warning "You do not have GLU and thus polygons that are not convex will not" -#warning "render correctly." -*/ - glBegin(GL_POLYGON); - for (l2 = points; l2; l2 = l2->next) - { - Evas_Point p; - - p = l2->data; - glVertex2d(p->x, p->y); - } - glEnd(); -/*#endif*/ - glEnable(GL_TEXTURE_2D); +#endif } - - - - - - - - - - /*****************************************************************************/ /* general externals *********************************************************/ /*****************************************************************************/ +void +__evas_gl_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_gl_sync(Display *disp) { + glFlush(); glXWaitGL(); XSync(disp, False); } @@ -2420,35 +2506,57 @@ __evas_gl_sync(Display *disp) void __evas_gl_flush_draw(Display *disp, Imlib_Image dstim, Window win) { - if ((__evas_current_win != win) || (__evas_current_disp != disp)) + Evas_GL_Window *glw; + Evas_List l; + + glw = __evas_gl_window_lookup(disp, win); + if (!glw) return; + if (glw->updates) { - glXMakeCurrent(disp, win, __evas_gl_cx); - __evas_current_disp = disp; - __evas_current_win = win; + for (l = glw->updates; l; l = l->next) + { + Evas_GL_Rect *rect; + + rect = l->data; +#ifndef GLSWB + __evas_gl_window_swap_rect(glw, rect->x, rect->y, rect->w, rect->h); +#endif + free(rect); + } + evas_list_free(glw->updates); + glw->updates = NULL; } +#ifdef GLSWB glXSwapBuffers(disp, win); +#endif } int __evas_gl_capable(Display *disp) { int eb, evb; + Evas_List l; + static Evas_List capables = NULL; - if (__evas_gl_cx) return 1; - if (glXQueryExtension(disp, &eb, &evb)) + for (l = capables; l; l = l->next) { - __evas_gl_init(disp, 0, 256); - if (__evas_gl_cx) return 1; - return 0; + if (l->data == disp) return 1; + } + if (glXQueryExtension(disp, &eb, &evb)) + { + capables = evas_list_prepend(capables, disp); + return 1; } return 0; } +static XVisualInfo *__evas_vi = NULL; + Visual * __evas_gl_get_visual(Display *disp, int screen) { static Display *d = NULL; - + if (d != disp) { d = disp; @@ -2473,30 +2581,32 @@ __evas_gl_get_colormap(Display *disp, int screen) if (!__evas_vi) __evas_gl_get_visual(disp, screen); if (d != disp) { - d = disp; - cmap = XCreateColormap(disp, RootWindow(disp, screen), __evas_vi->visual, 0); - } + d = disp; + cmap = XCreateColormap(disp, RootWindow(disp, screen), __evas_vi->visual, 0); + } return cmap; } void __evas_gl_init(Display *disp, int screen, int colors) { - if (__evas_gl_cx) return; - - __evas_gl_get_visual(disp, screen); - /* direct rendering client */ - __evas_gl_cx = glXCreateContext(disp, __evas_vi, NULL, GL_TRUE); - /* GLX indirect */ - if (!__evas_gl_cx) glXCreateContext(disp, __evas_vi, NULL, GL_FALSE); -/* __evas_gl_cx = glXCreateContext(disp, __evas_vi, NULL, GL_FALSE);*/ } void __evas_gl_draw_add_rect(Display *disp, Imlib_Image dstim, Window win, int x, int y, int w, int h) { - return; + Evas_GL_Window *glw; + Evas_GL_Rect *rect; + + glw = __evas_gl_window_lookup(disp, win); + if (!glw) return; + rect = malloc(sizeof(Evas_GL_Rect)); + rect->x = x; + rect->y = y; + rect->w = w; + rect->h = h; + glw->updates = evas_list_append(glw->updates, rect); } #else diff --git a/legacy/evas/src/evas_gl_routines.h b/legacy/evas/src/evas_gl_routines.h index b5a3369f90..506c7c968b 100644 --- a/legacy/evas/src/evas_gl_routines.h +++ b/legacy/evas/src/evas_gl_routines.h @@ -32,112 +32,166 @@ typedef int GLuint; #include "Evas_private.h" #include "Evas.h" -typedef struct _evas_gl_image Evas_GL_Image; -typedef struct _evas_gl_font Evas_GL_Font; -typedef struct _evas_gl_glyph_info Evas_GL_Glyph_Info; -typedef struct _evas_gl_gradient Evas_GL_Graident; -typedef struct _evas_gl_gradient_color Evas_GL_Graident_Color; -typedef enum _evas_gl_image_state Evas_GL_Image_State; +typedef struct _evas_gl_image Evas_GL_Image; +typedef struct _evas_gl_font Evas_GL_Font; +typedef struct _evas_gl_gradient Evas_GL_Graident; -enum _evas_gl_image_state +typedef struct _evas_gl_font_texture Evas_GL_Font_Texture; +typedef struct _evas_gl_glpyh_texture Evas_GL_Glyph_Texture; +typedef struct _evas_gl_glyph Evas_GL_Glyph; +typedef struct _evas_gl_gradient_texture Evas_GL_Graident_Texture; +typedef struct _evas_gl_window Evas_GL_Window; +typedef struct _evas_gl_context Evas_GL_Context; +typedef struct _evas_gl_rect Evas_GL_Rect; +typedef struct _evas_gl_texture Evas_GL_Texture; +typedef struct _evas_gl_texmesh Evas_GL_Texmesh; + +struct _evas_gl_window { - EVAS_STATE_DATA, - EVAS_STATE_TEXTURE + Display *disp; + Window win; + Window root; + int screen; + Evas_GL_Context *context; + Evas_List updates; + int w, h; +}; + +struct _evas_gl_context +{ + Display *disp; + int screen; + GLXContext context; + Window win; + Window root; + XVisualInfo *visualinfo; + Visual *visual; + Colormap colormap; + int dither; + int blend; + int texture; + DATA32 color; + struct { + int active; + int x, y, w, h; + } clip; + GLenum read_buf; + GLenum write_buf; + Evas_GL_Texture *bound_texture; + + int max_texture_depth; + int max_texture_size; +}; + +struct _evas_gl_rect +{ + int x, y, w, h; +}; + +struct _evas_gl_texture +{ + int w, h; + GLuint texture; + int smooth; +}; + +struct _evas_gl_texmesh +{ + struct { + int x, y; + int x_edge, y_edge; + int x_left, y_left; + } tiles; + Evas_GL_Texture **textures; + Evas_GL_Window *window; + Evas_GL_Context *context; }; struct _evas_gl_image { - Evas_GL_Image_State state; - int w, h; - int direct; - int bl, br, bt, bb; - int alpha; char *file; - /* data specific params */ - DATA32 *data; - /* common GL params */ - GLXContext context; - /* texture state specific params */ - struct - { - int max_size; - int w, h; - int edge_w, edge_h; - GLuint *textures; - } texture; - /* buffer specific params */ - struct - { - Display *display; - XVisualInfo *visual_info; - Colormap colormap; - Window window, dest; - int dest_w, dest_h; - } buffer; + Imlib_Image im; + int w, h; + struct { + int l, r, t, b; + } border; + int has_alpha; + Evas_List textures; int references; }; -struct _evas_gl_font +struct _evas_gl_gradient_texture { - char *file; - int size; - - TT_Engine engine; - TT_Face face; - TT_Instance instance; - TT_Face_Properties properties; - int num_glyph; - TT_Glyph *glyphs; - Evas_GL_Glyph_Info *glyphinfo; - int max_descent; - int max_ascent; - int descent; - int ascent; - int mem_use; - - GLXContext context; - int max_texture_size; - int num_textures; - GLuint *textures; - struct - { - Display *display; - XVisualInfo *visual_info; - Colormap colormap; - Window window, dest; - int dest_w, dest_h; - } buffer; - int references; -}; - -struct _evas_gl_glyph_info -{ - GLuint texture; - int px, py, pw, ph; - double x1, y1, x2, y2; -}; - -struct _evas_gl_gradient_color -{ - int r, g, b, a; - int dist; + Evas_GL_Window *window; + Evas_GL_Context *context; + Evas_GL_Texture *texture; }; struct _evas_gl_gradient { - Evas_List colors; - GLXContext context; - int max_texture_size; - int texture_w, texture_h; - GLuint texture; - struct - { - Display *display; - XVisualInfo *visual_info; - Colormap colormap; - Window window, dest; - int dest_w, dest_h; - } buffer; + Imlib_Color_Range col_range; + Evas_List textures; +}; + +struct _evas_gl_glpyh_texture +{ + struct { + double x1, x2, y1, y2; + } tex; + Evas_GL_Window *window; + Evas_GL_Context *context; + Evas_GL_Texture *texture; +}; + +struct _evas_gl_glyph +{ + int glyph_id; + TT_Glyph glyph; + + TT_Glyph_Metrics metrics; + + Evas_GL_Glyph_Texture *texture; + + struct { + double x1, x2, y1, y2; + } tex; + + Evas_List textures; +}; + +struct _evas_gl_font_texture +{ + struct { + int x, y; + int row_h; + } cursor; + Evas_GL_Window *window; + Evas_GL_Context *context; + Evas_GL_Texture *texture; +}; + +struct _evas_gl_font +{ + char *font; + int size; + + TT_Engine engine; + TT_Face face; + TT_Instance instance; + TT_Face_Properties properties; + TT_CharMap char_map; + TT_Instance_Metrics metrics; + + Evas_List glyphs[256]; + + Evas_List textures; + + int ascent; + int descent; + int max_descent; + int max_ascent; + + int references; }; /***************/ @@ -202,6 +256,7 @@ void __evas_gl_poly_draw (Display *disp, Imlib_Image dstim, Window /***********/ /* drawing */ /***********/ +void __evas_gl_set_clip_rect(int on, int x, int y, int w, int h, int r, int g, int b, int a); void __evas_gl_init(Display *disp, int screen, int colors); int __evas_gl_capable(Display *disp); void __evas_gl_flush_draw(Display *disp, Imlib_Image dstim, Window win); diff --git a/legacy/evas/src/evas_image_routines.c b/legacy/evas/src/evas_image_routines.c index a05d32b8c6..262e5da54f 100644 --- a/legacy/evas/src/evas_image_routines.c +++ b/legacy/evas/src/evas_image_routines.c @@ -4,6 +4,17 @@ static void __evas_image_image_cache_flush(Display *disp); static int __evas_anti_alias = 1; static Evas_List drawable_list = NULL; +/* 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 ***********************************************************/ /*****************************************************************************/ @@ -806,6 +817,20 @@ __evas_image_poly_draw (Display *disp, Imlib_Image dstim, Window win, static Visual *__evas_visual = NULL; static Colormap __evas_cmap = 0; +void +__evas_image_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_image_sync(Display *disp) { diff --git a/legacy/evas/src/evas_image_routines.h b/legacy/evas/src/evas_image_routines.h index 3db9164646..eb05e5d9af 100644 --- a/legacy/evas/src/evas_image_routines.h +++ b/legacy/evas/src/evas_image_routines.h @@ -108,6 +108,7 @@ void __evas_image_poly_draw (Display *disp, Imlib_Image dstim, W /***********/ /* drawing */ /***********/ +void __evas_image_set_clip_rect(int on, int x, int y, int w, int h, int r, int g, int b, int a); void __evas_image_init(Display *disp, int screen, int colors); int __evas_image_capable(Display *disp); void __evas_image_flush_draw(Display *disp, Imlib_Image dstim, Window win); diff --git a/legacy/evas/src/evas_imlib_routines.c b/legacy/evas/src/evas_imlib_routines.c index 783a42cb83..b1f69154c8 100644 --- a/legacy/evas/src/evas_imlib_routines.c +++ b/legacy/evas/src/evas_imlib_routines.c @@ -5,6 +5,17 @@ static void __evas_imlib_image_cache_flush(Display *disp); static int __evas_anti_alias = 1; static Evas_List drawable_list = NULL; +/* 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 ***********************************************************/ /*****************************************************************************/ @@ -68,7 +79,14 @@ __evas_imlib_image_draw(Evas_Imlib_Image *im, Evas_List l; Imlib_Color_Modifier cm = NULL; - if (ca == 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 == 0) return; if ((cr != 255) || (cg != 255) || (cb != 255) || (ca != 255)) { DATA8 r[256], g[256], b[256], a[256]; @@ -113,6 +131,13 @@ __evas_imlib_image_draw(Evas_Imlib_Image *im, if (RECTS_INTERSECT(up->x, up->y, up->w, up->h, dst_x, dst_y, dst_w, dst_h)) { + if (__evas_clip) + imlib_context_set_cliprect(__evas_clip_x - up->x, + __evas_clip_y - up->y, + __evas_clip_w, + __evas_clip_h); + else imlib_context_set_cliprect(0, 0, 0, 0); + if (!up->image) up->image = imlib_create_image(up->w, up->h); imlib_context_set_image(up->image); @@ -301,13 +326,21 @@ __evas_imlib_text_cache_get_size(Display *disp) void __evas_imlib_text_draw(Evas_Imlib_Font *fn, Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, int x, int y, char *text, - int r, int g, int b, int a) + int cr, int cg, int cb, int ca) { Evas_List l; 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 ((!fn) || (!text)) return; - imlib_context_set_color(r, g, b, a); + if (ca == 0) return; + imlib_context_set_color(cr, cg, cb, ca); imlib_context_set_font((Imlib_Font)fn); imlib_context_set_angle(0.0); imlib_context_set_operation(IMLIB_OP_COPY); @@ -336,6 +369,12 @@ __evas_imlib_text_draw(Evas_Imlib_Font *fn, Display *disp, Imlib_Image dstim, Wi if (RECTS_INTERSECT(up->x, up->y, up->w, up->h, x, y, w, h)) { + if (__evas_clip) + imlib_context_set_cliprect(__evas_clip_x - up->x, + __evas_clip_y - up->y, + __evas_clip_w, + __evas_clip_h); + else imlib_context_set_cliprect(0, 0, 0, 0); if (!up->image) up->image = imlib_create_image(up->w, up->h); imlib_context_set_image(up->image); @@ -407,11 +446,19 @@ __evas_imlib_text_get_character_number(Evas_Imlib_Font *fn, char *text, void __evas_imlib_rectangle_draw(Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, int x, int y, int w, int h, - int r, int g, int b, int a) + int cr, int cg, int cb, int ca) { Evas_List l; - imlib_context_set_color(r, g, b, a); + 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 == 0) return; + imlib_context_set_color(cr, cg, cb, ca); imlib_context_set_angle(0.0); imlib_context_set_operation(IMLIB_OP_COPY); imlib_context_set_color_modifier(NULL); @@ -438,6 +485,8 @@ void __evas_imlib_rectangle_draw(Display *disp, Imlib_Image dstim, if (RECTS_INTERSECT(up->x, up->y, up->w, up->h, x, y, w, h)) { + if (__evas_clip) imlib_context_set_cliprect(__evas_clip_x - up->x, __evas_clip_y - up->y, __evas_clip_w, __evas_clip_h); + else imlib_context_set_cliprect(0, 0, 0, 0); if (!up->image) up->image = imlib_create_image(up->w, up->h); imlib_context_set_image(up->image); @@ -471,12 +520,20 @@ void __evas_imlib_rectangle_draw(Display *disp, Imlib_Image dstim, void __evas_imlib_line_draw(Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, int x1, int y1, int x2, int y2, - int r, int g, int b, int a) + int cr, int cg, int cb, int ca) { Evas_List l; int x, y, w, h; - imlib_context_set_color(r, g, b, a); + 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 == 0) return; + imlib_context_set_color(cr, cg, cb, ca); imlib_context_set_angle(0.0); imlib_context_set_operation(IMLIB_OP_COPY); imlib_context_set_color_modifier(NULL); @@ -512,6 +569,8 @@ void __evas_imlib_line_draw(Display *disp, Imlib_Image dstim, Windo if (RECTS_INTERSECT(up->x, up->y, up->w, up->h, x, y, w, h)) { + if (__evas_clip) imlib_context_set_cliprect(__evas_clip_x - up->x, __evas_clip_y - up->y, __evas_clip_w, __evas_clip_h); + else imlib_context_set_cliprect(0, 0, 0, 0); if (!up->image) up->image = imlib_create_image(up->w, up->h); imlib_context_set_image(up->image); @@ -546,36 +605,75 @@ void __evas_imlib_line_draw(Display *disp, Imlib_Image dstim, Windo Evas_Imlib_Graident * __evas_imlib_gradient_new(Display *disp) { - return (Evas_Imlib_Graident *)imlib_create_color_range(); + Evas_Imlib_Graident *gr; + + gr = malloc(sizeof(Evas_Imlib_Graident)); + gr->colors = NULL; } void __evas_imlib_gradient_free(Evas_Imlib_Graident *gr) { - imlib_context_set_color_range((Imlib_Color_Range)gr); - imlib_free_color_range(); + 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_imlib_gradient_color_add(Evas_Imlib_Graident *gr, int r, int g, int b, int a, int dist) { - imlib_context_set_color_range((Imlib_Color_Range)gr); - imlib_context_set_color(r, g, b, a); - imlib_add_color_to_color_range(dist); + Evas_Imlib_Color *cl; + + cl = malloc(sizeof(Evas_Imlib_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_imlib_gradient_draw(Evas_Imlib_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_Color_Range cr; + + if ((__evas_clip) && (__evas_clip_a == 0)) return; imlib_context_set_angle(angle); imlib_context_set_operation(IMLIB_OP_COPY); imlib_context_set_color_modifier(NULL); imlib_context_set_direction(IMLIB_TEXT_TO_RIGHT); - imlib_context_set_color_range((Imlib_Color_Range)gr); imlib_context_set_anti_alias(1); imlib_context_set_blend(1); + cr = imlib_create_color_range(); + imlib_context_set_color_range(cr); + { + Evas_List l; + + for (l = gr->colors; l; l = l->next) + { + Evas_Imlib_Color *cl; + + cl = l->data; + if (__evas_clip) + imlib_context_set_color((cl->r * __evas_clip_r) / 255, + (cl->g * __evas_clip_g) / 255, + (cl->b * __evas_clip_b) / 255, + (cl->a * __evas_clip_a) / 255); + else + imlib_context_set_color(cl->r, cl->g, cl->b, cl->a); + imlib_add_color_to_color_range(cl->dist); + } + } for(l = drawable_list; l; l = l->next) { Evas_Imlib_Drawable *dr; @@ -596,6 +694,8 @@ __evas_imlib_gradient_draw(Evas_Imlib_Graident *gr, Display *disp, Imlib_Image d if (RECTS_INTERSECT(up->x, up->y, up->w, up->h, x, y, w, h)) { + if (__evas_clip) imlib_context_set_cliprect(__evas_clip_x - up->x, __evas_clip_y - up->y, __evas_clip_w, __evas_clip_h); + else imlib_context_set_cliprect(0, 0, 0, 0); if (!up->image) up->image = imlib_create_image(up->w, up->h); imlib_context_set_image(up->image); @@ -604,6 +704,7 @@ __evas_imlib_gradient_draw(Evas_Imlib_Graident *gr, Display *disp, Imlib_Image d } } } + imlib_free_color_range(); } @@ -616,12 +717,20 @@ void __evas_imlib_poly_draw (Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, Evas_List points, - int r, int g, int b, int a) + int cr, int cg, int cb, int ca) { Evas_List l, l2; int x, y, w, h; - imlib_context_set_color(r, g, b, a); + 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 == 0) return; + imlib_context_set_color(cr, cg, cb, ca); imlib_context_set_angle(0.0); imlib_context_set_operation(IMLIB_OP_COPY); imlib_context_set_color_modifier(NULL); @@ -682,6 +791,9 @@ __evas_imlib_poly_draw (Display *disp, Imlib_Image dstim, Window win, { ImlibPolygon pol; + if (__evas_clip) imlib_context_set_cliprect(__evas_clip_x - up->x, __evas_clip_y - up->y, __evas_clip_w, __evas_clip_h); + else imlib_context_set_cliprect(0, 0, 0, 0); + if (!up->image) up->image = imlib_create_image(up->w, up->h); imlib_context_set_image(up->image); @@ -720,6 +832,20 @@ __evas_imlib_poly_draw (Display *disp, Imlib_Image dstim, Window win, static Visual *__evas_visual = NULL; static Colormap __evas_cmap = 0; +void +__evas_imlib_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_imlib_sync(Display *disp) { diff --git a/legacy/evas/src/evas_imlib_routines.h b/legacy/evas/src/evas_imlib_routines.h index d85de104da..48796787ba 100644 --- a/legacy/evas/src/evas_imlib_routines.h +++ b/legacy/evas/src/evas_imlib_routines.h @@ -26,10 +26,11 @@ typedef void Evas_Imlib_Image; typedef void Evas_Imlib_Font; -typedef void Evas_Imlib_Graident; typedef struct _evas_imlib_drawable Evas_Imlib_Drawable; typedef struct _evas_imlib_update Evas_Imlib_Update; +typedef struct _evas_imlib_color Evas_Imlib_Color; +typedef struct _evas_imlib_gradient Evas_Imlib_Graident; struct _evas_imlib_drawable { @@ -44,6 +45,17 @@ struct _evas_imlib_update int x, y, w, h; }; +struct _evas_imlib_color +{ + int r, g, b, a; + int dist; +}; + +struct _evas_imlib_gradient +{ + Evas_List colors; +}; + /***************/ /* image stuff */ /***************/ @@ -108,6 +120,7 @@ void __evas_imlib_poly_draw (Display *disp, Imlib_Image dstim, W /***********/ /* drawing */ /***********/ +void __evas_imlib_set_clip_rect(int on, int x, int y, int w, int h, int r, int g, int b, int a); void __evas_imlib_init(Display *disp, int screen, int colors); int __evas_imlib_capable(Display *disp); void __evas_imlib_flush_draw(Display *disp, Imlib_Image dstim, Window win); diff --git a/legacy/evas/src/evas_object.c b/legacy/evas/src/evas_object.c index f63e818600..cd6bed8153 100644 --- a/legacy/evas/src/evas_object.c +++ b/legacy/evas/src/evas_object.c @@ -114,12 +114,139 @@ _evas_layer_free(Evas e, Evas_Layer layer) free(layer); } +void +_evas_cleanup_clip(Evas e, Evas_Object o) +{ + if (o->clip.list) + { + Evas_List l; + + for (l = o->clip.list; l; l = l->next) + { + Evas_Object o2; + + o2 = l->data; + o2->clip.object = NULL; + o2->clip.changed = 1; + o2->changed = 1; + e->changed = 1; + } + evas_list_free(o->clip.list); + } + if (o->clip.object) + o->clip.object->clip.list = evas_list_remove(o->clip.object->clip.list, o); +} + +void +_evas_get_current_clipped_geometry(Evas e, Evas_Object o, double *x, double *y, double *w, double *h) +{ + if (!o->current.visible) + { + *x = 0.0; + *y = 0.0; + *w = 0.0; + *h = 0.0; + return; + } + if (o->clip.object) + _evas_get_current_clipped_geometry(e, o->clip.object, x, y, w, h); + CLIP_TO(*x, *y, *w, *h, + o->current.x, o->current.y, o->current.w, o->current.h); +} + +void +_evas_get_previous_clipped_geometry(Evas e, Evas_Object o, double *x, double *y, double *w, double *h) +{ + if (!o->previous.visible) + { + *x = 0.0; + *y = 0.0; + *w = 0.0; + *h = 0.0; + return; + } + if (o->clip.object) + _evas_get_current_clipped_geometry(e, o->clip.object, x, y, w, h); + CLIP_TO(*x, *y, *w, *h, + o->previous.x, o->previous.y, o->previous.w, o->previous.h); +} + +int +_evas_point_in_object(Evas e, Evas_Object o, int x, int y) +{ + double cx, cy; + double ox, oy, ow, oh; + + if (o->delete_me) return 0; + cx = evas_screen_x_to_world(e, x); + cy = evas_screen_x_to_world(e, y); + ox = o->current.x; oy = o->current.y; + ow = o->current.w; oh = o->current.h; + _evas_get_current_clipped_geometry(e, o, &ox, &oy, &ow, &oh); + if ((cx >= ox) && (cx < (ox + ow)) && (cy >= oy) && (cy < (oy + oh))) + return 1; + return 0; +} + +void +evas_set_clip(Evas e, Evas_Object o, Evas_Object clip) +{ + if (!e) return; + if (!o) return; + if (!clip) return; + + if (o->clip.object == clip) return; + e->changed = 1; + o->changed = 1; + o->clip.changed = 1; + if (o->clip.object) + o->clip.object->clip.list = evas_list_remove(o->clip.object->clip.list, o); + o->clip.object = clip; + clip->clip.list = evas_list_prepend(clip->clip.list, o); +} + +void +evas_unset_clip(Evas e, Evas_Object o) +{ + if (!e) return; + if (!o) return; + + if (o->clip.object) + { + e->changed = 1; + o->changed = 1; + o->clip.changed = 1; + o->clip.object->clip.list = evas_list_remove(o->clip.object->clip.list, o); + o->clip.object = NULL; + } +} + +Evas_Object +evas_get_clip_object(Evas e, Evas_Object o) +{ + if (!e) return NULL; + if (!o) return NULL; + + return o->clip.object; +} + +Evas_List +evas_get_clip_list(Evas e, Evas_Object o) +{ + if (!e) return NULL; + if (!o) return NULL; + + return o->clip.list; +} + /* deleting objects */ void evas_del_object(Evas e, Evas_Object o) { if (!e) return; if (!o) return; + _evas_cleanup_clip(e, o); + e->changed = 1; evas_hide(e, o); o->delete_me = 1; } @@ -228,11 +355,14 @@ evas_objects_in_rect(Evas e, double x, double y, double w, double h) Evas_Object ob; ob = ll->data; - if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me)) + if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me) && (!ob->clip.list)) { - if (RECTS_INTERSECT(x, y, w, h, - ob->current.x, ob->current.y, - ob->current.w, ob->current.h)) + double ox, oy, ow, oh; + + ox = ob->current.x; oy = ob->current.y; + ow = ob->current.w; oh = ob->current.h; + _evas_get_current_clipped_geometry(e, ob, &ox, &oy, &ow, &oh); + if (RECTS_INTERSECT(x, y, w, h, ox, oy, ow, oh)) objs = evas_list_prepend(objs, ll->data); } } @@ -257,11 +387,14 @@ evas_objects_at_position(Evas e, double x, double y) Evas_Object ob; ob = ll->data; - if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me)) + if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me) && (!ob->clip.list)) { - if (RECTS_INTERSECT(x, y, 1, 1, - ob->current.x, ob->current.y, - ob->current.w, ob->current.h)) + double ox, oy, ow, oh; + + ox = ob->current.x; oy = ob->current.y; + ow = ob->current.w; oh = ob->current.h; + _evas_get_current_clipped_geometry(e, ob, &ox, &oy, &ow, &oh); + if (RECTS_INTERSECT(x, y, 1, 1, ox, oy, ow, oh)) objs = evas_list_prepend(objs, ll->data); } } @@ -287,11 +420,14 @@ evas_object_in_rect(Evas e, double x, double y, double w, double h) Evas_Object ob; ob = ll->data; - if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me)) + if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me) && (!ob->clip.list)) { - if (RECTS_INTERSECT(x, y, w, h, - ob->current.x, ob->current.y, - ob->current.w, ob->current.h)) + double ox, oy, ow, oh; + + ox = ob->current.x; oy = ob->current.y; + ow = ob->current.w; oh = ob->current.h; + _evas_get_current_clipped_geometry(e, ob, &ox, &oy, &ow, &oh); + if (RECTS_INTERSECT(x, y, w, h, ox, oy, ow, oh)) o = ob; } } @@ -317,11 +453,14 @@ evas_object_at_position(Evas e, double x, double y) Evas_Object ob; ob = ll->data; - if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me)) + if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me) && (!ob->clip.list)) { - if (RECTS_INTERSECT(x, y, 1, 1, - ob->current.x, ob->current.y, - ob->current.w, ob->current.h)) + double ox, oy, ow, oh; + + ox = ob->current.x; oy = ob->current.y; + ow = ob->current.w; oh = ob->current.h; + _evas_get_current_clipped_geometry(e, ob, &ox, &oy, &ow, &oh); + if (RECTS_INTERSECT(x, y, 1.0, 1.0, ox, oy, ow, oh)) o = ob; } } diff --git a/legacy/evas/src/evas_render.c b/legacy/evas/src/evas_render.c index 3a8126ea1d..731be5ca0d 100644 --- a/legacy/evas/src/evas_render.c +++ b/legacy/evas/src/evas_render.c @@ -17,43 +17,58 @@ ((SPANS_COMMON((x), (w), (xx), (ww))) && (SPANS_COMMON((y), (h), (yy), (hh)))) #endif +void _evas_get_current_clipped_geometry(Evas e, Evas_Object o, double *x, double *y, double *w, double *h); +void _evas_get_previous_clipped_geometry(Evas e, Evas_Object o, double *x, double *y, double *w, double *h); + void _evas_object_get_current_translated_coords(Evas e, Evas_Object o, - int *x, int *y, int *w, int *h) + int *x, int *y, int *w, int *h, int clip) { + double ox, oy, ow, oh; + + ox = o->current.x; oy = o->current.y; + ow = o->current.w; oh = o->current.h; + if (clip) + _evas_get_current_clipped_geometry(e, o, &ox, &oy, &ow, &oh); *x = (int) - (((o->current.x - e->current.viewport.x) * + (((ox - e->current.viewport.x) * (double)e->current.drawable_width) / e->current.viewport.w); *y = (int) - (((o->current.y - e->current.viewport.y) * + (((oy - e->current.viewport.y) * (double)e->current.drawable_height) / e->current.viewport.h); *w = (int) - ((o->current.w * (double)e->current.drawable_width) / + ((ow * (double)e->current.drawable_width) / e->current.viewport.w); *h = (int) - ((o->current.h * (double)e->current.drawable_height) / + ((oh * (double)e->current.drawable_height) / e->current.viewport.h); } void _evas_object_get_previous_translated_coords(Evas e, Evas_Object o, - int *x, int *y, int *w, int *h) + int *x, int *y, int *w, int *h, int clip) { + double ox, oy, ow, oh; + + ox = o->previous.x; oy = o->previous.y; + ow = o->previous.w; oh = o->previous.h; + if (clip) + _evas_get_previous_clipped_geometry(e, o, &ox, &oy, &ow, &oh); *x = (int) - (((o->previous.x - e->previous.viewport.x) * + (((ox - e->previous.viewport.x) * (double)e->previous.drawable_width) / e->previous.viewport.w); *y = (int) - (((o->previous.y - e->previous.viewport.y) * + (((oy - e->previous.viewport.y) * (double)e->previous.drawable_height) / e->previous.viewport.h); *w = (int) - ((o->previous.w * (double)e->previous.drawable_width) / + ((ow * (double)e->previous.drawable_width) / e->previous.viewport.w); *h = (int) - ((o->previous.h * (double)e->previous.drawable_height) / + ((oh * (double)e->previous.drawable_height) / e->previous.viewport.h); } @@ -178,6 +193,7 @@ evas_render_updates(Evas e) void (*func_line_draw) (Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, int x1, int y1, int x2, int y2, int r, int g, int b, int a); void (*func_gradient_draw) (void *gr, Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, int x, int y, int w, int h, double angle); void (*func_poly_draw) (Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, Evas_List points, int r, int g, int b, int a); + void (*func_set_clip_rect) (int on, int x, int y, int w, int h, int r, int g, int b, int a); if (!e) return NULL; if ((e->current.render_method == RENDER_METHOD_IMAGE) && @@ -215,6 +231,7 @@ evas_render_updates(Evas e) func_line_draw = __evas_imlib_line_draw; func_gradient_draw = __evas_imlib_gradient_draw; func_poly_draw = __evas_imlib_poly_draw; + func_set_clip_rect = __evas_imlib_set_clip_rect; break; case RENDER_METHOD_BASIC_HARDWARE: func_draw_add_rect = __evas_x11_draw_add_rect; @@ -233,6 +250,7 @@ evas_render_updates(Evas e) func_line_draw = __evas_x11_line_draw; func_gradient_draw = __evas_x11_gradient_draw; func_poly_draw = __evas_x11_poly_draw; + func_set_clip_rect = __evas_x11_set_clip_rect; break; case RENDER_METHOD_3D_HARDWARE: func_draw_add_rect = __evas_gl_draw_add_rect; @@ -251,6 +269,7 @@ evas_render_updates(Evas e) func_line_draw = __evas_gl_line_draw; func_gradient_draw = __evas_gl_gradient_draw; func_poly_draw = __evas_gl_poly_draw; + func_set_clip_rect = __evas_gl_set_clip_rect; break; case RENDER_METHOD_ALPHA_HARDWARE: func_draw_add_rect = __evas_render_draw_add_rect; @@ -269,6 +288,7 @@ evas_render_updates(Evas e) func_line_draw = __evas_render_line_draw; func_gradient_draw = __evas_render_gradient_draw; func_poly_draw = __evas_render_poly_draw; + func_set_clip_rect = __evas_render_set_clip_rect; break; case RENDER_METHOD_IMAGE: func_draw_add_rect = __evas_image_draw_add_rect; @@ -287,6 +307,7 @@ evas_render_updates(Evas e) func_line_draw = __evas_image_line_draw; func_gradient_draw = __evas_image_gradient_draw; func_poly_draw = __evas_image_poly_draw; + func_set_clip_rect = __evas_image_set_clip_rect; break; default: break; @@ -311,10 +332,11 @@ evas_render_updates(Evas e) for (ll = layer->objects; ll; ll = ll->next) { Evas_Object_Any o; - int real_change, prop_change; + int real_change, prop_change, clip_change; real_change = 0; prop_change = 0; + clip_change = 0; o = ll->data; if (o->delete_me) @@ -330,7 +352,8 @@ evas_render_updates(Evas e) (o->current.h != o->previous.h) || (o->current.zoomscale != o->previous.zoomscale) || (o->current.layer != o->previous.layer) || - (o->current.stacking))) + (o->current.stacking) || + (o->clip.changed))) ) { if (((o->current.visible != o->previous.visible) || @@ -353,8 +376,8 @@ evas_render_updates(Evas e) prop_change = 1; } real_change = 1; - } - + clip_change = o->clip.changed; + } o->current.stacking = 0; if ((!real_change) && (o->current.visible)) @@ -490,10 +513,12 @@ evas_render_updates(Evas e) _evas_object_get_previous_translated_coords(e, o, &x, &y, - &w, &h); + &w, &h, + 1 - clip_change); _evas_object_get_current_translated_coords(e, o, &xx, &yy, - &ww, &hh); + &ww, &hh, + 1 - clip_change); rl = NULL; if (x < xx) { @@ -576,11 +601,13 @@ evas_render_updates(Evas e) { _evas_object_get_previous_translated_coords(e, o, &x, &y, - &w, &h); + &w, &h, + 1 - clip_change); evas_update_rect(e, x, y, w, h); _evas_object_get_current_translated_coords(e, o, &x, &y, - &w, &h); + &w, &h, + 1 - clip_change); evas_update_rect(e, x, y, w, h); } } @@ -637,12 +664,50 @@ evas_render_updates(Evas e) _evas_object_get_current_translated_coords(e, o, &x, &y, - &w, &h); + &w, &h, + 1 - o->clip.changed); + o->clip.changed = 0; if (RECTS_INTERSECT(0, 0, e->current.drawable_width, e->current.drawable_height, - x, y, w, h)) + x, y, w, h) && + (!o->clip.list)) { + if (!o->clip.changed) + _evas_object_get_current_translated_coords(e, o, + &x, &y, + &w, &h, + 0); + if (o->clip.object) + { + Evas_Object_Rectangle oo; + int clr, clg, clb, cla; + int clx, cly, clw, clh; + + clr = 255; + clg = 255; + clb = 255; + cla = 255; + if (o->clip.object->type == OBJECT_RECTANGLE) + { + oo = o->clip.object; + + clr = oo->current.r; + clg = oo->current.g; + clb = oo->current.b; + cla = oo->current.a; + } + _evas_object_get_current_translated_coords(e, o, + &clx, &cly, + &clw, &clh, + 1); + if ((clw > 1) && (clh > 1)) + func_set_clip_rect(1, clx, cly, clw, clh, clr, clg, clb, cla); + else + func_set_clip_rect(1, e->current.drawable_width + 1, e->current.drawable_height + 1, 1, 1, 255, 255, 255, 255); + } + else + func_set_clip_rect(0, 0, 0, 0, 0, 255, 255, 255, 255); switch (o->type) { case OBJECT_IMAGE: diff --git a/legacy/evas/src/evas_render_routines.c b/legacy/evas/src/evas_render_routines.c index 9a6e6f3ee7..a77f8fadef 100644 --- a/legacy/evas/src/evas_render_routines.c +++ b/legacy/evas/src/evas_render_routines.c @@ -7,6 +7,17 @@ static void __evas_render_image_cache_flush(Display *disp); static int __evas_anti_alias = 1; static Evas_List drawable_list = NULL; +/* 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 ***********************************************************/ /*****************************************************************************/ @@ -611,6 +622,20 @@ __evas_render_poly_draw (Display *disp, Imlib_Image dstim, Window win, static Visual *__evas_visual = NULL; static Colormap __evas_cmap = 0; +void +__evas_render_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_render_sync(Display *disp) { @@ -811,6 +836,7 @@ void __evas_render_poly_draw (Display *disp, Imlib_Image dstim, Win /***********/ /* drawing */ /***********/ +void __evas_render_set_clip_rect(int on, int x, int y, int w, int h, int r, int g, int b, int a) {} void __evas_render_init(Display *disp, int screen, int colors){} int __evas_render_capable(Display *disp){return 0;} void __evas_render_flush_draw(Display *disp, Imlib_Image dstim, Window win){} diff --git a/legacy/evas/src/evas_render_routines.h b/legacy/evas/src/evas_render_routines.h index 1cc9f20a94..b575d76338 100644 --- a/legacy/evas/src/evas_render_routines.h +++ b/legacy/evas/src/evas_render_routines.h @@ -131,6 +131,7 @@ void __evas_render_poly_draw (Display *disp, Imlib_Image dstim, /***********/ /* drawing */ /***********/ +void __evas_render_set_clip_rect(int on, int x, int y, int w, int h, int r, int g, int b, int a); void __evas_render_init(Display *disp, int screen, int colors); int __evas_render_capable(Display *disp); void __evas_render_flush_draw(Display *disp, Imlib_Image dstim, Window win); diff --git a/legacy/evas/src/evas_x11_routines.c b/legacy/evas/src/evas_x11_routines.c index b6d6c04c84..5f91549760 100644 --- a/legacy/evas/src/evas_x11_routines.c +++ b/legacy/evas/src/evas_x11_routines.c @@ -1,4 +1,8 @@ #include "evas_x11_routines.h" +#include +#include +#include +#include #define CLIP(x, y, w, h, xx, yy, ww, hh) \ if (x < (xx)) {w += (x - (xx)); x = (xx);} \ @@ -6,6 +10,40 @@ 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; @@ -13,6 +51,22 @@ 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 ***********************************************************/ /*****************************************************************************/ @@ -20,11 +74,34 @@ static Colormap __evas_cmap = 0; static void __evas_x11_image_cache_flush(Display *disp) { - int size; + Evas_X11_Image *im, *im_last; + Evas_List l; - size = imlib_get_cache_size(); - imlib_set_cache_size(0); - imlib_set_cache_size(size); + 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); + } + } } /*****************************************************************************/ @@ -33,15 +110,57 @@ __evas_x11_image_cache_flush(Display *disp) Evas_X11_Image * __evas_x11_image_new_from_file(Display *disp, char *file) -{ - return (Evas_X11_Image *)imlib_load_image(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 = imlib_load_image(file); + if (!im->image) + { + free(im); + return NULL; + } + im->disp = disp; + im->file = strdup(file); + im->references = 1; + imlib_context_set_image(im->image); + 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) { - imlib_context_set_image((Imlib_Image)im); - imlib_free_image(); + im->references--; + if (im->references == 0) + { + /* flush */ + __evas_image_cache += im->pw * im->ph * 4; + __evas_x11_image_cache_flush(im->disp); + } } void @@ -52,18 +171,24 @@ __evas_x11_image_cache_empty(Display *disp) 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) { - imlib_set_cache_size(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 imlib_get_cache_size(); + return __evas_image_cache_max; } void @@ -75,11 +200,18 @@ __evas_x11_image_draw(Evas_X11_Image *im, { Evas_List l; Imlib_Color_Modifier cm = NULL; - Pixmap pmap = 0, mask = 0; 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]; @@ -103,9 +235,9 @@ __evas_x11_image_draw(Evas_X11_Image *im, imlib_context_set_visual(__evas_visual); imlib_context_set_colormap(__evas_cmap); imlib_context_set_drawable(w); - imlib_context_set_dither_mask(__evas_anti_alias); - imlib_context_set_anti_alias(__evas_anti_alias); - imlib_context_set_dither(1); + imlib_context_set_dither_mask(0); + imlib_context_set_anti_alias(0); + imlib_context_set_dither(__evas_anti_alias); imlib_context_set_blend(0); imlib_context_set_angle(0.0); imlib_context_set_operation(IMLIB_OP_COPY); @@ -129,45 +261,84 @@ __evas_x11_image_draw(Evas_X11_Image *im, if (RECTS_INTERSECT(up->x, up->y, up->w, up->h, dst_x, dst_y, dst_w, dst_h)) { - Imlib_Border bd; - int xx, yy, ww, hh, iw, ih; + 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); - imlib_context_set_image(im); - imlib_image_get_border(&bd); - /* if we haven't created a pixmap for thew image yet this */ - /* round of updates */ - iw = imlib_image_get_width(); - ih = imlib_image_get_height(); - ww = (iw * dst_w) / src_w; - hh = (ih * dst_h) / src_h; - xx = (src_x * src_w) / dst_w; - yy = (src_y * src_h) / dst_h; - if (!pmap) - imlib_render_pixmaps_for_whole_image_at_size(&pmap, &mask, - ww, hh); - if (mask) + 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 * src_w) / dw; + yy = (src_y * src_h) / dh; + if (__evas_clip) { - XSetClipMask(disp, dr->gc, mask); - XSetClipOrigin(disp, dr->gc, dst_x - up->x - src_x, dst_y - up->y - src_y); + 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; } - else + if ((dw > 1) && (dh > 1)) { - XSetClipMask(disp, dr->gc, None); + 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 (pmap) - XCopyArea(disp, pmap, up->p, dr->gc, - xx, yy, - dst_w, dst_h, - dst_x - up->x, dst_y - up->y); } } } } - if (pmap) imlib_free_pixmap_and_mask(pmap); if (cm) { imlib_free_color_modifier(); @@ -178,15 +349,13 @@ __evas_x11_image_draw(Evas_X11_Image *im, int __evas_x11_image_get_width(Evas_X11_Image *im) { - imlib_context_set_image((Imlib_Image)im); - return imlib_image_get_width(); + return im->w; } int __evas_x11_image_get_height(Evas_X11_Image *im) { - imlib_context_set_image((Imlib_Image)im); - return imlib_image_get_height(); + return im->h; } void @@ -195,12 +364,24 @@ __evas_x11_image_set_borders(Evas_X11_Image *im, int left, int right, { Imlib_Border bd; - imlib_context_set_image((Imlib_Image)im); - bd.left = left; - bd.right = right; - bd.top = top; - bd.bottom = bottom; - imlib_image_set_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 @@ -239,6 +420,275 @@ __evas_x11_image_set_smooth_scaling(int 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_rend_lut[9] = { 0, 64, 128, 192, 255, 255, 255, 255, 255 }; + +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); +} + +__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)) return strdup(buf); + } + 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)) return strdup(buf); + } + } + 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; + 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 = strdup(font); + fn->size = size; + fn->engine = __evas_tt_engine; + 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_List l; + + for (i = 0; i < 256; i++) + { + for (l = fn->glyphs[i]; l; l = l->next) + { + Evas_X11_Glyph *g; + + g = l->data; + __evas_font_cache -= (((g->pw -1) | 0x7) + 1) * g->ph / 8; + } + } + 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 ************************************************************/ /*****************************************************************************/ @@ -246,36 +696,101 @@ __evas_x11_image_set_smooth_scaling(int on) Evas_X11_Font * __evas_x11_text_font_new(Display *disp, char *font, int size) { - return NULL; + 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) + { + int i; + Evas_List l; + + for (i = 0; i < 256; i++) + { + for (l = fn->glyphs[i]; l; l = l->next) + { + Evas_X11_Glyph *g; + + g = l->data; + __evas_font_cache -= (((g->pw -1) | 0x7) + 1) * g->ph / 8; + } + } + } + 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) + { + int i; + Evas_List l; + + for (i = 0; i < 256; i++) + { + for (l = fn->glyphs[i]; l; l = l->next) + { + Evas_X11_Glyph *g; + + g = l->data; + __evas_font_cache += (((g->pw -1) | 0x7) + 1) * g->ph / 8; + } + } + } + } + __evas_x11_text_font_cache_flush(); } int __evas_x11_text_font_get_ascent(Evas_X11_Font *fn) { - return 1; + if (!fn) return 0; + return fn->ascent; } int __evas_x11_text_font_get_descent(Evas_X11_Font *fn) { - return 1; + if (!fn) return 0; + return fn->descent; } int __evas_x11_text_font_get_max_ascent(Evas_X11_Font *fn) { - return 1; + if (!fn) return 0; + return fn->max_ascent; } int __evas_x11_text_font_get_max_descent(Evas_X11_Font *fn) { - return 1; + if (!fn) return 0; + return fn->max_descent; } void @@ -283,44 +798,92 @@ __evas_x11_text_font_get_advances(Evas_X11_Font *fn, char *text, int *advance_horiz, int *advance_vert) { + if (advance_horiz) *advance_horiz = 0; + if (advance_horiz) *advance_vert = 0; + if (!fn) return; + if (!text) return; + if (text[0] == 0) return; + /* FIXME */ } int __evas_x11_text_font_get_first_inset(Evas_X11_Font *fn, char *text) { - return 1; + if (!fn) return 0; + if (!text) return 0; + if (text[0] == 0) return 0; + /* FIXME */ } 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] = strdup(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) { - return NULL; + *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 0; + return __evas_font_cache_max; } void @@ -328,11 +891,40 @@ __evas_x11_text_draw(Evas_X11_Font *fn, Display *disp, Imlib_Image dstim, Window int win_w, int win_h, int x, int y, char *text, int r, int g, int b, int a) { + /* FIXME */ } 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 */ + pw += (g->metrics.bbox.xMax / 64); + else + pw += g->metrics.advance / 64; + } + if (w) *w = pw + 1; + if (h) *h = ph + 1; } int @@ -340,6 +932,45 @@ __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; } @@ -348,6 +979,43 @@ __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; + } + } } @@ -381,21 +1049,28 @@ __evas_x11_text_get_character_number(Evas_X11_Font *fn, char *text, 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 r, int g, int b, int a) + int cr, int cg, int cb, int ca) { Evas_List l; DATA32 pixel; - Imlib_Image im = NULL; - Pixmap pmap = 0, mask = 0, s_mask = 0; - imlib_context_set_color(r, g, b, a); + 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_dither_mask(1); + 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(1); + imlib_context_set_dither(0); imlib_context_set_blend(0); imlib_context_set_angle(0.0); imlib_context_set_operation(IMLIB_OP_COPY); @@ -423,85 +1098,33 @@ void __evas_x11_rectangle_draw(Display *disp, Imlib_Image dstim, Wi { if (!up->p) up->p = XCreatePixmap(disp, win, up->w, up->h, dr->depth); - if (!im) + XSetForeground(disp, dr->gc, pixel); + XSetClipMask(disp, dr->gc, None); + XSetClipOrigin(disp, dr->gc, 0, 0); + XSetFillStyle(disp, dr->gc, FillSolid); { - pixel = (a << 24) | (r << 16) | (g << 8) | b; - im = imlib_create_image_using_data(1, 1, &pixel); - imlib_context_set_image(im); - if (a < 255) imlib_image_set_has_alpha(1); - if (!pmap) - imlib_render_pixmaps_for_whole_image_at_size(&pmap, &mask, - 32, 32); - } - if (a < 255) - { - if (mask) + 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) { - int xx, yy, ww, hh, x1, y1, xs, ys; - GC gc; - XGCValues gcv; - - xx = x - up->x; - yy = y - up->y; - ww = w; - hh = h; - CLIP(xx, yy, ww, hh, 0, 0, up->w, up->h); - s_mask = XCreatePixmap(disp, win, ww, hh, 1); - gc = XCreateGC(disp, s_mask, 0, &gcv); - xs = (x - up->x) % 32; - if (xs > 0) xs = 0; - else - { - while (xs < 0) xs += 32; - xs -= 32; - } - ys = (y - up->y) % 32; - if (ys > 0) ys = 0; - else - { - while (ys < 0) ys += 32; - ys -= 32; - } - for (y1 = ys; y1 < hh; y1 += 32) - { - for (x1 = xs; x1 < ww; x1 += 32) - XCopyArea(disp, mask, s_mask, gc, - 0, 0, 32, 32, - x1, y1); - } - XSetClipMask(disp, dr->gc, s_mask); - XSetClipOrigin(disp, dr->gc, xx, yy); - XFreeGC(disp, gc); - } - else - { - XSetClipMask(disp, dr->gc, None); + 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); } - if (pmap) - { - XSetFillStyle(disp, dr->gc, FillTiled); - XSetTile(disp, dr->gc, pmap); - XSetTSOrigin(disp, dr->gc, x - up->x, y - up->y); - } - else - { - XSetFillStyle(disp, dr->gc, FillSolid); - XSetTile(disp, dr->gc, None); - } - XFillRectangle(disp, up->p, dr->gc, x - up->x, y - up->y, w, h); - if (s_mask) XFreePixmap(disp, s_mask); - s_mask = 0; } } } } - if (pmap) imlib_free_pixmap_and_mask(pmap); - if (im) - { - imlib_context_set_image(im); - imlib_free_image(); - } } @@ -527,22 +1150,29 @@ void __evas_x11_rectangle_draw(Display *disp, Imlib_Image dstim, Wi 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 r, int g, int b, int a) + int cr, int cg, int cb, int ca) { Evas_List l; int x, y, w, h; DATA32 pixel; - Imlib_Image im = NULL; - Pixmap pmap = 0, mask = 0, s_mask = 0; - imlib_context_set_color(r, g, b, a); + 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_dither_mask(1); + 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(1); + imlib_context_set_dither(0); imlib_context_set_blend(0); imlib_context_set_angle(0.0); imlib_context_set_operation(IMLIB_OP_COPY); @@ -578,87 +1208,40 @@ void __evas_x11_line_draw(Display *disp, Imlib_Image dstim, Window x, y, w, h)) { if (!up->p) - up->p = XCreatePixmap(disp, win, up->w, up->h, dr->depth); - if (!im) + 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); { - pixel = (a << 24) | (r << 16) | (g << 8) | b; - im = imlib_create_image_using_data(1, 1, &pixel); - imlib_context_set_image(im); - if (a < 255) - imlib_image_set_has_alpha(1); - if (!pmap) - imlib_render_pixmaps_for_whole_image_at_size(&pmap, &mask, - 32, 32); - } - if (a < 255) - { - if (mask) + int xx, yy, ww, hh; + XRectangle rect; + + xx = up->x; + yy = up->y; + ww = up->w; + hh = up->h; + + if (__evas_clip) { - int xx, yy, ww, hh, x1, y1, xs, ys; - GC gc; - XGCValues gcv; - - xx = x - up->x; - yy = y - up->y; - ww = w; - hh = h; - CLIP(xx, yy, ww, hh, 0, 0, up->w, up->h); - s_mask = XCreatePixmap(disp, win, ww, hh, 1); - gc = XCreateGC(disp, s_mask, 0, &gcv); - xs = (x - up->x) % 32; - if (xs > 0) xs = 0; - else - { - while (xs < 0) xs += 32; - xs -= 32; - } - ys = (y - up->y) % 32; - if (ys > 0) ys = 0; - else - { - while (ys < 0) ys += 32; - ys -= 32; - } - for (y1 = ys; y1 < hh; y1 += 32) - { - for (x1 = xs; x1 < ww; x1 += 32) - XCopyArea(disp, mask, s_mask, gc, - 0, 0, 32, 32, - x1, y1); - } - XSetClipMask(disp, dr->gc, s_mask); - XSetClipOrigin(disp, dr->gc, xx, yy); - XFreeGC(disp, gc); - } - else - { - XSetClipMask(disp, dr->gc, None); + 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); } - if (pmap) - { - XSetFillStyle(disp, dr->gc, FillTiled); - XSetTile(disp, dr->gc, pmap); - XSetTSOrigin(disp, dr->gc, x - up->x, y - up->y); - } - else - { - XSetFillStyle(disp, dr->gc, FillSolid); - XSetTile(disp, dr->gc, None); - } - XDrawLine(disp, up->p, dr->gc, x1 - up->x, y1 - up->y, x2 - up->x, y2 - up->y); - if (s_mask) XFreePixmap(disp, s_mask); - s_mask = 0; } } } } - if (pmap) imlib_free_pixmap_and_mask(pmap); - if (im) - { - imlib_context_set_image(im); - imlib_free_image(); - } } @@ -685,22 +1268,40 @@ void __evas_x11_line_draw(Display *disp, Imlib_Image dstim, Window Evas_X11_Graident * __evas_x11_gradient_new(Display *disp) { - return (Evas_X11_Graident *)imlib_create_color_range(); + Evas_X11_Graident *gr; + + gr = malloc(sizeof(Evas_X11_Graident)); + gr->colors = NULL; } void __evas_x11_gradient_free(Evas_X11_Graident *gr) { - imlib_context_set_color_range((Imlib_Color_Range)gr); - imlib_free_color_range(); + 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) { - imlib_context_set_color_range((Imlib_Color_Range)gr); - imlib_context_set_color(r, g, b, a); - imlib_add_color_to_color_range(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 @@ -712,21 +1313,23 @@ __evas_x11_gradient_draw(Evas_X11_Graident *gr, Display *disp, Imlib_Image dstim imlib_context_set_visual(__evas_visual); imlib_context_set_colormap(__evas_cmap); imlib_context_set_drawable(win); - imlib_context_set_dither_mask(1); + imlib_context_set_dither_mask(0); imlib_context_set_anti_alias(0); - imlib_context_set_dither(1); + 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); - imlib_context_set_color_range((Imlib_Color_Range)gr); - for(l = drawable_list; l; l = l->next) + + 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; @@ -736,60 +1339,140 @@ __evas_x11_gradient_draw(Evas_X11_Graident *gr, Display *disp, Imlib_Image dstim 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)) { + int i, p, tot; int xx, yy, ww, hh; - Imlib_Image im = NULL; - Pixmap pmap = 0, mask = 0; + XRectangle rect; + Evas_List l2; - xx = x - up->x; - yy = y - up->y; - ww = w; - hh = h; - CLIP(xx, yy, ww, hh, 0, 0, up->w, up->h); if (!up->p) up->p = XCreatePixmap(disp, win, up->w, up->h, dr->depth); - im = imlib_create_image(ww, hh); - if (im) + + 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) { - DATA32 *data; + 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; - imlib_context_set_image(im); - data = imlib_image_get_data(); - memset(data, 0, ww * hh * sizeof(DATA32)); - imlib_image_put_back_data(data); - imlib_image_set_has_alpha(1); - imlib_image_fill_color_range_rectangle(x - xx - up->x, y - yy - up->y, w, h, angle); - pmap = XCreatePixmap(disp, win, ww, hh, dr->depth); - mask = XCreatePixmap(disp, win, ww, hh, 1); - imlib_context_set_drawable(pmap); - imlib_context_set_mask(mask); - imlib_render_image_on_drawable(0, 0); - imlib_context_set_mask(0); + c1 = l2->data; + if (l2 != gr->colors) tot += c1->dist; } - if (mask) + tot <<= 2; + if ((ww > 1) && (hh > 1)) { - XSetClipMask(disp, dr->gc, mask); - XSetClipOrigin(disp, dr->gc, xx, yy); - } - else - { - XSetClipMask(disp, dr->gc, None); - } - if (pmap) - XCopyArea(disp, pmap, up->p, dr->gc, - 0, 0, - ww, hh, - xx, yy); - if (pmap) XFreePixmap(disp, pmap); - if (mask) XFreePixmap(disp, mask); - if (im) - { - imlib_context_set_image(im); - imlib_free_image(); + 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++; + } + } } } } @@ -814,22 +1497,29 @@ void __evas_x11_poly_draw (Display *disp, Imlib_Image dstim, Window win, int win_w, int win_h, Evas_List points, - int r, int g, int b, int a) + int cr, int cg, int cb, int ca) { Evas_List l, l2; DATA32 pixel; - Imlib_Image im = NULL; - Pixmap pmap = 0, mask = 0, s_mask = 0; int x, y, w, h; - - imlib_context_set_color(r, g, b, a); + + 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_dither_mask(1); + 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(1); + imlib_context_set_dither(0); imlib_context_set_blend(0); imlib_context_set_angle(0.0); imlib_context_set_operation(IMLIB_OP_COPY); @@ -882,82 +1572,38 @@ __evas_x11_poly_draw (Display *disp, Imlib_Image dstim, Window win, 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); - if (!im) - { - pixel = (a << 24) | (r << 16) | (g << 8) | b; - im = imlib_create_image_using_data(1, 1, &pixel); - imlib_context_set_image(im); - if (a < 255) imlib_image_set_has_alpha(1); - if (!pmap) - imlib_render_pixmaps_for_whole_image_at_size(&pmap, &mask, - 32, 32); - } - if (a < 255) - { - if (mask) - { - int xx, yy, ww, hh, x1, y1, xs, ys; - GC gc; - XGCValues gcv; - - xx = x - up->x; - yy = y - up->y; - ww = w; - hh = h; - CLIP(xx, yy, ww, hh, 0, 0, up->w, up->h); - s_mask = XCreatePixmap(disp, win, ww, hh, 1); - gc = XCreateGC(disp, s_mask, 0, &gcv); - xs = (x - up->x) % 32; - if (xs > 0) xs = 0; - else - { - while (xs < 0) xs += 32; - xs -= 32; - } - ys = (y - up->y) % 32; - if (ys > 0) ys = 0; - else - { - while (ys < 0) ys += 32; - ys -= 32; - } - for (y1 = ys; y1 < hh; y1 += 32) - { - for (x1 = xs; x1 < ww; x1 += 32) - XCopyArea(disp, mask, s_mask, gc, - 0, 0, 32, 32, - x1, y1); - } - XSetClipMask(disp, dr->gc, s_mask); - XSetClipOrigin(disp, dr->gc, xx, yy); - XFreeGC(disp, gc); - } - else - { - XSetClipMask(disp, dr->gc, None); - } - } - if (pmap) - { - XSetFillStyle(disp, dr->gc, FillTiled); - XSetTile(disp, dr->gc, pmap); - XSetTSOrigin(disp, dr->gc, x - up->x, y - up->y); - } - else - { - XSetFillStyle(disp, dr->gc, FillSolid); - XSetTile(disp, dr->gc, None); - } + 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)); @@ -970,21 +1616,14 @@ __evas_x11_poly_draw (Display *disp, Imlib_Image dstim, Window win, xpoints[i].y = p->y - up->y; } XFillPolygon(disp, up->p, dr->gc, xpoints, - point_count, Complex, CoordModeOrigin); + point_count, Complex, + CoordModeOrigin); free(xpoints); } - if (s_mask) XFreePixmap(disp, s_mask); - s_mask = 0; } } } } - if (pmap) imlib_free_pixmap_and_mask(pmap); - if (im) - { - imlib_context_set_image(im); - imlib_free_image(); - } } @@ -1000,6 +1639,20 @@ __evas_x11_poly_draw (Display *disp, Imlib_Image dstim, Window win, /* 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) { @@ -1011,8 +1664,6 @@ __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; @@ -1020,6 +1671,8 @@ __evas_x11_flush_draw(Display *disp, Imlib_Image dstim, Window win) 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; @@ -1036,7 +1689,6 @@ __evas_x11_flush_draw(Display *disp, Imlib_Image dstim, Window win) 0, 0, up->w, up->h, up->x, up->y); XFreePixmap(disp, up->p); } - free(up); } if (dr->tmp_images) diff --git a/legacy/evas/src/evas_x11_routines.h b/legacy/evas/src/evas_x11_routines.h index 3c14422b40..3aa71142ca 100644 --- a/legacy/evas/src/evas_x11_routines.h +++ b/legacy/evas/src/evas_x11_routines.h @@ -12,6 +12,12 @@ #include #include +#ifdef HAVE_FREETYPE_FREETYPE_H +#include +#else +#include +#endif + #include "Evas_private.h" #include "Evas.h" @@ -24,12 +30,14 @@ ((SPANS_COMMON((x), (w), (xx), (ww))) && (SPANS_COMMON((y), (h), (yy), (hh)))) #endif -typedef void Evas_X11_Image; -typedef void Evas_X11_Font; -typedef void Evas_X11_Graident; +typedef struct _evas_x11_image Evas_X11_Image; +typedef struct _evas_x11_font Evas_X11_Font; +typedef struct _evas_x11_gradient Evas_X11_Graident; +typedef struct _evas_x11_color Evas_X11_Color; +typedef struct _evas_x11_glyph Evas_X11_Glyph; typedef struct _evas_x11_drawable Evas_X11_Drawable; -typedef struct _evas_x11_update Evas_X11_Update; +typedef struct _evas_x11_update Evas_X11_Update; struct _evas_x11_drawable { @@ -46,6 +54,67 @@ struct _evas_x11_update int x, y, w, h; }; +struct _evas_x11_image +{ + GC gc; + Display *disp; + Window win; + int pw, ph, pr, pg, pb, pa; + Pixmap pmap; + Pixmap mask; + int w, h; + int has_alpha; + char *file; + Imlib_Image image; + int references; +}; + +struct _evas_x11_glyph +{ + int glyph_id; + TT_Glyph glyph; + + TT_Glyph_Metrics metrics; + + int pw, ph; + Pixmap pmap; +}; + +struct _evas_x11_font +{ + char *font; + int size; + + Display *disp; + + TT_Engine engine; + TT_Face face; + TT_Instance instance; + TT_Face_Properties properties; + TT_CharMap char_map; + TT_Instance_Metrics metrics; + + Evas_List glyphs[256]; + + int ascent; + int descent; + int max_descent; + int max_ascent; + + int references; +}; + +struct _evas_x11_gradient +{ + Evas_List colors; +}; + +struct _evas_x11_color +{ + int r, g, b, a; + int dist; +}; + /***************/ /* image stuff */ /***************/ @@ -110,6 +179,7 @@ void __evas_x11_poly_draw (Display *disp, Imlib_Image dstim, Wi /***********/ /* drawing */ /***********/ +void __evas_x11_set_clip_rect(int on, int x, int y, int w, int h, int r, int g, int b, int a); void __evas_x11_init(Display *disp, int screen, int colors); int __evas_x11_capable(Display *disp); void __evas_x11_flush_draw(Display *disp, Imlib_Image dstim, Window win); diff --git a/legacy/evas/test/evas_test.c b/legacy/evas/test/evas_test.c index 95dc0860a3..a68fb1dfd4 100644 --- a/legacy/evas/test/evas_test.c +++ b/legacy/evas/test/evas_test.c @@ -1147,6 +1147,7 @@ animate(double val) fps = (double)framecount / (val - last_time); sprintf(buf, "FPS: %3.2f", fps); + printf("%s\n", buf); evas_set_text(evas_view, o_fps, buf); framecount = -1; last_time = val; diff --git a/legacy/evas/test/evas_test_old.c b/legacy/evas/test/evas_test_old.c index a342d2c315..14b9252e33 100644 --- a/legacy/evas/test/evas_test_old.c +++ b/legacy/evas/test/evas_test_old.c @@ -212,6 +212,25 @@ main(int argc, char **argv) h /= 2; evas_show(e, o[1]); + o_rect = evas_add_rectangle(e); + evas_show(e, o_rect); + evas_move(e, o_rect, 100, 80); + evas_resize(e, o_rect, 120, 120); + evas_set_color(e, o_rect, rand()&0xff, rand()&0xff, rand()&0xff, 200); + evas_set_layer(e, o_rect, 180); + evas_callback_add(e, o_rect, CALLBACK_MOUSE_DOWN, mouse_down, NULL); + evas_callback_add(e, o_rect, CALLBACK_MOUSE_UP, mouse_up, NULL); + evas_callback_add(e, o_rect, CALLBACK_MOUSE_MOVE, mouse_move, NULL); + evas_callback_add(e, o_rect, CALLBACK_MOUSE_IN, mouse_in, NULL); + evas_callback_add(e, o_rect, CALLBACK_MOUSE_OUT, mouse_out, NULL); + + o_rect = evas_add_rectangle(e); + evas_show(e, o_rect); + evas_move(e, o_rect, 200, 100); + evas_resize(e, o_rect, 300, 200); + evas_set_color(e, o_rect, rand()&0xff, rand()&0xff, rand()&0xff, 200); + evas_set_layer(e, o_rect, 150); + for (i = 2 ; i < 120; i++) { o[i] = evas_add_image_from_file(e, IMGDIR"mush.png"); @@ -222,6 +241,7 @@ main(int argc, char **argv) evas_callback_add(e, o[i], CALLBACK_MOUSE_MOVE, mouse_move, NULL); evas_callback_add(e, o[i], CALLBACK_MOUSE_IN, mouse_in, NULL); evas_callback_add(e, o[i], CALLBACK_MOUSE_OUT, mouse_out, NULL); + evas_set_clip(e, o[i], o_rect); } for (i = 120; i < 128; i++) { @@ -235,17 +255,6 @@ main(int argc, char **argv) evas_callback_add(e, o[i], CALLBACK_MOUSE_IN, mouse_in, NULL); evas_callback_add(e, o[i], CALLBACK_MOUSE_OUT, mouse_out, NULL); } - o_rect = evas_add_rectangle(e); - evas_show(e, o_rect); - evas_move(e, o_rect, 100, 100); - evas_resize(e, o_rect, 200, 100); - evas_set_color(e, o_rect, rand()&0xff, rand()&0xff, rand()&0xff, 120); - evas_set_layer(e, o_rect, 150); - evas_callback_add(e, o_rect, CALLBACK_MOUSE_DOWN, mouse_down, NULL); - evas_callback_add(e, o_rect, CALLBACK_MOUSE_UP, mouse_up, NULL); - evas_callback_add(e, o_rect, CALLBACK_MOUSE_MOVE, mouse_move, NULL); - evas_callback_add(e, o_rect, CALLBACK_MOUSE_IN, mouse_in, NULL); - evas_callback_add(e, o_rect, CALLBACK_MOUSE_OUT, mouse_out, NULL); o_poly = evas_add_poly(e); evas_show(e, o_poly); @@ -267,7 +276,7 @@ main(int argc, char **argv) o_line = evas_add_line(e); evas_show(e, o_line); evas_set_line_xy(e, o_line, 10, 20, 100, 50); - evas_set_color(e, o_line, rand()&0xff, rand()&0xff, rand()&0xff, 120); + evas_set_color(e, o_line, rand()&0xff, rand()&0xff, rand()&0xff, 140); evas_set_layer(e, o_rect, 150); evas_callback_add(e, o_line, CALLBACK_MOUSE_DOWN, mouse_down, NULL); evas_callback_add(e, o_line, CALLBACK_MOUSE_UP, mouse_up, NULL); @@ -278,7 +287,7 @@ main(int argc, char **argv) o_grad = evas_add_gradient_box(e); evas_show(e, o_grad); evas_move(e, o_grad, 300, 50); - evas_resize(e, o_grad, 200, 200); + evas_resize(e, o_grad, 300, 300); evas_set_layer(e, o_grad, 150); grad = evas_gradient_new(); evas_gradient_add_color(grad, 255, 255, 255, 255, 8); @@ -291,6 +300,7 @@ main(int argc, char **argv) evas_callback_add(e, o_grad, CALLBACK_MOUSE_MOVE, mouse_move, NULL); evas_callback_add(e, o_grad, CALLBACK_MOUSE_IN, mouse_in, NULL); evas_callback_add(e, o_grad, CALLBACK_MOUSE_OUT, mouse_out, NULL); +/* evas_set_clip(e, o_grad, o_rect);*/ o_text = evas_add_text(e, "grunge", 14, "Click and Drag Objects..."); evas_set_color(e, o_text, 0, 0, 0, 160); @@ -304,7 +314,7 @@ main(int argc, char **argv) evas_callback_add(e, o_text, CALLBACK_MOUSE_OUT, mouse_out, NULL); o_fps = evas_add_text(e, "morpheus", 16, "FPS..."); - evas_set_color(e, o_fps, 255, 255, 255, 120); + evas_set_color(e, o_fps, 255, 255, 255, 140); evas_move(e, o_fps, win_w, win_h); evas_show(e, o_fps); evas_set_layer(e, o_fps, 500); @@ -388,9 +398,9 @@ main(int argc, char **argv) if (i < 100) evas_set_image_file(e, o[i], imgs[(i) & 0x7]); evas_move(e, o[i], x, y); - ww = ((1.2 + cos((double)(a + j + m) * 2 * 3.141592654 / 1000)) * 48); - hh = ww; /* + ww = ((1.2 + cos((double)(a + j + m) * 2 * 3.141592654 / 1000)) * 24); + hh = ww; evas_resize(e, o[i], ww, hh); evas_set_image_fill(e, o[i], 0, 0, ww, hh); evas_set_color(e, o[i], 255, 255, 255,