summaryrefslogtreecommitdiffstats
path: root/xrdp/xrdp_bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'xrdp/xrdp_bitmap.c')
-rw-r--r--xrdp/xrdp_bitmap.c479
1 files changed, 479 insertions, 0 deletions
diff --git a/xrdp/xrdp_bitmap.c b/xrdp/xrdp_bitmap.c
new file mode 100644
index 00000000..2f965a2f
--- /dev/null
+++ b/xrdp/xrdp_bitmap.c
@@ -0,0 +1,479 @@
+
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Copyright (C) Jay Sorg 2004
+
+ bitmap, drawable
+
+*/
+
+#include "xrdp.h"
+
+/*****************************************************************************/
+struct xrdp_bitmap* xrdp_bitmap_create(int width, int height, int bpp,
+ int type)
+{
+ struct xrdp_bitmap* self;
+ int Bpp;
+
+ self = (struct xrdp_bitmap*)g_malloc(sizeof(struct xrdp_bitmap), 1);
+ self->type = type;
+ self->width = width;
+ self->height = height;
+ self->bpp = bpp;
+ Bpp = 4;
+ switch (bpp)
+ {
+ case 8: Bpp = 1; break;
+ case 15: Bpp = 2; break;
+ case 16: Bpp = 2; break;
+ }
+ self->data = (char*)g_malloc(width * height * Bpp, 1);
+ self->child_list = xrdp_list_create();
+ self->line_size = ((width + 3) & ~3) * Bpp;
+ return self;
+}
+
+/*****************************************************************************/
+void xrdp_bitmap_delete(struct xrdp_bitmap* self)
+{
+ int i;
+
+ if (self == 0)
+ return;
+ if (self->wm != 0)
+ {
+ if (self->wm->focused_window == self)
+ self->wm->focused_window = 0;
+ if (self->wm->dragging_window == self)
+ self->wm->dragging_window = 0;
+ if (self->wm->button_down == self)
+ self->wm->button_down = 0;
+ }
+ for (i = 0; i < self->child_list->count; i++)
+ xrdp_bitmap_delete((struct xrdp_bitmap*)self->child_list->items[i]);
+ xrdp_list_delete(self->child_list);
+ g_free(self->data);
+ g_free(self);
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_set_focus(struct xrdp_bitmap* self, int focused)
+{
+ struct xrdp_painter* painter;
+
+ if (self == 0)
+ return 0;
+ if (self->type != 1)
+ return 0;
+ self->focused = focused;
+ painter = xrdp_painter_create(self->wm);
+ xrdp_painter_begin_update(painter);
+ if (focused)
+ {
+ /* active title bar */
+ painter->fg_color = self->wm->blue;
+ xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+ }
+ else
+ {
+ /* inactive title bar */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+ }
+ DEBUG(("1\n\r"));
+ xrdp_painter_end_update(painter);
+ DEBUG(("2\n\r"));
+ xrdp_painter_delete(painter);
+ DEBUG(("3\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_get_index(struct xrdp_bitmap* self, int* palette, int color)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ {
+ if (color == palette[i])
+ return i;
+ }
+ for (i = 1; i < 256; i++)
+ {
+ if (palette[i] == 0)
+ {
+ palette[i] = color;
+ return i;
+ }
+ }
+ g_printf("color %8.8x not found\n", color);
+ return 255;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_resize(struct xrdp_bitmap* self, int width, int height)
+{
+ int Bpp;
+
+ g_free(self->data);
+ self->width = width;
+ self->height = height;
+ Bpp = 4;
+ switch (self->bpp)
+ {
+ case 8: Bpp = 1; break;
+ case 15: Bpp = 2; break;
+ case 16: Bpp = 2; break;
+ }
+ self->data = (char*)g_malloc(width * height * Bpp, 1);
+ self->line_size = ((width + 3) & ~3) * Bpp;
+ return 0;
+}
+
+/*****************************************************************************/
+/* load a bmp file */
+/* return 0 ok */
+/* return 1 error */
+int xrdp_bitmap_load(struct xrdp_bitmap* self, char* filename, int* palette)
+{
+ int fd;
+ int i;
+ int j;
+ int k;
+ int color;
+ int size;
+ int palette1[256];
+ char type1[3];
+ char* data;
+ struct xrdp_bmp_header header;
+
+ fd = g_file_open(filename);
+ if (fd != -1)
+ {
+ /* read file type */
+ if (g_file_read(fd, type1, 2) != 2)
+ {
+ g_file_close(fd);
+ return 1;
+ }
+ if (type1[0] != 'B' || type1[1] != 'M')
+ {
+ g_file_close(fd);
+ return 1;
+ }
+ /* read file size */
+ size = 0;
+ g_file_read(fd, (char*)&size, 4);
+ /* read bmp header */
+ g_file_seek(fd, 14);
+ g_file_read(fd, (char*)&header, sizeof(header));
+ if (header.bit_count != 8 && header.bit_count != 24)
+ {
+ g_file_close(fd);
+ return 1;
+ }
+ if (header.bit_count == 24) /* 24 bit bitmap */
+ {
+ g_file_seek(fd, 14 + header.size);
+ }
+ if (header.bit_count == 8) /* 8 bit bitmap */
+ {
+ /* read palette */
+ g_file_seek(fd, 14 + header.size);
+ g_file_read(fd, (char*)palette1, 256 * sizeof(int));
+ /* read data */
+ xrdp_bitmap_resize(self, header.image_width, header.image_height);
+ data = (char*)g_malloc(header.image_width * header.image_height, 1);
+ for (i = header.image_height - 1; i >= 0; i--)
+ g_file_read(fd, data + i * header.image_width, header.image_width);
+ for (i = 0; i < self->height; i++)
+ {
+ for (j = 0; j < self->width; j++)
+ {
+ k = (unsigned char)data[i * header.image_width + j];
+ color = palette1[k];
+ if (self->bpp == 8)
+ color = xrdp_bitmap_get_index(self, palette, color);
+ else if (self->bpp == 15)
+ color = xrdp_wm_color15((color & 0xff0000) >> 16,
+ (color & 0x00ff00) >> 8,
+ (color & 0x0000ff) >> 0);
+ else if (self->bpp == 16)
+ color = xrdp_wm_color16((color & 0xff0000) >> 16,
+ (color & 0x00ff00) >> 8,
+ (color & 0x0000ff) >> 0);
+ else if (self->bpp == 24)
+ color = xrdp_wm_color24((color & 0xff0000) >> 16,
+ (color & 0x00ff00) >> 8,
+ (color & 0x0000ff) >> 0);
+ xrdp_bitmap_set_pixel(self, j, i, color);
+ }
+ }
+ g_free(data);
+ }
+ g_file_close(fd);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_get_pixel(struct xrdp_bitmap* self, int x, int y)
+{
+ if (self == 0)
+ return 0;
+ if (self->data == 0)
+ return 0;
+ if (x >= 0 && x < self->width && y >= 0 && y < self->height)
+ {
+ if (self->bpp == 8)
+ return self->data[y * self->width + x];
+ else if (self->bpp == 15 || self->bpp == 16)
+ return ((short*)self->data)[y * self->width + x];
+ else if (self->bpp == 24)
+ return ((int*)self->data)[y * self->width + x];
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_set_pixel(struct xrdp_bitmap* self, int x, int y, int pixel)
+{
+ if (x >= 0 && x < self->width && y >= 0 && y < self->height)
+ {
+ if (self->bpp == 8)
+ self->data[y * self->width + x] = pixel;
+ else if (self->bpp == 15 || self->bpp == 16)
+ ((short*)(self->data))[y * self->width + x] = pixel;
+ else if (self->bpp == 24)
+ ((int*)(self->data))[y * self->width + x] = pixel;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_copy_box(struct xrdp_bitmap* self, struct xrdp_bitmap* dest,
+ int x, int y, int cx, int cy)
+{
+ int i;
+ int j;
+
+ if (self == 0)
+ return 0;
+ if (dest == 0)
+ return 0;
+ if (self->bpp != dest->bpp)
+ return 0;
+ for (i = 0; i < cy; i++)
+ {
+ for (j = 0; j < cx; j++)
+ {
+ xrdp_bitmap_set_pixel(dest, j, i,
+ xrdp_bitmap_get_pixel(self, j + x, i + y));
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_compare(struct xrdp_bitmap* self, struct xrdp_bitmap* b)
+{
+ if (self == 0)
+ return 0;
+ if (b == 0)
+ return 0;
+ if (self->bpp != b->bpp)
+ return 0;
+ if (self->width != b->width)
+ return 0;
+ if (self->height != b->height)
+ return 0;
+ if (g_memcmp(self->data, b->data, b->height * b->line_size) == 0)
+ return 1;
+ return 0;
+}
+
+/*****************************************************************************/
+/* nil for rect means the whole thing */
+int xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect)
+{
+ int i;
+ struct xrdp_bitmap* b;
+ struct xrdp_rect r1;
+ struct xrdp_rect r2;
+ struct xrdp_painter* painter;
+
+ if (self == 0) /* if no bitmap */
+ return 0;
+ if (self->type == 0) /* if bitmap, leave */
+ return 0;
+ painter = xrdp_painter_create(self->wm);
+ painter->rop = 0xcc; /* copy */
+ if (rect == 0)
+ painter->use_clip = 0;
+ else
+ {
+ if (xrdp_wm_rect_is_empty(rect))
+ {
+ xrdp_painter_delete(painter);
+ return 0;
+ }
+ painter->clip = *rect;
+ painter->use_clip = 1;
+ }
+ xrdp_painter_begin_update(painter);
+ if (self->type == 1) /* normal window */
+ {
+ /* draw grey background */
+ painter->fg_color = self->bg_color;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
+ /* top white line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
+ /* left white line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
+ /* bottom dark grey line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 1, self->height - 2,
+ self->width - 2, 1);
+ /* right dark grey line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, self->width - 2, 1, 1,
+ self->height - 2);
+ /* bottom black line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 0, self->height - 1,
+ self->width, 1);
+ /* right black line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, self->width - 1, 0,
+ 1, self->height);
+ if (self->focused)
+ {
+ /* active title bar */
+ painter->fg_color = self->wm->blue;
+ xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+ }
+ else
+ {
+ /* inactive title bar */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+ }
+ }
+ else if (self->type == 2) /* screen */
+ {
+ painter->fg_color = self->bg_color;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
+ }
+ else if (self->type == 3) /* button */
+ {
+ if (self->state == 0) /* button up */
+ {
+ /* gray box */
+ painter->fg_color = self->wm->grey;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
+ /* white top line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
+ /* white left line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
+ /* dark grey bottom line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 1, self->height - 2,
+ self->width - 1, 1);
+ /* dark grey right line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, self->width - 2, 1,
+ 1, self->height - 1);
+ /* black bottom line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 0, self->height - 1, self->width, 1);
+ /* black right line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, self->width - 1, 0, 1, self->height);
+ }
+ else if (self->state == 1) /* button down */
+ {
+ /* black top line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
+ /* black left line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
+ /* dark grey top line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
+ /* dark grey left line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
+ }
+ }
+ else if (self->type == 4) /* image */
+ {
+ xrdp_painter_draw_bitmap(painter, self, self, 0, 0, self->width,
+ self->height);
+ }
+ else if (self->type == 5) /* edit */
+ {
+ /* draw gray box */
+ painter->fg_color = self->wm->grey;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
+ /* main white background */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 3,
+ self->height - 3);
+ /* dark grey top line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
+ /* dark grey left line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
+ /* white bottom line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 0, self->height- 1, self->width, 1);
+ /* white right line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, self->width - 1, 0, 1, self->height);
+ /* black left line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
+ /* black top line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
+ }
+ /* draw any child windows in the area */
+ for (i = 0; i < self->child_list->count; i++)
+ {
+ b = (struct xrdp_bitmap*)xrdp_list_get_item(self->child_list, i);
+ if (rect == 0)
+ xrdp_bitmap_invalidate(b, 0);
+ else
+ {
+ xrdp_wm_rect(&r1, b->left, b->top, b->width, b->height);
+ if (xrdp_wm_rect_intersect(rect, &r1, &r2))
+ {
+ xrdp_wm_rect_offset(&r2, -(b->left), -(b->top));
+ xrdp_bitmap_invalidate(b, &r2);
+ }
+ }
+ }
+ xrdp_painter_end_update(painter);
+ xrdp_painter_delete(painter);
+ return 0;
+}