Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 0 additions & 23 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,6 @@
</PropertyGroup>

<Choose>
<When Condition="'$(TargetFramework)' == 'net472'">
<PropertyGroup>
<DefineConstants>$(DefineConstants);SUPPORTS_CODECOVERAGE</DefineConstants>
</PropertyGroup>
</When>
<When Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PropertyGroup>
<DefineConstants>$(DefineConstants);SUPPORTS_CODECOVERAGE</DefineConstants>
</PropertyGroup>
</When>
<When Condition="'$(TargetFramework)' == 'netstandard2.1'">
<PropertyGroup>
<DefineConstants>$(DefineConstants);SUPPORTS_MATHF</DefineConstants>
Expand All @@ -66,19 +56,6 @@
<DefineConstants>$(DefineConstants);SUPPORTS_NULLABLEREFATTRIBUTES</DefineConstants>
</PropertyGroup>
</When>
<When Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
<PropertyGroup>
<DefineConstants>$(DefineConstants);SUPPORTS_MATHF</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_CODECOVERAGE</DefineConstants>
</PropertyGroup>
</When>
<When Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
<PropertyGroup>
<DefineConstants>$(DefineConstants);SUPPORTS_MATHF</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_HASHCODE</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_CODECOVERAGE</DefineConstants>
</PropertyGroup>
</When>
<When Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<PropertyGroup>
<DefineConstants>$(DefineConstants);SUPPORTS_MATHF</DefineConstants>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Synercoding.FileFormats.Pdf.Primitives;
using Synercoding.FileFormats.Pdf.Extensions;
using Synercoding.Primitives;
using Synercoding.Primitives.Extensions;
using System.IO;
Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project>

<PropertyGroup>
<TargetFrameworks>net5.0;netcoreapp3.1;netcoreapp2.1;netstandard2.1;netstandard2.0;netstandard1.6</TargetFrameworks>
<TargetFrameworks>net5.0;netcoreapp3.1;netstandard2.1</TargetFrameworks>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.props</MSBuildAllProjects>
<SynercodingProjectCategory>src</SynercodingProjectCategory>
</PropertyGroup>
Expand Down
93 changes: 92 additions & 1 deletion src/Synercoding.FileFormats.Pdf/DocumentInformation.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
using Synercoding.FileFormats.Pdf.LowLevel;
using Synercoding.FileFormats.Pdf.LowLevel.Extensions;
using System;

namespace Synercoding.FileFormats.Pdf
{
/// <summary>
/// This class contains information about the document
/// </summary>
public class DocumentInformation
public class DocumentInformation : IPdfObject
{
private bool _isWritten;

internal DocumentInformation(PdfReference id)
{
Reference = id;
}

/// <summary>
/// The document's title
/// </summary>
Expand Down Expand Up @@ -46,5 +55,87 @@ public class DocumentInformation
/// The date and time the document was most recently modified, in human-readable form.
/// </summary>
public DateTime? ModDate { get; set; }

/// <inheritdoc />
public PdfReference Reference { get; }

internal uint WriteToStream(PdfStream stream)
{
if (_isWritten)
throw new InvalidOperationException("Object is already written to stream.");

var position = (uint)stream.Position;

stream.IndirectDictionary(this, static (did, dictionary) =>
{
if (!string.IsNullOrWhiteSpace(did.Title))
dictionary.Write(PdfName.Get("Title"), _toPdfHexadecimalString(did.Title!));
if (!string.IsNullOrWhiteSpace(did.Author))
dictionary.Write(PdfName.Get("Author"), _toPdfHexadecimalString(did.Author!));
if (!string.IsNullOrWhiteSpace(did.Subject))
dictionary.Write(PdfName.Get("Subject"), _toPdfHexadecimalString(did.Subject!));
if (!string.IsNullOrWhiteSpace(did.Keywords))
dictionary.Write(PdfName.Get("Keywords"), _toPdfHexadecimalString(did.Keywords!));
if (!string.IsNullOrWhiteSpace(did.Creator))
dictionary.Write(PdfName.Get("Creator"), _toPdfHexadecimalString(did.Creator!));
if (!string.IsNullOrWhiteSpace(did.Producer))
dictionary.Write(PdfName.Get("Producer"), _toPdfHexadecimalString(did.Producer!));
if (did.CreationDate != null)
dictionary.Write(PdfName.Get("CreationDate"), _toPdfDate(did.CreationDate.Value));
if (did.ModDate != null)
dictionary.Write(PdfName.Get("ModDate"), _toPdfDate(did.ModDate.Value));
});

_isWritten = true;

return position;
}

private static string _toPdfHexadecimalString(string input)
{
var bytes = System.Text.Encoding.ASCII.GetBytes(input);
var builder = new System.Text.StringBuilder((bytes.Length * 2) + 2);
builder.Append('<');
foreach (var b in bytes)
{
builder.Append(b.ToString("X2"));
}
builder.Append('>');
return builder.ToString();
}

private static string _toPdfDate(DateTimeOffset input)
{
var datePart = input.ToString("yyyyMMddHHmmss");

var builder = new System.Text.StringBuilder(22);
builder.Append("(D:");
builder.Append(datePart);

var hours = input.Offset.Hours;
var minutes = input.Offset.Minutes;

if (hours == 0 && minutes == 0)
{
builder.Append("Z00'00");
}
else
{
if (hours > 0 || (hours == 0 && minutes > 0))
{
builder.Append('+');
}
else
{
builder.Append('-');
}
builder.Append(Math.Abs(hours).ToString().PadLeft(2, '0'));
builder.Append('\'');
builder.Append(minutes.ToString().PadLeft(2, '0'));
}
builder.Append(')');

return builder.ToString();
}
}
}
35 changes: 0 additions & 35 deletions src/Synercoding.FileFormats.Pdf/Extensions/MatrixExtensions.cs

This file was deleted.

127 changes: 127 additions & 0 deletions src/Synercoding.FileFormats.Pdf/Extensions/PdfPageExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
using Synercoding.Primitives;
using System.IO;

namespace Synercoding.FileFormats.Pdf.Extensions
{
/// <summary>
/// Extension class for <see cref="PdfPage"/>
/// </summary>
public static class PdfPageExtensions
{
/// <summary>
/// Add an image to the pdf page
/// </summary>
/// <param name="page">The page to add the image to</param>
/// <param name="image">The image to add</param>
/// <param name="matrix">The placement matrix</param>
/// <returns>The same <see cref="PdfPage"/> to chain other calls.</returns>
public static PdfPage AddImage(this PdfPage page, Image image, Matrix matrix)
{
page.ContentStream
.SaveState()
.CTM(matrix)
.Paint(page.AddImageToResources(image))
.RestoreState();

return page;
}

/// <summary>
/// Add an image to the pdf page
/// </summary>
/// <param name="page">The page to add the image to</param>
/// <param name="image">The image to add</param>
/// <param name="rectangle">The placement rectangle</param>
/// <returns>The same <see cref="PdfPage"/> to chain other calls.</returns>
public static PdfPage AddImage(this PdfPage page, Image image, Rectangle rectangle)
=> page.AddImage(image, rectangle.AsPlacementMatrix());

/// <summary>
/// Add an image to the pdf page
/// </summary>
/// <param name="page">The page to add the image to</param>
/// <param name="image">The image to add</param>
/// <param name="matrix">The placement matrix</param>
/// <returns>The same <see cref="PdfPage"/> to chain other calls.</returns>
public static PdfPage AddImage(this PdfPage page, SixLabors.ImageSharp.Image image, Matrix matrix)
{
page.ContentStream
.SaveState()
.CTM(matrix)
.Paint(page.AddImageToResources(image))
.RestoreState();

return page;
}

/// <summary>
/// Add an image to the pdf page
/// </summary>
/// <param name="page">The page to add the image to</param>
/// <param name="image">The image to add</param>
/// <param name="rectangle">The placement rectangle</param>
/// <returns>The same <see cref="PdfPage"/> to chain other calls.</returns>
public static PdfPage AddImage(this PdfPage page, SixLabors.ImageSharp.Image image, Rectangle rectangle)
=> page.AddImage(image, rectangle.AsPlacementMatrix());

/// <summary>
/// Add an image to the pdf page
/// </summary>
/// <param name="page">The page to add the image to</param>
/// <param name="imageStream">The image to add</param>
/// <param name="matrix">The placement matrix</param>
/// <returns>The same <see cref="PdfPage"/> to chain other calls.</returns>
public static PdfPage AddImage(this PdfPage page, Stream imageStream, Matrix matrix)
{
page.ContentStream
.SaveState()
.CTM(matrix)
.Paint(page.AddImageToResources(imageStream))
.RestoreState();

return page;
}

/// <summary>
/// Add an image to the pdf page
/// </summary>
/// <param name="page">The page to add the image to</param>
/// <param name="imageStream">The image to add</param>
/// <param name="rectangle">The placement rectangle</param>
/// <returns>The same <see cref="PdfPage"/> to chain other calls.</returns>
public static PdfPage AddImage(this PdfPage page, Stream imageStream, Rectangle rectangle)
=> page.AddImage(imageStream, rectangle.AsPlacementMatrix());

/// <summary>
/// Add an image to the pdf page
/// </summary>
/// <param name="page">The page to add the image to</param>
/// <param name="jpgStream">The image to add</param>
/// <param name="originalWidth">The original width of the image</param>
/// <param name="originalHeight">The original height of the image</param>
/// <param name="matrix">The placement matrix</param>
/// <returns>The same <see cref="PdfPage"/> to chain other calls.</returns>
public static PdfPage AddImage(this PdfPage page, Stream jpgStream, int originalWidth, int originalHeight, Matrix matrix)
{
page.ContentStream
.SaveState()
.CTM(matrix)
.Paint(page.AddImageToResources(jpgStream, originalWidth, originalHeight))
.RestoreState();

return page;
}

/// <summary>
/// Add an image to the pdf page
/// </summary>
/// <param name="page">The page to add the image to</param>
/// <param name="jpgStream">The image to add</param>
/// <param name="originalWidth">The original width of the image</param>
/// <param name="originalHeight">The original height of the image</param>
/// <param name="rectangle">The placement rectangle</param>
/// <returns>The same <see cref="PdfPage"/> to chain other calls.</returns>
public static PdfPage AddImage(this PdfPage page, Stream jpgStream, int originalWidth, int originalHeight, Rectangle rectangle)
=> page.AddImage(jpgStream, originalWidth, originalHeight, rectangle.AsPlacementMatrix());
}
}
16 changes: 16 additions & 0 deletions src/Synercoding.FileFormats.Pdf/Extensions/PrimitiveExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Synercoding.Primitives;

namespace Synercoding.FileFormats.Pdf.Extensions
{
public static class PrimitiveExtensions
{
public static Matrix AsPlacementMatrix(this Rectangle rectangle)
{
rectangle = rectangle.ConvertTo(Unit.Points);
return new Matrix(
rectangle.URX.Raw - rectangle.LLX.Raw, 0,
0, rectangle.URY.Raw - rectangle.LLY.Raw,
rectangle.LLX.Raw, rectangle.LLY.Raw);
}
}
}
Loading