diff --git a/src/Backends/Rendering.h b/src/Backends/Rendering.h index 505aaf99..a3b81f96 100644 --- a/src/Backends/Rendering.h +++ b/src/Backends/Rendering.h @@ -28,6 +28,7 @@ void Backend_ColourFill(Backend_Surface *surface, const RECT *rect, unsigned cha BOOL Backend_SupportsSubpixelGlyphs(void); Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch, FontPixelMode 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); +void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels); +void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y); void Backend_HandleRenderTargetLoss(void); void Backend_HandleWindowResize(void); diff --git a/src/Backends/Rendering/OpenGL3.cpp b/src/Backends/Rendering/OpenGL3.cpp index 41ceda37..c3e5ad84 100644 --- a/src/Backends/Rendering/OpenGL3.cpp +++ b/src/Backends/Rendering/OpenGL3.cpp @@ -95,6 +95,9 @@ static RenderMode last_render_mode; static Backend_Surface framebuffer; +static unsigned char glyph_colour_channels[3]; +static Backend_Surface *glyph_destination_surface; + #ifdef USE_OPENGLES2 static const GLchar *vertex_shader_plain = " \ #version 100\n \ @@ -976,7 +979,17 @@ void Backend_UnloadGlyph(Backend_Glyph *glyph) free(glyph); } -void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours) +void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels) +{ + if (destination_surface == NULL) + return; + + glyph_destination_surface = destination_surface; + + memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels)); +} + +void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y) { static Backend_Surface *last_surface; static Backend_Glyph *last_glyph; @@ -984,36 +997,36 @@ void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, l static unsigned char last_green; static unsigned char last_blue; - if (glyph == NULL || surface == NULL) + if (glyph == NULL || glyph_destination_surface == NULL) return; const RenderMode render_mode = (glyph->pixel_mode == FONT_PIXEL_MODE_LCD ? MODE_DRAW_GLYPH_LCD : MODE_DRAW_GLYPH); - if (last_render_mode != render_mode || last_surface != surface || last_glyph != glyph || last_red != colours[0] || last_green != colours[1] || last_blue != colours[2]) + if (last_render_mode != render_mode || last_surface != glyph_destination_surface || last_glyph != glyph || last_red != glyph_colour_channels[0] || last_green != glyph_colour_channels[1] || last_blue != glyph_colour_channels[2]) { FlushVertexBuffer(); last_render_mode = render_mode; - last_surface = surface; + last_surface = glyph_destination_surface; last_glyph = glyph; - last_red = colours[0]; - last_green = colours[1]; - last_blue = colours[2]; + last_red = glyph_colour_channels[0]; + last_green = glyph_colour_channels[1]; + last_blue = glyph_colour_channels[2]; if (glyph->pixel_mode == FONT_PIXEL_MODE_LCD) { glUseProgram(program_glyph_subpixel_part2); - glUniform4f(program_glyph_subpixel_part2_uniform_colour, colours[0] / 255.0f, colours[1] / 255.0f, colours[2] / 255.0f, 1.0f); + glUniform4f(program_glyph_subpixel_part2_uniform_colour, glyph_colour_channels[0] / 255.0f, glyph_colour_channels[1] / 255.0f, glyph_colour_channels[2] / 255.0f, 1.0f); } else { glUseProgram(program_glyph_normal); - glUniform4f(program_glyph_normal_uniform_colour, colours[0] / 255.0f, colours[1] / 255.0f, colours[2] / 255.0f, 1.0f); + glUniform4f(program_glyph_normal_uniform_colour, glyph_colour_channels[0] / 255.0f, glyph_colour_channels[1] / 255.0f, glyph_colour_channels[2] / 255.0f, 1.0f); } // Point our framebuffer to the destination texture - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, surface->texture_id, 0); - glViewport(0, 0, surface->width, surface->height); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glyph_destination_surface->texture_id, 0); + glViewport(0, 0, glyph_destination_surface->width, glyph_destination_surface->height); glEnable(GL_BLEND); @@ -1023,10 +1036,10 @@ void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, l glBindTexture(GL_TEXTURE_2D, glyph->texture_id); } - const GLfloat vertex_left = (x * (2.0f / surface->width)) - 1.0f; - const GLfloat vertex_right = ((x + glyph->width) * (2.0f / surface->width)) - 1.0f; - const GLfloat vertex_top = (y * (2.0f / surface->height)) - 1.0f; - const GLfloat vertex_bottom = ((y + glyph->height) * (2.0f / surface->height)) - 1.0f; + const GLfloat vertex_left = (x * (2.0f / glyph_destination_surface->width)) - 1.0f; + const GLfloat vertex_right = ((x + glyph->width) * (2.0f / glyph_destination_surface->width)) - 1.0f; + const GLfloat vertex_top = (y * (2.0f / glyph_destination_surface->height)) - 1.0f; + const GLfloat vertex_bottom = ((y + glyph->height) * (2.0f / glyph_destination_surface->height)) - 1.0f; VertexBufferSlot *vertex_buffer_slot = GetVertexBufferSlot(); diff --git a/src/Backends/Rendering/SDLSurface.cpp b/src/Backends/Rendering/SDLSurface.cpp index 702e08d6..160b3b3f 100644 --- a/src/Backends/Rendering/SDLSurface.cpp +++ b/src/Backends/Rendering/SDLSurface.cpp @@ -24,6 +24,9 @@ static SDL_Surface *window_sdlsurface; static Backend_Surface framebuffer; +static unsigned char glyph_colour_channels[3]; +static SDL_Surface *glyph_destination_sdlsurface; + static void RectToSDLRect(const RECT *rect, SDL_Rect *sdl_rect) { sdl_rect->x = (int)rect->left; @@ -243,9 +246,19 @@ void Backend_UnloadGlyph(Backend_Glyph *glyph) free(glyph); } -void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours) +void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels) { - if (glyph == NULL || surface == NULL) + if (destination_surface == NULL) + return; + + glyph_destination_sdlsurface = destination_surface->sdlsurface; + + memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels)); +} + +void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y) +{ + if (glyph == NULL) return; SDL_Rect rect; @@ -254,9 +267,9 @@ void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, l rect.w = glyph->sdlsurface->w; rect.h = glyph->sdlsurface->h; - SDL_SetSurfaceColorMod(glyph->sdlsurface, colours[0], colours[1], colours[2]); + SDL_SetSurfaceColorMod(glyph->sdlsurface, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]); - SDL_BlitSurface(glyph->sdlsurface, NULL, surface->sdlsurface, &rect); + SDL_BlitSurface(glyph->sdlsurface, NULL, glyph_destination_sdlsurface, &rect); } void Backend_HandleRenderTargetLoss(void) diff --git a/src/Backends/Rendering/SDLTexture.cpp b/src/Backends/Rendering/SDLTexture.cpp index f315f4d6..41d1973e 100644 --- a/src/Backends/Rendering/SDLTexture.cpp +++ b/src/Backends/Rendering/SDLTexture.cpp @@ -42,6 +42,8 @@ static Backend_Surface framebuffer; static Backend_Surface *surface_list_head; +static unsigned char glyph_colour_channels[3]; + static void RectToSDLRect(const RECT *rect, SDL_Rect *sdl_rect) { sdl_rect->x = (int)rect->left; @@ -376,20 +378,29 @@ void Backend_UnloadGlyph(Backend_Glyph *glyph) free(glyph); } -void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours) +void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels) +{ + if (destination_surface == NULL) + return; + + SDL_SetRenderTarget(renderer, destination_surface->texture); + + memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels)); +} + +void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y) { // The SDL_Texture side of things uses alpha, not a colour-key, so the bug where the font is blended // with the colour key doesn't occur. - if (glyph == NULL || surface == NULL) + if (glyph == NULL) return; SDL_Rect destination_rect = {(int)x, (int)y, (int)glyph->width, (int)glyph->height}; // Blit the texture - SDL_SetTextureColorMod(glyph->texture, colours[0], colours[1], colours[2]); + SDL_SetTextureColorMod(glyph->texture, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]); SDL_SetTextureBlendMode(glyph->texture, SDL_BLENDMODE_BLEND); - SDL_SetRenderTarget(renderer, surface->texture); SDL_RenderCopy(renderer, glyph->texture, NULL, &destination_rect); } diff --git a/src/Backends/Rendering/Software.cpp b/src/Backends/Rendering/Software.cpp index 43ab81e6..381a9d9c 100644 --- a/src/Backends/Rendering/Software.cpp +++ b/src/Backends/Rendering/Software.cpp @@ -34,6 +34,9 @@ static SDL_Surface *window_sdlsurface; static SDL_Surface *framebuffer_sdlsurface; static Backend_Surface framebuffer; +static unsigned char glyph_colour_channels[3]; +static Backend_Surface *glyph_destination_surface; + Backend_Surface* Backend_Init(const char *title, int width, int height, BOOL fullscreen) { window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, 0); @@ -371,28 +374,38 @@ void Backend_UnloadGlyph(Backend_Glyph *glyph) free(glyph); } -void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours) +void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels) { - if (glyph == NULL || surface == NULL) + if (destination_surface == NULL) + return; + + glyph_destination_surface = destination_surface; + + memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels)); +} + +void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y) +{ + if (glyph == NULL) return; switch (glyph->pixel_mode) { case FONT_PIXEL_MODE_LCD: - for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, surface->height); ++iy) + for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, glyph_destination_surface->height); ++iy) { - for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, surface->width); ++ix) + for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, glyph_destination_surface->width); ++ix) { const float *font_pixel = (float*)glyph->pixels + (iy * glyph->width + ix) * 3; if (font_pixel[0] || font_pixel[1] || font_pixel[2]) { - unsigned char *bitmap_pixel = surface->pixels + (y + iy) * surface->pitch + (x + ix) * 3; + unsigned char *bitmap_pixel = glyph_destination_surface->pixels + (y + iy) * glyph_destination_surface->pitch + (x + ix) * 3; for (unsigned int j = 0; j < 3; ++j) { const float alpha = font_pixel[j]; - bitmap_pixel[j] = (unsigned char)((colours[j] * alpha) + (bitmap_pixel[j] * (1.0f - alpha))); // Alpha blending + bitmap_pixel[j] = (unsigned char)((glyph_colour_channels[j] * alpha) + (bitmap_pixel[j] * (1.0f - alpha))); // Alpha blending } } } @@ -401,18 +414,18 @@ void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, l break; case FONT_PIXEL_MODE_GRAY: - for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, surface->height); ++iy) + for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, glyph_destination_surface->height); ++iy) { - for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, surface->width); ++ix) + for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, glyph_destination_surface->width); ++ix) { const float alpha = ((float*)glyph->pixels)[iy * glyph->width + ix]; if (alpha) { - unsigned char *bitmap_pixel = surface->pixels + (y + iy) * surface->pitch + (x + ix) * 3; + unsigned char *bitmap_pixel = glyph_destination_surface->pixels + (y + iy) * glyph_destination_surface->pitch + (x + ix) * 3; for (unsigned int j = 0; j < 3; ++j) - bitmap_pixel[j] = (unsigned char)((colours[j] * alpha) + (bitmap_pixel[j] * (1.0f - alpha))); // Alpha blending + bitmap_pixel[j] = (unsigned char)((glyph_colour_channels[j] * alpha) + (bitmap_pixel[j] * (1.0f - alpha))); // Alpha blending } } } @@ -420,16 +433,16 @@ void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, l break; case FONT_PIXEL_MODE_MONO: - for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, surface->height); ++iy) + for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, glyph_destination_surface->height); ++iy) { - for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, surface->width); ++ix) + for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, glyph_destination_surface->width); ++ix) { if (((unsigned char*)glyph->pixels)[iy * glyph->width + ix]) { - unsigned char *bitmap_pixel = surface->pixels + (y + iy) * surface->pitch + (x + ix) * 3; + unsigned char *bitmap_pixel = glyph_destination_surface->pixels + (y + iy) * glyph_destination_surface->pitch + (x + ix) * 3; for (unsigned int j = 0; j < 3; ++j) - bitmap_pixel[j] = colours[j]; + bitmap_pixel[j] = glyph_colour_channels[j]; } } } diff --git a/src/Font.cpp b/src/Font.cpp index 68c2c456..41924617 100644 --- a/src/Font.cpp +++ b/src/Font.cpp @@ -1114,7 +1114,9 @@ void DrawText(FontObject *font_object, Backend_Surface *surface, int x, int y, u { if (font_object != NULL) { - const unsigned char colours[3] = {(unsigned char)colour, (unsigned char)(colour >> 8), (unsigned char)(colour >> 16)}; + const unsigned char colour_channels[3] = {(unsigned char)colour, (unsigned char)(colour >> 8), (unsigned char)(colour >> 16)}; + + Backend_PrepareToDrawGlyphs(surface, colour_channels); unsigned int pen_x = 0; @@ -1139,7 +1141,7 @@ void DrawText(FontObject *font_object, Backend_Surface *surface, int x, int y, u const int letter_y = y + glyph->y; if (glyph->backend != NULL) - Backend_DrawGlyph(surface, glyph->backend, letter_x, letter_y, colours); + Backend_DrawGlyph(glyph->backend, letter_x, letter_y); pen_x += glyph->x_advance; }