diff --git a/src/UglyToad.PdfPig.Core/Globals.cs b/src/UglyToad.PdfPig.Core/Globals.cs
new file mode 100644
index 000000000..30cd4b7b4
--- /dev/null
+++ b/src/UglyToad.PdfPig.Core/Globals.cs
@@ -0,0 +1,2 @@
+global using System;
+global using System.Collections.Generic;
\ No newline at end of file
diff --git a/src/UglyToad.PdfPig.Core/TransformationMatrix.cs b/src/UglyToad.PdfPig.Core/TransformationMatrix.cs
index 1496c7a3d..c21649ceb 100644
--- a/src/UglyToad.PdfPig.Core/TransformationMatrix.cs
+++ b/src/UglyToad.PdfPig.Core/TransformationMatrix.cs
@@ -1,9 +1,6 @@
namespace UglyToad.PdfPig.Core
{
- using System;
- using System.Collections.Generic;
using System.Diagnostics.Contracts;
- using System.Linq;
using static UglyToad.PdfPig.Core.PdfSubpath;
///
@@ -138,53 +135,27 @@ public static TransformationMatrix GetRotationMatrix(double degreesCounterclockw
throw new ArgumentOutOfRangeException(nameof(col), "Cannot access negative columns in a matrix.");
}
- switch (row)
- {
- case 0:
- {
- switch (col)
- {
- case 0:
- return A;
- case 1:
- return B;
- case 2:
- return row1;
- default:
- throw new ArgumentOutOfRangeException($"Trying to access {row}, {col} which was not in the value array.");
- }
- }
- case 1:
- {
- switch (col)
- {
- case 0:
- return C;
- case 1:
- return D;
- case 2:
- return row2;
- default:
- throw new ArgumentOutOfRangeException($"Trying to access {row}, {col} which was not in the value array.");
- }
- }
- case 2:
- {
- switch (col)
- {
- case 0:
- return E;
- case 1:
- return F;
- case 2:
- return row3;
- default:
- throw new ArgumentOutOfRangeException($"Trying to access {row}, {col} which was not in the value array.");
- }
- }
- default:
- throw new ArgumentOutOfRangeException($"Trying to access {row}, {col} which was not in the value array.");
- }
+ return row switch {
+ 0 => col switch {
+ 0 => A,
+ 1 => B,
+ 2 => row1,
+ _ => throw new ArgumentOutOfRangeException($"Trying to access {row}, {col} which was not in the value array.")
+ },
+ 1 => col switch {
+ 0 => C,
+ 1 => D,
+ 2 => row2,
+ _ => throw new ArgumentOutOfRangeException($"Trying to access {row}, {col} which was not in the value array.")
+ },
+ 2 => col switch {
+ 0 => E,
+ 1 => F,
+ 2 => row3,
+ _ => throw new ArgumentOutOfRangeException($"Trying to access {row}, {col} which was not in the value array.")
+ },
+ _ => throw new ArgumentOutOfRangeException($"Trying to access {row}, {col} which was not in the value array.")
+ };
}
}
@@ -201,7 +172,7 @@ public static TransformationMatrix GetRotationMatrix(double degreesCounterclockw
/// Create a new .
///
/// The 9 values of the matrix.
- public TransformationMatrix(double[] value) : this(value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], value[8])
+ public TransformationMatrix(ReadOnlySpan value) : this(value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], value[8])
{
}
@@ -373,7 +344,7 @@ public static TransformationMatrix FromValues(double a, double b, double c, doub
///
/// Either all 9 values of the matrix, 6 values in the default PDF order or the 4 values of the top left square.
///
- public static TransformationMatrix FromArray(double[] values)
+ public static TransformationMatrix FromArray(ReadOnlySpan values)
{
if (values.Length == 9)
{
@@ -394,7 +365,7 @@ public static TransformationMatrix FromArray(double[] values)
0, 0, 1);
}
- throw new ArgumentException("The array must either define all 9 elements of the matrix or all 6 key elements. Instead array was: " + values);
+ throw new ArgumentException("The array must either define all 9 elements of the matrix or all 6 key elements. Instead array was: " + string.Join(", ", values.ToArray()));
}
///
@@ -403,7 +374,7 @@ public static TransformationMatrix FromArray(double[] values)
/// The matrix to multiply
/// The resulting matrix.
[Pure]
- public TransformationMatrix Multiply(TransformationMatrix matrix)
+ public TransformationMatrix Multiply(in TransformationMatrix matrix)
{
var a = (A * matrix.A) + (B * matrix.C) + (row1 * matrix.E);
var b = (A * matrix.B) + (B * matrix.D) + (row1 * matrix.F);
@@ -524,17 +495,19 @@ public static bool Equals(TransformationMatrix a, TransformationMatrix b)
///
public override int GetHashCode()
{
- var hashCode = 472622392;
- hashCode = hashCode * -1521134295 + row1.GetHashCode();
- hashCode = hashCode * -1521134295 + row2.GetHashCode();
- hashCode = hashCode * -1521134295 + row3.GetHashCode();
- hashCode = hashCode * -1521134295 + A.GetHashCode();
- hashCode = hashCode * -1521134295 + B.GetHashCode();
- hashCode = hashCode * -1521134295 + C.GetHashCode();
- hashCode = hashCode * -1521134295 + D.GetHashCode();
- hashCode = hashCode * -1521134295 + E.GetHashCode();
- hashCode = hashCode * -1521134295 + F.GetHashCode();
- return hashCode;
+ var hashCode = new HashCode();
+
+ hashCode.Add(row1);
+ hashCode.Add(row2);
+ hashCode.Add(row3);
+ hashCode.Add(A);
+ hashCode.Add(B);
+ hashCode.Add(C);
+ hashCode.Add(D);
+ hashCode.Add(E);
+ hashCode.Add(F);
+
+ return hashCode.ToHashCode();
}
///
diff --git a/src/UglyToad.PdfPig.DocumentLayoutAnalysis/Globals.cs b/src/UglyToad.PdfPig.DocumentLayoutAnalysis/Globals.cs
new file mode 100644
index 000000000..30cd4b7b4
--- /dev/null
+++ b/src/UglyToad.PdfPig.DocumentLayoutAnalysis/Globals.cs
@@ -0,0 +1,2 @@
+global using System;
+global using System.Collections.Generic;
\ No newline at end of file
diff --git a/src/UglyToad.PdfPig.Fonts/Globals.cs b/src/UglyToad.PdfPig.Fonts/Globals.cs
new file mode 100644
index 000000000..30cd4b7b4
--- /dev/null
+++ b/src/UglyToad.PdfPig.Fonts/Globals.cs
@@ -0,0 +1,2 @@
+global using System;
+global using System.Collections.Generic;
\ No newline at end of file
diff --git a/src/UglyToad.PdfPig.Tokenization/Globals.cs b/src/UglyToad.PdfPig.Tokenization/Globals.cs
new file mode 100644
index 000000000..30cd4b7b4
--- /dev/null
+++ b/src/UglyToad.PdfPig.Tokenization/Globals.cs
@@ -0,0 +1,2 @@
+global using System;
+global using System.Collections.Generic;
\ No newline at end of file
diff --git a/src/UglyToad.PdfPig.Tokens/Globals.cs b/src/UglyToad.PdfPig.Tokens/Globals.cs
new file mode 100644
index 000000000..30cd4b7b4
--- /dev/null
+++ b/src/UglyToad.PdfPig.Tokens/Globals.cs
@@ -0,0 +1,2 @@
+global using System;
+global using System.Collections.Generic;
\ No newline at end of file
diff --git a/src/UglyToad.PdfPig/Annotations/QuadPointsQuadrilateral.cs b/src/UglyToad.PdfPig/Annotations/QuadPointsQuadrilateral.cs
index e39973be2..5dcb6f8c7 100644
--- a/src/UglyToad.PdfPig/Annotations/QuadPointsQuadrilateral.cs
+++ b/src/UglyToad.PdfPig/Annotations/QuadPointsQuadrilateral.cs
@@ -1,7 +1,5 @@
namespace UglyToad.PdfPig.Annotations
{
- using System;
- using System.Collections.Generic;
using Core;
///
@@ -10,13 +8,15 @@
///
public readonly struct QuadPointsQuadrilateral
{
+ private readonly PdfPoint[] points;
+
///
/// The 4 points defining this quadrilateral.
/// The PDF specification defines these as being in anti-clockwise order starting from the lower-left corner, however
/// Adobe's implementation doesn't obey the specification and points seem to go in the order: top-left, top-right,
/// bottom-left, bottom-right. See: https://stackoverflow.com/questions/9855814/pdf-spec-vs-acrobat-creation-quadpoints.
///
- public IReadOnlyList Points { get; }
+ public ReadOnlySpan Points => points;
///
/// Create a new .
@@ -33,7 +33,7 @@ public QuadPointsQuadrilateral(PdfPoint[] points)
throw new ArgumentException($"Quadpoints quadrilateral should only contain 4 points, instead got {points.Length} points.");
}
- Points = points;
+ this.points = points;
}
///
diff --git a/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs b/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs
index b483846ec..675776354 100644
--- a/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs
+++ b/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs
@@ -1,10 +1,8 @@
namespace UglyToad.PdfPig.Geometry
{
- using Core;
- using System;
- using System.Collections.Generic;
using System.Linq;
using System.Text;
+ using Core;
using UglyToad.PdfPig.Geometry.ClipperLibrary;
using UglyToad.PdfPig.Graphics;
using static UglyToad.PdfPig.Core.PdfSubpath;
@@ -83,7 +81,7 @@ private static PdfRectangle ParametricPerpendicularProjection(IReadOnlyList mrb = stackalloc double[8];
double Amin = double.PositiveInfinity;
int j = 1;
@@ -169,7 +167,7 @@ private static PdfRectangle ParametricPerpendicularProjection(IReadOnlyList
@@ -471,10 +469,19 @@ public static bool IntersectsWith(this PdfRectangle rectangle, PdfRectangle othe
/// Gets the axis-aligned rectangle that completely containing the original rectangle, with no rotation.
///
///
- public static PdfRectangle Normalise(this PdfRectangle rectangle)
+ public static PdfRectangle Normalise(this in PdfRectangle rectangle)
{
- var points = new[] { rectangle.BottomLeft, rectangle.BottomRight, rectangle.TopLeft, rectangle.TopRight };
- return new PdfRectangle(points.Min(p => p.X), points.Min(p => p.Y), points.Max(p => p.X), points.Max(p => p.Y));
+ var bottomLeft = rectangle.BottomLeft;
+ var bottomRight = rectangle.BottomRight;
+ var topLeft = rectangle.TopLeft;
+ var topRight = rectangle.TopRight;
+
+ var minX = Math.Min(Math.Min(bottomLeft.X, bottomRight.X), Math.Min(topLeft.X, topRight.X));
+ var minY = Math.Min(Math.Min(bottomLeft.Y, bottomRight.Y), Math.Min(topLeft.Y, topRight.Y));
+ var maxX = Math.Max(Math.Max(bottomLeft.X, bottomRight.X), Math.Max(topLeft.X, topRight.X));
+ var maxY = Math.Max(Math.Max(bottomLeft.Y, bottomRight.Y), Math.Max(topLeft.Y, topRight.Y));
+
+ return new PdfRectangle(minX, minY, maxX, maxY);
}
///
diff --git a/src/UglyToad.PdfPig/Globals.cs b/src/UglyToad.PdfPig/Globals.cs
new file mode 100644
index 000000000..30cd4b7b4
--- /dev/null
+++ b/src/UglyToad.PdfPig/Globals.cs
@@ -0,0 +1,2 @@
+global using System;
+global using System.Collections.Generic;
\ No newline at end of file
diff --git a/src/UglyToad.PdfPig/Images/Png/Adam7.cs b/src/UglyToad.PdfPig/Images/Png/Adam7.cs
index 0d4e5d45e..ce4ac0ad3 100644
--- a/src/UglyToad.PdfPig/Images/Png/Adam7.cs
+++ b/src/UglyToad.PdfPig/Images/Png/Adam7.cs
@@ -1,33 +1,29 @@
namespace UglyToad.PdfPig.Images.Png
{
- using System.Collections.Generic;
-
internal static class Adam7
{
///
/// For a given pass number (1 indexed) the scanline indexes of the lines included in that pass in the 8x8 grid.
///
- private static readonly IReadOnlyDictionary PassToScanlineGridIndex = new Dictionary
- {
- { 1, [0] },
- { 2, [0] },
- { 3, [4] },
- { 4, [0, 4] },
- { 5, [2, 6] },
- { 6, [0, 2, 4, 6] },
- { 7, [1, 3, 5, 7] }
- };
-
- private static readonly IReadOnlyDictionary PassToScanlineColumnIndex = new Dictionary
- {
- { 1, [0] },
- { 2, [4] },
- { 3, [0, 4] },
- { 4, [2, 6] },
- { 5, [0, 2, 4, 6] },
- { 6, [1, 3, 5, 7] },
- { 7, [0, 1, 2, 3, 4, 5, 6, 7] }
- };
+ private static readonly int[][] PassToScanlineGridIndex = [
+ [0],
+ [0],
+ [4],
+ [0, 4],
+ [2, 6],
+ [0, 2, 4, 6],
+ [1, 3, 5, 7]
+ ];
+
+ private static readonly int[][] PassToScanlineColumnIndex = [
+ [0],
+ [4],
+ [0, 4],
+ [2, 6],
+ [0, 2, 4, 6],
+ [1, 3, 5, 7],
+ [0, 1, 2, 3, 4, 5, 6, 7]
+ ];
/*
* To go from raw image data to interlaced:
@@ -50,7 +46,7 @@ internal static class Adam7
public static int GetNumberOfScanlinesInPass(ImageHeader header, int pass)
{
- var indices = PassToScanlineGridIndex[pass + 1];
+ var indices = PassToScanlineGridIndex[pass];
var mod = header.Height % 8;
@@ -75,7 +71,7 @@ public static int GetNumberOfScanlinesInPass(ImageHeader header, int pass)
public static int GetPixelsPerScanlineInPass(ImageHeader header, int pass)
{
- var indices = PassToScanlineColumnIndex[pass + 1];
+ var indices = PassToScanlineColumnIndex[pass];
var mod = header.Width % 8;
@@ -100,8 +96,8 @@ public static int GetPixelsPerScanlineInPass(ImageHeader header, int pass)
public static (int x, int y) GetPixelIndexForScanlineInPass(ImageHeader header, int pass, int scanlineIndex, int indexInScanline)
{
- var columnIndices = PassToScanlineColumnIndex[pass + 1];
- var rows = PassToScanlineGridIndex[pass + 1];
+ var columnIndices = PassToScanlineColumnIndex[pass];
+ var rows = PassToScanlineGridIndex[pass];
var actualRow = scanlineIndex % rows.Length;
var actualCol = indexInScanline % columnIndices.Length;
diff --git a/src/UglyToad.PdfPig/Parser/Parts/CrossReference/CrossReferenceStreamParser.cs b/src/UglyToad.PdfPig/Parser/Parts/CrossReference/CrossReferenceStreamParser.cs
index 19ff452f8..0e3f78df8 100644
--- a/src/UglyToad.PdfPig/Parser/Parts/CrossReference/CrossReferenceStreamParser.cs
+++ b/src/UglyToad.PdfPig/Parser/Parts/CrossReference/CrossReferenceStreamParser.cs
@@ -1,6 +1,5 @@
namespace UglyToad.PdfPig.Parser.Parts.CrossReference
{
- using System.Collections.Generic;
using Core;
using Filters;
using PdfPig.CrossReference;
@@ -45,7 +44,10 @@ public CrossReferenceTablePart Parse(long streamOffset, long? fromTableAtOffset,
var objectNumbers = GetObjectNumbers(stream.StreamDictionary);
var lineNumber = 0;
- var lineBuffer = new byte[fieldSizes.LineLength];
+ Span lineBuffer = fieldSizes.LineLength <= 64
+ ? stackalloc byte[fieldSizes.LineLength]
+ : new byte[fieldSizes.LineLength];
+
foreach (var objectNumber in objectNumbers)
{
if (lineNumber >= lineCount)
@@ -84,7 +86,7 @@ public CrossReferenceTablePart Parse(long streamOffset, long? fromTableAtOffset,
}
private static void ReadNextStreamObject(int type, long objectNumber, CrossReferenceStreamFieldSize fieldSizes,
- CrossReferenceTablePartBuilder builder, byte[] lineBuffer)
+ CrossReferenceTablePartBuilder builder, ReadOnlySpan lineBuffer)
{
switch (type)
{
diff --git a/src/UglyToad.PdfPig/Writer/NoTextTokenWriter.cs b/src/UglyToad.PdfPig/Writer/NoTextTokenWriter.cs
index 712f1171f..ff8857086 100644
--- a/src/UglyToad.PdfPig/Writer/NoTextTokenWriter.cs
+++ b/src/UglyToad.PdfPig/Writer/NoTextTokenWriter.cs
@@ -1,13 +1,10 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
-using System.Linq;
using UglyToad.PdfPig.Core;
using UglyToad.PdfPig.Filters;
-using UglyToad.PdfPig.Graphics.Operations.TextShowing;
-using UglyToad.PdfPig.Graphics.Operations;
using UglyToad.PdfPig.Graphics;
+using UglyToad.PdfPig.Graphics.Operations;
+using UglyToad.PdfPig.Graphics.Operations.TextShowing;
using UglyToad.PdfPig.Logging;
using UglyToad.PdfPig.Parser;
using UglyToad.PdfPig.Tokens;
@@ -17,7 +14,7 @@ namespace UglyToad.PdfPig.Writer
///
/// Derived class of that does not write or operations in streams
///
- internal class NoTextTokenWriter : TokenWriter
+ internal sealed class NoTextTokenWriter : TokenWriter
{
///
/// Set this value prior to processing page to get the right page number in log messages