Skip to content

Stream Deck Tools Version 7.0 - Cross-Platform support#89

Merged
BarRaider merged 32 commits intomasterfrom
feature/net48-net8-net9-graphics-migration
Apr 2, 2026
Merged

Stream Deck Tools Version 7.0 - Cross-Platform support#89
BarRaider merged 32 commits intomasterfrom
feature/net48-net8-net9-graphics-migration

Conversation

@BarRaider
Copy link
Copy Markdown
Owner

Introducing Stream Deck Tools Version 7.0

  • Cross-platform support: New SkiaSharp-based API surface (SkiaTools, SkiaGraphicsTools, SkiaExtensionMethods) for Windows + macOS.
  • Target frameworks: netstandard2.0, net48, net8.0, net10.0.
  • All System.Drawing-based APIs marked [Obsolete] with migration guidance.
  • New SetImageAsync(SKBitmap) and SetImageAsync(byte[]) overloads on ISDConnection.
  • New DrawTextLine extension method on SKCanvas with Y-as-top semantics (matching System.Drawing.Graphics.DrawString).
  • Breaking change (macOS): TitleParameters.FontFamily throws PlatformNotSupportedException on non-Windows. Use TitleParameters.FontFamilyName (string) or TitleParameters.TitleTypeface (SKTypeface) instead. On Windows, FontFamily still works but produces an [Obsolete] compiler warning.
  • New TitleParameters.FontFamilyName, TitleSKColor, TitleTypeface, FontStyleToSKFontStyle() for cross-platform rendering.
  • PluginBase is now [Obsolete] -- use KeypadBase, EncoderBase, or KeyAndEncoderBase.

Migration Guide:

  • See Migration Guide: for the full migration guide with code recipes and API mapping tables. (Pro-Tip: Use this file to let Cursor/Claude do the migration for you).

BarRaider added 30 commits April 2, 2026 14:46
…raction, v7.0

- Migrate TargetFrameworks from netstandard2.0;net8.0 to net48;net8.0;net9.0

- Add internal IImageCodec abstraction with thread-safe SystemDrawingImageCodec

- Route Tools.ImageToBase64, Base64StringToImage, ImageToSHA512 through codec

- Consolidate SDConnection.SetImageAsync(Image) to use string-based path

- Remove StreamDeckConnection.SetImageAsync(Image) overload

- Update CI to .NET 9 SDK, SamplePlugin to net48

- Bump version to 7.0

- Add migration guide, pre-existing issues tracker, and API inventory

Made-with: Cursor
…olete

- Add DecodeFromFile to IImageCodec/SystemDrawingImageCodec (copies pixel data to release file lock)

- Route Tools.FileToBase64 through ImageCodecProvider.Instance.DecodeFromFile

- Add Image.ToPngByteArray extension routed through codec abstraction

- Mark Image.ToByteArray [Obsolete] (BMP format, use ToPngByteArray instead)

Made-with: Cursor
- Reclassify APIs: 8 ADAPTED, 10 KEPT (future Obsolete), 10 HIGH-RISK

- Expand migration guide with v7.0 changelog, upgrade paths, and full API mapping

- Add deprecation timeline (v7.0 -> v7.x -> v8.0)

- Link API inventory and pre-existing issues from migration guide

Made-with: Cursor
…ssues

- Corrected KEPT count (10->9) and HIGH-RISK count (10->12) in API_INVENTORY.md

- Fixed duplicate numbering (#17) across KEPT and HIGH-RISK sections

- Updated GraphicsTools.cs per-file count (6->7)

- Added two pre-existing resource leaks to PRE_EXISTING_ISSUES.md:

  - ExtensionMethods.AddTextPath: Pen, GraphicsPath, SolidBrush not disposed

  - ExtensionMethods.SplitToFitKey: Font not disposed

Made-with: Cursor
…27 plugins

Analyzed 27 real-world plugins to validate v7.0 migration strategy:

- 14 plugins (52%%) require zero changes (Tier 1)

- 6 plugins (22%%) need minor migration via library helpers (Tier 2)

- 7 plugins (26%%) require direct graphics library adoption (Tier 3)

- TitleParameters confirmed critical: 14 plugins use it, must not change

- GenerateKeyImage workflow is the dominant rendering pattern

Made-with: Cursor
Planning/tracking docs (API_INVENTORY, MIGRATION, PRE_EXISTING_ISSUES, PLUGIN_USAGE_ANALYSIS) are kept locally but should not be pushed to the repository.

Made-with: Cursor
Expand abstraction layer with public APIs to replace common direct System.Drawing usage:

- Add IImageCodec.DecodeFromStream(Stream) + SystemDrawingImageCodec implementation

- Add Tools.LoadImage(string filePath) -- replaces direct Image.FromFile calls

- Add Tools.LoadImage(Stream stream) -- replaces direct Image.FromStream calls

- Add Tools.CreateFont(familyName, sizeInPoints, style) -- replaces direct new Font() calls

Quality gate: review agent (0 issues), bug-scan agent (0 migration bugs), build (0 errors, 0 warnings across net48/net8.0/net9.0)

Made-with: Cursor
…ePlugin

New APIs for plugins to avoid System.Drawing dependencies:

- SDConnection.SetImageAsync(byte[] pngImageBytes, ...) for byte-first workflows

- ISDConnection interface updated with matching declaration

SamplePlugin updated to demonstrate both paths:

- KeyPressed: legacy path (Image overload, TitleParameters, direct SD types)

- KeyReleased: modern path (ColorFromHex, CreateFont, ToPngByteArray, byte[] overload)

Quality gate: review (0 issues), bug-scan (1 SolidBrush leak fixed), build (0 errors)

Made-with: Cursor
If new Bitmap(original) throws, the original Image was not disposed

because it was scoped inside the try block. Moved declaration

outside try so catch can dispose it via original?.Dispose().

Final quality gate: review (APPROVED), bug-scan (1 issue fixed),

build (0 errors, 0 warnings), NuGet package verified (lib/net48, lib/net8.0, lib/net9.0).

Made-with: Cursor
Add SkiaSharp 3.119.2 (MIT license) as an unconditional NuGet dependency for all TFMs (net48, net8.0, net9.0). Create internal SkiaSharpImageCodec with PNG encode/decode methods using SKBitmap, enabling cross-platform image processing on Windows, macOS, and Linux.

Made-with: Cursor
…nMethods

Create cross-platform SkiaSharp-typed public API surface with feature parity to existing System.Drawing methods. Add SetImageAsync(SKBitmap) to ISDConnection/SDConnection. Add TitleSKColor, TitleTypeface, and FontStyleToSKFontStyle to TitleParameters for SkiaSharp consumers.

Made-with: Cursor
…harp

Mark all public System.Drawing-based methods in Tools.cs, GraphicsTools.cs, ExtensionMethods.cs, ISDConnection.cs, and SDConnection.cs as [Obsolete] with messages pointing to their SkiaSharp equivalents. Update SamplePlugin KeyReleased to demonstrate cross-platform SkiaSharp rendering path.

Made-with: Cursor
The destination rectangle was using full canvas dimensions (newWidth, newHeight) instead of the scaled dimensions (scaledWidth, scaledHeight), causing the image to be stretched instead of preserving aspect ratio.

Made-with: Cursor
- CI workflow: add macOS and Linux build jobs for net8.0/net9.0, trigger on feature/** branches, build in Release configuration

- Version: set NuGet package version to 7.0.0-beta.1 prerelease

- Fix missing XML doc param tag on SkiaExtensionMethods.SplitToFitKey

Made-with: Cursor
- Add netstandard2.0 to TargetFrameworks (now netstandard2.0;net48;net8.0;net9.0)

- Extend System.Drawing.Common conditional reference to include netstandard2.0

- Add netstandard2.0 PropertyGroup conditions for NoWarn and DocumentationFile

- Update CI workflow to build netstandard2.0 on macOS and Linux

- Zero code changes required: all source compiles as-is on netstandard2.0

Made-with: Cursor
CRITICAL: SendAsync(IMessage) returns Task.CompletedTask instead of null

HIGH: Fix SolidBrush leak in GenerateKeyImage, null-check GetEntryAssembly()

MEDIUM: Thread-safe previousImageHash, Dispose null-check, retry limit for title-change, OpenUrlAsync input validation, DecodeFromBytes logging

LOW: Remove unused NLog.Layouts import, dispose CancellationTokenSource, error handling in AutoPopulateSettings, JToken validation in FilenameFromPayload, fix resource leaks in AddTextPath and SplitToFitKey
Made-with: Cursor
Fix GetExeName() to correctly strip .exe extension on all platforms instead of using GetFileNameWithoutExtension which strips any extension. Bump NuGet package version to 7.0.0-beta.3.

Made-with: Cursor
- Scale font size by 72/imageWidth to match System.Drawing's GraphicsPath.AddString
- Add baseline-to-top-left offset using font ascent (DrawText uses baseline, not top-left)
- Handle newline characters from SplitToFitKey by drawing each line separately
- Fix horizontal centering by removing pixelsAlignment from X calculation
- Add null/empty guard for text parameter
- Correct bottom and middle vertical alignment using actual font metrics

Made-with: Cursor
- Bump version from 7.0.0-beta.4 to 7.0.0

- Add MigrateTo7.0.md: comprehensive migration guide with type mapping, method tables, code recipes, tiers, deprecation timeline

- Update README.md with v7.0 release notes and migration guide link

- Update NUGET.md with modern quick-start and v7.0 features

- Restore barraider-sdtools/README.md with v7.0 changelog entry

- Update SamplePlugin to net10.0 with SkiaSharp-only KeyPressed

- Fix csproj README path reference (../README.md)

Made-with: Cursor
@BarRaider BarRaider merged commit 0a2cf00 into master Apr 2, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant