2017-06-15 62 views
2

我目前正在將舊組件的繪製代碼從GDI + UniScribe替換爲Direct2D和DirectWrite(後繼)。將TImageList字形繪製到TDirect2DCanvas

到目前爲止,過渡很簡單,因爲大部分時間我需要做的是將對Canvas(類TCanvas)的調用替換爲自定義的FDirect2DCanvas實例(來自Direct2D單元的TDirect2DCanvas類)。

不幸的是,當試圖從TImageList實例繪製字形到FDirect2DCanvas時,看起來並不那麼簡單,因爲繪製方法僅用於TCanvas,而不用於相當一般的TCustomCanvas(它是TCanvas和TCanvas的祖先) TDirect2DCanvas)。

解決這個困境的解決方案是將繪製的TImageList字形到一個臨時位圖和畫本的TDirect2DCanvas。不過,我擔心這可能會大大減緩繪圖性能。

到目前爲止,有沒有人做過這件事?我有什麼選擇?

回答

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繪製到渲染目標上。

這看起來已經非常低效。當然,將這個函數傳遞給TBitmap並且沒有正當理由複製這個函數會很糟糕。

雖然當您嘗試混合兩個不同的圖形框架,但這種事情很難避免。您的圖像列表基於GDI,當您嘗試將其發送到Direct2D畫布時,會受到摩擦。沒有辦法將GDI位圖直接傳遞給Direct2D畫布,必須先將其轉換爲Direct2D位圖。

如果表現對你至關重要,那麼你不應該從圖像列表開始。當您從GDI圖像列表中提取位圖時,這將不可避免地產生成本,然後將其轉換爲等效的Direct2D對象ID2D1Bitmap

爲了實現最佳性能,請不要使用圖像列表。從圖像列表中提取每個圖像並使用TDirect2DCanvas.CreateBitmap獲取Direct2D位圖,ID2D1Bitmap。存儲這些而不是圖像列表。然後,當你需要畫畫時,請致電DrawBitmapRenderTarget,傳遞ID2D1Bitmap