Drawing a TImageList glyph to a TDirect2DCanvas

时间:2017-06-15 10:26:20

标签: delphi vcl direct2d directwrite timagelist

I'm currently about to replace the drawing code for an old component from GDI + UniScribe to Direct2D and DirectWrite (the successors).

So far the transition was straight forward as most of the time all I need to do was to replace calls to the Canvas (class TCanvas) to a custom FDirect2DCanvas instance (class TDirect2DCanvas, from the unit Direct2D).

Unfortunately it doesn't seem that simple when trying to draw a glyph from a TImageList instance onto the FDirect2DCanvas as the draw method is only meant for TCanvas and not for the rather general TCustomCanvas (which is the ancestor of both TCanvas and TDirect2DCanvas).

A solution for this dilemma would be to draw the TImageList glyph to a temporary bitmap and draw this to the TDirect2DCanvas. However, I fear this will probably slow down the drawing performance a lot.

Has anyone so far done this so far? What options do I have?

1 个答案:

答案 0 :(得分:2)

如果你看一下如何实现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绘制到渲染目标上。
  5. 这看起来效率很低。当然,调用这个函数传递TBitmap并且没有充分理由制作副本会很麻烦。

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

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

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