From 65777331f7bf70bb289ee061d1c02db3b830c7e4 Mon Sep 17 00:00:00 2001 From: shenlei Date: Wed, 30 Sep 2026 14:21:13 +0900 Subject: [PATCH] port: GrpImageInstance/GrpExpandedImageInstance verbatim; fix SCREEN blend factor Both units are the 40250 bodies; only the PDT-stream draw becomes UIRenderAddImage (with the rendering mode). SCREEN/COLOR_DODGE were packed as 0x28 (INVDESTALPHA+ONE); 40250 uses INVDESTCOLOR+ONE (0x2A). OnIsType calls the base OnIsType instead of 40250's recursing IsType. port.grp_resource covers the quads, UVs, colour and blend mode. Co-Authored-By: Claude Opus 5.5 --- audit/history.jsonl | 2 + .../EterLib/GrpExpandedImageInstance.cpp.json | 172 +++++++++++ .../port-map/EterLib/GrpFontTexture.cpp.json | 53 ++++ .../EterLib/GrpImageInstance.cpp.json | 225 ++++++++++++++ src/host/ui_batches.cpp | 6 +- .../EterLib/GrpExpandedImageInstance.cpp | 257 +++++++++------- src/platform/EterLib/GrpImageInstance.cpp | 280 +++++++++++------- tests/port/port_grp_resource_test.cpp | 55 +++- 8 files changed, 819 insertions(+), 231 deletions(-) create mode 100644 audit/port-map/EterLib/GrpExpandedImageInstance.cpp.json create mode 100644 audit/port-map/EterLib/GrpFontTexture.cpp.json create mode 100644 audit/port-map/EterLib/GrpImageInstance.cpp.json diff --git a/audit/history.jsonl b/audit/history.jsonl index 69996b5e..3e312067 100644 --- a/audit/history.jsonl +++ b/audit/history.jsonl @@ -631,3 +631,5 @@ {"date": "2026-09-30", "unit": "EterLib/GrpImageTexture.cpp", "action": "port", "evidence": "40250 flow: pack reload in CreateDeviceObjects, CDXTCImage header check + CreateDDSTexture size/mip bias, CreateFromDiskFile; handles stay platform textures; port.grp_resource"} {"date": "2026-09-30", "unit": "EterLib/GrpIndexBuffer.cpp", "action": "port", "evidence": "CPU buffers, bodies otherwise 40250; port.grp_resource"} {"date": "2026-09-30", "unit": "EterLib/GrpVertexBuffer.cpp", "action": "port", "evidence": "CPU buffers, bodies otherwise 40250; port.grp_resource"} +{"date": "2026-09-30", "unit": "EterLib/GrpImageInstance.cpp", "action": "port", "evidence": "verbatim; draw via UIRenderAddImage; port.grp_resource quad/uv/colour"} +{"date": "2026-09-30", "unit": "EterLib/GrpExpandedImageInstance.cpp", "action": "port", "evidence": "verbatim; draw + blend mode via UIRenderAddImage, SCREEN/COLOR_DODGE blend fixed to INVDESTCOLOR (0x2A); OnIsType recursion avoided; port.grp_resource"} diff --git a/audit/port-map/EterLib/GrpExpandedImageInstance.cpp.json b/audit/port-map/EterLib/GrpExpandedImageInstance.cpp.json new file mode 100644 index 00000000..971fb321 --- /dev/null +++ b/audit/port-map/EterLib/GrpExpandedImageInstance.cpp.json @@ -0,0 +1,172 @@ +{ + "reference": "EterLib/GrpExpandedImageInstance.cpp", + "reference_sha256": "1e3eb000f12b2ab0658da06ff55843874a2fa70619d249d9246c545746396a78", + "priority": "P4", + "contracts": [], + "functions": { + "CGraphicExpandedImageInstance::CreateSystem": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::CreateSystem" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::DestroySystem": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::DestroySystem" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::New": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::New" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::Delete": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::Delete" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::OnRender": { + "status": "ADAPTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::OnRender" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ], + "note": "40250: CULLMODE CCW for a mirrored scale, Save/RestoreRenderState SRCBLEND/DESTBLEND per RENDERING_MODE, PDT-stream fill-rect draw. Port: the verbatim vertices plus m_iRenderingMode go to UIRenderAddImage; the Vulkan UI pipeline (cull none) maps SCREEN/COLOR_DODGE to INVDESTCOLOR+ONE and MODULATE to ZERO+SRCCOLOR (ui_batches.cpp). Invariant: same corners, UVs and blend factors." + }, + "CGraphicExpandedImageInstance::SetDepth": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::SetDepth" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::SetOrigin": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::SetOrigin" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::SetRotation": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::SetRotation" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::SetScale": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::SetScale" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::SetRenderingRect": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::SetRenderingRect" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::SetRenderingMode": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::SetRenderingMode" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::Type": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::Type" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::OnSetImagePointer": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::OnSetImagePointer" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::OnIsType": { + "status": "ADAPTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::OnIsType" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ], + "note": "40250: falls back to CGraphicImageInstance::IsType, which re-dispatches to this override and recurses until stack overflow for a foreign type. Port: calls the base OnIsType. Invariant: TRUE for its own and CGraphicImageInstance type, FALSE otherwise." + }, + "CGraphicExpandedImageInstance::Initialize": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::Initialize" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::Destroy": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::Destroy" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::CGraphicExpandedImageInstance": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::CGraphicExpandedImageInstance" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicExpandedImageInstance::~CGraphicExpandedImageInstance": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpExpandedImageInstance.cpp:CGraphicExpandedImageInstance::~CGraphicExpandedImageInstance" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + } + } +} diff --git a/audit/port-map/EterLib/GrpFontTexture.cpp.json b/audit/port-map/EterLib/GrpFontTexture.cpp.json new file mode 100644 index 00000000..6fa13d68 --- /dev/null +++ b/audit/port-map/EterLib/GrpFontTexture.cpp.json @@ -0,0 +1,53 @@ +{ + "reference": "EterLib/GrpFontTexture.cpp", + "reference_sha256": "d50b85e6e494b2e2a10289f40a5ebc518be03e1e73d60cd7463fd2dc5032ba00", + "priority": "P4", + "contracts": [], + "functions": { + "CGraphicFontTexture::CGraphicFontTexture": { + "status": "TODO" + }, + "CGraphicFontTexture::~CGraphicFontTexture": { + "status": "TODO" + }, + "CGraphicFontTexture::Initialize": { + "status": "TODO" + }, + "CGraphicFontTexture::IsEmpty": { + "status": "TODO" + }, + "CGraphicFontTexture::Destroy": { + "status": "TODO" + }, + "CGraphicFontTexture::CreateDeviceObjects": { + "status": "TODO" + }, + "CGraphicFontTexture::DestroyDeviceObjects": { + "status": "TODO" + }, + "CGraphicFontTexture::Create": { + "status": "TODO" + }, + "CGraphicFontTexture::GetFont": { + "status": "TODO" + }, + "CGraphicFontTexture::AppendTexture": { + "status": "TODO" + }, + "CGraphicFontTexture::UpdateTexture": { + "status": "TODO" + }, + "CGraphicFontTexture::GetCharacterInfomation": { + "status": "TODO" + }, + "CGraphicFontTexture::UpdateCharacterInfomation": { + "status": "TODO" + }, + "CGraphicFontTexture::CheckTextureIndex": { + "status": "TODO" + }, + "CGraphicFontTexture::SelectTexture": { + "status": "TODO" + } + } +} diff --git a/audit/port-map/EterLib/GrpImageInstance.cpp.json b/audit/port-map/EterLib/GrpImageInstance.cpp.json new file mode 100644 index 00000000..1ed50fe1 --- /dev/null +++ b/audit/port-map/EterLib/GrpImageInstance.cpp.json @@ -0,0 +1,225 @@ +{ + "reference": "EterLib/GrpImageInstance.cpp", + "reference_sha256": "59c2dd35bca5a7ad3cf517070a6188ee37ac41cb1fd53ef3ee65437b737b622c", + "priority": "P4", + "contracts": [], + "functions": { + "CGraphicImageInstance::CreateSystem": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::CreateSystem" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::DestroySystem": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::DestroySystem" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::New": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::New" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::Delete": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::Delete" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::Render": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::Render" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::OnRender": { + "status": "ADAPTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::OnRender" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ], + "note": "40250: SetPDTStream + DEFAULT_IB_FILL_RECT + stage-0 texture, DrawIndexedPrimitive. Port: the same four TPDTVertex corners/UVs/diffuse go to UIRenderAddImage. Invariant: quad = image rect at m_v2Position-0.5, UVs = rect/texture size." + }, + "CGraphicImageInstance::GetTextureReference": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::GetTextureReference" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::GetTexturePointer": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::GetTexturePointer" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::GetGraphicImagePointer": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::GetGraphicImagePointer" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::GetWidth": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::GetWidth" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::GetHeight": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::GetHeight" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::SetDiffuseColor": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::SetDiffuseColor" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::SetPosition": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::SetPosition" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::SetImagePointer": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::SetImagePointer" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::ReloadImagePointer": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::ReloadImagePointer" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::IsEmpty": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::IsEmpty" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::Type": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::Type" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::IsType": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::IsType" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::OnIsType": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::OnIsType" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::OnSetImagePointer": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::OnSetImagePointer" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::Initialize": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::Initialize" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::Destroy": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::Destroy" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::CGraphicImageInstance": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::CGraphicImageInstance" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + }, + "CGraphicImageInstance::~CGraphicImageInstance": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpImageInstance.cpp:CGraphicImageInstance::~CGraphicImageInstance" + ], + "test": [ + "tests/port/port_grp_resource_test.cpp" + ] + } + } +} diff --git a/src/host/ui_batches.cpp b/src/host/ui_batches.cpp index 78633de2..af16a538 100644 --- a/src/host/ui_batches.cpp +++ b/src/host/ui_batches.cpp @@ -138,10 +138,10 @@ void VulkanWindow::build_ui_batches( const std::string& tex_name = cmd.kind == UIRenderCommand::Image ? cmd.text : std::string(); const std::string& mask_name = cmd.kind == UIRenderCommand::Image ? cmd.mask : std::string(); const bool is_masked = !mask_name.empty(); - // CGraphicExpandedImageInstance: SCREEN/COLOR_DODGE use - // INVDESTCOLOR + ONE; MODULATE uses ZERO + SRCCOLOR. + // CGraphicExpandedImageInstance: SCREEN/COLOR_DODGE use INVDESTCOLOR (10) + ONE (2); + // MODULATE uses ZERO (1) + SRCCOLOR (3). Packed as src | dst << 4. const std::uint8_t blend_mode = cmd.kind == UIRenderCommand::Image - ? ((cmd.blend == 1 || cmd.blend == 2) ? 0x28 : (cmd.blend == 3 ? 0x31 : 1)) + ? ((cmd.blend == 1 || cmd.blend == 2) ? 0x2A : (cmd.blend == 3 ? 0x31 : 1)) : 1; const VkPipeline pipeline = get_pipeline(0, 0, blend_mode); const VkDescriptorSet descriptor = get_ui_texture_descriptor(tex_name, mask_name, capture_textures); diff --git a/src/platform/EterLib/GrpExpandedImageInstance.cpp b/src/platform/EterLib/GrpExpandedImageInstance.cpp index 3c432de6..0f16f278 100644 --- a/src/platform/EterLib/GrpExpandedImageInstance.cpp +++ b/src/platform/EterLib/GrpExpandedImageInstance.cpp @@ -1,63 +1,148 @@ -// Platform skeleton for EterLib/GrpExpandedImageInstance.h (40250 EterLib/GrpExpandedImageInstance.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. +// 40250 EterLib/GrpExpandedImageInstance.cpp, verbatim. #include "EterLib/StdAfx.h" -#include "EterLib/GrpExpandedImageInstance.h" - -#include "../PlatformStub.h" #include "EterBase/CRC32.h" +#include "EterLib/GrpExpandedImageInstance.h" +#include "EterLib/StateManager.h" #include "UIRenderCommands.h" -#include +CDynamicPool CGraphicExpandedImageInstance::ms_kPool; -auto CGraphicExpandedImageInstance::Type() -> DWORD +void CGraphicExpandedImageInstance::CreateSystem(UINT uCapacity) { - static DWORD type = GetCRC32("CGraphicExpandedImageInstance", sizeof("CGraphicExpandedImageInstance") - 1); - return type; + ms_kPool.Create(uCapacity); } -CGraphicExpandedImageInstance::CGraphicExpandedImageInstance() +void CGraphicExpandedImageInstance::DestroySystem() { - Initialize(); + ms_kPool.Destroy(); } -CGraphicExpandedImageInstance::~CGraphicExpandedImageInstance() +CGraphicExpandedImageInstance* CGraphicExpandedImageInstance::New() { - Destroy(); + return ms_kPool.Alloc(); } -auto CGraphicExpandedImageInstance::Destroy() -> void +void CGraphicExpandedImageInstance::Delete(CGraphicExpandedImageInstance* pkImgInst) { - CGraphicImageInstance::Destroy(); - Initialize(); + pkImgInst->Destroy(); + ms_kPool.Free(pkImgInst); } -auto CGraphicExpandedImageInstance::SetDepth(float depth) -> void +void CGraphicExpandedImageInstance::OnRender() { - m_fDepth = depth; + CGraphicImage * pImage = m_roImage.GetPointer(); + CGraphicTexture * pTexture = pImage->GetTexturePointer(); + + const RECT& c_rRect = pImage->GetRectReference(); + float texReverseWidth = 1.0f / float(pTexture->GetWidth()); + float texReverseHeight = 1.0f / float(pTexture->GetHeight()); + float su = (c_rRect.left - m_RenderingRect.left) * texReverseWidth; + float sv = (c_rRect.top - m_RenderingRect.top) * texReverseHeight; + float eu = (c_rRect.left + m_RenderingRect.right + (c_rRect.right-c_rRect.left)) * texReverseWidth; + float ev = (c_rRect.top + m_RenderingRect.bottom + (c_rRect.bottom-c_rRect.top)) * texReverseHeight; + + TPDTVertex vertices[4]; + vertices[0].position.x = m_v2Position.x-0.5f; + vertices[0].position.y = m_v2Position.y-0.5f; + vertices[0].position.z = m_fDepth; + vertices[0].texCoord = TTextureCoordinate(su, sv); + vertices[0].diffuse = m_DiffuseColor; + + vertices[1].position.x = m_v2Position.x-0.5f; + vertices[1].position.y = m_v2Position.y-0.5f; + vertices[1].position.z = m_fDepth; + vertices[1].texCoord = TTextureCoordinate(eu, sv); + vertices[1].diffuse = m_DiffuseColor; + + vertices[2].position.x = m_v2Position.x-0.5f; + vertices[2].position.y = m_v2Position.y-0.5f; + vertices[2].position.z = m_fDepth; + vertices[2].texCoord = TTextureCoordinate(su, ev); + vertices[2].diffuse = m_DiffuseColor; + + vertices[3].position.x = m_v2Position.x-0.5f; + vertices[3].position.y = m_v2Position.y-0.5f; + vertices[3].position.z = m_fDepth; + vertices[3].texCoord = TTextureCoordinate(eu, ev); + vertices[3].diffuse = m_DiffuseColor; + + if (0.0f == m_fRotation) + { + float fimgWidth = float(pImage->GetWidth()) * m_v2Scale.x; + float fimgHeight = float(pImage->GetHeight()) * m_v2Scale.y; + + vertices[0].position.x -= m_RenderingRect.left; + vertices[0].position.y -= m_RenderingRect.top; + vertices[1].position.x += fimgWidth + m_RenderingRect.right; + vertices[1].position.y -= m_RenderingRect.top; + vertices[2].position.x -= m_RenderingRect.left; + vertices[2].position.y += fimgHeight + m_RenderingRect.bottom; + vertices[3].position.x += fimgWidth + m_RenderingRect.right; + vertices[3].position.y += fimgHeight + m_RenderingRect.bottom; + // PORT: 40250 flips D3DRS_CULLMODE to CCW for a mirrored scale; the UI pipeline draws both windings. + } + else + { + float fimgHalfWidth = float(pImage->GetWidth())/2.0f * m_v2Scale.x; + float fimgHalfHeight = float(pImage->GetHeight())/2.0f * m_v2Scale.y; + + for (int i = 0; i < 4; ++i) + { + vertices[i].position.x += m_v2Origin.x; + vertices[i].position.y += m_v2Origin.y; + } + + float fRadian = D3DXToRadian(m_fRotation); + vertices[0].position.x += (-fimgHalfWidth*cosf(fRadian)) - (-fimgHalfHeight*sinf(fRadian)); + vertices[0].position.y += (-fimgHalfWidth*sinf(fRadian)) + (-fimgHalfHeight*cosf(fRadian)); + vertices[1].position.x += (+fimgHalfWidth*cosf(fRadian)) - (-fimgHalfHeight*sinf(fRadian)); + vertices[1].position.y += (+fimgHalfWidth*sinf(fRadian)) + (-fimgHalfHeight*cosf(fRadian)); + vertices[2].position.x += (-fimgHalfWidth*cosf(fRadian)) - (+fimgHalfHeight*sinf(fRadian)); + vertices[2].position.y += (-fimgHalfWidth*sinf(fRadian)) + (+fimgHalfHeight*cosf(fRadian)); + vertices[3].position.x += (+fimgHalfWidth*cosf(fRadian)) - (+fimgHalfHeight*sinf(fRadian)); + vertices[3].position.y += (+fimgHalfWidth*sinf(fRadian)) + (+fimgHalfHeight*cosf(fRadian)); + } + + // PORT: 40250 saves SRCBLEND/DESTBLEND for the rendering mode (SCREEN/COLOR_DODGE: INVDESTCOLOR+ONE, + // MODULATE: ZERO+SRCCOLOR), draws the fill-rect quad with the PDT stream and restores the states; here + // the quad and its mode go to the UI command list, which picks the matching blend pipeline. + float x[4], y[4]; + for (int i = 0; i < 4; ++i) + { + x[i] = vertices[i].position.x; + y[i] = vertices[i].position.y; + } + UIRenderAddImage(pTexture, x, y, su, sv, eu, ev, vertices[0].diffuse, m_iRenderingMode); } -auto CGraphicExpandedImageInstance::SetOrigin() -> void +void CGraphicExpandedImageInstance::SetDepth(float fDepth) { - m_v2Origin = D3DXVECTOR2(GetWidth() * 0.5f, GetHeight() * 0.5f); + m_fDepth = fDepth; } -auto CGraphicExpandedImageInstance::SetOrigin(float x, float y) -> void +void CGraphicExpandedImageInstance::SetOrigin() { - m_v2Origin = D3DXVECTOR2(x, y); + SetOrigin(float(GetWidth()) / 2.0f, float(GetHeight()) / 2.0f); } -auto CGraphicExpandedImageInstance::SetRotation(float rotation) -> void +void CGraphicExpandedImageInstance::SetOrigin(float fx, float fy) { - m_fRotation = rotation; + m_v2Origin.x = fx; + m_v2Origin.y = fy; } -auto CGraphicExpandedImageInstance::SetScale(float x, float y) -> void +void CGraphicExpandedImageInstance::SetRotation(float fRotation) { - m_v2Scale = D3DXVECTOR2(x, y); + m_fRotation = fRotation; } -// In 40250, the arguments are fractions of the image size (uiToolTip gauges, SetPercentage). -auto CGraphicExpandedImageInstance::SetRenderingRect(float fLeft, float fTop, float fRight, float fBottom) -> void +void CGraphicExpandedImageInstance::SetScale(float fx, float fy) +{ + m_v2Scale.x = fx; + m_v2Scale.y = fy; +} + +void CGraphicExpandedImageInstance::SetRenderingRect(float fLeft, float fTop, float fRight, float fBottom) { if (IsEmpty()) return; @@ -71,115 +156,57 @@ auto CGraphicExpandedImageInstance::SetRenderingRect(float fLeft, float fTop, fl m_RenderingRect.bottom = fHeight * fBottom; } -auto CGraphicExpandedImageInstance::SetRenderingMode(int mode) -> void +void CGraphicExpandedImageInstance::SetRenderingMode(int iMode) { - m_iRenderingMode = mode; + m_iRenderingMode = iMode; } -auto CGraphicExpandedImageInstance::Initialize() -> void +DWORD CGraphicExpandedImageInstance::Type() { - m_fDepth = 0; - m_v2Origin = D3DXVECTOR2(0, 0); - m_v2Scale = D3DXVECTOR2(1, 1); - m_fRotation = 0; - m_RenderingRect = {0, 0, 0, 0}; - m_iRenderingMode = RENDERING_MODE_NORMAL; + static DWORD s_dwType = GetCRC32("CGraphicExpandedImageInstance", strlen("CGraphicExpandedImageInstance")); + return (s_dwType); } -// 40250 GrpExpandedImageInstance.cpp:29-142. The vertex and texture-coordinate arithmetic is -// verbatim; the D3D stream/blend-state calls become one UIRenderCommand with the four vertices. -auto CGraphicExpandedImageInstance::OnRender() -> void +void CGraphicExpandedImageInstance::OnSetImagePointer() { - CGraphicImage * pImage = m_roImage.GetPointer(); - CGraphicTexture * pTexture = pImage->GetTexturePointer(); - if (pTexture->GetWidth() <= 0 || pTexture->GetHeight() <= 0) + if (IsEmpty()) return; - const RECT& c_rRect = pImage->GetRectReference(); - float texReverseWidth = 1.0f / float(pTexture->GetWidth()); - float texReverseHeight = 1.0f / float(pTexture->GetHeight()); - float su = (c_rRect.left - m_RenderingRect.left) * texReverseWidth; - float sv = (c_rRect.top - m_RenderingRect.top) * texReverseHeight; - float eu = (c_rRect.left + m_RenderingRect.right + (c_rRect.right-c_rRect.left)) * texReverseWidth; - float ev = (c_rRect.top + m_RenderingRect.bottom + (c_rRect.bottom-c_rRect.top)) * texReverseHeight; - - float x[4], y[4]; - for (int i = 0; i < 4; ++i) - { - x[i] = m_v2Position.x-0.5f; - y[i] = m_v2Position.y-0.5f; - } - - if (0.0f == m_fRotation) - { - float fimgWidth = float(pImage->GetWidth()) * m_v2Scale.x; - float fimgHeight = float(pImage->GetHeight()) * m_v2Scale.y; - - x[0] -= m_RenderingRect.left; - y[0] -= m_RenderingRect.top; - x[1] += fimgWidth + m_RenderingRect.right; - y[1] -= m_RenderingRect.top; - x[2] -= m_RenderingRect.left; - y[2] += fimgHeight + m_RenderingRect.bottom; - x[3] += fimgWidth + m_RenderingRect.right; - y[3] += fimgHeight + m_RenderingRect.bottom; - // PORT: 40250 flips D3DRS_CULLMODE for a mirrored scale; the Godot canvas has no culling. - } - else - { - float fimgHalfWidth = float(pImage->GetWidth())/2.0f * m_v2Scale.x; - float fimgHalfHeight = float(pImage->GetHeight())/2.0f * m_v2Scale.y; - - for (int i = 0; i < 4; ++i) - { - x[i] += m_v2Origin.x; - y[i] += m_v2Origin.y; - } - - float fRadian = D3DXToRadian(m_fRotation); - x[0] += (-fimgHalfWidth*cosf(fRadian)) - (-fimgHalfHeight*sinf(fRadian)); - y[0] += (-fimgHalfWidth*sinf(fRadian)) + (-fimgHalfHeight*cosf(fRadian)); - x[1] += (+fimgHalfWidth*cosf(fRadian)) - (-fimgHalfHeight*sinf(fRadian)); - y[1] += (+fimgHalfWidth*sinf(fRadian)) + (-fimgHalfHeight*cosf(fRadian)); - x[2] += (-fimgHalfWidth*cosf(fRadian)) - (+fimgHalfHeight*sinf(fRadian)); - y[2] += (-fimgHalfWidth*sinf(fRadian)) + (+fimgHalfHeight*cosf(fRadian)); - x[3] += (+fimgHalfWidth*cosf(fRadian)) - (+fimgHalfHeight*sinf(fRadian)); - y[3] += (+fimgHalfWidth*sinf(fRadian)) + (+fimgHalfHeight*cosf(fRadian)); - } - - UIRenderAddImage(pTexture, x, y, su, sv, eu, ev, UIRenderColor(m_DiffuseColor), m_iRenderingMode); + SetOrigin(float(GetWidth()) / 2.0f, float(GetHeight()) / 2.0f); } -auto CGraphicExpandedImageInstance::OnSetImagePointer() -> void +BOOL CGraphicExpandedImageInstance::OnIsType(DWORD dwType) { - if (!IsEmpty()) SetOrigin(); + if (CGraphicExpandedImageInstance::Type() == dwType) + return TRUE; + + // PORT: 40250 calls CGraphicImageInstance::IsType, which dispatches back to this override and recurses + // until the stack overflows for any other type; the base OnIsType gives the intended answer. + return CGraphicImageInstance::OnIsType(dwType); } -auto CGraphicExpandedImageInstance::OnIsType(DWORD type) -> BOOL +void CGraphicExpandedImageInstance::Initialize() { - return type == Type() || CGraphicImageInstance::OnIsType(type); + m_iRenderingMode = RENDERING_MODE_NORMAL; + m_fDepth = 0.0f; + m_v2Origin.x = m_v2Origin.y = 0.0f; + m_v2Scale.x = m_v2Scale.y = 1.0f; + m_fRotation = 0.0f; + memset(&m_RenderingRect, 0, sizeof(RECT)); } -auto CGraphicExpandedImageInstance::CreateSystem(UINT) -> void +void CGraphicExpandedImageInstance::Destroy() { - MT_PLATFORM_STUB(); + CGraphicImageInstance::Destroy(); + Initialize(); } -auto CGraphicExpandedImageInstance::DestroySystem() -> void +CGraphicExpandedImageInstance::CGraphicExpandedImageInstance() { - MT_PLATFORM_STUB(); + Initialize(); } -auto CGraphicExpandedImageInstance::New() -> CGraphicExpandedImageInstance * +CGraphicExpandedImageInstance::~CGraphicExpandedImageInstance() { - return new CGraphicExpandedImageInstance(); + Destroy(); } - -auto CGraphicExpandedImageInstance::Delete(CGraphicExpandedImageInstance *instance) -> void -{ - if (!instance) return; - instance->Destroy(); - delete instance; -} - -decltype(CGraphicExpandedImageInstance::ms_kPool) CGraphicExpandedImageInstance::ms_kPool{}; diff --git a/src/platform/EterLib/GrpImageInstance.cpp b/src/platform/EterLib/GrpImageInstance.cpp index b6c7a14c..4027740f 100644 --- a/src/platform/EterLib/GrpImageInstance.cpp +++ b/src/platform/EterLib/GrpImageInstance.cpp @@ -1,118 +1,52 @@ -// Platform skeleton for EterLib/GrpImageInstance.h (40250 EterLib/GrpImageInstance.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. +// 40250 EterLib/GrpImageInstance.cpp, verbatim. #include "EterLib/StdAfx.h" #include "EterLib/GrpImageInstance.h" - -#include "../PlatformStub.h" +#include "EterLib/StateManager.h" #include "UIRenderCommands.h" + #include "EterBase/CRC32.h" +//STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR); +//STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); +//STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND); +//STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND); -auto CGraphicImageInstance::Type() -> DWORD +CDynamicPool CGraphicImageInstance::ms_kPool; + +void CGraphicImageInstance::CreateSystem(UINT uCapacity) { - static DWORD type = GetCRC32("CGraphicImageInstance", sizeof("CGraphicImageInstance") - 1); - return type; + ms_kPool.Create(uCapacity); } -auto CGraphicImageInstance::IsType(DWORD type) -> BOOL +void CGraphicImageInstance::DestroySystem() { - return OnIsType(type); + ms_kPool.Destroy(); } -CGraphicImageInstance::CGraphicImageInstance() +CGraphicImageInstance* CGraphicImageInstance::New() { - m_DiffuseColor = D3DXCOLOR(1, 1, 1, 1); - m_v2Position = D3DXVECTOR2(0, 0); + return ms_kPool.Alloc(); } -CGraphicImageInstance::~CGraphicImageInstance() +void CGraphicImageInstance::Delete(CGraphicImageInstance* pkImgInst) { - Destroy(); + pkImgInst->Destroy(); + ms_kPool.Free(pkImgInst); } -// 40250 Destroy(): drop the image reference, then Initialize() (white, at the origin). -auto CGraphicImageInstance::Destroy() -> void +void CGraphicImageInstance::Render() { - m_roImage.Clear(); - m_DiffuseColor = D3DXCOLOR(1, 1, 1, 1); - m_v2Position = D3DXVECTOR2(0, 0); + if (IsEmpty()) + return; + + assert(!IsEmpty()); + + OnRender(); } -auto CGraphicImageInstance::Render() -> void -{ - if (!IsEmpty()) OnRender(); -} - -auto CGraphicImageInstance::SetDiffuseColor(float r, float g, float b, float a) -> void -{ - m_DiffuseColor = D3DXCOLOR(r, g, b, a); -} - -auto CGraphicImageInstance::SetPosition(float x, float y) -> void -{ - m_v2Position = D3DXVECTOR2(x, y); -} - -auto CGraphicImageInstance::SetImagePointer(CGraphicImage *image) -> void -{ - m_roImage.SetPointer(image); - OnSetImagePointer(); -} - -auto CGraphicImageInstance::ReloadImagePointer(CGraphicImage *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicImageInstance::IsEmpty() const -> bool -{ - return m_roImage.IsNull() || m_roImage->IsEmpty(); -} - -auto CGraphicImageInstance::GetWidth() -> int -{ - return IsEmpty() ? 0 : m_roImage->GetWidth(); -} - -auto CGraphicImageInstance::GetHeight() -> int -{ - return IsEmpty() ? 0 : m_roImage->GetHeight(); -} - -auto CGraphicImageInstance::GetTexturePointer() -> CGraphicTexture * -{ - CGraphicImage* pkImage = m_roImage.GetPointer(); - return pkImage ? pkImage->GetTexturePointer() : NULL; -} - -auto CGraphicImageInstance::GetTextureReference() const -> const CGraphicTexture & -{ - return m_roImage->GetTextureReference(); -} - -auto CGraphicImageInstance::GetGraphicImagePointer() -> CGraphicImage * -{ - return m_roImage.GetPointer(); -} - -auto CGraphicImageInstance::operator==(const CGraphicImageInstance &) const -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicImageInstance::Initialize() -> void -{ - MT_PLATFORM_STUB(); -} - -// 40250 GrpImageInstance.cpp:44-96: the image's rect inside its texture (a .sub shares its parent's) -// becomes the texture coordinates of one quad. -auto CGraphicImageInstance::OnRender() -> void +void CGraphicImageInstance::OnRender() { CGraphicImage * pImage = m_roImage.GetPointer(); CGraphicTexture * pTexture = pImage->GetTexturePointer(); - if (pTexture->GetWidth() <= 0 || pTexture->GetHeight() <= 0) - return; float fimgWidth = pImage->GetWidth(); float fimgHeight = pImage->GetHeight(); @@ -124,44 +58,166 @@ auto CGraphicImageInstance::OnRender() -> void float sv = c_rRect.top * texReverseHeight; float eu = (c_rRect.left + (c_rRect.right-c_rRect.left)) * texReverseWidth; float ev = (c_rRect.top + (c_rRect.bottom-c_rRect.top)) * texReverseHeight; + + + TPDTVertex vertices[4]; + vertices[0].position.x = m_v2Position.x-0.5f; + vertices[0].position.y = m_v2Position.y-0.5f; + vertices[0].position.z = 0.0f; + vertices[0].texCoord = TTextureCoordinate(su, sv); + vertices[0].diffuse = m_DiffuseColor; - const float x[4] = {m_v2Position.x-0.5f, m_v2Position.x + fimgWidth-0.5f, - m_v2Position.x-0.5f, m_v2Position.x + fimgWidth-0.5f}; - const float y[4] = {m_v2Position.y-0.5f, m_v2Position.y-0.5f, - m_v2Position.y + fimgHeight-0.5f, m_v2Position.y + fimgHeight-0.5f}; - UIRenderAddImage(pTexture, x, y, su, sv, eu, ev, UIRenderColor(m_DiffuseColor)); + vertices[1].position.x = m_v2Position.x + fimgWidth-0.5f; + vertices[1].position.y = m_v2Position.y-0.5f; + vertices[1].position.z = 0.0f; + vertices[1].texCoord = TTextureCoordinate(eu, sv); + vertices[1].diffuse = m_DiffuseColor; + + vertices[2].position.x = m_v2Position.x-0.5f; + vertices[2].position.y = m_v2Position.y + fimgHeight-0.5f; + vertices[2].position.z = 0.0f; + vertices[2].texCoord = TTextureCoordinate(su, ev); + vertices[2].diffuse = m_DiffuseColor; + + vertices[3].position.x = m_v2Position.x + fimgWidth-0.5f; + vertices[3].position.y = m_v2Position.y + fimgHeight-0.5f; + vertices[3].position.z = 0.0f; + vertices[3].texCoord = TTextureCoordinate(eu, ev); + vertices[3].diffuse = m_DiffuseColor; + + // PORT: 40250 sets the PDT stream, the fill-rect index buffer, stage-0 texture and FVF and draws the + // two triangles; here the quad goes to the UI command list with the same corners and UVs. + float x[4], y[4]; + for (int i = 0; i < 4; ++i) + { + x[i] = vertices[i].position.x; + y[i] = vertices[i].position.y; + } + UIRenderAddImage(pTexture, x, y, su, sv, eu, ev, vertices[0].diffuse); + //OLD: STATEMANAGER.DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, c_FillRectIndices, D3DFMT_INDEX16, vertices, sizeof(TPDTVertex)); + //////////////////////////////////////////////////////////// } -auto CGraphicImageInstance::OnSetImagePointer() -> void +const CGraphicTexture & CGraphicImageInstance::GetTextureReference() const { - MT_PLATFORM_STUB(); + return m_roImage->GetTextureReference(); } -auto CGraphicImageInstance::OnIsType(DWORD type) -> BOOL +CGraphicTexture * CGraphicImageInstance::GetTexturePointer() { - return type == Type(); + CGraphicImage* pkImage = m_roImage.GetPointer(); + return pkImage ? pkImage->GetTexturePointer() : NULL; } -auto CGraphicImageInstance::CreateSystem(UINT) -> void +CGraphicImage * CGraphicImageInstance::GetGraphicImagePointer() { - MT_PLATFORM_STUB(); + return m_roImage.GetPointer(); } -auto CGraphicImageInstance::DestroySystem() -> void +int CGraphicImageInstance::GetWidth() { - MT_PLATFORM_STUB(); + if (IsEmpty()) + return 0; + + return m_roImage->GetWidth(); } -auto CGraphicImageInstance::New() -> CGraphicImageInstance * +int CGraphicImageInstance::GetHeight() { - return new CGraphicImageInstance(); + if (IsEmpty()) + return 0; + + return m_roImage->GetHeight(); } -auto CGraphicImageInstance::Delete(CGraphicImageInstance *instance) -> void +void CGraphicImageInstance::SetDiffuseColor(float fr, float fg, float fb, float fa) { - if (!instance) return; - instance->Destroy(); - delete instance; + m_DiffuseColor.r = fr; + m_DiffuseColor.g = fg; + m_DiffuseColor.b = fb; + m_DiffuseColor.a = fa; +} +void CGraphicImageInstance::SetPosition(float fx, float fy) +{ + m_v2Position.x = fx; + m_v2Position.y = fy; } -decltype(CGraphicImageInstance::ms_kPool) CGraphicImageInstance::ms_kPool{}; +void CGraphicImageInstance::SetImagePointer(CGraphicImage * pImage) +{ + m_roImage.SetPointer(pImage); + + OnSetImagePointer(); +} + +void CGraphicImageInstance::ReloadImagePointer(CGraphicImage * pImage) +{ + if (m_roImage.IsNull()) + { + SetImagePointer(pImage); + return; + } + + CGraphicImage * pkImage = m_roImage.GetPointer(); + + if (pkImage) + pkImage->Reload(); +} + +bool CGraphicImageInstance::IsEmpty() const +{ + if (!m_roImage.IsNull() && !m_roImage->IsEmpty()) + return false; + + return true; +} + +bool CGraphicImageInstance::operator == (const CGraphicImageInstance & rhs) const +{ + return (m_roImage.GetPointer() == rhs.m_roImage.GetPointer()); +} + +DWORD CGraphicImageInstance::Type() +{ + static DWORD s_dwType = GetCRC32("CGraphicImageInstance", strlen("CGraphicImageInstance")); + return (s_dwType); +} + +BOOL CGraphicImageInstance::IsType(DWORD dwType) +{ + return OnIsType(dwType); +} + +BOOL CGraphicImageInstance::OnIsType(DWORD dwType) +{ + if (CGraphicImageInstance::Type() == dwType) + return TRUE; + + return FALSE; +} + +void CGraphicImageInstance::OnSetImagePointer() +{ +} + +void CGraphicImageInstance::Initialize() +{ + m_DiffuseColor.r = m_DiffuseColor.g = m_DiffuseColor.b = m_DiffuseColor.a = 1.0f; + m_v2Position.x = m_v2Position.y = 0.0f; +} + +void CGraphicImageInstance::Destroy() +{ + m_roImage.SetPointer(NULL); // CRef 에서 레퍼런스 카운트가 떨어져야 함. + Initialize(); +} + +CGraphicImageInstance::CGraphicImageInstance() +{ + Initialize(); +} + +CGraphicImageInstance::~CGraphicImageInstance() +{ + Destroy(); +} diff --git a/tests/port/port_grp_resource_test.cpp b/tests/port/port_grp_resource_test.cpp index 14337cf4..bae2f0d9 100644 --- a/tests/port/port_grp_resource_test.cpp +++ b/tests/port/port_grp_resource_test.cpp @@ -2,6 +2,7 @@ // and its low-texture-memory mip bias, memory textures), CGraphicImage, CGraphicVertexBuffer/IndexBuffer. #include "EterLib/StdAfx.h" #include "EterLib/GrpImage.h" +#include "EterLib/GrpExpandedImageInstance.h" #include "EterLib/GrpImageTexture.h" #include "EterLib/GrpIndexBuffer.h" #include "EterLib/GrpVertexBuffer.h" @@ -52,7 +53,14 @@ std::vector MakeDDS(DWORD width, DWORD height, DWORD mips) struct ImageAccess : CGraphicImage { ImageAccess(const char* name) : CGraphicImage(name) {} - bool Load(int size, const void* data) { return OnLoad(size, data); } + // CResource::Load with the pack bytes: OnLoad, then the state that stops a reference from loading again. + bool Load(int size, const void* data) + { + if (!OnLoad(size, data)) + return false; + me_state = STATE_EXIST; + return true; + } }; std::vector MakePNGHeader(DWORD width, DWORD height) @@ -121,6 +129,51 @@ int main() check(image.IsEmpty() && image.GetRectReference().right == 0, "CGraphicImage Clear"); } + // CGraphicImageInstance draws the image rect as one quad at its position (40250's -0.5 pixel-centre + // offset, undone by +0.5 in the command); CGraphicExpandedImageInstance adds scale, the rendering + // rect and its blend mode. + { + std::vector png = MakePNGHeader(40, 20); + ImageAccess* image = new ImageAccess("f.png"); + check(image->Load(int(png.size()), png.data()), "instance image load"); + image->AddReference(); // held by the test, so releasing the instances never self-destructs it + + CGraphicImageInstance instance; + instance.SetImagePointer(image); + instance.SetPosition(10, 5); + instance.SetDiffuseColor(1, 0, 0, 0.5f); + UIRenderBeginFrame(); + instance.Render(); + const std::vector& commands = UIRenderCommands(); + check(commands.size() == 1, "image instance emits one quad"); + if (commands.size() == 1) + { + const UIRenderCommand& c = commands[0]; + check(c.text == "f.png" && c.qx[0] == 10 && c.qy[0] == 5 && c.qx[3] == 50 && c.qy[3] == 25, "image instance quad"); + check(c.su == 0 && c.eu == 1 && c.argb == 0x80FF0000u && c.blend == 0, "image instance uv/colour"); + } + + CGraphicExpandedImageInstance expanded; + expanded.SetImagePointer(image); + check(expanded.IsType(CGraphicExpandedImageInstance::Type()) && expanded.IsType(CGraphicImageInstance::Type()), "expanded IsType"); + expanded.SetPosition(0, 0); + expanded.SetScale(2, 1); + expanded.SetRenderingRect(0, 0, -0.5f, 0); + expanded.SetRenderingMode(CGraphicExpandedImageInstance::RENDERING_MODE_MODULATE); + UIRenderBeginFrame(); + expanded.Render(); + check(commands.size() == 1, "expanded instance emits one quad"); + if (commands.size() == 1) + { + const UIRenderCommand& c = commands[0]; + // Width 40 x 2 plus the right edge pulled in by half the image (-20). + check(c.qx[1] == 60 && c.qy[2] == 20 && c.eu == 0.5f, "expanded quad and rendering rect"); + check(c.blend == CGraphicExpandedImageInstance::RENDERING_MODE_MODULATE, "expanded blend mode"); + } + instance.Destroy(); + expanded.Destroy(); + } + // A memory texture (font page): Lock hands out A4R4G4B4 words, Unlock republishes them as ARGB32. { CGraphicImageTexture texture;