Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / client / X11 / xf_graphics.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * X11 Graphical Objects
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <X11/Xlib.h>
21 #include <X11/Xutil.h>
22
23 #ifdef WITH_XCURSOR
24 #include <X11/Xcursor/Xcursor.h>
25 #endif
26
27 #include <freerdp/codec/bitmap.h>
28
29 #include "xf_graphics.h"
30
31 /* Bitmap Class */
32
33 void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
34 {
35         uint8* data;
36         Pixmap pixmap;
37         XImage* image;
38         xfInfo* xfi = ((xfContext*) context)->xfi;
39
40         XSetFunction(xfi->display, xfi->gc, GXcopy);
41         pixmap = XCreatePixmap(xfi->display, xfi->drawable, bitmap->width, bitmap->height, xfi->depth);
42
43         if (bitmap->data != NULL)
44         {
45                 data = freerdp_image_convert(bitmap->data, NULL,
46                                 bitmap->width, bitmap->height, bitmap->bpp, xfi->bpp, xfi->clrconv);
47
48                 if (bitmap->ephemeral != true)
49                 {
50                         image = XCreateImage(xfi->display, xfi->visual, xfi->depth,
51                                 ZPixmap, 0, (char*) data, bitmap->width, bitmap->height, xfi->scanline_pad, 0);
52
53                         XPutImage(xfi->display, pixmap, xfi->gc, image, 0, 0, 0, 0, bitmap->width, bitmap->height);
54                         XFree(image);
55
56                         if (data != bitmap->data)
57                                 xfree(data);
58                 }
59                 else
60                 {
61                         if (data != bitmap->data)
62                                 xfree(bitmap->data);
63                         
64                         bitmap->data = data;
65                 }
66         }
67
68         ((xfBitmap*) bitmap)->pixmap = pixmap;
69 }
70
71 void xf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap)
72 {
73         xfInfo* xfi = ((xfContext*) context)->xfi;
74
75         if (((xfBitmap*) bitmap)->pixmap != 0)
76                 XFreePixmap(xfi->display, ((xfBitmap*) bitmap)->pixmap);
77 }
78
79 void xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
80 {
81         XImage* image;
82         int width, height;
83         xfInfo* xfi = ((xfContext*) context)->xfi;
84
85         width = bitmap->right - bitmap->left + 1;
86         height = bitmap->bottom - bitmap->top + 1;
87
88         XSetFunction(xfi->display, xfi->gc, GXcopy);
89
90         image = XCreateImage(xfi->display, xfi->visual, xfi->depth,
91                         ZPixmap, 0, (char*) bitmap->data, bitmap->width, bitmap->height, xfi->scanline_pad, 0);
92
93         XPutImage(xfi->display, xfi->primary, xfi->gc,
94                         image, 0, 0, bitmap->left, bitmap->top, width, height);
95
96         XFree(image);
97
98         if (xfi->remote_app != true)
99         {
100                 XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc,
101                                 bitmap->left, bitmap->top, width, height, bitmap->left, bitmap->top);
102         }
103
104         gdi_InvalidateRegion(xfi->hdc, bitmap->left, bitmap->top, width, height);
105 }
106
107 void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
108                 uint8* data, int width, int height, int bpp, int length, boolean compressed)
109 {
110         uint16 size;
111
112         size = width * height * (bpp + 7) / 8;
113
114         if (bitmap->data == NULL)
115                 bitmap->data = (uint8*) xmalloc(size);
116         else
117                 bitmap->data = (uint8*) xrealloc(bitmap->data, size);
118
119         if (compressed)
120         {
121                 boolean status;
122
123                 status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
124
125                 if (status != true)
126                 {
127                         printf("Bitmap Decompression Failed\n");
128                 }
129         }
130         else
131         {
132                 freerdp_image_flip(data, bitmap->data, width, height, bpp);
133         }
134
135         bitmap->compressed = false;
136         bitmap->length = size;
137         bitmap->bpp = bpp;
138 }
139
140 void xf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, boolean primary)
141 {
142         xfInfo* xfi = ((xfContext*) context)->xfi;
143
144         if (primary)
145                 xfi->drawing = xfi->primary;
146         else
147                 xfi->drawing = ((xfBitmap*) bitmap)->pixmap;
148 }
149
150 /* Pointer Class */
151
152 void xf_Pointer_New(rdpContext* context, rdpPointer* pointer)
153 {
154         XcursorImage ci;
155         xfInfo* xfi = ((xfContext*) context)->xfi;
156
157         memset(&ci, 0, sizeof(ci));
158         ci.version = XCURSOR_IMAGE_VERSION;
159         ci.size = sizeof(ci);
160         ci.width = pointer->width;
161         ci.height = pointer->height;
162         ci.xhot = pointer->xPos;
163         ci.yhot = pointer->yPos;
164         ci.pixels = (XcursorPixel*) malloc(ci.width * ci.height * 4);
165         memset(ci.pixels, 0, ci.width * ci.height * 4);
166
167         if ((pointer->andMaskData != 0) && (pointer->xorMaskData != 0))
168         {
169                 freerdp_alpha_cursor_convert((uint8*) (ci.pixels), pointer->xorMaskData, pointer->andMaskData,
170                                 pointer->width, pointer->height, pointer->xorBpp, xfi->clrconv);
171         }
172
173         ((xfPointer*) pointer)->cursor = XcursorImageLoadCursor(xfi->display, &ci);
174         xfree(ci.pixels);
175 }
176
177 void xf_Pointer_Free(rdpContext* context, rdpPointer* pointer)
178 {
179         xfInfo* xfi = ((xfContext*) context)->xfi;
180
181         if (((xfPointer*) pointer)->cursor != 0)
182                 XFreeCursor(xfi->display, ((xfPointer*) pointer)->cursor);
183 }
184
185 void xf_Pointer_Set(rdpContext* context, rdpPointer* pointer)
186 {
187         xfInfo* xfi = ((xfContext*) context)->xfi;
188
189         /* in RemoteApp mode, window can be null if none has had focus */
190
191         if (xfi->window != NULL)
192                 XDefineCursor(xfi->display, xfi->window->handle, ((xfPointer*) pointer)->cursor);
193 }
194 /* Glyph Class */
195
196 void xf_Glyph_New(rdpContext* context, rdpGlyph* glyph)
197 {
198         xfInfo* xfi;
199         int scanline;
200         XImage* image;
201         xfGlyph* xf_glyph;
202
203         xf_glyph = (xfGlyph*) glyph;
204         xfi = ((xfContext*) context)->xfi;
205
206         scanline = (glyph->cx + 7) / 8;
207
208         xf_glyph->pixmap = XCreatePixmap(xfi->display, xfi->drawing, glyph->cx, glyph->cy, 1);
209
210         image = XCreateImage(xfi->display, xfi->visual, 1,
211                         ZPixmap, 0, (char*) glyph->aj, glyph->cx, glyph->cy, 8, scanline);
212
213         image->byte_order = MSBFirst;
214         image->bitmap_bit_order = MSBFirst;
215
216         XInitImage(image);
217         XPutImage(xfi->display, xf_glyph->pixmap, xfi->gc_mono, image, 0, 0, 0, 0, glyph->cx, glyph->cy);
218         XFree(image);
219 }
220
221 void xf_Glyph_Free(rdpContext* context, rdpGlyph* glyph)
222 {
223         xfInfo* xfi = ((xfContext*) context)->xfi;
224
225         if (((xfGlyph*) glyph)->pixmap != 0)
226                 XFreePixmap(xfi->display, ((xfGlyph*) glyph)->pixmap);
227 }
228
229 void xf_Glyph_Draw(rdpContext* context, rdpGlyph* glyph, int x, int y)
230 {
231         xfGlyph* xf_glyph;
232         xfInfo* xfi = ((xfContext*) context)->xfi;
233
234         xf_glyph = (xfGlyph*) glyph;
235
236         XSetStipple(xfi->display, xfi->gc, xf_glyph->pixmap);
237         XSetTSOrigin(xfi->display, xfi->gc, x, y);
238         XFillRectangle(xfi->display, xfi->drawing, xfi->gc, x, y, glyph->cx, glyph->cy);
239         XSetStipple(xfi->display, xfi->gc, xfi->bitmap_mono);
240 }
241
242 void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor)
243 {
244         xfInfo* xfi = ((xfContext*) context)->xfi;
245
246         bgcolor = (xfi->clrconv->invert)?
247                 freerdp_color_convert_var_bgr(bgcolor, xfi->srcBpp, 32, xfi->clrconv):
248                 freerdp_color_convert_var_rgb(bgcolor, xfi->srcBpp, 32, xfi->clrconv);
249
250         fgcolor = (xfi->clrconv->invert)?
251                 freerdp_color_convert_var_bgr(fgcolor, xfi->srcBpp, 32, xfi->clrconv):
252                 freerdp_color_convert_var_rgb(fgcolor, xfi->srcBpp, 32, xfi->clrconv);
253
254         XSetFunction(xfi->display, xfi->gc, GXcopy);
255         XSetFillStyle(xfi->display, xfi->gc, FillSolid);
256         XSetForeground(xfi->display, xfi->gc, fgcolor);
257         XFillRectangle(xfi->display, xfi->drawing, xfi->gc, x, y, width, height);
258
259         XSetForeground(xfi->display, xfi->gc, bgcolor);
260         XSetBackground(xfi->display, xfi->gc, fgcolor);
261         XSetFillStyle(xfi->display, xfi->gc, FillStippled);
262 }
263
264 void xf_Glyph_EndDraw(rdpContext* context, int x, int y, int width, int height, uint32 bgcolor, uint32 fgcolor)
265 {
266         xfInfo* xfi = ((xfContext*) context)->xfi;
267
268         if (xfi->drawing == xfi->primary)
269         {
270                 if (xfi->remote_app != true)
271                 {
272                         XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc, x, y, width, height, x, y);
273                 }
274
275                 gdi_InvalidateRegion(xfi->hdc, x, y, width, height);
276         }
277 }
278
279 /* Graphics Module */
280
281 void xf_register_graphics(rdpGraphics* graphics)
282 {
283         rdpBitmap* bitmap;
284         rdpPointer* pointer;
285         rdpGlyph* glyph;
286
287         bitmap = xnew(rdpBitmap);
288         bitmap->size = sizeof(xfBitmap);
289
290         bitmap->New = xf_Bitmap_New;
291         bitmap->Free = xf_Bitmap_Free;
292         bitmap->Paint = xf_Bitmap_Paint;
293         bitmap->Decompress = xf_Bitmap_Decompress;
294         bitmap->SetSurface = xf_Bitmap_SetSurface;
295
296         graphics_register_bitmap(graphics, bitmap);
297         xfree(bitmap);
298
299         pointer = xnew(rdpPointer);
300         pointer->size = sizeof(xfPointer);
301
302         pointer->New = xf_Pointer_New;
303         pointer->Free = xf_Pointer_Free;
304         pointer->Set = xf_Pointer_Set;
305
306         graphics_register_pointer(graphics, pointer);
307         xfree(pointer);
308
309         glyph = xnew(rdpGlyph);
310         glyph->size = sizeof(xfGlyph);
311
312         glyph->New = xf_Glyph_New;
313         glyph->Free = xf_Glyph_Free;
314         glyph->Draw = xf_Glyph_Draw;
315         glyph->BeginDraw = xf_Glyph_BeginDraw;
316         glyph->EndDraw = xf_Glyph_EndDraw;
317
318         graphics_register_glyph(graphics, glyph);
319         xfree(glyph);
320 }