Delphi 将TImageList图示符绘制到TDirect2DCanvas

Delphi 将TImageList图示符绘制到TDirect2DCanvas,delphi,vcl,direct2d,directwrite,timagelist,Delphi,Vcl,Direct2d,Directwrite,Timagelist,我目前正准备将一个旧组件的绘图代码从GDI+UniScribe替换为Direct2D和DirectWrite(后续版本) 到目前为止,转换是直接进行的,因为我需要做的大部分时间都是将对画布(类TCanvas)的调用替换为自定义FDirect2DCanvas实例(类TDirect2DCanvas,来自单元Direct2D) 不幸的是,当尝试从TImageList实例在FDirect2DCanvas上绘制glyph时,它似乎并没有那么简单,因为draw方法仅适用于TCanvas,而不适用于相当通用的

我目前正准备将一个旧组件的绘图代码从GDI+UniScribe替换为Direct2D和DirectWrite(后续版本)

到目前为止,转换是直接进行的,因为我需要做的大部分时间都是将对画布(类TCanvas)的调用替换为自定义FDirect2DCanvas实例(类TDirect2DCanvas,来自单元Direct2D)

不幸的是,当尝试从TImageList实例在FDirect2DCanvas上绘制glyph时,它似乎并没有那么简单,因为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
    。存储这些,而不是图像列表。然后,当需要绘制时,在
    RenderTarget
    上调用
    DrawBitmap
    ,传递
    ID2D1Bitmap