blend2d + MFC
blend2d
+ MFC
Blend2D
是一种基于软件的2D渲染库,具有JIT管道构造,旨在成为高性能矢量图形引擎,由于多线程处理,它现在变得更快。
我简单尝试了一下,测试了上万个点的生成,贴到窗口上,感觉是要比直接画要快一些。理论上采用多线程生成位图再贴到窗口上是要比直接在窗口上画要快好多。这个库官网上的性能对比看起来就是吊打其他2d
绘图方式了,不过还是自己用得爽才算行。可以看看这个库官方的测评
。
官方文档上面只有配合qt
和生成图片的例子,我自己平时不太喜欢用qt
,想在mfc上用一下,对照看了qt
上的使用原理,自己实现了一下,如果你有更好的使用方式,可以指导一下告诉我。
简单说明
Blend2D
最终是生成位图数据的,只不过生成位图的过程用到了多线程的,这样提高了绘制的效率,在实际用的时候,将位图数据贴到窗口上就算完成了显示。
我用到了MFC
的的CImage
类,创建了一个和窗口同尺寸的图片,和BLImage
绑定一起,让Blend2D
的绘图直接在CImage
的内存上生成,最后用CImage
的函数BitBlt
贴到窗口上。
具体实现
.h
CImage m_bckImge;
BLImage m_blImage;
BLContext m_ctx;
BLContextCreateInfo createInfo{};
.cpp
Cblend2dDemoDlg::Cblend2dDemoDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_BLEND2DDEMO_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
createInfo.threadCount = 8; // Blend2D绘图时使用的线程数
}
void Cblend2dDemoDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
CRect rcWnd;
GetWindowRect(rcWnd);
m_blImage.reset();
m_bckImge.Destroy();
m_bckImge.Create(rcWnd.Width(), rcWnd.Height(), 32);
m_blImage.createFromData(m_bckImge.GetWidth(), m_bckImge.GetHeight(), BL_FORMAT_XRGB32, m_bckImge.GetBits(), m_bckImge.GetPitch());
}
void Cblend2dDemoDlg::drawMapBlend2d()
{
CRect rcWnd;
GetWindowRect(rcWnd);
BLContext ctx(m_blImage, createInfo);
ctx.setFillStyle(BLRgba32(0xFF000000));
ctx.fillAll();
BLPath path;
BLGradient linear(BLLinearGradientValues(0, 0, 0, 480));
linear.addStop(0.0, BLRgba32(0xFFFFFFFF));
int yLen = m_blImage.height();
int xLen = m_blImage.width();
int xCenter = m_blImage.width() / 2;
int yCenter = m_blImage.height() / 2;
path.addLine(BLLine(0, yCenter, xLen, yCenter));
path.addLine(BLLine(xCenter, 0, xCenter, yLen));
// 圆
path.addCircle(BLCircle(xCenter / 2, xCenter / 2, 50));
// 弧
path.addArc(BLArc(150, 150, 50, 50, 0, 120 * M_PI / 180.0f));
BLFontFace face;
BLResult err = face.createFromFile("arial.ttf");
// 文字
BLFont font;
font.createFromFace(face, 50.0f);
ctx.setFillStyle(BLRgba32(0xFFFFFFFF));
ctx.fillUtf8Text(BLPoint(xCenter + 150, 180), font, "Hello World!");
ctx.setCompOp(BL_COMP_OP_SRC_OVER);
ctx.setStrokeStyle(linear);
ctx.setStrokeWidth(1);
ctx.strokePath(path);
ctx.end();
m_bckImge.BitBlt(GetDC()->GetSafeHdc(), 0, 0, m_bckImge.GetWidth(), m_bckImge.GetHeight(), 0, 0, SRCCOPY);
}
void Cblend2dDemoDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
CRect rcWnd;
GetWindowRect(rcWnd);
m_blImage.reset();
m_bckImge.Destroy();
m_bckImge.Create(rcWnd.Width(), rcWnd.Height(), 32);
// GetPitch这个很重要了,图像的间距
m_blImage.createFromData(m_bckImge.GetWidth(), m_bckImge.GetHeight(), BL_FORMAT_XRGB32, m_bckImge.GetBits(), m_bckImge.GetPitch());
}