diff options
Diffstat (limited to 'libfreerdp/gdi/test')
-rw-r--r-- | libfreerdp/gdi/test/CMakeLists.txt | 40 | ||||
-rw-r--r-- | libfreerdp/gdi/test/TestGdiBitBlt.c | 577 | ||||
-rw-r--r-- | libfreerdp/gdi/test/TestGdiClip.c | 345 | ||||
-rw-r--r-- | libfreerdp/gdi/test/TestGdiCreate.c | 587 | ||||
-rw-r--r-- | libfreerdp/gdi/test/TestGdiEllipse.c | 169 | ||||
-rw-r--r-- | libfreerdp/gdi/test/TestGdiLine.c | 724 | ||||
-rw-r--r-- | libfreerdp/gdi/test/TestGdiRect.c | 168 | ||||
-rw-r--r-- | libfreerdp/gdi/test/TestGdiRegion.c | 256 | ||||
-rw-r--r-- | libfreerdp/gdi/test/TestGdiRop3.c | 208 | ||||
-rw-r--r-- | libfreerdp/gdi/test/helpers.c | 137 | ||||
-rw-r--r-- | libfreerdp/gdi/test/helpers.h | 37 |
11 files changed, 3248 insertions, 0 deletions
diff --git a/libfreerdp/gdi/test/CMakeLists.txt b/libfreerdp/gdi/test/CMakeLists.txt new file mode 100644 index 0000000..b859c16 --- /dev/null +++ b/libfreerdp/gdi/test/CMakeLists.txt @@ -0,0 +1,40 @@ + +set(MODULE_NAME "TestGdi") +set(MODULE_PREFIX "TEST_GDI") + +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") + diff --git a/libfreerdp/gdi/test/TestGdiBitBlt.c b/libfreerdp/gdi/test/TestGdiBitBlt.c new file mode 100644 index 0000000..ba746d5 --- /dev/null +++ b/libfreerdp/gdi/test/TestGdiBitBlt.c @@ -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: + 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 = NULL; + HGDI_DC hdcDst = NULL; + const UINT32 RawFormat = PIXEL_FORMAT_RGB8; + struct test_bitblt tests[] = { { GDI_SRCCOPY, bmp_SRCCOPY, NULL }, + { GDI_SPna, bmp_SPna, NULL }, + { GDI_BLACKNESS, bmp_BLACKNESS, NULL }, + { GDI_WHITENESS, bmp_WHITENESS, NULL }, + { GDI_SRCAND, bmp_SRCAND, NULL }, + { GDI_SRCPAINT, bmp_SRCPAINT, NULL }, + { GDI_SRCINVERT, bmp_SRCINVERT, NULL }, + { GDI_SRCERASE, bmp_SRCERASE, NULL }, + { GDI_NOTSRCCOPY, bmp_NOTSRCCOPY, NULL }, + { GDI_NOTSRCERASE, bmp_NOTSRCERASE, NULL }, + { GDI_DSTINVERT, bmp_DSTINVERT, NULL }, + { GDI_MERGECOPY, bmp_MERGECOPY, NULL }, + { GDI_MERGEPAINT, bmp_MERGEPAINT, NULL }, + { GDI_PATCOPY, bmp_PATCOPY, NULL }, + { GDI_PATPAINT, bmp_PATPAINT, NULL }, + { GDI_PATINVERT, bmp_PATINVERT, NULL }, + { GDI_DSTINVERT, bmp_SRC, NULL }, + { GDI_DSPDxax, bmp_SRC, NULL }, + { GDI_PSDPxax, bmp_SRC, NULL }, + { GDI_DSna, bmp_SRC, NULL }, + { GDI_DPa, bmp_SRC, NULL }, + { GDI_PDxn, bmp_SRC, NULL }, + { GDI_DSxn, bmp_SRC, NULL }, + { GDI_PSDnox, bmp_SRC, NULL }, + { GDI_PDSona, bmp_SRC, NULL }, + { GDI_DSPDxox, bmp_SRC, NULL }, + { GDI_DPSDonox, bmp_SRC, NULL }, + { GDI_SPDSxax, bmp_SRC, NULL }, + { GDI_DPon, bmp_SRC, NULL }, + { GDI_DPna, bmp_SRC, NULL }, + { GDI_Pn, bmp_SRC, NULL }, + { GDI_PDna, bmp_SRC, NULL }, + { GDI_DPan, bmp_SRC, NULL }, + { GDI_DSan, bmp_SRC, NULL }, + { GDI_DSxn, bmp_SRC, NULL }, + { GDI_DPa, bmp_SRC, NULL }, + { GDI_DSTCOPY, bmp_SRC, NULL }, + { GDI_DPno, bmp_SRC, NULL }, + { GDI_SDno, bmp_SRC, NULL }, + { GDI_PDno, bmp_SRC, NULL }, + { GDI_DPo, bmp_SRC, NULL } }; + const UINT32 number_tests = sizeof(tests) / sizeof(tests[0]); + HGDI_BITMAP hBmpSrc = NULL; + HGDI_BITMAP hBmpDst = NULL; + HGDI_BITMAP hBmpDstOriginal = NULL; + HGDI_BRUSH brush = NULL; + 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, NULL); + 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])) + { + fprintf(stderr, "test_gdi_BitBlt(SrcFormat=%s, DstFormat=%s) failed!\n", + FreeRDPGetColorFormatName(formatList[x]), + FreeRDPGetColorFormatName(formatList[y])); + rc = -1; + } + } + } + + return rc; +} diff --git a/libfreerdp/gdi/test/TestGdiClip.c b/libfreerdp/gdi/test/TestGdiClip.c new file mode 100644 index 0000000..bfef3cd --- /dev/null +++ b/libfreerdp/gdi/test/TestGdiClip.c @@ -0,0 +1,345 @@ + +#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 int test_gdi_ClipCoords(void) +{ + int rc = -1; + BOOL draw = 0; + HGDI_DC hdc = NULL; + HGDI_RGN rgn1 = NULL; + HGDI_RGN rgn2 = NULL; + HGDI_BITMAP bmp = NULL; + 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, NULL, NULL); + gdi_SelectObject(hdc, (HGDIOBJECT)bmp); + gdi_SetNullClipRgn(hdc); + rgn1 = gdi_CreateRectRgn(0, 0, 0, 0); + rgn2 = gdi_CreateRectRgn(0, 0, 0, 0); + rgn1->null = TRUE; + rgn2->null = TRUE; + /* null clipping region */ + gdi_SetNullClipRgn(hdc); + gdi_SetRgn(rgn1, 20, 20, 100, 100); + gdi_SetRgn(rgn2, 20, 20, 100, 100); + gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (!gdi_EqualRgn(rgn1, rgn2)) + goto fail; + + /* region all inside clipping region */ + gdi_SetClipRgn(hdc, 0, 0, 1024, 768); + gdi_SetRgn(rgn1, 20, 20, 100, 100); + gdi_SetRgn(rgn2, 20, 20, 100, 100); + gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (!gdi_EqualRgn(rgn1, rgn2)) + goto fail; + + /* region all outside clipping region, on the left */ + gdi_SetClipRgn(hdc, 300, 300, 100, 100); + gdi_SetRgn(rgn1, 20, 20, 100, 100); + gdi_SetRgn(rgn2, 0, 0, 0, 0); + draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (draw) + goto fail; + + /* region all outside clipping region, on the right */ + gdi_SetClipRgn(hdc, 300, 300, 100, 100); + gdi_SetRgn(rgn1, 420, 420, 100, 100); + gdi_SetRgn(rgn2, 0, 0, 0, 0); + draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (draw) + goto fail; + + /* region all outside clipping region, on top */ + gdi_SetClipRgn(hdc, 300, 300, 100, 100); + gdi_SetRgn(rgn1, 300, 20, 100, 100); + gdi_SetRgn(rgn2, 0, 0, 0, 0); + draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (draw) + goto fail; + + /* region all outside clipping region, at the bottom */ + gdi_SetClipRgn(hdc, 300, 300, 100, 100); + gdi_SetRgn(rgn1, 300, 420, 100, 100); + gdi_SetRgn(rgn2, 0, 0, 0, 0); + draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (draw) + goto fail; + + /* left outside, right = clip, top = clip, bottom = clip */ + gdi_SetClipRgn(hdc, 300, 300, 100, 100); + gdi_SetRgn(rgn1, 100, 300, 300, 100); + gdi_SetRgn(rgn2, 300, 300, 100, 100); + gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (!gdi_EqualRgn(rgn1, rgn2)) + goto fail; + + /* left outside, right inside, top = clip, bottom = clip */ + gdi_SetClipRgn(hdc, 300, 300, 100, 100); + gdi_SetRgn(rgn1, 100, 300, 250, 100); + gdi_SetRgn(rgn2, 300, 300, 50, 100); + gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (!gdi_EqualRgn(rgn1, rgn2)) + goto fail; + + /* left = clip, right outside, top = clip, bottom = clip */ + gdi_SetClipRgn(hdc, 300, 300, 100, 100); + gdi_SetRgn(rgn1, 300, 300, 300, 100); + gdi_SetRgn(rgn2, 300, 300, 100, 100); + gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (!gdi_EqualRgn(rgn1, rgn2)) + goto fail; + + /* left inside, right outside, top = clip, bottom = clip */ + gdi_SetClipRgn(hdc, 300, 300, 100, 100); + gdi_SetRgn(rgn1, 350, 300, 200, 100); + gdi_SetRgn(rgn2, 350, 300, 50, 100); + gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (!gdi_EqualRgn(rgn1, rgn2)) + goto fail; + + /* top outside, bottom = clip, left = clip, right = clip */ + gdi_SetClipRgn(hdc, 300, 300, 100, 100); + gdi_SetRgn(rgn1, 300, 100, 300, 300); + gdi_SetRgn(rgn2, 300, 300, 100, 100); + gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (!gdi_EqualRgn(rgn1, rgn2)) + goto fail; + + /* top = clip, bottom outside, left = clip, right = clip */ + gdi_SetClipRgn(hdc, 300, 300, 100, 100); + gdi_SetRgn(rgn1, 300, 300, 100, 200); + gdi_SetRgn(rgn2, 300, 300, 100, 100); + gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (!gdi_EqualRgn(rgn1, rgn2)) + goto fail; + + /* top = clip, bottom = clip, top = clip, bottom = clip */ + gdi_SetClipRgn(hdc, 300, 300, 100, 100); + gdi_SetRgn(rgn1, 300, 300, 100, 100); + gdi_SetRgn(rgn2, 300, 300, 100, 100); + gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL); + + if (!gdi_EqualRgn(rgn1, rgn2)) + goto fail; + + rc = 0; +fail: + gdi_DeleteObject((HGDIOBJECT)rgn1); + gdi_DeleteObject((HGDIOBJECT)rgn2); + gdi_DeleteObject((HGDIOBJECT)bmp); + gdi_DeleteDC(hdc); + return rc; +} + +static int test_gdi_InvalidateRegion(void) +{ + int rc = -1; + HGDI_DC hdc = NULL; + HGDI_RGN rgn1 = NULL; + HGDI_RGN rgn2 = NULL; + HGDI_RGN invalid = NULL; + HGDI_BITMAP bmp = NULL; + 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, NULL, NULL); + 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); + fprintf(stderr, "test_gdi_ClipCoords()\n"); + + if (test_gdi_ClipCoords() < 0) + return -1; + + fprintf(stderr, "test_gdi_InvalidateRegion()\n"); + + if (test_gdi_InvalidateRegion() < 0) + return -1; + + return 0; +} diff --git a/libfreerdp/gdi/test/TestGdiCreate.c b/libfreerdp/gdi/test/TestGdiCreate.c new file mode 100644 index 0000000..c71b396 --- /dev/null +++ b/libfreerdp/gdi/test/TestGdiCreate.c @@ -0,0 +1,587 @@ + +#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 "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 = NULL; + + 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 = NULL; + HGDI_DC chdc = NULL; + + 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 = NULL; + HGDI_BITMAP hBitmap = NULL; + width = 32; + height = 16; + + if (!(data = (BYTE*)winpr_aligned_malloc(width * height * 4, 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 + free(data); + + return rc; +} + +static int test_gdi_CreateCompatibleBitmap(void) +{ + int rc = -1; + HGDI_DC hdc = NULL; + INT32 width = 0; + INT32 height = 0; + HGDI_BITMAP hBitmap = NULL; + + 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, NULL); + + 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 = NULL; + HGDI_BITMAP hBitmap = NULL; + hBitmap = gdi_CreateBitmap(64, 64, 32, NULL); + 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; + HGDI_RECT hRect = NULL; + 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 BOOL test_gdi_GetPixel(void) +{ + BOOL rc = TRUE; + + for (UINT32 x = 0; x < colorFormatCount; x++) + { + UINT32 bpp = 0; + HGDI_DC hdc = NULL; + UINT32 width = 128; + UINT32 height = 64; + HGDI_BITMAP hBitmap = NULL; + + 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, rand(), rand(), rand(), rand()); + 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 = NULL; + UINT32 width = 128; + UINT32 height = 64; + HGDI_BITMAP hBitmap = NULL; + + 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, rand(), rand(), rand(), rand()); + 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 = NULL; + + 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 = NULL; + HGDI_PEN hPen = NULL; + HGDI_POINT prevPoint = NULL; + const UINT32 format = PIXEL_FORMAT_RGBA32; + gdiPalette* palette = NULL; + + 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, NULL); + + 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); + fprintf(stderr, "test_gdi_GetDC()\n"); + + if (test_gdi_GetDC() < 0) + return -1; + + fprintf(stderr, "test_gdi_CreateCompatibleDC()\n"); + + if (test_gdi_CreateCompatibleDC() < 0) + return -1; + + fprintf(stderr, "test_gdi_CreateBitmap()\n"); + + if (test_gdi_CreateBitmap() < 0) + return -1; + + fprintf(stderr, "test_gdi_CreateCompatibleBitmap()\n"); + + if (test_gdi_CreateCompatibleBitmap() < 0) + return -1; + + fprintf(stderr, "test_gdi_CreatePen()\n"); + + if (test_gdi_CreatePen() < 0) + return -1; + + fprintf(stderr, "test_gdi_CreateSolidBrush()\n"); + + if (test_gdi_CreateSolidBrush() < 0) + return -1; + + fprintf(stderr, "test_gdi_CreatePatternBrush()\n"); + + if (test_gdi_CreatePatternBrush() < 0) + return -1; + + fprintf(stderr, "test_gdi_CreateRectRgn()\n"); + + if (test_gdi_CreateRectRgn() < 0) + return -1; + + fprintf(stderr, "test_gdi_CreateRect()\n"); + + if (test_gdi_CreateRect() < 0) + return -1; + + fprintf(stderr, "test_gdi_GetPixel()\n"); + + if (!test_gdi_GetPixel()) + return -1; + + fprintf(stderr, "test_gdi_SetPixel()\n"); + + if (!test_gdi_SetPixel()) + return -1; + + fprintf(stderr, "test_gdi_SetROP2()\n"); + + if (test_gdi_SetROP2() < 0) + return -1; + + fprintf(stderr, "test_gdi_MoveToEx()\n"); + + if (test_gdi_MoveToEx() < 0) + return -1; + + return 0; +} diff --git a/libfreerdp/gdi/test/TestGdiEllipse.c b/libfreerdp/gdi/test/TestGdiEllipse.c new file mode 100644 index 0000000..ca9e629 --- /dev/null +++ b/libfreerdp/gdi/test/TestGdiEllipse.c @@ -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 = NULL; + HGDI_PEN pen = NULL; + HGDI_BITMAP hBmp = NULL; + HGDI_BITMAP hBmp_Ellipse_1 = NULL; + HGDI_BITMAP hBmp_Ellipse_2 = NULL; + HGDI_BITMAP hBmp_Ellipse_3 = NULL; + 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; +} diff --git a/libfreerdp/gdi/test/TestGdiLine.c b/libfreerdp/gdi/test/TestGdiLine.c new file mode 100644 index 0000000..f014f37 --- /dev/null +++ b/libfreerdp/gdi/test/TestGdiLine.c @@ -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, NULL); + 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 = { 0 }; + HGDI_DC hdc = NULL; + HGDI_PEN pen = NULL; + HGDI_BITMAP hBmp = NULL; + struct ropMap rop_map[] = { { GDI_R2_BLACK, NULL, line_to_R2_BLACK }, + { GDI_R2_NOTMERGEPEN, NULL, line_to_R2_NOTMERGEPEN }, + { GDI_R2_MASKNOTPEN, NULL, line_to_R2_MASKNOTPEN }, + { GDI_R2_NOTCOPYPEN, NULL, line_to_R2_NOTCOPYPEN }, + { GDI_R2_MASKPENNOT, NULL, line_to_R2_MASKPENNOT }, + { GDI_R2_NOT, NULL, line_to_R2_NOT }, + { GDI_R2_XORPEN, NULL, line_to_R2_XORPEN }, + { GDI_R2_NOTMASKPEN, NULL, line_to_R2_NOTMASKPEN }, + { GDI_R2_MASKPEN, NULL, line_to_R2_MASKPEN }, + { GDI_R2_NOTXORPEN, NULL, line_to_R2_NOTXORPEN }, + { GDI_R2_NOP, NULL, line_to_R2_NOP }, + { GDI_R2_MERGENOTPEN, NULL, line_to_R2_MERGENOTPEN }, + { GDI_R2_COPYPEN, NULL, line_to_R2_COPYPEN }, + { GDI_R2_MERGEPENNOT, NULL, line_to_R2_MERGEPENNOT }, + { GDI_R2_MERGEPEN, NULL, line_to_R2_MERGEPEN }, + { GDI_R2_WHITE, NULL, line_to_R2_WHITE } }; + const size_t map_size = sizeof(rop_map) / sizeof(rop_map[0]); + HGDI_BITMAP hBmp_LineTo[LINTETO_NUMBER] = { NULL }; + 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] = { 0 }; + _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, NULL); + 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; +} diff --git a/libfreerdp/gdi/test/TestGdiRect.c b/libfreerdp/gdi/test/TestGdiRect.c new file mode 100644 index 0000000..87cf577 --- /dev/null +++ b/libfreerdp/gdi/test/TestGdiRect.c @@ -0,0 +1,168 @@ + +#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; + HGDI_RECT hRect = NULL; + UINT32 left = 20; + UINT32 top = 40; + UINT32 right = 60; + UINT32 bottom = 80; + + if (!(hRect = gdi_CreateRect(left, top, right, 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, left, top)) + goto fail; + + if (!gdi_PtInRect(hRect, right, bottom)) + goto fail; + + if (!gdi_PtInRect(hRect, right, 60)) + goto fail; + + if (!gdi_PtInRect(hRect, 40, bottom)) + goto fail; + + rc = 0; +fail: + gdi_DeleteObject((HGDIOBJECT)hRect); + return rc; +} + +static int test_gdi_FillRect(void) +{ + int rc = -1; + HGDI_DC hdc = NULL; + HGDI_RECT hRect = NULL; + HGDI_BRUSH hBrush = NULL; + HGDI_BITMAP hBitmap = NULL; + 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(left, top, right, bottom))) + { + printf("gdi_CreateRect failed\n"); + goto fail; + } + + hBitmap = gdi_CreateCompatibleBitmap(hdc, width, height); + ZeroMemory(hBitmap->data, 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, NULL); + + if (gdi_PtInRect(hRect, x, 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; +} diff --git a/libfreerdp/gdi/test/TestGdiRegion.c b/libfreerdp/gdi/test/TestGdiRegion.c new file mode 100644 index 0000000..3f7ed93 --- /dev/null +++ b/libfreerdp/gdi/test/TestGdiRegion.c @@ -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 = NULL; + HGDI_RGN rgn2 = NULL; + HGDI_RECT rect1 = NULL; + HGDI_RECT rect2 = NULL; + + 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(NULL, -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(NULL, 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, NULL)) + goto fail; + if (gdi_CopyRect(NULL, rect1)) + goto fail; + if (gdi_CopyRect(NULL, NULL)) + 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; +} diff --git a/libfreerdp/gdi/test/TestGdiRop3.c b/libfreerdp/gdi/test/TestGdiRop3.c new file mode 100644 index 0000000..2756633 --- /dev/null +++ b/libfreerdp/gdi/test/TestGdiRop3.c @@ -0,0 +1,208 @@ + +#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) +{ + size_t length = 0; + BOOL unary = 0; + wStack* stack = NULL; + size_t al = 0; + size_t bl = 0; + size_t cl = 0; + size_t dl = 0; + char* a = NULL; + char* b = NULL; + char* c = NULL; + char* d = NULL; + bl = cl = dl = 0; + stack = Stack_New(FALSE); + length = strlen(postfix); + + for (size_t i = 0; i < length; i++) + { + if ((postfix[i] == 'P') || (postfix[i] == 'D') || (postfix[i] == 'S')) + { + /* token is an operand, push on the stack */ + a = malloc(2); + a[0] = postfix[i]; + a[1] = '\0'; + // printf("Operand: %s\n", a); + Stack_Push(stack, a); + } + else + { + /* token is an operator */ + unary = FALSE; + c = malloc(2); + 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 (unary) + b = NULL; + else + b = (char*)Stack_Pop(stack); + + al = strlen(a); + + if (b) + bl = strlen(b); + + cl = 1; + dl = al + bl + cl + 3; + d = malloc(dl + 1); + sprintf_s(d, dl, "(%s%s%s)", b ? b : "", c, a); + Stack_Push(stack, d); + free(a); + free(b); + free(c); + } + } + + d = (char*)Stack_Pop(stack); + Stack_Free(stack); + return d; +} + +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; +} diff --git a/libfreerdp/gdi/test/helpers.c b/libfreerdp/gdi/test/helpers.c new file mode 100644 index 0000000..b04b476 --- /dev/null +++ b/libfreerdp/gdi/test/helpers.c @@ -0,0 +1,137 @@ +/** + * 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 = NULL; + BYTE* data = NULL; + + if (DstStride == 0) + DstStride = nWidth * FreeRDPGetBytesPerPixel(DstFormat); + + data = winpr_aligned_malloc(DstStride * nHeight, 16); + + if (!data) + return NULL; + + 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 NULL; + } + + bmp = gdi_CreateBitmap(nWidth, nHeight, DstFormat, data); + + if (!bmp) + { + winpr_aligned_free(data); + return NULL; + } + + return bmp; +} + +static void test_dump_data(unsigned char* p, int len, int width, const char* name) +{ + unsigned char* line = p; + int thisline = 0; + int offset = 0; + printf("\n%s[%d][%d]:\n", name, len / width, width); + + while (offset < len) + { + int i = 0; + printf("%04x ", offset); + 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"); + fflush(stdout); +} + +void test_dump_bitmap(HGDI_BITMAP hBmp, const char* name) +{ + UINT32 stride = hBmp->width * FreeRDPGetBytesPerPixel(hBmp->format); + test_dump_data(hBmp->data, hBmp->height * stride, 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 = (hBmp1->width < hBmp2->width) ? hBmp1->width : hBmp2->width; + const UINT32 minh = (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"); + fflush(stdout); + fflush(stderr); + return TRUE; // TODO: Fix test cases + } + + return bitmapsEqual; +} diff --git a/libfreerdp/gdi/test/helpers.h b/libfreerdp/gdi/test/helpers.h new file mode 100644 index 0000000..d8be19c --- /dev/null +++ b/libfreerdp/gdi/test/helpers.h @@ -0,0 +1,37 @@ +/** + * 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> + +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); + +void test_dump_bitmap(HGDI_BITMAP hBmp, const char* name); +BOOL test_assert_bitmaps_equal(HGDI_BITMAP hBmpActual, HGDI_BITMAP hBmpExpected, const char* name, + const gdiPalette* palette); + +#endif /* __GDI_CORE_H */ |