Created
December 16, 2014 09:29
-
-
Save LYP951018/d6aa4aa069d21408efe4 to your computer and use it in GitHub Desktop.
Direct2D
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <d2d1.h> | |
| #include <d2d1helper.h> | |
| #include <dwrite.h> | |
| #include <tuple> | |
| #include <string> | |
| #include <limits> | |
| #include <cstdint> | |
| #pragma comment(lib,"d2d1.lib") | |
| #pragma comment(lib,"dwrite.lib") | |
| using D2DColor = D2D1::ColorF; | |
| #undef max | |
| #undef min | |
| class RenderEngine; | |
| class DWriteLayout; | |
| struct Rect :public D2D1_RECT_F | |
| { | |
| Rect(float l,float t,float r,float b) | |
| { | |
| this->top = t; | |
| this->bottom = b; | |
| this->right = r; | |
| this->left = l; | |
| } | |
| Rect() | |
| :Rect(0.f,0.f,0.f,0.f) | |
| { | |
| } | |
| float GetWidth() const | |
| { | |
| return this->right - this->left; | |
| } | |
| float GetHeight() const | |
| { | |
| return this->bottom - this->top; | |
| } | |
| }; | |
| struct Size : public D2D1_SIZE_U | |
| { | |
| Size(unsigned x, unsigned y) | |
| { | |
| this->width = x; | |
| this->height = y; | |
| } | |
| }; | |
| struct DWriteTextRange : public DWRITE_TEXT_RANGE | |
| { | |
| DWriteTextRange(decltype(startPosition) pos,decltype(length) len) | |
| { | |
| this->startPosition = pos; | |
| this->length = len; | |
| } | |
| //infinity | |
| DWriteTextRange(decltype(startPosition) pos) | |
| { | |
| this->startPosition = pos; | |
| this->length = std::numeric_limits<decltype(length)>::max() - startPosition; | |
| } | |
| }; | |
| struct Point : public D2D1_POINT_2F | |
| { | |
| Point(float X = 0.f, float Y = 0.f) | |
| { | |
| this->x = X; | |
| this->y = Y; | |
| } | |
| }; | |
| struct FontInfo | |
| { | |
| std::wstring FontFamilyName = L"Microsoft YaHei"; | |
| DWRITE_FONT_WEIGHT FontWeight = DWRITE_FONT_WEIGHT_NORMAL; | |
| DWRITE_FONT_STRETCH FontStretch = DWRITE_FONT_STRETCH_NORMAL; | |
| DWRITE_FONT_STYLE FontStyle = DWRITE_FONT_STYLE_NORMAL; | |
| UINT32 color = 0; | |
| BOOL HasUnderLine = FALSE; | |
| BOOL HasStrikeThrough = FALSE; | |
| }; | |
| class RenderEngine | |
| { | |
| private: | |
| ID2D1Factory* pD2DFactory; | |
| IDWriteFactory* pDwriteFactory; | |
| ID2D1HwndRenderTarget* pRenderTarget; | |
| IDWriteTextFormat* pTextFormat; | |
| //other things | |
| public: | |
| RenderEngine(ID2D1Factory* pfactory,IDWriteFactory* pdwfactory, HWND hwnd) | |
| :pD2DFactory(pfactory), | |
| pDwriteFactory(pdwfactory) | |
| { | |
| //Initialize | |
| RECT rc; | |
| ::GetClientRect(hwnd, &rc); | |
| D2D1_SIZE_U size = D2D1::SizeU( | |
| rc.right - rc.left, | |
| rc.bottom - rc.top); | |
| pD2DFactory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(), | |
| D2D1::HwndRenderTargetProperties(hwnd, size), | |
| &pRenderTarget); | |
| pDwriteFactory->CreateTextFormat( | |
| L"Microsoft YaHei", | |
| nullptr, | |
| DWRITE_FONT_WEIGHT_NORMAL, | |
| DWRITE_FONT_STYLE_NORMAL, | |
| DWRITE_FONT_STRETCH_NORMAL, | |
| 20.f, | |
| L"", | |
| &pTextFormat | |
| ); | |
| pD2DFactory->AddRef(); | |
| pDwriteFactory->AddRef(); | |
| } | |
| void SetTextFormat(IDWriteTextFormat* pformat) | |
| { | |
| pTextFormat = pformat; | |
| } | |
| ID2D1SolidColorBrush* GetBrush(const D2DColor& color) const | |
| { | |
| ID2D1SolidColorBrush* pBrush = nullptr; | |
| pRenderTarget->CreateSolidColorBrush( | |
| color, &pBrush); | |
| return pBrush; | |
| } | |
| void DrawRectangle(const Rect& r, const D2DColor& color,float width = 1.f) | |
| { | |
| auto p = GetBrush(color); | |
| pRenderTarget->DrawRectangle(r, p,width); | |
| p->Release(); | |
| } | |
| void FillRectangle(const Rect& r, const D2DColor& color) | |
| { | |
| auto p = GetBrush(color); | |
| pRenderTarget->FillRectangle(r, p); | |
| p->Release(); | |
| } | |
| void DrawLine(const Point& p1, const Point& p2, const D2DColor& color, float width = 1.0f) | |
| { | |
| auto p = GetBrush(color); | |
| pRenderTarget->DrawLine(p1, p2, p,width); | |
| p->Release(); | |
| } | |
| void ReSize(const Size& s) | |
| { | |
| if(pRenderTarget) | |
| pRenderTarget->Resize(s); | |
| } | |
| void BeginDraw() | |
| { | |
| pRenderTarget->BeginDraw(); | |
| } | |
| void EndDraw() | |
| { | |
| pRenderTarget->EndDraw(); | |
| } | |
| void ClearBackground(const D2DColor& co) | |
| { | |
| pRenderTarget->Clear(co); | |
| } | |
| HWND GetHwnd() const | |
| { | |
| return pRenderTarget->GetHwnd(); | |
| } | |
| ~RenderEngine() | |
| { | |
| pD2DFactory->Release(); | |
| pDwriteFactory->Release(); | |
| pRenderTarget->Release(); | |
| pTextFormat->Release(); | |
| } | |
| void RenderText(const DWriteLayout* playout, const Point& pos); | |
| ID2D1Factory* GetFactory() const | |
| { | |
| return pD2DFactory; | |
| } | |
| IDWriteFactory* GetDwFactory() const | |
| { | |
| return pDwriteFactory; | |
| } | |
| ID2D1HwndRenderTarget* GetRenderTarget() const | |
| { | |
| return pRenderTarget; | |
| } | |
| IDWriteTextFormat* GetTextFormat() const | |
| { | |
| return pTextFormat; | |
| } | |
| static inline std::pair<ID2D1Factory*, IDWriteFactory*> GetFactories() | |
| { | |
| ID2D1Factory* pFactory = nullptr; | |
| IDWriteFactory* pDwFactory = nullptr; | |
| D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, | |
| &pFactory); | |
| DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, | |
| __uuidof(IDWriteFactory), | |
| reinterpret_cast<IUnknown**>(&pDwFactory)); | |
| return std::make_pair(pFactory, pDwFactory); | |
| } | |
| template<typename T> | |
| void Draw(T& thing) | |
| { | |
| thing.Draw(this); | |
| } | |
| template<typename T> | |
| void Draw(T* pthing) | |
| { | |
| pthing->Draw(this); | |
| } | |
| }; | |
| class DWriteLayout | |
| { | |
| private: | |
| static IDWriteTextLayout* CreateTextLayout(RenderEngine* pengine, const std::wstring& text) | |
| { | |
| IDWriteTextLayout* pLayout = nullptr; | |
| auto hr = pengine->GetDwFactory()->CreateTextLayout( | |
| text.data(), | |
| text.length(), | |
| pengine->GetTextFormat(), | |
| std::numeric_limits<float>::infinity(), | |
| std::numeric_limits<float>::infinity(), | |
| &pLayout); | |
| return pLayout; | |
| } | |
| public: | |
| DWriteLayout(RenderEngine* pengine, const std::wstring& text) | |
| :pEngine(pengine) | |
| { | |
| pTextLayout = DWriteLayout::CreateTextLayout(pengine, text); | |
| } | |
| DWriteLayout(RenderEngine* pengine = nullptr) | |
| :pEngine(pengine), | |
| pTextLayout(nullptr) | |
| { | |
| } | |
| ~DWriteLayout() | |
| { | |
| if (pTextLayout) | |
| pTextLayout->Release(); | |
| } | |
| void SetEngine(RenderEngine* pengine) | |
| { | |
| pEngine = pengine; | |
| } | |
| void SetString(const std::wstring& text) | |
| { | |
| pTextLayout = DWriteLayout::CreateTextLayout(pEngine, text); | |
| } | |
| void SetUnderLine(bool hasunderline, const DWriteTextRange& range = { 0 }) | |
| { | |
| pTextLayout->SetUnderline(hasunderline, range); | |
| } | |
| void SetFontColor(const D2DColor& co, const DWriteTextRange& range = { 0 }) | |
| { | |
| auto p = pEngine->GetBrush(co); | |
| pTextLayout->SetDrawingEffect(p, range); | |
| p->Release(); | |
| } | |
| void SetFontWeight(DWRITE_FONT_WEIGHT weight, const DWriteTextRange& range = { 0 }) | |
| { | |
| pTextLayout->SetFontWeight(weight, range); | |
| } | |
| void SetMaxHeight(float height) | |
| { | |
| pTextLayout->SetMaxHeight(height); | |
| } | |
| void SetMaxWidth(float width) | |
| { | |
| pTextLayout->SetMaxWidth(width); | |
| } | |
| void SetFontSize(float size, const DWriteTextRange& range = { 0 }) | |
| { | |
| pTextLayout->SetFontSize(size, range); | |
| } | |
| IDWriteTextLayout* GetDWriteTextLayout() const | |
| { | |
| return pTextLayout; | |
| } | |
| void SetFont(const std::wstring& ws, const DWriteTextRange& range = { 0 }) | |
| { | |
| pTextLayout->SetFontFamilyName(ws.data(), range); | |
| } | |
| private: | |
| IDWriteTextLayout* pTextLayout; | |
| RenderEngine* pEngine; | |
| }; | |
| void RenderEngine::RenderText(const DWriteLayout* playout, const Point& pos) | |
| { | |
| auto p = GetBrush({ 0 }); | |
| pRenderTarget->DrawTextLayout( | |
| pos, | |
| playout->GetDWriteTextLayout(), | |
| p | |
| ); | |
| p->Release(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment