The TSVGDocument class is the base class for parsing a SVG and generating TSVGxxxElement classes to describe the SVG. Use the TSVGDocument class to load an SVG and paint the SVG to a TCanvas.
The TSVGDocument is only available at run-time. The TRSSVGDocument (VCL) and TRSFMXSVGDocument (FMX) components expose the TSVGDocument for loading at design-time. To use the TSVGDocument to load an SVG, perform the following steps:
procedure TForm20.FormCreate(Sender: TObject); Doc.LoadFromFile('c:\MySVG.svg'); |
The TSVGDocument can be drawn to any TCanvas (though with a printer in VCL, you need to draw to an offscreen bitmap/png and then draw that to the printer.canvas). The following code paints to a TPaintBox.Canvas (FMX): procedure TForm20.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
The VCL code is only slightly more complicated uses RSSVGTypes, RSGraphics;
procedure TForm1.PaintBox1Paint(Sender: TObject); var aCanvas: TSVGCanvas; begin aCanvas := TSVGCanvas.Create(PaintBox1.Canvas); try Doc.Draw(aCanvas, RectToRSRect(PaintBox1.ClientRect)); finally aCanvas.Free; end; end;
|
The TSVGDocument.DefaultAspectRatio property allows you to define a default aspect ratio for the SVG. If the SVG does not specify a preserveAspectRatio attribute, the SVG will use the default aspect ratio instead. The Aspect Ratio defines how the viewport stretches graphics to fill the rectangle. After loading an SVG, you can also define the aspect ratio for the SVG. procedure TForm20.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); Doc.AspectRatio.Align := saXMidYMid; |
Sometimes you want to be able to change an SVG element's appearance and rapidly redraw only that element. By using the TSVGDocument.DrawBeforeElement method and the TSVGDocument.DrawAfterElement methods, you can draw the "background" and "foreground" for an element to bitmap buffers. Then, when a SVG element changes, you just draw the background bitmap, call TSVGDocument.DrawElement for the changing element, and then draw the foreground bitmap.
The following example uses the DrawBeforeElement, DrawElement, and DrawAfterElement methods to optimize the drawing of an SVG where one element may be changed often (such as in an editor): procedure TfrmSVGEditor.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); var aRect: TSVGRect; begin // do we need to update the background (elements before) and foreground (elements // after) the current Element. By creating a bitmap of the background and // foreground, we can optimize the drawing of the SVG as the current Element // changes if UpdateBackground then begin // draw background and foreground Background.Canvas.BeginScene; try Background.Clear(TAlphaColorRec.Null); if Element is TSVGGraphicElement then SVG.DrawBeforeElement(TSVGGraphicElement(Element), Background.Canvas, RectF(0,0,Background.Width, Background.Height)); finally Background.Canvas.EndScene; end; Foreground.Canvas.BeginScene; try Foreground.Clear(TAlphaColorRec.Null); if Element is TSVGGraphicElement then SVG.DrawAfterElement(TSVGGraphicElement(Element), Foreground.Canvas, RectF(0,0,Foreground.Width, Foreground.Height)); finally Foreground.Canvas.EndScene; end; FUpdateBackground := False; end; if Element is TSVGGraphicElement then begin // if current Element is a graphical element, draw the background aRect := RectF(0, 0, Background.Width, Background.Height); Canvas.DrawBitmap(Background, aRect, aRect, 1); // draw the element SVG.DrawElement(TSVGGraphicElement(Element), Canvas, PaintBox1.ClipRect); // draw the foreground Canvas.DrawBitmap(Foreground, aRect, aRect, 1); end else // just draw the entire SVG without any background/foreground caching SVG.Draw(Canvas, PaintBox1.ClipRect); // draw the focus rectangle Canvas.DrawFocusRect(SelectRect); end;
The SVGEditorFMX demo project uses this technique to provide rapid response to user changes. |