move around - flatter.
[profile/ivi/evas.git] / src / modules / engines / xrender_x11 / evas_engine_font.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3 #include "evas_engine.h"
4 #include "Evas_Engine_XRender_X11.h"
5
6 static Evas_Hash *_xr_fg_pool = NULL;
7
8 XR_Font_Surface *
9 _xre_font_surface_new(Ximage_Info *xinf, RGBA_Font_Glyph *fg)
10 {    
11    XR_Font_Surface *fs;
12    DATA8 *data;
13    int w, h, j;
14    XRenderPictureAttributes att;
15    XRenderPictFormat *fmt;
16    Ximage_Image  *xim;
17    Evas_Hash *pool;
18    char buf[256], buf2[256];
19    
20    data = fg->glyph_out->bitmap.buffer;
21    w = fg->glyph_out->bitmap.width;
22    h = fg->glyph_out->bitmap.rows;
23    j = fg->glyph_out->bitmap.pitch;
24    if (j < w) j = w;
25    if ((w <= 0) || (h <= 0)) return NULL;
26
27    if (fg->ext_dat)
28      {
29         fs = fg->ext_dat;
30         if ((fs->xinf->disp == xinf->disp) && (fs->xinf->root == xinf->root))
31           return fs;
32         snprintf(buf, sizeof(buf), "@%p@/@%lx@", fs->xinf->disp, fs->xinf->root);
33         pool = evas_hash_find(_xr_fg_pool, buf);
34         if (pool)
35           {
36              snprintf(buf, sizeof(buf), "%p", fg);
37              fs = evas_hash_find(pool, buf);
38              if (fs) return fs;
39           }
40      }
41
42    fs = calloc(1, sizeof(XR_Font_Surface));
43    if (!fs) return NULL;
44
45    fs->xinf = xinf;
46    fs->fg = fg;
47    fs->xinf->references++;
48    fs->w = w;
49    fs->h = h;
50    
51    snprintf(buf, sizeof(buf), "@%p@/@%lx@", fs->xinf->disp, fs->xinf->root);
52    pool = evas_hash_find(_xr_fg_pool, buf);
53    snprintf(buf2, sizeof(buf2), "%p", fg);
54    pool = evas_hash_add(pool, buf2, fs);
55    _xr_fg_pool = evas_hash_add(_xr_fg_pool, buf, pool);
56
57    /* FIXME: maybe use fmt4? */
58    fmt = xinf->fmt8;
59    fs->draw = XCreatePixmap(xinf->disp, xinf->root, w, h,fmt->depth);
60    att.dither = 0;
61    att.component_alpha = 0;
62    att.repeat = 0;
63    fs->pic = XRenderCreatePicture(xinf->disp, fs->draw,fmt, 
64                                   CPRepeat | CPDither | CPComponentAlpha, &att);
65    
66    /* FIXME: handle if fmt->depth != 8 */
67    xim = _xr_image_new(fs->xinf, w, h,fmt->depth);
68    if ((fg->glyph_out->bitmap.num_grays == 256) &&
69        (fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
70      {
71         int x, y;
72         DATA8 *p1, *p2;
73         
74         for (y = 0; y < h; y++)
75           {
76              p1 = data + (j * y);
77              p2 = ((DATA8 *)xim->data) + (xim->line_bytes * y);
78              for (x = 0; x < w; x++)
79                {
80                   *p2 = *p1;
81                   p1++;
82                   p2++;
83                }
84           }
85         
86      }
87    else
88      {
89         DATA8 *tmpbuf = NULL, *dp, *tp, bits;
90         int bi, bj, end;
91         const DATA8 bitrepl[2] = {0x0, 0xff};
92         
93         tmpbuf = alloca(w);
94           {
95              int x, y;
96              DATA8 *p1, *p2;
97              
98              for (y = 0; y < h; y++)
99                {
100                   p1 = tmpbuf;
101                   p2 = ((DATA8 *)xim->data) + (xim->line_bytes * y);
102                   tp = tmpbuf;
103                   dp = data + (y * fg->glyph_out->bitmap.pitch);
104                   for (bi = 0; bi < w; bi += 8)
105                     {
106                        bits = *dp;
107                        if ((w - bi) < 8) end = w - bi;
108                        else end = 8;
109                        for (bj = 0; bj < end; bj++)
110                          {
111                             *tp = bitrepl[(bits >> (7 - bj)) & 0x1];
112                             tp++;
113                          }
114                        dp++;
115                     }
116                   for (x = 0; x < w; x++)
117                     {
118                        *p2 = *p1;
119                        p1++;
120                        p2++;
121                     }
122                }
123           }
124      }
125    _xr_image_put(xim, fs->draw, 0, 0, w, h);
126    return fs;
127 }
128
129 static Evas_Bool
130 _xre_font_pool_cb(const Evas_Hash *hash, const char *key, void *data, void *fdata)
131 {
132    Evas_Hash *pool;
133    XR_Font_Surface *fs;
134    char buf[256];
135    
136    fs = fdata;
137    pool = data;
138    snprintf(buf, sizeof(buf), "@%p@/@%lx@", fs->xinf->disp, fs->xinf->root);
139    pool = evas_hash_del(pool, buf, fs);
140    hash = evas_hash_modify(hash, key, pool);
141    return 1;
142 }
143
144 void
145 _xre_font_surface_free(XR_Font_Surface *fs)
146 {
147    if (!fs) return;
148    evas_hash_foreach(_xr_fg_pool, _xre_font_pool_cb, fs);
149    XFreePixmap(fs->xinf->disp, fs->draw);
150    XRenderFreePicture(fs->xinf->disp, fs->pic);
151    _xr_image_info_free(fs->xinf);
152    free(fs);
153 }
154
155 void
156 _xre_font_surface_draw(Ximage_Info *xinf, RGBA_Image *surface, RGBA_Draw_Context *dc, RGBA_Font_Glyph *fg, int x, int y)
157 {
158    XR_Font_Surface *fs;
159    Xrender_Surface *target_surface;
160    XRectangle rect;
161    int r, g, b, a;
162    
163    fs = fg->ext_dat;
164    if (!fs || !fs->xinf || !dc || !dc->col.col) return;
165    if (!surface || !surface->image.data) return;
166    target_surface = (Xrender_Surface *)(surface->image.data);
167    a = (dc->col.col >> 24) & 0xff;
168    r = (dc->col.col >> 16) & 0xff;
169    g = (dc->col.col >> 8 ) & 0xff;
170    b = (dc->col.col      ) & 0xff;
171    if ((fs->xinf->mul_r != r) || (fs->xinf->mul_g != g) ||
172        (fs->xinf->mul_b != b) || (fs->xinf->mul_a != a))
173      {
174         fs->xinf->mul_r = r;
175         fs->xinf->mul_g = g;
176         fs->xinf->mul_b = b;
177         fs->xinf->mul_a = a;
178         _xr_render_surface_solid_rectangle_set(fs->xinf->mul, r, g, b, a, 0, 0, 1, 1);
179      }
180    rect.x = x; rect.y = y; rect.width = fs->w; rect.height = fs->h;
181    if (dc->clip.use)
182      {
183         RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.width, rect.height,
184                            dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
185      }
186    XRenderSetPictureClipRectangles(target_surface->xinf->disp, 
187                                    target_surface->pic, 0, 0, &rect, 1);
188    XRenderComposite(fs->xinf->disp, PictOpOver, fs->xinf->mul->pic, 
189                     fs->pic, target_surface->pic,
190                     0, 0, 0, 0, x, y, fs->w, fs->h);
191 }