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

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

不幸的是,当尝试从TImageList实例将字形绘制到FDirect2DCanvas上时似乎并不那么简单,因为draw方法仅适用于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;


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


创建一个临时位图。
将图形复制到该位图中。
创建一个ID2D1Bitmap并将临时位图复制到其中。
将该ID2D1Bitmap绘制到渲染目标上。


这看起来效率很低。当然,调用此函数传入TBitmap并出于没有充分理由制作副本会很麻烦。

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

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

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

关于delphi - 将TImageList字形绘制到TDirect2DCanvas,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44565105/

10-10 16:56