Browse Source

Render the ColorSpectrum to physical device pixel resolution

pull/8050/head
robloo 4 years ago
parent
commit
d9ef01acfc
  1. 46
      src/Avalonia.Controls.ColorPicker/ColorSpectrum/ColorSpectrum.cs

46
src/Avalonia.Controls.ColorPicker/ColorSpectrum/ColorSpectrum.cs

@ -10,6 +10,7 @@ using Avalonia.Controls.Metadata;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Threading;
@ -587,8 +588,10 @@ namespace Avalonia.Controls.Primitives
return;
}
double xPosition = point.Position.X;
double yPosition = point.Position.Y;
// Remember the bitmap size follows physical device pixels
var scale = LayoutHelper.GetLayoutScale(this);
double xPosition = point.Position.X * scale;
double yPosition = point.Position.Y * scale;
double radius = Math.Min(_imageWidthFromLastBitmapCreation, _imageHeightFromLastBitmapCreation) / 2;
double distanceFromRadius = Math.Sqrt(Math.Pow(xPosition - radius, 2) + Math.Pow(yPosition - radius, 2));
@ -819,8 +822,10 @@ namespace Avalonia.Controls.Primitives
yPosition = (Math.Sin((thetaValue * Math.PI / 180.0) + Math.PI) * radius * rValue) + radius;
}
Canvas.SetLeft(_selectionEllipsePanel, xPosition - (_selectionEllipsePanel.Width / 2));
Canvas.SetTop(_selectionEllipsePanel, yPosition - (_selectionEllipsePanel.Height / 2));
// Remember the bitmap size follows physical device pixels
var scale = LayoutHelper.GetLayoutScale(this);
Canvas.SetLeft(_selectionEllipsePanel, (xPosition / scale) - (_selectionEllipsePanel.Width / 2));
Canvas.SetTop(_selectionEllipsePanel, (yPosition / scale) - (_selectionEllipsePanel.Height / 2));
// We only want to bother with the color name tool tip if we can provide color names.
if (IsFocused &&
@ -969,7 +974,14 @@ namespace Avalonia.Controls.Primitives
List<byte> bgraMaxPixelData = new List<byte>();
List<Hsv> newHsvValues = new List<Hsv>();
var pixelCount = (int)(Math.Round(minDimension) * Math.Round(minDimension));
// 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.
// A desktop or application scaling factor may be applied which must be accounted for here.
// Remember bitmaps in Avalonia are rendered mapping to actual device pixels, not the device-
// independent pixels of controls.
var scale = LayoutHelper.GetLayoutScale(this);
int pixelDimension = (int)Math.Round(minDimension * scale);
var pixelCount = pixelDimension * pixelDimension;
var pixelDataSize = pixelCount * 4;
bgraMinPixelData.Capacity = pixelDataSize;
@ -986,8 +998,6 @@ namespace Avalonia.Controls.Primitives
bgraMaxPixelData.Capacity = pixelDataSize;
newHsvValues.Capacity = pixelCount;
int minDimensionInt = (int)Math.Round(minDimension);
await Task.Run(() =>
{
// As the user perceives it, every time the third dimension not represented in the ColorSpectrum changes,
@ -1006,12 +1016,12 @@ namespace Avalonia.Controls.Primitives
// but the running time savings after that are *huge* when we can just set an opacity instead of generating a brand new bitmap.
if (shape == ColorSpectrumShape.Box)
{
for (int x = minDimensionInt - 1; x >= 0; --x)
for (int x = pixelDimension - 1; x >= 0; --x)
{
for (int y = minDimensionInt - 1; y >= 0; --y)
for (int y = pixelDimension - 1; y >= 0; --y)
{
FillPixelForBox(
x, y, hsv, minDimensionInt, components, minHue, maxHue, minSaturation, maxSaturation, minValue, maxValue,
x, y, hsv, pixelDimension, components, minHue, maxHue, minSaturation, maxSaturation, minValue, maxValue,
bgraMinPixelData, bgraMiddle1PixelData, bgraMiddle2PixelData, bgraMiddle3PixelData, bgraMiddle4PixelData, bgraMaxPixelData,
newHsvValues);
}
@ -1019,12 +1029,12 @@ namespace Avalonia.Controls.Primitives
}
else
{
for (int y = 0; y < minDimensionInt; ++y)
for (int y = 0; y < pixelDimension; ++y)
{
for (int x = 0; x < minDimensionInt; ++x)
for (int x = 0; x < pixelDimension; ++x)
{
FillPixelForRing(
x, y, minDimensionInt / 2.0, hsv, components, minHue, maxHue, minSaturation, maxSaturation, minValue, maxValue,
x, y, pixelDimension / 2.0, hsv, components, minHue, maxHue, minSaturation, maxSaturation, minValue, maxValue,
bgraMinPixelData, bgraMiddle1PixelData, bgraMiddle2PixelData, bgraMiddle3PixelData, bgraMiddle4PixelData, bgraMaxPixelData,
newHsvValues);
}
@ -1034,8 +1044,8 @@ namespace Avalonia.Controls.Primitives
Dispatcher.UIThread.Post(() =>
{
int pixelWidth = (int)Math.Round(minDimension);
int pixelHeight = (int)Math.Round(minDimension);
int pixelWidth = pixelDimension;
int pixelHeight = pixelDimension;
ColorSpectrumComponents components2 = Components;
@ -1066,8 +1076,8 @@ namespace Avalonia.Controls.Primitives
_shapeFromLastBitmapCreation = Shape;
_componentsFromLastBitmapCreation = Components;
_imageWidthFromLastBitmapCreation = minDimension;
_imageHeightFromLastBitmapCreation = minDimension;
_imageWidthFromLastBitmapCreation = pixelDimension;
_imageHeightFromLastBitmapCreation = pixelDimension;
_minHueFromLastBitmapCreation = MinHue;
_maxHueFromLastBitmapCreation = MaxHue;
_minSaturationFromLastBitmapCreation = MinSaturation;
@ -1086,7 +1096,7 @@ namespace Avalonia.Controls.Primitives
double x,
double y,
Hsv baseHsv,
double minDimension,
int minDimension,
ColorSpectrumComponents components,
double minHue,
double maxHue,

Loading…
Cancel
Save