95 lines
3.3 KiB
C++
95 lines
3.3 KiB
C++
#include "NativeRendererInternal.h"
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
|
|
namespace XCEngine::UI::Editor::Host {
|
|
|
|
using namespace NativeRendererInternal;
|
|
|
|
void NativeRenderer::RenderTextCommand(
|
|
ID2D1RenderTarget& renderTarget,
|
|
ID2D1SolidColorBrush& solidBrush,
|
|
const ::XCEngine::UI::UIDrawCommand& command) {
|
|
if (command.text.empty()) {
|
|
return;
|
|
}
|
|
|
|
const float dpiScale = ClampDpiScale(m_dpiScale);
|
|
const float fontSize = ResolveFontSize(command.fontSize);
|
|
const float scaledFontSize = fontSize * dpiScale;
|
|
IDWriteTextFormat* textFormat = GetTextFormat(scaledFontSize);
|
|
if (textFormat == nullptr) {
|
|
return;
|
|
}
|
|
|
|
const std::wstring text = Utf8ToWide(command.text);
|
|
if (text.empty()) {
|
|
return;
|
|
}
|
|
|
|
const D2D1_SIZE_F targetSize = renderTarget.GetSize();
|
|
const float originX = SnapToPixel(command.position.x, dpiScale);
|
|
const float originY = SnapToPixel(command.position.y, dpiScale);
|
|
const float lineHeight = std::ceil(scaledFontSize * 1.6f);
|
|
const D2D1_RECT_F layoutRect = D2D1::RectF(
|
|
originX,
|
|
originY,
|
|
targetSize.width,
|
|
originY + lineHeight);
|
|
renderTarget.DrawTextW(
|
|
text.c_str(),
|
|
static_cast<UINT32>(text.size()),
|
|
textFormat,
|
|
layoutRect,
|
|
&solidBrush,
|
|
D2D1_DRAW_TEXT_OPTIONS_CLIP,
|
|
DWRITE_MEASURING_MODE_GDI_NATURAL);
|
|
}
|
|
|
|
void NativeRenderer::RenderImageCommand(
|
|
ID2D1RenderTarget& renderTarget,
|
|
ID2D1SolidColorBrush& solidBrush,
|
|
const ::XCEngine::UI::UIDrawCommand& command) {
|
|
if (!command.texture.IsValid()) {
|
|
return;
|
|
}
|
|
|
|
const float dpiScale = ClampDpiScale(m_dpiScale);
|
|
Microsoft::WRL::ComPtr<ID2D1Bitmap> bitmap;
|
|
if (command.texture.kind == ::XCEngine::UI::UITextureHandleKind::ShaderResourceView) {
|
|
if (!ResolveInteropBitmap(command.texture, bitmap) || !bitmap) {
|
|
const D2D1_RECT_F rect = ToD2DRect(command.rect, dpiScale);
|
|
renderTarget.DrawRectangle(rect, &solidBrush, 1.0f);
|
|
return;
|
|
}
|
|
} else {
|
|
auto* texture = reinterpret_cast<NativeTextureResource*>(command.texture.nativeHandle);
|
|
if (texture == nullptr || m_liveTextures.find(texture) == m_liveTextures.end()) {
|
|
const D2D1_RECT_F rect = ToD2DRect(command.rect, dpiScale);
|
|
renderTarget.DrawRectangle(rect, &solidBrush, 1.0f);
|
|
return;
|
|
}
|
|
|
|
if (!ResolveTextureBitmap(renderTarget, *texture, bitmap) || !bitmap) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
const D2D1_RECT_F rect = ToD2DRect(command.rect, dpiScale);
|
|
const float sourceWidth = static_cast<float>(command.texture.width);
|
|
const float sourceHeight = static_cast<float>(command.texture.height);
|
|
const float sourceLeft = sourceWidth * std::clamp(command.uvMin.x, 0.0f, 1.0f);
|
|
const float sourceTop = sourceHeight * std::clamp(command.uvMin.y, 0.0f, 1.0f);
|
|
const float sourceRight = sourceWidth * std::clamp(command.uvMax.x, 0.0f, 1.0f);
|
|
const float sourceBottom = sourceHeight * std::clamp(command.uvMax.y, 0.0f, 1.0f);
|
|
renderTarget.DrawBitmap(
|
|
bitmap.Get(),
|
|
rect,
|
|
std::clamp(command.color.a, 0.0f, 1.0f),
|
|
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
|
|
D2D1::RectF(sourceLeft, sourceTop, sourceRight, sourceBottom));
|
|
}
|
|
|
|
} // namespace XCEngine::UI::Editor::Host
|