diff --git a/src/graphics/directx/DirectX2dInterface.cpp b/src/graphics/directx/DirectX2dInterface.cpp index 4c359f4..44d6fe3 100644 --- a/src/graphics/directx/DirectX2dInterface.cpp +++ b/src/graphics/directx/DirectX2dInterface.cpp @@ -35,17 +35,26 @@ ID2D1DeviceContext2* DirectX2dInterface::getContext() const return mDeviceContext.Get(); } -void DirectX2dInterface::initializeStandalone(IWICBitmap* bitmap, bool useSoftware) +ID2D1RenderTarget* DirectX2dInterface::getRenderTarget() const +{ + if (mRenderTarget) + { + return mRenderTarget.Get(); + } + else + { + return mDeviceContext.Get(); + } +} + +void DirectX2dInterface::initialize(IWICBitmap* bitmap, bool useSoftware) { D2D1_FACTORY_OPTIONS d2dFactoryOptions = {}; D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory3), &d2dFactoryOptions, &mFactory); auto hr = mFactory->CreateWicBitmapRenderTarget(bitmap, D2D1::RenderTargetProperties(), &mRenderTarget); -} -ID2D1RenderTarget* DirectX2dInterface::getRenderTarget() const -{ - return mRenderTarget.Get(); + initializeDirectWrite(); } bool DirectX2dInterface::initialize(IDXGIDevice* device) diff --git a/src/graphics/directx/DirectX2dInterface.h b/src/graphics/directx/DirectX2dInterface.h index 84f0e22..50d260a 100644 --- a/src/graphics/directx/DirectX2dInterface.h +++ b/src/graphics/directx/DirectX2dInterface.h @@ -25,7 +25,7 @@ public: ID2D1RenderTarget* getRenderTarget() const; bool initialize(IDXGIDevice* device); - void initializeStandalone(IWICBitmap* bitmap, bool useSoftware = true); + void initialize(IWICBitmap* bitmap, bool useSoftware = true); bool isValid() const; diff --git a/src/graphics/directx/DirectX2dPainter.cpp b/src/graphics/directx/DirectX2dPainter.cpp index 1db0fb0..7a170dc 100644 --- a/src/graphics/directx/DirectX2dPainter.cpp +++ b/src/graphics/directx/DirectX2dPainter.cpp @@ -17,7 +17,8 @@ void DirectX2dPainter::finishDrawing() D2D1::ColorF DirectX2dPainter::toD2dColor(const Color& color) { - return D2D1::ColorF(color.getR() / 255.0, color.getG() / 255.0, color.getB() / 255.0, static_cast(color.getAlpha())); + return D2D1::ColorF(static_cast(color.getR() / 255.0), static_cast(color.getG() / 255.0), + static_cast(color.getB() / 255.0), static_cast(color.getAlpha())); } void DirectX2dPainter::clearBackground(const Color& color) diff --git a/src/graphics/directx/DirectXPainter.cpp b/src/graphics/directx/DirectXPainter.cpp index 8225fc4..b59fbd3 100644 --- a/src/graphics/directx/DirectXPainter.cpp +++ b/src/graphics/directx/DirectXPainter.cpp @@ -28,8 +28,6 @@ #include -#include - DirectXPainter::DirectXPainter(DrawingContext* context) : AbstractPainter(context), mMeshPainter(std::make_unique()), @@ -44,11 +42,6 @@ DirectXMeshPainter* DirectXPainter::getMeshPainter() const return mMeshPainter.get(); } -DirectXTextPainter* DirectXPainter::getTextPainter() const -{ - return mTextPainter.get(); -} - void DirectXPainter::setDxInterface(DirectXInterface* dxInterface) { mRawDxInterface = dxInterface; @@ -72,11 +65,6 @@ void DirectXPainter::initializeMesh() mMeshPainter->initializeD3d(); } -void DirectXPainter::initializeText() -{ - mTextPainter->initialize(); -} - void DirectXPainter::updateMesh() { mMeshPainter->updateBuffers(mDrawingContext); @@ -89,7 +77,7 @@ void DirectXPainter::initializeDxInterface() auto backing_image = mDrawingContext->getSurface()->getImage(); auto wic_bitmap = dynamic_cast(backing_image->getPlatformImage())->getBitmap(); - mDxInterface->getD2dInterface()->initializeStandalone(wic_bitmap); + mDxInterface->getD2dInterface()->initialize(wic_bitmap); resetPainters(); } @@ -115,7 +103,12 @@ void DirectXPainter::paint() for (const auto item : scene->getItems()) { - if (item->getType() == SceneItem::Type::MODEL && item->isVisible()) + if (!item->isVisible()) + { + continue; + } + + if (item->getType() == SceneItem::Type::MODEL) { auto model = dynamic_cast(item); if (model->getGeometry()) @@ -123,6 +116,12 @@ void DirectXPainter::paint() m2dPainter->paint(model); } } + else if (item->getType() == SceneItem::Type::TEXT) + { + auto text = dynamic_cast(item); + mTextPainter->paint(text, mDrawingContext); + } + } m2dPainter->finishDrawing(); @@ -139,19 +138,6 @@ void DirectXPainter::paintMesh(ID3D12GraphicsCommandList* commandList) mMeshPainter->updateCommandList(commandList); } -void DirectXPainter::paintText() -{ - auto scene = mDrawingContext->getSurface()->getScene(); - for (const auto item : scene->getItems()) - { - if (item->getType() == SceneItem::Type::TEXT && item->isVisible()) - { - auto text = dynamic_cast(item); - mTextPainter->paint(text, mDrawingContext); - } - } -} - bool DirectXPainter::supportsGeometryPrimitives() const { return true; diff --git a/src/graphics/directx/DirectXPainter.h b/src/graphics/directx/DirectXPainter.h index 5891045..750a30e 100644 --- a/src/graphics/directx/DirectXPainter.h +++ b/src/graphics/directx/DirectXPainter.h @@ -21,17 +21,11 @@ public: DirectXPainter(DrawingContext* context); DirectXMeshPainter* getMeshPainter() const; - DirectXTextPainter* getTextPainter() const; - void initializeMesh(); - void initializeText(); void paint() override; - void paintBackground(const D3D12_CPU_DESCRIPTOR_HANDLE& rtvHandle, ID3D12GraphicsCommandList* commandList); - void paintMesh(ID3D12GraphicsCommandList* commandList); - void paintText(); void setDxInterface(DirectXInterface* dxInterface); diff --git a/src/graphics/directx/DirectXTextPainter.cpp b/src/graphics/directx/DirectXTextPainter.cpp index 02b2b42..100815a 100644 --- a/src/graphics/directx/DirectXTextPainter.cpp +++ b/src/graphics/directx/DirectXTextPainter.cpp @@ -29,27 +29,18 @@ DirectXTextPainter::DirectXTextPainter() void DirectXTextPainter::setD2dInterface(DirectX2dInterface* d2dIterface) { mD2dInterface = d2dIterface; + mD2dInterface->getRenderTarget()->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &mTextBrush); } -void DirectXTextPainter::initialize() -{ - initializeBrush(); -} - -void DirectXTextPainter::initializeBrush() -{ - mD2dInterface->getContext()->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &mTextBrush); -} - -void DirectXTextPainter::updateTextFormat(float fontSize) +void DirectXTextPainter::updateTextFormat(const FontItem& font) { mD2dInterface->getDirectWriteFactory()->CreateTextFormat( - L"Verdana", - NULL, + StringUtils::convert(font.getFaceName()).c_str(), + nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, - fontSize, + static_cast(font.getSize()), L"en-us", &mTextFormat ); @@ -62,14 +53,11 @@ void DirectXTextPainter::paint(SceneText* text, DrawingContext* context) const auto location = text->getTransform().getLocation(); D2D1_RECT_F textRect = D2D1::RectF(static_cast(location.getX()), static_cast(location.getY()), static_cast(location.getX() + 200), static_cast(location.getY() + 100)); - updateTextFormat(static_cast(text->getTextData().mFont.getSize())); + updateTextFormat(text->getTextData().mFont); auto content = StringUtils::convert(text->getTextData().mContent); - mD2dInterface->getContext()->BeginDraw(); - mD2dInterface->getContext()->SetTransform(D2D1::Matrix3x2F::Identity()); - mD2dInterface->getContext()->DrawText(content.c_str(), static_cast(content.size()), mTextFormat.Get(), &textRect, mTextBrush.Get()); - mD2dInterface->getContext()->EndDraw(); + mD2dInterface->getRenderTarget()->DrawText(content.c_str(), static_cast(content.size()), mTextFormat.Get(), &textRect, mTextBrush.Get()); } diff --git a/src/graphics/directx/DirectXTextPainter.h b/src/graphics/directx/DirectXTextPainter.h index f29c08c..ffeb031 100644 --- a/src/graphics/directx/DirectXTextPainter.h +++ b/src/graphics/directx/DirectXTextPainter.h @@ -1,5 +1,7 @@ #pragma once +#include "FontItem.h" + #include #include #include @@ -25,15 +27,12 @@ class DirectXTextPainter public: DirectXTextPainter(); - void initialize(); - void paint(SceneText* text, DrawingContext* context); void setD2dInterface(DirectX2dInterface* d2dIterface); private: - void initializeBrush(); - void updateTextFormat(float fontSize); + void updateTextFormat(const FontItem& font); DirectX2dInterface* mD2dInterface{ nullptr }; Microsoft::WRL::ComPtr mTextBrush; diff --git a/src/publishing/latex/LatexSymbols.cpp b/src/publishing/latex/LatexSymbols.cpp index e69de29..ae86fe3 100644 --- a/src/publishing/latex/LatexSymbols.cpp +++ b/src/publishing/latex/LatexSymbols.cpp @@ -0,0 +1,35 @@ +#include "LatexSymbols.h" + +#include "StringUtils.h" + +std::unordered_map LatexSymbolLookup::mSymbols = { + {"Psi", L"\u03A8"}, + {"alpha", L"\u03B1"}, + {"beta", L"\u03B2"}, + {"gamma", L"\u03B3"}, + {"psi", L"\u03C8"} +}; + +std::optional LatexSymbolLookup::getSymbolUtf8(const std::string& tag) +{ + if (auto entry = getSymbolUtf16(tag); entry) + { + return StringUtils::convert(*entry); + } + else + { + return std::nullopt; + } +} + +std::optional LatexSymbolLookup::getSymbolUtf16(const std::string& tag) +{ + if (auto iter = mSymbols.find(tag); iter != mSymbols.end()) + { + return iter->second; + } + else + { + return std::nullopt; + } +} \ No newline at end of file diff --git a/src/publishing/latex/LatexSymbols.h b/src/publishing/latex/LatexSymbols.h index 993d462..e91b79e 100644 --- a/src/publishing/latex/LatexSymbols.h +++ b/src/publishing/latex/LatexSymbols.h @@ -22,5 +22,10 @@ struct LatexMathSymbol class LatexSymbolLookup { public: - std::unordered_map mTags; + static std::optional getSymbolUtf8(const std::string& tag); + + static std::optional getSymbolUtf16(const std::string& tag); + +private: + static std::unordered_map mSymbols; }; \ No newline at end of file diff --git a/src/visual_elements/nodes/TextNode.cpp b/src/visual_elements/nodes/TextNode.cpp index 402eec2..7f3e660 100644 --- a/src/visual_elements/nodes/TextNode.cpp +++ b/src/visual_elements/nodes/TextNode.cpp @@ -79,6 +79,15 @@ void TextNode::setContent(const std::string& content) } } +void TextNode::setFont(const FontItem& font) +{ + if (mTextData.mFont != font) + { + mTextData.mFont = font; + mContentIsDirty = true; + } +} + SceneItem* TextNode::getSceneItem(std::size_t idx) const { if (idx == 0) diff --git a/src/visual_elements/nodes/TextNode.h b/src/visual_elements/nodes/TextNode.h index 948dedf..ae5941d 100644 --- a/src/visual_elements/nodes/TextNode.h +++ b/src/visual_elements/nodes/TextNode.h @@ -33,6 +33,8 @@ public: void setContent(const std::string& content); + void setFont(const FontItem& font); + void update(SceneInfo* sceneInfo) override; private: diff --git a/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp b/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp index 45bf07f..ac8a8ba 100644 --- a/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp +++ b/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp @@ -39,8 +39,7 @@ void DirectX2dIntegration::render() // Render text directly to the back buffer. mDx2dInterface->getContext()->SetTarget(getD2dRenderTarget()); - auto painter = dynamic_cast(mWindow->getDrawingContent()->getPainter()); - painter->paintText(); + mWindow->getDrawingContent()->getPainter()->paint(); // Release our wrapped render target resource. Releasing // transitions the back buffer resource to the state specified diff --git a/src/windows/ui_interfaces/win32/directx/Win32DxWindowInterface.cpp b/src/windows/ui_interfaces/win32/directx/Win32DxWindowInterface.cpp index bb24848..463b65f 100644 --- a/src/windows/ui_interfaces/win32/directx/Win32DxWindowInterface.cpp +++ b/src/windows/ui_interfaces/win32/directx/Win32DxWindowInterface.cpp @@ -256,9 +256,8 @@ bool Win32DxWindowInterface::loadAssets() { auto painter = dynamic_cast(mWindow->getDrawingContent()->getPainter()); painter->initializeMesh(); - painter->initializeText(); - painter->updateMesh(); + return true; } diff --git a/test/graphics/TestD2dOffScreenRendering.cpp b/test/graphics/TestD2dOffScreenRendering.cpp index 1960e0e..1b3a09b 100644 --- a/test/graphics/TestD2dOffScreenRendering.cpp +++ b/test/graphics/TestD2dOffScreenRendering.cpp @@ -1,38 +1,19 @@ -#include "TestCase.h" -#include "TestCaseRunner.h" - -#include "TestUiApplication.h" - #include "TestFramework.h" #include "TestUtils.h" - -#include "DrawingSurface.h" -#include "DrawingContext.h" -#include "AbstractPainter.h" -#include "Image.h" -#include "PngWriter.h" +#include "TestRenderUtils.h" #include "RectangleNode.h" -#include "Scene.h" + TEST_CASE(TestD2dOffScreenRendering, "graphics") { - auto surface = std::make_unique(); - surface->setSize(800, 800); - - auto drawing_context = std::make_unique(surface.get()); + TestRenderer renderer(800, 800); auto rect = std::make_unique(Point(10, 10), 200.0, 200.0); - auto scene = surface->getScene(); + auto scene = renderer.getScene(); //scene->setBackgroundColor(Color(100, 100, 0)); scene->addNode(rect.get()); - drawing_context->paint(); - - auto image = surface->getImage(); - - PngWriter writer; - writer.setPath(TestUtils::getTestOutputDir(__FILE__) / "out.png"); - writer.write(image); + renderer.write(TestUtils::getTestOutputDir(__FILE__) / "out.png"); }; \ No newline at end of file diff --git a/test/publishing/TestLatexConverter.cpp b/test/publishing/TestLatexConverter.cpp index fd44443..46ffe53 100644 --- a/test/publishing/TestLatexConverter.cpp +++ b/test/publishing/TestLatexConverter.cpp @@ -1,22 +1,29 @@ #include "TestFramework.h" #include "TestUtils.h" +#include "TestRenderUtils.h" #include "StringUtils.h" -#include "File.h" - -#include +#include "FontItem.h" +#include "TextNode.h" +#include "LatexSymbols.h" TEST_CASE(TestLatexConverter, "publishing") { - std::wstring out = L"\u03A8"; - std::wcout << out << std::endl; + FontItem font("Cambria Math", 14); + auto psi = LatexSymbolLookup::getSymbolUtf8("psi"); + auto alpha = LatexSymbolLookup::getSymbolUtf8("alpha"); + auto beta = LatexSymbolLookup::getSymbolUtf8("beta"); - std::string out_c = StringUtils::convert(out); + auto content = *psi + " " + *alpha + " " + *beta + " "; - File file(TestUtils::getTestOutputDir(__FILE__) / "utf8_render.dat"); - file.writeText(out_c); + TestRenderer renderer(800, 800); - //std::cout << out_c << std::endl; + auto text = std::make_unique(content, Point(10, 10)); + text->setFont(font); + + renderer.getScene()->addNode(text.get()); + + renderer.write(TestUtils::getTestOutputDir(__FILE__) / "out.png"); }; \ No newline at end of file diff --git a/test/test_utils/CMakeLists.txt b/test/test_utils/CMakeLists.txt index 6b8d93c..d3eb386 100644 --- a/test/test_utils/CMakeLists.txt +++ b/test/test_utils/CMakeLists.txt @@ -6,6 +6,7 @@ add_library(test_utils STATIC TestCaseRunner.cpp TestUiApplication.h TestUiApplication.cpp + TestRenderUtils.h ) target_include_directories(test_utils PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/test/test_utils/TestRenderUtils.h b/test/test_utils/TestRenderUtils.h new file mode 100644 index 0000000..3750f58 --- /dev/null +++ b/test/test_utils/TestRenderUtils.h @@ -0,0 +1,40 @@ +#pragma once + +#include "DrawingSurface.h" +#include "DrawingContext.h" +#include "AbstractPainter.h" +#include "Image.h" +#include "PngWriter.h" +#include "Scene.h" + +class TestRenderer +{ +public: + TestRenderer(unsigned width = 1000, unsigned height = 1000) + { + mSurface = std::make_unique(); + mSurface->setSize(width, height); + + mDrawingContext = std::make_unique(mSurface.get()); + } + + Scene* getScene() const + { + return mSurface->getScene(); + } + + void write(const Path& path) + { + mDrawingContext->paint(); + + auto image = mSurface->getImage(); + + PngWriter writer; + writer.setPath(path); + writer.write(image); + } + +private: + std::unique_ptr mSurface; + std::unique_ptr mDrawingContext; +}; \ No newline at end of file