Allow font atlases to be non-square
Saves a little memory in some cases. It's the backend's job to decide if this is a problem or not, and pad it if it has to.
This commit is contained in:
parent
17da39fa14
commit
daa55b1a3c
7 changed files with 28 additions and 26 deletions
|
@ -24,7 +24,7 @@ unsigned char* RenderBackend_LockSurface(RenderBackend_Surface *surface, size_t
|
|||
void RenderBackend_UnlockSurface(RenderBackend_Surface *surface, size_t width, size_t height);
|
||||
void RenderBackend_Blit(RenderBackend_Surface *source_surface, const RenderBackend_Rect *rect, RenderBackend_Surface *destination_surface, long x, long y, bool colour_key);
|
||||
void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RenderBackend_Rect *rect, unsigned char red, unsigned char green, unsigned char blue);
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t size);
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t width, size_t height);
|
||||
void RenderBackend_DestroyGlyphAtlas(RenderBackend_GlyphAtlas *atlas);
|
||||
void RenderBackend_UploadGlyph(RenderBackend_GlyphAtlas *atlas, size_t x, size_t y, const unsigned char *pixels, size_t width, size_t height);
|
||||
void RenderBackend_PrepareToDrawGlyphs(RenderBackend_GlyphAtlas *atlas, RenderBackend_Surface *destination_surface, unsigned char red, unsigned char green, unsigned char blue);
|
||||
|
|
|
@ -40,7 +40,8 @@ typedef struct RenderBackend_Surface
|
|||
typedef struct RenderBackend_GlyphAtlas
|
||||
{
|
||||
GLuint texture_id;
|
||||
size_t size;
|
||||
size_t width;
|
||||
size_t height;
|
||||
} RenderBackend_GlyphAtlas;
|
||||
|
||||
typedef struct Coordinate2D
|
||||
|
@ -866,21 +867,22 @@ void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RenderBacken
|
|||
// Glyph management //
|
||||
//////////////////////
|
||||
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t size)
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t width, size_t height)
|
||||
{
|
||||
RenderBackend_GlyphAtlas *atlas = (RenderBackend_GlyphAtlas*)malloc(sizeof(RenderBackend_GlyphAtlas));
|
||||
|
||||
if (atlas != NULL)
|
||||
{
|
||||
atlas->size = size;
|
||||
atlas->width = width;
|
||||
atlas->height = height;
|
||||
|
||||
glGenTextures(1, &atlas->texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, atlas->texture_id);
|
||||
|
||||
#ifdef USE_OPENGLES2
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, size, size, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, size, size, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
||||
#endif
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
@ -986,10 +988,10 @@ void RenderBackend_DrawGlyph(RenderBackend_GlyphAtlas *atlas, long x, long y, si
|
|||
vertex_buffer_slot->vertices[1][2].position.x = vertex_left;
|
||||
vertex_buffer_slot->vertices[1][2].position.y = vertex_bottom;
|
||||
|
||||
const GLfloat texture_left = glyph_x / (GLfloat)atlas->size;
|
||||
const GLfloat texture_top = glyph_y / (GLfloat)atlas->size;
|
||||
const GLfloat texture_right = (glyph_x + glyph_width) / (GLfloat)atlas->size;
|
||||
const GLfloat texture_bottom = (glyph_y + glyph_height) / (GLfloat)atlas->size;
|
||||
const GLfloat texture_left = glyph_x / (GLfloat)atlas->width;
|
||||
const GLfloat texture_top = glyph_y / (GLfloat)atlas->height;
|
||||
const GLfloat texture_right = (glyph_x + glyph_width) / (GLfloat)atlas->width;
|
||||
const GLfloat texture_bottom = (glyph_y + glyph_height) / (GLfloat)atlas->height;
|
||||
|
||||
vertex_buffer_slot->vertices[0][0].texture.x = texture_left;
|
||||
vertex_buffer_slot->vertices[0][0].texture.y = texture_top;
|
||||
|
|
|
@ -197,13 +197,13 @@ void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RenderBacken
|
|||
Backend_PrintError("Couldn't fill rectangle with color: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t size)
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t width, size_t height)
|
||||
{
|
||||
RenderBackend_GlyphAtlas *atlas = (RenderBackend_GlyphAtlas*)malloc(sizeof(RenderBackend_GlyphAtlas));
|
||||
|
||||
if (atlas != NULL)
|
||||
{
|
||||
atlas->sdlsurface = SDL_CreateRGBSurfaceWithFormat(0, size, size, 0, SDL_PIXELFORMAT_RGBA32);
|
||||
atlas->sdlsurface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 0, SDL_PIXELFORMAT_RGBA32);
|
||||
|
||||
if (atlas->sdlsurface != NULL)
|
||||
{
|
||||
|
|
|
@ -335,13 +335,13 @@ void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RenderBacken
|
|||
Backend_PrintError("Couldn't enable alpha blending for drawing operations: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t size)
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t width, size_t height)
|
||||
{
|
||||
RenderBackend_GlyphAtlas *atlas = (RenderBackend_GlyphAtlas*)malloc(sizeof(RenderBackend_GlyphAtlas));
|
||||
|
||||
if (atlas != NULL)
|
||||
{
|
||||
atlas->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, size, size);
|
||||
atlas->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, width, height);
|
||||
|
||||
if (atlas->texture != NULL)
|
||||
{
|
||||
|
|
|
@ -22,7 +22,8 @@ typedef struct RenderBackend_Surface
|
|||
typedef struct RenderBackend_GlyphAtlas
|
||||
{
|
||||
unsigned char *pixels;
|
||||
size_t size;
|
||||
size_t width;
|
||||
size_t height;
|
||||
} RenderBackend_GlyphAtlas;
|
||||
|
||||
static RenderBackend_Surface framebuffer;
|
||||
|
@ -258,17 +259,18 @@ ATTRIBUTE_HOT void RenderBackend_ColourFill(RenderBackend_Surface *surface, cons
|
|||
}
|
||||
}
|
||||
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t size)
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t width, size_t height)
|
||||
{
|
||||
RenderBackend_GlyphAtlas *atlas = (RenderBackend_GlyphAtlas*)malloc(sizeof(RenderBackend_GlyphAtlas));
|
||||
|
||||
if (atlas != NULL)
|
||||
{
|
||||
atlas->pixels = (unsigned char*)malloc(size * size);
|
||||
atlas->pixels = (unsigned char*)malloc(width * height);
|
||||
|
||||
if (atlas->pixels != NULL)
|
||||
{
|
||||
atlas->size = size;
|
||||
atlas->width = width;
|
||||
atlas->height = height;
|
||||
|
||||
return atlas;
|
||||
}
|
||||
|
@ -288,7 +290,7 @@ void RenderBackend_DestroyGlyphAtlas(RenderBackend_GlyphAtlas *atlas)
|
|||
void RenderBackend_UploadGlyph(RenderBackend_GlyphAtlas *atlas, size_t x, size_t y, const unsigned char *pixels, size_t width, size_t height)
|
||||
{
|
||||
for (size_t i = 0; i < height; ++i)
|
||||
memcpy(&atlas->pixels[(y + i) * atlas->size + x], &pixels[i * width], width);
|
||||
memcpy(&atlas->pixels[(y + i) * atlas->width + x], &pixels[i * width], width);
|
||||
}
|
||||
|
||||
void RenderBackend_PrepareToDrawGlyphs(RenderBackend_GlyphAtlas *atlas, RenderBackend_Surface *destination_surface, unsigned char red, unsigned char green, unsigned char blue)
|
||||
|
@ -311,7 +313,7 @@ void RenderBackend_DrawGlyph(RenderBackend_GlyphAtlas *atlas, long x, long y, si
|
|||
{
|
||||
for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph_width, glyph_destination_surface->width); ++ix)
|
||||
{
|
||||
const unsigned char alpha_int = atlas->pixels[(glyph_y + iy) * atlas->size + (glyph_x + ix)];
|
||||
const unsigned char alpha_int = atlas->pixels[(glyph_y + iy) * atlas->width + (glyph_x + ix)];
|
||||
|
||||
if (alpha_int != 0)
|
||||
{
|
||||
|
|
|
@ -722,7 +722,7 @@ void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RenderBacken
|
|||
}
|
||||
}
|
||||
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t size)
|
||||
RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t width, size_t height)
|
||||
{
|
||||
RenderBackend_GlyphAtlas *atlas = (RenderBackend_GlyphAtlas*)malloc(sizeof(RenderBackend_GlyphAtlas));
|
||||
|
||||
|
@ -730,8 +730,8 @@ RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t size)
|
|||
{
|
||||
// Initialise texture
|
||||
memset(&atlas->texture, 0, sizeof(atlas->texture));
|
||||
atlas->texture.surface.width = size;
|
||||
atlas->texture.surface.height = size;
|
||||
atlas->texture.surface.width = width;
|
||||
atlas->texture.surface.height = height;
|
||||
atlas->texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R8;
|
||||
atlas->texture.surface.depth = 1;
|
||||
atlas->texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include "File.h"
|
||||
#include "Backends/Rendering.h"
|
||||
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
// Cave Story wasn't intended to use font anti-aliasing. It's only because Microsoft enabled it
|
||||
// by default from Windows Vista onwards that the game started using it.
|
||||
// Font anti-aliasing conflicts with the game's colour-keying, causing ugly artifacting around
|
||||
|
@ -1087,7 +1085,7 @@ Font* LoadFontFromData(const unsigned char *data, size_t data_size, size_t cell_
|
|||
|
||||
font->atlas_row_length = atlas_columns;
|
||||
|
||||
font->atlas = RenderBackend_CreateGlyphAtlas(MAX(atlas_columns * atlas_entry_width, atlas_rows * atlas_entry_height));
|
||||
font->atlas = RenderBackend_CreateGlyphAtlas(atlas_columns * atlas_entry_width, atlas_rows * atlas_entry_height);
|
||||
|
||||
if (font->atlas != NULL)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue