`IImage` represents a base interface for raster and vector images. `IBitmap` now implements this interface and `DrawingContext` accepts this interface in `DrawImage`.
The interface defines a `Draw` method which introduces a level of indirection for drawing the image through the image itself.
Renamed `IDrawingContextImpl.DrawImage` to `DrawBitmap` as this only handles drawing bitmap images. `Bitmap` now calls this method directly on the platform implementation.
The renderer was using the wrong bounds for text where `TextAlignment != Left` as seen in #1625. To fix this, change `FormattedTextImpl.Size` to `Bounds`, which returns a rect that takes into account the text alignment and similarly change `FormattedText.Measure` to return a `Rect` instead of a `Size.
Fixes#1625.
`ILockedFrameBuffer.Dpi` was a `Size` but it would make more sense as a `Vector` because `Size * Vector` produces a `Size` whereas a `Size * Size` would produce a `Size3D` if that type existed.
Previously `IFormattedTextImpl` had `SetForegroundBrush` which set
mutable state. Make `FormattedText` fully mutable (before it was kinda
mutable, kinda immutable) and create immutable `IFormattedTextImpl`s on
demand.
Also:
- Change `GradientBrush.GradientStops` to be a readonly list, as changes
to it would have been ignored anyway.
- Fix typo in ImageBrush filename.
Run deferred render tests on a background thread to expose any threading
errors in the deferred rendering path. And threading errors found. Also
had to decrease the timeout for D2D render tests as
`renderTarget.EndDraw` is hanging when an exception is thrown between
`renderTarget.BeginDraw` and `EndDraw`.
Because it needs to be shared between the UI thread and the render
thread. This also required making it non-disposable like the other
graphics primitive impls.