librdtk: initial nine patch rendering
This commit is contained in:
parent
24b594d592
commit
75d609741a
@ -46,3 +46,6 @@ install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT RdTkTa
|
|||||||
|
|
||||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "RdTk")
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "RdTk")
|
||||||
|
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
add_subdirectory(test)
|
||||||
|
endif()
|
||||||
|
@ -26,33 +26,15 @@
|
|||||||
|
|
||||||
#include "rdtk_nine_patch.h"
|
#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 x, y;
|
||||||
int nXSrc;
|
|
||||||
int nYSrc;
|
|
||||||
int nSrcStep;
|
|
||||||
int nDstStep;
|
|
||||||
int nSrcPad;
|
int nSrcPad;
|
||||||
int nDstPad;
|
int nDstPad;
|
||||||
BYTE* pSrcData;
|
|
||||||
BYTE* pSrcPixel;
|
BYTE* pSrcPixel;
|
||||||
BYTE* pDstData;
|
|
||||||
BYTE* pDstPixel;
|
BYTE* pDstPixel;
|
||||||
BYTE A, R, G, B;
|
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));
|
nSrcPad = (nSrcStep - (nWidth * 4));
|
||||||
nDstPad = (nDstStep - (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;
|
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* rdtk_nine_patch_new(rdtkEngine* engine)
|
||||||
{
|
{
|
||||||
rdtkNinePatch* ninePatch;
|
rdtkNinePatch* ninePatch;
|
||||||
@ -153,7 +462,7 @@ int rdtk_nine_patch_engine_init(rdtkEngine* engine)
|
|||||||
ninePatch = engine->button9patch = rdtk_nine_patch_new(engine);
|
ninePatch = engine->button9patch = rdtk_nine_patch_new(engine);
|
||||||
|
|
||||||
if (ninePatch)
|
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);
|
ninePatch = engine->textField9patch = rdtk_nine_patch_new(engine);
|
||||||
|
|
||||||
if (ninePatch)
|
if (ninePatch)
|
||||||
ninePatch->image = image;
|
rdtk_nine_patch_set_image(ninePatch, image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,12 +32,32 @@ struct rdtk_nine_patch
|
|||||||
rdtkEngine* engine;
|
rdtkEngine* engine;
|
||||||
|
|
||||||
wImage* image;
|
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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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_draw(rdtkSurface* surface, int nXDst, int nYDst, int nWidth, int nHeight, rdtkNinePatch* ninePatch);
|
||||||
|
|
||||||
int rdtk_nine_patch_engine_init(rdtkEngine* engine);
|
int rdtk_nine_patch_engine_init(rdtkEngine* engine);
|
||||||
|
4
rdtk/librdtk/test/.gitignore
vendored
Normal file
4
rdtk/librdtk/test/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
TestRdTk
|
||||||
|
TestRdTk.c
|
||||||
|
|
||||||
|
|
25
rdtk/librdtk/test/CMakeLists.txt
Normal file
25
rdtk/librdtk/test/CMakeLists.txt
Normal file
@ -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")
|
13
rdtk/librdtk/test/TestRdTkNinePatch.c
Normal file
13
rdtk/librdtk/test/TestRdTkNinePatch.c
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
#include <rdtk/rdtk.h>
|
||||||
|
|
||||||
|
int TestRdTkNinePatch(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
rdtkEngine* engine;
|
||||||
|
|
||||||
|
engine = rdtk_engine_new();
|
||||||
|
|
||||||
|
rdtk_engine_free(engine);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user