diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index 8dc82c34a..a9bf3d4a5 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -484,7 +484,7 @@ bool CGraphics_Threaded::UnloadTextTextures(CTextureHandle &TextTexture, CTextur return true; } -bool CGraphics_Threaded::UpdateTextTexture(CTextureHandle TextureId, int x, int y, size_t Width, size_t Height, const uint8_t *pData) +bool CGraphics_Threaded::UpdateTextTexture(CTextureHandle TextureId, int x, int y, size_t Width, size_t Height, uint8_t *pData, bool IsMovedPointer) { CCommandBuffer::SCommand_TextTexture_Update Cmd; Cmd.m_Slot = TextureId.Id(); @@ -493,10 +493,17 @@ bool CGraphics_Threaded::UpdateTextTexture(CTextureHandle TextureId, int x, int Cmd.m_Width = Width; Cmd.m_Height = Height; - const size_t MemSize = Width * Height; - uint8_t *pTmpData = static_cast(malloc(MemSize)); - mem_copy(pTmpData, pData, MemSize); - Cmd.m_pData = pTmpData; + if(IsMovedPointer) + { + Cmd.m_pData = pData; + } + else + { + const size_t MemSize = Width * Height; + uint8_t *pTmpData = static_cast(malloc(MemSize)); + mem_copy(pTmpData, pData, MemSize); + Cmd.m_pData = pTmpData; + } AddCmd(Cmd); return true; diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index 01774d58f..1a7b023eb 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -950,7 +950,7 @@ public: bool LoadTextTextures(size_t Width, size_t Height, CTextureHandle &TextTexture, CTextureHandle &TextOutlineTexture, uint8_t *pTextData, uint8_t *pTextOutlineData) override; bool UnloadTextTextures(CTextureHandle &TextTexture, CTextureHandle &TextOutlineTexture) override; - bool UpdateTextTexture(CTextureHandle TextureId, int x, int y, size_t Width, size_t Height, const uint8_t *pData) override; + bool UpdateTextTexture(CTextureHandle TextureId, int x, int y, size_t Width, size_t Height, uint8_t *pData, bool IsMovedPointer) override; CTextureHandle LoadSpriteTexture(const CImageInfo &FromImageInfo, const struct CDataSprite *pSprite) override; diff --git a/src/engine/client/text.cpp b/src/engine/client/text.cpp index 86eb6f891..252f80f03 100644 --- a/src/engine/client/text.cpp +++ b/src/engine/client/text.cpp @@ -321,9 +321,6 @@ private: CAtlas m_TextureAtlas; std::unordered_map, SGlyph, SGlyphKeyHash, SGlyphKeyEquals> m_Glyphs; - // Data used for rendering glyphs - uint8_t m_aaGlyphData[NUM_FONT_TEXTURES][64 * 1024]; - // Font faces FT_Face m_DefaultFace = nullptr; FT_Face m_IconFace = nullptr; @@ -485,13 +482,13 @@ private: return OutlineThickness; } - void UploadGlyph(int TextureIndex, int PosX, int PosY, size_t Width, size_t Height, const unsigned char *pData) + void UploadGlyph(int TextureIndex, int PosX, int PosY, size_t Width, size_t Height, uint8_t *pData) { for(size_t y = 0; y < Height; ++y) { mem_copy(&m_apTextureData[TextureIndex][PosX + ((y + PosY) * m_TextureDimension)], &pData[y * Width], Width); } - Graphics()->UpdateTextTexture(m_aTextures[TextureIndex], PosX, PosY, Width, Height, pData); + Graphics()->UpdateTextTexture(m_aTextures[TextureIndex], PosX, PosY, Width, Height, pData, true); } bool FitGlyph(size_t Width, size_t Height, int &PosX, int &PosY) @@ -510,6 +507,11 @@ private: } const FT_Bitmap *pBitmap = &Glyph.m_Face->glyph->bitmap; + if(pBitmap->pixel_mode != FT_PIXEL_MODE_GRAY) + { + log_debug("textrender", "Error loading glyph, unsupported pixel mode. Chr=%d GlyphIndex=%u PixelMode=%d", Glyph.m_Chr, Glyph.m_GlyphIndex, pBitmap->pixel_mode); + return false; + } const unsigned RealWidth = pBitmap->width; const unsigned RealHeight = pBitmap->rows; @@ -544,23 +546,23 @@ private: } // prepare glyph data - mem_zero(m_aaGlyphData[FONT_TEXTURE_FILL], (size_t)Width * Height * sizeof(uint8_t)); + const size_t GlyphDataSize = (size_t)Width * Height * sizeof(uint8_t); + uint8_t *pGlyphDataFill = static_cast(malloc(GlyphDataSize)); + uint8_t *pGlyphDataOutline = static_cast(malloc(GlyphDataSize)); + mem_zero(pGlyphDataFill, GlyphDataSize); for(unsigned py = 0; py < pBitmap->rows; ++py) { - mem_copy(&m_aaGlyphData[FONT_TEXTURE_FILL][(py + y) * Width + x], &pBitmap->buffer[py * pBitmap->width], pBitmap->width); + mem_copy(&pGlyphDataFill[(py + y) * Width + x], &pBitmap->buffer[py * pBitmap->width], pBitmap->width); } + Grow(pGlyphDataFill, pGlyphDataOutline, Width, Height, OutlineThickness); // upload the glyph - UploadGlyph(FONT_TEXTURE_FILL, X, Y, Width, Height, m_aaGlyphData[FONT_TEXTURE_FILL]); - Grow(m_aaGlyphData[FONT_TEXTURE_FILL], m_aaGlyphData[FONT_TEXTURE_OUTLINE], Width, Height, OutlineThickness); - UploadGlyph(FONT_TEXTURE_OUTLINE, X, Y, Width, Height, m_aaGlyphData[FONT_TEXTURE_OUTLINE]); + UploadGlyph(FONT_TEXTURE_FILL, X, Y, Width, Height, pGlyphDataFill); + UploadGlyph(FONT_TEXTURE_OUTLINE, X, Y, Width, Height, pGlyphDataOutline); } // set glyph info { - const int BmpWidth = pBitmap->width + x * 2; - const int BmpHeight = pBitmap->rows + y * 2; - Glyph.m_Height = Height; Glyph.m_Width = Width; Glyph.m_CharHeight = RealHeight; @@ -571,8 +573,8 @@ private: Glyph.m_aUVs[0] = X; Glyph.m_aUVs[1] = Y; - Glyph.m_aUVs[2] = Glyph.m_aUVs[0] + BmpWidth; - Glyph.m_aUVs[3] = Glyph.m_aUVs[1] + BmpHeight; + Glyph.m_aUVs[2] = Glyph.m_aUVs[0] + Width; + Glyph.m_aUVs[3] = Glyph.m_aUVs[1] + Height; Glyph.m_State = SGlyph::EState::RENDERED; } @@ -694,7 +696,7 @@ public: for(size_t TextureIndex = 0; TextureIndex < NUM_FONT_TEXTURES; ++TextureIndex) { mem_zero(m_apTextureData[TextureIndex], m_TextureDimension * m_TextureDimension * sizeof(uint8_t)); - Graphics()->UpdateTextTexture(m_aTextures[TextureIndex], 0, 0, m_TextureDimension, m_TextureDimension, m_apTextureData[TextureIndex]); + Graphics()->UpdateTextTexture(m_aTextures[TextureIndex], 0, 0, m_TextureDimension, m_TextureDimension, m_apTextureData[TextureIndex], false); } m_TextureAtlas.Clear(m_TextureDimension); @@ -791,13 +793,12 @@ public: } const FT_Bitmap *pBitmap = &Face->glyph->bitmap; - - // prepare glyph data - const size_t GlyphDataSize = (size_t)pBitmap->width * pBitmap->rows * sizeof(uint8_t); - if(pBitmap->pixel_mode == FT_PIXEL_MODE_GRAY) - mem_copy(m_aaGlyphData[FONT_TEXTURE_FILL], pBitmap->buffer, GlyphDataSize); - else - mem_zero(m_aaGlyphData[FONT_TEXTURE_FILL], GlyphDataSize); + if(pBitmap->pixel_mode != FT_PIXEL_MODE_GRAY) + { + log_debug("textrender", "Error loading glyph, unsupported pixel mode. Chr=%d GlyphIndex=%u PixelMode=%d", NextCharacter, GlyphIndex, pBitmap->pixel_mode); + pCurrent = pTmp; + continue; + } for(unsigned OffY = 0; OffY < pBitmap->rows; ++OffY) { @@ -806,18 +807,11 @@ public: const int ImgOffX = clamp(x + OffX + WidthLastChars, x, (x + TexSubWidth) - 1); const int ImgOffY = clamp(y + OffY, y, (y + TexSubHeight) - 1); const size_t ImageOffset = ImgOffY * (TextImage.m_Width * PixelSize) + ImgOffX * PixelSize; - const size_t GlyphOffset = OffY * pBitmap->width + OffX; - for(size_t i = 0; i < PixelSize; ++i) + for(size_t i = 0; i < PixelSize - 1; ++i) { - if(i != PixelSize - 1) - { - *(TextImage.m_pData + ImageOffset + i) = 255; - } - else - { - *(TextImage.m_pData + ImageOffset + i) = *(m_aaGlyphData[FONT_TEXTURE_FILL] + GlyphOffset); - } + TextImage.m_pData[ImageOffset + i] = 255; } + TextImage.m_pData[ImageOffset + PixelSize - 1] = pBitmap->buffer[OffY * pBitmap->width + OffX]; } } diff --git a/src/engine/graphics.h b/src/engine/graphics.h index 3699c3ea7..610f46e30 100644 --- a/src/engine/graphics.h +++ b/src/engine/graphics.h @@ -284,7 +284,7 @@ public: // pTextData & pTextOutlineData are automatically free'd virtual bool LoadTextTextures(size_t Width, size_t Height, CTextureHandle &TextTexture, CTextureHandle &TextOutlineTexture, uint8_t *pTextData, uint8_t *pTextOutlineData) = 0; virtual bool UnloadTextTextures(CTextureHandle &TextTexture, CTextureHandle &TextOutlineTexture) = 0; - virtual bool UpdateTextTexture(CTextureHandle TextureId, int x, int y, size_t Width, size_t Height, const uint8_t *pData) = 0; + virtual bool UpdateTextTexture(CTextureHandle TextureId, int x, int y, size_t Width, size_t Height, uint8_t *pData, bool IsMovedPointer) = 0; virtual CTextureHandle LoadSpriteTexture(const CImageInfo &FromImageInfo, const struct CDataSprite *pSprite) = 0;