19 #include <winpr/config.h>
20 #include <winpr/assert.h>
22 #include <rdtk/config.h>
24 #include "rdtk_resources.h"
26 #include "rdtk_nine_patch.h"
28 #if defined(WINPR_WITH_PNG)
29 #define FILE_EXT "png"
31 #define FILE_EXT "bmp"
34 static int rdtk_image_copy_alpha_blend(uint8_t* pDstData,
int nDstStep,
int nXDst,
int nYDst,
35 int nWidth,
int nHeight,
const uint8_t* pSrcData,
36 int nSrcStep,
int nXSrc,
int nYSrc)
38 WINPR_ASSERT(pDstData);
39 WINPR_ASSERT(pSrcData);
41 for (
int y = 0; y < nHeight; y++)
43 const uint8_t* pSrcPixel = &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * 4)];
44 uint8_t* pDstPixel = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4)];
46 for (
int x = 0; x < nWidth; x++)
48 uint8_t B = pSrcPixel[0];
49 uint8_t G = pSrcPixel[1];
50 uint8_t R = pSrcPixel[2];
51 uint8_t A = pSrcPixel[3];
65 pDstPixel[0] = B + (pDstPixel[0] * (255 - A) + (255 / 2)) / 255;
66 pDstPixel[1] = G + (pDstPixel[1] * (255 - A) + (255 / 2)) / 255;
67 pDstPixel[2] = R + (pDstPixel[2] * (255 - A) + (255 / 2)) / 255;
78 int rdtk_nine_patch_draw(rdtkSurface* surface,
int nXDst,
int nYDst,
int nWidth,
int nHeight,
79 rdtkNinePatch* ninePatch)
81 WINPR_ASSERT(surface);
82 WINPR_ASSERT(ninePatch);
84 if (nWidth < ninePatch->width)
85 nWidth = ninePatch->width;
87 if (nHeight < ninePatch->height)
88 nHeight = ninePatch->height;
90 WINPR_UNUSED(nHeight);
92 int scaleWidth = nWidth - (ninePatch->width - ninePatch->scaleWidth);
93 int nSrcStep = ninePatch->scanline;
94 const uint8_t* pSrcData = ninePatch->data;
95 uint8_t* pDstData = surface->data;
96 WINPR_ASSERT(surface->scanline <= INT_MAX);
97 int nDstStep = (int)surface->scanline;
104 int width = ninePatch->scaleLeft;
105 int height = ninePatch->scaleTop;
106 rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, width, height, pSrcData,
107 nSrcStep, nXSrc, nYSrc);
110 nXSrc = ninePatch->scaleLeft;
112 height = ninePatch->scaleTop;
114 while (x < (nXSrc + scaleWidth))
116 width = (nXSrc + scaleWidth) - x;
118 if (width > ninePatch->scaleWidth)
119 width = ninePatch->scaleWidth;
121 rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, width, height,
122 pSrcData, nSrcStep, nXSrc, nYSrc);
127 nXSrc = ninePatch->scaleRight;
129 width = ninePatch->width - ninePatch->scaleRight;
130 height = ninePatch->scaleTop;
131 rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, width, height, pSrcData,
132 nSrcStep, nXSrc, nYSrc);
135 y = ninePatch->scaleTop;
138 nYSrc = ninePatch->scaleTop;
139 width = ninePatch->scaleLeft;
140 height = ninePatch->scaleHeight;
141 rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, width, height, pSrcData,
142 nSrcStep, nXSrc, nYSrc);
145 nXSrc = ninePatch->scaleLeft;
146 nYSrc = ninePatch->scaleTop;
147 height = ninePatch->scaleHeight;
149 while (x < (nXSrc + scaleWidth))
151 width = (nXSrc + scaleWidth) - x;
153 if (width > ninePatch->scaleWidth)
154 width = ninePatch->scaleWidth;
156 rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, width, height,
157 pSrcData, nSrcStep, nXSrc, nYSrc);
162 nXSrc = ninePatch->scaleRight;
163 nYSrc = ninePatch->scaleTop;
164 width = ninePatch->width - ninePatch->scaleRight;
165 height = ninePatch->scaleHeight;
166 rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, width, height, pSrcData,
167 nSrcStep, nXSrc, nYSrc);
170 y = ninePatch->scaleBottom;
173 nYSrc = ninePatch->scaleBottom;
174 width = ninePatch->scaleLeft;
175 height = ninePatch->height - ninePatch->scaleBottom;
176 rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, width, height, pSrcData,
177 nSrcStep, nXSrc, nYSrc);
180 nXSrc = ninePatch->scaleLeft;
181 nYSrc = ninePatch->scaleBottom;
182 height = ninePatch->height - ninePatch->scaleBottom;
184 while (x < (nXSrc + scaleWidth))
186 width = (nXSrc + scaleWidth) - x;
188 if (width > ninePatch->scaleWidth)
189 width = ninePatch->scaleWidth;
191 rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, width, height,
192 pSrcData, nSrcStep, nXSrc, nYSrc);
197 nXSrc = ninePatch->scaleRight;
198 nYSrc = ninePatch->scaleBottom;
199 width = ninePatch->width - ninePatch->scaleRight;
200 height = ninePatch->height - ninePatch->scaleBottom;
201 rdtk_image_copy_alpha_blend(pDstData, nDstStep, nXDst + x, nYDst + y, width, height, pSrcData,
202 nSrcStep, nXSrc, nYSrc);
206 static BOOL rdtk_nine_patch_get_scale_lr(rdtkNinePatch* ninePatch,
wImage* image)
209 WINPR_ASSERT(ninePatch);
211 WINPR_ASSERT(image->data);
212 WINPR_ASSERT(image->width > 0);
217 for (uint32_t x = 1; x < image->width - 1; x++)
219 const uint32_t* pixel = (
const uint32_t*)&image->data[
sizeof(uint32_t) * x];
235 if ((beg <= 0) || (end <= 0))
238 WINPR_ASSERT(beg <= INT32_MAX);
239 WINPR_ASSERT(end <= INT32_MAX);
240 ninePatch->scaleLeft = (int32_t)beg - 1;
241 ninePatch->scaleRight = (int32_t)end - 1;
242 ninePatch->scaleWidth = ninePatch->scaleRight - ninePatch->scaleLeft;
247 static BOOL rdtk_nine_patch_get_scale_ht(rdtkNinePatch* ninePatch,
wImage* image)
250 WINPR_ASSERT(ninePatch);
252 WINPR_ASSERT(image->data);
253 WINPR_ASSERT(image->height > 0);
254 WINPR_ASSERT(image->scanline > 0);
259 for (uint32_t y = 1; y < image->height - 1; y++)
261 const uint32_t* pixel =
262 (
const uint32_t*)&image->data[1ULL * image->scanline * y];
278 if ((beg <= 0) || (end <= 0))
281 WINPR_ASSERT(beg <= INT32_MAX);
282 WINPR_ASSERT(end <= INT32_MAX);
283 ninePatch->scaleTop = (int32_t)beg - 1;
284 ninePatch->scaleBottom = (int32_t)end - 1;
285 ninePatch->scaleHeight = ninePatch->scaleBottom - ninePatch->scaleTop;
290 static BOOL rdtk_nine_patch_get_fill_lr(rdtkNinePatch* ninePatch,
wImage* image)
293 WINPR_ASSERT(ninePatch);
295 WINPR_ASSERT(image->data);
296 WINPR_ASSERT(image->width > 0);
297 WINPR_ASSERT(image->height > 0);
298 WINPR_ASSERT(image->scanline > 0);
303 for (uint32_t x = 1; x < image->width - 1; x++)
305 const uint32_t* pixel =
306 (uint32_t*)&image->data[((1ULL * image->height - 1ULL) * image->scanline) +
307 x *
sizeof(uint32_t)];
323 if ((beg <= 0) || (end <= 0))
326 WINPR_ASSERT(beg <= INT32_MAX);
327 WINPR_ASSERT(end <= INT32_MAX);
329 ninePatch->fillLeft = (int32_t)beg - 1;
330 ninePatch->fillRight = (int32_t)end - 1;
331 ninePatch->fillWidth = ninePatch->fillRight - ninePatch->fillLeft;
336 static BOOL rdtk_nine_patch_get_fill_ht(rdtkNinePatch* ninePatch,
wImage* image)
339 WINPR_ASSERT(ninePatch);
341 WINPR_ASSERT(image->data);
342 WINPR_ASSERT(image->width > 0);
343 WINPR_ASSERT(image->height > 0);
344 WINPR_ASSERT(image->scanline > 0);
349 for (uint32_t y = 1; y < image->height - 1; y++)
351 const uint32_t* pixel =
352 (uint32_t*)&image->data[((image->width - 1) *
sizeof(uint32_t)) +
353 1ull * image->scanline * y];
369 if ((beg <= 0) || (end <= 0))
372 WINPR_ASSERT(beg <= INT32_MAX);
373 WINPR_ASSERT(end <= INT32_MAX);
374 ninePatch->scaleTop = (int32_t)beg - 1;
375 ninePatch->scaleBottom = (int32_t)end - 1;
376 ninePatch->scaleHeight = ninePatch->scaleBottom - ninePatch->scaleTop;
381 int rdtk_nine_patch_set_image(rdtkNinePatch* ninePatch,
wImage* image)
384 WINPR_ASSERT(ninePatch);
386 ninePatch->image = image;
389 if (!rdtk_nine_patch_get_scale_lr(ninePatch, image))
392 if (!rdtk_nine_patch_get_scale_ht(ninePatch, image))
396 if (!rdtk_nine_patch_get_fill_lr(ninePatch, image))
399 if (!rdtk_nine_patch_get_fill_ht(ninePatch, image))
403 WINPR_ASSERT(image->width >= 2);
404 WINPR_ASSERT(image->height >= 2);
405 WINPR_ASSERT(image->scanline > 0);
406 WINPR_ASSERT(image->width <= INT32_MAX);
407 WINPR_ASSERT(image->height <= INT32_MAX);
408 WINPR_ASSERT(image->scanline <= INT32_MAX);
409 WINPR_ASSERT(image->data);
411 ninePatch->width = (int32_t)image->width - 2;
412 ninePatch->height = (int32_t)image->height - 2;
413 ninePatch->data = &image->data[image->scanline + 4];
414 ninePatch->scanline = (int32_t)image->scanline;
419 rdtkNinePatch* rdtk_nine_patch_new(rdtkEngine* engine)
421 WINPR_ASSERT(engine);
422 rdtkNinePatch* ninePatch = (rdtkNinePatch*)calloc(1,
sizeof(rdtkNinePatch));
427 ninePatch->engine = engine;
431 void rdtk_nine_patch_free(rdtkNinePatch* ninePatch)
436 winpr_image_free(ninePatch->image, TRUE);
440 int rdtk_nine_patch_engine_init(rdtkEngine* engine)
444 rdtkNinePatch* ninePatch = NULL;
446 WINPR_ASSERT(engine);
448 if (!engine->button9patch)
451 const uint8_t* data = NULL;
453 size = rdtk_get_embedded_resource_file(
"btn_default_normal.9." FILE_EXT, &data);
457 image = winpr_image_new();
460 status = winpr_image_read_buffer(image, data, (
size_t)size);
465 ninePatch = engine->button9patch = rdtk_nine_patch_new(engine);
468 rdtk_nine_patch_set_image(ninePatch, image);
470 winpr_image_free(image, TRUE);
473 winpr_image_free(image, TRUE);
476 if (!engine->textField9patch)
479 const uint8_t* data = NULL;
481 size = rdtk_get_embedded_resource_file(
"textfield_default.9." FILE_EXT, &data);
486 image = winpr_image_new();
489 status = winpr_image_read_buffer(image, data, (
size_t)size);
494 ninePatch = engine->textField9patch = rdtk_nine_patch_new(engine);
497 rdtk_nine_patch_set_image(ninePatch, image);
499 winpr_image_free(image, TRUE);
502 winpr_image_free(image, TRUE);
508 int rdtk_nine_patch_engine_uninit(rdtkEngine* engine)
510 WINPR_ASSERT(engine);
511 if (engine->button9patch)
513 rdtk_nine_patch_free(engine->button9patch);
514 engine->button9patch = NULL;
517 if (engine->textField9patch)
519 rdtk_nine_patch_free(engine->textField9patch);
520 engine->textField9patch = NULL;