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?
答案 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;
让我们解开所涉及的步骤:
ID2D1Bitmap
并将临时位图复制到其中。ID2D1Bitmap
绘制到渲染目标上。这看起来效率很低。当然,调用这个函数传递TBitmap
并且没有充分理由制作副本会很麻烦。
当您尝试混合两个不同的图形框架时,很难避免这种情况。您的图像列表是基于GDI的,因此在尝试将其发送到Direct2D画布时会遇到摩擦。根本无法将GDI位图直接传递给Direct2D画布,它们必须首先转换为Direct2D位图。
如果性能对您而言重要,那么您不应该从图像列表开始。当您从GDI图像列表中提取位图,然后将其转换为等效的Direct2D对象ID2D1Bitmap
时,这将不可避免地产生成本。
为了获得最佳性能,请勿使用图像列表。从图像列表中提取每个图像,并使用TDirect2DCanvas.CreateBitmap
获取Direct2D位图ID2D1Bitmap
。存储这些而不是图像列表。然后,当您需要绘制时,请在DrawBitmap
上拨打RenderTarget
,然后传递ID2D1Bitmap
。