port(EterLib): TextBar/DibBar/BlockTexture for uiTip TipBoard/BigBoard
TextBar and DibBar verbatim over the FreeType GDI shim (+GetTextExtentPoint32A); BlockTexture verbatim except Render, which records the clipped quad as a UI image of the device CPU texture (UIRenderAddImageNamed). Notices now render; port.text_bar covers block split, pixels, colour, ClearBar and TipBoard clip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c7bcb9bbbe
commit
6d2d262de8
@@ -614,3 +614,6 @@
|
|||||||
{"date": "2026-09-30", "unit": "EterLib/GrpMath.cpp", "action": "all PORTED verbatim", "evidence": "port.grp_math"}
|
{"date": "2026-09-30", "unit": "EterLib/GrpMath.cpp", "action": "all PORTED verbatim", "evidence": "port.grp_math"}
|
||||||
{"date": "2026-09-30", "unit": "EterLib/GrpColor.cpp", "action": "all PORTED verbatim", "evidence": "port.grp_math"}
|
{"date": "2026-09-30", "unit": "EterLib/GrpColor.cpp", "action": "all PORTED verbatim", "evidence": "port.grp_math"}
|
||||||
{"date": "2026-09-30", "unit": "EterLib/GrpColorInstance.cpp", "action": "all PORTED verbatim", "evidence": "port.grp_math"}
|
{"date": "2026-09-30", "unit": "EterLib/GrpColorInstance.cpp", "action": "all PORTED verbatim", "evidence": "port.grp_math"}
|
||||||
|
{"date": "2026-09-30", "unit": "EterLib/TextBar.cpp", "action": "all PORTED verbatim; GetTextExtentPoint32A added to the GDI shim", "evidence": "port.text_bar"}
|
||||||
|
{"date": "2026-09-30", "unit": "EterLib/DibBar.cpp", "action": "all PORTED verbatim", "evidence": "port.text_bar"}
|
||||||
|
{"date": "2026-09-30", "unit": "EterLib/BlockTexture.cpp", "action": "Render ADAPTED (UI image of the CPU texture), rest PORTED verbatim", "evidence": "port.text_bar"}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"reference": "EterLib/BlockTexture.cpp",
|
||||||
|
"reference_sha256": "791df4fed556b4aad015ede57d85763393fefd48cc505584198865f84c7a1b99",
|
||||||
|
"priority": "P4",
|
||||||
|
"contracts": [],
|
||||||
|
"functions": {
|
||||||
|
"CBlockTexture::SetClipRect": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/BlockTexture.cpp:CBlockTexture::SetClipRect"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (CreateTexture/LockRect on the recording device's CPU texture)."
|
||||||
|
},
|
||||||
|
"CBlockTexture::Render": {
|
||||||
|
"status": "ADAPTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/BlockTexture.cpp:CBlockTexture::Render"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "40250: SetPDTStream + DEFAULT_IB_FILL_RECT + stage-0 m_lpd3dTexture + DrawIndexedPrimitive in the UI pass. Port: the same clipped corners/UVs recorded as a UI image of the device CPU texture (UIRenderAddImageNamed). Invariant: identical quad, UVs and texels; clipped-out blocks draw nothing."
|
||||||
|
},
|
||||||
|
"CBlockTexture::InvalidateRect": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/BlockTexture.cpp:CBlockTexture::InvalidateRect"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (CreateTexture/LockRect on the recording device's CPU texture)."
|
||||||
|
},
|
||||||
|
"CBlockTexture::Create": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/BlockTexture.cpp:CBlockTexture::Create"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (CreateTexture/LockRect on the recording device's CPU texture)."
|
||||||
|
},
|
||||||
|
"CBlockTexture::CBlockTexture": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/BlockTexture.cpp:CBlockTexture::CBlockTexture"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (CreateTexture/LockRect on the recording device's CPU texture)."
|
||||||
|
},
|
||||||
|
"CBlockTexture::~CBlockTexture": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/BlockTexture.cpp:CBlockTexture::~CBlockTexture"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (CreateTexture/LockRect on the recording device's CPU texture)."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
{
|
||||||
|
"reference": "EterLib/DibBar.cpp",
|
||||||
|
"reference_sha256": "5523feed6b35f7e13d1af6fb3e517db52a2ba88a5b8887a2bf5a35bbff91aec2",
|
||||||
|
"priority": "P4",
|
||||||
|
"contracts": [],
|
||||||
|
"functions": {
|
||||||
|
"CDibBar::Invalidate": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/DibBar.cpp:CDibBar::Invalidate"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (RECT initialisers cast to the 32-bit LONG)."
|
||||||
|
},
|
||||||
|
"CDibBar::SetClipRect": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/DibBar.cpp:CDibBar::SetClipRect"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (RECT initialisers cast to the 32-bit LONG)."
|
||||||
|
},
|
||||||
|
"CDibBar::ClearBar": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/DibBar.cpp:CDibBar::ClearBar"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (RECT initialisers cast to the 32-bit LONG)."
|
||||||
|
},
|
||||||
|
"CDibBar::Render": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/DibBar.cpp:CDibBar::Render"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (RECT initialisers cast to the 32-bit LONG)."
|
||||||
|
},
|
||||||
|
"CDibBar::__NearTextureSize": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/DibBar.cpp:CDibBar::__NearTextureSize"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (RECT initialisers cast to the 32-bit LONG)."
|
||||||
|
},
|
||||||
|
"CDibBar::__DivideTextureSize": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/DibBar.cpp:CDibBar::__DivideTextureSize"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (RECT initialisers cast to the 32-bit LONG)."
|
||||||
|
},
|
||||||
|
"CDibBar::__BuildTextureBlock": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/DibBar.cpp:CDibBar::__BuildTextureBlock"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (RECT initialisers cast to the 32-bit LONG)."
|
||||||
|
},
|
||||||
|
"CDibBar::__BuildTextureBlockList": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/DibBar.cpp:CDibBar::__BuildTextureBlockList"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (RECT initialisers cast to the 32-bit LONG)."
|
||||||
|
},
|
||||||
|
"CDibBar::Create": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/DibBar.cpp:CDibBar::Create"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (RECT initialisers cast to the 32-bit LONG)."
|
||||||
|
},
|
||||||
|
"CDibBar::CDibBar": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/DibBar.cpp:CDibBar::CDibBar"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (RECT initialisers cast to the 32-bit LONG)."
|
||||||
|
},
|
||||||
|
"CDibBar::~CDibBar": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/DibBar.cpp:CDibBar::~CDibBar"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 (RECT initialisers cast to the 32-bit LONG)."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"reference": "EterLib/TextBar.cpp",
|
||||||
|
"reference_sha256": "f9f6d12d01e94d76150cb3b50617c10bdf22fcd1c9075ab4d6f40e0b429f7de3",
|
||||||
|
"priority": "P4",
|
||||||
|
"contracts": [],
|
||||||
|
"functions": {
|
||||||
|
"CTextBar::__SetFont": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/TextBar.cpp:CTextBar::__SetFont"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 over the Win32Gdi FreeType GDI shim (CreateFontIndirect/SelectObject/SetTextColor/GetTextExtentPoint32A). Live: uiTip.TipBoard/BigBoard via grp.CreateTextBar/CreateBigTextBar."
|
||||||
|
},
|
||||||
|
"CTextBar::SetTextColor": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/TextBar.cpp:CTextBar::SetTextColor"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 over the Win32Gdi FreeType GDI shim (CreateFontIndirect/SelectObject/SetTextColor/GetTextExtentPoint32A). Live: uiTip.TipBoard/BigBoard via grp.CreateTextBar/CreateBigTextBar."
|
||||||
|
},
|
||||||
|
"CTextBar::GetTextExtent": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/TextBar.cpp:CTextBar::GetTextExtent"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 over the Win32Gdi FreeType GDI shim (CreateFontIndirect/SelectObject/SetTextColor/GetTextExtentPoint32A). Live: uiTip.TipBoard/BigBoard via grp.CreateTextBar/CreateBigTextBar."
|
||||||
|
},
|
||||||
|
"CTextBar::TextOut": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/TextBar.cpp:CTextBar::TextOut"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 over the Win32Gdi FreeType GDI shim (CreateFontIndirect/SelectObject/SetTextColor/GetTextExtentPoint32A). Live: uiTip.TipBoard/BigBoard via grp.CreateTextBar/CreateBigTextBar."
|
||||||
|
},
|
||||||
|
"CTextBar::OnCreate": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/TextBar.cpp:CTextBar::OnCreate"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 over the Win32Gdi FreeType GDI shim (CreateFontIndirect/SelectObject/SetTextColor/GetTextExtentPoint32A). Live: uiTip.TipBoard/BigBoard via grp.CreateTextBar/CreateBigTextBar."
|
||||||
|
},
|
||||||
|
"CTextBar::CTextBar": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/TextBar.cpp:CTextBar::CTextBar"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 over the Win32Gdi FreeType GDI shim (CreateFontIndirect/SelectObject/SetTextColor/GetTextExtentPoint32A). Live: uiTip.TipBoard/BigBoard via grp.CreateTextBar/CreateBigTextBar."
|
||||||
|
},
|
||||||
|
"CTextBar::~CTextBar": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/TextBar.cpp:CTextBar::~CTextBar"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_text_bar_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "Verbatim 40250 over the Win32Gdi FreeType GDI shim (CreateFontIndirect/SelectObject/SetTextColor/GetTextExtentPoint32A). Live: uiTip.TipBoard/BigBoard via grp.CreateTextBar/CreateBigTextBar."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,185 @@
|
|||||||
|
// 40250 EterLib/BlockTexture.cpp. Verbatim except Render: the texture is the device's CPU texture
|
||||||
|
// (CreateTexture/LockRect as 40250), and the quad 40250 draws with SetPDTStream + DrawIndexedPrimitive
|
||||||
|
// in the UI pass is recorded as a UI image of that texture with the same corners and UVs.
|
||||||
|
#include "EterLib/StdAfx.h"
|
||||||
|
#include "EterLib/BlockTexture.h"
|
||||||
|
#include "EterLib/GrpBase.h"
|
||||||
|
#include "EterLib/GrpDIB.h"
|
||||||
|
#include "EterBase/Stl.h"
|
||||||
|
#include "EterLib/StateManager.h"
|
||||||
|
#include "UIRenderCommands.h"
|
||||||
|
void CBlockTexture::SetClipRect(const RECT & c_rRect)
|
||||||
|
{
|
||||||
|
m_bClipEnable = TRUE;
|
||||||
|
m_clipRect = c_rRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBlockTexture::Render(int ix, int iy)
|
||||||
|
{
|
||||||
|
int isx = ix + m_rect.left;
|
||||||
|
int isy = iy + m_rect.top;
|
||||||
|
int iex = ix + m_rect.left + m_dwWidth;
|
||||||
|
int iey = iy + m_rect.top + m_dwHeight;
|
||||||
|
|
||||||
|
float su = 0.0f;
|
||||||
|
float sv = 0.0f;
|
||||||
|
float eu = 1.0f;
|
||||||
|
float ev = 1.0f;
|
||||||
|
|
||||||
|
if (m_bClipEnable)
|
||||||
|
{
|
||||||
|
if (isx > m_clipRect.right)
|
||||||
|
return;
|
||||||
|
if (iex < m_clipRect.left)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isy > m_clipRect.bottom)
|
||||||
|
return;
|
||||||
|
if (iey < m_clipRect.top)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_clipRect.left > isx)
|
||||||
|
{
|
||||||
|
int idx = m_clipRect.left - isx;
|
||||||
|
isx += idx;
|
||||||
|
su += float(idx) / float(m_dwWidth);
|
||||||
|
}
|
||||||
|
if (iex > m_clipRect.right)
|
||||||
|
{
|
||||||
|
int idx = iex - m_clipRect.right;
|
||||||
|
iex -= idx;
|
||||||
|
eu -= float(idx) / float(m_dwWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_clipRect.top > isy)
|
||||||
|
{
|
||||||
|
int idy = m_clipRect.top - isy;
|
||||||
|
isy += idy;
|
||||||
|
sv += float(idy) / float(m_dwHeight);
|
||||||
|
}
|
||||||
|
if (iey > m_clipRect.bottom)
|
||||||
|
{
|
||||||
|
int idy = iey - m_clipRect.bottom;
|
||||||
|
iey -= idy;
|
||||||
|
ev -= float(idy) / float(m_dwHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TPDTVertex vertices[4];
|
||||||
|
vertices[0].position.x = isx - 0.5f;
|
||||||
|
vertices[0].position.y = isy - 0.5f;
|
||||||
|
vertices[0].position.z = 0.0f;
|
||||||
|
vertices[0].texCoord = TTextureCoordinate(su, sv);
|
||||||
|
vertices[0].diffuse = 0xffffffff;
|
||||||
|
|
||||||
|
vertices[1].position.x = iex - 0.5f;
|
||||||
|
vertices[1].position.y = isy - 0.5f;
|
||||||
|
vertices[1].position.z = 0.0f;
|
||||||
|
vertices[1].texCoord = TTextureCoordinate(eu, sv);
|
||||||
|
vertices[1].diffuse = 0xffffffff;
|
||||||
|
|
||||||
|
vertices[2].position.x = isx - 0.5f;
|
||||||
|
vertices[2].position.y = iey - 0.5f;
|
||||||
|
vertices[2].position.z = 0.0f;
|
||||||
|
vertices[2].texCoord = TTextureCoordinate(su, ev);
|
||||||
|
vertices[2].diffuse = 0xffffffff;
|
||||||
|
|
||||||
|
vertices[3].position.x = iex - 0.5f;
|
||||||
|
vertices[3].position.y = iey - 0.5f;
|
||||||
|
vertices[3].position.z = 0.0f;
|
||||||
|
vertices[3].texCoord = TTextureCoordinate(eu, ev);
|
||||||
|
vertices[3].diffuse = 0xffffffff;
|
||||||
|
|
||||||
|
// PORT: 40250 sets the stream, stage-0 texture and FVF and draws the fill-rect triangle list.
|
||||||
|
float x[4], y[4];
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
x[i] = vertices[i].position.x;
|
||||||
|
y[i] = vertices[i].position.y;
|
||||||
|
}
|
||||||
|
UIRenderAddImageNamed(UIRenderTextureNameFromHandle(m_lpd3dTexture), x, y, su, sv, eu, ev, vertices[0].diffuse);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBlockTexture::InvalidateRect(const RECT & c_rsrcRect)
|
||||||
|
{
|
||||||
|
RECT dstRect = m_rect;
|
||||||
|
if (c_rsrcRect.right < dstRect.left ||
|
||||||
|
c_rsrcRect.left > dstRect.right ||
|
||||||
|
c_rsrcRect.bottom < dstRect.top ||
|
||||||
|
c_rsrcRect.top > dstRect.bottom)
|
||||||
|
{
|
||||||
|
Tracef("InvalidateRect() - Strange rect");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// DIBBAR_LONGSIZE_BUGFIX
|
||||||
|
const RECT clipRect = {
|
||||||
|
max(c_rsrcRect.left - dstRect.left, 0),
|
||||||
|
max(c_rsrcRect.top - dstRect.top, 0),
|
||||||
|
min(c_rsrcRect.right - dstRect.left, dstRect.right - dstRect.left),
|
||||||
|
min(c_rsrcRect.bottom - dstRect.top, dstRect.bottom - dstRect.top),
|
||||||
|
};
|
||||||
|
// END_OF_DIBBAR_LONGSIZE_BUGFIX
|
||||||
|
|
||||||
|
|
||||||
|
DWORD * pdwSrc;
|
||||||
|
pdwSrc = (DWORD *)m_pDIB->GetPointer();
|
||||||
|
pdwSrc += dstRect.left + dstRect.top*m_pDIB->GetWidth();
|
||||||
|
|
||||||
|
D3DLOCKED_RECT lockedRect;
|
||||||
|
if (FAILED(m_lpd3dTexture->LockRect(0, &lockedRect, &clipRect, 0)))
|
||||||
|
{
|
||||||
|
Tracef("InvalidateRect() - Failed to LockRect");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iclipWidth = clipRect.right - clipRect.left;
|
||||||
|
int iclipHeight = clipRect.bottom - clipRect.top;
|
||||||
|
DWORD * pdwDst = (DWORD *)lockedRect.pBits;
|
||||||
|
DWORD dwDstWidth = lockedRect.Pitch>>2;
|
||||||
|
DWORD dwSrcWidth = m_pDIB->GetWidth();
|
||||||
|
for (int i = 0; i < iclipHeight; ++i)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < iclipWidth; ++i)
|
||||||
|
{
|
||||||
|
if (pdwSrc[i])
|
||||||
|
pdwDst[i] = pdwSrc[i] | 0xff000000;
|
||||||
|
else
|
||||||
|
pdwDst[i] = 0;
|
||||||
|
}
|
||||||
|
pdwDst += dwDstWidth;
|
||||||
|
pdwSrc += dwSrcWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lpd3dTexture->UnlockRect(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBlockTexture::Create(CGraphicDib * pDIB, const RECT & c_rRect, DWORD dwWidth, DWORD dwHeight)
|
||||||
|
{
|
||||||
|
if (FAILED(ms_lpd3dDevice->CreateTexture(dwWidth, dwHeight, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_lpd3dTexture)))
|
||||||
|
{
|
||||||
|
Tracef("Failed to create block texture %u, %u\n", dwWidth, dwHeight);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pDIB = pDIB;
|
||||||
|
m_rect = c_rRect;
|
||||||
|
m_dwWidth = dwWidth;
|
||||||
|
m_dwHeight = dwHeight;
|
||||||
|
m_bClipEnable = FALSE;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBlockTexture::CBlockTexture()
|
||||||
|
{
|
||||||
|
m_pDIB = NULL;
|
||||||
|
m_lpd3dTexture = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBlockTexture::~CBlockTexture()
|
||||||
|
{
|
||||||
|
safe_release(m_lpd3dTexture);
|
||||||
|
m_lpd3dTexture = NULL;
|
||||||
|
}
|
||||||
+156
-54
@@ -1,64 +1,166 @@
|
|||||||
// Platform skeleton for EterLib/DibBar.h (40250 EterLib/DibBar.cpp), generated by platform_stub.py.
|
// 40250 EterLib/DibBar.cpp, verbatim (RECT initialisers cast to LONG).
|
||||||
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
|
|
||||||
#include "EterLib/StdAfx.h"
|
#include "EterLib/StdAfx.h"
|
||||||
#include "EterLib/DibBar.h"
|
#include "EterLib/DibBar.h"
|
||||||
|
#include "EterLib/BlockTexture.h"
|
||||||
|
|
||||||
#include "../PlatformStub.h"
|
void CDibBar::Invalidate()
|
||||||
|
{
|
||||||
|
// PORT: RECT holds the 32-bit Win32 LONG, so static_cast<long> would narrow here.
|
||||||
|
RECT rect = { static_cast<LONG>(0), static_cast<LONG>(0), static_cast<LONG>(m_dwWidth), static_cast<LONG>(m_dwHeight)};
|
||||||
|
|
||||||
|
std::vector<CBlockTexture *>::iterator itor = m_kVec_pkBlockTexture.begin();
|
||||||
|
for (; itor != m_kVec_pkBlockTexture.end(); ++itor)
|
||||||
|
{
|
||||||
|
CBlockTexture * pTexture = *itor;
|
||||||
|
pTexture->InvalidateRect(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDibBar::SetClipRect(const RECT & c_rRect)
|
||||||
|
{
|
||||||
|
std::vector<CBlockTexture *>::iterator itor = m_kVec_pkBlockTexture.begin();
|
||||||
|
for (; itor != m_kVec_pkBlockTexture.end(); ++itor)
|
||||||
|
{
|
||||||
|
CBlockTexture * pTexture = *itor;
|
||||||
|
assert(pTexture);
|
||||||
|
if (!pTexture)
|
||||||
|
continue;
|
||||||
|
pTexture->SetClipRect(c_rRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDibBar::ClearBar()
|
||||||
|
{
|
||||||
|
DWORD * pdwBuf = (DWORD *)m_dib.GetPointer();
|
||||||
|
memset(pdwBuf, 0, m_dib.GetWidth()*m_dib.GetHeight()*4);
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDibBar::Render(int ix, int iy)
|
||||||
|
{
|
||||||
|
std::vector<CBlockTexture *>::iterator itor = m_kVec_pkBlockTexture.begin();
|
||||||
|
for (; itor != m_kVec_pkBlockTexture.end(); ++itor)
|
||||||
|
{
|
||||||
|
CBlockTexture * pTexture = *itor;
|
||||||
|
pTexture->Render(ix, iy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD CDibBar::__NearTextureSize(DWORD dwSize)
|
||||||
|
{
|
||||||
|
if ((dwSize & (dwSize-1)) == 0)
|
||||||
|
return dwSize;
|
||||||
|
|
||||||
|
DWORD dwRet = 2;
|
||||||
|
while (dwRet < dwSize)
|
||||||
|
{
|
||||||
|
dwRet <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dwRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDibBar::__DivideTextureSize(DWORD dwSize, DWORD dwMax, DWORD * pdwxStep, DWORD * pdwxCount, DWORD * pdwxRest)
|
||||||
|
{
|
||||||
|
if (dwSize<dwMax)
|
||||||
|
{
|
||||||
|
*pdwxStep = dwMax;
|
||||||
|
*pdwxCount = 0;
|
||||||
|
*pdwxRest = dwSize%dwMax;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pdwxStep = dwMax;
|
||||||
|
*pdwxCount = dwSize/dwMax;
|
||||||
|
*pdwxRest = dwSize%dwMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBlockTexture * CDibBar::__BuildTextureBlock(DWORD dwxPos, DWORD dwyPos, DWORD dwImageWidth, DWORD dwImageHeight, DWORD dwTextureWidth, DWORD dwTextureHeight)
|
||||||
|
{
|
||||||
|
if (dwTextureWidth == 0 || dwTextureHeight == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// PORT: RECT holds the 32-bit Win32 LONG, so static_cast<long> would narrow here.
|
||||||
|
RECT posRect = { static_cast<LONG>(dwxPos), static_cast<LONG>(dwyPos), static_cast<LONG>(dwxPos+dwImageWidth), static_cast<LONG>(dwyPos+dwImageHeight)};
|
||||||
|
|
||||||
|
CBlockTexture * pBlockTexture = new CBlockTexture;
|
||||||
|
if (!pBlockTexture->Create(&m_dib, posRect, dwTextureWidth, dwTextureHeight))
|
||||||
|
{
|
||||||
|
delete pBlockTexture;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pBlockTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDibBar::__BuildTextureBlockList(DWORD dwWidth, DWORD dwHeight, DWORD dwMax)
|
||||||
|
{
|
||||||
|
DWORD dwxStep, dwyStep;
|
||||||
|
DWORD dwxCount, dwyCount;
|
||||||
|
DWORD dwxRest, dwyRest;
|
||||||
|
__DivideTextureSize(dwWidth, dwMax, &dwxStep, &dwxCount, &dwxRest);
|
||||||
|
__DivideTextureSize(dwHeight, dwMax, &dwyStep, &dwyCount, &dwyRest);
|
||||||
|
DWORD dwxTexRest = __NearTextureSize(dwxRest);
|
||||||
|
DWORD dwyTexRest = __NearTextureSize(dwyRest);
|
||||||
|
|
||||||
|
for (DWORD y = 0; y < dwyCount; ++y)
|
||||||
|
{
|
||||||
|
for (DWORD x = 0; x < dwxCount; ++x)
|
||||||
|
{
|
||||||
|
CBlockTexture * pTexture = __BuildTextureBlock(x*dwxStep, y*dwyStep,
|
||||||
|
dwxStep, dwyStep,
|
||||||
|
dwMax, dwMax);
|
||||||
|
if (pTexture)
|
||||||
|
m_kVec_pkBlockTexture.push_back(pTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBlockTexture * pTexture = __BuildTextureBlock(dwxCount*dwxStep, y*dwyStep,
|
||||||
|
dwxRest, dwyStep,
|
||||||
|
dwxTexRest, dwMax);
|
||||||
|
|
||||||
|
if (pTexture)
|
||||||
|
m_kVec_pkBlockTexture.push_back(pTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DWORD x = 0; x < dwxCount; ++x)
|
||||||
|
{
|
||||||
|
CBlockTexture * pTexture = __BuildTextureBlock(x*dwxStep, dwyCount*dwyStep,
|
||||||
|
dwxStep, dwyRest,
|
||||||
|
dwMax, dwyTexRest);
|
||||||
|
if (pTexture)
|
||||||
|
m_kVec_pkBlockTexture.push_back(pTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwxRest > 0 && dwyRest > 0)
|
||||||
|
{
|
||||||
|
CBlockTexture * pTexture = __BuildTextureBlock(dwxCount*dwxStep, dwyCount*dwyStep,
|
||||||
|
dwxRest, dwyRest,
|
||||||
|
dwxTexRest, dwyTexRest);
|
||||||
|
if (pTexture)
|
||||||
|
m_kVec_pkBlockTexture.push_back(pTexture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDibBar::Create(HDC hdc, DWORD dwWidth, DWORD dwHeight)
|
||||||
|
{
|
||||||
|
if (!m_dib.Create(hdc, dwWidth, dwHeight))
|
||||||
|
{
|
||||||
|
Tracef(" Failed to create CDibBar\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dwWidth = dwWidth;
|
||||||
|
m_dwHeight = dwHeight;
|
||||||
|
|
||||||
|
__BuildTextureBlockList(dwWidth, dwHeight);
|
||||||
|
OnCreate();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
CDibBar::CDibBar()
|
CDibBar::CDibBar()
|
||||||
{
|
{
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CDibBar::~CDibBar()
|
CDibBar::~CDibBar()
|
||||||
{
|
{
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CDibBar::Create(HDC, DWORD, DWORD) -> bool
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
return mt_platform_stub_return<bool>();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CDibBar::Invalidate() -> void
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CDibBar::SetClipRect(const RECT &) -> void
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CDibBar::ClearBar() -> void
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CDibBar::Render(int, int) -> void
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CDibBar::__NearTextureSize(DWORD) -> DWORD
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
return mt_platform_stub_return<DWORD>();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CDibBar::__DivideTextureSize(DWORD, DWORD, DWORD *, DWORD *, DWORD *) -> void
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CDibBar::__BuildTextureBlock(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD) -> CBlockTexture *
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
return mt_platform_stub_return<CBlockTexture *>();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CDibBar::__BuildTextureBlockList(DWORD, DWORD, DWORD) -> void
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,77 @@
|
|||||||
// Platform skeleton for EterLib/TextBar.h (40250 EterLib/TextBar.cpp), generated by platform_stub.py.
|
// 40250 EterLib/TextBar.cpp, verbatim.
|
||||||
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
|
|
||||||
#include "EterLib/StdAfx.h"
|
#include "EterLib/StdAfx.h"
|
||||||
#include "EterLib/TextBar.h"
|
#include "EterLib/TextBar.h"
|
||||||
|
#include "EterLib/Util.h"
|
||||||
|
|
||||||
#include "../PlatformStub.h"
|
void CTextBar::__SetFont(int fontSize, bool isBold)
|
||||||
|
|
||||||
CTextBar::CTextBar(int, bool)
|
|
||||||
{
|
{
|
||||||
MT_PLATFORM_STUB();
|
int iCodePage = GetDefaultCodePage();
|
||||||
|
|
||||||
|
LOGFONT logFont;
|
||||||
|
|
||||||
|
memset(&logFont, 0, sizeof(LOGFONT));
|
||||||
|
|
||||||
|
logFont.lfHeight = fontSize;
|
||||||
|
logFont.lfEscapement = 0;
|
||||||
|
logFont.lfOrientation = 0;
|
||||||
|
|
||||||
|
if (isBold)
|
||||||
|
logFont.lfWeight = FW_BOLD;
|
||||||
|
else
|
||||||
|
logFont.lfWeight = FW_NORMAL;
|
||||||
|
|
||||||
|
logFont.lfItalic = FALSE;
|
||||||
|
logFont.lfUnderline = FALSE;
|
||||||
|
logFont.lfStrikeOut = FALSE;
|
||||||
|
logFont.lfCharSet = GetCharsetFromCodePage(iCodePage);
|
||||||
|
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
||||||
|
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||||
|
logFont.lfQuality = ANTIALIASED_QUALITY;
|
||||||
|
logFont.lfPitchAndFamily = DEFAULT_PITCH;
|
||||||
|
strcpy(logFont.lfFaceName, GetFontFaceFromCodePage(iCodePage));
|
||||||
|
m_hFont = CreateFontIndirect(&logFont);
|
||||||
|
|
||||||
|
|
||||||
|
HDC hdc = m_dib.GetDCHandle();
|
||||||
|
m_hOldFont = (HFONT)SelectObject(hdc, m_hFont);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTextBar::SetTextColor(int r, int g, int b)
|
||||||
|
{
|
||||||
|
HDC hDC = m_dib.GetDCHandle();
|
||||||
|
::SetTextColor(hDC, RGB(r, g, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTextBar::GetTextExtent(const char * c_szText, SIZE* p_size)
|
||||||
|
{
|
||||||
|
HDC hDC = m_dib.GetDCHandle();
|
||||||
|
GetTextExtentPoint32(hDC, c_szText, strlen(c_szText), p_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTextBar::TextOut(int ix, int iy, const char * c_szText)
|
||||||
|
{
|
||||||
|
m_dib.TextOut(ix, iy, c_szText);
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTextBar::OnCreate()
|
||||||
|
{
|
||||||
|
m_dib.SetBkMode(TRANSPARENT);
|
||||||
|
|
||||||
|
__SetFont(m_fontSize, m_isBold);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTextBar::CTextBar(int fontSize, bool isBold)
|
||||||
|
{
|
||||||
|
m_hOldFont = NULL;
|
||||||
|
m_fontSize = fontSize;
|
||||||
|
m_isBold = isBold;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CTextBar::~CTextBar()
|
CTextBar::~CTextBar()
|
||||||
{
|
{
|
||||||
MT_PLATFORM_STUB();
|
HDC hdc = m_dib.GetDCHandle();
|
||||||
}
|
SelectObject(hdc, m_hOldFont);
|
||||||
|
|
||||||
auto CTextBar::TextOut(int, int, const char *) -> void
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CTextBar::SetTextColor(int, int, int) -> void
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CTextBar::GetTextExtent(const char *, SIZE *) -> void
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CTextBar::__SetFont(int, bool) -> void
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CTextBar::OnCreate() -> void
|
|
||||||
{
|
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,11 @@ void UIRenderRestoreClip() {
|
|||||||
|
|
||||||
void UIRenderAddImage(const CGraphicTexture* texture, const float x[4], const float y[4],
|
void UIRenderAddImage(const CGraphicTexture* texture, const float x[4], const float y[4],
|
||||||
float su, float sv, float eu, float ev, std::uint32_t argb, int blend) {
|
float su, float sv, float eu, float ev, std::uint32_t argb, int blend) {
|
||||||
|
UIRenderAddImageNamed(UIRenderTextureName(texture), x, y, su, sv, eu, ev, argb, blend);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIRenderAddImageNamed(const std::string& texture_name, const float x[4], const float y[4],
|
||||||
|
float su, float sv, float eu, float ev, std::uint32_t argb, int blend) {
|
||||||
// 40250 draws the image quad through the device: the UI pass's world transform places it
|
// 40250 draws the image quad through the device: the UI pass's world transform places it
|
||||||
// (identity except where a caller sets one, e.g. CPythonMiniMap::RenderAtlas's window offset) and a
|
// (identity except where a caller sets one, e.g. CPythonMiniMap::RenderAtlas's window offset) and a
|
||||||
// stage-0 MODULATE with D3DTA_TFACTOR tints it (the atlas's NPC/warp/waypoint marks).
|
// stage-0 MODULATE with D3DTA_TFACTOR tints it (the atlas's NPC/warp/waypoint marks).
|
||||||
@@ -139,7 +144,7 @@ void UIRenderAddImage(const CGraphicTexture* texture, const float x[4], const fl
|
|||||||
command.y1 = std::min({command.qy[0], command.qy[1], command.qy[2], command.qy[3]});
|
command.y1 = std::min({command.qy[0], command.qy[1], command.qy[2], command.qy[3]});
|
||||||
command.x2 = std::max({command.qx[0], command.qx[1], command.qx[2], command.qx[3]});
|
command.x2 = std::max({command.qx[0], command.qx[1], command.qx[2], command.qx[3]});
|
||||||
command.y2 = std::max({command.qy[0], command.qy[1], command.qy[2], command.qy[3]});
|
command.y2 = std::max({command.qy[0], command.qy[1], command.qy[2], command.qy[3]});
|
||||||
command.text = UIRenderTextureName(texture);
|
command.text = texture_name;
|
||||||
command.quad = true;
|
command.quad = true;
|
||||||
command.su = su; command.sv = sv; command.eu = eu; command.ev = ev;
|
command.su = su; command.sv = sv; command.eu = eu; command.ev = ev;
|
||||||
command.blend = blend;
|
command.blend = blend;
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ bool MtCpuMemoryTexture(const std::string& name, UIMemoryTexture* out);
|
|||||||
// Godot canvas puts them on .5, so the quad is shifted back by +0.5 here.
|
// Godot canvas puts them on .5, so the quad is shifted back by +0.5 here.
|
||||||
void UIRenderAddImage(const CGraphicTexture* texture, const float x[4], const float y[4],
|
void UIRenderAddImage(const CGraphicTexture* texture, const float x[4], const float y[4],
|
||||||
float su, float sv, float eu, float ev, std::uint32_t argb, int blend = 0);
|
float su, float sv, float eu, float ev, std::uint32_t argb, int blend = 0);
|
||||||
|
// The same quad for a texture named as UIRenderTextureNameFromHandle (a raw device texture: CBlockTexture).
|
||||||
|
void UIRenderAddImageNamed(const std::string& texture_name, const float x[4], const float y[4],
|
||||||
|
float su, float sv, float eu, float ev, std::uint32_t argb, int blend = 0);
|
||||||
|
|
||||||
void UIRenderSetSize(int width, int height);
|
void UIRenderSetSize(int width, int height);
|
||||||
void UIRenderGetSize(unsigned* width, unsigned* height);
|
void UIRenderGetSize(unsigned* width, unsigned* height);
|
||||||
|
|||||||
@@ -455,3 +455,16 @@ BOOL TextOutA(HDC hdc, int x, int y, LPCSTR lpString, int c)
|
|||||||
MultiByteToWideChar(CP_ACP, 0, lpString, c, wide.data(), n);
|
MultiByteToWideChar(CP_ACP, 0, lpString, c, wide.data(), n);
|
||||||
return TextOutW(hdc, x, y, wide.data(), n);
|
return TextOutW(hdc, x, y, wide.data(), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL GetTextExtentPoint32A(HDC hdc, LPCSTR lpString, int c, LPSIZE psizl)
|
||||||
|
{
|
||||||
|
const int n = MultiByteToWideChar(CP_ACP, 0, lpString, c, nullptr, 0);
|
||||||
|
if (n <= 0)
|
||||||
|
{
|
||||||
|
if (c != 0 || !psizl) return FALSE;
|
||||||
|
return GetTextExtentPoint32W(hdc, nullptr, 0, psizl);
|
||||||
|
}
|
||||||
|
std::vector<WCHAR> wide(static_cast<size_t>(n));
|
||||||
|
MultiByteToWideChar(CP_ACP, 0, lpString, c, wide.data(), n);
|
||||||
|
return GetTextExtentPoint32W(hdc, wide.data(), n, psizl);
|
||||||
|
}
|
||||||
|
|||||||
@@ -194,6 +194,10 @@ if(BUILD_TESTING AND CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME)
|
|||||||
target_link_libraries(port_text_test PRIVATE port_platform)
|
target_link_libraries(port_text_test PRIVATE port_platform)
|
||||||
add_test(NAME port.text COMMAND $<TARGET_FILE:port_text_test>)
|
add_test(NAME port.text COMMAND $<TARGET_FILE:port_text_test>)
|
||||||
set_tests_properties(port.text PROPERTIES SKIP_RETURN_CODE 77)
|
set_tests_properties(port.text PROPERTIES SKIP_RETURN_CODE 77)
|
||||||
|
add_executable(port_text_bar_test ${PROJECT_SOURCE_DIR}/tests/port/port_text_bar_test.cpp)
|
||||||
|
target_link_libraries(port_text_bar_test PRIVATE port_platform)
|
||||||
|
add_test(NAME port.text_bar COMMAND $<TARGET_FILE:port_text_bar_test>)
|
||||||
|
set_tests_properties(port.text_bar PROPERTIES SKIP_RETURN_CODE 77)
|
||||||
|
|
||||||
# MilesLib: the 40250 sound managers over the Miles emulation (platform/MilesLib/MilesAil.cpp).
|
# MilesLib: the 40250 sound managers over the Miles emulation (platform/MilesLib/MilesAil.cpp).
|
||||||
add_executable(port_miles_test ${PROJECT_SOURCE_DIR}/tests/port/port_miles_test.cpp)
|
add_executable(port_miles_test ${PROJECT_SOURCE_DIR}/tests/port/port_miles_test.cpp)
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GrpBase.h"
|
||||||
|
|
||||||
|
class CGraphicDib;
|
||||||
|
|
||||||
|
class CBlockTexture : public CGraphicBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CBlockTexture();
|
||||||
|
virtual ~CBlockTexture();
|
||||||
|
|
||||||
|
bool Create(CGraphicDib * pDIB, const RECT & c_rRect, DWORD dwWidth, DWORD dwHeight);
|
||||||
|
void SetClipRect(const RECT & c_rRect);
|
||||||
|
void Render(int ix, int iy);
|
||||||
|
void InvalidateRect(const RECT & c_rsrcRect);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CGraphicDib * m_pDIB;
|
||||||
|
RECT m_rect;
|
||||||
|
RECT m_clipRect;
|
||||||
|
BOOL m_bClipEnable;
|
||||||
|
DWORD m_dwWidth;
|
||||||
|
DWORD m_dwHeight;
|
||||||
|
LPDIRECT3DTEXTURE8 m_lpd3dTexture;
|
||||||
|
};
|
||||||
@@ -58,6 +58,8 @@ COLORREF SetTextColor(HDC hdc, COLORREF color);
|
|||||||
COLORREF SetBkColor(HDC hdc, COLORREF color);
|
COLORREF SetBkColor(HDC hdc, COLORREF color);
|
||||||
int SetBkMode(HDC hdc, int mode);
|
int SetBkMode(HDC hdc, int mode);
|
||||||
BOOL GetTextExtentPoint32W(HDC hdc, LPCWSTR lpString, int c, LPSIZE psizl);
|
BOOL GetTextExtentPoint32W(HDC hdc, LPCWSTR lpString, int c, LPSIZE psizl);
|
||||||
|
BOOL GetTextExtentPoint32A(HDC hdc, LPCSTR lpString, int c, LPSIZE psizl);
|
||||||
|
#define GetTextExtentPoint32 GetTextExtentPoint32A
|
||||||
BOOL GetCharABCWidthsFloatW(HDC hdc, UINT iFirst, UINT iLast, LPABCFLOAT lpABC);
|
BOOL GetCharABCWidthsFloatW(HDC hdc, UINT iFirst, UINT iLast, LPABCFLOAT lpABC);
|
||||||
BOOL TextOutW(HDC hdc, int x, int y, LPCWSTR lpString, int c);
|
BOOL TextOutW(HDC hdc, int x, int y, LPCWSTR lpString, int c);
|
||||||
BOOL TextOutA(HDC hdc, int x, int y, LPCSTR lpString, int c);
|
BOOL TextOutA(HDC hdc, int x, int y, LPCSTR lpString, int c);
|
||||||
|
|||||||
@@ -0,0 +1,170 @@
|
|||||||
|
// EterLib CTextBar -> CDibBar -> CBlockTexture (40250 uiTip.TipBoard / BigBoard: grp.CreateTextBar):
|
||||||
|
// GDI text into the DIB over platform/Win32Gdi.cpp, the DIB split into power-of-two device textures,
|
||||||
|
// and each block's quad recorded as a UI image (the draw 40250 sends through the device).
|
||||||
|
//
|
||||||
|
// Needs a system Arial or Tahoma; exit 77 (ctest SKIP) without one, unless MT_ASSETS_STRICT=1.
|
||||||
|
#include "EterLib/StdAfx.h"
|
||||||
|
#include "EterLib/TextBar.h"
|
||||||
|
#include "EterLib/GrpBase.h"
|
||||||
|
#include "EterLib/Util.h"
|
||||||
|
#include "../../src/platform/EterLib/UIRenderCommands.h"
|
||||||
|
#include "../../src/platform/EterLib/RecordingDevice.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static int g_failures = 0;
|
||||||
|
#define CHECK(cond) \
|
||||||
|
do { \
|
||||||
|
if (!(cond)) { \
|
||||||
|
std::fprintf(stderr, "%s:%d: CHECK(%s)\n", __FILE__, __LINE__, #cond); \
|
||||||
|
++g_failures; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
struct DeviceAccess : CGraphicBase
|
||||||
|
{
|
||||||
|
static void Set(IDirect3DDevice8* device) { ms_lpd3dDevice = device; }
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::vector<UIRenderCommand> images()
|
||||||
|
{
|
||||||
|
std::vector<UIRenderCommand> out;
|
||||||
|
for (const auto& command : UIRenderCommands())
|
||||||
|
if (command.kind == UIRenderCommand::Image)
|
||||||
|
out.push_back(command);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int opaque_pixels(const std::string& name, std::uint32_t* sample)
|
||||||
|
{
|
||||||
|
UIMemoryTexture texture;
|
||||||
|
if (!UIRenderMemoryTexture(name, &texture))
|
||||||
|
return -1;
|
||||||
|
int count = 0;
|
||||||
|
for (std::uint32_t px : texture.argb)
|
||||||
|
{
|
||||||
|
if ((px >> 24) == 0xFF)
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
*sample = px;
|
||||||
|
}
|
||||||
|
else if (px >> 24)
|
||||||
|
return -2; // InvalidateRect writes either 0 or src | 0xff000000
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool near(float a, float b)
|
||||||
|
{
|
||||||
|
return std::fabs(a - b) < 1e-3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
const bool is_strict = std::getenv("MT_ASSETS_STRICT") && std::string(std::getenv("MT_ASSETS_STRICT")) == "1";
|
||||||
|
if (access("/System/Library/Fonts/Supplemental/Arial.ttf", 0) != 0 && access("/System/Library/Fonts/Supplemental/Tahoma.ttf", 0) != 0)
|
||||||
|
{
|
||||||
|
std::fprintf(stderr, "port_text_bar_test: no system Arial/Tahoma\n");
|
||||||
|
return is_strict ? 1 : 77;
|
||||||
|
}
|
||||||
|
SetDefaultCodePage(1252);
|
||||||
|
IDirect3DDevice8* device = MtCreateRecordingDevice(800, 600);
|
||||||
|
DeviceAccess::Set(device);
|
||||||
|
|
||||||
|
{
|
||||||
|
// uiTip.TipBoard: grp.CreateTextBar(370, 300) -> CTextBar(12, false).
|
||||||
|
CTextBar bar(12, false);
|
||||||
|
CHECK(bar.Create(NULL, 370, 300));
|
||||||
|
|
||||||
|
SIZE size = {};
|
||||||
|
bar.GetTextExtent("Notice", &size);
|
||||||
|
CHECK(size.cx > 20 && size.cx < 60 && size.cy >= 12 && size.cy <= 16);
|
||||||
|
|
||||||
|
bar.TextOut(0, 0, "Notice");
|
||||||
|
UIRenderBeginFrame();
|
||||||
|
bar.Render(10, 20);
|
||||||
|
std::vector<UIRenderCommand> blocks = images();
|
||||||
|
// 370 x 300 = 256 + 114 by 256 + 44: blocks of 256x256, 128x256, 256x64, 128x64 texels.
|
||||||
|
CHECK(blocks.size() == 4);
|
||||||
|
if (blocks.size() == 4)
|
||||||
|
{
|
||||||
|
CHECK(blocks[0].text.compare(0, 8, "mem:cpu_") == 0);
|
||||||
|
// Unclipped: the quad is the full texture from the block origin, shifted +0.5 back.
|
||||||
|
CHECK(near(blocks[0].qx[0], 10.0f) && near(blocks[0].qy[0], 20.0f));
|
||||||
|
CHECK(near(blocks[0].qx[3], 266.0f) && near(blocks[0].qy[3], 276.0f));
|
||||||
|
CHECK(near(blocks[1].qx[0], 266.0f) && near(blocks[1].qx[3], 394.0f));
|
||||||
|
CHECK(near(blocks[2].qy[0], 276.0f) && near(blocks[2].qy[3], 340.0f));
|
||||||
|
CHECK(blocks[0].su == 0.0f && blocks[0].ev == 1.0f);
|
||||||
|
|
||||||
|
std::uint32_t sample = 0;
|
||||||
|
const int lit = opaque_pixels(blocks[0].text, &sample);
|
||||||
|
CHECK(lit > 20);
|
||||||
|
// CGraphicDib::Create sets a white text colour; anti-aliased edges stay grey.
|
||||||
|
CHECK(((sample >> 16) & 0xFF) > 0 && ((sample >> 16) & 0xFF) == (sample & 0xFF));
|
||||||
|
std::uint32_t unused = 0;
|
||||||
|
CHECK(opaque_pixels(blocks[1].text, &unused) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// uiTip.BigBoard colour; ClearBar zeroes the DIB and every block.
|
||||||
|
bar.SetTextColor(242, 231, 193);
|
||||||
|
bar.TextOut(0, 0, "Notice");
|
||||||
|
UIRenderBeginFrame();
|
||||||
|
bar.Render(0, 0);
|
||||||
|
blocks = images();
|
||||||
|
if (!blocks.empty())
|
||||||
|
{
|
||||||
|
std::uint32_t sample = 0;
|
||||||
|
CHECK(opaque_pixels(blocks[0].text, &sample) > 20);
|
||||||
|
}
|
||||||
|
bar.ClearBar();
|
||||||
|
UIRenderBeginFrame();
|
||||||
|
bar.Render(0, 0);
|
||||||
|
blocks = images();
|
||||||
|
if (!blocks.empty())
|
||||||
|
{
|
||||||
|
std::uint32_t sample = 0;
|
||||||
|
CHECK(opaque_pixels(blocks[0].text, &sample) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TipBoard's SetClipRect(0, y, screen width, y + 18) at textBar position (3, 5 - curPos):
|
||||||
|
// the lower blocks start past the clip bottom and are skipped, the upper ones are cut to 18 rows.
|
||||||
|
RECT clip = {0, 20, 800, 38};
|
||||||
|
bar.SetClipRect(clip);
|
||||||
|
UIRenderBeginFrame();
|
||||||
|
bar.Render(3, 5);
|
||||||
|
blocks = images();
|
||||||
|
CHECK(blocks.size() == 2);
|
||||||
|
if (blocks.size() == 2)
|
||||||
|
{
|
||||||
|
CHECK(near(blocks[0].qy[0], 20.0f) && near(blocks[0].qy[3], 38.0f));
|
||||||
|
CHECK(near(blocks[0].sv, 15.0f / 256.0f) && near(blocks[0].ev, 1.0f - 223.0f / 256.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// uiTip.BigBoard: grp.CreateBigTextBar(500, 300, 18) -> CTextBar(18, true).
|
||||||
|
CTextBar big(18, true);
|
||||||
|
CHECK(big.Create(NULL, 500, 300));
|
||||||
|
SIZE small = {}, large = {};
|
||||||
|
CTextBar normal(12, false);
|
||||||
|
CHECK(normal.Create(NULL, 64, 64));
|
||||||
|
normal.GetTextExtent("Notice", &small);
|
||||||
|
big.GetTextExtent("Notice", &large);
|
||||||
|
CHECK(large.cx > small.cx && large.cy > small.cy);
|
||||||
|
UIRenderBeginFrame();
|
||||||
|
normal.Render(0, 0);
|
||||||
|
CHECK(images().size() == 1); // 64 x 64 fits in one block (count 0, rest 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceAccess::Set(NULL);
|
||||||
|
device->Release();
|
||||||
|
if (!g_failures)
|
||||||
|
std::printf("ok\n");
|
||||||
|
return g_failures ? 1 : 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user