将 TImageList 字形绘制到 TDirect2DCanvas



我目前正在将旧组件的绘图代码从GDI + UniScribe替换为Direct2D和DirectWrite(后续产品)。

到目前为止,过渡是直截了当的,因为大多数时候我需要做的就是将对 Canvas(类 TCanvas)的调用替换为自定义 FDirect2DCanvas 实例(类 TDirect2DCanvas,来自单元 Direct2D)。

不幸的是,当尝试将字形从 TImageList 实例绘制到 FDirect2DCanvas 上时,这似乎并不那么简单,因为绘制方法仅适用于 TCanvas,而不是相当通用的 TCustomCanvas(它是 TCanvas 和 TDirect2DCanvas 的祖先)。

解决这一困境的方法是将 TImageList 字形绘制到临时位图中,并将其绘制到 TDirect2DCanvas。但是,我担心这可能会大大减慢绘图性能。

到目前为止,有没有人这样做过?我有哪些选择?

如果您查看如何实现绘制图形对象以TDirect2DCanvas,您会发现它通过此例程进行路由。

procedure TDirect2DCanvas.StretchDraw(const Rect: TRect; Graphic: TGraphic;
Opacity: Byte);
var
D2DBitmap:  ID2D1Bitmap;
D2DRect: TD2DRectF;
Bitmap: TBitmap;
begin
Bitmap := TBitmap.Create;
try
Bitmap.Assign(Graphic);
D2DBitmap := CreateBitmap(Bitmap);
D2DRect.Left   := Rect.Left;
D2DRect.Right  := Rect.Right;
D2DRect.Top    := Rect.Top;
D2DRect.Bottom := Rect.Bottom;
RenderTarget.DrawBitmap(D2DBitmap, @D2DRect, Opacity/255);
finally
Bitmap.Free;
end;
end;

让我们取消选择所涉及的步骤:

  1. 创建临时位图。
  2. 将图形复制到该位图中。
  3. 创建一个ID2D1Bitmap并将临时位图复制到其中。
  4. 将该ID2D1Bitmap绘制到呈现器目标上。

这看起来已经非常低效了。当然,调用这个函数传入TBitmap并无缘无故地制作副本会很令人讨厌。

当您尝试混合两个不同的图形框架时,这种事情很难避免。你的图像列表是基于 GDI 的,因此当你尝试将其发送到 Direct2D 画布时,必然会遇到摩擦。根本无法将 GDI 位图直接传递到 Direct2D 画布,必须先将它们转换为 Direct2D 位图。

如果性能对您很重要,那么您不应该从映像列表开始。当您从 GDI 图像列表中提取位图,然后将其转换为等效的 Direct2D 对象时,这将不可避免地产生成本,ID2D1Bitmap

为了获得最佳性能,请勿使用图像列表。从图像列表中提取每个图像,并使用TDirect2DCanvas.CreateBitmap获取 Direct2D 位图,ID2D1Bitmap。存储这些而不是图像列表。然后当你需要画画时,在RenderTarget上调用DrawBitmap,传递一个ID2D1Bitmap

相关内容

  • 没有找到相关文章

最新更新