This is a hotfix for some crashing on single CPU systems, and a rendering bug in the Rounded Rectangle shape.

As usual, you can download the update directly from the website, or you can use the built-in updater via Settings –> Updates –> Check Now.

Change log:

  • Fixed: Rounded Rectangle rendering was incorrect for some values of "Corner size"
  • Fixed: Effects and Adjustments were crashing the app on systems with only 1 CPU core, or virtual machines configured for only 1 CPU

And, for convenience, here is the change log for 4.0.11:

Enjoy!

This update adds the ability to configure the Rounded Rectangle shape’s corner size. It also fixes issues with scrolling and panning, effect rendering performance, high DPI, and a rare system hang caused by WPF.

As usual, you can download the update directly from the website, or you can use the built-in updater via Settings –> Updates –> Check Now.

Change log:

Enjoy!

This update introduces overscroll, which is the ability to scroll the canvas past the bounds of the image. This has been a highly requested feature for several years now, and it’s finally here🙂

Also included is a big serving of miscellaneous bug fixes and small improvements.

As usual, you can download the update directly from the website, or you can use the built-in updater via Settings –> Updates –> Check Now.

Change log:

  • New: The canvas may now be scrolled past the edge of the image
  • New: When holding the spacebar, you may scroll using the keyboard arrow keys (in addition to click-and-drag panning). Holding Ctrl will scroll at 10x the rate.
  • New: You can now hold Ctrl+Shift while clicking on the floating window icons in order to reset their location and docking. Ctrl+Shift along with the appropriate hotkey (F5, F6, F7, F8) also does the trick.
  • Improved: The rate of auto-scrolling, which triggers when the mouse is at the canvas edge and a button is being held down, has been improved and is based on time instead of frames
  • Improved: Fixed Size selection drawing now defaults to 400×300 pixels instead of 4×3 inches
  • Improved: Tooltips for Custom Shapes now include their file system location
  • Improved: Edit->Invert Selection should perform much faster when used with unmodified selections from the Magic Wand tool
  • Improved: When running within VMWare, "Hardware accelerated rendering" is disabled by default (Microsoft’s WARP is faster than VMWare’s D3D emulation)
  • Fixed: Erratic brush/pencil drawing when running within VMWare (this is caused by a bug in Win32’s GetMouseMovePointEx API, and is not actually limited to VMWare)
  • Fixed: Color Picker tool could crash if used at the bottom of the image, as reported at http://forums.getpaint.net/index.php?/topic/109248-paintnet-crashes-when-color-picker-off-screen-update/
  • Fixed: There was a glitch in the Gradient tool’s rendering when dx was equal to dy, as reported at http://forums.getpaint.net/index.php?/topic/107380-gradient-bugs-in-direction-and-length/
  • Fixed: The Layers window would sometimes auto-scroll the active layer to the bottom when performing certain operations, as reported at http://forums.getpaint.net/index.php?/topic/32527-layers-auto-scrolling-when-adding-or-duplicating/
  • Fixed some mouse cursor glitches when using panning using the spacebar
  • Fixed many glitches and a few crashes in the image size dialogs (File->New, Image->Resize, Image->Canvas Size)
  • Fixed a problem with inconsinstently skipped input when using the arrow keys to move tool handles, as reported at http://forums.getpaint.net/index.php?/topic/108932-selected-area-moving-with-direction-keys-bug/
  • Fixed: Custom Shapes did not always have the correct bounding box, and would have weird behavior as a result
  • Fixed: Line/Curve handles were unusable for up to 500ms after adjusting properties in the toolbar
  • Fixed some crashes and soft hangs in the Save Configuration dialog
  • Fixed a blemish at the top of the main window when Windows is set to 200% DPI
  • Fixed: There were some precision bugs with IndirectUI sliders that would cause them to get "stuck" at certain values (mostly affects effect plugins)
  • Improved: IndirectUI’s Angle Chooser control now supports the DecimalPlaces property (for plugins)
  • Improved: IndirectUI’s Slider controls now support all-negative ranges (e.g. [-200, -20])

Enjoy!

There’s a big heaping handful of bug fixes and small changes, and I’ve added the currently top requested feature: you can now scroll the canvas past the edge of the image, aka “overscroll.”

Check it out at the forum: http://forums.getpaint.net/index.php?/topic/109756-paintnet-40-beta-build-6022/

There were still a few nasty bugs that were found in 4.0.8, so here’s an update that squashes them. The selection and Line/Curve tools should now be trouble-free for everyone!

As usual, you can download the update directly from the website, or you can use the built-in updater via Settings –> Updates –> Check Now.

Here are the fixes:

  • Fixed: Selection tools would sometimes crash
  • Fixed: Line/Curve tool would draw nothing if the Shapes tool was configured for “Draw Filled Shape”
  • Fixed: Thumbnails for .PDN files were not working on some systems
  • Fixed: The “Finish” button in the toolbar would not update its enable/disable state when switching between images

Enjoy!

Unfortunately there was a nasty crashing bug that snuck into the Line/Curve tool in the 4.0.7 release earlier today. So, here’s a 4.0.8 update with the fix.

As usual, you can download the update directly from the website, or you can use the built-in updater via Settings –> Updates –> Check Now.

Here’s the official, and very brief, changelog for 4.0.8:

  • Fixed: The Line/Curve tool was crashing when drawing vertical lines of particular lengths.

As for 4.0.7, it has its own blog post, but here is its changelog for convenience:

  • Changed: .NET Framework 4.6 is now required, and will be installed if necessary
  • New: Swedish translation
  • Fixed: Title bar now uses the Windows 10 accent color
  • Fixed: Floating windows were not remembering their locations on some non-English systems
  • Improved: Performance of "committing" (finishing) is now up to 10x faster, which greatly improves responsivness for quick drawing operations
  • Improved Shapes tool quality when drawn without antialiasing, with line styles, and at 1 pixel brush width
  • Improved Shapes tool rendering performance on CPUs with many cores (8+)
  • Improved: Installing a "complex" custom Shape no longer causes very long hangs at app startup
  • Improved: Image->Resize is now much faster
  • Fixed: Image->Resize would sometimes cause the main window to flicker or lose focus
  • Fixed: Image->Resize would sometimes do nothing instead of resizing the image to a very large size
  • Fixed: Labels on the vertical ruler were misleading because they were on the wrong side of the tick mark
  • Improved the ruler’s performance
  • Fixed: Edit->Copy now works if the data copied to the clipboard is larger than 2GB
  • Fixed: Page Up, Page Down, Home, and End keys now work in the main canvas area
  • Fixed: Paint.NET will no longer incorrectly block Windows from restarting
  • Fixed: Rotate/Zoom no longer crashes on very large images
  • Improved: Reduced CPU/GPU and battery use when the app is not in the foreground
  • Improved: Reduced CPU and battery use of the UI for the Move and Shapes tools
  • Added: Custom Shapes XAML now supports cardinal splines via PolyCurveSegment (a new PathSegment type)
  • Improved: Various performance improvements
  • Fixed: Several rare or uncommon crashes

Enjoy!

Whew! I originally started work on getting Paint.NET’s title bar area to respect the Windows 10 TH2 “accent color” functionality (which is NOT easy for a classic (non-universal / desktop) app … how about some documentation, Microsoft?!). Along the way I found (and rediscovered) many important performance issues that I’ve now fixed. I also finally found some fixes for a handful of rare and vexing startup crashes, including one that’s caused by a silly bug when WPF’s data binding system initializes (it’s a bug in WPF). Oh, and there’s now a Swedish translation. Various things related to the Shapes tool have been improved as well.

As usual, you can download the update directly from the website, or you can use the built-in updater via Settings –> Updates –> Check Now.

Hare are all the the new fixes and changes:

  • Changed: .NET Framework 4.6 is now required, and will be installed if necessary
  • New: Swedish translation
  • Fixed: Title bar now uses the Windows 10 accent color
  • Fixed: Floating windows were not remembering their locations on some non-English systems
  • Improved: Performance of "committing" (finishing) is now up to 10x faster, which greatly improves responsivness for quick drawing operations
  • Improved Shapes tool quality when drawn without antialiasing, with line styles, and at 1 pixel brush width
  • Improved Shapes tool rendering performance on CPUs with many cores (8+)
  • Improved: Installing a "complex" custom Shape no longer causes very long hangs at app startup
  • Improved: Image->Resize is now much faster
  • Fixed: Image->Resize would sometimes cause the main window to flicker or lose focus
  • Fixed: Image->Resize would sometimes do nothing instead of resizing the image to a very large size
  • Fixed: Labels on the vertical ruler were misleading because they were on the wrong side of the tick mark
  • Improved the ruler’s performance
  • Fixed: Edit->Copy now works if the data copied to the clipboard is larger than 2GB
  • Fixed: Page Up, Page Down, Home, and End keys now work in the main canvas area
  • Fixed: Paint.NET will no longer incorrectly block Windows from restarting
  • Fixed: Rotate/Zoom no longer crashes on very large images
  • Improved: Reduced CPU/GPU and battery use when the app is not in the foreground
  • Improved: Reduced CPU and battery use of the UI for the Move and Shapes tools
  • Added: Custom Shapes XAML now supports cardinal splines via PolyCurveSegment (a new PathSegment type)
  • Improved: Various performance improvements
  • Fixed: Several rare or uncommon crashes

Enjoy!

This update is probably a little more interesting than you may have been expecting. It has the usual grab bag of small bug fixes, but also includes the ability to install custom shapes (for the Shapes tool, obviously Smile). I’ve also updated everything to look good in Windows 10, and fixed many high-DPI blemishes that had gone unfixed for awhile.

If you’d like more info about custom shapes, you can check out BoltBait’s guide, “How to Install Paint.NET Shapes", which has installation instructions and a pack of sample shapes. It’s all XAML based and will look very familiar to you if you’ve ever worked with WPF’s Geometry system.

As usual, you can download the update directly from the website, or you can use the built-in updater via Settings –> Updates –> Check Now.

  • New: You can now create and install custom shapes for the Shapes tool.
  • New: Updated to work better with Windows 10.
  • New: Increased the maximum brush size to 2000.
  • New: IndirectUI-based effect plugins can now provide help text, accessible via the question mark button.
  • New: Effect plugins may now access the current palette via IPalettesService.
  • Improved: Reduced memory usage of brush tools when using large brush sizes.
  • Fixed: Holding shift to constrain the angle of the roll control (Layers -> Rotate/Zoom) wasn’t working correctly.
  • Fixed: Various shapes (hexagon, pentagon, triangle, etc.) are now symmetric when holding the shift key.
  • Fixed: Multiple high-dpi blemishes in the main window and many dialog boxes (Settings, Save Configuration, all effect dialogs, etc.)
  • Fixed: Various minor/rare crashes.

Enjoy!

(Side note: expect a Paint.NET 4.0.6 update soon, hopefully timed with the availability of Windows 10. It’s not just a bugfix release, either. More info soon!)

If you have some code whose performance is limited by string building or concatenation, you may want to read this. For everyone else: close your eyes! Here be dragons! (just kidding, but seriously, be careful with this stuff)

Everybody knows that strings are immutable in .NET. When I first tried out C# (in 2003?) this annoyed me, as I was used to C and C++ and being able to do whatever I wanted. I quickly learned to love this property, and embraced immutability and functional programming style in general. The benefits far outweigh the initial clumsiness.

Everybody also knows that you can pin a string with unsafe and fixed, get a pointer to the first character, and read directly from it or even hand it off the native code. No copying required. Right? Right?!

And following from that, there’s a dirty little secret here that nobody really likes to talk about: .NET strings aren’t actually immutable. You can get a pointer to one, and you can write to that pointer because it’s allocated in the regular heap and not in some special read-only memory pages (e.g. via VirtualProtect). Strings in .NET don’t cache their hash code, therefore there’s nothing to cause an inconsistency if you do something like …

String s = “I’m immutable, right?”;
unsafe
{
    fixed (char* p = s)
    {
        *(p + 4) = ‘_‘;
        *(p + 5) = ‘_‘;        
    }
}

Console.WriteLine(s); // outputs “I’m __mutable, right?”;

Note that if you do this anywhere other than while initializing a string, be prepared for the local townsfolk to come knocking on your door. With torches and pitchforks. It’s very important to respect the immutability contract once you hand off a String to external code.

If we browse around with Reflector or over on github in the coreclr repo, we can see that .NET itself takes advantage of this in functions such as System.String.Concat()  and its helper function FillStringChecked():

public static String Concat(String str0, String str1, String str2) {
    // … parameter checking and other stuff omitted for brevity …
    int totalLength = str0.Length + str1.Length + str2.Length;
    String result = FastAllocateString(totalLength);
    FillStringChecked(result, 0, str0);
    FillStringChecked(result, str0.Length, str1);
    FillStringChecked(result, str0.Length + str1.Length, str2);
    return result;
}

unsafe private static void FillStringChecked(String dest, int destPos, String src)
{
    // … parameter checking omitted for brevity
    fixed(char *pDest = &dest.m_firstChar)
    fixed (char *pSrc = &src.m_firstChar) {
        wstrcpy(pDest + destPos, pSrc, src.Length);
    }
}

And wstrcpy just calls into some regular ol’ memcpy/memmove type code. Some of those code paths (via wstrcpy) are managed code, others eventually thunk into native, but none of it’s magic: you can do all of this yourself! You can’t call FastAllocateString()*, but you can still allocate a string of a specified length via new String(char c, int count). Just use a placeholder character for the first parameter, like a space or even null ‘’. Also note that all .NET strings are null-terminated, so if you create one of length N, you actually have N+1 characters. The memory layout intentionally matches BSTR which gives a lot of flexibility for passing things to native code without having to do any copying. (I don’t know what would happen if you overwrote the length prefix, but feel free to try it out and post a comment!)

With this information you can build your own versions of String.Concat or StringBuilder that can avoid making copies in specialized situations. However, I’m not actually sure how useful this is: I looked through the Paint.NET codebase and found only a handful of places that do lots of string manipulation, and even then they were mostly in error reporting code paths whose performance was entirely unimportant. I decided to leave the code alone, preferring safety over a little bit of performance (and fun and creativity). Your Mileage May Vary.

On a side note, the fact that you can do this at all is one of the reasons why I love .NET and C#. You get all the good stuff that a managed runtime and high-level language is supposed to provide, but you also get “escape hatches” to drill through the glass floors on the abstraction ladder. You can push the runtime and its safety guarantees out of the way in the name of performance (or for other reasons). Paint.NET takes advantage of this a lot: graphics code loves things like pointers and structs. Lately I’ve been doing a lot of work on Android** with Java, and the lack of things like pointers and structs … gosh, it just makes things so much more difficult to work with from a performance standpoint!

* Well, maybe you could with reflection Winking smile That would probably eliminate its “fast” property though.

** Sorry, not for Paint.NET.

There were a few bugs that got introduced in 4.0.4, so here’s an update that fixes them. Chiefly among these bugs are a break in how the Magic Wand tool works, a crash when using Effects, and one when trying to use the Shapes tool.

As usual, you can download it directly from the website, or you can use the built-in updater via Settings –> Updates –> Check Now.

  • Fixed: Subtraction mode in the Magic Wand tool was generating B-A instead of A-B.
  • Fixed: Crash when using Effect –> Repeat.
  • Fixed: Crash (AccessViolationException) on some systems when initializing the canvas for hardware accelerated rendering. It will still crash but then switch to software rendering for the next startup, which will then avoid the crashing.
  • Fixed: Crash when clicking on the Shapes tool if you had run an old 4.0 beta/alpha and had also changed which shape is used at startup to be a line or curve.
  • Fixed: Crash when using Settings –> Update –> Check Now due to incorrectly determining that UAC is not enabled.

Enjoy!