Skip to content

FAQ - Advanced Topics

This page covers advanced usage scenarios, troubleshooting, and best practices for the SVGIconImageList library.

Architecture and Design

Q. What is the difference between TSVGIconImageList and TSVGIconImageCollection?

A. They serve different purposes in the architecture:

  • TSVGIconImageList: Self-contained component that stores AND renders SVG icons. Suitable for simple scenarios and all Delphi versions (XE6+). Each image list has its own icon storage.

  • TSVGIconImageCollection (Delphi 10.3+): Storage-only component that holds SVG icons without rendering. Used with TSVGIconVirtualImageList for rendering. Multiple virtual lists can share one collection, saving memory when you need the same icons at different sizes.

When to use each:

  • Use TSVGIconImageList for single-size icon lists, quick prototyping, or Delphi versions before 10.3
  • Use TSVGIconImageCollection + TSVGIconVirtualImageList for modern applications needing multiple sizes, centralized management, or memory efficiency

Q. How do the four rendering engines (Image32, Skia, Direct2D, SVGMagic) compare?

A. Here's a detailed comparison:

FeatureImage32Skia4DelphiDirect2DSVGMagic
PlatformWindows, AllWindows, AllWindows onlyWindows only
PerformanceGoodExcellentExcellentGood
SVG ComplianceHighHighestHighMedium
Memory UsageLowMediumLowLow
DependenciesNoneSkia DLLWindows 7+SVGMagic DLL
Setup ComplexityEasyMediumEasyMedium
Best ForGeneral useHigh qualityNative WindowsLegacy projects

Recommendations:

  • Image32: Default choice, good all-around performance, no dependencies
  • Skia4Delphi: Best rendering quality, cross-platform, worth the setup for production apps
  • Direct2D: Excellent for Windows-only apps using modern OS features
  • SVGMagic: Available for compatibility, consider migrating to Image32/Skia

Q. Can I switch rendering engines at runtime?

A. Yes, but with limitations:

pascal
// Switch global factory
SetGlobalSvgFactory(GetSkiaSVGFactory);

// Existing icons must be reloaded or updated
SVGIconImageList1.RecreateBitmaps;

// New icons will automatically use the new factory

Important notes:

  • Only one engine can be active at a time per application
  • Switching engines clears the SVG cache
  • Some engine-specific features may not transfer
  • Best practice: Choose engine at application startup

Performance Optimization

Q. How can I improve icon rendering performance?

A. Follow these optimization strategies:

1. Use Appropriate Icon Sizes

pascal
// Good: Use standard sizes that match UI elements
SVGIconImageList1.Size := 16;  // For toolbars
SVGIconImageList2.Size := 32;  // For buttons

// Avoid: Constantly changing sizes
for I := 16 to 128 do
  SVGIconImageList1.Size := I;  // Regenerates bitmaps each time!

2. Leverage Bitmap Caching

pascal
// Icons are cached after first render
// Requesting the same size again is fast
SVGIconImageList1.Size := 32;  // Renders and caches
// ... later ...
SVGIconImageList1.Size := 48;  // Renders and caches
// ... later ...
SVGIconImageList1.Size := 32;  // Uses cache, very fast!

3. Use Virtual ImageLists

pascal
// Memory efficient for multiple sizes
SVGIconImageCollection1.LoadFromFiles(Files);  // Load once

SmallList.ImageCollection := SVGIconImageCollection1;
SmallList.Size := 16;

LargeList.ImageCollection := SVGIconImageCollection1;
LargeList.Size := 48;

// Storage shared, minimal overhead for multiple sizes

4. Avoid Unnecessary Redraws

pascal
// Bad: Triggers redraw on each property change
SVGIconImageList1.BeginUpdate;
try
  SVGIconImageList1.FixedColor := clBlue;
  SVGIconImageList1.Opacity := 200;
  SVGIconImageList1.GrayScale := True;
finally
  SVGIconImageList1.EndUpdate;  // Single redraw
end;

5. Preload Icons

pascal
procedure TForm1.FormCreate(Sender: TObject);
begin
  // Load all icons at startup
  SVGIconImageList1.LoadFromFiles(GetAllIconFiles);

  // Now switching icons is instant (just bitmap copy)
  Button1.ImageIndex := 0;  // Fast
  Button2.ImageIndex := 1;  // Fast
end;

Q. My application loads slowly with many SVG icons. How can I improve startup time?

A. Consider these approaches:

1. Lazy Loading

pascal
procedure TForm1.LoadIconsOnDemand;
begin
  // Don't load all icons at startup
  // Load when needed
  if not IconsLoaded then
  begin
    SVGIconImageList1.LoadFromFiles(CommonIcons);
    IconsLoaded := True;
  end;
end;

2. Background Loading

pascal
procedure TForm1.LoadIconsInThread;
begin
  TTask.Run(
    procedure
    var
      Files: TStringList;
    begin
      Files := GetAllIconFiles;
      TThread.Synchronize(nil,
        procedure
        begin
          SVGIconImageList1.LoadFromFiles(Files);
        end
      );
    end
  );
end;

3. Use Resource Loading

pascal
// Faster than file loading
// Icons embedded in executable
function LoadIconsFromResources: Integer;
begin
  Result := 0;
  Inc(Result, SVGIconCollection1.LoadFromResource(HInstance, 'ICON_HOME', 'home'));
  Inc(Result, SVGIconCollection1.LoadFromResource(HInstance, 'ICON_SETTINGS', 'settings'));
  // ... more icons ...
end;

4. Optimize SVG Files

  • Simplify paths (use SVGO optimizer)
  • Remove unnecessary metadata
  • Minimize decimal precision
  • Remove comments and whitespace

Advanced Styling

Q. How can I implement a complete dark/light theme system?

A. Here's a comprehensive theming approach:

pascal
type
  TThemeMode = (tmLight, tmDark, tmSystem);

  TThemeManager = class
  private
    FCurrentTheme: TThemeMode;
    procedure ApplyThemeToImageList(AImageList: TSVGIconImageListBase; AIsDark: Boolean);
  public
    procedure SetTheme(ATheme: TThemeMode);
    property CurrentTheme: TThemeMode read FCurrentTheme;
  end;

procedure TThemeManager.ApplyThemeToImageList(AImageList: TSVGIconImageListBase; AIsDark: Boolean);
begin
  AImageList.BeginUpdate;
  try
    if AIsDark then
    begin
      AImageList.FixedColor := clWhite;
      AImageList.AntiAliasColor := $202020;
      AImageList.DisabledOpacity := 100;
    end
    else
    begin
      AImageList.FixedColor := clBlack;
      AImageList.AntiAliasColor := clWhite;
      AImageList.DisabledOpacity := 125;
    end;
  finally
    AImageList.EndUpdate;
  end;
end;

procedure TThemeManager.SetTheme(ATheme: TThemeMode);
var
  IsDark: Boolean;
  Component: TComponent;
begin
  // Determine if dark mode
  case ATheme of
    tmLight: IsDark := False;
    tmDark: IsDark := True;
    tmSystem: IsDark := IsWindowsDarkModeEnabled;  // Implement this
  end;

  // Apply to all image lists in application
  for var I := 0 to Screen.FormCount - 1 do
    for var J := 0 to Screen.Forms[I].ComponentCount - 1 do
    begin
      Component := Screen.Forms[I].Components[J];
      if Component is TSVGIconImageListBase then
        ApplyThemeToImageList(TSVGIconImageListBase(Component), IsDark);
    end;

  FCurrentTheme := ATheme;
end;

Q. Can I apply different colors to different parts of an SVG icon?

A. The ApplyFixedColorToRootOnly property provides limited control:

pascal
// Apply red to root element only
SVGIconImage1.FixedColor := clRed;
SVGIconImage1.ApplyFixedColorToRootOnly := True;

For more complex colorization, you need to:

  1. Modify the SVG source directly:
pascal
procedure ColorizeIconParts(Item: TSVGIconItem);
var
  SVGText: string;
begin
  SVGText := Item.SVGText;

  // Replace specific colors in SVG
  SVGText := StringReplace(SVGText, 'fill="#000000"', 'fill="#FF0000"', [rfReplaceAll]);
  SVGText := StringReplace(SVGText, 'fill="#FFFFFF"', 'fill="#0000FF"', [rfReplaceAll]);

  Item.SVGText := SVGText;
end;
  1. Use multiple icon variations:
pascal
// Keep separate icons for different color schemes
Collection.Add(RedHomeIcon, 'home-red');
Collection.Add(BlueHomeIcon, 'home-blue');

Memory Management

Q. How much memory do SVG icons use compared to PNG bitmaps?

A. Memory usage comparison:

PNG Bitmaps (Traditional ImageList):

16x16 @ 32bpp  = 1,024 bytes per icon
32x32 @ 32bpp  = 4,096 bytes per icon
64x64 @ 32bpp  = 16,384 bytes per icon
128x128 @ 32bpp = 65,536 bytes per icon

For 100 icons at multiple sizes:
100 icons × (1KB + 4KB + 16KB + 64KB) = 8.5 MB

SVG Icons (SVGIconImageList):

SVG source text = ~1-5 KB per icon (stored once)
Cached bitmaps = Generated on demand for active size only

For 100 icons:
100 icons × 3KB average = 300 KB (source)
+ Current size bitmaps = 300 KB + 100-6500 KB = ~400KB to 7MB total

Memory savings: Significant when not all sizes are needed simultaneously

Best Practice:

  • Use TSVGIconImageCollection with Virtual ImageLists for maximum efficiency
  • Icons stored once, rendered at requested sizes only
  • Unused sizes are not kept in memory

Q. How can I reduce memory usage in my application?

A. Strategies to minimize memory footprint:

1. Use Virtual ImageLists

pascal
// Instead of multiple TSVGIconImageList instances
// Use one collection with multiple virtual lists
SVGIconImageCollection1.LoadFromFiles(Files);  // ~500KB for 100 icons

VirtualList16.ImageCollection := SVGIconImageCollection1;  // +100KB
VirtualList32.ImageCollection := SVGIconImageCollection1;  // +400KB
VirtualList48.ImageCollection := SVGIconImageCollection1;  // +900KB

// Total: ~2MB instead of ~9MB with separate lists

2. Clear Unused Icons

pascal
// Remove icons no longer needed
SVGIconImageList1.Delete(UnusedIndex);
SVGIconImageList1.ClearIcons;  // Remove all

3. Optimize SVG Source

pascal
// Minimize SVG file size before loading
// Use SVGO or similar optimizer
// Remove unnecessary attributes, comments, metadata

Troubleshooting

Q. Icons appear blurry or pixelated. What's wrong?

A. Common causes and solutions:

1. DPI Scaling Issues

pascal
// Ensure Scaled property is True
SVGIconImageList1.Scaled := True;

// For DataModules, manually handle DPI
procedure TDataModule1.DataModuleCreate(Sender: TObject);
begin
  if Screen.PixelsPerInch <> 96 then
    SVGIconImageList1.Size := MulDiv(16, Screen.PixelsPerInch, 96);
end;

2. Size Mismatch

pascal
// Icons are scaled down/up from rendered size
// Always render at target size for best quality

// Bad: Rendering 16px icons and displaying at 64px
SVGIconImageList1.Size := 16;
LargeButton.Width := 64;
LargeButton.Height := 64;

// Good: Render at display size
SVGIconImageList1.Size := 64;

3. AntiAlias Color

pascal
// AntiAliasColor should match background
// Wrong antialiasing causes edge artifacts

Panel1.Color := clBlack;
SVGIconImageList1.AntiAliasColor := clBlack;  // Match panel color

Q. Some icons display incorrectly or not at all. How can I debug this?

A. Diagnostic steps:

1. Check SVG Validity

pascal
procedure TestSVGLoading(const AFileName: string);
var
  SVG: ISVG;
begin
  SVG := GlobalSVGFactory.NewSvg;
  try
    SVG.LoadFromFile(AFileName);
    if SVG.IsEmpty then
      ShowMessage('SVG is empty or failed to load')
    else
      ShowMessage(Format('SVG loaded: %.0fx%.0f', [SVG.Width, SVG.Height]));
  except
    on E: Exception do
      ShowMessage('Error loading SVG: ' + E.Message);
  end;
end;

2. Try Different Engines

pascal
// Test with Image32
SetGlobalSvgFactory(GetImage32SVGFactory);
TestIcon;

// Test with Skia
SetGlobalSvgFactory(GetSkiaSVGFactory);
TestIcon;

// Different engines have different SVG feature support

3. Examine SVG Source

pascal
// Check for unsupported features
var Item := SVGIconImageList1.SVGIconItems[0];
Memo1.Lines.Text := Item.SVGText;

// Common issues:
// - External references (<use xlink:href="">)
// - Unsupported filters
// - Complex gradients
// - Embedded images

4. Simplify SVG

pascal
// Optimize SVG using online tools:
// - SVGO: https://jakearchibald.github.io/svgomg/
// - Removes unnecessary attributes
// - Simplifies paths
// - Improves compatibility

Q. Can I use icon fonts instead of SVG files?

A. The library is specifically designed for SVG files, not icon fonts. However, you can:

  1. Convert icon fonts to SVG using tools like:

    • IcoMoon (export as SVG)
    • FontForge (export glyphs)
    • Online converters
  2. Use dedicated icon font libraries for VCL/FMX that support fonts directly

Advantages of SVG over icon fonts:

  • Multi-color support
  • Complex shapes and gradients
  • No font installation required
  • Better for custom graphics
  • Easier to edit and customize

Q. How do I handle SVG icons in a multi-language application?

A. Approaches for internationalization:

1. Language-Specific Icons

pascal
procedure TForm1.LoadLocalizedIcons;
var
  LangCode: string;
  IconPath: string;
begin
  LangCode := GetCurrentLanguage;  // 'en', 'it', 'fr', etc.
  IconPath := Format('icons\%s\', [LangCode]);

  SVGIconImageList1.LoadFromFiles(GetFilesInPath(IconPath));
end;

2. Dynamic Text Replacement

pascal
// For icons containing text elements
procedure UpdateIconText(Item: TSVGIconItem; const AText: string);
var
  SVGText: string;
begin
  SVGText := Item.SVGText;
  // Replace text in <text> elements
  SVGText := ReplaceTextInSVG(SVGText, AText);
  Item.SVGText := SVGText;
end;

3. Fallback Icons

pascal
procedure LoadIconWithFallback(const ALocalizedName, ADefaultName: string);
begin
  if FileExists(GetLocalizedIconPath(ALocalizedName)) then
    LoadIcon(GetLocalizedIconPath(ALocalizedName))
  else
    LoadIcon(GetDefaultIconPath(ADefaultName));
end;

Best Practices

Q. What are the recommended best practices for using SVG icons in production applications?

A. Follow these guidelines:

1. Standardize Icon Sizes

pascal
// Define standard sizes for consistency
const
  ICON_SIZE_SMALL = 16;
  ICON_SIZE_MEDIUM = 24;
  ICON_SIZE_LARGE = 32;
  ICON_SIZE_XLARGE = 48;

// Use throughout application
ToolBar1.Images.Size := ICON_SIZE_SMALL;
Ribbon1.Images.Size := ICON_SIZE_LARGE;

2. Organize Icons with Categories

pascal
// Use consistent naming
Collection.Add(HomeIcon, 'home', 'Navigation');
Collection.Add(BackIcon, 'back', 'Navigation');
Collection.Add(SaveIcon, 'save', 'Actions');
Collection.Add(DeleteIcon, 'delete', 'Actions');

3. Centralize Icon Management

pascal
// Create a DataModule for shared icons
type
  TdmIcons = class(TDataModule)
    IconCollection: TSVGIconImageCollection;
    VirtualImageList16: TSVGIconVirtualImageList;
    VirtualImageList32: TSVGIconVirtualImageList;
    procedure DataModuleCreate(Sender: TObject);
  end;

// Use throughout application
Button1.Images := dmIcons.VirtualImageList16;

4. Version Control SVG Files

  • Store original SVG files in source control
  • Keep optimized versions separately
  • Document any manual modifications
  • Use consistent file naming conventions

5. Test Across DPI Settings

pascal
// Test at different DPI scales
// Windows: 100%, 125%, 150%, 200%
// Ensure icons remain sharp at all scales

6. Implement Graceful Fallbacks

pascal
procedure LoadIconSafely(Item: TSVGIconItem; const AFileName: string);
begin
  try
    Item.SVG.LoadFromFile(AFileName);
  except
    // Load default placeholder icon
    Item.SVG.Source := GetDefaultIconSVG;
  end;
end;

See Also

Released under Apache License, Version 2.0.