From 628207f7220a8f468d5e3908c2f4638ad1d3dd16 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[EMAIL REDACTED]>
Date: Mon, 9 May 2022 19:28:55 +0100
Subject: [PATCH] Factor out repeated code to allocate a SDL_Surface
Signed-off-by: Simon McVittie <smcv@collabora.com>
---
SDL_ttf.c | 158 +++++++++++++-----------------------------------------
1 file changed, 38 insertions(+), 120 deletions(-)
diff --git a/SDL_ttf.c b/SDL_ttf.c
index aac2b16..0cfccb0 100644
--- a/SDL_ttf.c
+++ b/SDL_ttf.c
@@ -1366,19 +1366,27 @@ static SDL_INLINE int Render_Line(const render_mode_t render_mode, int subpixel,
#endif
}
-static SDL_Surface* Create_Surface_Solid(int width, int height, SDL_Color fg, Uint32 *color)
+
+/* Create a surface with memory:
+ * - pitch is rounded to alignment
+ * - address is aligned
+ *
+ * If format is 4 bytes per pixel, bgcolor is used to initialize each
+ * 4-byte word in the image data.
+ *
+ * Otherwise, the low byte of format is used to initialize each byte
+ * in the image data.
+ */
+static SDL_Surface *AllocateAlignedPixels(int width, int height, SDL_PixelFormatEnum format, Uint32 bgcolor)
{
const int alignment = Get_Alignement() - 1;
- SDL_Surface *textbuf;
+ const int bytes_per_pixel = SDL_BYTESPERPIXEL(format);
+ SDL_Surface *textbuf = NULL;
Sint64 size;
-
- /* Create a surface with memory:
- * - pitch is rounded to alignment
- * - adress is aligned
- */
void *pixels, *ptr;
- /* Worse case at the end of line pulling 'alignment' extra blank pixels */
- Sint64 pitch = (Sint64)width + (Sint64)alignment;
+ /* Worst case at the end of line pulling 'alignment' extra blank pixels */
+ Sint64 pitch = ((Sint64)width + (Sint64)alignment) * bytes_per_pixel;
+
pitch += alignment;
pitch &= ~alignment;
size = height * pitch + sizeof (void *) + alignment;
@@ -1396,7 +1404,7 @@ static SDL_Surface* Create_Surface_Solid(int width, int height, SDL_Color fg, Ui
pixels = (void *)(((uintptr_t)ptr + sizeof(void *) + alignment) & ~alignment);
((void **)pixels)[-1] = ptr;
- textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, (int)pitch, SDL_PIXELFORMAT_INDEX8);
+ textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, (int)pitch, format);
if (textbuf == NULL) {
SDL_free(ptr);
return NULL;
@@ -1406,8 +1414,22 @@ static SDL_Surface* Create_Surface_Solid(int width, int height, SDL_Color fg, Ui
textbuf->flags &= ~SDL_PREALLOC;
textbuf->flags |= SDL_SIMD_ALIGNED;
- /* Initialize with background to 0 */
- SDL_memset(pixels, 0, height * pitch);
+ if (bytes_per_pixel == 4) {
+ SDL_memset4(pixels, bgcolor, (height * pitch) / 4);
+ }
+ else {
+ SDL_memset(pixels, (bgcolor & 0xff), height * pitch);
+ }
+
+ return textbuf;
+}
+
+static SDL_Surface* Create_Surface_Solid(int width, int height, SDL_Color fg, Uint32 *color)
+{
+ SDL_Surface *textbuf = AllocateAlignedPixels(width, height, SDL_PIXELFORMAT_INDEX8, 0);
+ if (textbuf == NULL) {
+ return NULL;
+ }
/* Underline/Strikethrough color style */
*color = 1;
@@ -1431,48 +1453,12 @@ static SDL_Surface* Create_Surface_Solid(int width, int height, SDL_Color fg, Ui
static SDL_Surface* Create_Surface_Shaded(int width, int height, SDL_Color fg, SDL_Color bg, Uint32 *color)
{
- const int alignment = Get_Alignement() - 1;
- SDL_Surface *textbuf;
- Sint64 size;
+ SDL_Surface *textbuf = AllocateAlignedPixels(width, height, SDL_PIXELFORMAT_INDEX8, 0);
Uint8 bg_alpha = bg.a;
-
- /* Create a surface with memory:
- * - pitch is rounded to alignment
- * - adress is aligned
- */
- void *pixels, *ptr;
- /* Worse case at the end of line pulling 'alignment' extra blank pixels */
- Sint64 pitch = (Sint64)width + (Sint64)alignment;
- pitch += alignment;
- pitch &= ~alignment;
- size = height * pitch + sizeof (void *) + alignment;
- if (size < 0 || size > SDL_MAX_SINT32) {
- /* Overflow... */
- return NULL;
- }
-
- ptr = SDL_malloc((size_t)size);
- if (ptr == NULL) {
- return NULL;
- }
-
- /* address is aligned */
- pixels = (void *)(((uintptr_t)ptr + sizeof(void *) + alignment) & ~alignment);
- ((void **)pixels)[-1] = ptr;
-
- textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, (int)pitch, SDL_PIXELFORMAT_INDEX8);
if (textbuf == NULL) {
- SDL_free(ptr);
return NULL;
}
- /* Let SDL handle the memory allocation */
- textbuf->flags &= ~SDL_PREALLOC;
- textbuf->flags |= SDL_SIMD_ALIGNED;
-
- /* Initialize with background to 0 */
- SDL_memset(pixels, 0, height * pitch);
-
/* Underline/Strikethrough color style */
*color = NUM_GRAYS - 1;
@@ -1520,11 +1506,10 @@ static SDL_Surface* Create_Surface_Shaded(int width, int height, SDL_Color fg, S
static SDL_Surface *Create_Surface_Blended(int width, int height, SDL_Color fg, Uint32 *color)
{
- const int alignment = Get_Alignement() - 1;
SDL_Surface *textbuf = NULL;
Uint32 bgcolor;
- /* Background color */
+ /* Background color: initialize with fg and 0 alpha */
bgcolor = (fg.r << 16) | (fg.g << 8) | fg.b;
/* Underline/Strikethrough color style */
@@ -1532,44 +1517,11 @@ static SDL_Surface *Create_Surface_Blended(int width, int height, SDL_Color fg,
/* Create the target surface if required */
if (width != 0) {
- /* Create a surface with memory:
- * - pitch is rounded to alignment
- * - adress is aligned
- */
- Sint64 size;
- void *pixels, *ptr;
- /* Worse case at the end of line pulling 'alignment' extra blank pixels */
- Sint64 pitch = ((Sint64)width + (Sint64)alignment) * 4;
- pitch += alignment;
- pitch &= ~alignment;
- size = height * pitch + sizeof (void *) + alignment;
- if (size < 0 || size > SDL_MAX_SINT32) {
- /* Overflow... */
- return NULL;
- }
-
- ptr = SDL_malloc((size_t)size);
- if (ptr == NULL) {
- return NULL;
- }
-
- /* address is aligned */
- pixels = (void *)(((uintptr_t)ptr + sizeof(void *) + alignment) & ~alignment);
- ((void **)pixels)[-1] = ptr;
-
- textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, (int)pitch, SDL_PIXELFORMAT_ARGB8888);
+ textbuf = AllocateAlignedPixels(width, height, SDL_PIXELFORMAT_ARGB8888, bgcolor);
if (textbuf == NULL) {
- SDL_free(ptr);
return NULL;
}
- /* Let SDL handle the memory allocation */
- textbuf->flags &= ~SDL_PREALLOC;
- textbuf->flags |= SDL_SIMD_ALIGNED;
-
- /* Initialize with fg and 0 alpha */
- SDL_memset4(pixels, bgcolor, (height * pitch) / 4);
-
/* Support alpha blending */
if (fg.a != SDL_ALPHA_OPAQUE) {
SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND);
@@ -1581,7 +1533,6 @@ static SDL_Surface *Create_Surface_Blended(int width, int height, SDL_Color fg,
static SDL_Surface* Create_Surface_LCD(int width, int height, SDL_Color fg, SDL_Color bg, Uint32 *color)
{
- const int alignment = Get_Alignement() - 1;
SDL_Surface *textbuf = NULL;
Uint32 bgcolor;
@@ -1593,44 +1544,11 @@ static SDL_Surface* Create_Surface_LCD(int width, int height, SDL_Color fg, SDL_
/* Create the target surface if required */
if (width != 0) {
- /* Create a surface with memory:
- * - pitch is rounded to alignment
- * - adress is aligned
- */
- Sint64 size;
- void *pixels, *ptr;
- /* Worse case at the end of line pulling 'alignment' extra blank pixels */
- Sint64 pitch = ((Sint64)width + (Sint64)alignment) * 4;
- pitch += alignment;
- pitch &= ~alignment;
- size = height * pitch + sizeof (void *) + alignment;
- if (size < 0 || size > SDL_MAX_SINT32) {
- /* Overflow... */
- return NULL;
- }
-
- ptr = SDL_malloc((size_t)size);
- if (ptr == NULL) {
- return NULL;
- }
-
- /* address is aligned */
- pixels = (void *)(((uintptr_t)ptr + sizeof(void *) + alignment) & ~alignment);
- ((void **)pixels)[-1] = ptr;
-
- textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, pitch, SDL_PIXELFORMAT_ARGB8888);
+ textbuf = AllocateAlignedPixels(width, height, SDL_PIXELFORMAT_ARGB8888, bgcolor);
if (textbuf == NULL) {
- SDL_free(ptr);
return NULL;
}
- /* Let SDL handle the memory allocation */
- textbuf->flags &= ~SDL_PREALLOC;
- textbuf->flags |= SDL_SIMD_ALIGNED;
-
- /* Initialize with fg and 0 alpha */
- SDL_memset4(pixels, bgcolor, (height * pitch) / 4);
-
/* Support alpha blending */
if (bg.a != SDL_ALPHA_OPAQUE) {
SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND);