Browse Source

Introduced new Color struct utilizing more performant uint-based value

Marcin Ziąbek 1 year ago
parent
commit
f4ef02d7f7
43 changed files with 589 additions and 577 deletions
  1. 3 2
      Source/QuestPDF.Examples/CanvasExamples.cs
  2. 1 1
      Source/QuestPDF.Examples/DynamicFibonacci.cs
  3. 14 14
      Source/QuestPDF.Examples/ElementExamples.cs
  4. 1 1
      Source/QuestPDF.Examples/FrameExample.cs
  5. 2 1
      Source/QuestPDF.Examples/LoremPicsumExample.cs
  6. 22 21
      Source/QuestPDF.Examples/Padding.cs
  7. 1 1
      Source/QuestPDF.Examples/PageBackgroundForegroundExample.cs
  8. 2 2
      Source/QuestPDF.Examples/PlaceholderExamples.cs
  9. 1 1
      Source/QuestPDF.Examples/StopPaging.cs
  10. 2 1
      Source/QuestPDF.Examples/TableExamples.cs
  11. 1 1
      Source/QuestPDF.Examples/TextBenchmark.cs
  12. 2 2
      Source/QuestPDF.LayoutTests/TestEngine/AnnotateInvalidAreaHelper.cs
  13. 12 12
      Source/QuestPDF.LayoutTests/TestEngine/LayoutTestOutputVisualization.cs
  14. 2 2
      Source/QuestPDF.UnitTests/ImageTests.cs
  15. 4 4
      Source/QuestPDF.UnitTests/TestEngine/MockCanvas.cs
  16. 3 3
      Source/QuestPDF.UnitTests/TestEngine/OperationRecordingCanvas.cs
  17. 2 2
      Source/QuestPDF.UnitTests/TestEngine/Operations/CanvasDrawRectangleOperation.cs
  18. 1 1
      Source/QuestPDF.UnitTests/TestEngine/TestPlan.cs
  19. 3 3
      Source/QuestPDF/Drawing/FreeCanvas.cs
  20. 7 7
      Source/QuestPDF/Drawing/SkiaCanvasBase.cs
  21. 1 1
      Source/QuestPDF/Elements/Background.cs
  22. 1 1
      Source/QuestPDF/Elements/Border.cs
  23. 2 2
      Source/QuestPDF/Elements/DebugArea.cs
  24. 3 3
      Source/QuestPDF/Elements/LayoutOverflowVisualization.cs
  25. 1 1
      Source/QuestPDF/Elements/Line.cs
  26. 1 1
      Source/QuestPDF/Elements/Page.cs
  27. 2 2
      Source/QuestPDF/Elements/SvgPath.cs
  28. 1 3
      Source/QuestPDF/Fluent/BorderExtensions.cs
  29. 2 4
      Source/QuestPDF/Fluent/DebugExtensions.cs
  30. 1 3
      Source/QuestPDF/Fluent/ElementExtensions.cs
  31. 1 2
      Source/QuestPDF/Fluent/LineExtensions.cs
  32. 2 3
      Source/QuestPDF/Fluent/PageExtensions.cs
  33. 1 1
      Source/QuestPDF/Fluent/SvgExtensions.cs
  34. 2 4
      Source/QuestPDF/Fluent/TextSpanDescriptorExtensions.cs
  35. 2 4
      Source/QuestPDF/Fluent/TextStyleExtensions.cs
  36. 90 5
      Source/QuestPDF/Helpers/ColorParser.cs
  37. 0 33
      Source/QuestPDF/Helpers/ColorValidator.cs
  38. 314 312
      Source/QuestPDF/Helpers/Colors.cs
  39. 3 4
      Source/QuestPDF/Helpers/Placeholders.cs
  40. 65 0
      Source/QuestPDF/Infrastructure/Color.cs
  41. 3 3
      Source/QuestPDF/Infrastructure/ICanvas.cs
  42. 5 5
      Source/QuestPDF/Infrastructure/TextStyle.cs
  43. 0 98
      Source/QuestPDF/Skia/SkColor.cs

+ 3 - 2
Source/QuestPDF.Examples/CanvasExamples.cs

@@ -2,6 +2,7 @@ using NUnit.Framework;
 using QuestPDF.Examples.Engine;
 using QuestPDF.Examples.Engine;
 using QuestPDF.Fluent;
 using QuestPDF.Fluent;
 using QuestPDF.Helpers;
 using QuestPDF.Helpers;
+using QuestPDF.Infrastructure;
 using SkiaSharp;
 using SkiaSharp;
 
 
 namespace QuestPDF.Examples
 namespace QuestPDF.Examples
@@ -29,11 +30,11 @@ namespace QuestPDF.Examples
                                 DrawRoundedRectangle(Colors.White, false);
                                 DrawRoundedRectangle(Colors.White, false);
                                 DrawRoundedRectangle(Colors.Blue.Darken2, true);
                                 DrawRoundedRectangle(Colors.Blue.Darken2, true);
 
 
-                                void DrawRoundedRectangle(string color, bool isStroke)
+                                void DrawRoundedRectangle(Color color, bool isStroke)
                                 {
                                 {
                                     using var paint = new SKPaint
                                     using var paint = new SKPaint
                                     {
                                     {
-                                        Color = SKColor.Parse(color),
+                                        Color = new SKColor(color.Hex),
                                         IsStroke = isStroke,
                                         IsStroke = isStroke,
                                         StrokeWidth = 2,
                                         StrokeWidth = 2,
                                         IsAntialias = true
                                         IsAntialias = true

+ 1 - 1
Source/QuestPDF.Examples/DynamicFibonacci.cs

@@ -19,7 +19,7 @@ namespace QuestPDF.Examples
     {
     {
         public FibonacciHeaderState State { get; set; }
         public FibonacciHeaderState State { get; set; }
         
         
-        public static readonly string[] ColorsTable =
+        public static readonly Color[] ColorsTable =
         {
         {
             Colors.Red.Lighten2,
             Colors.Red.Lighten2,
             Colors.Orange.Lighten2,
             Colors.Orange.Lighten2,

+ 14 - 14
Source/QuestPDF.Examples/ElementExamples.cs

@@ -20,7 +20,7 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FFF")
+                        .Background(Colors.White)
                         .Padding(25)
                         .Padding(25)
                         .Placeholder();
                         .Placeholder();
                 });
                 });
@@ -35,7 +35,7 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FFF")
+                        .Background(Colors.White)
                         .Padding(25)
                         .Padding(25)
                         .Decoration(decoration =>
                         .Decoration(decoration =>
                         {
                         {
@@ -45,7 +45,7 @@ namespace QuestPDF.Examples
                                 .Padding(10)
                                 .Padding(10)
                                 .Text("Notes")
                                 .Text("Notes")
                                 .FontSize(16)
                                 .FontSize(16)
-                                .FontColor("#FFF");
+                                .FontColor(Colors.White);
                     
                     
                             decoration
                             decoration
                                 .Content()
                                 .Content()
@@ -67,7 +67,7 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FFF")
+                        .Background(Colors.White)
                         .Padding(20)
                         .Padding(20)
                         .Column(column =>
                         .Column(column =>
                         {
                         {
@@ -107,7 +107,7 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FFF")
+                        .Background(Colors.White)
                         .Padding(20)
                         .Padding(20)
                         .Row(row =>
                         .Row(row =>
                         {
                         {
@@ -128,7 +128,7 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FFF")
+                        .Background(Colors.White)
                         .Padding(15)
                         .Padding(15)
                         .Column(column =>
                         .Column(column =>
                         {
                         {
@@ -178,7 +178,7 @@ namespace QuestPDF.Examples
                         .Element(x =>
                         .Element(x =>
                         {
                         {
                             if (string.IsNullOrWhiteSpace(text))
                             if (string.IsNullOrWhiteSpace(text))
-                                x.Height(10).Width(50).Background("#DDD");
+                                x.Height(10).Width(50).Background(Colors.Grey.Medium);
                             else
                             else
                                 x.Text(text);
                                 x.Text(text);
                         });
                         });
@@ -228,7 +228,7 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FFF")
+                        .Background(Colors.White)
                         .Padding(25)
                         .Padding(25)
                         .SkiaSharpCanvas((canvas, size) =>
                         .SkiaSharpCanvas((canvas, size) =>
                         {
                         {
@@ -439,7 +439,7 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FFF")
+                        .Background(Colors.White)
                         .Padding(25)
                         .Padding(25)
                         .Layers(layers =>
                         .Layers(layers =>
                         {
                         {
@@ -463,7 +463,7 @@ namespace QuestPDF.Examples
                                 canvas.DrawCircle(0, 0, 50, paint);
                                 canvas.DrawCircle(0, 0, 50, paint);
                             });
                             });
                     
                     
-                            layers.Layer().Background("#8F00").Extend();
+                            layers.Layer().Background(Colors.Red.Medium.WithAlpha(128)).Extend();
                             layers.Layer().PaddingTop(40).Text("It works!").FontSize(24);
                             layers.Layer().PaddingTop(40).Text("It works!").FontSize(24);
                         });
                         });
                 });
                 });
@@ -478,7 +478,7 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FFF")
+                        .Background(Colors.White)
                         .Padding(15)
                         .Padding(15)
                         .Border(4)
                         .Border(4)
                         .BorderColor(Colors.Blue.Medium)
                         .BorderColor(Colors.Blue.Medium)
@@ -504,8 +504,8 @@ namespace QuestPDF.Examples
                         {
                         {
                             var headerFontStyle = TextStyle
                             var headerFontStyle = TextStyle
                                 .Default
                                 .Default
-                                .Size(20)
-                                .Color(Colors.Blue.Darken2)
+                                .FontSize(20)
+                                .FontColor(Colors.Blue.Darken2)
                                 .SemiBold();
                                 .SemiBold();
     
     
                             decoration
                             decoration
@@ -551,7 +551,7 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FFF")
+                        .Background(Colors.White)
                         .MinimalBox()
                         .MinimalBox()
                         
                         
                         .Padding(25)
                         .Padding(25)

+ 1 - 1
Source/QuestPDF.Examples/FrameExample.cs

@@ -34,7 +34,7 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FFF")
+                        .Background(Colors.White)
                         .Padding(25)
                         .Padding(25)
                         .Column(column =>
                         .Column(column =>
                         {
                         {

+ 2 - 1
Source/QuestPDF.Examples/LoremPicsumExample.cs

@@ -2,6 +2,7 @@ using System.Net;
 using NUnit.Framework;
 using NUnit.Framework;
 using QuestPDF.Examples.Engine;
 using QuestPDF.Examples.Engine;
 using QuestPDF.Fluent;
 using QuestPDF.Fluent;
+using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
 using QuestPDF.Infrastructure;
 
 
 namespace QuestPDF.Examples
 namespace QuestPDF.Examples
@@ -43,7 +44,7 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FFF")
+                        .Background(Colors.White)
                         .Padding(25)
                         .Padding(25)
                         .Column(column =>
                         .Column(column =>
                         {
                         {

+ 22 - 21
Source/QuestPDF.Examples/Padding.cs

@@ -1,6 +1,7 @@
 using NUnit.Framework;
 using NUnit.Framework;
 using QuestPDF.Examples.Engine;
 using QuestPDF.Examples.Engine;
 using QuestPDF.Fluent;
 using QuestPDF.Fluent;
+using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
 using QuestPDF.Infrastructure;
 
 
 namespace QuestPDF.Examples
 namespace QuestPDF.Examples
@@ -17,16 +18,16 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#FDD")
+                        .Background(Colors.Red.Lighten2)
                         .Padding(50)
                         .Padding(50)
 
 
-                        .Background("#AFA")
+                        .Background(Colors.Green.Lighten2)
                         .PaddingVertical(50)
                         .PaddingVertical(50)
 
 
-                        .Background("#77F")
+                        .Background(Colors.Blue.Lighten2)
                         .PaddingHorizontal(50)
                         .PaddingHorizontal(50)
 
 
-                        .Background("#444");
+                        .Background(Colors.Grey.Darken2);
                 });
                 });
         }
         }
         
         
@@ -39,15 +40,15 @@ namespace QuestPDF.Examples
                 .Render(container =>
                 .Render(container =>
                 {
                 {
                     container
                     container
-                        .Background("#EEE")
+                        .Background(Colors.Grey.Lighten3)
                         .Padding(25)
                         .Padding(25)
 
 
                         .AlignBottom()
                         .AlignBottom()
                         .AlignCenter()
                         .AlignCenter()
                         .BorderBottom(2)
                         .BorderBottom(2)
-                        .BorderColor("#000")
+                        .BorderColor(Colors.Black)
                 
                 
-                        .Background("FFF")
+                        .Background(Colors.White)
                         .Padding(5)
                         .Padding(5)
                         .AlignCenter()
                         .AlignCenter()
                         .Text("Sample text")
                         .Text("Sample text")
@@ -69,38 +70,38 @@ namespace QuestPDF.Examples
                             column
                             column
                                 .Item()
                                 .Item()
                                 .Height(100)
                                 .Height(100)
-                                .Background("#FFF")
+                                .Background(Colors.White)
                         
                         
                                 .AlignLeft()
                                 .AlignLeft()
                                 .AlignMiddle()
                                 .AlignMiddle()
 
 
                                 .Width(50)
                                 .Width(50)
                                 .Height(50)
                                 .Height(50)
-                                .Background("#444");
+                                .Background(Colors.Grey.Darken2);
                     
                     
                             column
                             column
                                 .Item()
                                 .Item()
                                 .Height(100)
                                 .Height(100)
-                                .Background("#DDD")
+                                .Background(Colors.Grey.Lighten4)
                         
                         
                                 .AlignCenter()
                                 .AlignCenter()
                                 .AlignMiddle()
                                 .AlignMiddle()
 
 
                                 .Width(50)
                                 .Width(50)
                                 .Height(50)
                                 .Height(50)
-                                .Background("#222");
+                                .Background(Colors.Grey.Darken3);
                     
                     
                             column
                             column
                                 .Item()
                                 .Item()
                                 .Height(100)
                                 .Height(100)
-                                .Background("#BBB")
+                                .Background(Colors.Grey.Lighten3)
                         
                         
                                 .AlignRight()
                                 .AlignRight()
                                 .AlignMiddle()
                                 .AlignMiddle()
 
 
                                 .Width(50)
                                 .Width(50)
                                 .Height(50)
                                 .Height(50)
-                                .Background("#000");
+                                .Background(Colors.Black);
                         });
                         });
                 });
                 });
         }
         }
@@ -123,19 +124,19 @@ namespace QuestPDF.Examples
                                 {
                                 {
                                     row.RelativeItem()
                                     row.RelativeItem()
                                         .Extend()
                                         .Extend()
-                                        .Background("FFF")
+                                        .Background(Colors.White)
 
 
                                         .Height(50)
                                         .Height(50)
                                         .Width(50)
                                         .Width(50)
-                                        .Background("444");
+                                        .Background(Colors.Grey.Darken2);
                             
                             
                                     row.RelativeItem()
                                     row.RelativeItem()
                                         .Extend()
                                         .Extend()
-                                        .Background("BBB")
+                                        .Background(Colors.Grey.Lighten3)
 
 
                                         .Height(50)
                                         .Height(50)
                                         .ExtendHorizontal()
                                         .ExtendHorizontal()
-                                        .Background("444");
+                                        .Background(Colors.Grey.Darken2);
                                 });
                                 });
                     
                     
                             column
                             column
@@ -145,19 +146,19 @@ namespace QuestPDF.Examples
                                 {
                                 {
                                     row.RelativeItem()
                                     row.RelativeItem()
                                         .Extend()
                                         .Extend()
-                                        .Background("BBB")
+                                        .Background(Colors.Grey.Lighten3)
 
 
                                         .ExtendVertical()
                                         .ExtendVertical()
                                         .Width(50)
                                         .Width(50)
-                                        .Background("444");
+                                        .Background(Colors.Grey.Darken2);
                             
                             
                                     row.RelativeItem()
                                     row.RelativeItem()
                                         .Extend()
                                         .Extend()
-                                        .Background("BBB")
+                                        .Background(Colors.Grey.Lighten3)
 
 
                                         .ExtendVertical()
                                         .ExtendVertical()
                                         .ExtendHorizontal()
                                         .ExtendHorizontal()
-                                        .Background("444");
+                                        .Background(Colors.Grey.Darken2);
                                 });
                                 });
                         });
                         });
                 });
                 });

+ 1 - 1
Source/QuestPDF.Examples/PageBackgroundForegroundExample.cs

@@ -27,7 +27,7 @@ namespace QuestPDF.Examples
                         page.DefaultTextStyle(TextStyle.Default.FontSize(16));
                         page.DefaultTextStyle(TextStyle.Default.FontSize(16));
                         page.PageColor(Colors.White);
                         page.PageColor(Colors.White);
 
 
-                        const string transparentBlue = "#662196f3";
+                        var transparentBlue = Colors.LightBlue.Medium.WithAlpha(64);
 
 
                         page.Background()
                         page.Background()
                             .AlignTop()
                             .AlignTop()

+ 2 - 2
Source/QuestPDF.Examples/PlaceholderExamples.cs

@@ -106,13 +106,13 @@ public class PlaceholderExamples
     [Test]
     [Test]
     public void BackgroundColor()
     public void BackgroundColor()
     {
     {
-        PrintRandomValues(Placeholders.BackgroundColor);
+        PrintRandomValues(() => Placeholders.BackgroundColor());
     }
     }
     
     
     [Test]
     [Test]
     public void Color()
     public void Color()
     {
     {
-        PrintRandomValues(Placeholders.Color);
+        PrintRandomValues(() => Placeholders.Color());
     }
     }
 }
 }
     
     

+ 1 - 1
Source/QuestPDF.Examples/StopPaging.cs

@@ -27,7 +27,7 @@ namespace QuestPDF.Examples
                                 .Before()
                                 .Before()
                                 .Text(text =>
                                 .Text(text =>
                                 {
                                 {
-                                    text.DefaultTextStyle(TextStyle.Default.SemiBold().Color(Colors.Blue.Medium));
+                                    text.DefaultTextStyle(TextStyle.Default.SemiBold().FontColor(Colors.Blue.Medium));
                                     
                                     
                                     text.Span("Page ");
                                     text.Span("Page ");
                                     text.CurrentPageNumber();
                                     text.CurrentPageNumber();

+ 2 - 1
Source/QuestPDF.Examples/TableExamples.cs

@@ -11,6 +11,7 @@ using QuestPDF.Examples.Engine;
 using QuestPDF.Fluent;
 using QuestPDF.Fluent;
 using QuestPDF.Helpers;
 using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
 using QuestPDF.Infrastructure;
+using Color = QuestPDF.Infrastructure.Color;
 using IContainer = QuestPDF.Infrastructure.IContainer;
 using IContainer = QuestPDF.Infrastructure.IContainer;
 
 
 namespace QuestPDF.Examples
 namespace QuestPDF.Examples
@@ -398,7 +399,7 @@ namespace QuestPDF.Examples
                         .Border(1)
                         .Border(1)
                         .Table(table =>
                         .Table(table =>
                         {
                         {
-                            IContainer DefaultCellStyle(IContainer container, string backgroundColor)
+                            IContainer DefaultCellStyle(IContainer container, Color backgroundColor)
                             {
                             {
                                 return container
                                 return container
                                     .Border(1)
                                     .Border(1)

+ 1 - 1
Source/QuestPDF.Examples/TextBenchmark.cs

@@ -104,7 +104,7 @@ namespace QuestPDF.Examples
         
         
         private void ComposeBook(IDocumentContainer container, ICollection<BookChapter> chapters)
         private void ComposeBook(IDocumentContainer container, ICollection<BookChapter> chapters)
         {
         {
-            var subtitleStyle = TextStyle.Default.Size(24).SemiBold().Color(Colors.Blue.Medium);
+            var subtitleStyle = TextStyle.Default.Size(24).SemiBold().FontColor(Colors.Blue.Medium);
             var normalStyle = TextStyle.Default.Size(14);
             var normalStyle = TextStyle.Default.Size(14);
 
 
             container.Page(page =>
             container.Page(page =>

+ 2 - 2
Source/QuestPDF.LayoutTests/TestEngine/AnnotateInvalidAreaHelper.cs

@@ -7,7 +7,7 @@ internal static class AnnotateInvalidAreaHelper
 {
 {
     private const float StripeThickness = 1f;
     private const float StripeThickness = 1f;
     private const float StripeScale = 3f;
     private const float StripeScale = 3f;
-    private const string LineColor = Colors.Red.Medium;
+    private static readonly Color LineColor = Colors.Red.Medium;
     
     
     public static void Annotate(SKCanvas canvas, SKPath area)
     public static void Annotate(SKCanvas canvas, SKPath area)
     {
     {
@@ -24,7 +24,7 @@ internal static class AnnotateInvalidAreaHelper
 
 
             using var paint = new SKPaint
             using var paint = new SKPaint
             {
             {
-                Color = SKColor.Parse(LineColor),
+                Color = new SKColor(LineColor),
                 PathEffect = SKPathEffect.Create2DLine(StripeThickness, matrix),
                 PathEffect = SKPathEffect.Create2DLine(StripeThickness, matrix),
                 IsAntialias = true
                 IsAntialias = true
             };
             };

+ 12 - 12
Source/QuestPDF.LayoutTests/TestEngine/LayoutTestOutputVisualization.cs

@@ -13,9 +13,9 @@ internal static class LayoutTestResultVisualization
     private const int Padding = 10;
     private const int Padding = 10;
     
     
     // document colors
     // document colors
-    private const string DocumentBackgroundColor = Colors.Grey.Darken2;
-    private const string PageBackgroundColor = Colors.Grey.Lighten1;
-    private const string RequiredAreaBackgroundColor = Colors.White;
+    private static readonly Color DocumentBackgroundColor = Colors.Grey.Darken2;
+    private static readonly Color PageBackgroundColor = Colors.Grey.Lighten1;
+    private static readonly Color RequiredAreaBackgroundColor = Colors.White;
     
     
     // grid configuration
     // grid configuration
     private const float GridSize = 10;
     private const float GridSize = 10;
@@ -25,7 +25,7 @@ internal static class LayoutTestResultVisualization
     // mock drawing settings
     // mock drawing settings
     private const byte OccludedMockBorderThickness = 5;
     private const byte OccludedMockBorderThickness = 5;
 
 
-    private static readonly string[] DefaultElementColors =
+    private static readonly Color[] DefaultElementColors =
     {
     {
         Colors.DeepPurple.Lighten2,
         Colors.DeepPurple.Lighten2,
         Colors.Blue.Lighten2,
         Colors.Blue.Lighten2,
@@ -58,7 +58,7 @@ internal static class LayoutTestResultVisualization
         using var canvas = pdf.BeginPage(canvasWidth * OutputImageScale, canvasHeight * OutputImageScale);
         using var canvas = pdf.BeginPage(canvasWidth * OutputImageScale, canvasHeight * OutputImageScale);
         
         
         canvas.Scale(OutputImageScale, OutputImageScale);
         canvas.Scale(OutputImageScale, OutputImageScale);
-        canvas.Clear(SKColor.Parse(DocumentBackgroundColor));
+        canvas.Clear(new SKColor(DocumentBackgroundColor));
 
 
         // draw content
         // draw content
         var mockColors = AssignColorsToMocks();
         var mockColors = AssignColorsToMocks();
@@ -68,7 +68,7 @@ internal static class LayoutTestResultVisualization
         pdf.EndPage();
         pdf.EndPage();
         pdf.Close();
         pdf.Close();
 
 
-        IDictionary<string, string> AssignColorsToMocks()
+        IDictionary<string, Color> AssignColorsToMocks()
         {
         {
             var mocks = Enumerable
             var mocks = Enumerable
                 .Concat(result.ActualLayout.Pages, result.ExpectedLayout.Pages)
                 .Concat(result.ActualLayout.Pages, result.ExpectedLayout.Pages)
@@ -90,7 +90,7 @@ internal static class LayoutTestResultVisualization
             using var textPaint = new SKPaint
             using var textPaint = new SKPaint
             {
             {
                 TextSize = 8,
                 TextSize = 8,
-                Color = Colors.White.ColorToCode(),
+                Color = SKColors.White,
                 Typeface = SKTypeface.FromFamilyName("Calibri", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright),
                 Typeface = SKTypeface.FromFamilyName("Calibri", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright),
                 TextAlign = SKTextAlign.Center
                 TextAlign = SKTextAlign.Center
             };
             };
@@ -131,7 +131,7 @@ internal static class LayoutTestResultVisualization
             // draw page
             // draw page
             using var availableAreaPaint = new SKPaint
             using var availableAreaPaint = new SKPaint
             {
             {
-                Color = SKColor.Parse(PageBackgroundColor)
+                Color = new SKColor(PageBackgroundColor)
             };
             };
             
             
             canvas.DrawRect(0, 0, result.PageSize.Width, result.PageSize.Height, availableAreaPaint);
             canvas.DrawRect(0, 0, result.PageSize.Width, result.PageSize.Height, availableAreaPaint);
@@ -145,7 +145,7 @@ internal static class LayoutTestResultVisualization
             // draw required area
             // draw required area
             using var requiredAreaPaint = new SKPaint
             using var requiredAreaPaint = new SKPaint
             {
             {
-                Color = SKColor.Parse(RequiredAreaBackgroundColor)
+                Color = new SKColor(RequiredAreaBackgroundColor)
             };
             };
             
             
             canvas.DrawRect(0, 0, pageLayout.RequiredArea.Width, pageLayout.RequiredArea.Height, requiredAreaPaint);
             canvas.DrawRect(0, 0, pageLayout.RequiredArea.Width, pageLayout.RequiredArea.Height, requiredAreaPaint);
@@ -166,7 +166,7 @@ internal static class LayoutTestResultVisualization
                 
                 
             using var mockAreaPaint = new SKPaint
             using var mockAreaPaint = new SKPaint
             {
             {
-                Color = SKColor.Parse(color)
+                Color = new SKColor(color)
             };
             };
             
             
             canvas.Save();
             canvas.Save();
@@ -183,7 +183,7 @@ internal static class LayoutTestResultVisualization
                 
                 
             using var mockBorderPaint = new SKPaint
             using var mockBorderPaint = new SKPaint
             {
             {
-                Color = SKColor.Parse(color),
+                Color = new SKColor(color),
                 IsStroke = true,
                 IsStroke = true,
                 StrokeWidth = OccludedMockBorderThickness
                 StrokeWidth = OccludedMockBorderThickness
             };
             };
@@ -201,7 +201,7 @@ internal static class LayoutTestResultVisualization
         {
         {
             using var paint = new SKPaint
             using var paint = new SKPaint
             {
             {
-                Color = SKColor.Parse(Colors.Black).WithAlpha(GridLineTransparency),
+                Color = SKColors.Black.WithAlpha(GridLineTransparency),
                 StrokeWidth = GridLineThickness
                 StrokeWidth = GridLineThickness
             };
             };
 
 

+ 2 - 2
Source/QuestPDF.UnitTests/ImageTests.cs

@@ -51,7 +51,7 @@ namespace QuestPDF.UnitTests
         [Test]
         [Test]
         public void Fluent_RecognizesImageProportions()
         public void Fluent_RecognizesImageProportions()
         {
         {
-            var image = GenerateDocumentImage(600, 200);
+            var image = GenerateDocumentImage(60, 20);
             
             
             TestPlan
             TestPlan
                 .For(x =>
                 .For(x =>
@@ -61,7 +61,7 @@ namespace QuestPDF.UnitTests
                     return container;
                     return container;
                 })
                 })
                 .MeasureElement(new Size(300, 200))
                 .MeasureElement(new Size(300, 200))
-                .CheckMeasureResult(SpacePlan.FullRender(300, 100));;
+                .CheckMeasureResult(SpacePlan.FullRender(300, 100));
         }
         }
         
         
         [Test]
         [Test]

+ 4 - 4
Source/QuestPDF.UnitTests/TestEngine/MockCanvas.cs

@@ -12,7 +12,7 @@ namespace QuestPDF.UnitTests.TestEngine
         public Action<float> RotateFunc { get; set; }
         public Action<float> RotateFunc { get; set; }
         public Action<float, float> ScaleFunc { get; set; }
         public Action<float, float> ScaleFunc { get; set; }
         public Action<SkImage, Position, Size> DrawImageFunc { get; set; }
         public Action<SkImage, Position, Size> DrawImageFunc { get; set; }
-        public Action<Position, Size, string> DrawRectFunc { get; set; }
+        public Action<Position, Size, Color> DrawRectFunc { get; set; }
 
 
         public void Save() => throw new NotImplementedException();
         public void Save() => throw new NotImplementedException();
         public void Restore() => throw new NotImplementedException();
         public void Restore() => throw new NotImplementedException();
@@ -21,12 +21,12 @@ namespace QuestPDF.UnitTests.TestEngine
         public void Rotate(float angle) => RotateFunc(angle);
         public void Rotate(float angle) => RotateFunc(angle);
         public void Scale(float scaleX, float scaleY) => ScaleFunc(scaleX, scaleY);
         public void Scale(float scaleX, float scaleY) => ScaleFunc(scaleX, scaleY);
 
 
-        public void DrawFilledRectangle(Position vector, Size size, string color) => DrawRectFunc(vector, size, color);
-        public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, string color) => throw new NotImplementedException();
+        public void DrawFilledRectangle(Position vector, Size size, Color color) => DrawRectFunc(vector, size, color);
+        public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, Color color) => throw new NotImplementedException();
         public void DrawParagraph(SkParagraph paragraph) => throw new NotImplementedException();
         public void DrawParagraph(SkParagraph paragraph) => throw new NotImplementedException();
         public void DrawImage(SkImage image, Size size) => DrawImageFunc(image, Position.Zero, size);
         public void DrawImage(SkImage image, Size size) => DrawImageFunc(image, Position.Zero, size);
         public void DrawPicture(SkPicture picture) => throw new NotImplementedException();
         public void DrawPicture(SkPicture picture) => throw new NotImplementedException();
-        public void DrawSvgPath(string path, uint color) => throw new NotImplementedException();
+        public void DrawSvgPath(string path, Color color) => throw new NotImplementedException();
         public void DrawSvg(SkSvgImage svgImage, Size size) => throw new NotImplementedException();
         public void DrawSvg(SkSvgImage svgImage, Size size) => throw new NotImplementedException();
         
         
         public void DrawOverflowArea(SkRect area) => throw new NotImplementedException();
         public void DrawOverflowArea(SkRect area) => throw new NotImplementedException();

+ 3 - 3
Source/QuestPDF.UnitTests/TestEngine/OperationRecordingCanvas.cs

@@ -18,12 +18,12 @@ namespace QuestPDF.UnitTests.TestEngine
         public void Rotate(float angle) => Operations.Add(new CanvasRotateOperation(angle));
         public void Rotate(float angle) => Operations.Add(new CanvasRotateOperation(angle));
         public void Scale(float scaleX, float scaleY) => Operations.Add(new CanvasScaleOperation(scaleX, scaleY));
         public void Scale(float scaleX, float scaleY) => Operations.Add(new CanvasScaleOperation(scaleX, scaleY));
 
 
-        public void DrawFilledRectangle(Position vector, Size size, string color) => Operations.Add(new CanvasDrawRectangleOperation(vector, size, color));
-        public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, string color) => throw new NotImplementedException();
+        public void DrawFilledRectangle(Position vector, Size size, Color color) => Operations.Add(new CanvasDrawRectangleOperation(vector, size, color));
+        public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, Color color) => throw new NotImplementedException();
         public void DrawParagraph(SkParagraph paragraph) => throw new NotImplementedException();
         public void DrawParagraph(SkParagraph paragraph) => throw new NotImplementedException();
         public void DrawImage(SkImage image, Size size) => Operations.Add(new CanvasDrawImageOperation(Position.Zero, size));
         public void DrawImage(SkImage image, Size size) => Operations.Add(new CanvasDrawImageOperation(Position.Zero, size));
         public void DrawPicture(SkPicture picture) => throw new NotImplementedException();
         public void DrawPicture(SkPicture picture) => throw new NotImplementedException();
-        public void DrawSvgPath(string path, uint color) => throw new NotImplementedException();
+        public void DrawSvgPath(string path, Color color) => throw new NotImplementedException();
         public void DrawSvg(SkSvgImage svgImage, Size size) => throw new NotImplementedException();
         public void DrawSvg(SkSvgImage svgImage, Size size) => throw new NotImplementedException();
         
         
         public void DrawOverflowArea(SkRect area) => throw new NotImplementedException();
         public void DrawOverflowArea(SkRect area) => throw new NotImplementedException();

+ 2 - 2
Source/QuestPDF.UnitTests/TestEngine/Operations/CanvasDrawRectangleOperation.cs

@@ -6,9 +6,9 @@ namespace QuestPDF.UnitTests.TestEngine.Operations
     {
     {
         public Position Position { get; } 
         public Position Position { get; } 
         public Size Size { get; }
         public Size Size { get; }
-        public string Color { get; }
+        public Color Color { get; }
 
 
-        public CanvasDrawRectangleOperation(Position position, Size size, string color)
+        public CanvasDrawRectangleOperation(Position position, Size size, Color color)
         {
         {
             Position = position;
             Position = position;
             Size = size;
             Size = size;

+ 1 - 1
Source/QuestPDF.UnitTests/TestEngine/TestPlan.cs

@@ -184,7 +184,7 @@ namespace QuestPDF.UnitTests.TestEngine
             return AddOperation(new CanvasRotateOperation(angle));
             return AddOperation(new CanvasRotateOperation(angle));
         }
         }
         
         
-        public TestPlan ExpectCanvasDrawRectangle(Position position, Size size, string color)
+        public TestPlan ExpectCanvasDrawRectangle(Position position, Size size, Color color)
         {
         {
             return AddOperation(new CanvasDrawRectangleOperation(position, size, color));
             return AddOperation(new CanvasDrawRectangleOperation(position, size, color));
         }
         }

+ 3 - 3
Source/QuestPDF/Drawing/FreeCanvas.cs

@@ -54,12 +54,12 @@ namespace QuestPDF.Drawing
             
             
         }
         }
 
 
-        public void DrawFilledRectangle(Position vector, Size size, string color)
+        public void DrawFilledRectangle(Position vector, Size size, Color color)
         {
         {
             
             
         }
         }
 
 
-        public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, string color)
+        public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, Color color)
         {
         {
             
             
         }
         }
@@ -79,7 +79,7 @@ namespace QuestPDF.Drawing
             
             
         }
         }
 
 
-        public void DrawSvgPath(string path, uint color)
+        public void DrawSvgPath(string path, Color color)
         {
         {
             
             
         }
         }

+ 7 - 7
Source/QuestPDF/Drawing/SkiaCanvasBase.cs

@@ -40,11 +40,11 @@ namespace QuestPDF.Drawing
         private void DrawLayoutIssuesIndicatorOnCurrentPage()
         private void DrawLayoutIssuesIndicatorOnCurrentPage()
         {
         {
             // visual configuration
             // visual configuration
-            const string lineColor = Colors.Red.Medium;
+            var lineColor = Colors.Red.Medium;
             const byte lineOpacity = 64;
             const byte lineOpacity = 64;
         
         
             // implementation
             // implementation
-            var indicatorColor = SkColor.Parse(lineColor).ColorWithAlpha(lineOpacity);
+            var indicatorColor = lineColor.WithAlpha(lineOpacity);
             var position = new SkRect(0, 0, CurrentPageSize.Width, CurrentPageSize.Height);
             var position = new SkRect(0, 0, CurrentPageSize.Width, CurrentPageSize.Height);
             Canvas.DrawFilledRectangle(position, indicatorColor);
             Canvas.DrawFilledRectangle(position, indicatorColor);
         }
         }
@@ -68,22 +68,22 @@ namespace QuestPDF.Drawing
             Canvas.Translate(vector.X, vector.Y);
             Canvas.Translate(vector.X, vector.Y);
         }
         }
 
 
-        public void DrawFilledRectangle(Position vector, Size size, string color)
+        public void DrawFilledRectangle(Position vector, Size size, Color color)
         {
         {
             if (size.Width < Size.Epsilon || size.Height < Size.Epsilon)
             if (size.Width < Size.Epsilon || size.Height < Size.Epsilon)
                 return;
                 return;
 
 
             var position = new SkRect(vector.X, vector.Y, vector.X + size.Width, vector.Y + size.Height);
             var position = new SkRect(vector.X, vector.Y, vector.X + size.Width, vector.Y + size.Height);
-            Canvas.DrawFilledRectangle(position, color.ColorToCode());
+            Canvas.DrawFilledRectangle(position, color);
         }
         }
         
         
-        public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, string color)
+        public void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, Color color)
         {
         {
             if (size.Width < Size.Epsilon || size.Height < Size.Epsilon)
             if (size.Width < Size.Epsilon || size.Height < Size.Epsilon)
                 return;
                 return;
 
 
             var position = new SkRect(vector.X, vector.Y, vector.X + size.Width, vector.Y + size.Height);
             var position = new SkRect(vector.X, vector.Y, vector.X + size.Width, vector.Y + size.Height);
-            Canvas.DrawStrokeRectangle(position, strokeWidth, color.ColorToCode());
+            Canvas.DrawStrokeRectangle(position, strokeWidth, color);
         }
         }
 
 
         public void DrawParagraph(SkParagraph paragraph)
         public void DrawParagraph(SkParagraph paragraph)
@@ -101,7 +101,7 @@ namespace QuestPDF.Drawing
             Canvas.DrawPicture(picture);
             Canvas.DrawPicture(picture);
         }
         }
 
 
-        public void DrawSvgPath(string path, uint color)
+        public void DrawSvgPath(string path, Color color)
         {
         {
             Canvas.DrawSvgPath(path, color);
             Canvas.DrawSvgPath(path, color);
         }
         }

+ 1 - 1
Source/QuestPDF/Elements/Background.cs

@@ -5,7 +5,7 @@ namespace QuestPDF.Elements
 {
 {
     internal sealed class Background : ContainerElement
     internal sealed class Background : ContainerElement
     {
     {
-        public string Color { get; set; } = Colors.Black;
+        public Color Color { get; set; } = Colors.Black;
         
         
         internal override void Draw(Size availableSpace)
         internal override void Draw(Size availableSpace)
         {
         {

+ 1 - 1
Source/QuestPDF/Elements/Border.cs

@@ -5,7 +5,7 @@ namespace QuestPDF.Elements
 {
 {
     internal sealed class Border : ContainerElement
     internal sealed class Border : ContainerElement
     {
     {
-        public string Color { get; set; } = Colors.Black;
+        public Color Color { get; set; } = Colors.Black;
 
 
         public float Top { get; set; }
         public float Top { get; set; }
         public float Right { get; set; }
         public float Right { get; set; }

+ 2 - 2
Source/QuestPDF/Elements/DebugArea.cs

@@ -10,10 +10,10 @@ namespace QuestPDF.Elements
         public IElement? Child { get; set; }
         public IElement? Child { get; set; }
         
         
         public string Text { get; set; }
         public string Text { get; set; }
-        public string Color { get; set; } = Colors.Red.Medium;
+        public Color Color { get; set; } = Colors.Red.Medium;
         public void Compose(IContainer container)
         public void Compose(IContainer container)
         {
         {
-            var backgroundColor = SkColor.Parse(Color).ColorWithAlpha(50).ColorToString();
+            var backgroundColor = Color.WithAlpha(64);
             
             
             container
             container
                 .Border(1)
                 .Border(1)

+ 3 - 3
Source/QuestPDF/Elements/LayoutOverflowVisualization.cs

@@ -10,8 +10,8 @@ namespace QuestPDF.Elements;
 internal class LayoutOverflowVisualization : ContainerElement, IContentDirectionAware
 internal class LayoutOverflowVisualization : ContainerElement, IContentDirectionAware
 {
 {
     private const float BorderThickness = 1.5f;
     private const float BorderThickness = 1.5f;
-    private const string LineColor = Colors.Red.Medium;
-    private const string AvailableAreaColor = Colors.Green.Medium;
+    private readonly Color LineColor = Colors.Red.Medium;
+    private readonly Color AvailableAreaColor = Colors.Green.Medium;
     private const byte AreaOpacity = 64;
     private const byte AreaOpacity = 64;
 
 
     public ContentDirection ContentDirection { get; set; }
     public ContentDirection ContentDirection { get; set; }
@@ -67,7 +67,7 @@ internal class LayoutOverflowVisualization : ContainerElement, IContentDirection
 
 
     private void DrawOverflowArea(Size availableSpace, Size contentSize)
     private void DrawOverflowArea(Size availableSpace, Size contentSize)
     {
     {
-        var availableSpaceColor = SkColor.Parse(AvailableAreaColor).ColorWithAlpha(AreaOpacity).ColorToString();
+        var availableSpaceColor = AvailableAreaColor.WithAlpha(AreaOpacity);
         Canvas.DrawFilledRectangle(Position.Zero, availableSpace, availableSpaceColor);
         Canvas.DrawFilledRectangle(Position.Zero, availableSpace, availableSpaceColor);
 
 
         Canvas.Save();
         Canvas.Save();

+ 1 - 1
Source/QuestPDF/Elements/Line.cs

@@ -18,7 +18,7 @@ namespace QuestPDF.Elements
     internal sealed class Line : Element, ILine, ICacheable
     internal sealed class Line : Element, ILine, ICacheable
     {
     {
         public LineType Type { get; set; } = LineType.Vertical;
         public LineType Type { get; set; } = LineType.Vertical;
-        public string Color { get; set; } = Colors.Black;
+        public Color Color { get; set; } = Colors.Black;
         public float Size { get; set; } = 1;
         public float Size { get; set; } = 1;
         
         
         internal override SpacePlan Measure(Size availableSpace)
         internal override SpacePlan Measure(Size availableSpace)

+ 1 - 1
Source/QuestPDF/Elements/Page.cs

@@ -18,7 +18,7 @@ namespace QuestPDF.Elements
         public float MarginTop { get; set; }
         public float MarginTop { get; set; }
         public float MarginBottom { get; set; }
         public float MarginBottom { get; set; }
 
 
-        public string BackgroundColor { get; set; } = Colors.White;
+        public Color BackgroundColor { get; set; } = Colors.White;
         
         
         public Element Background { get; set; } = Empty.Instance;
         public Element Background { get; set; } = Empty.Instance;
         public Element Foreground { get; set; } = Empty.Instance;
         public Element Foreground { get; set; } = Empty.Instance;

+ 2 - 2
Source/QuestPDF/Elements/SvgPath.cs

@@ -8,7 +8,7 @@ namespace QuestPDF.Elements;
 internal class SvgPath : Element
 internal class SvgPath : Element
 {
 {
     public string Path { get; set; } = string.Empty;
     public string Path { get; set; } = string.Empty;
-    public string FillColor { get; set; } = Colors.Black;
+    public Color FillColor { get; set; } = Colors.Black;
     
     
     internal override SpacePlan Measure(Size availableSpace)
     internal override SpacePlan Measure(Size availableSpace)
     {
     {
@@ -19,6 +19,6 @@ internal class SvgPath : Element
 
 
     internal override void Draw(Size availableSpace)
     internal override void Draw(Size availableSpace)
     {
     {
-        Canvas.DrawSvgPath(Path, SkColor.Parse(FillColor));
+        Canvas.DrawSvgPath(Path, FillColor);
     }
     }
 }
 }

+ 1 - 3
Source/QuestPDF/Fluent/BorderExtensions.cs

@@ -93,10 +93,8 @@ namespace QuestPDF.Fluent
         /// <a href="https://www.questpdf.com/api-reference/border.html">Learn more</a>
         /// <a href="https://www.questpdf.com/api-reference/border.html">Learn more</a>
         /// </summary>
         /// </summary>
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
-        public static IContainer BorderColor(this IContainer element, string color)
+        public static IContainer BorderColor(this IContainer element, Color color)
         {
         {
-            ColorValidator.Validate(color);
-            
             var border = element as Border ?? new Border();
             var border = element as Border ?? new Border();
             border.Color = color;
             border.Color = color;
             return element.Element(border);
             return element.Element(border);

+ 2 - 4
Source/QuestPDF/Fluent/DebugExtensions.cs

@@ -15,17 +15,15 @@ namespace QuestPDF.Fluent
         /// </summary>
         /// </summary>
         /// <param name="text">Optional label displayed within the box.</param>
         /// <param name="text">Optional label displayed within the box.</param>
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
-        public static IContainer DebugArea(this IContainer parent, string? text = null, string color = Colors.Red.Medium)
+        public static IContainer DebugArea(this IContainer parent, string? text = null, Color? color = null)
         {
         {
-            ColorValidator.Validate(color);
-            
             var container = new Container();
             var container = new Container();
 
 
             parent.Component(new DebugArea
             parent.Component(new DebugArea
             {
             {
                 Child = container,
                 Child = container,
                 Text = text ?? string.Empty,
                 Text = text ?? string.Empty,
-                Color = color
+                Color = color ?? Colors.Red.Medium
             });
             });
 
 
             return container;
             return container;

+ 1 - 3
Source/QuestPDF/Fluent/ElementExtensions.cs

@@ -89,10 +89,8 @@ namespace QuestPDF.Fluent
         /// <a href="https://www.questpdf.com/api-reference/background.html">Learn more</a>
         /// <a href="https://www.questpdf.com/api-reference/background.html">Learn more</a>
         /// </summary>
         /// </summary>
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
-        public static IContainer Background(this IContainer element, string color)
+        public static IContainer Background(this IContainer element, Color color)
         {
         {
-            ColorValidator.Validate(color);
-            
             return element.Element(new Background
             return element.Element(new Background
             {
             {
                 Color = color
                 Color = color

+ 1 - 2
Source/QuestPDF/Fluent/LineExtensions.cs

@@ -48,9 +48,8 @@ namespace QuestPDF.Fluent
         /// Specifies the color for the line.
         /// Specifies the color for the line.
         /// </summary>
         /// </summary>
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
-        public static void LineColor(this ILine descriptor, string color)
+        public static void LineColor(this ILine descriptor, Color color)
         {
         {
-            ColorValidator.Validate(color);
             (descriptor as Line).Color = color;
             (descriptor as Line).Color = color;
         }
         }
     }
     }

+ 2 - 3
Source/QuestPDF/Fluent/PageExtensions.cs

@@ -186,14 +186,13 @@ namespace QuestPDF.Fluent
         /// When working with file formats that support the alpha channel, it is possible to set the color to <see cref="Colors.Transparent" /> if necessary.
         /// When working with file formats that support the alpha channel, it is possible to set the color to <see cref="Colors.Transparent" /> if necessary.
         /// </remarks>
         /// </remarks>
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
-        public void PageColor(string color)
+        public void PageColor(Color color)
         {
         {
-            ColorValidator.Validate(color);
             Page.BackgroundColor = color;
             Page.BackgroundColor = color;
         }
         }
         
         
         [Obsolete("This element has been renamed since version 2022.3. Please use the PageColor method.")]
         [Obsolete("This element has been renamed since version 2022.3. Please use the PageColor method.")]
-        public void Background(string color)
+        public void Background(Color color)
         {
         {
             PageColor(color);
             PageColor(color);
         }
         }

+ 1 - 1
Source/QuestPDF/Fluent/SvgExtensions.cs

@@ -66,7 +66,7 @@ public class SvgImageDescriptor
 
 
 public static class SvgExtensions
 public static class SvgExtensions
 {
 {
-    internal static void SvgPath(this IContainer container, string svgPath, string color)
+    internal static void SvgPath(this IContainer container, string svgPath, Color color)
     {
     {
         container.Element(new SvgPath
         container.Element(new SvgPath
         {
         {

+ 2 - 4
Source/QuestPDF/Fluent/TextSpanDescriptorExtensions.cs

@@ -31,18 +31,16 @@ namespace QuestPDF.Fluent
         
         
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="text.fontColor"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="text.fontColor"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
-        public static T FontColor<T>(this T descriptor, string color) where T : TextSpanDescriptor
+        public static T FontColor<T>(this T descriptor, Color color) where T : TextSpanDescriptor
         {
         {
-            ColorValidator.Validate(color);
             descriptor.MutateTextStyle(TextStyleExtensions.FontColor, color);
             descriptor.MutateTextStyle(TextStyleExtensions.FontColor, color);
             return descriptor;
             return descriptor;
         }
         }
         
         
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="text.backgroundColor"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="text.backgroundColor"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
-        public static T BackgroundColor<T>(this T descriptor, string color) where T : TextSpanDescriptor
+        public static T BackgroundColor<T>(this T descriptor, Color color) where T : TextSpanDescriptor
         {
         {
-            ColorValidator.Validate(color);
             descriptor.MutateTextStyle(TextStyleExtensions.BackgroundColor, color);
             descriptor.MutateTextStyle(TextStyleExtensions.BackgroundColor, color);
             return descriptor;
             return descriptor;
         }
         }

+ 2 - 4
Source/QuestPDF/Fluent/TextStyleExtensions.cs

@@ -14,17 +14,15 @@ namespace QuestPDF.Fluent
         
         
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="text.fontColor"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="text.fontColor"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
-        public static TextStyle FontColor(this TextStyle style, string color)
+        public static TextStyle FontColor(this TextStyle style, Color color)
         {
         {
-            ColorValidator.Validate(color);
             return style.Mutate(TextStyleProperty.Color, color);
             return style.Mutate(TextStyleProperty.Color, color);
         }
         }
         
         
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="text.backgroundColor"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="text.backgroundColor"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
         /// <include file='../Resources/Documentation.xml' path='documentation/doc[@for="colorParam"]/*' />
-        public static TextStyle BackgroundColor(this TextStyle style, string color)
+        public static TextStyle BackgroundColor(this TextStyle style, Color color)
         {
         {
-            ColorValidator.Validate(color);
             return style.Mutate(TextStyleProperty.BackgroundColor, color);
             return style.Mutate(TextStyleProperty.BackgroundColor, color);
         }
         }
         
         

+ 90 - 5
Source/QuestPDF/Helpers/ColorParser.cs

@@ -1,14 +1,99 @@
+using System;
 using System.Collections.Concurrent;
 using System.Collections.Concurrent;
-using QuestPDF.Skia;
+using System.Globalization;
+using QuestPDF.Infrastructure;
 
 
 namespace QuestPDF.Helpers;
 namespace QuestPDF.Helpers;
 
 
-internal static class ColorParser
+static class ColorParser
 {
 {
-    private static readonly ConcurrentDictionary<string, uint> ColorCodes = new();
+    private static readonly ConcurrentDictionary<string, Color?> Cache = new(); 
     
     
-    internal static uint ColorToCode(this string color)
+    public static Color ParseColorHex(string hexString)
     {
     {
-        return ColorCodes.GetOrAdd(color, SkColor.Parse);
+        if (!TryParseColorHex(hexString, out var color))
+        {
+            throw new ArgumentException(
+                $"The provided value '{color}' is not a valid hex color. " +
+                "The following formats are supported: #RGB, #ARGB, #RRGGBB, #AARRGGBB. " +
+                "The hash sign is optional so the following formats are also valid: RGB, ARGB, RRGGBB, AARRGGBB. " +
+                "For example #FF8800 is a solid orange color, while #20CF is a barely visible aqua color.",
+                nameof(color));
+        }
+        
+        return color;
+    }
+    
+    // inspired by: https://github.com/mono/SkiaSharp/blob/9274aeec807fd17eec2a3266ad4c2475c37d8a0c/binding/SkiaSharp/SKColor.cs#L123
+    public static bool TryParseColorHex(string hexString, out Color color)
+    {
+        var result = Cache.GetOrAdd(hexString, ParseColor);
+        color = result ?? Colors.Black;
+        return result.HasValue;
+
+        static Color? ParseColor(string hexString)
+        {
+            uint color = 0;
+            
+            if (string.IsNullOrWhiteSpace(hexString))
+                return null;
+    
+            // clean up string
+            var hexSpan = hexString.AsSpan().Trim().TrimStart('#');
+    
+            var len = hexSpan.Length;
+    
+            if (len == 3 || len == 4)
+            {
+                byte a;
+                
+                // parse [A]
+                if (len == 4)
+                {
+                    if (!byte.TryParse(hexSpan.Slice(0, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out a))
+                        return null;
+    
+                    a = (byte)((a << 4) | a);
+                }
+                else
+                {
+                    a = 255;
+                }
+    
+                // parse RGB
+                if (!byte.TryParse(hexSpan.Slice(len - 3, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var r) ||
+                    !byte.TryParse(hexSpan.Slice(len - 2, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var g) ||
+                    !byte.TryParse(hexSpan.Slice(len - 1, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var b))
+                {
+                    return null;
+                }
+    
+                r |= (byte)(r << 4);
+                g |= (byte)(g << 4);
+                b |= (byte)(b << 4);
+                
+                // success
+                color = (uint)((a << 24) | (r << 16) | (g << 8) | b);
+                return new Color(color);
+            }
+    
+            if (len == 6 || len == 8)
+            {
+                // parse [AA]RRGGBB
+                if (!uint.TryParse(hexSpan, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var number))
+                    return null;
+    
+                // success
+                color = number;
+    
+                // alpha was not provided, so use 255
+                if (len == 6)
+                    color |= 0xFF000000;
+                
+                return new Color(color);
+            }
+    
+            return null;
+        }
     }
     }
 }
 }

+ 0 - 33
Source/QuestPDF/Helpers/ColorValidator.cs

@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using QuestPDF.Skia;
-
-namespace QuestPDF.Helpers
-{
-    internal static class ColorValidator
-    {
-        static ColorValidator()
-        {
-            NativeDependencyCompatibilityChecker.Test();
-        }
-        
-        private static readonly ConcurrentDictionary<string, bool> ColorsValidityCache = new();
-        
-        public static void Validate(string? color)
-        {
-            if (color == null)
-                throw new ArgumentException("Color value cannot be null");
-            
-            var isValid = ColorsValidityCache.GetOrAdd(color, x => SkColor.TryParse(x, out var _));
-            
-            if (isValid)
-                return;
-
-            throw new ArgumentException(
-                $"The provided value '{color}' is not a valid hex color. " +
-                "The following formats are supported: #RGB, #ARGB, #RRGGBB, #AARRGGBB. " +
-                "The hash sign is optional so the following formats are also valid: RGB, ARGB, RRGGBB, AARRGGBB. " +
-                "For example #FF8800 is a solid orange color, while #20CF is a barely visible aqua color.");
-        }
-    }
-}

+ 314 - 312
Source/QuestPDF/Helpers/Colors.cs

@@ -1,4 +1,6 @@
-#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+using QuestPDF.Infrastructure;
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
 
 
 namespace QuestPDF.Helpers
 namespace QuestPDF.Helpers
 {
 {
@@ -20,392 +22,392 @@ namespace QuestPDF.Helpers
     /// </example>
     /// </example>
     public static class Colors
     public static class Colors
     {
     {
-        public const string Black = "#000000";
-        public const string White = "#ffffff";
-        public const string Transparent = "#00000000";
+        public static readonly Color Black = new(0xFF000000);
+        public static readonly Color White = new(0xFFFFFF);
+        public static readonly Color Transparent = new(0x00000000);
 
 
         public static class Red
         public static class Red
         {
         {
-            public const string Lighten5 = "#ffebee";
-            public const string Lighten4 = "#ffcdd2";
-            public const string Lighten3 = "#ef9a9a";
-            public const string Lighten2 = "#e57373";
-            public const string Lighten1 = "#ef5350";
-            
-            public const string Medium = "#f44336";
-            
-            public const string Darken1 = "#e53935";
-            public const string Darken2 = "#d32f2f";
-            public const string Darken3 = "#c62828";
-            public const string Darken4 = "#b71c1c";
-            
-            public const string Accent1 = "#ff8a80";
-            public const string Accent2 = "#ff5252";
-            public const string Accent3 = "#ff1744";
-            public const string Accent4 = "#d50000";
+            public static readonly Color Lighten5 = new(0xFFEBEE);
+            public static readonly Color Lighten4 = new(0xFFCDD2);
+            public static readonly Color Lighten3 = new(0xEF9A9A);
+            public static readonly Color Lighten2 = new(0xE57373);
+            public static readonly Color Lighten1 = new(0xEF5350);
+            
+            public static readonly Color Medium = new(0xF44336);
+            
+            public static readonly Color Darken1 = new(0xE53935);
+            public static readonly Color Darken2 = new(0xD32F2F);
+            public static readonly Color Darken3 = new(0xC62828);
+            public static readonly Color Darken4 = new(0xB71C1C);
+            
+            public static readonly Color Accent1 = new(0xFF8A80);
+            public static readonly Color Accent2 = new(0xFF5252);
+            public static readonly Color Accent3 = new(0xFF1744);
+            public static readonly Color Accent4 = new(0xD50000);
         }
         }
 
 
         public static class Pink
         public static class Pink
         {
         {
-            public const string Lighten5 = "#fce4ec";
-            public const string Lighten4 = "#f8bbd0";
-            public const string Lighten3 = "#f48fb1";
-            public const string Lighten2 = "#f06292";
-            public const string Lighten1 = "#ec407a";
-            
-            public const string Medium = "#e91e63";
-            
-            public const string Darken1 = "#d81b60";
-            public const string Darken2 = "#c2185b";
-            public const string Darken3 = "#ad1457";
-            public const string Darken4 = "#880e4f";
-            
-            public const string Accent1 = "#ff80ab";
-            public const string Accent2 = "#ff4081";
-            public const string Accent3 = "#f50057";
-            public const string Accent4 = "#c51162";
+            public static readonly Color Lighten5 = new(0xFCE4EC);
+            public static readonly Color Lighten4 = new(0xF8BBD0);
+            public static readonly Color Lighten3 = new(0xF48FB1);
+            public static readonly Color Lighten2 = new(0xF06292);
+            public static readonly Color Lighten1 = new(0xEC407A);
+            
+            public static readonly Color Medium = new(0xE91E63);
+            
+            public static readonly Color Darken1 = new(0xD81B60);
+            public static readonly Color Darken2 = new(0xC2185B);
+            public static readonly Color Darken3 = new(0xAD1457);
+            public static readonly Color Darken4 = new(0x880E4F);
+            
+            public static readonly Color Accent1 = new(0xFF80AB);
+            public static readonly Color Accent2 = new(0xFF4081);
+            public static readonly Color Accent3 = new(0xF50057);
+            public static readonly Color Accent4 = new(0xC51162);
         }
         }
 
 
         public static class Purple
         public static class Purple
         {
         {
-            public const string Lighten5 = "#f3e5f5";
-            public const string Lighten4 = "#e1bee7";
-            public const string Lighten3 = "#ce93d8";
-            public const string Lighten2 = "#ba68c8";
-            public const string Lighten1 = "#ab47bc";
-            
-            public const string Medium = "#9c27b0";
-            
-            public const string Darken1 = "#8e24aa";
-            public const string Darken2 = "#7b1fa2";
-            public const string Darken3 = "#6a1b9a";
-            public const string Darken4 = "#4a148c";
-            
-            public const string Accent1 = "#ea80fc";
-            public const string Accent2 = "#e040fb";
-            public const string Accent3 = "#d500f9";
-            public const string Accent4 = "#aa00ff";
+            public static readonly Color Lighten5 = new(0xF3E5F5);
+            public static readonly Color Lighten4 = new(0xE1BEE7);
+            public static readonly Color Lighten3 = new(0xCE93D8);
+            public static readonly Color Lighten2 = new(0xBA68C8);
+            public static readonly Color Lighten1 = new(0xAB47BC);
+            
+            public static readonly Color Medium = new(0x9C27B0);
+            
+            public static readonly Color Darken1 = new(0x8E24AA);
+            public static readonly Color Darken2 = new(0x7B1FA2);
+            public static readonly Color Darken3 = new(0x6A1B9A);
+            public static readonly Color Darken4 = new(0x4A148C);
+            
+            public static readonly Color Accent1 = new(0xEA80FC);
+            public static readonly Color Accent2 = new(0xE040FB);
+            public static readonly Color Accent3 = new(0xD500F9);
+            public static readonly Color Accent4 = new(0xAA00FF);
         }
         }
 
 
         public static class DeepPurple
         public static class DeepPurple
         {
         {
-            public const string Lighten5 = "#ede7f6";
-            public const string Lighten4 = "#d1c4e9";
-            public const string Lighten3 = "#b39ddb";
-            public const string Lighten2 = "#9575cd";
-            public const string Lighten1 = "#7e57c2";
-            
-            public const string Medium = "#673ab7";
-            
-            public const string Darken1 = "#5e35b1";
-            public const string Darken2 = "#512da8";
-            public const string Darken3 = "#4527a0";
-            public const string Darken4 = "#311b92";
-            
-            public const string Accent1 = "#b388ff";
-            public const string Accent2 = "#7c4dff";
-            public const string Accent3 = "#651fff";
-            public const string Accent4 = "#6200ea";
+            public static readonly Color Lighten5 = new(0xEDE7F6);
+            public static readonly Color Lighten4 = new(0xD1C4E9);
+            public static readonly Color Lighten3 = new(0xB39DDB);
+            public static readonly Color Lighten2 = new(0x9575CD);
+            public static readonly Color Lighten1 = new(0x7E57C2);
+            
+            public static readonly Color Medium = new(0x673AB7);
+            
+            public static readonly Color Darken1 = new(0x5E35B1);
+            public static readonly Color Darken2 = new(0x512DA8);
+            public static readonly Color Darken3 = new(0x4527A0);
+            public static readonly Color Darken4 = new(0x311B92);
+            
+            public static readonly Color Accent1 = new(0xB388FF);
+            public static readonly Color Accent2 = new(0x7C4DFF);
+            public static readonly Color Accent3 = new(0x651FFF);
+            public static readonly Color Accent4 = new(0x6200EA);
         }
         }
 
 
         public static class Indigo
         public static class Indigo
         {
         {
-            public const string Lighten5 = "#e8eaf6";
-            public const string Lighten4 = "#c5cae9";
-            public const string Lighten3 = "#9fa8da";
-            public const string Lighten2 = "#7986cb";
-            public const string Lighten1 = "#5c6bc0";
-            
-            public const string Medium = "#3f51b5";
-            
-            public const string Darken1 = "#3949ab";
-            public const string Darken2 = "#303f9f";
-            public const string Darken3 = "#283593";
-            public const string Darken4 = "#1a237e";
-            
-            public const string Accent1 = "#8c9eff";
-            public const string Accent2 = "#536dfe";
-            public const string Accent3 = "#3d5afe";
-            public const string Accent4 = "#304ffe";
+            public static readonly Color Lighten5 = new(0xE8EAF6);
+            public static readonly Color Lighten4 = new(0xC5CAE9);
+            public static readonly Color Lighten3 = new(0x9FA8DA);
+            public static readonly Color Lighten2 = new(0x7986CB);
+            public static readonly Color Lighten1 = new(0x5C6BC0);
+            
+            public static readonly Color Medium = new(0x3F51B5);
+            
+            public static readonly Color Darken1 = new(0x3949AB);
+            public static readonly Color Darken2 = new(0x303F9F);
+            public static readonly Color Darken3 = new(0x283593);
+            public static readonly Color Darken4 = new(0x1A237E);
+            
+            public static readonly Color Accent1 = new(0x8C9EFF);
+            public static readonly Color Accent2 = new(0x536DFE);
+            public static readonly Color Accent3 = new(0x3D5AFE);
+            public static readonly Color Accent4 = new(0x304FFE);
         }
         }
 
 
         public static class Blue
         public static class Blue
         {
         {
-            public const string Lighten5 = "#e3f2fd";
-            public const string Lighten4 = "#bbdefb";
-            public const string Lighten3 = "#90caf9";
-            public const string Lighten2 = "#64b5f6";
-            public const string Lighten1 = "#42a5f5";
-            
-            public const string Medium = "#2196f3";
-            
-            public const string Darken1 = "#1e88e5";
-            public const string Darken2 = "#1976d2";
-            public const string Darken3 = "#1565c0";
-            public const string Darken4 = "#0d47a1";
-            
-            public const string Accent1 = "#82b1ff";
-            public const string Accent2 = "#448aff";
-            public const string Accent3 = "#2979ff";
-            public const string Accent4 = "#2962ff";
+            public static readonly Color Lighten5 = new(0xE3F2FD);
+            public static readonly Color Lighten4 = new(0xBBDEFB);
+            public static readonly Color Lighten3 = new(0x90CAF9);
+            public static readonly Color Lighten2 = new(0x64B5F6);
+            public static readonly Color Lighten1 = new(0x42A5F5);
+            
+            public static readonly Color Medium = new(0x2196F3);
+            
+            public static readonly Color Darken1 = new(0x1E88E5);
+            public static readonly Color Darken2 = new(0x1976D2);
+            public static readonly Color Darken3 = new(0x1565C0);
+            public static readonly Color Darken4 = new(0x0D47A1);
+            
+            public static readonly Color Accent1 = new(0x82B1FF);
+            public static readonly Color Accent2 = new(0x448AFF);
+            public static readonly Color Accent3 = new(0x2979FF);
+            public static readonly Color Accent4 = new(0x2962FF);
         }
         }
 
 
         public static class LightBlue
         public static class LightBlue
         {
         {
-            public const string Lighten5 = "#e1f5fe";
-            public const string Lighten4 = "#b3e5fc";
-            public const string Lighten3 = "#81d4fa";
-            public const string Lighten2 = "#4fc3f7";
-            public const string Lighten1 = "#29b6f6";
-            
-            public const string Medium = "#03a9f4";
-            
-            public const string Darken1 = "#039be5";
-            public const string Darken2 = "#0288d1";
-            public const string Darken3 = "#0277bd";
-            public const string Darken4 = "#01579b";
-            
-            public const string Accent1 = "#80d8ff";
-            public const string Accent2 = "#40c4ff";
-            public const string Accent3 = "#00b0ff";
-            public const string Accent4 = "#0091ea";
+            public static readonly Color Lighten5 = new(0xE1F5FE);
+            public static readonly Color Lighten4 = new(0xB3E5FC);
+            public static readonly Color Lighten3 = new(0x81D4FA);
+            public static readonly Color Lighten2 = new(0x4FC3F7);
+            public static readonly Color Lighten1 = new(0x29B6F6);
+            
+            public static readonly Color Medium = new(0x03A9F4);
+            
+            public static readonly Color Darken1 = new(0x039BE5);
+            public static readonly Color Darken2 = new(0x0288D1);
+            public static readonly Color Darken3 = new(0x0277BD);
+            public static readonly Color Darken4 = new(0x01579B);
+            
+            public static readonly Color Accent1 = new(0x80D8FF);
+            public static readonly Color Accent2 = new(0x40C4FF);
+            public static readonly Color Accent3 = new(0x00B0FF);
+            public static readonly Color Accent4 = new(0x0091EA);
         }
         }
 
 
         public static class Cyan
         public static class Cyan
         {
         {
-            public const string Lighten5 = "#e0f7fa";
-            public const string Lighten4 = "#b2ebf2";
-            public const string Lighten3 = "#80deea";
-            public const string Lighten2 = "#4dd0e1";
-            public const string Lighten1 = "#26c6da";
-            
-            public const string Medium = "#00bcd4";
-            
-            public const string Darken1 = "#00acc1";
-            public const string Darken2 = "#0097a7";
-            public const string Darken3 = "#00838f";
-            public const string Darken4 = "#006064";
-            
-            public const string Accent1 = "#84ffff";
-            public const string Accent2 = "#18ffff";
-            public const string Accent3 = "#00e5ff";
-            public const string Accent4 = "#00b8d4";
+            public static readonly Color Lighten5 = new(0xE0F7FA);
+            public static readonly Color Lighten4 = new(0xB2EBF2);
+            public static readonly Color Lighten3 = new(0x80DEEA);
+            public static readonly Color Lighten2 = new(0x4DD0E1);
+            public static readonly Color Lighten1 = new(0x26C6DA);
+            
+            public static readonly Color Medium = new(0x00BCD4);
+            
+            public static readonly Color Darken1 = new(0x00ACC1);
+            public static readonly Color Darken2 = new(0x0097A7);
+            public static readonly Color Darken3 = new(0x00838F);
+            public static readonly Color Darken4 = new(0x006064);
+            
+            public static readonly Color Accent1 = new(0x84FFFF);
+            public static readonly Color Accent2 = new(0x18FFFF);
+            public static readonly Color Accent3 = new(0x00E5FF);
+            public static readonly Color Accent4 = new(0x00B8D4);
         }
         }
 
 
         public static class Teal
         public static class Teal
         {
         {
-            public const string Lighten5 = "#e0f2f1";
-            public const string Lighten4 = "#b2dfdb";
-            public const string Lighten3 = "#80cbc4";
-            public const string Lighten2 = "#4db6ac";
-            public const string Lighten1 = "#26a69a";
-            
-            public const string Medium = "#009688";
-            
-            public const string Darken1 = "#00897b";
-            public const string Darken2 = "#00796b";
-            public const string Darken3 = "#00695c";
-            public const string Darken4 = "#004d40";
-            
-            public const string Accent1 = "#a7ffeb";
-            public const string Accent2 = "#64ffda";
-            public const string Accent3 = "#1de9b6";
-            public const string Accent4 = "#00bfa5";
+            public static readonly Color Lighten5 = new(0xE0F2F1);
+            public static readonly Color Lighten4 = new(0xB2DFDB);
+            public static readonly Color Lighten3 = new(0x80CBC4);
+            public static readonly Color Lighten2 = new(0x4DB6AC);
+            public static readonly Color Lighten1 = new(0x26A69A);
+            
+            public static readonly Color Medium = new(0x009688);
+            
+            public static readonly Color Darken1 = new(0x00897B);
+            public static readonly Color Darken2 = new(0x00796B);
+            public static readonly Color Darken3 = new(0x00695C);
+            public static readonly Color Darken4 = new(0x004D40);
+            
+            public static readonly Color Accent1 = new(0xA7FFEB);
+            public static readonly Color Accent2 = new(0x64FFDA);
+            public static readonly Color Accent3 = new(0x1DE9B6);
+            public static readonly Color Accent4 = new(0x00BFA5);
         }
         }
 
 
         public static class Green
         public static class Green
         {
         {
-            public const string Lighten5 = "#e8f5e9";
-            public const string Lighten4 = "#c8e6c9";
-            public const string Lighten3 = "#a5d6a7";
-            public const string Lighten2 = "#81c784";
-            public const string Lighten1 = "#66bb6a";
-            
-            public const string Medium = "#4caf50";
-            
-            public const string Darken1 = "#43a047";
-            public const string Darken2 = "#388e3c";
-            public const string Darken3 = "#2e7d32";
-            public const string Darken4 = "#1b5e20";
-            
-            public const string Accent1 = "#b9f6ca";
-            public const string Accent2 = "#69f0ae";
-            public const string Accent3 = "#00e676";
-            public const string Accent4 = "#00c853";
+            public static readonly Color Lighten5 = new(0xE8F5E9);
+            public static readonly Color Lighten4 = new(0xC8E6C9);
+            public static readonly Color Lighten3 = new(0xA5D6A7);
+            public static readonly Color Lighten2 = new(0x81C784);
+            public static readonly Color Lighten1 = new(0x66BB6A);
+            
+            public static readonly Color Medium = new(0x4CAF50);
+            
+            public static readonly Color Darken1 = new(0x43A047);
+            public static readonly Color Darken2 = new(0x388E3C);
+            public static readonly Color Darken3 = new(0x2E7D32);
+            public static readonly Color Darken4 = new(0x1B5E20);
+            
+            public static readonly Color Accent1 = new(0xB9F6CA);
+            public static readonly Color Accent2 = new(0x69F0AE);
+            public static readonly Color Accent3 = new(0x00E676);
+            public static readonly Color Accent4 = new(0x00C853);
         }
         }
 
 
         public static class LightGreen
         public static class LightGreen
         {
         {
-            public const string Lighten5 = "#f1f8e9";
-            public const string Lighten4 = "#dcedc8";
-            public const string Lighten3 = "#c5e1a5";
-            public const string Lighten2 = "#aed581";
-            public const string Lighten1 = "#9ccc65";
-            
-            public const string Medium = "#8bc34a";
-            
-            public const string Darken1 = "#7cb342";
-            public const string Darken2 = "#689f38";
-            public const string Darken3 = "#558b2f";
-            public const string Darken4 = "#33691e";
-            
-            public const string Accent1 = "#ccff90";
-            public const string Accent2 = "#b2ff59";
-            public const string Accent3 = "#76ff03";
-            public const string Accent4 = "#64dd17";
+            public static readonly Color Lighten5 = new(0xF1F8E9);
+            public static readonly Color Lighten4 = new(0xDCEDC8);
+            public static readonly Color Lighten3 = new(0xC5E1A5);
+            public static readonly Color Lighten2 = new(0xAED581);
+            public static readonly Color Lighten1 = new(0x9CCC65);
+            
+            public static readonly Color Medium = new(0x8BC34A);
+            
+            public static readonly Color Darken1 = new(0x7CB342);
+            public static readonly Color Darken2 = new(0x689F38);
+            public static readonly Color Darken3 = new(0x558B2F);
+            public static readonly Color Darken4 = new(0x33691E);
+            
+            public static readonly Color Accent1 = new(0xCCFF90);
+            public static readonly Color Accent2 = new(0xB2FF59);
+            public static readonly Color Accent3 = new(0x76FF03);
+            public static readonly Color Accent4 = new(0x64DD17);
         }
         }
 
 
         public static class Lime
         public static class Lime
         {
         {
-            public const string Lighten5 = "#f9fbe7";
-            public const string Lighten4 = "#f0f4c3";
-            public const string Lighten3 = "#e6ee9c";
-            public const string Lighten2 = "#dce775";
-            public const string Lighten1 = "#d4e157";
-            
-            public const string Medium = "#cddc39";
-            
-            public const string Darken1 = "#c0ca33";
-            public const string Darken2 = "#afb42b";
-            public const string Darken3 = "#9e9d24";
-            public const string Darken4 = "#827717";
-            
-            public const string Accent1 = "#f4ff81";
-            public const string Accent2 = "#eeff41";
-            public const string Accent3 = "#c6ff00";
-            public const string Accent4 = "#aeea00";
+            public static readonly Color Lighten5 = new(0xF9FBE7);
+            public static readonly Color Lighten4 = new(0xF0F4C3);
+            public static readonly Color Lighten3 = new(0xE6EE9C);
+            public static readonly Color Lighten2 = new(0xDCE775);
+            public static readonly Color Lighten1 = new(0xD4E157);
+            
+            public static readonly Color Medium = new(0xCDDC39);
+            
+            public static readonly Color Darken1 = new(0xC0CA33);
+            public static readonly Color Darken2 = new(0xAFB42B);
+            public static readonly Color Darken3 = new(0x9E9D24);
+            public static readonly Color Darken4 = new(0x827717);
+            
+            public static readonly Color Accent1 = new(0xF4FF81);
+            public static readonly Color Accent2 = new(0xEEFF41);
+            public static readonly Color Accent3 = new(0xC6FF00);
+            public static readonly Color Accent4 = new(0xAEEA00);
         }
         }
 
 
         public static class Yellow
         public static class Yellow
         {
         {
-            public const string Lighten5 = "#fffde7";
-            public const string Lighten4 = "#fff9c4";
-            public const string Lighten3 = "#fff59d";
-            public const string Lighten2 = "#fff176";
-            public const string Lighten1 = "#ffee58";
-            
-            public const string Medium = "#ffeb3b";
-            
-            public const string Darken1 = "#fdd835";
-            public const string Darken2 = "#fbc02d";
-            public const string Darken3 = "#f9a825";
-            public const string Darken4 = "#f57f17";
-            
-            public const string Accent1 = "#ffff8d";
-            public const string Accent2 = "#ffff00";
-            public const string Accent3 = "#ffea00";
-            public const string Accent4 = "#ffd600";
+            public static readonly Color Lighten5 = new(0xFFFDE7);
+            public static readonly Color Lighten4 = new(0xFFF9C4);
+            public static readonly Color Lighten3 = new(0xFFF59D);
+            public static readonly Color Lighten2 = new(0xFFF176);
+            public static readonly Color Lighten1 = new(0xFFEE58);
+            
+            public static readonly Color Medium = new(0xFFEB3B);
+            
+            public static readonly Color Darken1 = new(0xFDD835);
+            public static readonly Color Darken2 = new(0xFBC02D);
+            public static readonly Color Darken3 = new(0xF9A825);
+            public static readonly Color Darken4 = new(0xF57F17);
+            
+            public static readonly Color Accent1 = new(0xFFFF8D);
+            public static readonly Color Accent2 = new(0xFFFF00);
+            public static readonly Color Accent3 = new(0xFFEA00);
+            public static readonly Color Accent4 = new(0xFFD600);
         }
         }
 
 
         public static class Amber
         public static class Amber
         {
         {
-            public const string Lighten5 = "#fff8e1";
-            public const string Lighten4 = "#ffecb3";
-            public const string Lighten3 = "#ffe082";
-            public const string Lighten2 = "#ffd54f";
-            public const string Lighten1 = "#ffca28";
-            
-            public const string Medium = "#ffc107";
-            
-            public const string Darken1 = "#ffb300";
-            public const string Darken2 = "#ffa000";
-            public const string Darken3 = "#ff8f00";
-            public const string Darken4 = "#ff6f00";
-            
-            public const string Accent1 = "#ffe57f";
-            public const string Accent2 = "#ffd740";
-            public const string Accent3 = "#ffc400";
-            public const string Accent4 = "#ffab00";
+            public static readonly Color Lighten5 = new(0xFFF8E1);
+            public static readonly Color Lighten4 = new(0xFFECB3);
+            public static readonly Color Lighten3 = new(0xFFE082);
+            public static readonly Color Lighten2 = new(0xFFD54F);
+            public static readonly Color Lighten1 = new(0xFFCA28);
+            
+            public static readonly Color Medium = new(0xFFC107);
+            
+            public static readonly Color Darken1 = new(0xFFB300);
+            public static readonly Color Darken2 = new(0xFFA000);
+            public static readonly Color Darken3 = new(0xFF8F00);
+            public static readonly Color Darken4 = new(0xFF6F00);
+            
+            public static readonly Color Accent1 = new(0xFFE57F);
+            public static readonly Color Accent2 = new(0xFFD740);
+            public static readonly Color Accent3 = new(0xFFC400);
+            public static readonly Color Accent4 = new(0xFFAB00);
         }
         }
 
 
         public static class Orange
         public static class Orange
         {
         {
-            public const string Lighten5 = "#fff3e0";
-            public const string Lighten4 = "#ffe0b2";
-            public const string Lighten3 = "#ffcc80";
-            public const string Lighten2 = "#ffb74d";
-            public const string Lighten1 = "#ffa726";
-            
-            public const string Medium = "#ff9800";
-            
-            public const string Darken1 = "#fb8c00";
-            public const string Darken2 = "#f57c00";
-            public const string Darken3 = "#ef6c00";
-            public const string Darken4 = "#e65100";
-            
-            public const string Accent1 = "#ffd180";
-            public const string Accent2 = "#ffab40";
-            public const string Accent3 = "#ff9100";
-            public const string Accent4 = "#ff6d00";
+            public static readonly Color Lighten5 = new(0xFFF3E0);
+            public static readonly Color Lighten4 = new(0xFFE0B2);
+            public static readonly Color Lighten3 = new(0xFFCC80);
+            public static readonly Color Lighten2 = new(0xFFB74D);
+            public static readonly Color Lighten1 = new(0xFFA726);
+            
+            public static readonly Color Medium = new(0xFF9800);
+            
+            public static readonly Color Darken1 = new(0xFB8C00);
+            public static readonly Color Darken2 = new(0xF57C00);
+            public static readonly Color Darken3 = new(0xEF6C00);
+            public static readonly Color Darken4 = new(0xE65100);
+            
+            public static readonly Color Accent1 = new(0xFFD180);
+            public static readonly Color Accent2 = new(0xFFAB40);
+            public static readonly Color Accent3 = new(0xFF9100);
+            public static readonly Color Accent4 = new(0xFF6D00);
         }
         }
 
 
         public static class DeepOrange
         public static class DeepOrange
         {
         {
-            public const string Lighten5 = "#fbe9e7";
-            public const string Lighten4 = "#ffccbc";
-            public const string Lighten3 = "#ffab91";
-            public const string Lighten2 = "#ff8a65";
-            public const string Lighten1 = "#ff7043";
-            
-            public const string Medium = "#ff5722";
-            
-            public const string Darken1 = "#f4511e";
-            public const string Darken2 = "#e64a19";
-            public const string Darken3 = "#d84315";
-            public const string Darken4 = "#bf360c";
-            
-            public const string Accent1 = "#ff9e80";
-            public const string Accent2 = "#ff6e40";
-            public const string Accent3 = "#ff3d00";
-            public const string Accent4 = "#dd2c00";
+            public static readonly Color Lighten5 = new(0xFBE9E7);
+            public static readonly Color Lighten4 = new(0xFFCCBC);
+            public static readonly Color Lighten3 = new(0xFFAB91);
+            public static readonly Color Lighten2 = new(0xFF8A65);
+            public static readonly Color Lighten1 = new(0xFF7043);
+            
+            public static readonly Color Medium = new(0xFF5722);
+            
+            public static readonly Color Darken1 = new(0xF4511E);
+            public static readonly Color Darken2 = new(0xE64A19);
+            public static readonly Color Darken3 = new(0xD84315);
+            public static readonly Color Darken4 = new(0xBF360C);
+            
+            public static readonly Color Accent1 = new(0xFF9E80);
+            public static readonly Color Accent2 = new(0xFF6E40);
+            public static readonly Color Accent3 = new(0xFF3D00);
+            public static readonly Color Accent4 = new(0xDD2C00);
         }
         }
 
 
         public static class Brown
         public static class Brown
         {
         {
-            public const string Lighten5 = "#efebe9";
-            public const string Lighten4 = "#d7ccc8";
-            public const string Lighten3 = "#bcaaa4";
-            public const string Lighten2 = "#a1887f";
-            public const string Lighten1 = "#8d6e63";
-            
-            public const string Medium = "#795548";
-            
-            public const string Darken1 = "#6d4c41";
-            public const string Darken2 = "#5d4037";
-            public const string Darken3 = "#4e342e";
-            public const string Darken4 = "#3e2723";
+            public static readonly Color Lighten5 = new(0xEFEBE9);
+            public static readonly Color Lighten4 = new(0xD7CCC8);
+            public static readonly Color Lighten3 = new(0xBCAAA4);
+            public static readonly Color Lighten2 = new(0xA1887F);
+            public static readonly Color Lighten1 = new(0x8D6E63);
+            
+            public static readonly Color Medium = new(0x795548);
+            
+            public static readonly Color Darken1 = new(0x6D4C41);
+            public static readonly Color Darken2 = new(0x5D4037);
+            public static readonly Color Darken3 = new(0x4E342E);
+            public static readonly Color Darken4 = new(0x3E2723);
         }
         }
 
 
         public static class Grey
         public static class Grey
         {
         {
-            public const string Lighten5 = "#fafafa";
-            public const string Lighten4 = "#f5f5f5";
-            public const string Lighten3 = "#eeeeee";
-            public const string Lighten2 = "#e0e0e0";
-            public const string Lighten1 = "#bdbdbd";
-            
-            public const string Medium = "#9e9e9e";
-            
-            public const string Darken1 = "#757575";
-            public const string Darken2 = "#616161";
-            public const string Darken3 = "#424242";
-            public const string Darken4 = "#212121";
+            public static readonly Color Lighten5 = new(0xFAFAFA);
+            public static readonly Color Lighten4 = new(0xF5F5F5);
+            public static readonly Color Lighten3 = new(0xEEEEEE);
+            public static readonly Color Lighten2 = new(0xE0E0E0);
+            public static readonly Color Lighten1 = new(0xBDBDBD);
+            
+            public static readonly Color Medium = new(0x9E9E9E);
+            
+            public static readonly Color Darken1 = new(0x757575);
+            public static readonly Color Darken2 = new(0x616161);
+            public static readonly Color Darken3 = new(0x424242);
+            public static readonly Color Darken4 = new(0x212121);
         }
         }
 
 
         public static class BlueGrey
         public static class BlueGrey
         {
         {
-            public const string Lighten5 = "#eceff1";
-            public const string Lighten4 = "#cfd8dc";
-            public const string Lighten3 = "#b0bec5";
-            public const string Lighten2 = "#90a4ae";
-            public const string Lighten1 = "#78909c";
-            
-            public const string Medium = "#607d8b";
-            
-            public const string Darken1 = "#546e7a";
-            public const string Darken2 = "#455a64";
-            public const string Darken3 = "#37474f";
-            public const string Darken4 = "#263238";
+            public static readonly Color Lighten5 = new(0xECEFF1);
+            public static readonly Color Lighten4 = new(0xCFD8DC);
+            public static readonly Color Lighten3 = new(0xB0BEC5);
+            public static readonly Color Lighten2 = new(0x90A4AE);
+            public static readonly Color Lighten1 = new(0x78909C);
+            
+            public static readonly Color Medium = new(0x607D8B);
+            
+            public static readonly Color Darken1 = new(0x546E7A);
+            public static readonly Color Darken2 = new(0x455A64);
+            public static readonly Color Darken3 = new(0x37474F);
+            public static readonly Color Darken4 = new(0x263238);
         }
         }
     }
     }
 }
 }

+ 3 - 4
Source/QuestPDF/Helpers/Placeholders.cs

@@ -294,7 +294,7 @@ namespace QuestPDF.Helpers
 
 
         #region Visual
         #region Visual
 
 
-        private static readonly string[] BackgroundColors =
+        private static readonly Color[] BackgroundColors =
         {
         {
             Colors.Red.Lighten3,
             Colors.Red.Lighten3,
             Colors.Pink.Lighten3,
             Colors.Pink.Lighten3,
@@ -325,7 +325,7 @@ namespace QuestPDF.Helpers
         /// #bcaaa4 <br />
         /// #bcaaa4 <br />
         /// #ffab91
         /// #ffab91
         /// </example>
         /// </example>
-        public static string BackgroundColor()
+        public static Color BackgroundColor()
         {
         {
             var index = Random.Next(0, BackgroundColors.Length);
             var index = Random.Next(0, BackgroundColors.Length);
             return BackgroundColors[index];
             return BackgroundColors[index];
@@ -339,7 +339,7 @@ namespace QuestPDF.Helpers
         /// #f44336 <br />
         /// #f44336 <br />
         /// #9c27b0
         /// #9c27b0
         /// </example>
         /// </example>
-        public static string Color()
+        public static Color Color()
         {
         {
             var colors = new[]
             var colors = new[]
             {
             {
@@ -394,7 +394,6 @@ namespace QuestPDF.Helpers
             var colors = BackgroundColors
             var colors = BackgroundColors
                 .OrderBy(_ => Random.Next())
                 .OrderBy(_ => Random.Next())
                 .Take(2)
                 .Take(2)
-                .Select(SkColor.Parse)
                 .ToArray();
                 .ToArray();
             
             
             using var placeholderImage = SkImage.GeneratePlaceholder(size.Width, size.Height, colors[0], colors[1]);
             using var placeholderImage = SkImage.GeneratePlaceholder(size.Width, size.Height, colors[0], colors[1]);

+ 65 - 0
Source/QuestPDF/Infrastructure/Color.cs

@@ -0,0 +1,65 @@
+using QuestPDF.Helpers;
+
+namespace QuestPDF.Infrastructure;
+
+public readonly struct Color
+{
+    public uint Hex { get; }
+    
+    public byte Alpha => (byte) ((Hex & 0xFF000000) >> 24);
+    public byte Red => (byte) ((Hex & 0xFF0000) >> 16);
+    public byte Green => (byte) ((Hex & 0x00FF00) >> 8);
+    public byte Blue => (byte) (Hex & 0x0000FF);
+
+    public Color(uint hex)
+    {
+        if (hex <= 0x00FFFFFF && hex != 0x00000000) 
+            hex |= 0xFF000000;
+        
+        Hex = hex;
+    }
+    
+    public Color WithAlpha(byte alpha)
+    {
+        var newHex = (Hex & 0x00FFFFFF) | ((uint)alpha << 24);
+        return new Color(newHex);
+    }
+    
+    public static Color FromHex(string hex)
+    {
+        return ColorParser.ParseColorHex(hex);
+    }
+
+    public static Color FromRGB(byte red, byte green, byte blue)
+    {
+        return new Color((uint) (red << 16 | green << 8 | blue));
+    }
+    
+    public static Color FromARGB(byte alpha, byte red, byte green, byte blue)
+    {
+        return new Color((uint) (alpha << 24 | red << 16 | green << 8 | blue));
+    }
+    
+    public static implicit operator string(Color color)
+    {
+        return color.ToString();
+    }
+    
+    public static implicit operator Color(string hex)
+    {
+        return FromHex(hex);
+    }
+    
+    public static implicit operator uint(Color color)
+    {
+        return color.Hex;
+    }
+
+    public override string ToString()
+    {
+        if (Alpha == 0xFF)
+            return $"#{Red:X2}{Green:X2}{Blue:X2}";
+        
+        return $"#{Alpha:X2}{Red:X2}{Green:X2}{Blue:X2}";
+    }
+}

+ 3 - 3
Source/QuestPDF/Infrastructure/ICanvas.cs

@@ -10,12 +10,12 @@ namespace QuestPDF.Infrastructure
         
         
         void Translate(Position vector);
         void Translate(Position vector);
         
         
-        void DrawFilledRectangle(Position vector, Size size, string color);
-        void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, string color);
+        void DrawFilledRectangle(Position vector, Size size, Color color);
+        void DrawStrokeRectangle(Position vector, Size size, float strokeWidth, Color color);
         void DrawParagraph(SkParagraph paragraph);
         void DrawParagraph(SkParagraph paragraph);
         void DrawImage(SkImage image, Size size);
         void DrawImage(SkImage image, Size size);
         void DrawPicture(SkPicture picture);
         void DrawPicture(SkPicture picture);
-        void DrawSvgPath(string path, uint color);
+        void DrawSvgPath(string path, Color color);
         void DrawSvg(SkSvgImage svgImage, Size size);
         void DrawSvg(SkSvgImage svgImage, Size size);
 
 
         void DrawOverflowArea(SkRect area);
         void DrawOverflowArea(SkRect area);

+ 5 - 5
Source/QuestPDF/Infrastructure/TextStyle.cs

@@ -8,8 +8,8 @@ namespace QuestPDF.Infrastructure
     {
     {
         internal int Id { get; set; }
         internal int Id { get; set; }
         
         
-        internal string? Color { get; set; }
-        internal string? BackgroundColor { get; set; }
+        internal Color? Color { get; set; }
+        internal Color? BackgroundColor { get; set; }
         internal string? FontFamily { get; set; }
         internal string? FontFamily { get; set; }
         internal string? FontFamilyFallback { get; set; }
         internal string? FontFamilyFallback { get; set; }
         internal float? Size { get; set; }
         internal float? Size { get; set; }
@@ -60,9 +60,9 @@ namespace QuestPDF.Infrastructure
                 IsItalic = IsItalic ?? false,
                 IsItalic = IsItalic ?? false,
                 FontFamily = FontFamily,
                 FontFamily = FontFamily,
                 FontFamilyFallback = FontFamilyFallback,
                 FontFamilyFallback = FontFamilyFallback,
-                ForegroundColor = Color?.ColorToCode() ?? 0,
-                BackgroundColor = BackgroundColor?.ColorToCode() ?? 0,
-                DecorationColor = Color?.ColorToCode() ?? 0,
+                ForegroundColor = Color ?? Colors.Black,
+                BackgroundColor = BackgroundColor ?? Colors.Transparent,
+                DecorationColor = Color ?? Colors.Black,
                 DecorationType = CreateDecoration(),
                 DecorationType = CreateDecoration(),
                 
                 
                 // TODO: create public API to support these properties
                 // TODO: create public API to support these properties

+ 0 - 98
Source/QuestPDF/Skia/SkColor.cs

@@ -1,98 +0,0 @@
-using System;
-using System.Globalization;
-
-namespace QuestPDF.Skia;
-
-internal static class SkColor
-{
-    public static uint Parse(string hexString)
-    {
-        if (!TryParse(hexString, out var color))
-        {
-            throw new ArgumentException(
-                $"The provided value '{color}' is not a valid hex color. " +
-                "The following formats are supported: #RGB, #ARGB, #RRGGBB, #AARRGGBB. " +
-                "The hash sign is optional so the following formats are also valid: RGB, ARGB, RRGGBB, AARRGGBB. " +
-                "For example #FF8800 is a solid orange color, while #20CF is a barely visible aqua color.",
-                nameof(color));
-        }
-        
-        return color;
-    }
-    
-    // inspired by: https://github.com/mono/SkiaSharp/blob/9274aeec807fd17eec2a3266ad4c2475c37d8a0c/binding/SkiaSharp/SKColor.cs#L123
-    public static bool TryParse(string hexString, out uint color)
-    {
-        color = 0;
-        
-        if (string.IsNullOrWhiteSpace(hexString))
-            return false;
-
-        // clean up string
-        var hexSpan = hexString.AsSpan().Trim().TrimStart('#');
-
-        var len = hexSpan.Length;
-
-        if (len == 3 || len == 4)
-        {
-            byte a;
-            
-            // parse [A]
-            if (len == 4)
-            {
-                if (!byte.TryParse(hexSpan.Slice(0, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out a))
-                    return false;
-
-                a = (byte)((a << 4) | a);
-            }
-            else
-            {
-                a = 255;
-            }
-
-            // parse RGB
-            if (!byte.TryParse(hexSpan.Slice(len - 3, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var r) ||
-                !byte.TryParse(hexSpan.Slice(len - 2, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var g) ||
-                !byte.TryParse(hexSpan.Slice(len - 1, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var b))
-            {
-                return false;
-            }
-
-            r |= (byte)(r << 4);
-            g |= (byte)(g << 4);
-            b |= (byte)(b << 4);
-            
-            // success
-            color = (uint)((a << 24) | (r << 16) | (g << 8) | b);
-            return true;
-        }
-
-        if (len == 6 || len == 8)
-        {
-            // parse [AA]RRGGBB
-            if (!uint.TryParse(hexSpan, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var number))
-                return false;
-
-            // success
-            color = number;
-
-            // alpha was not provided, so use 255
-            if (len == 6)
-                color |= 0xFF000000;
-            
-            return true;
-        }
-
-        return false;
-    }
-
-    public static uint ColorWithAlpha(this uint color, byte alpha)
-    {
-        return (color & 0x00FFFFFF) | ((uint)alpha << 24);
-    }
-    
-    public static string ColorToString(this uint color)
-    {
-        return $"#{color:X8}";
-    }
-}