diff --git a/data/shaders/drawrect.frag b/data/shaders/drawrect.frag index be6bed1a80..f5a26749bd 100644 --- a/data/shaders/drawrect.frag +++ b/data/shaders/drawrect.frag @@ -4,6 +4,7 @@ const int MASK_REMAP_COUNT = 3; const int FLAG_NO_TEXTURE = (1 << 2); const int FLAG_MASK = (1 << 3); const int FLAG_CROSS_HATCH = (1 << 4); +const int FLAG_TTF_TEXT = (1 << 5); uniform usampler2DArray uTexture; uniform usampler2D uPaletteTex; @@ -41,7 +42,14 @@ void main() { discard; } - texel += fColour; + if ((fFlags & FLAG_TTF_TEXT) == 0) + { + texel += fColour; + } + else + { + texel = fColour; + } } else { diff --git a/src/openrct2-ui/drawing/engines/opengl/DrawCommands.h b/src/openrct2-ui/drawing/engines/opengl/DrawCommands.h index ee4802fcf8..2becc8f8bb 100644 --- a/src/openrct2-ui/drawing/engines/opengl/DrawCommands.h +++ b/src/openrct2-ui/drawing/engines/opengl/DrawCommands.h @@ -118,6 +118,7 @@ struct DrawRectCommand FLAG_NO_TEXTURE = (1u << 2u), FLAG_MASK = (1u << 3u), FLAG_CROSS_HATCH = (1u << 4u), + FLAG_TTF_TEXT = (1u << 5u), }; }; diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp index 2372e3dff9..b18a8f4e42 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -23,6 +23,7 @@ # include # include +# include # include # include # include @@ -109,8 +110,9 @@ public: DrawPixelInfo* dpi, int32_t x, int32_t y, const ImageId maskImage, const ImageId colourImage) override; void DrawSpriteSolid(DrawPixelInfo* dpi, const ImageId image, int32_t x, int32_t y, uint8_t colour) override; void DrawGlyph(DrawPixelInfo* dpi, const ImageId image, int32_t x, int32_t y, const PaletteMap& palette) override; - void DrawBitmap( - DrawPixelInfo* dpi, ImageIndex image, const void* pixels, int32_t width, int32_t height, int32_t x, int32_t y) override; + void DrawTTFBitmap( + DrawPixelInfo* dpi, TextDrawInfo* info, ImageIndex image, const void* pixels, int32_t width, int32_t height, int32_t x, + int32_t y) override; void FlushCommandBuffers(); @@ -906,8 +908,9 @@ void OpenGLDrawingContext::DrawGlyph(DrawPixelInfo* dpi, const ImageId image, in command.depth = _drawCount++; } -void OpenGLDrawingContext::DrawBitmap( - DrawPixelInfo* dpi, ImageIndex image, const void* pixels, int32_t width, int32_t height, int32_t x, int32_t y) +void OpenGLDrawingContext::DrawTTFBitmap( + DrawPixelInfo* dpi, TextDrawInfo* info, ImageIndex image, const void* pixels, int32_t width, int32_t height, int32_t x, + int32_t y) { CalculcateClipping(dpi); @@ -937,16 +940,53 @@ void OpenGLDrawingContext::DrawBitmap( right += _offsetX; bottom += _offsetY; - DrawRectCommand& command = _commandBuffers.rects.allocate(); + if (info->flags & TEXT_DRAW_FLAG_OUTLINE) + { + std::array boundsArr = { { + { left + 1, top, right + 1, bottom }, + { left - 1, top, right - 1, bottom }, + { left, top + 1, right, bottom + 1 }, + { left, top - 1, right, bottom - 1 }, + } }; + for (auto b : boundsArr) + { + DrawRectCommand& command = _commandBuffers.rects.allocate(); + command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom }; + command.texColourAtlas = texture.index; + command.texColourBounds = texture.normalizedBounds; + command.texMaskAtlas = 0; + command.texMaskBounds = { 0.0f, 0.0f, 0.0f, 0.0f }; + command.palettes = { 0, 0, 0 }; + command.flags = DrawRectCommand::FLAG_TTF_TEXT; + command.colour = info->palette[3]; + command.bounds = b; + command.depth = _drawCount++; + } + } + if (info->flags & TEXT_DRAW_FLAG_INSET) + { + DrawRectCommand& command = _commandBuffers.rects.allocate(); + command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom }; + command.texColourAtlas = texture.index; + command.texColourBounds = texture.normalizedBounds; + command.texMaskAtlas = 0; + command.texMaskBounds = { 0.0f, 0.0f, 0.0f, 0.0f }; + command.palettes = { 0, 0, 0 }; + command.flags = DrawRectCommand::FLAG_TTF_TEXT; + command.colour = info->palette[3]; + command.bounds = { left + 1, top + 1, right + 1, bottom + 1 }; + command.depth = _drawCount++; + } + DrawRectCommand& command = _commandBuffers.rects.allocate(); command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom }; command.texColourAtlas = texture.index; command.texColourBounds = texture.normalizedBounds; command.texMaskAtlas = 0; command.texMaskBounds = { 0.0f, 0.0f, 0.0f, 0.0f }; command.palettes = { 0, 0, 0 }; - command.flags = 0; - command.colour = 0; + command.flags = DrawRectCommand::FLAG_TTF_TEXT; + command.colour = info->palette[1]; command.bounds = { left, top, right, bottom }; command.depth = _drawCount++; } diff --git a/src/openrct2/drawing/Drawing.String.cpp b/src/openrct2/drawing/Drawing.String.cpp index 45ad5dab29..86cee0a5ee 100644 --- a/src/openrct2/drawing/Drawing.String.cpp +++ b/src/openrct2/drawing/Drawing.String.cpp @@ -28,18 +28,6 @@ using namespace OpenRCT2; -enum : uint32_t -{ - TEXT_DRAW_FLAG_INSET = 1 << 0, - TEXT_DRAW_FLAG_OUTLINE = 1 << 1, - TEXT_DRAW_FLAG_DARK = 1 << 2, - TEXT_DRAW_FLAG_EXTRA_DARK = 1 << 3, - TEXT_DRAW_FLAG_NO_FORMATTING = 1 << 28, - TEXT_DRAW_FLAG_Y_OFFSET_EFFECT = 1 << 29, - TEXT_DRAW_FLAG_TTF = 1 << 30, - TEXT_DRAW_FLAG_NO_DRAW = 1u << 31 -}; - static int32_t TTFGetStringWidth(std::string_view text, FontStyle fontStyle, bool noFormatting); /** @@ -490,20 +478,6 @@ void DrawNewsTicker( } } -struct TextDrawInfo -{ - int32_t startX; - int32_t startY; - int32_t x; - int32_t y; - int32_t maxX; - int32_t maxY; - int32_t flags; - uint8_t palette[8]; - ::FontStyle FontStyle; - const int8_t* y_offset; -}; - static void TTFDrawCharacterSprite(DrawPixelInfo& dpi, int32_t codepoint, TextDrawInfo* info) { int32_t characterWidth = FontSpriteGetCodepointWidth(info->FontStyle, codepoint); @@ -563,29 +537,17 @@ static void TTFDrawStringRawTTF(DrawPixelInfo& dpi, std::string_view text, TextD int32_t drawY = info->y + fontDesc->offset_y; int32_t width = surface->w; int32_t height = surface->h; + bool use_hinting = gConfigFonts.EnableHinting && fontDesc->hinting_threshold > 0; if (OpenRCT2::GetContext()->GetDrawingEngineType() == DrawingEngine::OpenGL) { - auto pixels = reinterpret_cast(const_cast(surface->pixels)); - auto pixelsLen = static_cast(surface->pitch) * surface->h; - for (size_t pp = 0; pp < pixelsLen; pp++) - { - if (pixels[pp] != 0) - { - pixels[pp] = colour; - } - else - { - pixels[pp] = PALETTE_INDEX_0; - } - } - + // if(use_hinting) return; // Not implemented yet. auto baseId = uint32_t(0x7FFFF) - 1024; auto imageId = baseId + _ttfGlId; auto drawingEngine = dpi.DrawingEngine; auto drawingContext = drawingEngine->GetDrawingContext(); drawingEngine->InvalidateImage(imageId); - drawingContext->DrawBitmap(&dpi, imageId, surface->pixels, surface->pitch, surface->h, drawX, drawY); + drawingContext->DrawTTFBitmap(&dpi, info, imageId, surface->pixels, surface->pitch, surface->h, drawX, drawY); _ttfGlId++; if (_ttfGlId >= 1023) @@ -670,7 +632,6 @@ static void TTFDrawStringRawTTF(DrawPixelInfo& dpi, std::string_view text, TextD dst = dst_orig; src = src_orig; - bool use_hinting = gConfigFonts.EnableHinting && fontDesc->hinting_threshold > 0; for (int32_t yy = 0; yy < height; yy++) { for (int32_t xx = 0; xx < width; xx++) @@ -692,9 +653,7 @@ static void TTFDrawStringRawTTF(DrawPixelInfo& dpi, std::string_view text, TextD // Simulate font hinting by shading the background colour instead. if (info->flags & TEXT_DRAW_FLAG_OUTLINE) { - // As outlines are black, these texts should always use a darker shade - // of the foreground colour for font hinting. - *dst = BlendColours(colour, PALETTE_INDEX_0); + *dst = BlendColours(colour, info->palette[3]); } else { diff --git a/src/openrct2/drawing/Drawing.h b/src/openrct2/drawing/Drawing.h index de2196b1d2..ebacfe38fc 100644 --- a/src/openrct2/drawing/Drawing.h +++ b/src/openrct2/drawing/Drawing.h @@ -132,6 +132,32 @@ struct DrawPixelInfo DrawPixelInfo Crop(const ScreenCoordsXY& pos, const ScreenSize& size) const; }; +struct TextDrawInfo +{ + int32_t startX; + int32_t startY; + int32_t x; + int32_t y; + int32_t maxX; + int32_t maxY; + int32_t flags; + uint8_t palette[8]; + ::FontStyle FontStyle; + const int8_t* y_offset; +}; + +enum : uint32_t +{ + TEXT_DRAW_FLAG_INSET = 1 << 0, + TEXT_DRAW_FLAG_OUTLINE = 1 << 1, + TEXT_DRAW_FLAG_DARK = 1 << 2, + TEXT_DRAW_FLAG_EXTRA_DARK = 1 << 3, + TEXT_DRAW_FLAG_NO_FORMATTING = 1 << 28, + TEXT_DRAW_FLAG_Y_OFFSET_EFFECT = 1 << 29, + TEXT_DRAW_FLAG_TTF = 1 << 30, + TEXT_DRAW_FLAG_NO_DRAW = 1u << 31 +}; + struct RCTG1Element { uint32_t offset; // 0x00 note: uint32_t always! diff --git a/src/openrct2/drawing/IDrawingContext.h b/src/openrct2/drawing/IDrawingContext.h index 273b72ca89..096fdb0f69 100644 --- a/src/openrct2/drawing/IDrawingContext.h +++ b/src/openrct2/drawing/IDrawingContext.h @@ -32,9 +32,9 @@ namespace OpenRCT2::Drawing virtual void DrawSpriteSolid(DrawPixelInfo* dpi, const ImageId image, int32_t x, int32_t y, uint8_t colour) abstract; virtual void DrawGlyph( DrawPixelInfo* dpi, const ImageId image, int32_t x, int32_t y, const PaletteMap& palette) abstract; - virtual void DrawBitmap( - DrawPixelInfo* dpi, ImageIndex image, const void* pixels, int32_t width, int32_t height, int32_t x, - int32_t y) abstract; + virtual void DrawTTFBitmap( + DrawPixelInfo* dpi, TextDrawInfo* info, ImageIndex image, const void* pixels, int32_t width, int32_t height, + int32_t x, int32_t y) abstract; }; } // namespace OpenRCT2::Drawing diff --git a/src/openrct2/drawing/TTF.cpp b/src/openrct2/drawing/TTF.cpp index e1749579a7..780d248de1 100644 --- a/src/openrct2/drawing/TTF.cpp +++ b/src/openrct2/drawing/TTF.cpp @@ -365,12 +365,7 @@ static TTFSurface* TTFRender(TTF_Font* font, std::string_view text) { thread_local std::string buffer; buffer.assign(text); - if (TTF_GetFontHinting(font) != 0) - { - return TTF_RenderUTF8_Shaded(font, buffer.c_str(), 0x000000FF, 0x000000FF); - } - - return TTF_RenderUTF8_Solid(font, buffer.c_str(), 0x000000FF); + return TTF_RenderUTF8(font, buffer.c_str(), TTF_GetFontHinting(font) != 0); } void TTFFreeSurface(TTFSurface* surface) diff --git a/src/openrct2/drawing/TTF.h b/src/openrct2/drawing/TTF.h index 9cdf83fc94..b793c3ce96 100644 --- a/src/openrct2/drawing/TTF.h +++ b/src/openrct2/drawing/TTF.h @@ -38,8 +38,7 @@ int TTF_Init(void); TTF_Font* TTF_OpenFont(const char* file, int ptsize); int TTF_GlyphIsProvided(const TTF_Font* font, codepoint_t ch); int TTF_SizeUTF8(TTF_Font* font, const char* text, int* w, int* h); -TTFSurface* TTF_RenderUTF8_Solid(TTF_Font* font, const char* text, uint32_t colour); -TTFSurface* TTF_RenderUTF8_Shaded(TTF_Font* font, const char* text, uint32_t fg, uint32_t bg); +TTFSurface* TTF_RenderUTF8(TTF_Font* font, const char* text, bool shaded); void TTF_CloseFont(TTF_Font* font); void TTF_SetFontHinting(TTF_Font* font, int hinting); int TTF_GetFontHinting(const TTF_Font* font); diff --git a/src/openrct2/drawing/TTFSDLPort.cpp b/src/openrct2/drawing/TTFSDLPort.cpp index e27207919f..f26b35b86c 100644 --- a/src/openrct2/drawing/TTFSDLPort.cpp +++ b/src/openrct2/drawing/TTFSDLPort.cpp @@ -1263,7 +1263,7 @@ int TTF_SizeUTF8(TTF_Font* font, const char* text, int* w, int* h) return status; } -TTFSurface* TTF_RenderUTF8_Solid(TTF_Font* font, const char* text, [[maybe_unused]] uint32_t colour) +TTFSurface* TTF_RenderUTF8(TTF_Font* font, const char* text, bool shaded) { bool first; int xstart; @@ -1321,7 +1321,7 @@ TTFSurface* TTF_RenderUTF8_Solid(TTF_Font* font, const char* text, [[maybe_unuse continue; } - error = Find_Glyph(font, c, CACHED_METRICS | CACHED_BITMAP); + error = Find_Glyph(font, c, CACHED_METRICS | (shaded ? CACHED_PIXMAP : CACHED_BITMAP)); if (error) { TTF_SetFTError("Couldn't find glyph", error); @@ -1329,7 +1329,7 @@ TTFSurface* TTF_RenderUTF8_Solid(TTF_Font* font, const char* text, [[maybe_unuse return NULL; } glyph = font->current; - current = &glyph->bitmap; + current = shaded ? &glyph->pixmap : &glyph->bitmap; /* Ensure the width of the pixmap is correct. On some cases, * freetype may report a larger pixmap than possible.*/ width = current->width; @@ -1385,152 +1385,20 @@ TTFSurface* TTF_RenderUTF8_Solid(TTF_Font* font, const char* text, [[maybe_unuse if (TTF_HANDLE_STYLE_UNDERLINE(font)) { row = TTF_underline_top_row(font); - TTF_drawLine_Solid(font, textbuf, row); + if (shaded) + TTF_drawLine_Shaded(font, textbuf, row); + else + TTF_drawLine_Solid(font, textbuf, row); } /* Handle the strikethrough style */ if (TTF_HANDLE_STYLE_STRIKETHROUGH(font)) { row = TTF_strikethrough_top_row(font); - TTF_drawLine_Solid(font, textbuf, row); - } - return textbuf; -} - -TTFSurface* TTF_RenderUTF8_Shaded(TTF_Font* font, const char* text, [[maybe_unused]] uint32_t fg, [[maybe_unused]] uint32_t bg) -{ - bool first; - int xstart; - int width; - int height; - TTFSurface* textbuf; - uint8_t* src; - uint8_t* dst; - uint8_t* dst_check; - unsigned int row, col; - FT_Bitmap* current; - c_glyph* glyph; - FT_Error error; - FT_Long use_kerning; - FT_UInt prev_index = 0; - size_t textlen; - - TTF_CHECKPOINTER(text, NULL); - - /* Get the dimensions of the text surface */ - if ((TTF_SizeUTF8(font, text, &width, &height) < 0) || !width) - { - TTF_SetError("Text has zero width"); - return NULL; - } - - /* Create the target surface */ - textbuf = static_cast(calloc(1, sizeof(TTFSurface))); - if (textbuf == NULL) - { - return NULL; - } - textbuf->w = width; - textbuf->h = height; - textbuf->pitch = width; - textbuf->pixels = calloc(1, width * height); - - /* Adding bound checking to avoid all kinds of memory corruption errors - that may occur. */ - dst_check = const_cast(static_cast(textbuf->pixels)) + textbuf->pitch * textbuf->h; - - /* check kerning */ - use_kerning = FT_HAS_KERNING(font->face) && font->kerning; - - /* Load and render each character */ - textlen = strlen(text); - first = true; - xstart = 0; - while (textlen > 0) - { - uint16_t c = UTF8_getch(&text, &textlen); - if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED) - { - continue; - } - - error = Find_Glyph(font, c, CACHED_METRICS | CACHED_PIXMAP); - if (error) - { - TTF_SetFTError("Couldn't find glyph", error); - TTFFreeSurface(textbuf); - return NULL; - } - - glyph = font->current; - - /* Ensure the width of the pixmap is correct. On some cases, - * freetype may report a larger pixmap than possible.*/ - width = glyph->pixmap.width; - if (font->outline <= 0 && width > glyph->maxx - glyph->minx) - { - width = glyph->maxx - glyph->minx; - } - - /* do kerning, if possible AC-Patch */ - if (use_kerning && prev_index && glyph->index) - { - FT_Vector delta; - FT_Get_Kerning(font->face, prev_index, glyph->index, ft_kerning_default, &delta); - xstart += delta.x >> 6; - } - - /* Compensate for the wrap around with negative minx's */ - if (first && (glyph->minx < 0)) - { - xstart -= glyph->minx; - } - first = false; - - current = &glyph->pixmap; - for (row = 0; row < current->rows; ++row) - { - /* Make sure we don't go either over, or under the - * limit */ - if (static_cast(row) + glyph->yoffset < 0) - { - continue; - } - if (static_cast(row) + glyph->yoffset >= textbuf->h) - { - continue; - } - - dst = const_cast(static_cast(textbuf->pixels)) + (row + glyph->yoffset) * textbuf->pitch - + xstart + glyph->minx; - src = current->buffer + row * current->pitch; - - for (col = width; col > 0 && dst < dst_check; --col) - { - *dst++ |= *src++; - } - } - - xstart += glyph->advance; - if (TTF_HANDLE_STYLE_BOLD(font)) - { - xstart += font->glyph_overhang; - } - prev_index = glyph->index; - } - - /* Handle the underline style */ - if (TTF_HANDLE_STYLE_UNDERLINE(font)) - { - row = TTF_underline_top_row(font); - TTF_drawLine_Shaded(font, textbuf, row); - } - - /* Handle the strikethrough style */ - if (TTF_HANDLE_STYLE_STRIKETHROUGH(font)) - { - row = TTF_strikethrough_top_row(font); - TTF_drawLine_Shaded(font, textbuf, row); + if (shaded) + TTF_drawLine_Shaded(font, textbuf, row); + else + TTF_drawLine_Solid(font, textbuf, row); } return textbuf; } diff --git a/src/openrct2/drawing/X8DrawingEngine.h b/src/openrct2/drawing/X8DrawingEngine.h index 15af40cc0a..a11aa9d8c8 100644 --- a/src/openrct2/drawing/X8DrawingEngine.h +++ b/src/openrct2/drawing/X8DrawingEngine.h @@ -147,9 +147,9 @@ namespace OpenRCT2 void DrawSpriteSolid(DrawPixelInfo* dpi, const ImageId image, int32_t x, int32_t y, uint8_t colour) override; void DrawGlyph( DrawPixelInfo* dpi, const ImageId image, int32_t x, int32_t y, const PaletteMap& paletteMap) override; - void DrawBitmap( - DrawPixelInfo* dpi, uint32_t image, const void* pixels, int32_t width, int32_t height, int32_t x, - int32_t y) override + void DrawTTFBitmap( + DrawPixelInfo* dpi, TextDrawInfo* info, uint32_t image, const void* pixels, int32_t width, int32_t height, + int32_t x, int32_t y) override { } };