duilib 绘图机制分析

旧时模样 提交于 2020-08-14 22:47:07

 

注:本文使用的是云信duilib

1 绘图功能基本接口 抽象类

   不负责具体实现功能,而是定义绘图时,应该具有的功能,由纯虚函数定义

在duilib中,将与绘制相关的功能,定义成了抽象类纯虚函数接口,定义了绘图使用的渲染上下文环境

在IRender.h中,定义了各种接口 抽象类

其中,最重要的就是IRenderContext ,渲染上下文接口类,此抽象类中定义了绘图所应该有的常用功能

class UILIB_API IRenderContext : public nbase::SupportWeakCallback
{
public:
	virtual HDC GetDC() = 0;
	virtual bool Resize(int width, int height, bool flipBItmap = true) = 0;
	virtual void Clear() = 0;
	virtual std::unique_ptr<IRenderContext> Clone() = 0;

	virtual HBITMAP DetachBitmap() = 0;
	virtual BYTE* GetBits() = 0;
	virtual int	GetWidth() = 0;
	virtual int GetHeight() = 0;
	virtual void ClearAlpha(const UiRect& rcDirty, int alpha = 0) = 0;
	virtual void RestoreAlpha(const UiRect& rcDirty, const UiRect& rcShadowPadding = UiRect(), int alpha = 0) = 0;

	virtual bool IsRenderTransparent() const = 0;
	virtual bool SetRenderTransparent(bool bTransparent) = 0;

	virtual void Save() = 0;
	virtual void Restore() = 0;
	virtual CPoint OffsetWindowOrg(CPoint ptOffset) = 0;
	virtual CPoint SetWindowOrg(CPoint ptOffset) = 0;
	virtual CPoint GetWindowOrg() const = 0;

	virtual void SetClip(const UiRect& rc) = 0;
	virtual void SetRoundClip(const UiRect& rcItem, int width, int height) = 0;
	virtual void ClearClip() = 0;

	virtual HRESULT BitBlt(int x, int y, int cx, int cy, HDC hdcSrc, int xSrc = 0, int yScr = 0, DWORD rop = SRCCOPY) = 0;
	virtual bool AlphaBlend(int xDest, int yDest, int widthDest, int heightDest, HDC hdcSrc, int xSrc, int yScr, int widthSrc, int heightSrc, BYTE uFade = 255) = 0;

	virtual void DrawImage(const UiRect& rcPaint, HBITMAP hBitmap, bool bAlphaChannel,
		const UiRect& rcImageDest, const UiRect& rcImageSource, const UiRect& rcCorners, BYTE uFade = 255, bool xtiled = false, bool ytiled = false) = 0;

	virtual void DrawColor(const UiRect& rc, DWORD dwColor, BYTE uFade = 255) = 0;
	virtual void DrawColor(const UiRect& rc, const std::wstring& colorStr, BYTE uFade = 255) = 0;

	virtual void DrawLine(const UiRect& rc, int nSize, DWORD dwPenColor) = 0;
	virtual void DrawLine(const IPen* pen, int x1, int y1, int x2, int y2) = 0;
	virtual void DrawBezier(const IPen* pen, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) = 0;
	virtual void DrawRect(const UiRect& rc, int nSize, DWORD dwPenColor) = 0;
	virtual void DrawText(const UiRect& rc, const std::wstring& strText, DWORD dwTextColor, int iFont, UINT uStyle, BYTE uFade = 255, bool bLineLimit = false) = 0;

	virtual void DrawEllipse(const UiRect& rc, int nSize, DWORD dwColor) = 0;
	virtual void FillEllipse(const UiRect& rc, DWORD dwColor) = 0;

	virtual UiRect MeasureText(const std::wstring& strText, int iFont, UINT uStyle, int width = DUI_NOSET_VALUE) = 0;

	virtual void DrawPath(const IPath* path, const IPen* pen) = 0;
	virtual void FillPath(const IPath* path, const IBrush* brush) = 0;
};

 

类似的还有 IPen  IBrush IBitmap IMatrix等

class UILIB_API IPen : public nbase::SupportWeakCallback
{
public:
	IPen(DWORD color, int width = 1) : color_(color) {};
	IPen(const IPen& r) : color_(r.color_) {};
	IPen& operator=(const IPen& r) = delete;

	virtual IPen* Clone() = 0;

	virtual void SetWidth(int width) = 0;
	virtual int GetWidth() = 0;
	virtual void SetColor(DWORD color) = 0;
	virtual DWORD GetColor() { return color_; };

	enum LineCap
	{
		LineCapFlat = 0,
		LineCapSquare = 1,
		LineCapRound = 2,
		LineCapTriangle = 3
	};
	virtual void SetStartCap(LineCap cap) = 0;
	virtual void SetEndCap(LineCap cap) = 0;
	virtual void SetDashCap(LineCap cap) = 0;
	virtual LineCap GetStartCap() = 0;
	virtual LineCap GetEndCap() = 0;
	virtual LineCap GetDashCap() = 0;

	enum LineJoin
	{
		LineJoinMiter = 0,
		LineJoinBevel = 1,
		LineJoinRound = 2,
		LineJoinMiterClipped = 3
	};
	virtual void SetLineJoin(LineJoin join) = 0;
	virtual LineJoin GetLineJoin() = 0;

	enum DashStyle
	{
		DashStyleSolid,          // 0
		DashStyleDash,           // 1
		DashStyleDot,            // 2
		DashStyleDashDot,        // 3
		DashStyleDashDotDot,     // 4
		DashStyleCustom          // 5
	};
	virtual void SetDashStyle(DashStyle style) = 0;
	virtual DashStyle GetDashStyle() = 0;

protected:
	DWORD color_ = 0;
};

 

class UILIB_API IBrush : public nbase::SupportWeakCallback
{
public:
	IBrush(DWORD color) : color_(color){};
	IBrush(HBITMAP bitmap) {};
	IBrush(const IBrush& r)	: color_(r.color_)	{};
	IBrush& operator=(const IBrush& r) = delete;

	virtual IBrush* Clone() = 0;

	virtual DWORD GetColor() { return color_; };
	virtual IBitmap* GetBitmap() { return bitmap_.get(); };

protected:
	DWORD color_ = 0;
	std::unique_ptr<IBitmap> bitmap_;
};
class UILIB_API IBitmap : public nbase::SupportWeakCallback
{
    virtual bool Init(HDC hSrcDC, int width, int height, bool flipBItmap) = 0;
    virtual void Clear() = 0;
    virtual HBITMAP DetachBitmap() = 0;

    virtual HBITMAP GetBitmap() = 0;
    virtual BYTE* GetBits() = 0;
    virtual int    GetWidth() = 0;
    virtual int GetHeight() = 0;

    virtual void ClearAlpha(const UiRect& rcDirty, int alpha) = 0;
    virtual void RestoreAlpha(const UiRect& rcDirty, const UiRect& rcShadowPadding, int alpha) = 0;
};

 

 

class UILIB_API IMatrix : public nbase::SupportWeakCallback
{
public:
	virtual void Translate(int offsetX, int offsetY) = 0;
	virtual void Scale(int scaleX, int scaleY) = 0;
	virtual void Rotate(float angle) = 0;
	virtual void RotateAt(float angle, const CPoint& center) = 0;
};

 

2 使用工厂模式, 定义抽象工厂类,来生产创建各种具体的绘图实例

 

class UILIB_API IRenderFactory
{
public:
	virtual ui::IPen* CreatePen(DWORD color, int width = 1) = 0;
	virtual ui::IBrush* CreateBrush(DWORD corlor) = 0;
	virtual ui::IBrush* CreateBrush(HBITMAP bitmap) = 0;
	virtual ui::IMatrix* CreateMatrix() = 0;
	virtual ui::IPath* CreatePath() = 0;
	virtual ui::IBitmap* CreateBitmap() = 0;
	virtual ui::IRenderContext* CreateRenderContext() = 0;
};

3 负责具体绘制功能的子类  使用gdiplus进行渲染的  实现抽象类定义的各种功能

比如:


class UILIB_API RenderContext_GdiPlus : public IRenderContext
{
public:
	RenderContext_GdiPlus();
	virtual ~RenderContext_GdiPlus();

	virtual HDC GetDC() override;
	virtual bool Resize(int width, int height, bool flipBItmap = true) override;
	virtual void Clear() override;
	virtual std::unique_ptr<IRenderContext> Clone() override;

	virtual HBITMAP DetachBitmap() override;
	virtual BYTE* GetBits() override;
	virtual int	GetWidth() override;
	virtual int GetHeight() override;
	virtual void ClearAlpha(const UiRect& rcDirty, int alpha = 0) override;
	virtual void RestoreAlpha(const UiRect& rcDirty, const UiRect& rcShadowPadding = UiRect(), int alpha = 0) override;

	virtual bool IsRenderTransparent() const override;
	virtual bool SetRenderTransparent(bool bTransparent) override;

	virtual void Save() override;
	virtual void Restore() override;

	virtual CPoint OffsetWindowOrg(CPoint ptOffset) override;
	virtual CPoint SetWindowOrg(CPoint ptOffset) override;
	virtual CPoint GetWindowOrg() const override;

	virtual void SetClip(const UiRect& rc) override;
	virtual void SetRoundClip(const UiRect& rc, int width, int height) override;
	virtual void ClearClip() override;

	virtual HRESULT BitBlt(int x, int y, int cx, int cy, HDC hdcSrc, int xSrc = 0, int yScr = 0, DWORD rop = SRCCOPY) override;
	virtual bool AlphaBlend(int xDest, int yDest, int widthDest, int heightDest, HDC hdcSrc, int xSrc, int yScr, int widthSrc, int heightSrc, BYTE uFade = 255) override;

	virtual void DrawImage(const UiRect& rcPaint, HBITMAP hBitmap, bool bAlphaChannel,
		const UiRect& rcImageDest, const UiRect& rcImageSource, const UiRect& rcCorners, BYTE uFade = 255, bool xtiled = false, bool ytiled = false) override;

	virtual void DrawColor(const UiRect& rc, DWORD dwColor, BYTE uFade = 255) override;
	virtual void DrawColor(const UiRect& rc, const std::wstring& colorStr, BYTE uFade = 255) override;

	virtual void DrawLine(const UiRect& rc, int nSize, DWORD dwPenColor) override;
	virtual void DrawLine(const IPen* pen, int x1, int y1, int x2, int y2) override;
	virtual void DrawBezier(const IPen* pen, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) override;
	virtual void DrawRect(const UiRect& rc, int nSize, DWORD dwPenColor) override;
	virtual void DrawText(const UiRect& rc, const std::wstring& strText, DWORD dwTextColor, int iFont, UINT uStyle, BYTE uFade = 255, bool bLineLimit = false) override;

	virtual void DrawEllipse(const UiRect& rc, int nSize, DWORD dwColor) override;
	virtual void FillEllipse(const UiRect& rc, DWORD dwColor) override;

	virtual UiRect MeasureText(const std::wstring& strText, int iFont, UINT uStyle, int width = DUI_NOSET_VALUE) override;

	virtual void DrawPath(const IPath* path, const IPen* pen) override;
	virtual void FillPath(const IPath* path, const IBrush* brush) override;

private:
	HDC			m_hDC;
	int			m_saveDC;
	HBITMAP		m_hOldBitmap;

	bool		m_bTransparent;
	GdiClip		m_clip;
	GdiBitmap	m_bitmap;
};

class UILIB_API Brush_Gdiplus : public IBrush
{
public:
	Brush_Gdiplus(DWORD color);
	Brush_Gdiplus(HBITMAP bitmap);
	Brush_Gdiplus(const Brush_Gdiplus& r);
	Brush_Gdiplus& operator=(const Brush_Gdiplus& r) = delete;

	virtual IBrush* Clone() override;

	Gdiplus::Brush* GetBrush() { return brush_ ? brush_.get() : bitmap_brush_.get(); };
private:
	std::unique_ptr<Gdiplus::Brush> brush_;
	std::unique_ptr<Gdiplus::Brush> bitmap_brush_;
};

 

using namespace Gdiplus;

Brush_Gdiplus::Brush_Gdiplus(DWORD color)
	: IBrush(color)
{
	brush_.reset(new SolidBrush(color));
}

Brush_Gdiplus::Brush_Gdiplus(HBITMAP bitmap)
	: IBrush(bitmap)
{
	Gdiplus::Bitmap image(bitmap, NULL);
	bitmap_brush_.reset(new TextureBrush(&image));
}

Brush_Gdiplus::Brush_Gdiplus(const Brush_Gdiplus& r)
	: IBrush(r)
{
	if (r.brush_)
		brush_.reset(r.brush_->Clone());

	if (r.bitmap_brush_)
		bitmap_brush_.reset(r.bitmap_brush_->Clone());
}

ui::IBrush* Brush_Gdiplus::Clone()
{
	return new Brush_Gdiplus(*this);
}

 

GDI+工厂派生类的实现

 

class UILIB_API RenderFactory_GdiPlus : public IRenderFactory
{
public:
	virtual ui::IPen* CreatePen(DWORD color, int width = 1) override;
	virtual ui::IBrush* CreateBrush(DWORD corlor) override;
	virtual ui::IBrush* CreateBrush(HBITMAP bitmap) override;
	virtual ui::IMatrix* CreateMatrix() override;
	virtual ui::IPath* CreatePath() override;
	virtual ui::IBitmap* CreateBitmap() override;
	virtual ui::IRenderContext* CreateRenderContext() override;
};




ui::IPen* RenderFactory_GdiPlus::CreatePen(DWORD color, int width /*= 1*/)
{
	return new Pen_GdiPlus(color, width);
}

ui::IBrush* RenderFactory_GdiPlus::CreateBrush(DWORD color)
{
	return new Brush_Gdiplus(color);
}

ui::IBrush* RenderFactory_GdiPlus::CreateBrush(HBITMAP bitmap)
{
	return new Brush_Gdiplus(bitmap);
}

ui::IMatrix* RenderFactory_GdiPlus::CreateMatrix()
{
	return new Matrix_Gdiplus();
}

ui::IPath* RenderFactory_GdiPlus::CreatePath()
{
	return new Path_Gdiplus();
}

ui::IBitmap* RenderFactory_GdiPlus::CreateBitmap()
{
	return new GdiBitmap();
}

ui::IRenderContext* RenderFactory_GdiPlus::CreateRenderContext()
{
	return new RenderContext_GdiPlus();
}

 

实例

初始化duilib时,先创建具体实现gdiplus功能的工厂类

 

std::unique_ptr<IRenderFactory> GlobalManager::m_renderFactory;


void GlobalManager::Startup(const std::wstring& strResourcePath, const CreateControlCallback& callback, bool bAdaptDpi, const std::wstring& theme, const std::wstring& language)
{
	m_renderFactory = std::make_unique<RenderFactory_GdiPlus>();

   然后,由工厂类,创建各种具体的接口派生实现类

 

std::unique_ptr<ui::IRenderContext> GlobalManager::CreateRenderContext()
{
	std::unique_ptr<ui::IRenderContext> p;
	p.reset(m_renderFactory->CreateRenderContext());
	return p;
}

std::unique_ptr<ui::IPen> GlobalManager::CreatePen(DWORD color, int width /*= 1*/)
{
	std::unique_ptr<ui::IPen> p;
	p.reset(m_renderFactory->CreatePen(color, width));
	return p;
}

std::unique_ptr<ui::IBrush> GlobalManager::CreateBrush(DWORD color)
{
	std::unique_ptr<ui::IBrush> p;
	p.reset(m_renderFactory->CreateBrush(color));
	return p;
}

std::unique_ptr<ui::IMatrix> GlobalManager::CreateMatrix()
{
	std::unique_ptr<ui::IMatrix> p;
	p.reset(m_renderFactory->CreateMatrix());
	return p;
}

std::unique_ptr<ui::IPath> GlobalManager::CreatePath()
{
	std::unique_ptr<ui::IPath> p;
	p.reset(m_renderFactory->CreatePath());
	return p;
}



 

 

void GlobalManager::Shutdown()
{
	if (g_hzip)
	{
		CloseZip(g_hzip);
		g_hzip = NULL;
	}
	m_renderFactory.reset();
	RemoveAllFonts();
	Gdiplus::GdiplusShutdown(g_gdiplusToken);
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!