Skip to content

Instantly share code, notes, and snippets.

@LYP951018
Created December 16, 2014 09:29
Show Gist options
  • Select an option

  • Save LYP951018/d6aa4aa069d21408efe4 to your computer and use it in GitHub Desktop.

Select an option

Save LYP951018/d6aa4aa069d21408efe4 to your computer and use it in GitHub Desktop.
Direct2D
#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