Split xrdp_bitmap.c into separate files for testing
This commit is contained in:
parent
ee79247110
commit
2c841d0603
@ -43,6 +43,8 @@ xrdp_SOURCES = \
|
||||
xrdp.c \
|
||||
xrdp.h \
|
||||
xrdp_bitmap.c \
|
||||
xrdp_bitmap_load.c \
|
||||
xrdp_bitmap_common.c \
|
||||
xrdp_cache.c \
|
||||
xrdp_encoder.c \
|
||||
xrdp_encoder.h \
|
||||
|
67
xrdp/xrdp.h
67
xrdp/xrdp.h
@ -185,7 +185,7 @@ int
|
||||
xrdp_region_get_rect(struct xrdp_region *self, int index,
|
||||
struct xrdp_rect *rect);
|
||||
|
||||
/* xrdp_bitmap.c */
|
||||
/* xrdp_bitmap_common.c */
|
||||
struct xrdp_bitmap *
|
||||
xrdp_bitmap_create(int width, int height, int bpp,
|
||||
int type, struct xrdp_wm *wm);
|
||||
@ -195,39 +195,8 @@ xrdp_bitmap_create_with_data(int width, int height,
|
||||
struct xrdp_wm *wm);
|
||||
void
|
||||
xrdp_bitmap_delete(struct xrdp_bitmap *self);
|
||||
struct xrdp_bitmap *
|
||||
xrdp_bitmap_get_child_by_id(struct xrdp_bitmap *self, int id);
|
||||
int
|
||||
xrdp_bitmap_set_focus(struct xrdp_bitmap *self, int focused);
|
||||
int
|
||||
xrdp_bitmap_resize(struct xrdp_bitmap *self, int width, int height);
|
||||
/**
|
||||
* Loads a bitmap from a file and (optionally) transforms it
|
||||
*
|
||||
* @param self from rdp_bitmap_create()
|
||||
* @param filename Filename to load
|
||||
* @param[in] palette For 8-bit conversions. Currently unused
|
||||
* @param background Background color for alpha-blending
|
||||
* @param transform Transform to apply to the image after loading
|
||||
* @param twidth target width if transform != XBLT_NONE
|
||||
* @param theight target height if transform != XBLT_NONE
|
||||
* @return 0 for success.
|
||||
*
|
||||
* The background color is only used if the specified image contains
|
||||
* an alpha layer
|
||||
*
|
||||
* After a successful call, the bitmap is resized to the image file size.
|
||||
*
|
||||
* If the call is not successful, the bitmap will be in an indeterminate
|
||||
* state and should not be used.
|
||||
*/
|
||||
int
|
||||
xrdp_bitmap_load(struct xrdp_bitmap *self, const char *filename,
|
||||
const int *palette,
|
||||
int background,
|
||||
enum xrdp_bitmap_load_transform transform,
|
||||
int twidth,
|
||||
int theight);
|
||||
int
|
||||
xrdp_bitmap_get_pixel(struct xrdp_bitmap *self, int x, int y);
|
||||
int
|
||||
@ -236,6 +205,12 @@ int
|
||||
xrdp_bitmap_copy_box(struct xrdp_bitmap *self,
|
||||
struct xrdp_bitmap *dest,
|
||||
int x, int y, int cx, int cy);
|
||||
|
||||
/* xrdp_bitmap.c */
|
||||
struct xrdp_bitmap *
|
||||
xrdp_bitmap_get_child_by_id(struct xrdp_bitmap *self, int id);
|
||||
int
|
||||
xrdp_bitmap_set_focus(struct xrdp_bitmap *self, int focused);
|
||||
int
|
||||
xrdp_bitmap_hash_crc(struct xrdp_bitmap *self);
|
||||
int
|
||||
@ -264,6 +239,34 @@ xrdp_bitmap_get_screen_clip(struct xrdp_bitmap *self,
|
||||
struct xrdp_rect *rect,
|
||||
int *dx, int *dy);
|
||||
|
||||
/* xrdp_bitmap_load.c */
|
||||
/**
|
||||
* Loads a bitmap from a file and (optionally) transforms it
|
||||
*
|
||||
* @param self from rdp_bitmap_create()
|
||||
* @param filename Filename to load
|
||||
* @param[in] palette For 8-bit conversions. Currently unused
|
||||
* @param background Background color for alpha-blending
|
||||
* @param transform Transform to apply to the image after loading
|
||||
* @param twidth target width if transform != XBLT_NONE
|
||||
* @param theight target height if transform != XBLT_NONE
|
||||
* @return 0 for success.
|
||||
*
|
||||
* The background color is only used if the specified image contains
|
||||
* an alpha layer
|
||||
*
|
||||
* After a successful call, the bitmap is resized to the image file size.
|
||||
*
|
||||
* If the call is not successful, the bitmap will be in an indeterminate
|
||||
* state and should not be used.
|
||||
*/
|
||||
int
|
||||
xrdp_bitmap_load(struct xrdp_bitmap *self, const char *filename,
|
||||
const int *palette,
|
||||
int background,
|
||||
enum xrdp_bitmap_load_transform transform,
|
||||
int twidth,
|
||||
int theight);
|
||||
/* xrdp_painter.c */
|
||||
struct xrdp_painter *
|
||||
xrdp_painter_create(struct xrdp_wm *wm, struct xrdp_session *session);
|
||||
|
1048
xrdp/xrdp_bitmap.c
1048
xrdp/xrdp_bitmap.c
File diff suppressed because it is too large
Load Diff
509
xrdp/xrdp_bitmap_common.c
Normal file
509
xrdp/xrdp_bitmap_common.c
Normal file
@ -0,0 +1,509 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2014
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Common bitmap functions for all xrdp_bitmap*.c files
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "xrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Allocate bitmap for specified dimensions, checking for int overflow */
|
||||
static char *
|
||||
alloc_bitmap_data(int width, int height, int Bpp)
|
||||
{
|
||||
char *result = NULL;
|
||||
if (width > 0 && height > 0 && Bpp > 0)
|
||||
{
|
||||
int len = width;
|
||||
/* g_malloc() currently takes an 'int' size */
|
||||
if (len < INT_MAX / height)
|
||||
{
|
||||
len *= height;
|
||||
if (len < INT_MAX / Bpp)
|
||||
{
|
||||
len *= Bpp;
|
||||
result = (char *)malloc(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_bitmap *
|
||||
xrdp_bitmap_create(int width, int height, int bpp,
|
||||
int type, struct xrdp_wm *wm)
|
||||
{
|
||||
struct xrdp_bitmap *self = (struct xrdp_bitmap *)NULL;
|
||||
int Bpp = 0;
|
||||
|
||||
self = (struct xrdp_bitmap *)g_malloc(sizeof(struct xrdp_bitmap), 1);
|
||||
if (self == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_bitmap_create: no memory");
|
||||
return self;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (self->type == WND_TYPE_BITMAP || self->type == WND_TYPE_IMAGE)
|
||||
{
|
||||
self->data = alloc_bitmap_data(width, height, Bpp);
|
||||
if (self->data == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_bitmap_create: size overflow %dx%dx%d",
|
||||
width, height, Bpp);
|
||||
g_free(self);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(XRDP_PAINTER)
|
||||
if (self->type == WND_TYPE_SCREEN) /* noorders */
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_bitmap_create: noorders");
|
||||
self->data = alloc_bitmap_data(width, height, Bpp);
|
||||
if (self->data == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_bitmap_create: size overflow %dx%dx%d",
|
||||
width, height, Bpp);
|
||||
g_free(self);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (self->type != WND_TYPE_BITMAP)
|
||||
{
|
||||
self->child_list = list_create();
|
||||
}
|
||||
|
||||
self->line_size = width * Bpp;
|
||||
|
||||
if (self->type == WND_TYPE_COMBO)
|
||||
{
|
||||
self->string_list = list_create();
|
||||
self->string_list->auto_free = 1;
|
||||
self->data_list = list_create();
|
||||
self->data_list->auto_free = 1;
|
||||
}
|
||||
|
||||
self->wm = wm;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_bitmap *
|
||||
xrdp_bitmap_create_with_data(int width, int height,
|
||||
int bpp, char *data,
|
||||
struct xrdp_wm *wm)
|
||||
{
|
||||
struct xrdp_bitmap *self = (struct xrdp_bitmap *)NULL;
|
||||
int Bpp;
|
||||
#if defined(NEED_ALIGN)
|
||||
tintptr data_as_int;
|
||||
#endif
|
||||
|
||||
self = (struct xrdp_bitmap *)g_malloc(sizeof(struct xrdp_bitmap), 1);
|
||||
self->type = WND_TYPE_BITMAP;
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
self->bpp = bpp;
|
||||
self->wm = wm;
|
||||
|
||||
Bpp = 4;
|
||||
switch (bpp)
|
||||
{
|
||||
case 8:
|
||||
Bpp = 1;
|
||||
break;
|
||||
case 15:
|
||||
Bpp = 2;
|
||||
break;
|
||||
case 16:
|
||||
Bpp = 2;
|
||||
break;
|
||||
}
|
||||
self->line_size = width * Bpp;
|
||||
|
||||
#if defined(NEED_ALIGN)
|
||||
data_as_int = (tintptr) data;
|
||||
if (((bpp >= 24) && (data_as_int & 3)) ||
|
||||
(((bpp == 15) || (bpp == 16)) && (data_as_int & 1)))
|
||||
{
|
||||
/* got to copy data here, it's not aligned
|
||||
other calls in this file assume alignment */
|
||||
self->data = (char *)g_malloc(width * height * Bpp, 0);
|
||||
g_memcpy(self->data, data, width * height * Bpp);
|
||||
return self;
|
||||
}
|
||||
#endif
|
||||
self->data = data;
|
||||
self->do_not_free_data = 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
xrdp_bitmap_delete(struct xrdp_bitmap *self)
|
||||
{
|
||||
int i = 0;
|
||||
struct xrdp_mod_data *mod_data = (struct xrdp_mod_data *)NULL;
|
||||
|
||||
if (self == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->wm != 0)
|
||||
{
|
||||
if (self->wm->focused_window != 0)
|
||||
{
|
||||
if (self->wm->focused_window->focused_control == self)
|
||||
{
|
||||
self->wm->focused_window->focused_control = 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;
|
||||
}
|
||||
|
||||
if (self->wm->popup_wnd == self)
|
||||
{
|
||||
self->wm->popup_wnd = 0;
|
||||
}
|
||||
|
||||
if (self->wm->login_window == self)
|
||||
{
|
||||
self->wm->login_window = 0;
|
||||
}
|
||||
|
||||
if (self->wm->log_wnd == self)
|
||||
{
|
||||
self->wm->log_wnd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->child_list != 0)
|
||||
{
|
||||
for (i = self->child_list->count - 1; i >= 0; i--)
|
||||
{
|
||||
xrdp_bitmap_delete((struct xrdp_bitmap *)self->child_list->items[i]);
|
||||
}
|
||||
|
||||
list_delete(self->child_list);
|
||||
}
|
||||
|
||||
if (self->parent != 0)
|
||||
{
|
||||
i = list_index_of(self->parent->child_list, (long)self);
|
||||
|
||||
if (i >= 0)
|
||||
{
|
||||
list_remove_item(self->parent->child_list, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (self->string_list != 0) /* for combo */
|
||||
{
|
||||
list_delete(self->string_list);
|
||||
}
|
||||
|
||||
if (self->data_list != 0) /* for combo */
|
||||
{
|
||||
for (i = 0; i < self->data_list->count; i++)
|
||||
{
|
||||
mod_data = (struct xrdp_mod_data *)list_get_item(self->data_list, i);
|
||||
|
||||
if (mod_data != 0)
|
||||
{
|
||||
list_delete(mod_data->names);
|
||||
list_delete(mod_data->values);
|
||||
}
|
||||
}
|
||||
|
||||
list_delete(self->data_list);
|
||||
}
|
||||
|
||||
if (!self->do_not_free_data)
|
||||
{
|
||||
g_free(self->data);
|
||||
}
|
||||
|
||||
g_free(self->caption1);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int
|
||||
xrdp_bitmap_resize(struct xrdp_bitmap *self, int width, int height)
|
||||
{
|
||||
int Bpp = 0;
|
||||
|
||||
if ((width == self->width) && (height == self->height))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self->do_not_free_data)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
g_free(self->data);
|
||||
self->data = (char *)g_malloc(width * height * Bpp, 0);
|
||||
self->line_size = width * Bpp;
|
||||
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 GETPIXEL8(self->data, x, y, self->width);
|
||||
}
|
||||
else if (self->bpp == 15 || self->bpp == 16)
|
||||
{
|
||||
return GETPIXEL16(self->data, x, y, self->width);
|
||||
}
|
||||
else if (self->bpp >= 24)
|
||||
{
|
||||
return GETPIXEL32(self->data, x, y, self->width);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
xrdp_bitmap_set_pixel(struct xrdp_bitmap *self, int x, int y, int pixel)
|
||||
{
|
||||
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)
|
||||
{
|
||||
SETPIXEL8(self->data, x, y, self->width, pixel);
|
||||
}
|
||||
else if (self->bpp == 15 || self->bpp == 16)
|
||||
{
|
||||
SETPIXEL16(self->data, x, y, self->width, pixel);
|
||||
}
|
||||
else if (self->bpp >= 24)
|
||||
{
|
||||
SETPIXEL32(self->data, x, y, self->width, pixel);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* copy part of self at x, y to 0, 0 in dest */
|
||||
/* returns error */
|
||||
int
|
||||
xrdp_bitmap_copy_box(struct xrdp_bitmap *self,
|
||||
struct xrdp_bitmap *dest,
|
||||
int x, int y, int cx, int cy)
|
||||
{
|
||||
int i;
|
||||
int destx;
|
||||
int desty;
|
||||
int incs;
|
||||
int incd;
|
||||
tui8 *s8;
|
||||
tui8 *d8;
|
||||
tui16 *s16;
|
||||
tui16 *d16;
|
||||
tui32 *s32;
|
||||
tui32 *d32;
|
||||
|
||||
if (self == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dest == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (self->type != WND_TYPE_BITMAP && self->type != WND_TYPE_IMAGE)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dest->type != WND_TYPE_BITMAP && dest->type != WND_TYPE_IMAGE)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (self->bpp != dest->bpp)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
destx = 0;
|
||||
desty = 0;
|
||||
|
||||
if (!check_bounds(self, &x, &y, &cx, &cy))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!check_bounds(dest, &destx, &desty, &cx, &cy))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (self->bpp >= 24)
|
||||
{
|
||||
s32 = ((tui32 *)(self->data)) + (self->width * y + x);
|
||||
d32 = ((tui32 *)(dest->data)) + (dest->width * desty + destx);
|
||||
incs = self->width - cx;
|
||||
incd = dest->width - cx;
|
||||
|
||||
for (i = 0; i < cy; i++)
|
||||
{
|
||||
g_memcpy(d32, s32, cx * 4);
|
||||
s32 += cx;
|
||||
d32 += cx;
|
||||
|
||||
s32 += incs;
|
||||
d32 += incd;
|
||||
}
|
||||
|
||||
}
|
||||
else if (self->bpp == 15 || self->bpp == 16)
|
||||
{
|
||||
s16 = ((tui16 *)(self->data)) + (self->width * y + x);
|
||||
d16 = ((tui16 *)(dest->data)) + (dest->width * desty + destx);
|
||||
incs = self->width - cx;
|
||||
incd = dest->width - cx;
|
||||
|
||||
for (i = 0; i < cy; i++)
|
||||
{
|
||||
g_memcpy(d16, s16, cx * 2);
|
||||
s16 += cx;
|
||||
d16 += cx;
|
||||
|
||||
s16 += incs;
|
||||
d16 += incd;
|
||||
}
|
||||
}
|
||||
else if (self->bpp == 8)
|
||||
{
|
||||
s8 = ((tui8 *)(self->data)) + (self->width * y + x);
|
||||
d8 = ((tui8 *)(dest->data)) + (dest->width * desty + destx);
|
||||
incs = self->width - cx;
|
||||
incd = dest->width - cx;
|
||||
|
||||
for (i = 0; i < cy; i++)
|
||||
{
|
||||
g_memcpy(d8, s8, cx);
|
||||
s8 += cx;
|
||||
d8 += cx;
|
||||
|
||||
s8 += incs;
|
||||
d8 += incd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
585
xrdp/xrdp_bitmap_load.c
Normal file
585
xrdp/xrdp_bitmap_load.c
Normal file
@ -0,0 +1,585 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2014
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Load xrdp_bitmap from file
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "xrdp.h"
|
||||
#include "log.h"
|
||||
|
||||
/**************************************************************************//**
|
||||
* Private routine to swap pixel data between two pixmaps
|
||||
* @param a First bitmap
|
||||
* @param b Second bitmap
|
||||
*
|
||||
* The main use-case for this routine is to modify an existing bitmap using
|
||||
* the following logic:-
|
||||
* - Create a temporary WND_TYPE_BITMAP
|
||||
* - Process the data in a bitmap in some way, moving it to the temporary
|
||||
* - Call this routine
|
||||
* - Delete the temporary
|
||||
*
|
||||
*/
|
||||
static void
|
||||
swap_pixel_data(struct xrdp_bitmap *a, struct xrdp_bitmap *b)
|
||||
{
|
||||
int tmp_width = a->width;
|
||||
int tmp_height = a->height;
|
||||
int tmp_bpp = a->bpp;
|
||||
int tmp_line_size = a->line_size;
|
||||
char *tmp_data = a->data;
|
||||
int tmp_do_not_free_data = a->do_not_free_data;
|
||||
|
||||
a->width = b->width;
|
||||
a->height = b->height;
|
||||
a->bpp = b->bpp;
|
||||
a->line_size = b->line_size;
|
||||
a->data = b->data;
|
||||
a->do_not_free_data = b->do_not_free_data;
|
||||
|
||||
b->width = tmp_width;
|
||||
b->height = tmp_height;
|
||||
b->bpp = tmp_bpp;
|
||||
b->line_size = tmp_line_size;
|
||||
b->data = tmp_data;
|
||||
b->do_not_free_data = tmp_do_not_free_data;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Scales a bitmap image
|
||||
*
|
||||
* @param self Bitmap to scale
|
||||
* @param target_width target width
|
||||
* @param target_height target height
|
||||
* @return 0 for success
|
||||
*/
|
||||
static int
|
||||
xrdp_bitmap_scale(struct xrdp_bitmap *self, int targ_width, int targ_height)
|
||||
{
|
||||
int src_width = self->width;
|
||||
int src_height = self->height;
|
||||
|
||||
if (src_width != targ_width || src_height != targ_height)
|
||||
{
|
||||
struct xrdp_bitmap *target =
|
||||
xrdp_bitmap_create(targ_width, targ_height,
|
||||
self->bpp, WND_TYPE_BITMAP, 0);
|
||||
int targ_x, targ_y;
|
||||
|
||||
if (target == NULL)
|
||||
{
|
||||
/* Error is logged */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For each pixel in the target pixmap, scale to one in the source */
|
||||
for (targ_x = 0 ; targ_x < targ_width; ++targ_x)
|
||||
{
|
||||
int src_x = targ_x * src_width / targ_width;
|
||||
for (targ_y = 0 ; targ_y < targ_height; ++targ_y)
|
||||
{
|
||||
int src_y = targ_y * src_height / targ_height;
|
||||
int pixel = xrdp_bitmap_get_pixel(self, src_x, src_y);
|
||||
xrdp_bitmap_set_pixel(target, targ_x, targ_y, pixel);
|
||||
}
|
||||
}
|
||||
swap_pixel_data(self, target);
|
||||
xrdp_bitmap_delete(target);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Zooms a bitmap image
|
||||
*
|
||||
* @param self Bitmap to zoom
|
||||
* @param target_width target width
|
||||
* @param target_height target height
|
||||
* @return 0 for success
|
||||
*
|
||||
* This works the same way as a scaled image, but the aspect ratio is
|
||||
* maintained by removing pixels from the top-and-bottom,
|
||||
* or the left-and-right before scaling.
|
||||
*/
|
||||
static int
|
||||
xrdp_bitmap_zoom(struct xrdp_bitmap *self, int targ_width, int targ_height)
|
||||
{
|
||||
int src_width = self->width;
|
||||
int src_height = self->height;
|
||||
double targ_ratio = (double)targ_width / targ_height;
|
||||
double src_ratio = (double)src_width / src_height;
|
||||
|
||||
unsigned int chop_width;
|
||||
unsigned int chop_left_margin;
|
||||
unsigned int chop_height;
|
||||
unsigned int chop_top_margin;
|
||||
|
||||
int result = 0;
|
||||
|
||||
if (src_ratio > targ_ratio)
|
||||
{
|
||||
/* Source is relatively wider than source. Select a box
|
||||
* narrower than the source, but the same height */
|
||||
chop_width = (int)(targ_ratio * src_height + .5);
|
||||
chop_left_margin = (src_width - chop_width) / 2;
|
||||
chop_height = src_height;
|
||||
chop_top_margin = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Source is relatively taller than source (or same shape) */
|
||||
chop_width = src_width;
|
||||
chop_left_margin = 0;
|
||||
chop_height = (int)(src_width / targ_ratio + .5);
|
||||
chop_top_margin = (src_height - chop_height) / 2;
|
||||
}
|
||||
|
||||
/* Only chop the image if there's a need to */
|
||||
if (chop_top_margin != 0 || chop_left_margin != 0)
|
||||
{
|
||||
struct xrdp_bitmap *chopbox;
|
||||
chopbox = xrdp_bitmap_create(chop_width, chop_height, self->bpp,
|
||||
WND_TYPE_BITMAP, 0);
|
||||
if (chopbox == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_bitmap_zoom: no memory");
|
||||
result = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = xrdp_bitmap_copy_box(self, chopbox,
|
||||
chop_left_margin, chop_top_margin,
|
||||
chop_width, chop_height);
|
||||
if (result != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_bitmap_zoom: can't copy box");
|
||||
}
|
||||
else
|
||||
{
|
||||
swap_pixel_data(self, chopbox);
|
||||
}
|
||||
xrdp_bitmap_delete(chopbox);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
result = xrdp_bitmap_scale(self, targ_width, targ_height);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_bitmap_get_index(struct xrdp_bitmap *self, const int *palette, int color)
|
||||
{
|
||||
int r = 0;
|
||||
int g = 0;
|
||||
int b = 0;
|
||||
|
||||
r = (color & 0xff0000) >> 16;
|
||||
g = (color & 0x00ff00) >> 8;
|
||||
b = (color & 0x0000ff) >> 0;
|
||||
r = (r >> 5) << 0;
|
||||
g = (g >> 5) << 3;
|
||||
b = (b >> 6) << 6;
|
||||
return (b | g | r);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* load a bmp file */
|
||||
/* return 0 ok */
|
||||
/* return 1 error */
|
||||
static int
|
||||
xrdp_bitmap_load_bmp(struct xrdp_bitmap *self, const char *filename,
|
||||
const int *palette)
|
||||
{
|
||||
int fd = 0;
|
||||
int len = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int k = 0;
|
||||
int color = 0;
|
||||
int size = 0;
|
||||
int palette1[256];
|
||||
char type1[4];
|
||||
struct xrdp_bmp_header header;
|
||||
struct stream *s = (struct stream *)NULL;
|
||||
|
||||
g_memset(palette1, 0, sizeof(int) * 256);
|
||||
g_memset(type1, 0, sizeof(char) * 4);
|
||||
g_memset(&header, 0, sizeof(struct xrdp_bmp_header));
|
||||
|
||||
if (!g_file_exist(filename))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: error bitmap file [%s] does not exist",
|
||||
__func__, filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd = g_file_open(filename);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: error loading bitmap from file [%s]",
|
||||
__func__, filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* read file type */
|
||||
if (g_file_read(fd, type1, 2) != 2)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: error bitmap file [%s] read error",
|
||||
__func__, filename);
|
||||
g_file_close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((type1[0] != 'B') || (type1[1] != 'M'))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: error bitmap file [%s] not BMP file",
|
||||
__func__, filename);
|
||||
g_file_close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* read file size */
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (g_file_read(fd, s->data, 4) != 4)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: missing length in file %s",
|
||||
__func__, filename);
|
||||
free_stream(s);
|
||||
g_file_close(fd);
|
||||
return 1;
|
||||
}
|
||||
s->end = s->data + 4;
|
||||
in_uint32_le(s, size);
|
||||
/* read bmp header */
|
||||
if (g_file_seek(fd, 14) < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: seek error in file %s",
|
||||
__func__, filename);
|
||||
free_stream(s);
|
||||
g_file_close(fd);
|
||||
return 1;
|
||||
}
|
||||
init_stream(s, 8192);
|
||||
len = g_file_read(fd, s->data, 40); /* size better be 40 */
|
||||
if (len != 40)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: unexpected read length %d in file %s",
|
||||
__func__, len, filename);
|
||||
free_stream(s);
|
||||
g_file_close(fd);
|
||||
return 1;
|
||||
}
|
||||
s->end = s->data + len;
|
||||
in_uint32_le(s, header.size);
|
||||
in_uint32_le(s, header.image_width);
|
||||
in_uint32_le(s, header.image_height);
|
||||
in_uint16_le(s, header.planes);
|
||||
in_uint16_le(s, header.bit_count);
|
||||
in_uint32_le(s, header.compression);
|
||||
in_uint32_le(s, header.image_size);
|
||||
in_uint32_le(s, header.x_pels_per_meter);
|
||||
in_uint32_le(s, header.y_pels_per_meter);
|
||||
in_uint32_le(s, header.clr_used);
|
||||
in_uint32_le(s, header.clr_important);
|
||||
|
||||
if ((header.bit_count != 4) && (header.bit_count != 8) &&
|
||||
(header.bit_count != 24))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: error bitmap file [%s] bad bpp %d",
|
||||
__func__, filename, header.bit_count);
|
||||
free_stream(s);
|
||||
g_file_close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (header.bit_count == 24) /* 24 bit bitmap */
|
||||
{
|
||||
if (g_file_seek(fd, 14 + header.size) < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "%s: seek error in file %s",
|
||||
__func__, filename);
|
||||
}
|
||||
xrdp_bitmap_resize(self, header.image_width, header.image_height);
|
||||
size = header.image_width * header.image_height * 3;
|
||||
init_stream(s, size);
|
||||
/* Pre-fill the buffer, so if we get short reads we're
|
||||
* not working with uninitialised data */
|
||||
g_memset(s->data, 0, size);
|
||||
s->end = s->data + size;
|
||||
|
||||
/* read data */
|
||||
for (i = header.image_height - 1; i >= 0; i--)
|
||||
{
|
||||
size = header.image_width * 3;
|
||||
k = g_file_read(fd, s->data + i * size, size);
|
||||
|
||||
if (k != size)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "%s: error bitmap file [%s] read",
|
||||
__func__, filename);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < self->height; i++)
|
||||
{
|
||||
for (j = 0; j < self->width; j++)
|
||||
{
|
||||
in_uint8(s, k);
|
||||
color = k;
|
||||
in_uint8(s, k);
|
||||
color |= k << 8;
|
||||
in_uint8(s, k);
|
||||
color |= k << 16;
|
||||
|
||||
if (self->bpp == 8)
|
||||
{
|
||||
color = xrdp_bitmap_get_index(self, palette, color);
|
||||
}
|
||||
else if (self->bpp == 15)
|
||||
{
|
||||
color = COLOR15((color & 0xff0000) >> 16,
|
||||
(color & 0x00ff00) >> 8,
|
||||
(color & 0x0000ff) >> 0);
|
||||
}
|
||||
else if (self->bpp == 16)
|
||||
{
|
||||
color = COLOR16((color & 0xff0000) >> 16,
|
||||
(color & 0x00ff00) >> 8,
|
||||
(color & 0x0000ff) >> 0);
|
||||
}
|
||||
|
||||
xrdp_bitmap_set_pixel(self, j, i, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (header.bit_count == 8) /* 8 bit bitmap */
|
||||
{
|
||||
/* read palette */
|
||||
if (g_file_seek(fd, 14 + header.size) < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "%s: seek error in file %s",
|
||||
__func__, filename);
|
||||
}
|
||||
size = header.clr_used * sizeof(int);
|
||||
|
||||
init_stream(s, size);
|
||||
/* Pre-fill the buffer, so if we get short reads we're
|
||||
* not working with uninitialised data */
|
||||
g_memset(s->data, 0, size);
|
||||
s->end = s->data + size;
|
||||
|
||||
len = g_file_read(fd, s->data, size);
|
||||
if (len != size)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: unexpected read length in file %s",
|
||||
__func__, filename);
|
||||
}
|
||||
|
||||
for (i = 0; i < header.clr_used; i++)
|
||||
{
|
||||
in_uint32_le(s, palette1[i]);
|
||||
}
|
||||
|
||||
xrdp_bitmap_resize(self, header.image_width, header.image_height);
|
||||
size = header.image_width * header.image_height;
|
||||
init_stream(s, size);
|
||||
/* Pre-fill the buffer, so if we get short reads we're
|
||||
* not working with uninitialised data */
|
||||
g_memset(s->data, 0, size);
|
||||
s->end = s->data + size;
|
||||
|
||||
/* read data */
|
||||
for (i = header.image_height - 1; i >= 0; i--)
|
||||
{
|
||||
size = header.image_width;
|
||||
k = g_file_read(fd, s->data + i * size, size);
|
||||
|
||||
if (k != size)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "%s: error bitmap file [%s] read",
|
||||
__func__, filename);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < self->height; i++)
|
||||
{
|
||||
for (j = 0; j < self->width; j++)
|
||||
{
|
||||
in_uint8(s, k);
|
||||
color = palette1[k];
|
||||
|
||||
if (self->bpp == 8)
|
||||
{
|
||||
color = xrdp_bitmap_get_index(self, palette, color);
|
||||
}
|
||||
else if (self->bpp == 15)
|
||||
{
|
||||
color = COLOR15((color & 0xff0000) >> 16,
|
||||
(color & 0x00ff00) >> 8,
|
||||
(color & 0x0000ff) >> 0);
|
||||
}
|
||||
else if (self->bpp == 16)
|
||||
{
|
||||
color = COLOR16((color & 0xff0000) >> 16,
|
||||
(color & 0x00ff00) >> 8,
|
||||
(color & 0x0000ff) >> 0);
|
||||
}
|
||||
|
||||
xrdp_bitmap_set_pixel(self, j, i, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (header.bit_count == 4) /* 4 bit bitmap */
|
||||
{
|
||||
/* read palette */
|
||||
if (g_file_seek(fd, 14 + header.size) < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "%s: seek error in file %s",
|
||||
__func__, filename);
|
||||
}
|
||||
size = header.clr_used * sizeof(int);
|
||||
|
||||
init_stream(s, size);
|
||||
/* Pre-fill the buffer, so if we get short reads we're
|
||||
* not working with uninitialised data */
|
||||
g_memset(s->data, 0, size);
|
||||
s->end = s->data + size;
|
||||
|
||||
len = g_file_read(fd, s->data, size);
|
||||
if (len != size)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: unexpected read length in file %s",
|
||||
__func__, filename);
|
||||
}
|
||||
|
||||
for (i = 0; i < header.clr_used; i++)
|
||||
{
|
||||
in_uint32_le(s, palette1[i]);
|
||||
}
|
||||
|
||||
xrdp_bitmap_resize(self, header.image_width, header.image_height);
|
||||
size = (header.image_width * header.image_height) / 2;
|
||||
init_stream(s, size);
|
||||
/* Pre-fill the buffer, so if we get short reads we're
|
||||
* not working with uninitialised data */
|
||||
g_memset(s->data, 0, size);
|
||||
s->end = s->data + size;
|
||||
|
||||
/* read data */
|
||||
for (i = header.image_height - 1; i >= 0; i--)
|
||||
{
|
||||
size = header.image_width / 2;
|
||||
k = g_file_read(fd, s->data + i * size, size);
|
||||
|
||||
if (k != size)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "%s: error bitmap file [%s] read",
|
||||
__func__, filename);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < self->height; i++)
|
||||
{
|
||||
for (j = 0; j < self->width; j++)
|
||||
{
|
||||
if ((j & 1) == 0)
|
||||
{
|
||||
in_uint8(s, k);
|
||||
color = (k >> 4) & 0xf;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = k & 0xf;
|
||||
}
|
||||
|
||||
color = palette1[color];
|
||||
|
||||
if (self->bpp == 8)
|
||||
{
|
||||
color = xrdp_bitmap_get_index(self, palette, color);
|
||||
}
|
||||
else if (self->bpp == 15)
|
||||
{
|
||||
color = COLOR15((color & 0xff0000) >> 16,
|
||||
(color & 0x00ff00) >> 8,
|
||||
(color & 0x0000ff) >> 0);
|
||||
}
|
||||
else if (self->bpp == 16)
|
||||
{
|
||||
color = COLOR16((color & 0xff0000) >> 16,
|
||||
(color & 0x00ff00) >> 8,
|
||||
(color & 0x0000ff) >> 0);
|
||||
}
|
||||
|
||||
xrdp_bitmap_set_pixel(self, j, i, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_file_close(fd);
|
||||
free_stream(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
xrdp_bitmap_load(struct xrdp_bitmap *self, const char *filename,
|
||||
const int *palette,
|
||||
int background,
|
||||
enum xrdp_bitmap_load_transform transform,
|
||||
int twidth,
|
||||
int theight)
|
||||
{
|
||||
/* this is the default bmp-only implementation if a graphics library
|
||||
* isn't built in */
|
||||
|
||||
int result = xrdp_bitmap_load_bmp(self, filename, palette);
|
||||
if (result == 0)
|
||||
{
|
||||
switch (transform)
|
||||
{
|
||||
case XBLT_NONE:
|
||||
break;
|
||||
|
||||
case XBLT_SCALE:
|
||||
result = xrdp_bitmap_scale(self, twidth, theight);
|
||||
break;
|
||||
|
||||
case XBLT_ZOOM:
|
||||
result = xrdp_bitmap_zoom(self, twidth, theight);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(LOG_LEVEL_WARNING, "Invalid bitmap transform %d specified",
|
||||
transform);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
Loading…
Reference in New Issue
Block a user