Milestone 5: deliver embedded RDP sessions and lifecycle hardening

This commit is contained in:
Keith Smith
2026-03-03 18:59:26 -07:00
parent 230a401386
commit 36006bd4aa
2941 changed files with 724359 additions and 77 deletions

View File

@@ -0,0 +1,37 @@
set(MODULE_NAME "TestGdi")
set(MODULE_PREFIX "TEST_GDI")
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS
TestGdiRop3.c
# TestGdiLine.c # TODO: This test is broken
TestGdiRegion.c
TestGdiRect.c
TestGdiBitBlt.c
TestGdiCreate.c
TestGdiEllipse.c
TestGdiClip.c
)
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
include_directories(..)
add_library(helpers STATIC helpers.c)
target_link_libraries(helpers freerdp)
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
target_link_libraries(${MODULE_NAME} winpr freerdp helpers)
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
foreach(test ${${MODULE_PREFIX}_TESTS})
get_filename_component(TestName ${test} NAME_WE)
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Test")

View File

@@ -0,0 +1,577 @@
#include <freerdp/gdi/gdi.h>
#include <freerdp/gdi/dc.h>
#include <freerdp/gdi/pen.h>
#include <freerdp/gdi/region.h>
#include <freerdp/gdi/bitmap.h>
#include <winpr/crt.h>
#include "line.h"
#include "brush.h"
#include "helpers.h"
/* BitBlt() Test Data */
/* source bitmap (16x16) */
static const BYTE bmp_SRC[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
/* destination bitmap (16x16) */
static const BYTE bmp_DST[256] = {
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
};
/* SRCCOPY (0x00CC0020) */
static const BYTE bmp_SRCCOPY[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
/* BLACKNESS (0x00000042) */
static const BYTE bmp_BLACKNESS[256] = {
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
};
/* WHITENESS (0x00FF0062) */
static const BYTE bmp_WHITENESS[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
/* SRCAND (0x008800C6) */
static const BYTE bmp_SRCAND[256] = {
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
};
/* SRCPAINT (0x00EE0086) */
static const BYTE bmp_SRCPAINT[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
/* SRCINVERT (0x00660046) */
static const BYTE bmp_SRCINVERT[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
/* SRCERASE (0x00440328) */
static const BYTE bmp_SRCERASE[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
/* NOTSRCCOPY (0x00330008) */
static const BYTE bmp_NOTSRCCOPY[256] = {
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00"
"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00"
"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00"
"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00"
"\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
};
/* NOTSRCERASE (0x001100A6) */
static const BYTE bmp_NOTSRCERASE[256] = {
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
};
/* DSTINVERT (0x00550009) */
static const BYTE bmp_DSTINVERT[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
/* SPna (0x000C0324) */
static const BYTE bmp_SPna[256] = {
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x00\x00"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
};
/* MERGEPAINT (0x00BB0226) */
static const BYTE bmp_MERGEPAINT[256] = {
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00"
};
/* MERGECOPY (0x00C000CA) */
static const BYTE bmp_MERGECOPY[256] = {
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x00\x00"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
};
/* PATPAINT (0x00FB0A09) */
static const BYTE bmp_PATPAINT[256] = {
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
};
/* PATCOPY (0x00F00021) */
static const BYTE bmp_PATCOPY[256] = {
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
};
/* PATINVERT (0x005A0049) */
static const BYTE bmp_PATINVERT[256] = {
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00\x00\x00\xFF\xFF\x00\x00\xFF\xFF"
};
struct test_bitblt
{
UINT32 rop;
const BYTE* src;
HGDI_BITMAP bmp;
};
static BOOL test_rop(HGDI_DC hdcDst, HGDI_DC hdcSrc, HGDI_BITMAP hBmpSrc, HGDI_BITMAP hBmpDst,
HGDI_BITMAP hBmpDstOriginal, UINT32 rop, HGDI_BITMAP expected,
const gdiPalette* hPalette)
{
BOOL success = FALSE;
/* restore original destination bitmap */
gdi_SelectObject(hdcSrc, (HGDIOBJECT)hBmpDstOriginal);
gdi_SelectObject(hdcDst, (HGDIOBJECT)hBmpDst);
if (!gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, GDI_SRCCOPY, hPalette))
goto fail;
if (!test_assert_bitmaps_equal(hBmpDst, hBmpDstOriginal, gdi_rop_to_string(GDI_SRCCOPY),
hPalette))
goto fail;
gdi_SelectObject(hdcSrc, (HGDIOBJECT)hBmpSrc);
if (!gdi_BitBlt(hdcDst, 0, 0, 16, 16, hdcSrc, 0, 0, rop, hPalette))
goto fail;
if (!test_assert_bitmaps_equal(hBmpDst, expected, gdi_rop_to_string(rop), hPalette))
goto fail;
success = TRUE;
fail:
(void)fprintf(stderr, "[%s] ROP=%s returned %d\n", __func__, gdi_rop_to_string(rop), success);
return success;
}
static BOOL test_gdi_BitBlt(UINT32 SrcFormat, UINT32 DstFormat)
{
BOOL rc = FALSE;
BOOL failed = FALSE;
HGDI_DC hdcSrc = nullptr;
HGDI_DC hdcDst = nullptr;
const UINT32 RawFormat = PIXEL_FORMAT_RGB8;
struct test_bitblt tests[] = { { GDI_SRCCOPY, bmp_SRCCOPY, nullptr },
{ GDI_SPna, bmp_SPna, nullptr },
{ GDI_BLACKNESS, bmp_BLACKNESS, nullptr },
{ GDI_WHITENESS, bmp_WHITENESS, nullptr },
{ GDI_SRCAND, bmp_SRCAND, nullptr },
{ GDI_SRCPAINT, bmp_SRCPAINT, nullptr },
{ GDI_SRCINVERT, bmp_SRCINVERT, nullptr },
{ GDI_SRCERASE, bmp_SRCERASE, nullptr },
{ GDI_NOTSRCCOPY, bmp_NOTSRCCOPY, nullptr },
{ GDI_NOTSRCERASE, bmp_NOTSRCERASE, nullptr },
{ GDI_DSTINVERT, bmp_DSTINVERT, nullptr },
{ GDI_MERGECOPY, bmp_MERGECOPY, nullptr },
{ GDI_MERGEPAINT, bmp_MERGEPAINT, nullptr },
{ GDI_PATCOPY, bmp_PATCOPY, nullptr },
{ GDI_PATPAINT, bmp_PATPAINT, nullptr },
{ GDI_PATINVERT, bmp_PATINVERT, nullptr },
{ GDI_DSTINVERT, bmp_SRC, nullptr },
{ GDI_DSPDxax, bmp_SRC, nullptr },
{ GDI_PSDPxax, bmp_SRC, nullptr },
{ GDI_DSna, bmp_SRC, nullptr },
{ GDI_DPa, bmp_SRC, nullptr },
{ GDI_PDxn, bmp_SRC, nullptr },
{ GDI_DSxn, bmp_SRC, nullptr },
{ GDI_PSDnox, bmp_SRC, nullptr },
{ GDI_PDSona, bmp_SRC, nullptr },
{ GDI_DSPDxox, bmp_SRC, nullptr },
{ GDI_DPSDonox, bmp_SRC, nullptr },
{ GDI_SPDSxax, bmp_SRC, nullptr },
{ GDI_DPon, bmp_SRC, nullptr },
{ GDI_DPna, bmp_SRC, nullptr },
{ GDI_Pn, bmp_SRC, nullptr },
{ GDI_PDna, bmp_SRC, nullptr },
{ GDI_DPan, bmp_SRC, nullptr },
{ GDI_DSan, bmp_SRC, nullptr },
{ GDI_DSxn, bmp_SRC, nullptr },
{ GDI_DPa, bmp_SRC, nullptr },
{ GDI_DSTCOPY, bmp_SRC, nullptr },
{ GDI_DPno, bmp_SRC, nullptr },
{ GDI_SDno, bmp_SRC, nullptr },
{ GDI_PDno, bmp_SRC, nullptr },
{ GDI_DPo, bmp_SRC, nullptr } };
const UINT32 number_tests = sizeof(tests) / sizeof(tests[0]);
HGDI_BITMAP hBmpSrc = nullptr;
HGDI_BITMAP hBmpDst = nullptr;
HGDI_BITMAP hBmpDstOriginal = nullptr;
HGDI_BRUSH brush = nullptr;
gdiPalette g;
gdiPalette* hPalette = &g;
g.format = DstFormat;
for (UINT32 x = 0; x < 256; x++)
g.palette[x] = FreeRDPGetColor(DstFormat, x, x, x, 0xFF);
if (!(hdcSrc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
goto fail;
}
hdcSrc->format = SrcFormat;
if (!(hdcDst = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
goto fail;
}
hdcDst->format = DstFormat;
hBmpSrc =
test_convert_to_bitmap(bmp_SRC, RawFormat, 0, 0, 0, SrcFormat, 0, 0, 0, 16, 16, hPalette);
if (!hBmpSrc)
goto fail;
hBmpDst =
test_convert_to_bitmap(bmp_DST, RawFormat, 0, 0, 0, DstFormat, 0, 0, 0, 16, 16, hPalette);
if (!hBmpDst)
goto fail;
hBmpDstOriginal =
test_convert_to_bitmap(bmp_DST, RawFormat, 0, 0, 0, SrcFormat, 0, 0, 0, 16, 16, hPalette);
if (!hBmpDstOriginal)
goto fail;
for (size_t x = 0; x < ARRAYSIZE(tests); x++)
{
struct test_bitblt* test = &tests[x];
test->bmp = test_convert_to_bitmap(test->src, RawFormat, 0, 0, 0, SrcFormat, 0, 0, 0, 16,
16, hPalette);
if (!test->bmp)
goto fail;
}
brush = gdi_CreateSolidBrush(0x123456);
gdi_SelectObject(hdcDst, (HGDIOBJECT)brush);
for (size_t x = 0; x < ARRAYSIZE(tests); x++)
{
struct test_bitblt* test = &tests[x];
if (!test_rop(hdcDst, hdcSrc, hBmpSrc, hBmpDst, hBmpDstOriginal, test->rop, test->bmp,
hPalette))
failed = TRUE;
}
gdi_SelectObject(hdcDst, nullptr);
gdi_DeleteObject((HGDIOBJECT)brush);
rc = !failed;
fail:
for (size_t x = 0; x < ARRAYSIZE(tests); x++)
{
struct test_bitblt* test = &tests[x];
gdi_DeleteObject((HGDIOBJECT)test->bmp);
}
gdi_DeleteObject((HGDIOBJECT)hBmpSrc);
gdi_DeleteObject((HGDIOBJECT)hBmpDst);
gdi_DeleteObject((HGDIOBJECT)hBmpDstOriginal);
gdi_DeleteDC(hdcSrc);
gdi_DeleteDC(hdcDst);
return rc;
}
int TestGdiBitBlt(int argc, char* argv[])
{
int rc = 0;
const UINT32 formatList[] = { PIXEL_FORMAT_RGB8, PIXEL_FORMAT_RGB15, PIXEL_FORMAT_ARGB15,
PIXEL_FORMAT_RGB16, PIXEL_FORMAT_RGB24, PIXEL_FORMAT_RGBA32,
PIXEL_FORMAT_RGBX32, PIXEL_FORMAT_ARGB32, PIXEL_FORMAT_XRGB32,
PIXEL_FORMAT_BGR15, PIXEL_FORMAT_ABGR15, PIXEL_FORMAT_BGR16,
PIXEL_FORMAT_BGR24, PIXEL_FORMAT_BGRA32, PIXEL_FORMAT_BGRX32,
PIXEL_FORMAT_ABGR32, PIXEL_FORMAT_XBGR32 };
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
for (size_t x = 0; x < ARRAYSIZE(formatList); x++)
{
/* Skip 8bpp, only supported on remote end. */
for (size_t y = 1; y < ARRAYSIZE(formatList); y++)
{
if (!test_gdi_BitBlt(formatList[x], formatList[y]))
{
(void)fprintf(stderr, "test_gdi_BitBlt(SrcFormat=%s, DstFormat=%s) failed!\n",
FreeRDPGetColorFormatName(formatList[x]),
FreeRDPGetColorFormatName(formatList[y]));
rc = -1;
}
}
}
return rc;
}

View File

@@ -0,0 +1,364 @@
#include <freerdp/gdi/gdi.h>
#include <freerdp/gdi/dc.h>
#include <freerdp/gdi/pen.h>
#include <freerdp/gdi/region.h>
#include <freerdp/gdi/bitmap.h>
#include <winpr/crt.h>
#include "line.h"
#include "brush.h"
#include "clipping.h"
static bool test_gdi_coords(size_t testNr, HGDI_DC hdc, const GDI_RGN* clip, const GDI_RGN* input,
const GDI_RGN* expect)
{
bool rc = false;
WINPR_ASSERT(hdc);
WINPR_ASSERT(input);
HGDI_RGN rgn1 = gdi_CreateRectRgn(0, 0, 0, 0);
HGDI_RGN rgn2 = gdi_CreateRectRgn(0, 0, 0, 0);
if (!rgn1 || !rgn2)
{
(void)fprintf(stderr, "[%s:%" PRIuz "] gdi_CreateRectRgn failed: rgn1=%p, rgn2=%p\n",
__func__, testNr, rgn1, rgn2);
goto fail;
}
if (!clip)
{
if (!gdi_SetNullClipRgn(hdc))
{
(void)fprintf(stderr, "[%s:%" PRIuz "] gdi_SetNullClipRgn failed\n", __func__, testNr);
goto fail;
}
}
else if (!gdi_SetClipRgn(hdc, clip->x, clip->y, clip->w, clip->h))
{
(void)fprintf(stderr, "[%s:%" PRIuz "] gdi_SetClipRgn failed\n", __func__, testNr);
goto fail;
}
if (!gdi_SetRgn(rgn1, input->x, input->y, input->w, input->h))
{
(void)fprintf(stderr, "[%s:%" PRIuz "] gdi_SetRgn (rgn1) failed\n", __func__, testNr);
goto fail;
}
if (expect)
{
if (!gdi_SetRgn(rgn2, expect->x, expect->y, expect->w, expect->h))
{
(void)fprintf(stderr, "[%s:%" PRIuz "] gdi_SetRgn (rgn2) failed\n", __func__, testNr);
goto fail;
}
}
const BOOL draw =
gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), nullptr, nullptr);
if (expect)
{
if (!draw)
{
(void)fprintf(stderr,
"[%s:%" PRIuz "] gdi_ClipCoords failed: expected TRUE, got FALSE\n",
__func__, testNr);
goto fail;
}
if (!gdi_EqualRgn(rgn1, rgn2))
{
char buffer1[64] = WINPR_C_ARRAY_INIT;
char buffer2[64] = WINPR_C_ARRAY_INIT;
(void)fprintf(stderr, "[%s:%" PRIuz "] gdi_EqualRgn failed: expected %s, got %s\n",
__func__, testNr, buffer1, buffer2);
goto fail;
}
}
else
{
if (draw)
{
(void)fprintf(stderr,
"[%s:%" PRIuz "] gdi_ClipCoords failed: expected FALSE, got TRUE\n",
__func__, testNr);
goto fail;
}
}
rc = true;
fail:
gdi_DeleteObject((HGDIOBJECT)rgn1);
gdi_DeleteObject((HGDIOBJECT)rgn2);
return rc;
}
static int test_gdi_ClipCoords(void)
{
int rc = -1;
HGDI_DC hdc = nullptr;
HGDI_BITMAP bmp = nullptr;
const UINT32 format = PIXEL_FORMAT_ARGB32;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
return -1;
}
hdc->format = format;
bmp = gdi_CreateBitmapEx(1024, 768, PIXEL_FORMAT_XRGB32, 0, nullptr, nullptr);
gdi_SelectObject(hdc, (HGDIOBJECT)bmp);
gdi_SetNullClipRgn(hdc);
struct testcase_t
{
const GDI_RGN* clip;
const GDI_RGN* in;
const GDI_RGN* expect;
};
const GDI_RGN rgn0x0_1024x768 = { 0, 0, 0, 1024, 768, FALSE };
const GDI_RGN rgn20x20_100x100 = { 0, 20, 20, 100, 100, FALSE };
const GDI_RGN rgn100x300_250x100 = { 0, 100, 300, 250, 100, FALSE };
const GDI_RGN rgn100x300_300x100 = { 0, 100, 300, 300, 100, FALSE };
const GDI_RGN rgn300x20_100x100 = { 0, 300, 20, 100, 100, FALSE };
const GDI_RGN rgn300x100_300x300 = { 0, 300, 100, 300, 300, FALSE };
const GDI_RGN rgn300x300_50x100 = { 0, 300, 300, 50, 100, FALSE };
const GDI_RGN rgn300x300_100x100 = { 0, 300, 300, 100, 100, FALSE };
const GDI_RGN rgn300x300_300x100 = { 0, 300, 300, 300, 100, FALSE };
const GDI_RGN rgn300x300_300x200 = { 0, 300, 300, 100, 200, FALSE };
const GDI_RGN rgn300x420_100x100 = { 0, 300, 420, 100, 100, FALSE };
const GDI_RGN rgn350x300_50x100 = { 0, 350, 300, 50, 100, FALSE };
const GDI_RGN rgn350x300_200x100 = { 0, 350, 300, 200, 100, FALSE };
const GDI_RGN rgn420x420_100x100 = { 0, 420, 420, 100, 100, FALSE };
const struct testcase_t testcases[] = {
/* null clipping region */
{ nullptr, &rgn20x20_100x100, &rgn20x20_100x100 },
/* region all inside clipping region */
{ &rgn0x0_1024x768, &rgn20x20_100x100, &rgn20x20_100x100 },
/* region all outside clipping region, on the left */
{ &rgn300x300_100x100, &rgn20x20_100x100, nullptr },
/* region all outside clipping region, on the right */
{ &rgn300x300_100x100, &rgn420x420_100x100, nullptr },
/* region all outside clipping region, on top */
{ &rgn300x300_100x100, &rgn300x20_100x100, nullptr },
/* region all outside clipping region, at the bottom */
{ &rgn300x300_100x100, &rgn300x420_100x100, nullptr },
/* left outside, right = clip, top = clip, bottom = clip */
{ &rgn300x300_100x100, &rgn100x300_300x100, &rgn300x300_100x100 },
/* left outside, right inside, top = clip, bottom = clip */
{ &rgn300x300_100x100, &rgn100x300_250x100, &rgn300x300_50x100 },
/* left = clip, right outside, top = clip, bottom = clip */
{ &rgn300x300_100x100, &rgn300x300_300x100, &rgn300x300_100x100 },
/* left inside, right outside, top = clip, bottom = clip */
{ &rgn300x300_100x100, &rgn350x300_200x100, &rgn350x300_50x100 },
/* top outside, bottom = clip, left = clip, right = clip */
{ &rgn300x300_100x100, &rgn300x100_300x300, &rgn300x300_100x100 },
/* top = clip, bottom outside, left = clip, right = clip */
{ &rgn300x300_100x100, &rgn300x300_300x200, &rgn300x300_100x100 },
/* top = clip, bottom = clip, top = clip, bottom = clip */
{ &rgn300x300_100x100, &rgn300x300_100x100, &rgn300x300_100x100 }
};
for (size_t x = 0; x < ARRAYSIZE(testcases); x++)
{
const struct testcase_t* cur = &testcases[x];
if (!test_gdi_coords(x, hdc, cur->clip, cur->in, cur->expect))
goto fail;
}
rc = 0;
fail:
gdi_DeleteObject((HGDIOBJECT)bmp);
gdi_DeleteDC(hdc);
return rc;
}
static int test_gdi_InvalidateRegion(void)
{
int rc = -1;
HGDI_DC hdc = nullptr;
HGDI_RGN rgn1 = nullptr;
HGDI_RGN rgn2 = nullptr;
HGDI_RGN invalid = nullptr;
HGDI_BITMAP bmp = nullptr;
const UINT32 format = PIXEL_FORMAT_XRGB32;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
return -1;
}
hdc->format = format;
bmp = gdi_CreateBitmapEx(1024, 768, PIXEL_FORMAT_XRGB32, 0, nullptr, nullptr);
gdi_SelectObject(hdc, (HGDIOBJECT)bmp);
gdi_SetNullClipRgn(hdc);
hdc->hwnd = (HGDI_WND)calloc(1, sizeof(GDI_WND));
hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0);
hdc->hwnd->invalid->null = TRUE;
invalid = hdc->hwnd->invalid;
hdc->hwnd->count = 16;
hdc->hwnd->cinvalid = (HGDI_RGN)calloc(hdc->hwnd->count, sizeof(GDI_RGN));
rgn1 = gdi_CreateRectRgn(0, 0, 0, 0);
rgn2 = gdi_CreateRectRgn(0, 0, 0, 0);
rgn1->null = TRUE;
rgn2->null = TRUE;
/* no previous invalid region */
invalid->null = TRUE;
gdi_SetRgn(rgn1, 300, 300, 100, 100);
gdi_SetRgn(rgn2, 300, 300, 100, 100);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* region same as invalid region */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 300, 300, 100, 100);
gdi_SetRgn(rgn2, 300, 300, 100, 100);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* left outside */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 100, 300, 300, 100);
gdi_SetRgn(rgn2, 100, 300, 300, 100);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* right outside */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 300, 300, 300, 100);
gdi_SetRgn(rgn2, 300, 300, 300, 100);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* top outside */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 300, 100, 100, 300);
gdi_SetRgn(rgn2, 300, 100, 100, 300);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* bottom outside */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 300, 300, 100, 300);
gdi_SetRgn(rgn2, 300, 300, 100, 300);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* left outside, right outside */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 100, 300, 600, 300);
gdi_SetRgn(rgn2, 100, 300, 600, 300);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* top outside, bottom outside */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 300, 100, 100, 500);
gdi_SetRgn(rgn2, 300, 100, 100, 500);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* all outside, left */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 100, 300, 100, 100);
gdi_SetRgn(rgn2, 100, 300, 300, 100);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* all outside, right */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 700, 300, 100, 100);
gdi_SetRgn(rgn2, 300, 300, 500, 100);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* all outside, top */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 300, 100, 100, 100);
gdi_SetRgn(rgn2, 300, 100, 100, 300);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* all outside, bottom */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 300, 500, 100, 100);
gdi_SetRgn(rgn2, 300, 300, 100, 300);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* all outside */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 100, 100, 600, 600);
gdi_SetRgn(rgn2, 100, 100, 600, 600);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
/* everything */
gdi_SetRgn(invalid, 300, 300, 100, 100);
gdi_SetRgn(rgn1, 0, 0, 1024, 768);
gdi_SetRgn(rgn2, 0, 0, 1024, 768);
gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);
if (!gdi_EqualRgn(invalid, rgn2))
goto fail;
rc = 0;
fail:
gdi_DeleteObject((HGDIOBJECT)rgn1);
gdi_DeleteObject((HGDIOBJECT)rgn2);
gdi_DeleteObject((HGDIOBJECT)bmp);
gdi_DeleteDC(hdc);
return rc;
}
int TestGdiClip(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
(void)fprintf(stderr, "test_gdi_ClipCoords()\n");
if (test_gdi_ClipCoords() < 0)
return -1;
(void)fprintf(stderr, "test_gdi_InvalidateRegion()\n");
if (test_gdi_InvalidateRegion() < 0)
return -1;
return 0;
}

View File

@@ -0,0 +1,600 @@
#include <freerdp/gdi/gdi.h>
#include <freerdp/gdi/dc.h>
#include <freerdp/gdi/pen.h>
#include <freerdp/gdi/region.h>
#include <freerdp/gdi/bitmap.h>
#include <winpr/crt.h>
#include <winpr/crypto.h>
#include "line.h"
#include "brush.h"
#include "drawing.h"
static const UINT32 colorFormatList[] = {
PIXEL_FORMAT_RGB15, PIXEL_FORMAT_BGR15, PIXEL_FORMAT_RGB16, PIXEL_FORMAT_BGR16,
PIXEL_FORMAT_RGB24, PIXEL_FORMAT_BGR24, PIXEL_FORMAT_ARGB32, PIXEL_FORMAT_ABGR32,
PIXEL_FORMAT_XRGB32, PIXEL_FORMAT_XBGR32, PIXEL_FORMAT_RGBX32, PIXEL_FORMAT_BGRX32
};
static const UINT32 colorFormatCount = sizeof(colorFormatList) / sizeof(colorFormatList[0]);
static int test_gdi_GetDC(void)
{
int rc = -1;
HGDI_DC hdc = nullptr;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
return -1;
}
if (hdc->format != PIXEL_FORMAT_XRGB32)
goto fail;
if (hdc->drawMode != GDI_R2_BLACK)
goto fail;
rc = 0;
fail:
gdi_DeleteDC(hdc);
return rc;
}
static int test_gdi_CreateCompatibleDC(void)
{
int rc = -1;
HGDI_DC hdc = nullptr;
HGDI_DC chdc = nullptr;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
return -1;
}
hdc->format = PIXEL_FORMAT_RGB16;
hdc->drawMode = GDI_R2_XORPEN;
if (!(chdc = gdi_CreateCompatibleDC(hdc)))
{
printf("gdi_CreateCompatibleDC failed\n");
goto fail;
}
if (chdc->format != hdc->format)
goto fail;
if (chdc->drawMode != hdc->drawMode)
goto fail;
rc = 0;
fail:
if (chdc)
gdi_DeleteDC(chdc);
gdi_DeleteDC(hdc);
return rc;
}
static int test_gdi_CreateBitmap(void)
{
int rc = -1;
UINT32 format = PIXEL_FORMAT_ARGB32;
INT32 width = 0;
INT32 height = 0;
BYTE* data = nullptr;
HGDI_BITMAP hBitmap = nullptr;
width = 32;
height = 16;
if (!(data = (BYTE*)winpr_aligned_malloc(4ULL * width * height, 16)))
{
printf("failed to allocate aligned bitmap data memory\n");
return -1;
}
if (!(hBitmap = gdi_CreateBitmap(width, height, format, data)))
{
printf("gdi_CreateBitmap failed\n");
goto fail;
}
if (hBitmap->objectType != GDIOBJECT_BITMAP)
goto fail;
if (hBitmap->format != format)
goto fail;
if (hBitmap->width != width)
goto fail;
if (hBitmap->height != height)
goto fail;
if (hBitmap->data != data)
goto fail;
rc = 0;
fail:
if (hBitmap)
gdi_DeleteObject((HGDIOBJECT)hBitmap);
else
winpr_aligned_free(data);
return rc;
}
static int test_gdi_CreateCompatibleBitmap(void)
{
int rc = -1;
HGDI_DC hdc = nullptr;
INT32 width = 0;
INT32 height = 0;
HGDI_BITMAP hBitmap = nullptr;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
return -1;
}
hdc->format = PIXEL_FORMAT_ARGB32;
width = 32;
height = 16;
hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height);
if (hBitmap->objectType != GDIOBJECT_BITMAP)
goto fail;
if (hBitmap->format != hdc->format)
goto fail;
if (hBitmap->width != width)
goto fail;
if (hBitmap->height != height)
goto fail;
if (!hBitmap->data)
goto fail;
rc = 0;
fail:
if (hBitmap)
gdi_DeleteObject((HGDIOBJECT)hBitmap);
gdi_DeleteDC(hdc);
return rc;
}
static int test_gdi_CreatePen(void)
{
int rc = -1;
const UINT32 format = PIXEL_FORMAT_RGBA32;
HGDI_PEN hPen = gdi_CreatePen(GDI_PS_SOLID, 8, 0xAABBCCDD, format, nullptr);
if (!hPen)
{
printf("gdi_CreatePen failed\n");
return -1;
}
if (hPen->style != GDI_PS_SOLID)
goto fail;
if (hPen->width != 8)
goto fail;
if (hPen->color != 0xAABBCCDD)
goto fail;
rc = 0;
fail:
gdi_DeleteObject((HGDIOBJECT)hPen);
return rc;
}
static int test_gdi_CreateSolidBrush(void)
{
int rc = -1;
HGDI_BRUSH hBrush = gdi_CreateSolidBrush(0xAABBCCDD);
if (hBrush->objectType != GDIOBJECT_BRUSH)
goto fail;
if (hBrush->style != GDI_BS_SOLID)
goto fail;
if (hBrush->color != 0xAABBCCDD)
goto fail;
rc = 0;
fail:
gdi_DeleteObject((HGDIOBJECT)hBrush);
return rc;
}
static int test_gdi_CreatePatternBrush(void)
{
int rc = -1;
HGDI_BRUSH hBrush = nullptr;
HGDI_BITMAP hBitmap = nullptr;
hBitmap = gdi_CreateBitmap(64, 64, 32, nullptr);
hBrush = gdi_CreatePatternBrush(hBitmap);
if (!hBitmap || !hBrush)
goto fail;
if (hBrush->objectType != GDIOBJECT_BRUSH)
goto fail;
if (hBrush->style != GDI_BS_PATTERN)
goto fail;
if (hBrush->pattern != hBitmap)
goto fail;
rc = 0;
fail:
if (hBitmap)
gdi_DeleteObject((HGDIOBJECT)hBitmap);
if (hBrush)
gdi_DeleteObject((HGDIOBJECT)hBrush);
return rc;
}
static int test_gdi_CreateRectRgn(void)
{
int rc = -1;
INT32 x1 = 32;
INT32 y1 = 64;
INT32 x2 = 128;
INT32 y2 = 256;
HGDI_RGN hRegion = gdi_CreateRectRgn(x1, y1, x2, y2);
if (!hRegion)
return rc;
if (hRegion->objectType != GDIOBJECT_REGION)
goto fail;
if (hRegion->x != x1)
goto fail;
if (hRegion->y != y1)
goto fail;
if (hRegion->w != x2 - x1 + 1)
goto fail;
if (hRegion->h != y2 - y1 + 1)
goto fail;
if (hRegion->null)
goto fail;
rc = 0;
fail:
gdi_DeleteObject((HGDIOBJECT)hRegion);
return rc;
}
static int test_gdi_CreateRect(void)
{
int rc = -1;
GDI_RECT* hRect = nullptr;
INT32 x1 = 32;
INT32 y1 = 64;
INT32 x2 = 128;
INT32 y2 = 256;
if (!(hRect = gdi_CreateRect(x1, y1, x2, y2)))
{
printf("gdi_CreateRect failed\n");
return -1;
}
if (hRect->objectType != GDIOBJECT_RECT)
goto fail;
if (hRect->left != x1)
goto fail;
if (hRect->top != y1)
goto fail;
if (hRect->right != x2)
goto fail;
if (hRect->bottom != y2)
goto fail;
rc = 0;
fail:
gdi_DeleteObject((HGDIOBJECT)hRect);
return rc;
}
static BYTE prand(void)
{
BYTE tmp = 0;
if (winpr_RAND(&tmp, sizeof(tmp)) < 0)
{
(void)fprintf(stderr, "winpr_RAND faild,retry...\n");
// NOLINTNEXTLINE(concurrency-mt-unsafe)
exit(-1);
}
return tmp;
}
static BOOL test_gdi_GetPixel(void)
{
BOOL rc = TRUE;
for (UINT32 x = 0; x < colorFormatCount; x++)
{
UINT32 bpp = 0;
HGDI_DC hdc = nullptr;
UINT32 width = 128;
UINT32 height = 64;
HGDI_BITMAP hBitmap = nullptr;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
return -1;
}
hdc->format = colorFormatList[x];
hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height);
if (!hBitmap)
{
gdi_DeleteDC(hdc);
return -1;
}
gdi_SelectObject(hdc, (HGDIOBJECT)hBitmap);
bpp = FreeRDPGetBytesPerPixel(hBitmap->format);
for (UINT32 i = 0; i < height; i++)
{
for (UINT32 j = 0; j < width; j++)
{
UINT32 pixel = 0;
const UINT32 color =
FreeRDPGetColor(hBitmap->format, prand(), prand(), prand(), prand());
FreeRDPWriteColor(&hBitmap->data[i * hBitmap->scanline + j * bpp], hBitmap->format,
color);
pixel = gdi_GetPixel(hdc, j, i);
if (pixel != color)
{
rc = FALSE;
break;
}
}
if (!rc)
break;
}
gdi_DeleteObject((HGDIOBJECT)hBitmap);
gdi_DeleteDC(hdc);
}
return rc;
}
static BOOL test_gdi_SetPixel(void)
{
BOOL rc = TRUE;
for (UINT32 x = 0; x < colorFormatCount; x++)
{
UINT32 bpp = 0;
HGDI_DC hdc = nullptr;
UINT32 width = 128;
UINT32 height = 64;
HGDI_BITMAP hBitmap = nullptr;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
return FALSE;
}
hdc->format = colorFormatList[x];
hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height);
gdi_SelectObject(hdc, (HGDIOBJECT)hBitmap);
bpp = FreeRDPGetBytesPerPixel(hBitmap->format);
for (UINT32 i = 0; i < height; i++)
{
for (UINT32 j = 0; j < width; j++)
{
UINT32 pixel = 0;
const UINT32 color =
FreeRDPGetColor(hBitmap->format, prand(), prand(), prand(), prand());
gdi_SetPixel(hdc, j, i, color);
pixel = FreeRDPReadColor(&hBitmap->data[i * hBitmap->scanline + j * bpp],
hBitmap->format);
if (pixel != color)
{
rc = FALSE;
break;
}
}
if (!rc)
break;
}
gdi_DeleteObject((HGDIOBJECT)hBitmap);
gdi_DeleteDC(hdc);
}
return rc;
}
static int test_gdi_SetROP2(void)
{
int rc = -1;
HGDI_DC hdc = nullptr;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
return -1;
}
gdi_SetROP2(hdc, GDI_R2_BLACK);
if (hdc->drawMode != GDI_R2_BLACK)
goto fail;
rc = 0;
fail:
gdi_DeleteDC(hdc);
return rc;
}
static int test_gdi_MoveToEx(void)
{
int rc = -1;
HGDI_DC hdc = nullptr;
HGDI_PEN hPen = nullptr;
HGDI_POINT prevPoint = nullptr;
const UINT32 format = PIXEL_FORMAT_RGBA32;
gdiPalette* palette = nullptr;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
return -1;
}
if (!(hPen = gdi_CreatePen(GDI_PS_SOLID, 8, 0xAABBCCDD, format, palette)))
{
printf("gdi_CreatePen failed\n");
goto fail;
}
gdi_SelectObject(hdc, (HGDIOBJECT)hPen);
gdi_MoveToEx(hdc, 128, 256, nullptr);
if (hdc->pen->posX != 128)
goto fail;
if (hdc->pen->posY != 256)
goto fail;
prevPoint = (HGDI_POINT)malloc(sizeof(GDI_POINT));
ZeroMemory(prevPoint, sizeof(GDI_POINT));
gdi_MoveToEx(hdc, 64, 128, prevPoint);
if (prevPoint->x != 128)
goto fail;
if (prevPoint->y != 256)
goto fail;
if (hdc->pen->posX != 64)
goto fail;
if (hdc->pen->posY != 128)
goto fail;
rc = 0;
fail:
if (hPen)
gdi_DeleteObject((HGDIOBJECT)hPen);
free(prevPoint);
gdi_DeleteDC(hdc);
return rc;
}
int TestGdiCreate(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
(void)fprintf(stderr, "test_gdi_GetDC()\n");
if (test_gdi_GetDC() < 0)
return -1;
(void)fprintf(stderr, "test_gdi_CreateCompatibleDC()\n");
if (test_gdi_CreateCompatibleDC() < 0)
return -1;
(void)fprintf(stderr, "test_gdi_CreateBitmap()\n");
if (test_gdi_CreateBitmap() < 0)
return -1;
(void)fprintf(stderr, "test_gdi_CreateCompatibleBitmap()\n");
if (test_gdi_CreateCompatibleBitmap() < 0)
return -1;
(void)fprintf(stderr, "test_gdi_CreatePen()\n");
if (test_gdi_CreatePen() < 0)
return -1;
(void)fprintf(stderr, "test_gdi_CreateSolidBrush()\n");
if (test_gdi_CreateSolidBrush() < 0)
return -1;
(void)fprintf(stderr, "test_gdi_CreatePatternBrush()\n");
if (test_gdi_CreatePatternBrush() < 0)
return -1;
(void)fprintf(stderr, "test_gdi_CreateRectRgn()\n");
if (test_gdi_CreateRectRgn() < 0)
return -1;
(void)fprintf(stderr, "test_gdi_CreateRect()\n");
if (test_gdi_CreateRect() < 0)
return -1;
(void)fprintf(stderr, "test_gdi_GetPixel()\n");
if (!test_gdi_GetPixel())
return -1;
(void)fprintf(stderr, "test_gdi_SetPixel()\n");
if (!test_gdi_SetPixel())
return -1;
(void)fprintf(stderr, "test_gdi_SetROP2()\n");
if (test_gdi_SetROP2() < 0)
return -1;
(void)fprintf(stderr, "test_gdi_MoveToEx()\n");
if (test_gdi_MoveToEx() < 0)
return -1;
return 0;
}

View File

@@ -0,0 +1,169 @@
#include <freerdp/gdi/gdi.h>
#include <freerdp/gdi/dc.h>
#include <freerdp/gdi/pen.h>
#include <freerdp/gdi/shape.h>
#include <freerdp/gdi/region.h>
#include <freerdp/gdi/bitmap.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include "line.h"
#include "brush.h"
#include "clipping.h"
#include "helpers.h"
/* Ellipse() Test Data */
static const BYTE ellipse_case_1[256] = {
"\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE ellipse_case_2[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE ellipse_case_3[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF"
"\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
int TestGdiEllipse(int argc, char* argv[])
{
int rc = -1;
const UINT32 RawFormat = PIXEL_FORMAT_RGB8;
const UINT32 colorFormats[] = { PIXEL_FORMAT_RGB15, PIXEL_FORMAT_ARGB15, PIXEL_FORMAT_RGB16,
PIXEL_FORMAT_RGB24, PIXEL_FORMAT_ARGB32, PIXEL_FORMAT_XRGB32,
PIXEL_FORMAT_RGBA32, PIXEL_FORMAT_RGBX32, PIXEL_FORMAT_BGR15,
PIXEL_FORMAT_ABGR15, PIXEL_FORMAT_BGR16, PIXEL_FORMAT_BGR24,
PIXEL_FORMAT_ABGR32, PIXEL_FORMAT_XBGR32, PIXEL_FORMAT_BGRA32,
PIXEL_FORMAT_BGRX32 };
const UINT32 number_formats = sizeof(colorFormats) / sizeof(colorFormats[0]);
gdiPalette g;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
for (UINT32 i = 0; i < number_formats; i++)
{
HGDI_DC hdc = nullptr;
HGDI_PEN pen = nullptr;
HGDI_BITMAP hBmp = nullptr;
HGDI_BITMAP hBmp_Ellipse_1 = nullptr;
HGDI_BITMAP hBmp_Ellipse_2 = nullptr;
HGDI_BITMAP hBmp_Ellipse_3 = nullptr;
const UINT32 format = colorFormats[i];
gdiPalette* hPalette = &g;
g.format = format;
for (UINT32 j = 0; j < 256; j++)
g.palette[i] = FreeRDPGetColor(format, j, j, j, 0xFF);
rc = -1;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
goto fail;
}
hdc->format = format;
gdi_SetNullClipRgn(hdc);
if (!(pen = gdi_CreatePen(1, 1, 0, format, hPalette)))
{
printf("gdi_CreatePen failed\n");
goto fail;
}
gdi_SelectObject(hdc, (HGDIOBJECT)pen);
hBmp = gdi_CreateCompatibleBitmap(hdc, 16, 16);
gdi_SelectObject(hdc, (HGDIOBJECT)hBmp);
hBmp_Ellipse_1 = test_convert_to_bitmap(ellipse_case_1, RawFormat, 0, 0, 0, format, 0, 0, 0,
16, 16, hPalette);
if (!hBmp_Ellipse_1)
goto fail;
hBmp_Ellipse_2 = test_convert_to_bitmap(ellipse_case_2, RawFormat, 0, 0, 0, format, 0, 0, 0,
16, 16, hPalette);
if (!hBmp_Ellipse_2)
goto fail;
hBmp_Ellipse_3 = test_convert_to_bitmap(ellipse_case_3, RawFormat, 0, 0, 0, format, 0, 0, 0,
16, 16, hPalette);
if (!hBmp_Ellipse_3)
goto fail;
/* Test Case 1: (0,0) -> (16, 16) */
if (!gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS, hPalette))
{
printf("gdi_BitBlt failed (line #%u)\n", __LINE__);
goto fail;
}
if (!gdi_Ellipse(hdc, 0, 0, 15, 15))
goto fail;
rc = 0;
fail:
gdi_DeleteObject((HGDIOBJECT)hBmp_Ellipse_1);
gdi_DeleteObject((HGDIOBJECT)hBmp_Ellipse_2);
gdi_DeleteObject((HGDIOBJECT)hBmp_Ellipse_3);
gdi_DeleteObject((HGDIOBJECT)hBmp);
gdi_DeleteObject((HGDIOBJECT)pen);
gdi_DeleteDC(hdc);
if (rc != 0)
break;
}
return rc;
}

View File

@@ -0,0 +1,724 @@
#include <freerdp/gdi/gdi.h>
#include <freerdp/gdi/dc.h>
#include <freerdp/gdi/pen.h>
#include <freerdp/gdi/region.h>
#include <freerdp/gdi/bitmap.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include "line.h"
#include "brush.h"
#include "clipping.h"
#include "drawing.h"
#include "helpers.h"
/* LineTo() Test Data */
static const BYTE line_to_case_1[256] = {
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_case_2[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"
};
static const BYTE line_to_case_3[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_case_4[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_case_5[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_case_6[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_case_7[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_case_8[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_case_9[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_case_10[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_case_11[256] = {
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"
};
static const BYTE* line_to_case[] = { line_to_case_1, line_to_case_2, line_to_case_3,
line_to_case_4, line_to_case_5, line_to_case_6,
line_to_case_7, line_to_case_8, line_to_case_9,
line_to_case_10, line_to_case_11 };
static const BYTE line_to_R2_BLACK[256] = {
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"
};
static const BYTE line_to_R2_NOTMERGEPEN[256] = {
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"
};
static const BYTE line_to_R2_MASKNOTPEN[256] = {
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"
};
static const BYTE line_to_R2_NOTCOPYPEN[256] = {
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"
};
static const BYTE line_to_R2_MASKPENNOT[256] = {
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"
};
static const BYTE line_to_R2_NOT[256] = {
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"
};
static const BYTE line_to_R2_XORPEN[256] = {
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"
};
static const BYTE line_to_R2_NOTMASKPEN[256] = {
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00"
};
static const BYTE line_to_R2_MASKPEN[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_R2_NOTXORPEN[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_R2_NOP[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_R2_MERGENOTPEN[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_R2_COPYPEN[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_R2_MERGEPENNOT[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_R2_MERGEPEN[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
static const BYTE line_to_R2_WHITE[256] = {
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
};
#define LINTETO_NUMBER 11
struct ropMap
{
UINT32 rop;
HGDI_BITMAP bmp;
const BYTE* src;
};
static BOOL test_line(HGDI_DC hdc, const gdiPalette* hPalette, UINT32 mX, UINT32 mY, UINT32 lX,
UINT32 lY, HGDI_BITMAP hBmp, HGDI_BITMAP hOrgBmp, UINT32 cX, UINT32 cY,
UINT32 cW, UINT32 cH)
{
if (!gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS, hPalette))
return FALSE;
if ((cX > 0) || (cY > 0) || (cW > 0) || (cH > 0))
gdi_SetClipRgn(hdc, cX, cY, cW, cH);
gdi_MoveToEx(hdc, mX, mY, nullptr);
gdi_LineTo(hdc, lX, lY);
if (!test_assert_bitmaps_equal(hBmp, hOrgBmp, "Case 10", hPalette))
return FALSE;
return TRUE;
}
int TestGdiLine(int argc, char* argv[])
{
int rc = -1;
const UINT32 RawFormat = PIXEL_FORMAT_RGB8;
const UINT32 colorFormats[] = { PIXEL_FORMAT_RGB15, PIXEL_FORMAT_ARGB15, PIXEL_FORMAT_RGB16,
PIXEL_FORMAT_RGB24, PIXEL_FORMAT_ARGB32, PIXEL_FORMAT_XRGB32,
PIXEL_FORMAT_RGBA32, PIXEL_FORMAT_RGBX32, PIXEL_FORMAT_BGR15,
PIXEL_FORMAT_ABGR15, PIXEL_FORMAT_BGR16, PIXEL_FORMAT_BGR24,
PIXEL_FORMAT_ABGR32, PIXEL_FORMAT_XBGR32, PIXEL_FORMAT_BGRA32,
PIXEL_FORMAT_BGRX32 };
const size_t number_formats = sizeof(colorFormats) / sizeof(colorFormats[0]);
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
for (size_t ifmt = 0; ifmt < number_formats; ifmt++)
{
gdiPalette g = WINPR_C_ARRAY_INIT;
HGDI_DC hdc = nullptr;
HGDI_PEN pen = nullptr;
HGDI_BITMAP hBmp = nullptr;
struct ropMap rop_map[] = { { GDI_R2_BLACK, nullptr, line_to_R2_BLACK },
{ GDI_R2_NOTMERGEPEN, nullptr, line_to_R2_NOTMERGEPEN },
{ GDI_R2_MASKNOTPEN, nullptr, line_to_R2_MASKNOTPEN },
{ GDI_R2_NOTCOPYPEN, nullptr, line_to_R2_NOTCOPYPEN },
{ GDI_R2_MASKPENNOT, nullptr, line_to_R2_MASKPENNOT },
{ GDI_R2_NOT, nullptr, line_to_R2_NOT },
{ GDI_R2_XORPEN, nullptr, line_to_R2_XORPEN },
{ GDI_R2_NOTMASKPEN, nullptr, line_to_R2_NOTMASKPEN },
{ GDI_R2_MASKPEN, nullptr, line_to_R2_MASKPEN },
{ GDI_R2_NOTXORPEN, nullptr, line_to_R2_NOTXORPEN },
{ GDI_R2_NOP, nullptr, line_to_R2_NOP },
{ GDI_R2_MERGENOTPEN, nullptr, line_to_R2_MERGENOTPEN },
{ GDI_R2_COPYPEN, nullptr, line_to_R2_COPYPEN },
{ GDI_R2_MERGEPENNOT, nullptr, line_to_R2_MERGEPENNOT },
{ GDI_R2_MERGEPEN, nullptr, line_to_R2_MERGEPEN },
{ GDI_R2_WHITE, nullptr, line_to_R2_WHITE } };
const size_t map_size = sizeof(rop_map) / sizeof(rop_map[0]);
HGDI_BITMAP hBmp_LineTo[LINTETO_NUMBER] = { nullptr };
gdiPalette* hPalette = &g;
UINT32 penColor = 0;
const UINT32 format = colorFormats[ifmt];
g.format = format;
for (unsigned x = 0; x < 256; x++)
g.palette[x] = FreeRDPGetColor(format, x, x, x, 0xFF);
rc = -1;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
goto fail;
}
hdc->format = format;
gdi_SetNullClipRgn(hdc);
penColor = FreeRDPGetColor(format, 0xFF, 0xFF, 0xFF, 0xFF);
if (!(pen = gdi_CreatePen(1, 1, penColor, format, hPalette)))
{
printf("gdi_CreatePen failed\n");
goto fail;
}
gdi_SelectObject(hdc, (HGDIOBJECT)pen);
hBmp = gdi_CreateCompatibleBitmap(hdc, 16, 16);
gdi_SelectObject(hdc, (HGDIOBJECT)hBmp);
for (UINT32 x = 0; x < LINTETO_NUMBER; x++)
{
hBmp_LineTo[x] = test_convert_to_bitmap(line_to_case[x], RawFormat, 0, 0, 0, format, 0,
0, 0, 16, 16, hPalette);
if (!hBmp_LineTo[x])
goto fail;
}
for (UINT32 x = 0; x < map_size; x++)
{
rop_map[x].bmp = test_convert_to_bitmap(rop_map[x].src, RawFormat, 0, 0, 0, format, 0,
0, 0, 16, 16, hPalette);
if (!rop_map[x].bmp)
goto fail;
}
if (!test_line(hdc, hPalette, 0, 0, 15, 15, hBmp, hBmp_LineTo[0], 0, 0, 16, 16))
goto fail;
if (!test_line(hdc, hPalette, 15, 15, 0, 0, hBmp, hBmp_LineTo[1], 0, 0, 16, 16))
goto fail;
if (!test_line(hdc, hPalette, 15, 0, 0, 15, hBmp, hBmp_LineTo[2], 0, 0, 16, 16))
goto fail;
if (!test_line(hdc, hPalette, 0, 15, 15, 0, hBmp, hBmp_LineTo[3], 0, 0, 16, 16))
goto fail;
if (!test_line(hdc, hPalette, 0, 8, 15, 8, hBmp, hBmp_LineTo[4], 0, 0, 16, 16))
goto fail;
if (!test_line(hdc, hPalette, 15, 8, 0, 8, hBmp, hBmp_LineTo[5], 0, 0, 16, 16))
goto fail;
if (!test_line(hdc, hPalette, 8, 0, 8, 15, hBmp, hBmp_LineTo[6], 0, 0, 16, 16))
goto fail;
if (!test_line(hdc, hPalette, 8, 15, 8, 0, hBmp, hBmp_LineTo[7], 0, 0, 16, 16))
goto fail;
if (!test_line(hdc, hPalette, 4, 4, 12, 12, hBmp, hBmp_LineTo[8], 0, 0, 16, 16))
goto fail;
if (!test_line(hdc, hPalette, 0, 0, 16, 16, hBmp, hBmp_LineTo[9], 5, 5, 8, 8))
goto fail;
if (!test_line(hdc, hPalette, 0, 0, 26, 26, hBmp, hBmp_LineTo[10], 0, 0, 16, 16))
goto fail;
for (UINT32 x = 0; x < map_size; x++)
{
char name[1024] = WINPR_C_ARRAY_INIT;
_snprintf(name, sizeof(name), "%s [%s]", gdi_rop_to_string(rop_map[x].rop),
FreeRDPGetColorFormatName(hdc->format));
/* Test Case 13: (0,0) -> (16,16), R2_NOTMERGEPEN */
if (!gdi_BitBlt(hdc, 0, 0, 16, 16, hdc, 0, 0, GDI_WHITENESS, hPalette))
{
printf("gdi_BitBlt failed (line #%u)\n", __LINE__);
goto fail;
}
gdi_SetClipRgn(hdc, 0, 0, 16, 16);
gdi_MoveToEx(hdc, 0, 0, nullptr);
gdi_SetROP2(hdc, rop_map[x].rop);
gdi_LineTo(hdc, 16, 16);
if (!test_assert_bitmaps_equal(hBmp, rop_map[x].bmp, name, hPalette))
goto fail;
}
rc = 0;
fail:
for (UINT32 x = 0; x < LINTETO_NUMBER; x++)
gdi_DeleteObject((HGDIOBJECT)hBmp_LineTo[x]);
for (UINT32 x = 0; x < map_size; x++)
gdi_DeleteObject((HGDIOBJECT)rop_map[x].bmp);
gdi_DeleteObject((HGDIOBJECT)hBmp);
gdi_DeleteObject((HGDIOBJECT)pen);
gdi_DeleteDC(hdc);
if (rc != 0)
break;
}
return rc;
}

View File

@@ -0,0 +1,175 @@
#include <freerdp/gdi/gdi.h>
#include <freerdp/gdi/dc.h>
#include <freerdp/gdi/pen.h>
#include <freerdp/gdi/shape.h>
#include <freerdp/gdi/region.h>
#include <freerdp/gdi/bitmap.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include "line.h"
#include "brush.h"
#include "clipping.h"
static int test_gdi_PtInRect(void)
{
int rc = -1;
GDI_RECT* hRect = nullptr;
UINT32 left = 20;
UINT32 top = 40;
UINT32 right = 60;
UINT32 bottom = 80;
if (!(hRect = gdi_CreateRect(
WINPR_ASSERTING_INT_CAST(int, left), WINPR_ASSERTING_INT_CAST(int, top),
WINPR_ASSERTING_INT_CAST(int, right), WINPR_ASSERTING_INT_CAST(int, bottom))))
{
printf("gdi_CreateRect failed\n");
return rc;
}
if (gdi_PtInRect(hRect, 0, 0))
goto fail;
if (gdi_PtInRect(hRect, 500, 500))
goto fail;
if (gdi_PtInRect(hRect, 40, 100))
goto fail;
if (gdi_PtInRect(hRect, 10, 40))
goto fail;
if (!gdi_PtInRect(hRect, 30, 50))
goto fail;
if (!gdi_PtInRect(hRect, WINPR_ASSERTING_INT_CAST(int, left),
WINPR_ASSERTING_INT_CAST(int, top)))
goto fail;
if (!gdi_PtInRect(hRect, WINPR_ASSERTING_INT_CAST(int, right),
WINPR_ASSERTING_INT_CAST(int, bottom)))
goto fail;
if (!gdi_PtInRect(hRect, WINPR_ASSERTING_INT_CAST(int, right), 60))
goto fail;
if (!gdi_PtInRect(hRect, 40, WINPR_ASSERTING_INT_CAST(int, bottom)))
goto fail;
rc = 0;
fail:
gdi_DeleteObject((HGDIOBJECT)hRect);
return rc;
}
static int test_gdi_FillRect(void)
{
int rc = -1;
HGDI_DC hdc = nullptr;
GDI_RECT* hRect = nullptr;
HGDI_BRUSH hBrush = nullptr;
HGDI_BITMAP hBitmap = nullptr;
UINT32 color = 0;
UINT32 pixel = 0;
UINT32 rawPixel = 0;
UINT32 badPixels = 0;
UINT32 goodPixels = 0;
UINT32 width = 200;
UINT32 height = 300;
UINT32 left = 20;
UINT32 top = 40;
UINT32 right = 60;
UINT32 bottom = 80;
if (!(hdc = gdi_GetDC()))
{
printf("failed to get gdi device context\n");
goto fail;
}
hdc->format = PIXEL_FORMAT_XRGB32;
if (!(hRect = gdi_CreateRect(
WINPR_ASSERTING_INT_CAST(int, left), WINPR_ASSERTING_INT_CAST(int, top),
WINPR_ASSERTING_INT_CAST(int, right), WINPR_ASSERTING_INT_CAST(int, bottom))))
{
printf("gdi_CreateRect failed\n");
goto fail;
}
hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height);
ZeroMemory(hBitmap->data, 1ULL * width * height * FreeRDPGetBytesPerPixel(hdc->format));
gdi_SelectObject(hdc, (HGDIOBJECT)hBitmap);
color = FreeRDPGetColor(PIXEL_FORMAT_ARGB32, 0xAA, 0xBB, 0xCC, 0xFF);
hBrush = gdi_CreateSolidBrush(color);
gdi_FillRect(hdc, hRect, hBrush);
badPixels = 0;
goodPixels = 0;
for (UINT32 x = 0; x < width; x++)
{
for (UINT32 y = 0; y < height; y++)
{
rawPixel = gdi_GetPixel(hdc, x, y);
pixel = FreeRDPConvertColor(rawPixel, hdc->format, PIXEL_FORMAT_ARGB32, nullptr);
if (gdi_PtInRect(hRect, WINPR_ASSERTING_INT_CAST(int, x),
WINPR_ASSERTING_INT_CAST(int, y)))
{
if (pixel == color)
{
goodPixels++;
}
else
{
printf("actual:%08" PRIX32 " expected:%08" PRIX32 "\n", gdi_GetPixel(hdc, x, y),
color);
badPixels++;
}
}
else
{
if (pixel == color)
{
badPixels++;
}
else
{
goodPixels++;
}
}
}
}
if (goodPixels != width * height)
goto fail;
if (badPixels != 0)
goto fail;
rc = 0;
fail:
gdi_DeleteObject((HGDIOBJECT)hBrush);
gdi_DeleteObject((HGDIOBJECT)hBitmap);
gdi_DeleteObject((HGDIOBJECT)hRect);
gdi_DeleteDC(hdc);
return rc;
}
int TestGdiRect(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
if (test_gdi_PtInRect() < 0)
return -1;
if (test_gdi_FillRect() < 0)
return -1;
return 0;
}

View File

@@ -0,0 +1,256 @@
#include <freerdp/gdi/gdi.h>
#include <freerdp/gdi/dc.h>
#include <freerdp/gdi/pen.h>
#include <freerdp/gdi/region.h>
#include <freerdp/gdi/bitmap.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include "helpers.h"
int TestGdiRegion(int argc, char* argv[])
{
int rc = -1;
INT32 x = 0;
INT32 y = 0;
INT32 w = 0;
INT32 h = 0;
INT32 l = 0;
INT32 r = 0;
INT32 t = 0;
INT32 b = 0;
HGDI_RGN rgn1 = nullptr;
HGDI_RGN rgn2 = nullptr;
GDI_RECT* rect1 = nullptr;
GDI_RECT* rect2 = nullptr;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
rgn1 = gdi_CreateRectRgn(111, 2, 65, 77);
rect1 = gdi_CreateRect(2311, 11, 42, 17);
if (rgn1 || rect1)
goto fail;
rgn1 = gdi_CreateRectRgn(1, 2, 65, 77);
rgn2 = gdi_CreateRectRgn(11, 2, 65, 77);
rect1 = gdi_CreateRect(23, 11, 42, 17);
rect2 = gdi_CreateRect(23, 11, 42, 17);
if (!rgn1 || !rgn2 || !rect1 || !rect2)
goto fail;
if (!gdi_RectToRgn(rect1, rgn1))
goto fail;
if (rgn1->x != rect1->left)
goto fail;
if (rgn1->y != rect1->top)
goto fail;
if (rgn1->w != (rect1->right - rect1->left + 1))
goto fail;
if (rgn1->h != (rect1->bottom - rect1->top + 1))
goto fail;
if (gdi_CRectToRgn(1123, 111, 333, 444, rgn2))
goto fail;
if (gdi_CRectToRgn(123, 1111, 333, 444, rgn2))
goto fail;
if (!gdi_CRectToRgn(123, 111, 333, 444, rgn2))
goto fail;
if (rgn2->x != 123)
goto fail;
if (rgn2->y != 111)
goto fail;
if (rgn2->w != (333 - 123 + 1))
goto fail;
if (rgn2->h != (444 - 111 + 1))
goto fail;
if (!gdi_RectToCRgn(rect1, &x, &y, &w, &h))
goto fail;
if (rect1->left != x)
goto fail;
if (rect1->top != y)
goto fail;
if (rect1->right != (x + w - 1))
goto fail;
if (rect1->bottom != (y + h - 1))
goto fail;
w = 23;
h = 42;
if (gdi_CRectToCRgn(1, 2, 0, 4, &x, &y, &w, &h))
goto fail;
if ((w != 0) || (h != 0))
goto fail;
w = 23;
h = 42;
if (gdi_CRectToCRgn(1, 2, 3, 1, &x, &y, &w, &h))
goto fail;
if ((w != 0) || (h != 0))
goto fail;
w = 23;
h = 42;
if (!gdi_CRectToCRgn(1, 2, 3, 4, &x, &y, &w, &h))
goto fail;
if (x != 1)
goto fail;
if (y != 2)
goto fail;
if (w != (3 - 1 + 1))
goto fail;
if (h != (4 - 2 + 1))
goto fail;
if (!gdi_RgnToRect(rgn1, rect2))
goto fail;
if (rgn1->x != rect2->left)
goto fail;
if (rgn1->y != rect2->top)
goto fail;
if (rgn1->w != (rect2->right - rect2->left + 1))
goto fail;
if (rgn1->h != (rect2->bottom - rect2->top + 1))
goto fail;
if (gdi_CRgnToRect(1, 2, 0, 4, rect2))
goto fail;
if (gdi_CRgnToRect(1, 2, -1, 4, rect2))
goto fail;
if (gdi_CRgnToRect(1, 2, 3, 0, rect2))
goto fail;
if (gdi_CRgnToRect(1, 2, 3, -1, rect2))
goto fail;
if (!gdi_CRgnToRect(1, 2, 3, 4, rect2))
goto fail;
if (rect2->left != 1)
goto fail;
if (rect2->right != (1 + 3 - 1))
goto fail;
if (rect2->top != 2)
goto fail;
if (rect2->bottom != (2 + 4 - 1))
goto fail;
if (!gdi_RgnToCRect(rgn1, &l, &t, &r, &b))
goto fail;
if (rgn1->x != l)
goto fail;
if (rgn1->y != t)
goto fail;
if (rgn1->w != (r - l + 1))
goto fail;
if (rgn1->h != (b - t + 1))
goto fail;
if (gdi_CRgnToCRect(1, 2, -1, 4, &l, &t, &r, &b))
goto fail;
if (gdi_CRgnToCRect(1, 2, 0, 4, &l, &t, &r, &b))
goto fail;
if (gdi_CRgnToCRect(1, 2, 3, -1, &l, &t, &r, &b))
goto fail;
if (gdi_CRgnToCRect(1, 2, 3, -0, &l, &t, &r, &b))
goto fail;
if (!gdi_CRgnToCRect(1, 2, 3, 4, &l, &t, &r, &b))
goto fail;
if (l != 1)
goto fail;
if (t != 2)
goto fail;
if (r != (1 + 3 - 1))
goto fail;
if (b != 2 + 4 - 1)
goto fail;
if (gdi_CopyOverlap(1, 2, 5, 3, -5, 3))
goto fail;
if (gdi_CopyOverlap(1, 2, 5, 3, 3, -2))
goto fail;
if (!gdi_CopyOverlap(1, 2, 5, 3, 2, 3))
goto fail;
if (gdi_SetRect(rect2, -4, 500, 66, -5))
goto fail;
if (gdi_SetRect(rect2, -4, -500, -66, -5))
goto fail;
if (!gdi_SetRect(rect2, -4, 500, 66, 754))
goto fail;
if (gdi_SetRgn(nullptr, -23, -42, 33, 99))
goto fail;
if (gdi_SetRgn(rgn2, -23, -42, -33, 99))
goto fail;
if (gdi_SetRgn(rgn2, -23, -42, 33, -99))
goto fail;
if (!gdi_SetRgn(rgn2, -23, -42, 33, 99))
goto fail;
if (rgn2->x != -23)
goto fail;
if (rgn2->y != -42)
goto fail;
if (rgn2->w != 33)
goto fail;
if (rgn2->h != 99)
goto fail;
if (rgn2->null)
goto fail;
if (gdi_SetRectRgn(nullptr, 33, 22, 44, 33))
goto fail;
if (gdi_SetRectRgn(rgn1, 331, 22, 44, 33))
goto fail;
if (gdi_SetRectRgn(rgn1, 33, 122, 44, 33))
goto fail;
if (!gdi_SetRectRgn(rgn1, 33, 22, 44, 33))
goto fail;
if (rgn1->x != 33)
goto fail;
if (rgn1->y != 22)
goto fail;
if (rgn1->w != (44 - 33 + 1))
goto fail;
if (rgn1->h != (33 - 22 + 1))
goto fail;
if (gdi_EqualRgn(rgn1, rgn2))
goto fail;
if (!gdi_EqualRgn(rgn1, rgn1))
goto fail;
if (gdi_CopyRect(rect1, nullptr))
goto fail;
if (gdi_CopyRect(nullptr, rect1))
goto fail;
if (gdi_CopyRect(nullptr, nullptr))
goto fail;
if (!gdi_CopyRect(rect1, rect2))
goto fail;
if (rect1->left != rect2->left)
goto fail;
if (rect1->top != rect2->top)
goto fail;
if (rect1->right != rect2->right)
goto fail;
if (rect1->bottom != rect2->bottom)
goto fail;
if (gdi_PtInRect(rect1, -23, 550))
goto fail;
if (gdi_PtInRect(rect1, 2, 3))
goto fail;
if (!gdi_PtInRect(rect1, 2, 550))
goto fail;
// BOOL gdi_InvalidateRegion(HGDI_DC hdc, INT32 x, INT32 y, INT32 w, INT32 h);
rc = 0;
fail:
free(rgn1);
free(rgn2);
free(rect1);
free(rect2);
return rc;
}

View File

@@ -0,0 +1,219 @@
#include <winpr/crt.h>
#include <winpr/winpr.h>
#include <winpr/collections.h>
/**
* Ternary Raster Operations:
* See "Windows Graphics Programming: Win32 GDI and DirectDraw", chapter 11. Advanced Bitmap
* Graphics
*
* Operators:
*
* AND & a
* OR | o
* NOT ~ n
* XOR ^ x
*
* Operands:
*
* Pen/Brush P
* Destination D
* Source S
*
* Example:
*
* Raster operation which returns P if S is 1 or D otherwise:
* (rop_S & rop_P) | (~rop_S & rop_D); -> 0xE2 (0x00E20746)
*
* Postfix notation: DSPDxax
* Infix notation: D^(S&(P^D))), (S&P)|(~S&D)
*
* DSPDxax using D^(S&(P^D)):
*
* mov eax, P // P
* xor eax, D // P^D
* and eax, S // S&(P^D)
* xor eax, D // D^(S&(P^D))
* mov D, eax // write result
*
* DSPDxax using (S&P)|(~S&D):
*
* mov eax, S // S
* and eax, P // S&P
* mov ebx, S // S
* not ebx // ~S
* and ebx, D // ~D&D
* or eax, ebx // (S&P)|(~S&D)
* mov D, eax // write result
*
* Raster operation lower word encoding:
*
* _______________________________________________________________________________
* | | | | | | | | | | | | | | | | |
* | Op5 | Op4 | Op3 | Op2 | Op1 | Not| Parse String | Offset |
* |____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|
* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
*
* Operator:
* 0: NOT
* 1: XOR
* 2: OR
* 3: AND
*
* Parse String:
* 0: SPDDDDDD
* 1: SPDSPDSP
* 2: SDPSDPSD
* 3: DDDDDDDD
* 4: DDDDDDDD
* 5: S+SP-DSS
* 6: S+SP-PDS
* 7: S+SD-PDS
*
* The lower word for 0x00E20746 is 0x0746 (00000111 01000110)
*
* 00 Op5 (NOT, n)
* 00 Op4 (NOT, n)
* 01 Op3 (XOR, x)
* 11 Op2 (AND, a)
* 01 Op1 (XOR, x)
* 0 Not (unused)
* 001 String (SPDSPDSP)
* 10 Offset (2)
*
* We shift SPDSPDSP to the left by 2: DSPDSPSP
*
* We have 5 operators: 3 binary operators and the last two are unary operators,
* so only four operands are needed. The parse string is truncated to reflect
* the number of operands we need: DSPD
*
* The operator string (from Op1 to Op5) is xaxnn, which can be simplified to xax
*
* The complete string representing the operation is DSPDxax
*
*/
static char* gdi_convert_postfix_to_infix(const char* postfix)
{
BOOL unary = 0;
size_t al = 0;
size_t bl = 0;
wStack* stack = Stack_New(FALSE);
size_t length = strlen(postfix);
for (size_t i = 0; i < length; i++)
{
BOOL success = FALSE;
if ((postfix[i] == 'P') || (postfix[i] == 'D') || (postfix[i] == 'S'))
{
/* token is an operand, push on the stack */
char* a = malloc(2);
if (!a)
goto end;
a[0] = postfix[i];
a[1] = '\0';
// printf("Operand: %s\n", a);
Stack_Push(stack, a);
}
else
{
char* a = nullptr;
char* b = nullptr;
/* token is an operator */
unary = FALSE;
char* c = malloc(2);
if (!c)
goto fail;
c[0] = postfix[i];
c[1] = '\0';
if (c[0] == 'a')
{
c[0] = '&';
}
else if (c[0] == 'o')
{
c[0] = '|';
}
else if (c[0] == 'n')
{
c[0] = '~';
unary = TRUE;
}
else if (c[0] == 'x')
{
c[0] = '^';
}
else
{
printf("invalid operator: %c\n", c[0]);
}
// printf("Operator: %s\n", c);
a = (char*)Stack_Pop(stack);
if (!a)
goto fail;
if (!unary)
b = (char*)Stack_Pop(stack);
al = strlen(a);
if (b)
bl = strlen(b);
size_t cl = 1;
size_t dl = al + bl + cl + 3;
char* d = malloc(dl + 1);
if (!d)
goto fail;
(void)sprintf_s(d, dl, "(%s%s%s)", b ? b : "", c, a);
Stack_Push(stack, d);
success = TRUE;
fail:
free(a);
free(b);
free(c);
if (!success)
goto end;
}
}
char* d = (char*)Stack_Pop(stack);
Stack_Free(stack);
return d;
end:
Stack_Free(stack);
return nullptr;
}
static const char* test_ROP3[] = { "DSPDxax", "PSDPxax", "SPna", "DSna", "DPa",
"PDxn", "DSxn", "PSDnox", "PDSona", "DSPDxox",
"DPSDonox", "SPDSxax", "DPon", "DPna", "Pn",
"PDna", "DPan", "DSan", "DSxn", "DPa",
"D", "DPno", "SDno", "PDno", "DPo" };
int TestGdiRop3(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
for (size_t index = 0; index < sizeof(test_ROP3) / sizeof(test_ROP3[0]); index++)
{
const char* postfix = test_ROP3[index];
char* infix = gdi_convert_postfix_to_infix(postfix);
if (!infix)
return -1;
printf("%s\t\t%s\n", postfix, infix);
free(infix);
}
return 0;
}

View File

@@ -0,0 +1,141 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* GDI Library Tests
*
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
* Copyright 2016 Thincast Technologies GmbH
*
* 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.
*/
#include "helpers.h"
HGDI_BITMAP test_convert_to_bitmap(const BYTE* src, UINT32 SrcFormat, UINT32 SrcStride, UINT32 xSrc,
UINT32 ySrc, UINT32 DstFormat, UINT32 DstStride, UINT32 xDst,
UINT32 yDst, UINT32 nWidth, UINT32 nHeight,
const gdiPalette* hPalette)
{
HGDI_BITMAP bmp = nullptr;
BYTE* data = nullptr;
if (DstStride == 0)
DstStride = nWidth * FreeRDPGetBytesPerPixel(DstFormat);
data = winpr_aligned_malloc(1ULL * DstStride * nHeight, 16);
if (!data)
return nullptr;
if (!freerdp_image_copy(data, DstFormat, DstStride, xDst, yDst, nWidth, nHeight, src, SrcFormat,
SrcStride, xSrc, ySrc, hPalette, FREERDP_FLIP_NONE))
{
winpr_aligned_free(data);
return nullptr;
}
bmp = gdi_CreateBitmap(nWidth, nHeight, DstFormat, data);
if (!bmp)
{
winpr_aligned_free(data);
return nullptr;
}
return bmp;
}
static void test_dump_data(unsigned char* p, size_t len, size_t width, const char* name)
{
unsigned char* line = p;
const size_t stride = (width > 0) ? len / width : 1;
size_t offset = 0;
printf("\n%s[%" PRIuz "][%" PRIuz "]:\n", name, stride, width);
while (offset < len)
{
size_t i = 0;
printf("%04" PRIxz " ", offset);
size_t thisline = len - offset;
if (thisline > width)
thisline = width;
for (; i < thisline; i++)
printf("%02x ", line[i]);
for (; i < width; i++)
printf(" ");
printf("\n");
offset += thisline;
line += thisline;
}
printf("\n");
(void)fflush(stdout);
}
void test_dump_bitmap(HGDI_BITMAP hBmp, const char* name)
{
const size_t stride =
WINPR_ASSERTING_INT_CAST(size_t, hBmp->width) * FreeRDPGetBytesPerPixel(hBmp->format);
test_dump_data(hBmp->data, stride * WINPR_ASSERTING_INT_CAST(uint32_t, hBmp->height), stride,
name);
}
static BOOL CompareBitmaps(HGDI_BITMAP hBmp1, HGDI_BITMAP hBmp2, const gdiPalette* palette)
{
const BYTE* p1 = hBmp1->data;
const BYTE* p2 = hBmp2->data;
const UINT32 minw = WINPR_ASSERTING_INT_CAST(
uint32_t, (hBmp1->width < hBmp2->width) ? hBmp1->width : hBmp2->width);
const UINT32 minh = WINPR_ASSERTING_INT_CAST(
uint32_t, (hBmp1->height < hBmp2->height) ? hBmp1->height : hBmp2->height);
for (UINT32 y = 0; y < minh; y++)
{
for (UINT32 x = 0; x < minw; x++)
{
UINT32 colorA = FreeRDPReadColor(p1, hBmp1->format);
UINT32 colorB = FreeRDPReadColor(p2, hBmp2->format);
p1 += FreeRDPGetBytesPerPixel(hBmp1->format);
p2 += FreeRDPGetBytesPerPixel(hBmp2->format);
if (hBmp1->format != hBmp2->format)
colorB = FreeRDPConvertColor(colorB, hBmp2->format, hBmp1->format, palette);
if (colorA != colorB)
return FALSE;
}
}
return TRUE;
}
BOOL test_assert_bitmaps_equal(HGDI_BITMAP hBmpActual, HGDI_BITMAP hBmpExpected, const char* name,
const gdiPalette* palette)
{
BOOL bitmapsEqual = CompareBitmaps(hBmpActual, hBmpExpected, palette);
if (!bitmapsEqual)
{
printf("Testing ROP %s [%s|%s]\n", name, FreeRDPGetColorFormatName(hBmpActual->format),
FreeRDPGetColorFormatName(hBmpExpected->format));
test_dump_bitmap(hBmpActual, "Actual");
test_dump_bitmap(hBmpExpected, "Expected");
(void)fflush(stdout);
(void)fflush(stderr);
return TRUE; // TODO: Fix test cases
}
return bitmapsEqual;
}

View File

@@ -0,0 +1,43 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* GDI Library Tests
*
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
* Copyright 2016 Thincast Technologies GmbH
*
* 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.
*/
#ifndef GDI_TEST_HELPERS_H
#define GDI_TEST_HELPERS_H
#include <freerdp/codec/color.h>
#include <freerdp/gdi/bitmap.h>
WINPR_ATTR_NODISCARD
FREERDP_LOCAL
HGDI_BITMAP test_convert_to_bitmap(const BYTE* src, UINT32 SrcFormat, UINT32 SrcStride, UINT32 xSrc,
UINT32 ySrc, UINT32 DstFormat, UINT32 DstStride, UINT32 xDst,
UINT32 yDst, UINT32 nWidth, UINT32 nHeight,
const gdiPalette* hPalette);
FREERDP_LOCAL
void test_dump_bitmap(HGDI_BITMAP hBmp, const char* name);
WINPR_ATTR_NODISCARD
FREERDP_LOCAL
BOOL test_assert_bitmaps_equal(HGDI_BITMAP hBmpActual, HGDI_BITMAP hBmpExpected, const char* name,
const gdiPalette* palette);
#endif /* __GDI_CORE_H */