From 6a7fd148339a91c66a265f4dc374350c31a38eaf Mon Sep 17 00:00:00 2001 From: Clownacy Date: Tue, 23 Jul 2019 17:20:56 +0100 Subject: [PATCH] Font refactor part 2: SDL_Surface No per-component alpha support here --- src/Backends/Rendering.h | 1 + src/Backends/Rendering/SDLSurface.cpp | 89 +++++++++++++++++++++++++-- src/Backends/Rendering/Software.cpp | 5 ++ src/Font.cpp | 2 +- 4 files changed, 92 insertions(+), 5 deletions(-) diff --git a/src/Backends/Rendering.h b/src/Backends/Rendering.h index 8f2be6e0..b3239995 100644 --- a/src/Backends/Rendering.h +++ b/src/Backends/Rendering.h @@ -26,6 +26,7 @@ void Backend_BlitToScreen(Backend_Surface *source_surface, const RECT *rect, lon void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue); void Backend_ColourFillToScreen(const RECT *rect, unsigned char red, unsigned char green, unsigned char blue); void Backend_ScreenToSurface(Backend_Surface *surface, const RECT *rect); +BOOL Backend_SupportsSubpixelGlyph(void); Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch, unsigned short total_greys, unsigned char pixel_mode); void Backend_UnloadGlyph(Backend_Glyph *glyph); void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours); diff --git a/src/Backends/Rendering/SDLSurface.cpp b/src/Backends/Rendering/SDLSurface.cpp index c7e173f6..ec530add 100644 --- a/src/Backends/Rendering/SDLSurface.cpp +++ b/src/Backends/Rendering/SDLSurface.cpp @@ -14,6 +14,11 @@ typedef struct Backend_Surface SDL_Surface *sdl_surface; } Backend_Surface; +typedef struct Backend_Glyph +{ + SDL_Surface *sdl_surface; +} Backend_Glyph; + static SDL_Window *window; static SDL_Surface *window_surface; @@ -132,14 +137,90 @@ void Backend_ScreenToSurface(Backend_Surface *surface, const RECT *rect) Backend_Blit(&framebuffer, rect, surface, rect->left, rect->top, FALSE); } -void Backend_DrawText(Backend_Surface *surface, FontObject *font, int x, int y, const char *text, unsigned long colour) +BOOL Backend_SupportsSubpixelGlyph(void) { - DrawText(font, (unsigned char*)surface->sdl_surface->pixels, surface->sdl_surface->pitch, surface->sdl_surface->w, surface->sdl_surface->h, x, y, colour, text, strlen(text)); + return FALSE; // SDL_Surfaces don't have per-component alpha } -void Backend_DrawTextToScreen(FontObject *font, int x, int y, const char *text, unsigned long colour) +Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch, unsigned short total_greys, unsigned char pixel_mode) { - Backend_DrawText(&framebuffer, font, x, y, text, colour); + Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph)); + + if (glyph == NULL) + return NULL; + + glyph->sdl_surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 0, SDL_PIXELFORMAT_RGBA32); + + if (glyph->sdl_surface == NULL) + { + free(glyph); + return NULL; + } + + switch (pixel_mode) + { + // FONT_PIXEL_MODE_LCD is unsupported + + case FONT_PIXEL_MODE_GRAY: + for (unsigned int y = 0; y < height; ++y) + { + const unsigned char *source_pointer = pixels + y * pitch; + unsigned char *destination_pointer = (unsigned char*)glyph->sdl_surface->pixels + y * glyph->sdl_surface->pitch; + + for (unsigned int x = 0; x < width; ++x) + { + *destination_pointer++ = 0xFF; + *destination_pointer++ = 0xFF; + *destination_pointer++ = 0xFF; + *destination_pointer++ = (unsigned char)(pow((double)*source_pointer++ / (total_greys - 1), 1.0 / 1.8) * 255.0); + } + } + + break; + + case FONT_PIXEL_MODE_MONO: + for (unsigned int y = 0; y < height; ++y) + { + const unsigned char *source_pointer = pixels + y * pitch; + unsigned char *destination_pointer = (unsigned char*)glyph->sdl_surface->pixels + y * glyph->sdl_surface->pitch; + + for (unsigned int x = 0; x < width; ++x) + { + *destination_pointer++ = 0xFF; + *destination_pointer++ = 0xFF; + *destination_pointer++ = 0xFF; + *destination_pointer++ = *source_pointer++ ? 0xFF : 0; + } + } + + break; + } + + return glyph; +} + +void Backend_UnloadGlyph(Backend_Glyph *glyph) +{ + SDL_FreeSurface(glyph->sdl_surface); + free(glyph); +} + +void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours) +{ + SDL_Rect rect; + rect.x = x; + rect.y = y; + rect.w = glyph->sdl_surface->w; + rect.h = glyph->sdl_surface->h; + + SDL_SetSurfaceColorMod(glyph->sdl_surface, colours[0], colours[1], colours[2]); + + SDL_BlitSurface(glyph->sdl_surface, NULL, surface->sdl_surface, &rect); +} + +void Backend_DrawGlyphToScreen(Backend_Glyph *glyph, long x, long y, const unsigned char *colours) +{ + Backend_DrawGlyph(&framebuffer, glyph, x, y, colours); } void Backend_HandleDeviceLoss(void) diff --git a/src/Backends/Rendering/Software.cpp b/src/Backends/Rendering/Software.cpp index 25c69bfa..7b9bd4f9 100644 --- a/src/Backends/Rendering/Software.cpp +++ b/src/Backends/Rendering/Software.cpp @@ -255,6 +255,11 @@ void Backend_ScreenToSurface(Backend_Surface *surface, const RECT *rect) Backend_Blit(&framebuffer, rect, surface, rect->left, rect->top, FALSE); } +BOOL Backend_SupportsSubpixelGlyph(void) +{ + 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 short total_greys, unsigned char pixel_mode) { Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph)); diff --git a/src/Font.cpp b/src/Font.cpp index 4487f181..64ab31f8 100644 --- a/src/Font.cpp +++ b/src/Font.cpp @@ -1788,7 +1788,7 @@ FontObject* LoadFontFromData(const unsigned char *data, size_t data_size, unsign FT_Init_FreeType(&font_object->library); #ifndef DISABLE_FONT_ANTIALIASING - font_object->lcd_mode = FT_Library_SetLcdFilter(font_object->library, FT_LCD_FILTER_DEFAULT) != FT_Err_Unimplemented_Feature; + font_object->lcd_mode = Backend_SupportsSubpixelGlyph() && FT_Library_SetLcdFilter(font_object->library, FT_LCD_FILTER_DEFAULT) != FT_Err_Unimplemented_Feature; #endif font_object->data = (unsigned char*)malloc(data_size);