Skip to content

TFmxImageSVG (FMX)

Unit: FMX.ImageSVG

Inherits from: TObject

Description

TFmxImageSVG is the base abstract class for SVG rendering in FireMonkey applications. It provides a unified interface for SVG document manipulation and rendering, implemented by different rendering engines (Image32, Skia4Delphi).

This class is used internally by all SVG components but can also be used directly for low-level SVG manipulation and custom rendering scenarios.

Purpose

TFmxImageSVG abstracts the SVG rendering engine, providing:

  • Engine Independence: Code works with any rendering engine
  • Unified API: Consistent interface across Image32 and Skia4Delphi
  • Direct Rendering: Paint SVG directly to bitmaps
  • Property Management: Control colors, opacity, and effects

Properties

SVG Content

Source: String

pascal
property Source: string read GetSource;

Read-only access to the raw SVG XML source.

Example:

pascal
var
  SVG: TFmxImageSVG;
begin
  SVG := GlobalSVGFactory.NewSvg;
  SVG.LoadFromFile('icon.svg');
  Memo1.Text := SVG.Source; // Display SVG XML
end;

Rendering Attributes

FixedColor: TAlphaColor

pascal
property FixedColor: TAlphaColor read GetFixedColor write SetFixedColor;

Override all colors in the SVG with this fixed color. Use TAlphaColorRec.Null to preserve original colors.

Example:

pascal
SVG.FixedColor := TAlphaColorRec.Blue; // All elements become blue
SVG.FixedColor := TAlphaColorRec.Null; // Restore original colors

ApplyFixedColorToRootOnly: Boolean

pascal
property ApplyFixedColorToRootOnly: Boolean read GetApplyFixedColorToRootOnly write SetApplyFixedColorToRootOnly;

When True, applies FixedColor only to the root SVG element. Default: False.

Example:

pascal
SVG.FixedColor := TAlphaColorRec.Red;
SVG.ApplyFixedColorToRootOnly := True; // Only root changes color

GrayScale: Boolean

pascal
property GrayScale: Boolean read GetGrayScale write SetGrayScale;

Renders the SVG in grayscale. Default: False.

Example:

pascal
SVG.GrayScale := True; // Convert to grayscale

Opacity: Single

pascal
property Opacity: Single read GetOpacity write SetOpacity;

Overall opacity of the SVG (0.0 = transparent, 1.0 = opaque). Default: 1.0.

Example:

pascal
SVG.Opacity := 0.5; // 50% transparent

Methods

Construction

Create

pascal
constructor Create; virtual;

Creates a new TFmxImageSVG instance. Use the factory pattern instead of calling directly.

Recommended:

pascal
var
  SVG: TFmxImageSVG;
begin
  SVG := GlobalSVGFactory.NewSvg; // Use factory
  try
    // Use SVG...
  finally
    SVG.Free;
  end;
end;

Loading SVG Content

LoadFromFile

pascal
procedure LoadFromFile(const FileName: string);

Loads SVG content from a file.

Example:

pascal
var
  SVG: TFmxImageSVG;
begin
  SVG := GlobalSVGFactory.NewSvg;
  try
    SVG.LoadFromFile('C:\Icons\home.svg');
    // Use SVG...
  finally
    SVG.Free;
  end;
end;

LoadFromStream

pascal
procedure LoadFromStream(Stream: TStream); virtual; abstract;

Loads SVG content from a stream. Implementation provided by derived classes.

Example:

pascal
var
  SVG: TFmxImageSVG;
  Stream: TFileStream;
begin
  SVG := GlobalSVGFactory.NewSvg;
  Stream := TFileStream.Create('icon.svg', fmOpenRead);
  try
    SVG.LoadFromStream(Stream);
    // Use SVG...
  finally
    Stream.Free;
    SVG.Free;
  end;
end;

LoadFromText

pascal
procedure LoadFromText(const ASVGText: string);

Loads SVG content from a string.

Example:

pascal
const
  SVG_CONTENT = '<svg width="100" height="100"><circle cx="50" cy="50" r="40" fill="blue"/></svg>';
var
  SVG: TFmxImageSVG;
begin
  SVG := GlobalSVGFactory.NewSvg;
  try
    SVG.LoadFromText(SVG_CONTENT);
    // Use SVG...
  finally
    SVG.Free;
  end;
end;

Saving SVG Content

SaveToFile

pascal
procedure SaveToFile(const FileName: string);

Saves current SVG content to a file.

Example:

pascal
SVG.SaveToFile('C:\Output\modified.svg');

SaveToStream

pascal
procedure SaveToStream(Stream: TStream);

Saves current SVG content to a stream.

Example:

pascal
var
  Stream: TMemoryStream;
begin
  Stream := TMemoryStream.Create;
  try
    SVG.SaveToStream(Stream);
    Stream.Position := 0;
    // Process stream...
  finally
    Stream.Free;
  end;
end;

Rendering

PaintToBitmap

pascal
procedure PaintToBitmap(ABitmap: TBitmap; const AZoom: Integer = 100; const KeepAspectRatio: Boolean = True); virtual; abstract;

Renders the SVG to a bitmap. Implementation provided by derived classes.

Parameters:

  • ABitmap: Target bitmap (must be already sized)
  • AZoom: Zoom percentage (10-100), default 100
  • KeepAspectRatio: Maintain SVG aspect ratio, default True

Example:

pascal
var
  SVG: TFmxImageSVG;
  Bitmap: TBitmap;
begin
  SVG := GlobalSVGFactory.NewSvg;
  SVG.LoadFromFile('icon.svg');

  Bitmap := TBitmap.Create(64, 64);
  try
    SVG.PaintToBitmap(Bitmap, 100, True);
    Image1.Bitmap.Assign(Bitmap);
  finally
    Bitmap.Free;
    SVG.Free;
  end;
end;

State Check

IsEmpty

pascal
function IsEmpty: Boolean; virtual; abstract;

Returns True if no SVG content is loaded.

Example:

pascal
if SVG.IsEmpty then
  ShowMessage('No SVG loaded')
else
  ShowMessage('SVG is loaded');

Usage Examples

Basic SVG Rendering

pascal
procedure TForm1.RenderSVG;
var
  SVG: TFmxImageSVG;
  Bitmap: TBitmap;
begin
  SVG := GlobalSVGFactory.NewSvg;
  try
    // Load SVG
    SVG.LoadFromFile('logo.svg');

    // Configure rendering
    SVG.FixedColor := TAlphaColorRec.Blue;
    SVG.Opacity := 0.8;

    // Render to bitmap
    Bitmap := TBitmap.Create(128, 128);
    try
      SVG.PaintToBitmap(Bitmap, 100, True);
      Image1.Bitmap.Assign(Bitmap);
    finally
      Bitmap.Free;
    end;
  finally
    SVG.Free;
  end;
end;

Load and Modify SVG

pascal
procedure TForm1.ModifySVG;
var
  SVG: TFmxImageSVG;
begin
  SVG := GlobalSVGFactory.NewSvg;
  try
    // Load original
    SVG.LoadFromFile('original.svg');

    // Apply modifications
    SVG.FixedColor := TAlphaColorRec.Red;
    SVG.GrayScale := False;
    SVG.Opacity := 1.0;

    // Save modified
    SVG.SaveToFile('modified.svg');
  finally
    SVG.Free;
  end;
end;

Render at Multiple Sizes

pascal
procedure TForm1.RenderMultipleSizes;
var
  SVG: TFmxImageSVG;
  Bitmap: TBitmap;
  Sizes: array[0..3] of Integer;
  I: Integer;
begin
  Sizes[0] := 16;
  Sizes[1] := 32;
  Sizes[2] := 64;
  Sizes[3] := 128;

  SVG := GlobalSVGFactory.NewSvg;
  try
    SVG.LoadFromFile('icon.svg');

    for I := 0 to High(Sizes) do
    begin
      Bitmap := TBitmap.Create(Sizes[I], Sizes[I]);
      try
        SVG.PaintToBitmap(Bitmap, 100, True);
        Bitmap.SaveToFile(Format('icon_%dx%d.png', [Sizes[I], Sizes[I]]));
      finally
        Bitmap.Free;
      end;
    end;
  finally
    SVG.Free;
  end;
end;

Create Thumbnail

pascal
procedure TForm1.CreateThumbnail(const ASourceFile, ATargetFile: string; ASize: Integer);
var
  SVG: TFmxImageSVG;
  Bitmap: TBitmap;
begin
  SVG := GlobalSVGFactory.NewSvg;
  try
    SVG.LoadFromFile(ASourceFile);

    Bitmap := TBitmap.Create(ASize, ASize);
    try
      SVG.PaintToBitmap(Bitmap, 100, True);
      Bitmap.SaveToFile(ATargetFile);
    finally
      Bitmap.Free;
    end;
  finally
    SVG.Free;
  end;
end;

Batch Process SVG Files

pascal
procedure TForm1.BatchConvertToGrayscale(const APath: string);
var
  Files: TStringDynArray;
  SVG: TFmxImageSVG;
  FileName, OutputName: string;
begin
  Files := TDirectory.GetFiles(APath, '*.svg');

  for FileName in Files do
  begin
    SVG := GlobalSVGFactory.NewSvg;
    try
      SVG.LoadFromFile(FileName);
      SVG.GrayScale := True;

      OutputName := TPath.ChangeExtension(FileName, '_gray.svg');
      SVG.SaveToFile(OutputName);
    finally
      SVG.Free;
    end;
  end;
end;

Apply Theme Colors

pascal
procedure TForm1.ApplyThemeToSVG(const AFileName: string; ADarkMode: Boolean);
var
  SVG: TFmxImageSVG;
begin
  SVG := GlobalSVGFactory.NewSvg;
  try
    SVG.LoadFromFile(AFileName);

    if ADarkMode then
      SVG.FixedColor := TAlphaColorRec.White
    else
      SVG.FixedColor := TAlphaColorRec.Black;

    SVG.SaveToFile(AFileName); // Overwrite
  finally
    SVG.Free;
  end;
end;

Generate Icon Variations

pascal
procedure TForm1.GenerateColorVariations(const ASourceFile: string);
var
  SVG: TFmxImageSVG;
  Colors: array[0..2] of record Name: string; Color: TAlphaColor; end;
  I: Integer;
  OutputName: string;
begin
  Colors[0].Name := 'red';
  Colors[0].Color := TAlphaColorRec.Red;
  Colors[1].Name := 'green';
  Colors[1].Color := TAlphaColorRec.Green;
  Colors[2].Name := 'blue';
  Colors[2].Color := TAlphaColorRec.Blue;

  SVG := GlobalSVGFactory.NewSvg;
  try
    SVG.LoadFromFile(ASourceFile);

    for I := 0 to High(Colors) do
    begin
      SVG.FixedColor := Colors[I].Color;
      OutputName := TPath.GetFileNameWithoutExtension(ASourceFile) +
                    '_' + Colors[I].Name + '.svg';
      SVG.SaveToFile(OutputName);
    end;
  finally
    SVG.Free;
  end;
end;

Custom Rendering Loop

pascal
procedure TForm1.AnimatedRender;
var
  SVG: TFmxImageSVG;
  Bitmap: TBitmap;
  Opacity: Single;
begin
  SVG := GlobalSVGFactory.NewSvg;
  try
    SVG.LoadFromFile('icon.svg');

    Bitmap := TBitmap.Create(100, 100);
    try
      // Fade animation
      Opacity := 0.0;
      while Opacity <= 1.0 do
      begin
        SVG.Opacity := Opacity;
        SVG.PaintToBitmap(Bitmap, 100, True);
        Image1.Bitmap.Assign(Bitmap);
        Application.ProcessMessages;
        Sleep(50);
        Opacity := Opacity + 0.1;
      end;
    finally
      Bitmap.Free;
    end;
  finally
    SVG.Free;
  end;
end;

Factory Pattern

Always use the factory pattern to create TFmxImageSVG instances:

pascal
// Correct: Use factory
var
  SVG: TFmxImageSVG;
begin
  SVG := GlobalSVGFactory.NewSvg;
  try
    // Use SVG...
  finally
    SVG.Free;
  end;
end;

// Wrong: Direct instantiation
// SVG := TFmxImageSVG.Create; // Don't do this!

The factory automatically creates the correct derived class based on the selected rendering engine (Image32 or Skia4Delphi).

Derived Classes

TFmxImageSVG is abstract. Concrete implementations:

  • TImage32SVG - Image32 engine implementation
  • TImageSkiaSVG - Skia4Delphi engine implementation

The factory (GlobalSVGFactory.NewSvg) automatically creates the correct class based on compilation defines:

  • {$DEFINE FMX_Image32_SVGEngine} → TImage32SVG
  • {$DEFINE FMX_Skia_SVGEngine} → TImageSkiaSVG

Thread Safety

TFmxImageSVG instances are NOT thread-safe. Each thread should create its own instance:

pascal
// Safe: Each thread has its own SVG instance
TTask.Run(
  procedure
  var
    SVG: TFmxImageSVG;
  begin
    SVG := GlobalSVGFactory.NewSvg;
    try
      SVG.LoadFromFile('icon.svg');
      // Process...
    finally
      SVG.Free;
    end;
  end
);

Memory Management

Always free TFmxImageSVG instances:

pascal
var
  SVG: TFmxImageSVG;
begin
  SVG := GlobalSVGFactory.NewSvg;
  try
    // Use SVG...
  finally
    SVG.Free; // Always free!
  end;
end;

See Also

Released under Apache License, Version 2.0.