diff --git a/plugins/quantum_computing/src/CMakeLists.txt b/plugins/quantum_computing/src/CMakeLists.txt index fcc16cf..99014bd 100644 --- a/plugins/quantum_computing/src/CMakeLists.txt +++ b/plugins/quantum_computing/src/CMakeLists.txt @@ -27,4 +27,5 @@ target_include_directories(${PLUGIN_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/visuals ) target_link_libraries(${PLUGIN_NAME} PUBLIC core visual_elements ntk_math) -set_property(TARGET ${PLUGIN_NAME} PROPERTY FOLDER plugins) \ No newline at end of file +set_property(TARGET ${PLUGIN_NAME} PROPERTY FOLDER plugins) +set_target_properties( ${PLUGIN_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) \ No newline at end of file diff --git a/plugins/quantum_computing/test/TestBlochSphereNode.cpp b/plugins/quantum_computing/test/TestBlochSphereNode.cpp index 57ef710..5e461a4 100644 --- a/plugins/quantum_computing/test/TestBlochSphereNode.cpp +++ b/plugins/quantum_computing/test/TestBlochSphereNode.cpp @@ -13,7 +13,7 @@ TEST_CASE(TestBlochSphereNode, "quantum_computing") { - auto node = std::make_unique(); + auto node = std::make_unique(DiscretePoint(0.5, 0.5)); Qubit state({ 1.0, 0.0 }, { 0.0, 0.0 }); diff --git a/src/fonts/CMakeLists.txt b/src/fonts/CMakeLists.txt index 2a2c104..a42bacd 100644 --- a/src/fonts/CMakeLists.txt +++ b/src/fonts/CMakeLists.txt @@ -8,6 +8,12 @@ list(APPEND fonts_LIB_INCLUDES TrueTypeFont.cpp FontsManager.cpp FontGlyph.cpp + FontReader.h + TrueTypeFont.h + FontsManager.h + FontGlyph.h + IFont.h + IFontEngine.h ) if(UNIX) @@ -24,15 +30,26 @@ if(UNIX) else() message(STATUS "Freetype not found - skipping support") endif() +else() + list(APPEND fonts_LIB_INCLUDES + directx/DirectWriteFontEngine.h + directx/DirectWriteHelpers.h + directx/DirectWriteFontEngine.cpp + directx/DirectWriteHelpers.cpp + ) + list(APPEND fonts_LIB_DEPENDS + Dwrite.lib D2d1.lib uuid.lib + ) endif() add_library(${MODULE_NAME} SHARED ${fonts_LIB_INCLUDES}) target_include_directories(${MODULE_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/directx ) -target_link_libraries(${MODULE_NAME} PUBLIC core image ${fonts_LIB_DEPENDS}) +target_link_libraries(${MODULE_NAME} PUBLIC core geometry image ${fonts_LIB_DEPENDS}) target_compile_definitions(${MODULE_NAME} PRIVATE ${DEFINES}) set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src) diff --git a/src/fonts/FontGlyph.cpp b/src/fonts/FontGlyph.cpp index f5a1432..f1e9907 100644 --- a/src/fonts/FontGlyph.cpp +++ b/src/fonts/FontGlyph.cpp @@ -1,5 +1,43 @@ #include "FontGlyph.h" +void GlyphRunOutlines::addToFeature(const Point& point) +{ + mFeatures[mFeatures.size() - 1].mPoints.push_back(point); +} + +void GlyphRunOutlines::startFeature(const Point& point, bool isFilled) +{ + GlyphRunOutline feature; + feature.mFilled = isFilled; + feature.mPoints.push_back(point); + mFeatures.push_back(feature); +} + +const std::vector GlyphRunOutlines::getFeatures() const +{ + return mFeatures; +} + +std::string GlyphRunOutlines::toPostScriptPath() +{ + std::string path; + for (const auto& feature : mFeatures) + { + if (feature.mPoints.empty()) + { + continue; + } + auto last_point = feature.mPoints[0]; + path += "M" + std::to_string(last_point.getX()) + " " + std::to_string(last_point.getY()) + " "; + for (std::size_t idx = 1; idx < feature.mPoints.size(); idx++) + { + path += "L" + std::to_string(feature.mPoints[idx].getX()) + " " + std::to_string(feature.mPoints[idx].getY()) + " "; + } + path += "z "; + } + return path; +} + FontGlyph::FontGlyph(unsigned width, unsigned height, int bearingX, int bearingY, int advanceX, std::unique_ptr > image) : mImage(std::move(image)), diff --git a/src/fonts/FontGlyph.h b/src/fonts/FontGlyph.h index ac357a4..170758b 100644 --- a/src/fonts/FontGlyph.h +++ b/src/fonts/FontGlyph.h @@ -1,9 +1,31 @@ #pragma once -#include - +#include "Point.h" #include "Image.h" +#include +#include +#include + +struct GlyphRunOutline +{ + bool mFilled{ true }; + std::vector mPoints; +}; + +class GlyphRunOutlines +{ +public: + void addToFeature(const Point& point); + void startFeature(const Point& point, bool isFilled); + + const std::vector getFeatures() const; + + std::string toPostScriptPath(); +private: + std::vector mFeatures; +}; + class FontGlyph { diff --git a/src/fonts/directx/DirectWriteFontEngine.cpp b/src/fonts/directx/DirectWriteFontEngine.cpp new file mode 100644 index 0000000..fe55846 --- /dev/null +++ b/src/fonts/directx/DirectWriteFontEngine.cpp @@ -0,0 +1,54 @@ +#include "DirectWriteFontEngine.h" + +#include "FontGlyph.h" +#include "StringUtils.h" + +#include "DirectWriteHelpers.h" + +#include + +void DirectWriteFontEngine::initialize() +{ + mIsValid = SUCCEEDED(::DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &mDWriteFactory)); + + loadFontFaceFromName("Verdana", 16); +} + +void DirectWriteFontEngine::initializeOffScreenRenderer() +{ + if (mOffScreenRenderer) + { + return; + } + auto pInterface = OffScreenTextRenderer::Create(); + pInterface->QueryInterface(IID_IOffScreenTextRenderer, &mOffScreenRenderer); +} + +void DirectWriteFontEngine::loadFontFaceFromName(const std::string& fontName, int penSize) +{ + mDWriteFactory->CreateTextFormat(StringUtils::convert(fontName).c_str(), nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, + penSize, L"en-us", &mTextFormat); +} + +std::unique_ptr DirectWriteFontEngine::loadGlyph(uint32_t charCode) +{ + return nullptr; +} + +std::unique_ptr DirectWriteFontEngine::getGlyphRunOutlines(const std::vector& charCodes) +{ + initializeOffScreenRenderer(); + + std::wstring text; + for (auto code : charCodes) + { + text.push_back(code); + } + + auto hr = mDWriteFactory->CreateTextLayout(text.c_str(), text.size(), mTextFormat.Get(), 50.0, 50.0, &mTextLayout); + + mTextLayout->Draw(nullptr, mOffScreenRenderer.Get(), 0.0, 0.0); + + return mOffScreenRenderer->getGlypyRunOutline(); +} + diff --git a/src/fonts/directx/DirectWriteFontEngine.h b/src/fonts/directx/DirectWriteFontEngine.h new file mode 100644 index 0000000..cd9e32e --- /dev/null +++ b/src/fonts/directx/DirectWriteFontEngine.h @@ -0,0 +1,38 @@ +#pragma once + +#include "IFontEngine.h" +#include "FontGlyph.h" + +#include + +#include + +class GlyphOutlineGeometrySink; +class OffScreenTextRenderer; + +struct IDWriteFactory; +struct IDWriteTextFormat; +struct IDWriteTextLayout; + +class DirectWriteFontEngine : public IFontEngine +{ +public: + void initialize() override; + + void loadFontFace(const std::filesystem::path& fontFile, int penSize = 16) override {}; + + void loadFontFaceFromName(const std::string& fontName, int penSize = 16); + + std::unique_ptr loadGlyph(uint32_t charCode) override; + + std::unique_ptr getGlyphRunOutlines(const std::vector& charCodes); + +private: + void initializeOffScreenRenderer(); + + bool mIsValid{ false }; + Microsoft::WRL::ComPtr mDWriteFactory; + Microsoft::WRL::ComPtr mTextFormat; + Microsoft::WRL::ComPtr mTextLayout; + Microsoft::WRL::ComPtr mOffScreenRenderer; +}; \ No newline at end of file diff --git a/src/fonts/directx/DirectWriteHelpers.cpp b/src/fonts/directx/DirectWriteHelpers.cpp new file mode 100644 index 0000000..d2db26a --- /dev/null +++ b/src/fonts/directx/DirectWriteHelpers.cpp @@ -0,0 +1,235 @@ +#include "DirectWriteHelpers.h" + +#include "FileLogger.h" + +#include + +GlyphOutlineGeometrySink::GlyphOutlineGeometrySink() + : mGlyphRunOutline(std::make_unique()) +{ + +} + +IUnknown* GlyphOutlineGeometrySink::Create() +{ + return static_cast(new GlyphOutlineGeometrySink); +} + +HRESULT __stdcall GlyphOutlineGeometrySink::QueryInterface(const IID& iid, void** ppv) +{ + if (IsEqualIID(iid, __uuidof(IUnknown))) + { + *ppv = static_cast(this); + } + else if (IsEqualIID(iid, IID_ID2D1SimplifiedGeometrySink)) + { + *ppv = static_cast(this); + } + else if (IsEqualIID(iid, IID_IGlyphOutlineGeometrySink)) + { + *ppv = static_cast(this); + } + else + { + *ppv = nullptr; + return E_NOINTERFACE; + } + reinterpret_cast(*ppv)->AddRef(); + return S_OK; +} + +ULONG __stdcall GlyphOutlineGeometrySink::AddRef() +{ + return ::InterlockedIncrement(&mRefCount); +} + +ULONG __stdcall GlyphOutlineGeometrySink::Release() +{ + return 0; + if (::InterlockedDecrement(&mRefCount) == 0) + { + delete this; + return 0; + } + return mRefCount; +} + +void __stdcall GlyphOutlineGeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) +{ + MLOG_INFO("SetFillMode: " << bool(fillMode == D2D1_FILL_MODE_ALTERNATE)); +} + +void __stdcall GlyphOutlineGeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags) +{ + MLOG_INFO("SetSegmentFlags"); + if (vertexFlags == D2D1_PATH_SEGMENT_NONE) + { + MLOG_INFO("D2D1_PATH_SEGMENT_NONE"); + } + else if (vertexFlags == D2D1_PATH_SEGMENT_FORCE_UNSTROKED) + { + MLOG_INFO("D2D1_PATH_SEGMENT_FORCE_UNSTROKED"); + } + else if (vertexFlags == D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN) + { + MLOG_INFO("D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN"); + } + else if (vertexFlags == D2D1_PATH_SEGMENT_FORCE_DWORD) + { + MLOG_INFO("D2D1_PATH_SEGMENT_FORCE_DWORD"); + } + else + { + MLOG_INFO("UKNOWN"); + } +} + +void __stdcall GlyphOutlineGeometrySink::BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) +{ + MLOG_INFO("BeginFigure, is filled: " << bool(figureBegin == D2D1_FIGURE_BEGIN_FILLED)); + mGlyphRunOutline->startFeature(Point(startPoint.x, startPoint.y), figureBegin == D2D1_FIGURE_BEGIN_FILLED); +} + +void __stdcall GlyphOutlineGeometrySink::AddLines(_In_reads_(pointsCount) CONST D2D1_POINT_2F* points, UINT32 pointsCount) +{ + MLOG_INFO("AddLines"); + for (UINT32 idx = 0; idx < pointsCount; idx++) + { + auto point = points[idx]; + MLOG_INFO("Adding point: " << point.x << " " << point.y); + mGlyphRunOutline->addToFeature(Point(point.x, point.y)); + } +} + +void __stdcall GlyphOutlineGeometrySink::AddBeziers(_In_reads_(beziersCount) CONST D2D1_BEZIER_SEGMENT* beziers, UINT32 beziersCount) +{ + MLOG_INFO("AddBeziers"); +} + +void __stdcall GlyphOutlineGeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) +{ + MLOG_INFO("EndFigure"); +} + +HRESULT __stdcall GlyphOutlineGeometrySink::Close() +{ + return S_OK; +} + +std::unique_ptr GlyphOutlineGeometrySink::getGlypyRunOutline() +{ + return std::move(mGlyphRunOutline); +} + +IUnknown* OffScreenTextRenderer::Create() +{ + return static_cast(new OffScreenTextRenderer); +} + +HRESULT __stdcall OffScreenTextRenderer::QueryInterface(const IID& iid, void** ppv) +{ + if (IsEqualIID(iid, __uuidof(IUnknown))) + { + *ppv = static_cast(this); + } + else if (IsEqualIID(iid, __uuidof(IDWritePixelSnapping))) + { + *ppv = static_cast(this); + } + else if (IsEqualIID(iid, __uuidof(IDWriteTextRenderer))) + { + *ppv = static_cast(this); + } + else if (IsEqualIID(iid, IID_IOffScreenTextRenderer)) + { + *ppv = static_cast(this); + } + else + { + *ppv = nullptr; + return E_NOINTERFACE; + } + reinterpret_cast(*ppv)->AddRef(); + return S_OK; +} + +ULONG __stdcall OffScreenTextRenderer::AddRef() +{ + return ::InterlockedIncrement(&mRefCount); +} + +ULONG __stdcall OffScreenTextRenderer::Release() +{ + return 0; + if (::InterlockedDecrement(&mRefCount) == 0) + { + delete this; + return 0; + } + return mRefCount; +} + +HRESULT __stdcall OffScreenTextRenderer::DrawGlyphRun(_In_opt_ void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE measuringMode, + _In_ DWRITE_GLYPH_RUN const* glyphRun, _In_ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, _In_opt_ IUnknown* clientDrawingEffect) +{ + auto pInterface = GlyphOutlineGeometrySink::Create(); + Microsoft::WRL::ComPtr sink; + pInterface->QueryInterface(IID_IGlyphOutlineGeometrySink, &sink); + + auto hr = glyphRun->fontFace->GetGlyphRunOutline( + glyphRun->fontEmSize, + glyphRun->glyphIndices, + glyphRun->glyphAdvances, + glyphRun->glyphOffsets, + glyphRun->glyphCount, + glyphRun->isSideways, + glyphRun->bidiLevel % 2, + sink.Get() + ); + sink->Close(); + + mGlyphRunOutline = sink->getGlypyRunOutline(); + + return S_OK; +} + +HRESULT __stdcall OffScreenTextRenderer::DrawUnderline(_In_opt_ void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, _In_ DWRITE_UNDERLINE const* underline, + _In_opt_ IUnknown* clientDrawingEffect) +{ + return S_OK; +} + +HRESULT __stdcall OffScreenTextRenderer::DrawStrikethrough(_In_opt_ void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, _In_ DWRITE_STRIKETHROUGH const* strikethrough, + _In_opt_ IUnknown* clientDrawingEffect) +{ + return S_OK; +} + +HRESULT __stdcall OffScreenTextRenderer::DrawInlineObject(_In_opt_ void* clientDrawingContext, FLOAT originX, FLOAT originY, _In_ IDWriteInlineObject* inlineObject, + BOOL isSideways, BOOL isRightToLeft, _In_opt_ IUnknown* clientDrawingEffect) +{ + return S_OK; +} + +HRESULT __stdcall OffScreenTextRenderer::IsPixelSnappingDisabled(_In_opt_ void* clientDrawingContext, _Out_ BOOL* isDisabled) +{ + *isDisabled = FALSE; + return S_OK; +} + +HRESULT __stdcall OffScreenTextRenderer::GetCurrentTransform(_In_opt_ void* clientDrawingContext, _Out_ DWRITE_MATRIX* transform) +{ + *transform = DWRITE_MATRIX(1.0, 0.0, 0.0, 1.0, 0.0, 0.0); + return S_OK; +} + +HRESULT __stdcall OffScreenTextRenderer::GetPixelsPerDip(_In_opt_ void* clientDrawingContext, _Out_ FLOAT* pixelsPerDip) +{ + *pixelsPerDip = 1.0; + return S_OK; +} + +std::unique_ptr OffScreenTextRenderer::getGlypyRunOutline() +{ + return std::move(mGlyphRunOutline); +} \ No newline at end of file diff --git a/src/fonts/directx/DirectWriteHelpers.h b/src/fonts/directx/DirectWriteHelpers.h new file mode 100644 index 0000000..966f523 --- /dev/null +++ b/src/fonts/directx/DirectWriteHelpers.h @@ -0,0 +1,90 @@ +#pragma once + +#include "FontGlyph.h" + +#include +#include + +#include + +static const IID IID_IGlyphOutlineGeometrySink = { 0xaaf6ab8d, 0xd6cf, 0x4a3b, { 0xa6, 0x7a, 0x12, 0xf1, 0x42, 0xe0, 0x6b, 0xb9 } }; +class IGlyphOutlineGeometrySink : public IDWriteGeometrySink +{ +public: + virtual std::unique_ptr getGlypyRunOutline() = 0; +}; + +class GlyphOutlineGeometrySink :public IGlyphOutlineGeometrySink +{ +public: + GlyphOutlineGeometrySink(); + + // IUnknown + virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv); + virtual ULONG __stdcall AddRef(); + virtual ULONG __stdcall Release(); + + static IUnknown* Create(); + + // IDWriteGeometrySink aka ID2D1SimplifiedGeometrySink + STDMETHOD_(void, SetFillMode)(D2D1_FILL_MODE fillMode); + + STDMETHOD_(void, SetSegmentFlags)(D2D1_PATH_SEGMENT vertexFlags); + + STDMETHOD_(void, BeginFigure)(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin); + + STDMETHOD_(void, AddLines)(_In_reads_(pointsCount) CONST D2D1_POINT_2F* points, UINT32 pointsCount); + + STDMETHOD_(void, AddBeziers)(_In_reads_(beziersCount) CONST D2D1_BEZIER_SEGMENT* beziers, UINT32 beziersCount); + + STDMETHOD_(void, EndFigure)(D2D1_FIGURE_END figureEnd); + + STDMETHOD(Close)(); + + // IGlyphOutlineGeometrySink + std::unique_ptr getGlypyRunOutline() override; +private: + std::unique_ptr mGlyphRunOutline; + long mRefCount{ 0 }; +}; + + +static const IID IID_IOffScreenTextRenderer = { 0xa43b0c49, 0x6080, 0x4731, { 0xa8, 0x72, 0x61, 0x50, 0x47, 0x3, 0x78, 0x10 } }; +class IOffScreenTextRenderer : public IDWriteTextRenderer +{ + virtual std::unique_ptr getGlypyRunOutline() = 0; +}; + +class OffScreenTextRenderer :public IOffScreenTextRenderer +{ +public: + // IUnknown + virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv); + virtual ULONG __stdcall AddRef(); + virtual ULONG __stdcall Release(); + + static IUnknown* Create(); + + STDMETHOD(DrawGlyphRun)(_In_opt_ void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE measuringMode, + _In_ DWRITE_GLYPH_RUN const* glyphRun, _In_ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, _In_opt_ IUnknown* clientDrawingEffect); + + STDMETHOD(DrawUnderline)(_In_opt_ void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, _In_ DWRITE_UNDERLINE const* underline, + _In_opt_ IUnknown* clientDrawingEffect); + + STDMETHOD(DrawStrikethrough)(_In_opt_ void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, _In_ DWRITE_STRIKETHROUGH const* strikethrough, + _In_opt_ IUnknown* clientDrawingEffect); + + STDMETHOD(DrawInlineObject)(_In_opt_ void* clientDrawingContext, FLOAT originX, FLOAT originY, _In_ IDWriteInlineObject* inlineObject, + BOOL isSideways, BOOL isRightToLeft, _In_opt_ IUnknown* clientDrawingEffect); + + STDMETHOD(IsPixelSnappingDisabled)(_In_opt_ void* clientDrawingContext, _Out_ BOOL* isDisabled); + + STDMETHOD(GetCurrentTransform)(_In_opt_ void* clientDrawingContext, _Out_ DWRITE_MATRIX* transform); + + STDMETHOD(GetPixelsPerDip)(_In_opt_ void* clientDrawingContext, _Out_ FLOAT* pixelsPerDip); + + std::unique_ptr getGlypyRunOutline() override; +private: + std::unique_ptr mGlyphRunOutline; + long mRefCount{ 0 }; +}; \ No newline at end of file diff --git a/src/web/svg/SvgDocument.cpp b/src/web/svg/SvgDocument.cpp index 96ce451..87b2f84 100644 --- a/src/web/svg/SvgDocument.cpp +++ b/src/web/svg/SvgDocument.cpp @@ -17,7 +17,7 @@ SvgDocument::SvgDocument() setRoot(std::move(root)); } -void SvgDocument::setViewBox(unsigned x, unsigned y, unsigned w, unsigned h) +void SvgDocument::setViewBox(double x, double y, double w, double h) { auto viewbox = std::make_unique("viewBox"); std::stringstream sstr; diff --git a/src/web/svg/SvgDocument.h b/src/web/svg/SvgDocument.h index c2ee0ed..a7fb0d1 100644 --- a/src/web/svg/SvgDocument.h +++ b/src/web/svg/SvgDocument.h @@ -6,5 +6,5 @@ class SvgDocument : public XmlDocument { public: SvgDocument(); - void setViewBox(unsigned x, unsigned y, unsigned w, unsigned h); + void setViewBox(double x, double y, double w, double h); }; diff --git a/src/web/svg/elements/SvgShapeElements.cpp b/src/web/svg/elements/SvgShapeElements.cpp index a3091cd..be3c13f 100644 --- a/src/web/svg/elements/SvgShapeElements.cpp +++ b/src/web/svg/elements/SvgShapeElements.cpp @@ -104,3 +104,23 @@ void SvgPolyline::setPoints(const std::vector& locs) addAttribute(std::move(points)); } + +SvgPath::SvgPath() + : SvgShapeElement("path") +{ + +} + +void SvgPath::setPath(const std::string& mPath) +{ + auto path = std::make_unique("d"); + path->setValue(mPath); + addAttribute(std::move(path)); +} + +void SvgPath::setFillRule(const std::string& fillRule) +{ + auto rule = std::make_unique("fill-rule"); + rule->setValue(fillRule); + addAttribute(std::move(rule)); +} diff --git a/src/web/svg/elements/SvgShapeElements.h b/src/web/svg/elements/SvgShapeElements.h index b77c6fd..d8825aa 100644 --- a/src/web/svg/elements/SvgShapeElements.h +++ b/src/web/svg/elements/SvgShapeElements.h @@ -42,3 +42,12 @@ public: void setPoints(const std::vector& loc); }; + +class SvgPath : public SvgShapeElement +{ +public: + SvgPath(); + + void setPath(const std::string& mPath); + void setFillRule(const std::string& fillRule); +}; diff --git a/test/fonts/CMakeLists.txt b/test/fonts/CMakeLists.txt index 98e5834..5267014 100644 --- a/test/fonts/CMakeLists.txt +++ b/test/fonts/CMakeLists.txt @@ -7,6 +7,10 @@ if(UNIX) fonts/TestFreeTypeFontEngine.cpp ) endif() +else() + set(PLATFORM_UNIT_TEST_FILES + fonts/TestDirectWriteFontEngine.cpp + ) endif() diff --git a/test/fonts/TestDirectWriteFontEngine.cpp b/test/fonts/TestDirectWriteFontEngine.cpp new file mode 100644 index 0000000..73a7436 --- /dev/null +++ b/test/fonts/TestDirectWriteFontEngine.cpp @@ -0,0 +1,36 @@ +#include "TestFramework.h" +#include "TestUtils.h" + +#include "DirectWriteHelpers.h" +#include "DirectWriteFontEngine.h" +#include "FileLogger.h" + +#include "SvgDocument.h" +#include "SvgWriter.h" +#include "SvgShapeElements.h" +#include "File.h" + +TEST_CASE(TestDirectWriteFontEngine, "fonts") +{ + DirectWriteFontEngine font_engine; + font_engine.initialize(); + + auto glyph_run_outlines = font_engine.getGlyphRunOutlines({ 66 }); + auto path = glyph_run_outlines->toPostScriptPath(); + + auto doc = std::make_unique(); + + auto element = std::make_unique(); + element->setPath(path); + element->setFillRule("evenodd"); + + doc->getRoot()->addChild(std::move(element)); + doc->setViewBox(-20.0, -20.0, 40.0, 40.0); + + auto writer = std::make_unique(); + auto doc_string = writer->toString(doc.get()); + + File file(TestUtils::getTestOutputDir(__FILE__) / "out.svg"); + file.writeText(doc_string); + +} \ No newline at end of file