@ -6,6 +6,7 @@
using System ;
using System ;
using System.Collections.Generic ;
using System.Collections.Generic ;
using System.Threading.Tasks ;
using System.Threading.Tasks ;
using Avalonia.Collections.Pooled ;
using Avalonia.Controls.Metadata ;
using Avalonia.Controls.Metadata ;
using Avalonia.Controls.Shapes ;
using Avalonia.Controls.Shapes ;
using Avalonia.Input ;
using Avalonia.Input ;
@ -64,19 +65,19 @@ namespace Avalonia.Controls.Primitives
private Panel ? _ selectionEllipsePanel ;
private Panel ? _ selectionEllipsePanel ;
// Put the spectrum images in a bitmap, which is then given to an ImageBrush.
// Put the spectrum images in a bitmap, which is then given to an ImageBrush.
private Writeable Bitmap? _ hueRedBitmap ;
private Bitmap ? _ hueRedBitmap ;
private Writeable Bitmap? _ hueYellowBitmap ;
private Bitmap ? _ hueYellowBitmap ;
private Writeable Bitmap? _ hueGreenBitmap ;
private Bitmap ? _ hueGreenBitmap ;
private Writeable Bitmap? _ hueCyanBitmap ;
private Bitmap ? _ hueCyanBitmap ;
private Writeable Bitmap? _ hueBlueBitmap ;
private Bitmap ? _ hueBlueBitmap ;
private Writeable Bitmap? _ huePurpleBitmap ;
private Bitmap ? _ huePurpleBitmap ;
private Writeable Bitmap? _ saturationMinimumBitmap ;
private Bitmap ? _ saturationMinimumBitmap ;
private Writeable Bitmap? _ saturationMaximumBitmap ;
private Bitmap ? _ saturationMaximumBitmap ;
private Writeable Bitmap? _ valueBitmap ;
private Bitmap ? _ valueBitmap ;
private Writeable Bitmap? _ minBitmap ;
private Bitmap ? _ minBitmap ;
private Writeable Bitmap? _ maxBitmap ;
private Bitmap ? _ maxBitmap ;
// Fields used by UpdateEllipse() to ensure that it's using the data
// Fields used by UpdateEllipse() to ensure that it's using the data
// associated with the last call to CreateBitmapsAndColorMap(),
// associated with the last call to CreateBitmapsAndColorMap(),
@ -1101,17 +1102,7 @@ namespace Avalonia.Controls.Primitives
}
}
Hsv hsv = new Hsv ( hsvColor ) ;
Hsv hsv = new Hsv ( hsvColor ) ;
// The middle 4 are only needed and used in the case of hue as the third dimension.
// Saturation and luminosity need only a min and max.
ArrayList < byte > bgraMinPixelData ;
ArrayList < byte > bgraMiddle1PixelData ;
ArrayList < byte > bgraMiddle2PixelData ;
ArrayList < byte > bgraMiddle3PixelData ;
ArrayList < byte > bgraMiddle4PixelData ;
ArrayList < byte > bgraMaxPixelData ;
List < Hsv > newHsvValues ;
// In Avalonia, Bounds returns the actual device-independent pixel size of a control.
// In Avalonia, Bounds returns the actual device-independent pixel size of a control.
// However, this is not necessarily the size of the control rendered on a display.
// However, this is not necessarily the size of the control rendered on a display.
// A desktop or application scaling factor may be applied which must be accounted for here.
// A desktop or application scaling factor may be applied which must be accounted for here.
@ -1121,27 +1112,20 @@ namespace Avalonia.Controls.Primitives
int pixelDimension = ( int ) Math . Round ( minDimension * scale ) ;
int pixelDimension = ( int ) Math . Round ( minDimension * scale ) ;
var pixelCount = pixelDimension * pixelDimension ;
var pixelCount = pixelDimension * pixelDimension ;
var pixelDataSize = pixelCount * 4 ;
var pixelDataSize = pixelCount * 4 ;
bgraMinPixelData = new ArrayList < byte > ( pixelDataSize ) ;
bgraMaxPixelData = new ArrayList < byte > ( pixelDataSize ) ;
newHsvValues = new List < Hsv > ( pixelCount ) ;
// We'll only save pixel data for the middle bitmaps if our third dimension is hue.
// We'll only save pixel data for the middle bitmaps if our third dimension is hue.
if ( components = = ColorSpectrumComponents . ValueSaturation | |
var middleBitmapsSize =
components = = ColorSpectrumComponents . SaturationValue )
components is ColorSpectrumComponents . ValueSaturation or ColorSpectrumComponents . SaturationValue
{
? pixelDataSize : 0 ;
bgraMiddle1PixelData = new ArrayList < byte > ( pixelDataSize ) ;
bgraMiddle2PixelData = new ArrayList < byte > ( pixelDataSize ) ;
var newHsvValues = new List < Hsv > ( pixelCount ) ;
bgraMiddle3PixelData = new ArrayList < byte > ( pixelDataSize ) ;
using var bgraMinPixelData = new PooledList < byte > ( pixelDataSize , ClearMode . Never ) ;
bgraMiddle4PixelData = new ArrayList < byte > ( pixelDataSize ) ;
using var bgraMaxPixelData = new PooledList < byte > ( pixelDataSize , ClearMode . Never ) ;
}
// The middle 4 are only needed and used in the case of hue as the third dimension.
else
// Saturation and luminosity need only a min and max.
{
using var bgraMiddle1PixelData = new PooledList < byte > ( middleBitmapsSize , ClearMode . Never ) ;
bgraMiddle1PixelData = new ArrayList < byte > ( 0 ) ;
using var bgraMiddle2PixelData = new PooledList < byte > ( middleBitmapsSize , ClearMode . Never ) ;
bgraMiddle2PixelData = new ArrayList < byte > ( 0 ) ;
using var bgraMiddle3PixelData = new PooledList < byte > ( middleBitmapsSize , ClearMode . Never ) ;
bgraMiddle3PixelData = new ArrayList < byte > ( 0 ) ;
using var bgraMiddle4PixelData = new PooledList < byte > ( middleBitmapsSize , ClearMode . Never ) ;
bgraMiddle4PixelData = new ArrayList < byte > ( 0 ) ;
}
await Task . Run ( ( ) = >
await Task . Run ( ( ) = >
{
{
@ -1187,7 +1171,7 @@ namespace Avalonia.Controls.Primitives
}
}
} ) ;
} ) ;
Dispatcher . UIThread . Post ( ( ) = >
await Dispatcher . UIThread . InvokeAsync ( ( ) = >
{
{
int pixelWidth = pixelDimension ;
int pixelWidth = pixelDimension ;
int pixelHeight = pixelDimension ;
int pixelHeight = pixelDimension ;
@ -1201,20 +1185,29 @@ namespace Avalonia.Controls.Primitives
{
{
case ColorSpectrumComponents . HueValue :
case ColorSpectrumComponents . HueValue :
case ColorSpectrumComponents . ValueHue :
case ColorSpectrumComponents . ValueHue :
_ saturationMinimumBitmap ? . Dispose ( ) ;
_ saturationMinimumBitmap = _ minBitmap ;
_ saturationMinimumBitmap = _ minBitmap ;
_ saturationMaximumBitmap ? . Dispose ( ) ;
_ saturationMaximumBitmap = _ maxBitmap ;
_ saturationMaximumBitmap = _ maxBitmap ;
break ;
break ;
case ColorSpectrumComponents . HueSaturation :
case ColorSpectrumComponents . HueSaturation :
case ColorSpectrumComponents . SaturationHue :
case ColorSpectrumComponents . SaturationHue :
_ valueBitmap ? . Dispose ( ) ;
_ valueBitmap = _ maxBitmap ;
_ valueBitmap = _ maxBitmap ;
break ;
break ;
case ColorSpectrumComponents . ValueSaturation :
case ColorSpectrumComponents . ValueSaturation :
case ColorSpectrumComponents . SaturationValue :
case ColorSpectrumComponents . SaturationValue :
_ hueRedBitmap ? . Dispose ( ) ;
_ hueRedBitmap = _ minBitmap ;
_ hueRedBitmap = _ minBitmap ;
_ hueYellowBitmap ? . Dispose ( ) ;
_ hueYellowBitmap = ColorPickerHelpers . CreateBitmapFromPixelData ( bgraMiddle1PixelData , pixelWidth , pixelHeight ) ;
_ hueYellowBitmap = ColorPickerHelpers . CreateBitmapFromPixelData ( bgraMiddle1PixelData , pixelWidth , pixelHeight ) ;
_ hueGreenBitmap ? . Dispose ( ) ;
_ hueGreenBitmap = ColorPickerHelpers . CreateBitmapFromPixelData ( bgraMiddle2PixelData , pixelWidth , pixelHeight ) ;
_ hueGreenBitmap = ColorPickerHelpers . CreateBitmapFromPixelData ( bgraMiddle2PixelData , pixelWidth , pixelHeight ) ;
_ hueCyanBitmap ? . Dispose ( ) ;
_ hueCyanBitmap = ColorPickerHelpers . CreateBitmapFromPixelData ( bgraMiddle3PixelData , pixelWidth , pixelHeight ) ;
_ hueCyanBitmap = ColorPickerHelpers . CreateBitmapFromPixelData ( bgraMiddle3PixelData , pixelWidth , pixelHeight ) ;
_ hueBlueBitmap ? . Dispose ( ) ;
_ hueBlueBitmap = ColorPickerHelpers . CreateBitmapFromPixelData ( bgraMiddle4PixelData , pixelWidth , pixelHeight ) ;
_ hueBlueBitmap = ColorPickerHelpers . CreateBitmapFromPixelData ( bgraMiddle4PixelData , pixelWidth , pixelHeight ) ;
_ huePurpleBitmap ? . Dispose ( ) ;
_ huePurpleBitmap = _ maxBitmap ;
_ huePurpleBitmap = _ maxBitmap ;
break ;
break ;
}
}
@ -1249,12 +1242,12 @@ namespace Avalonia.Controls.Primitives
double maxSaturation ,
double maxSaturation ,
double minValue ,
double minValue ,
double maxValue ,
double maxValue ,
Array List< byte > bgraMinPixelData ,
Pooled List< byte > bgraMinPixelData ,
Array List< byte > bgraMiddle1PixelData ,
Pooled List< byte > bgraMiddle1PixelData ,
Array List< byte > bgraMiddle2PixelData ,
Pooled List< byte > bgraMiddle2PixelData ,
Array List< byte > bgraMiddle3PixelData ,
Pooled List< byte > bgraMiddle3PixelData ,
Array List< byte > bgraMiddle4PixelData ,
Pooled List< byte > bgraMiddle4PixelData ,
Array List< byte > bgraMaxPixelData ,
Pooled List< byte > bgraMaxPixelData ,
List < Hsv > newHsvValues )
List < Hsv > newHsvValues )
{
{
double hMin = minHue ;
double hMin = minHue ;
@ -1409,12 +1402,12 @@ namespace Avalonia.Controls.Primitives
double maxSaturation ,
double maxSaturation ,
double minValue ,
double minValue ,
double maxValue ,
double maxValue ,
Array List< byte > bgraMinPixelData ,
Pooled List< byte > bgraMinPixelData ,
Array List< byte > bgraMiddle1PixelData ,
Pooled List< byte > bgraMiddle1PixelData ,
Array List< byte > bgraMiddle2PixelData ,
Pooled List< byte > bgraMiddle2PixelData ,
Array List< byte > bgraMiddle3PixelData ,
Pooled List< byte > bgraMiddle3PixelData ,
Array List< byte > bgraMiddle4PixelData ,
Pooled List< byte > bgraMiddle4PixelData ,
Array List< byte > bgraMaxPixelData ,
Pooled List< byte > bgraMaxPixelData ,
List < Hsv > newHsvValues )
List < Hsv > newHsvValues )
{
{
double hMin = minHue ;
double hMin = minHue ;