Skip to content

Spec: High-DPI / Scale Support

Overview

Ensure DigitalWorks renders crisply and functions correctly at all display scale factors (100%–400%) and resolutions (1080p through 8K), including multi-monitor setups with different DPI settings per display.

Motivation

Modern displays range from standard 1080p (96 DPI) to 4K/5K monitors (200+ DPI) and even 8K panels. Windows display scaling (125%, 150%, 200%, etc.) is common. Without proper High-DPI support, the application appears blurry, elements are too small or too large, and multi-monitor workflows break.

Requirements

Functional Requirements

  1. Per-Monitor DPI Awareness: Application responds correctly to different DPI on each monitor.
  2. Dynamic DPI Change: Handle DPI changes at runtime (dragging window between monitors).
  3. Crisp Rendering at All Scales: All UI elements, canvas content, and text render at native resolution.
  4. Canvas Scaling: Circuit canvas renders at display-native resolution (not upscaled bitmap).
  5. Consistent Element Sizes: Components, wires, and pins maintain consistent physical size across DPI.
  6. UI Element Scaling: Toolbars, dialogs, panels, and menus scale proportionally.
  7. Icon Assets: Provide multiple icon resolutions (1x, 1.5x, 2x, 3x) or use vector icons.
  8. Font Scaling: All text renders at correct size relative to DPI (not pixelated).
  9. Grid Scaling: Grid lines remain at consistent visual spacing regardless of zoom/DPI.
  10. Print Fidelity: Export/print at actual DPI (not screen DPI).
  11. User Scale Override: Allow users to adjust UI scale independently of system setting.

Non-Functional Requirements

  • No blurry rendering at any standard Windows scale factor (100–400%).
  • No layout breakage when scale changes at runtime.
  • Smooth transition when dragging between monitors of different DPI.
  • Memory usage scales reasonably with resolution (no 4x bitmap memory at 2x scale).
  • Performance maintained at high DPI (60fps canvas rendering at 4K).

Design

DPI Awareness Model

WinUI 3 apps are automatically per-monitor DPI-aware v2. Key considerations:

csharp
// Get effective DPI for the current window
double scaleFactor = XamlRoot.RasterizationScale;  // 1.0, 1.25, 1.5, 2.0, etc.

// Canvas rendering must account for scale
public void OnDraw(CanvasDrawEventArgs args)
{
    var session = args.DrawingSession;
    // Win2D automatically handles DPI - draw in logical pixels
    // The CanvasControl.DpiScale handles physical pixel mapping
}

Canvas Rendering Strategy

Win2D CanvasControl is already DPI-aware:

  • Draw calls use logical (DIP) coordinates.
  • Win2D internally renders at the display's physical pixel density.
  • No manual scaling math needed for basic rendering.

Additional considerations:

  • Custom offscreen render targets must specify correct DPI.
  • Bitmap caches (minimap, thumbnails) must be invalidated on DPI change.
  • Shape definitions must use resolution-independent units.

Areas Requiring DPI-Aware Code

AreaApproach
Canvas renderingWin2D handles automatically
Hit-testingUse logical coordinates (already correct)
Custom controlsUse WinUI layout system (automatic)
Offscreen bitmapsSpecify DPI when creating CanvasBitmap
MinimapRegenerate at new DPI on scale change
Exported imagesUse export DPI setting, not screen DPI
Icons/assetsUse vector (SVG) icons or multi-resolution assets
Grid renderingCalculate grid spacing in logical pixels
Mouse positionEnsure raw position is in logical coordinates

Multi-Monitor Handling

csharp
// Listen for DPI changes
window.DpiChanged += (sender, args) =>
{
    // Invalidate bitmap caches
    _minimapCache = null;
    _componentThumbnails.Clear();
    
    // Re-render canvas at new DPI
    _canvas.Invalidate();
    
    // Update any custom pixel calculations
    UpdateHitTestThresholds(args.NewDpi);
};

Icon Strategy

Replace raster icons with:

  • SVG icons (rendered via Win2D or WinUI image elements) — scales perfectly.
  • Or provide asset variants: icon.scale-100.png, icon.scale-150.png, icon.scale-200.png, etc.

Implementation Tasks

  1. Audit all custom pixel calculations for DPI-dependence.
  2. Ensure all offscreen render targets specify correct DPI.
  3. Implement DPI change handler (invalidate caches, re-render).
  4. Replace raster icon assets with vector (SVG) or multi-scale assets.
  5. Verify hit-testing uses logical coordinates at all scale factors.
  6. Update minimap rendering to regenerate on DPI change.
  7. Verify grid rendering at various scale factors (100%, 150%, 200%, 300%).
  8. Test multi-monitor scenarios (drag between different DPI displays).
  9. Add user-configurable UI scale override in preferences.
  10. Verify export/print uses correct DPI (not screen DPI).
  11. Performance test canvas rendering at 4K (3840×2160) at 60fps.

Risks & Open Questions

  • Are there any Win2D limitations at very high DPI (8K displays)?
  • Memory impact of high-DPI offscreen bitmaps for large circuits?
  • Should custom controls handle DPI themselves or rely on WinUI layout?
  • How to test across many DPI values without physical hardware (virtual displays)?

Priority

Low-Medium — WinUI 3 + Win2D handle most cases automatically; main risk is custom code with pixel assumptions.