Merge pull request #1962 from matt335672/imlib2
Add imlib2 support for login screen customisation (#1962)
@ -6,11 +6,11 @@ FreeBSD_task:
|
||||
freebsd_instance:
|
||||
image_family: freebsd-12-2
|
||||
prepare_script:
|
||||
- pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm fusefs-libs check
|
||||
- pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm fusefs-libs check imlib2
|
||||
- git submodule update --init --recursive
|
||||
configure_script:
|
||||
- ./bootstrap
|
||||
- env CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure --localstatedir=/var --enable-strict-locations --with-pkgconfigdir=/usr/local/libdata/pkgconfig --enable-strict-locations --enable-ipv6 --enable-opus --enable-jpeg --enable-fdkaac --enable-painter --enable-pixman --enable-fuse
|
||||
- env CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure --localstatedir=/var --enable-strict-locations --with-pkgconfigdir=/usr/local/libdata/pkgconfig --enable-strict-locations --enable-ipv6 --enable-opus --enable-jpeg --enable-fdkaac --enable-painter --enable-pixman --enable-fuse --with-imlib2
|
||||
build_script:
|
||||
- make -j $(sysctl -n hw.ncpu || echo 4)
|
||||
install_script:
|
||||
|
4
.github/workflows/build.yml
vendored
@ -94,10 +94,10 @@ jobs:
|
||||
--disable-pixman"
|
||||
CONF_FLAGS_amd64_max: "--enable-ipv6 --enable-jpeg --enable-fuse --enable-mp3lame
|
||||
--enable-fdkaac --enable-opus --enable-rfxcodec --enable-painter
|
||||
--enable-pixman"
|
||||
--enable-pixman --with-imlib2"
|
||||
CONF_FLAGS_i386_max: "--enable-ipv6 --enable-jpeg --enable-fuse --enable-mp3lame
|
||||
--enable-fdkaac --enable-opus --enable-rfxcodec --enable-painter
|
||||
--disable-pixman --host=i686-linux"
|
||||
--disable-pixman --with-imlib2 --host=i686-linux"
|
||||
|
||||
PKG_CONFIG_PATH_i386: "/usr/lib/i386-linux-gnu/pkgconfig"
|
||||
CFLAGS_i386: "-m32"
|
||||
|
47
configure.ac
@ -166,6 +166,8 @@ AC_ARG_ENABLE(rdpsndaudin, AS_HELP_STRING([--enable-rdpsndaudin],
|
||||
[], [enable_rdpsndaudin=no])
|
||||
AM_CONDITIONAL(XRDP_RDPSNDAUDIN, [test x$enable_rdpsndaudin = xyes])
|
||||
|
||||
AC_ARG_WITH(imlib2, AC_HELP_STRING([--with-imlib2=ARG], [imlib2 library to use for non-BMP backgrounds (ARG=yes/no/<abs-path>)]),,)
|
||||
|
||||
# Obsolete options
|
||||
AC_ARG_ENABLE(xrdpdebug, AS_HELP_STRING([--enable-xrdpdebug],
|
||||
[This option is no longer supported - use --enable-devel-all]))
|
||||
@ -216,6 +218,44 @@ AC_CHECK_HEADER([security/_pam_types.h],
|
||||
AC_CHECK_HEADER([security/pam_constants.h],
|
||||
[AC_DEFINE([HAVE_PAM_CONSTANTS_H], 1, [Using OpenPAM], [])])
|
||||
|
||||
# Find imlib2
|
||||
case "$with_imlib2" in
|
||||
'' | no) AC_MSG_NOTICE([imlib2 will not be supported])
|
||||
use_imlib2=no
|
||||
;;
|
||||
yes)
|
||||
PKG_CHECK_MODULES([IMLIB2], [imlib2 >= 1.4.10],
|
||||
[use_imlib2=yes],
|
||||
[AC_MSG_ERROR([please install libimlib2-dev or imlib2-devel])])
|
||||
;;
|
||||
/*) AC_MSG_CHECKING([for imlib2 in $with_imlib2])
|
||||
if test -d $with_imlib2/lib; then
|
||||
IMLIB2_LIBS="-L$with_imlib2/lib -lImlib2"
|
||||
elif test -d $with_imlib2/lib64; then
|
||||
IMLIB2_LIBS="-L$with_imlib2/lib64 -lImlib2"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([Can't find libImlib2 in $with_imlib2])
|
||||
fi
|
||||
|
||||
if test -f $with_imlib2/include/Imlib2.h; then
|
||||
IMLIB2_CFLAGS="-I $with_imlib2/include"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([Can't find $with_imlib2/include/Imlib2.h])
|
||||
fi
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_SUBST([IMLIB2_LIBS])
|
||||
AC_SUBST([IMLIB2_CFLAGS])
|
||||
use_imlib2=yes
|
||||
;;
|
||||
*) AC_MSG_ERROR([--with-imlib2 needs yes/no or absolute path])
|
||||
esac
|
||||
|
||||
if test x$use_imlib2 = xyes; then
|
||||
AC_DEFINE([USE_IMLIB2],1, [Compile with imlib2 support])
|
||||
fi
|
||||
|
||||
# Check only one auth mechanism is specified, and give it a name
|
||||
auth_cnt=0
|
||||
auth_mech="Builtin"
|
||||
@ -454,6 +494,7 @@ AC_CONFIG_FILES([
|
||||
tests/Makefile
|
||||
tests/common/Makefile
|
||||
tests/memtest/Makefile
|
||||
tests/xrdp/Makefile
|
||||
tools/Makefile
|
||||
tools/devel/Makefile
|
||||
tools/devel/tcp_proxy/Makefile
|
||||
@ -485,6 +526,12 @@ echo " vsock $enable_vsock"
|
||||
echo " auth mechanism $auth_mech"
|
||||
echo " rdpsndaudin $enable_rdpsndaudin"
|
||||
echo
|
||||
if test x$use_imlib2 = xyes; then
|
||||
echo " with imlib2 yes"
|
||||
else
|
||||
echo " with imlib2 no"
|
||||
fi
|
||||
echo
|
||||
echo " development logging $devel_logging"
|
||||
echo " development streamcheck $devel_streamcheck"
|
||||
echo ""
|
||||
|
@ -50,6 +50,7 @@ in
|
||||
libjpeg-dev \
|
||||
libmp3lame-dev \
|
||||
libfdk-aac-dev \
|
||||
libimlib2-dev \
|
||||
libopus-dev \
|
||||
libpixman-1-dev"
|
||||
;;
|
||||
@ -66,6 +67,7 @@ in
|
||||
libgl1-mesa-dev:i386 \
|
||||
libglu1-mesa-dev:i386 \
|
||||
libjpeg-dev:i386 \
|
||||
libimlib2-dev:i386 \
|
||||
libmp3lame-dev:i386 \
|
||||
libfdk-aac-dev:i386 \
|
||||
libopus-dev:i386 \
|
||||
|
@ -4,4 +4,5 @@ EXTRA_DIST = \
|
||||
|
||||
SUBDIRS = \
|
||||
common \
|
||||
memtest
|
||||
memtest \
|
||||
xrdp
|
||||
|
41
tests/xrdp/Makefile.am
Normal file
@ -0,0 +1,41 @@
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_builddir) \
|
||||
-I$(top_srcdir)/xrdp \
|
||||
-I$(top_srcdir)/libxrdp \
|
||||
-I$(top_srcdir)/common \
|
||||
$(IMLIB2_CFLAGS)
|
||||
|
||||
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
|
||||
$(top_srcdir)/tap-driver.sh
|
||||
|
||||
PACKAGE_STRING="XRDP daemon"
|
||||
|
||||
EXTRA_DIST = \
|
||||
test_4bit.bmp \
|
||||
test_8bit.bmp \
|
||||
test_24bit.bmp \
|
||||
test_not4_4bit.bmp \
|
||||
test_not4_8bit.bmp \
|
||||
test_not4_24bit.bmp \
|
||||
test1.jpg \
|
||||
test_alpha_blend.png
|
||||
|
||||
TESTS = test_xrdp
|
||||
check_PROGRAMS = test_xrdp
|
||||
|
||||
test_xrdp_SOURCES = \
|
||||
test_xrdp.h \
|
||||
test_xrdp_main.c \
|
||||
test_bitmap_load.c
|
||||
|
||||
test_xrdp_CFLAGS = \
|
||||
-D IMAGEDIR=\"$(srcdir)\" \
|
||||
@CHECK_CFLAGS@
|
||||
|
||||
test_xrdp_LDADD = \
|
||||
$(top_builddir)/xrdp/xrdp_bitmap_load.o \
|
||||
$(top_builddir)/xrdp/xrdp_bitmap_common.o \
|
||||
$(top_builddir)/xrdp/funcs.o \
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
$(IMLIB2_LIBS) \
|
||||
@CHECK_LIBS@
|
BIN
tests/xrdp/test1.jpg
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
tests/xrdp/test_24bit.bmp
Normal file
After Width: | Height: | Size: 192 KiB |
BIN
tests/xrdp/test_4bit.bmp
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
tests/xrdp/test_8bit.bmp
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
tests/xrdp/test_alpha_blend.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
337
tests/xrdp/test_bitmap_load.c
Normal file
@ -0,0 +1,337 @@
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config_ac.h"
|
||||
#endif
|
||||
|
||||
#include "test_xrdp.h"
|
||||
#include "xrdp.h"
|
||||
|
||||
/* Where the image files are located */
|
||||
#ifndef IMAGEDIR
|
||||
#define IMAGEDIR "."
|
||||
#endif
|
||||
|
||||
/* Handy color definitions. These are variables so they are displayed
|
||||
* in assert messages if tests fail */
|
||||
static int RED = COLOR24RGB(255, 0, 0);
|
||||
static int GREEN = COLOR24RGB(0, 255, 0);
|
||||
static int BLUE = COLOR24RGB(0, 0, 255);
|
||||
static int WHITE = COLOR24RGB(255, 255, 255);
|
||||
|
||||
/* Virtual desktop maxima and minima [MS-RDPBCGR] 2.2.1.3.6 */
|
||||
#define MAX_VDESKTOP_WIDTH 32766
|
||||
#define MAX_VDESKTOP_HEIGHT 32766
|
||||
#define MIN_VDESKTOP_WIDTH 200
|
||||
#define MIN_VDESKTOP_HEIGHT 200
|
||||
|
||||
/* Characteristics of the test bitmap(s) */
|
||||
#define TEST_BM_WIDTH 256
|
||||
#define TEST_BM_HEIGHT 256
|
||||
|
||||
#define TEST_NOT4_BM_WIDTH 62
|
||||
#define TEST_NOT4_BM_HEIGHT 62
|
||||
|
||||
#define TEST_BM_TOP_LEFT_PIXEL RED
|
||||
#define TEST_BM_TOP_RIGHT_PIXEL GREEN
|
||||
#define TEST_BM_BOTTOM_LEFT_PIXEL BLUE
|
||||
#define TEST_BM_BOTTOM_RIGHT_PIXEL WHITE
|
||||
|
||||
/*
|
||||
* Scaling bitmaps properly will introduce color changes with dithering.
|
||||
* Also some filetypes use compression, and these do not represent colors
|
||||
* perfectly.
|
||||
*
|
||||
* This is the Pythagorean distance we allow between two colors for them to
|
||||
* be considered close enough to each other */
|
||||
#define MAX_SIMILAR_COLOR_DISTANCE 3
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void teardown(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Tests an error is returned for a non-existent file */
|
||||
START_TEST(test_bitmap_load__with_invalid_image__fail)
|
||||
{
|
||||
struct xrdp_wm *wm = NULL;
|
||||
int result;
|
||||
|
||||
struct xrdp_bitmap *bm = xrdp_bitmap_create(4, 4, 32, WND_TYPE_IMAGE, wm);
|
||||
|
||||
ck_assert_ptr_ne(bm, NULL);
|
||||
|
||||
result = xrdp_bitmap_load(bm, "/dev/null", NULL, 0, XBLT_NONE, 0, 0);
|
||||
|
||||
ck_assert_int_ne(result, 0);
|
||||
|
||||
xrdp_bitmap_delete(bm);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Checks a particular pixmap value is expected */
|
||||
static void
|
||||
check_pixel(struct xrdp_bitmap *bm, int i, int j, int expected)
|
||||
{
|
||||
int pixel = xrdp_bitmap_get_pixel(bm, i, j);
|
||||
if (pixel != expected)
|
||||
{
|
||||
ck_abort_msg("Pixmap (%d,%d) expected 0x%06x, got 0x%06x",
|
||||
i, j, expected, pixel);
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculates whether two colors are close enough to be considered the same */
|
||||
static void
|
||||
check_is_close_color(struct xrdp_bitmap *bm, int i, int j, int expected)
|
||||
{
|
||||
int pixel = xrdp_bitmap_get_pixel(bm, i, j);
|
||||
int r1;
|
||||
int g1;
|
||||
int b1;
|
||||
int r2;
|
||||
int g2;
|
||||
int b2;
|
||||
int variance;
|
||||
|
||||
SPLITCOLOR32(r1, g1, b1, pixel);
|
||||
SPLITCOLOR32(r2, g2, b2, expected);
|
||||
|
||||
variance = ((r1 - r2) * (r1 - r2) +
|
||||
(g1 - g2) * (g1 - g2) +
|
||||
(b1 - b2) * (b1 - b2));
|
||||
|
||||
if (variance > MAX_SIMILAR_COLOR_DISTANCE * MAX_SIMILAR_COLOR_DISTANCE)
|
||||
{
|
||||
ck_abort_msg("Pixmap (%d,%d) expected 0x%06x, got 0x%06x"
|
||||
" which exceeds distance of %d",
|
||||
i, j, expected, pixel, MAX_SIMILAR_COLOR_DISTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check we can load images of various depths with various transforms */
|
||||
static void
|
||||
load_and_transform_img(const char *name,
|
||||
enum xrdp_bitmap_load_transform transform,
|
||||
int twidth, int theight)
|
||||
{
|
||||
struct xrdp_wm *wm = NULL;
|
||||
int result;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
char full_name[256];
|
||||
|
||||
struct xrdp_bitmap *bm = xrdp_bitmap_create(4, 4, 32, WND_TYPE_IMAGE, wm);
|
||||
|
||||
ck_assert_ptr_ne(bm, NULL);
|
||||
|
||||
g_snprintf(full_name, sizeof(full_name), IMAGEDIR "/%s", name);
|
||||
result = xrdp_bitmap_load(bm, full_name, NULL, HCOLOR(bm->bpp, WHITE),
|
||||
transform, twidth, theight);
|
||||
|
||||
ck_assert_int_eq(result, 0);
|
||||
|
||||
/* Bitmap right size? */
|
||||
if (transform == XBLT_NONE)
|
||||
{
|
||||
width = TEST_BM_WIDTH;
|
||||
height = TEST_BM_HEIGHT;
|
||||
ck_assert_int_eq(bm->width, TEST_BM_WIDTH);
|
||||
ck_assert_int_eq(bm->height, TEST_BM_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
width = twidth;
|
||||
height = theight;
|
||||
ck_assert_int_eq(bm->width, twidth);
|
||||
ck_assert_int_eq(bm->height, theight);
|
||||
}
|
||||
|
||||
/* Corners OK? Allow for dithering */
|
||||
check_is_close_color(bm, 0, 0, TEST_BM_TOP_LEFT_PIXEL);
|
||||
check_is_close_color(bm, width - 1, 0, TEST_BM_TOP_RIGHT_PIXEL);
|
||||
check_is_close_color(bm, 0, height - 1, TEST_BM_BOTTOM_LEFT_PIXEL);
|
||||
check_is_close_color(bm, width - 1, height - 1, TEST_BM_BOTTOM_RIGHT_PIXEL);
|
||||
|
||||
xrdp_bitmap_delete(bm);
|
||||
}
|
||||
|
||||
/* Check we can load bitmaps that aren't a multiple of 4 pixels wide */
|
||||
static void
|
||||
load_not4_img(const char *name)
|
||||
{
|
||||
struct xrdp_wm *wm = NULL;
|
||||
int result;
|
||||
|
||||
const int width = TEST_NOT4_BM_WIDTH;
|
||||
const int height = TEST_NOT4_BM_HEIGHT;
|
||||
|
||||
char full_name[256];
|
||||
int i;
|
||||
int j;
|
||||
|
||||
struct xrdp_bitmap *bm = xrdp_bitmap_create(4, 4, 32, WND_TYPE_IMAGE, wm);
|
||||
|
||||
ck_assert_ptr_ne(bm, NULL);
|
||||
|
||||
g_snprintf(full_name, sizeof(full_name), IMAGEDIR "/%s", name);
|
||||
result = xrdp_bitmap_load(bm, full_name, NULL, HCOLOR(bm->bpp, WHITE),
|
||||
XBLT_NONE, 0, 0);
|
||||
|
||||
ck_assert_int_eq(result, 0);
|
||||
|
||||
/* Bitmap right size? */
|
||||
ck_assert_int_eq(bm->width, TEST_NOT4_BM_WIDTH);
|
||||
ck_assert_int_eq(bm->height, TEST_NOT4_BM_HEIGHT);
|
||||
|
||||
/* Check all data */
|
||||
for (i = 0 ; i < width / 2 ; ++i)
|
||||
{
|
||||
for (j = 0 ; j < height / 2 ; ++j)
|
||||
{
|
||||
check_pixel(bm, i, j, TEST_BM_TOP_LEFT_PIXEL);
|
||||
check_pixel(bm, i + width / 2, j, TEST_BM_TOP_RIGHT_PIXEL);
|
||||
check_pixel(bm, i, j + height / 2, TEST_BM_BOTTOM_LEFT_PIXEL);
|
||||
check_pixel(bm, i + width / 2, j + height / 2,
|
||||
TEST_BM_BOTTOM_RIGHT_PIXEL);
|
||||
}
|
||||
}
|
||||
|
||||
xrdp_bitmap_delete(bm);
|
||||
}
|
||||
|
||||
START_TEST(test_bitmap_load__4_bit__ok)
|
||||
{
|
||||
load_and_transform_img("test_4bit.bmp", XBLT_NONE, 0, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bitmap_load__8_bit__ok)
|
||||
{
|
||||
load_and_transform_img("test_8bit.bmp", XBLT_NONE, 0, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bitmap_load__24_bit__ok)
|
||||
{
|
||||
load_and_transform_img("test_24bit.bmp", XBLT_NONE, 0, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bitmap_load__max_width_zoom__ok)
|
||||
{
|
||||
load_and_transform_img("test_24bit.bmp",
|
||||
XBLT_ZOOM, MAX_VDESKTOP_WIDTH, MIN_VDESKTOP_HEIGHT);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bitmap_load__max_height_zoom__ok)
|
||||
{
|
||||
load_and_transform_img("test_24bit.bmp",
|
||||
XBLT_ZOOM, MIN_VDESKTOP_WIDTH, MAX_VDESKTOP_HEIGHT);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bitmap_load__min_zoom__ok)
|
||||
{
|
||||
load_and_transform_img("test_24bit.bmp",
|
||||
XBLT_ZOOM, MIN_VDESKTOP_WIDTH, MIN_VDESKTOP_HEIGHT);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bitmap_load__max_width_scale__ok)
|
||||
{
|
||||
load_and_transform_img("test_24bit.bmp",
|
||||
XBLT_SCALE, MAX_VDESKTOP_WIDTH, MIN_VDESKTOP_HEIGHT);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bitmap_load__max_height_scale__ok)
|
||||
{
|
||||
load_and_transform_img("test_24bit.bmp",
|
||||
XBLT_SCALE, MIN_VDESKTOP_WIDTH, MAX_VDESKTOP_HEIGHT);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bitmap_load__min_scale__ok)
|
||||
{
|
||||
load_and_transform_img("test_24bit.bmp",
|
||||
XBLT_SCALE, MIN_VDESKTOP_WIDTH, MIN_VDESKTOP_HEIGHT);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bitmap_load__not_4_pixels_wide_4_bit__ok)
|
||||
{
|
||||
load_not4_img("test_not4_4bit.bmp");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bitmap_load__not_4_pixels_wide_8_bit__ok)
|
||||
{
|
||||
load_not4_img("test_not4_8bit.bmp");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bitmap_load__not_4_pixels_wide_24_bit__ok)
|
||||
{
|
||||
load_not4_img("test_not4_24bit.bmp");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
#ifdef USE_IMLIB2
|
||||
START_TEST(test_png_load__blend_ok)
|
||||
{
|
||||
load_and_transform_img("test_alpha_blend.png", XBLT_NONE, 0, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_jpg_load__ok)
|
||||
{
|
||||
load_and_transform_img("test1.jpg", XBLT_NONE, 0, 0);
|
||||
}
|
||||
END_TEST
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
Suite *
|
||||
make_suite_test_bitmap_load(void)
|
||||
{
|
||||
Suite *s;
|
||||
TCase *tc_bitmap_load;
|
||||
#ifdef USE_IMLIB2
|
||||
TCase *tc_other_load;
|
||||
#endif
|
||||
|
||||
s = suite_create("BitmapLoad");
|
||||
|
||||
tc_bitmap_load = tcase_create("xrdp_bitmap_load");
|
||||
tcase_add_checked_fixture(tc_bitmap_load, setup, teardown);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__with_invalid_image__fail);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__4_bit__ok);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__8_bit__ok);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__24_bit__ok);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__max_width_zoom__ok);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__max_height_zoom__ok);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__min_zoom__ok);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__max_width_scale__ok);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__max_height_scale__ok);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__min_scale__ok);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__not_4_pixels_wide_4_bit__ok);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__not_4_pixels_wide_8_bit__ok);
|
||||
tcase_add_test(tc_bitmap_load, test_bitmap_load__not_4_pixels_wide_24_bit__ok);
|
||||
|
||||
suite_add_tcase(s, tc_bitmap_load);
|
||||
|
||||
#ifdef USE_IMLIB2
|
||||
tc_other_load = tcase_create("xrdp_other_load");
|
||||
tcase_add_checked_fixture(tc_other_load, setup, teardown);
|
||||
tcase_add_test(tc_other_load, test_png_load__blend_ok);
|
||||
tcase_add_test(tc_other_load, test_jpg_load__ok);
|
||||
suite_add_tcase(s, tc_other_load);
|
||||
#endif
|
||||
|
||||
return s;
|
||||
}
|
BIN
tests/xrdp/test_not4_24bit.bmp
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
tests/xrdp/test_not4_4bit.bmp
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
tests/xrdp/test_not4_8bit.bmp
Normal file
After Width: | Height: | Size: 4.9 KiB |
8
tests/xrdp/test_xrdp.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef TEST_XRDP_H
|
||||
#define TEST_XRDP_H
|
||||
|
||||
#include <check.h>
|
||||
|
||||
Suite *make_suite_test_bitmap_load(void);
|
||||
|
||||
#endif /* TEST_XRDP_H */
|
62
tests/xrdp/test_xrdp_main.c
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2021
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Test driver for XRDP routines
|
||||
*
|
||||
* If you want to run this driver under valgrind to check for memory leaks,
|
||||
* use the following command line:-
|
||||
*
|
||||
* CK_FORK=no valgrind --leak-check=full --show-leak-kinds=all \
|
||||
* .libs/test_xrdp
|
||||
*
|
||||
* without the 'CK_FORK=no', memory still allocated by the test driver will
|
||||
* be logged
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config_ac.h"
|
||||
#endif
|
||||
|
||||
#include "log.h"
|
||||
#include "os_calls.h"
|
||||
#include "test_xrdp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
int number_failed;
|
||||
SRunner *sr;
|
||||
struct log_config *logging;
|
||||
|
||||
/* Configure the logging sub-system so that functions can use
|
||||
* the log functions as appropriate */
|
||||
logging = log_config_init_for_console(LOG_LEVEL_INFO,
|
||||
g_getenv("TEST_LOG_LEVEL"));
|
||||
log_start_from_param(logging);
|
||||
log_config_free(logging);
|
||||
|
||||
sr = srunner_create (make_suite_test_bitmap_load());
|
||||
|
||||
srunner_set_tap(sr, "-");
|
||||
srunner_run_all (sr, CK_ENV);
|
||||
number_failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
log_end();
|
||||
|
||||
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
@ -12,7 +12,8 @@ AM_CPPFLAGS = \
|
||||
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
|
||||
-I$(top_builddir) \
|
||||
-I$(top_srcdir)/common \
|
||||
-I$(top_srcdir)/libxrdp
|
||||
-I$(top_srcdir)/libxrdp \
|
||||
$(IMLIB2_CFLAGS)
|
||||
|
||||
XRDP_EXTRA_LIBS =
|
||||
|
||||
@ -43,6 +44,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 \
|
||||
@ -59,6 +62,7 @@ xrdp_SOURCES = \
|
||||
xrdp_LDADD = \
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
$(top_builddir)/libxrdp/libxrdp.la \
|
||||
$(IMLIB2_LIBS) \
|
||||
$(XRDP_EXTRA_LIBS)
|
||||
|
||||
xrdpsysconfdir=$(sysconfdir)/xrdp
|
||||
|
43
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,15 +195,9 @@ 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);
|
||||
int
|
||||
xrdp_bitmap_load(struct xrdp_bitmap *self, const char *filename, int *palette);
|
||||
int
|
||||
xrdp_bitmap_get_pixel(struct xrdp_bitmap *self, int x, int y);
|
||||
int
|
||||
xrdp_bitmap_set_pixel(struct xrdp_bitmap *self, int x, int y, int pixel);
|
||||
@ -211,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
|
||||
@ -239,6 +239,35 @@ 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. It is in HCOLOR format, and the bpp must correspond to
|
||||
* the bpp used to create 'self'.
|
||||
*
|
||||
* 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);
|
||||
|
@ -129,12 +129,27 @@ ls_height=430
|
||||
; login screen background color in RGB format
|
||||
ls_bg_color=dedede
|
||||
|
||||
; optional background image filename (bmp format).
|
||||
; optional background image filename. BMP format is always supported,
|
||||
; but other formats will be supported if xrdp is build with imlib2
|
||||
; The transform can be one of the following:-
|
||||
; none : No transformation. Image is placed in bottom-right corner
|
||||
; of the screen.
|
||||
; scale : Image is scaled to the screen size. The image aspect
|
||||
; ratio is not preserved.
|
||||
; zoom : Image is scaled to the screen size. The image aspect
|
||||
; ratio is preserved by clipping the image.
|
||||
#ls_background_image=
|
||||
#ls_background_transform=none
|
||||
|
||||
; logo
|
||||
; full path to bmp-file or file in shared folder
|
||||
; full path to file or file in shared folder. BMP format is always supported,
|
||||
; but other formats will be supported if xrdp is build with imlib2
|
||||
; For transform values, see 'ls_background_transform'. The logo width and
|
||||
; logo height are ignored for a transform of 'none'.
|
||||
ls_logo_filename=
|
||||
#ls_logo_transform=none
|
||||
#ls_logo_width=240
|
||||
#ls_logo_height=140
|
||||
ls_logo_x_pos=55
|
||||
ls_logo_y_pos=50
|
||||
|
||||
|
@ -25,8 +25,6 @@
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "xrdp.h"
|
||||
#include "log.h"
|
||||
#include "string_calls.h"
|
||||
@ -86,258 +84,6 @@ static const unsigned int g_crc_table[256] =
|
||||
(in_crc) = g_crc_table[((in_crc) ^ (in_pixel)) & 0xff] ^ ((in_crc) >> 8)
|
||||
#define CRC_END(in_crc) (in_crc) = ((in_crc) ^ 0xFFFFFFFF)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* 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);
|
||||
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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_bitmap *
|
||||
xrdp_bitmap_get_child_by_id(struct xrdp_bitmap *self, int id)
|
||||
@ -401,593 +147,6 @@ xrdp_bitmap_set_focus(struct xrdp_bitmap *self, int focused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_bitmap_get_index(struct xrdp_bitmap *self, 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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* load a bmp file */
|
||||
/* return 0 ok */
|
||||
/* return 1 error */
|
||||
int
|
||||
xrdp_bitmap_load(struct xrdp_bitmap *self, const char *filename, 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, "xrdp_bitmap_load: error bitmap file [%s] "
|
||||
"does not exist", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd = g_file_open(filename);
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
/* read file type */
|
||||
if (g_file_read(fd, type1, 2) != 2)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_bitmap_load: error bitmap file [%s] "
|
||||
"read error", filename);
|
||||
g_file_close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((type1[0] != 'B') || (type1[1] != 'M'))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_bitmap_load: error bitmap file [%s] "
|
||||
"not BMP file", 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, "xrdp_bitmap_load: missing length in file %s",
|
||||
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, "xrdp_bitmap_load: seek error in file %s",
|
||||
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, "xrdp_bitmap_load: "
|
||||
"unexpected read length %d in file %s",
|
||||
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, "xrdp_bitmap_load: error bitmap file [%s] "
|
||||
"bad bpp %d", 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, "xrdp_bitmap_load: seek error in file %s",
|
||||
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, "xrdp_bitmap_load: error bitmap "
|
||||
"file [%s] read", 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, "xrdp_bitmap_load: seek error in file %s",
|
||||
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, "xrdp_bitmap_load: "
|
||||
"unexpected read length in file %s",
|
||||
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, "xrdp_bitmap_load: error bitmap "
|
||||
"file [%s] read", 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, "xrdp_bitmap_load: seek error in file %s",
|
||||
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, "xrdp_bitmap_load: "
|
||||
"unexpected read length in file %s",
|
||||
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, "xrdp_bitmap_load: error bitmap "
|
||||
"file [%s] read", 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_bitmap_load: error loading bitmap "
|
||||
"from file [%s]", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
xrdp_bitmap_hash_crc(struct xrdp_bitmap *self)
|
||||
|
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;
|
||||
}
|
1099
xrdp/xrdp_bitmap_load.c
Normal file
@ -643,7 +643,9 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
|
||||
int log_width;
|
||||
int log_height;
|
||||
int regular;
|
||||
int primary_x_offset;
|
||||
int primary_width; /* Dimensions of primary screen */
|
||||
int primary_height;
|
||||
int primary_x_offset; /* Offset of centre of primary screen */
|
||||
int primary_y_offset;
|
||||
int index;
|
||||
int x;
|
||||
@ -653,8 +655,10 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
|
||||
|
||||
globals = &self->xrdp_config->cfg_globals;
|
||||
|
||||
primary_x_offset = self->screen->width / 2;
|
||||
primary_y_offset = self->screen->height / 2;
|
||||
primary_width = self->screen->width;
|
||||
primary_height = self->screen->height;
|
||||
primary_x_offset = primary_width / 2;
|
||||
primary_y_offset = primary_height / 2;
|
||||
|
||||
log_width = globals->ls_width;
|
||||
log_height = globals->ls_height;
|
||||
@ -686,8 +690,10 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
|
||||
cx = self->client_info->minfo_wm[index].right;
|
||||
cy = self->client_info->minfo_wm[index].bottom;
|
||||
|
||||
primary_x_offset = x + ((cx - x) / 2);
|
||||
primary_y_offset = y + ((cy - y) / 2);
|
||||
primary_width = cx - x;
|
||||
primary_height = cy - y;
|
||||
primary_x_offset = x + (primary_width / 2);
|
||||
primary_y_offset = y + (primary_height / 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -725,27 +731,62 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
|
||||
{
|
||||
/* Load the background image. */
|
||||
/* If no file is specified no default image will be loaded. */
|
||||
/* We only load the image if bpp > 8 */
|
||||
if (globals->ls_background_image[0] != 0 && self->screen->bpp > 8)
|
||||
/* We only load the image if bpp > 8, and if the user hasn't
|
||||
* disabled wallpaer in the performance settings */
|
||||
if (globals->ls_background_image[0] != 0)
|
||||
{
|
||||
char fileName[256] ;
|
||||
but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE, self);
|
||||
if (globals->ls_background_image[0] == '/')
|
||||
if (self->screen->bpp <= 8)
|
||||
{
|
||||
g_snprintf(fileName, 255, "%s", globals->ls_background_image);
|
||||
LOG(LOG_LEVEL_INFO, "Login background not loaded for bpp=%d",
|
||||
self->screen->bpp);
|
||||
}
|
||||
else if ((self->client_info->rdp5_performanceflags &
|
||||
RDP5_NO_WALLPAPER) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Login background not loaded as client "
|
||||
"has requested PERF_DISABLE_WALLPAPER");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(fileName, 255, "%s/%s",
|
||||
XRDP_SHARE_PATH, globals->ls_background_image);
|
||||
char fileName[256] ;
|
||||
but = xrdp_bitmap_create(4, 4, self->screen->bpp,
|
||||
WND_TYPE_IMAGE, self);
|
||||
if (globals->ls_background_image[0] == '/')
|
||||
{
|
||||
g_snprintf(fileName, 255, "%s",
|
||||
globals->ls_background_image);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(fileName, 255, "%s/%s",
|
||||
XRDP_SHARE_PATH, globals->ls_background_image);
|
||||
}
|
||||
LOG(LOG_LEVEL_DEBUG, "We try to load the following background file: %s", fileName);
|
||||
if (globals->ls_background_transform == XBLT_NONE)
|
||||
{
|
||||
xrdp_bitmap_load(but, fileName, self->palette,
|
||||
globals->ls_top_window_bg_color,
|
||||
globals->ls_background_transform,
|
||||
0, 0);
|
||||
/* Place the background in the bottom right corner */
|
||||
but->left = primary_x_offset + (primary_width / 2) -
|
||||
but->width;
|
||||
but->top = primary_y_offset + (primary_height / 2) -
|
||||
but->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
xrdp_bitmap_load(but, fileName, self->palette,
|
||||
globals->ls_top_window_bg_color,
|
||||
globals->ls_background_transform,
|
||||
primary_width, primary_height);
|
||||
but->left = primary_x_offset - (primary_width / 2);
|
||||
but->top = primary_y_offset - (primary_height / 2);
|
||||
}
|
||||
but->parent = self->screen;
|
||||
but->owner = self->screen;
|
||||
list_add_item(self->screen->child_list, (long)but);
|
||||
}
|
||||
LOG(LOG_LEVEL_DEBUG, "We try to load the following background file: %s", fileName);
|
||||
xrdp_bitmap_load(but, fileName, self->palette);
|
||||
but->parent = self->screen;
|
||||
but->owner = self->screen;
|
||||
but->left = self->screen->width - but->width;
|
||||
but->top = self->screen->height - but->height;
|
||||
list_add_item(self->screen->child_list, (long)but);
|
||||
}
|
||||
|
||||
/* if logo image not specified, use default */
|
||||
@ -762,7 +803,11 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
|
||||
g_snprintf(globals->ls_logo_filename, 255, "%s/ad256.bmp", XRDP_SHARE_PATH);
|
||||
}
|
||||
|
||||
xrdp_bitmap_load(but, globals->ls_logo_filename, self->palette);
|
||||
xrdp_bitmap_load(but, globals->ls_logo_filename, self->palette,
|
||||
globals->ls_bg_color,
|
||||
globals->ls_logo_transform,
|
||||
globals->ls_logo_width,
|
||||
globals->ls_logo_height);
|
||||
but->parent = self->login_window;
|
||||
but->owner = self->login_window;
|
||||
but->left = globals->ls_logo_x_pos;
|
||||
@ -831,6 +876,42 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a bitmap transform string to a value
|
||||
*
|
||||
* @param param Param we're trying to read
|
||||
* @param str String we're trying to map
|
||||
*
|
||||
* @return enum xrdp_bitmap_load_transform value
|
||||
*
|
||||
* A warning is logged if the string is not recognised
|
||||
*****************************************************************************/
|
||||
static enum xrdp_bitmap_load_transform
|
||||
bitmap_transform_str_to_val(const char *param, const char *str)
|
||||
{
|
||||
enum xrdp_bitmap_load_transform rv;
|
||||
if (g_strcmp(str, "none") == 0)
|
||||
{
|
||||
rv = XBLT_NONE;
|
||||
}
|
||||
else if (g_strcmp(str, "scale") == 0)
|
||||
{
|
||||
rv = XBLT_SCALE;
|
||||
}
|
||||
else if (g_strcmp(str, "zoom") == 0)
|
||||
{
|
||||
rv = XBLT_ZOOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Param '%s' has unrecognised value '%s'"
|
||||
" - assuming 'none'", param, str);
|
||||
rv = XBLT_NONE;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load configuration from xrdp.ini file
|
||||
*
|
||||
@ -866,6 +947,8 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp)
|
||||
globals->ls_bg_color = HCOLOR(bpp, xrdp_wm_htoi("dedede"));
|
||||
globals->ls_width = 350;
|
||||
globals->ls_height = 350;
|
||||
globals->ls_background_transform = XBLT_NONE;
|
||||
globals->ls_logo_transform = XBLT_NONE;
|
||||
globals->ls_logo_x_pos = 63;
|
||||
globals->ls_logo_y_pos = 50;
|
||||
globals->ls_label_x_pos = 30;
|
||||
@ -1103,16 +1186,39 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp)
|
||||
globals->ls_title[255] = 0;
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_logo_filename", 255) == 0)
|
||||
{
|
||||
g_strncpy(globals->ls_logo_filename, v, 255);
|
||||
globals->ls_logo_filename[255] = 0;
|
||||
}
|
||||
else if (g_strncmp(n, "ls_background_image", 255) == 0)
|
||||
{
|
||||
g_strncpy(globals->ls_background_image, v, 255);
|
||||
globals->ls_background_image[255] = 0;
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_background_transform", 255) == 0)
|
||||
{
|
||||
globals->ls_background_transform =
|
||||
bitmap_transform_str_to_val(n, v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_logo_filename", 255) == 0)
|
||||
{
|
||||
g_strncpy(globals->ls_logo_filename, v, 255);
|
||||
globals->ls_logo_filename[255] = 0;
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_logo_transform", 255) == 0)
|
||||
{
|
||||
globals->ls_logo_transform = bitmap_transform_str_to_val(n, v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_logo_width", 64) == 0)
|
||||
{
|
||||
globals->ls_logo_width = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_logo_height", 64) == 0)
|
||||
{
|
||||
globals->ls_logo_height = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_logo_x_pos", 64) == 0)
|
||||
{
|
||||
globals->ls_logo_x_pos = g_atoi(v);
|
||||
|
@ -168,6 +168,16 @@ struct xrdp_mod
|
||||
struct source_info *si;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transform to apply to loaded images
|
||||
*/
|
||||
enum xrdp_bitmap_load_transform
|
||||
{
|
||||
XBLT_NONE = 0,
|
||||
XBLT_SCALE,
|
||||
XBLT_ZOOM
|
||||
};
|
||||
|
||||
/* header for bmp file */
|
||||
struct xrdp_bmp_header
|
||||
{
|
||||
@ -634,8 +644,14 @@ struct xrdp_cfg_globals
|
||||
int ls_width; /* window width */
|
||||
int ls_height; /* window height */
|
||||
int ls_bg_color; /* background color */
|
||||
char ls_logo_filename[256]; /* logo filename */
|
||||
char ls_background_image[256]; /* background image file name */
|
||||
enum xrdp_bitmap_load_transform ls_background_transform;
|
||||
/* transform to apply to background image */
|
||||
char ls_logo_filename[256]; /* logo filename */
|
||||
enum xrdp_bitmap_load_transform ls_logo_transform;
|
||||
/* transform to apply to logo */
|
||||
int ls_logo_width; /* logo width (optional) */
|
||||
int ls_logo_height; /* logo height (optional) */
|
||||
int ls_logo_x_pos; /* logo x co-ordinate */
|
||||
int ls_logo_y_pos; /* logo y co-ordinate */
|
||||
int ls_label_x_pos; /* x pos of labels */
|
||||
|