Skip to content

Commit cdeafe3

Browse files
committed
fix build errors against old targets
1 parent 0946c10 commit cdeafe3

4 files changed

Lines changed: 59 additions & 4 deletions

File tree

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Apache License, Version 2.0.
3+
4+
using System.Runtime.CompilerServices;
5+
6+
namespace SixLabors.ImageSharp.Drawing
7+
{
8+
internal static class NumericExtensions
9+
{
10+
// https://apisof.net/catalog/System.Numerics.BitOperations.Log2(UInt32)
11+
// BitOperations.Log2() has been introduced in .NET Core 3.0,
12+
// since we do target only 3.1+, we can detect it's presence by using SUPPORTS_RUNTIME_INTRINSICS
13+
// TODO: Ideally this should have a separate definition in Build.props, but that adaption should be done cross-repo. Using a workaround until then.
14+
#if SUPPORTS_RUNTIME_INTRINSICS
15+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
16+
public static int Log2(uint value) => System.Numerics.BitOperations.Log2(value);
17+
#else
18+
private static System.ReadOnlySpan<byte> Log2DeBruijn => new byte[32]
19+
{
20+
00, 09, 01, 10, 13, 21, 02, 29,
21+
11, 14, 16, 18, 22, 25, 03, 30,
22+
08, 12, 20, 28, 15, 17, 24, 07,
23+
19, 27, 23, 06, 26, 05, 04, 31
24+
};
25+
26+
#pragma warning disable SA1515, SA1414, SA1114
27+
// Adapted from:
28+
// https://github.com/dotnet/runtime/blob/5c65d891f203618245184fa54397ced0a8ca806c/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs#L205-L223
29+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
30+
public static int Log2(uint value)
31+
{
32+
// No AggressiveInlining due to large method size
33+
// Has conventional contract 0->0 (Log(0) is undefined)
34+
35+
// Fill trailing zeros with ones, eg 00010010 becomes 00011111
36+
value |= value >> 01;
37+
value |= value >> 02;
38+
value |= value >> 04;
39+
value |= value >> 08;
40+
value |= value >> 16;
41+
42+
// uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check
43+
return Unsafe.AddByteOffset(
44+
// Using deBruijn sequence, k=2, n=5 (2^5=32) : 0b_0000_0111_1100_0100_1010_1100_1101_1101u
45+
ref System.Runtime.InteropServices.MemoryMarshal.GetReference(Log2DeBruijn),
46+
// uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here
47+
(System.IntPtr)(int)((value * 0x07C4ACDDu) >> 27));
48+
}
49+
#pragma warning restore
50+
#endif
51+
}
52+
}

src/ImageSharp.Drawing/Shapes/Helpers/TopologyUtilities.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ private static int GetPolygonOrientation(ReadOnlySpan<PointF> polygon)
4646

4747
// Normally, this should be a tolerant comparison, we don't have a special path for zero-area
4848
// (or for self-intersecting, semi-zero-area) polygons in edge scanning.
49-
return MathF.Sign(sum);
49+
return Math.Sign(sum);
5050
}
5151
}
5252
}

src/ImageSharp.Drawing/Utilities/SortUtility.KeyValueSort.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ private static void IntrospectiveSort(Span<float> keys, Span<TValue> values)
4949
{
5050
if (keys.Length > 1)
5151
{
52-
IntroSort(keys, values, 2 * (BitOperations.Log2((uint)keys.Length) + 1));
52+
IntroSort(keys, values, 2 * (NumericExtensions.Log2((uint)keys.Length) + 1));
5353
}
5454
}
5555

@@ -89,7 +89,11 @@ private static void IntroSort(Span<float> keys, Span<TValue> values, int depthLi
8989
int p = PickPivotAndPartition(keys.Slice(0, partitionSize), values.Slice(0, partitionSize));
9090

9191
// Note we've already partitioned around the pivot and do not have to move the pivot again.
92-
IntroSort(keys[(p + 1) .. partitionSize], values[(p + 1) .. partitionSize], depthLimit);
92+
int s = p + 1;
93+
int l = partitionSize - s;
94+
95+
// IntroSort(keys[(p + 1) .. partitionSize], values[(p + 1) .. partitionSize], depthLimit);
96+
IntroSort(keys.Slice(s, l), values.Slice(s, l), depthLimit);
9397
partitionSize = p;
9498
}
9599
}

tests/ImageSharp.Drawing.Tests/Drawing/DrawingRobustnessTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ private Image<Rgba32> FillGeoJsonPolygons(TestImageProvider<Rgba32> provider, st
124124
GraphicsOptions = new GraphicsOptions() {Antialias = aa > 0, AntialiasSubpixelDepth = aa},
125125
};
126126
var rnd = new Random(42);
127-
int i = 0;
128127
byte[] rgb = new byte[3];
129128
foreach (PointF[] loop in points)
130129
{

0 commit comments

Comments
 (0)