From 5c69133a1fe4c172f47266ee60b99191be4f7520 Mon Sep 17 00:00:00 2001 From: Nomango <569629550@qq.com> Date: Wed, 17 Oct 2018 00:49:49 +0800 Subject: [PATCH] refactoring: remove e2dimpl.h --- core/e2dimpl.h | 160 -------- core/e2dmacros.h | 7 - core/e2dmodule.h | 30 +- core/e2dtool.h | 1 - core/e2dutil.h | 51 +++ core/impl/TextRenderer.cpp | 410 --------------------- core/modules/Game.cpp | 4 +- core/modules/Graphics.cpp | 501 +++++++++++++++++++++++++- core/objects/Node.cpp | 6 +- core/objects/Text.cpp | 8 +- project/vs2012/Easy2D.vcxproj | 2 - project/vs2012/Easy2D.vcxproj.filters | 7 - project/vs2013/Easy2D.vcxproj | 2 - project/vs2013/Easy2D.vcxproj.filters | 7 - project/vs2017/Easy2D.vcxproj | 2 - project/vs2017/Easy2D.vcxproj.filters | 7 - 16 files changed, 578 insertions(+), 627 deletions(-) delete mode 100644 core/e2dimpl.h delete mode 100644 core/impl/TextRenderer.cpp diff --git a/core/e2dimpl.h b/core/e2dimpl.h deleted file mode 100644 index 34aecf47..00000000 --- a/core/e2dimpl.h +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) 2016-2018 Easy2D - Nomango -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#ifndef __E2D_IMPL_H__ -#define __E2D_IMPL_H__ - - -#include "e2dutil.h" - -namespace easy2d -{ - - // 文字渲染器 - class TextRenderer - : public IDWriteTextRenderer - { - public: - static HRESULT Create( - TextRenderer** ppTextRenderer, - ID2D1Factory* pD2DFactory, - ID2D1HwndRenderTarget* pRT, - ID2D1SolidColorBrush* pBrush - ); - - STDMETHOD_(void, SetTextStyle)( - CONST D2D1_COLOR_F &fillColor, - BOOL outline, - CONST D2D1_COLOR_F &outline_color, - FLOAT outline_width, - D2D1_LINE_JOIN outlineJoin - ); - - STDMETHOD(DrawGlyphRun)( - __maybenull void* clientDrawingContext, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - DWRITE_MEASURING_MODE measuringMode, - __in DWRITE_GLYPH_RUN const* glyphRun, - __in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, - IUnknown* clientDrawingEffect - ); - - STDMETHOD(DrawUnderline)( - __maybenull void* clientDrawingContext, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - __in DWRITE_UNDERLINE const* underline, - IUnknown* clientDrawingEffect - ); - - STDMETHOD(DrawStrikethrough)( - __maybenull void* clientDrawingContext, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - __in DWRITE_STRIKETHROUGH const* strikethrough, - IUnknown* clientDrawingEffect - ); - - STDMETHOD(DrawInlineObject)( - __maybenull void* clientDrawingContext, - FLOAT originX, - FLOAT originY, - IDWriteInlineObject* inlineObject, - BOOL IsSideways, - BOOL IsRightToLeft, - IUnknown* clientDrawingEffect - ); - - STDMETHOD(IsPixelSnappingDisabled)( - __maybenull void* clientDrawingContext, - __out BOOL* isDisabled - ); - - STDMETHOD(GetCurrentTransform)( - __maybenull void* clientDrawingContext, - __out DWRITE_MATRIX* transform - ); - - STDMETHOD(GetPixelsPerDip)( - __maybenull void* clientDrawingContext, - __out FLOAT* pixelsPerDip - ); - - public: - unsigned long STDMETHODCALLTYPE AddRef(); - unsigned long STDMETHODCALLTYPE Release(); - HRESULT STDMETHODCALLTYPE QueryInterface( - IID const& riid, - void** ppvObject - ); - - private: - TextRenderer(); - - ~TextRenderer(); - - private: - unsigned long cRefCount_; - D2D1_COLOR_F sFillColor_; - D2D1_COLOR_F sOutlineColor_; - FLOAT fOutlineWidth; - BOOL bShowOutline_; - ID2D1Factory* pD2DFactory_; - ID2D1HwndRenderTarget* pRT_; - ID2D1SolidColorBrush* pBrush_; - ID2D1StrokeStyle* pCurrStrokeStyle_; - }; - - - // 运行时异常 - class RuntimeException - : public std::exception - { - public: - RuntimeException() E2D_NOEXCEPT - : exception("unknown runtime exception", 1) - { - } - - explicit RuntimeException( - char const* const message - ) E2D_NOEXCEPT - : exception(message, 1) - { - } - }; - - - inline void ThrowIfFailed(HRESULT hr) - { - if (FAILED(hr)) - { - // 在此处设置断点以捕获系统异常. - static char s_str[64] = {}; - sprintf_s(s_str, "Failure with HRESULT of %08X", static_cast(hr)); - throw RuntimeException(s_str); - } - } - -} // end of easy2d namespace - - -#endif // __E2D_IMPL_H__ diff --git a/core/e2dmacros.h b/core/e2dmacros.h index 2ecb9266..03c124f5 100644 --- a/core/e2dmacros.h +++ b/core/e2dmacros.h @@ -130,13 +130,6 @@ #endif -#ifdef UNICODE -# define OutputDebugStringEx OutputDebugStringExW -#else -# define OutputDebugStringEx OutputDebugStringExA -#endif - - #ifndef E2D_WARNING # if defined( DEBUG ) || defined( _DEBUG ) # define E2D_WARNING(msg) do { ::OutputDebugStringW(L"Warning: " _CRT_WIDE(msg) L"\r\n"); } while(0) diff --git a/core/e2dmodule.h b/core/e2dmodule.h index 2aad77cf..9c9b6454 100644 --- a/core/e2dmodule.h +++ b/core/e2dmodule.h @@ -22,7 +22,6 @@ #define __E2D_MODULE_H__ -#include "e2dimpl.h" #include "e2dobject.h" #include "e2dtransition.h" @@ -50,31 +49,40 @@ namespace easy2d void DrawDebugInfo(); // 获取 ID2D1Factory 对象 - ID2D1Factory * GetFactory() const; + ID2D1Factory* GetFactory() const; // 获取 IWICImagingFactory 对象 - IWICImagingFactory * GetImagingFactory() const; + IWICImagingFactory* GetImagingFactory() const; // 获取 IDWriteFactory 对象 - IDWriteFactory * GetWriteFactory() const; + IDWriteFactory* GetWriteFactory() const; // 获取 ID2D1HwndRenderTarget 对象 - ID2D1HwndRenderTarget * GetRenderTarget() const; + ID2D1HwndRenderTarget* GetRenderTarget() const; // 获取 ID2D1SolidColorBrush 对象 - ID2D1SolidColorBrush * GetSolidBrush() const; + ID2D1SolidColorBrush* GetSolidBrush() const; // 获取文字渲染工具 - TextRenderer * GetTextRender() const; + IDWriteTextRenderer* GetTextRender() const; // 获取 Miter 样式的 ID2D1StrokeStyle - ID2D1StrokeStyle * GetMiterStrokeStyle(); + ID2D1StrokeStyle* GetMiterStrokeStyle(); // 获取 Bevel 样式的 ID2D1StrokeStyle - ID2D1StrokeStyle * GetBevelStrokeStyle(); + ID2D1StrokeStyle* GetBevelStrokeStyle(); // 获取 Round 样式的 ID2D1StrokeStyle - ID2D1StrokeStyle * GetRoundStrokeStyle(); + ID2D1StrokeStyle* GetRoundStrokeStyle(); + + // 设置文字渲染样式 + void SetTextRendererStyle( + const Color& fill_color, + bool has_outline, + const Color& outline_color, + float outline_width, + Stroke outline_stroke + ); // 获取 DPI static float GetDpi(); @@ -87,7 +95,7 @@ namespace easy2d ID2D1StrokeStyle* miter_stroke_style_; ID2D1StrokeStyle* bevel_stroke_style_; ID2D1StrokeStyle* round_stroke_style_; - TextRenderer* text_renderer_; + IDWriteTextRenderer* text_renderer_; IDWriteTextFormat* fps_text_format_; IDWriteTextLayout* fps_text_layout_; ID2D1SolidColorBrush* solid_brush_; diff --git a/core/e2dtool.h b/core/e2dtool.h index 94f42fc6..f922ac12 100644 --- a/core/e2dtool.h +++ b/core/e2dtool.h @@ -23,7 +23,6 @@ #include "e2dutil.h" -#include "e2dimpl.h" namespace easy2d { diff --git a/core/e2dutil.h b/core/e2dutil.h index fa0a2fba..76f8d60e 100644 --- a/core/e2dutil.h +++ b/core/e2dutil.h @@ -678,6 +678,57 @@ namespace easy2d } } + // 运行时异常 + class RuntimeError + { + public: + RuntimeError() E2D_NOEXCEPT + : message_(nullptr) + { + } + + explicit RuntimeError(char const* const message) E2D_NOEXCEPT + : message_(message) + { + } + + RuntimeError(RuntimeError const& other) E2D_NOEXCEPT + : message_(other.message_) + { + } + + RuntimeError& operator=(RuntimeError const& other) noexcept + { + if (this == &other) + { + return *this; + } + + message_ = other.message_; + return *this; + } + + virtual char const* Message() const + { + return message_ ? message_ : "Unknown runtime exception"; + } + + private: + char const* message_; + }; + + + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + // 在此处设置断点以捕获系统异常. + static char s_str[64] = {}; + sprintf_s(s_str, "Failure with HRESULT of %08X", static_cast(hr)); + throw RuntimeError(s_str); + } + } + } // end of easy2d namespace diff --git a/core/impl/TextRenderer.cpp b/core/impl/TextRenderer.cpp deleted file mode 100644 index 8a6f5c2c..00000000 --- a/core/impl/TextRenderer.cpp +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright (c) 2016-2018 Easy2D - Nomango -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#include "..\e2dimpl.h" -#include "..\e2dmodule.h" - -using namespace easy2d; - -TextRenderer::TextRenderer() - : cRefCount_(0) - , pD2DFactory_(nullptr) - , pRT_(nullptr) - , pBrush_(nullptr) - , sFillColor_() - , sOutlineColor_() - , fOutlineWidth(1) - , bShowOutline_(TRUE) - , pCurrStrokeStyle_(nullptr) -{ -} - -TextRenderer::~TextRenderer() -{ - SafeRelease(pD2DFactory_); - SafeRelease(pRT_); - SafeRelease(pBrush_); -} - -HRESULT TextRenderer::Create( - TextRenderer** ppTextRenderer, - ID2D1Factory* pD2DFactory, - ID2D1HwndRenderTarget* pRT, - ID2D1SolidColorBrush* pBrush -) -{ - *ppTextRenderer = new (std::nothrow) TextRenderer(); - if (*ppTextRenderer) - { - pD2DFactory->AddRef(); - pRT->AddRef(); - pBrush->AddRef(); - - (*ppTextRenderer)->pD2DFactory_ = pD2DFactory; - (*ppTextRenderer)->pRT_ = pRT; - (*ppTextRenderer)->pBrush_ = pBrush; - (*ppTextRenderer)->AddRef(); - return S_OK; - } - return E_FAIL; -} - -STDMETHODIMP_(void) TextRenderer::SetTextStyle( - CONST D2D1_COLOR_F &fillColor, - BOOL outline, - CONST D2D1_COLOR_F &outline_color, - FLOAT outline_width, - D2D1_LINE_JOIN outlineJoin -) -{ - sFillColor_ = fillColor; - bShowOutline_ = outline; - sOutlineColor_ = outline_color; - fOutlineWidth = 2 * outline_width; - - switch (outlineJoin) - { - case D2D1_LINE_JOIN_MITER: - pCurrStrokeStyle_ = Device::GetGraphics()->GetMiterStrokeStyle(); - break; - case D2D1_LINE_JOIN_BEVEL: - pCurrStrokeStyle_ = Device::GetGraphics()->GetBevelStrokeStyle(); - break; - case D2D1_LINE_JOIN_ROUND: - pCurrStrokeStyle_ = Device::GetGraphics()->GetRoundStrokeStyle(); - break; - default: - pCurrStrokeStyle_ = nullptr; - break; - } -} - -STDMETHODIMP TextRenderer::DrawGlyphRun( - __maybenull void* clientDrawingContext, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - DWRITE_MEASURING_MODE measuringMode, - __in DWRITE_GLYPH_RUN const* glyphRun, - __in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, - IUnknown* clientDrawingEffect -) -{ - HRESULT hr = S_OK; - - ID2D1PathGeometry* pPathGeometry = nullptr; - hr = pD2DFactory_->CreatePathGeometry( - &pPathGeometry - ); - - ID2D1GeometrySink* pSink = nullptr; - if (SUCCEEDED(hr)) - { - hr = pPathGeometry->Open( - &pSink - ); - } - - if (SUCCEEDED(hr)) - { - hr = glyphRun->fontFace->GetGlyphRunOutline( - glyphRun->fontEmSize, - glyphRun->glyphIndices, - glyphRun->glyphAdvances, - glyphRun->glyphOffsets, - glyphRun->glyphCount, - glyphRun->isSideways, - glyphRun->bidiLevel % 2, - pSink - ); - } - - if (SUCCEEDED(hr)) - { - hr = pSink->Close(); - } - - D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F( - 1.0f, 0.0f, - 0.0f, 1.0f, - baselineOriginX, baselineOriginY - ); - - ID2D1TransformedGeometry* pTransformedGeometry = nullptr; - if (SUCCEEDED(hr)) - { - hr = pD2DFactory_->CreateTransformedGeometry( - pPathGeometry, - &matrix, - &pTransformedGeometry - ); - } - - if (SUCCEEDED(hr) && bShowOutline_) - { - pBrush_->SetColor(sOutlineColor_); - - pRT_->DrawGeometry( - pTransformedGeometry, - pBrush_, - fOutlineWidth, - pCurrStrokeStyle_ - ); - } - - if (SUCCEEDED(hr)) - { - pBrush_->SetColor(sFillColor_); - - pRT_->FillGeometry( - pTransformedGeometry, - pBrush_ - ); - } - - SafeRelease(pPathGeometry); - SafeRelease(pSink); - SafeRelease(pTransformedGeometry); - - return hr; -} - -STDMETHODIMP TextRenderer::DrawUnderline( - __maybenull void* clientDrawingContext, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - __in DWRITE_UNDERLINE const* underline, - IUnknown* clientDrawingEffect -) -{ - HRESULT hr; - - D2D1_RECT_F rect = D2D1::RectF( - 0, - underline->offset, - underline->width, - underline->offset + underline->thickness - ); - - ID2D1RectangleGeometry* pRectangleGeometry = nullptr; - hr = pD2DFactory_->CreateRectangleGeometry( - &rect, - &pRectangleGeometry - ); - - D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F( - 1.0f, 0.0f, - 0.0f, 1.0f, - baselineOriginX, baselineOriginY - ); - - ID2D1TransformedGeometry* pTransformedGeometry = nullptr; - if (SUCCEEDED(hr)) - { - hr = pD2DFactory_->CreateTransformedGeometry( - pRectangleGeometry, - &matrix, - &pTransformedGeometry - ); - } - - if (SUCCEEDED(hr) && bShowOutline_) - { - pBrush_->SetColor(sOutlineColor_); - - pRT_->DrawGeometry( - pTransformedGeometry, - pBrush_, - fOutlineWidth, - pCurrStrokeStyle_ - ); - } - - if (SUCCEEDED(hr)) - { - pBrush_->SetColor(sFillColor_); - - pRT_->FillGeometry( - pTransformedGeometry, - pBrush_ - ); - } - - SafeRelease(pRectangleGeometry); - SafeRelease(pTransformedGeometry); - - return S_OK; -} - -STDMETHODIMP TextRenderer::DrawStrikethrough( - __maybenull void* clientDrawingContext, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - __in DWRITE_STRIKETHROUGH const* strikethrough, - IUnknown* clientDrawingEffect -) -{ - HRESULT hr; - - D2D1_RECT_F rect = D2D1::RectF( - 0, - strikethrough->offset, - strikethrough->width, - strikethrough->offset + strikethrough->thickness - ); - - ID2D1RectangleGeometry* pRectangleGeometry = nullptr; - hr = pD2DFactory_->CreateRectangleGeometry( - &rect, - &pRectangleGeometry - ); - - D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F( - 1.0f, 0.0f, - 0.0f, 1.0f, - baselineOriginX, baselineOriginY - ); - - ID2D1TransformedGeometry* pTransformedGeometry = nullptr; - if (SUCCEEDED(hr)) - { - hr = pD2DFactory_->CreateTransformedGeometry( - pRectangleGeometry, - &matrix, - &pTransformedGeometry - ); - } - - if (SUCCEEDED(hr) && bShowOutline_) - { - pBrush_->SetColor(sOutlineColor_); - - pRT_->DrawGeometry( - pTransformedGeometry, - pBrush_, - fOutlineWidth, - pCurrStrokeStyle_ - ); - } - - if (SUCCEEDED(hr)) - { - pBrush_->SetColor(sFillColor_); - - pRT_->FillGeometry( - pTransformedGeometry, - pBrush_ - ); - } - - SafeRelease(pRectangleGeometry); - SafeRelease(pTransformedGeometry); - - return S_OK; -} - -STDMETHODIMP TextRenderer::DrawInlineObject( - __maybenull void* clientDrawingContext, - FLOAT originX, - FLOAT originY, - IDWriteInlineObject* inlineObject, - BOOL IsSideways, - BOOL IsRightToLeft, - IUnknown* clientDrawingEffect -) -{ - return E_NOTIMPL; -} - -STDMETHODIMP_(unsigned long) TextRenderer::AddRef() -{ - return InterlockedIncrement(&cRefCount_); -} - -STDMETHODIMP_(unsigned long) TextRenderer::Release() -{ - unsigned long newCount = InterlockedDecrement(&cRefCount_); - - if (newCount == 0) - { - delete this; - return 0; - } - - return newCount; -} - -STDMETHODIMP TextRenderer::IsPixelSnappingDisabled( - __maybenull void* clientDrawingContext, - __out BOOL* isDisabled -) -{ - *isDisabled = FALSE; - return S_OK; -} - -STDMETHODIMP TextRenderer::GetCurrentTransform( - __maybenull void* clientDrawingContext, - __out DWRITE_MATRIX* transform -) -{ - pRT_->GetTransform(reinterpret_cast(transform)); - return S_OK; -} - -STDMETHODIMP TextRenderer::GetPixelsPerDip( - __maybenull void* clientDrawingContext, - __out FLOAT* pixelsPerDip -) -{ - float x, yUnused; - - pRT_->GetDpi(&x, &yUnused); - *pixelsPerDip = x / 96; - - return S_OK; -} - -STDMETHODIMP TextRenderer::QueryInterface( - IID const& riid, - void** ppvObject -) -{ - if (__uuidof(IDWriteTextRenderer) == riid) - { - *ppvObject = this; - } - else if (__uuidof(IDWritePixelSnapping) == riid) - { - *ppvObject = this; - } - else if (__uuidof(IUnknown) == riid) - { - *ppvObject = this; - } - else - { - *ppvObject = nullptr; - return E_FAIL; - } - - AddRef(); - - return S_OK; -} \ No newline at end of file diff --git a/core/modules/Game.cpp b/core/modules/Game.cpp index 7e7f48fe..1c2b0974 100644 --- a/core/modules/Game.cpp +++ b/core/modules/Game.cpp @@ -51,7 +51,7 @@ easy2d::Game::Game() { if (instance) { - throw RuntimeException("同时只能存在一个游戏实例"); + throw RuntimeError("同时只能存在一个游戏实例"); } instance = this; @@ -326,7 +326,7 @@ void easy2d::Game::Init() if (hwnd_ == nullptr) { ::UnregisterClass(REGISTER_CLASS, HINST_THISCOMPONENT); - throw RuntimeException("Create window failed"); + throw RuntimeError("Create window failed"); return; } diff --git a/core/modules/Graphics.cpp b/core/modules/Graphics.cpp index f41df0d2..3c044218 100644 --- a/core/modules/Graphics.cpp +++ b/core/modules/Graphics.cpp @@ -22,6 +22,492 @@ #include "..\e2dobject.h" +namespace easy2d +{ + // 文字渲染器 + class TextRenderer + : public IDWriteTextRenderer + { + public: + static HRESULT Create( + IDWriteTextRenderer** ppTextRenderer, + ID2D1Factory* pD2DFactory, + ID2D1HwndRenderTarget* pRT, + ID2D1SolidColorBrush* pBrush + ); + + STDMETHOD_(void, SetTextStyle)( + CONST D2D1_COLOR_F &fillColor, + BOOL outline, + CONST D2D1_COLOR_F &outline_color, + FLOAT outline_width, + D2D1_LINE_JOIN outlineJoin + ); + + STDMETHOD(DrawGlyphRun)( + __maybenull void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + DWRITE_MEASURING_MODE measuringMode, + __in DWRITE_GLYPH_RUN const* glyphRun, + __in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, + IUnknown* clientDrawingEffect + ); + + STDMETHOD(DrawUnderline)( + __maybenull void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + __in DWRITE_UNDERLINE const* underline, + IUnknown* clientDrawingEffect + ); + + STDMETHOD(DrawStrikethrough)( + __maybenull void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + __in DWRITE_STRIKETHROUGH const* strikethrough, + IUnknown* clientDrawingEffect + ); + + STDMETHOD(DrawInlineObject)( + __maybenull void* clientDrawingContext, + FLOAT originX, + FLOAT originY, + IDWriteInlineObject* inlineObject, + BOOL IsSideways, + BOOL IsRightToLeft, + IUnknown* clientDrawingEffect + ); + + STDMETHOD(IsPixelSnappingDisabled)( + __maybenull void* clientDrawingContext, + __out BOOL* isDisabled + ); + + STDMETHOD(GetCurrentTransform)( + __maybenull void* clientDrawingContext, + __out DWRITE_MATRIX* transform + ); + + STDMETHOD(GetPixelsPerDip)( + __maybenull void* clientDrawingContext, + __out FLOAT* pixelsPerDip + ); + + public: + unsigned long STDMETHODCALLTYPE AddRef(); + unsigned long STDMETHODCALLTYPE Release(); + HRESULT STDMETHODCALLTYPE QueryInterface( + IID const& riid, + void** ppvObject + ); + + private: + TextRenderer( + ID2D1Factory* pD2DFactory, + ID2D1HwndRenderTarget* pRT, + ID2D1SolidColorBrush* pBrush + ); + + ~TextRenderer(); + + private: + unsigned long cRefCount_; + D2D1_COLOR_F sFillColor_; + D2D1_COLOR_F sOutlineColor_; + FLOAT fOutlineWidth; + BOOL bShowOutline_; + ID2D1Factory* pD2DFactory_; + ID2D1HwndRenderTarget* pRT_; + ID2D1SolidColorBrush* pBrush_; + ID2D1StrokeStyle* pCurrStrokeStyle_; + }; + + TextRenderer::TextRenderer(ID2D1Factory* pD2DFactory, ID2D1HwndRenderTarget* pRT, ID2D1SolidColorBrush* pBrush) + : cRefCount_(0) + , pD2DFactory_(pD2DFactory) + , pRT_(pRT) + , pBrush_(pBrush) + , sFillColor_() + , sOutlineColor_() + , fOutlineWidth(1) + , bShowOutline_(TRUE) + , pCurrStrokeStyle_(nullptr) + { + pD2DFactory->AddRef(); + pRT->AddRef(); + pBrush->AddRef(); + } + + TextRenderer::~TextRenderer() + { + SafeRelease(pD2DFactory_); + SafeRelease(pRT_); + SafeRelease(pBrush_); + } + + HRESULT TextRenderer::Create( + IDWriteTextRenderer** ppTextRenderer, + ID2D1Factory* pD2DFactory, + ID2D1HwndRenderTarget* pRT, + ID2D1SolidColorBrush* pBrush + ) + { + *ppTextRenderer = new (std::nothrow) TextRenderer(pD2DFactory, pRT, pBrush); + if (*ppTextRenderer) + { + (*ppTextRenderer)->AddRef(); + return S_OK; + } + return E_FAIL; + } + + STDMETHODIMP_(void) TextRenderer::SetTextStyle( + CONST D2D1_COLOR_F &fillColor, + BOOL outline, + CONST D2D1_COLOR_F &outline_color, + FLOAT outline_width, + D2D1_LINE_JOIN outlineJoin + ) + { + sFillColor_ = fillColor; + bShowOutline_ = outline; + sOutlineColor_ = outline_color; + fOutlineWidth = 2 * outline_width; + + switch (outlineJoin) + { + case D2D1_LINE_JOIN_MITER: + pCurrStrokeStyle_ = Device::GetGraphics()->GetMiterStrokeStyle(); + break; + case D2D1_LINE_JOIN_BEVEL: + pCurrStrokeStyle_ = Device::GetGraphics()->GetBevelStrokeStyle(); + break; + case D2D1_LINE_JOIN_ROUND: + pCurrStrokeStyle_ = Device::GetGraphics()->GetRoundStrokeStyle(); + break; + default: + pCurrStrokeStyle_ = nullptr; + break; + } + } + + STDMETHODIMP TextRenderer::DrawGlyphRun( + __maybenull void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + DWRITE_MEASURING_MODE measuringMode, + __in DWRITE_GLYPH_RUN const* glyphRun, + __in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, + IUnknown* clientDrawingEffect + ) + { + HRESULT hr = S_OK; + + ID2D1PathGeometry* pPathGeometry = nullptr; + hr = pD2DFactory_->CreatePathGeometry( + &pPathGeometry + ); + + ID2D1GeometrySink* pSink = nullptr; + if (SUCCEEDED(hr)) + { + hr = pPathGeometry->Open( + &pSink + ); + } + + if (SUCCEEDED(hr)) + { + hr = glyphRun->fontFace->GetGlyphRunOutline( + glyphRun->fontEmSize, + glyphRun->glyphIndices, + glyphRun->glyphAdvances, + glyphRun->glyphOffsets, + glyphRun->glyphCount, + glyphRun->isSideways, + glyphRun->bidiLevel % 2, + pSink + ); + } + + if (SUCCEEDED(hr)) + { + hr = pSink->Close(); + } + + D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F( + 1.0f, 0.0f, + 0.0f, 1.0f, + baselineOriginX, baselineOriginY + ); + + ID2D1TransformedGeometry* pTransformedGeometry = nullptr; + if (SUCCEEDED(hr)) + { + hr = pD2DFactory_->CreateTransformedGeometry( + pPathGeometry, + &matrix, + &pTransformedGeometry + ); + } + + if (SUCCEEDED(hr) && bShowOutline_) + { + pBrush_->SetColor(sOutlineColor_); + + pRT_->DrawGeometry( + pTransformedGeometry, + pBrush_, + fOutlineWidth, + pCurrStrokeStyle_ + ); + } + + if (SUCCEEDED(hr)) + { + pBrush_->SetColor(sFillColor_); + + pRT_->FillGeometry( + pTransformedGeometry, + pBrush_ + ); + } + + SafeRelease(pPathGeometry); + SafeRelease(pSink); + SafeRelease(pTransformedGeometry); + + return hr; + } + + STDMETHODIMP TextRenderer::DrawUnderline( + __maybenull void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + __in DWRITE_UNDERLINE const* underline, + IUnknown* clientDrawingEffect + ) + { + HRESULT hr; + + D2D1_RECT_F rect = D2D1::RectF( + 0, + underline->offset, + underline->width, + underline->offset + underline->thickness + ); + + ID2D1RectangleGeometry* pRectangleGeometry = nullptr; + hr = pD2DFactory_->CreateRectangleGeometry( + &rect, + &pRectangleGeometry + ); + + D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F( + 1.0f, 0.0f, + 0.0f, 1.0f, + baselineOriginX, baselineOriginY + ); + + ID2D1TransformedGeometry* pTransformedGeometry = nullptr; + if (SUCCEEDED(hr)) + { + hr = pD2DFactory_->CreateTransformedGeometry( + pRectangleGeometry, + &matrix, + &pTransformedGeometry + ); + } + + if (SUCCEEDED(hr) && bShowOutline_) + { + pBrush_->SetColor(sOutlineColor_); + + pRT_->DrawGeometry( + pTransformedGeometry, + pBrush_, + fOutlineWidth, + pCurrStrokeStyle_ + ); + } + + if (SUCCEEDED(hr)) + { + pBrush_->SetColor(sFillColor_); + + pRT_->FillGeometry( + pTransformedGeometry, + pBrush_ + ); + } + + SafeRelease(pRectangleGeometry); + SafeRelease(pTransformedGeometry); + + return S_OK; + } + + STDMETHODIMP TextRenderer::DrawStrikethrough( + __maybenull void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + __in DWRITE_STRIKETHROUGH const* strikethrough, + IUnknown* clientDrawingEffect + ) + { + HRESULT hr; + + D2D1_RECT_F rect = D2D1::RectF( + 0, + strikethrough->offset, + strikethrough->width, + strikethrough->offset + strikethrough->thickness + ); + + ID2D1RectangleGeometry* pRectangleGeometry = nullptr; + hr = pD2DFactory_->CreateRectangleGeometry( + &rect, + &pRectangleGeometry + ); + + D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F( + 1.0f, 0.0f, + 0.0f, 1.0f, + baselineOriginX, baselineOriginY + ); + + ID2D1TransformedGeometry* pTransformedGeometry = nullptr; + if (SUCCEEDED(hr)) + { + hr = pD2DFactory_->CreateTransformedGeometry( + pRectangleGeometry, + &matrix, + &pTransformedGeometry + ); + } + + if (SUCCEEDED(hr) && bShowOutline_) + { + pBrush_->SetColor(sOutlineColor_); + + pRT_->DrawGeometry( + pTransformedGeometry, + pBrush_, + fOutlineWidth, + pCurrStrokeStyle_ + ); + } + + if (SUCCEEDED(hr)) + { + pBrush_->SetColor(sFillColor_); + + pRT_->FillGeometry( + pTransformedGeometry, + pBrush_ + ); + } + + SafeRelease(pRectangleGeometry); + SafeRelease(pTransformedGeometry); + + return S_OK; + } + + STDMETHODIMP TextRenderer::DrawInlineObject( + __maybenull void* clientDrawingContext, + FLOAT originX, + FLOAT originY, + IDWriteInlineObject* inlineObject, + BOOL IsSideways, + BOOL IsRightToLeft, + IUnknown* clientDrawingEffect + ) + { + return E_NOTIMPL; + } + + STDMETHODIMP_(unsigned long) TextRenderer::AddRef() + { + return InterlockedIncrement(&cRefCount_); + } + + STDMETHODIMP_(unsigned long) TextRenderer::Release() + { + unsigned long newCount = InterlockedDecrement(&cRefCount_); + + if (newCount == 0) + { + delete this; + return 0; + } + + return newCount; + } + + STDMETHODIMP TextRenderer::IsPixelSnappingDisabled( + __maybenull void* clientDrawingContext, + __out BOOL* isDisabled + ) + { + *isDisabled = FALSE; + return S_OK; + } + + STDMETHODIMP TextRenderer::GetCurrentTransform( + __maybenull void* clientDrawingContext, + __out DWRITE_MATRIX* transform + ) + { + pRT_->GetTransform(reinterpret_cast(transform)); + return S_OK; + } + + STDMETHODIMP TextRenderer::GetPixelsPerDip( + __maybenull void* clientDrawingContext, + __out FLOAT* pixelsPerDip + ) + { + float x, yUnused; + + pRT_->GetDpi(&x, &yUnused); + *pixelsPerDip = x / 96; + + return S_OK; + } + + STDMETHODIMP TextRenderer::QueryInterface( + IID const& riid, + void** ppvObject + ) + { + if (__uuidof(IDWriteTextRenderer) == riid) + { + *ppvObject = this; + } + else if (__uuidof(IDWritePixelSnapping) == riid) + { + *ppvObject = this; + } + else if (__uuidof(IUnknown) == riid) + { + *ppvObject = this; + } + else + { + *ppvObject = nullptr; + return E_FAIL; + } + + AddRef(); + + return S_OK; + } +} + + easy2d::Graphics::Graphics(HWND hwnd) : factory_(nullptr) , imaging_factory_(nullptr) @@ -196,7 +682,7 @@ void easy2d::Graphics::DrawDebugInfo() { render_target_->SetTransform(D2D1::Matrix3x2F::Identity()); solid_brush_->SetOpacity(1.0f); - text_renderer_->SetTextStyle( + static_cast(text_renderer_)->SetTextStyle( D2D1::ColorF(D2D1::ColorF::White), TRUE, D2D1::ColorF(D2D1::ColorF::Black, 0.4f), @@ -223,7 +709,7 @@ ID2D1SolidColorBrush * easy2d::Graphics::GetSolidBrush() const return solid_brush_; } -easy2d::TextRenderer * easy2d::Graphics::GetTextRender() const +IDWriteTextRenderer* easy2d::Graphics::GetTextRender() const { return text_renderer_; } @@ -312,6 +798,17 @@ ID2D1StrokeStyle * easy2d::Graphics::GetRoundStrokeStyle() return round_stroke_style_; } +void easy2d::Graphics::SetTextRendererStyle(const Color & fill_color, bool has_outline, const Color & outline_color, float outline_width, Stroke outline_stroke) +{ + static_cast(text_renderer_)->SetTextStyle( + D2D1_COLOR_F(fill_color), + has_outline, + D2D1_COLOR_F(outline_color), + outline_width, + D2D1_LINE_JOIN(outline_stroke) + ); +} + float easy2d::Graphics::GetDpi() { static float dpi = -1; diff --git a/core/objects/Node.cpp b/core/objects/Node.cpp index 11a6fed0..c4d9c541 100644 --- a/core/objects/Node.cpp +++ b/core/objects/Node.cpp @@ -601,14 +601,14 @@ void easy2d::Node::AddChild(Node * child, int order) { if (child->parent_ != nullptr) { - throw RuntimeException("节点已有父节点, 不能再添加到其他节点"); + throw RuntimeError("节点已有父节点, 不能再添加到其他节点"); } for (Node * parent = this; parent != nullptr; parent = parent->GetParent()) { if (child == parent) { - throw RuntimeException("一个节点不能同时是另一个节点的父节点和子节点"); + throw RuntimeError("一个节点不能同时是另一个节点的父节点和子节点"); } } @@ -782,7 +782,7 @@ void easy2d::Node::RunAction(Action * action) } else { - throw RuntimeException("该 Action 已有执行目标"); + throw RuntimeError("该 Action 已有执行目标"); } } } diff --git a/core/objects/Text.cpp b/core/objects/Text.cpp index 972f702f..76749f25 100644 --- a/core/objects/Text.cpp +++ b/core/objects/Text.cpp @@ -319,12 +319,12 @@ void easy2d::Text::Draw() const graphics->GetSolidBrush()->SetOpacity(display_opacity_); // 获取文本渲染器 auto text_renderer = graphics->GetTextRender(); - text_renderer->SetTextStyle( - (D2D1_COLOR_F)style_.color, + graphics->SetTextRendererStyle( + style_.color, style_.outline, - (D2D1_COLOR_F)style_.outline_color, + style_.outline_color, style_.outline_width, - D2D1_LINE_JOIN(style_.outline_stroke) + style_.outline_stroke ); text_layout_->Draw(nullptr, text_renderer, 0, 0); } diff --git a/project/vs2012/Easy2D.vcxproj b/project/vs2012/Easy2D.vcxproj index 341c8e0d..d93370d8 100644 --- a/project/vs2012/Easy2D.vcxproj +++ b/project/vs2012/Easy2D.vcxproj @@ -44,7 +44,6 @@ - @@ -89,7 +88,6 @@ - diff --git a/project/vs2012/Easy2D.vcxproj.filters b/project/vs2012/Easy2D.vcxproj.filters index 20bd63df..7354ab3b 100644 --- a/project/vs2012/Easy2D.vcxproj.filters +++ b/project/vs2012/Easy2D.vcxproj.filters @@ -13,9 +13,6 @@ {7ffdcb87-b6a2-4815-be96-5598f74155ee} - - {3475b59d-d50c-43b1-8334-bcb9e1703ed2} - {6c9657de-02d5-4d3b-9e1d-bc921eb5aea3} @@ -138,9 +135,6 @@ components - - impl - events @@ -225,7 +219,6 @@ - diff --git a/project/vs2013/Easy2D.vcxproj b/project/vs2013/Easy2D.vcxproj index a8b6502b..d16cb5ec 100644 --- a/project/vs2013/Easy2D.vcxproj +++ b/project/vs2013/Easy2D.vcxproj @@ -188,7 +188,6 @@ - @@ -233,7 +232,6 @@ - diff --git a/project/vs2013/Easy2D.vcxproj.filters b/project/vs2013/Easy2D.vcxproj.filters index 20bd63df..7354ab3b 100644 --- a/project/vs2013/Easy2D.vcxproj.filters +++ b/project/vs2013/Easy2D.vcxproj.filters @@ -13,9 +13,6 @@ {7ffdcb87-b6a2-4815-be96-5598f74155ee} - - {3475b59d-d50c-43b1-8334-bcb9e1703ed2} - {6c9657de-02d5-4d3b-9e1d-bc921eb5aea3} @@ -138,9 +135,6 @@ components - - impl - events @@ -225,7 +219,6 @@ - diff --git a/project/vs2017/Easy2D.vcxproj b/project/vs2017/Easy2D.vcxproj index 6b67da54..7e2f10a6 100644 --- a/project/vs2017/Easy2D.vcxproj +++ b/project/vs2017/Easy2D.vcxproj @@ -221,7 +221,6 @@ - @@ -266,7 +265,6 @@ - diff --git a/project/vs2017/Easy2D.vcxproj.filters b/project/vs2017/Easy2D.vcxproj.filters index 20bd63df..7354ab3b 100644 --- a/project/vs2017/Easy2D.vcxproj.filters +++ b/project/vs2017/Easy2D.vcxproj.filters @@ -13,9 +13,6 @@ {7ffdcb87-b6a2-4815-be96-5598f74155ee} - - {3475b59d-d50c-43b1-8334-bcb9e1703ed2} - {6c9657de-02d5-4d3b-9e1d-bc921eb5aea3} @@ -138,9 +135,6 @@ components - - impl - events @@ -225,7 +219,6 @@ -