mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-06-28 15:30:17 +08:00
Enable nullable annotations (#803)
* Enable nullable annotations * Remove unused Jetbrain annotations * Ensure system using statements are first * Improve nullability annotations * Annotate encryptionDictionary is non-null when IsEncrypted is true * Disable nullable for PdfTokenScanner.Get * Improve nullability annotations for ObjectLocationProvider.TryGetCached * Revert changes to RGBWorkingSpace * Update UglyToad.PdfPig.Package with new framework targets (fixes nightly builds)
This commit is contained in:
parent
bf6c519483
commit
a412a239be
@ -6,7 +6,6 @@
|
||||
using Core;
|
||||
using Fields;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// A collection of interactive fields for gathering data from a user through dropdowns, textboxes, checkboxes, etc.
|
||||
@ -22,7 +21,6 @@
|
||||
/// <summary>
|
||||
/// The raw PDF dictionary which is the root form object.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DictionaryToken Dictionary { get; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -42,12 +42,12 @@ namespace UglyToad.PdfPig.AcroForms
|
||||
/// <summary>
|
||||
/// Get string values of field.
|
||||
/// </summary>
|
||||
public static KeyValuePair<string, string> GetFieldValue(this AcroFieldBase fieldBase)
|
||||
public static KeyValuePair<string?, string?> GetFieldValue(this AcroFieldBase fieldBase)
|
||||
{
|
||||
return fieldBase switch
|
||||
{
|
||||
AcroTextField textField => new(textField.Information.PartialName, textField.Value),
|
||||
AcroCheckboxField checkboxField => new(checkboxField.Information.PartialName, checkboxField.IsChecked.ToString()),
|
||||
AcroCheckboxField checkboxField => new(checkboxField.Information.PartialName, checkboxField.IsChecked.ToString())!,
|
||||
_ => new(fieldBase.Information.PartialName, ""),
|
||||
};
|
||||
}
|
||||
|
@ -1,18 +1,17 @@
|
||||
namespace UglyToad.PdfPig.AcroForms
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content;
|
||||
using Core;
|
||||
using CrossReference;
|
||||
using Fields;
|
||||
using Filters;
|
||||
using Parser.Parts;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Tokenization.Scanner;
|
||||
using Tokens;
|
||||
using Util;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the <see cref="AcroForm"/> from the document, if available.
|
||||
@ -43,15 +42,14 @@
|
||||
/// Retrieve the <see cref="AcroForm"/> from the document, if applicable.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="AcroForm"/> if the document contains one.</returns>
|
||||
[CanBeNull]
|
||||
public AcroForm GetAcroForm(Catalog catalog)
|
||||
public AcroForm? GetAcroForm(Catalog catalog)
|
||||
{
|
||||
if (!catalog.CatalogDictionary.TryGet(NameToken.AcroForm, out var acroRawToken) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!DirectObjectFinder.TryGet(acroRawToken, tokenScanner, out DictionaryToken acroDictionary))
|
||||
if (!DirectObjectFinder.TryGet(acroRawToken, tokenScanner, out DictionaryToken? acroDictionary))
|
||||
{
|
||||
var fieldsRefs = new List<IndirectReferenceToken>();
|
||||
|
||||
@ -59,12 +57,12 @@
|
||||
foreach (var reference in crossReferenceTable.ObjectOffsets.Keys)
|
||||
{
|
||||
var referenceToken = new IndirectReferenceToken(reference);
|
||||
if (!DirectObjectFinder.TryGet(referenceToken, tokenScanner, out DictionaryToken dict))
|
||||
if (!DirectObjectFinder.TryGet(referenceToken, tokenScanner, out DictionaryToken? dict))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dict.TryGet(NameToken.Kids, tokenScanner, out ArrayToken _) && dict.TryGet(NameToken.T, tokenScanner, out StringToken _))
|
||||
if (dict.TryGet(NameToken.Kids, tokenScanner, out ArrayToken? _) && dict.TryGet(NameToken.T, tokenScanner, out StringToken? _))
|
||||
{
|
||||
fieldsRefs.Add(referenceToken);
|
||||
}
|
||||
@ -82,40 +80,40 @@
|
||||
}
|
||||
|
||||
var signatureFlags = (SignatureFlags)0;
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.SigFlags, tokenScanner, out NumericToken signatureToken))
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.SigFlags, tokenScanner, out NumericToken? signatureToken))
|
||||
{
|
||||
signatureFlags = (SignatureFlags)signatureToken.Int;
|
||||
}
|
||||
|
||||
var needAppearances = false;
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.NeedAppearances, tokenScanner, out BooleanToken appearancesToken))
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.NeedAppearances, tokenScanner, out BooleanToken? appearancesToken))
|
||||
{
|
||||
needAppearances = appearancesToken.Data;
|
||||
}
|
||||
|
||||
var calculationOrder = default(ArrayToken);
|
||||
ArrayToken? calculationOrder;
|
||||
acroDictionary.TryGetOptionalTokenDirect(NameToken.Co, tokenScanner, out calculationOrder);
|
||||
|
||||
var formResources = default(DictionaryToken);
|
||||
DictionaryToken? formResources = default;
|
||||
acroDictionary.TryGetOptionalTokenDirect(NameToken.Dr, tokenScanner, out formResources);
|
||||
|
||||
var da = default(string);
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.Da, tokenScanner, out StringToken daToken))
|
||||
string? da = default;
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.Da, tokenScanner, out StringToken? daToken))
|
||||
{
|
||||
da = daToken.Data;
|
||||
}
|
||||
else if (acroDictionary.TryGetOptionalTokenDirect(NameToken.Da, tokenScanner, out HexToken daHexToken))
|
||||
else if (acroDictionary.TryGetOptionalTokenDirect(NameToken.Da, tokenScanner, out HexToken? daHexToken))
|
||||
{
|
||||
da = daHexToken.Data;
|
||||
}
|
||||
|
||||
var q = default(int?);
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.Q, tokenScanner, out NumericToken qToken))
|
||||
if (acroDictionary.TryGetOptionalTokenDirect(NameToken.Q, tokenScanner, out NumericToken? qToken))
|
||||
{
|
||||
q = qToken.Int;
|
||||
}
|
||||
|
||||
if (!acroDictionary.TryGet(NameToken.Fields, tokenScanner, out ArrayToken fieldsArray))
|
||||
if (!acroDictionary.TryGet(NameToken.Fields, tokenScanner, out ArrayToken? fieldsArray))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -146,12 +144,12 @@
|
||||
|
||||
fieldDictionary = combinedFieldDictionary;
|
||||
|
||||
fieldDictionary.TryGet(NameToken.Ft, tokenScanner, out NameToken fieldType);
|
||||
fieldDictionary.TryGet(NameToken.Ff, tokenScanner, out NumericToken fieldFlagsToken);
|
||||
fieldDictionary.TryGet(NameToken.Ft, tokenScanner, out NameToken? fieldType);
|
||||
fieldDictionary.TryGet(NameToken.Ff, tokenScanner, out NumericToken? fieldFlagsToken);
|
||||
|
||||
var kids = new List<(bool hasParent, DictionaryToken dictionary)>();
|
||||
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.Kids, tokenScanner, out ArrayToken kidsToken))
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.Kids, tokenScanner, out ArrayToken? kidsToken))
|
||||
{
|
||||
foreach (var kid in kidsToken.Data)
|
||||
{
|
||||
@ -185,13 +183,13 @@
|
||||
var information = new AcroFieldCommonInformation(parentReferenceToken?.Data, partialFieldName, alternateFieldName, mappingName);
|
||||
|
||||
int? pageNumber = null;
|
||||
if (fieldDictionary.TryGet(NameToken.P, tokenScanner, out IndirectReferenceToken pageReference))
|
||||
if (fieldDictionary.TryGet(NameToken.P, tokenScanner, out IndirectReferenceToken? pageReference))
|
||||
{
|
||||
pageNumber = catalog.Pages.GetPageByReference(pageReference.Data)?.PageNumber;
|
||||
}
|
||||
|
||||
PdfRectangle? bounds = null;
|
||||
if (fieldDictionary.TryGet(NameToken.Rect, tokenScanner, out ArrayToken rectArray) && rectArray.Length == 4)
|
||||
if (fieldDictionary.TryGet(NameToken.Rect, tokenScanner, out ArrayToken? rectArray) && rectArray.Length == 4)
|
||||
{
|
||||
bounds = rectArray.ToRectangle(tokenScanner);
|
||||
}
|
||||
@ -303,22 +301,22 @@
|
||||
var textValue = default(string);
|
||||
if (fieldDictionary.TryGet(NameToken.V, out var textValueToken))
|
||||
{
|
||||
if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out StringToken valueStringToken))
|
||||
if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out StringToken? valueStringToken))
|
||||
{
|
||||
textValue = valueStringToken.Data;
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out HexToken valueHexToken))
|
||||
else if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out HexToken? valueHexToken))
|
||||
{
|
||||
textValue = valueHexToken.Data;
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out StreamToken valueStreamToken))
|
||||
else if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out StreamToken? valueStreamToken))
|
||||
{
|
||||
textValue = OtherEncodings.BytesAsLatin1String(valueStreamToken.Decode(filterProvider, tokenScanner).ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
var maxLength = default(int?);
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.MaxLen, tokenScanner, out NumericToken maxLenToken))
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.MaxLen, tokenScanner, out NumericToken? maxLenToken))
|
||||
{
|
||||
maxLength = maxLenToken.Int;
|
||||
}
|
||||
@ -341,27 +339,27 @@
|
||||
var selectedOptions = Array.Empty<string>();
|
||||
if (fieldDictionary.TryGet(NameToken.V, out var valueToken))
|
||||
{
|
||||
if (DirectObjectFinder.TryGet(valueToken, tokenScanner, out StringToken valueString))
|
||||
if (DirectObjectFinder.TryGet(valueToken, tokenScanner, out StringToken? valueString))
|
||||
{
|
||||
selectedOptions = [valueString.Data];
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(valueToken, tokenScanner, out HexToken valueHex))
|
||||
else if (DirectObjectFinder.TryGet(valueToken, tokenScanner, out HexToken? valueHex))
|
||||
{
|
||||
selectedOptions = [valueHex.Data];
|
||||
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(valueToken, tokenScanner, out ArrayToken valueArray))
|
||||
else if (DirectObjectFinder.TryGet(valueToken, tokenScanner, out ArrayToken? valueArray))
|
||||
{
|
||||
selectedOptions = new string[valueArray.Length];
|
||||
for (var i = 0; i < valueArray.Length; i++)
|
||||
{
|
||||
var valueOptToken = valueArray.Data[i];
|
||||
|
||||
if (DirectObjectFinder.TryGet(valueOptToken, tokenScanner, out StringToken valueOptString))
|
||||
if (DirectObjectFinder.TryGet(valueOptToken, tokenScanner, out StringToken? valueOptString))
|
||||
{
|
||||
selectedOptions[i] = valueOptString.Data;
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(valueOptToken, tokenScanner, out HexToken valueOptHex))
|
||||
else if (DirectObjectFinder.TryGet(valueOptToken, tokenScanner, out HexToken? valueOptHex))
|
||||
{
|
||||
selectedOptions[i] = valueOptHex.Data;
|
||||
}
|
||||
@ -370,7 +368,7 @@
|
||||
}
|
||||
|
||||
var selectedIndices = default(int[]);
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.I, tokenScanner, out ArrayToken indicesArray))
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.I, tokenScanner, out ArrayToken? indicesArray))
|
||||
{
|
||||
selectedIndices = new int[indicesArray.Length];
|
||||
for (var i = 0; i < indicesArray.Data.Count; i++)
|
||||
@ -382,24 +380,24 @@
|
||||
}
|
||||
|
||||
var options = new List<AcroChoiceOption>();
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.Opt, tokenScanner, out ArrayToken optionsArrayToken))
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.Opt, tokenScanner, out ArrayToken? optionsArrayToken))
|
||||
{
|
||||
for (var i = 0; i < optionsArrayToken.Data.Count; i++)
|
||||
{
|
||||
var optionToken = optionsArrayToken.Data[i];
|
||||
if (DirectObjectFinder.TryGet(optionToken, tokenScanner, out StringToken optionStringToken))
|
||||
if (DirectObjectFinder.TryGet(optionToken, tokenScanner, out StringToken? optionStringToken))
|
||||
{
|
||||
var name = optionStringToken.Data;
|
||||
var isSelected = IsChoiceSelected(selectedOptions, selectedIndices, i, name);
|
||||
options.Add(new AcroChoiceOption(i, isSelected, optionStringToken.Data));
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(optionToken, tokenScanner, out HexToken optionHexToken))
|
||||
else if (DirectObjectFinder.TryGet(optionToken, tokenScanner, out HexToken? optionHexToken))
|
||||
{
|
||||
var name = optionHexToken.Data;
|
||||
var isSelected = IsChoiceSelected(selectedOptions, selectedIndices, i, name);
|
||||
options.Add(new AcroChoiceOption(i, isSelected, optionHexToken.Data));
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(optionToken, tokenScanner, out ArrayToken optionArrayToken))
|
||||
else if (DirectObjectFinder.TryGet(optionToken, tokenScanner, out ArrayToken? optionArrayToken))
|
||||
{
|
||||
if (optionArrayToken.Length != 2)
|
||||
{
|
||||
@ -407,11 +405,11 @@
|
||||
}
|
||||
|
||||
string exportValue;
|
||||
if (DirectObjectFinder.TryGet(optionArrayToken.Data[0], tokenScanner, out StringToken exportValueStringToken))
|
||||
if (DirectObjectFinder.TryGet(optionArrayToken.Data[0], tokenScanner, out StringToken? exportValueStringToken))
|
||||
{
|
||||
exportValue = exportValueStringToken.Data;
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(optionArrayToken.Data[0], tokenScanner, out HexToken exportValueHexToken))
|
||||
else if (DirectObjectFinder.TryGet(optionArrayToken.Data[0], tokenScanner, out HexToken? exportValueHexToken))
|
||||
{
|
||||
exportValue = exportValueHexToken.Data;
|
||||
}
|
||||
@ -421,11 +419,11 @@
|
||||
}
|
||||
|
||||
string name;
|
||||
if (DirectObjectFinder.TryGet(optionArrayToken.Data[1], tokenScanner, out StringToken nameStringToken))
|
||||
if (DirectObjectFinder.TryGet(optionArrayToken.Data[1], tokenScanner, out StringToken? nameStringToken))
|
||||
{
|
||||
name = nameStringToken.Data;
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(optionArrayToken.Data[1], tokenScanner, out HexToken nameHexToken))
|
||||
else if (DirectObjectFinder.TryGet(optionArrayToken.Data[1], tokenScanner, out HexToken? nameHexToken))
|
||||
{
|
||||
name = nameHexToken.Data;
|
||||
}
|
||||
@ -458,7 +456,7 @@
|
||||
}
|
||||
|
||||
var topIndex = default(int?);
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.Ti, tokenScanner, out NumericToken topIndexToken))
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.Ti, tokenScanner, out NumericToken? topIndexToken))
|
||||
{
|
||||
topIndex = topIndexToken.Int;
|
||||
}
|
||||
@ -475,10 +473,10 @@
|
||||
private (bool isChecked, NameToken stateName) GetCheckedState(DictionaryToken fieldDictionary, bool inheritsValue)
|
||||
{
|
||||
var isChecked = false;
|
||||
if (!fieldDictionary.TryGetOptionalTokenDirect(NameToken.V, tokenScanner, out NameToken valueToken))
|
||||
if (!fieldDictionary.TryGetOptionalTokenDirect(NameToken.V, tokenScanner, out NameToken? valueToken))
|
||||
{
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.As, tokenScanner, out NameToken appearanceStateName)
|
||||
&& fieldDictionary.TryGetOptionalTokenDirect(NameToken.Ap, tokenScanner, out DictionaryToken _))
|
||||
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.As, tokenScanner, out NameToken? appearanceStateName)
|
||||
&& fieldDictionary.TryGetOptionalTokenDirect(NameToken.Ap, tokenScanner, out DictionaryToken? _))
|
||||
{
|
||||
// Issue #267 - Use the set appearance instead, this might not work for 3 state checkboxes.
|
||||
isChecked = !string.Equals(
|
||||
@ -490,7 +488,7 @@
|
||||
}
|
||||
valueToken = NameToken.Off;
|
||||
}
|
||||
else if (inheritsValue && fieldDictionary.TryGet(NameToken.As, tokenScanner, out NameToken appearanceStateName))
|
||||
else if (inheritsValue && fieldDictionary.TryGet(NameToken.As, tokenScanner, out NameToken? appearanceStateName))
|
||||
{
|
||||
// The parent field's V entry holds a name object corresponding to the
|
||||
// appearance state of whichever child field is currently in the on state.
|
||||
@ -546,7 +544,7 @@
|
||||
return (new DictionaryToken(inheritedDictionary), inheritsValue);
|
||||
}
|
||||
|
||||
private static bool IsChoiceSelected(IReadOnlyList<string> selectedOptionNames, IReadOnlyList<int> selectedOptionIndices, int index, string name)
|
||||
private static bool IsChoiceSelected(IReadOnlyList<string> selectedOptionNames, IReadOnlyList<int>? selectedOptionIndices, int index, string name)
|
||||
{
|
||||
if (selectedOptionNames.Count == 0)
|
||||
{
|
||||
|
@ -23,7 +23,7 @@
|
||||
/// <summary>
|
||||
/// The value of the option when the form is exported.
|
||||
/// </summary>
|
||||
public string ExportValue { get; }
|
||||
public string? ExportValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the field defined an export value for this option.
|
||||
@ -33,7 +33,7 @@
|
||||
/// <summary>
|
||||
/// Create a new <see cref="AcroChoiceOption"/>.
|
||||
/// </summary>
|
||||
public AcroChoiceOption(int index, bool isSelected, string name, string exportValue = null)
|
||||
public AcroChoiceOption(int index, bool isSelected, string name, string? exportValue = null)
|
||||
{
|
||||
Index = index;
|
||||
IsSelected = isSelected;
|
||||
|
@ -4,7 +4,6 @@
|
||||
using System.Collections.Generic;
|
||||
using Core;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
@ -21,20 +20,17 @@
|
||||
/// <summary>
|
||||
/// The options to be presented to the user.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public IReadOnlyList<AcroChoiceOption> Options { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The names of any currently selected options.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public IReadOnlyList<string> SelectedOptions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// For multiple select lists with duplicate names gives the indices of the selected options.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public IReadOnlyList<int> SelectedOptionIndices { get; }
|
||||
public IReadOnlyList<int>? SelectedOptionIndices { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
@ -49,10 +45,13 @@
|
||||
/// <param name="selectedOptions">The names of the selected options.</param>
|
||||
/// <param name="pageNumber">The number of the page this field appears on.</param>
|
||||
/// <param name="bounds">The location of this field on the page.</param>
|
||||
public AcroComboBoxField(DictionaryToken dictionary, string fieldType, AcroChoiceFieldFlags fieldFlags,
|
||||
public AcroComboBoxField(
|
||||
DictionaryToken dictionary,
|
||||
string fieldType,
|
||||
AcroChoiceFieldFlags fieldFlags,
|
||||
AcroFieldCommonInformation information, IReadOnlyList<AcroChoiceOption> options,
|
||||
IReadOnlyList<string> selectedOptions,
|
||||
IReadOnlyList<int> selectedOptionIndices,
|
||||
IReadOnlyList<int>? selectedOptionIndices,
|
||||
int? pageNumber,
|
||||
PdfRectangle? bounds) :
|
||||
base(dictionary, fieldType, (uint)fieldFlags, AcroFieldType.ComboBox, information,
|
||||
|
@ -1,9 +1,8 @@
|
||||
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||
{
|
||||
using System;
|
||||
using Core;
|
||||
using System;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// A field in an interactive <see cref="AcroForm"/>.
|
||||
@ -13,13 +12,11 @@
|
||||
/// <summary>
|
||||
/// The raw PDF dictionary for this field.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DictionaryToken Dictionary { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="string"/> representing the type of this field in PDF format.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public string RawFieldType { get; }
|
||||
|
||||
/// <summary>
|
||||
@ -35,7 +32,6 @@
|
||||
/// <summary>
|
||||
/// The optional information common to all types of field.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public AcroFieldCommonInformation Information { get; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,7 +1,6 @@
|
||||
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||
{
|
||||
using Core;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Information from the field dictionary which is common across all field types.
|
||||
@ -18,26 +17,23 @@
|
||||
/// The partial field name for this field. The fully qualified field name is the
|
||||
/// period '.' joined name of all parents' partial names and this field's partial name.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string PartialName { get; }
|
||||
public string? PartialName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The alternate field name to be used instead of the fully qualified field name where
|
||||
/// the field is being identified on the user interface or by screen readers.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string AlternateName { get; }
|
||||
public string? AlternateName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The mapping name used when exporting form field data from the document.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string MappingName { get; }
|
||||
public string? MappingName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="AcroFieldCommonInformation"/>.
|
||||
/// </summary>
|
||||
public AcroFieldCommonInformation(IndirectReference? parent, string partialName, string alternateName, string mappingName)
|
||||
public AcroFieldCommonInformation(IndirectReference? parent, string? partialName, string? alternateName, string? mappingName)
|
||||
{
|
||||
Parent = parent;
|
||||
PartialName = partialName;
|
||||
@ -48,7 +44,7 @@
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
string AppendIfNotNull(string val, string label, string result)
|
||||
string AppendIfNotNull(string? val, string label, string result)
|
||||
{
|
||||
if (val is null)
|
||||
{
|
||||
|
@ -4,7 +4,6 @@
|
||||
using System.Collections.Generic;
|
||||
using Core;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
@ -20,20 +19,17 @@
|
||||
/// <summary>
|
||||
/// The options to be presented to the user.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public IReadOnlyList<AcroChoiceOption> Options { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The names of any currently selected options.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public IReadOnlyList<string> SelectedOptions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// For multiple select lists with duplicate names gives the indices of the selected options.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public IReadOnlyList<int> SelectedOptionIndices { get; }
|
||||
public IReadOnlyList<int>? SelectedOptionIndices { get; }
|
||||
|
||||
/// <summary>
|
||||
/// For scrollable list boxes gives the index of the first visible option.
|
||||
@ -62,7 +58,7 @@
|
||||
public AcroListBoxField(DictionaryToken dictionary, string fieldType, AcroChoiceFieldFlags fieldFlags,
|
||||
AcroFieldCommonInformation information, IReadOnlyList<AcroChoiceOption> options,
|
||||
IReadOnlyList<string> selectedOptions,
|
||||
IReadOnlyList<int> selectedOptionIndices,
|
||||
IReadOnlyList<int>? selectedOptionIndices,
|
||||
int? topIndex,
|
||||
int? pageNumber,
|
||||
PdfRectangle? bounds) :
|
||||
|
@ -19,7 +19,7 @@
|
||||
/// The value of the text in this text field.
|
||||
/// This can be <see langword="null"/> if no value has been set.
|
||||
/// </summary>
|
||||
public string Value { get; }
|
||||
public string? Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The optional maximum length of the text field.
|
||||
@ -50,7 +50,7 @@
|
||||
/// <param name="bounds">The location of this field on the page.</param>
|
||||
public AcroTextField(DictionaryToken dictionary, string fieldType, AcroTextFieldFlags fieldFlags,
|
||||
AcroFieldCommonInformation information,
|
||||
string value,
|
||||
string? value,
|
||||
int? maxLength,
|
||||
int? pageNumber,
|
||||
PdfRectangle? bounds) :
|
||||
|
@ -1,11 +1,11 @@
|
||||
namespace UglyToad.PdfPig.Actions
|
||||
{
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Core;
|
||||
using Logging;
|
||||
using Outline;
|
||||
using Outline.Destinations;
|
||||
using Tokenization.Scanner;
|
||||
using Tokens;
|
||||
using Outline.Destinations;
|
||||
using Util;
|
||||
|
||||
internal static class ActionProvider
|
||||
@ -13,20 +13,21 @@
|
||||
/// <summary>
|
||||
/// Get an action (A) from dictionary. If GoTo, GoToR or GoToE, also fetches the action destination.
|
||||
/// </summary>
|
||||
internal static bool TryGetAction(DictionaryToken dictionary,
|
||||
internal static bool TryGetAction(
|
||||
DictionaryToken dictionary,
|
||||
NamedDestinations namedDestinations,
|
||||
IPdfTokenScanner pdfScanner,
|
||||
ILog log,
|
||||
out PdfAction result)
|
||||
[NotNullWhen(true)] out PdfAction? result)
|
||||
{
|
||||
result = null;
|
||||
|
||||
if (!dictionary.TryGet(NameToken.A, pdfScanner, out DictionaryToken actionDictionary))
|
||||
if (!dictionary.TryGet(NameToken.A, pdfScanner, out DictionaryToken? actionDictionary))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!actionDictionary.TryGet(NameToken.S, pdfScanner, out NameToken actionType))
|
||||
if (!actionDictionary.TryGet(NameToken.S, pdfScanner, out NameToken? actionType))
|
||||
{
|
||||
throw new PdfDocumentFormatException($"No action type (/S) specified for action: {actionDictionary}.");
|
||||
}
|
||||
@ -81,7 +82,7 @@
|
||||
fileSpecification = null;
|
||||
}
|
||||
|
||||
result = new GoToEAction(destination, fileSpecification);
|
||||
result = new GoToEAction(destination, fileSpecification!);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace UglyToad.PdfPig.Actions
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Actions
|
||||
{
|
||||
/// <summary>
|
||||
/// Action to open a URI
|
||||
|
@ -2,6 +2,7 @@
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content;
|
||||
using Core;
|
||||
using Filters;
|
||||
@ -37,14 +38,14 @@
|
||||
/// </summary>
|
||||
/// <param name="embeddedFiles">The set of embedded files in this document.</param>
|
||||
/// <returns><see langword="true"/> if this document contains more than zero embedded files, otherwise <see langword="false"/>.</returns>
|
||||
public bool TryGetEmbeddedFiles(out IReadOnlyList<EmbeddedFile> embeddedFiles)
|
||||
public bool TryGetEmbeddedFiles([NotNullWhen(true)] out IReadOnlyList<EmbeddedFile>? embeddedFiles)
|
||||
{
|
||||
GuardDisposed();
|
||||
|
||||
embeddedFiles = null;
|
||||
|
||||
if (!catalog.CatalogDictionary.TryGet(NameToken.Names, pdfScanner, out DictionaryToken namesDictionary)
|
||||
|| !namesDictionary.TryGet(NameToken.EmbeddedFiles, pdfScanner, out DictionaryToken embeddedFileNamesDictionary))
|
||||
if (!catalog.CatalogDictionary.TryGet(NameToken.Names, pdfScanner, out DictionaryToken? namesDictionary)
|
||||
|| !namesDictionary.TryGet(NameToken.EmbeddedFiles, pdfScanner, out DictionaryToken? embeddedFileNamesDictionary))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -60,15 +61,15 @@
|
||||
|
||||
foreach (var keyValuePair in embeddedFileNames)
|
||||
{
|
||||
if (!DirectObjectFinder.TryGet(keyValuePair.Value, pdfScanner, out DictionaryToken fileDescriptorDictionaryToken)
|
||||
|| !fileDescriptorDictionaryToken.TryGet(NameToken.Ef, pdfScanner, out DictionaryToken efDictionary)
|
||||
|| !efDictionary.TryGet(NameToken.F, pdfScanner, out StreamToken fileStreamToken))
|
||||
if (!DirectObjectFinder.TryGet(keyValuePair.Value, pdfScanner, out DictionaryToken? fileDescriptorDictionaryToken)
|
||||
|| !fileDescriptorDictionaryToken.TryGet(NameToken.Ef, pdfScanner, out DictionaryToken? efDictionary)
|
||||
|| !efDictionary.TryGet(NameToken.F, pdfScanner, out StreamToken? fileStreamToken))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var fileSpecification = string.Empty;
|
||||
if (fileDescriptorDictionaryToken.TryGet(NameToken.F, pdfScanner, out IDataToken<string> fileSpecificationToken))
|
||||
if (fileDescriptorDictionaryToken.TryGet(NameToken.F, pdfScanner, out IDataToken<string>? fileSpecificationToken))
|
||||
{
|
||||
fileSpecification = fileSpecificationToken.Data;
|
||||
}
|
||||
|
@ -5,22 +5,20 @@
|
||||
using Core;
|
||||
using Actions;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// An annotation on a page in a PDF document.
|
||||
/// </summary>
|
||||
public class Annotation
|
||||
{
|
||||
internal readonly AppearanceStream normalAppearanceStream;
|
||||
internal readonly AppearanceStream rollOverAppearanceStream;
|
||||
internal readonly AppearanceStream downAppearanceStream;
|
||||
internal readonly string appearanceState;
|
||||
internal readonly AppearanceStream? normalAppearanceStream;
|
||||
internal readonly AppearanceStream? rollOverAppearanceStream;
|
||||
internal readonly AppearanceStream? downAppearanceStream;
|
||||
internal readonly string? appearanceState;
|
||||
|
||||
/// <summary>
|
||||
/// The underlying PDF dictionary which this annotation was created from.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DictionaryToken AnnotationDictionary { get; }
|
||||
|
||||
/// <summary>
|
||||
@ -36,20 +34,17 @@
|
||||
/// <summary>
|
||||
/// The annotation text, or if the annotation does not display text, a description of the annotation's contents. Optional.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Content { get; }
|
||||
public string? Content { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of this annotation which should be unique per page. Optional.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Name { get; }
|
||||
public string? Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The date and time the annotation was last modified, can be in any format. Optional.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string ModifiedDate { get; }
|
||||
public string? ModifiedDate { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Flags defining the appearance and behaviour of this annotation.
|
||||
@ -71,7 +66,7 @@
|
||||
/// <summary>
|
||||
/// Action for this annotation, if any (can be null)
|
||||
/// </summary>
|
||||
public PdfAction Action { get; }
|
||||
public PdfAction? Action { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if a normal appearance is present for this annotation
|
||||
@ -91,7 +86,7 @@
|
||||
/// <summary>
|
||||
/// The <see cref="Annotation"/> this annotation was in reply to. Can be <see langword="null" />
|
||||
/// </summary>
|
||||
public Annotation InReplyTo { get; }
|
||||
public Annotation? InReplyTo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Annotation"/>.
|
||||
@ -100,18 +95,18 @@
|
||||
DictionaryToken annotationDictionary,
|
||||
AnnotationType type,
|
||||
PdfRectangle rectangle,
|
||||
string content,
|
||||
string name,
|
||||
string modifiedDate,
|
||||
string? content,
|
||||
string? name,
|
||||
string? modifiedDate,
|
||||
AnnotationFlags flags,
|
||||
AnnotationBorder border,
|
||||
IReadOnlyList<QuadPointsQuadrilateral> quadPoints,
|
||||
PdfAction action,
|
||||
AppearanceStream normalAppearanceStream,
|
||||
AppearanceStream rollOverAppearanceStream,
|
||||
AppearanceStream downAppearanceStream,
|
||||
string appearanceState,
|
||||
Annotation inReplyTo)
|
||||
PdfAction? action,
|
||||
AppearanceStream? normalAppearanceStream,
|
||||
AppearanceStream? rollOverAppearanceStream,
|
||||
AppearanceStream? downAppearanceStream,
|
||||
string? appearanceState,
|
||||
Annotation? inReplyTo)
|
||||
{
|
||||
AnnotationDictionary = annotationDictionary ?? throw new ArgumentNullException(nameof(annotationDictionary));
|
||||
Type = type;
|
||||
|
@ -1,7 +1,6 @@
|
||||
namespace UglyToad.PdfPig.Annotations
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// A border for a PDF <see cref="Annotation"/> object.
|
||||
@ -31,13 +30,12 @@
|
||||
/// <summary>
|
||||
/// The dash pattern for the border lines if provided. Optional.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public IReadOnlyList<double> LineDashPattern { get; }
|
||||
public IReadOnlyList<double>? LineDashPattern { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="AnnotationBorder"/>.
|
||||
/// </summary>
|
||||
public AnnotationBorder(double horizontalCornerRadius, double verticalCornerRadius, double borderWidth, IReadOnlyList<double> lineDashPattern)
|
||||
public AnnotationBorder(double horizontalCornerRadius, double verticalCornerRadius, double borderWidth, IReadOnlyList<double>? lineDashPattern)
|
||||
{
|
||||
HorizontalCornerRadius = horizontalCornerRadius;
|
||||
VerticalCornerRadius = verticalCornerRadius;
|
||||
|
@ -1,9 +1,9 @@
|
||||
namespace UglyToad.PdfPig.Annotations
|
||||
{
|
||||
using Actions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Actions;
|
||||
using Core;
|
||||
using Logging;
|
||||
using Outline.Destinations;
|
||||
@ -46,21 +46,21 @@
|
||||
{
|
||||
var lookupAnnotations = new Dictionary<IndirectReference, Annotation>();
|
||||
|
||||
if (!pageDictionary.TryGet(NameToken.Annots, tokenScanner, out ArrayToken annotationsArray))
|
||||
if (!pageDictionary.TryGet(NameToken.Annots, tokenScanner, out ArrayToken? annotationsArray))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var token in annotationsArray.Data)
|
||||
{
|
||||
if (!DirectObjectFinder.TryGet(token, tokenScanner, out DictionaryToken annotationDictionary))
|
||||
if (!DirectObjectFinder.TryGet(token, tokenScanner, out DictionaryToken? annotationDictionary))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Annotation replyTo = null;
|
||||
if (annotationDictionary.TryGet(NameToken.Irt, out IndirectReferenceToken referencedAnnotation)
|
||||
&& lookupAnnotations.TryGetValue(referencedAnnotation.Data, out var linkedAnnotation))
|
||||
Annotation? replyTo = null;
|
||||
if (annotationDictionary.TryGet(NameToken.Irt, out IndirectReferenceToken? referencedAnnotation)
|
||||
&& lookupAnnotations.TryGetValue(referencedAnnotation!.Data, out var linkedAnnotation))
|
||||
{
|
||||
replyTo = linkedAnnotation;
|
||||
}
|
||||
@ -77,14 +77,14 @@
|
||||
|
||||
var flags = (AnnotationFlags)0;
|
||||
if (annotationDictionary.TryGet(NameToken.F, out var flagsToken) &&
|
||||
DirectObjectFinder.TryGet(flagsToken, tokenScanner, out NumericToken flagsNumericToken))
|
||||
DirectObjectFinder.TryGet(flagsToken, tokenScanner, out NumericToken? flagsNumericToken))
|
||||
{
|
||||
flags = (AnnotationFlags)flagsNumericToken.Int;
|
||||
}
|
||||
|
||||
var border = AnnotationBorder.Default;
|
||||
if (annotationDictionary.TryGet(NameToken.Border, out var borderToken) &&
|
||||
DirectObjectFinder.TryGet(borderToken, tokenScanner, out ArrayToken borderArray)
|
||||
DirectObjectFinder.TryGet(borderToken, tokenScanner, out ArrayToken? borderArray)
|
||||
&& borderArray.Length >= 3)
|
||||
{
|
||||
var horizontal = borderArray.GetNumeric(0).Data;
|
||||
@ -101,7 +101,7 @@
|
||||
}
|
||||
|
||||
var quadPointRectangles = new List<QuadPointsQuadrilateral>();
|
||||
if (annotationDictionary.TryGet(NameToken.Quadpoints, tokenScanner, out ArrayToken quadPointsArray))
|
||||
if (annotationDictionary.TryGet(NameToken.Quadpoints, tokenScanner, out ArrayToken? quadPointsArray))
|
||||
{
|
||||
var values = new List<double>();
|
||||
for (var i = 0; i < quadPointsArray.Length; i++)
|
||||
@ -128,14 +128,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
AppearanceStream normalAppearanceStream = null;
|
||||
AppearanceStream downAppearanceStream = null;
|
||||
AppearanceStream rollOverAppearanceStream = null;
|
||||
AppearanceStream? normalAppearanceStream = null;
|
||||
AppearanceStream? downAppearanceStream = null;
|
||||
AppearanceStream? rollOverAppearanceStream = null;
|
||||
|
||||
if (annotationDictionary.TryGet(NameToken.Ap, out DictionaryToken appearanceDictionary))
|
||||
{
|
||||
// The normal appearance of this annotation
|
||||
if (AppearanceStreamFactory.TryCreate(appearanceDictionary, NameToken.N, tokenScanner, out AppearanceStream stream))
|
||||
if (AppearanceStreamFactory.TryCreate(appearanceDictionary, NameToken.N, tokenScanner, out AppearanceStream? stream))
|
||||
{
|
||||
normalAppearanceStream = stream;
|
||||
}
|
||||
@ -153,7 +153,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
string appearanceState = null;
|
||||
string? appearanceState = null;
|
||||
if (annotationDictionary.TryGet(NameToken.As, out NameToken appearanceStateToken))
|
||||
{
|
||||
appearanceState = appearanceStateToken.Data;
|
||||
@ -185,7 +185,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
internal PdfAction GetAction(DictionaryToken annotationDictionary)
|
||||
internal PdfAction? GetAction(DictionaryToken annotationDictionary)
|
||||
{
|
||||
// If this annotation returns a direct destination, turn it into a GoTo action.
|
||||
if (DestinationProvider.TryGetDestination(annotationDictionary,
|
||||
@ -209,9 +209,9 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
private string GetNamedString(NameToken name, DictionaryToken dictionary)
|
||||
private string? GetNamedString(NameToken name, DictionaryToken dictionary)
|
||||
{
|
||||
string content = null;
|
||||
string? content = null;
|
||||
if (dictionary.TryGet(name, out var contentToken))
|
||||
{
|
||||
if (contentToken is StringToken contentString)
|
||||
@ -222,7 +222,7 @@
|
||||
{
|
||||
content = contentHex.Data;
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(contentToken, tokenScanner, out StringToken indirectContentString))
|
||||
else if (DirectObjectFinder.TryGet(contentToken, tokenScanner, out StringToken? indirectContentString))
|
||||
{
|
||||
content = indirectContentString.Data;
|
||||
}
|
||||
|
@ -12,9 +12,9 @@
|
||||
/// </summary>
|
||||
public class AppearanceStream
|
||||
{
|
||||
private readonly IDictionary<string, StreamToken> appearanceStreamsByState;
|
||||
private readonly IDictionary<string, StreamToken>? appearanceStreamsByState;
|
||||
|
||||
private readonly StreamToken statelessAppearanceStream;
|
||||
private readonly StreamToken? statelessAppearanceStream;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if this appearance stream is stateless, or whether you can get appearances by state.
|
||||
@ -30,7 +30,7 @@
|
||||
/// Constructor for stateless appearance stream
|
||||
/// </summary>
|
||||
/// <param name="streamToken"></param>
|
||||
internal AppearanceStream(StreamToken streamToken)
|
||||
internal AppearanceStream(StreamToken? streamToken)
|
||||
{
|
||||
statelessAppearanceStream = streamToken;
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
namespace UglyToad.PdfPig.Annotations
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Tokenization.Scanner;
|
||||
using Tokens;
|
||||
|
||||
internal static class AppearanceStreamFactory
|
||||
{
|
||||
public static bool TryCreate(DictionaryToken appearanceDictionary, NameToken name, IPdfTokenScanner tokenScanner, out AppearanceStream appearanceStream)
|
||||
public static bool TryCreate(DictionaryToken appearanceDictionary, NameToken name, IPdfTokenScanner tokenScanner, [NotNullWhen(true)] out AppearanceStream? appearanceStream)
|
||||
{
|
||||
if (appearanceDictionary.TryGet(name, out IndirectReferenceToken appearanceReference))
|
||||
{
|
||||
@ -24,7 +25,7 @@
|
||||
stateRef is IndirectReferenceToken appearanceRef)
|
||||
{
|
||||
var streamToken = tokenScanner.Get(appearanceRef.Data)?.Data as StreamToken;
|
||||
dict[state] = streamToken;
|
||||
dict[state] = streamToken!;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,15 +25,15 @@
|
||||
}
|
||||
|
||||
// Must be a link annotation with an action of type /URI.
|
||||
if (!annotation.AnnotationDictionary.TryGet(NameToken.A, pdfScanner, out DictionaryToken actionDictionary)
|
||||
|| !actionDictionary.TryGet(NameToken.S, pdfScanner, out NameToken actionType)
|
||||
if (!annotation.AnnotationDictionary.TryGet(NameToken.A, pdfScanner, out DictionaryToken? actionDictionary)
|
||||
|| !actionDictionary.TryGet(NameToken.S, pdfScanner, out NameToken? actionType)
|
||||
|| actionType != NameToken.Uri)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// (Required) The uniform resource identifier to resolve, encoded in 7-bit ASCII.
|
||||
if (!actionDictionary.TryGet(NameToken.Uri, pdfScanner, out IDataToken<string> uriStringToken))
|
||||
if (!actionDictionary.TryGet(NameToken.Uri, pdfScanner, out IDataToken<string>? uriStringToken))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
namespace UglyToad.PdfPig.Content
|
||||
{
|
||||
using Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Core;
|
||||
using Tokens;
|
||||
using UglyToad.PdfPig.Graphics;
|
||||
|
||||
@ -26,12 +26,12 @@
|
||||
/// The artifact's subtype. Standard values are Header, Footer, and Watermark.
|
||||
/// Additional values may be specified for this entry, provided they comply with the naming conventions.
|
||||
/// </summary>
|
||||
public string SubType { get; }
|
||||
public string? SubType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The artifact's attribute owners.
|
||||
/// </summary>
|
||||
public string AttributeOwners { get; }
|
||||
public string? AttributeOwners { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The artifact's bounding box.
|
||||
@ -64,13 +64,13 @@
|
||||
public bool IsRightAttached => IsAttached(NameToken.Right);
|
||||
|
||||
internal ArtifactMarkedContentElement(int markedContentIdentifier, NameToken tag, DictionaryToken properties,
|
||||
string language,
|
||||
string actualText,
|
||||
string alternateDescription,
|
||||
string expandedForm,
|
||||
string? language,
|
||||
string? actualText,
|
||||
string? alternateDescription,
|
||||
string? expandedForm,
|
||||
ArtifactType artifactType,
|
||||
string subType,
|
||||
string attributeOwners,
|
||||
string? subType,
|
||||
string? attributeOwners,
|
||||
PdfRectangle? boundingBox,
|
||||
IReadOnlyList<NameToken> attached,
|
||||
IReadOnlyList<MarkedContentElement> children,
|
||||
|
@ -79,7 +79,7 @@
|
||||
}
|
||||
|
||||
var rotation = new PageRotationDegrees(pageTreeMembers.Rotation);
|
||||
if (dictionary.TryGet(NameToken.Rotate, PdfScanner, out NumericToken rotateToken))
|
||||
if (dictionary.TryGet(NameToken.Rotate, PdfScanner, out NumericToken? rotateToken))
|
||||
{
|
||||
rotation = new PageRotationDegrees(rotateToken.Int);
|
||||
}
|
||||
@ -94,7 +94,7 @@
|
||||
stackDepth++;
|
||||
}
|
||||
|
||||
if (dictionary.TryGet(NameToken.Resources, PdfScanner, out DictionaryToken resources))
|
||||
if (dictionary.TryGet(NameToken.Resources, PdfScanner, out DictionaryToken? resources))
|
||||
{
|
||||
ResourceStore.LoadResourceDictionary(resources);
|
||||
stackDepth++;
|
||||
@ -177,7 +177,7 @@
|
||||
UserSpaceUnit userSpaceUnit,
|
||||
PageRotationDegrees rotation,
|
||||
TransformationMatrix initialMatrix,
|
||||
IReadOnlyList<byte> contentBytes)
|
||||
IReadOnlyList<byte>? contentBytes)
|
||||
{
|
||||
IReadOnlyList<IGraphicsStateOperation> operations;
|
||||
|
||||
@ -192,7 +192,8 @@
|
||||
ParsingOptions.Logger);
|
||||
}
|
||||
|
||||
return ProcessPage(pageNumber,
|
||||
return ProcessPage(
|
||||
pageNumber,
|
||||
dictionary,
|
||||
namedDestinations,
|
||||
mediaBox,
|
||||
@ -246,7 +247,7 @@
|
||||
{
|
||||
CropBox cropBox;
|
||||
if (dictionary.TryGet(NameToken.CropBox, out var cropBoxObject) &&
|
||||
DirectObjectFinder.TryGet(cropBoxObject, PdfScanner, out ArrayToken cropBoxArray))
|
||||
DirectObjectFinder.TryGet(cropBoxObject, PdfScanner, out ArrayToken? cropBoxArray))
|
||||
{
|
||||
if (cropBoxArray.Length != 4)
|
||||
{
|
||||
@ -275,7 +276,7 @@
|
||||
{
|
||||
MediaBox mediaBox;
|
||||
if (dictionary.TryGet(NameToken.MediaBox, out var mediaBoxObject)
|
||||
&& DirectObjectFinder.TryGet(mediaBoxObject, PdfScanner, out ArrayToken mediaBoxArray))
|
||||
&& DirectObjectFinder.TryGet(mediaBoxObject, PdfScanner, out ArrayToken? mediaBoxArray))
|
||||
{
|
||||
if (mediaBoxArray.Length != 4)
|
||||
{
|
||||
|
@ -3,7 +3,6 @@
|
||||
using System;
|
||||
using Outline.Destinations;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// The root of the document's object hierarchy. Contains references to objects defining the contents,
|
||||
@ -14,7 +13,6 @@
|
||||
/// <summary>
|
||||
/// The catalog dictionary containing assorted information.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DictionaryToken CatalogDictionary { get; }
|
||||
|
||||
internal NamedDestinations NamedDestinations { get; }
|
||||
|
@ -5,7 +5,6 @@
|
||||
using System.Text;
|
||||
using Tokens;
|
||||
using Util;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Metadata for the PDF document.
|
||||
@ -20,59 +19,58 @@
|
||||
/// <summary>
|
||||
/// The underlying document information PDF dictionary from the document.
|
||||
/// </summary>
|
||||
public DictionaryToken DocumentInformationDictionary { get; }
|
||||
public DictionaryToken? DocumentInformationDictionary { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The title of this document if applicable.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Title { get; }
|
||||
public string? Title { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the person who created this document if applicable.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Author { get; }
|
||||
public string? Author { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The subject of this document if applicable.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Subject { get; }
|
||||
public string? Subject { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Any keywords associated with this document if applicable.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Keywords { get; }
|
||||
public string? Keywords { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the application which created the original document before it was converted to PDF if applicable.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Creator { get; }
|
||||
public string? Creator { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the application used to convert the original document to PDF if applicable.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Producer { get; }
|
||||
public string? Producer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The date and time the document was created.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string CreationDate { get; }
|
||||
public string? CreationDate { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The date and time the document was most recently modified.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string ModifiedDate { get; }
|
||||
public string? ModifiedDate { get; }
|
||||
|
||||
internal DocumentInformation(DictionaryToken documentInformationDictionary, string title, string author, string subject, string keywords, string creator, string producer,
|
||||
string creationDate,
|
||||
string modifiedDate)
|
||||
internal DocumentInformation(
|
||||
DictionaryToken? documentInformationDictionary,
|
||||
string? title,
|
||||
string? author,
|
||||
string? subject,
|
||||
string? keywords,
|
||||
string? creator,
|
||||
string? producer,
|
||||
string? creationDate,
|
||||
string? modifiedDate)
|
||||
{
|
||||
DocumentInformationDictionary = documentInformationDictionary ?? new DictionaryToken(new Dictionary<NameToken, IToken>());
|
||||
Title = title;
|
||||
@ -103,6 +101,11 @@
|
||||
/// </summary>
|
||||
public DateTimeOffset? GetCreatedDateTimeOffset()
|
||||
{
|
||||
if (CreationDate is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return DateFormatHelper.TryParseDateTimeOffset(CreationDate, out var result) ? result : default(DateTimeOffset?);
|
||||
}
|
||||
|
||||
@ -111,6 +114,11 @@
|
||||
/// </summary>
|
||||
public DateTimeOffset? GetModifiedDateTimeOffset()
|
||||
{
|
||||
if (ModifiedDate is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return DateFormatHelper.TryParseDateTimeOffset(ModifiedDate, out var result) ? result : default(DateTimeOffset?);
|
||||
}
|
||||
|
||||
@ -122,7 +130,7 @@
|
||||
return representation;
|
||||
}
|
||||
|
||||
private static void AppendPart(string name, string value, StringBuilder builder)
|
||||
private static void AppendPart(string name, string? value, StringBuilder builder)
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
namespace UglyToad.PdfPig.Content
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Core;
|
||||
using Graphics.Colors;
|
||||
using Graphics.Core;
|
||||
@ -85,17 +86,17 @@
|
||||
/// This is not defined where <see cref="IsImageMask"/> is <see langword="true"/> and is optional where the image is JPXEncoded for <see cref="XObjectImage"/>.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
ColorSpaceDetails ColorSpaceDetails { get; }
|
||||
ColorSpaceDetails? ColorSpaceDetails { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the decoded bytes of the image if applicable. For JPEG images and some other types the
|
||||
/// <see cref="RawBytes"/> should be used directly.
|
||||
/// </summary>
|
||||
bool TryGetBytes(out IReadOnlyList<byte> bytes);
|
||||
bool TryGetBytes([NotNullWhen(true)] out IReadOnlyList<byte>? bytes);
|
||||
|
||||
/// <summary>
|
||||
/// Try to convert the image to PNG. Doesn't support conversion of JPG to PNG.
|
||||
/// </summary>
|
||||
bool TryGetPng(out byte[] bytes);
|
||||
bool TryGetPng([NotNullWhen(true)] out byte[]? bytes);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
namespace UglyToad.PdfPig.Content
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Graphics.Colors;
|
||||
using PdfFonts;
|
||||
using System.Collections.Generic;
|
||||
using Tokens;
|
||||
|
||||
/// <summary>
|
||||
@ -24,12 +25,12 @@
|
||||
/// <summary>
|
||||
/// Get the font corresponding to the name.
|
||||
/// </summary>
|
||||
IFont GetFont(NameToken name);
|
||||
IFont? GetFont(NameToken name);
|
||||
|
||||
/// <summary>
|
||||
/// Try getting the XObject corresponding to the name.
|
||||
/// </summary>
|
||||
bool TryGetXObject(NameToken name, out StreamToken stream);
|
||||
bool TryGetXObject(NameToken name, [NotNullWhen(true)] out StreamToken? stream);
|
||||
|
||||
/// <summary>
|
||||
/// Get the extended graphics state dictionary corresponding to the name.
|
||||
@ -49,12 +50,12 @@
|
||||
/// <summary>
|
||||
/// Get the color space details corresponding to the name.
|
||||
/// </summary>
|
||||
ColorSpaceDetails GetColorSpaceDetails(NameToken name, DictionaryToken dictionary);
|
||||
ColorSpaceDetails GetColorSpaceDetails(NameToken? name, DictionaryToken? dictionary);
|
||||
|
||||
/// <summary>
|
||||
/// Get the marked content properties dictionary corresponding to the name.
|
||||
/// </summary>
|
||||
DictionaryToken GetMarkedContentPropertiesDictionary(NameToken name);
|
||||
DictionaryToken? GetMarkedContentPropertiesDictionary(NameToken name);
|
||||
|
||||
/// <summary>
|
||||
/// Get all <see cref="PatternColor"/> as a dictionary. Keys are the <see cref="PatternColor"/> names.
|
||||
|
@ -2,6 +2,7 @@
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Core;
|
||||
using Filters;
|
||||
@ -9,7 +10,6 @@
|
||||
using Graphics.Core;
|
||||
using Tokens;
|
||||
using Images.Png;
|
||||
using UglyToad.PdfPig.Util.JetBrains.Annotations;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
@ -17,7 +17,7 @@
|
||||
/// </summary>
|
||||
public class InlineImage : IPdfImage
|
||||
{
|
||||
private readonly Lazy<IReadOnlyList<byte>> bytesFactory;
|
||||
private readonly Lazy<IReadOnlyList<byte>>? bytesFactory;
|
||||
|
||||
/// <inheritdoc />
|
||||
public PdfRectangle Bounds { get; }
|
||||
@ -41,7 +41,6 @@
|
||||
public bool IsInlineImage { get; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
[NotNull]
|
||||
public DictionaryToken ImageDictionary { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -105,7 +104,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetBytes(out IReadOnlyList<byte> bytes)
|
||||
public bool TryGetBytes([NotNullWhen(true)] out IReadOnlyList<byte>? bytes)
|
||||
{
|
||||
bytes = null;
|
||||
if (bytesFactory is null)
|
||||
@ -119,7 +118,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetPng(out byte[] bytes) => PngFromPdfImageFactory.TryGenerate(this, out bytes);
|
||||
public bool TryGetPng([NotNullWhen(true)] out byte[]? bytes) => PngFromPdfImageFactory.TryGenerate(this, out bytes);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
|
@ -3,7 +3,6 @@
|
||||
using Core;
|
||||
using Graphics.Colors;
|
||||
using PdfFonts;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A glyph or combination of glyphs (characters) drawn by a PDF content stream.
|
||||
@ -55,7 +54,7 @@
|
||||
/// <summary>
|
||||
/// The name of the font.
|
||||
/// </summary>
|
||||
public string FontName => Font?.Name;
|
||||
public string? FontName => Font?.Name;
|
||||
|
||||
/// <summary>
|
||||
/// Details about the font for this letter.
|
||||
|
@ -60,31 +60,32 @@
|
||||
/// <summary>
|
||||
/// The natural language specification.
|
||||
/// </summary>
|
||||
public string Language { get; }
|
||||
public string? Language { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The replacement text.
|
||||
/// </summary>
|
||||
public string ActualText { get; }
|
||||
public string? ActualText { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The alternate description.
|
||||
/// </summary>
|
||||
public string AlternateDescription { get; }
|
||||
public string? AlternateDescription { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The abbreviation expansion text.
|
||||
/// </summary>
|
||||
public string ExpandedForm { get; }
|
||||
public string? ExpandedForm { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="MarkedContentElement"/>.
|
||||
/// </summary>
|
||||
public MarkedContentElement(int markedContentIdentifier, NameToken tag, DictionaryToken properties,
|
||||
string language,
|
||||
string actualText,
|
||||
string alternateDescription,
|
||||
string expandedForm,
|
||||
public MarkedContentElement(int markedContentIdentifier, NameToken tag,
|
||||
DictionaryToken properties,
|
||||
string? language,
|
||||
string? actualText,
|
||||
string? alternateDescription,
|
||||
string? expandedForm,
|
||||
bool isArtifact,
|
||||
IReadOnlyList<MarkedContentElement> children,
|
||||
IReadOnlyList<Letter> letters,
|
||||
|
@ -20,18 +20,18 @@ namespace UglyToad.PdfPig.Content
|
||||
/// <summary>
|
||||
/// The name of the optional content group, suitable for presentation in a viewer application's user interface.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
public string? Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A single name or an array containing any combination of names.
|
||||
/// <para>Default value is 'View'.</para>
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> Intent { get; }
|
||||
public IReadOnlyList<string>? Intent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A usage dictionary describing the nature of the content controlled by the group.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, IToken> Usage { get; }
|
||||
public IReadOnlyDictionary<string, IToken>? Usage { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Underlying <see cref="MarkedContentElement"/>.
|
||||
@ -43,11 +43,11 @@ namespace UglyToad.PdfPig.Content
|
||||
MarkedContent = markedContentElement;
|
||||
|
||||
// Type - Required
|
||||
if (markedContentElement.Properties.TryGet(NameToken.Type, pdfTokenScanner, out NameToken type))
|
||||
if (markedContentElement.Properties.TryGet(NameToken.Type, pdfTokenScanner, out NameToken? type))
|
||||
{
|
||||
Type = type.Data;
|
||||
}
|
||||
else if (markedContentElement.Properties.TryGet(NameToken.Type, pdfTokenScanner, out StringToken typeStr))
|
||||
else if (markedContentElement.Properties.TryGet(NameToken.Type, pdfTokenScanner, out StringToken? typeStr))
|
||||
{
|
||||
Type = typeStr.Data;
|
||||
}
|
||||
@ -60,11 +60,11 @@ namespace UglyToad.PdfPig.Content
|
||||
{
|
||||
case "OCG": // Optional content group dictionary
|
||||
// Name - Required
|
||||
if (markedContentElement.Properties.TryGet(NameToken.Name, pdfTokenScanner, out NameToken name))
|
||||
if (markedContentElement.Properties.TryGet(NameToken.Name, pdfTokenScanner, out NameToken? name))
|
||||
{
|
||||
Name = name.Data;
|
||||
}
|
||||
else if (markedContentElement.Properties.TryGet(NameToken.Name, pdfTokenScanner, out StringToken nameStr))
|
||||
else if (markedContentElement.Properties.TryGet(NameToken.Name, pdfTokenScanner, out StringToken? nameStr))
|
||||
{
|
||||
Name = nameStr.Data;
|
||||
}
|
||||
@ -74,15 +74,15 @@ namespace UglyToad.PdfPig.Content
|
||||
}
|
||||
|
||||
// Intent - Optional
|
||||
if (markedContentElement.Properties.TryGet(NameToken.Intent, pdfTokenScanner, out NameToken intentName))
|
||||
if (markedContentElement.Properties.TryGet(NameToken.Intent, pdfTokenScanner, out NameToken? intentName))
|
||||
{
|
||||
Intent = new string[] { intentName.Data };
|
||||
Intent = [intentName.Data];
|
||||
}
|
||||
else if (markedContentElement.Properties.TryGet(NameToken.Intent, pdfTokenScanner, out StringToken intentStr))
|
||||
else if (markedContentElement.Properties.TryGet(NameToken.Intent, pdfTokenScanner, out StringToken? intentStr))
|
||||
{
|
||||
Intent = new string[] { intentStr.Data };
|
||||
Intent = [intentStr.Data];
|
||||
}
|
||||
else if (markedContentElement.Properties.TryGet(NameToken.Intent, pdfTokenScanner, out ArrayToken intentArray))
|
||||
else if (markedContentElement.Properties.TryGet(NameToken.Intent, pdfTokenScanner, out ArrayToken? intentArray))
|
||||
{
|
||||
List<string> intentList = new List<string>();
|
||||
foreach (var token in intentArray.Data)
|
||||
@ -105,11 +105,11 @@ namespace UglyToad.PdfPig.Content
|
||||
else
|
||||
{
|
||||
// Default value is 'View'.
|
||||
Intent = new string[] { "View" };
|
||||
Intent = ["View"];
|
||||
}
|
||||
|
||||
// Usage - Optional
|
||||
if (markedContentElement.Properties.TryGet(NameToken.Usage, pdfTokenScanner, out DictionaryToken usage))
|
||||
if (markedContentElement.Properties.TryGet(NameToken.Usage, pdfTokenScanner, out DictionaryToken? usage))
|
||||
{
|
||||
this.Usage = usage.Data;
|
||||
}
|
||||
@ -117,25 +117,25 @@ namespace UglyToad.PdfPig.Content
|
||||
|
||||
case "OCMD":
|
||||
// OCGs - Optional
|
||||
if (markedContentElement.Properties.TryGet(NameToken.Ocgs, pdfTokenScanner, out DictionaryToken ocgsD))
|
||||
if (markedContentElement.Properties.TryGet(NameToken.Ocgs, pdfTokenScanner, out DictionaryToken? ocgsD))
|
||||
{
|
||||
// dictionary or array
|
||||
throw new NotImplementedException($"{NameToken.Ocgs}");
|
||||
}
|
||||
else if (markedContentElement.Properties.TryGet(NameToken.Ocgs, pdfTokenScanner, out ArrayToken ocgsA))
|
||||
else if (markedContentElement.Properties.TryGet(NameToken.Ocgs, pdfTokenScanner, out ArrayToken? ocgsA))
|
||||
{
|
||||
// dictionary or array
|
||||
throw new NotImplementedException($"{NameToken.Ocgs}");
|
||||
}
|
||||
|
||||
// P - Optional
|
||||
if (markedContentElement.Properties.TryGet(NameToken.P, pdfTokenScanner, out NameToken p))
|
||||
if (markedContentElement.Properties.TryGet(NameToken.P, pdfTokenScanner, out NameToken? p))
|
||||
{
|
||||
throw new NotImplementedException($"{NameToken.P}");
|
||||
}
|
||||
|
||||
// VE - Optional
|
||||
if (markedContentElement.Properties.TryGet(NameToken.VE, pdfTokenScanner, out ArrayToken ve))
|
||||
if (markedContentElement.Properties.TryGet(NameToken.VE, pdfTokenScanner, out ArrayToken? ve))
|
||||
{
|
||||
throw new NotImplementedException($"{NameToken.VE}");
|
||||
}
|
||||
|
@ -3,15 +3,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using Annotations;
|
||||
using Geometry;
|
||||
using Graphics.Operations;
|
||||
using Tokens;
|
||||
using Util;
|
||||
using Util.JetBrains.Annotations;
|
||||
using Tokenization.Scanner;
|
||||
using Graphics;
|
||||
using System.Linq;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the content and provides access to methods of a single page in the <see cref="PdfDocument"/>.
|
||||
@ -87,7 +86,6 @@
|
||||
/// <summary>
|
||||
/// Access to members whose future locations within the API will change without warning.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public Experimental ExperimentalAccess { get; }
|
||||
|
||||
internal Page(int number, DictionaryToken dictionary, MediaBox mediaBox, CropBox cropBox, PageRotationDegrees rotation, PageContent content,
|
||||
@ -215,12 +213,12 @@
|
||||
// TO DO
|
||||
//var annots = GetAnnotations().ToList();
|
||||
|
||||
return mcesOptional.GroupBy(oc => oc.Name).ToDictionary(g => g.Key, g => g.ToList() as IReadOnlyList<OptionalContentGroupElement>);
|
||||
return mcesOptional.GroupBy(oc => oc.Name).ToDictionary(g => g.Key!, g => (IReadOnlyList<OptionalContentGroupElement>)g.ToList());
|
||||
}
|
||||
|
||||
private void GetOptionalContentsRecursively(IReadOnlyList<MarkedContentElement> markedContentElements, ref List<OptionalContentGroupElement> mcesOptional)
|
||||
private void GetOptionalContentsRecursively(IReadOnlyList<MarkedContentElement>? markedContentElements, ref List<OptionalContentGroupElement> mcesOptional)
|
||||
{
|
||||
if (markedContentElements.Count == 0)
|
||||
if (markedContentElements is null || markedContentElements.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is PageRotationDegrees degrees && Equals(degrees);
|
||||
}
|
||||
|
@ -147,11 +147,11 @@
|
||||
Height = height;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is WidthHeight height &&
|
||||
Math.Round(Width) == Math.Round(height.Width) &&
|
||||
Math.Round(Height) == Math.Round(height.Height);
|
||||
return obj is WidthHeight other &&
|
||||
Math.Round(Width) == Math.Round(other.Width) &&
|
||||
Math.Round(Height) == Math.Round(other.Height);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace UglyToad.PdfPig.Content
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Content
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Tokens;
|
||||
|
@ -4,7 +4,6 @@
|
||||
using System.Collections.Generic;
|
||||
using Core;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// A node in the PDF document's page tree.
|
||||
@ -16,7 +15,6 @@
|
||||
/// <summary>
|
||||
/// The dictionary for this node in the page tree.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DictionaryToken NodeDictionary { get; }
|
||||
|
||||
/// <summary>
|
||||
@ -37,14 +35,12 @@
|
||||
/// <summary>
|
||||
/// The child nodes of this node if <see cref="IsPage"/> is <see langword="false" />
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public IReadOnlyList<PageTreeNode> Children { get; private set; }
|
||||
public IReadOnlyList<PageTreeNode>? Children { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The parent node of this node, unless it is the root node.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public PageTreeNode Parent { get; private set; }
|
||||
public PageTreeNode? Parent { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this node is the root node.
|
||||
@ -93,7 +89,7 @@
|
||||
return $"Page #{PageNumber}: {NodeDictionary}.";
|
||||
}
|
||||
|
||||
return $"Pages ({Children.Count} children): {NodeDictionary}";
|
||||
return $"Pages ({Children?.Count ?? 0} children): {NodeDictionary}";
|
||||
}
|
||||
}
|
||||
}
|
@ -81,17 +81,17 @@
|
||||
{
|
||||
currentNode = pageStack.Pop();
|
||||
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.Resources, pdfScanner, out DictionaryToken resourcesDictionary))
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.Resources, pdfScanner, out DictionaryToken? resourcesDictionary))
|
||||
{
|
||||
pageTreeMembers.ParentResources.Enqueue(resourcesDictionary);
|
||||
}
|
||||
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.MediaBox, pdfScanner, out ArrayToken mediaBox))
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.MediaBox, pdfScanner, out ArrayToken? mediaBox))
|
||||
{
|
||||
pageTreeMembers.MediaBox = new MediaBox(mediaBox.ToRectangle(pdfScanner));
|
||||
}
|
||||
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.Rotate, pdfScanner, out NumericToken rotateToken))
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.Rotate, pdfScanner, out NumericToken? rotateToken))
|
||||
{
|
||||
pageTreeMembers.Rotation = rotateToken.Int;
|
||||
}
|
||||
@ -167,7 +167,7 @@
|
||||
return node;
|
||||
}
|
||||
|
||||
internal PageTreeNode GetPageByReference(IndirectReference reference)
|
||||
internal PageTreeNode? GetPageByReference(IndirectReference reference)
|
||||
{
|
||||
foreach (var page in pagesByNumber)
|
||||
{
|
||||
|
@ -131,7 +131,7 @@
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
if (!current.nodeDictionary.TryGet(NameToken.Kids, pdfTokenScanner, out ArrayToken kids))
|
||||
if (!current.nodeDictionary.TryGet(NameToken.Kids, pdfTokenScanner, out ArrayToken? kids))
|
||||
{
|
||||
if (!isLenientParsing)
|
||||
{
|
||||
@ -148,7 +148,7 @@
|
||||
throw new PdfDocumentFormatException($"Kids array contained invalid entry (must be indirect reference): {kid}.");
|
||||
}
|
||||
|
||||
if (!DirectObjectFinder.TryGet(kidRef, pdfTokenScanner, out DictionaryToken kidDictionaryToken))
|
||||
if (!DirectObjectFinder.TryGet(kidRef, pdfTokenScanner, out DictionaryToken? kidDictionaryToken))
|
||||
{
|
||||
throw new PdfDocumentFormatException($"Could not find dictionary associated with reference in pages kids array: {kidRef}.");
|
||||
}
|
||||
@ -181,7 +181,7 @@
|
||||
action();
|
||||
}
|
||||
|
||||
foreach (var child in firstPage.Children.ToRecursiveOrderList(x => x.Children).Where(child => child.IsPage))
|
||||
foreach (var child in firstPage.Children!.ToRecursiveOrderList(x => x.Children!).Where(child => child.IsPage))
|
||||
{
|
||||
pageNumber.Increment();
|
||||
child.PageNumber = pageNumber.PageCount;
|
||||
@ -194,22 +194,28 @@
|
||||
{
|
||||
var isPage = false;
|
||||
|
||||
if (!nodeDictionary.TryGet(NameToken.Type, pdfTokenScanner, out NameToken type))
|
||||
if (!nodeDictionary.TryGet(NameToken.Type, pdfTokenScanner, out NameToken? type))
|
||||
{
|
||||
if (!isLenientParsing) { throw new PdfDocumentFormatException($"Node in the document pages tree did not define a type: {nodeDictionary}."); }
|
||||
|
||||
if (!nodeDictionary.TryGet(NameToken.Kids, pdfTokenScanner, out ArrayToken _)) { isPage = true; }
|
||||
if (!nodeDictionary.TryGet(NameToken.Kids, pdfTokenScanner, out ArrayToken? _)) { isPage = true; }
|
||||
}
|
||||
else
|
||||
{
|
||||
isPage = type.Equals(NameToken.Page);
|
||||
|
||||
if (!isPage && !type.Equals(NameToken.Pages) && !isLenientParsing) { throw new PdfDocumentFormatException($"Node in the document pages tree defined invalid type: {nodeDictionary}."); }
|
||||
if (!isPage && !type.Equals(NameToken.Pages) && !isLenientParsing)
|
||||
{
|
||||
throw new PdfDocumentFormatException($"Node in the document pages tree defined invalid type: {nodeDictionary}.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!isLenientParsing && !isRoot)
|
||||
{
|
||||
if (!nodeDictionary.TryGet(NameToken.Parent, pdfTokenScanner, out IndirectReferenceToken parentReferenceToken)) { throw new PdfDocumentFormatException($"Could not find parent indirect reference token on pages tree node: {nodeDictionary}."); }
|
||||
if (!nodeDictionary.TryGet(NameToken.Parent, pdfTokenScanner, out IndirectReferenceToken? parentReferenceToken))
|
||||
{
|
||||
throw new PdfDocumentFormatException($"Could not find parent indirect reference token on pages tree node: {nodeDictionary}.");
|
||||
}
|
||||
|
||||
if (!parentReferenceToken.Data.Equals(parentReference)) { throw new PdfDocumentFormatException($"Pages tree node parent reference {parentReferenceToken.Data} did not match actual parent {parentReference}."); }
|
||||
}
|
||||
@ -230,7 +236,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var child in node.Children)
|
||||
foreach (var child in node.Children!)
|
||||
{
|
||||
PopulatePageByNumberDictionary(child, result);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Core;
|
||||
using Graphics.Colors;
|
||||
using Parser.Parts;
|
||||
@ -33,7 +34,7 @@
|
||||
|
||||
private readonly Dictionary<NameToken, PatternColor> patternsProperties = new Dictionary<NameToken, PatternColor>();
|
||||
|
||||
private (NameToken name, IFont font) lastLoadedFont;
|
||||
private (NameToken? name, IFont? font) lastLoadedFont;
|
||||
|
||||
public ResourceStore(IPdfTokenScanner scanner,
|
||||
IFontFactory fontFactory,
|
||||
@ -81,7 +82,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (resourceDictionary.TryGet(NameToken.ExtGState, scanner, out DictionaryToken extGStateDictionaryToken))
|
||||
if (resourceDictionary.TryGet(NameToken.ExtGState, scanner, out DictionaryToken? extGStateDictionaryToken))
|
||||
{
|
||||
foreach (var pair in extGStateDictionaryToken.Data)
|
||||
{
|
||||
@ -92,17 +93,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (resourceDictionary.TryGet(NameToken.ColorSpace, scanner, out DictionaryToken colorSpaceDictionary))
|
||||
if (resourceDictionary.TryGet(NameToken.ColorSpace, scanner, out DictionaryToken? colorSpaceDictionary))
|
||||
{
|
||||
foreach (var nameColorSpacePair in colorSpaceDictionary.Data)
|
||||
{
|
||||
var name = NameToken.Create(nameColorSpacePair.Key);
|
||||
|
||||
if (DirectObjectFinder.TryGet(nameColorSpacePair.Value, scanner, out NameToken colorSpaceName))
|
||||
if (DirectObjectFinder.TryGet(nameColorSpacePair.Value, scanner, out NameToken? colorSpaceName))
|
||||
{
|
||||
namedColorSpaces[name] = new ResourceColorSpace(colorSpaceName);
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(nameColorSpacePair.Value, scanner, out ArrayToken colorSpaceArray))
|
||||
else if (DirectObjectFinder.TryGet(nameColorSpacePair.Value, scanner, out ArrayToken? colorSpaceArray))
|
||||
{
|
||||
if (colorSpaceArray.Length == 0)
|
||||
{
|
||||
@ -125,7 +126,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (resourceDictionary.TryGet(NameToken.Pattern, scanner, out DictionaryToken patternDictionary))
|
||||
if (resourceDictionary.TryGet(NameToken.Pattern, scanner, out DictionaryToken? patternDictionary))
|
||||
{
|
||||
// NB: in PDF, all patterns shall be local to the context in which they are defined.
|
||||
foreach (var namePatternPair in patternDictionary.Data)
|
||||
@ -135,13 +136,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (resourceDictionary.TryGet(NameToken.Properties, scanner, out DictionaryToken markedContentPropertiesList))
|
||||
if (resourceDictionary.TryGet(NameToken.Properties, scanner, out DictionaryToken? markedContentPropertiesList))
|
||||
{
|
||||
foreach (var pair in markedContentPropertiesList.Data)
|
||||
{
|
||||
var key = NameToken.Create(pair.Key);
|
||||
|
||||
if (!DirectObjectFinder.TryGet(pair.Value, scanner, out DictionaryToken namedProperties))
|
||||
if (!DirectObjectFinder.TryGet(pair.Value, scanner, out DictionaryToken? namedProperties))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -150,16 +151,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (resourceDictionary.TryGet(NameToken.Shading, scanner, out DictionaryToken shadingList))
|
||||
if (resourceDictionary.TryGet(NameToken.Shading, scanner, out DictionaryToken? shadingList))
|
||||
{
|
||||
foreach (var pair in shadingList.Data)
|
||||
{
|
||||
var key = NameToken.Create(pair.Key);
|
||||
if (DirectObjectFinder.TryGet(pair.Value, scanner, out DictionaryToken namedPropertiesDictionary))
|
||||
if (DirectObjectFinder.TryGet(pair.Value, scanner, out DictionaryToken? namedPropertiesDictionary))
|
||||
{
|
||||
shadingsProperties[key] = ShadingParser.Create(namedPropertiesDictionary, scanner, this, filterProvider);
|
||||
}
|
||||
else if (DirectObjectFinder.TryGet(pair.Value, scanner, out StreamToken namedPropertiesStream))
|
||||
else if (DirectObjectFinder.TryGet(pair.Value, scanner, out StreamToken? namedPropertiesStream))
|
||||
{
|
||||
// Shading types 4 to 7 shall be defined by a stream containing descriptive data characterizing
|
||||
// the shading's gradient fill.
|
||||
@ -229,14 +230,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
public IFont GetFont(NameToken name)
|
||||
public IFont? GetFont(NameToken name)
|
||||
{
|
||||
if (lastLoadedFont.name == name)
|
||||
{
|
||||
return lastLoadedFont.font;
|
||||
}
|
||||
|
||||
IFont font;
|
||||
IFont? font;
|
||||
if (currentResourceState.TryGetValue(name, out var reference))
|
||||
{
|
||||
loadedFonts.TryGetValue(reference, out font);
|
||||
@ -255,7 +256,7 @@
|
||||
{
|
||||
lastLoadedFont = (null, null);
|
||||
|
||||
if (!DirectObjectFinder.TryGet(fontReferenceToken, scanner, out DictionaryToken fontDictionaryToken))
|
||||
if (!DirectObjectFinder.TryGet(fontReferenceToken, scanner, out DictionaryToken? fontDictionaryToken))
|
||||
{
|
||||
throw new PdfDocumentFormatException($"The requested font reference token {fontReferenceToken} wasn't a font.");
|
||||
}
|
||||
@ -265,7 +266,7 @@
|
||||
return font;
|
||||
}
|
||||
|
||||
public bool TryGetNamedColorSpace(NameToken name, out ResourceColorSpace namedToken)
|
||||
public bool TryGetNamedColorSpace(NameToken? name, out ResourceColorSpace namedToken)
|
||||
{
|
||||
namedToken = default(ResourceColorSpace);
|
||||
|
||||
@ -284,13 +285,10 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
public ColorSpaceDetails GetColorSpaceDetails(NameToken name, DictionaryToken dictionary)
|
||||
{
|
||||
if (dictionary is null)
|
||||
{
|
||||
dictionary = new DictionaryToken(new Dictionary<NameToken, IToken>());
|
||||
}
|
||||
|
||||
public ColorSpaceDetails GetColorSpaceDetails(NameToken? name, DictionaryToken? dictionary)
|
||||
{
|
||||
dictionary ??= new DictionaryToken(new Dictionary<NameToken, IToken>());
|
||||
|
||||
// Null color space for images
|
||||
if (name is null)
|
||||
{
|
||||
@ -299,12 +297,12 @@
|
||||
|
||||
if (name.TryMapToColorSpace(out ColorSpace colorspaceActual))
|
||||
{
|
||||
// TODO - We need to find a way to store profile that have an actual dictionnary, e.g. ICC profiles - without parsing them again
|
||||
// TODO - We need to find a way to store profile that have an actual dictionary, e.g. ICC profiles - without parsing them again
|
||||
return ColorSpaceDetailsParser.GetColorSpaceDetails(colorspaceActual, dictionary, scanner, this, filterProvider);
|
||||
}
|
||||
|
||||
// Named color spaces
|
||||
if (loadedNamedColorSpaceDetails.TryGetValue(name, out ColorSpaceDetails csdLoaded))
|
||||
if (loadedNamedColorSpaceDetails.TryGetValue(name, out ColorSpaceDetails? csdLoaded))
|
||||
{
|
||||
return csdLoaded;
|
||||
}
|
||||
@ -327,7 +325,7 @@
|
||||
throw new InvalidOperationException($"Could not find color space for token '{name}'.");
|
||||
}
|
||||
|
||||
public bool TryGetXObject(NameToken name, out StreamToken stream)
|
||||
public bool TryGetXObject(NameToken name, [NotNullWhen(true)] out StreamToken? stream)
|
||||
{
|
||||
stream = null;
|
||||
if (!currentResourceState.TryGetValue(name, out var indirectReference))
|
||||
@ -343,7 +341,7 @@
|
||||
return extendedGraphicsStates[name];
|
||||
}
|
||||
|
||||
public DictionaryToken GetMarkedContentPropertiesDictionary(NameToken name)
|
||||
public DictionaryToken? GetMarkedContentPropertiesDictionary(NameToken name)
|
||||
{
|
||||
return markedContentProperties.TryGetValue(name, out var result) ? result : null;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
||||
/// <summary>
|
||||
/// The name of the font for the word.
|
||||
/// </summary>
|
||||
public string FontName { get; }
|
||||
public string? FontName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The letters contained in the word.
|
||||
|
@ -8,7 +8,6 @@
|
||||
using Filters;
|
||||
using Tokenization.Scanner;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Wraps an XML based Extensible Metadata Platform (XMP) document. These XML documents are embedded in PDFs to provide metadata
|
||||
@ -22,7 +21,6 @@
|
||||
/// <summary>
|
||||
/// The underlying <see cref="StreamToken"/> for this metadata.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public StreamToken MetadataStreamToken { get; }
|
||||
|
||||
internal XmpMetadata(StreamToken stream, ILookupFilterProvider filterProvider, IPdfTokenScanner pdfTokenScanner)
|
||||
|
@ -3,7 +3,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Core;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// The cross-reference table contains information that enables random access to PDF objects within the file by object number
|
||||
@ -19,7 +18,6 @@
|
||||
/// <summary>
|
||||
/// The corresponding byte offset for each keyed object in this document.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public IReadOnlyDictionary<IndirectReference, long> ObjectOffsets => objectOffsets;
|
||||
|
||||
/// <summary>
|
||||
@ -30,14 +28,12 @@
|
||||
/// <summary>
|
||||
/// The trailer dictionary.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public TrailerDictionary Trailer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The byte offsets of each cross-reference table or stream in this document and the previous
|
||||
/// table or stream they link to if applicable.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public IReadOnlyList<CrossReferenceOffset> CrossReferenceOffsets { get; }
|
||||
|
||||
internal CrossReferenceTable(CrossReferenceType type, IReadOnlyDictionary<IndirectReference, long> objectOffsets,
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
public long Previous { get; set; }
|
||||
|
||||
public DictionaryToken Dictionary { get; set; }
|
||||
public DictionaryToken? Dictionary { get; set; }
|
||||
|
||||
public CrossReferenceType XRefType { get; set; }
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
public CrossReferenceTablePart Build()
|
||||
{
|
||||
return new CrossReferenceTablePart(objects, Offset, Previous, Dictionary, XRefType, TiedToPreviousAtOffset);
|
||||
return new CrossReferenceTablePart(objects, Offset, Previous, Dictionary!, XRefType, TiedToPreviousAtOffset);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,10 +3,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Core;
|
||||
using Exceptions;
|
||||
using Tokens;
|
||||
using Util;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Contains information for interpreting the cross-reference table.
|
||||
@ -47,8 +45,7 @@
|
||||
/// <summary>
|
||||
/// The document's encryption dictionary.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public IToken EncryptionToken { get; }
|
||||
public IToken? EncryptionToken { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TrailerDictionary"/>.
|
||||
|
@ -1,9 +1,9 @@
|
||||
namespace UglyToad.PdfPig.Encryption
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Exceptions;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
internal class EncryptionDictionary
|
||||
{
|
||||
@ -15,21 +15,19 @@
|
||||
|
||||
public int Revision { get; }
|
||||
|
||||
public byte[] OwnerBytes { get; }
|
||||
public byte[]? OwnerBytes { get; }
|
||||
|
||||
public byte[] UserBytes { get; }
|
||||
public byte[]? UserBytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Required if <see cref="Revision"/> is 5 or above. A 32-byte string, based on the owner and user passwords that is used in computing the encryption key.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public byte[] OwnerEncryptionBytes { get; }
|
||||
public byte[]? OwnerEncryptionBytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Required if <see cref="Revision"/> is 5 or above. A 32-byte string, based on the user password that is used in computing the encryption key.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public byte[] UserEncryptionBytes { get; }
|
||||
public byte[]? UserEncryptionBytes { get; }
|
||||
|
||||
public UserAccessPermissions UserAccessPermissions { get; }
|
||||
|
||||
@ -42,10 +40,10 @@
|
||||
public EncryptionDictionary(string filter, EncryptionAlgorithmCode encryptionAlgorithmCode,
|
||||
int? keyLength,
|
||||
int revision,
|
||||
byte[] ownerBytes,
|
||||
byte[] userBytes,
|
||||
byte[] ownerEncryptionBytes,
|
||||
byte[] userEncryptionBytes,
|
||||
byte[]? ownerBytes,
|
||||
byte[]? userBytes,
|
||||
byte[]? ownerEncryptionBytes,
|
||||
byte[]? userEncryptionBytes,
|
||||
UserAccessPermissions userAccessPermissions,
|
||||
DictionaryToken dictionary,
|
||||
bool encryptMetadata)
|
||||
@ -63,7 +61,7 @@
|
||||
EncryptMetadata = encryptMetadata;
|
||||
}
|
||||
|
||||
public bool TryGetCryptHandler(out CryptHandler cryptHandler)
|
||||
public bool TryGetCryptHandler([NotNullWhen(true)] out CryptHandler? cryptHandler)
|
||||
{
|
||||
cryptHandler = null;
|
||||
|
||||
|
@ -20,25 +20,25 @@
|
||||
|
||||
var code = EncryptionAlgorithmCode.Unrecognized;
|
||||
|
||||
if (encryptionDictionary.TryGetOptionalTokenDirect(NameToken.V, tokenScanner, out NumericToken vNum))
|
||||
if (encryptionDictionary.TryGetOptionalTokenDirect(NameToken.V, tokenScanner, out NumericToken? vNum))
|
||||
{
|
||||
code = (EncryptionAlgorithmCode) vNum.Int;
|
||||
}
|
||||
|
||||
var length = default(int?);
|
||||
|
||||
if (encryptionDictionary.TryGetOptionalTokenDirect(NameToken.Length, tokenScanner, out NumericToken lengthToken))
|
||||
if (encryptionDictionary.TryGetOptionalTokenDirect(NameToken.Length, tokenScanner, out NumericToken? lengthToken))
|
||||
{
|
||||
length = lengthToken.Int;
|
||||
}
|
||||
|
||||
var revision = default(int);
|
||||
if (encryptionDictionary.TryGetOptionalTokenDirect(NameToken.R, tokenScanner, out NumericToken revisionToken))
|
||||
if (encryptionDictionary.TryGetOptionalTokenDirect(NameToken.R, tokenScanner, out NumericToken? revisionToken))
|
||||
{
|
||||
revision = revisionToken.Int;
|
||||
}
|
||||
|
||||
byte[] ownerBytes = null;
|
||||
byte[]? ownerBytes = null;
|
||||
if (encryptionDictionary.TryGet(NameToken.O, out IToken ownerToken))
|
||||
{
|
||||
if (ownerToken is StringToken ownerString)
|
||||
@ -51,7 +51,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
byte[] userBytes = null;
|
||||
byte[]? userBytes = null;
|
||||
if (encryptionDictionary.TryGet(NameToken.U, out IToken userToken))
|
||||
{
|
||||
if (userToken is StringToken userString)
|
||||
@ -66,22 +66,25 @@
|
||||
|
||||
var access = default(UserAccessPermissions);
|
||||
|
||||
if (encryptionDictionary.TryGetOptionalTokenDirect(NameToken.P, tokenScanner, out NumericToken accessToken))
|
||||
if (encryptionDictionary.TryGetOptionalTokenDirect(NameToken.P, tokenScanner, out NumericToken? accessToken))
|
||||
{
|
||||
// This can be bigger than an integer.
|
||||
access = (UserAccessPermissions) accessToken.Long;
|
||||
}
|
||||
|
||||
byte[] userEncryptionBytes = null, ownerEncryptionBytes = null;
|
||||
byte[]? userEncryptionBytes = null;
|
||||
byte[]? ownerEncryptionBytes = null;
|
||||
if (revision >= 5)
|
||||
{
|
||||
ownerEncryptionBytes = GetEncryptionBytesOrDefault(encryptionDictionary, tokenScanner, false);
|
||||
userEncryptionBytes = GetEncryptionBytesOrDefault(encryptionDictionary, tokenScanner, true);
|
||||
}
|
||||
|
||||
encryptionDictionary.TryGetOptionalTokenDirect(NameToken.EncryptMetaData, tokenScanner, out BooleanToken encryptMetadata);
|
||||
encryptionDictionary.TryGetOptionalTokenDirect(NameToken.EncryptMetaData, tokenScanner, out BooleanToken? encryptMetadata);
|
||||
|
||||
return new EncryptionDictionary(filter.Data, code, length, revision, ownerBytes, userBytes,
|
||||
return new EncryptionDictionary(filter.Data, code, length, revision,
|
||||
ownerBytes,
|
||||
userBytes,
|
||||
ownerEncryptionBytes,
|
||||
userEncryptionBytes,
|
||||
access,
|
||||
@ -89,15 +92,15 @@
|
||||
encryptMetadata?.Data ?? true);
|
||||
}
|
||||
|
||||
private static byte[] GetEncryptionBytesOrDefault(DictionaryToken encryptionDictionary, IPdfTokenScanner tokenScanner, bool isUser)
|
||||
private static byte[]? GetEncryptionBytesOrDefault(DictionaryToken encryptionDictionary, IPdfTokenScanner tokenScanner, bool isUser)
|
||||
{
|
||||
var name = isUser ? NameToken.Ue : NameToken.Oe;
|
||||
if (encryptionDictionary.TryGet(name, tokenScanner, out StringToken stringToken))
|
||||
if (encryptionDictionary.TryGet(name, tokenScanner, out StringToken? stringToken))
|
||||
{
|
||||
return OtherEncodings.StringAsLatin1Bytes(stringToken.Data);
|
||||
}
|
||||
|
||||
if (encryptionDictionary.TryGet(name, tokenScanner, out HexToken hexToken))
|
||||
if (encryptionDictionary.TryGet(name, tokenScanner, out HexToken? hexToken))
|
||||
{
|
||||
return hexToken.Bytes.ToArray();
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace UglyToad.PdfPig.Encryption
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Encryption
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -11,7 +13,6 @@
|
||||
using Exceptions;
|
||||
using Tokens;
|
||||
using Util;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
internal sealed class EncryptionHandler : IEncryptionHandler
|
||||
{
|
||||
@ -28,22 +29,16 @@
|
||||
];
|
||||
|
||||
private readonly HashSet<IndirectReference> previouslyDecrypted = new HashSet<IndirectReference>();
|
||||
|
||||
[CanBeNull]
|
||||
private readonly EncryptionDictionary encryptionDictionary;
|
||||
|
||||
[CanBeNull]
|
||||
private readonly CryptHandler cryptHandler;
|
||||
|
||||
private readonly byte[] encryptionKey;
|
||||
|
||||
private readonly bool useAes;
|
||||
|
||||
public EncryptionHandler(EncryptionDictionary encryptionDictionary, TrailerDictionary trailerDictionary, IReadOnlyList<string> passwords)
|
||||
{
|
||||
this.encryptionDictionary = encryptionDictionary;
|
||||
|
||||
passwords ??= new[] { string.Empty };
|
||||
passwords ??= [string.Empty];
|
||||
|
||||
if (!passwords.Contains(string.Empty))
|
||||
{
|
||||
@ -268,7 +263,7 @@
|
||||
{
|
||||
// 5. (Revision 2 only) Decrypt the value of the encryption dictionary's owner entry,
|
||||
// using an RC4 encryption function with the encryption key computed in step 1 - 4.
|
||||
userPassword = RC4.Encrypt(key, encryptionDictionary.OwnerBytes);
|
||||
userPassword = RC4.Encrypt(key, encryptionDictionary.OwnerBytes!);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -282,12 +277,12 @@
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
output = encryptionDictionary.OwnerBytes;
|
||||
output = encryptionDictionary.OwnerBytes!;
|
||||
}
|
||||
|
||||
// Decrypt the value of the encryption dictionary's owner entry (first iteration)
|
||||
// or the output from the previous iteration using an RC4 encryption function.
|
||||
output = RC4.Encrypt(keyIter, output);
|
||||
output = RC4.Encrypt(keyIter, output!);
|
||||
}
|
||||
|
||||
userPassword = output;
|
||||
@ -648,14 +643,14 @@
|
||||
|
||||
if (encryptionDictionary.Revision == 6)
|
||||
{
|
||||
intermediateKey = ComputeStupidIsoHash(password, ownerKeySalt, encryptionDictionary.UserBytes);
|
||||
intermediateKey = ComputeStupidIsoHash(password, ownerKeySalt, encryptionDictionary.UserBytes!);
|
||||
}
|
||||
else
|
||||
{
|
||||
intermediateKey = ComputeSha256Hash(password, ownerKeySalt, encryptionDictionary.UserBytes);
|
||||
intermediateKey = ComputeSha256Hash(password, ownerKeySalt, encryptionDictionary.UserBytes!);
|
||||
}
|
||||
|
||||
encryptedFileKey = encryptionDictionary.OwnerEncryptionBytes;
|
||||
encryptedFileKey = encryptionDictionary.OwnerEncryptionBytes!;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -11,7 +11,7 @@
|
||||
[Serializable]
|
||||
public class PdfDocumentEncryptedException : Exception
|
||||
{
|
||||
internal EncryptionDictionary Dictionary { get; }
|
||||
internal EncryptionDictionary? Dictionary { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public PdfDocumentEncryptedException()
|
||||
|
@ -10,7 +10,7 @@
|
||||
///
|
||||
/// Ported from https://github.com/apache/pdfbox/blob/e644c29279e276bde14ce7a33bdeef0cb1001b3e/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxDecoderStream.java
|
||||
/// </summary>
|
||||
internal class CcittFaxDecoderStream : StreamWrapper
|
||||
internal sealed class CcittFaxDecoderStream : StreamWrapper
|
||||
{
|
||||
// See TIFF 6.0 Specification, Section 10: "Modified Huffman Compression", page 43.
|
||||
|
||||
@ -450,8 +450,8 @@
|
||||
|
||||
private class Node
|
||||
{
|
||||
public Node Left { get; set; }
|
||||
public Node Right { get; set; }
|
||||
public Node? Left { get; set; }
|
||||
public Node? Right { get; set; }
|
||||
|
||||
public int Value { get; set; }
|
||||
|
||||
@ -472,7 +472,7 @@
|
||||
|
||||
public Node Walk(bool next)
|
||||
{
|
||||
return next ? Right : Left;
|
||||
return next ? Right! : Left!;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace UglyToad.PdfPig.Filters
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Filters
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -10,7 +12,7 @@
|
||||
/// The LZW (Lempel-Ziv-Welch) filter is a variable-length, adaptive compression method
|
||||
/// that has been adopted as one of the standard compression methods in the Tag Image File Format (TIFF) standard.
|
||||
/// </summary>
|
||||
internal class LzwFilter : IFilter
|
||||
internal sealed class LzwFilter : IFilter
|
||||
{
|
||||
private const int DefaultColors = 1;
|
||||
private const int DefaultBitsPerComponent = 8;
|
||||
@ -146,7 +148,7 @@
|
||||
|
||||
for (var i = 0; i < 256; i++)
|
||||
{
|
||||
table[i] = new[] { (byte)i };
|
||||
table[i] = [(byte)i];
|
||||
}
|
||||
|
||||
table[ClearTable] = null;
|
||||
|
@ -12,12 +12,12 @@
|
||||
/// <summary>
|
||||
/// The function dictionary.
|
||||
/// </summary>
|
||||
public DictionaryToken FunctionDictionary { get; }
|
||||
public DictionaryToken? FunctionDictionary { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The function stream.
|
||||
/// </summary>
|
||||
public StreamToken FunctionStream { get; }
|
||||
public StreamToken? FunctionStream { get; }
|
||||
|
||||
private int numberOfInputValues = -1;
|
||||
private int numberOfOutputValues = -1;
|
||||
@ -25,7 +25,7 @@
|
||||
/// <summary>
|
||||
/// This class represents a function in a PDF document.
|
||||
/// </summary>
|
||||
public PdfFunction(DictionaryToken function, ArrayToken domain, ArrayToken range)
|
||||
public PdfFunction(DictionaryToken function, ArrayToken domain, ArrayToken? range)
|
||||
{
|
||||
FunctionDictionary = function;
|
||||
DomainValues = domain;
|
||||
@ -35,7 +35,7 @@
|
||||
/// <summary>
|
||||
/// This class represents a function in a PDF document.
|
||||
/// </summary>
|
||||
public PdfFunction(StreamToken function, ArrayToken domain, ArrayToken range)
|
||||
public PdfFunction(StreamToken function, ArrayToken domain, ArrayToken? range)
|
||||
{
|
||||
FunctionStream = function;
|
||||
DomainValues = domain;
|
||||
@ -58,7 +58,7 @@
|
||||
/// Returns the function's dictionary. If <see cref="FunctionDictionary"/> is defined, it will be returned.
|
||||
/// If not, the <see cref="FunctionStream"/>'s StreamDictionary will be returned.
|
||||
/// </summary>
|
||||
public DictionaryToken GetDictionary()
|
||||
public DictionaryToken? GetDictionary()
|
||||
{
|
||||
if (FunctionStream != null)
|
||||
{
|
||||
@ -106,7 +106,7 @@
|
||||
/// <returns>The range for this component.</returns>
|
||||
public PdfRange GetRangeForOutput(int n)
|
||||
{
|
||||
return new PdfRange(RangeValues.Data.OfType<NumericToken>().Select(t => t.Double), n);
|
||||
return new PdfRange(RangeValues!.Data.OfType<NumericToken>().Select(t => t.Double), n);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -154,7 +154,7 @@
|
||||
/// Returns all ranges for the output values as <see cref="ArrayToken"/>. Required for type 0 and type 4 functions.
|
||||
/// </summary>
|
||||
/// <returns>the ranges array.</returns>
|
||||
protected ArrayToken RangeValues { get; }
|
||||
protected ArrayToken? RangeValues { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns all domains for the input values as <see cref="ArrayToken"/>. Required for all function types.
|
||||
@ -169,7 +169,7 @@
|
||||
/// <returns>the clipped values</returns>
|
||||
protected double[] ClipToRange(double[] inputValues)
|
||||
{
|
||||
ArrayToken rangesArray = RangeValues;
|
||||
ArrayToken rangesArray = RangeValues!;
|
||||
double[] result;
|
||||
if (rangesArray != null && rangesArray.Length > 0)
|
||||
{
|
||||
|
@ -12,7 +12,7 @@
|
||||
/// <summary>
|
||||
/// The samples of the function.
|
||||
/// </summary>
|
||||
private int[][] samples;
|
||||
private int[][]? samples;
|
||||
|
||||
/// <summary>
|
||||
/// Stitching function
|
||||
@ -262,7 +262,7 @@
|
||||
ArrayToken sizes = Size;
|
||||
for (int i = 0; i < nIn; i++)
|
||||
{
|
||||
arraySize *= (sizes[i] as NumericToken).Int;
|
||||
arraySize *= ((NumericToken)sizes[i]).Int;
|
||||
}
|
||||
samples = new int[arraySize][];
|
||||
int bitsPerSample = BitsPerSample;
|
||||
@ -270,7 +270,7 @@
|
||||
// PDF spec 1.7 p.171:
|
||||
// Each sample value is represented as a sequence of BitsPerSample bits.
|
||||
// Successive values are adjacent in the bit stream; there is no padding at byte boundaries.
|
||||
var bits = new BitArray(FunctionStream.Data.ToArray());
|
||||
var bits = new BitArray(FunctionStream!.Data.ToArray());
|
||||
|
||||
for (int i = 0; i < arraySize; i++)
|
||||
{
|
||||
@ -311,10 +311,9 @@
|
||||
for (int i = 0; i < numberOfInputValues; i++)
|
||||
{
|
||||
PdfRange domain = GetDomainForInput(i);
|
||||
PdfRange? encodeValues = GetEncodeForParameter(i);
|
||||
PdfRange encodeValues = GetEncodeForParameter(i)!.Value;
|
||||
input[i] = ClipToRange(input[i], domain.Min, domain.Max);
|
||||
input[i] = Interpolate(input[i], domain.Min, domain.Max,
|
||||
encodeValues.Value.Min, encodeValues.Value.Max);
|
||||
input[i] = Interpolate(input[i], domain.Min, domain.Max, encodeValues.Min, encodeValues.Max);
|
||||
input[i] = ClipToRange(input[i], 0, sizeValues[i] - 1);
|
||||
inputPrev[i] = (int)Math.Floor(input[i]);
|
||||
inputNext[i] = (int)Math.Ceiling(input[i]);
|
||||
|
@ -11,7 +11,7 @@
|
||||
/// <summary>
|
||||
/// Exponential interpolation function
|
||||
/// </summary>
|
||||
internal PdfFunctionType2(DictionaryToken function, ArrayToken domain, ArrayToken range, ArrayToken c0, ArrayToken c1, double n)
|
||||
internal PdfFunctionType2(DictionaryToken function, ArrayToken domain, ArrayToken? range, ArrayToken c0, ArrayToken c1, double n)
|
||||
: base(function, domain, range)
|
||||
{
|
||||
C0 = c0;
|
||||
@ -19,7 +19,7 @@
|
||||
N = n;
|
||||
}
|
||||
|
||||
internal PdfFunctionType2(StreamToken function, ArrayToken domain, ArrayToken range, ArrayToken c0, ArrayToken c1, double n)
|
||||
internal PdfFunctionType2(StreamToken function, ArrayToken domain, ArrayToken? range, ArrayToken c0, ArrayToken c1, double n)
|
||||
: base(function, domain, range)
|
||||
{
|
||||
C0 = c0;
|
||||
|
@ -17,7 +17,7 @@
|
||||
/// <summary>
|
||||
/// Stitching function
|
||||
/// </summary>
|
||||
internal PdfFunctionType3(DictionaryToken function, ArrayToken domain, ArrayToken range, IReadOnlyList<PdfFunction> functionsArray, ArrayToken bounds, ArrayToken encode)
|
||||
internal PdfFunctionType3(DictionaryToken function, ArrayToken domain, ArrayToken? range, IReadOnlyList<PdfFunction> functionsArray, ArrayToken bounds, ArrayToken encode)
|
||||
: base(function, domain, range)
|
||||
{
|
||||
if (functionsArray is null || functionsArray.Count == 0)
|
||||
@ -59,7 +59,7 @@
|
||||
// This function is known as a "stitching" function. Based on the input, it decides which child function to call.
|
||||
// All functions in the array are 1-value-input functions
|
||||
// See PDF Reference section 3.9.3.
|
||||
PdfFunction function = null;
|
||||
PdfFunction? function = null;
|
||||
double x = input[0];
|
||||
PdfRange domain = GetDomainForInput(0);
|
||||
// clip input value to domain
|
||||
|
@ -20,7 +20,7 @@
|
||||
internal PdfFunctionType4(StreamToken function, ArrayToken domain, ArrayToken range)
|
||||
: base(function, domain, range)
|
||||
{
|
||||
byte[] bytes = FunctionStream.Data.ToArray();
|
||||
byte[] bytes = FunctionStream!.Data.ToArray();
|
||||
string str = OtherEncodings.Iso88591.GetString(bytes);
|
||||
this.instructions = InstructionSequenceBuilder.Parse(str);
|
||||
}
|
||||
|
@ -70,6 +70,8 @@
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
using System;
|
||||
|
@ -73,6 +73,7 @@
|
||||
|
||||
//use_lines: Enables open path clipping. Adds a very minor cost to performance.
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
|
@ -123,7 +123,7 @@ namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
return !(val1 == val2);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (!(obj is ClipperInt128 i128))
|
||||
{
|
||||
|
@ -69,6 +69,9 @@
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
@ -69,6 +69,9 @@
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperJoin
|
||||
|
@ -69,6 +69,9 @@
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperLocalMinima
|
||||
|
@ -69,6 +69,9 @@
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperMaxima
|
||||
|
@ -69,6 +69,9 @@
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperOutPt
|
||||
|
@ -69,6 +69,9 @@
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -117,7 +117,7 @@ namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
|
||||
public static bool operator !=(ClipperIntPoint a, ClipperIntPoint b) => a.X != b.X || a.Y != b.Y;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
|
@ -69,6 +69,9 @@
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
@ -69,6 +69,9 @@
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperScanbeam
|
||||
|
@ -69,6 +69,9 @@
|
||||
* Code modified for PdfPig *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Geometry.ClipperLibrary
|
||||
{
|
||||
internal class ClipperTEdge
|
||||
|
@ -24,7 +24,7 @@
|
||||
/// <summary>
|
||||
/// Generates the result of applying a clipping path to another path.
|
||||
/// </summary>
|
||||
public static PdfPath Clip(this PdfPath clipping, PdfPath subject, ILog? log = null)
|
||||
public static PdfPath? Clip(this PdfPath clipping, PdfPath subject, ILog? log = null)
|
||||
{
|
||||
if (clipping is null)
|
||||
{
|
||||
|
@ -741,12 +741,12 @@
|
||||
/// The intersection of the line formed by <paramref name="pl1"/> and <paramref name="pl2"/>
|
||||
/// intersects the rectangle.
|
||||
/// </summary>
|
||||
private static PdfPoint[] Intersect(PdfRectangle rectangle, PdfPoint pl1, PdfPoint pl2)
|
||||
private static PdfPoint[]? Intersect(PdfRectangle rectangle, PdfPoint pl1, PdfPoint pl2)
|
||||
{
|
||||
var clipper = new Clipper();
|
||||
clipper.AddPath(rectangle.ToClipperPolygon().ToList(), ClipperPolyType.Clip, true);
|
||||
|
||||
clipper.AddPath(new List<ClipperIntPoint>() { pl1.ToClipperIntPoint(), pl2.ToClipperIntPoint() }, ClipperPolyType.Subject, false);
|
||||
clipper.AddPath([pl1.ToClipperIntPoint(), pl2.ToClipperIntPoint()], ClipperPolyType.Subject, false);
|
||||
|
||||
var solutions = new ClipperPolyTree();
|
||||
if (clipper.Execute(ClipperClipType.Intersection, solutions))
|
||||
@ -759,11 +759,11 @@
|
||||
{
|
||||
var solution = solutions.Children[0];
|
||||
|
||||
return new[]
|
||||
{
|
||||
return
|
||||
[
|
||||
new PdfPoint(solution.Contour[0].X / ClippingExtensions.Factor, solution.Contour[0].Y / ClippingExtensions.Factor),
|
||||
new PdfPoint(solution.Contour[1].X / ClippingExtensions.Factor, solution.Contour[1].Y / ClippingExtensions.Factor)
|
||||
};
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -906,7 +906,7 @@
|
||||
/// Get the t values that are the intersections of the line and the curve.
|
||||
/// </summary>
|
||||
/// <returns>List of t values where the <see cref="BezierCurve"/> and the <see cref="PdfLine"/> intersect.</returns>
|
||||
public static double[] IntersectT(this BezierCurve bezierCurve, PdfLine line)
|
||||
public static double[]? IntersectT(this BezierCurve bezierCurve, PdfLine line)
|
||||
{
|
||||
return IntersectT(bezierCurve, line.Point1, line.Point2);
|
||||
}
|
||||
@ -915,12 +915,12 @@
|
||||
/// Get the t values that are the intersections of the line and the curve.
|
||||
/// </summary>
|
||||
/// <returns>List of t values where the <see cref="BezierCurve"/> and the <see cref="Line"/> intersect.</returns>
|
||||
public static double[] IntersectT(this BezierCurve bezierCurve, Line line)
|
||||
public static double[]? IntersectT(this BezierCurve bezierCurve, Line line)
|
||||
{
|
||||
return IntersectT(bezierCurve, line.From, line.To);
|
||||
}
|
||||
|
||||
private static double[] IntersectT(BezierCurve bezierCurve, PdfPoint p1, PdfPoint p2)
|
||||
private static double[]? IntersectT(BezierCurve bezierCurve, PdfPoint p1, PdfPoint p2)
|
||||
{
|
||||
// if the bounding boxes do not intersect, they cannot intersect
|
||||
var bezierBbox = bezierCurve.GetBoundingRectangle();
|
||||
|
@ -1,5 +1,10 @@
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
using Colors;
|
||||
using Content;
|
||||
using Core;
|
||||
@ -10,10 +15,6 @@
|
||||
using Parser;
|
||||
using PdfFonts;
|
||||
using PdfPig.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Tokenization.Scanner;
|
||||
using Tokens;
|
||||
using XObjects;
|
||||
@ -67,12 +68,12 @@
|
||||
/// <summary>
|
||||
/// The active ExtendedGraphicsState font.
|
||||
/// </summary>
|
||||
protected IFont ActiveExtendedGraphicsStateFont;
|
||||
protected IFont? ActiveExtendedGraphicsStateFont;
|
||||
|
||||
/// <summary>
|
||||
/// Inline image builder.
|
||||
/// </summary>
|
||||
protected InlineImageBuilder InlineImageBuilder;
|
||||
protected InlineImageBuilder? InlineImageBuilder;
|
||||
|
||||
/// <summary>
|
||||
/// The page number.
|
||||
@ -281,8 +282,8 @@
|
||||
var boundingBox = font.GetBoundingBox(code);
|
||||
|
||||
RenderGlyph(font,
|
||||
currentState.CurrentStrokingColor,
|
||||
currentState.CurrentNonStrokingColor,
|
||||
currentState.CurrentStrokingColor!,
|
||||
currentState.CurrentNonStrokingColor!,
|
||||
currentState.FontState.TextRenderingMode,
|
||||
fontSize,
|
||||
pointSize,
|
||||
@ -336,7 +337,7 @@
|
||||
|
||||
var currentState = GetCurrentState();
|
||||
|
||||
var textState = currentState.FontState;
|
||||
var textState = currentState.FontState!;
|
||||
|
||||
var fontSize = textState.FontSize;
|
||||
var horizontalScaling = textState.HorizontalScaling / 100.0;
|
||||
@ -346,7 +347,7 @@
|
||||
{
|
||||
if (ParsingOptions.SkipMissingFonts)
|
||||
{
|
||||
ParsingOptions.Logger.Warn($"Skipping a missing font with name {currentState.FontState.FontName} " +
|
||||
ParsingOptions.Logger.Warn($"Skipping a missing font with name {currentState.FontState!.FontName} " +
|
||||
$"since it is not present in the document and {nameof(PdfPig.ParsingOptions.SkipMissingFonts)} " +
|
||||
"is set to true. This may result in some text being skipped and not included in the output.");
|
||||
|
||||
@ -469,11 +470,9 @@
|
||||
* 5. Restore the saved graphics state, as if by invoking the Q operator.
|
||||
*/
|
||||
|
||||
var hasResources =
|
||||
formStream.StreamDictionary.TryGet<DictionaryToken>(NameToken.Resources,
|
||||
if (formStream.StreamDictionary.TryGet<DictionaryToken>(NameToken.Resources,
|
||||
PdfScanner,
|
||||
out var formResources);
|
||||
if (hasResources)
|
||||
out var formResources))
|
||||
{
|
||||
ResourceStore.LoadResourceDictionary(formResources);
|
||||
}
|
||||
@ -484,7 +483,7 @@
|
||||
var startState = GetCurrentState();
|
||||
|
||||
// Transparency Group XObjects
|
||||
if (formStream.StreamDictionary.TryGet(NameToken.Group, PdfScanner, out DictionaryToken formGroupToken))
|
||||
if (formStream.StreamDictionary.TryGet(NameToken.Group, PdfScanner, out DictionaryToken? formGroupToken))
|
||||
{
|
||||
if (!formGroupToken.TryGet<NameToken>(NameToken.S, PdfScanner, out var sToken) ||
|
||||
sToken != NameToken.Transparency)
|
||||
@ -512,16 +511,16 @@
|
||||
startState.AlphaConstantNonStroking = 1.0;
|
||||
startState.AlphaConstantStroking = 1.0;
|
||||
|
||||
if (formGroupToken.TryGet(NameToken.Cs, PdfScanner, out NameToken csNameToken))
|
||||
if (formGroupToken.TryGet(NameToken.Cs, PdfScanner, out NameToken? csNameToken))
|
||||
{
|
||||
startState.ColorSpaceContext.SetNonStrokingColorspace(csNameToken);
|
||||
startState.ColorSpaceContext!.SetNonStrokingColorspace(csNameToken);
|
||||
}
|
||||
else if (formGroupToken.TryGet(NameToken.Cs, PdfScanner, out ArrayToken csArrayToken)
|
||||
else if (formGroupToken.TryGet(NameToken.Cs, PdfScanner, out ArrayToken? csArrayToken)
|
||||
&& csArrayToken.Length > 0)
|
||||
{
|
||||
if (csArrayToken.Data[0] is NameToken firstColorSpaceName)
|
||||
{
|
||||
startState.ColorSpaceContext.SetNonStrokingColorspace(firstColorSpaceName, formGroupToken);
|
||||
startState.ColorSpaceContext!.SetNonStrokingColorspace(firstColorSpaceName, formGroupToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -530,7 +529,7 @@
|
||||
}
|
||||
|
||||
bool isolated = false;
|
||||
if (formGroupToken.TryGet(NameToken.I, PdfScanner, out BooleanToken isolatedToken))
|
||||
if (formGroupToken.TryGet(NameToken.I, PdfScanner, out BooleanToken? isolatedToken))
|
||||
{
|
||||
/*
|
||||
* (Optional) A flag specifying whether the transparency group is isolated (see “Isolated Groups”).
|
||||
@ -542,7 +541,7 @@
|
||||
}
|
||||
|
||||
bool knockout = false;
|
||||
if (formGroupToken.TryGet(NameToken.K, PdfScanner, out BooleanToken knockoutToken))
|
||||
if (formGroupToken.TryGet(NameToken.K, PdfScanner, out BooleanToken? knockoutToken))
|
||||
{
|
||||
/*
|
||||
* (Optional) A flag specifying whether the transparency group is a knockout group (see “Knockout Groups”).
|
||||
@ -597,7 +596,7 @@
|
||||
// 5. Restore saved state.
|
||||
PopState();
|
||||
|
||||
if (hasResources)
|
||||
if (formResources != null) // has resources
|
||||
{
|
||||
ResourceStore.UnloadResourceDictionary();
|
||||
}
|
||||
@ -667,22 +666,22 @@
|
||||
|
||||
var state = ResourceStore.GetExtendedGraphicsStateDictionary(stateName);
|
||||
|
||||
if (state.TryGet(NameToken.Lw, PdfScanner, out NumericToken lwToken))
|
||||
if (state.TryGet(NameToken.Lw, PdfScanner, out NumericToken? lwToken))
|
||||
{
|
||||
currentGraphicsState.LineWidth = lwToken.Data;
|
||||
}
|
||||
|
||||
if (state.TryGet(NameToken.Lc, PdfScanner, out NumericToken lcToken))
|
||||
if (state.TryGet(NameToken.Lc, PdfScanner, out NumericToken? lcToken))
|
||||
{
|
||||
currentGraphicsState.CapStyle = (LineCapStyle)lcToken.Int;
|
||||
}
|
||||
|
||||
if (state.TryGet(NameToken.Lj, PdfScanner, out NumericToken ljToken))
|
||||
if (state.TryGet(NameToken.Lj, PdfScanner, out NumericToken? ljToken))
|
||||
{
|
||||
currentGraphicsState.JoinStyle = (LineJoinStyle)ljToken.Int;
|
||||
}
|
||||
|
||||
if (state.TryGet(NameToken.Font, PdfScanner, out ArrayToken fontArray) && fontArray.Length == 2
|
||||
if (state.TryGet(NameToken.Font, PdfScanner, out ArrayToken? fontArray) && fontArray.Length == 2
|
||||
&& fontArray.Data[0] is IndirectReferenceToken fontReference &&
|
||||
fontArray.Data[1] is NumericToken sizeToken)
|
||||
{
|
||||
@ -691,7 +690,7 @@
|
||||
ActiveExtendedGraphicsStateFont = ResourceStore.GetFontDirectly(fontReference);
|
||||
}
|
||||
|
||||
if (state.TryGet(NameToken.Ais, PdfScanner, out BooleanToken aisToken))
|
||||
if (state.TryGet(NameToken.Ais, PdfScanner, out BooleanToken? aisToken))
|
||||
{
|
||||
// The alpha source flag (“alpha is shape”), specifying
|
||||
// whether the current soft mask and alpha constant are to be interpreted as
|
||||
@ -699,7 +698,7 @@
|
||||
currentGraphicsState.AlphaSource = aisToken.Data;
|
||||
}
|
||||
|
||||
if (state.TryGet(NameToken.Ca, PdfScanner, out NumericToken caToken))
|
||||
if (state.TryGet(NameToken.Ca, PdfScanner, out NumericToken? caToken))
|
||||
{
|
||||
// (Optional; PDF 1.4) The current stroking alpha constant, specifying the constant
|
||||
// shape or constant opacity value to be used for stroking operations in the
|
||||
@ -708,7 +707,7 @@
|
||||
currentGraphicsState.AlphaConstantStroking = caToken.Data;
|
||||
}
|
||||
|
||||
if (state.TryGet(NameToken.CaNs, PdfScanner, out NumericToken cansToken))
|
||||
if (state.TryGet(NameToken.CaNs, PdfScanner, out NumericToken? cansToken))
|
||||
{
|
||||
// (Optional; PDF 1.4) The current stroking alpha constant, specifying the constant
|
||||
// shape or constant opacity value to be used for NON-stroking operations in the
|
||||
@ -717,7 +716,7 @@
|
||||
currentGraphicsState.AlphaConstantNonStroking = cansToken.Data;
|
||||
}
|
||||
|
||||
if (state.TryGet(NameToken.Op, PdfScanner, out BooleanToken OPToken))
|
||||
if (state.TryGet(NameToken.Op, PdfScanner, out BooleanToken? OPToken))
|
||||
{
|
||||
// (Optional) A flag specifying whether to apply overprint (see Section 4.5.6,
|
||||
// “Overprint Control”). In PDF 1.2 and earlier, there is a single overprint
|
||||
@ -729,7 +728,7 @@
|
||||
currentGraphicsState.Overprint = OPToken.Data;
|
||||
}
|
||||
|
||||
if (state.TryGet(NameToken.OpNs, PdfScanner, out BooleanToken opToken))
|
||||
if (state.TryGet(NameToken.OpNs, PdfScanner, out BooleanToken? opToken))
|
||||
{
|
||||
// (Optional; PDF 1.3) A flag specifying whether to apply overprint (see Section
|
||||
// 4.5.6, “Overprint Control”) for painting operations other than stroking. If
|
||||
@ -737,13 +736,13 @@
|
||||
currentGraphicsState.NonStrokingOverprint = opToken.Data;
|
||||
}
|
||||
|
||||
if (state.TryGet(NameToken.Opm, PdfScanner, out NumericToken opmToken))
|
||||
if (state.TryGet(NameToken.Opm, PdfScanner, out NumericToken? opmToken))
|
||||
{
|
||||
// (Optional; PDF 1.3) The overprint mode (see Section 4.5.6, “Overprint Control”).
|
||||
currentGraphicsState.OverprintMode = opmToken.Data;
|
||||
}
|
||||
|
||||
if (state.TryGet(NameToken.Sa, PdfScanner, out BooleanToken saToken))
|
||||
if (state.TryGet(NameToken.Sa, PdfScanner, out BooleanToken? saToken))
|
||||
{
|
||||
// (Optional) A flag specifying whether to apply automatic stroke adjustment
|
||||
// (see Section 6.5.4, “Automatic Stroke Adjustment”).
|
||||
@ -805,9 +804,10 @@
|
||||
protected abstract void RenderInlineImage(InlineImage inlineImage);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract void BeginMarkedContent(NameToken name,
|
||||
NameToken propertyDictionaryName,
|
||||
DictionaryToken properties);
|
||||
public abstract void BeginMarkedContent(
|
||||
NameToken name,
|
||||
NameToken? propertyDictionaryName,
|
||||
DictionaryToken? properties);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract void EndMarkedContent();
|
||||
|
@ -22,7 +22,7 @@
|
||||
this.resourceStore = resourceStore ?? throw new ArgumentNullException(nameof(resourceStore));
|
||||
}
|
||||
|
||||
public void SetStrokingColorspace(NameToken colorspace, DictionaryToken dictionary = null)
|
||||
public void SetStrokingColorspace(NameToken colorspace, DictionaryToken? dictionary = null)
|
||||
{
|
||||
CurrentStrokingColorSpace = resourceStore.GetColorSpaceDetails(colorspace, dictionary);
|
||||
if (CurrentStrokingColorSpace is UnsupportedColorSpaceDetails)
|
||||
@ -33,7 +33,7 @@
|
||||
currentStateFunc().CurrentStrokingColor = CurrentStrokingColorSpace.GetInitializeColor();
|
||||
}
|
||||
|
||||
public void SetStrokingColor(IReadOnlyList<double> operands, NameToken patternName)
|
||||
public void SetStrokingColor(IReadOnlyList<double> operands, NameToken? patternName)
|
||||
{
|
||||
if (CurrentStrokingColorSpace is UnsupportedColorSpaceDetails)
|
||||
{
|
||||
@ -69,7 +69,7 @@
|
||||
currentStateFunc().CurrentStrokingColor = CurrentStrokingColorSpace.GetColor(c, m, y, k);
|
||||
}
|
||||
|
||||
public void SetNonStrokingColorspace(NameToken colorspace, DictionaryToken dictionary = null)
|
||||
public void SetNonStrokingColorspace(NameToken colorspace, DictionaryToken? dictionary = null)
|
||||
{
|
||||
CurrentNonStrokingColorSpace = resourceStore.GetColorSpaceDetails(colorspace, dictionary);
|
||||
if (CurrentNonStrokingColorSpace is UnsupportedColorSpaceDetails)
|
||||
@ -80,7 +80,7 @@
|
||||
currentStateFunc().CurrentNonStrokingColor = CurrentNonStrokingColorSpace.GetInitializeColor();
|
||||
}
|
||||
|
||||
public void SetNonStrokingColor(IReadOnlyList<double> operands, NameToken patternName)
|
||||
public void SetNonStrokingColor(IReadOnlyList<double> operands, NameToken? patternName)
|
||||
{
|
||||
if (CurrentNonStrokingColorSpace is UnsupportedColorSpaceDetails)
|
||||
{
|
||||
|
@ -56,7 +56,7 @@
|
||||
var mXYZ = new Matrix3x3(
|
||||
Xr, Xg, Xb,
|
||||
Yr, Yg, Yb,
|
||||
Zr, Zg, Zb).Inverse();
|
||||
Zr, Zg, Zb).Inverse()!;
|
||||
|
||||
var S = mXYZ.Multiply(destinationWorkingSpace.ReferenceWhite);
|
||||
|
||||
@ -69,7 +69,7 @@
|
||||
Sr * Yr, Sg * Yg, Sb * Yb,
|
||||
Sr * Zr, Sg * Zg, Sb * Zb);
|
||||
|
||||
transformationMatrix = M.Inverse();
|
||||
transformationMatrix = M.Inverse()!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -61,16 +61,20 @@ namespace UglyToad.PdfPig.Graphics.Colors
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return Equals(obj as CMYKColor);
|
||||
return obj is CMYKColor other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(CMYKColor other)
|
||||
public bool Equals(CMYKColor? other)
|
||||
{
|
||||
return other != null &&
|
||||
C == other.C &&
|
||||
if (other is null)
|
||||
{
|
||||
return this is null;
|
||||
}
|
||||
|
||||
return C == other.C &&
|
||||
M == other.M &&
|
||||
Y == other.Y &&
|
||||
K == other.K;
|
||||
@ -79,12 +83,7 @@ namespace UglyToad.PdfPig.Graphics.Colors
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashCode = -492570696;
|
||||
hashCode = hashCode * -1521134295 + C.GetHashCode();
|
||||
hashCode = hashCode * -1521134295 + M.GetHashCode();
|
||||
hashCode = hashCode * -1521134295 + Y.GetHashCode();
|
||||
hashCode = hashCode * -1521134295 + K.GetHashCode();
|
||||
return hashCode;
|
||||
return HashCode.Combine(C, M, Y, K);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -17,8 +17,8 @@
|
||||
(double Xwd, double Ywd, double Zwd) destinationReferenceWhite,
|
||||
Method method = Method.Bradford)
|
||||
{
|
||||
var coneReponseDomain = GetConeResponseDomain(method);
|
||||
var inverseConeResponseDomain = coneReponseDomain.Inverse();
|
||||
var coneReponseDomain = GetConeResponseDomain(method)!;
|
||||
var inverseConeResponseDomain = coneReponseDomain.Inverse()!;
|
||||
var (ρS, γS, βS) = coneReponseDomain.Multiply(sourceReferenceWhite);
|
||||
|
||||
var (ρD, γD, βD) = coneReponseDomain.Multiply(destinationReferenceWhite);
|
||||
|
@ -8,7 +8,6 @@
|
||||
using UglyToad.PdfPig.Content;
|
||||
using UglyToad.PdfPig.Functions;
|
||||
using UglyToad.PdfPig.Util;
|
||||
using UglyToad.PdfPig.Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Contains more document-specific information about the <see cref="ColorSpace"/>.
|
||||
@ -58,7 +57,7 @@
|
||||
/// <summary>
|
||||
/// Get the color that initialize the current stroking or nonstroking colour.
|
||||
/// </summary>
|
||||
public abstract IColor GetInitializeColor();
|
||||
public abstract IColor? GetInitializeColor();
|
||||
|
||||
/// <summary>
|
||||
/// Transform image bytes.
|
||||
@ -106,7 +105,7 @@
|
||||
{
|
||||
if (values is null || values.Length != NumberOfColorComponents)
|
||||
{
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values.Length}", nameof(values));
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values?.Length ?? 0}", nameof(values));
|
||||
}
|
||||
|
||||
double gray = values[0];
|
||||
@ -168,7 +167,7 @@
|
||||
{
|
||||
if (values is null || values.Length != NumberOfColorComponents)
|
||||
{
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values.Length}", nameof(values));
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values?.Length ?? 0}", nameof(values));
|
||||
}
|
||||
|
||||
double r = values[0];
|
||||
@ -230,7 +229,7 @@
|
||||
{
|
||||
if (values is null || values.Length != NumberOfColorComponents)
|
||||
{
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values.Length}", nameof(values));
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values?.Length ?? 0}", nameof(values));
|
||||
}
|
||||
|
||||
double c = values[0];
|
||||
@ -332,7 +331,7 @@
|
||||
{
|
||||
if (values is null || values.Length != NumberOfColorComponents)
|
||||
{
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values.Length}", nameof(values));
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values?.Length ?? 0}", nameof(values));
|
||||
}
|
||||
|
||||
return cache.GetOrAdd(values[0], v =>
|
||||
@ -345,7 +344,7 @@
|
||||
internal byte[] UnwrapIndexedColorSpaceBytes(IReadOnlyList<byte> input)
|
||||
{
|
||||
var multiplier = 1;
|
||||
Func<byte, IEnumerable<byte>> transformer = null;
|
||||
Func<byte, IEnumerable<byte>>? transformer = null;
|
||||
switch (BaseType)
|
||||
{
|
||||
case ColorSpace.DeviceRGB:
|
||||
@ -520,7 +519,7 @@
|
||||
{
|
||||
if (values is null || values.Length != NumberOfColorComponents)
|
||||
{
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values.Length}", nameof(values));
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values?.Length ?? 0}", nameof(values));
|
||||
}
|
||||
|
||||
// TODO - use attributes
|
||||
@ -546,7 +545,7 @@
|
||||
comps[n] = b / 255.0;
|
||||
}
|
||||
|
||||
if (!cache.TryGetValue(key, out double[] colors))
|
||||
if (!cache.TryGetValue(key, out double[]? colors))
|
||||
{
|
||||
colors = Process(comps);
|
||||
cache[key] = colors;
|
||||
@ -582,17 +581,17 @@
|
||||
/// <summary>
|
||||
/// Colorants - dictionary - Required if Subtype is NChannel and the colour space includes spot colorants; otherwise optional.
|
||||
/// </summary>
|
||||
public DictionaryToken Colorants { get; }
|
||||
public DictionaryToken? Colorants { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Process - dictionary - Required if Subtype is NChannel and the colour space includes components of a process colour space, otherwise optional.
|
||||
/// </summary>
|
||||
public DictionaryToken Process { get; }
|
||||
public DictionaryToken? Process { get; }
|
||||
|
||||
/// <summary>
|
||||
/// MixingHints - dictionary - Optional
|
||||
/// </summary>
|
||||
public DictionaryToken MixingHints { get; }
|
||||
public DictionaryToken? MixingHints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="DeviceNColorSpaceAttributes"/>.
|
||||
@ -608,7 +607,7 @@
|
||||
/// <summary>
|
||||
/// Create a new <see cref="DeviceNColorSpaceAttributes"/>.
|
||||
/// </summary>
|
||||
public DeviceNColorSpaceAttributes(NameToken subtype, DictionaryToken colorants, DictionaryToken process, DictionaryToken mixingHints)
|
||||
public DeviceNColorSpaceAttributes(NameToken subtype, DictionaryToken? colorants, DictionaryToken? process, DictionaryToken? mixingHints)
|
||||
{
|
||||
Subtype = subtype;
|
||||
Colorants = colorants;
|
||||
@ -690,7 +689,7 @@
|
||||
{
|
||||
if (values is null || values.Length != NumberOfColorComponents)
|
||||
{
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values.Length}", nameof(values));
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values?.Length ?? 0}", nameof(values));
|
||||
}
|
||||
|
||||
// TODO - we ignore the name for now
|
||||
@ -710,7 +709,7 @@
|
||||
for (var i = 0; i < values.Count; i += 3)
|
||||
{
|
||||
byte b = values[i++];
|
||||
if (!cache.TryGetValue(b, out double[] colors))
|
||||
if (!cache.TryGetValue(b, out double[]? colors))
|
||||
{
|
||||
colors = Process(b / 255.0);
|
||||
cache[b] = colors;
|
||||
@ -770,7 +769,7 @@
|
||||
/// <summary>
|
||||
/// Create a new <see cref="CalGrayColorSpaceDetails"/>.
|
||||
/// </summary>
|
||||
public CalGrayColorSpaceDetails([NotNull] IReadOnlyList<double> whitePoint, [CanBeNull] IReadOnlyList<double> blackPoint, double? gamma)
|
||||
public CalGrayColorSpaceDetails(IReadOnlyList<double> whitePoint, IReadOnlyList<double>? blackPoint, double? gamma)
|
||||
: base(ColorSpace.CalGray)
|
||||
{
|
||||
WhitePoint = whitePoint ?? throw new ArgumentNullException(nameof(whitePoint));
|
||||
@ -782,7 +781,7 @@
|
||||
BlackPoint = blackPoint ?? new[] { 0.0, 0, 0 }.ToArray();
|
||||
if (BlackPoint.Count != 3)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(blackPoint), blackPoint, $"Must consist of exactly three numbers, but was passed {blackPoint.Count}.");
|
||||
throw new ArgumentOutOfRangeException(nameof(blackPoint), blackPoint, $"Must consist of exactly three numbers, but was passed {blackPoint?.Count ?? 0}.");
|
||||
}
|
||||
|
||||
Gamma = gamma ?? 1.0;
|
||||
@ -840,7 +839,7 @@
|
||||
{
|
||||
if (values is null || values.Length != NumberOfColorComponents)
|
||||
{
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values.Length}", nameof(values));
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values?.Length ?? 0}", nameof(values));
|
||||
}
|
||||
|
||||
return TransformToRGB(values[0]);
|
||||
@ -901,7 +900,7 @@
|
||||
/// <summary>
|
||||
/// Create a new <see cref="CalRGBColorSpaceDetails"/>.
|
||||
/// </summary>
|
||||
public CalRGBColorSpaceDetails([NotNull] IReadOnlyList<double> whitePoint, [CanBeNull] IReadOnlyList<double> blackPoint, [CanBeNull] IReadOnlyList<double> gamma, [CanBeNull] IReadOnlyList<double> matrix)
|
||||
public CalRGBColorSpaceDetails(IReadOnlyList<double> whitePoint, IReadOnlyList<double>? blackPoint, IReadOnlyList<double>? gamma, IReadOnlyList<double>? matrix)
|
||||
: base(ColorSpace.CalRGB)
|
||||
{
|
||||
WhitePoint = whitePoint ?? throw new ArgumentNullException(nameof(whitePoint));
|
||||
@ -910,22 +909,22 @@
|
||||
throw new ArgumentOutOfRangeException(nameof(whitePoint), whitePoint, $"Must consist of exactly three numbers, but was passed {whitePoint.Count}.");
|
||||
}
|
||||
|
||||
BlackPoint = blackPoint ?? new[] { 0.0, 0, 0 }.ToArray();
|
||||
BlackPoint = blackPoint ?? new[] { 0.0, 0, 0 };
|
||||
if (BlackPoint.Count != 3)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(blackPoint), blackPoint, $"Must consist of exactly three numbers, but was passed {blackPoint.Count}.");
|
||||
throw new ArgumentOutOfRangeException(nameof(blackPoint), blackPoint, $"Must consist of exactly three numbers, but was passed {blackPoint!.Count}.");
|
||||
}
|
||||
|
||||
Gamma = gamma ?? new[] { 1.0, 1, 1 }.ToArray();
|
||||
Gamma = gamma ?? new[] { 1.0, 1, 1 };
|
||||
if (Gamma.Count != 3)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(gamma), gamma, $"Must consist of exactly three numbers, but was passed {gamma.Count}.");
|
||||
throw new ArgumentOutOfRangeException(nameof(gamma), gamma, $"Must consist of exactly three numbers, but was passed {gamma!.Count}.");
|
||||
}
|
||||
|
||||
Matrix = matrix ?? new[] { 1.0, 0, 0, 0, 1, 0, 0, 0, 1 }.ToArray();
|
||||
Matrix = matrix ?? new[] { 1.0, 0, 0, 0, 1, 0, 0, 0, 1 };
|
||||
if (Matrix.Count != 9)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(matrix), matrix, $"Must consist of exactly nine numbers, but was passed {matrix.Count}.");
|
||||
throw new ArgumentOutOfRangeException(nameof(matrix), matrix, $"Must consist of exactly nine numbers, but was passed {matrix!.Count}.");
|
||||
}
|
||||
|
||||
colorSpaceTransformer =
|
||||
@ -981,7 +980,7 @@
|
||||
{
|
||||
if (values is null || values.Length != NumberOfColorComponents)
|
||||
{
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values.Length}", nameof(values));
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values?.Length ?? 0}", nameof(values));
|
||||
}
|
||||
|
||||
return TransformToRGB((values[0], values[1], values[2]));
|
||||
@ -1037,7 +1036,7 @@
|
||||
/// <summary>
|
||||
/// Create a new <see cref="LabColorSpaceDetails"/>.
|
||||
/// </summary>
|
||||
public LabColorSpaceDetails([NotNull] IReadOnlyList<double> whitePoint, [CanBeNull] IReadOnlyList<double> blackPoint, [CanBeNull] IReadOnlyList<double> matrix)
|
||||
public LabColorSpaceDetails(IReadOnlyList<double> whitePoint, IReadOnlyList<double>? blackPoint, IReadOnlyList<double>? matrix)
|
||||
: base(ColorSpace.Lab)
|
||||
{
|
||||
WhitePoint = whitePoint?.Select(v => v).ToArray() ?? throw new ArgumentNullException(nameof(whitePoint));
|
||||
@ -1049,13 +1048,13 @@
|
||||
BlackPoint = blackPoint?.Select(v => v).ToArray() ?? new[] { 0.0, 0.0, 0.0 };
|
||||
if (BlackPoint.Count != 3)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(blackPoint), blackPoint, $"Must consist of exactly three numbers, but was passed {blackPoint.Count}.");
|
||||
throw new ArgumentOutOfRangeException(nameof(blackPoint), blackPoint, $"Must consist of exactly three numbers, but was passed {blackPoint!.Count}.");
|
||||
}
|
||||
|
||||
Matrix = matrix?.Select(v => v).ToArray() ?? new[] { -100.0, 100.0, -100.0, 100.0 };
|
||||
if (Matrix.Count != 4)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(matrix), matrix, $"Must consist of exactly four numbers, but was passed {matrix.Count}.");
|
||||
throw new ArgumentOutOfRangeException(nameof(matrix), matrix, $"Must consist of exactly four numbers, but was passed {matrix!.Count}.");
|
||||
}
|
||||
|
||||
colorSpaceTransformer = new CIEBasedColorSpaceTransformer((WhitePoint[0], WhitePoint[1], WhitePoint[2]), RGBWorkingSpace.sRGB);
|
||||
@ -1122,7 +1121,7 @@
|
||||
{
|
||||
if (values is null || values.Length != NumberOfColorComponents)
|
||||
{
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values.Length}", nameof(values));
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values?.Length ?? 0}", nameof(values));
|
||||
}
|
||||
|
||||
return TransformToRGB((values[0], values[1], values[2]));
|
||||
@ -1176,7 +1175,6 @@
|
||||
/// must be substituted.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public ColorSpaceDetails AlternateColorSpace { get; }
|
||||
|
||||
/// <summary>
|
||||
@ -1184,20 +1182,20 @@
|
||||
/// specifies the minimum and maximum valid values of the corresponding color components. These
|
||||
/// values must match the information in the ICC profile. Default value: [0.0 1.0 0.0 1.0 ...].
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public IReadOnlyList<double> Range { get; }
|
||||
|
||||
/// <summary>
|
||||
/// An optional metadata stream that contains metadata for the color space.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public XmpMetadata Metadata { get; }
|
||||
public XmpMetadata? Metadata { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="ICCBasedColorSpaceDetails"/>.
|
||||
/// </summary>
|
||||
internal ICCBasedColorSpaceDetails(int numberOfColorComponents, [CanBeNull] ColorSpaceDetails alternateColorSpaceDetails,
|
||||
[CanBeNull] IReadOnlyList<double> range, [CanBeNull] XmpMetadata metadata)
|
||||
internal ICCBasedColorSpaceDetails(int numberOfColorComponents,
|
||||
ColorSpaceDetails? alternateColorSpaceDetails,
|
||||
IReadOnlyList<double>? range,
|
||||
XmpMetadata? metadata)
|
||||
: base(ColorSpace.ICCBased)
|
||||
{
|
||||
if (numberOfColorComponents != 1 && numberOfColorComponents != 3 && numberOfColorComponents != 4)
|
||||
@ -1207,8 +1205,8 @@
|
||||
|
||||
NumberOfColorComponents = numberOfColorComponents;
|
||||
AlternateColorSpace = alternateColorSpaceDetails ??
|
||||
(NumberOfColorComponents == 1 ? (ColorSpaceDetails)DeviceGrayColorSpaceDetails.Instance :
|
||||
NumberOfColorComponents == 3 ? (ColorSpaceDetails)DeviceRgbColorSpaceDetails.Instance : (ColorSpaceDetails)DeviceCmykColorSpaceDetails.Instance);
|
||||
(NumberOfColorComponents == 1 ? DeviceGrayColorSpaceDetails.Instance :
|
||||
NumberOfColorComponents == 3 ? DeviceRgbColorSpaceDetails.Instance : DeviceCmykColorSpaceDetails.Instance);
|
||||
|
||||
BaseType = AlternateColorSpace.BaseType;
|
||||
Range = range ??
|
||||
@ -1216,7 +1214,7 @@
|
||||
if (Range.Count != 2 * numberOfColorComponents)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(range), range,
|
||||
$"Must consist of exactly {2 * numberOfColorComponents} (2 x NumberOfColorComponents), but was passed {range.Count}");
|
||||
$"Must consist of exactly {2 * numberOfColorComponents} (2 x NumberOfColorComponents), but was passed {range?.Count ?? 0}");
|
||||
}
|
||||
Metadata = metadata;
|
||||
}
|
||||
@ -1234,7 +1232,7 @@
|
||||
{
|
||||
if (values is null || values.Length != NumberOfColorComponents)
|
||||
{
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values.Length}", nameof(values));
|
||||
throw new ArgumentException($"Invalid number of inputs, expecting {NumberOfColorComponents} but got {values?.Length ?? 0}", nameof(values));
|
||||
}
|
||||
|
||||
// TODO - use ICC profile
|
||||
@ -1293,13 +1291,12 @@
|
||||
/// Valid for Uncoloured Tiling Patterns. Wwill throw a <see cref="InvalidOperationException"/> otherwise.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
internal override int BaseNumberOfColorComponents => UnderlyingColourSpace.NumberOfColorComponents;
|
||||
internal override int BaseNumberOfColorComponents => UnderlyingColourSpace!.NumberOfColorComponents;
|
||||
|
||||
/// <summary>
|
||||
/// The underlying color space for Uncoloured Tiling Patterns.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public ColorSpaceDetails UnderlyingColourSpace { get; }
|
||||
public ColorSpaceDetails? UnderlyingColourSpace { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="PatternColorSpaceDetails"/>.
|
||||
@ -1349,7 +1346,7 @@
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <returns>Always returns <c>null</c>.</returns>
|
||||
public override IColor GetInitializeColor()
|
||||
public override IColor? GetInitializeColor()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -1409,7 +1406,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IColor GetInitializeColor()
|
||||
public override IColor? GetInitializeColor()
|
||||
{
|
||||
throw new InvalidOperationException("UnsupportedColorSpaceDetails");
|
||||
}
|
||||
|
@ -41,16 +41,20 @@ namespace UglyToad.PdfPig.Graphics.Colors
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return Equals(obj as GrayColor);
|
||||
return obj is GrayColor other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(GrayColor other)
|
||||
public bool Equals(GrayColor? other)
|
||||
{
|
||||
return other != null &&
|
||||
Gray == other.Gray;
|
||||
if (other is null)
|
||||
{
|
||||
return this is null;
|
||||
}
|
||||
|
||||
return Gray == other.Gray;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -143,19 +143,19 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is TilingPatternColor color)
|
||||
{
|
||||
return Equals(color);
|
||||
}
|
||||
|
||||
return false;
|
||||
return obj is TilingPatternColor other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(TilingPatternColor other)
|
||||
public bool Equals(TilingPatternColor? other)
|
||||
{
|
||||
if (other is null)
|
||||
{
|
||||
return this is null;
|
||||
}
|
||||
|
||||
return PatternType.Equals(other.PatternType) &&
|
||||
Matrix.Equals(other.Matrix) &&
|
||||
ExtGState.Equals(other.ExtGState) &&
|
||||
@ -210,19 +210,19 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is ShadingPatternColor color)
|
||||
{
|
||||
return Equals(color);
|
||||
}
|
||||
|
||||
return false;
|
||||
return obj is ShadingPatternColor other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(ShadingPatternColor other)
|
||||
public bool Equals(ShadingPatternColor? other)
|
||||
{
|
||||
if (other is null)
|
||||
{
|
||||
return this is null;
|
||||
}
|
||||
|
||||
return PatternType.Equals(other.PatternType) &&
|
||||
Matrix.Equals(other.Matrix) &&
|
||||
ExtGState.Equals(other.ExtGState) &&
|
||||
|
@ -53,26 +53,25 @@
|
||||
public (double r, double g, double b) ToRGBValues() => (R, G, B);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is RGBColor color)
|
||||
{
|
||||
return Equals(color);
|
||||
}
|
||||
|
||||
return false;
|
||||
return obj is RGBColor other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Whether 2 RGB colors are equal across all channels.
|
||||
/// </summary>
|
||||
public bool Equals(RGBColor other)
|
||||
public bool Equals(RGBColor? other)
|
||||
{
|
||||
return other != null &&
|
||||
R == other.R &&
|
||||
G == other.G &&
|
||||
B == other.B;
|
||||
if (other is null)
|
||||
{
|
||||
return this is null;
|
||||
}
|
||||
|
||||
return R == other.R
|
||||
&& G == other.G
|
||||
&& B == other.B;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Colors
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Graphics.Colors
|
||||
{
|
||||
using System;
|
||||
|
||||
@ -7,8 +9,7 @@
|
||||
{
|
||||
public static readonly XYZReferenceWhite ReferenceWhites = new XYZReferenceWhite();
|
||||
|
||||
public static readonly RGBWorkingSpace AdobeRGB1998 = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace AdobeRGB1998 = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(2.2),
|
||||
ReferenceWhite = ReferenceWhites.D65,
|
||||
RedPrimary = (0.6400, 0.3300, 0.297361),
|
||||
@ -16,8 +17,7 @@
|
||||
BluePrimary = (0.1500, 0.0600, 0.075285),
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace AppleRGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace AppleRGB = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(1.8),
|
||||
ReferenceWhite = ReferenceWhites.D65,
|
||||
RedPrimary = (0.6250, 0.3400, 0.244634),
|
||||
@ -25,8 +25,7 @@
|
||||
BluePrimary = (0.1550, 0.0700, 0.083332)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace BestRGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace BestRGB = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(2.2),
|
||||
ReferenceWhite = ReferenceWhites.D50,
|
||||
RedPrimary = (0.7347, 0.2653, 0.228457),
|
||||
@ -34,8 +33,7 @@
|
||||
BluePrimary = (0.1300, 0.0350, 0.034191)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace BetaRGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace BetaRGB = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(2.2),
|
||||
ReferenceWhite = ReferenceWhites.D50,
|
||||
RedPrimary = (0.6888, 0.3112, 0.303273),
|
||||
@ -43,8 +41,7 @@
|
||||
BluePrimary = (0.1265, 0.0352, 0.032941)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace BruceRGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace BruceRGB = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(2.2),
|
||||
ReferenceWhite = ReferenceWhites.D65,
|
||||
RedPrimary = (0.6400, 0.3300, 0.240995),
|
||||
@ -52,8 +49,7 @@
|
||||
BluePrimary = (0.1500, 0.0600, 0.075452)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace CIE_RGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace CIE_RGB = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(2.2),
|
||||
ReferenceWhite = ReferenceWhites.E,
|
||||
RedPrimary = (0.7350, 0.2650, 0.176204),
|
||||
@ -61,8 +57,7 @@
|
||||
BluePrimary = (0.1670, 0.0090, 0.010811)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace ColorMatchRGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace ColorMatchRGB = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(1.8),
|
||||
ReferenceWhite = ReferenceWhites.D50,
|
||||
RedPrimary = (0.6300, 0.3400, 0.274884),
|
||||
@ -70,8 +65,7 @@
|
||||
BluePrimary = (0.1500, 0.0750, 0.066985)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace DonRGB4 = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace DonRGB4 = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(2.2),
|
||||
ReferenceWhite = ReferenceWhites.D50,
|
||||
RedPrimary = (0.6960, 0.3000, 0.278350),
|
||||
@ -79,8 +73,7 @@
|
||||
BluePrimary = (0.1300, 0.0350, 0.033680)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace EktaSpacePS5 = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace EktaSpacePS5 = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(2.2),
|
||||
ReferenceWhite = ReferenceWhites.D50,
|
||||
RedPrimary = (0.6950, 0.3050, 0.260629),
|
||||
@ -88,8 +81,7 @@
|
||||
BluePrimary = (0.1100, 0.0050, 0.004425)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace NTSC_RGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace NTSC_RGB = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(2.2),
|
||||
ReferenceWhite = ReferenceWhites.C,
|
||||
RedPrimary = (0.6700, 0.3300, 0.298839),
|
||||
@ -97,8 +89,7 @@
|
||||
BluePrimary = (0.1400, 0.0800, 0.114350)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace PAL_SECAM_RGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace PAL_SECAM_RGB = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(2.2),
|
||||
ReferenceWhite = ReferenceWhites.D65,
|
||||
RedPrimary = (0.6400, 0.3300, 0.222021),
|
||||
@ -106,8 +97,7 @@
|
||||
BluePrimary = (0.1500, 0.0600, 0.071334)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace ProPhotoRGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace ProPhotoRGB = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(1.8),
|
||||
ReferenceWhite = ReferenceWhites.D50,
|
||||
RedPrimary = (0.7347, 0.2653, 0.288040),
|
||||
@ -115,8 +105,7 @@
|
||||
BluePrimary = (0.0366, 0.0001, 0.000086)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace SMPTE_C_RGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace SMPTE_C_RGB = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(2.2),
|
||||
ReferenceWhite = ReferenceWhites.D65,
|
||||
RedPrimary = (0.6300, 0.3400, 0.212395),
|
||||
@ -124,8 +113,7 @@
|
||||
BluePrimary = (0.1550, 0.0700, 0.086556)
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace sRGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace sRGB = new RGBWorkingSpace {
|
||||
// sRGB gamma correction obtained from: http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html
|
||||
GammaCorrection = val => val <= 0.0031308 ? 12.92 * val : (1.055 * Math.Pow(val, (1 / 2.4)) - 0.055),
|
||||
ReferenceWhite = ReferenceWhites.D65,
|
||||
@ -134,8 +122,7 @@
|
||||
BluePrimary = (0.1500, 0.0600, 0.072186),
|
||||
};
|
||||
|
||||
public static readonly RGBWorkingSpace WideGamutRGB = new RGBWorkingSpace
|
||||
{
|
||||
public static readonly RGBWorkingSpace WideGamutRGB = new RGBWorkingSpace {
|
||||
GammaCorrection = CreateGammaFunc(2.2),
|
||||
ReferenceWhite = ReferenceWhites.D50,
|
||||
RedPrimary = (0.7350, 0.2650, 0.258187),
|
||||
@ -151,8 +138,7 @@
|
||||
|
||||
private static Func<double, double> CreateGammaFunc(double gamma)
|
||||
{
|
||||
return val =>
|
||||
{
|
||||
return val => {
|
||||
var result = Math.Pow(val, 1 / gamma);
|
||||
return double.IsNaN(result) ? 0 : result;
|
||||
};
|
||||
@ -175,4 +161,4 @@
|
||||
public readonly (double X, double Y, double Z) F11 = (1.00962, 1.00000, 0.64350);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,9 +15,9 @@
|
||||
/// <summary>
|
||||
/// The color space data.
|
||||
/// </summary>
|
||||
public IToken Data { get; }
|
||||
public IToken? Data { get; }
|
||||
|
||||
internal ResourceColorSpace(NameToken name, IToken data)
|
||||
internal ResourceColorSpace(NameToken name, IToken? data)
|
||||
{
|
||||
Name = name;
|
||||
Data = data;
|
||||
|
@ -35,7 +35,7 @@
|
||||
/// the shading, to fill those portions of the area to be painted
|
||||
/// that lie outside the bounds of the shading object.
|
||||
/// </summary>
|
||||
public double[] Background { get; }
|
||||
public double[]? Background { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The shading's bounding box. The coordinates shall be interpreted
|
||||
@ -62,7 +62,7 @@
|
||||
/// Create a new <see cref="Shading"/>.
|
||||
/// </summary>
|
||||
protected internal Shading(ShadingType shadingType, bool antiAlias, DictionaryToken shadingDictionary,
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[] background)
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[]? background)
|
||||
{
|
||||
ShadingType = shadingType;
|
||||
AntiAlias = antiAlias;
|
||||
@ -75,7 +75,7 @@
|
||||
/// <summary>
|
||||
/// The shading's function(s), if any.
|
||||
/// </summary>
|
||||
public abstract PdfFunction[] Functions { get; }
|
||||
public abstract PdfFunction[]? Functions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Convert the input values using the functions of the shading.
|
||||
@ -157,7 +157,7 @@
|
||||
/// Create a new <see cref="FunctionBasedShading"/>.
|
||||
/// </summary>
|
||||
public FunctionBasedShading(bool antiAlias, DictionaryToken shadingDictionary,
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[] background, double[] domain,
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[]? background, double[] domain,
|
||||
TransformationMatrix matrix, PdfFunction[] functions)
|
||||
: base(ShadingType.FunctionBased, antiAlias, shadingDictionary, colorSpace, bbox, background)
|
||||
{
|
||||
@ -207,7 +207,7 @@
|
||||
/// Create a new <see cref="AxialShading"/>.
|
||||
/// </summary>
|
||||
public AxialShading(bool antiAlias, DictionaryToken shadingDictionary,
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[] background,
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[]? background,
|
||||
double[] coords, double[] domain, PdfFunction[] functions, bool[] extend)
|
||||
: base(ShadingType.Axial, antiAlias, shadingDictionary, colorSpace, bbox, background)
|
||||
{
|
||||
@ -267,7 +267,7 @@
|
||||
/// Create a new <see cref="RadialShading"/>.
|
||||
/// </summary>
|
||||
public RadialShading(bool antiAlias, DictionaryToken shadingDictionary,
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[] background,
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[]? background,
|
||||
double[] coords, double[] domain, PdfFunction[] functions, bool[] extend)
|
||||
: base(ShadingType.Radial, antiAlias, shadingDictionary, colorSpace, bbox, background)
|
||||
{
|
||||
@ -327,14 +327,14 @@
|
||||
/// to the nearest valid value.
|
||||
/// This entry shall not be used with an Indexed colour space.
|
||||
/// </summary>
|
||||
public override PdfFunction[] Functions { get; }
|
||||
public override PdfFunction[]? Functions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="FreeFormGouraudShading"/>.
|
||||
/// </summary>
|
||||
public FreeFormGouraudShading(bool antiAlias, StreamToken shadingStream,
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[] background,
|
||||
int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag, double[] decode, PdfFunction[] functions)
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[]? background,
|
||||
int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag, double[] decode, PdfFunction[]? functions)
|
||||
: base(ShadingType.FreeFormGouraud, antiAlias, shadingStream.StreamDictionary, colorSpace, bbox, background)
|
||||
{
|
||||
BitsPerCoordinate = bitsPerCoordinate;
|
||||
@ -390,14 +390,14 @@
|
||||
/// component is out of range, it shall be adjusted to the nearest valid value.
|
||||
/// This entry shall not be used with an Indexed colour space.
|
||||
/// </summary>
|
||||
public override PdfFunction[] Functions { get; }
|
||||
public override PdfFunction[]? Functions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="LatticeFormGouraudShading"/>.
|
||||
/// </summary>
|
||||
public LatticeFormGouraudShading(bool antiAlias, StreamToken shadingStream,
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[] background,
|
||||
int bitsPerCoordinate, int bitsPerComponent, int verticesPerRow, double[] decode, PdfFunction[] functions)
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[]? background,
|
||||
int bitsPerCoordinate, int bitsPerComponent, int verticesPerRow, double[] decode, PdfFunction[]? functions)
|
||||
: base(ShadingType.LatticeFormGouraud, antiAlias, shadingStream.StreamDictionary, colorSpace, bbox, background)
|
||||
{
|
||||
BitsPerCoordinate = bitsPerCoordinate;
|
||||
@ -455,14 +455,14 @@
|
||||
/// shall be adjusted to the nearest valid value.
|
||||
/// This entry shall not be used with an Indexed colour space.
|
||||
/// </summary>
|
||||
public override PdfFunction[] Functions { get; }
|
||||
public override PdfFunction[]? Functions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="CoonsPatchMeshesShading"/>.
|
||||
/// </summary>
|
||||
public CoonsPatchMeshesShading(bool antiAlias, StreamToken shadingStream,
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[] background,
|
||||
int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag, double[] decode, PdfFunction[] functions)
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[]? background,
|
||||
int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag, double[] decode, PdfFunction[]? functions)
|
||||
: base(ShadingType.CoonsPatch, antiAlias, shadingStream.StreamDictionary, colorSpace, bbox, background)
|
||||
{
|
||||
BitsPerCoordinate = bitsPerCoordinate;
|
||||
@ -520,14 +520,14 @@
|
||||
/// shall be adjusted to the nearest valid value.
|
||||
/// This entry shall not be used with an Indexed colour space.
|
||||
/// </summary>
|
||||
public override PdfFunction[] Functions { get; }
|
||||
public override PdfFunction[]? Functions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TensorProductPatchMeshesShading"/>.
|
||||
/// </summary>
|
||||
public TensorProductPatchMeshesShading(bool antiAlias, StreamToken shadingStream,
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[] background,
|
||||
int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag, double[] decode, PdfFunction[] functions)
|
||||
ColorSpaceDetails colorSpace, PdfRectangle? bbox, double[]? background,
|
||||
int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag, double[] decode, PdfFunction[]? functions)
|
||||
: base(ShadingType.TensorProductPatch, antiAlias, shadingStream.StreamDictionary, colorSpace, bbox, background)
|
||||
{
|
||||
BitsPerCoordinate = bitsPerCoordinate;
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -30,8 +32,7 @@
|
||||
/// <summary>
|
||||
/// Stores a link to each image (either inline or XObject) as it is encountered in the content stream.
|
||||
/// </summary>
|
||||
private readonly List<Union<XObjectContentRecord, InlineImage>> images =
|
||||
new List<Union<XObjectContentRecord, InlineImage>>();
|
||||
private readonly List<Union<XObjectContentRecord, InlineImage>> images = new();
|
||||
|
||||
/// <summary>
|
||||
/// Stores each marked content as it is encountered in the content stream.
|
||||
@ -362,7 +363,7 @@
|
||||
{
|
||||
AddCurrentSubpath();
|
||||
|
||||
if (CurrentPath.IsClipping)
|
||||
if (CurrentPath!.IsClipping)
|
||||
{
|
||||
EndPath();
|
||||
return;
|
||||
@ -413,7 +414,7 @@
|
||||
|
||||
if (ParsingOptions.ClipPaths)
|
||||
{
|
||||
var currentClipping = GetCurrentState().CurrentClippingPath;
|
||||
var currentClipping = GetCurrentState().CurrentClippingPath!;
|
||||
currentClipping.SetClipping(clippingRule);
|
||||
|
||||
var newClippings = CurrentPath.Clip(currentClipping, ParsingOptions.Logger);
|
||||
|
@ -3,7 +3,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
|
||||
@ -19,7 +18,6 @@
|
||||
/// <summary>
|
||||
/// The numbers that specify the lengths of alternating dashes and gaps.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public IReadOnlyList<double> Array { get; }
|
||||
|
||||
/// <summary>
|
||||
@ -27,7 +25,7 @@
|
||||
/// </summary>
|
||||
/// <param name="phase">The phase. <see cref="Phase"/>.</param>
|
||||
/// <param name="array">The array. <see cref="Array"/>.</param>
|
||||
public LineDashPattern(int phase, [NotNull]IReadOnlyList<double> array)
|
||||
public LineDashPattern(int phase, IReadOnlyList<double> array)
|
||||
{
|
||||
Phase = phase;
|
||||
Array = array ?? throw new ArgumentNullException(nameof(array));
|
||||
|
@ -1,7 +1,9 @@
|
||||
// ReSharper disable RedundantDefaultMemberInitializer
|
||||
#nullable disable
|
||||
|
||||
// ReSharper disable RedundantDefaultMemberInitializer
|
||||
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
{
|
||||
using Core;
|
||||
using Operations.SpecialGraphicsState;
|
||||
using PdfPig.Core;
|
||||
using Tokens;
|
||||
|
@ -1,4 +1,6 @@
|
||||
// ReSharper disable RedundantDefaultMemberInitializer
|
||||
#nullable disable
|
||||
|
||||
// ReSharper disable RedundantDefaultMemberInitializer
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
{
|
||||
using Colors;
|
||||
|
@ -1,7 +1,7 @@
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
{
|
||||
using Colors;
|
||||
using System.Collections.Generic;
|
||||
using Colors;
|
||||
using Tokens;
|
||||
using UglyToad.PdfPig.Core;
|
||||
|
||||
@ -25,19 +25,19 @@
|
||||
/// </summary>
|
||||
/// <param name="colorspace">The color space name.</param>
|
||||
/// <param name="dictionary">The color space dictionary. Default value is null.</param>
|
||||
void SetStrokingColorspace(NameToken colorspace, DictionaryToken dictionary = null);
|
||||
void SetStrokingColorspace(NameToken colorspace, DictionaryToken? dictionary = null);
|
||||
|
||||
/// <summary>
|
||||
/// Set the current color space to use for nonstroking operations and initialize the nonstroking color.
|
||||
/// </summary>
|
||||
/// <param name="colorspace">The color space name.</param>
|
||||
/// <param name="dictionary">The color space dictionary. Default value is null.</param>
|
||||
void SetNonStrokingColorspace(NameToken colorspace, DictionaryToken dictionary = null);
|
||||
void SetNonStrokingColorspace(NameToken colorspace, DictionaryToken? dictionary = null);
|
||||
|
||||
/// <summary>
|
||||
/// Set the color to use for stroking operations using the current color space.
|
||||
/// </summary>
|
||||
void SetStrokingColor(IReadOnlyList<double> operands, NameToken patternName = null);
|
||||
void SetStrokingColor(IReadOnlyList<double> operands, NameToken? patternName = null);
|
||||
|
||||
/// <summary>
|
||||
/// Set the stroking color space to DeviceGray and set the gray level to use for stroking operations.
|
||||
@ -65,7 +65,7 @@
|
||||
/// <summary>
|
||||
/// Set the color to use for nonstroking operations using the current color space.
|
||||
/// </summary>
|
||||
void SetNonStrokingColor(IReadOnlyList<double> operands, NameToken patternName = null);
|
||||
void SetNonStrokingColor(IReadOnlyList<double> operands, NameToken? patternName = null);
|
||||
|
||||
/// <summary>
|
||||
/// Set the nonstroking color space to DeviceGray and set the gray level to use for nonstroking operations.
|
||||
|
@ -3,11 +3,9 @@
|
||||
using System.Collections.Generic;
|
||||
using Operations;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
internal interface IGraphicsStateOperationFactory
|
||||
{
|
||||
[CanBeNull]
|
||||
IGraphicsStateOperation Create(OperatorToken op, IReadOnlyList<IToken> operands);
|
||||
IGraphicsStateOperation? Create(OperatorToken op, IReadOnlyList<IToken> operands);
|
||||
}
|
||||
}
|
@ -132,7 +132,7 @@
|
||||
/// <summary>
|
||||
/// Indicate that a marked content region is started.
|
||||
/// </summary>
|
||||
void BeginMarkedContent(NameToken name, NameToken propertyDictionaryName, DictionaryToken properties);
|
||||
void BeginMarkedContent(NameToken name, NameToken? propertyDictionaryName, DictionaryToken? properties);
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the current marked content region is complete.
|
||||
|
@ -18,14 +18,15 @@
|
||||
/// <summary>
|
||||
/// Inline image properties.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<NameToken, IToken> Properties { get; internal set; }
|
||||
public IReadOnlyDictionary<NameToken, IToken>? Properties { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Inline image bytes.
|
||||
/// </summary>
|
||||
public IReadOnlyList<byte> Bytes { get; internal set; }
|
||||
public IReadOnlyList<byte>? Bytes { get; internal set; }
|
||||
|
||||
internal InlineImage CreateInlineImage(TransformationMatrix transformationMatrix, ILookupFilterProvider filterProvider,
|
||||
internal InlineImage CreateInlineImage(TransformationMatrix transformationMatrix,
|
||||
ILookupFilterProvider filterProvider,
|
||||
IPdfTokenScanner tokenScanner,
|
||||
RenderingIntent defaultRenderingIntent,
|
||||
IResourceStore resourceStore)
|
||||
@ -48,7 +49,7 @@
|
||||
|
||||
var bitsPerComponent = GetByKeys<NumericToken>(NameToken.BitsPerComponent, NameToken.Bpc, !isMask)?.Int ?? 1;
|
||||
|
||||
NameToken colorSpaceName = null;
|
||||
NameToken? colorSpaceName = null;
|
||||
|
||||
if (!isMask)
|
||||
{
|
||||
@ -110,8 +111,11 @@
|
||||
details);
|
||||
}
|
||||
|
||||
#nullable disable
|
||||
|
||||
// ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
|
||||
private T GetByKeys<T>(NameToken name1, NameToken name2, bool required) where T : IToken
|
||||
private T GetByKeys<T>(NameToken name1, NameToken name2, bool required)
|
||||
where T : class, IToken
|
||||
{
|
||||
if (Properties.TryGetValue(name1, out var val) && val is T result)
|
||||
{
|
||||
@ -131,7 +135,7 @@
|
||||
throw new PdfDocumentFormatException($"Inline image dictionary missing required entry {name1}/{name2}.");
|
||||
}
|
||||
|
||||
return default(T);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
private readonly Stack<MarkedContentElementActiveBuilder> builderStack = new Stack<MarkedContentElementActiveBuilder>();
|
||||
|
||||
private int number = -1;
|
||||
private MarkedContentElementActiveBuilder top;
|
||||
private MarkedContentElementActiveBuilder? top;
|
||||
|
||||
public bool CanPop => top != null;
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
builderStack.Push(top);
|
||||
}
|
||||
|
||||
public MarkedContentElement Pop(IPdfTokenScanner pdfScanner)
|
||||
public MarkedContentElement? Pop(IPdfTokenScanner pdfScanner)
|
||||
{
|
||||
var builder = builderStack.Pop();
|
||||
|
||||
@ -116,7 +116,7 @@
|
||||
public MarkedContentElement Build(IPdfTokenScanner pdfScanner)
|
||||
{
|
||||
var mcid = -1;
|
||||
if (properties.TryGet(NameToken.Mcid, pdfScanner, out NumericToken mcidToken))
|
||||
if (properties.TryGet(NameToken.Mcid, pdfScanner, out NumericToken? mcidToken))
|
||||
{
|
||||
mcid = mcidToken.Int;
|
||||
}
|
||||
@ -142,7 +142,7 @@
|
||||
}
|
||||
|
||||
var artifactType = ArtifactMarkedContentElement.ArtifactType.Unknown;
|
||||
if (properties.TryGet(NameToken.Type, pdfScanner, out IDataToken<string> typeToken)
|
||||
if (properties.TryGet(NameToken.Type, pdfScanner, out IDataToken<string>? typeToken)
|
||||
&& Enum.TryParse(typeToken.Data, true, out ArtifactMarkedContentElement.ArtifactType parsedType))
|
||||
{
|
||||
artifactType = parsedType;
|
||||
@ -152,12 +152,12 @@
|
||||
var attributeOwners = GetOptional(NameToken.O, pdfScanner);
|
||||
|
||||
var boundingBox = default(PdfRectangle?);
|
||||
if (properties.TryGet(NameToken.Bbox, pdfScanner, out ArrayToken arrayToken))
|
||||
if (properties.TryGet(NameToken.Bbox, pdfScanner, out ArrayToken? arrayToken))
|
||||
{
|
||||
NumericToken left = null;
|
||||
NumericToken bottom = null;
|
||||
NumericToken right = null;
|
||||
NumericToken top = null;
|
||||
NumericToken? left = null;
|
||||
NumericToken? bottom = null;
|
||||
NumericToken? right = null;
|
||||
NumericToken? top = null;
|
||||
|
||||
if (arrayToken.Length == 4)
|
||||
{
|
||||
@ -192,7 +192,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
return new ArtifactMarkedContentElement(mcid, name, properties, language,
|
||||
return new ArtifactMarkedContentElement(mcid, name,properties,
|
||||
language,
|
||||
actualText,
|
||||
alternateDescription,
|
||||
expandedForm,
|
||||
@ -208,10 +209,10 @@
|
||||
number);
|
||||
}
|
||||
|
||||
private string GetOptional(NameToken optionName, IPdfTokenScanner pdfScanner)
|
||||
private string? GetOptional(NameToken optionName, IPdfTokenScanner pdfScanner)
|
||||
{
|
||||
var result = default(string);
|
||||
if (properties.TryGet(optionName, pdfScanner, out IDataToken<string> token))
|
||||
if (properties.TryGet(optionName, pdfScanner, out IDataToken<string>? token))
|
||||
{
|
||||
result = token.Data;
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
{
|
||||
using System.IO;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
using Writer;
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -30,15 +29,13 @@
|
||||
/// The name of the property dictionary in the Properties subdictionary of the current resource dictionary.
|
||||
/// Can be <see langword="null"/> if the property dictionary is provided inline.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public NameToken PropertyDictionaryName { get; }
|
||||
public NameToken? PropertyDictionaryName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The marked-content sequence properties.
|
||||
/// Can be <see langword="null"/> if a name of the property dictionary is provided instead.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public DictionaryToken Properties { get; }
|
||||
public DictionaryToken? Properties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="BeginMarkedContentWithProperties"/>.
|
||||
@ -65,7 +62,7 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.BeginMarkedContent(Name, PropertyDictionaryName, Properties);
|
||||
operationContext.BeginMarkedContent(Name, PropertyDictionaryName, Properties!);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -80,7 +77,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
TokenWriter.WriteToken(Properties, stream);
|
||||
TokenWriter.WriteToken(Properties!, stream);
|
||||
}
|
||||
|
||||
stream.WriteWhiteSpace();
|
||||
|
@ -2,7 +2,6 @@
|
||||
{
|
||||
using System.IO;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
using Writer;
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -30,15 +29,13 @@
|
||||
/// The name of the property dictionary in the Properties subdictionary of the current resource dictionary.
|
||||
/// Can be <see langword="null"/> if the property dictionary is provided inline.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public NameToken PropertyDictionaryName { get; }
|
||||
public NameToken? PropertyDictionaryName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The marked-content point properties.
|
||||
/// Can be <see langword="null"/> if a name of the property dictionary is provided instead.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public DictionaryToken Properties { get; }
|
||||
public DictionaryToken? Properties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="DesignateMarkedContentPointWithProperties"/>.
|
||||
@ -80,7 +77,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
TokenWriter.WriteToken(Properties, stream);
|
||||
TokenWriter.WriteToken(Properties!, stream);
|
||||
}
|
||||
|
||||
stream.WriteWhiteSpace();
|
||||
|
@ -29,7 +29,7 @@
|
||||
/// <summary>
|
||||
/// The name of an entry in the Pattern subdictionary of the current resource dictionary.
|
||||
/// </summary>
|
||||
public NameToken PatternName { get; }
|
||||
public NameToken? PatternName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetNonStrokeColorAdvanced"/>.
|
||||
|
@ -29,7 +29,7 @@
|
||||
/// <summary>
|
||||
/// The name of an entry in the Pattern subdictionary of the current resource dictionary.
|
||||
/// </summary>
|
||||
public NameToken PatternName { get; }
|
||||
public NameToken? PatternName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetStrokeColor"/>.
|
||||
|
@ -2,7 +2,6 @@
|
||||
{
|
||||
using System.IO;
|
||||
using TextPositioning;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
@ -21,14 +20,12 @@
|
||||
/// <summary>
|
||||
/// The text to show as a <see cref="string"/>.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Text { get; }
|
||||
public string? Text { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The text to show as hex bytes.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public byte[] Bytes { get; }
|
||||
public byte[]? Bytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="MoveToNextLineShowText"/>.
|
||||
@ -53,7 +50,7 @@
|
||||
{
|
||||
var move = MoveToNextLine.Value;
|
||||
|
||||
var showText = Text != null ? new ShowText(Text) : new ShowText(Bytes);
|
||||
var showText = Text != null ? new ShowText(Text) : new ShowText(Bytes!);
|
||||
|
||||
move.Run(operationContext);
|
||||
showText.Run(operationContext);
|
||||
|
@ -3,7 +3,6 @@
|
||||
using System.IO;
|
||||
using TextPositioning;
|
||||
using TextState;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
@ -32,14 +31,12 @@
|
||||
/// <summary>
|
||||
/// The bytes of the text.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public byte[] Bytes { get; }
|
||||
public byte[]? Bytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The text to show.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Text { get; }
|
||||
public string? Text { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="MoveToNextLineShowTextWithSpacing"/>.
|
||||
@ -73,7 +70,7 @@
|
||||
var setWordSpacing = new SetWordSpacing(WordSpacing);
|
||||
var setCharacterSpacing = new SetCharacterSpacing(CharacterSpacing);
|
||||
var moveToNextLine = MoveToNextLine.Value;
|
||||
var showText = Text != null ? new ShowText(Text) : new ShowText(Bytes);
|
||||
var showText = Text != null ? new ShowText(Text) : new ShowText(Bytes!);
|
||||
|
||||
setWordSpacing.Run(operationContext);
|
||||
setCharacterSpacing.Run(operationContext);
|
||||
|
@ -1,8 +1,7 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextShowing
|
||||
{
|
||||
using System.IO;
|
||||
using PdfPig.Core;
|
||||
using Util.JetBrains.Annotations;
|
||||
using System.IO;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
@ -34,14 +33,12 @@
|
||||
/// <summary>
|
||||
/// The text string to show.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Text { get; }
|
||||
public string? Text { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The bytes of the string to show.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public byte[] Bytes { get; }
|
||||
public byte[]? Bytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="ShowText"/>.
|
||||
@ -67,7 +64,7 @@
|
||||
operationContext.ShowText(input);
|
||||
}
|
||||
|
||||
string EscapeText(string text)
|
||||
string? EscapeText(string? text)
|
||||
{
|
||||
if (text is null) return null;
|
||||
// Fix Issue 350 from PDF Spec 1.7 (page 408) on handling 'special characters' of '(', ')' and '\'.
|
||||
|
@ -4,7 +4,6 @@
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
@ -25,7 +24,6 @@
|
||||
/// <summary>
|
||||
/// The name of the font as defined in the resource dictionary.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public NameToken Font { get; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -29,7 +29,7 @@
|
||||
/// <summary>
|
||||
/// The fill color.
|
||||
/// </summary>
|
||||
public IColor FillColor { get; internal set; }
|
||||
public IColor? FillColor { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the path is stroked.
|
||||
@ -39,7 +39,7 @@
|
||||
/// <summary>
|
||||
/// The stroke color.
|
||||
/// </summary>
|
||||
public IColor StrokeColor { get; internal set; }
|
||||
public IColor? StrokeColor { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Thickness in user space units of path to be stroked.
|
||||
|
@ -30,7 +30,7 @@ namespace UglyToad.PdfPig.Graphics
|
||||
|
||||
public ReflectionGraphicsStateOperationFactory()
|
||||
{
|
||||
var assemblyTypes = Assembly.GetAssembly(typeof(ReflectionGraphicsStateOperationFactory)).GetTypes();
|
||||
var assemblyTypes = Assembly.GetAssembly(typeof(ReflectionGraphicsStateOperationFactory))!.GetTypes();
|
||||
|
||||
var result = new Dictionary<string, Type>();
|
||||
|
||||
@ -45,7 +45,7 @@ namespace UglyToad.PdfPig.Graphics
|
||||
throw new InvalidOperationException("An operation type was defined without the public const Symbol being declared. Type was: " + assemblyType.FullName);
|
||||
}
|
||||
|
||||
var value = symbol.GetValue(null).ToString();
|
||||
var value = symbol.GetValue(null)!.ToString()!;
|
||||
|
||||
result[value] = assemblyType;
|
||||
}
|
||||
@ -114,7 +114,7 @@ namespace UglyToad.PdfPig.Graphics
|
||||
return numeric.Data;
|
||||
}
|
||||
|
||||
public IGraphicsStateOperation Create(OperatorToken op, IReadOnlyList<IToken> operands)
|
||||
public IGraphicsStateOperation? Create(OperatorToken op, IReadOnlyList<IToken> operands)
|
||||
{
|
||||
switch (op.Data)
|
||||
{
|
||||
@ -388,7 +388,7 @@ namespace UglyToad.PdfPig.Graphics
|
||||
return new ShowTextsWithPositioning(array);
|
||||
}
|
||||
|
||||
if (!operations.TryGetValue(op.Data, out Type operationType))
|
||||
if (!operations.TryGetValue(op.Data, out Type? operationType))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -405,7 +405,7 @@ namespace UglyToad.PdfPig.Graphics
|
||||
|
||||
if (constructor.IsPrivate)
|
||||
{
|
||||
return (IGraphicsStateOperation)operationType.GetField("Value").GetValue(null);
|
||||
return (IGraphicsStateOperation)operationType.GetField("Value")?.GetValue(null)!;
|
||||
}
|
||||
|
||||
var parameters = constructor.GetParameters();
|
||||
|
@ -5,7 +5,6 @@
|
||||
using Core;
|
||||
using PdfPig.Core;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
using XObjects;
|
||||
|
||||
/// <summary>
|
||||
@ -21,7 +20,6 @@
|
||||
/// <summary>
|
||||
/// The XObject stream.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public StreamToken Stream { get; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace UglyToad.PdfPig.IO
|
||||
#nullable disable
|
||||
|
||||
namespace UglyToad.PdfPig.IO
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user