2017-06-15 5 views
2

Ich bin im Begriff, den Zeichnungscode für eine alte Komponente von GDI + UniScribe zu Direct2D und DirectWrite (die Nachfolger) zu ersetzen.Zeichnen eines TImageList Glyph zu einem TDirect2DCanvas

Bisher war der Übergang einfach, da ich die meiste Zeit nur Aufrufe an Canvas (Klasse TCanvas) an eine benutzerdefinierte FDirect2DCanvas-Instanz (Klasse TDirect2DCanvas, aus der Unit Direct2D) ersetzen musste.

Leider ist es nicht so einfach erscheinen, wenn eine Glyphe aus einer TImageList Instanz auf die FDirect2DCanvas als das Ziehverfahren nur zu ziehen versucht, für TCanvas gemeint ist und nicht für die eher allgemeine TCustomCanvas (das ist die Vorfahre der beiden TCanvas und TDirect2DCanvas).

Eine Lösung für dieses Dilemma wäre, das TImageList-Zeichen in ein temporäres Bitmap zu zeichnen und dieses auf TDirect2DCanvas zu zeichnen. Ich befürchte jedoch, dass dies die Ziehungsleistung sehr verlangsamen wird.

Hat das bisher jemand soweit gemacht? Welche Möglichkeiten habe ich?

Antwort

2

Wenn Sie sich ansehen, wie das Zeichnen von Grafikobjekten auf TDirect2DCanvas implementiert ist, werden Sie feststellen, dass es diese Routine durchläuft.

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; 

Lassen Sie uns die Schritte unpick beteiligt: ​​

  1. eine temporäre Bitmap erstellen.
  2. Kopieren Sie die Grafik in diese Bitmap.
  3. Erstellen Sie eine ID2D1Bitmap und kopieren Sie die temporäre Bitmap hinein.
  4. Zeichnen Sie diese ID2D1Bitmap auf das Renderziel.

Das sieht schon ziemlich ineffizient aus. Sicher wäre es ärgerlich diese Funktion in einer TBitmap zu nennen und eine Kopie ohne guten Grund zu haben.

Diese Art der Sache ist schwer zu vermeiden, wenn Sie versuchen, zwei verschiedene Grafik-Frameworks zu mischen. Ihre Bilderliste basiert auf GDI und ist daher auf Reibung angewiesen, wenn Sie versuchen, sie an eine Direct2D-Arbeitsfläche zu senden. Es gibt einfach keine Möglichkeit, GDI-Bitmaps direkt an ein Direct2D-Canvas zu übergeben, sie müssen zuerst in Direct2D-Bitmaps konvertiert werden.

Wenn Ihnen die Leistung wichtig ist, sollten Sie nicht von einer Bildliste ausgehen. Dies wird unweigerlich Kosten verursachen, wenn Sie die Bitmap aus der GDI-Bildliste extrahieren und dann in das entsprechende Direct2D-Objekt ID2D1Bitmap konvertieren.

Um eine optimale Leistung zu erzielen, arbeiten Sie nicht mit Bildlisten. Extrahieren Sie jedes Bild aus der Bildliste und verwenden Sie TDirect2DCanvas.CreateBitmap, um eine Direct2D-Bitmap zu erhalten, ID2D1Bitmap. Speichern Sie diese statt der Bilderliste. Dann, wenn Sie zeichnen müssen, rufen Sie DrawBitmap auf RenderTarget, unter der ID2D1Bitmap.