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