Split glyph surface creation and pixel upload
When DirectX-SDL2 loses its device, it doesn't lose its textures, just their contents, so we shouldn't remake the textures when we regenerate the glyphs (that's coming next commit).
This commit is contained in:
parent
29c84ae222
commit
5da3b72fca
6 changed files with 145 additions and 110 deletions
|
@ -25,8 +25,9 @@ void Backend_UnlockSurface(Backend_Surface *surface);
|
||||||
void Backend_Blit(Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key);
|
void Backend_Blit(Backend_Surface *source_surface, const RECT *rect, Backend_Surface *destination_surface, long x, long y, BOOL colour_key);
|
||||||
void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue);
|
void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue);
|
||||||
BOOL Backend_SupportsSubpixelGlyphs(void);
|
BOOL Backend_SupportsSubpixelGlyphs(void);
|
||||||
Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch, unsigned char pixel_mode);
|
Backend_Glyph* Backend_CreateGlyph(unsigned int width, unsigned int height, unsigned char pixel_mode);
|
||||||
void Backend_UnloadGlyph(Backend_Glyph *glyph);
|
void Backend_FreeGlyph(Backend_Glyph *glyph);
|
||||||
|
void Backend_LoadGlyphPixels(Backend_Glyph *glyph, const unsigned char *pixels, int pitch);
|
||||||
void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours);
|
void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours);
|
||||||
void Backend_HandleDeviceLoss(void);
|
void Backend_HandleDeviceLoss(void);
|
||||||
void Backend_HandleWindowResize(void);
|
void Backend_HandleWindowResize(void);
|
||||||
|
|
|
@ -628,37 +628,73 @@ BOOL Backend_SupportsSubpixelGlyphs(void)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch, unsigned char pixel_mode)
|
Backend_Glyph* Backend_CreateGlyph(unsigned int width, unsigned int height, unsigned char pixel_mode)
|
||||||
{
|
{
|
||||||
Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
|
Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
|
||||||
|
|
||||||
if (glyph == NULL)
|
if (glyph == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
const unsigned int destination_pitch = (width + 3) & ~3; // Round up to the nearest 4 (OpenGL needs this)
|
GLint previously_bound_texture;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &previously_bound_texture);
|
||||||
|
|
||||||
unsigned char *buffer = (unsigned char*)malloc(destination_pitch * height);
|
glGenTextures(1, &glyph->texture_id);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, glyph->texture_id);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
switch (pixel_mode)
|
glyph->width = width;
|
||||||
|
glyph->height = height;
|
||||||
|
glyph->pixel_mode = pixel_mode;
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, previously_bound_texture);
|
||||||
|
|
||||||
|
return glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backend_FreeGlyph(Backend_Glyph *glyph)
|
||||||
|
{
|
||||||
|
if (glyph == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
glDeleteTextures(1, &glyph->texture_id);
|
||||||
|
free(glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backend_LoadGlyphPixels(Backend_Glyph *glyph, const unsigned char *pixels, int pitch)
|
||||||
|
{
|
||||||
|
if (glyph == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const unsigned int width_in_bytes = (glyph->pixel_mode == FONT_PIXEL_MODE_LCD ? glyph->width * 3 : glyph->width);
|
||||||
|
|
||||||
|
const unsigned int destination_pitch = (width_in_bytes + 3) & ~3; // Round up to the nearest 4 (OpenGL needs this)
|
||||||
|
|
||||||
|
unsigned char *buffer = (unsigned char*)malloc(destination_pitch * glyph->height);
|
||||||
|
|
||||||
|
switch (glyph->pixel_mode)
|
||||||
{
|
{
|
||||||
case FONT_PIXEL_MODE_LCD:
|
case FONT_PIXEL_MODE_LCD:
|
||||||
case FONT_PIXEL_MODE_GRAY:
|
case FONT_PIXEL_MODE_GRAY:
|
||||||
for (unsigned int y = 0; y < height; ++y)
|
for (unsigned int y = 0; y < glyph->height; ++y)
|
||||||
{
|
{
|
||||||
const unsigned char *source_pointer = pixels + y * pitch;
|
const unsigned char *source_pointer = pixels + y * pitch;
|
||||||
unsigned char *destination_pointer = buffer + y * destination_pitch;
|
unsigned char *destination_pointer = buffer + y * destination_pitch;
|
||||||
memcpy(destination_pointer, source_pointer, width);
|
memcpy(destination_pointer, source_pointer, width_in_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FONT_PIXEL_MODE_MONO:
|
case FONT_PIXEL_MODE_MONO:
|
||||||
for (unsigned int y = 0; y < height; ++y)
|
for (unsigned int y = 0; y < glyph->height; ++y)
|
||||||
{
|
{
|
||||||
const unsigned char *source_pointer = pixels + y * pitch;
|
const unsigned char *source_pointer = pixels + y * pitch;
|
||||||
unsigned char *destination_pointer = buffer + y * destination_pitch;
|
unsigned char *destination_pointer = buffer + y * destination_pitch;
|
||||||
|
|
||||||
for (unsigned int x = 0; x < width; ++x)
|
for (unsigned int x = 0; x < width_in_bytes; ++x)
|
||||||
*destination_pointer++ = (*source_pointer++ ? 0xFF : 0);
|
*destination_pointer++ = (*source_pointer++ ? 0xFF : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,36 +704,15 @@ Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width
|
||||||
GLint previously_bound_texture;
|
GLint previously_bound_texture;
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &previously_bound_texture);
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &previously_bound_texture);
|
||||||
|
|
||||||
glGenTextures(1, &glyph->texture_id);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, glyph->texture_id);
|
glBindTexture(GL_TEXTURE_2D, glyph->texture_id);
|
||||||
if (pixel_mode == FONT_PIXEL_MODE_LCD)
|
if (glyph->pixel_mode == FONT_PIXEL_MODE_LCD)
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width / 3, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, glyph->width, glyph->height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
||||||
else
|
else
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, buffer);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, glyph->width, glyph->height, 0, GL_RED, GL_UNSIGNED_BYTE, buffer);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
glyph->width = (pixel_mode == FONT_PIXEL_MODE_LCD ? width / 3 : width);
|
|
||||||
glyph->height = height;
|
|
||||||
glyph->pixel_mode = pixel_mode;
|
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, previously_bound_texture);
|
glBindTexture(GL_TEXTURE_2D, previously_bound_texture);
|
||||||
|
|
||||||
return glyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Backend_UnloadGlyph(Backend_Glyph *glyph)
|
|
||||||
{
|
|
||||||
if (glyph == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
glDeleteTextures(1, &glyph->texture_id);
|
|
||||||
free(glyph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
|
void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
|
||||||
|
|
|
@ -15,6 +15,7 @@ typedef struct Backend_Surface
|
||||||
typedef struct Backend_Glyph
|
typedef struct Backend_Glyph
|
||||||
{
|
{
|
||||||
SDL_Surface *sdlsurface;
|
SDL_Surface *sdlsurface;
|
||||||
|
unsigned char pixel_mode;
|
||||||
} Backend_Glyph;
|
} Backend_Glyph;
|
||||||
|
|
||||||
static SDL_Window *window;
|
static SDL_Window *window;
|
||||||
|
@ -142,7 +143,7 @@ BOOL Backend_SupportsSubpixelGlyphs(void)
|
||||||
return FALSE; // SDL_Surfaces don't have per-component alpha
|
return FALSE; // SDL_Surfaces don't have per-component alpha
|
||||||
}
|
}
|
||||||
|
|
||||||
Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch, unsigned char pixel_mode)
|
Backend_Glyph* Backend_CreateGlyph(unsigned int width, unsigned int height, unsigned char pixel_mode)
|
||||||
{
|
{
|
||||||
Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
|
Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
|
||||||
|
|
||||||
|
@ -157,17 +158,36 @@ Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pixel_mode)
|
glyph->pixel_mode = pixel_mode;
|
||||||
|
|
||||||
|
return glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backend_FreeGlyph(Backend_Glyph *glyph)
|
||||||
|
{
|
||||||
|
if (glyph == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDL_FreeSurface(glyph->sdlsurface);
|
||||||
|
free(glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backend_LoadGlyphPixels(Backend_Glyph *glyph, const unsigned char *pixels, int pitch)
|
||||||
|
{
|
||||||
|
if (glyph == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (glyph->pixel_mode)
|
||||||
{
|
{
|
||||||
// FONT_PIXEL_MODE_LCD is unsupported
|
// FONT_PIXEL_MODE_LCD is unsupported
|
||||||
|
|
||||||
case FONT_PIXEL_MODE_GRAY:
|
case FONT_PIXEL_MODE_GRAY:
|
||||||
for (unsigned int y = 0; y < height; ++y)
|
for (int y = 0; y < glyph->sdlsurface->h; ++y)
|
||||||
{
|
{
|
||||||
const unsigned char *source_pointer = pixels + y * pitch;
|
const unsigned char *source_pointer = pixels + y * pitch;
|
||||||
unsigned char *destination_pointer = (unsigned char*)glyph->sdlsurface->pixels + y * glyph->sdlsurface->pitch;
|
unsigned char *destination_pointer = (unsigned char*)glyph->sdlsurface->pixels + y * glyph->sdlsurface->pitch;
|
||||||
|
|
||||||
for (unsigned int x = 0; x < width; ++x)
|
for (int x = 0; x < glyph->sdlsurface->w; ++x)
|
||||||
{
|
{
|
||||||
*destination_pointer++ = 0xFF;
|
*destination_pointer++ = 0xFF;
|
||||||
*destination_pointer++ = 0xFF;
|
*destination_pointer++ = 0xFF;
|
||||||
|
@ -179,12 +199,12 @@ Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FONT_PIXEL_MODE_MONO:
|
case FONT_PIXEL_MODE_MONO:
|
||||||
for (unsigned int y = 0; y < height; ++y)
|
for (int y = 0; y < glyph->sdlsurface->h; ++y)
|
||||||
{
|
{
|
||||||
const unsigned char *source_pointer = pixels + y * pitch;
|
const unsigned char *source_pointer = pixels + y * pitch;
|
||||||
unsigned char *destination_pointer = (unsigned char*)glyph->sdlsurface->pixels + y * glyph->sdlsurface->pitch;
|
unsigned char *destination_pointer = (unsigned char*)glyph->sdlsurface->pixels + y * glyph->sdlsurface->pitch;
|
||||||
|
|
||||||
for (unsigned int x = 0; x < width; ++x)
|
for (int x = 0; x < glyph->sdlsurface->w; ++x)
|
||||||
{
|
{
|
||||||
*destination_pointer++ = 0xFF;
|
*destination_pointer++ = 0xFF;
|
||||||
*destination_pointer++ = 0xFF;
|
*destination_pointer++ = 0xFF;
|
||||||
|
@ -195,17 +215,6 @@ Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return glyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Backend_UnloadGlyph(Backend_Glyph *glyph)
|
|
||||||
{
|
|
||||||
if (glyph == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SDL_FreeSurface(glyph->sdlsurface);
|
|
||||||
free(glyph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
|
void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
|
||||||
|
|
|
@ -24,6 +24,7 @@ typedef struct Backend_Surface
|
||||||
typedef struct Backend_Glyph
|
typedef struct Backend_Glyph
|
||||||
{
|
{
|
||||||
Backend_Surface *surface;
|
Backend_Surface *surface;
|
||||||
|
unsigned char pixel_mode;
|
||||||
} Backend_Glyph;
|
} Backend_Glyph;
|
||||||
|
|
||||||
static SDL_Renderer *renderer;
|
static SDL_Renderer *renderer;
|
||||||
|
@ -150,10 +151,10 @@ void Backend_UnlockSurface(Backend_Surface *surface)
|
||||||
const unsigned char *src_pixel = surface->pixels;
|
const unsigned char *src_pixel = surface->pixels;
|
||||||
|
|
||||||
// Convert the SDL_Surface's colour-keyed pixels to RGBA32
|
// Convert the SDL_Surface's colour-keyed pixels to RGBA32
|
||||||
for (int y = 0; y < surface->height; ++y)
|
for (unsigned int y = 0; y < surface->height; ++y)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int x = 0; x < surface->width; ++x)
|
for (unsigned int x = 0; x < surface->width; ++x)
|
||||||
{
|
{
|
||||||
*buffer_pointer++ = src_pixel[0];
|
*buffer_pointer++ = src_pixel[0];
|
||||||
*buffer_pointer++ = src_pixel[1];
|
*buffer_pointer++ = src_pixel[1];
|
||||||
|
@ -218,7 +219,7 @@ BOOL Backend_SupportsSubpixelGlyphs(void)
|
||||||
return FALSE; // SDL_Textures don't have per-component alpha
|
return FALSE; // SDL_Textures don't have per-component alpha
|
||||||
}
|
}
|
||||||
|
|
||||||
Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch, unsigned char pixel_mode)
|
Backend_Glyph* Backend_CreateGlyph(unsigned int width, unsigned int height, unsigned char pixel_mode)
|
||||||
{
|
{
|
||||||
Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
|
Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
|
||||||
|
|
||||||
|
@ -233,20 +234,39 @@ Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glyph->pixel_mode = pixel_mode;
|
||||||
|
|
||||||
|
return glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backend_FreeGlyph(Backend_Glyph *glyph)
|
||||||
|
{
|
||||||
|
if (glyph == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Backend_FreeSurface(glyph->surface);
|
||||||
|
free(glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backend_LoadGlyphPixels(Backend_Glyph *glyph, const unsigned char *pixels, int pitch)
|
||||||
|
{
|
||||||
|
if (glyph == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
unsigned int surface_pitch;
|
unsigned int surface_pitch;
|
||||||
unsigned char *surface_pixels = Backend_LockSurface(glyph->surface, &surface_pitch);
|
unsigned char *surface_pixels = Backend_LockSurface(glyph->surface, &surface_pitch);
|
||||||
|
|
||||||
switch (pixel_mode)
|
switch (glyph->pixel_mode)
|
||||||
{
|
{
|
||||||
// FONT_PIXEL_MODE_LCD is unsupported
|
// FONT_PIXEL_MODE_LCD is unsupported
|
||||||
|
|
||||||
case FONT_PIXEL_MODE_GRAY:
|
case FONT_PIXEL_MODE_GRAY:
|
||||||
for (unsigned int y = 0; y < height; ++y)
|
for (unsigned int y = 0; y < glyph->surface->height; ++y)
|
||||||
{
|
{
|
||||||
const unsigned char *source_pointer = pixels + y * pitch;
|
const unsigned char *source_pointer = pixels + y * pitch;
|
||||||
unsigned char *destination_pointer = surface_pixels + y * surface_pitch;
|
unsigned char *destination_pointer = surface_pixels + y * surface_pitch;
|
||||||
|
|
||||||
for (unsigned int x = 0; x < width; ++x)
|
for (unsigned int x = 0; x < glyph->surface->width; ++x)
|
||||||
{
|
{
|
||||||
*destination_pointer++ = 0xFF;
|
*destination_pointer++ = 0xFF;
|
||||||
*destination_pointer++ = 0xFF;
|
*destination_pointer++ = 0xFF;
|
||||||
|
@ -258,12 +278,12 @@ Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FONT_PIXEL_MODE_MONO:
|
case FONT_PIXEL_MODE_MONO:
|
||||||
for (unsigned int y = 0; y < height; ++y)
|
for (unsigned int y = 0; y < glyph->surface->height; ++y)
|
||||||
{
|
{
|
||||||
const unsigned char *source_pointer = pixels + y * pitch;
|
const unsigned char *source_pointer = pixels + y * pitch;
|
||||||
unsigned char *destination_pointer = surface_pixels + y * surface_pitch;
|
unsigned char *destination_pointer = surface_pixels + y * surface_pitch;
|
||||||
|
|
||||||
for (unsigned int x = 0; x < width; ++x)
|
for (unsigned int x = 0; x < glyph->surface->width; ++x)
|
||||||
{
|
{
|
||||||
*destination_pointer++ = 0xFF;
|
*destination_pointer++ = 0xFF;
|
||||||
*destination_pointer++ = 0xFF;
|
*destination_pointer++ = 0xFF;
|
||||||
|
@ -276,17 +296,6 @@ Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width
|
||||||
}
|
}
|
||||||
|
|
||||||
Backend_UnlockSurface(glyph->surface);
|
Backend_UnlockSurface(glyph->surface);
|
||||||
|
|
||||||
return glyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Backend_UnloadGlyph(Backend_Glyph *glyph)
|
|
||||||
{
|
|
||||||
if (glyph == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Backend_FreeSurface(glyph->surface);
|
|
||||||
free(glyph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
|
void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
|
||||||
|
|
|
@ -260,33 +260,56 @@ BOOL Backend_SupportsSubpixelGlyphs(void)
|
||||||
return TRUE; // It's a software renderer, baby
|
return TRUE; // It's a software renderer, baby
|
||||||
}
|
}
|
||||||
|
|
||||||
Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch, unsigned char pixel_mode)
|
Backend_Glyph* Backend_CreateGlyph(unsigned int width, unsigned int height, unsigned char pixel_mode)
|
||||||
{
|
{
|
||||||
Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
|
Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
|
||||||
|
|
||||||
if (glyph == NULL)
|
if (glyph == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
switch (pixel_mode)
|
glyph->pixels = malloc(width * height * (pixel_mode == FONT_PIXEL_MODE_MONO ? sizeof(unsigned char) : sizeof(float)));
|
||||||
|
|
||||||
|
if (glyph->pixels == NULL)
|
||||||
|
{
|
||||||
|
free(glyph);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
glyph->width = width;
|
||||||
|
glyph->height = height;
|
||||||
|
glyph->pixel_mode = pixel_mode;
|
||||||
|
|
||||||
|
return glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backend_FreeGlyph(Backend_Glyph *glyph)
|
||||||
|
{
|
||||||
|
if (glyph == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
free(glyph->pixels);
|
||||||
|
free(glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backend_LoadGlyphPixels(Backend_Glyph *glyph, const unsigned char *pixels, int pitch)
|
||||||
|
{
|
||||||
|
if (glyph == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const unsigned int width_in_bytes = (glyph->pixel_mode == FONT_PIXEL_MODE_LCD ? glyph->width * 3 : glyph->width);
|
||||||
|
|
||||||
|
switch (glyph->pixel_mode)
|
||||||
{
|
{
|
||||||
case FONT_PIXEL_MODE_LCD:
|
case FONT_PIXEL_MODE_LCD:
|
||||||
case FONT_PIXEL_MODE_GRAY:
|
case FONT_PIXEL_MODE_GRAY:
|
||||||
{
|
{
|
||||||
glyph->pixels = malloc(width * height * sizeof(float));
|
|
||||||
|
|
||||||
if (glyph->pixels == NULL)
|
|
||||||
{
|
|
||||||
free(glyph);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
float *destination_pointer = (float*)glyph->pixels;
|
float *destination_pointer = (float*)glyph->pixels;
|
||||||
|
|
||||||
for (unsigned int y = 0; y < height; ++y)
|
for (unsigned int y = 0; y < glyph->height; ++y)
|
||||||
{
|
{
|
||||||
const unsigned char *source_pointer = pixels + y * pitch;
|
const unsigned char *source_pointer = pixels + y * pitch;
|
||||||
|
|
||||||
for (unsigned int x = 0; x < width; ++x)
|
for (unsigned int x = 0; x < width_in_bytes; ++x)
|
||||||
*destination_pointer++ = *source_pointer++ / 255.0f;
|
*destination_pointer++ = *source_pointer++ / 255.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,40 +318,17 @@ Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width
|
||||||
|
|
||||||
case FONT_PIXEL_MODE_MONO:
|
case FONT_PIXEL_MODE_MONO:
|
||||||
{
|
{
|
||||||
glyph->pixels = malloc(width * height);
|
for (unsigned int y = 0; y < glyph->height; ++y)
|
||||||
|
|
||||||
if (glyph->pixels == NULL)
|
|
||||||
{
|
|
||||||
free(glyph);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int y = 0; y < height; ++y)
|
|
||||||
{
|
{
|
||||||
const unsigned char *source_pointer = pixels + y * pitch;
|
const unsigned char *source_pointer = pixels + y * pitch;
|
||||||
unsigned char *destination_pointer = (unsigned char*)glyph->pixels + y * width;
|
unsigned char *destination_pointer = (unsigned char*)glyph->pixels + y * width_in_bytes;
|
||||||
|
|
||||||
memcpy(destination_pointer, source_pointer, width);
|
memcpy(destination_pointer, source_pointer, width_in_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glyph->width = (pixel_mode == FONT_PIXEL_MODE_LCD ? width / 3 : width);
|
|
||||||
glyph->height = height;
|
|
||||||
glyph->pixel_mode = pixel_mode;
|
|
||||||
|
|
||||||
return glyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Backend_UnloadGlyph(Backend_Glyph *glyph)
|
|
||||||
{
|
|
||||||
if (glyph == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
free(glyph->pixels);
|
|
||||||
free(glyph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
|
void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
|
||||||
|
|
|
@ -1027,7 +1027,8 @@ static CachedGlyph* GetGlyphCached(FontObject *font_object, unsigned long unicod
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
glyph->backend = Backend_LoadGlyph(bitmap.buffer, bitmap.width, bitmap.rows, bitmap.pitch, pixel_mode);
|
glyph->backend = Backend_CreateGlyph((pixel_mode == FT_PIXEL_MODE_LCD ? bitmap.width / 3 : bitmap.width), bitmap.rows, pixel_mode);
|
||||||
|
Backend_LoadGlyphPixels(glyph->backend, bitmap.buffer, bitmap.pitch);
|
||||||
|
|
||||||
FT_Bitmap_Done(font_object->library, &bitmap);
|
FT_Bitmap_Done(font_object->library, &bitmap);
|
||||||
}
|
}
|
||||||
|
@ -1042,7 +1043,7 @@ static void UnloadCachedGlyphs(FontObject *font_object)
|
||||||
{
|
{
|
||||||
CachedGlyph *next_glyph = glyph->next;
|
CachedGlyph *next_glyph = glyph->next;
|
||||||
|
|
||||||
Backend_UnloadGlyph(glyph->backend);
|
Backend_FreeGlyph(glyph->backend);
|
||||||
free(glyph);
|
free(glyph);
|
||||||
|
|
||||||
glyph = next_glyph;
|
glyph = next_glyph;
|
||||||
|
|
Loading…
Add table
Reference in a new issue