Compare commits
1 Commits
2022.12
...
styled-box
| Author | SHA1 | Date | |
|---|---|---|---|
| d39819bf8d |
@@ -21,7 +21,7 @@ namespace QuestPDF.UnitTests
|
||||
Color = Colors.Red.Medium
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectCanvasDrawRectangle(new Position(0, 0), new Size(400, 300), Colors.Red.Medium)
|
||||
.ExpectCanvasDrawFilledRectangle(new Position(0, 0), new Size(400, 300), Colors.Red.Medium)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace QuestPDF.UnitTests
|
||||
Child = x.CreateChild()
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectCanvasDrawRectangle(new Position(0, 0), new Size(400, 300), Colors.Red.Medium)
|
||||
.ExpectCanvasDrawFilledRectangle(new Position(0, 0), new Size(400, 300), Colors.Red.Medium)
|
||||
.ExpectChildDraw(new Size(400, 300))
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using NUnit.Framework;
|
||||
using System.Drawing;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
using QuestPDF.UnitTests.TestEngine;
|
||||
using Size = QuestPDF.Infrastructure.Size;
|
||||
|
||||
namespace QuestPDF.UnitTests
|
||||
{
|
||||
@@ -32,7 +34,29 @@ namespace QuestPDF.UnitTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Draw_HorizontalRight_VerticalTop()
|
||||
public void Draw_SameWidths_Optimized()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Border
|
||||
{
|
||||
Top = 10,
|
||||
Right = 10,
|
||||
Bottom = 10,
|
||||
Left = 10,
|
||||
|
||||
Color = Colors.Red.Medium,
|
||||
|
||||
Child = x.CreateChild()
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildDraw(new Size(400, 300))
|
||||
.ExpectCanvasDrawStrokedRectangle(new Size(400, 300), Colors.Red.Medium, 10)
|
||||
.ExpectChildDraw(new Size(400, 300))
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Draw_VariousWidths()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Border
|
||||
@@ -48,10 +72,10 @@ namespace QuestPDF.UnitTests
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildDraw(new Size(400, 300))
|
||||
.ExpectCanvasDrawRectangle(new Position(-20, -5), new Size(430, 10), Colors.Red.Medium) // top
|
||||
.ExpectCanvasDrawRectangle(new Position(-20, -5), new Size(40, 320), Colors.Red.Medium) // left
|
||||
.ExpectCanvasDrawRectangle(new Position(-20, 285), new Size(430, 30), Colors.Red.Medium) // bottom
|
||||
.ExpectCanvasDrawRectangle(new Position(390, -5), new Size(20, 320), Colors.Red.Medium) // right
|
||||
.ExpectCanvasDrawFilledRectangle(new Position(-20, -5), new Size(430, 10), Colors.Red.Medium) // top
|
||||
.ExpectCanvasDrawFilledRectangle(new Position(-20, -5), new Size(40, 320), Colors.Red.Medium) // left
|
||||
.ExpectCanvasDrawFilledRectangle(new Position(-20, 285), new Size(430, 30), Colors.Red.Medium) // bottom
|
||||
.ExpectCanvasDrawFilledRectangle(new Position(390, -5), new Size(20, 320), Colors.Red.Medium) // right
|
||||
.ExpectChildDraw(new Size(400, 300))
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
@@ -11,13 +11,15 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
public Action<float, float> ScaleFunc { get; set; }
|
||||
public Action<SKImage, Position, Size> DrawImageFunc { get; set; }
|
||||
public Action<string, Position, TextStyle> DrawTextFunc { get; set; }
|
||||
public Action<Position, Size, string> DrawRectFunc { get; set; }
|
||||
public Action<Position, Size, string> DrawFilledRectangleFunc { get; set; }
|
||||
public Action<Size, string, float> DrawStrokedRectangleFunc { get; set; }
|
||||
|
||||
public void Translate(Position vector) => TranslateFunc(vector);
|
||||
public void Rotate(float angle) => RotateFunc(angle);
|
||||
public void Scale(float scaleX, float scaleY) => ScaleFunc(scaleX, scaleY);
|
||||
|
||||
public void DrawRectangle(Position vector, Size size, string color) => DrawRectFunc(vector, size, color);
|
||||
public void DrawFilledRectangle(Position vector, Size size, string color) => DrawFilledRectangleFunc(vector, size, color);
|
||||
public void DrawStrokedRectangle(Size size, string color, float width) => DrawStrokedRectangleFunc(size, color, width);
|
||||
public void DrawText(string text, Position position, TextStyle style) => DrawTextFunc(text, position, style);
|
||||
public void DrawImage(SKImage image, Position position, Size size) => DrawImageFunc(image, position, size);
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
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 DrawRectangle(Position vector, Size size, string color) => Operations.Add(new CanvasDrawRectangleOperation(vector, size, color));
|
||||
public void DrawFilledRectangle(Position vector, Size size, string color) => Operations.Add(new CanvasDrawFilledRectangleOperation(vector, size, color));
|
||||
public void DrawStrokedRectangle(Size size, string color, float width) => Operations.Add(new CanvasDrawStrokedRectangleOperation(size, color, width));
|
||||
public void DrawText(string text, Position position, TextStyle style) => Operations.Add(new CanvasDrawTextOperation(text, position, style));
|
||||
public void DrawImage(SKImage image, Position position, Size size) => Operations.Add(new CanvasDrawImageOperation(position, size));
|
||||
|
||||
|
||||
+2
-2
@@ -2,13 +2,13 @@
|
||||
|
||||
namespace QuestPDF.UnitTests.TestEngine.Operations
|
||||
{
|
||||
internal class CanvasDrawRectangleOperation : OperationBase
|
||||
internal class CanvasDrawFilledRectangleOperation : OperationBase
|
||||
{
|
||||
public Position Position { get; }
|
||||
public Size Size { get; }
|
||||
public string Color { get; }
|
||||
|
||||
public CanvasDrawRectangleOperation(Position position, Size size, string color)
|
||||
public CanvasDrawFilledRectangleOperation(Position position, Size size, string color)
|
||||
{
|
||||
Position = position;
|
||||
Size = size;
|
||||
@@ -0,0 +1,18 @@
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.UnitTests.TestEngine.Operations
|
||||
{
|
||||
internal class CanvasDrawStrokedRectangleOperation : OperationBase
|
||||
{
|
||||
public Size Size { get; }
|
||||
public string Color { get; }
|
||||
public float Width { get; set; }
|
||||
|
||||
public CanvasDrawStrokedRectangleOperation(Size size, string color, float width)
|
||||
{
|
||||
Size = size;
|
||||
Color = color;
|
||||
Width = width;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,17 +70,27 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
Assert.AreEqual(expected.ScaleX, scaleX, "Scale X");
|
||||
Assert.AreEqual(expected.ScaleY, scaleY, "Scale Y");
|
||||
},
|
||||
DrawRectFunc = (position, size, color) =>
|
||||
DrawFilledRectangleFunc = (position, size, color) =>
|
||||
{
|
||||
var expected = GetExpected<CanvasDrawRectangleOperation>();
|
||||
var expected = GetExpected<CanvasDrawFilledRectangleOperation>();
|
||||
|
||||
Assert.AreEqual(expected.Position.X, position.X, "Draw rectangle: X");
|
||||
Assert.AreEqual(expected.Position.Y, position.Y, "Draw rectangle: Y");
|
||||
Assert.AreEqual(expected.Position.X, position.X, "Draw filled rectangle: X");
|
||||
Assert.AreEqual(expected.Position.Y, position.Y, "Draw filled rectangle: Y");
|
||||
|
||||
Assert.AreEqual(expected.Size.Width, size.Width, "Draw rectangle: width");
|
||||
Assert.AreEqual(expected.Size.Height, size.Height, "Draw rectangle: height");
|
||||
Assert.AreEqual(expected.Size.Width, size.Width, "Draw filled rectangle: width");
|
||||
Assert.AreEqual(expected.Size.Height, size.Height, "Draw filled rectangle: height");
|
||||
|
||||
Assert.AreEqual(expected.Color, color, "Draw rectangle: color");
|
||||
Assert.AreEqual(expected.Color, color, "Draw filled rectangle: color");
|
||||
},
|
||||
DrawStrokedRectangleFunc = (size, color, width) =>
|
||||
{
|
||||
var expected = GetExpected<CanvasDrawStrokedRectangleOperation>();
|
||||
|
||||
Assert.AreEqual(expected.Size.Width, size.Width, "Draw stroked rectangle: width");
|
||||
Assert.AreEqual(expected.Size.Height, size.Height, "Draw stroked rectangle: height");
|
||||
|
||||
Assert.AreEqual(expected.Color, color, "Draw stroked rectangle: color");
|
||||
Assert.AreEqual(expected.Width, width, "Draw stroked rectangle: width");
|
||||
},
|
||||
DrawTextFunc = (text, position, style) =>
|
||||
{
|
||||
@@ -196,9 +206,14 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
return AddOperation(new CanvasRotateOperation(angle));
|
||||
}
|
||||
|
||||
public TestPlan ExpectCanvasDrawRectangle(Position position, Size size, string color)
|
||||
public TestPlan ExpectCanvasDrawFilledRectangle(Position position, Size size, string color)
|
||||
{
|
||||
return AddOperation(new CanvasDrawRectangleOperation(position, size, color));
|
||||
return AddOperation(new CanvasDrawFilledRectangleOperation(position, size, color));
|
||||
}
|
||||
|
||||
public TestPlan ExpectCanvasDrawStrokedRectangle(Size size, string color, float width)
|
||||
{
|
||||
return AddOperation(new CanvasDrawStrokedRectangleOperation(size, color, width));
|
||||
}
|
||||
|
||||
public TestPlan ExpectCanvasDrawText(string text, Position position, TextStyle style)
|
||||
|
||||
@@ -36,7 +36,12 @@ namespace QuestPDF.Drawing
|
||||
|
||||
}
|
||||
|
||||
public void DrawRectangle(Position vector, Size size, string color)
|
||||
public void DrawFilledRectangle(Position vector, Size size, string color)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void DrawStrokedRectangle(Size size, string color, float width)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Collections.Concurrent;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace QuestPDF.Drawing
|
||||
{
|
||||
internal class SkiaCache
|
||||
{
|
||||
private static ConcurrentDictionary<string, SKPaint> RectangleFillPaints = new ConcurrentDictionary<string, SKPaint>();
|
||||
private static ConcurrentDictionary<string, SKPaint> RectangleStrokePaints = new ConcurrentDictionary<string, SKPaint>();
|
||||
|
||||
public static SKPaint GetRectangleFillPaint(string color)
|
||||
{
|
||||
return RectangleFillPaints.GetOrAdd(color, _ => Convert());
|
||||
|
||||
SKPaint Convert()
|
||||
{
|
||||
return new SKPaint
|
||||
{
|
||||
Color = SKColor.Parse(color),
|
||||
Style = SKPaintStyle.Fill
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static SKPaint GetRectangleStrokePaint(string color, float width)
|
||||
{
|
||||
var key = $"{color}|{width}";
|
||||
return RectangleStrokePaints.GetOrAdd(key, _ => Convert());
|
||||
|
||||
SKPaint Convert()
|
||||
{
|
||||
return new SKPaint
|
||||
{
|
||||
Color = SKColor.Parse(color),
|
||||
Style = SKPaintStyle.Stroke,
|
||||
StrokeWidth = width
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,14 +18,20 @@ namespace QuestPDF.Drawing
|
||||
Canvas.Translate(vector.X, vector.Y);
|
||||
}
|
||||
|
||||
public void DrawRectangle(Position vector, Size size, string color)
|
||||
public void DrawFilledRectangle(Position vector, Size size, string color)
|
||||
{
|
||||
if (size.Width < Size.Epsilon || size.Height < Size.Epsilon)
|
||||
return;
|
||||
|
||||
var paint = color.ColorToPaint();
|
||||
var paint = SkiaCache.GetRectangleFillPaint(color);
|
||||
Canvas.DrawRect(vector.X, vector.Y, size.Width, size.Height, paint);
|
||||
}
|
||||
|
||||
public void DrawStrokedRectangle(Size size, string color, float width)
|
||||
{
|
||||
var paint = SkiaCache.GetRectangleStrokePaint(color, width);
|
||||
Canvas.DrawRect(0, 0, size.Width, size.Height, paint);
|
||||
}
|
||||
|
||||
public void DrawText(string text, Position vector, TextStyle style)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace QuestPDF.Elements
|
||||
|
||||
internal override void Draw(Size availableSpace)
|
||||
{
|
||||
Canvas.DrawRectangle(Position.Zero, availableSpace, Color);
|
||||
Canvas.DrawFilledRectangle(Position.Zero, availableSpace, Color);
|
||||
base.Draw(availableSpace);
|
||||
}
|
||||
}
|
||||
|
||||
+42
-22
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
@@ -15,31 +16,50 @@ namespace QuestPDF.Elements
|
||||
internal override void Draw(Size availableSpace)
|
||||
{
|
||||
base.Draw(availableSpace);
|
||||
|
||||
Canvas.DrawRectangle(
|
||||
new Position(-Left/2, -Top/2),
|
||||
new Size(availableSpace.Width + Left/2 + Right/2, Top),
|
||||
Color);
|
||||
|
||||
Canvas.DrawRectangle(
|
||||
new Position(-Left/2, -Top/2),
|
||||
new Size(Left, availableSpace.Height + Top/2 + Bottom/2),
|
||||
Color);
|
||||
|
||||
Canvas.DrawRectangle(
|
||||
new Position(-Left/2, availableSpace.Height-Bottom/2),
|
||||
new Size(availableSpace.Width + Left/2 + Right/2, Bottom),
|
||||
Color);
|
||||
|
||||
Canvas.DrawRectangle(
|
||||
new Position(availableSpace.Width-Right/2, -Top/2),
|
||||
new Size(Right, availableSpace.Height + Top/2 + Bottom/2),
|
||||
Color);
|
||||
|
||||
if (HasEqualWidthOnAllSides())
|
||||
{
|
||||
Canvas.DrawStrokedRectangle(availableSpace, Color, Top);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawCustomRectangle(availableSpace);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
private void DrawCustomRectangle(Size size)
|
||||
{
|
||||
return $"Border: Top({Top}) Right({Right}) Bottom({Bottom}) Left({Left}) Color({Color})";
|
||||
Canvas.DrawFilledRectangle(
|
||||
new Position(-Left / 2, -Top / 2),
|
||||
new Size(size.Width + Left / 2 + Right / 2, Top),
|
||||
Color);
|
||||
|
||||
Canvas.DrawFilledRectangle(
|
||||
new Position(-Left / 2, -Top / 2),
|
||||
new Size(Left, size.Height + Top / 2 + Bottom / 2),
|
||||
Color);
|
||||
|
||||
Canvas.DrawFilledRectangle(
|
||||
new Position(-Left / 2, size.Height - Bottom / 2),
|
||||
new Size(size.Width + Left / 2 + Right / 2, Bottom),
|
||||
Color);
|
||||
|
||||
Canvas.DrawFilledRectangle(
|
||||
new Position(size.Width - Right / 2, -Top / 2),
|
||||
new Size(Right, size.Height + Top / 2 + Bottom / 2),
|
||||
Color);
|
||||
}
|
||||
|
||||
private bool HasEqualWidthOnAllSides()
|
||||
{
|
||||
return IsClose(Top, Bottom) &&
|
||||
IsClose(Left, Right) &&
|
||||
IsClose(Top, Left);
|
||||
}
|
||||
|
||||
private static bool IsClose(float x, float y)
|
||||
{
|
||||
return Math.Abs(x - y) < Size.Epsilon;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ namespace QuestPDF.Elements.Text.Items
|
||||
|
||||
var text = Text.Substring(request.StartIndex, request.EndIndex - request.StartIndex);
|
||||
|
||||
request.Canvas.DrawRectangle(new Position(0, request.TotalAscent), new Size(request.TextSize.Width, request.TextSize.Height), Style.BackgroundColor);
|
||||
request.Canvas.DrawFilledRectangle(new Position(0, request.TotalAscent), new Size(request.TextSize.Width, request.TextSize.Height), Style.BackgroundColor);
|
||||
request.Canvas.DrawText(text, Position.Zero, Style);
|
||||
|
||||
// draw underline
|
||||
@@ -124,7 +124,7 @@ namespace QuestPDF.Elements.Text.Items
|
||||
|
||||
void DrawLine(float offset, float thickness)
|
||||
{
|
||||
request.Canvas.DrawRectangle(new Position(0, offset - thickness / 2f), new Size(request.TextSize.Width, thickness), Style.Color);
|
||||
request.Canvas.DrawFilledRectangle(new Position(0, offset - thickness / 2f), new Size(request.TextSize.Width, thickness), Style.Color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ namespace QuestPDF.Infrastructure
|
||||
{
|
||||
void Translate(Position vector);
|
||||
|
||||
void DrawRectangle(Position vector, Size size, string color);
|
||||
void DrawFilledRectangle(Position vector, Size size, string color);
|
||||
void DrawStrokedRectangle(Size size, string color, float width);
|
||||
void DrawText(string text, Position position, TextStyle style);
|
||||
void DrawImage(SKImage image, Position position, Size size);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user