Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SVG bitmap and optimize rendering #3981

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 38 additions & 14 deletions Client/mods/deathmatch/logic/CClientVectorGraphicDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "StdInc.h"
#include "CClientVectorGraphicDisplay.h"
#include "CClientVectorGraphic.h"
#include <lunasvg.h>

using namespace lunasvg;

Expand Down Expand Up @@ -45,6 +44,37 @@ void CClientVectorGraphicDisplay::Render()
}
}

void CClientVectorGraphicDisplay::UnpremultiplyBitmap(Bitmap& bitmap)
{
auto width = bitmap.width();
auto height = bitmap.height();
auto stride = bitmap.stride();
auto rowData = bitmap.data();

for (std::uint32_t y = 0; y < height; y++)
{
auto data = rowData;
for (std::uint32_t x = 0; x < width; x++)
{
auto& b = data[0];
auto& g = data[1];
auto& r = data[2];
auto& a = data[3];

if (a != 0)
{
r = (r * 255) / a;
g = (g * 255) / a;
b = (b * 255) / a;
}

data += 4;
}

rowData += stride;
}
}

void CClientVectorGraphicDisplay::UpdateTexture()
{
if (!m_pVectorGraphic || m_pVectorGraphic->IsDestroyed())
Expand All @@ -62,25 +92,19 @@ void CClientVectorGraphicDisplay::UpdateTexture()
if (!surface)
return;

Bitmap bitmap = svgDocument->renderToBitmap(pVectorGraphicItem->m_uiSizeX, pVectorGraphicItem->m_uiSizeY);
if (!bitmap.valid())
return;
// SVG has a predefined width and height. We need transform it to the requested size
const Matrix transformationMatrix(pVectorGraphicItem->m_uiSizeX / svgDocument->width(), 0, 0, pVectorGraphicItem->m_uiSizeY / svgDocument->height(), 0, 0);

// Lock surface
D3DLOCKED_RECT LockedRect;
if (SUCCEEDED(surface->LockRect(&LockedRect, nullptr, D3DLOCK_DISCARD)))
{
auto surfaceData = static_cast<byte*>(LockedRect.pBits);
auto sourceData = static_cast<const byte*>(bitmap.data());
auto surfaceData = static_cast<std::uint8_t*>(LockedRect.pBits);
auto stride = static_cast<std::uint32_t>(LockedRect.Pitch);

for (uint32_t y = 0; y < bitmap.height(); ++y)
{
memcpy(surfaceData, sourceData, bitmap.width() * 4); // 4 bytes per pixel

// advance row pointers
sourceData += bitmap.stride();
surfaceData += LockedRect.Pitch;
}
Bitmap bitmap{surfaceData, pVectorGraphicItem->m_uiSizeX, pVectorGraphicItem->m_uiSizeY, stride};
svgDocument->render(bitmap, transformationMatrix);
UnpremultiplyBitmap(bitmap);

// Unlock surface
surface->UnlockRect();
Expand Down
4 changes: 4 additions & 0 deletions Client/mods/deathmatch/logic/CClientVectorGraphicDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class CClientVectorGraphicDisplay;

#include "CClientDisplay.h"
#include "CClientDisplayManager.h"
#include <lunasvg.h>

class CClientVectorGraphicDisplay final : public CClientDisplay
{
Expand All @@ -34,6 +35,9 @@ class CClientVectorGraphicDisplay final : public CClientDisplay

void Update();

private:
void UnpremultiplyBitmap(lunasvg::Bitmap& bitmap);

private:
CClientVectorGraphic* m_pVectorGraphic;

Expand Down
Loading