Skip to content

Commit 5d969c1

Browse files
authored
Merge pull request #18 from synercoder/document-information-dictionary
Added document information
2 parents 99c6c0b + d622526 commit 5d969c1

File tree

9 files changed

+247
-147
lines changed

9 files changed

+247
-147
lines changed

samples/Synercoding.FileFormats.Pdf.ConsoleTester/Program.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ public static void Main(string[] args)
2626
);
2727

2828
writer
29+
// Set document info
30+
.SetDocumentInfo(info =>
31+
{
32+
info.Author = "Gerard Gunnewijk";
33+
info.Title = "Example 1";
34+
})
2935
// Test placement using rectangle
3036
.AddPage(page =>
3137
{
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
3+
namespace Synercoding.FileFormats.Pdf
4+
{
5+
/// <summary>
6+
/// This class contains information about the document
7+
/// </summary>
8+
public class DocumentInformation
9+
{
10+
/// <summary>
11+
/// The document's title
12+
/// </summary>
13+
public string Title { get; set; }
14+
15+
/// <summary>
16+
/// The name of the person who created the document
17+
/// </summary>
18+
public string Author { get; set; }
19+
20+
/// <summary>
21+
/// The subject of the document
22+
/// </summary>
23+
public string Subject { get; set; }
24+
25+
/// <summary>
26+
/// Keywords associated with the document
27+
/// </summary>
28+
public string Keywords { get; set; }
29+
30+
/// <summary>
31+
/// If the document was converted to PDF from another format, the name of the conforming product that created the original document from which it was converted. Otherwise the name of the application that created the document.
32+
/// </summary>
33+
public string Creator { get; set; }
34+
35+
/// <summary>
36+
/// If the document was converted to PDF from another format, the name of the conforming product that converted it to PDF.
37+
/// </summary>
38+
public string Producer { get; set; }
39+
40+
/// <summary>
41+
/// The date and time the document was created, in human-readable form.
42+
/// </summary>
43+
public DateTime? CreationDate { get; set; } = DateTime.Now;
44+
45+
/// <summary>
46+
/// The date and time the document was most recently modified, in human-readable form.
47+
/// </summary>
48+
public DateTime? ModDate { get; set; }
49+
}
50+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System;
2+
3+
namespace Synercoding.FileFormats.Pdf.Helpers
4+
{
5+
internal static class PdfTypeHelper
6+
{
7+
public static string ToPdfHexadecimalString(string input)
8+
{
9+
var bytes = System.Text.Encoding.ASCII.GetBytes(input);
10+
var builder = new System.Text.StringBuilder(bytes.Length + 2);
11+
builder.Append("<");
12+
foreach (var b in bytes)
13+
{
14+
builder.Append(b.ToString("X2"));
15+
}
16+
builder.Append(">");
17+
return builder.ToString();
18+
}
19+
20+
public static string ToPdfDate(DateTimeOffset input)
21+
{
22+
var datePart = input.ToString("yyyyMMddHHmmss");
23+
24+
var builder = new System.Text.StringBuilder(22);
25+
builder.Append("(D:");
26+
builder.Append(datePart);
27+
28+
var hours = input.Offset.Hours;
29+
var minutes = input.Offset.Minutes;
30+
31+
if (hours == 0 && minutes == 0)
32+
{
33+
builder.Append("Z00'00");
34+
}
35+
else
36+
{
37+
if (hours > 0 || ( hours == 0 && minutes > 0 ))
38+
{
39+
builder.Append("+");
40+
}
41+
else
42+
{
43+
builder.Append("-");
44+
}
45+
builder.Append(Math.Abs(hours).ToString().PadLeft(2, '0'));
46+
builder.Append("'");
47+
builder.Append(minutes.ToString().PadLeft(2, '0'));
48+
}
49+
builder.Append(")");
50+
51+
return builder.ToString();
52+
}
53+
}
54+
}

src/Synercoding.FileFormats.Pdf/PdfInternals/Objects/Catalog.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ namespace Synercoding.FileFormats.Pdf.PdfInternals.Objects
66
{
77
internal class Catalog : IPdfObject
88
{
9-
private readonly PdfReference _pageTree;
109
public Catalog(PdfReference id, PdfReference pageTree)
1110
{
1211
Reference = id;
13-
_pageTree = pageTree;
12+
PageTree = pageTree;
1413
}
1514

16-
public PdfReference Reference { get; private set; }
15+
public PdfReference Reference { get; }
16+
17+
public PdfReference PageTree { get; }
1718

1819
public bool IsWritten { get; private set; }
1920

@@ -29,7 +30,7 @@ public uint WriteToStream(Stream stream)
2930
{
3031
dictionary
3132
.Type(ObjectType.Catalog)
32-
.Write("/Pages", _pageTree);
33+
.Write("/Pages", PageTree);
3334
});
3435
IsWritten = true;
3536

@@ -39,5 +40,4 @@ public uint WriteToStream(Stream stream)
3940
public void Dispose()
4041
{ }
4142
}
42-
4343
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using Synercoding.FileFormats.Pdf.Extensions;
2+
using Synercoding.FileFormats.Pdf.Helpers;
3+
using System;
4+
using System.IO;
5+
6+
namespace Synercoding.FileFormats.Pdf.PdfInternals.Objects
7+
{
8+
internal class DocumentInformationDictionary : IPdfObject
9+
{
10+
private DocumentInformation _documentInformation;
11+
12+
public DocumentInformationDictionary(PdfReference id)
13+
{
14+
Reference = id;
15+
}
16+
17+
public DocumentInformationDictionary(PdfReference id, DocumentInformation data)
18+
: this(id)
19+
{
20+
Data = data ?? throw new ArgumentNullException(nameof(data));
21+
}
22+
23+
public PdfReference Reference { get; }
24+
25+
public bool IsWritten { get; private set; }
26+
27+
public DocumentInformation Data
28+
{
29+
get => _documentInformation;
30+
set => _documentInformation = value ?? throw new ArgumentNullException(nameof(Data));
31+
}
32+
33+
public void Dispose()
34+
{ }
35+
36+
public uint WriteToStream(Stream stream)
37+
{
38+
if (IsWritten)
39+
{
40+
throw new InvalidOperationException("Object is already written to stream.");
41+
}
42+
var position = (uint)stream.Position;
43+
44+
stream.IndirectDictionary(Reference, dictionary =>
45+
{
46+
if (!string.IsNullOrWhiteSpace(Data.Title))
47+
dictionary.Write("/Title", PdfTypeHelper.ToPdfHexadecimalString(Data.Title));
48+
if (!string.IsNullOrWhiteSpace(Data.Author))
49+
dictionary.Write("/Author", PdfTypeHelper.ToPdfHexadecimalString(Data.Author));
50+
if (!string.IsNullOrWhiteSpace(Data.Subject))
51+
dictionary.Write("/Subject", PdfTypeHelper.ToPdfHexadecimalString(Data.Subject));
52+
if (!string.IsNullOrWhiteSpace(Data.Keywords))
53+
dictionary.Write("/Keywords", PdfTypeHelper.ToPdfHexadecimalString(Data.Keywords));
54+
if (!string.IsNullOrWhiteSpace(Data.Creator))
55+
dictionary.Write("/Creator", PdfTypeHelper.ToPdfHexadecimalString(Data.Creator));
56+
if (!string.IsNullOrWhiteSpace(Data.Producer))
57+
dictionary.Write("/Producer", PdfTypeHelper.ToPdfHexadecimalString(Data.Producer));
58+
if (Data.CreationDate != null)
59+
dictionary.Write("/CreationDate", PdfTypeHelper.ToPdfDate(Data.CreationDate.Value));
60+
if (Data.ModDate != null)
61+
dictionary.Write("/ModDate", PdfTypeHelper.ToPdfDate(Data.ModDate.Value));
62+
});
63+
64+
IsWritten = true;
65+
66+
return position;
67+
}
68+
}
69+
}

src/Synercoding.FileFormats.Pdf/PdfInternals/Objects/PageTree.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ namespace Synercoding.FileFormats.Pdf.PdfInternals.Objects
88
{
99
internal class PageTree : IPdfObject
1010
{
11-
private readonly IEnumerable<IPdfObject> _pages;
11+
private readonly IList<IPdfObject> _pages;
1212

13-
public PageTree(PdfReference id, IEnumerable<IPdfObject> pages)
13+
public PageTree(PdfReference id, IList<IPdfObject> pages)
1414
{
1515
Reference = id;
1616
_pages = pages;

0 commit comments

Comments
 (0)