diff --git a/rdtk/librdtk/CMakeLists.txt b/rdtk/librdtk/CMakeLists.txt index 03e358a47..88dc229ac 100644 --- a/rdtk/librdtk/CMakeLists.txt +++ b/rdtk/librdtk/CMakeLists.txt @@ -46,3 +46,6 @@ install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT RdTkTa set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "RdTk") +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/rdtk/librdtk/rdtk_nine_patch.c b/rdtk/librdtk/rdtk_nine_patch.c index cd68b74af..c2c33897a 100644 --- a/rdtk/librdtk/rdtk_nine_patch.c +++ b/rdtk/librdtk/rdtk_nine_patch.c @@ -26,33 +26,15 @@ #include "rdtk_nine_patch.h" -int rdtk_nine_patch_draw(rdtkSurface* surface, int nXDst, int nYDst, int nWidth, int nHeight, rdtkNinePatch* ninePatch) +int rdtk_image_copy_alpha_blend(BYTE* pDstData, int nDstStep, int nXDst, int nYDst, + int nWidth, int nHeight, BYTE* pSrcData, int nSrcStep, int nXSrc, int nYSrc) { int x, y; - int nXSrc; - int nYSrc; - int nSrcStep; - int nDstStep; int nSrcPad; int nDstPad; - BYTE* pSrcData; BYTE* pSrcPixel; - BYTE* pDstData; BYTE* pDstPixel; BYTE A, R, G, B; - wImage* image = ninePatch->image; - - nXSrc = 0; - nYSrc = 0; - - nWidth = image->width; - nHeight = image->height; - - nSrcStep = image->scanline; - pSrcData = image->data; - - pDstData = surface->data; - nDstStep = surface->scanline; nSrcPad = (nSrcStep - (nWidth * 4)); nDstPad = (nDstStep - (nWidth * 4)); @@ -101,6 +83,333 @@ int rdtk_nine_patch_draw(rdtkSurface* surface, int nXDst, int nYDst, int nWidth, return 1; } +int rdtk_nine_patch_draw(rdtkSurface* surface, int nXDst, int nYDst, int nWidth, int nHeight, rdtkNinePatch* ninePatch) +{ + int x, y; + int width; + int height; + int nXSrc; + int nYSrc; + int nSrcStep; + int nDstStep; + BYTE* pSrcData; + BYTE* pDstData; + int scaleWidth; + int scaleHeight; + + if (nWidth < ninePatch->width) + nWidth = ninePatch->width; + + if (nHeight < ninePatch->height) + nHeight = ninePatch->height; + + scaleWidth = nWidth - (ninePatch->width - ninePatch->scaleWidth); + scaleHeight = nHeight - (ninePatch->height - ninePatch->scaleHeight); + + nSrcStep = ninePatch->scanline; + pSrcData = ninePatch->data; + + pDstData = surface->data; + nDstStep = surface->scanline; + + /* top */ + + x = 0; + y = 0; + + /* top left */ + + nXSrc = 0; + nYSrc = 0; + width = ninePatch->scaleLeft; + height = ninePatch->scaleTop; + + rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, + width, height, pSrcData, nSrcStep, nXSrc, nYSrc); + + x += width; + + /* top middle (scalable) */ + + nXSrc = ninePatch->scaleLeft; + nYSrc = 0; + width = ninePatch->scaleWidth; + height = ninePatch->scaleTop; + + while (x < (nXSrc + scaleWidth)) + { + width = (nXSrc + scaleWidth) - x; + + if (width > ninePatch->scaleWidth) + width = ninePatch->scaleWidth; + + rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, + width, height, pSrcData, nSrcStep, nXSrc, nYSrc); + + x += width; + } + + /* top right */ + + nXSrc = ninePatch->scaleRight; + nYSrc = 0; + width = ninePatch->width - ninePatch->scaleRight; + height = ninePatch->scaleTop; + + rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, + width, height, pSrcData, nSrcStep, nXSrc, nYSrc); + + /* middle */ + + x = 0; + y = ninePatch->scaleTop; + + /* middle left */ + + nXSrc = 0; + nYSrc = ninePatch->scaleTop; + width = ninePatch->scaleLeft; + height = ninePatch->scaleHeight; + + rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, + width, height, pSrcData, nSrcStep, nXSrc, nYSrc); + + x += width; + + /* middle (scalable) */ + + nXSrc = ninePatch->scaleLeft; + nYSrc = ninePatch->scaleTop; + width = ninePatch->scaleWidth; + height = ninePatch->scaleHeight; + + while (x < (nXSrc + scaleWidth)) + { + width = (nXSrc + scaleWidth) - x; + + if (width > ninePatch->scaleWidth) + width = ninePatch->scaleWidth; + + rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, + width, height, pSrcData, nSrcStep, nXSrc, nYSrc); + + x += width; + } + + /* middle right */ + + nXSrc = ninePatch->scaleRight; + nYSrc = ninePatch->scaleTop; + width = ninePatch->width - ninePatch->scaleRight; + height = ninePatch->scaleHeight; + + rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, + width, height, pSrcData, nSrcStep, nXSrc, nYSrc); + + /* bottom */ + + x = 0; + y = ninePatch->scaleBottom; + + /* bottom left */ + + nXSrc = 0; + nYSrc = ninePatch->scaleBottom; + width = ninePatch->scaleLeft; + height = ninePatch->height - ninePatch->scaleBottom; + + rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, + width, height, pSrcData, nSrcStep, nXSrc, nYSrc); + + x += width; + + /* bottom middle (scalable) */ + + nXSrc = ninePatch->scaleLeft; + nYSrc = ninePatch->scaleBottom; + width = ninePatch->scaleWidth; + height = ninePatch->height - ninePatch->scaleBottom; + + while (x < (nXSrc + scaleWidth)) + { + width = (nXSrc + scaleWidth) - x; + + if (width > ninePatch->scaleWidth) + width = ninePatch->scaleWidth; + + rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, + width, height, pSrcData, nSrcStep, nXSrc, nYSrc); + + x += width; + } + + /* bottom right */ + + nXSrc = ninePatch->scaleRight; + nYSrc = ninePatch->scaleBottom; + width = ninePatch->width - ninePatch->scaleRight; + height = ninePatch->height - ninePatch->scaleBottom; + + rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, + width, height, pSrcData, nSrcStep, nXSrc, nYSrc); + + return 1; +} + +int rdtk_nine_patch_set_image(rdtkNinePatch* ninePatch, wImage* image) +{ + int x, y; + BYTE* data; + int beg, end; + int scanline; + UINT32* pixel; + int width, height; + + ninePatch->image = image; + + width = image->width; + height = image->height; + scanline = image->scanline; + data = image->data; + + /* parse scalable area */ + + beg = end = -1; + pixel = (UINT32*) &data[4]; /* (1, 0) */ + + for (x = 1; x < width - 1; x++) + { + if (beg < 0) + { + if (*pixel) + { + beg = x; + } + } + else if (end < 0) + { + if (!(*pixel)) + { + end = x; + break; + } + } + + pixel++; + } + + ninePatch->scaleLeft = beg - 1; + ninePatch->scaleRight = end - 1; + ninePatch->scaleWidth = ninePatch->scaleRight - ninePatch->scaleLeft; + + beg = end = -1; + pixel = (UINT32*) &data[scanline]; /* (0, 1) */ + + for (y = 1; y < height - 1; y++) + { + if (beg < 0) + { + if (*pixel) + { + beg = y; + } + } + else if (end < 0) + { + if (!(*pixel)) + { + end = y; + break; + } + } + + pixel = (UINT32*) &((BYTE*) pixel)[scanline]; + } + + ninePatch->scaleTop = beg - 1; + ninePatch->scaleBottom = end - 1; + ninePatch->scaleHeight = ninePatch->scaleBottom - ninePatch->scaleTop; + + /* parse fillable area */ + + beg = end = -1; + pixel = (UINT32*) &data[((height - 1) * scanline) + 4]; /* (1, height - 1) */ + + for (x = 1; x < width - 1; x++) + { + if (beg < 0) + { + if (*pixel) + { + beg = x; + } + } + else if (end < 0) + { + if (!(*pixel)) + { + end = x; + break; + } + } + + pixel++; + } + + ninePatch->fillLeft = beg - 1; + ninePatch->fillRight = end - 1; + ninePatch->fillWidth = ninePatch->fillRight - ninePatch->fillLeft; + + beg = end = -1; + pixel = (UINT32*) &data[((width - 1) * 4) + scanline]; /* (width - 1, 1) */ + + for (y = 1; y < height - 1; y++) + { + if (beg < 0) + { + if (*pixel) + { + beg = y; + } + } + else if (end < 0) + { + if (!(*pixel)) + { + end = y; + break; + } + } + + pixel = (UINT32*) &((BYTE*) pixel)[scanline]; + } + + ninePatch->fillTop = beg - 1; + ninePatch->fillBottom = end - 1; + ninePatch->fillHeight = ninePatch->fillBottom - ninePatch->fillTop; + + /* cut out borders from image */ + + ninePatch->width = width - 2; + ninePatch->height = height - 2; + ninePatch->data = &data[scanline + 4]; /* (1, 1) */ + ninePatch->scanline = scanline; + +#if 0 + printf("width: %d height: %d\n", ninePatch->width, ninePatch->height); + + printf("scale: left: %d right: %d top: %d bottom: %d\n", + ninePatch->scaleLeft, ninePatch->scaleRight, + ninePatch->scaleTop, ninePatch->scaleBottom); + + printf("fill: left: %d right: %d top: %d bottom: %d\n", + ninePatch->fillLeft, ninePatch->fillRight, + ninePatch->fillTop, ninePatch->fillBottom); +#endif + + return 1; +} + rdtkNinePatch* rdtk_nine_patch_new(rdtkEngine* engine) { rdtkNinePatch* ninePatch; @@ -153,7 +462,7 @@ int rdtk_nine_patch_engine_init(rdtkEngine* engine) ninePatch = engine->button9patch = rdtk_nine_patch_new(engine); if (ninePatch) - ninePatch->image = image; + rdtk_nine_patch_set_image(ninePatch, image); } } @@ -179,7 +488,7 @@ int rdtk_nine_patch_engine_init(rdtkEngine* engine) ninePatch = engine->textField9patch = rdtk_nine_patch_new(engine); if (ninePatch) - ninePatch->image = image; + rdtk_nine_patch_set_image(ninePatch, image); } } diff --git a/rdtk/librdtk/rdtk_nine_patch.h b/rdtk/librdtk/rdtk_nine_patch.h index 8d5656a58..f3b6a6a6d 100644 --- a/rdtk/librdtk/rdtk_nine_patch.h +++ b/rdtk/librdtk/rdtk_nine_patch.h @@ -32,12 +32,32 @@ struct rdtk_nine_patch rdtkEngine* engine; wImage* image; + + int width; + int height; + int scanline; + BYTE* data; + + int scaleLeft; + int scaleRight; + int scaleWidth; + int scaleTop; + int scaleBottom; + int scaleHeight; + + int fillLeft; + int fillRight; + int fillWidth; + int fillTop; + int fillBottom; + int fillHeight; }; #ifdef __cplusplus extern "C" { #endif +int rdtk_nine_patch_set_image(rdtkNinePatch* ninePatch, wImage* image); int rdtk_nine_patch_draw(rdtkSurface* surface, int nXDst, int nYDst, int nWidth, int nHeight, rdtkNinePatch* ninePatch); int rdtk_nine_patch_engine_init(rdtkEngine* engine); diff --git a/rdtk/librdtk/test/.gitignore b/rdtk/librdtk/test/.gitignore new file mode 100644 index 000000000..409b2b6bc --- /dev/null +++ b/rdtk/librdtk/test/.gitignore @@ -0,0 +1,4 @@ +TestRdTk +TestRdTk.c + + diff --git a/rdtk/librdtk/test/CMakeLists.txt b/rdtk/librdtk/test/CMakeLists.txt new file mode 100644 index 000000000..c570541ed --- /dev/null +++ b/rdtk/librdtk/test/CMakeLists.txt @@ -0,0 +1,25 @@ + +set(MODULE_NAME "TestRdTk") +set(MODULE_PREFIX "TEST_RDTK") + +set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) + +set(${MODULE_PREFIX}_TESTS + TestRdTkNinePatch.c) + +create_test_sourcelist(${MODULE_PREFIX}_SRCS + ${${MODULE_PREFIX}_DRIVER} + ${${MODULE_PREFIX}_TESTS}) + +add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + +target_link_libraries(${MODULE_NAME} rdtk) + +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 "RdTk/Test") diff --git a/rdtk/librdtk/test/TestRdTkNinePatch.c b/rdtk/librdtk/test/TestRdTkNinePatch.c new file mode 100644 index 000000000..fb50dee8c --- /dev/null +++ b/rdtk/librdtk/test/TestRdTkNinePatch.c @@ -0,0 +1,13 @@ + +#include + +int TestRdTkNinePatch(int argc, char* argv[]) +{ + rdtkEngine* engine; + + engine = rdtk_engine_new(); + + rdtk_engine_free(engine); + + return 0; +}