2000-08-01 21:01:18 -07:00
|
|
|
#include "evas_gl_routines.h"
|
2000-08-06 17:50:40 -07:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
2000-08-01 20:33:11 -07:00
|
|
|
|
|
|
|
static int __evas_gl_configuration[] =
|
|
|
|
{
|
|
|
|
GLX_DOUBLEBUFFER,
|
|
|
|
GLX_RGBA,
|
|
|
|
GLX_RED_SIZE, 1,
|
|
|
|
GLX_GREEN_SIZE, 1,
|
|
|
|
GLX_BLUE_SIZE, 1,
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
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_destroy(Evas_GL_Image *im);
|
2000-08-05 19:06:24 -07:00
|
|
|
static void __evas_gl_image_cache_flush(Display *disp);
|
2000-08-05 13:11:27 -07:00
|
|
|
|
2000-08-09 21:20:29 -07:00
|
|
|
static void __evas_gl_text_font_render_textures(Evas_GL_Font *f);
|
2000-08-06 14:19:37 -07:00
|
|
|
static TT_Raster_Map *__evas_gl_text_font_raster_new(int width, int height);
|
2000-08-09 21:20:29 -07:00
|
|
|
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);
|
2000-08-06 14:19:37 -07:00
|
|
|
|
|
|
|
|
2000-08-05 13:11:27 -07:00
|
|
|
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;
|
|
|
|
|
2000-08-06 17:50:40 -07:00
|
|
|
static Display *__evas_current_disp = NULL;
|
|
|
|
static Window __evas_current_win = 0;
|
|
|
|
|
2000-08-06 14:19:37 -07:00
|
|
|
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;
|
|
|
|
|
2000-08-10 15:12:42 -07:00
|
|
|
static int __evas_anti_alias = 1;
|
|
|
|
|
2000-08-06 17:50:40 -07:00
|
|
|
const int __evas_rend_lut[9] = { 0, 64, 128, 192, 255, 255, 255, 255, 255};
|
2000-08-06 14:19:37 -07:00
|
|
|
|
|
|
|
#define TT_VALID( handle ) ( ( handle ).z != NULL )
|
2000-08-05 17:26:34 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* image internals ***********************************************************/
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
static void
|
|
|
|
__evas_gl_image_copy_image_rect_to_texture(Evas_GL_Image *im, int x, int y,
|
2000-08-01 20:33:11 -07:00
|
|
|
int w, int h, int tw, int th,
|
|
|
|
GLuint texture)
|
|
|
|
{
|
|
|
|
int tx, ty;
|
|
|
|
DATA32 *data, *p1, *p2;
|
|
|
|
|
|
|
|
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);
|
2000-08-10 15:12:42 -07:00
|
|
|
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
|
|
|
|
{
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
}
|
2000-08-01 20:33:11 -07:00
|
|
|
|
|
|
|
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++)
|
|
|
|
{
|
|
|
|
*p2 =
|
|
|
|
((*p1 & 0xff000000)) |
|
|
|
|
((*p1 & 0x00ff0000) >> 16) |
|
|
|
|
((*p1 & 0x0000ff00)) |
|
|
|
|
((*p1 & 0x000000ff) << 16);
|
|
|
|
p2++; p1++;
|
|
|
|
}
|
2000-08-10 03:14:55 -07:00
|
|
|
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];
|
2000-08-01 20:33:11 -07:00
|
|
|
}
|
2000-08-10 15:12:42 -07:00
|
|
|
if (__evas_anti_alias)
|
|
|
|
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, tw, th, GL_RGBA,
|
|
|
|
GL_UNSIGNED_BYTE, data);
|
|
|
|
else
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tw, th, 0,
|
|
|
|
GL_RGBA, GL_UNSIGNED_BYTE, data);
|
2000-08-01 20:33:11 -07:00
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
static void
|
|
|
|
__evas_gl_image_move_state_data_to_texture(Evas_GL_Image *im)
|
2000-08-01 20:33:11 -07:00
|
|
|
{
|
|
|
|
int i, x, y;
|
2000-08-05 13:11:27 -07:00
|
|
|
int image_data = 0;
|
2000-08-05 17:26:34 -07:00
|
|
|
Imlib_Image image = NULL;
|
2000-08-01 20:33:11 -07:00
|
|
|
|
2000-08-05 13:11:27 -07:00
|
|
|
if ((!im->data) && (im->file))
|
|
|
|
{
|
|
|
|
image = imlib_load_image(im->file);
|
|
|
|
if (image)
|
|
|
|
{
|
|
|
|
imlib_context_set_image(image);
|
|
|
|
im->data = imlib_image_get_data_for_reading_only();
|
|
|
|
image_data = 1;
|
|
|
|
}
|
|
|
|
}
|
2000-08-01 20:33:11 -07:00
|
|
|
if (!im->data) return;
|
2000-08-05 13:11:27 -07:00
|
|
|
|
2000-08-01 20:33:11 -07:00
|
|
|
im->texture.w = im->w / (im->texture.max_size - 2);
|
|
|
|
if (im->w > ((im->texture.max_size - 2) * im->texture.w))
|
|
|
|
{
|
|
|
|
int shift = 0;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2000-08-05 13:11:27 -07:00
|
|
|
if (!__evas_context_window)
|
|
|
|
{
|
2000-08-06 14:19:37 -07:00
|
|
|
XSetWindowAttributes att;
|
2000-08-05 13:11:27 -07:00
|
|
|
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);
|
2000-08-06 17:50:40 -07:00
|
|
|
__evas_current_disp = im->buffer.display;
|
|
|
|
__evas_current_win = im->buffer.window;
|
2000-08-05 13:11:27 -07:00
|
|
|
}
|
|
|
|
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);
|
2000-08-06 17:50:40 -07:00
|
|
|
__evas_current_disp = im->buffer.display;
|
|
|
|
__evas_current_win = im->buffer.window;
|
2000-08-05 13:11:27 -07:00
|
|
|
}
|
2000-08-01 20:33:11 -07:00
|
|
|
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++)
|
|
|
|
{
|
|
|
|
int xx, yy, ww, hh, tw, th;
|
2000-08-10 03:14:55 -07:00
|
|
|
|
2000-08-01 20:33:11 -07:00
|
|
|
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--;
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
__evas_gl_image_copy_image_rect_to_texture(im, xx, yy, ww, hh, tw, th,
|
2000-08-01 20:33:11 -07:00
|
|
|
im->texture.textures[i]);
|
2000-08-05 13:11:27 -07:00
|
|
|
__evas_image_cache_used += (tw * th * 4);
|
2000-08-01 20:33:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* done - set the actual image state to textured */
|
|
|
|
im->state = EVAS_STATE_TEXTURE;
|
2000-08-05 13:11:27 -07:00
|
|
|
if (image_data)
|
|
|
|
{
|
|
|
|
imlib_context_set_image(image);
|
|
|
|
imlib_image_put_back_data(im->data);
|
|
|
|
im->data = NULL;
|
|
|
|
imlib_free_image();
|
|
|
|
}
|
2000-08-01 20:33:11 -07:00
|
|
|
}
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
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)
|
2000-08-01 20:33:11 -07:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
static Evas_GL_Image *
|
2000-08-01 20:33:11 -07:00
|
|
|
__evas_gl_create_image(void)
|
|
|
|
{
|
|
|
|
Evas_GL_Image *im;
|
|
|
|
|
|
|
|
im = malloc(sizeof(Evas_GL_Image));
|
|
|
|
memset(im, 0, sizeof(Evas_GL_Image));
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
static Evas_GL_Image *
|
2000-08-05 13:11:27 -07:00
|
|
|
__evas_gl_image_create_from_file(Display *disp, char *file)
|
2000-08-01 20:33:11 -07:00
|
|
|
{
|
|
|
|
Evas_GL_Image *im;
|
|
|
|
Imlib_Image i;
|
|
|
|
|
2000-08-05 13:11:27 -07:00
|
|
|
if (!file) return NULL;
|
2000-08-01 20:33:11 -07:00
|
|
|
im = __evas_gl_create_image();
|
2000-08-05 13:11:27 -07:00
|
|
|
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;
|
2000-08-01 20:33:11 -07:00
|
|
|
im->texture.max_size = 256;
|
2000-08-05 13:11:27 -07:00
|
|
|
im->texture.w = 0;
|
|
|
|
im->texture.h = 0;
|
|
|
|
im->texture.edge_w = 0;
|
|
|
|
im->texture.edge_h = 0;
|
|
|
|
im->texture.textures = NULL;
|
|
|
|
|
2000-08-01 20:33:11 -07:00
|
|
|
im->context = __evas_gl_cx;
|
|
|
|
im->buffer.display = disp;
|
2000-08-05 19:06:24 -07:00
|
|
|
im->buffer.colormap = __evas_gl_get_colormap(disp, 0);
|
2000-08-01 20:33:11 -07:00
|
|
|
im->buffer.visual_info = __evas_vi;
|
2000-08-05 13:11:27 -07:00
|
|
|
im->buffer.window = 0;
|
|
|
|
im->buffer.dest = 0;
|
|
|
|
im->buffer.dest_w = 0;
|
|
|
|
im->buffer.dest_h = 0;
|
|
|
|
|
|
|
|
im->references = 1;
|
|
|
|
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
static void
|
|
|
|
__evas_gl_image_destroy(Evas_GL_Image *im)
|
|
|
|
{
|
|
|
|
if (im->file) free(im->file);
|
|
|
|
if (im->data) free(im->data);
|
|
|
|
if (im->texture.textures)
|
|
|
|
{
|
|
|
|
glDeleteTextures(im->texture.w * im->texture.h, im->texture.textures);
|
|
|
|
free(im->texture.textures);
|
|
|
|
}
|
|
|
|
free(im);
|
|
|
|
}
|
|
|
|
|
2000-08-05 19:06:24 -07:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
__evas_images = evas_list_remove(__evas_images, im_last);
|
|
|
|
__evas_gl_image_destroy(im_last);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
disp = NULL;
|
|
|
|
}
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* image externals ***********************************************************/
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
__evas_gl_image_draw(Evas_GL_Image *im,
|
|
|
|
Display *disp, 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 x, y, i;
|
|
|
|
double dx, dy, dw, dh;
|
2000-08-10 03:14:55 -07:00
|
|
|
|
|
|
|
if ((src_w <= 0) || (src_h <= 0) || (dst_w <= 0) || (dst_h <= 0)) return;
|
2000-08-05 17:26:34 -07:00
|
|
|
if (im->state != EVAS_STATE_TEXTURE)
|
|
|
|
__evas_gl_image_move_state_data_to_texture(im);
|
2000-08-10 03:14:55 -07:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
}
|
|
|
|
|
|
|
|
src_y = im->h - src_h - src_y;
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
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);
|
2000-08-10 03:14:55 -07:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
/* project src and dst rects to overall dest rect */
|
2000-08-06 17:50:40 -07:00
|
|
|
glColor4f(1.0, 1.0, 1.0, 1.0);
|
2000-08-10 03:14:55 -07:00
|
|
|
if ((im->direct) ||
|
|
|
|
((im->bl == 0) && (im->br == 0) && (im->bt == 0) && (im->bb == 0)))
|
2000-08-05 17:26:34 -07:00
|
|
|
{
|
2000-08-10 03:14:55 -07:00
|
|
|
for (y = 0, i = 0; y < im->texture.h; y++)
|
2000-08-05 17:26:34 -07:00
|
|
|
{
|
2000-08-10 03:14:55 -07:00
|
|
|
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]);
|
|
|
|
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();
|
|
|
|
}
|
2000-08-05 17:26:34 -07:00
|
|
|
}
|
|
|
|
}
|
2000-08-10 03:14:55 -07:00
|
|
|
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, w, win_w, win_h,
|
|
|
|
0, 0, bl, bt,
|
|
|
|
dx, dy, bl, bt);
|
|
|
|
__evas_gl_image_draw(im, disp, w, win_w, win_h,
|
|
|
|
bl, 0, im->w - bl - br, bt,
|
|
|
|
dx + bl, dy, dw - bl - br, bt);
|
|
|
|
__evas_gl_image_draw(im, disp, w, win_w, win_h,
|
|
|
|
im->w - br, 0, br, bt,
|
|
|
|
dx + dw - br, dy, br, bt);
|
|
|
|
|
|
|
|
__evas_gl_image_draw(im, disp, w, win_w, win_h,
|
|
|
|
0, bt, bl, im->h - bt - bb,
|
|
|
|
dx, dy + bt, bl, dh - bt - bb);
|
|
|
|
__evas_gl_image_draw(im, disp, 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);
|
|
|
|
__evas_gl_image_draw(im, disp, w, win_w, win_h,
|
|
|
|
im->w - br, bt, br, im->h - bt - bb,
|
|
|
|
dx + dw - br, dy + bt, br, dh - bt - bb);
|
|
|
|
|
|
|
|
__evas_gl_image_draw(im, disp, w, win_w, win_h,
|
|
|
|
0, im->h - bb, bl, bb,
|
|
|
|
dx, dy + dh - bb, bl, bb);
|
|
|
|
__evas_gl_image_draw(im, disp, w, win_w, win_h,
|
|
|
|
bl, im->h - bb, im->w - bl - br, bb,
|
|
|
|
dx + bl, dy + dh - bb, dw - bl - br, bb);
|
|
|
|
__evas_gl_image_draw(im, disp, w, win_w, win_h,
|
|
|
|
im->w - br, im->h - bb, br, bb,
|
|
|
|
dx + dw - br, dy + dh - bb, br, bb);
|
|
|
|
im->direct = 0;
|
|
|
|
}
|
2000-08-05 17:26:34 -07:00
|
|
|
}
|
|
|
|
|
2000-08-05 13:11:27 -07:00
|
|
|
Evas_GL_Image *
|
|
|
|
__evas_gl_image_new_from_file(Display *disp, char *file)
|
|
|
|
{
|
|
|
|
Evas_GL_Image *im;
|
|
|
|
Evas_List l;
|
|
|
|
|
|
|
|
for (l = __evas_images; l; l = l->next)
|
|
|
|
{
|
|
|
|
im = l->data;
|
|
|
|
|
|
|
|
if (((im->file) && (im->buffer.display == disp)) &&
|
|
|
|
(!strcmp(im->file, file)))
|
|
|
|
{
|
|
|
|
if (l != __evas_images)
|
|
|
|
{
|
|
|
|
__evas_images = evas_list_remove(__evas_images, im);
|
|
|
|
__evas_images = evas_list_prepend(__evas_images, im);
|
|
|
|
}
|
|
|
|
im->references++;
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
im = __evas_gl_image_create_from_file(disp, file);
|
|
|
|
__evas_images = evas_list_prepend(__evas_images, im);
|
|
|
|
|
2000-08-01 20:33:11 -07:00
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-08-05 13:11:27 -07:00
|
|
|
__evas_gl_image_free(Evas_GL_Image *im)
|
|
|
|
{
|
|
|
|
im->references--;
|
|
|
|
if (im->references <= 0)
|
|
|
|
__evas_gl_image_cache_flush(im->buffer.display);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__evas_gl_image_cache_empty(Display *disp)
|
|
|
|
{
|
|
|
|
Evas_GL_Image *im = NULL, *im_last;
|
|
|
|
Evas_List l;
|
|
|
|
im_last = (Evas_GL_Image *)1;
|
|
|
|
|
|
|
|
while (im_last)
|
|
|
|
{
|
|
|
|
im_last = NULL;
|
|
|
|
for (l = __evas_images; l; l = l->next)
|
|
|
|
{
|
|
|
|
im = l->data;
|
|
|
|
|
|
|
|
if (im->references <= 0)
|
|
|
|
im_last = im;
|
|
|
|
}
|
|
|
|
if (im_last)
|
|
|
|
{
|
|
|
|
__evas_images = evas_list_remove(__evas_images, im_last);
|
|
|
|
__evas_gl_image_destroy(im_last);
|
|
|
|
}
|
|
|
|
}
|
2000-08-05 17:26:34 -07:00
|
|
|
disp = NULL;
|
2000-08-05 13:11:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__evas_gl_image_cache_set_size(Display *disp, int size)
|
|
|
|
{
|
|
|
|
__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;
|
2000-08-05 17:26:34 -07:00
|
|
|
disp = NULL;
|
|
|
|
}
|
|
|
|
|
2000-08-05 21:53:53 -07:00
|
|
|
int
|
|
|
|
__evas_gl_image_get_width(Evas_GL_Image *im)
|
|
|
|
{
|
|
|
|
return im->w;
|
|
|
|
}
|
2000-08-05 17:26:34 -07:00
|
|
|
|
2000-08-05 21:53:53 -07:00
|
|
|
int
|
|
|
|
__evas_gl_image_get_height(Evas_GL_Image *im)
|
|
|
|
{
|
|
|
|
return im->h;
|
|
|
|
}
|
2000-08-05 17:26:34 -07:00
|
|
|
|
2000-08-10 03:14:55 -07:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2000-08-05 17:26:34 -07:00
|
|
|
|
2000-08-10 15:12:42 -07:00
|
|
|
void
|
|
|
|
__evas_gl_image_set_smooth_scaling(int on)
|
|
|
|
{
|
|
|
|
__evas_anti_alias = on;
|
|
|
|
}
|
2000-08-05 17:26:34 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* font internals ************************************************************/
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
2000-08-06 14:19:37 -07:00
|
|
|
|
2000-08-06 17:50:40 -07:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
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);
|
2000-08-10 03:14:55 -07:00
|
|
|
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;
|
2000-08-06 17:50:40 -07:00
|
|
|
|
|
|
|
__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;
|
|
|
|
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);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-08-06 14:19:37 -07:00
|
|
|
static void
|
|
|
|
__evas_gl_text_font_render_textures(Evas_GL_Font *f)
|
|
|
|
{
|
|
|
|
int i, maxw, maxh, cols, rows, pop, j, k, c, r, x, y;
|
|
|
|
int didlast = 0;
|
|
|
|
unsigned char *data = NULL;
|
|
|
|
|
|
|
|
maxw = 0;
|
|
|
|
maxh = 0;
|
|
|
|
for (i = 0; i < f->num_glyph; i++)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, f->textures[0]);
|
|
|
|
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);
|
2000-08-06 17:50:40 -07:00
|
|
|
for (j = 0, k = 0, i = 0; i < f->num_glyph; i++)
|
2000-08-06 14:19:37 -07:00
|
|
|
{
|
2000-08-06 17:50:40 -07:00
|
|
|
TT_F26Dot6 xmin, ymin, xmax, ymax;
|
|
|
|
int w, h;
|
2000-08-06 14:19:37 -07:00
|
|
|
TT_Raster_Map *rtmp;
|
|
|
|
|
|
|
|
if (TT_VALID(f->glyphs[i]))
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
TT_Get_Glyph_Pixmap(f->glyphs[i], rtmp, -xmin, -ymin);
|
|
|
|
f->glyphinfo[i].texture = f->textures[j];
|
|
|
|
f->glyphinfo[i].px = c * maxw;
|
2000-08-06 17:50:40 -07:00
|
|
|
f->glyphinfo[i].py = r * maxh;
|
2000-08-06 14:19:37 -07:00
|
|
|
f->glyphinfo[i].pw = w;
|
|
|
|
f->glyphinfo[i].ph = h;
|
2000-08-06 17:50:40 -07:00
|
|
|
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);
|
2000-08-06 14:19:37 -07:00
|
|
|
|
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
2000-08-06 17:50:40 -07:00
|
|
|
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;
|
2000-08-06 14:19:37 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
__evas_gl_text_font_raster_free(rtmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
k++;
|
|
|
|
if (k == (cols * rows))
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
k = 0;
|
|
|
|
r = 0;
|
|
|
|
c = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c++;
|
|
|
|
if (c == cols)
|
|
|
|
{
|
|
|
|
c = 0;
|
|
|
|
r++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!didlast)
|
|
|
|
{
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA4, f->max_texture_size, f->max_texture_size, 0,
|
|
|
|
GL_ALPHA, GL_UNSIGNED_BYTE, data);
|
|
|
|
}
|
|
|
|
if (data)
|
|
|
|
{
|
|
|
|
free(data);
|
|
|
|
data = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static TT_Raster_Map *
|
|
|
|
__evas_gl_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_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_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);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
__evas_gl_text_font_path_del(const 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static char **
|
|
|
|
__evas_gl_text_font_path_list(int *num_ret)
|
|
|
|
{
|
|
|
|
*num_ret = __evas_fpath_num;
|
|
|
|
return __evas_fpath;
|
|
|
|
}
|
|
|
|
|
2000-08-06 17:50:40 -07:00
|
|
|
static int
|
|
|
|
__evas_gl_is_file(char *file)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (stat(file, &st) < 0)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2000-08-06 14:19:37 -07:00
|
|
|
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);
|
2000-08-06 17:50:40 -07:00
|
|
|
if (__evas_gl_is_file(tmp))
|
2000-08-06 14:19:37 -07:00
|
|
|
file = strdup(tmp);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(tmp, "%s.TTF", font);
|
2000-08-06 17:50:40 -07:00
|
|
|
if (__evas_gl_is_file(tmp))
|
2000-08-06 14:19:37 -07:00
|
|
|
file = strdup(tmp);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(tmp, "%s", font);
|
2000-08-06 17:50:40 -07:00
|
|
|
if (__evas_gl_is_file(tmp))
|
2000-08-06 14:19:37 -07:00
|
|
|
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);
|
2000-08-06 17:50:40 -07:00
|
|
|
if (__evas_gl_is_file(tmp))
|
2000-08-06 14:19:37 -07:00
|
|
|
file = strdup(tmp);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(tmp, "%s/%s.TTF", __evas_fpath[j], font);
|
2000-08-06 17:50:40 -07:00
|
|
|
if (__evas_gl_is_file(tmp))
|
2000-08-06 14:19:37 -07:00
|
|
|
file = strdup(tmp);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(tmp, "%s/%s", __evas_fpath[j], font);
|
2000-08-06 17:50:40 -07:00
|
|
|
if (__evas_gl_is_file(tmp))
|
2000-08-06 14:19:37 -07:00
|
|
|
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;
|
|
|
|
|
2000-08-06 18:54:22 -07:00
|
|
|
__evas_font_cache_used += 256 * 128 * font->num_textures;
|
2000-08-06 14:19:37 -07:00
|
|
|
/* 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);
|
2000-08-06 18:54:22 -07:00
|
|
|
if (font->textures)
|
|
|
|
{
|
|
|
|
glDeleteTextures(font->num_textures, font->textures);
|
|
|
|
free(font->textures);
|
|
|
|
}
|
2000-08-06 14:19:37 -07:00
|
|
|
/* free font struct & name */
|
|
|
|
free(font->file);
|
|
|
|
free(font);
|
|
|
|
}
|
|
|
|
|
2000-08-06 18:54:22 -07:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-08-06 14:19:37 -07:00
|
|
|
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* font externals ************************************************************/
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
Evas_GL_Font *
|
2000-08-05 19:06:24 -07:00
|
|
|
__evas_gl_text_font_new(Display *disp, char *font, int size)
|
2000-08-05 17:26:34 -07:00
|
|
|
{
|
2000-08-06 14:19:37 -07:00
|
|
|
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))
|
|
|
|
{
|
|
|
|
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);
|
2000-08-06 17:50:40 -07:00
|
|
|
if (!f) return NULL;
|
2000-08-06 14:19:37 -07:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
f->buffer.window = __evas_context_window;
|
|
|
|
glXMakeCurrent(f->buffer.display, f->buffer.window, f->context);
|
|
|
|
}
|
|
|
|
__evas_gl_text_font_render_textures(f);
|
|
|
|
__evas_fonts = evas_list_prepend(__evas_fonts, f);
|
|
|
|
return f;
|
2000-08-05 13:11:27 -07:00
|
|
|
}
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
void
|
|
|
|
__evas_gl_text_font_free(Evas_GL_Font *fn)
|
|
|
|
{
|
2000-08-06 18:54:22 -07:00
|
|
|
fn->references--;
|
|
|
|
if (fn->references == 0)
|
|
|
|
__evas_font_cache_used += 256 * 128 * fn->num_textures;
|
|
|
|
__evas_gl_text_cache_flush();
|
2000-08-05 17:26:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__evas_gl_text_font_add_path(char *path)
|
|
|
|
{
|
2000-08-06 17:50:40 -07:00
|
|
|
__evas_gl_text_font_path_add(path);
|
2000-08-05 17:26:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__evas_gl_text_font_del_path(char *path)
|
|
|
|
{
|
2000-08-06 17:50:40 -07:00
|
|
|
__evas_gl_text_font_path_del(path);
|
2000-08-05 17:26:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
char **
|
|
|
|
__evas_gl_text_font_list_paths(int *count)
|
|
|
|
{
|
2000-08-06 17:50:40 -07:00
|
|
|
return __evas_gl_text_font_path_list(count);
|
2000-08-05 17:26:34 -07:00
|
|
|
}
|
|
|
|
|
2000-08-05 19:06:24 -07:00
|
|
|
void
|
|
|
|
__evas_gl_text_cache_empty(Display *disp)
|
|
|
|
{
|
2000-08-06 18:54:22 -07:00
|
|
|
Evas_List l;
|
|
|
|
Evas_GL_Font *last_f;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2000-08-05 19:06:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__evas_gl_text_cache_set_size(Display *disp, int size)
|
|
|
|
{
|
2000-08-06 18:54:22 -07:00
|
|
|
__evas_font_cache_max = size;
|
|
|
|
__evas_gl_text_cache_flush();
|
2000-08-05 19:06:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
__evas_gl_text_cache_get_size(Display *disp)
|
|
|
|
{
|
2000-08-06 18:54:22 -07:00
|
|
|
return __evas_font_cache_max;
|
2000-08-05 19:06:24 -07:00
|
|
|
}
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
void
|
2000-08-06 17:50:40 -07:00
|
|
|
__evas_gl_text_draw(Evas_GL_Font *fn, Display *disp, Window win,
|
|
|
|
int win_w, int win_h, int x, int y, char *text,
|
|
|
|
int r, int g, int b, int a)
|
2000-08-05 17:26:34 -07:00
|
|
|
{
|
2000-08-06 17:50:40 -07:00
|
|
|
if ((!fn) || (!text)) return;
|
|
|
|
__evas_gl_text_paste(fn, text, disp, win, win_w, win_h, x, y, r, g, b, a);
|
2000-08-05 17:26:34 -07:00
|
|
|
}
|
|
|
|
|
2000-08-06 18:54:22 -07:00
|
|
|
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);
|
|
|
|
}
|
2000-08-05 17:26:34 -07:00
|
|
|
|
2000-08-10 15:12:42 -07:00
|
|
|
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;
|
|
|
|
ppx = 0;
|
|
|
|
px = 0;
|
|
|
|
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);
|
|
|
|
ppx = px;
|
|
|
|
if (i == 0)
|
|
|
|
px += ((-gmetrics.bearingX) / 64);
|
|
|
|
if (text[i + 1] == 0)
|
|
|
|
px += (gmetrics.bbox.xMax / 64);
|
|
|
|
else
|
|
|
|
px += gmetrics.advance / 64;
|
|
|
|
if ((x >= ppx) && (x < px))
|
|
|
|
{
|
|
|
|
if (cx)
|
|
|
|
*cx = ppx;
|
|
|
|
if (cw)
|
|
|
|
*cw = px - ppx;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*cw = 0;
|
|
|
|
*ch = 0;
|
|
|
|
*cx = 0;
|
|
|
|
*cy = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__evas_gl_text_get_character_pos(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;
|
|
|
|
ppx = 0;
|
|
|
|
px = 0;
|
|
|
|
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);
|
|
|
|
ppx = px;
|
|
|
|
if (i == 0)
|
|
|
|
px += ((-gmetrics.bearingX) / 64);
|
|
|
|
if (text[i + 1] == 0)
|
|
|
|
px += (gmetrics.bbox.xMax / 64);
|
|
|
|
else
|
|
|
|
px += gmetrics.advance / 64;
|
|
|
|
if (i == num)
|
|
|
|
{
|
|
|
|
if (cx)
|
|
|
|
*cx = ppx;
|
|
|
|
if (cw)
|
|
|
|
*cw = px - ppx;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*cw = 0;
|
|
|
|
*ch = 0;
|
|
|
|
*cx = 0;
|
|
|
|
*cy = 0;
|
|
|
|
}
|
2000-08-05 17:26:34 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-08-06 20:11:05 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* rectangle externals *******************************************************/
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
void __evas_gl_rectangle_draw(Display *disp, Window win,
|
|
|
|
int win_w, int win_h,
|
|
|
|
int x, int y, int w, int h,
|
|
|
|
int r, int g, int b, int a)
|
|
|
|
{
|
|
|
|
float rr, gg, bb, aa;
|
|
|
|
static int dest_w = 0, dest_h = 0;
|
|
|
|
|
|
|
|
if ((__evas_current_win != win) || (__evas_current_disp != disp))
|
|
|
|
{
|
|
|
|
glXMakeCurrent(disp, win, __evas_gl_cx);
|
|
|
|
__evas_current_disp = disp;
|
|
|
|
__evas_current_win = win;
|
|
|
|
}
|
|
|
|
rr = (float)r / 255;
|
|
|
|
gg = (float)g / 255;
|
|
|
|
bb = (float)b / 255;
|
|
|
|
aa = (float)a / 255;
|
|
|
|
glColor4f(rr, gg, bb, aa);
|
2000-08-10 03:14:55 -07:00
|
|
|
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;
|
2000-08-06 20:11:05 -07:00
|
|
|
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);
|
|
|
|
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glVertex2i(x, y);
|
|
|
|
glVertex2i(x + w, y);
|
|
|
|
glVertex2i(x + w, y + h);
|
|
|
|
glVertex2i(x, y + h);
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* line externals ************************************************************/
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
void __evas_gl_line_draw(Display *disp, Window win,
|
|
|
|
int win_w, int win_h,
|
|
|
|
int x1, int y1, int x2, int y2,
|
|
|
|
int r, int g, int b, int a)
|
|
|
|
{
|
|
|
|
float rr, gg, bb, aa;
|
|
|
|
static int dest_w = 0, dest_h = 0;
|
|
|
|
|
|
|
|
if ((__evas_current_win != win) || (__evas_current_disp != disp))
|
|
|
|
{
|
|
|
|
glXMakeCurrent(disp, win, __evas_gl_cx);
|
|
|
|
__evas_current_disp = disp;
|
|
|
|
__evas_current_win = win;
|
|
|
|
}
|
|
|
|
rr = (float)r / 255;
|
|
|
|
gg = (float)g / 255;
|
|
|
|
bb = (float)b / 255;
|
|
|
|
aa = (float)a / 255;
|
|
|
|
glColor4f(rr, gg, bb, aa);
|
2000-08-10 03:14:55 -07:00
|
|
|
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;
|
|
|
|
|
2000-08-07 18:55:28 -07:00
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2000-08-06 20:11:05 -07:00
|
|
|
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);
|
2000-08-07 18:55:28 -07:00
|
|
|
glEnable(GL_LINE_SMOOTH);
|
2000-08-06 20:11:05 -07:00
|
|
|
|
|
|
|
glBegin(GL_LINES);
|
2000-08-07 18:55:28 -07:00
|
|
|
glVertex2d((double)x1 + 0.5, (double)y1 + 0.5);
|
|
|
|
glVertex2d((double)x2 + 0.5, (double)y2 + 0.5);
|
2000-08-06 20:11:05 -07:00
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-08-09 21:20:29 -07:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* 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)
|
|
|
|
{
|
|
|
|
Evas_GL_Graident_Color *cl;
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
for (j = 0; j < cl2->dist; j++)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
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];
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2000-08-10 03:14:55 -07:00
|
|
|
for (i = ll; i < gr->max_texture_size; i++)
|
|
|
|
{
|
|
|
|
map[j++] = r;
|
|
|
|
map[j++] = g;
|
|
|
|
map[j++] = b;
|
|
|
|
map[j++] = a;
|
|
|
|
}
|
2000-08-09 21:20:29 -07:00
|
|
|
}
|
|
|
|
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);
|
2000-08-10 03:14:55 -07:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gr->max_texture_size, 1, 0,
|
2000-08-09 21:20:29 -07:00
|
|
|
GL_RGBA, GL_UNSIGNED_BYTE, map);
|
|
|
|
gr->texture_w = ll;
|
|
|
|
gr->texture_h = 1;
|
|
|
|
free(pmap);
|
|
|
|
free(map);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* gradient externals ********************************************************/
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
Evas_GL_Graident *
|
|
|
|
__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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__evas_gl_gradient_draw(Evas_GL_Graident *gr,
|
|
|
|
Display *disp, 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];
|
|
|
|
|
|
|
|
|
|
|
|
if (gr->texture_w == 0)
|
|
|
|
__evas_gl_gradient_gen_texture(gr);
|
|
|
|
if ((__evas_current_win != win) || (__evas_current_disp != disp))
|
|
|
|
{
|
|
|
|
glXMakeCurrent(disp, win, __evas_gl_cx);
|
|
|
|
__evas_current_disp = disp;
|
|
|
|
__evas_current_win = win;
|
|
|
|
}
|
|
|
|
glColor4f(1.0, 1.0, 1.0, 1.0);
|
2000-08-10 03:14:55 -07:00
|
|
|
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;
|
|
|
|
|
2000-08-09 21:20:29 -07:00
|
|
|
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);
|
|
|
|
|
|
|
|
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] = (((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();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* general externals *********************************************************/
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
2000-08-05 13:11:27 -07:00
|
|
|
void
|
|
|
|
__evas_gl_sync(Display *disp)
|
2000-08-01 20:33:11 -07:00
|
|
|
{
|
|
|
|
glXWaitGL();
|
|
|
|
XSync(disp, False);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-08-05 13:11:27 -07:00
|
|
|
__evas_gl_flush_draw(Display *disp, Window win)
|
2000-08-01 20:33:11 -07:00
|
|
|
{
|
|
|
|
glXSwapBuffers(disp, win);
|
|
|
|
}
|
|
|
|
|
2000-08-05 17:26:34 -07:00
|
|
|
int
|
|
|
|
__evas_gl_capable(Display *disp)
|
|
|
|
{
|
|
|
|
int eb, evb;
|
|
|
|
return glXQueryExtension(disp, &eb, &evb);
|
|
|
|
}
|
|
|
|
|
|
|
|
Visual *
|
2000-08-05 19:06:24 -07:00
|
|
|
__evas_gl_get_visual(Display *disp, int screen)
|
2000-08-05 17:26:34 -07:00
|
|
|
{
|
|
|
|
static Display *d = NULL;
|
|
|
|
|
|
|
|
if (d != disp)
|
|
|
|
{
|
|
|
|
d = disp;
|
2000-08-05 19:06:24 -07:00
|
|
|
__evas_vi = glXChooseVisual(disp, screen, __evas_gl_configuration);
|
2000-08-05 17:26:34 -07:00
|
|
|
}
|
|
|
|
return __evas_vi->visual;
|
|
|
|
}
|
|
|
|
|
|
|
|
XVisualInfo *
|
2000-08-05 19:06:24 -07:00
|
|
|
__evas_gl_get_visual_info(Display *disp, int screen)
|
2000-08-05 17:26:34 -07:00
|
|
|
{
|
2000-08-05 19:06:24 -07:00
|
|
|
__evas_gl_get_visual(disp, screen);
|
2000-08-05 17:26:34 -07:00
|
|
|
return __evas_vi;
|
|
|
|
}
|
|
|
|
|
|
|
|
Colormap
|
2000-08-05 19:06:24 -07:00
|
|
|
__evas_gl_get_colormap(Display *disp, int screen)
|
2000-08-05 17:26:34 -07:00
|
|
|
{
|
|
|
|
static Display *d = NULL;
|
|
|
|
static Colormap cmap = 0;
|
|
|
|
|
2000-08-05 19:06:24 -07:00
|
|
|
if (!__evas_vi) __evas_gl_get_visual(disp, screen);
|
2000-08-05 17:26:34 -07:00
|
|
|
if (d != disp)
|
|
|
|
{
|
|
|
|
d = disp;
|
2000-08-05 19:06:24 -07:00
|
|
|
cmap = XCreateColormap(disp, RootWindow(disp, screen), __evas_vi->visual, 0);
|
2000-08-05 17:26:34 -07:00
|
|
|
}
|
|
|
|
return cmap;
|
|
|
|
}
|
|
|
|
|
2000-08-01 20:33:11 -07:00
|
|
|
void
|
2000-08-05 23:01:25 -07:00
|
|
|
__evas_gl_init(Display *disp, int screen)
|
2000-08-01 20:33:11 -07:00
|
|
|
{
|
2000-08-05 17:26:34 -07:00
|
|
|
if (__evas_gl_cx) return;
|
|
|
|
|
|
|
|
if (!__evas_gl_capable(disp)) return;
|
2000-08-05 23:01:25 -07:00
|
|
|
__evas_gl_get_visual(disp, screen);
|
2000-08-05 17:26:34 -07:00
|
|
|
/* direct rendering client */
|
|
|
|
__evas_gl_cx = glXCreateContext(disp, __evas_vi, NULL, GL_TRUE);
|
|
|
|
/* GLX indirect */
|
|
|
|
/* __evas_gl_cx = glXCreateContext(disp, __evas_vi, NULL, GL_FALSE);*/
|
2000-08-01 20:33:11 -07:00
|
|
|
}
|
2000-08-05 17:26:34 -07:00
|
|
|
|
2000-08-05 21:53:53 -07:00
|
|
|
void
|
|
|
|
__evas_gl_draw_add_rect(Display *disp, Window win,
|
|
|
|
int x, int y, int w, int h)
|
|
|
|
{
|
2000-08-06 14:19:37 -07:00
|
|
|
return;
|
2000-08-05 21:53:53 -07:00
|
|
|
}
|
|
|
|
|