From a412a239beccb99d8bbd73e2c64744b013b5c563 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Sun, 17 Mar 2024 11:51:40 -0700 Subject: [PATCH] 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) --- src/UglyToad.PdfPig/AcroForms/AcroForm.cs | 2 - .../AcroForms/AcroFormExtensions.cs | 4 +- .../AcroForms/AcroFormFactory.cs | 92 +- .../AcroForms/Fields/AcroChoiceOption.cs | 4 +- .../AcroForms/Fields/AcroComboBoxField.cs | 13 +- .../AcroForms/Fields/AcroFieldBase.cs | 6 +- .../Fields/AcroFieldCommonInformation.cs | 14 +- .../AcroForms/Fields/AcroListBoxField.cs | 8 +- .../AcroForms/Fields/AcroTextField.cs | 4 +- src/UglyToad.PdfPig/Actions/ActionProvider.cs | 15 +- src/UglyToad.PdfPig/Actions/UriAction.cs | 4 +- .../AdvancedPdfDocumentAccess.cs | 15 +- src/UglyToad.PdfPig/Annotations/Annotation.cs | 41 +- .../Annotations/AnnotationBorder.cs | 6 +- .../Annotations/AnnotationProvider.cs | 36 +- .../Annotations/AppearanceStream.cs | 6 +- .../Annotations/AppearanceStreamFactory.cs | 5 +- .../Annotations/HyperlinkFactory.cs | 6 +- .../Content/ArtifactMarkedContentElement.cs | 18 +- .../Content/BasePageFactory.cs | 13 +- src/UglyToad.PdfPig/Content/Catalog.cs | 2 - .../Content/DocumentInformation.cs | 54 +- src/UglyToad.PdfPig/Content/IPdfImage.cs | 7 +- src/UglyToad.PdfPig/Content/IResourceStore.cs | 11 +- src/UglyToad.PdfPig/Content/InlineImage.cs | 9 +- src/UglyToad.PdfPig/Content/Letter.cs | 3 +- .../Content/MarkedContentElement.cs | 19 +- .../Content/OptionalContentGroupElement.cs | 36 +- src/UglyToad.PdfPig/Content/Page.cs | 10 +- .../Content/PageRotationDegrees.cs | 2 +- src/UglyToad.PdfPig/Content/PageSize.cs | 8 +- .../Content/PageTreeMembers.cs | 4 +- src/UglyToad.PdfPig/Content/PageTreeNode.cs | 10 +- src/UglyToad.PdfPig/Content/Pages.cs | 8 +- src/UglyToad.PdfPig/Content/PagesFactory.cs | 22 +- src/UglyToad.PdfPig/Content/ResourceStore.cs | 50 +- src/UglyToad.PdfPig/Content/Word.cs | 2 +- src/UglyToad.PdfPig/Content/XmpMetadata.cs | 2 - .../CrossReference/CrossReferenceTable.cs | 4 - .../CrossReferenceTablePartBuilder.cs | 4 +- .../CrossReference/TrailerDictionary.cs | 5 +- .../Encryption/EncryptionDictionary.cs | 22 +- .../Encryption/EncryptionDictionaryFactory.cs | 27 +- .../Encryption/EncryptionHandler.cs | 25 +- .../PdfDocumentEncryptedException.cs | 2 +- .../Filters/CcittFaxDecoderStream.cs | 8 +- src/UglyToad.PdfPig/Filters/LzwFilter.cs | 8 +- src/UglyToad.PdfPig/Functions/PdfFunction.cs | 16 +- .../Functions/PdfFunctionType0.cs | 11 +- .../Functions/PdfFunctionType2.cs | 4 +- .../Functions/PdfFunctionType3.cs | 4 +- .../Functions/PdfFunctionType4.cs | 2 +- .../Geometry/ClipperLibrary/Clipper.cs | 2 + .../Geometry/ClipperLibrary/ClipperBase.cs | 1 + .../Geometry/ClipperLibrary/ClipperInt128.cs | 2 +- .../ClipperLibrary/ClipperIntersectNode.cs | 3 + .../Geometry/ClipperLibrary/ClipperJoin.cs | 3 + .../ClipperLibrary/ClipperLocalMinima.cs | 3 + .../Geometry/ClipperLibrary/ClipperMaxima.cs | 3 + .../Geometry/ClipperLibrary/ClipperOutPt.cs | 3 + .../Geometry/ClipperLibrary/ClipperOutRec.cs | 3 + .../Geometry/ClipperLibrary/ClipperPoints.cs | 2 +- .../ClipperLibrary/ClipperPolyNode.cs | 3 + .../ClipperLibrary/ClipperScanbeam.cs | 3 + .../Geometry/ClipperLibrary/ClipperTEdge.cs | 3 + .../Geometry/ClippingExtensions.cs | 2 +- .../Geometry/GeometryExtensions.cs | 16 +- .../Graphics/BaseStreamProcessor.cs | 72 +- .../Graphics/ColorSpaceContext.cs | 8 +- .../Colors/CIEBasedColorSpaceTransformer.cs | 4 +- .../Graphics/Colors/CMYKColor.cs | 21 +- .../Graphics/Colors/ChromaticAdaptation.cs | 4 +- .../Graphics/Colors/ColorSpaceDetails.cs | 87 +- .../Graphics/Colors/GrayColor.cs | 14 +- .../Graphics/Colors/PatternColor.cs | 32 +- .../Graphics/Colors/RGBColor.cs | 23 +- .../Graphics/Colors/RGBWorkingSpace.cs | 54 +- .../Graphics/Colors/ResourceColorSpace.cs | 4 +- .../Graphics/Colors/Shading.cs | 36 +- .../Graphics/ContentStreamProcessor.cs | 11 +- .../Graphics/Core/LineDashPattern.cs | 4 +- .../Graphics/CurrentFontState.cs | 6 +- .../Graphics/CurrentGraphicsState.cs | 4 +- .../Graphics/IColorSpaceContext.cs | 10 +- .../IGraphicsStateOperationFactory.cs | 4 +- .../Graphics/IOperationContext.cs | 2 +- .../Graphics/InlineImageBuilder.cs | 16 +- .../Graphics/MarkedContentStack.cs | 25 +- .../BeginMarkedContentWithProperties.cs | 11 +- ...signateMarkedContentPointWithProperties.cs | 9 +- .../Operations/SetNonStrokeColorAdvanced.cs | 2 +- .../Operations/SetStrokeColorAdvanced.cs | 2 +- .../TextShowing/MoveToNextLineShowText.cs | 9 +- .../MoveToNextLineShowTextWithSpacing.cs | 9 +- .../Operations/TextShowing/ShowText.cs | 11 +- .../Operations/TextState/SetFontAndSize.cs | 2 - src/UglyToad.PdfPig/Graphics/PdfPath.cs | 4 +- ...ReflectionGraphicsStateOperationFactory.cs | 10 +- .../Graphics/XObjectContentRecord.cs | 2 - src/UglyToad.PdfPig/IO/RandomAccessBuffer.cs | 4 +- src/UglyToad.PdfPig/Images/Png/Pixel.cs | 25 +- src/UglyToad.PdfPig/Images/Png/Png.cs | 6 +- .../Images/Png/PngFromPdfImageFactory.cs | 11 +- src/UglyToad.PdfPig/Images/Png/PngOpener.cs | 4 +- .../Images/Png/PngOpenerSettings.cs | 2 +- src/UglyToad.PdfPig/Images/Png/RawPngData.cs | 8 +- .../Outline/BookmarksProvider.cs | 10 +- .../Destinations/DestinationProvider.cs | 14 +- .../Outline/Destinations/NamedDestinations.cs | 5 +- .../Destinations/NamedDestinationsProvider.cs | 30 +- .../Parser/DocumentInformationFactory.cs | 8 +- .../FileStructure/CrossReferenceParser.cs | 5 +- .../Parser/FileStructure/FileHeaderParser.cs | 9 +- .../Parser/FileStructure/FileTrailerParser.cs | 2 +- .../FileStructure/XrefOffsetValidator.cs | 16 +- .../Parser/PageContentParser.cs | 7 +- .../Parser/Parts/BruteForceSearcher.cs | 4 +- .../Parser/Parts/DirectObjectFinder.cs | 11 +- .../Parser/Parts/NameTreeParser.cs | 10 +- .../Parser/PdfDocumentFactory.cs | 31 +- src/UglyToad.PdfPig/PdfDocument.cs | 43 +- src/UglyToad.PdfPig/PdfExtensions.cs | 8 +- .../CharacterIdentifierToGlyphIndexMap.cs | 4 +- .../PdfFonts/CidFonts/ICidFont.cs | 13 +- .../PdfFonts/CidFonts/ICidFontProgram.cs | 7 +- .../CidFonts/PdfCidCompactFontFormatFont.cs | 7 +- .../PdfFonts/CidFonts/PdfCidTrueTypeFont.cs | 9 +- .../PdfFonts/CidFonts/Type0CidFont.cs | 12 +- .../PdfFonts/CidFonts/Type2CidFont.cs | 16 +- .../CidFonts/VerticalWritingMetrics.cs | 18 +- src/UglyToad.PdfPig/PdfFonts/Cmap/CMap.cs | 14 +- .../PdfFonts/Cmap/CMapCache.cs | 3 +- .../CharacterIdentifierSystemInfoBuilder.cs | 9 +- .../PdfFonts/Cmap/CharacterMapBuilder.cs | 14 +- .../PdfFonts/Composite/ToUnicodeCMap.cs | 18 +- .../PdfFonts/Composite/Type0Font.cs | 37 +- .../PdfFonts/FontDescriptor.cs | 19 +- src/UglyToad.PdfPig/PdfFonts/FontDetails.cs | 4 +- src/UglyToad.PdfPig/PdfFonts/FontFactory.cs | 2 +- src/UglyToad.PdfPig/PdfFonts/IFont.cs | 11 +- .../PdfFonts/Parser/CMapParser.cs | 7 +- .../PdfFonts/Parser/EncodingReader.cs | 18 +- .../Parser/FontDictionaryAccessHelper.cs | 2 +- .../Parser/Handlers/TrueTypeFontHandler.cs | 22 +- .../Parser/Handlers/Type0FontHandler.cs | 23 +- .../Parser/Handlers/Type1FontHandler.cs | 12 +- .../Parser/Handlers/Type3FontHandler.cs | 11 +- .../PdfFonts/Parser/IEncodingReader.cs | 6 +- .../Parser/Parts/BaseFontRangeParser.cs | 8 +- .../PdfFonts/Parser/Parts/CidFontFactory.cs | 33 +- .../Parser/Parts/FontDescriptorFactory.cs | 8 +- .../PdfFonts/Simple/TrueTypeSimpleFont.cs | 46 +- .../TrueTypeStandard14FallbackSimpleFont.cs | 15 +- .../PdfFonts/Simple/Type1FontSimple.cs | 21 +- .../PdfFonts/Simple/Type1Standard14Font.cs | 17 +- .../PdfFonts/Simple/Type3Font.cs | 11 +- .../Polyfills/NullableAnnotations.cs | 51 + src/UglyToad.PdfPig/Structure.cs | 3 - .../Scanner/IObjectLocationProvider.cs | 3 +- .../Scanner/ObjectLocationProvider.cs | 9 +- .../Tokenization/Scanner/PdfTokenScanner.cs | 31 +- src/UglyToad.PdfPig/UglyToad.PdfPig.csproj | 4 +- src/UglyToad.PdfPig/Util/Annotations.cs | 1067 ----------------- .../Util/ColorSpaceDetailsParser.cs | 108 +- src/UglyToad.PdfPig/Util/Diacritics.cs | 3 +- .../Util/DictionaryTokenExtensions.cs | 34 +- src/UglyToad.PdfPig/Util/Matrix3x3.cs | 9 +- src/UglyToad.PdfPig/Util/PatternParser.cs | 22 +- src/UglyToad.PdfPig/Util/PdfFunctionParser.cs | 33 +- src/UglyToad.PdfPig/Util/ShadingParser.cs | 64 +- src/UglyToad.PdfPig/Util/StackDictionary.cs | 7 +- .../Writer/Fonts/IWritingFont.cs | 4 +- .../Writer/Fonts/Standard14WritingFont.cs | 2 +- .../Writer/Fonts/TrueTypeWritingFont.cs | 3 +- .../Writer/IPdfStreamWriter.cs | 2 +- .../Writer/NoTextTokenWriter.cs | 5 +- .../Writer/PdfABaselineRuleBuilder.cs | 2 +- .../Writer/PdfDedupStreamWriter.cs | 4 +- .../Writer/PdfDocumentBuilder.cs | 75 +- src/UglyToad.PdfPig/Writer/PdfMerger.cs | 66 +- src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs | 33 +- src/UglyToad.PdfPig/Writer/PdfStreamWriter.cs | 10 +- src/UglyToad.PdfPig/Writer/PdfTextRemover.cs | 10 +- src/UglyToad.PdfPig/Writer/TokenWriter.cs | 8 +- src/UglyToad.PdfPig/Writer/WriterUtil.cs | 25 +- src/UglyToad.PdfPig/Writer/Xmp/XmpWriter.cs | 14 +- .../XObjects/XObjectFactory.cs | 20 +- src/UglyToad.PdfPig/XObjects/XObjectImage.cs | 16 +- .../UglyToad.PdfPig.Package.csproj | 2 +- 189 files changed, 1392 insertions(+), 2384 deletions(-) create mode 100644 src/UglyToad.PdfPig/Polyfills/NullableAnnotations.cs delete mode 100644 src/UglyToad.PdfPig/Util/Annotations.cs diff --git a/src/UglyToad.PdfPig/AcroForms/AcroForm.cs b/src/UglyToad.PdfPig/AcroForms/AcroForm.cs index 212b7b3d5..1ba48ca53 100644 --- a/src/UglyToad.PdfPig/AcroForms/AcroForm.cs +++ b/src/UglyToad.PdfPig/AcroForms/AcroForm.cs @@ -6,7 +6,6 @@ using Core; using Fields; using Tokens; - using Util.JetBrains.Annotations; /// /// A collection of interactive fields for gathering data from a user through dropdowns, textboxes, checkboxes, etc. @@ -22,7 +21,6 @@ public class AcroForm /// /// The raw PDF dictionary which is the root form object. /// - [NotNull] public DictionaryToken Dictionary { get; } /// diff --git a/src/UglyToad.PdfPig/AcroForms/AcroFormExtensions.cs b/src/UglyToad.PdfPig/AcroForms/AcroFormExtensions.cs index 86ac5d920..84659519c 100644 --- a/src/UglyToad.PdfPig/AcroForms/AcroFormExtensions.cs +++ b/src/UglyToad.PdfPig/AcroForms/AcroFormExtensions.cs @@ -42,12 +42,12 @@ public static IEnumerable GetFields(this AcroFieldBase fieldBase) /// /// Get string values of field. /// - public static KeyValuePair GetFieldValue(this AcroFieldBase fieldBase) + public static KeyValuePair 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, ""), }; } diff --git a/src/UglyToad.PdfPig/AcroForms/AcroFormFactory.cs b/src/UglyToad.PdfPig/AcroForms/AcroFormFactory.cs index 2d5102236..e63295ffa 100644 --- a/src/UglyToad.PdfPig/AcroForms/AcroFormFactory.cs +++ b/src/UglyToad.PdfPig/AcroForms/AcroFormFactory.cs @@ -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; /// /// Extracts the from the document, if available. @@ -43,15 +42,14 @@ public AcroFormFactory(IPdfTokenScanner tokenScanner, ILookupFilterProvider filt /// Retrieve the from the document, if applicable. /// /// The if the document contains one. - [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(); @@ -59,12 +57,12 @@ public AcroForm GetAcroForm(Catalog catalog) 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 @@ public AcroForm GetAcroForm(Catalog catalog) } 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 @@ private AcroFieldBase GetAcroField(DictionaryToken fieldDictionary, Catalog cata 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 @@ private AcroFieldBase GetAcroField(DictionaryToken fieldDictionary, Catalog cata 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 @@ private AcroFieldBase GetTextField(DictionaryToken fieldDictionary, NameToken fi 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 @@ private AcroFieldBase GetChoiceField(DictionaryToken fieldDictionary, NameToken var selectedOptions = Array.Empty(); 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 @@ private AcroFieldBase GetChoiceField(DictionaryToken fieldDictionary, NameToken } 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 @@ private AcroFieldBase GetChoiceField(DictionaryToken fieldDictionary, NameToken } var options = new List(); - 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 @@ private AcroFieldBase GetChoiceField(DictionaryToken fieldDictionary, NameToken } 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 @@ private AcroFieldBase GetChoiceField(DictionaryToken fieldDictionary, NameToken } 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 @@ private AcroFieldBase GetChoiceField(DictionaryToken fieldDictionary, NameToken } 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 AcroFieldBase GetChoiceField(DictionaryToken fieldDictionary, NameToken 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 @@ private AcroFieldBase GetChoiceField(DictionaryToken fieldDictionary, NameToken } 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 @@ private static (DictionaryToken dictionary, bool inheritsValue) CreateInheritedD return (new DictionaryToken(inheritedDictionary), inheritsValue); } - private static bool IsChoiceSelected(IReadOnlyList selectedOptionNames, IReadOnlyList selectedOptionIndices, int index, string name) + private static bool IsChoiceSelected(IReadOnlyList selectedOptionNames, IReadOnlyList? selectedOptionIndices, int index, string name) { if (selectedOptionNames.Count == 0) { diff --git a/src/UglyToad.PdfPig/AcroForms/Fields/AcroChoiceOption.cs b/src/UglyToad.PdfPig/AcroForms/Fields/AcroChoiceOption.cs index 31faed41a..ce2df71e3 100644 --- a/src/UglyToad.PdfPig/AcroForms/Fields/AcroChoiceOption.cs +++ b/src/UglyToad.PdfPig/AcroForms/Fields/AcroChoiceOption.cs @@ -23,7 +23,7 @@ public class AcroChoiceOption /// /// The value of the option when the form is exported. /// - public string ExportValue { get; } + public string? ExportValue { get; } /// /// Whether the field defined an export value for this option. @@ -33,7 +33,7 @@ public class AcroChoiceOption /// /// Create a new . /// - 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; diff --git a/src/UglyToad.PdfPig/AcroForms/Fields/AcroComboBoxField.cs b/src/UglyToad.PdfPig/AcroForms/Fields/AcroComboBoxField.cs index 1f5dcfb92..a4f88e4ba 100644 --- a/src/UglyToad.PdfPig/AcroForms/Fields/AcroComboBoxField.cs +++ b/src/UglyToad.PdfPig/AcroForms/Fields/AcroComboBoxField.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using Core; using Tokens; - using Util.JetBrains.Annotations; /// /// @@ -21,20 +20,17 @@ public class AcroComboBoxField : AcroFieldBase /// /// The options to be presented to the user. /// - [NotNull] public IReadOnlyList Options { get; } /// /// The names of any currently selected options. /// - [NotNull] public IReadOnlyList SelectedOptions { get; } /// /// For multiple select lists with duplicate names gives the indices of the selected options. /// - [CanBeNull] - public IReadOnlyList SelectedOptionIndices { get; } + public IReadOnlyList? SelectedOptionIndices { get; } /// /// @@ -49,10 +45,13 @@ public class AcroComboBoxField : AcroFieldBase /// The names of the selected options. /// The number of the page this field appears on. /// The location of this field on the page. - public AcroComboBoxField(DictionaryToken dictionary, string fieldType, AcroChoiceFieldFlags fieldFlags, + public AcroComboBoxField( + DictionaryToken dictionary, + string fieldType, + AcroChoiceFieldFlags fieldFlags, AcroFieldCommonInformation information, IReadOnlyList options, IReadOnlyList selectedOptions, - IReadOnlyList selectedOptionIndices, + IReadOnlyList? selectedOptionIndices, int? pageNumber, PdfRectangle? bounds) : base(dictionary, fieldType, (uint)fieldFlags, AcroFieldType.ComboBox, information, diff --git a/src/UglyToad.PdfPig/AcroForms/Fields/AcroFieldBase.cs b/src/UglyToad.PdfPig/AcroForms/Fields/AcroFieldBase.cs index 13b72f89b..f8ded2a7e 100644 --- a/src/UglyToad.PdfPig/AcroForms/Fields/AcroFieldBase.cs +++ b/src/UglyToad.PdfPig/AcroForms/Fields/AcroFieldBase.cs @@ -1,9 +1,8 @@ namespace UglyToad.PdfPig.AcroForms.Fields { - using System; using Core; + using System; using Tokens; - using Util.JetBrains.Annotations; /// /// A field in an interactive . @@ -13,13 +12,11 @@ public abstract class AcroFieldBase /// /// The raw PDF dictionary for this field. /// - [NotNull] public DictionaryToken Dictionary { get; } /// /// The representing the type of this field in PDF format. /// - [NotNull] public string RawFieldType { get; } /// @@ -35,7 +32,6 @@ public abstract class AcroFieldBase /// /// The optional information common to all types of field. /// - [NotNull] public AcroFieldCommonInformation Information { get; } /// diff --git a/src/UglyToad.PdfPig/AcroForms/Fields/AcroFieldCommonInformation.cs b/src/UglyToad.PdfPig/AcroForms/Fields/AcroFieldCommonInformation.cs index 9f63adc3f..7fe001adb 100644 --- a/src/UglyToad.PdfPig/AcroForms/Fields/AcroFieldCommonInformation.cs +++ b/src/UglyToad.PdfPig/AcroForms/Fields/AcroFieldCommonInformation.cs @@ -1,7 +1,6 @@ namespace UglyToad.PdfPig.AcroForms.Fields { using Core; - using Util.JetBrains.Annotations; /// /// Information from the field dictionary which is common across all field types. @@ -18,26 +17,23 @@ public class AcroFieldCommonInformation /// 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. /// - [CanBeNull] - public string PartialName { get; } + public string? PartialName { get; } /// /// 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. /// - [CanBeNull] - public string AlternateName { get; } + public string? AlternateName { get; } /// /// The mapping name used when exporting form field data from the document. /// - [CanBeNull] - public string MappingName { get; } + public string? MappingName { get; } /// /// Create a new . /// - 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 @@ public AcroFieldCommonInformation(IndirectReference? parent, string partialName, /// public override string ToString() { - string AppendIfNotNull(string val, string label, string result) + string AppendIfNotNull(string? val, string label, string result) { if (val is null) { diff --git a/src/UglyToad.PdfPig/AcroForms/Fields/AcroListBoxField.cs b/src/UglyToad.PdfPig/AcroForms/Fields/AcroListBoxField.cs index bd1de8813..f47502713 100644 --- a/src/UglyToad.PdfPig/AcroForms/Fields/AcroListBoxField.cs +++ b/src/UglyToad.PdfPig/AcroForms/Fields/AcroListBoxField.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using Core; using Tokens; - using Util.JetBrains.Annotations; /// /// @@ -20,20 +19,17 @@ public class AcroListBoxField : AcroFieldBase /// /// The options to be presented to the user. /// - [NotNull] public IReadOnlyList Options { get; } /// /// The names of any currently selected options. /// - [NotNull] public IReadOnlyList SelectedOptions { get; } /// /// For multiple select lists with duplicate names gives the indices of the selected options. /// - [CanBeNull] - public IReadOnlyList SelectedOptionIndices { get; } + public IReadOnlyList? SelectedOptionIndices { get; } /// /// For scrollable list boxes gives the index of the first visible option. @@ -62,7 +58,7 @@ public class AcroListBoxField : AcroFieldBase public AcroListBoxField(DictionaryToken dictionary, string fieldType, AcroChoiceFieldFlags fieldFlags, AcroFieldCommonInformation information, IReadOnlyList options, IReadOnlyList selectedOptions, - IReadOnlyList selectedOptionIndices, + IReadOnlyList? selectedOptionIndices, int? topIndex, int? pageNumber, PdfRectangle? bounds) : diff --git a/src/UglyToad.PdfPig/AcroForms/Fields/AcroTextField.cs b/src/UglyToad.PdfPig/AcroForms/Fields/AcroTextField.cs index 9f807f088..b5c5d9b32 100644 --- a/src/UglyToad.PdfPig/AcroForms/Fields/AcroTextField.cs +++ b/src/UglyToad.PdfPig/AcroForms/Fields/AcroTextField.cs @@ -19,7 +19,7 @@ public class AcroTextField : AcroFieldBase /// The value of the text in this text field. /// This can be if no value has been set. /// - public string Value { get; } + public string? Value { get; } /// /// The optional maximum length of the text field. @@ -50,7 +50,7 @@ public class AcroTextField : AcroFieldBase /// The location of this field on the page. public AcroTextField(DictionaryToken dictionary, string fieldType, AcroTextFieldFlags fieldFlags, AcroFieldCommonInformation information, - string value, + string? value, int? maxLength, int? pageNumber, PdfRectangle? bounds) : diff --git a/src/UglyToad.PdfPig/Actions/ActionProvider.cs b/src/UglyToad.PdfPig/Actions/ActionProvider.cs index 0f1bd1c4d..3e15ec74e 100644 --- a/src/UglyToad.PdfPig/Actions/ActionProvider.cs +++ b/src/UglyToad.PdfPig/Actions/ActionProvider.cs @@ -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 @@ internal static class ActionProvider /// /// Get an action (A) from dictionary. If GoTo, GoToR or GoToE, also fetches the action destination. /// - 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 @@ internal static bool TryGetAction(DictionaryToken dictionary, fileSpecification = null; } - result = new GoToEAction(destination, fileSpecification); + result = new GoToEAction(destination, fileSpecification!); return true; } } diff --git a/src/UglyToad.PdfPig/Actions/UriAction.cs b/src/UglyToad.PdfPig/Actions/UriAction.cs index aed209ac3..a05eb015e 100644 --- a/src/UglyToad.PdfPig/Actions/UriAction.cs +++ b/src/UglyToad.PdfPig/Actions/UriAction.cs @@ -1,4 +1,6 @@ -namespace UglyToad.PdfPig.Actions +#nullable disable + +namespace UglyToad.PdfPig.Actions { /// /// Action to open a URI diff --git a/src/UglyToad.PdfPig/AdvancedPdfDocumentAccess.cs b/src/UglyToad.PdfPig/AdvancedPdfDocumentAccess.cs index 5e3e02602..49d6053ce 100644 --- a/src/UglyToad.PdfPig/AdvancedPdfDocumentAccess.cs +++ b/src/UglyToad.PdfPig/AdvancedPdfDocumentAccess.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Content; using Core; using Filters; @@ -37,14 +38,14 @@ internal AdvancedPdfDocumentAccess(IPdfTokenScanner pdfScanner, /// /// The set of embedded files in this document. /// if this document contains more than zero embedded files, otherwise . - public bool TryGetEmbeddedFiles(out IReadOnlyList embeddedFiles) + public bool TryGetEmbeddedFiles([NotNullWhen(true)] out IReadOnlyList? 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 @@ public bool TryGetEmbeddedFiles(out IReadOnlyList embeddedFiles) 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 fileSpecificationToken)) + if (fileDescriptorDictionaryToken.TryGet(NameToken.F, pdfScanner, out IDataToken? fileSpecificationToken)) { fileSpecification = fileSpecificationToken.Data; } diff --git a/src/UglyToad.PdfPig/Annotations/Annotation.cs b/src/UglyToad.PdfPig/Annotations/Annotation.cs index 7be1ebd2c..54ba5a0aa 100644 --- a/src/UglyToad.PdfPig/Annotations/Annotation.cs +++ b/src/UglyToad.PdfPig/Annotations/Annotation.cs @@ -5,22 +5,20 @@ using Core; using Actions; using Tokens; - using Util.JetBrains.Annotations; /// /// An annotation on a page in a PDF document. /// 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; /// /// The underlying PDF dictionary which this annotation was created from. /// - [NotNull] public DictionaryToken AnnotationDictionary { get; } /// @@ -36,20 +34,17 @@ public class Annotation /// /// The annotation text, or if the annotation does not display text, a description of the annotation's contents. Optional. /// - [CanBeNull] - public string Content { get; } + public string? Content { get; } /// /// The name of this annotation which should be unique per page. Optional. /// - [CanBeNull] - public string Name { get; } + public string? Name { get; } /// /// The date and time the annotation was last modified, can be in any format. Optional. /// - [CanBeNull] - public string ModifiedDate { get; } + public string? ModifiedDate { get; } /// /// Flags defining the appearance and behaviour of this annotation. @@ -71,7 +66,7 @@ public class Annotation /// /// Action for this annotation, if any (can be null) /// - public PdfAction Action { get; } + public PdfAction? Action { get; } /// /// Indicates if a normal appearance is present for this annotation @@ -91,7 +86,7 @@ public class Annotation /// /// The this annotation was in reply to. Can be /// - public Annotation InReplyTo { get; } + public Annotation? InReplyTo { get; } /// /// Create a new . @@ -100,18 +95,18 @@ public Annotation( DictionaryToken annotationDictionary, AnnotationType type, PdfRectangle rectangle, - string content, - string name, - string modifiedDate, + string? content, + string? name, + string? modifiedDate, AnnotationFlags flags, AnnotationBorder border, IReadOnlyList 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; diff --git a/src/UglyToad.PdfPig/Annotations/AnnotationBorder.cs b/src/UglyToad.PdfPig/Annotations/AnnotationBorder.cs index f18d5af84..a7647a78e 100644 --- a/src/UglyToad.PdfPig/Annotations/AnnotationBorder.cs +++ b/src/UglyToad.PdfPig/Annotations/AnnotationBorder.cs @@ -1,7 +1,6 @@ namespace UglyToad.PdfPig.Annotations { using System.Collections.Generic; - using Util.JetBrains.Annotations; /// /// A border for a PDF object. @@ -31,13 +30,12 @@ public class AnnotationBorder /// /// The dash pattern for the border lines if provided. Optional. /// - [CanBeNull] - public IReadOnlyList LineDashPattern { get; } + public IReadOnlyList? LineDashPattern { get; } /// /// Create a new . /// - public AnnotationBorder(double horizontalCornerRadius, double verticalCornerRadius, double borderWidth, IReadOnlyList lineDashPattern) + public AnnotationBorder(double horizontalCornerRadius, double verticalCornerRadius, double borderWidth, IReadOnlyList? lineDashPattern) { HorizontalCornerRadius = horizontalCornerRadius; VerticalCornerRadius = verticalCornerRadius; diff --git a/src/UglyToad.PdfPig/Annotations/AnnotationProvider.cs b/src/UglyToad.PdfPig/Annotations/AnnotationProvider.cs index 34596b917..2ce4dacbe 100644 --- a/src/UglyToad.PdfPig/Annotations/AnnotationProvider.cs +++ b/src/UglyToad.PdfPig/Annotations/AnnotationProvider.cs @@ -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 @@ public IEnumerable GetAnnotations() { var lookupAnnotations = new Dictionary(); - 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 @@ public IEnumerable GetAnnotations() 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 @@ public IEnumerable GetAnnotations() } var quadPointRectangles = new List(); - if (annotationDictionary.TryGet(NameToken.Quadpoints, tokenScanner, out ArrayToken quadPointsArray)) + if (annotationDictionary.TryGet(NameToken.Quadpoints, tokenScanner, out ArrayToken? quadPointsArray)) { var values = new List(); for (var i = 0; i < quadPointsArray.Length; i++) @@ -128,14 +128,14 @@ public IEnumerable GetAnnotations() } } - 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 @@ public IEnumerable GetAnnotations() } } - string appearanceState = null; + string? appearanceState = null; if (annotationDictionary.TryGet(NameToken.As, out NameToken appearanceStateToken)) { appearanceState = appearanceStateToken.Data; @@ -185,7 +185,7 @@ public IEnumerable GetAnnotations() } } - 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 @@ internal PdfAction GetAction(DictionaryToken annotationDictionary) 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 @@ private string GetNamedString(NameToken name, DictionaryToken dictionary) { content = contentHex.Data; } - else if (DirectObjectFinder.TryGet(contentToken, tokenScanner, out StringToken indirectContentString)) + else if (DirectObjectFinder.TryGet(contentToken, tokenScanner, out StringToken? indirectContentString)) { content = indirectContentString.Data; } diff --git a/src/UglyToad.PdfPig/Annotations/AppearanceStream.cs b/src/UglyToad.PdfPig/Annotations/AppearanceStream.cs index 6d1ab5a05..48b52fb2c 100644 --- a/src/UglyToad.PdfPig/Annotations/AppearanceStream.cs +++ b/src/UglyToad.PdfPig/Annotations/AppearanceStream.cs @@ -12,9 +12,9 @@ /// public class AppearanceStream { - private readonly IDictionary appearanceStreamsByState; + private readonly IDictionary? appearanceStreamsByState; - private readonly StreamToken statelessAppearanceStream; + private readonly StreamToken? statelessAppearanceStream; /// /// Indicates if this appearance stream is stateless, or whether you can get appearances by state. @@ -30,7 +30,7 @@ public class AppearanceStream /// Constructor for stateless appearance stream /// /// - internal AppearanceStream(StreamToken streamToken) + internal AppearanceStream(StreamToken? streamToken) { statelessAppearanceStream = streamToken; } diff --git a/src/UglyToad.PdfPig/Annotations/AppearanceStreamFactory.cs b/src/UglyToad.PdfPig/Annotations/AppearanceStreamFactory.cs index 9db463706..b8fd639d9 100644 --- a/src/UglyToad.PdfPig/Annotations/AppearanceStreamFactory.cs +++ b/src/UglyToad.PdfPig/Annotations/AppearanceStreamFactory.cs @@ -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 @@ public static bool TryCreate(DictionaryToken appearanceDictionary, NameToken nam stateRef is IndirectReferenceToken appearanceRef) { var streamToken = tokenScanner.Get(appearanceRef.Data)?.Data as StreamToken; - dict[state] = streamToken; + dict[state] = streamToken!; } } diff --git a/src/UglyToad.PdfPig/Annotations/HyperlinkFactory.cs b/src/UglyToad.PdfPig/Annotations/HyperlinkFactory.cs index 0ad3c0f11..5b4d57693 100644 --- a/src/UglyToad.PdfPig/Annotations/HyperlinkFactory.cs +++ b/src/UglyToad.PdfPig/Annotations/HyperlinkFactory.cs @@ -25,15 +25,15 @@ public static IReadOnlyList GetHyperlinks(Page page, IPdfTokenScanner } // 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 uriStringToken)) + if (!actionDictionary.TryGet(NameToken.Uri, pdfScanner, out IDataToken? uriStringToken)) { continue; } diff --git a/src/UglyToad.PdfPig/Content/ArtifactMarkedContentElement.cs b/src/UglyToad.PdfPig/Content/ArtifactMarkedContentElement.cs index 8efcb09e0..04729258a 100644 --- a/src/UglyToad.PdfPig/Content/ArtifactMarkedContentElement.cs +++ b/src/UglyToad.PdfPig/Content/ArtifactMarkedContentElement.cs @@ -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 @@ public class ArtifactMarkedContentElement : MarkedContentElement /// 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. /// - public string SubType { get; } + public string? SubType { get; } /// /// The artifact's attribute owners. /// - public string AttributeOwners { get; } + public string? AttributeOwners { get; } /// /// The artifact's bounding box. @@ -64,13 +64,13 @@ public class ArtifactMarkedContentElement : MarkedContentElement 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 attached, IReadOnlyList children, diff --git a/src/UglyToad.PdfPig/Content/BasePageFactory.cs b/src/UglyToad.PdfPig/Content/BasePageFactory.cs index 608a62930..4a6dab081 100644 --- a/src/UglyToad.PdfPig/Content/BasePageFactory.cs +++ b/src/UglyToad.PdfPig/Content/BasePageFactory.cs @@ -79,7 +79,7 @@ public TPage Create(int number, DictionaryToken dictionary, PageTreeMembers page } 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 @@ public TPage Create(int number, DictionaryToken dictionary, PageTreeMembers page 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 @@ private TPage ProcessPageInternal( UserSpaceUnit userSpaceUnit, PageRotationDegrees rotation, TransformationMatrix initialMatrix, - IReadOnlyList contentBytes) + IReadOnlyList? contentBytes) { IReadOnlyList operations; @@ -192,7 +192,8 @@ private TPage ProcessPageInternal( ParsingOptions.Logger); } - return ProcessPage(pageNumber, + return ProcessPage( + pageNumber, dictionary, namedDestinations, mediaBox, @@ -246,7 +247,7 @@ protected CropBox GetCropBox(DictionaryToken dictionary, PageTreeMembers pageTre { 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 @@ protected MediaBox GetMediaBox(int number, DictionaryToken dictionary, PageTreeM { 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) { diff --git a/src/UglyToad.PdfPig/Content/Catalog.cs b/src/UglyToad.PdfPig/Content/Catalog.cs index 582c1bed1..bb900f233 100644 --- a/src/UglyToad.PdfPig/Content/Catalog.cs +++ b/src/UglyToad.PdfPig/Content/Catalog.cs @@ -3,7 +3,6 @@ using System; using Outline.Destinations; using Tokens; - using Util.JetBrains.Annotations; /// /// The root of the document's object hierarchy. Contains references to objects defining the contents, @@ -14,7 +13,6 @@ public sealed class Catalog /// /// The catalog dictionary containing assorted information. /// - [NotNull] public DictionaryToken CatalogDictionary { get; } internal NamedDestinations NamedDestinations { get; } diff --git a/src/UglyToad.PdfPig/Content/DocumentInformation.cs b/src/UglyToad.PdfPig/Content/DocumentInformation.cs index 5c7a7e9a8..e17ec5509 100644 --- a/src/UglyToad.PdfPig/Content/DocumentInformation.cs +++ b/src/UglyToad.PdfPig/Content/DocumentInformation.cs @@ -5,7 +5,6 @@ using System.Text; using Tokens; using Util; - using Util.JetBrains.Annotations; /// /// Metadata for the PDF document. @@ -20,59 +19,58 @@ public class DocumentInformation /// /// The underlying document information PDF dictionary from the document. /// - public DictionaryToken DocumentInformationDictionary { get; } + public DictionaryToken? DocumentInformationDictionary { get; } /// /// The title of this document if applicable. /// - [CanBeNull] - public string Title { get; } + public string? Title { get; } /// /// The name of the person who created this document if applicable. /// - [CanBeNull] - public string Author { get; } + public string? Author { get; } /// /// The subject of this document if applicable. /// - [CanBeNull] - public string Subject { get; } + public string? Subject { get; } /// /// Any keywords associated with this document if applicable. /// - [CanBeNull] - public string Keywords { get; } + public string? Keywords { get; } /// /// The name of the application which created the original document before it was converted to PDF if applicable. /// - [CanBeNull] - public string Creator { get; } + public string? Creator { get; } /// /// The name of the application used to convert the original document to PDF if applicable. /// - [CanBeNull] - public string Producer { get; } + public string? Producer { get; } /// /// The date and time the document was created. /// - [CanBeNull] - public string CreationDate { get; } + public string? CreationDate { get; } /// /// The date and time the document was most recently modified. /// - [CanBeNull] - public string ModifiedDate { get; } - - internal DocumentInformation(DictionaryToken documentInformationDictionary, string title, string author, string subject, string keywords, string creator, string producer, - string creationDate, - string modifiedDate) + public string? ModifiedDate { get; } + + 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()); Title = title; @@ -103,6 +101,11 @@ internal DocumentInformation(DictionaryToken documentInformationDictionary, stri /// public DateTimeOffset? GetCreatedDateTimeOffset() { + if (CreationDate is null) + { + return null; + } + return DateFormatHelper.TryParseDateTimeOffset(CreationDate, out var result) ? result : default(DateTimeOffset?); } @@ -111,6 +114,11 @@ internal DocumentInformation(DictionaryToken documentInformationDictionary, stri /// public DateTimeOffset? GetModifiedDateTimeOffset() { + if (ModifiedDate is null) + { + return null; + } + return DateFormatHelper.TryParseDateTimeOffset(ModifiedDate, out var result) ? result : default(DateTimeOffset?); } @@ -122,7 +130,7 @@ public override string ToString() 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) { diff --git a/src/UglyToad.PdfPig/Content/IPdfImage.cs b/src/UglyToad.PdfPig/Content/IPdfImage.cs index 4b6d20a12..856b73e3b 100644 --- a/src/UglyToad.PdfPig/Content/IPdfImage.cs +++ b/src/UglyToad.PdfPig/Content/IPdfImage.cs @@ -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 @@ public interface IPdfImage /// This is not defined where is and is optional where the image is JPXEncoded for . /// /// - ColorSpaceDetails ColorSpaceDetails { get; } + ColorSpaceDetails? ColorSpaceDetails { get; } /// /// Get the decoded bytes of the image if applicable. For JPEG images and some other types the /// should be used directly. /// - bool TryGetBytes(out IReadOnlyList bytes); + bool TryGetBytes([NotNullWhen(true)] out IReadOnlyList? bytes); /// /// Try to convert the image to PNG. Doesn't support conversion of JPG to PNG. /// - bool TryGetPng(out byte[] bytes); + bool TryGetPng([NotNullWhen(true)] out byte[]? bytes); } } diff --git a/src/UglyToad.PdfPig/Content/IResourceStore.cs b/src/UglyToad.PdfPig/Content/IResourceStore.cs index 87cbfff64..eb499a4f9 100644 --- a/src/UglyToad.PdfPig/Content/IResourceStore.cs +++ b/src/UglyToad.PdfPig/Content/IResourceStore.cs @@ -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; /// @@ -24,12 +25,12 @@ public interface IResourceStore /// /// Get the font corresponding to the name. /// - IFont GetFont(NameToken name); + IFont? GetFont(NameToken name); /// /// Try getting the XObject corresponding to the name. /// - bool TryGetXObject(NameToken name, out StreamToken stream); + bool TryGetXObject(NameToken name, [NotNullWhen(true)] out StreamToken? stream); /// /// Get the extended graphics state dictionary corresponding to the name. @@ -49,12 +50,12 @@ public interface IResourceStore /// /// Get the color space details corresponding to the name. /// - ColorSpaceDetails GetColorSpaceDetails(NameToken name, DictionaryToken dictionary); + ColorSpaceDetails GetColorSpaceDetails(NameToken? name, DictionaryToken? dictionary); /// /// Get the marked content properties dictionary corresponding to the name. /// - DictionaryToken GetMarkedContentPropertiesDictionary(NameToken name); + DictionaryToken? GetMarkedContentPropertiesDictionary(NameToken name); /// /// Get all as a dictionary. Keys are the names. diff --git a/src/UglyToad.PdfPig/Content/InlineImage.cs b/src/UglyToad.PdfPig/Content/InlineImage.cs index 8fec607b4..e06fc38f7 100644 --- a/src/UglyToad.PdfPig/Content/InlineImage.cs +++ b/src/UglyToad.PdfPig/Content/InlineImage.cs @@ -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; /// /// @@ -17,7 +17,7 @@ /// public class InlineImage : IPdfImage { - private readonly Lazy> bytesFactory; + private readonly Lazy>? bytesFactory; /// public PdfRectangle Bounds { get; } @@ -41,7 +41,6 @@ public class InlineImage : IPdfImage public bool IsInlineImage { get; } = true; /// - [NotNull] public DictionaryToken ImageDictionary { get; } /// @@ -105,7 +104,7 @@ internal InlineImage(PdfRectangle bounds, int widthInSamples, int heightInSample } /// - public bool TryGetBytes(out IReadOnlyList bytes) + public bool TryGetBytes([NotNullWhen(true)] out IReadOnlyList? bytes) { bytes = null; if (bytesFactory is null) @@ -119,7 +118,7 @@ public bool TryGetBytes(out IReadOnlyList bytes) } /// - public bool TryGetPng(out byte[] bytes) => PngFromPdfImageFactory.TryGenerate(this, out bytes); + public bool TryGetPng([NotNullWhen(true)] out byte[]? bytes) => PngFromPdfImageFactory.TryGenerate(this, out bytes); /// public override string ToString() diff --git a/src/UglyToad.PdfPig/Content/Letter.cs b/src/UglyToad.PdfPig/Content/Letter.cs index 08abfcd34..3ee0222f7 100644 --- a/src/UglyToad.PdfPig/Content/Letter.cs +++ b/src/UglyToad.PdfPig/Content/Letter.cs @@ -3,7 +3,6 @@ using Core; using Graphics.Colors; using PdfFonts; - using System.Diagnostics; /// /// A glyph or combination of glyphs (characters) drawn by a PDF content stream. @@ -55,7 +54,7 @@ public class Letter /// /// The name of the font. /// - public string FontName => Font?.Name; + public string? FontName => Font?.Name; /// /// Details about the font for this letter. diff --git a/src/UglyToad.PdfPig/Content/MarkedContentElement.cs b/src/UglyToad.PdfPig/Content/MarkedContentElement.cs index 0da3914f9..e0be7ae5b 100644 --- a/src/UglyToad.PdfPig/Content/MarkedContentElement.cs +++ b/src/UglyToad.PdfPig/Content/MarkedContentElement.cs @@ -60,31 +60,32 @@ public class MarkedContentElement /// /// The natural language specification. /// - public string Language { get; } + public string? Language { get; } /// /// The replacement text. /// - public string ActualText { get; } + public string? ActualText { get; } /// /// The alternate description. /// - public string AlternateDescription { get; } + public string? AlternateDescription { get; } /// /// The abbreviation expansion text. /// - public string ExpandedForm { get; } + public string? ExpandedForm { get; } /// /// Create a new . /// - 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 children, IReadOnlyList letters, diff --git a/src/UglyToad.PdfPig/Content/OptionalContentGroupElement.cs b/src/UglyToad.PdfPig/Content/OptionalContentGroupElement.cs index 1a688c43b..33ac16de4 100644 --- a/src/UglyToad.PdfPig/Content/OptionalContentGroupElement.cs +++ b/src/UglyToad.PdfPig/Content/OptionalContentGroupElement.cs @@ -20,18 +20,18 @@ public class OptionalContentGroupElement /// /// The name of the optional content group, suitable for presentation in a viewer application's user interface. /// - public string Name { get; } + public string? Name { get; } /// /// A single name or an array containing any combination of names. /// Default value is 'View'. /// - public IReadOnlyList Intent { get; } + public IReadOnlyList? Intent { get; } /// /// A usage dictionary describing the nature of the content controlled by the group. /// - public IReadOnlyDictionary Usage { get; } + public IReadOnlyDictionary? Usage { get; } /// /// Underlying . @@ -43,11 +43,11 @@ internal OptionalContentGroupElement(MarkedContentElement markedContentElement, 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 @@ internal OptionalContentGroupElement(MarkedContentElement markedContentElement, { 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 @@ internal OptionalContentGroupElement(MarkedContentElement markedContentElement, } // 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 intentList = new List(); foreach (var token in intentArray.Data) @@ -105,11 +105,11 @@ internal OptionalContentGroupElement(MarkedContentElement markedContentElement, 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 @@ internal OptionalContentGroupElement(MarkedContentElement markedContentElement, 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}"); } diff --git a/src/UglyToad.PdfPig/Content/Page.cs b/src/UglyToad.PdfPig/Content/Page.cs index 2b6ddd365..fefbacdaa 100644 --- a/src/UglyToad.PdfPig/Content/Page.cs +++ b/src/UglyToad.PdfPig/Content/Page.cs @@ -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; /// /// Contains the content and provides access to methods of a single page in the . @@ -87,7 +86,6 @@ public class Page /// /// Access to members whose future locations within the API will change without warning. /// - [NotNull] public Experimental ExperimentalAccess { get; } internal Page(int number, DictionaryToken dictionary, MediaBox mediaBox, CropBox cropBox, PageRotationDegrees rotation, PageContent content, @@ -215,12 +213,12 @@ public IReadOnlyDictionary> G // TO DO //var annots = GetAnnotations().ToList(); - return mcesOptional.GroupBy(oc => oc.Name).ToDictionary(g => g.Key, g => g.ToList() as IReadOnlyList); + return mcesOptional.GroupBy(oc => oc.Name).ToDictionary(g => g.Key!, g => (IReadOnlyList)g.ToList()); } - private void GetOptionalContentsRecursively(IReadOnlyList markedContentElements, ref List mcesOptional) + private void GetOptionalContentsRecursively(IReadOnlyList? markedContentElements, ref List mcesOptional) { - if (markedContentElements.Count == 0) + if (markedContentElements is null || markedContentElements.Count == 0) { return; } diff --git a/src/UglyToad.PdfPig/Content/PageRotationDegrees.cs b/src/UglyToad.PdfPig/Content/PageRotationDegrees.cs index 7f88ef51a..b1ca2950f 100644 --- a/src/UglyToad.PdfPig/Content/PageRotationDegrees.cs +++ b/src/UglyToad.PdfPig/Content/PageRotationDegrees.cs @@ -72,7 +72,7 @@ public override string ToString() } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is PageRotationDegrees degrees && Equals(degrees); } diff --git a/src/UglyToad.PdfPig/Content/PageSize.cs b/src/UglyToad.PdfPig/Content/PageSize.cs index b3564eb51..0de70e8e2 100644 --- a/src/UglyToad.PdfPig/Content/PageSize.cs +++ b/src/UglyToad.PdfPig/Content/PageSize.cs @@ -147,11 +147,11 @@ public WidthHeight(double width, double height) 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() diff --git a/src/UglyToad.PdfPig/Content/PageTreeMembers.cs b/src/UglyToad.PdfPig/Content/PageTreeMembers.cs index 8e3f15b0d..4822a7c8a 100644 --- a/src/UglyToad.PdfPig/Content/PageTreeMembers.cs +++ b/src/UglyToad.PdfPig/Content/PageTreeMembers.cs @@ -1,4 +1,6 @@ -namespace UglyToad.PdfPig.Content +#nullable disable + +namespace UglyToad.PdfPig.Content { using System.Collections.Generic; using Tokens; diff --git a/src/UglyToad.PdfPig/Content/PageTreeNode.cs b/src/UglyToad.PdfPig/Content/PageTreeNode.cs index 69e23dc90..4e06451bd 100644 --- a/src/UglyToad.PdfPig/Content/PageTreeNode.cs +++ b/src/UglyToad.PdfPig/Content/PageTreeNode.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using Core; using Tokens; - using Util.JetBrains.Annotations; /// /// A node in the PDF document's page tree. @@ -16,7 +15,6 @@ public class PageTreeNode /// /// The dictionary for this node in the page tree. /// - [NotNull] public DictionaryToken NodeDictionary { get; } /// @@ -37,14 +35,12 @@ public class PageTreeNode /// /// The child nodes of this node if is /// - [NotNull] - public IReadOnlyList Children { get; private set; } + public IReadOnlyList? Children { get; private set; } /// /// The parent node of this node, unless it is the root node. /// - [CanBeNull] - public PageTreeNode Parent { get; private set; } + public PageTreeNode? Parent { get; private set; } /// /// Whether this node is the root node. @@ -93,7 +89,7 @@ public override string ToString() return $"Page #{PageNumber}: {NodeDictionary}."; } - return $"Pages ({Children.Count} children): {NodeDictionary}"; + return $"Pages ({Children?.Count ?? 0} children): {NodeDictionary}"; } } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Content/Pages.cs b/src/UglyToad.PdfPig/Content/Pages.cs index 21d39089b..98f9e3817 100644 --- a/src/UglyToad.PdfPig/Content/Pages.cs +++ b/src/UglyToad.PdfPig/Content/Pages.cs @@ -81,17 +81,17 @@ private TPage GetPage(IPageFactory pageFactory, { 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 @@ internal PageTreeNode GetPageNode(int pageNumber) return node; } - internal PageTreeNode GetPageByReference(IndirectReference reference) + internal PageTreeNode? GetPageByReference(IndirectReference reference) { foreach (var page in pagesByNumber) { diff --git a/src/UglyToad.PdfPig/Content/PagesFactory.cs b/src/UglyToad.PdfPig/Content/PagesFactory.cs index aa804e10f..45ce51e89 100644 --- a/src/UglyToad.PdfPig/Content/PagesFactory.cs +++ b/src/UglyToad.PdfPig/Content/PagesFactory.cs @@ -131,7 +131,7 @@ private static PageTreeNode ProcessPagesNode(IndirectReference referenceInput, } } #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 @@ private static PageTreeNode ProcessPagesNode(IndirectReference referenceInput, 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 @@ private static PageTreeNode ProcessPagesNode(IndirectReference referenceInput, 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 @@ private static bool CheckIfIsPage(DictionaryToken nodeDictionary, IndirectRefere { 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 @@ private static void PopulatePageByNumberDictionary(PageTreeNode node, Dictionary return; } - foreach (var child in node.Children) + foreach (var child in node.Children!) { PopulatePageByNumberDictionary(child, result); } diff --git a/src/UglyToad.PdfPig/Content/ResourceStore.cs b/src/UglyToad.PdfPig/Content/ResourceStore.cs index 31d50a662..4982d1731 100644 --- a/src/UglyToad.PdfPig/Content/ResourceStore.cs +++ b/src/UglyToad.PdfPig/Content/ResourceStore.cs @@ -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 @@ internal class ResourceStore : IResourceStore private readonly Dictionary patternsProperties = new Dictionary(); - private (NameToken name, IFont font) lastLoadedFont; + private (NameToken? name, IFont? font) lastLoadedFont; public ResourceStore(IPdfTokenScanner scanner, IFontFactory fontFactory, @@ -81,7 +82,7 @@ public void LoadResourceDictionary(DictionaryToken resourceDictionary) } } - 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 @@ public void LoadResourceDictionary(DictionaryToken resourceDictionary) } } - 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 @@ public void LoadResourceDictionary(DictionaryToken resourceDictionary) } } - 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 @@ public void LoadResourceDictionary(DictionaryToken resourceDictionary) } } - 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 @@ public void LoadResourceDictionary(DictionaryToken resourceDictionary) } } - 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 @@ private void LoadFontDictionary(DictionaryToken fontDictionary) } } - 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 @@ public IFont GetFontDirectly(IndirectReferenceToken fontReferenceToken) { 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 @@ public IFont GetFontDirectly(IndirectReferenceToken fontReferenceToken) 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 @@ public bool TryGetNamedColorSpace(NameToken name, out ResourceColorSpace namedTo return true; } - public ColorSpaceDetails GetColorSpaceDetails(NameToken name, DictionaryToken dictionary) - { - if (dictionary is null) - { - dictionary = new DictionaryToken(new Dictionary()); - } - + public ColorSpaceDetails GetColorSpaceDetails(NameToken? name, DictionaryToken? dictionary) + { + dictionary ??= new DictionaryToken(new Dictionary()); + // Null color space for images if (name is null) { @@ -299,12 +297,12 @@ public ColorSpaceDetails GetColorSpaceDetails(NameToken name, DictionaryToken di 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 @@ public ColorSpaceDetails GetColorSpaceDetails(NameToken name, DictionaryToken di 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 @@ public DictionaryToken GetExtendedGraphicsStateDictionary(NameToken name) return extendedGraphicsStates[name]; } - public DictionaryToken GetMarkedContentPropertiesDictionary(NameToken name) + public DictionaryToken? GetMarkedContentPropertiesDictionary(NameToken name) { return markedContentProperties.TryGetValue(name, out var result) ? result : null; } diff --git a/src/UglyToad.PdfPig/Content/Word.cs b/src/UglyToad.PdfPig/Content/Word.cs index 2d93a067c..1a27d477e 100644 --- a/src/UglyToad.PdfPig/Content/Word.cs +++ b/src/UglyToad.PdfPig/Content/Word.cs @@ -29,7 +29,7 @@ public class Word /// /// The name of the font for the word. /// - public string FontName { get; } + public string? FontName { get; } /// /// The letters contained in the word. diff --git a/src/UglyToad.PdfPig/Content/XmpMetadata.cs b/src/UglyToad.PdfPig/Content/XmpMetadata.cs index d4160388d..77fafbca4 100644 --- a/src/UglyToad.PdfPig/Content/XmpMetadata.cs +++ b/src/UglyToad.PdfPig/Content/XmpMetadata.cs @@ -8,7 +8,6 @@ using Filters; using Tokenization.Scanner; using Tokens; - using Util.JetBrains.Annotations; /// /// Wraps an XML based Extensible Metadata Platform (XMP) document. These XML documents are embedded in PDFs to provide metadata @@ -22,7 +21,6 @@ public class XmpMetadata /// /// The underlying for this metadata. /// - [NotNull] public StreamToken MetadataStreamToken { get; } internal XmpMetadata(StreamToken stream, ILookupFilterProvider filterProvider, IPdfTokenScanner pdfTokenScanner) diff --git a/src/UglyToad.PdfPig/CrossReference/CrossReferenceTable.cs b/src/UglyToad.PdfPig/CrossReference/CrossReferenceTable.cs index aa08be61c..fe404ea2c 100644 --- a/src/UglyToad.PdfPig/CrossReference/CrossReferenceTable.cs +++ b/src/UglyToad.PdfPig/CrossReference/CrossReferenceTable.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using Core; - using Util.JetBrains.Annotations; /// /// The cross-reference table contains information that enables random access to PDF objects within the file by object number @@ -19,7 +18,6 @@ public class CrossReferenceTable /// /// The corresponding byte offset for each keyed object in this document. /// - [NotNull] public IReadOnlyDictionary ObjectOffsets => objectOffsets; /// @@ -30,14 +28,12 @@ public class CrossReferenceTable /// /// The trailer dictionary. /// - [NotNull] public TrailerDictionary Trailer { get; } /// /// The byte offsets of each cross-reference table or stream in this document and the previous /// table or stream they link to if applicable. /// - [NotNull] public IReadOnlyList CrossReferenceOffsets { get; } internal CrossReferenceTable(CrossReferenceType type, IReadOnlyDictionary objectOffsets, diff --git a/src/UglyToad.PdfPig/CrossReference/CrossReferenceTablePartBuilder.cs b/src/UglyToad.PdfPig/CrossReference/CrossReferenceTablePartBuilder.cs index d2ca13af7..1cda8ca61 100644 --- a/src/UglyToad.PdfPig/CrossReference/CrossReferenceTablePartBuilder.cs +++ b/src/UglyToad.PdfPig/CrossReference/CrossReferenceTablePartBuilder.cs @@ -12,7 +12,7 @@ internal class CrossReferenceTablePartBuilder 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 void Add(long objectId, int generationNumber, long offset) public CrossReferenceTablePart Build() { - return new CrossReferenceTablePart(objects, Offset, Previous, Dictionary, XRefType, TiedToPreviousAtOffset); + return new CrossReferenceTablePart(objects, Offset, Previous, Dictionary!, XRefType, TiedToPreviousAtOffset); } } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/CrossReference/TrailerDictionary.cs b/src/UglyToad.PdfPig/CrossReference/TrailerDictionary.cs index 93ecaa1c7..ab2c2e93b 100644 --- a/src/UglyToad.PdfPig/CrossReference/TrailerDictionary.cs +++ b/src/UglyToad.PdfPig/CrossReference/TrailerDictionary.cs @@ -3,10 +3,8 @@ using System; using System.Collections.Generic; using Core; - using Exceptions; using Tokens; using Util; - using Util.JetBrains.Annotations; /// /// Contains information for interpreting the cross-reference table. @@ -47,8 +45,7 @@ public class TrailerDictionary /// /// The document's encryption dictionary. /// - [CanBeNull] - public IToken EncryptionToken { get; } + public IToken? EncryptionToken { get; } /// /// Create a new . diff --git a/src/UglyToad.PdfPig/Encryption/EncryptionDictionary.cs b/src/UglyToad.PdfPig/Encryption/EncryptionDictionary.cs index eb539c6b8..8f58c82a7 100644 --- a/src/UglyToad.PdfPig/Encryption/EncryptionDictionary.cs +++ b/src/UglyToad.PdfPig/Encryption/EncryptionDictionary.cs @@ -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 @@ internal class EncryptionDictionary public int Revision { get; } - public byte[] OwnerBytes { get; } + public byte[]? OwnerBytes { get; } - public byte[] UserBytes { get; } + public byte[]? UserBytes { get; } /// /// Required if is 5 or above. A 32-byte string, based on the owner and user passwords that is used in computing the encryption key. /// - [CanBeNull] - public byte[] OwnerEncryptionBytes { get; } + public byte[]? OwnerEncryptionBytes { get; } /// /// Required if is 5 or above. A 32-byte string, based on the user password that is used in computing the encryption key. /// - [CanBeNull] - public byte[] UserEncryptionBytes { get; } + public byte[]? UserEncryptionBytes { get; } public UserAccessPermissions UserAccessPermissions { get; } @@ -42,10 +40,10 @@ internal class EncryptionDictionary 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 @@ public EncryptionDictionary(string filter, EncryptionAlgorithmCode encryptionAlg EncryptMetadata = encryptMetadata; } - public bool TryGetCryptHandler(out CryptHandler cryptHandler) + public bool TryGetCryptHandler([NotNullWhen(true)] out CryptHandler? cryptHandler) { cryptHandler = null; diff --git a/src/UglyToad.PdfPig/Encryption/EncryptionDictionaryFactory.cs b/src/UglyToad.PdfPig/Encryption/EncryptionDictionaryFactory.cs index 9e248ae19..5743e6e06 100644 --- a/src/UglyToad.PdfPig/Encryption/EncryptionDictionaryFactory.cs +++ b/src/UglyToad.PdfPig/Encryption/EncryptionDictionaryFactory.cs @@ -20,25 +20,25 @@ public static EncryptionDictionary Read(DictionaryToken encryptionDictionary, IP 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 @@ public static EncryptionDictionary Read(DictionaryToken encryptionDictionary, IP } } - byte[] userBytes = null; + byte[]? userBytes = null; if (encryptionDictionary.TryGet(NameToken.U, out IToken userToken)) { if (userToken is StringToken userString) @@ -66,22 +66,25 @@ public static EncryptionDictionary Read(DictionaryToken encryptionDictionary, IP 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 @@ public static EncryptionDictionary Read(DictionaryToken encryptionDictionary, IP 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(); } diff --git a/src/UglyToad.PdfPig/Encryption/EncryptionHandler.cs b/src/UglyToad.PdfPig/Encryption/EncryptionHandler.cs index 1906b11f7..4f4a68df6 100644 --- a/src/UglyToad.PdfPig/Encryption/EncryptionHandler.cs +++ b/src/UglyToad.PdfPig/Encryption/EncryptionHandler.cs @@ -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 @@ internal sealed class EncryptionHandler : IEncryptionHandler ]; private readonly HashSet previouslyDecrypted = new HashSet(); - - [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 passwords) { this.encryptionDictionary = encryptionDictionary; - passwords ??= new[] { string.Empty }; + passwords ??= [string.Empty]; if (!passwords.Contains(string.Empty)) { @@ -268,7 +263,7 @@ private static bool IsOwnerPassword(byte[] passwordBytes, EncryptionDictionary e { // 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 @@ private static bool IsOwnerPassword(byte[] passwordBytes, EncryptionDictionary e 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 @@ private static byte[] CalculateKeyRevisions5And6(byte[] password, EncryptionDict 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 { diff --git a/src/UglyToad.PdfPig/Exceptions/PdfDocumentEncryptedException.cs b/src/UglyToad.PdfPig/Exceptions/PdfDocumentEncryptedException.cs index 3a4e91c4d..22e79eb64 100644 --- a/src/UglyToad.PdfPig/Exceptions/PdfDocumentEncryptedException.cs +++ b/src/UglyToad.PdfPig/Exceptions/PdfDocumentEncryptedException.cs @@ -11,7 +11,7 @@ [Serializable] public class PdfDocumentEncryptedException : Exception { - internal EncryptionDictionary Dictionary { get; } + internal EncryptionDictionary? Dictionary { get; } /// public PdfDocumentEncryptedException() diff --git a/src/UglyToad.PdfPig/Filters/CcittFaxDecoderStream.cs b/src/UglyToad.PdfPig/Filters/CcittFaxDecoderStream.cs index 0440f7bc2..341c2d3ef 100644 --- a/src/UglyToad.PdfPig/Filters/CcittFaxDecoderStream.cs +++ b/src/UglyToad.PdfPig/Filters/CcittFaxDecoderStream.cs @@ -10,7 +10,7 @@ /// /// Ported from https://github.com/apache/pdfbox/blob/e644c29279e276bde14ce7a33bdeef0cb1001b3e/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxDecoderStream.java /// - 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 @@ public override int Read(byte[] b, int off, int len) 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 void Set(bool next, Node node) public Node Walk(bool next) { - return next ? Right : Left; + return next ? Right! : Left!; } public override string ToString() diff --git a/src/UglyToad.PdfPig/Filters/LzwFilter.cs b/src/UglyToad.PdfPig/Filters/LzwFilter.cs index 26e5148e1..b46137f31 100644 --- a/src/UglyToad.PdfPig/Filters/LzwFilter.cs +++ b/src/UglyToad.PdfPig/Filters/LzwFilter.cs @@ -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. /// - internal class LzwFilter : IFilter + internal sealed class LzwFilter : IFilter { private const int DefaultColors = 1; private const int DefaultBitsPerComponent = 8; @@ -146,7 +148,7 @@ private static Dictionary GetDefaultTable() for (var i = 0; i < 256; i++) { - table[i] = new[] { (byte)i }; + table[i] = [(byte)i]; } table[ClearTable] = null; diff --git a/src/UglyToad.PdfPig/Functions/PdfFunction.cs b/src/UglyToad.PdfPig/Functions/PdfFunction.cs index 70a24146d..0150c4f66 100644 --- a/src/UglyToad.PdfPig/Functions/PdfFunction.cs +++ b/src/UglyToad.PdfPig/Functions/PdfFunction.cs @@ -12,12 +12,12 @@ public abstract class PdfFunction /// /// The function dictionary. /// - public DictionaryToken FunctionDictionary { get; } + public DictionaryToken? FunctionDictionary { get; } /// /// The function stream. /// - public StreamToken FunctionStream { get; } + public StreamToken? FunctionStream { get; } private int numberOfInputValues = -1; private int numberOfOutputValues = -1; @@ -25,7 +25,7 @@ public abstract class PdfFunction /// /// This class represents a function in a PDF document. /// - public PdfFunction(DictionaryToken function, ArrayToken domain, ArrayToken range) + public PdfFunction(DictionaryToken function, ArrayToken domain, ArrayToken? range) { FunctionDictionary = function; DomainValues = domain; @@ -35,7 +35,7 @@ public PdfFunction(DictionaryToken function, ArrayToken domain, ArrayToken range /// /// This class represents a function in a PDF document. /// - public PdfFunction(StreamToken function, ArrayToken domain, ArrayToken range) + public PdfFunction(StreamToken function, ArrayToken domain, ArrayToken? range) { FunctionStream = function; DomainValues = domain; @@ -58,7 +58,7 @@ public PdfFunction(StreamToken function, ArrayToken domain, ArrayToken range) /// Returns the function's dictionary. If is defined, it will be returned. /// If not, the 's StreamDictionary will be returned. /// - public DictionaryToken GetDictionary() + public DictionaryToken? GetDictionary() { if (FunctionStream != null) { @@ -106,7 +106,7 @@ public int NumberOfOutputParameters /// The range for this component. public PdfRange GetRangeForOutput(int n) { - return new PdfRange(RangeValues.Data.OfType().Select(t => t.Double), n); + return new PdfRange(RangeValues!.Data.OfType().Select(t => t.Double), n); } /// @@ -154,7 +154,7 @@ public PdfRange GetDomainForInput(int n) /// Returns all ranges for the output values as . Required for type 0 and type 4 functions. /// /// the ranges array. - protected ArrayToken RangeValues { get; } + protected ArrayToken? RangeValues { get; } /// /// Returns all domains for the input values as . Required for all function types. @@ -169,7 +169,7 @@ public PdfRange GetDomainForInput(int n) /// the clipped values protected double[] ClipToRange(double[] inputValues) { - ArrayToken rangesArray = RangeValues; + ArrayToken rangesArray = RangeValues!; double[] result; if (rangesArray != null && rangesArray.Length > 0) { diff --git a/src/UglyToad.PdfPig/Functions/PdfFunctionType0.cs b/src/UglyToad.PdfPig/Functions/PdfFunctionType0.cs index 4ca7fe0d7..817360953 100644 --- a/src/UglyToad.PdfPig/Functions/PdfFunctionType0.cs +++ b/src/UglyToad.PdfPig/Functions/PdfFunctionType0.cs @@ -12,7 +12,7 @@ internal sealed class PdfFunctionType0 : PdfFunction /// /// The samples of the function. /// - private int[][] samples; + private int[][]? samples; /// /// Stitching function @@ -262,7 +262,7 @@ private int[][] GetSamples() 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 @@ private int[][] GetSamples() // 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 @@ public override double[] Eval(params double[] input) 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]); diff --git a/src/UglyToad.PdfPig/Functions/PdfFunctionType2.cs b/src/UglyToad.PdfPig/Functions/PdfFunctionType2.cs index 89a8bbbdf..ba0f1791e 100644 --- a/src/UglyToad.PdfPig/Functions/PdfFunctionType2.cs +++ b/src/UglyToad.PdfPig/Functions/PdfFunctionType2.cs @@ -11,7 +11,7 @@ internal sealed class PdfFunctionType2 : PdfFunction /// /// Exponential interpolation function /// - 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 @@ internal PdfFunctionType2(DictionaryToken function, ArrayToken domain, ArrayToke 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; diff --git a/src/UglyToad.PdfPig/Functions/PdfFunctionType3.cs b/src/UglyToad.PdfPig/Functions/PdfFunctionType3.cs index 3e4422122..dbe565a2b 100644 --- a/src/UglyToad.PdfPig/Functions/PdfFunctionType3.cs +++ b/src/UglyToad.PdfPig/Functions/PdfFunctionType3.cs @@ -17,7 +17,7 @@ internal sealed class PdfFunctionType3 : PdfFunction /// /// Stitching function /// - internal PdfFunctionType3(DictionaryToken function, ArrayToken domain, ArrayToken range, IReadOnlyList functionsArray, ArrayToken bounds, ArrayToken encode) + internal PdfFunctionType3(DictionaryToken function, ArrayToken domain, ArrayToken? range, IReadOnlyList functionsArray, ArrayToken bounds, ArrayToken encode) : base(function, domain, range) { if (functionsArray is null || functionsArray.Count == 0) @@ -59,7 +59,7 @@ public override double[] Eval(params double[] input) // 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 diff --git a/src/UglyToad.PdfPig/Functions/PdfFunctionType4.cs b/src/UglyToad.PdfPig/Functions/PdfFunctionType4.cs index 5b0308fab..f47f7251b 100644 --- a/src/UglyToad.PdfPig/Functions/PdfFunctionType4.cs +++ b/src/UglyToad.PdfPig/Functions/PdfFunctionType4.cs @@ -20,7 +20,7 @@ internal sealed class PdfFunctionType4 : PdfFunction 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); } diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/Clipper.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/Clipper.cs index 61e19e2b8..688f42d16 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/Clipper.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/Clipper.cs @@ -70,6 +70,8 @@ * * *******************************************************************************/ +#nullable disable + namespace UglyToad.PdfPig.Geometry.ClipperLibrary { using System; diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperBase.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperBase.cs index 0dd17d290..8b97ae6c3 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperBase.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperBase.cs @@ -73,6 +73,7 @@ //use_lines: Enables open path clipping. Adds a very minor cost to performance. +#nullable disable namespace UglyToad.PdfPig.Geometry.ClipperLibrary { diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperInt128.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperInt128.cs index 4f13fd0ee..ee3a24128 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperInt128.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperInt128.cs @@ -123,7 +123,7 @@ public bool IsNegative() return !(val1 == val2); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (!(obj is ClipperInt128 i128)) { diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperIntersectNode.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperIntersectNode.cs index f4775ac61..0f83046dd 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperIntersectNode.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperIntersectNode.cs @@ -69,6 +69,9 @@ * Code modified for PdfPig * * * *******************************************************************************/ + +#nullable disable + namespace UglyToad.PdfPig.Geometry.ClipperLibrary { using System.Collections.Generic; diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperJoin.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperJoin.cs index dc49caf18..0860fa826 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperJoin.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperJoin.cs @@ -69,6 +69,9 @@ * Code modified for PdfPig * * * *******************************************************************************/ + +#nullable disable + namespace UglyToad.PdfPig.Geometry.ClipperLibrary { internal class ClipperJoin diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperLocalMinima.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperLocalMinima.cs index 9b1ee12a6..3a90ed25d 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperLocalMinima.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperLocalMinima.cs @@ -69,6 +69,9 @@ * Code modified for PdfPig * * * *******************************************************************************/ + +#nullable disable + namespace UglyToad.PdfPig.Geometry.ClipperLibrary { internal class ClipperLocalMinima diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperMaxima.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperMaxima.cs index 764d525d2..c329aa52d 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperMaxima.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperMaxima.cs @@ -69,6 +69,9 @@ * Code modified for PdfPig * * * *******************************************************************************/ + +#nullable disable + namespace UglyToad.PdfPig.Geometry.ClipperLibrary { internal class ClipperMaxima diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutPt.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutPt.cs index 191cdb3e3..2e822556b 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutPt.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutPt.cs @@ -69,6 +69,9 @@ * Code modified for PdfPig * * * *******************************************************************************/ + +#nullable disable + namespace UglyToad.PdfPig.Geometry.ClipperLibrary { internal class ClipperOutPt diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutRec.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutRec.cs index 4e2a6531a..f8beffd35 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutRec.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperOutRec.cs @@ -69,6 +69,9 @@ * Code modified for PdfPig * * * *******************************************************************************/ + +#nullable disable + namespace UglyToad.PdfPig.Geometry.ClipperLibrary { /// diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPoints.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPoints.cs index 243e4306f..ce89658fd 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPoints.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPoints.cs @@ -117,7 +117,7 @@ public ClipperIntPoint(ClipperIntPoint pt) : this(pt.X, pt.Y) 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) { diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPolyNode.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPolyNode.cs index 0e36a6764..2745937ee 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPolyNode.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperPolyNode.cs @@ -69,6 +69,9 @@ * Code modified for PdfPig * * * *******************************************************************************/ + +#nullable disable + namespace UglyToad.PdfPig.Geometry.ClipperLibrary { using System.Collections.Generic; diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperScanbeam.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperScanbeam.cs index 2a9b41345..deb16cacd 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperScanbeam.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperScanbeam.cs @@ -69,6 +69,9 @@ * Code modified for PdfPig * * * *******************************************************************************/ + +#nullable disable + namespace UglyToad.PdfPig.Geometry.ClipperLibrary { internal class ClipperScanbeam diff --git a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperTEdge.cs b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperTEdge.cs index 964362c06..2833346e5 100644 --- a/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperTEdge.cs +++ b/src/UglyToad.PdfPig/Geometry/ClipperLibrary/ClipperTEdge.cs @@ -69,6 +69,9 @@ * Code modified for PdfPig * * * *******************************************************************************/ + +#nullable disable + namespace UglyToad.PdfPig.Geometry.ClipperLibrary { internal class ClipperTEdge diff --git a/src/UglyToad.PdfPig/Geometry/ClippingExtensions.cs b/src/UglyToad.PdfPig/Geometry/ClippingExtensions.cs index 76f40abb7..957471c48 100644 --- a/src/UglyToad.PdfPig/Geometry/ClippingExtensions.cs +++ b/src/UglyToad.PdfPig/Geometry/ClippingExtensions.cs @@ -24,7 +24,7 @@ internal static class ClippingExtensions /// /// Generates the result of applying a clipping path to another path. /// - 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) { diff --git a/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs b/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs index 3bff69627..4994b4970 100644 --- a/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs +++ b/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs @@ -741,12 +741,12 @@ public static bool IntersectsWith(PdfPoint p11, PdfPoint p12, PdfPoint p21, PdfP /// The intersection of the line formed by and /// intersects the rectangle. /// - 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() { 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 @@ private static PdfPoint[] Intersect(PdfRectangle rectangle, PdfPoint pl1, PdfPoi { 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 @@ private static PdfPoint[] Intersect(BezierCurve bezierCurve, PdfPoint p1, PdfPoi /// Get the t values that are the intersections of the line and the curve. /// /// List of t values where the and the intersect. - 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 @@ public static double[] IntersectT(this BezierCurve bezierCurve, PdfLine line) /// Get the t values that are the intersections of the line and the curve. /// /// List of t values where the and the intersect. - 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(); diff --git a/src/UglyToad.PdfPig/Graphics/BaseStreamProcessor.cs b/src/UglyToad.PdfPig/Graphics/BaseStreamProcessor.cs index 21ad43172..3311b0380 100644 --- a/src/UglyToad.PdfPig/Graphics/BaseStreamProcessor.cs +++ b/src/UglyToad.PdfPig/Graphics/BaseStreamProcessor.cs @@ -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 @@ public abstract class BaseStreamProcessor : IOperationContext /// /// The active ExtendedGraphicsState font. /// - protected IFont ActiveExtendedGraphicsStateFont; + protected IFont? ActiveExtendedGraphicsStateFont; /// /// Inline image builder. /// - protected InlineImageBuilder InlineImageBuilder; + protected InlineImageBuilder? InlineImageBuilder; /// /// The page number. @@ -281,8 +282,8 @@ public void ShowText(IInputBytes bytes) var boundingBox = font.GetBoundingBox(code); RenderGlyph(font, - currentState.CurrentStrokingColor, - currentState.CurrentNonStrokingColor, + currentState.CurrentStrokingColor!, + currentState.CurrentNonStrokingColor!, currentState.FontState.TextRenderingMode, fontSize, pointSize, @@ -336,7 +337,7 @@ public virtual void ShowPositionedText(IReadOnlyList tokens) 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 @@ public virtual void ShowPositionedText(IReadOnlyList tokens) { 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 @@ protected virtual void ProcessFormXObject(StreamToken formStream, NameToken xObj * 5. Restore the saved graphics state, as if by invoking the Q operator. */ - var hasResources = - formStream.StreamDictionary.TryGet(NameToken.Resources, + if (formStream.StreamDictionary.TryGet(NameToken.Resources, PdfScanner, - out var formResources); - if (hasResources) + out var formResources)) { ResourceStore.LoadResourceDictionary(formResources); } @@ -484,7 +483,7 @@ protected virtual void ProcessFormXObject(StreamToken formStream, NameToken xObj 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.S, PdfScanner, out var sToken) || sToken != NameToken.Transparency) @@ -512,16 +511,16 @@ protected virtual void ProcessFormXObject(StreamToken formStream, NameToken xObj 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 @@ protected virtual void ProcessFormXObject(StreamToken formStream, NameToken xObj } 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 @@ protected virtual void ProcessFormXObject(StreamToken formStream, NameToken xObj } 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 @@ protected virtual void ProcessFormXObject(StreamToken formStream, NameToken xObj // 5. Restore saved state. PopState(); - if (hasResources) + if (formResources != null) // has resources { ResourceStore.UnloadResourceDictionary(); } @@ -667,22 +666,22 @@ public virtual void SetNamedGraphicsState(NameToken stateName) 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 @@ public virtual void SetNamedGraphicsState(NameToken stateName) 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 @@ public virtual void SetNamedGraphicsState(NameToken stateName) 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 @@ public virtual void SetNamedGraphicsState(NameToken stateName) 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 @@ public virtual void SetNamedGraphicsState(NameToken stateName) 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 @@ public virtual void SetNamedGraphicsState(NameToken stateName) 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 @@ public virtual void SetNamedGraphicsState(NameToken stateName) 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 @@ public virtual void EndInlineImage(IReadOnlyList bytes) protected abstract void RenderInlineImage(InlineImage inlineImage); /// - public abstract void BeginMarkedContent(NameToken name, - NameToken propertyDictionaryName, - DictionaryToken properties); + public abstract void BeginMarkedContent( + NameToken name, + NameToken? propertyDictionaryName, + DictionaryToken? properties); /// public abstract void EndMarkedContent(); diff --git a/src/UglyToad.PdfPig/Graphics/ColorSpaceContext.cs b/src/UglyToad.PdfPig/Graphics/ColorSpaceContext.cs index 0b81cb2d2..7c8ee22b5 100644 --- a/src/UglyToad.PdfPig/Graphics/ColorSpaceContext.cs +++ b/src/UglyToad.PdfPig/Graphics/ColorSpaceContext.cs @@ -22,7 +22,7 @@ public ColorSpaceContext(Func currentStateFunc, IResourceS 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 @@ public void SetStrokingColorspace(NameToken colorspace, DictionaryToken dictiona currentStateFunc().CurrentStrokingColor = CurrentStrokingColorSpace.GetInitializeColor(); } - public void SetStrokingColor(IReadOnlyList operands, NameToken patternName) + public void SetStrokingColor(IReadOnlyList operands, NameToken? patternName) { if (CurrentStrokingColorSpace is UnsupportedColorSpaceDetails) { @@ -69,7 +69,7 @@ public void SetStrokingColorCmyk(double c, double m, double y, double k) 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 @@ public void SetNonStrokingColorspace(NameToken colorspace, DictionaryToken dicti currentStateFunc().CurrentNonStrokingColor = CurrentNonStrokingColorSpace.GetInitializeColor(); } - public void SetNonStrokingColor(IReadOnlyList operands, NameToken patternName) + public void SetNonStrokingColor(IReadOnlyList operands, NameToken? patternName) { if (CurrentNonStrokingColorSpace is UnsupportedColorSpaceDetails) { diff --git a/src/UglyToad.PdfPig/Graphics/Colors/CIEBasedColorSpaceTransformer.cs b/src/UglyToad.PdfPig/Graphics/Colors/CIEBasedColorSpaceTransformer.cs index bc7b392bb..e3c91647f 100644 --- a/src/UglyToad.PdfPig/Graphics/Colors/CIEBasedColorSpaceTransformer.cs +++ b/src/UglyToad.PdfPig/Graphics/Colors/CIEBasedColorSpaceTransformer.cs @@ -56,7 +56,7 @@ public CIEBasedColorSpaceTransformer((double X, double Y, double Z) sourceRefere 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 @@ public CIEBasedColorSpaceTransformer((double X, double Y, double Z) sourceRefere Sr * Yr, Sg * Yg, Sb * Yb, Sr * Zr, Sg * Zg, Sb * Zb); - transformationMatrix = M.Inverse(); + transformationMatrix = M.Inverse()!; } /// diff --git a/src/UglyToad.PdfPig/Graphics/Colors/CMYKColor.cs b/src/UglyToad.PdfPig/Graphics/Colors/CMYKColor.cs index 147768390..12045f4d8 100644 --- a/src/UglyToad.PdfPig/Graphics/Colors/CMYKColor.cs +++ b/src/UglyToad.PdfPig/Graphics/Colors/CMYKColor.cs @@ -61,16 +61,20 @@ public CMYKColor(double c, double m, double y, double k) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { - return Equals(obj as CMYKColor); + return obj is CMYKColor other && Equals(other); } /// - 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 @@ public bool Equals(CMYKColor other) /// 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); } /// diff --git a/src/UglyToad.PdfPig/Graphics/Colors/ChromaticAdaptation.cs b/src/UglyToad.PdfPig/Graphics/Colors/ChromaticAdaptation.cs index bb43130eb..91156af2b 100644 --- a/src/UglyToad.PdfPig/Graphics/Colors/ChromaticAdaptation.cs +++ b/src/UglyToad.PdfPig/Graphics/Colors/ChromaticAdaptation.cs @@ -17,8 +17,8 @@ public ChromaticAdaptation( (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); diff --git a/src/UglyToad.PdfPig/Graphics/Colors/ColorSpaceDetails.cs b/src/UglyToad.PdfPig/Graphics/Colors/ColorSpaceDetails.cs index d46fa3d3f..44bda3687 100644 --- a/src/UglyToad.PdfPig/Graphics/Colors/ColorSpaceDetails.cs +++ b/src/UglyToad.PdfPig/Graphics/Colors/ColorSpaceDetails.cs @@ -8,7 +8,6 @@ using UglyToad.PdfPig.Content; using UglyToad.PdfPig.Functions; using UglyToad.PdfPig.Util; - using UglyToad.PdfPig.Util.JetBrains.Annotations; /// /// Contains more document-specific information about the . @@ -58,7 +57,7 @@ protected internal ColorSpaceDetails(ColorSpace type) /// /// Get the color that initialize the current stroking or nonstroking colour. /// - public abstract IColor GetInitializeColor(); + public abstract IColor? GetInitializeColor(); /// /// Transform image bytes. @@ -106,7 +105,7 @@ public override IColor GetColor(params double[] values) { 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 @@ public override IColor GetColor(params double[] values) { 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 @@ public override IColor GetColor(params double[] values) { 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 @@ public override IColor GetColor(params double[] values) { 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 @@ public override IColor GetColor(params double[] values) internal byte[] UnwrapIndexedColorSpaceBytes(IReadOnlyList input) { var multiplier = 1; - Func> transformer = null; + Func>? transformer = null; switch (BaseType) { case ColorSpace.DeviceRGB: @@ -520,7 +519,7 @@ public override IColor GetColor(params double[] values) { 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 @@ internal override IReadOnlyList Transform(IReadOnlyList decoded) 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 @@ public readonly struct DeviceNColorSpaceAttributes /// /// Colorants - dictionary - Required if Subtype is NChannel and the colour space includes spot colorants; otherwise optional. /// - public DictionaryToken Colorants { get; } + public DictionaryToken? Colorants { get; } /// /// Process - dictionary - Required if Subtype is NChannel and the colour space includes components of a process colour space, otherwise optional. /// - public DictionaryToken Process { get; } + public DictionaryToken? Process { get; } /// /// MixingHints - dictionary - Optional /// - public DictionaryToken MixingHints { get; } + public DictionaryToken? MixingHints { get; } /// /// Create a new . @@ -608,7 +607,7 @@ public DeviceNColorSpaceAttributes() /// /// Create a new . /// - 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 @@ public override IColor GetColor(params double[] values) { 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 @@ internal override IReadOnlyList Transform(IReadOnlyList values) 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 @@ public sealed class CalGrayColorSpaceDetails : ColorSpaceDetails /// /// Create a new . /// - public CalGrayColorSpaceDetails([NotNull] IReadOnlyList whitePoint, [CanBeNull] IReadOnlyList blackPoint, double? gamma) + public CalGrayColorSpaceDetails(IReadOnlyList whitePoint, IReadOnlyList? blackPoint, double? gamma) : base(ColorSpace.CalGray) { WhitePoint = whitePoint ?? throw new ArgumentNullException(nameof(whitePoint)); @@ -782,7 +781,7 @@ public CalGrayColorSpaceDetails([NotNull] IReadOnlyList whitePoint, [Can 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 @@ public override IColor GetColor(params double[] values) { 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 @@ public sealed class CalRGBColorSpaceDetails : ColorSpaceDetails /// /// Create a new . /// - public CalRGBColorSpaceDetails([NotNull] IReadOnlyList whitePoint, [CanBeNull] IReadOnlyList blackPoint, [CanBeNull] IReadOnlyList gamma, [CanBeNull] IReadOnlyList matrix) + public CalRGBColorSpaceDetails(IReadOnlyList whitePoint, IReadOnlyList? blackPoint, IReadOnlyList? gamma, IReadOnlyList? matrix) : base(ColorSpace.CalRGB) { WhitePoint = whitePoint ?? throw new ArgumentNullException(nameof(whitePoint)); @@ -910,22 +909,22 @@ public CalRGBColorSpaceDetails([NotNull] IReadOnlyList whitePoint, [CanB 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 @@ public override IColor GetColor(params double[] values) { 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 @@ public sealed class LabColorSpaceDetails : ColorSpaceDetails /// /// Create a new . /// - public LabColorSpaceDetails([NotNull] IReadOnlyList whitePoint, [CanBeNull] IReadOnlyList blackPoint, [CanBeNull] IReadOnlyList matrix) + public LabColorSpaceDetails(IReadOnlyList whitePoint, IReadOnlyList? blackPoint, IReadOnlyList? matrix) : base(ColorSpace.Lab) { WhitePoint = whitePoint?.Select(v => v).ToArray() ?? throw new ArgumentNullException(nameof(whitePoint)); @@ -1049,13 +1048,13 @@ public LabColorSpaceDetails([NotNull] IReadOnlyList whitePoint, [CanBeNu 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 @@ public override IColor GetColor(params double[] values) { 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 @@ public sealed class ICCBasedColorSpaceDetails : ColorSpaceDetails /// must be substituted. /// /// - [NotNull] public ColorSpaceDetails AlternateColorSpace { get; } /// @@ -1184,20 +1182,20 @@ public sealed class ICCBasedColorSpaceDetails : ColorSpaceDetails /// 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 ...]. /// - [NotNull] public IReadOnlyList Range { get; } /// /// An optional metadata stream that contains metadata for the color space. /// - [CanBeNull] - public XmpMetadata Metadata { get; } + public XmpMetadata? Metadata { get; } /// /// Create a new . /// - internal ICCBasedColorSpaceDetails(int numberOfColorComponents, [CanBeNull] ColorSpaceDetails alternateColorSpaceDetails, - [CanBeNull] IReadOnlyList range, [CanBeNull] XmpMetadata metadata) + internal ICCBasedColorSpaceDetails(int numberOfColorComponents, + ColorSpaceDetails? alternateColorSpaceDetails, + IReadOnlyList? range, + XmpMetadata? metadata) : base(ColorSpace.ICCBased) { if (numberOfColorComponents != 1 && numberOfColorComponents != 3 && numberOfColorComponents != 4) @@ -1207,8 +1205,8 @@ internal ICCBasedColorSpaceDetails(int numberOfColorComponents, [CanBeNull] Colo 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 @@ internal ICCBasedColorSpaceDetails(int numberOfColorComponents, [CanBeNull] Colo 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 @@ public override IColor GetColor(params double[] values) { 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 @@ public sealed class PatternColorSpaceDetails : ColorSpaceDetails /// Valid for Uncoloured Tiling Patterns. Wwill throw a otherwise. /// /// - internal override int BaseNumberOfColorComponents => UnderlyingColourSpace.NumberOfColorComponents; + internal override int BaseNumberOfColorComponents => UnderlyingColourSpace!.NumberOfColorComponents; /// /// The underlying color space for Uncoloured Tiling Patterns. /// - [CanBeNull] - public ColorSpaceDetails UnderlyingColourSpace { get; } + public ColorSpaceDetails? UnderlyingColourSpace { get; } /// /// Create a new . @@ -1349,7 +1346,7 @@ public override IColor GetColor(params double[] values) /// /// /// Always returns null. - public override IColor GetInitializeColor() + public override IColor? GetInitializeColor() { return null; } @@ -1409,7 +1406,7 @@ public override IColor GetColor(params double[] values) } /// - public override IColor GetInitializeColor() + public override IColor? GetInitializeColor() { throw new InvalidOperationException("UnsupportedColorSpaceDetails"); } diff --git a/src/UglyToad.PdfPig/Graphics/Colors/GrayColor.cs b/src/UglyToad.PdfPig/Graphics/Colors/GrayColor.cs index bb070b947..6bce44b76 100644 --- a/src/UglyToad.PdfPig/Graphics/Colors/GrayColor.cs +++ b/src/UglyToad.PdfPig/Graphics/Colors/GrayColor.cs @@ -41,16 +41,20 @@ public GrayColor(double gray) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { - return Equals(obj as GrayColor); + return obj is GrayColor other && Equals(other); } /// - 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; } /// diff --git a/src/UglyToad.PdfPig/Graphics/Colors/PatternColor.cs b/src/UglyToad.PdfPig/Graphics/Colors/PatternColor.cs index 6b8aeb6a2..42d5209cf 100644 --- a/src/UglyToad.PdfPig/Graphics/Colors/PatternColor.cs +++ b/src/UglyToad.PdfPig/Graphics/Colors/PatternColor.cs @@ -143,19 +143,19 @@ public TilingPatternColor(TransformationMatrix matrix, DictionaryToken extGState } /// - 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); } /// - 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 @@ public ShadingPatternColor(TransformationMatrix matrix, DictionaryToken extGStat } /// - 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); } /// - 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) && diff --git a/src/UglyToad.PdfPig/Graphics/Colors/RGBColor.cs b/src/UglyToad.PdfPig/Graphics/Colors/RGBColor.cs index 695ab7c99..2f3c2f9a9 100644 --- a/src/UglyToad.PdfPig/Graphics/Colors/RGBColor.cs +++ b/src/UglyToad.PdfPig/Graphics/Colors/RGBColor.cs @@ -53,26 +53,25 @@ public RGBColor(double r, double g, double b) public (double r, double g, double b) ToRGBValues() => (R, G, B); /// - 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); } /// /// /// Whether 2 RGB colors are equal across all channels. /// - 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; } /// diff --git a/src/UglyToad.PdfPig/Graphics/Colors/RGBWorkingSpace.cs b/src/UglyToad.PdfPig/Graphics/Colors/RGBWorkingSpace.cs index a090c9919..f05dcff37 100644 --- a/src/UglyToad.PdfPig/Graphics/Colors/RGBWorkingSpace.cs +++ b/src/UglyToad.PdfPig/Graphics/Colors/RGBWorkingSpace.cs @@ -1,4 +1,6 @@ -namespace UglyToad.PdfPig.Graphics.Colors +#nullable disable + +namespace UglyToad.PdfPig.Graphics.Colors { using System; @@ -7,8 +9,7 @@ internal class RGBWorkingSpace { 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace 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 @@ internal class RGBWorkingSpace private static Func CreateGammaFunc(double gamma) { - return val => - { + return val => { var result = Math.Pow(val, 1 / gamma); return double.IsNaN(result) ? 0 : result; }; @@ -175,4 +161,4 @@ internal XYZReferenceWhite() { } public readonly (double X, double Y, double Z) F11 = (1.00962, 1.00000, 0.64350); } } -} +} \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Graphics/Colors/ResourceColorSpace.cs b/src/UglyToad.PdfPig/Graphics/Colors/ResourceColorSpace.cs index 8d0cafe8f..ccbab895e 100644 --- a/src/UglyToad.PdfPig/Graphics/Colors/ResourceColorSpace.cs +++ b/src/UglyToad.PdfPig/Graphics/Colors/ResourceColorSpace.cs @@ -15,9 +15,9 @@ public readonly struct ResourceColorSpace /// /// The color space data. /// - public IToken Data { get; } + public IToken? Data { get; } - internal ResourceColorSpace(NameToken name, IToken data) + internal ResourceColorSpace(NameToken name, IToken? data) { Name = name; Data = data; diff --git a/src/UglyToad.PdfPig/Graphics/Colors/Shading.cs b/src/UglyToad.PdfPig/Graphics/Colors/Shading.cs index 49dc7e957..90e5335d2 100644 --- a/src/UglyToad.PdfPig/Graphics/Colors/Shading.cs +++ b/src/UglyToad.PdfPig/Graphics/Colors/Shading.cs @@ -35,7 +35,7 @@ public abstract class Shading /// the shading, to fill those portions of the area to be painted /// that lie outside the bounds of the shading object. /// - public double[] Background { get; } + public double[]? Background { get; } /// /// The shading's bounding box. The coordinates shall be interpreted @@ -62,7 +62,7 @@ public abstract class Shading /// Create a new . /// 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 @@ protected internal Shading(ShadingType shadingType, bool antiAlias, DictionaryTo /// /// The shading's function(s), if any. /// - public abstract PdfFunction[] Functions { get; } + public abstract PdfFunction[]? Functions { get; } /// /// Convert the input values using the functions of the shading. @@ -157,7 +157,7 @@ public sealed class FunctionBasedShading : Shading /// Create a new . /// 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 @@ public sealed class AxialShading : Shading /// Create a new . /// 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 @@ public sealed class RadialShading : Shading /// Create a new . /// 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 @@ public sealed class FreeFormGouraudShading : Shading /// to the nearest valid value. /// This entry shall not be used with an Indexed colour space. /// - public override PdfFunction[] Functions { get; } + public override PdfFunction[]? Functions { get; } /// /// Create a new . /// 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 @@ public sealed class LatticeFormGouraudShading : Shading /// 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. /// - public override PdfFunction[] Functions { get; } + public override PdfFunction[]? Functions { get; } /// /// Create a new . /// 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 @@ public class CoonsPatchMeshesShading : Shading /// shall be adjusted to the nearest valid value. /// This entry shall not be used with an Indexed colour space. /// - public override PdfFunction[] Functions { get; } + public override PdfFunction[]? Functions { get; } /// /// Create a new . /// 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 @@ public sealed class TensorProductPatchMeshesShading : Shading /// shall be adjusted to the nearest valid value. /// This entry shall not be used with an Indexed colour space. /// - public override PdfFunction[] Functions { get; } + public override PdfFunction[]? Functions { get; } /// /// Create a new . /// 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; diff --git a/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs b/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs index a3353de4a..40d50db7e 100644 --- a/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs +++ b/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs @@ -1,4 +1,6 @@ -namespace UglyToad.PdfPig.Graphics +#nullable disable + +namespace UglyToad.PdfPig.Graphics { using System; using System.Collections.Generic; @@ -30,8 +32,7 @@ internal class ContentStreamProcessor : BaseStreamProcessor /// /// Stores a link to each image (either inline or XObject) as it is encountered in the content stream. /// - private readonly List> images = - new List>(); + private readonly List> images = new(); /// /// Stores each marked content as it is encountered in the content stream. @@ -362,7 +363,7 @@ public override void ClosePath() { AddCurrentSubpath(); - if (CurrentPath.IsClipping) + if (CurrentPath!.IsClipping) { EndPath(); return; @@ -413,7 +414,7 @@ public override void ModifyClippingIntersect(FillingRule clippingRule) if (ParsingOptions.ClipPaths) { - var currentClipping = GetCurrentState().CurrentClippingPath; + var currentClipping = GetCurrentState().CurrentClippingPath!; currentClipping.SetClipping(clippingRule); var newClippings = CurrentPath.Clip(currentClipping, ParsingOptions.Logger); diff --git a/src/UglyToad.PdfPig/Graphics/Core/LineDashPattern.cs b/src/UglyToad.PdfPig/Graphics/Core/LineDashPattern.cs index ec86ffc3d..02c43829e 100644 --- a/src/UglyToad.PdfPig/Graphics/Core/LineDashPattern.cs +++ b/src/UglyToad.PdfPig/Graphics/Core/LineDashPattern.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.Linq; - using Util.JetBrains.Annotations; /// /// The line dash pattern controls the pattern of dashes and gaps used to stroke paths. @@ -19,7 +18,6 @@ public readonly struct LineDashPattern /// /// The numbers that specify the lengths of alternating dashes and gaps. /// - [NotNull] public IReadOnlyList Array { get; } /// @@ -27,7 +25,7 @@ public readonly struct LineDashPattern /// /// The phase. . /// The array. . - public LineDashPattern(int phase, [NotNull]IReadOnlyList array) + public LineDashPattern(int phase, IReadOnlyList array) { Phase = phase; Array = array ?? throw new ArgumentNullException(nameof(array)); diff --git a/src/UglyToad.PdfPig/Graphics/CurrentFontState.cs b/src/UglyToad.PdfPig/Graphics/CurrentFontState.cs index 20d78d2fa..e6d134af8 100644 --- a/src/UglyToad.PdfPig/Graphics/CurrentFontState.cs +++ b/src/UglyToad.PdfPig/Graphics/CurrentFontState.cs @@ -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; diff --git a/src/UglyToad.PdfPig/Graphics/CurrentGraphicsState.cs b/src/UglyToad.PdfPig/Graphics/CurrentGraphicsState.cs index 61d27c169..ad8a13bcc 100644 --- a/src/UglyToad.PdfPig/Graphics/CurrentGraphicsState.cs +++ b/src/UglyToad.PdfPig/Graphics/CurrentGraphicsState.cs @@ -1,4 +1,6 @@ -// ReSharper disable RedundantDefaultMemberInitializer +#nullable disable + +// ReSharper disable RedundantDefaultMemberInitializer namespace UglyToad.PdfPig.Graphics { using Colors; diff --git a/src/UglyToad.PdfPig/Graphics/IColorSpaceContext.cs b/src/UglyToad.PdfPig/Graphics/IColorSpaceContext.cs index 375c89d13..80e82fffd 100644 --- a/src/UglyToad.PdfPig/Graphics/IColorSpaceContext.cs +++ b/src/UglyToad.PdfPig/Graphics/IColorSpaceContext.cs @@ -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 @@ public interface IColorSpaceContext : IDeepCloneable /// /// The color space name. /// The color space dictionary. Default value is null. - void SetStrokingColorspace(NameToken colorspace, DictionaryToken dictionary = null); + void SetStrokingColorspace(NameToken colorspace, DictionaryToken? dictionary = null); /// /// Set the current color space to use for nonstroking operations and initialize the nonstroking color. /// /// The color space name. /// The color space dictionary. Default value is null. - void SetNonStrokingColorspace(NameToken colorspace, DictionaryToken dictionary = null); + void SetNonStrokingColorspace(NameToken colorspace, DictionaryToken? dictionary = null); /// /// Set the color to use for stroking operations using the current color space. /// - void SetStrokingColor(IReadOnlyList operands, NameToken patternName = null); + void SetStrokingColor(IReadOnlyList operands, NameToken? patternName = null); /// /// Set the stroking color space to DeviceGray and set the gray level to use for stroking operations. @@ -65,7 +65,7 @@ public interface IColorSpaceContext : IDeepCloneable /// /// Set the color to use for nonstroking operations using the current color space. /// - void SetNonStrokingColor(IReadOnlyList operands, NameToken patternName = null); + void SetNonStrokingColor(IReadOnlyList operands, NameToken? patternName = null); /// /// Set the nonstroking color space to DeviceGray and set the gray level to use for nonstroking operations. diff --git a/src/UglyToad.PdfPig/Graphics/IGraphicsStateOperationFactory.cs b/src/UglyToad.PdfPig/Graphics/IGraphicsStateOperationFactory.cs index 06196854c..72c092e7d 100644 --- a/src/UglyToad.PdfPig/Graphics/IGraphicsStateOperationFactory.cs +++ b/src/UglyToad.PdfPig/Graphics/IGraphicsStateOperationFactory.cs @@ -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 operands); + IGraphicsStateOperation? Create(OperatorToken op, IReadOnlyList operands); } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Graphics/IOperationContext.cs b/src/UglyToad.PdfPig/Graphics/IOperationContext.cs index e1b7f9d19..0722acfdc 100644 --- a/src/UglyToad.PdfPig/Graphics/IOperationContext.cs +++ b/src/UglyToad.PdfPig/Graphics/IOperationContext.cs @@ -132,7 +132,7 @@ public interface IOperationContext /// /// Indicate that a marked content region is started. /// - void BeginMarkedContent(NameToken name, NameToken propertyDictionaryName, DictionaryToken properties); + void BeginMarkedContent(NameToken name, NameToken? propertyDictionaryName, DictionaryToken? properties); /// /// Indicates that the current marked content region is complete. diff --git a/src/UglyToad.PdfPig/Graphics/InlineImageBuilder.cs b/src/UglyToad.PdfPig/Graphics/InlineImageBuilder.cs index 641b99ab9..3ea587a67 100644 --- a/src/UglyToad.PdfPig/Graphics/InlineImageBuilder.cs +++ b/src/UglyToad.PdfPig/Graphics/InlineImageBuilder.cs @@ -18,14 +18,15 @@ public sealed class InlineImageBuilder /// /// Inline image properties. /// - public IReadOnlyDictionary Properties { get; internal set; } + public IReadOnlyDictionary? Properties { get; internal set; } /// /// Inline image bytes. /// - public IReadOnlyList Bytes { get; internal set; } + public IReadOnlyList? 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 @@ internal InlineImage CreateInlineImage(TransformationMatrix transformationMatrix var bitsPerComponent = GetByKeys(NameToken.BitsPerComponent, NameToken.Bpc, !isMask)?.Int ?? 1; - NameToken colorSpaceName = null; + NameToken? colorSpaceName = null; if (!isMask) { @@ -110,8 +111,11 @@ internal InlineImage CreateInlineImage(TransformationMatrix transformationMatrix details); } +#nullable disable + // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local - private T GetByKeys(NameToken name1, NameToken name2, bool required) where T : IToken + private T GetByKeys(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 @@ private T GetByKeys(NameToken name1, NameToken name2, bool required) where T throw new PdfDocumentFormatException($"Inline image dictionary missing required entry {name1}/{name2}."); } - return default(T); + return null; } } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Graphics/MarkedContentStack.cs b/src/UglyToad.PdfPig/Graphics/MarkedContentStack.cs index 9d26487b5..64702afec 100644 --- a/src/UglyToad.PdfPig/Graphics/MarkedContentStack.cs +++ b/src/UglyToad.PdfPig/Graphics/MarkedContentStack.cs @@ -17,7 +17,7 @@ internal class MarkedContentStack private readonly Stack builderStack = new Stack(); private int number = -1; - private MarkedContentElementActiveBuilder top; + private MarkedContentElementActiveBuilder? top; public bool CanPop => top != null; @@ -32,7 +32,7 @@ public void Push(NameToken name, DictionaryToken properties) builderStack.Push(top); } - public MarkedContentElement Pop(IPdfTokenScanner pdfScanner) + public MarkedContentElement? Pop(IPdfTokenScanner pdfScanner) { var builder = builderStack.Pop(); @@ -116,7 +116,7 @@ public void AddPath(PdfPath path) 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 @@ public MarkedContentElement Build(IPdfTokenScanner pdfScanner) } var artifactType = ArtifactMarkedContentElement.ArtifactType.Unknown; - if (properties.TryGet(NameToken.Type, pdfScanner, out IDataToken typeToken) + if (properties.TryGet(NameToken.Type, pdfScanner, out IDataToken? typeToken) && Enum.TryParse(typeToken.Data, true, out ArtifactMarkedContentElement.ArtifactType parsedType)) { artifactType = parsedType; @@ -152,12 +152,12 @@ public MarkedContentElement Build(IPdfTokenScanner pdfScanner) 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 @@ public MarkedContentElement Build(IPdfTokenScanner pdfScanner) } } - return new ArtifactMarkedContentElement(mcid, name, properties, language, + return new ArtifactMarkedContentElement(mcid, name,properties, + language, actualText, alternateDescription, expandedForm, @@ -208,10 +209,10 @@ public MarkedContentElement Build(IPdfTokenScanner pdfScanner) 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 token)) + if (properties.TryGet(optionName, pdfScanner, out IDataToken? token)) { result = token.Data; } diff --git a/src/UglyToad.PdfPig/Graphics/Operations/MarkedContent/BeginMarkedContentWithProperties.cs b/src/UglyToad.PdfPig/Graphics/Operations/MarkedContent/BeginMarkedContentWithProperties.cs index 75063865b..4f493721a 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/MarkedContent/BeginMarkedContentWithProperties.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/MarkedContent/BeginMarkedContentWithProperties.cs @@ -2,7 +2,6 @@ { using System.IO; using Tokens; - using Util.JetBrains.Annotations; using Writer; /// @@ -30,15 +29,13 @@ public class BeginMarkedContentWithProperties : IGraphicsStateOperation /// The name of the property dictionary in the Properties subdictionary of the current resource dictionary. /// Can be if the property dictionary is provided inline. /// - [CanBeNull] - public NameToken PropertyDictionaryName { get; } + public NameToken? PropertyDictionaryName { get; } /// /// The marked-content sequence properties. /// Can be if a name of the property dictionary is provided instead. /// - [CanBeNull] - public DictionaryToken Properties { get; } + public DictionaryToken? Properties { get; } /// /// Create a new . @@ -65,7 +62,7 @@ public BeginMarkedContentWithProperties(NameToken name, DictionaryToken properti /// public void Run(IOperationContext operationContext) { - operationContext.BeginMarkedContent(Name, PropertyDictionaryName, Properties); + operationContext.BeginMarkedContent(Name, PropertyDictionaryName, Properties!); } /// @@ -80,7 +77,7 @@ public void Write(Stream stream) } else { - TokenWriter.WriteToken(Properties, stream); + TokenWriter.WriteToken(Properties!, stream); } stream.WriteWhiteSpace(); diff --git a/src/UglyToad.PdfPig/Graphics/Operations/MarkedContent/DesignateMarkedContentPointWithProperties.cs b/src/UglyToad.PdfPig/Graphics/Operations/MarkedContent/DesignateMarkedContentPointWithProperties.cs index 0f282fc02..a10f787d8 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/MarkedContent/DesignateMarkedContentPointWithProperties.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/MarkedContent/DesignateMarkedContentPointWithProperties.cs @@ -2,7 +2,6 @@ { using System.IO; using Tokens; - using Util.JetBrains.Annotations; using Writer; /// @@ -30,15 +29,13 @@ public class DesignateMarkedContentPointWithProperties : IGraphicsStateOperation /// The name of the property dictionary in the Properties subdictionary of the current resource dictionary. /// Can be if the property dictionary is provided inline. /// - [CanBeNull] - public NameToken PropertyDictionaryName { get; } + public NameToken? PropertyDictionaryName { get; } /// /// The marked-content point properties. /// Can be if a name of the property dictionary is provided instead. /// - [CanBeNull] - public DictionaryToken Properties { get; } + public DictionaryToken? Properties { get; } /// /// Create a new . @@ -80,7 +77,7 @@ public void Write(Stream stream) } else { - TokenWriter.WriteToken(Properties, stream); + TokenWriter.WriteToken(Properties!, stream); } stream.WriteWhiteSpace(); diff --git a/src/UglyToad.PdfPig/Graphics/Operations/SetNonStrokeColorAdvanced.cs b/src/UglyToad.PdfPig/Graphics/Operations/SetNonStrokeColorAdvanced.cs index f5a34ae87..fea19d627 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/SetNonStrokeColorAdvanced.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/SetNonStrokeColorAdvanced.cs @@ -29,7 +29,7 @@ public class SetNonStrokeColorAdvanced : IGraphicsStateOperation /// /// The name of an entry in the Pattern subdictionary of the current resource dictionary. /// - public NameToken PatternName { get; } + public NameToken? PatternName { get; } /// /// Create a new . diff --git a/src/UglyToad.PdfPig/Graphics/Operations/SetStrokeColorAdvanced.cs b/src/UglyToad.PdfPig/Graphics/Operations/SetStrokeColorAdvanced.cs index 848e503e0..73e7e0d22 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/SetStrokeColorAdvanced.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/SetStrokeColorAdvanced.cs @@ -29,7 +29,7 @@ public class SetStrokeColorAdvanced : IGraphicsStateOperation /// /// The name of an entry in the Pattern subdictionary of the current resource dictionary. /// - public NameToken PatternName { get; } + public NameToken? PatternName { get; } /// /// Create a new . diff --git a/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/MoveToNextLineShowText.cs b/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/MoveToNextLineShowText.cs index 21af2144a..519a0c328 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/MoveToNextLineShowText.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/MoveToNextLineShowText.cs @@ -2,7 +2,6 @@ { using System.IO; using TextPositioning; - using Util.JetBrains.Annotations; /// /// @@ -21,14 +20,12 @@ public class MoveToNextLineShowText : IGraphicsStateOperation /// /// The text to show as a . /// - [CanBeNull] - public string Text { get; } + public string? Text { get; } /// /// The text to show as hex bytes. /// - [CanBeNull] - public byte[] Bytes { get; } + public byte[]? Bytes { get; } /// /// Create a new . @@ -53,7 +50,7 @@ public void Run(IOperationContext operationContext) { 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); diff --git a/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/MoveToNextLineShowTextWithSpacing.cs b/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/MoveToNextLineShowTextWithSpacing.cs index 3f7fb1d8a..179f8a26e 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/MoveToNextLineShowTextWithSpacing.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/MoveToNextLineShowTextWithSpacing.cs @@ -3,7 +3,6 @@ using System.IO; using TextPositioning; using TextState; - using Util.JetBrains.Annotations; /// /// @@ -32,14 +31,12 @@ public class MoveToNextLineShowTextWithSpacing : IGraphicsStateOperation /// /// The bytes of the text. /// - [CanBeNull] - public byte[] Bytes { get; } + public byte[]? Bytes { get; } /// /// The text to show. /// - [CanBeNull] - public string Text { get; } + public string? Text { get; } /// /// Create a new . @@ -73,7 +70,7 @@ public void Run(IOperationContext operationContext) 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); diff --git a/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/ShowText.cs b/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/ShowText.cs index e8a1d8cb5..8de89b1b0 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/ShowText.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/TextShowing/ShowText.cs @@ -1,8 +1,7 @@ namespace UglyToad.PdfPig.Graphics.Operations.TextShowing { - using System.IO; using PdfPig.Core; - using Util.JetBrains.Annotations; + using System.IO; /// /// @@ -34,14 +33,12 @@ public class ShowText : IGraphicsStateOperation /// /// The text string to show. /// - [CanBeNull] - public string Text { get; } + public string? Text { get; } /// /// The bytes of the string to show. /// - [CanBeNull] - public byte[] Bytes { get; } + public byte[]? Bytes { get; } /// /// Create a new . @@ -67,7 +64,7 @@ public void Run(IOperationContext operationContext) 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 '\'. diff --git a/src/UglyToad.PdfPig/Graphics/Operations/TextState/SetFontAndSize.cs b/src/UglyToad.PdfPig/Graphics/Operations/TextState/SetFontAndSize.cs index 0f7cce241..6837f73d4 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/TextState/SetFontAndSize.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/TextState/SetFontAndSize.cs @@ -4,7 +4,6 @@ using System.Globalization; using System.IO; using Tokens; - using Util.JetBrains.Annotations; /// /// @@ -25,7 +24,6 @@ public class SetFontAndSize : IGraphicsStateOperation /// /// The name of the font as defined in the resource dictionary. /// - [NotNull] public NameToken Font { get; } /// diff --git a/src/UglyToad.PdfPig/Graphics/PdfPath.cs b/src/UglyToad.PdfPig/Graphics/PdfPath.cs index bfd569852..7d9aa8f5f 100644 --- a/src/UglyToad.PdfPig/Graphics/PdfPath.cs +++ b/src/UglyToad.PdfPig/Graphics/PdfPath.cs @@ -29,7 +29,7 @@ public class PdfPath : List /// /// The fill color. /// - public IColor FillColor { get; internal set; } + public IColor? FillColor { get; internal set; } /// /// Returns true if the path is stroked. @@ -39,7 +39,7 @@ public class PdfPath : List /// /// The stroke color. /// - public IColor StrokeColor { get; internal set; } + public IColor? StrokeColor { get; internal set; } /// /// Thickness in user space units of path to be stroked. diff --git a/src/UglyToad.PdfPig/Graphics/ReflectionGraphicsStateOperationFactory.cs b/src/UglyToad.PdfPig/Graphics/ReflectionGraphicsStateOperationFactory.cs index 8c1f36753..53cd79dae 100644 --- a/src/UglyToad.PdfPig/Graphics/ReflectionGraphicsStateOperationFactory.cs +++ b/src/UglyToad.PdfPig/Graphics/ReflectionGraphicsStateOperationFactory.cs @@ -30,7 +30,7 @@ internal class ReflectionGraphicsStateOperationFactory : IGraphicsStateOperation public ReflectionGraphicsStateOperationFactory() { - var assemblyTypes = Assembly.GetAssembly(typeof(ReflectionGraphicsStateOperationFactory)).GetTypes(); + var assemblyTypes = Assembly.GetAssembly(typeof(ReflectionGraphicsStateOperationFactory))!.GetTypes(); var result = new Dictionary(); @@ -45,7 +45,7 @@ public ReflectionGraphicsStateOperationFactory() 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 @@ private static double OperandToDouble(IToken token) return numeric.Data; } - public IGraphicsStateOperation Create(OperatorToken op, IReadOnlyList operands) + public IGraphicsStateOperation? Create(OperatorToken op, IReadOnlyList operands) { switch (op.Data) { @@ -388,7 +388,7 @@ public IGraphicsStateOperation Create(OperatorToken op, IReadOnlyList op 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 @@ public IGraphicsStateOperation Create(OperatorToken op, IReadOnlyList op if (constructor.IsPrivate) { - return (IGraphicsStateOperation)operationType.GetField("Value").GetValue(null); + return (IGraphicsStateOperation)operationType.GetField("Value")?.GetValue(null)!; } var parameters = constructor.GetParameters(); diff --git a/src/UglyToad.PdfPig/Graphics/XObjectContentRecord.cs b/src/UglyToad.PdfPig/Graphics/XObjectContentRecord.cs index b8d4b498c..f7cfa8eee 100644 --- a/src/UglyToad.PdfPig/Graphics/XObjectContentRecord.cs +++ b/src/UglyToad.PdfPig/Graphics/XObjectContentRecord.cs @@ -5,7 +5,6 @@ using Core; using PdfPig.Core; using Tokens; - using Util.JetBrains.Annotations; using XObjects; /// @@ -21,7 +20,6 @@ public class XObjectContentRecord /// /// The XObject stream. /// - [NotNull] public StreamToken Stream { get; } /// diff --git a/src/UglyToad.PdfPig/IO/RandomAccessBuffer.cs b/src/UglyToad.PdfPig/IO/RandomAccessBuffer.cs index 69ce8e167..b6f351b68 100644 --- a/src/UglyToad.PdfPig/IO/RandomAccessBuffer.cs +++ b/src/UglyToad.PdfPig/IO/RandomAccessBuffer.cs @@ -1,4 +1,6 @@ -namespace UglyToad.PdfPig.IO +#nullable disable + +namespace UglyToad.PdfPig.IO { using System; using System.Collections.Generic; diff --git a/src/UglyToad.PdfPig/Images/Png/Pixel.cs b/src/UglyToad.PdfPig/Images/Png/Pixel.cs index 46c5766c5..db4cc17a0 100644 --- a/src/UglyToad.PdfPig/Images/Png/Pixel.cs +++ b/src/UglyToad.PdfPig/Images/Png/Pixel.cs @@ -1,5 +1,7 @@ namespace UglyToad.PdfPig.Images.Png { + using System; + /// /// A pixel in a image. /// @@ -76,18 +78,9 @@ public Pixel(byte grayscale) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { - if (obj is Pixel pixel) - { - return IsGrayscale == pixel.IsGrayscale - && A == pixel.A - && R == pixel.R - && G == pixel.G - && B == pixel.B; - } - - return false; + return obj is Pixel other && Equals(other); } /// @@ -103,15 +96,7 @@ public bool Equals(Pixel other) /// public override int GetHashCode() { - unchecked - { - var hashCode = R.GetHashCode(); - hashCode = (hashCode * 397) ^ G.GetHashCode(); - hashCode = (hashCode * 397) ^ B.GetHashCode(); - hashCode = (hashCode * 397) ^ A.GetHashCode(); - hashCode = (hashCode * 397) ^ IsGrayscale.GetHashCode(); - return hashCode; - } + return HashCode.Combine(R, G, B, A, IsGrayscale); } /// diff --git a/src/UglyToad.PdfPig/Images/Png/Png.cs b/src/UglyToad.PdfPig/Images/Png/Png.cs index 9532d5a4d..d64850e2e 100644 --- a/src/UglyToad.PdfPig/Images/Png/Png.cs +++ b/src/UglyToad.PdfPig/Images/Png/Png.cs @@ -56,7 +56,7 @@ internal Png(ImageHeader header, RawPngData data, bool hasTransparencyChunk) /// The stream containing PNG data to be read. /// Optional: A visitor which is called whenever a chunk is read by the library. /// The data from the stream. - public static Png Open(Stream stream, IChunkVisitor chunkVisitor = null) + public static Png Open(Stream stream, IChunkVisitor? chunkVisitor = null) => PngOpener.Open(stream, chunkVisitor); /// @@ -65,7 +65,7 @@ public static Png Open(Stream stream, IChunkVisitor chunkVisitor = null) /// The bytes of the PNG data to be read. /// Optional: A visitor which is called whenever a chunk is read by the library. /// The data from the bytes. - public static Png Open(byte[] bytes, IChunkVisitor chunkVisitor = null) + public static Png Open(byte[] bytes, IChunkVisitor? chunkVisitor = null) { using (var memoryStream = new MemoryStream(bytes)) { @@ -80,7 +80,7 @@ public static Png Open(byte[] bytes, IChunkVisitor chunkVisitor = null) /// Optional: A visitor which is called whenever a chunk is read by the library. /// This will open the file to obtain a so will lock the file during reading. /// The data from the file. - public static Png Open(string filePath, IChunkVisitor chunkVisitor = null) + public static Png Open(string filePath, IChunkVisitor? chunkVisitor = null) { using (var fileStream = File.OpenRead(filePath)) { diff --git a/src/UglyToad.PdfPig/Images/Png/PngFromPdfImageFactory.cs b/src/UglyToad.PdfPig/Images/Png/PngFromPdfImageFactory.cs index 38572183d..5fe3106c6 100644 --- a/src/UglyToad.PdfPig/Images/Png/PngFromPdfImageFactory.cs +++ b/src/UglyToad.PdfPig/Images/Png/PngFromPdfImageFactory.cs @@ -1,18 +1,19 @@ namespace UglyToad.PdfPig.Images.Png -{ +{ + using System.Diagnostics.CodeAnalysis; using Content; using Graphics.Colors; using UglyToad.PdfPig.Core; internal static class PngFromPdfImageFactory { - public static bool TryGenerate(IPdfImage image, out byte[] bytes) + public static bool TryGenerate(IPdfImage image, [NotNullWhen(true)] out byte[]? bytes) { bytes = null; var hasValidDetails = image.ColorSpaceDetails != null && !(image.ColorSpaceDetails is UnsupportedColorSpaceDetails); - var isColorSpaceSupported = hasValidDetails && image.ColorSpaceDetails.BaseType != ColorSpace.Pattern; + var isColorSpaceSupported = hasValidDetails && image.ColorSpaceDetails!.BaseType != ColorSpace.Pattern; if (!isColorSpaceSupported || !image.TryGetBytes(out var bytesPure)) { @@ -21,10 +22,10 @@ public static bool TryGenerate(IPdfImage image, out byte[] bytes) try { - bytesPure = ColorSpaceDetailsByteConverter.Convert(image.ColorSpaceDetails, bytesPure, + bytesPure = ColorSpaceDetailsByteConverter.Convert(image.ColorSpaceDetails!, bytesPure, image.BitsPerComponent, image.WidthInSamples, image.HeightInSamples); - var numberOfComponents = image.ColorSpaceDetails.BaseNumberOfColorComponents; + var numberOfComponents = image.ColorSpaceDetails!.BaseNumberOfColorComponents; var is3Byte = numberOfComponents == 3; diff --git a/src/UglyToad.PdfPig/Images/Png/PngOpener.cs b/src/UglyToad.PdfPig/Images/Png/PngOpener.cs index f3a8f300d..8cce79d6c 100644 --- a/src/UglyToad.PdfPig/Images/Png/PngOpener.cs +++ b/src/UglyToad.PdfPig/Images/Png/PngOpener.cs @@ -8,7 +8,7 @@ internal static class PngOpener { - public static Png Open(Stream stream, IChunkVisitor chunkVisitor = null) => Open(stream, new PngOpenerSettings + public static Png Open(Stream stream, IChunkVisitor? chunkVisitor = null) => Open(stream, new PngOpenerSettings { ChunkVisitor = chunkVisitor }); @@ -37,7 +37,7 @@ public static Png Open(Stream stream, PngOpenerSettings settings) var hasEncounteredImageEnd = false; - Palette palette = null; + Palette? palette = null; using (var output = new MemoryStream()) { diff --git a/src/UglyToad.PdfPig/Images/Png/PngOpenerSettings.cs b/src/UglyToad.PdfPig/Images/Png/PngOpenerSettings.cs index 621e82049..f55d70619 100644 --- a/src/UglyToad.PdfPig/Images/Png/PngOpenerSettings.cs +++ b/src/UglyToad.PdfPig/Images/Png/PngOpenerSettings.cs @@ -5,7 +5,7 @@ internal class PngOpenerSettings /// /// The code to execute whenever a chunk is read. Can be . /// - public IChunkVisitor ChunkVisitor { get; set; } + public IChunkVisitor? ChunkVisitor { get; set; } /// /// Whether to throw if the image contains data after the image end marker. diff --git a/src/UglyToad.PdfPig/Images/Png/RawPngData.cs b/src/UglyToad.PdfPig/Images/Png/RawPngData.cs index 68754d953..18318f8ce 100644 --- a/src/UglyToad.PdfPig/Images/Png/RawPngData.cs +++ b/src/UglyToad.PdfPig/Images/Png/RawPngData.cs @@ -5,12 +5,12 @@ /// /// Provides convenience methods for indexing into a raw byte array to extract pixel values. /// - internal class RawPngData + internal sealed class RawPngData { private readonly byte[] data; private readonly int bytesPerPixel; private readonly int width; - private readonly Palette palette; + private readonly Palette? palette; private readonly ColorType colorType; private readonly int rowOffset; private readonly int bitDepth; @@ -22,7 +22,7 @@ internal class RawPngData /// The number of bytes in each pixel. /// The palette for the image. /// The image header. - public RawPngData(byte[] data, int bytesPerPixel, Palette palette, ImageHeader imageHeader) + public RawPngData(byte[] data, int bytesPerPixel, Palette? palette, ImageHeader imageHeader) { if (width < 0) { @@ -120,7 +120,7 @@ public Pixel GetPixel(int x, int y) return pixel; default: - throw new InvalidOperationException($"Unreconized number of bytes per pixel: {bytesPerPixel}."); + throw new InvalidOperationException($"Unrecognized number of bytes per pixel: {bytesPerPixel}."); } } diff --git a/src/UglyToad.PdfPig/Outline/BookmarksProvider.cs b/src/UglyToad.PdfPig/Outline/BookmarksProvider.cs index 962b7099c..9eb96c4e4 100644 --- a/src/UglyToad.PdfPig/Outline/BookmarksProvider.cs +++ b/src/UglyToad.PdfPig/Outline/BookmarksProvider.cs @@ -25,19 +25,19 @@ public BookmarksProvider(ILog log, IPdfTokenScanner pdfScanner) /// /// Extract bookmarks, if any. /// - public Bookmarks GetBookmarks(Catalog catalog) + public Bookmarks? GetBookmarks(Catalog catalog) { - if (!catalog.CatalogDictionary.TryGet(NameToken.Outlines, pdfScanner, out DictionaryToken outlinesDictionary)) + if (!catalog.CatalogDictionary.TryGet(NameToken.Outlines, pdfScanner, out DictionaryToken? outlinesDictionary)) { return null; } - if (outlinesDictionary.TryGet(NameToken.Type, pdfScanner, out NameToken typeName) && typeName != NameToken.Outlines) + if (outlinesDictionary.TryGet(NameToken.Type, pdfScanner, out NameToken? typeName) && typeName != NameToken.Outlines) { log?.Error($"Outlines (bookmarks) dictionary did not have correct type specified: {typeName}."); } - if (!outlinesDictionary.TryGet(NameToken.First, pdfScanner, out DictionaryToken next)) + if (!outlinesDictionary.TryGet(NameToken.First, pdfScanner, out DictionaryToken? next)) { return null; } @@ -78,7 +78,7 @@ private void ReadBookmarksRecursively(DictionaryToken nodeDictionary, int level, } var children = new List(); - if (nodeDictionary.TryGet(NameToken.First, pdfScanner, out DictionaryToken firstChild)) + if (nodeDictionary.TryGet(NameToken.First, pdfScanner, out DictionaryToken? firstChild)) { ReadBookmarksRecursively(firstChild, level + 1, true, seen, namedDestinations, children); } diff --git a/src/UglyToad.PdfPig/Outline/Destinations/DestinationProvider.cs b/src/UglyToad.PdfPig/Outline/Destinations/DestinationProvider.cs index 52f5d97c9..9da4c6f8d 100644 --- a/src/UglyToad.PdfPig/Outline/Destinations/DestinationProvider.cs +++ b/src/UglyToad.PdfPig/Outline/Destinations/DestinationProvider.cs @@ -1,5 +1,6 @@ namespace UglyToad.PdfPig.Outline.Destinations { + using System.Diagnostics.CodeAnalysis; using Logging; using Tokenization.Scanner; using Tokens; @@ -18,13 +19,20 @@ internal static class DestinationProvider /// to enforce a check for indirect page references (which is not allowed for GoToR) /// /// - internal static bool TryGetDestination(DictionaryToken dictionary, NameToken destinationToken, NamedDestinations namedDestinations, IPdfTokenScanner pdfScanner, ILog log, bool isRemoteDestination, out ExplicitDestination destination) + internal static bool TryGetDestination( + DictionaryToken dictionary, + NameToken destinationToken, + NamedDestinations namedDestinations, + IPdfTokenScanner pdfScanner, + ILog log, + bool isRemoteDestination, + [NotNullWhen(true)] out ExplicitDestination? destination) { - if (dictionary.TryGet(destinationToken, pdfScanner, out ArrayToken destArray)) + if (dictionary.TryGet(destinationToken, pdfScanner, out ArrayToken? destArray)) { return namedDestinations.TryGetExplicitDestination(destArray, log, isRemoteDestination, out destination); } - if (dictionary.TryGet(destinationToken, pdfScanner, out IDataToken destStringToken)) + if (dictionary.TryGet(destinationToken, pdfScanner, out IDataToken? destStringToken)) { return namedDestinations.TryGet(destStringToken.Data, out destination); } diff --git a/src/UglyToad.PdfPig/Outline/Destinations/NamedDestinations.cs b/src/UglyToad.PdfPig/Outline/Destinations/NamedDestinations.cs index 1ce883787..0837e3889 100644 --- a/src/UglyToad.PdfPig/Outline/Destinations/NamedDestinations.cs +++ b/src/UglyToad.PdfPig/Outline/Destinations/NamedDestinations.cs @@ -1,6 +1,7 @@ namespace UglyToad.PdfPig.Outline.Destinations { using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Content; using Logging; using Tokens; @@ -31,12 +32,12 @@ internal NamedDestinations(IReadOnlyDictionary name this.pages = pages; } - internal bool TryGet(string name, out ExplicitDestination destination) + internal bool TryGet(string name, [NotNullWhen(true)] out ExplicitDestination? destination) { return namedDestinations.TryGetValue(name, out destination); } - internal bool TryGetExplicitDestination(ArrayToken explicitDestinationArray, ILog log, bool isRemoteDestination, out ExplicitDestination destination) + internal bool TryGetExplicitDestination(ArrayToken explicitDestinationArray, ILog log, bool isRemoteDestination, [NotNullWhen(true)] out ExplicitDestination? destination) { return NamedDestinationsProvider.TryGetExplicitDestination(explicitDestinationArray, pages, log, isRemoteDestination, out destination); } diff --git a/src/UglyToad.PdfPig/Outline/Destinations/NamedDestinationsProvider.cs b/src/UglyToad.PdfPig/Outline/Destinations/NamedDestinationsProvider.cs index 6ea1c9f9f..9fab251d9 100644 --- a/src/UglyToad.PdfPig/Outline/Destinations/NamedDestinationsProvider.cs +++ b/src/UglyToad.PdfPig/Outline/Destinations/NamedDestinationsProvider.cs @@ -1,6 +1,7 @@ namespace UglyToad.PdfPig.Outline.Destinations { using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Content; using Logging; using Parser.Parts; @@ -9,11 +10,11 @@ internal static class NamedDestinationsProvider { - internal static NamedDestinations Read(DictionaryToken catalogDictionary, IPdfTokenScanner pdfScanner, Pages pages, ILog log) + internal static NamedDestinations Read(DictionaryToken catalogDictionary, IPdfTokenScanner pdfScanner, Pages pages, ILog? log) { var destinationsByName = new Dictionary(); - if (catalogDictionary.TryGet(NameToken.Dests, pdfScanner, out DictionaryToken destinations)) + if (catalogDictionary.TryGet(NameToken.Dests, pdfScanner, out DictionaryToken? destinations)) { /* * In PDF 1.1, the correspondence between name objects and destinations is defined by the /Dests entry in the document catalog. @@ -30,7 +31,7 @@ internal static NamedDestinations Read(DictionaryToken catalogDictionary, IPdfTo } } } - else if (catalogDictionary.TryGet(NameToken.Names, pdfScanner, out DictionaryToken names) + else if (catalogDictionary.TryGet(NameToken.Names, pdfScanner, out DictionaryToken? names) && names.TryGet(NameToken.Dests, pdfScanner, out destinations)) { /* @@ -47,23 +48,29 @@ internal static NamedDestinations Read(DictionaryToken catalogDictionary, IPdfTo } return null; - }, destinationsByName); + }, destinationsByName!); } return new NamedDestinations(destinationsByName, pages); } - private static bool TryReadExplicitDestination(IToken value, IPdfTokenScanner pdfScanner, Pages pages, ILog log, bool isRemoteDestination, out ExplicitDestination destination) + private static bool TryReadExplicitDestination( + IToken value, + IPdfTokenScanner pdfScanner, + Pages pages, + ILog? log, + bool isRemoteDestination, + [NotNullWhen(true)] out ExplicitDestination? destination) { destination = null; - if (DirectObjectFinder.TryGet(value, pdfScanner, out ArrayToken valueArray) + if (DirectObjectFinder.TryGet(value, pdfScanner, out ArrayToken? valueArray) && TryGetExplicitDestination(valueArray, pages, log, isRemoteDestination, out destination)) { return true; } - if (DirectObjectFinder.TryGet(value, pdfScanner, out DictionaryToken valueDictionary) + if (DirectObjectFinder.TryGet(value, pdfScanner, out DictionaryToken? valueDictionary) && valueDictionary.TryGet(NameToken.D, pdfScanner, out valueArray) && TryGetExplicitDestination(valueArray, pages, log, isRemoteDestination, out destination)) { @@ -73,7 +80,12 @@ private static bool TryReadExplicitDestination(IToken value, IPdfTokenScanner pd return false; } - internal static bool TryGetExplicitDestination(ArrayToken explicitDestinationArray, Pages pages, ILog log, bool isRemoteDestination, out ExplicitDestination destination) + internal static bool TryGetExplicitDestination( + ArrayToken explicitDestinationArray, + Pages pages, + ILog? log, + bool isRemoteDestination, + [NotNullWhen(true)] out ExplicitDestination? destination) { destination = null; @@ -131,7 +143,7 @@ internal static bool TryGetExplicitDestination(ArrayToken explicitDestinationArr return false; } - NameToken destTypeToken = null; + NameToken? destTypeToken = null; if (explicitDestinationArray.Length > 1) { destTypeToken = explicitDestinationArray[1] as NameToken; diff --git a/src/UglyToad.PdfPig/Parser/DocumentInformationFactory.cs b/src/UglyToad.PdfPig/Parser/DocumentInformationFactory.cs index 0683f091f..0ec7c5fd9 100644 --- a/src/UglyToad.PdfPig/Parser/DocumentInformationFactory.cs +++ b/src/UglyToad.PdfPig/Parser/DocumentInformationFactory.cs @@ -60,10 +60,10 @@ public static DocumentInformation Create(IPdfTokenScanner pdfTokenScanner, Trail return DocumentInformation.Default; } - throw new PdfDocumentFormatException($"Unknown document information token was found {token.GetType().Name}"); + throw new PdfDocumentFormatException($"Unknown document information token was found {token?.GetType().Name}"); } - private static string GetEntryOrDefault(DictionaryToken infoDictionary, NameToken key, IPdfTokenScanner pdfTokenScanner) + private static string? GetEntryOrDefault(DictionaryToken infoDictionary, NameToken key, IPdfTokenScanner pdfTokenScanner) { if (infoDictionary is null) { @@ -77,12 +77,12 @@ private static string GetEntryOrDefault(DictionaryToken infoDictionary, NameToke if (value is IndirectReferenceToken idr) { - if (DirectObjectFinder.TryGet(idr, pdfTokenScanner, out StringToken strI)) + if (DirectObjectFinder.TryGet(idr, pdfTokenScanner, out StringToken? strI)) { return strI.Data; } - if (DirectObjectFinder.TryGet(idr, pdfTokenScanner, out HexToken hexI)) + if (DirectObjectFinder.TryGet(idr, pdfTokenScanner, out HexToken? hexI)) { return hexI.Data; } diff --git a/src/UglyToad.PdfPig/Parser/FileStructure/CrossReferenceParser.cs b/src/UglyToad.PdfPig/Parser/FileStructure/CrossReferenceParser.cs index bdf46e26e..2bb7ed349 100644 --- a/src/UglyToad.PdfPig/Parser/FileStructure/CrossReferenceParser.cs +++ b/src/UglyToad.PdfPig/Parser/FileStructure/CrossReferenceParser.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Core; using CrossReference; using Logging; @@ -77,7 +78,7 @@ public CrossReferenceTable Parse(IInputBytes bytes, bool isLenientParsing, long DictionaryToken tableDictionary = tablePart.Dictionary; - CrossReferenceTablePart streamPart = null; + CrossReferenceTablePart? streamPart = null; // check for a XRef stream, it may contain some object ids of compressed objects if (tableDictionary.ContainsKey(NameToken.XrefStm)) @@ -252,7 +253,7 @@ private bool TryParseCrossReferenceStream( long objByteOffset, IPdfTokenScanner pdfScanner, long? fromTableAtOffset, - out CrossReferenceTablePart xrefTablePart) + [NotNullWhen(true)] out CrossReferenceTablePart? xrefTablePart) { xrefTablePart = null; diff --git a/src/UglyToad.PdfPig/Parser/FileStructure/FileHeaderParser.cs b/src/UglyToad.PdfPig/Parser/FileStructure/FileHeaderParser.cs index 8d0950299..55da29dd6 100644 --- a/src/UglyToad.PdfPig/Parser/FileStructure/FileHeaderParser.cs +++ b/src/UglyToad.PdfPig/Parser/FileStructure/FileHeaderParser.cs @@ -1,13 +1,13 @@ namespace UglyToad.PdfPig.Parser.FileStructure { using System; + using System.Diagnostics.CodeAnalysis; using System.Globalization; using Content; using Core; using Logging; using Tokenization.Scanner; using Tokens; - using Util.JetBrains.Annotations; /// /// Used to retrieve the version header from the PDF file. @@ -28,8 +28,7 @@ /// internal static class FileHeaderParser { - [NotNull] - public static HeaderVersion Parse([NotNull] ISeekableTokenScanner scanner, IInputBytes inputBytes, bool isLenientParsing, ILog log) + public static HeaderVersion Parse(ISeekableTokenScanner scanner, IInputBytes inputBytes, bool isLenientParsing, ILog log) { if (scanner is null) { @@ -40,7 +39,7 @@ public static HeaderVersion Parse([NotNull] ISeekableTokenScanner scanner, IInpu const int junkTokensTolerance = 30; var attempts = 0; - CommentToken comment; + CommentToken? comment; do { if (attempts == junkTokensTolerance || !scanner.MoveNext()) @@ -91,7 +90,7 @@ private static HeaderVersion GetHeaderVersionAndResetScanner(CommentToken commen return result; } - private static bool TryBruteForceVersionLocation(long startPosition, IInputBytes inputBytes, out HeaderVersion headerVersion) + private static bool TryBruteForceVersionLocation(long startPosition, IInputBytes inputBytes, [NotNullWhen(true)] out HeaderVersion? headerVersion) { headerVersion = null; diff --git a/src/UglyToad.PdfPig/Parser/FileStructure/FileTrailerParser.cs b/src/UglyToad.PdfPig/Parser/FileStructure/FileTrailerParser.cs index 9613eb613..761f9af96 100644 --- a/src/UglyToad.PdfPig/Parser/FileStructure/FileTrailerParser.cs +++ b/src/UglyToad.PdfPig/Parser/FileStructure/FileTrailerParser.cs @@ -53,7 +53,7 @@ public static long GetFirstCrossReferenceOffset(IInputBytes bytes, ISeekableToke throw new InvalidOperationException($"The start xref position we found was not correct. Found {startXrefPosition} but it was occupied by token {scanner.CurrentToken}."); } - NumericToken numeric = null; + NumericToken? numeric = null; while (scanner.MoveNext()) { if (scanner.CurrentToken is NumericToken token) diff --git a/src/UglyToad.PdfPig/Parser/FileStructure/XrefOffsetValidator.cs b/src/UglyToad.PdfPig/Parser/FileStructure/XrefOffsetValidator.cs index 55cd733b8..bd10b66cd 100644 --- a/src/UglyToad.PdfPig/Parser/FileStructure/XrefOffsetValidator.cs +++ b/src/UglyToad.PdfPig/Parser/FileStructure/XrefOffsetValidator.cs @@ -13,8 +13,8 @@ internal class XrefOffsetValidator private readonly ILog log; - private List bfSearchXRefTablesOffsets; - private List bfSearchXRefStreamsOffsets; + private List? bfSearchXRefTablesOffsets; + private List? bfSearchXRefStreamsOffsets; public XrefOffsetValidator(ILog log) { @@ -78,9 +78,7 @@ private long CalculateXRefFixedOffset(long objectOffset, ISeekableTokenScanner s log.Error($"Can\'t find the object xref table/stream at offset {objectOffset}"); return 0; - } - - + } private long BruteForceSearchForXref(long xrefOffset, ISeekableTokenScanner scanner, IInputBytes reader) { @@ -110,23 +108,23 @@ private long BruteForceSearchForXref(long xrefOffset, ISeekableTokenScanner scan if (Math.Abs(differenceTable) > Math.Abs(differenceStream)) { newOffset = newOffsetStream; - bfSearchXRefStreamsOffsets.Remove(newOffsetStream); + bfSearchXRefStreamsOffsets!.Remove(newOffsetStream); } else { newOffset = newOffsetTable; - bfSearchXRefTablesOffsets.Remove(newOffsetTable); + bfSearchXRefTablesOffsets!.Remove(newOffsetTable); } } else if (newOffsetTable > -1) { newOffset = newOffsetTable; - bfSearchXRefTablesOffsets.Remove(newOffsetTable); + bfSearchXRefTablesOffsets!.Remove(newOffsetTable); } else if (newOffsetStream > -1) { newOffset = newOffsetStream; - bfSearchXRefStreamsOffsets.Remove(newOffsetStream); + bfSearchXRefStreamsOffsets!.Remove(newOffsetStream); } return newOffset; } diff --git a/src/UglyToad.PdfPig/Parser/PageContentParser.cs b/src/UglyToad.PdfPig/Parser/PageContentParser.cs index 9a5780888..1bb0b79da 100644 --- a/src/UglyToad.PdfPig/Parser/PageContentParser.cs +++ b/src/UglyToad.PdfPig/Parser/PageContentParser.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Core; using Graphics; using Graphics.Operations; @@ -68,7 +69,7 @@ public IReadOnlyList Parse( if (op.Data == "EI") { // Check an end image operation was the last thing that happened. - IGraphicsStateOperation lastOperation = graphicsStateOperations.Count > 0 + IGraphicsStateOperation? lastOperation = graphicsStateOperations.Count > 0 ? graphicsStateOperations[graphicsStateOperations.Count - 1] : null; @@ -109,7 +110,7 @@ public IReadOnlyList Parse( } else { - IGraphicsStateOperation operation; + IGraphicsStateOperation? operation; try { operation = operationFactory.Create(op, precedingTokens); @@ -174,7 +175,7 @@ public IReadOnlyList Parse( return graphicsStateOperations; } - private static bool TryGetLastEndImage(List graphicsStateOperations, out EndInlineImage endImage, out int index) + private static bool TryGetLastEndImage(List graphicsStateOperations, [NotNullWhen(true)] out EndInlineImage? endImage, out int index) { index = -1; endImage = null; diff --git a/src/UglyToad.PdfPig/Parser/Parts/BruteForceSearcher.cs b/src/UglyToad.PdfPig/Parser/Parts/BruteForceSearcher.cs index 6278aa075..c767a74dd 100644 --- a/src/UglyToad.PdfPig/Parser/Parts/BruteForceSearcher.cs +++ b/src/UglyToad.PdfPig/Parser/Parts/BruteForceSearcher.cs @@ -1,11 +1,10 @@ namespace UglyToad.PdfPig.Parser.Parts { - using Core; using System; using System.Collections.Generic; using System.Globalization; using System.Text; - using Util.JetBrains.Annotations; + using Core; /// /// Brute force search for all objects in the document. @@ -19,7 +18,6 @@ internal static class BruteForceSearcher /// /// The bytes of the document. /// The object keys and offsets for the objects in this document. - [NotNull] public static IReadOnlyDictionary GetObjectLocations(IInputBytes bytes) { if (bytes is null) diff --git a/src/UglyToad.PdfPig/Parser/Parts/DirectObjectFinder.cs b/src/UglyToad.PdfPig/Parser/Parts/DirectObjectFinder.cs index 39b88528c..90ca51943 100644 --- a/src/UglyToad.PdfPig/Parser/Parts/DirectObjectFinder.cs +++ b/src/UglyToad.PdfPig/Parser/Parts/DirectObjectFinder.cs @@ -1,14 +1,16 @@ namespace UglyToad.PdfPig.Parser.Parts { + using System.Diagnostics.CodeAnalysis; using Core; using Tokenization.Scanner; using Tokens; internal static class DirectObjectFinder { - public static bool TryGet(IToken token, IPdfTokenScanner scanner, out T tokenResult) where T : IToken + public static bool TryGet(IToken? token, IPdfTokenScanner scanner, [NotNullWhen(true)] out T? tokenResult) + where T : class, IToken { - tokenResult = default(T); + tokenResult = null; if (token is T t) { tokenResult = t; @@ -43,7 +45,8 @@ public static bool TryGet(IToken token, IPdfTokenScanner scanner, out T token return false; } - public static T Get(IndirectReference reference, IPdfTokenScanner scanner) where T : class, IToken + public static T? Get(IndirectReference reference, IPdfTokenScanner scanner) + where T : class, IToken { var temp = scanner.Get(reference); if (temp is null || temp.Data is NullToken) @@ -79,6 +82,7 @@ public static T Get(IndirectReference reference, IPdfTokenScanner scanner) wh throw new PdfDocumentFormatException($"Could not find the object number {reference} with type {typeof(T).Name} instead, it was found with type {temp.GetType().Name}."); } +#nullable disable public static T Get(IToken token, IPdfTokenScanner scanner) where T : class, IToken { if (token is T result) @@ -93,5 +97,6 @@ public static T Get(IToken token, IPdfTokenScanner scanner) where T : class, throw new PdfDocumentFormatException($"Could not find the object {token} with type {typeof(T).Name} instead, it was found with type {token.GetType().Name}."); } +#nullable enable } } diff --git a/src/UglyToad.PdfPig/Parser/Parts/NameTreeParser.cs b/src/UglyToad.PdfPig/Parser/Parts/NameTreeParser.cs index 31c926bee..8f338faef 100644 --- a/src/UglyToad.PdfPig/Parser/Parts/NameTreeParser.cs +++ b/src/UglyToad.PdfPig/Parser/Parts/NameTreeParser.cs @@ -1,4 +1,6 @@ -namespace UglyToad.PdfPig.Parser.Parts +#nullable disable + +namespace UglyToad.PdfPig.Parser.Parts { using System; using System.Collections.Generic; @@ -7,7 +9,8 @@ internal static class NameTreeParser { - public static IReadOnlyDictionary FlattenNameTreeToDictionary(DictionaryToken nameTreeNodeDictionary, + public static IReadOnlyDictionary FlattenNameTreeToDictionary( + DictionaryToken nameTreeNodeDictionary, IPdfTokenScanner pdfScanner, Func valuesFactory) where TResult : class { @@ -18,7 +21,8 @@ public static IReadOnlyDictionary FlattenNameTreeToDictionary(DictionaryToken nameTreeNodeDictionary, + public static void FlattenNameTree( + DictionaryToken nameTreeNodeDictionary, IPdfTokenScanner pdfScanner, Func valuesFactory, Dictionary result) where TResult : class diff --git a/src/UglyToad.PdfPig/Parser/PdfDocumentFactory.cs b/src/UglyToad.PdfPig/Parser/PdfDocumentFactory.cs index a18e0bc92..f5cac50e9 100644 --- a/src/UglyToad.PdfPig/Parser/PdfDocumentFactory.cs +++ b/src/UglyToad.PdfPig/Parser/PdfDocumentFactory.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using AcroForms; @@ -13,7 +14,6 @@ using Filters; using Fonts.SystemFonts; using Graphics; - using Logging; using Outline; using Parts; using Parts.CrossReference; @@ -26,14 +26,14 @@ internal static class PdfDocumentFactory { - public static PdfDocument Open(byte[] fileBytes, ParsingOptions options = null) + public static PdfDocument Open(byte[] fileBytes, ParsingOptions? options = null) { var inputBytes = new ByteArrayInputBytes(fileBytes); return Open(inputBytes, options); } - public static PdfDocument Open(string filename, ParsingOptions options = null) + public static PdfDocument Open(string filename, ParsingOptions? options = null) { if (!File.Exists(filename)) { @@ -43,7 +43,7 @@ public static PdfDocument Open(string filename, ParsingOptions options = null) return Open(File.ReadAllBytes(filename), options); } - internal static PdfDocument Open(Stream stream, ParsingOptions options) + internal static PdfDocument Open(Stream stream, ParsingOptions? options) { var initialPosition = stream.Position; @@ -66,7 +66,7 @@ internal static PdfDocument Open(Stream stream, ParsingOptions options) } } - private static PdfDocument Open(IInputBytes inputBytes, ParsingOptions options = null) + private static PdfDocument Open(IInputBytes inputBytes, ParsingOptions? options = null) { options ??= new ParsingOptions() { @@ -79,12 +79,12 @@ private static PdfDocument Open(IInputBytes inputBytes, ParsingOptions options = var passwords = new List(); - if (options?.Password != null) + if (options.Password != null) { passwords.Add(options.Password); } - if (options?.Passwords != null) + if (options.Passwords != null) { passwords.AddRange(options.Passwords.Where(x => x != null)); } @@ -108,7 +108,7 @@ private static PdfDocument OpenDocument( { var filterProvider = new FilterProviderWithLookup(DefaultFilterProvider.Instance); - CrossReferenceTable crossReferenceTable = null; + CrossReferenceTable? crossReferenceTable = null; var xrefValidator = new XrefOffsetValidator(parsingOptions.Logger); @@ -219,12 +219,15 @@ private static PdfDocument OpenDocument( parsingOptions); } - private static (IndirectReference, DictionaryToken) ParseTrailer(CrossReferenceTable crossReferenceTable, bool isLenientParsing, IPdfTokenScanner pdfTokenScanner, - out EncryptionDictionary encryptionDictionary) + private static (IndirectReference, DictionaryToken) ParseTrailer( + CrossReferenceTable crossReferenceTable, + bool isLenientParsing, + IPdfTokenScanner pdfTokenScanner, + [NotNullWhen(true)] out EncryptionDictionary? encryptionDictionary) { encryptionDictionary = GetEncryptionDictionary(crossReferenceTable, pdfTokenScanner); - var rootDictionary = DirectObjectFinder.Get(crossReferenceTable.Trailer.Root, pdfTokenScanner); + var rootDictionary = DirectObjectFinder.Get(crossReferenceTable.Trailer.Root, pdfTokenScanner)!; if (!rootDictionary.ContainsKey(NameToken.Type) && isLenientParsing) { @@ -234,16 +237,16 @@ private static (IndirectReference, DictionaryToken) ParseTrailer(CrossReferenceT return (crossReferenceTable.Trailer.Root, rootDictionary); } - private static EncryptionDictionary GetEncryptionDictionary(CrossReferenceTable crossReferenceTable, IPdfTokenScanner pdfTokenScanner) + private static EncryptionDictionary? GetEncryptionDictionary(CrossReferenceTable crossReferenceTable, IPdfTokenScanner pdfTokenScanner) { if (crossReferenceTable.Trailer.EncryptionToken is null) { return null; } - if (!DirectObjectFinder.TryGet(crossReferenceTable.Trailer.EncryptionToken, pdfTokenScanner, out DictionaryToken encryptionDictionaryToken)) + if (!DirectObjectFinder.TryGet(crossReferenceTable.Trailer.EncryptionToken, pdfTokenScanner, out DictionaryToken? encryptionDictionaryToken)) { - if (DirectObjectFinder.TryGet(crossReferenceTable.Trailer.EncryptionToken, pdfTokenScanner, out NullToken _)) + if (DirectObjectFinder.TryGet(crossReferenceTable.Trailer.EncryptionToken, pdfTokenScanner, out NullToken? _)) { return null; } diff --git a/src/UglyToad.PdfPig/PdfDocument.cs b/src/UglyToad.PdfPig/PdfDocument.cs index 19ca1247d..85b6303a7 100644 --- a/src/UglyToad.PdfPig/PdfDocument.cs +++ b/src/UglyToad.PdfPig/PdfDocument.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.IO; using AcroForms; using Content; @@ -15,7 +16,6 @@ using Tokens; using Outline; using Outline.Destinations; - using Util.JetBrains.Annotations; /// /// @@ -26,35 +26,24 @@ public class PdfDocument : IDisposable private bool isDisposed; private readonly Lazy documentForm; - [NotNull] private readonly HeaderVersion version; - private readonly IInputBytes inputBytes; - - [CanBeNull] - private readonly EncryptionDictionary encryptionDictionary; - - [NotNull] + private readonly EncryptionDictionary? encryptionDictionary; private readonly IPdfTokenScanner pdfScanner; - private readonly ILookupFilterProvider filterProvider; private readonly BookmarksProvider bookmarksProvider; private readonly ParsingOptions parsingOptions; - - [NotNull] private readonly Pages pages; private readonly NamedDestinations namedDestinations; /// /// The metadata associated with this document. /// - [NotNull] public DocumentInformation Information { get; } /// /// Access to the underlying raw structure of the document. /// - [NotNull] public Structure Structure { get; } /// @@ -75,14 +64,16 @@ public class PdfDocument : IDisposable /// /// Whether the document content is encrypted. /// + [MemberNotNullWhen(true, nameof(encryptionDictionary))] public bool IsEncrypted => encryptionDictionary != null; - internal PdfDocument(IInputBytes inputBytes, + internal PdfDocument( + IInputBytes inputBytes, HeaderVersion version, CrossReferenceTable crossReferenceTable, Catalog catalog, DocumentInformation information, - EncryptionDictionary encryptionDictionary, + EncryptionDictionary? encryptionDictionary, IPdfTokenScanner pdfScanner, ILookupFilterProvider filterProvider, AcroFormFactory acroFormFactory, @@ -102,7 +93,7 @@ internal PdfDocument(IInputBytes inputBytes, namedDestinations = catalog.NamedDestinations; Structure = new Structure(catalog, crossReferenceTable, pdfScanner); Advanced = new AdvancedPdfDocumentAccess(pdfScanner, filterProvider, catalog); - documentForm = new Lazy(() => acroFormFactory.GetAcroForm(catalog)); + documentForm = new Lazy(() => acroFormFactory.GetAcroForm(catalog)!); } /// @@ -111,7 +102,7 @@ internal PdfDocument(IInputBytes inputBytes, /// The bytes of the PDF file. /// Optional parameters controlling parsing. /// A providing access to the file contents. - public static PdfDocument Open(byte[] fileBytes, ParsingOptions options = null) => PdfDocumentFactory.Open(fileBytes, options); + public static PdfDocument Open(byte[] fileBytes, ParsingOptions? options = null) => PdfDocumentFactory.Open(fileBytes, options); /// /// Opens a file and creates a for reading from the provided file path. @@ -119,7 +110,7 @@ internal PdfDocument(IInputBytes inputBytes, /// The full path to the file location of the PDF file. /// Optional parameters controlling parsing. /// A providing access to the file contents. - public static PdfDocument Open(string filePath, ParsingOptions options = null) => PdfDocumentFactory.Open(filePath, options); + public static PdfDocument Open(string filePath, ParsingOptions? options = null) => PdfDocumentFactory.Open(filePath, options); /// /// Creates a for reading from the provided stream. @@ -131,7 +122,7 @@ internal PdfDocument(IInputBytes inputBytes, /// /// Optional parameters controlling parsing. /// A providing access to the file contents. - public static PdfDocument Open(Stream stream, ParsingOptions options = null) => PdfDocumentFactory.Open(stream, options); + public static PdfDocument Open(Stream stream, ParsingOptions? options = null) => PdfDocumentFactory.Open(stream, options); /// /// TODO @@ -209,7 +200,7 @@ public TPage GetPage(int pageNumber) { if (IsEncrypted) { - throw new PdfDocumentEncryptedException("Document was encrypted which may have caused error when retrieving page.", encryptionDictionary, ex); + throw new PdfDocumentEncryptedException("Document was encrypted which may have caused error when retrieving page.", encryptionDictionary!, ex); } throw; @@ -245,7 +236,7 @@ public IEnumerable GetPages() /// This will throw a if called on a disposed . /// The metadata stream if it exists. /// if the metadata is present, otherwise. - public bool TryGetXmpMetadata(out XmpMetadata metadata) + public bool TryGetXmpMetadata([NotNullWhen(true)] out XmpMetadata? metadata) { if (isDisposed) { @@ -254,7 +245,7 @@ public bool TryGetXmpMetadata(out XmpMetadata metadata) metadata = null; - if (!Structure.Catalog.CatalogDictionary.TryGet(NameToken.Metadata, pdfScanner, out StreamToken xmpStreamToken)) + if (!Structure.Catalog.CatalogDictionary.TryGet(NameToken.Metadata, pdfScanner, out StreamToken? xmpStreamToken)) { return false; } @@ -268,7 +259,7 @@ public bool TryGetXmpMetadata(out XmpMetadata metadata) /// Gets the bookmarks if this document contains some. /// /// This will throw a if called on a disposed . - public bool TryGetBookmarks(out Bookmarks bookmarks) + public bool TryGetBookmarks([NotNullWhen(true)] out Bookmarks? bookmarks) { if (isDisposed) { @@ -276,12 +267,8 @@ public bool TryGetBookmarks(out Bookmarks bookmarks) } bookmarks = bookmarksProvider.GetBookmarks(Structure.Catalog); - if (bookmarks != null) - { - return true; - } - return false; + return bookmarks != null; } /// diff --git a/src/UglyToad.PdfPig/PdfExtensions.cs b/src/UglyToad.PdfPig/PdfExtensions.cs index 4bbcc9977..fddf44a75 100644 --- a/src/UglyToad.PdfPig/PdfExtensions.cs +++ b/src/UglyToad.PdfPig/PdfExtensions.cs @@ -1,6 +1,7 @@ namespace UglyToad.PdfPig { - using System.Collections.Generic; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Core; using Filters; using Parser.Parts; @@ -15,9 +16,10 @@ public static class PdfExtensions /// /// Try and get the entry with a given name and type or look-up the object if it's an indirect reference. /// - public static bool TryGet(this DictionaryToken dictionary, NameToken name, IPdfTokenScanner tokenScanner, out T token) where T : IToken + public static bool TryGet(this DictionaryToken dictionary, NameToken name, IPdfTokenScanner tokenScanner, [NotNullWhen(true)] out T? token) + where T : class, IToken { - token = default(T); + token = default; if (!dictionary.TryGet(name, out var t) || !(t is T typedToken)) { if (t is IndirectReferenceToken reference) diff --git a/src/UglyToad.PdfPig/PdfFonts/CidFonts/CharacterIdentifierToGlyphIndexMap.cs b/src/UglyToad.PdfPig/PdfFonts/CidFonts/CharacterIdentifierToGlyphIndexMap.cs index dbb0fdbdb..c375cc9c2 100644 --- a/src/UglyToad.PdfPig/PdfFonts/CidFonts/CharacterIdentifierToGlyphIndexMap.cs +++ b/src/UglyToad.PdfPig/PdfFonts/CidFonts/CharacterIdentifierToGlyphIndexMap.cs @@ -9,7 +9,7 @@ internal class CharacterIdentifierToGlyphIndexMap { private readonly bool isIdentity; - private readonly int[] map; + private readonly int[]? map; public CharacterIdentifierToGlyphIndexMap() { @@ -40,7 +40,7 @@ public CharacterIdentifierToGlyphIndexMap(IReadOnlyList streamBytes) return characterIdentifier; } - if (characterIdentifier >= map.Length || characterIdentifier < 0) + if (characterIdentifier >= map!.Length || characterIdentifier < 0) { return 0; } diff --git a/src/UglyToad.PdfPig/PdfFonts/CidFonts/ICidFont.cs b/src/UglyToad.PdfPig/PdfFonts/CidFonts/ICidFont.cs index 065df8ae4..509c8b3d8 100644 --- a/src/UglyToad.PdfPig/PdfFonts/CidFonts/ICidFont.cs +++ b/src/UglyToad.PdfPig/PdfFonts/CidFonts/ICidFont.cs @@ -1,9 +1,10 @@ namespace UglyToad.PdfPig.PdfFonts.CidFonts { + using System; + using System.Diagnostics.CodeAnalysis; + using System.Collections.Generic; using Core; using Geometry; - using System.Collections.Generic; - using System; using Tokens; /// @@ -61,7 +62,7 @@ internal interface ICidFont /// /// Character code in a PDF. Not to be confused with unicode. /// The glyph path for the given character code. - bool TryGetPath(int characterCode, out IReadOnlyList path); + bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path); /// /// Returns the glyph path for the given character code. @@ -69,14 +70,14 @@ internal interface ICidFont /// Character code in a PDF. Not to be confused with unicode. /// /// The glyph path for the given character code. - bool TryGetPath(int characterCode, Func characterCodeToGlyphId, out IReadOnlyList path); + bool TryGetPath(int characterCode, Func characterCodeToGlyphId, [NotNullWhen(true)] out IReadOnlyList? path); /// /// Returns the normalised glyph path for the given character code in a PDF. /// /// Character code in a PDF. Not to be confused with unicode. /// The normalized glyph path for the given character code. - bool TryGetNormalisedPath(int characterCode, out IReadOnlyList path); + bool TryGetNormalisedPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path); /// /// Returns the normalised glyph path for the given character code in a PDF. @@ -84,6 +85,6 @@ internal interface ICidFont /// Character code in a PDF. Not to be confused with unicode. /// /// The normalized glyph path for the given character code. - bool TryGetNormalisedPath(int characterCode, Func characterCodeToGlyphId, out IReadOnlyList path); + bool TryGetNormalisedPath(int characterCode, Func characterCodeToGlyphId, [NotNullWhen(true)] out IReadOnlyList? path); } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/PdfFonts/CidFonts/ICidFontProgram.cs b/src/UglyToad.PdfPig/PdfFonts/CidFonts/ICidFontProgram.cs index 6d92518fd..2638e92b1 100644 --- a/src/UglyToad.PdfPig/PdfFonts/CidFonts/ICidFontProgram.cs +++ b/src/UglyToad.PdfPig/PdfFonts/CidFonts/ICidFontProgram.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Core; /// @@ -19,15 +20,15 @@ internal interface ICidFontProgram bool TryGetBoundingAdvancedWidth(int characterIdentifier, out double width); - bool TryGetPath(int characterCode, out IReadOnlyList path); + bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path); - bool TryGetPath(int characterCode, Func characterCodeToGlyphId, out IReadOnlyList path); + bool TryGetPath(int characterCode, Func characterCodeToGlyphId, [NotNullWhen(true)] out IReadOnlyList? path); int GetFontMatrixMultiplier(); /// /// Try to get the font matrix if available. /// - bool TryGetFontMatrix(int characterCode, out TransformationMatrix? matrix); + bool TryGetFontMatrix(int characterCode, [NotNullWhen(true)] out TransformationMatrix? matrix); } } diff --git a/src/UglyToad.PdfPig/PdfFonts/CidFonts/PdfCidCompactFontFormatFont.cs b/src/UglyToad.PdfPig/PdfFonts/CidFonts/PdfCidCompactFontFormatFont.cs index 1e7f50408..1ab9c75f3 100644 --- a/src/UglyToad.PdfPig/PdfFonts/CidFonts/PdfCidCompactFontFormatFont.cs +++ b/src/UglyToad.PdfPig/PdfFonts/CidFonts/PdfCidCompactFontFormatFont.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Core; using Fonts; using Fonts.CompactFontFormat; @@ -18,7 +19,7 @@ public PdfCidCompactFontFormatFont(CompactFontFormatFontCollection fontCollectio Details = GetDetails(fontCollection?.FirstFont); } - private static FontDetails GetDetails(CompactFontFormatFont font) + private static FontDetails GetDetails(CompactFontFormatFont? font) { if (font is null) { @@ -78,7 +79,7 @@ public int GetFontMatrixMultiplier() return 1000; } - public bool TryGetFontMatrix(int characterCode, out TransformationMatrix? matrix) + public bool TryGetFontMatrix(int characterCode, [NotNullWhen(true)] out TransformationMatrix? matrix) { var font = GetFont(); var name = font.GetCharacterName(characterCode, true); @@ -112,7 +113,7 @@ private CompactFontFormatFont GetFont() return fontCollection.FirstFont; } - public bool TryGetPath(int characterCode, out IReadOnlyList path) + public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { path = null; diff --git a/src/UglyToad.PdfPig/PdfFonts/CidFonts/PdfCidTrueTypeFont.cs b/src/UglyToad.PdfPig/PdfFonts/CidFonts/PdfCidTrueTypeFont.cs index df891a354..12c59deb5 100644 --- a/src/UglyToad.PdfPig/PdfFonts/CidFonts/PdfCidTrueTypeFont.cs +++ b/src/UglyToad.PdfPig/PdfFonts/CidFonts/PdfCidTrueTypeFont.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Core; using Fonts.TrueType; using Fonts.TrueType.Tables; @@ -25,24 +26,24 @@ public PdfCidTrueTypeFont(TrueTypeFont font) public bool TryGetBoundingBox(int characterIdentifier, out PdfRectangle boundingBox) => TryGetBoundingBox(characterIdentifier, null, out boundingBox); - public bool TryGetBoundingBox(int characterIdentifier, Func characterCodeToGlyphId, out PdfRectangle boundingBox) + public bool TryGetBoundingBox(int characterIdentifier, Func? characterCodeToGlyphId, out PdfRectangle boundingBox) => font.TryGetBoundingBox(characterIdentifier, characterCodeToGlyphId, out boundingBox); public bool TryGetBoundingAdvancedWidth(int characterIdentifier, out double width) => TryGetBoundingAdvancedWidth(characterIdentifier, null, out width); - public bool TryGetBoundingAdvancedWidth(int characterIdentifier, Func characterCodeToGlyphId, out double width) + public bool TryGetBoundingAdvancedWidth(int characterIdentifier, Func? characterCodeToGlyphId, out double width) => font.TryGetAdvanceWidth(characterIdentifier, characterCodeToGlyphId, out width); public int GetFontMatrixMultiplier() => font.GetUnitsPerEm(); - public bool TryGetFontMatrix(int characterCode, out TransformationMatrix? matrix) + public bool TryGetFontMatrix(int characterCode, [NotNullWhen(true)] out TransformationMatrix? matrix) { // We don't have a matrix here matrix = null; return false; } - public bool TryGetPath(int characterCode, out IReadOnlyList path) => font.TryGetPath(characterCode, out path); + public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) => font.TryGetPath(characterCode, out path); public bool TryGetPath(int characterCode, Func characterCodeToGlyphId, out IReadOnlyList path) => font.TryGetPath(characterCode, characterCodeToGlyphId, out path); diff --git a/src/UglyToad.PdfPig/PdfFonts/CidFonts/Type0CidFont.cs b/src/UglyToad.PdfPig/PdfFonts/CidFonts/Type0CidFont.cs index dc159da40..ff66b0316 100644 --- a/src/UglyToad.PdfPig/PdfFonts/CidFonts/Type0CidFont.cs +++ b/src/UglyToad.PdfPig/PdfFonts/CidFonts/Type0CidFont.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.Linq; using Core; using Geometry; @@ -38,7 +39,8 @@ internal sealed class Type0CidFont : ICidFont public IReadOnlyDictionary Widths { get; } - public Type0CidFont(ICidFontProgram fontProgram, + public Type0CidFont( + ICidFontProgram fontProgram, NameToken type, NameToken subType, NameToken baseFont, @@ -146,7 +148,7 @@ public TransformationMatrix GetFontMatrix(int characterIdentifier) return fontProgram.TryGetFontMatrix(characterIdentifier, out var m) ? m.Value : FontMatrix; } - public bool TryGetPath(int characterCode, out IReadOnlyList path) + public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { path = null; if (fontProgram is null) @@ -157,7 +159,7 @@ public bool TryGetPath(int characterCode, out IReadOnlyList path) return fontProgram.TryGetPath(characterCode, out path); } - public bool TryGetPath(int characterCode, Func characterCodeToGlyphId, out IReadOnlyList path) + public bool TryGetPath(int characterCode, Func characterCodeToGlyphId, [NotNullWhen(true)] out IReadOnlyList? path) { path = null; if (fontProgram is null) @@ -168,7 +170,7 @@ public bool TryGetPath(int characterCode, Func characterCodeToGlyphId return fontProgram.TryGetPath(characterCode, characterCodeToGlyphId, out path); } - public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList path) + public bool TryGetNormalisedPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { path = null; if (fontProgram is null) @@ -185,7 +187,7 @@ public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList characterCodeToGlyphId, out IReadOnlyList path) + public bool TryGetNormalisedPath(int characterCode, Func characterCodeToGlyphId, [NotNullWhen(true)] out IReadOnlyList? path) { path = null; if (fontProgram is null) diff --git a/src/UglyToad.PdfPig/PdfFonts/CidFonts/Type2CidFont.cs b/src/UglyToad.PdfPig/PdfFonts/CidFonts/Type2CidFont.cs index 24667a5ed..596e8c733 100644 --- a/src/UglyToad.PdfPig/PdfFonts/CidFonts/Type2CidFont.cs +++ b/src/UglyToad.PdfPig/PdfFonts/CidFonts/Type2CidFont.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.Linq; using Core; using Geometry; @@ -14,7 +15,7 @@ /// internal sealed class Type2CidFont : ICidFont { - private readonly ICidFontProgram fontProgram; + private readonly ICidFontProgram? fontProgram; private readonly VerticalWritingMetrics verticalWritingMetrics; private readonly IReadOnlyDictionary widths; private readonly double? defaultWidth; @@ -37,12 +38,13 @@ internal sealed class Type2CidFont : ICidFont public FontDetails Details => fontProgram?.Details ?? Descriptor?.ToDetails(BaseFont?.Data) ?? FontDetails.GetDefault(BaseFont?.Data); - public Type2CidFont(NameToken type, + public Type2CidFont( + NameToken type, NameToken subType, NameToken baseFont, CharacterIdentifierSystemInfo systemInfo, FontDescriptor descriptor, - ICidFontProgram fontProgram, + ICidFontProgram? fontProgram, VerticalWritingMetrics verticalWritingMetrics, IReadOnlyDictionary widths, double? defaultWidth, @@ -127,9 +129,9 @@ public TransformationMatrix GetFontMatrix(int characterIdentifier) return FontMatrix; } - public bool TryGetPath(int characterCode, out IReadOnlyList path) => TryGetPath(characterCode, cidToGid.GetGlyphIndex, out path); + public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) => TryGetPath(characterCode, cidToGid.GetGlyphIndex, out path); - public bool TryGetPath(int characterCode, Func characterCodeToGlyphId, out IReadOnlyList path) + public bool TryGetPath(int characterCode, Func characterCodeToGlyphId, [NotNullWhen(true)] out IReadOnlyList? path) { path = null; if (fontProgram is null) @@ -140,12 +142,12 @@ public bool TryGetPath(int characterCode, Func characterCodeToGlyphId return fontProgram.TryGetPath(characterCode, characterCodeToGlyphId, out path); } - public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList path) + public bool TryGetNormalisedPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { return TryGetNormalisedPath(characterCode, cidToGid.GetGlyphIndex, out path); } - public bool TryGetNormalisedPath(int characterCode, Func characterCodeToGlyphId, out IReadOnlyList path) + public bool TryGetNormalisedPath(int characterCode, Func characterCodeToGlyphId, [NotNullWhen(true)] out IReadOnlyList? path) { path = null; if (fontProgram is null) diff --git a/src/UglyToad.PdfPig/PdfFonts/CidFonts/VerticalWritingMetrics.cs b/src/UglyToad.PdfPig/PdfFonts/CidFonts/VerticalWritingMetrics.cs index dcc4cd5f6..4f5d6ddd4 100644 --- a/src/UglyToad.PdfPig/PdfFonts/CidFonts/VerticalWritingMetrics.cs +++ b/src/UglyToad.PdfPig/PdfFonts/CidFonts/VerticalWritingMetrics.cs @@ -2,7 +2,6 @@ { using System.Collections.Generic; using Geometry; - using Util.JetBrains.Annotations; /// /// Glyphs from fonts which support vertical writing mode define displacement and position vectors. @@ -19,27 +18,24 @@ internal class VerticalWritingMetrics /// /// Overrides displacement vector y components for glyphs specified by CID code. /// - [NotNull] public IReadOnlyDictionary IndividualVerticalWritingDisplacements { get; } /// /// Overrides position vector (x and y) components for glyphs specified by CID code. /// - [NotNull] public IReadOnlyDictionary IndividualVerticalWritingPositions { get; } /// /// Create new . /// - public VerticalWritingMetrics(VerticalVectorComponents defaultVerticalWritingMetrics, - [CanBeNull] IReadOnlyDictionary individualVerticalWritingDisplacements, - [CanBeNull] IReadOnlyDictionary individualVerticalWritingPositions) + public VerticalWritingMetrics( + VerticalVectorComponents defaultVerticalWritingMetrics, + IReadOnlyDictionary? individualVerticalWritingDisplacements, + IReadOnlyDictionary? individualVerticalWritingPositions) { DefaultVerticalWritingMetrics = defaultVerticalWritingMetrics; - IndividualVerticalWritingDisplacements = individualVerticalWritingDisplacements - ?? new Dictionary(0); - IndividualVerticalWritingPositions = individualVerticalWritingPositions - ?? new Dictionary(0); + IndividualVerticalWritingDisplacements = individualVerticalWritingDisplacements ?? new Dictionary(0); + IndividualVerticalWritingPositions = individualVerticalWritingPositions ?? new Dictionary(0); } /// @@ -68,4 +64,4 @@ public PdfVector GetDisplacementVector(int characterIdentifier) return DefaultVerticalWritingMetrics.GetDisplacementVector(); } } -} +} \ No newline at end of file diff --git a/src/UglyToad.PdfPig/PdfFonts/Cmap/CMap.cs b/src/UglyToad.PdfPig/PdfFonts/Cmap/CMap.cs index ee47dc2be..d107ba6dc 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Cmap/CMap.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Cmap/CMap.cs @@ -2,9 +2,9 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.Linq; using Core; - using Util.JetBrains.Annotations; /// /// The CMap (character code map) maps character codes to character identifiers (CIDs). @@ -27,28 +27,23 @@ internal class CMap /// /// The version number of the CIDFont file. /// - [CanBeNull] - public string Version { get; } + public string? Version { get; } - [NotNull] public IReadOnlyDictionary BaseFontCharacterMap { get; } /// /// Describes the set of valid input character codes. /// - [NotNull] public IReadOnlyList CodespaceRanges { get; } /// /// Associates ranges of character codes with their corresponding CID values. /// - [NotNull] public IReadOnlyList CidRanges { get; } /// /// Overrides CID mappings for single character codes. /// - [NotNull] public IReadOnlyDictionary CidCharacterMappings { get; } /// @@ -67,7 +62,8 @@ internal class CMap private readonly int minCodeLength = 4; private readonly int maxCodeLength; - public CMap(CharacterIdentifierSystemInfo info, int type, int wMode, string name, string version, + public CMap(CharacterIdentifierSystemInfo info, int type, int wMode, string name, + string? version, IReadOnlyDictionary baseFontCharacterMap, IReadOnlyList codespaceRanges, IReadOnlyList cidRanges, @@ -114,7 +110,7 @@ public CMap(CharacterIdentifierSystemInfo info, int type, int wMode, string name /// Character code /// Unicode characters(may be more than one, e.g "fi" ligature) /// if this character map contains an entry for this code, otherwise. - public bool TryConvertToUnicode(int code, out string result) + public bool TryConvertToUnicode(int code, [NotNullWhen(true)] out string? result) { var found = BaseFontCharacterMap.TryGetValue(code, out result); diff --git a/src/UglyToad.PdfPig/PdfFonts/Cmap/CMapCache.cs b/src/UglyToad.PdfPig/PdfFonts/Cmap/CMapCache.cs index d4202d0ee..6432bf07a 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Cmap/CMapCache.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Cmap/CMapCache.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Core; using Parser; @@ -12,7 +13,7 @@ internal static class CMapCache private static readonly CMapParser CMapParser = new CMapParser(); - public static bool TryGet(string name, out CMap result) + public static bool TryGet(string name, [NotNullWhen(true)] out CMap? result) { result = null; diff --git a/src/UglyToad.PdfPig/PdfFonts/Cmap/CharacterIdentifierSystemInfoBuilder.cs b/src/UglyToad.PdfPig/PdfFonts/Cmap/CharacterIdentifierSystemInfoBuilder.cs index 2fb65be37..73e56872f 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Cmap/CharacterIdentifierSystemInfoBuilder.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Cmap/CharacterIdentifierSystemInfoBuilder.cs @@ -2,8 +2,8 @@ { internal class CharacterIdentifierSystemInfoBuilder { - private string registry; - public string Registry + private string? registry; + public string? Registry { get => registry; set @@ -15,8 +15,9 @@ public string Registry public bool HasRegistry { get; private set; } - private string ordering; - public string Ordering + private string? ordering; + + public string? Ordering { get => ordering; set diff --git a/src/UglyToad.PdfPig/PdfFonts/Cmap/CharacterMapBuilder.cs b/src/UglyToad.PdfPig/PdfFonts/Cmap/CharacterMapBuilder.cs index 83b9af915..d402b4ae3 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Cmap/CharacterMapBuilder.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Cmap/CharacterMapBuilder.cs @@ -1,10 +1,11 @@ -namespace UglyToad.PdfPig.PdfFonts.Cmap +#nullable disable + +namespace UglyToad.PdfPig.PdfFonts.Cmap { - using System; + using Core; using System.Collections.Generic; using System.Linq; using System.Text; - using Core; /// /// A mutable class used when parsing and generating a . @@ -36,14 +37,17 @@ internal class CharacterMapBuilder /// public string Name { get; set; } +#nullable enable + /// /// Defines the version of this CIDFont file. /// /// /// Defined as optional. /// - public string Version { get; set; } + public string? Version { get; set; } +#nullable disable /// /// Defines changes to the internal structure of Character Map files /// or operator semantics. @@ -92,7 +96,7 @@ private CharacterIdentifierSystemInfo GetCidSystemInfo() if (SystemInfoBuilder.HasOrdering && SystemInfoBuilder.HasRegistry && SystemInfoBuilder.HasSupplement) { - return new CharacterIdentifierSystemInfo(SystemInfoBuilder.Registry, SystemInfoBuilder.Ordering, SystemInfoBuilder.Supplement); + return new CharacterIdentifierSystemInfo(SystemInfoBuilder.Registry!, SystemInfoBuilder.Ordering!, SystemInfoBuilder.Supplement); } return CharacterIdentifierSystemInfo; diff --git a/src/UglyToad.PdfPig/PdfFonts/Composite/ToUnicodeCMap.cs b/src/UglyToad.PdfPig/PdfFonts/Composite/ToUnicodeCMap.cs index 69369ad7d..c114b0734 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Composite/ToUnicodeCMap.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Composite/ToUnicodeCMap.cs @@ -1,9 +1,9 @@ namespace UglyToad.PdfPig.PdfFonts.Composite { using System; + using System.Diagnostics.CodeAnalysis; using Cmap; using Core; - using Util.JetBrains.Annotations; /// /// Defines the information content (actual text) of the font @@ -11,8 +11,7 @@ /// internal class ToUnicodeCMap { - [CanBeNull] - private readonly CMap cMap; + private readonly CMap? cMap; /// /// Does the font provide a CMap to map CIDs to Unicode values? @@ -24,22 +23,21 @@ internal class ToUnicodeCMap /// public bool IsUsingIdentityAsUnicodeMap { get; } - public ToUnicodeCMap([CanBeNull]CMap cMap) + public ToUnicodeCMap(CMap? cMap) { this.cMap = cMap; - if (CanMapToUnicode) + if (cMap != null) { - IsUsingIdentityAsUnicodeMap = - cMap.Name?.StartsWith("Identity-", StringComparison.InvariantCultureIgnoreCase) == true; + IsUsingIdentityAsUnicodeMap = cMap.Name?.StartsWith("Identity-", StringComparison.InvariantCultureIgnoreCase) == true; } } - public bool TryGet(int code, out string value) + public bool TryGet(int code, [NotNullWhen(true)] out string? value) { value = null; - if (!CanMapToUnicode) + if (cMap is null) { return false; } @@ -49,7 +47,7 @@ public bool TryGet(int code, out string value) public int ReadCode(IInputBytes inputBytes) { - return cMap.ReadCode(inputBytes); + return cMap!.ReadCode(inputBytes); } } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/PdfFonts/Composite/Type0Font.cs b/src/UglyToad.PdfPig/PdfFonts/Composite/Type0Font.cs index 8bf673482..cf3fd5079 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Composite/Type0Font.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Composite/Type0Font.cs @@ -1,13 +1,13 @@ namespace UglyToad.PdfPig.PdfFonts.Composite { + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using CidFonts; using Cmap; using Core; using Geometry; - using System; - using System.Collections.Generic; using Tokens; - using Util.JetBrains.Annotations; using Debug = System.Diagnostics.Debug; /// @@ -15,7 +15,7 @@ /// internal sealed class Type0Font : IFont, IVerticalWritingSupported { - private readonly CMap ucs2CMap; + private readonly CMap? ucs2CMap; // ReSharper disable once NotAccessedField.Local private readonly bool isChineseJapaneseOrKorean; private readonly Dictionary boundingBoxCache @@ -23,24 +23,24 @@ private readonly Dictionary boundingBoxCache public NameToken Name => BaseFont; - [NotNull] public NameToken BaseFont { get; } - [NotNull] public ICidFont CidFont { get; } - [NotNull] public CMap CMap { get; } - [NotNull] public ToUnicodeCMap ToUnicode { get; } public bool IsVertical => CMap.WritingMode == WritingMode.Vertical; public FontDetails Details { get; } - public Type0Font(NameToken baseFont, ICidFont cidFont, CMap cmap, CMap toUnicodeCMap, - CMap ucs2CMap, + public Type0Font( + NameToken baseFont, + ICidFont cidFont, + CMap cmap, + CMap? toUnicodeCMap, + CMap? ucs2CMap, bool isChineseJapaneseOrKorean) { this.ucs2CMap = ucs2CMap; @@ -65,15 +65,14 @@ public int ReadCharacterCode(IInputBytes bytes, out int codeLength) return code; } - public bool TryGetUnicode(int characterCode, out string value) + public bool TryGetUnicode(int characterCode, [NotNullWhen(true)] out string? value) { value = null; var HaveCMap = ToUnicode.CanMapToUnicode; if (HaveCMap == false) { - var HaveUnicode2CMap = (ucs2CMap is null == false); - if (HaveUnicode2CMap) + if (ucs2CMap != null) { // Have both ucs2Map and CMap convert to unicode by // characterCode ----by CMAP---> CID ---ucs2Map---> Unicode @@ -88,10 +87,10 @@ public bool TryGetUnicode(int characterCode, out string value) { return value != null; } - } - if (HaveUnicode2CMap) // 2022-12-24 @fnatzke left as fall-back. Possible? - { - // characterCode ---ucs2Map---> Unicode (?) @fnatzke possible? + + // 2022-12-24 @fnatzke left as fall-back. Possible? + + // characterCode ---ucs2Map---> Unicode (?) @fnatzke possible? if (ucs2CMap.TryConvertToUnicode(characterCode, out value)) { return value != null; @@ -157,7 +156,7 @@ public PdfVector GetDisplacementVector(int characterCode) } /// - public bool TryGetPath(int characterCode, out IReadOnlyList path) + public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { var characterIdentifier = CMap.ConvertToCid(characterCode); @@ -165,7 +164,7 @@ public bool TryGetPath(int characterCode, out IReadOnlyList path) } /// - public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList path) + public bool TryGetNormalisedPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { var characterIdentifier = CMap.ConvertToCid(characterCode); diff --git a/src/UglyToad.PdfPig/PdfFonts/FontDescriptor.cs b/src/UglyToad.PdfPig/PdfFonts/FontDescriptor.cs index 05c5b7187..d310a45df 100644 --- a/src/UglyToad.PdfPig/PdfFonts/FontDescriptor.cs +++ b/src/UglyToad.PdfPig/PdfFonts/FontDescriptor.cs @@ -2,7 +2,6 @@ { using Core; using Tokens; - using Util.JetBrains.Annotations; /// /// Specifies metrics and attributes of a simple font or CID Font for the whole font rather than per-glyph. @@ -30,7 +29,7 @@ public class FontDescriptor /// The preferred font family. /// /// Optional - public string FontFamily { get; } + public string? FontFamily { get; } /// /// The font stretch value. @@ -143,15 +142,13 @@ public class FontDescriptor /// The bytes of the font program. /// /// Optional - [CanBeNull] - public DescriptorFontFile FontFile { get; } + public DescriptorFontFile? FontFile { get; } /// /// The character names defined in a font subset. /// /// Optional - [CanBeNull] - public string CharSet { get; } + public string? CharSet { get; } /// /// Create a new . @@ -179,7 +176,7 @@ public FontDescriptor(Builder builder) CharSet = builder.CharSet; } - internal FontDetails ToDetails(string name = null) + internal FontDetails ToDetails(string? name = null) { return new FontDetails(name ?? FontName ?? string.Empty, FontWeight > 500, @@ -200,7 +197,7 @@ public class Builder /// /// Sets the . /// - public string FontFamily { get; set; } + public string? FontFamily { get; set; } /// /// Sets the . @@ -280,14 +277,12 @@ public class Builder /// /// Sets the . /// - [CanBeNull] - public DescriptorFontFile FontFile { get; set; } + public DescriptorFontFile? FontFile { get; set; } /// /// Sets the . /// - [CanBeNull] - public string CharSet { get; set; } + public string? CharSet { get; set; } /// /// Create a new . diff --git a/src/UglyToad.PdfPig/PdfFonts/FontDetails.cs b/src/UglyToad.PdfPig/PdfFonts/FontDetails.cs index 58dd0b61d..e49e74ccc 100644 --- a/src/UglyToad.PdfPig/PdfFonts/FontDetails.cs +++ b/src/UglyToad.PdfPig/PdfFonts/FontDetails.cs @@ -38,7 +38,7 @@ public class FontDetails /// /// Create a new . /// - public FontDetails(string name, bool isBold, int weight, bool isItalic) + public FontDetails(string? name, bool isBold, int weight, bool isItalic) { Name = name ?? string.Empty; IsBold = isBold; @@ -46,7 +46,7 @@ public FontDetails(string name, bool isBold, int weight, bool isItalic) IsItalic = isItalic; } - internal static FontDetails GetDefault(string name = null) => new FontDetails(name ?? string.Empty, + internal static FontDetails GetDefault(string? name = null) => new FontDetails(name ?? string.Empty, false, DefaultWeight, false); diff --git a/src/UglyToad.PdfPig/PdfFonts/FontFactory.cs b/src/UglyToad.PdfPig/PdfFonts/FontFactory.cs index 1332fd769..7114d1a72 100644 --- a/src/UglyToad.PdfPig/PdfFonts/FontFactory.cs +++ b/src/UglyToad.PdfPig/PdfFonts/FontFactory.cs @@ -39,7 +39,7 @@ public IFont Get(DictionaryToken dictionary) var subtype = dictionary.GetNameOrDefault(NameToken.Subtype); - if (handlers.TryGetValue(subtype, out var handler)) + if (subtype != null && handlers.TryGetValue(subtype, out var handler)) { return handler.Generate(dictionary); } diff --git a/src/UglyToad.PdfPig/PdfFonts/IFont.cs b/src/UglyToad.PdfPig/PdfFonts/IFont.cs index 0b70c95f0..05fd82453 100644 --- a/src/UglyToad.PdfPig/PdfFonts/IFont.cs +++ b/src/UglyToad.PdfPig/PdfFonts/IFont.cs @@ -1,7 +1,8 @@ namespace UglyToad.PdfPig.PdfFonts { - using Core; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using Core; using Tokens; /// @@ -12,7 +13,7 @@ public interface IFont /// /// The font name. /// - NameToken Name { get; } + NameToken? Name { get; } /// /// Is the font vertical. @@ -32,7 +33,7 @@ public interface IFont /// /// Try get the unicode value. /// - bool TryGetUnicode(int characterCode, out string value); + bool TryGetUnicode(int characterCode, [NotNullWhen(true)] out string? value); /// /// Get the font bounding box. @@ -49,13 +50,13 @@ public interface IFont /// /// Character code in a PDF. Not to be confused with unicode. /// The glyph path for the given character code. - bool TryGetPath(int characterCode, out IReadOnlyList path); + bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path); /// /// Returns the normalised glyph path for the given character code in a PDF. /// /// Character code in a PDF. Not to be confused with unicode. /// The normalized glyph path for the given character code. - bool TryGetNormalisedPath(int characterCode, out IReadOnlyList path); + bool TryGetNormalisedPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path); } } diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/CMapParser.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/CMapParser.cs index 190f7b41e..279124811 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/CMapParser.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/CMapParser.cs @@ -1,12 +1,13 @@ namespace UglyToad.PdfPig.PdfFonts.Parser { using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using Cmap; using Core; using Parts; - using System.Collections.Generic; using Tokenization.Scanner; using Tokens; @@ -30,7 +31,7 @@ public CMap Parse(IInputBytes inputBytes) var builder = new CharacterMapBuilder(); - IToken previousToken = null; + IToken? previousToken = null; while (scanner.MoveNext()) { var token = scanner.CurrentToken; @@ -124,7 +125,7 @@ public CMap Parse(IInputBytes inputBytes) return builder.Build(); } - public bool TryParseExternal(string name, out CMap result) + public bool TryParseExternal(string name, [NotNullWhen(true)] out CMap? result) { result = null; diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/EncodingReader.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/EncodingReader.cs index edcfc61d8..0835ee7bf 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/EncodingReader.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/EncodingReader.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Fonts; using Fonts.Encodings; using PdfPig.Parser.Parts; @@ -17,22 +18,24 @@ public EncodingReader(IPdfTokenScanner pdfScanner) this.pdfScanner = pdfScanner; } - public Encoding Read(DictionaryToken fontDictionary, FontDescriptor descriptor = null, - Encoding fontEncoding = null) + public Encoding? Read( + DictionaryToken fontDictionary, + FontDescriptor? descriptor = null, + Encoding? fontEncoding = null) { if (!fontDictionary.TryGet(NameToken.Encoding, out var baseEncodingObject)) { return null; } - if (DirectObjectFinder.TryGet(baseEncodingObject, pdfScanner, out NameToken name)) + if (DirectObjectFinder.TryGet(baseEncodingObject, pdfScanner, out NameToken? name)) { if (TryGetNamedEncoding(descriptor, name, out var namedEncoding)) { return namedEncoding; } - if (fontDictionary.TryGet(NameToken.BaseFont, pdfScanner, out NameToken baseFontName)) + if (fontDictionary.TryGet(NameToken.BaseFont, pdfScanner, out NameToken? baseFontName)) { if (string.Equals(baseFontName.Data, "ZapfDingbats", StringComparison.OrdinalIgnoreCase)) { @@ -55,7 +58,7 @@ public Encoding Read(DictionaryToken fontDictionary, FontDescriptor descriptor = return encoding; } - private Encoding ReadEncodingDictionary(DictionaryToken encodingDictionary, Encoding fontEncoding) + private Encoding? ReadEncodingDictionary(DictionaryToken encodingDictionary, Encoding? fontEncoding) { if (encodingDictionary is null) { @@ -120,7 +123,7 @@ private Encoding ReadEncodingDictionary(DictionaryToken encodingDictionary, Enco return differences; } - private static bool TryGetNamedEncoding(FontDescriptor descriptor, NameToken encodingName, out Encoding encoding) + private static bool TryGetNamedEncoding(FontDescriptor? descriptor, NameToken encodingName, [NotNullWhen(true)] out Encoding? encoding) { encoding = null; // Symbolic fonts default to standard encoding. @@ -137,5 +140,4 @@ private static bool TryGetNamedEncoding(FontDescriptor descriptor, NameToken enc return true; } } -} - +} \ No newline at end of file diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/FontDictionaryAccessHelper.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/FontDictionaryAccessHelper.cs index 1013eff34..62c4be65b 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/FontDictionaryAccessHelper.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/FontDictionaryAccessHelper.cs @@ -55,7 +55,7 @@ public static double[] GetWidths(IPdfTokenScanner pdfScanner, DictionaryToken di public static FontDescriptor GetFontDescriptor(IPdfTokenScanner pdfScanner, DictionaryToken dictionary) { - if (!dictionary.TryGet(NameToken.FontDescriptor, pdfScanner, out DictionaryToken parsed)) + if (!dictionary.TryGet(NameToken.FontDescriptor, pdfScanner, out DictionaryToken? parsed)) { throw new InvalidFontFormatException($"No font descriptor indirect reference found in the TrueType font: {dictionary}."); } diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/TrueTypeFontHandler.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/TrueTypeFontHandler.cs index a10cb8141..0a6163fa1 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/TrueTypeFontHandler.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/TrueTypeFontHandler.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using Cmap; @@ -30,7 +31,10 @@ internal class TrueTypeFontHandler : IFontHandler private readonly ISystemFontFinder systemFontFinder; private readonly IFontHandler type1FontHandler; - public TrueTypeFontHandler(ILog log, IPdfTokenScanner pdfScanner, ILookupFilterProvider filterProvider, + public TrueTypeFontHandler( + ILog log, + IPdfTokenScanner pdfScanner, + ILookupFilterProvider filterProvider, IEncodingReader encodingReader, ISystemFontFinder systemFontFinder, IFontHandler type1FontHandler) @@ -45,11 +49,11 @@ public TrueTypeFontHandler(ILog log, IPdfTokenScanner pdfScanner, ILookupFilterP public IFont Generate(DictionaryToken dictionary) { - if (!dictionary.TryGetOptionalTokenDirect(NameToken.FirstChar, pdfScanner, out NumericToken firstCharacterToken) + if (!dictionary.TryGetOptionalTokenDirect(NameToken.FirstChar, pdfScanner, out NumericToken? firstCharacterToken) || !dictionary.TryGet(NameToken.FontDescriptor, pdfScanner, out _) || !dictionary.TryGet(NameToken.Widths, out IToken _)) { - if (!dictionary.TryGetOptionalTokenDirect(NameToken.BaseFont, pdfScanner, out NameToken baseFont)) + if (!dictionary.TryGetOptionalTokenDirect(NameToken.BaseFont, pdfScanner, out NameToken? baseFont)) { throw new InvalidFontFormatException($"The provided TrueType font dictionary did not contain a /FirstChar or a /BaseFont entry: {dictionary}."); } @@ -72,14 +76,14 @@ public IFont Generate(DictionaryToken dictionary) } int? firstChar = null; - double[] widthsOverride = null; + double[]? widthsOverride = null; if (dictionary.TryGet(NameToken.FirstChar, pdfScanner, out firstCharacterToken)) { firstChar = firstCharacterToken.Int; } - if (dictionary.TryGet(NameToken.Widths, pdfScanner, out ArrayToken widthsArray)) + if (dictionary.TryGet(NameToken.Widths, pdfScanner, out ArrayToken? widthsArray)) { widthsOverride = widthsArray.Data.OfType() .Select(x => x.Double).ToArray(); @@ -104,7 +108,7 @@ public IFont Generate(DictionaryToken dictionary) var name = FontDictionaryAccessHelper.GetName(pdfScanner, dictionary, descriptor); - CMap toUnicodeCMap = null; + CMap? toUnicodeCMap = null; if (dictionary.TryGet(NameToken.ToUnicode, out var toUnicodeObj)) { try @@ -124,7 +128,7 @@ public IFont Generate(DictionaryToken dictionary) } } - Encoding encoding = encodingReader.Read(dictionary, descriptor); + Encoding? encoding = encodingReader.Read(dictionary, descriptor); if (encoding is null && font?.TableRegister?.CMapTable != null && font.TableRegister.PostScriptTable?.GlyphNames != null) @@ -157,7 +161,7 @@ public IFont Generate(DictionaryToken dictionary) return new TrueTypeSimpleFont(name, descriptor, toUnicodeCMap, encoding, font, firstCharacter, widths); } - private TrueTypeFont ParseTrueTypeFont(FontDescriptor descriptor, out IFontHandler actualHandler) + private TrueTypeFont? ParseTrueTypeFont(FontDescriptor descriptor, [NotNullWhen(true)] out IFontHandler? actualHandler) { actualHandler = null; @@ -186,7 +190,7 @@ private TrueTypeFont ParseTrueTypeFont(FontDescriptor descriptor, out IFontHandl { var shouldThrow = true; - if (fontFileStream.StreamDictionary.TryGet(NameToken.Subtype, pdfScanner, out NameToken subTypeName)) + if (fontFileStream.StreamDictionary.TryGet(NameToken.Subtype, pdfScanner, out NameToken? subTypeName)) { if (subTypeName == NameToken.Type1C) { diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type0FontHandler.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type0FontHandler.cs index becd354b3..7f8f104cf 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type0FontHandler.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type0FontHandler.cs @@ -1,6 +1,7 @@ namespace UglyToad.PdfPig.PdfFonts.Parser.Handlers { using System; + using System.Diagnostics.CodeAnalysis; using CidFonts; using Cmap; using Composite; @@ -56,7 +57,7 @@ public IFont Generate(DictionaryToken dictionary) descendantFontDictionary = (DictionaryToken)descendantObject; } - cidFont = ParseDescendant(descendantFontDictionary); + cidFont = ParseDescendant(descendantFontDictionary)!; } else { @@ -65,7 +66,7 @@ public IFont Generate(DictionaryToken dictionary) var (ucs2CMap, isChineseJapaneseOrKorean) = GetUcs2CMap(dictionary, isCMapPredefined, cidFont); - CMap toUnicodeCMap = null; + CMap? toUnicodeCMap = null; if (dictionary.ContainsKey(NameToken.ToUnicode)) { var toUnicodeValue = dictionary.Data[NameToken.ToUnicode]; @@ -92,12 +93,12 @@ public IFont Generate(DictionaryToken dictionary) } } - var font = new Type0Font(baseFont, cidFont, cMap, toUnicodeCMap, ucs2CMap, isChineseJapaneseOrKorean); + var font = new Type0Font(baseFont!, cidFont, cMap, toUnicodeCMap, ucs2CMap, isChineseJapaneseOrKorean); return font; } - private static bool TryGetFirstDescendant(DictionaryToken dictionary, out IToken descendant) + private static bool TryGetFirstDescendant(DictionaryToken dictionary, [NotNullWhen(true)] out IToken? descendant) { descendant = null; @@ -133,7 +134,7 @@ private static bool TryGetFirstDescendant(DictionaryToken dictionary, out IToken return false; } - private ICidFont ParseDescendant(DictionaryToken dictionary) + private ICidFont? ParseDescendant(DictionaryToken dictionary) { var type = dictionary.GetNameOrDefault(NameToken.Type); if (type?.Equals(NameToken.Font) != true) @@ -141,9 +142,7 @@ private ICidFont ParseDescendant(DictionaryToken dictionary) throw new InvalidFontFormatException($"Expected \'Font\' dictionary but found \'{type}\'"); } - var result = cidFontFactory.Generate(dictionary); - - return result; + return cidFontFactory.Generate(dictionary); } private CMap ReadEncoding(DictionaryToken dictionary, out bool isCMapPredefined) @@ -151,7 +150,7 @@ private CMap ReadEncoding(DictionaryToken dictionary, out bool isCMapPredefined) isCMapPredefined = false; CMap result; - if (dictionary.TryGet(NameToken.Encoding, scanner, out NameToken encodingName)) + if (dictionary.TryGet(NameToken.Encoding, scanner, out NameToken? encodingName)) { if (!CMapCache.TryGet(encodingName.Data, out var cmap)) { @@ -162,7 +161,7 @@ private CMap ReadEncoding(DictionaryToken dictionary, out bool isCMapPredefined) isCMapPredefined = true; } - else if (dictionary.TryGet(NameToken.Encoding, scanner, out StreamToken stream)) + else if (dictionary.TryGet(NameToken.Encoding, scanner, out StreamToken? stream)) { var decoded = stream.Decode(filterProvider, scanner); @@ -179,7 +178,7 @@ private CMap ReadEncoding(DictionaryToken dictionary, out bool isCMapPredefined) return result; } - private static (CMap, bool isChineseJapaneseOrKorean) GetUcs2CMap(DictionaryToken dictionary, bool isCMapPredefined, ICidFont cidFont) + private static (CMap?, bool isChineseJapaneseOrKorean) GetUcs2CMap(DictionaryToken dictionary, bool isCMapPredefined, ICidFont cidFont) { if (!isCMapPredefined) { @@ -221,7 +220,7 @@ private static (CMap, bool isChineseJapaneseOrKorean) GetUcs2CMap(DictionaryToke return (null, false); } - var fullCmapName = cidFont.SystemInfo.ToString(); + var fullCmapName = cidFont!.SystemInfo.ToString(); string registry; string ordering; diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type1FontHandler.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type1FontHandler.cs index 94d01304e..04d20a932 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type1FontHandler.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type1FontHandler.cs @@ -71,7 +71,7 @@ public IFont Generate(DictionaryToken dictionary) if (!dictionary.TryGet(NameToken.FontDescriptor, out var _)) { if (dictionary.TryGet(NameToken.BaseFont, out var baseFontToken) && - DirectObjectFinder.TryGet(baseFontToken, pdfScanner, out NameToken baseFontName)) + DirectObjectFinder.TryGet(baseFontToken, pdfScanner, out NameToken? baseFontName)) { var metrics = Standard14.GetAdobeFontMetrics(baseFontName.Data); @@ -87,7 +87,7 @@ public IFont Generate(DictionaryToken dictionary) var name = FontDictionaryAccessHelper.GetName(pdfScanner, dictionary, descriptor); - CMap toUnicodeCMap = null; + CMap? toUnicodeCMap = null; if (dictionary.TryGet(NameToken.ToUnicode, out var toUnicodeObj)) { var toUnicode = DirectObjectFinder.Get(toUnicodeObj, pdfScanner); @@ -116,15 +116,15 @@ public IFont Generate(DictionaryToken dictionary) var encoding = encodingReader.Read(dictionary, descriptor, fromFont); - if (encoding is null && font != null && font.TryGetFirst(out var t1FontReplacment)) + if (encoding is null && font != null && font.TryGetFirst(out var t1FontReplacement)) { - encoding = new BuiltInEncoding(t1FontReplacment.Encoding); + encoding = new BuiltInEncoding(t1FontReplacement.Encoding); } - return new Type1FontSimple(name, firstCharacter, lastCharacter, widths, descriptor, encoding, toUnicodeCMap, font); + return new Type1FontSimple(name, firstCharacter, lastCharacter, widths, descriptor, encoding!, toUnicodeCMap!, font!); } - private Union ParseFontProgram(FontDescriptor descriptor) + private Union? ParseFontProgram(FontDescriptor descriptor) { if (descriptor?.FontFile is null) { diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type3FontHandler.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type3FontHandler.cs index 2eb0b67b3..4b3376e5f 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type3FontHandler.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type3FontHandler.cs @@ -41,9 +41,9 @@ public IFont Generate(DictionaryToken dictionary) var lastCharacter = FontDictionaryAccessHelper.GetLastCharacter(dictionary); var widths = FontDictionaryAccessHelper.GetWidths(scanner, dictionary); - Encoding encoding = encodingReader.Read(dictionary); + Encoding? encoding = encodingReader.Read(dictionary); - CMap toUnicodeCMap = null; + CMap? toUnicodeCMap = null; if (dictionary.TryGet(NameToken.ToUnicode, out var toUnicodeObj)) { var toUnicode = DirectObjectFinder.Get(toUnicodeObj, scanner); @@ -58,13 +58,14 @@ public IFont Generate(DictionaryToken dictionary) var name = GetFontName(dictionary); - return new Type3Font(name, boundingBox, fontMatrix, encoding, firstCharacter, - lastCharacter, widths, toUnicodeCMap); + return new Type3Font(name, boundingBox, fontMatrix, encoding!, + firstCharacter, + lastCharacter, widths, toUnicodeCMap!); } private NameToken GetFontName(DictionaryToken dictionary) { - if (dictionary.TryGet(NameToken.Name, scanner, out NameToken fontName)) + if (dictionary.TryGet(NameToken.Name, scanner, out NameToken? fontName)) { return fontName; } diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/IEncodingReader.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/IEncodingReader.cs index 096854593..7448eb7ae 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/IEncodingReader.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/IEncodingReader.cs @@ -5,7 +5,9 @@ internal interface IEncodingReader { - Encoding Read(DictionaryToken fontDictionary, FontDescriptor descriptor = null, - Encoding fontEncoding = null); + Encoding? Read( + DictionaryToken fontDictionary, + FontDescriptor? descriptor = null, + Encoding? fontEncoding = null); } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/BaseFontRangeParser.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/BaseFontRangeParser.cs index 0d92ac8ce..1febe4269 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/BaseFontRangeParser.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/BaseFontRangeParser.cs @@ -34,8 +34,8 @@ public void Parse(NumericToken numberOfOperations, ITokenScanner scanner, Charac throw new InvalidFontFormatException("bfrange ended unexpectedly after the high source code."); } - List destinationBytes = null; - ArrayToken destinationArray = null; + List? destinationBytes = null; + ArrayToken? destinationArray = null; switch (scanner.CurrentToken) { @@ -91,11 +91,11 @@ public void Parse(NumericToken numberOfOperations, ITokenScanner scanner, Charac done = true; } - builder.AddBaseFontCharacter(startCode, destinationBytes); + builder.AddBaseFontCharacter(startCode, destinationBytes!); Increment(startCode, startCode.Count - 1); - Increment(destinationBytes, destinationBytes.Count - 1); + Increment(destinationBytes!, destinationBytes!.Count - 1); } } } diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/CidFontFactory.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/CidFontFactory.cs index be50f79b0..65b396c18 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/CidFontFactory.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/CidFontFactory.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using CidFonts; using Core; using Filters; @@ -29,7 +30,7 @@ public CidFontFactory(ILog log, IPdfTokenScanner pdfScanner, ILookupFilterProvid this.filterProvider = filterProvider; } - public ICidFont Generate(DictionaryToken dictionary) + public ICidFont? Generate(DictionaryToken dictionary) { var type = dictionary.GetNameOrDefault(NameToken.Type); if (!NameToken.Font.Equals(type)) @@ -40,20 +41,20 @@ public ICidFont Generate(DictionaryToken dictionary) var widths = ReadWidths(dictionary); var defaultWidth = default(double?); - if (dictionary.TryGet(NameToken.Dw, pdfScanner, out NumericToken defaultWidthToken)) + if (dictionary.TryGet(NameToken.Dw, pdfScanner, out NumericToken? defaultWidthToken)) { defaultWidth = defaultWidthToken.Double; } var verticalWritingMetrics = ReadVerticalDisplacements(dictionary); - FontDescriptor descriptor = null; + FontDescriptor? descriptor = null; if (TryGetFontDescriptor(dictionary, out var descriptorDictionary)) { descriptor = FontDescriptorFactory.Generate(descriptorDictionary, pdfScanner); } - ICidFontProgram fontProgram = null; + ICidFontProgram? fontProgram = null; try { fontProgram = ReadDescriptorFile(descriptor); @@ -70,25 +71,25 @@ public ICidFont Generate(DictionaryToken dictionary) var subType = dictionary.GetNameOrDefault(NameToken.Subtype); if (NameToken.CidFontType0.Equals(subType)) { - return new Type0CidFont(fontProgram, type, subType, baseFont, systemInfo, descriptor, verticalWritingMetrics, widths, defaultWidth); + return new Type0CidFont(fontProgram!, type!, subType!, baseFont!, systemInfo, descriptor!, verticalWritingMetrics, widths, defaultWidth); } if (NameToken.CidFontType2.Equals(subType)) { var cidToGid = GetCharacterIdentifierToGlyphIndexMap(dictionary); - return new Type2CidFont(type, subType, baseFont, systemInfo, descriptor, fontProgram, verticalWritingMetrics, widths, defaultWidth, cidToGid); + return new Type2CidFont(type!, subType!, baseFont!, systemInfo, descriptor!, fontProgram, verticalWritingMetrics, widths, defaultWidth, cidToGid); } return null; } - private bool TryGetFontDescriptor(DictionaryToken dictionary, out DictionaryToken descriptorDictionary) + private bool TryGetFontDescriptor(DictionaryToken dictionary, [NotNullWhen(true)] out DictionaryToken? descriptorDictionary) { return dictionary.TryGet(NameToken.FontDescriptor, pdfScanner, out descriptorDictionary); } - private ICidFontProgram ReadDescriptorFile(FontDescriptor descriptor) + private ICidFontProgram? ReadDescriptorFile(FontDescriptor? descriptor) { if (descriptor?.FontFile is null) { @@ -114,12 +115,12 @@ private ICidFontProgram ReadDescriptorFile(FontDescriptor descriptor) } case DescriptorFontFile.FontFileType.FromSubtype: { - if (!DirectObjectFinder.TryGet(descriptor.FontFile.ObjectKey, pdfScanner, out StreamToken str)) + if (!DirectObjectFinder.TryGet(descriptor.FontFile.ObjectKey, pdfScanner, out StreamToken? str)) { throw new NotSupportedException("Cannot read CID font from subtype."); } - if (!str.StreamDictionary.TryGet(NameToken.Subtype, out NameToken subtypeName)) + if (!str.StreamDictionary.TryGet(NameToken.Subtype, out NameToken? subtypeName)) { throw new PdfDocumentFormatException($"The font file stream did not contain a subtype entry: {str.StreamDictionary}."); } @@ -150,7 +151,7 @@ private IReadOnlyDictionary ReadWidths(DictionaryToken dict) { var widths = new Dictionary(); - if (!dict.TryGet(NameToken.W, pdfScanner, out ArrayToken widthArray)) + if (!dict.TryGet(NameToken.W, pdfScanner, out ArrayToken? widthArray)) { return widths; } @@ -161,7 +162,7 @@ private IReadOnlyDictionary ReadWidths(DictionaryToken dict) { var firstCode = DirectObjectFinder.Get(widthArray.Data[counter++], pdfScanner); var next = widthArray.Data[counter++]; - if (DirectObjectFinder.TryGet(next, pdfScanner, out ArrayToken array)) + if (DirectObjectFinder.TryGet(next, pdfScanner, out ArrayToken? array)) { var startRange = firstCode.Int; var arraySize = array.Data.Count; @@ -279,12 +280,12 @@ private CharacterIdentifierToGlyphIndexMap GetCharacterIdentifierToGlyphIndexMap return new CharacterIdentifierToGlyphIndexMap(); } - if (DirectObjectFinder.TryGet(entry, pdfScanner, out NameToken _)) + if (DirectObjectFinder.TryGet(entry, pdfScanner, out NameToken? _)) { return new CharacterIdentifierToGlyphIndexMap(); } - if (!DirectObjectFinder.TryGet(entry, pdfScanner, out StreamToken stream)) + if (!DirectObjectFinder.TryGet(entry, pdfScanner, out StreamToken? stream)) { throw new PdfDocumentFormatException($"No stream or name token found for /CIDToGIDMap in dictionary: {dictionary}."); } @@ -313,12 +314,12 @@ private string SafeKeyAccess(DictionaryToken dictionary, NameToken keyName) if (token is IndirectReferenceToken obj) { - if (DirectObjectFinder.TryGet(obj, pdfScanner, out StringToken stringToken)) + if (DirectObjectFinder.TryGet(obj, pdfScanner, out StringToken? stringToken)) { return stringToken.Data; } - if (DirectObjectFinder.TryGet(obj, pdfScanner, out HexToken hexToken)) + if (DirectObjectFinder.TryGet(obj, pdfScanner, out HexToken? hexToken)) { return hexToken.Data; } diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/FontDescriptorFactory.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/FontDescriptorFactory.cs index 5d4d458be..cc7ed9548 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/FontDescriptorFactory.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/Parts/FontDescriptorFactory.cs @@ -5,7 +5,6 @@ using Tokenization.Scanner; using Tokens; using Util; - using Util.JetBrains.Annotations; internal static class FontDescriptorFactory { @@ -58,7 +57,7 @@ private static double GetDoubleOrDefault(DictionaryToken dictionary, NameToken n private static NameToken GetFontName(DictionaryToken dictionary, IPdfTokenScanner scanner) { - if (!dictionary.TryGet(NameToken.FontName, scanner, out NameToken name)) + if (!dictionary.TryGet(NameToken.FontName, scanner, out NameToken? name)) { name = NameToken.Create(string.Empty); } @@ -113,7 +112,7 @@ private static PdfRectangle GetBoundingBox(DictionaryToken dictionary, IPdfToken return boxArray.ToRectangle(pdfScanner); } - private static string GetCharSet(DictionaryToken dictionary) + private static string? GetCharSet(DictionaryToken dictionary) { if (!dictionary.TryGet(NameToken.CharSet, out var set) || !(set is NameToken setName)) { @@ -123,8 +122,7 @@ private static string GetCharSet(DictionaryToken dictionary) return setName.Data; } - [CanBeNull] - private static DescriptorFontFile GetFontFile(DictionaryToken dictionary) + private static DescriptorFontFile? GetFontFile(DictionaryToken dictionary) { if (dictionary.TryGet(NameToken.FontFile, out var value)) { diff --git a/src/UglyToad.PdfPig/PdfFonts/Simple/TrueTypeSimpleFont.cs b/src/UglyToad.PdfPig/PdfFonts/Simple/TrueTypeSimpleFont.cs index 490b9d586..13e4162d9 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Simple/TrueTypeSimpleFont.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Simple/TrueTypeSimpleFont.cs @@ -1,51 +1,52 @@ namespace UglyToad.PdfPig.PdfFonts.Simple { + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Linq; using Cmap; using Composite; using Core; using Fonts; using Fonts.Encodings; using Fonts.TrueType; - using System; - using System.Collections.Generic; - using System.Linq; using Tokens; - using Util.JetBrains.Annotations; internal sealed class TrueTypeSimpleFont : IFont { private static readonly TransformationMatrix DefaultTransformation = TransformationMatrix.FromValues(1 / 1000.0, 0, 0, 1 / 1000.0, 0, 0); - private readonly FontDescriptor descriptor; + private readonly FontDescriptor? descriptor; - private readonly Dictionary boundingBoxCache - = new Dictionary(); + private readonly Dictionary boundingBoxCache = new(); private readonly Dictionary unicodeValuesCache = new Dictionary(); - [CanBeNull] private readonly Encoding encoding; + private readonly Encoding? encoding; - [CanBeNull] private readonly TrueTypeFont font; + private readonly TrueTypeFont? font; private readonly int firstCharacter; private readonly double[] widths; +#nullable disable public NameToken Name { get; } +#nullable enable public bool IsVertical { get; } public FontDetails Details { get; } - [NotNull] public ToUnicodeCMap ToUnicode { get; set; } - public TrueTypeSimpleFont(NameToken name, - FontDescriptor descriptor, - [CanBeNull] CMap toUnicodeCMap, - [CanBeNull] Encoding encoding, - [CanBeNull] TrueTypeFont font, + public TrueTypeSimpleFont( + NameToken name, + FontDescriptor? descriptor, + CMap? toUnicodeCMap, + Encoding? encoding, + TrueTypeFont? font, int firstCharacter, double[] widths) { @@ -58,6 +59,7 @@ public TrueTypeSimpleFont(NameToken name, Name = name; IsVertical = false; ToUnicode = new ToUnicodeCMap(toUnicodeCMap); + Details = descriptor?.ToDetails(Name?.Data) ?? FontDetails.GetDefault(Name?.Data); } @@ -68,7 +70,7 @@ public int ReadCharacterCode(IInputBytes bytes, out int codeLength) return bytes.CurrentByte; } - public bool TryGetUnicode(int characterCode, out string value) + public bool TryGetUnicode(int characterCode, [NotNullWhen(true)] out string? value) { value = null; @@ -196,7 +198,7 @@ private PdfRectangle GetBoundingBoxInGlyphSpace(int characterCode, out bool from if (font is null) { - return descriptor.BoundingBox; + return descriptor!.BoundingBox; } if (font.TryGetBoundingBox(characterCode, CharacterCodeToGlyphId, out var bounds)) @@ -216,13 +218,13 @@ private PdfRectangle GetBoundingBoxInGlyphSpace(int characterCode, out bool from private int? CharacterCodeToGlyphId(int characterCode) { - bool HasFlag(FontDescriptorFlags value, FontDescriptorFlags target) + static bool HasFlag(FontDescriptorFlags value, FontDescriptorFlags target) { return (value & target) == target; } if (descriptor is null || !unicodeValuesCache.TryGetValue(characterCode, out var unicode) - || font.TableRegister.CMapTable is null + || font!.TableRegister.CMapTable is null || encoding is null || !encoding.CodeToNameMap.TryGetValue(characterCode, out var name) || name is null) @@ -317,14 +319,14 @@ private double GetWidth(int characterCode) if (index < 0 || index >= widths.Length) { - return descriptor.MissingWidth; + return descriptor!.MissingWidth; } return widths[index]; } /// - public bool TryGetPath(int characterCode, out IReadOnlyList path) + public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { if (font is null) { @@ -336,7 +338,7 @@ public bool TryGetPath(int characterCode, out IReadOnlyList path) } /// - public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList path) + public bool TryGetNormalisedPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { if (!TryGetPath(characterCode, out path)) { diff --git a/src/UglyToad.PdfPig/PdfFonts/Simple/TrueTypeStandard14FallbackSimpleFont.cs b/src/UglyToad.PdfPig/PdfFonts/Simple/TrueTypeStandard14FallbackSimpleFont.cs index 64e741b98..0b3ad1475 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Simple/TrueTypeStandard14FallbackSimpleFont.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Simple/TrueTypeStandard14FallbackSimpleFont.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.Linq; using Core; using Fonts; @@ -23,7 +24,7 @@ internal sealed class TrueTypeStandard14FallbackSimpleFont : IFont private readonly TrueTypeFont font; private readonly MetricOverrides overrides; - public NameToken Name { get; } + public NameToken? Name { get; } public bool IsVertical { get; } = false; @@ -49,7 +50,7 @@ public int ReadCharacterCode(IInputBytes bytes, out int codeLength) return bytes.CurrentByte; } - public bool TryGetUnicode(int characterCode, out string value) + public bool TryGetUnicode(int characterCode, [NotNullWhen(true)] out string? value) { value = null; @@ -134,7 +135,7 @@ public TransformationMatrix GetFontMatrix() } /// - public bool TryGetPath(int characterCode, out IReadOnlyList path) + public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { path = null; if (font is null) @@ -145,7 +146,7 @@ public bool TryGetPath(int characterCode, out IReadOnlyList path) } /// - public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList path) + public bool TryGetNormalisedPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { if (!TryGetPath(characterCode, out path)) { @@ -160,11 +161,11 @@ public class MetricOverrides { public int? FirstCharacterCode { get; } - public IReadOnlyList Widths { get; } + public IReadOnlyList? Widths { get; } public bool HasOverriddenMetrics { get; } - public MetricOverrides(int? firstCharacterCode, IReadOnlyList widths) + public MetricOverrides(int? firstCharacterCode, IReadOnlyList? widths) { FirstCharacterCode = firstCharacterCode; Widths = widths; @@ -183,7 +184,7 @@ public bool TryGetWidth(int characterCode, out double width) var index = characterCode - FirstCharacterCode.Value; - if (index < 0 || index >= Widths.Count) + if (index < 0 || index >= Widths!.Count) { return false; } diff --git a/src/UglyToad.PdfPig/PdfFonts/Simple/Type1FontSimple.cs b/src/UglyToad.PdfPig/PdfFonts/Simple/Type1FontSimple.cs index 084716b49..3b6d546e2 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Simple/Type1FontSimple.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Simple/Type1FontSimple.cs @@ -1,6 +1,7 @@ namespace UglyToad.PdfPig.PdfFonts.Simple { using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.Linq; using Cmap; using Composite; @@ -10,7 +11,6 @@ using Fonts.Encodings; using Fonts.Type1; using Tokens; - using Util.JetBrains.Annotations; /// /// A font based on the Adobe Type 1 font format. @@ -31,8 +31,7 @@ internal sealed class Type1FontSimple : IFont private readonly Encoding encoding; - [CanBeNull] - private readonly Union fontProgram; + private readonly Union? fontProgram; private readonly ToUnicodeCMap toUnicodeCMap; @@ -44,7 +43,13 @@ internal sealed class Type1FontSimple : IFont public FontDetails Details { get; } - public Type1FontSimple(NameToken name, int firstChar, int lastChar, double[] widths, FontDescriptor fontDescriptor, Encoding encoding, + public Type1FontSimple( + NameToken name, + int firstChar, + int lastChar, + double[] widths, + FontDescriptor fontDescriptor, + Encoding encoding, CMap toUnicodeCMap, Union fontProgram) { @@ -83,7 +88,7 @@ public int ReadCharacterCode(IInputBytes bytes, out int codeLength) return bytes.CurrentByte; } - public bool TryGetUnicode(int characterCode, out string value) + public bool TryGetUnicode(int characterCode, [NotNullWhen(true)] out string? value) { if (toUnicodeCMap.CanMapToUnicode) { @@ -218,10 +223,10 @@ public TransformationMatrix GetFontMatrix() } /// - public bool TryGetPath(int characterCode, out IReadOnlyList path) + public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { path = null; - IReadOnlyList tempPath = null; + IReadOnlyList? tempPath = null; if (characterCode < firstChar || characterCode > lastChar) { return false; @@ -263,7 +268,7 @@ public bool TryGetPath(int characterCode, out IReadOnlyList path) } /// - public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList path) + public bool TryGetNormalisedPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { if (TryGetPath(characterCode, out path)) { diff --git a/src/UglyToad.PdfPig/PdfFonts/Simple/Type1Standard14Font.cs b/src/UglyToad.PdfPig/PdfFonts/Simple/Type1Standard14Font.cs index 0093f7a4a..51316f814 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Simple/Type1Standard14Font.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Simple/Type1Standard14Font.cs @@ -1,13 +1,14 @@ //// ReSharper disable CompareOfFloatsByEqualityOperator namespace UglyToad.PdfPig.PdfFonts.Simple { + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; using Core; using Fonts; using Fonts.AdobeFontMetrics; using Fonts.Encodings; - using System; - using System.Collections.Generic; - using System.Diagnostics; using Tokens; /// @@ -26,7 +27,7 @@ internal sealed class Type1Standard14Font : IFont private readonly TransformationMatrix fontMatrix = TransformationMatrix.FromValues(0.001, 0, 0, 0.001, 0, 0); - public Type1Standard14Font(AdobeFontMetrics standardFontMetrics, Encoding overrideEncoding = null) + public Type1Standard14Font(AdobeFontMetrics standardFontMetrics, Encoding? overrideEncoding = null) { this.standardFontMetrics = standardFontMetrics ?? throw new ArgumentNullException(nameof(standardFontMetrics)); encoding = overrideEncoding ?? new AdobeFontMetricsEncoding(standardFontMetrics); @@ -46,7 +47,7 @@ public int ReadCharacterCode(IInputBytes bytes, out int codeLength) return bytes.CurrentByte; } - public bool TryGetUnicode(int characterCode, out string value) + public bool TryGetUnicode(int characterCode, [NotNullWhen(true)] out string? value) { var name = encoding.GetName(characterCode); if (string.Equals(name, GlyphList.NotDefined, StringComparison.OrdinalIgnoreCase)) @@ -124,9 +125,9 @@ public TransformationMatrix GetFontMatrix() /// /// - /// Not implemeted. + /// Not implemented. /// - public bool TryGetPath(int characterCode, out IReadOnlyList path) + public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { // https://github.com/apache/pdfbox/blob/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Standard14Fonts.java path = null; @@ -137,7 +138,7 @@ public bool TryGetPath(int characterCode, out IReadOnlyList path) /// /// Not implemeted. /// - public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList path) + public bool TryGetNormalisedPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { return TryGetPath(characterCode, out path); } diff --git a/src/UglyToad.PdfPig/PdfFonts/Simple/Type3Font.cs b/src/UglyToad.PdfPig/PdfFonts/Simple/Type3Font.cs index d8bc5c545..2e9596faf 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Simple/Type3Font.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Simple/Type3Font.cs @@ -1,11 +1,12 @@ namespace UglyToad.PdfPig.PdfFonts.Simple -{ +{ + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Cmap; using Composite; using Core; using Fonts; using Fonts.Encodings; - using System.Collections.Generic; using Tokens; internal class Type3Font : IFont @@ -49,7 +50,7 @@ public int ReadCharacterCode(IInputBytes bytes, out int codeLength) return bytes.CurrentByte; } - public bool TryGetUnicode(int characterCode, out string value) + public bool TryGetUnicode(int characterCode, [NotNullWhen(true)] out string? value) { if (toUnicodeCMap.CanMapToUnicode) { @@ -93,7 +94,7 @@ public TransformationMatrix GetFontMatrix() /// /// Type 3 fonts do not use vector paths. Always returns false. /// - public bool TryGetPath(int characterCode, out IReadOnlyList path) + public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { path = null; return false; @@ -103,7 +104,7 @@ public bool TryGetPath(int characterCode, out IReadOnlyList path) /// /// Type 3 fonts do not use vector paths. Always returns false. /// - public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList path) + public bool TryGetNormalisedPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList? path) { return TryGetPath(characterCode, out path); } diff --git a/src/UglyToad.PdfPig/Polyfills/NullableAnnotations.cs b/src/UglyToad.PdfPig/Polyfills/NullableAnnotations.cs new file mode 100644 index 000000000..0b362e2e3 --- /dev/null +++ b/src/UglyToad.PdfPig/Polyfills/NullableAnnotations.cs @@ -0,0 +1,51 @@ +// Based on code at located at https://github.com/dotnet/runtime/blob/79ae74f5ca5c8a6fe3a48935e85bd7374959c570/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics.CodeAnalysis; + +#if NETSTANDARD2_0 || NETFRAMEWORK +internal sealed class DoesNotReturnAttribute : Attribute { } + +[AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +internal sealed class NotNullWhenAttribute(bool returnValue) : Attribute +{ + public bool ReturnValue { get; } = returnValue; +} + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] +internal sealed class AllowNullAttribute : Attribute { } + +internal sealed class MemberNotNullAttribute : Attribute +{ + public MemberNotNullAttribute(string member) => Members = [member]; + + public MemberNotNullAttribute(params string[] members) => Members = members; + + public string[] Members { get; } +} + +[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] +internal sealed class MemberNotNullWhenAttribute : Attribute +{ + public MemberNotNullWhenAttribute(bool returnValue, string member) + { + ReturnValue = returnValue; + Members = [member]; + } + + public MemberNotNullWhenAttribute(bool returnValue, params string[] members) + { + ReturnValue = returnValue; + Members = members; + } + + /// Gets the return value condition. + public bool ReturnValue { get; } + + /// Gets field or property member names. + public string[] Members { get; } +} + +#endif \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Structure.cs b/src/UglyToad.PdfPig/Structure.cs index 3d280008a..794b50b57 100644 --- a/src/UglyToad.PdfPig/Structure.cs +++ b/src/UglyToad.PdfPig/Structure.cs @@ -6,7 +6,6 @@ using CrossReference; using Tokenization.Scanner; using Tokens; - using Util.JetBrains.Annotations; /// /// Provides access to explore and retrieve the underlying PDF objects from the document. @@ -16,13 +15,11 @@ public class Structure /// /// The root of the document's hierarchy providing access to the page tree as well as other information. /// - [NotNull] public Catalog Catalog { get; } /// /// The cross-reference table enables direct access to objects by number. /// - [NotNull] public CrossReferenceTable CrossReferenceTable { get; } /// diff --git a/src/UglyToad.PdfPig/Tokenization/Scanner/IObjectLocationProvider.cs b/src/UglyToad.PdfPig/Tokenization/Scanner/IObjectLocationProvider.cs index ca9631a91..c84d937fa 100644 --- a/src/UglyToad.PdfPig/Tokenization/Scanner/IObjectLocationProvider.cs +++ b/src/UglyToad.PdfPig/Tokenization/Scanner/IObjectLocationProvider.cs @@ -1,5 +1,6 @@ namespace UglyToad.PdfPig.Tokenization.Scanner { + using System.Diagnostics.CodeAnalysis; using Core; using Tokens; @@ -9,7 +10,7 @@ internal interface IObjectLocationProvider void UpdateOffset(IndirectReference reference, long offset); - bool TryGetCached(IndirectReference reference, out ObjectToken objectToken); + bool TryGetCached(IndirectReference reference, [NotNullWhen(true)] out ObjectToken? objectToken); void Cache(ObjectToken objectToken, bool force = false); } diff --git a/src/UglyToad.PdfPig/Tokenization/Scanner/ObjectLocationProvider.cs b/src/UglyToad.PdfPig/Tokenization/Scanner/ObjectLocationProvider.cs index e5a707d4d..29e6c474e 100644 --- a/src/UglyToad.PdfPig/Tokenization/Scanner/ObjectLocationProvider.cs +++ b/src/UglyToad.PdfPig/Tokenization/Scanner/ObjectLocationProvider.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Core; using CrossReference; using Parser.Parts; @@ -14,11 +15,11 @@ internal class ObjectLocationProvider : IObjectLocationProvider /// /// Since we want to scan objects while reading the cross reference table we lazily load it when it's ready. /// - private readonly Func crossReferenceTable; + private readonly Func crossReferenceTable; private readonly IInputBytes bytes; - private IReadOnlyDictionary bruteForcedOffsets; + private IReadOnlyDictionary? bruteForcedOffsets; /// /// Indicates whether we now have a cross reference table. @@ -27,7 +28,7 @@ internal class ObjectLocationProvider : IObjectLocationProvider private readonly Dictionary offsets = new Dictionary(); - public ObjectLocationProvider(Func crossReferenceTable, IInputBytes bytes) + public ObjectLocationProvider(Func crossReferenceTable, IInputBytes bytes) { this.crossReferenceTable = crossReferenceTable; this.bytes = bytes; @@ -68,7 +69,7 @@ public void UpdateOffset(IndirectReference reference, long offset) offsets[reference] = offset; } - public bool TryGetCached(IndirectReference reference, out ObjectToken objectToken) + public bool TryGetCached(IndirectReference reference, [NotNullWhen(true)] out ObjectToken? objectToken) { return cache.TryGetValue(reference, out objectToken); } diff --git a/src/UglyToad.PdfPig/Tokenization/Scanner/PdfTokenScanner.cs b/src/UglyToad.PdfPig/Tokenization/Scanner/PdfTokenScanner.cs index 7d4b422ec..899e33527 100644 --- a/src/UglyToad.PdfPig/Tokenization/Scanner/PdfTokenScanner.cs +++ b/src/UglyToad.PdfPig/Tokenization/Scanner/PdfTokenScanner.cs @@ -3,13 +3,14 @@ using System; using System.Collections.Generic; using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; + using System.Linq; using System.Text.RegularExpressions; using Core; using Encryption; using Filters; - using System.Linq; using Tokens; internal class PdfTokenScanner : IPdfTokenScanner @@ -41,7 +42,7 @@ internal class PdfTokenScanner : IPdfTokenScanner private readonly long[] previousTokenPositions = new long[3]; private readonly IToken[] previousTokens = new IToken[3]; - public IToken CurrentToken { get; private set; } + public IToken? CurrentToken { get; private set; } private IndirectReference? callingObject; @@ -49,8 +50,12 @@ internal class PdfTokenScanner : IPdfTokenScanner public long Length => coreTokenScanner.Length; - public PdfTokenScanner(IInputBytes inputBytes, IObjectLocationProvider objectLocationProvider, ILookupFilterProvider filterProvider, - IEncryptionHandler encryptionHandler, ParsingOptions parsingOptions) + public PdfTokenScanner( + IInputBytes inputBytes, + IObjectLocationProvider objectLocationProvider, + ILookupFilterProvider filterProvider, + IEncryptionHandler encryptionHandler, + ParsingOptions parsingOptions) { this.inputBytes = inputBytes; this.objectLocationProvider = objectLocationProvider; @@ -257,14 +262,14 @@ public bool MoveNext() return true; } - private bool TryReadStream(long startStreamTokenOffset, bool getLength, out StreamToken stream) + private bool TryReadStream(long startStreamTokenOffset, bool getLength, [NotNullWhen(true)] out StreamToken? stream) { stream = null; DictionaryToken streamDictionaryToken = GetStreamDictionary(); // Get the expected length from the stream dictionary if present. - long? length = getLength ? GetStreamLength(streamDictionaryToken) : default(long?); + long? length = getLength ? GetStreamLength(streamDictionaryToken) : default; if (!getLength && streamDictionaryToken.TryGet(NameToken.Length, out NumericToken inlineLengthToken)) { @@ -473,7 +478,7 @@ private bool TryReadStream(long startStreamTokenOffset, bool getLength, out Stre return true; } - private static bool TryReadUsingLength(IInputBytes inputBytes, long? length, long startDataOffset, out byte[] data) + private static bool TryReadUsingLength(IInputBytes inputBytes, long? length, long startDataOffset, [NotNullWhen(true)] out byte[]? data) { data = null; @@ -610,7 +615,7 @@ private DictionaryToken GetStreamDictionary() // Keep a copy of the read tokens here since this list must be empty prior to move next. var oldData = new List(readTokens); readTokens.Clear(); - if (MoveNext() && ((ObjectToken)CurrentToken).Data is NumericToken lengthToken) + if (MoveNext() && ((ObjectToken)CurrentToken!).Data is NumericToken lengthToken) { length = lengthToken.Long; } @@ -684,6 +689,8 @@ public void DeregisterCustomTokenizer(ITokenizer tokenizer) coreTokenScanner.DeregisterCustomTokenizer(tokenizer); } +#nullable disable + public ObjectToken Get(IndirectReference reference) { if (isDisposed) @@ -726,7 +733,7 @@ public ObjectToken Get(IndirectReference reference) return BruteForceFileToFindReference(reference); } - var found = (ObjectToken)CurrentToken; + var found = (ObjectToken)CurrentToken!; if (found.Number.Equals(reference)) { @@ -736,6 +743,8 @@ public ObjectToken Get(IndirectReference reference) return BruteForceFileToFindReference(reference); } +#nullable enable + public void ReplaceToken(IndirectReference reference, IToken token) { // Using 0 position as it isn't written to stream and this value doesn't @@ -754,7 +763,7 @@ private ObjectToken BruteForceFileToFindReference(IndirectReference reference) while (MoveNext()) { - objectLocationProvider.Cache((ObjectToken)CurrentToken, true); + objectLocationProvider.Cache((ObjectToken)CurrentToken!, true); } if (!objectLocationProvider.TryGetCached(reference, out var objectToken)) @@ -779,7 +788,7 @@ private ObjectToken GetObjectFromStream(IndirectReference reference, long offset if (!(streamObject.Data is StreamToken stream)) { throw new PdfDocumentFormatException("Requested a stream object by reference but the requested stream object " + - $"was not a stream: {reference}, {streamObject.Data}."); + $"was not a stream: {reference}, {streamObject?.Data}."); } var objects = ParseObjectStream(stream, offset); diff --git a/src/UglyToad.PdfPig/UglyToad.PdfPig.csproj b/src/UglyToad.PdfPig/UglyToad.PdfPig.csproj index f784e3447..e8e06de50 100644 --- a/src/UglyToad.PdfPig/UglyToad.PdfPig.csproj +++ b/src/UglyToad.PdfPig/UglyToad.PdfPig.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;net462;net471;net6.0;net8.0 12 @@ -7,7 +7,7 @@ true true ..\pdfpig.snk - annotations + enable true diff --git a/src/UglyToad.PdfPig/Util/Annotations.cs b/src/UglyToad.PdfPig/Util/Annotations.cs deleted file mode 100644 index 6b0c8d334..000000000 --- a/src/UglyToad.PdfPig/Util/Annotations.cs +++ /dev/null @@ -1,1067 +0,0 @@ -namespace UglyToad.PdfPig.Util -{ - /* MIT License - -Copyright (c) 2016 JetBrains http://www.jetbrains.com - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. */ - using System; - -#pragma warning disable 1591 - // ReSharper disable UnusedMember.Global - // ReSharper disable MemberCanBePrivate.Global - // ReSharper disable UnusedAutoPropertyAccessor.Global - // ReSharper disable IntroduceOptionalParameters.Global - // ReSharper disable MemberCanBeProtected.Global - // ReSharper disable InconsistentNaming - - namespace JetBrains.Annotations - { - /// - /// Indicates that the value of the marked element could be null sometimes, - /// so the check for null is necessary before its usage. - /// - /// - /// [CanBeNull] object Test() => null; - /// - /// void UseTest() { - /// var p = Test(); - /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException' - /// } - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] - internal sealed class CanBeNullAttribute : Attribute { } - - /// - /// Indicates that the value of the marked element could never be null. - /// - /// - /// [NotNull] object Foo() { - /// return null; // Warning: Possible 'null' assignment - /// } - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] - internal sealed class NotNullAttribute : Attribute { } - - /// - /// Can be appplied to symbols of types derived from IEnumerable as well as to symbols of Task - /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property - /// or of the Lazy.Value property can never be null. - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field)] - internal sealed class ItemNotNullAttribute : Attribute { } - - /// - /// Can be appplied to symbols of types derived from IEnumerable as well as to symbols of Task - /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property - /// or of the Lazy.Value property can be null. - /// - [AttributeUsage( - AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | - AttributeTargets.Delegate | AttributeTargets.Field)] - internal sealed class ItemCanBeNullAttribute : Attribute { } - - /// - /// Indicates that the marked method builds string by format pattern and (optional) arguments. - /// Parameter, which contains format string, should be given in constructor. The format string - /// should be in -like form. - /// - /// - /// [StringFormatMethod("message")] - /// void ShowError(string message, params object[] args) { /* do something */ } - /// - /// void Foo() { - /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string - /// } - /// - [AttributeUsage( - AttributeTargets.Constructor | AttributeTargets.Method | - AttributeTargets.Property | AttributeTargets.Delegate)] - internal sealed class StringFormatMethodAttribute : Attribute - { - /// - /// Specifies which parameter of an annotated method should be treated as format-string - /// - public StringFormatMethodAttribute([NotNull] string formatParameterName) - { - FormatParameterName = formatParameterName; - } - - [NotNull] public string FormatParameterName { get; private set; } - } - - /// - /// For a parameter that is expected to be one of the limited set of values. - /// Specify fields of which type should be used as values for this parameter. - /// - [AttributeUsage( - AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field, - AllowMultiple = true)] - internal sealed class ValueProviderAttribute : Attribute - { - public ValueProviderAttribute([NotNull] string name) - { - Name = name; - } - - [NotNull] public string Name { get; private set; } - } - - /// - /// Indicates that the function argument should be string literal and match one - /// of the parameters of the caller function. For example, ReSharper annotates - /// the parameter of . - /// - /// - /// void Foo(string param) { - /// if (param is null) - /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol - /// } - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class InvokerParameterNameAttribute : Attribute { } - - /// - /// Indicates that the method is contained in a type that implements - /// System.ComponentModel.INotifyPropertyChanged interface and this method - /// is used to notify that some property value changed. - /// - /// - /// The method should be non-static and conform to one of the supported signatures: - /// - /// NotifyChanged(string) - /// NotifyChanged(params string[]) - /// NotifyChanged{T}(Expression{Func{T}}) - /// NotifyChanged{T,U}(Expression{Func{T,U}}) - /// SetProperty{T}(ref T, T, string) - /// - /// - /// - /// public class Foo : INotifyPropertyChanged { - /// public event PropertyChangedEventHandler PropertyChanged; - /// - /// [NotifyPropertyChangedInvocator] - /// protected virtual void NotifyChanged(string propertyName) { ... } - /// - /// string _name; - /// - /// public string Name { - /// get { return _name; } - /// set { _name = value; NotifyChanged("LastName"); /* Warning */ } - /// } - /// } - /// - /// Examples of generated notifications: - /// - /// NotifyChanged("Property") - /// NotifyChanged(() => Property) - /// NotifyChanged((VM x) => x.Property) - /// SetProperty(ref myField, value, "Property") - /// - /// - [AttributeUsage(AttributeTargets.Method)] - internal sealed class NotifyPropertyChangedInvocatorAttribute : Attribute - { - public NotifyPropertyChangedInvocatorAttribute() { } - public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName) - { - ParameterName = parameterName; - } - - [CanBeNull] public string ParameterName { get; private set; } - } - - /// - /// Describes dependency between method input and output. - /// - /// - ///

Function Definition Table syntax:

- /// - /// FDT ::= FDTRow [;FDTRow]* - /// FDTRow ::= Input => Output | Output <= Input - /// Input ::= ParameterName: Value [, Input]* - /// Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value} - /// Value ::= true | false | null | notnull | canbenull - /// - /// If method has single input parameter, it's name could be omitted.
- /// Using halt (or void/nothing, which is the same) for method output - /// means that the methos doesn't return normally (throws or terminates the process).
- /// Value canbenull is only applicable for output parameters.
- /// You can use multiple [ContractAnnotation] for each FDT row, or use single attribute - /// with rows separated by semicolon. There is no notion of order rows, all rows are checked - /// for applicability and applied per each program state tracked by R# analysis.
- ///
- /// - /// - /// [ContractAnnotation("=> halt")] - /// public void TerminationMethod() - /// - /// - /// [ContractAnnotation("halt <= condition: false")] - /// public void Assert(bool condition, string text) // regular assertion method - /// - /// - /// [ContractAnnotation("s:null => true")] - /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty() - /// - /// - /// // A method that returns null if the parameter is null, - /// // and not null if the parameter is not null - /// [ContractAnnotation("null => null; notnull => notnull")] - /// public object Transform(object data) - /// - /// - /// [ContractAnnotation("=> true, result: notnull; => false, result: null")] - /// public bool TryParse(string s, out Person result) - /// - /// - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - internal sealed class ContractAnnotationAttribute : Attribute - { - public ContractAnnotationAttribute([NotNull] string contract) - : this(contract, false) { } - - public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates) - { - Contract = contract; - ForceFullStates = forceFullStates; - } - - [NotNull] public string Contract { get; private set; } - - public bool ForceFullStates { get; private set; } - } - - /// - /// Indicates that marked element should be localized or not. - /// - /// - /// [LocalizationRequiredAttribute(true)] - /// class Foo { - /// string str = "my string"; // Warning: Localizable string - /// } - /// - [AttributeUsage(AttributeTargets.All)] - internal sealed class LocalizationRequiredAttribute : Attribute - { - public LocalizationRequiredAttribute() : this(true) { } - - public LocalizationRequiredAttribute(bool required) - { - Required = required; - } - - public bool Required { get; private set; } - } - - /// - /// Indicates that the value of the marked type (or its derivatives) - /// cannot be compared using '==' or '!=' operators and Equals() - /// should be used instead. However, using '==' or '!=' for comparison - /// with null is always permitted. - /// - /// - /// [CannotApplyEqualityOperator] - /// class NoEquality { } - /// - /// class UsesNoEquality { - /// void Test() { - /// var ca1 = new NoEquality(); - /// var ca2 = new NoEquality(); - /// if (ca1 != null) { // OK - /// bool condition = ca1 == ca2; // Warning - /// } - /// } - /// } - /// - [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] - internal sealed class CannotApplyEqualityOperatorAttribute : Attribute { } - - /// - /// When applied to a target attribute, specifies a requirement for any type marked - /// with the target attribute to implement or inherit specific type or types. - /// - /// - /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement - /// class ComponentAttribute : Attribute { } - /// - /// [Component] // ComponentAttribute requires implementing IComponent interface - /// class MyComponent : IComponent { } - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - [BaseTypeRequired(typeof(Attribute))] - internal sealed class BaseTypeRequiredAttribute : Attribute - { - public BaseTypeRequiredAttribute([NotNull] Type baseType) - { - BaseType = baseType; - } - - [NotNull] public Type BaseType { get; private set; } - } - - /// - /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), - /// so this symbol will not be marked as unused (as well as by other usage inspections). - /// - [AttributeUsage(AttributeTargets.All)] - internal sealed class UsedImplicitlyAttribute : Attribute - { - public UsedImplicitlyAttribute() - : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } - - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) - : this(useKindFlags, ImplicitUseTargetFlags.Default) { } - - public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) - : this(ImplicitUseKindFlags.Default, targetFlags) { } - - public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; - } - - public ImplicitUseKindFlags UseKindFlags { get; private set; } - - public ImplicitUseTargetFlags TargetFlags { get; private set; } - } - - /// - /// Should be used on attributes and causes ReSharper to not mark symbols marked with such attributes - /// as unused (as well as by other usage inspections) - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter)] - internal sealed class MeansImplicitUseAttribute : Attribute - { - public MeansImplicitUseAttribute() - : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } - - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) - : this(useKindFlags, ImplicitUseTargetFlags.Default) { } - - public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) - : this(ImplicitUseKindFlags.Default, targetFlags) { } - - public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; - } - - [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; private set; } - - [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; private set; } - } - - [Flags] - internal enum ImplicitUseKindFlags - { - Default = Access | Assign | InstantiatedWithFixedConstructorSignature, - /// Only entity marked with attribute considered used. - Access = 1, - /// Indicates implicit assignment to a member. - Assign = 2, - /// - /// Indicates implicit instantiation of a type with fixed constructor signature. - /// That means any unused constructor parameters won't be reported as such. - /// - InstantiatedWithFixedConstructorSignature = 4, - /// Indicates implicit instantiation of a type. - InstantiatedNoFixedConstructorSignature = 8, - } - - /// - /// Specify what is considered used implicitly when marked - /// with or . - /// - [Flags] - internal enum ImplicitUseTargetFlags - { - Default = Itself, - Itself = 1, - /// Members of entity marked with attribute are considered used. - Members = 2, - /// Entity marked with attribute and all its members considered used. - WithMembers = Itself | Members - } - - /// - /// This attribute is intended to mark publicly available API - /// which should not be removed and so is treated as used. - /// - [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] - internal sealed class PublicAPIAttribute : Attribute - { - public PublicAPIAttribute() { } - - public PublicAPIAttribute([NotNull] string comment) - { - Comment = comment; - } - - [CanBeNull] public string Comment { get; private set; } - } - - /// - /// Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. - /// If the parameter is a delegate, indicates that delegate is executed while the method is executed. - /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed. - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class InstantHandleAttribute : Attribute { } - - /// - /// Indicates that a method does not make any observable state changes. - /// The same as System.Diagnostics.Contracts.PureAttribute. - /// - /// - /// [Pure] int Multiply(int x, int y) => x * y; - /// - /// void M() { - /// Multiply(123, 42); // Waring: Return value of pure method is not used - /// } - /// - [AttributeUsage(AttributeTargets.Method)] - internal sealed class PureAttribute : Attribute { } - - /// - /// Indicates that the return value of method invocation must be used. - /// - [AttributeUsage(AttributeTargets.Method)] - internal sealed class MustUseReturnValueAttribute : Attribute - { - public MustUseReturnValueAttribute() { } - - public MustUseReturnValueAttribute([NotNull] string justification) - { - Justification = justification; - } - - [CanBeNull] public string Justification { get; private set; } - } - - /// - /// Indicates the type member or parameter of some type, that should be used instead of all other ways - /// to get the value that type. This annotation is useful when you have some "context" value evaluated - /// and stored somewhere, meaning that all other ways to get this value must be consolidated with existing one. - /// - /// - /// class Foo { - /// [ProvidesContext] IBarService _barService = ...; - /// - /// void ProcessNode(INode node) { - /// DoSomething(node, node.GetGlobalServices().Bar); - /// // ^ Warning: use value of '_barService' field - /// } - /// } - /// - [AttributeUsage( - AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method | - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.GenericParameter)] - internal sealed class ProvidesContextAttribute : Attribute { } - - /// - /// Indicates that a parameter is a path to a file or a folder within a web project. - /// Path can be relative or absolute, starting from web root (~). - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class PathReferenceAttribute : Attribute - { - public PathReferenceAttribute() { } - - public PathReferenceAttribute([NotNull, PathReference] string basePath) - { - BasePath = basePath; - } - - [CanBeNull] public string BasePath { get; private set; } - } - - /// - /// An extension method marked with this attribute is processed by ReSharper code completion - /// as a 'Source Template'. When extension method is completed over some expression, it's source code - /// is automatically expanded like a template at call site. - /// - /// - /// Template method body can contain valid source code and/or special comments starting with '$'. - /// Text inside these comments is added as source code when the template is applied. Template parameters - /// can be used either as additional method parameters or as identifiers wrapped in two '$' signs. - /// Use the attribute to specify macros for parameters. - /// - /// - /// In this example, the 'forEach' method is a source template available over all values - /// of enumerable types, producing ordinary C# 'foreach' statement and placing caret inside block: - /// - /// [SourceTemplate] - /// public static void forEach<T>(this IEnumerable<T> xs) { - /// foreach (var x in xs) { - /// //$ $END$ - /// } - /// } - /// - /// - [AttributeUsage(AttributeTargets.Method)] - internal sealed class SourceTemplateAttribute : Attribute { } - - /// - /// Allows specifying a macro for a parameter of a source template. - /// - /// - /// You can apply the attribute on the whole method or on any of its additional parameters. The macro expression - /// is defined in the property. When applied on a method, the target - /// template parameter is defined in the property. To apply the macro silently - /// for the parameter, set the property value = -1. - /// - /// - /// Applying the attribute on a source template method: - /// - /// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")] - /// public static void forEach<T>(this IEnumerable<T> collection) { - /// foreach (var item in collection) { - /// //$ $END$ - /// } - /// } - /// - /// Applying the attribute on a template method parameter: - /// - /// [SourceTemplate] - /// public static void something(this Entity x, [Macro(Expression = "guid()", Editable = -1)] string newguid) { - /// /*$ var $x$Id = "$newguid$" + x.ToString(); - /// x.DoSomething($x$Id); */ - /// } - /// - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)] - internal sealed class MacroAttribute : Attribute - { - /// - /// Allows specifying a macro that will be executed for a source template - /// parameter when the template is expanded. - /// - [CanBeNull] public string Expression { get; set; } - - /// - /// Allows specifying which occurrence of the target parameter becomes editable when the template is deployed. - /// - /// - /// If the target parameter is used several times in the template, only one occurrence becomes editable; - /// other occurrences are changed synchronously. To specify the zero-based index of the editable occurrence, - /// use values >= 0. To make the parameter non-editable when the template is expanded, use -1. - /// > - public int Editable { get; set; } - - /// - /// Identifies the target parameter of a source template if the - /// is applied on a template method. - /// - [CanBeNull] public string Target { get; set; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - internal sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute - { - public AspMvcAreaMasterLocationFormatAttribute([NotNull] string format) - { - Format = format; - } - - [NotNull] public string Format { get; private set; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - internal sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute - { - public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] string format) - { - Format = format; - } - - [NotNull] public string Format { get; private set; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - internal sealed class AspMvcAreaViewLocationFormatAttribute : Attribute - { - public AspMvcAreaViewLocationFormatAttribute([NotNull] string format) - { - Format = format; - } - - [NotNull] public string Format { get; private set; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - internal sealed class AspMvcMasterLocationFormatAttribute : Attribute - { - public AspMvcMasterLocationFormatAttribute([NotNull] string format) - { - Format = format; - } - - [NotNull] public string Format { get; private set; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - internal sealed class AspMvcPartialViewLocationFormatAttribute : Attribute - { - public AspMvcPartialViewLocationFormatAttribute([NotNull] string format) - { - Format = format; - } - - [NotNull] public string Format { get; private set; } - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] - internal sealed class AspMvcViewLocationFormatAttribute : Attribute - { - public AspMvcViewLocationFormatAttribute([NotNull] string format) - { - Format = format; - } - - [NotNull] public string Format { get; private set; } - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC action. If applied to a method, the MVC action name is calculated - /// implicitly from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] - internal sealed class AspMvcActionAttribute : Attribute - { - public AspMvcActionAttribute() { } - - public AspMvcActionAttribute([NotNull] string anonymousProperty) - { - AnonymousProperty = anonymousProperty; - } - - [CanBeNull] public string AnonymousProperty { get; private set; } - } - - /// - /// ASP.NET MVC attribute. Indicates that a parameter is an MVC area. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class AspMvcAreaAttribute : Attribute - { - public AspMvcAreaAttribute() { } - - public AspMvcAreaAttribute([NotNull] string anonymousProperty) - { - AnonymousProperty = anonymousProperty; - } - - [CanBeNull] public string AnonymousProperty { get; private set; } - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is - /// an MVC controller. If applied to a method, the MVC controller name is calculated - /// implicitly from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] - internal sealed class AspMvcControllerAttribute : Attribute - { - public AspMvcControllerAttribute() { } - - public AspMvcControllerAttribute([NotNull] string anonymousProperty) - { - AnonymousProperty = anonymousProperty; - } - - [CanBeNull] public string AnonymousProperty { get; private set; } - } - - /// - /// ASP.NET MVC attribute. Indicates that a parameter is an MVC Master. Use this attribute - /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, String). - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class AspMvcMasterAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that a parameter is an MVC model type. Use this attribute - /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, Object). - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class AspMvcModelTypeAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC - /// partial view. If applied to a method, the MVC partial view name is calculated implicitly - /// from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] - internal sealed class AspMvcPartialViewAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] - internal sealed class AspMvcSuppressViewErrorAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class AspMvcDisplayTemplateAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that a parameter is an MVC editor template. - /// Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String). - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class AspMvcEditorTemplateAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. Indicates that a parameter is an MVC template. - /// Use this attribute for custom wrappers similar to - /// System.ComponentModel.DataAnnotations.UIHintAttribute(System.String). - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class AspMvcTemplateAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component. If applied to a method, the MVC view name is calculated implicitly - /// from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Controller.View(Object). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] - internal sealed class AspMvcViewAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component name. - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class AspMvcViewComponentAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC view component view. If applied to a method, the MVC view component view name is default. - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] - internal sealed class AspMvcViewComponentViewAttribute : Attribute { } - - /// - /// ASP.NET MVC attribute. When applied to a parameter of an attribute, - /// indicates that this parameter is an MVC action name. - /// - /// - /// [ActionName("Foo")] - /// public ActionResult Login(string returnUrl) { - /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK - /// return RedirectToAction("Bar"); // Error: Cannot resolve action - /// } - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] - internal sealed class AspMvcActionSelectorAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] - internal sealed class HtmlElementAttributesAttribute : Attribute - { - public HtmlElementAttributesAttribute() { } - - public HtmlElementAttributesAttribute([NotNull] string name) - { - Name = name; - } - - [CanBeNull] public string Name { get; private set; } - } - - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] - internal sealed class HtmlAttributeValueAttribute : Attribute - { - public HtmlAttributeValueAttribute([NotNull] string name) - { - Name = name; - } - - [NotNull] public string Name { get; private set; } - } - - /// - /// Razor attribute. Indicates that a parameter or a method is a Razor section. - /// Use this attribute for custom wrappers similar to - /// System.Web.WebPages.WebPageBase.RenderSection(String). - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] - internal sealed class RazorSectionAttribute : Attribute { } - - /// - /// Indicates how method, constructor invocation or property access - /// over collection type affects content of the collection. - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)] - internal sealed class CollectionAccessAttribute : Attribute - { - public CollectionAccessAttribute(CollectionAccessType collectionAccessType) - { - CollectionAccessType = collectionAccessType; - } - - public CollectionAccessType CollectionAccessType { get; private set; } - } - - [Flags] - internal enum CollectionAccessType - { - /// Method does not use or modify content of the collection. - None = 0, - /// Method only reads content of the collection but does not modify it. - Read = 1, - /// Method can change content of the collection but does not add new elements. - ModifyExistingContent = 2, - /// Method can add new elements to the collection. - UpdatedContent = ModifyExistingContent | 4 - } - - /// - /// Indicates that the marked method is assertion method, i.e. it halts control flow if - /// one of the conditions is satisfied. To set the condition, mark one of the parameters with - /// attribute. - /// - [AttributeUsage(AttributeTargets.Method)] - internal sealed class AssertionMethodAttribute : Attribute { } - - /// - /// Indicates the condition parameter of the assertion method. The method itself should be - /// marked by attribute. The mandatory argument of - /// the attribute is the assertion type. - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class AssertionConditionAttribute : Attribute - { - public AssertionConditionAttribute(AssertionConditionType conditionType) - { - ConditionType = conditionType; - } - - public AssertionConditionType ConditionType { get; private set; } - } - - /// - /// Specifies assertion type. If the assertion method argument satisfies the condition, - /// then the execution continues. Otherwise, execution is assumed to be halted. - /// - internal enum AssertionConditionType - { - /// Marked parameter should be evaluated to true. - IS_TRUE = 0, - /// Marked parameter should be evaluated to false. - IS_FALSE = 1, - /// Marked parameter should be evaluated to null value. - IS_NULL = 2, - /// Marked parameter should be evaluated to not null value. - IS_NOT_NULL = 3, - } - - /// - /// Indicates that the marked method unconditionally terminates control flow execution. - /// For example, it could unconditionally throw exception. - /// - [Obsolete("Use [ContractAnnotation('=> halt')] instead")] - [AttributeUsage(AttributeTargets.Method)] - internal sealed class TerminatesProgramAttribute : Attribute { } - - /// - /// Indicates that method is pure LINQ method, with postponed enumeration (like Enumerable.Select, - /// .Where). This annotation allows inference of [InstantHandle] annotation for parameters - /// of delegate type by analyzing LINQ method chains. - /// - [AttributeUsage(AttributeTargets.Method)] - internal sealed class LinqTunnelAttribute : Attribute { } - - /// - /// Indicates that IEnumerable, passed as parameter, is not enumerated. - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class NoEnumerationAttribute : Attribute { } - - /// - /// Indicates that parameter is regular expression pattern. - /// - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class RegexPatternAttribute : Attribute { } - - /// - /// Prevents the Member Reordering feature from tossing members of the marked class. - /// - /// - /// The attribute must be mentioned in your member reordering patterns - /// - [AttributeUsage( - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum)] - internal sealed class NoReorderAttribute : Attribute { } - - /// - /// XAML attribute. Indicates the type that has ItemsSource property and should be treated - /// as ItemsControl-derived type, to enable inner items DataContext type resolve. - /// - [AttributeUsage(AttributeTargets.Class)] - internal sealed class XamlItemsControlAttribute : Attribute { } - - /// - /// XAML attribute. Indicates the property of some BindingBase-derived type, that - /// is used to bind some item of ItemsControl-derived type. This annotation will - /// enable the DataContext type resolve for XAML bindings for such properties. - /// - /// - /// Property should have the tree ancestor of the ItemsControl type or - /// marked with the attribute. - /// - [AttributeUsage(AttributeTargets.Property)] - internal sealed class XamlItemBindingOfItemsControlAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - internal sealed class AspChildControlTypeAttribute : Attribute - { - public AspChildControlTypeAttribute([NotNull] string tagName, [NotNull] Type controlType) - { - TagName = tagName; - ControlType = controlType; - } - - [NotNull] public string TagName { get; private set; } - - [NotNull] public Type ControlType { get; private set; } - } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] - internal sealed class AspDataFieldAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] - internal sealed class AspDataFieldsAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Property)] - internal sealed class AspMethodPropertyAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - internal sealed class AspRequiredAttributeAttribute : Attribute - { - public AspRequiredAttributeAttribute([NotNull] string attribute) - { - Attribute = attribute; - } - - [NotNull] public string Attribute { get; private set; } - } - - [AttributeUsage(AttributeTargets.Property)] - internal sealed class AspTypePropertyAttribute : Attribute - { - public bool CreateConstructorReferences { get; private set; } - - public AspTypePropertyAttribute(bool createConstructorReferences) - { - CreateConstructorReferences = createConstructorReferences; - } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - internal sealed class RazorImportNamespaceAttribute : Attribute - { - public RazorImportNamespaceAttribute([NotNull] string name) - { - Name = name; - } - - [NotNull] public string Name { get; private set; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - internal sealed class RazorInjectionAttribute : Attribute - { - public RazorInjectionAttribute([NotNull] string type, [NotNull] string fieldName) - { - Type = type; - FieldName = fieldName; - } - - [NotNull] public string Type { get; private set; } - - [NotNull] public string FieldName { get; private set; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - internal sealed class RazorDirectiveAttribute : Attribute - { - public RazorDirectiveAttribute([NotNull] string directive) - { - Directive = directive; - } - - [NotNull] public string Directive { get; private set; } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - internal sealed class RazorPageBaseTypeAttribute : Attribute - { - public RazorPageBaseTypeAttribute([NotNull] string baseType) - { - BaseType = baseType; - } - public RazorPageBaseTypeAttribute([NotNull] string baseType, string pageName) - { - BaseType = baseType; - PageName = pageName; - } - - [NotNull] public string BaseType { get; private set; } - [CanBeNull] public string PageName { get; private set; } - } - - [AttributeUsage(AttributeTargets.Method)] - internal sealed class RazorHelperCommonAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Property)] - internal sealed class RazorLayoutAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Method)] - internal sealed class RazorWriteLiteralMethodAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Method)] - internal sealed class RazorWriteMethodAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Parameter)] - internal sealed class RazorWriteMethodParameterAttribute : Attribute { } - } -} diff --git a/src/UglyToad.PdfPig/Util/ColorSpaceDetailsParser.cs b/src/UglyToad.PdfPig/Util/ColorSpaceDetailsParser.cs index ce5ff245e..e05016e0b 100644 --- a/src/UglyToad.PdfPig/Util/ColorSpaceDetailsParser.cs +++ b/src/UglyToad.PdfPig/Util/ColorSpaceDetailsParser.cs @@ -1,12 +1,12 @@ namespace UglyToad.PdfPig.Util -{ +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Content; - using Core; using Filters; using Graphics.Colors; using Parser.Parts; - using System; - using System.Collections.Generic; using System.Linq; using Tokenization.Scanner; using Tokens; @@ -94,8 +94,8 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, var second = colorSpaceArray[1]; // WhitePoint is required - if (!DirectObjectFinder.TryGet(second, scanner, out DictionaryToken dictionaryToken) || - !dictionaryToken.TryGet(NameToken.WhitePoint, scanner, out ArrayToken whitePointToken)) + if (!DirectObjectFinder.TryGet(second, scanner, out DictionaryToken? dictionaryToken) || + !dictionaryToken.TryGet(NameToken.WhitePoint, scanner, out ArrayToken? whitePointToken)) { return UnsupportedColorSpaceDetails.Instance; } @@ -103,15 +103,15 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, var whitePoint = whitePointToken.Data.OfType().Select(x => x.Double).ToArray(); // BlackPoint is optional - IReadOnlyList blackPoint = null; - if (dictionaryToken.TryGet(NameToken.BlackPoint, scanner, out ArrayToken blackPointToken)) + IReadOnlyList? blackPoint = null; + if (dictionaryToken.TryGet(NameToken.BlackPoint, scanner, out ArrayToken? blackPointToken)) { blackPoint = blackPointToken.Data.OfType().Select(x => x.Double).ToArray(); } // Gamma is optional double? gamma = null; - if (dictionaryToken.TryGet(NameToken.Gamma, scanner, out NumericToken gammaToken)) + if (dictionaryToken.TryGet(NameToken.Gamma, scanner, out NumericToken? gammaToken)) { gamma = gammaToken.Double; } @@ -137,8 +137,8 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, var second = colorSpaceArray[1]; // WhitePoint is required - if (!DirectObjectFinder.TryGet(second, scanner, out DictionaryToken dictionaryToken) || - !dictionaryToken.TryGet(NameToken.WhitePoint, scanner, out ArrayToken whitePointToken)) + if (!DirectObjectFinder.TryGet(second, scanner, out DictionaryToken? dictionaryToken) || + !dictionaryToken.TryGet(NameToken.WhitePoint, scanner, out ArrayToken? whitePointToken)) { return UnsupportedColorSpaceDetails.Instance; } @@ -146,22 +146,22 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, var whitePoint = whitePointToken.Data.OfType().Select(x => x.Double).ToArray(); // BlackPoint is optional - IReadOnlyList blackPoint = null; - if (dictionaryToken.TryGet(NameToken.BlackPoint, scanner, out ArrayToken blackPointToken)) + IReadOnlyList? blackPoint = null; + if (dictionaryToken.TryGet(NameToken.BlackPoint, scanner, out ArrayToken? blackPointToken)) { blackPoint = blackPointToken.Data.OfType().Select(x => x.Double).ToArray(); } // Gamma is optional - IReadOnlyList gamma = null; - if (dictionaryToken.TryGet(NameToken.Gamma, scanner, out ArrayToken gammaToken)) + IReadOnlyList? gamma = null; + if (dictionaryToken.TryGet(NameToken.Gamma, scanner, out ArrayToken? gammaToken)) { gamma = gammaToken.Data.OfType().Select(x => x.Double).ToArray(); } // Matrix is optional - IReadOnlyList matrix = null; - if (dictionaryToken.TryGet(NameToken.Matrix, scanner, out ArrayToken matrixToken)) + IReadOnlyList? matrix = null; + if (dictionaryToken.TryGet(NameToken.Matrix, scanner, out ArrayToken? matrixToken)) { matrix = matrixToken.Data.OfType().Select(x => x.Double).ToArray(); } @@ -187,8 +187,8 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, var second = colorSpaceArray[1]; // WhitePoint is required - if (!DirectObjectFinder.TryGet(second, scanner, out DictionaryToken dictionaryToken) || - !dictionaryToken.TryGet(NameToken.WhitePoint, scanner, out ArrayToken whitePointToken)) + if (!DirectObjectFinder.TryGet(second, scanner, out DictionaryToken? dictionaryToken) || + !dictionaryToken.TryGet(NameToken.WhitePoint, scanner, out ArrayToken? whitePointToken)) { return UnsupportedColorSpaceDetails.Instance; } @@ -196,15 +196,15 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, var whitePoint = whitePointToken.Data.OfType().Select(x => x.Double).ToArray(); // BlackPoint is optional - IReadOnlyList blackPoint = null; - if (dictionaryToken.TryGet(NameToken.BlackPoint, scanner, out ArrayToken blackPointToken)) + IReadOnlyList? blackPoint = null; + if (dictionaryToken.TryGet(NameToken.BlackPoint, scanner, out ArrayToken? blackPointToken)) { blackPoint = blackPointToken.Data.OfType().Select(x => x.Double).ToArray(); } // Matrix is optional - IReadOnlyList matrix = null; - if (dictionaryToken.TryGet(NameToken.Matrix, scanner, out ArrayToken matrixToken)) + IReadOnlyList? matrix = null; + if (dictionaryToken.TryGet(NameToken.Matrix, scanner, out ArrayToken? matrixToken)) { matrix = matrixToken.Data.OfType().Select(x => x.Double).ToArray(); } @@ -230,14 +230,14 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, var second = colorSpaceArray[1]; // N is required - if (!DirectObjectFinder.TryGet(second, scanner, out StreamToken streamToken) || - !streamToken.StreamDictionary.TryGet(NameToken.N, scanner, out NumericToken numeric)) + if (!DirectObjectFinder.TryGet(second, scanner, out StreamToken? streamToken) || + !streamToken.StreamDictionary.TryGet(NameToken.N, scanner, out NumericToken? numeric)) { return UnsupportedColorSpaceDetails.Instance; } // Alternate is optional - ColorSpaceDetails alternateColorSpaceDetails = null; + ColorSpaceDetails? alternateColorSpaceDetails = null; if (streamToken.StreamDictionary.TryGet(NameToken.Alternate, out NameToken alternateColorSpaceNameToken) && ColorSpaceMapper.TryMap(alternateColorSpaceNameToken, resourceStore, out var alternateColorSpace)) { @@ -246,15 +246,15 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, } // Range is optional - IReadOnlyList range = null; - if (streamToken.StreamDictionary.TryGet(NameToken.Range, scanner, out ArrayToken arrayToken)) + IReadOnlyList? range = null; + if (streamToken.StreamDictionary.TryGet(NameToken.Range, scanner, out ArrayToken? arrayToken)) { range = arrayToken.Data.OfType().Select(x => x.Double).ToArray(); } // Metadata is optional - XmpMetadata metadata = null; - if (streamToken.StreamDictionary.TryGet(NameToken.Metadata, scanner, out StreamToken metadataStream)) + XmpMetadata? metadata = null; + if (streamToken.StreamDictionary.TryGet(NameToken.Metadata, scanner, out StreamToken? metadataStream)) { metadata = new XmpMetadata(metadataStream, filterProvider, scanner); } @@ -287,7 +287,7 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, ColorSpaceDetails baseDetails; - if (DirectObjectFinder.TryGet(second, scanner, out NameToken baseColorSpaceNameToken) + if (DirectObjectFinder.TryGet(second, scanner, out NameToken? baseColorSpaceNameToken) && ColorSpaceMapper.TryMap(baseColorSpaceNameToken, resourceStore, out var baseColorSpaceName)) { baseDetails = GetColorSpaceDetails( @@ -298,7 +298,7 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, filterProvider, true); } - else if (DirectObjectFinder.TryGet(second, scanner, out ArrayToken baseColorSpaceArrayToken) + else if (DirectObjectFinder.TryGet(second, scanner, out ArrayToken? baseColorSpaceArrayToken) && baseColorSpaceArrayToken.Length > 0 && baseColorSpaceArrayToken[0] is NameToken baseColorSpaceArrayNameToken && ColorSpaceMapper.TryMap(baseColorSpaceArrayNameToken, resourceStore, out var baseColorSpaceArrayColorSpace)) { @@ -328,7 +328,7 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, var third = colorSpaceArray[2]; - if (!DirectObjectFinder.TryGet(third, scanner, out NumericToken hiValNumericToken)) + if (!DirectObjectFinder.TryGet(third, scanner, out NumericToken? hiValNumericToken)) { return UnsupportedColorSpaceDetails.Instance; } @@ -339,15 +339,15 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, IReadOnlyList tableBytes; - if (DirectObjectFinder.TryGet(fourth, scanner, out HexToken tableHexToken)) + if (DirectObjectFinder.TryGet(fourth, scanner, out HexToken? tableHexToken)) { tableBytes = tableHexToken.Bytes; } - else if (DirectObjectFinder.TryGet(fourth, scanner, out StreamToken tableStreamToken)) + else if (DirectObjectFinder.TryGet(fourth, scanner, out StreamToken? tableStreamToken)) { tableBytes = tableStreamToken.Decode(filterProvider, scanner); } - else if (DirectObjectFinder.TryGet(fourth, scanner, out StringToken stringToken)) + else if (DirectObjectFinder.TryGet(fourth, scanner, out StringToken? stringToken)) { tableBytes = stringToken.GetBytes(); } @@ -375,14 +375,14 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, return UnsupportedColorSpaceDetails.Instance; } - if (!DirectObjectFinder.TryGet(colorSpaceArray[0], scanner, out NameToken patternColorSpaceNameToken) + if (!DirectObjectFinder.TryGet(colorSpaceArray[0], scanner, out NameToken? patternColorSpaceNameToken) || !patternColorSpaceNameToken.Equals(NameToken.Pattern)) { return UnsupportedColorSpaceDetails.Instance; } // Uncoloured Tiling Patterns - if (colorSpaceArray.Length > 1 && DirectObjectFinder.TryGet(colorSpaceArray[1], scanner, out NameToken underlyingCsNameToken) + if (colorSpaceArray.Length > 1 && DirectObjectFinder.TryGet(colorSpaceArray[1], scanner, out NameToken? underlyingCsNameToken) && ColorSpaceMapper.TryMap(underlyingCsNameToken, resourceStore, out var underlyingColorSpaceName)) { underlyingColourSpace = GetColorSpaceDetails( @@ -405,19 +405,19 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, return UnsupportedColorSpaceDetails.Instance; } - if (!DirectObjectFinder.TryGet(colorSpaceArray[0], scanner, out NameToken separationColorSpaceNameToken) + if (!DirectObjectFinder.TryGet(colorSpaceArray[0], scanner, out NameToken? separationColorSpaceNameToken) || !separationColorSpaceNameToken.Equals(NameToken.Separation)) { return UnsupportedColorSpaceDetails.Instance; } - if (!DirectObjectFinder.TryGet(colorSpaceArray[1], scanner, out NameToken separationNameToken)) + if (!DirectObjectFinder.TryGet(colorSpaceArray[1], scanner, out NameToken? separationNameToken)) { return UnsupportedColorSpaceDetails.Instance; } ColorSpaceDetails alternateColorSpaceDetails; - if (DirectObjectFinder.TryGet(colorSpaceArray[2], scanner, out NameToken alternateNameToken) + if (DirectObjectFinder.TryGet(colorSpaceArray[2], scanner, out NameToken? alternateNameToken) && ColorSpaceMapper.TryMap(alternateNameToken, resourceStore, out var baseColorSpaceName)) { alternateColorSpaceDetails = GetColorSpaceDetails( @@ -428,7 +428,7 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, filterProvider, true); } - else if (DirectObjectFinder.TryGet(colorSpaceArray[2], scanner, out ArrayToken alternateArrayToken) + else if (DirectObjectFinder.TryGet(colorSpaceArray[2], scanner, out ArrayToken? alternateArrayToken) && alternateArrayToken.Length > 0 && alternateArrayToken[0] is NameToken alternateColorSpaceNameToken && ColorSpaceMapper.TryMap(alternateColorSpaceNameToken, resourceStore, out var alternateArrayColorSpace)) @@ -455,11 +455,11 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, PdfFunction function; var func = colorSpaceArray[3]; - if (DirectObjectFinder.TryGet(func, scanner, out DictionaryToken functionDictionary)) + if (DirectObjectFinder.TryGet(func, scanner, out DictionaryToken? functionDictionary)) { function = PdfFunctionParser.Create(functionDictionary, scanner, filterProvider); } - else if (DirectObjectFinder.TryGet(func, scanner, out StreamToken functionStream)) + else if (DirectObjectFinder.TryGet(func, scanner, out StreamToken? functionStream)) { function = PdfFunctionParser.Create(functionStream, scanner, filterProvider); } @@ -479,19 +479,19 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, return UnsupportedColorSpaceDetails.Instance; } - if (!DirectObjectFinder.TryGet(colorSpaceArray[0], scanner, out NameToken deviceNColorSpaceNameToken) + if (!DirectObjectFinder.TryGet(colorSpaceArray[0], scanner, out NameToken? deviceNColorSpaceNameToken) || !deviceNColorSpaceNameToken.Equals(NameToken.Devicen)) { return UnsupportedColorSpaceDetails.Instance; } - if (!DirectObjectFinder.TryGet(colorSpaceArray[1], scanner, out ArrayToken deviceNNamesToken)) + if (!DirectObjectFinder.TryGet(colorSpaceArray[1], scanner, out ArrayToken? deviceNNamesToken)) { return UnsupportedColorSpaceDetails.Instance; } ColorSpaceDetails alternateColorSpaceDetails; - if (DirectObjectFinder.TryGet(colorSpaceArray[2], scanner, out NameToken alternateNameToken) + if (DirectObjectFinder.TryGet(colorSpaceArray[2], scanner, out NameToken? alternateNameToken) && ColorSpaceMapper.TryMap(alternateNameToken, resourceStore, out var baseColorSpaceName)) { alternateColorSpaceDetails = GetColorSpaceDetails( @@ -502,7 +502,7 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, filterProvider, true); } - else if (DirectObjectFinder.TryGet(colorSpaceArray[2], scanner, out ArrayToken alternateArrayToken) + else if (DirectObjectFinder.TryGet(colorSpaceArray[2], scanner, out ArrayToken? alternateArrayToken) && alternateArrayToken.Length > 0 && alternateArrayToken[0] is NameToken alternateColorSpaceNameToken && ColorSpaceMapper.TryMap(alternateColorSpaceNameToken, resourceStore, out var alternateArrayColorSpace)) @@ -529,7 +529,7 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, var func = colorSpaceArray[3]; PdfFunction tintFunc = PdfFunctionParser.Create(func, scanner, filterProvider); - if (colorSpaceArray.Length > 4 && DirectObjectFinder.TryGet(colorSpaceArray[4], scanner, out DictionaryToken deviceNAttributesToken)) + if (colorSpaceArray.Length > 4 && DirectObjectFinder.TryGet(colorSpaceArray[4], scanner, out DictionaryToken? deviceNAttributesToken)) { // Optionnal @@ -541,21 +541,21 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, } // Colorants - dictionary - Required if Subtype is NChannel and the colour space includes spot colorants; otherwise optional - DictionaryToken colorants = null; + DictionaryToken? colorants = null; if (deviceNAttributesToken.ContainsKey(NameToken.Colorants)) { colorants = deviceNAttributesToken.Get(NameToken.Colorants, scanner); } // Process - dictionary - Required if Subtype is NChannel and the colour space includes components of a process colour space, otherwise optional; PDF 1.6 - DictionaryToken process = null; + DictionaryToken? process = null; if (deviceNAttributesToken.ContainsKey(NameToken.Process)) { process = deviceNAttributesToken.Get(NameToken.Process, scanner); } // MixingHints - dictionary - Optional - DictionaryToken mixingHints = null; + DictionaryToken? mixingHints = null; if (deviceNAttributesToken.ContainsKey(NameToken.MixingHints)) { mixingHints = deviceNAttributesToken.Get(NameToken.MixingHints, scanner); @@ -575,12 +575,12 @@ public static ColorSpaceDetails GetColorSpaceDetails(ColorSpace? colorSpace, private static bool TryGetColorSpaceArray(DictionaryToken imageDictionary, IResourceStore resourceStore, IPdfTokenScanner scanner, - out ArrayToken colorSpaceArray) + [NotNullWhen(true)] out ArrayToken? colorSpaceArray) { var colorSpace = imageDictionary.GetObjectOrDefault(NameToken.ColorSpace, NameToken.Cs); if (!DirectObjectFinder.TryGet(colorSpace, scanner, out colorSpaceArray) - && DirectObjectFinder.TryGet(colorSpace, scanner, out NameToken colorSpaceName) && + && DirectObjectFinder.TryGet(colorSpace, scanner, out NameToken? colorSpaceName) && resourceStore.TryGetNamedColorSpace(colorSpaceName, out var colorSpaceNamedToken)) { colorSpaceArray = colorSpaceNamedToken.Data as ArrayToken; diff --git a/src/UglyToad.PdfPig/Util/Diacritics.cs b/src/UglyToad.PdfPig/Util/Diacritics.cs index 95251ced4..d67e8633a 100644 --- a/src/UglyToad.PdfPig/Util/Diacritics.cs +++ b/src/UglyToad.PdfPig/Util/Diacritics.cs @@ -1,6 +1,7 @@ namespace UglyToad.PdfPig.Util { using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.Globalization; internal static class Diacritics @@ -39,7 +40,7 @@ public static bool IsInCombiningDiacriticRange(string value) return false; } - public static bool TryCombineDiacriticWithPreviousLetter(string diacritic, string previous, out string result) + public static bool TryCombineDiacriticWithPreviousLetter(string diacritic, string previous, [NotNullWhen(true)] out string? result) { result = null; diff --git a/src/UglyToad.PdfPig/Util/DictionaryTokenExtensions.cs b/src/UglyToad.PdfPig/Util/DictionaryTokenExtensions.cs index cc1799a5c..67ec33f9a 100644 --- a/src/UglyToad.PdfPig/Util/DictionaryTokenExtensions.cs +++ b/src/UglyToad.PdfPig/Util/DictionaryTokenExtensions.cs @@ -1,16 +1,15 @@ namespace UglyToad.PdfPig.Util { using System; + using System.Diagnostics.CodeAnalysis; using Core; - using JetBrains.Annotations; using Parser.Parts; using Tokenization.Scanner; using Tokens; internal static class DictionaryTokenExtensions { - [CanBeNull] - public static IToken GetObjectOrDefault(this DictionaryToken token, NameToken name) + public static IToken? GetObjectOrDefault(this DictionaryToken token, NameToken name) { if (token.TryGet(name, out var obj)) { @@ -20,8 +19,7 @@ public static IToken GetObjectOrDefault(this DictionaryToken token, NameToken na return null; } - [CanBeNull] - public static IToken GetObjectOrDefault(this DictionaryToken token, NameToken first, NameToken second) + public static IToken? GetObjectOrDefault(this DictionaryToken token, NameToken first, NameToken second) { if (token.TryGet(first, out var obj)) { @@ -96,8 +94,7 @@ public static bool GetBooleanOrDefault(this DictionaryToken token, NameToken nam return boolean?.Data ?? defaultValue; } - [CanBeNull] - public static NameToken GetNameOrDefault(this DictionaryToken token, NameToken name) + public static NameToken? GetNameOrDefault(this DictionaryToken token, NameToken name) { if (token is null) { @@ -107,10 +104,11 @@ public static NameToken GetNameOrDefault(this DictionaryToken token, NameToken n return token.GetObjectOrDefault(name) as NameToken; } - public static bool TryGetOptionalTokenDirect(this DictionaryToken token, NameToken name, IPdfTokenScanner scanner, out T result) where T : IToken + public static bool TryGetOptionalTokenDirect(this DictionaryToken token, NameToken name, IPdfTokenScanner scanner, [NotNullWhen(true)] out T? result) + where T : class, IToken { - result = default(T); - if (token.TryGet(name, out var appearancesToken) && DirectObjectFinder.TryGet(appearancesToken, scanner, out T innerResult)) + result = null; + if (token.TryGet(name, out var appearancesToken) && DirectObjectFinder.TryGet(appearancesToken, scanner, out T? innerResult)) { result = innerResult; return true; @@ -119,16 +117,16 @@ public static bool TryGetOptionalTokenDirect(this DictionaryToken token, Name return false; } - public static bool TryGetOptionalStringDirect(this DictionaryToken token, NameToken name, IPdfTokenScanner scanner, out string result) + public static bool TryGetOptionalStringDirect(this DictionaryToken token, NameToken name, IPdfTokenScanner scanner, [NotNullWhen(true)] out string? result) { - result = default(string); - if (token.TryGetOptionalTokenDirect(name, scanner, out StringToken stringToken)) + result = null; + if (token.TryGetOptionalTokenDirect(name, scanner, out StringToken? stringToken)) { result = stringToken.Data; return true; } - if (token.TryGetOptionalTokenDirect(name, scanner, out HexToken hexToken)) + if (token.TryGetOptionalTokenDirect(name, scanner, out HexToken? hexToken)) { result = hexToken.Data; return true; @@ -172,7 +170,8 @@ public static PdfRectangle ToRectangle(this ArrayToken array, IPdfTokenScanner t throw new PdfDocumentFormatException($"Cannot convert array to rectangle, expected 4 values instead got: {array.Data.Count}."); } - return new PdfRectangle(DirectObjectFinder.Get(array[0], tokenScanner).Double, + return new PdfRectangle( + DirectObjectFinder.Get(array[0], tokenScanner).Double, DirectObjectFinder.Get(array[1], tokenScanner).Double, DirectObjectFinder.Get(array[2], tokenScanner).Double, DirectObjectFinder.Get(array[3], tokenScanner).Double); @@ -190,10 +189,11 @@ public static PdfRectangle ToIntRectangle(this ArrayToken array, IPdfTokenScanne throw new PdfDocumentFormatException($"Cannot convert array to rectangle, expected 4 values instead got: {array.Data.Count}."); } - return new PdfRectangle(DirectObjectFinder.Get(array[0], tokenScanner).Int, + return new PdfRectangle( + DirectObjectFinder.Get(array[0], tokenScanner).Int, DirectObjectFinder.Get(array[1], tokenScanner).Int, DirectObjectFinder.Get(array[2], tokenScanner).Int, DirectObjectFinder.Get(array[3], tokenScanner).Int); } } -} +} \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Util/Matrix3x3.cs b/src/UglyToad.PdfPig/Util/Matrix3x3.cs index a3f8e968f..613685421 100644 --- a/src/UglyToad.PdfPig/Util/Matrix3x3.cs +++ b/src/UglyToad.PdfPig/Util/Matrix3x3.cs @@ -69,7 +69,7 @@ public IEnumerator GetEnumerator() /// /// If an inverse matrix does not exist, null is returned. ///
- public Matrix3x3 Inverse() + public Matrix3x3? Inverse() { var determinant = GetDeterminant(); @@ -154,13 +154,12 @@ public Matrix3x3 Transpose() m13, m23, m33); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { - var other = obj as Matrix3x3; - return Equals(other); + return obj is Matrix3x3 other && Equals(other); } - public bool Equals(Matrix3x3 other) + public bool Equals(Matrix3x3? other) { if (other is null) { diff --git a/src/UglyToad.PdfPig/Util/PatternParser.cs b/src/UglyToad.PdfPig/Util/PatternParser.cs index 30d49de40..d1aee3c7c 100644 --- a/src/UglyToad.PdfPig/Util/PatternParser.cs +++ b/src/UglyToad.PdfPig/Util/PatternParser.cs @@ -15,14 +15,14 @@ internal static class PatternParser public static PatternColor Create(IToken pattern, IPdfTokenScanner scanner, IResourceStore resourceStore, ILookupFilterProvider filterProvider) { DictionaryToken patternDictionary; - StreamToken patternStream = null; + StreamToken? patternStream = null; - if (DirectObjectFinder.TryGet(pattern, scanner, out StreamToken fs)) + if (DirectObjectFinder.TryGet(pattern, scanner, out StreamToken? fs)) { patternDictionary = fs.StreamDictionary; patternStream = new StreamToken(fs.StreamDictionary, fs.Decode(filterProvider, scanner)); } - else if (DirectObjectFinder.TryGet(pattern, scanner, out DictionaryToken fd)) + else if (DirectObjectFinder.TryGet(pattern, scanner, out DictionaryToken? fd)) { patternDictionary = fd; } @@ -36,11 +36,11 @@ public static PatternColor Create(IToken pattern, IPdfTokenScanner scanner, IRes throw new Exception("TODO"); } - int patternType = (patternDictionary.Data[NameToken.PatternType] as NumericToken).Int; + int patternType = ((NumericToken)patternDictionary.Data[NameToken.PatternType]).Int; TransformationMatrix matrix; if ((patternDictionary.Data.ContainsKey(NameToken.Matrix) && - DirectObjectFinder.TryGet(patternDictionary.Data[NameToken.Matrix], scanner, out ArrayToken patternMatrix))) + DirectObjectFinder.TryGet(patternDictionary.Data[NameToken.Matrix], scanner, out ArrayToken? patternMatrix))) { matrix = TransformationMatrix.FromArray(patternMatrix.Data.OfType().Select(n => n.Data).ToArray()); } @@ -50,7 +50,7 @@ public static PatternColor Create(IToken pattern, IPdfTokenScanner scanner, IRes matrix = TransformationMatrix.FromArray([1, 0, 0, 1, 0, 0]); } - DictionaryToken patternExtGState = null; + DictionaryToken? patternExtGState = null; if (!(patternDictionary.Data.ContainsKey(NameToken.ExtGState) && DirectObjectFinder.TryGet(patternDictionary.Data[NameToken.ExtGState], scanner, out patternExtGState))) { @@ -59,7 +59,7 @@ public static PatternColor Create(IToken pattern, IPdfTokenScanner scanner, IRes return patternType switch { // Tiling - 1 => CreateTilingPattern(patternStream, patternExtGState, matrix, scanner), + 1 => CreateTilingPattern(patternStream!, patternExtGState!, matrix, scanner), // Shading 2 => CreateShadingPattern(patternDictionary, patternExtGState, matrix, scanner, resourceStore, filterProvider), _ => throw new PdfDocumentFormatException($"Invalid Pattern type encountered in page resource dictionary: {patternType}.") @@ -112,17 +112,17 @@ private static PatternColor CreateTilingPattern(StreamToken patternStream, Dicti patternStream.Data); } - private static PatternColor CreateShadingPattern(DictionaryToken patternDictionary, DictionaryToken patternExtGState, + private static PatternColor CreateShadingPattern(DictionaryToken patternDictionary, DictionaryToken? patternExtGState, TransformationMatrix matrix, IPdfTokenScanner scanner, IResourceStore resourceStore, ILookupFilterProvider filterProvider) { IToken shadingToken = patternDictionary.Data[NameToken.Shading]; Shading patternShading; - if (DirectObjectFinder.TryGet(shadingToken, scanner, out DictionaryToken patternShadingDictionary)) + if (DirectObjectFinder.TryGet(shadingToken, scanner, out DictionaryToken? patternShadingDictionary)) { patternShading = ShadingParser.Create(patternShadingDictionary, scanner, resourceStore, filterProvider); } - else if (DirectObjectFinder.TryGet(shadingToken, scanner, out StreamToken patternShadingStream)) + else if (DirectObjectFinder.TryGet(shadingToken, scanner, out StreamToken? patternShadingStream)) { patternShading = ShadingParser.Create(patternShadingStream, scanner, resourceStore, filterProvider); } @@ -130,7 +130,7 @@ private static PatternColor CreateShadingPattern(DictionaryToken patternDictiona { throw new ArgumentException("TODO"); } - return new ShadingPatternColor(matrix, patternExtGState, patternDictionary, patternShading); + return new ShadingPatternColor(matrix, patternExtGState!, patternDictionary, patternShading); } } } diff --git a/src/UglyToad.PdfPig/Util/PdfFunctionParser.cs b/src/UglyToad.PdfPig/Util/PdfFunctionParser.cs index 1b8a5bc55..0e591220a 100644 --- a/src/UglyToad.PdfPig/Util/PdfFunctionParser.cs +++ b/src/UglyToad.PdfPig/Util/PdfFunctionParser.cs @@ -14,14 +14,14 @@ internal static class PdfFunctionParser public static PdfFunction Create(IToken function, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) { DictionaryToken functionDictionary; - StreamToken functionStream = null; + StreamToken? functionStream = null; - if (DirectObjectFinder.TryGet(function, scanner, out StreamToken fs)) + if (DirectObjectFinder.TryGet(function, scanner, out StreamToken? fs)) { functionDictionary = fs.StreamDictionary; functionStream = new StreamToken(fs.StreamDictionary, fs.Decode(filterProvider, scanner)); } - else if (DirectObjectFinder.TryGet(function, scanner, out DictionaryToken fd)) + else if (DirectObjectFinder.TryGet(function, scanner, out DictionaryToken? fd)) { functionDictionary = fd; } @@ -30,14 +30,14 @@ public static PdfFunction Create(IToken function, IPdfTokenScanner scanner, ILoo throw new ArgumentException(nameof(function)); } - if (!functionDictionary.TryGet(NameToken.Domain, scanner, out ArrayToken domain)) + if (!functionDictionary.TryGet(NameToken.Domain, scanner, out ArrayToken? domain)) { throw new ArgumentNullException(NameToken.Domain); } - functionDictionary.TryGet(NameToken.Range, scanner, out ArrayToken range); + functionDictionary.TryGet(NameToken.Range, scanner, out ArrayToken? range); - int functionType = (functionDictionary.Data[NameToken.FunctionType] as NumericToken).Int; + int functionType = ((NumericToken)functionDictionary.Data[NameToken.FunctionType]).Int; switch (functionType) { @@ -46,7 +46,7 @@ public static PdfFunction Create(IToken function, IPdfTokenScanner scanner, ILoo { throw new NotImplementedException("PdfFunctionType0 not stream"); } - return CreatePdfFunctionType0(functionStream, domain, range, scanner); + return CreatePdfFunctionType0(functionStream, domain, range!, scanner); case 2: return CreatePdfFunctionType2(functionDictionary, domain, range, scanner); @@ -59,7 +59,7 @@ public static PdfFunction Create(IToken function, IPdfTokenScanner scanner, ILoo { throw new NotImplementedException("PdfFunctionType4 not stream"); } - return CreatePdfFunctionType4(functionStream, domain, range, scanner); + return CreatePdfFunctionType4(functionStream, domain, range!, scanner); default: throw new IOException("Error: Unknown function type " + functionType); @@ -97,7 +97,7 @@ private static PdfFunctionType0 CreatePdfFunctionType0(StreamToken functionStrea for (int i = 0; i < sizeValuesSize; i++) { values.Add(new NumericToken(0)); - values.Add(new NumericToken((size[i] as NumericToken).Int - 1)); + values.Add(new NumericToken(((NumericToken)size[i]).Int - 1)); } encode = new ArrayToken(values); } @@ -111,19 +111,19 @@ private static PdfFunctionType0 CreatePdfFunctionType0(StreamToken functionStrea return new PdfFunctionType0(functionStream, domain, range, size, bps.Int, order, encode, decode); } - private static PdfFunctionType2 CreatePdfFunctionType2(DictionaryToken functionDictionary, ArrayToken domain, ArrayToken range, IPdfTokenScanner scanner) + private static PdfFunctionType2 CreatePdfFunctionType2(DictionaryToken functionDictionary, ArrayToken domain, ArrayToken? range, IPdfTokenScanner scanner) { - if (!functionDictionary.TryGet(NameToken.C0, scanner, out ArrayToken array0) || array0.Length == 0) + if (!functionDictionary.TryGet(NameToken.C0, scanner, out ArrayToken? array0) || array0.Length == 0) { array0 = new ArrayToken(new List() { new NumericToken(0) }); // Default value: [0.0]. } - if (!functionDictionary.TryGet(NameToken.C1, scanner, out ArrayToken array1) || array1.Length == 0) + if (!functionDictionary.TryGet(NameToken.C1, scanner, out ArrayToken? array1) || array1.Length == 0) { array1 = new ArrayToken(new List() { new NumericToken(1) }); // Default value: [1.0]. } - if (!functionDictionary.TryGet(NameToken.N, scanner, out NumericToken exp)) + if (!functionDictionary.TryGet(NameToken.N, scanner, out NumericToken? exp)) { throw new ArgumentNullException(NameToken.N); } @@ -131,7 +131,12 @@ private static PdfFunctionType2 CreatePdfFunctionType2(DictionaryToken functionD return new PdfFunctionType2(functionDictionary, domain, range, array0, array1, exp.Double); } - private static PdfFunctionType3 CreatePdfFunctionType3(DictionaryToken functionDictionary, ArrayToken domain, ArrayToken range, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) + private static PdfFunctionType3 CreatePdfFunctionType3( + DictionaryToken functionDictionary, + ArrayToken domain, + ArrayToken? range, + IPdfTokenScanner scanner, + ILookupFilterProvider filterProvider) { var functions = new List(); if (functionDictionary.TryGet(NameToken.Functions, scanner, out var functionsToken)) diff --git a/src/UglyToad.PdfPig/Util/ShadingParser.cs b/src/UglyToad.PdfPig/Util/ShadingParser.cs index d0c249fed..4c3173ad1 100644 --- a/src/UglyToad.PdfPig/Util/ShadingParser.cs +++ b/src/UglyToad.PdfPig/Util/ShadingParser.cs @@ -29,7 +29,7 @@ public static Shading Create(IToken shading, IPdfTokenScanner scanner, IResource } ShadingType shadingType; - if (shadingDictionary.TryGet(NameToken.ShadingType, scanner, out var shadingTypeToken)) + if (shadingDictionary!.TryGet(NameToken.ShadingType, scanner, out var shadingTypeToken)) { // Shading types 4 to 7 shall be defined by a stream containing descriptive data characterizing // the shading's gradient fill. @@ -45,17 +45,17 @@ public static Shading Create(IToken shading, IPdfTokenScanner scanner, IResource throw new ArgumentNullException($"'{NameToken.ShadingType}' is required for shading."); } - ColorSpaceDetails colorSpace = null; - if (shadingDictionary.TryGet(NameToken.ColorSpace, scanner, out var colorSpaceToken)) + ColorSpaceDetails? colorSpace = null; + if (shadingDictionary!.TryGet(NameToken.ColorSpace, scanner, out var colorSpaceToken)) { colorSpace = resourceStore.GetColorSpaceDetails(colorSpaceToken, shadingDictionary); } - else if (shadingDictionary.TryGet(NameToken.ColorSpace, scanner, out var colorSpaceSToken)) + else if (shadingDictionary!.TryGet(NameToken.ColorSpace, scanner, out var colorSpaceSToken)) { var first = colorSpaceSToken.Data[0]; if (first is NameToken firstColorSpaceName) { - colorSpace = resourceStore.GetColorSpaceDetails(firstColorSpaceName, shadingDictionary); + colorSpace = resourceStore.GetColorSpaceDetails(firstColorSpaceName, shadingDictionary!); } else { @@ -67,45 +67,45 @@ public static Shading Create(IToken shading, IPdfTokenScanner scanner, IResource throw new ArgumentNullException($"'{NameToken.ColorSpace}' is required for shading."); } - double[] background = null; - if (shadingDictionary.TryGet(NameToken.Background, scanner, out var backgroundToken)) + double[]? background = null; + if (shadingDictionary!.TryGet(NameToken.Background, scanner, out var backgroundToken)) { // Optional background = backgroundToken.Data.OfType().Select(v => v.Double).ToArray(); } PdfRectangle? bbox = null; - if (shadingDictionary.TryGet(NameToken.Bbox, scanner, out var bboxToken)) + if (shadingDictionary!.TryGet(NameToken.Bbox, scanner, out var bboxToken)) { // Optional bbox = bboxToken.ToRectangle(scanner); } // Optional - bool antiAlias = shadingDictionary.TryGet(NameToken.AntiAlias, scanner, out var antiAliasToken) && antiAliasToken.Data; // Default value: false. + bool antiAlias = shadingDictionary!.TryGet(NameToken.AntiAlias, scanner, out var antiAliasToken) && antiAliasToken.Data; // Default value: false. switch (shadingType) { case ShadingType.FunctionBased: - return CreateFunctionBasedShading(shadingDictionary, colorSpace, background, bbox, antiAlias, scanner, filterProvider); + return CreateFunctionBasedShading(shadingDictionary!, colorSpace, background, bbox, antiAlias, scanner, filterProvider); case ShadingType.Axial: - return CreateAxialShading(shadingDictionary, colorSpace, background, bbox, antiAlias, scanner, filterProvider); + return CreateAxialShading(shadingDictionary!, colorSpace, background, bbox, antiAlias, scanner, filterProvider); case ShadingType.Radial: - return CreateRadialShading(shadingDictionary, colorSpace, background, bbox, antiAlias, scanner, filterProvider); + return CreateRadialShading(shadingDictionary!, colorSpace, background, bbox, antiAlias, scanner, filterProvider); case ShadingType.FreeFormGouraud: - return CreateFreeFormGouraudShadedTriangleMeshesShading(shadingStream, colorSpace, background, bbox, antiAlias, scanner, filterProvider); + return CreateFreeFormGouraudShadedTriangleMeshesShading(shadingStream!, colorSpace, background, bbox, antiAlias, scanner, filterProvider); case ShadingType.LatticeFormGouraud: - return CreateLatticeFormGouraudShadedTriangleMeshesShading(shadingStream, colorSpace, background, bbox, antiAlias, scanner, filterProvider); + return CreateLatticeFormGouraudShadedTriangleMeshesShading(shadingStream!, colorSpace, background, bbox, antiAlias, scanner, filterProvider); case ShadingType.CoonsPatch: - return CreateCoonsPatchMeshesShading(shadingStream, colorSpace, background, bbox, antiAlias, scanner, filterProvider); + return CreateCoonsPatchMeshesShading(shadingStream!, colorSpace, background, bbox, antiAlias, scanner, filterProvider); case ShadingType.TensorProductPatch: - return CreateTensorProductPatchMeshesShading(shadingStream, colorSpace, background, bbox, antiAlias, scanner, filterProvider); + return CreateTensorProductPatchMeshesShading(shadingStream!, colorSpace, background, bbox, antiAlias, scanner, filterProvider); default: throw new PdfDocumentFormatException($"Invalid Shading type encountered in page resource dictionary: '{shadingType}'."); @@ -114,7 +114,7 @@ public static Shading Create(IToken shading, IPdfTokenScanner scanner, IResource private static PdfFunction[] GetFunctions(IToken functionToken, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) { - if (DirectObjectFinder.TryGet(functionToken, scanner, out ArrayToken fa)) + if (DirectObjectFinder.TryGet(functionToken, scanner, out ArrayToken? fa)) { var functionArray = new PdfFunction[fa.Length]; for (int i = 0; i < fa.Length; i++) @@ -130,9 +130,9 @@ private static PdfFunction[] GetFunctions(IToken functionToken, IPdfTokenScanner } private static FunctionBasedShading CreateFunctionBasedShading(DictionaryToken shadingDictionary, ColorSpaceDetails colorSpace, - double[] background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) + double[]? background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) { - double[] domain = null; + double[]? domain = null; if (shadingDictionary.TryGet(NameToken.Domain, scanner, out var domainToken)) { domain = domainToken.Data.OfType().Select(v => v.Double).ToArray(); @@ -165,9 +165,9 @@ private static FunctionBasedShading CreateFunctionBasedShading(DictionaryToken s } private static AxialShading CreateAxialShading(DictionaryToken shadingDictionary, ColorSpaceDetails colorSpace, - double[] background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) + double[]? background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) { - double[] coords = null; + double[]? coords = null; if (shadingDictionary.TryGet(NameToken.Coords, scanner, out var coordsToken)) { coords = coordsToken.Data.OfType().Select(v => v.Double).ToArray(); @@ -177,7 +177,7 @@ private static AxialShading CreateAxialShading(DictionaryToken shadingDictionary throw new ArgumentNullException($"{NameToken.Coords} is required for shading type '{ShadingType.Axial}'."); } - double[] domain = null; + double[]? domain = null; if (shadingDictionary.TryGet(NameToken.Domain, scanner, out var domainToken)) { domain = domainToken.Data.OfType().Select(v => v.Double).ToArray(); @@ -195,7 +195,7 @@ private static AxialShading CreateAxialShading(DictionaryToken shadingDictionary PdfFunction[] functions = GetFunctions(shadingDictionary.Data[NameToken.Function], scanner, filterProvider); - bool[] extend = new bool[] { false, false }; // Default values + bool[] extend = [false, false]; // Default values if (shadingDictionary.TryGet(NameToken.Extend, scanner, out var extendToken)) { extend = extendToken.Data.OfType().Select(v => v.Data).ToArray(); @@ -205,7 +205,7 @@ private static AxialShading CreateAxialShading(DictionaryToken shadingDictionary } private static RadialShading CreateRadialShading(DictionaryToken shadingDictionary, ColorSpaceDetails colorSpace, - double[] background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) + double[]? background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) { double[]? coords = null; if (shadingDictionary.TryGet(NameToken.Coords, scanner, out var coordsToken)) @@ -217,7 +217,7 @@ private static RadialShading CreateRadialShading(DictionaryToken shadingDictiona throw new ArgumentNullException($"{NameToken.Coords} is required for shading type '{ShadingType.Radial}'."); } - double[] domain = null; + double[]? domain = null; if (shadingDictionary.TryGet(NameToken.Domain, scanner, out var domainToken)) { domain = domainToken.Data.OfType().Select(v => v.Double).ToArray(); @@ -245,7 +245,7 @@ private static RadialShading CreateRadialShading(DictionaryToken shadingDictiona } private static FreeFormGouraudShading CreateFreeFormGouraudShadedTriangleMeshesShading(StreamToken shadingStream, - ColorSpaceDetails colorSpace, double[] background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) + ColorSpaceDetails colorSpace, double[]? background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) { int bitsPerCoordinate; if (shadingStream.StreamDictionary.TryGet(NameToken.BitsPerCoordinate, scanner, out var bitsPerCoordinateToken)) @@ -298,7 +298,7 @@ private static FreeFormGouraudShading CreateFreeFormGouraudShadedTriangleMeshesS } private static LatticeFormGouraudShading CreateLatticeFormGouraudShadedTriangleMeshesShading(StreamToken shadingStream, - ColorSpaceDetails colorSpace, double[] background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) + ColorSpaceDetails colorSpace, double[]? background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) { int bitsPerCoordinate; if (shadingStream.StreamDictionary.TryGet(NameToken.BitsPerCoordinate, scanner, out var bitsPerCoordinateToken)) @@ -340,7 +340,7 @@ private static LatticeFormGouraudShading CreateLatticeFormGouraudShadedTriangleM throw new ArgumentNullException($"{NameToken.Decode} is required for shading type '{ShadingType.LatticeFormGouraud}'."); } - PdfFunction[] functions = null; // Optional + PdfFunction[]? functions = null; // Optional if (shadingStream.StreamDictionary.ContainsKey(NameToken.Function)) { functions = GetFunctions(shadingStream.StreamDictionary.Data[NameToken.Function], scanner, filterProvider); @@ -351,7 +351,7 @@ private static LatticeFormGouraudShading CreateLatticeFormGouraudShadedTriangleM } private static CoonsPatchMeshesShading CreateCoonsPatchMeshesShading(StreamToken shadingStream, - ColorSpaceDetails colorSpace, double[] background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) + ColorSpaceDetails colorSpace, double[]? background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) { int bitsPerCoordinate; if (shadingStream.StreamDictionary.TryGet(NameToken.BitsPerCoordinate, scanner, out var bitsPerCoordinateToken)) @@ -393,7 +393,7 @@ private static CoonsPatchMeshesShading CreateCoonsPatchMeshesShading(StreamToken throw new ArgumentNullException($"{NameToken.Decode} is required for shading type '{ShadingType.CoonsPatch}'."); } - PdfFunction[] functions = null; // Optional + PdfFunction[]? functions = null; // Optional if (shadingStream.StreamDictionary.ContainsKey(NameToken.Function)) { functions = GetFunctions(shadingStream.StreamDictionary.Data[NameToken.Function], scanner, filterProvider); @@ -404,7 +404,7 @@ private static CoonsPatchMeshesShading CreateCoonsPatchMeshesShading(StreamToken } private static TensorProductPatchMeshesShading CreateTensorProductPatchMeshesShading(StreamToken shadingStream, - ColorSpaceDetails colorSpace, double[] background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) + ColorSpaceDetails colorSpace, double[]? background, PdfRectangle? bbox, bool antiAlias, IPdfTokenScanner scanner, ILookupFilterProvider filterProvider) { int bitsPerCoordinate; if (shadingStream.StreamDictionary.TryGet(NameToken.BitsPerCoordinate, scanner, out var bitsPerCoordinateToken)) @@ -446,7 +446,7 @@ private static TensorProductPatchMeshesShading CreateTensorProductPatchMeshesSha throw new ArgumentNullException($"{NameToken.Decode} is required for shading type '{ShadingType.TensorProductPatch}'."); } - PdfFunction[] functions = null; // Optional + PdfFunction[]? functions = null; // Optional if (shadingStream.StreamDictionary.ContainsKey(NameToken.Function)) { functions = GetFunctions(shadingStream.StreamDictionary.Data[NameToken.Function], scanner, filterProvider); diff --git a/src/UglyToad.PdfPig/Util/StackDictionary.cs b/src/UglyToad.PdfPig/Util/StackDictionary.cs index c3a3408b6..4b91e06ce 100644 --- a/src/UglyToad.PdfPig/Util/StackDictionary.cs +++ b/src/UglyToad.PdfPig/Util/StackDictionary.cs @@ -3,6 +3,7 @@ namespace UglyToad.PdfPig.Util { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; internal class StackDictionary { @@ -30,7 +31,7 @@ public V this[K key] } } - public bool TryGetValue(K key, out V result) + public bool TryGetValue(K key, [NotNullWhen(true)] out V result) { if (values.Count == 0) { @@ -39,13 +40,13 @@ public bool TryGetValue(K key, out V result) for (var i = values.Count - 1; i >= 0; i--) { - if (values[i].TryGetValue(key, out result)) + if (values[i].TryGetValue(key, out result!)) { return true; } } - result = default(V); + result = default!; return false; } diff --git a/src/UglyToad.PdfPig/Writer/Fonts/IWritingFont.cs b/src/UglyToad.PdfPig/Writer/Fonts/IWritingFont.cs index 7bf4fd944..eb2d88385 100644 --- a/src/UglyToad.PdfPig/Writer/Fonts/IWritingFont.cs +++ b/src/UglyToad.PdfPig/Writer/Fonts/IWritingFont.cs @@ -1,9 +1,7 @@ namespace UglyToad.PdfPig.Writer.Fonts { - using System.IO; using Core; using Tokens; - using Util.JetBrains.Annotations; internal interface IWritingFont { @@ -17,7 +15,7 @@ internal interface IWritingFont TransformationMatrix GetFontMatrix(); - IndirectReferenceToken WriteFont(IPdfStreamWriter writer, [CanBeNull]IndirectReferenceToken reservedIndirect=null); + IndirectReferenceToken WriteFont(IPdfStreamWriter writer, IndirectReferenceToken? reservedIndirect = null); byte GetValueForCharacter(char character); } diff --git a/src/UglyToad.PdfPig/Writer/Fonts/Standard14WritingFont.cs b/src/UglyToad.PdfPig/Writer/Fonts/Standard14WritingFont.cs index 9d44f5a68..99bedacc0 100644 --- a/src/UglyToad.PdfPig/Writer/Fonts/Standard14WritingFont.cs +++ b/src/UglyToad.PdfPig/Writer/Fonts/Standard14WritingFont.cs @@ -69,7 +69,7 @@ public TransformationMatrix GetFontMatrix() return TransformationMatrix.FromValues(1 / 1000.0, 0, 0, 1 / 1000.0, 0, 0); } - public IndirectReferenceToken WriteFont(IPdfStreamWriter writer, IndirectReferenceToken reservedIndirect = null) + public IndirectReferenceToken WriteFont(IPdfStreamWriter writer, IndirectReferenceToken? reservedIndirect = null) { var encoding = NameToken.StandardEncoding; if (string.Equals(metrics.FontName, "Symbol", StringComparison.OrdinalIgnoreCase) diff --git a/src/UglyToad.PdfPig/Writer/Fonts/TrueTypeWritingFont.cs b/src/UglyToad.PdfPig/Writer/Fonts/TrueTypeWritingFont.cs index 727bd4579..63bfc4c10 100644 --- a/src/UglyToad.PdfPig/Writer/Fonts/TrueTypeWritingFont.cs +++ b/src/UglyToad.PdfPig/Writer/Fonts/TrueTypeWritingFont.cs @@ -2,7 +2,6 @@ { using System; using System.Collections.Generic; - using System.IO; using System.Linq; using Core; using PdfFonts; @@ -47,7 +46,7 @@ public TransformationMatrix GetFontMatrix() return TransformationMatrix.FromValues(1.0 / unitsPerEm, 0, 0, 1.0 / unitsPerEm, 0, 0); } - public IndirectReferenceToken WriteFont(IPdfStreamWriter writer, IndirectReferenceToken reservedIndirect=null) + public IndirectReferenceToken WriteFont(IPdfStreamWriter writer, IndirectReferenceToken? reservedIndirect = null) { var newEncoding = new TrueTypeSubsetEncoding(characterMapping.Keys.ToList()); var subsetBytes = TrueTypeSubsetter.Subset(fontFileBytes.ToArray(), newEncoding); diff --git a/src/UglyToad.PdfPig/Writer/IPdfStreamWriter.cs b/src/UglyToad.PdfPig/Writer/IPdfStreamWriter.cs index 98d5941d2..9755fc743 100644 --- a/src/UglyToad.PdfPig/Writer/IPdfStreamWriter.cs +++ b/src/UglyToad.PdfPig/Writer/IPdfStreamWriter.cs @@ -57,6 +57,6 @@ internal interface IPdfStreamWriter : IDisposable ///
/// Indirect reference of catalog. /// Reference to document information (optional) - void CompletePdf(IndirectReferenceToken catalogReference, IndirectReferenceToken documentInformationReference=null); + void CompletePdf(IndirectReferenceToken catalogReference, IndirectReferenceToken? documentInformationReference = null); } } diff --git a/src/UglyToad.PdfPig/Writer/NoTextTokenWriter.cs b/src/UglyToad.PdfPig/Writer/NoTextTokenWriter.cs index d72cf995d..86e8ec121 100644 --- a/src/UglyToad.PdfPig/Writer/NoTextTokenWriter.cs +++ b/src/UglyToad.PdfPig/Writer/NoTextTokenWriter.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using UglyToad.PdfPig.Core; @@ -30,7 +31,7 @@ internal class NoTextTokenWriter : TokenWriter /// protected override void WriteStream(StreamToken streamToken, Stream outputStream) { - StreamToken outputStreamToken; + StreamToken? outputStreamToken; if (!WritingPageContents && !IsFormStream(streamToken)) { outputStreamToken = streamToken; @@ -62,7 +63,7 @@ private static bool IsFormStream(StreamToken streamToken) /// /// true if any text operation found (and we have a valid without the text operations), /// false if no text operation found (in which case is null) - private bool TryGetStreamWithoutText(StreamToken streamToken, out StreamToken outputStreamToken) + private bool TryGetStreamWithoutText(StreamToken streamToken, [NotNullWhen(true)] out StreamToken? outputStreamToken) { var filterProvider = new FilterProviderWithLookup(DefaultFilterProvider.Instance); IReadOnlyList bytes; diff --git a/src/UglyToad.PdfPig/Writer/PdfABaselineRuleBuilder.cs b/src/UglyToad.PdfPig/Writer/PdfABaselineRuleBuilder.cs index aa9014f16..7137b5f42 100644 --- a/src/UglyToad.PdfPig/Writer/PdfABaselineRuleBuilder.cs +++ b/src/UglyToad.PdfPig/Writer/PdfABaselineRuleBuilder.cs @@ -15,7 +15,7 @@ public static void Obey( PdfDocumentBuilder.DocumentInformationBuilder documentInformationBuilder, PdfAStandard archiveStandard, double version, - XDocument xmpMetadata) + XDocument? xmpMetadata) { catalog[NameToken.OutputIntents] = OutputIntentsFactory.GetOutputIntentsArray(writerFunc); var xmpStream = XmpWriter.GenerateXmpStream(documentInformationBuilder, version, archiveStandard, xmpMetadata); diff --git a/src/UglyToad.PdfPig/Writer/PdfDedupStreamWriter.cs b/src/UglyToad.PdfPig/Writer/PdfDedupStreamWriter.cs index 17f29c563..1a0de0402 100644 --- a/src/UglyToad.PdfPig/Writer/PdfDedupStreamWriter.cs +++ b/src/UglyToad.PdfPig/Writer/PdfDedupStreamWriter.cs @@ -12,8 +12,8 @@ internal class PdfDedupStreamWriter : PdfStreamWriter public PdfDedupStreamWriter( Stream stream, bool dispose, - ITokenWriter tokenWriter = null, - Action recordVersion = null + ITokenWriter? tokenWriter = null, + Action? recordVersion = null ) : base(stream, dispose, tokenWriter, recordVersion) { } diff --git a/src/UglyToad.PdfPig/Writer/PdfDocumentBuilder.cs b/src/UglyToad.PdfPig/Writer/PdfDocumentBuilder.cs index 8f2ffb678..9f2aea494 100644 --- a/src/UglyToad.PdfPig/Writer/PdfDocumentBuilder.cs +++ b/src/UglyToad.PdfPig/Writer/PdfDocumentBuilder.cs @@ -6,6 +6,7 @@ namespace UglyToad.PdfPig.Writer using System.IO; using System.Linq; using System.Runtime.CompilerServices; + using System.Xml.Linq; using Content; using Core; using Fonts; @@ -18,9 +19,6 @@ namespace UglyToad.PdfPig.Writer using Tokenization.Scanner; using Tokens; - using Util.JetBrains.Annotations; - using System.Xml.Linq; - /// /// Provides methods to construct new PDF documents. /// @@ -60,13 +58,13 @@ public class PdfDocumentBuilder : IDisposable /// /// The bookmark nodes to include in the document outline dictionary. /// - public Bookmarks Bookmarks { get; set; } + public Bookmarks? Bookmarks { get; set; } /// /// The document level metadata, which is XML in the XMP (Extensible Metadata Platform) format. Will only be added, if the PDF is /// created with an ArchiveStandard other than PdfAStandard.None. /// - public XDocument XmpMetadata { get; set; } + public XDocument? XmpMetadata { get; set; } /// /// The current page builders in the document and the corresponding 1 indexed page numbers. Use @@ -106,7 +104,7 @@ public PdfDocumentBuilder(double version) /// Type of pdf stream writer to use /// Pdf version to use in header. /// Token writer to use - public PdfDocumentBuilder(Stream stream, bool disposeStream = false, PdfWriterType type = PdfWriterType.Default, double version = 1.7, ITokenWriter tokenWriter = null) + public PdfDocumentBuilder(Stream stream, bool disposeStream = false, PdfWriterType type = PdfWriterType.Default, double version = 1.7, ITokenWriter? tokenWriter = null) { switch (type) { @@ -238,7 +236,7 @@ public PdfPageBuilder AddPage(double width, double height) throw new ArgumentOutOfRangeException(nameof(height), $"Height cannot be negative, got: {height}."); } - PdfPageBuilder builder = null; + PdfPageBuilder? builder = null; for (var i = 0; i < pages.Count; i++) { if (!pages.ContainsKey(i + 1)) @@ -297,17 +295,16 @@ internal IToken CopyToken(IPdfTokenScanner source, IToken token) return WriterUtil.CopyToken(context, token, source, refs); } - private class PageInfo + private sealed class PageInfo(DictionaryToken page, IReadOnlyList parents) { - public DictionaryToken Page { get; set; } - public IReadOnlyList Parents { get; set; } + public DictionaryToken Page { get; } = page; + + public IReadOnlyList Parents { get; } = parents; } - private readonly ConditionalWeakTable> existingCopies = - new ConditionalWeakTable>(); + private readonly ConditionalWeakTable> existingCopies = new(); - private readonly ConditionalWeakTable> existingTrees = - new ConditionalWeakTable>(); + private readonly ConditionalWeakTable> existingTrees = new(); /// /// Add a new page with the specified size, this page will be included in the output when is called. @@ -327,7 +324,7 @@ public PdfPageBuilder AddPage(PdfDocument document, int pageNumber) /// Page to copy. /// If set, links are copied based on the result of the delegate. /// A builder for editing the page. - public PdfPageBuilder AddPage(PdfDocument document, int pageNumber, Func copyLink) + public PdfPageBuilder AddPage(PdfDocument document, int pageNumber, Func? copyLink) { if (!existingCopies.TryGetValue(document.Structure.TokenScanner, out var refs)) { @@ -341,18 +338,14 @@ public PdfPageBuilder AddPage(PdfDocument document, int pageNumber, Func(); foreach (var annot in arr.Data) { - DictionaryToken tk = GetRemoteDict(annot); + DictionaryToken? tk = GetRemoteDict(annot); if (tk is null) { // malformed @@ -465,7 +458,7 @@ public PdfPageBuilder AddPage(PdfDocument document, int pageNumber, Func destinationDict) { - DictionaryToken dict = GetRemoteDict(token); + DictionaryToken? dict = GetRemoteDict(token); if (dict is null) { return; @@ -568,9 +561,9 @@ void CopyResourceDict(IToken token, Dictionary destinationDic } } - DictionaryToken GetRemoteDict(IToken token) + DictionaryToken? GetRemoteDict(IToken token) { - DictionaryToken dict = null; + DictionaryToken? dict = null; if (token is IndirectReferenceToken ir) { dict = document.Structure.TokenScanner.Get(ir.Data).Data as DictionaryToken; @@ -696,7 +689,7 @@ private void CompleteDocument() var leaf = leafs[0]; var id = leaf[dummyName] as IndirectReferenceToken; leaf.Remove(dummyName); - catalogDictionary[NameToken.Pages] = context.WriteToken(new DictionaryToken(leaf), id); + catalogDictionary[NameToken.Pages] = context.WriteToken(new DictionaryToken(leaf), id!); } else { @@ -761,7 +754,7 @@ private void CompleteDocument() completed = true; - (int Count, IndirectReferenceToken Ref) CreatePageTree(List> pagesNodes, IndirectReferenceToken parent) + (int Count, IndirectReferenceToken Ref) CreatePageTree(List> pagesNodes, IndirectReferenceToken? parent) { // TODO shorten page tree when there is a single or small number of pages left in a branch var count = 0; @@ -788,8 +781,8 @@ private void CompleteDocument() page[NameToken.Parent] = thisObj; var id = page[dummyName] as IndirectReferenceToken; page.Remove(dummyName); - count += (page[NameToken.Count] as NumericToken).Int; - children.Add(context.WriteToken(new DictionaryToken(page), id)); + count += ((NumericToken)page[NameToken.Count]).Int; + children.Add(context.WriteToken(new DictionaryToken(page), id!)); } } @@ -844,7 +837,7 @@ private static ArrayToken RectangleToArray(PdfRectangle rectangle) ]); } - private IndirectReferenceToken[] CreateBookmarkTree(IReadOnlyList nodes, Dictionary pageReferences, IndirectReferenceToken parent) + private IndirectReferenceToken[] CreateBookmarkTree(IReadOnlyList nodes, Dictionary pageReferences, IndirectReferenceToken? parent) { var childObjectNumbers = new IndirectReferenceToken[nodes.Count]; for (var i = 0; i < nodes.Count; i++) @@ -1048,10 +1041,8 @@ private static DictionaryToken CreateActionToken(PdfAction action, Dictionary /// . /// - public string Title { get; set; } + public string? Title { get; set; } /// /// . /// - public string Author { get; set; } + public string? Author { get; set; } /// /// . /// - public string Subject { get; set; } + public string? Subject { get; set; } /// /// . /// - public string Keywords { get; set; } + public string? Keywords { get; set; } /// /// . /// - public string Creator { get; set; } + public string? Creator { get; set; } /// /// . @@ -1131,12 +1122,12 @@ public class DocumentInformationBuilder /// /// . /// - public string CreationDate { get; set; } + public string? CreationDate { get; set; } /// /// . /// - public string ModifiedDate { get; set; } + public string? ModifiedDate { get; set; } internal Dictionary ToDictionary() { diff --git a/src/UglyToad.PdfPig/Writer/PdfMerger.cs b/src/UglyToad.PdfPig/Writer/PdfMerger.cs index ba1b8043f..97510d95e 100644 --- a/src/UglyToad.PdfPig/Writer/PdfMerger.cs +++ b/src/UglyToad.PdfPig/Writer/PdfMerger.cs @@ -21,7 +21,13 @@ public static class PdfMerger /// /// Merge two PDF documents together with the pages from followed by . /// - public static byte[] Merge(string file1, string file2, IReadOnlyList file1Selection = null, IReadOnlyList file2Selection = null, PdfAStandard archiveStandard = PdfAStandard.None, PdfDocumentBuilder.DocumentInformationBuilder docInfoBuilder = null) + public static byte[] Merge( + string file1, + string file2, + IReadOnlyList? file1Selection = null, + IReadOnlyList? file2Selection = null, + PdfAStandard archiveStandard = PdfAStandard.None, + PdfDocumentBuilder.DocumentInformationBuilder? docInfoBuilder = null) { using (var output = new MemoryStream()) { @@ -33,7 +39,14 @@ public static byte[] Merge(string file1, string file2, IReadOnlyList file1S /// /// Merge two PDF documents together with the pages from followed by into the output stream. /// - public static void Merge(string file1, string file2, Stream output, IReadOnlyList file1Selection = null, IReadOnlyList file2Selection = null, PdfAStandard archiveStandard = PdfAStandard.None, PdfDocumentBuilder.DocumentInformationBuilder docInfoBuilder = null) + public static void Merge( + string file1, + string file2, + Stream output, + IReadOnlyList? file1Selection = null, + IReadOnlyList? file2Selection = null, + PdfAStandard archiveStandard = PdfAStandard.None, + PdfDocumentBuilder.DocumentInformationBuilder? docInfoBuilder = null) { _ = file1 ?? throw new ArgumentNullException(nameof(file1)); _ = file2 ?? throw new ArgumentNullException(nameof(file2)); @@ -58,7 +71,7 @@ public static byte[] Merge(params string[] filePaths) /// /// Merge multiple PDF documents together with the pages in the order the file paths are provided. /// - public static byte[] Merge(PdfAStandard archiveStandard, PdfDocumentBuilder.DocumentInformationBuilder docInfoBuilder, params string[] filePaths) + public static byte[] Merge(PdfAStandard archiveStandard, PdfDocumentBuilder.DocumentInformationBuilder? docInfoBuilder, params string[] filePaths) { using (var output = new MemoryStream()) { @@ -78,7 +91,7 @@ public static void Merge(Stream output, params string[] filePaths) /// /// Merge multiple PDF documents together with the pages in the order the file paths are provided into the output stream /// - public static void Merge(Stream output, PdfAStandard archiveStandard, PdfDocumentBuilder.DocumentInformationBuilder docInfoBuilder, params string[] filePaths) + public static void Merge(Stream output, PdfAStandard archiveStandard, PdfDocumentBuilder.DocumentInformationBuilder? docInfoBuilder, params string[] filePaths) { var streams = new List(filePaths.Length); try @@ -103,7 +116,11 @@ public static void Merge(Stream output, PdfAStandard archiveStandard, PdfDocumen /// /// Merge the set of PDF documents. /// - public static byte[] Merge(IReadOnlyList files, IReadOnlyList> pagesBundle = null, PdfAStandard archiveStandard = PdfAStandard.None, PdfDocumentBuilder.DocumentInformationBuilder docInfoBuilder = null) + public static byte[] Merge( + IReadOnlyList files, + IReadOnlyList>? pagesBundle = null, + PdfAStandard archiveStandard = PdfAStandard.None, + PdfDocumentBuilder.DocumentInformationBuilder? docInfoBuilder = null) { _ = files ?? throw new ArgumentNullException(nameof(files)); @@ -125,7 +142,12 @@ public static byte[] Merge(IReadOnlyList files, IReadOnlyList /// /// - public static void Merge(IReadOnlyList streams, Stream output, IReadOnlyList> pagesBundle = null, PdfAStandard archiveStandard = PdfAStandard.None, PdfDocumentBuilder.DocumentInformationBuilder docInfoBuilder = null) + public static void Merge( + IReadOnlyList streams, + Stream output, + IReadOnlyList?>? pagesBundle = null, + PdfAStandard archiveStandard = PdfAStandard.None, + PdfDocumentBuilder.DocumentInformationBuilder? docInfoBuilder = null) { _ = streams ?? throw new ArgumentNullException(nameof(streams)); _ = output ?? throw new ArgumentNullException(nameof(output)); @@ -133,7 +155,12 @@ public static void Merge(IReadOnlyList streams, Stream output, IReadOnly Merge(streams.Select(f => PdfDocument.Open(f)).ToArray(), output, pagesBundle, archiveStandard, docInfoBuilder); } - private static void Merge(IReadOnlyList files, Stream output, IReadOnlyList> pagesBundle, PdfAStandard archiveStandard = PdfAStandard.None, PdfDocumentBuilder.DocumentInformationBuilder docInfoBuilder = null) + private static void Merge( + IReadOnlyList files, + Stream output, + IReadOnlyList?>? pagesBundle, + PdfAStandard archiveStandard = PdfAStandard.None, + PdfDocumentBuilder.DocumentInformationBuilder? docInfoBuilder = null) { var maxVersion = files.Select(x => x.Version).Max(); using (var document = new PdfDocumentBuilder(output, false, PdfWriterType.Default, maxVersion)) @@ -147,7 +174,7 @@ private static void Merge(IReadOnlyList files, Stream output, IRead foreach (var fileIndex in Enumerable.Range(0, files.Count)) { var existing = files[fileIndex]; - IReadOnlyList pages = null; + IReadOnlyList? pages = null; if (pagesBundle != null && fileIndex < pagesBundle.Count) { pages = pagesBundle[fileIndex]; @@ -179,7 +206,7 @@ private static void Merge(IReadOnlyList files, Stream output, IRead } } - PdfAction CopyLink(PdfAction action, Func getPageNumber) + PdfAction? CopyLink(PdfAction action, Func getPageNumber) { var link = action as AbstractGoToAction; if (link is null) @@ -197,22 +224,13 @@ PdfAction CopyLink(PdfAction action, Func getPageNumber) var newDestination = new ExplicitDestination(newPageNumber.Value, link.Destination.Type, link.Destination.Coordinates); - switch (action) - { - case GoToAction goToAction: - return new GoToAction(newDestination); - - case GoToEAction goToEAction: - return new GoToEAction(newDestination, goToEAction.FileSpecification); - - case GoToRAction goToRAction: - return new GoToRAction(newDestination, goToRAction.Filename); - - default: - return action; - } + return action switch { + GoToAction goToAction => new GoToAction(newDestination), + GoToEAction goToEAction => new GoToEAction(newDestination, goToEAction.FileSpecification), + GoToRAction goToRAction => new GoToRAction(newDestination, goToRAction.Filename), + _ => action + }; } } - } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs b/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs index da61813ed..33880945b 100644 --- a/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs +++ b/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs @@ -1,5 +1,9 @@ namespace UglyToad.PdfPig.Writer { + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; using Content; using Core; using Fonts; @@ -13,10 +17,6 @@ using Graphics.Operations.TextShowing; using Graphics.Operations.TextState; using Images; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; using PdfFonts; using Tokens; using Graphics.Operations.PathPainting; @@ -34,10 +34,13 @@ public NameConflictSolver(string prefix) this.prefix = prefix; } - private string ExtractPrefix(string name) + private string ExtractPrefix(string? name) { if (name is null) + { return prefix; + } + var i = 0; while (i < name.Length && (name[i] < '0' || name[i] > '9')) { @@ -47,9 +50,9 @@ private string ExtractPrefix(string name) return i != 0 ? name.Substring(0, i) : prefix; } - public string NewName(string orginalName = null) + public string NewName(string? originalName = null) { - var newPrefix = ExtractPrefix(orginalName); + var newPrefix = ExtractPrefix(originalName); var name = $"{newPrefix}{key}"; @@ -91,7 +94,7 @@ public class PdfPageBuilder private IPageContentStream currentStream; // links to be resolved when all page references are available - internal readonly List<(DictionaryToken token, PdfAction action)> links; + internal readonly List<(DictionaryToken token, PdfAction action)>? links; // maps fonts added using PdfDocumentBuilder to page font names private readonly Dictionary documentFonts = new Dictionary(); @@ -548,7 +551,7 @@ public PdfPageBuilder SetTextRenderingMode(TextRenderingMode mode) private NameToken GetAddedFont(PdfDocumentBuilder.AddedFont font) { - if (!documentFonts.TryGetValue(font.Id, out NameToken value)) + if (!documentFonts.TryGetValue(font.Id, out NameToken? value)) { value = NameToken.Create($"F{nextFontId++}"); var resources = pageDictionary.GetOrCreateDict(NameToken.Resources); @@ -725,7 +728,7 @@ public AddedImage AddPng(Stream pngStream, PdfRectangle placementRectangle = def var widthToken = new NumericToken(png.Width); var heightToken = new NumericToken(png.Height); - IndirectReferenceToken smaskReference = null; + IndirectReferenceToken? smaskReference = null; if (png.HasAlphaChannel && documentBuilder.ArchiveStandard != PdfAStandard.A1B && documentBuilder.ArchiveStandard != PdfAStandard.A1A) { @@ -815,7 +818,7 @@ public PdfPageBuilder CopyFrom(Page srcPage) var destinationStream = currentStream; - if (!srcPage.Dictionary.TryGet(NameToken.Resources, srcPage.pdfScanner, out DictionaryToken srcResourceDictionary)) + if (!srcPage.Dictionary.TryGet(NameToken.Resources, srcPage.pdfScanner, out DictionaryToken? srcResourceDictionary)) { // If the page doesn't have resources, then we copy the entire content stream, since not operation would collide // with the ones already written @@ -857,7 +860,7 @@ public PdfPageBuilder CopyFrom(Page srcPage) // Special cases // Since we don't directly add font's to the pages resources, we have to go look at the document's font - if (srcResourceDictionary.TryGet(NameToken.Font, srcPage.pdfScanner, out DictionaryToken fontsDictionary)) + if (srcResourceDictionary.TryGet(NameToken.Font, srcPage.pdfScanner, out DictionaryToken? fontsDictionary)) { var pageFontsDictionary = resources.GetOrCreateDict(NameToken.Font); @@ -902,7 +905,7 @@ public PdfPageBuilder CopyFrom(Page srcPage) } // Since we don't directly add xobjects's to the pages resources, we have to go look at the document's xobjects - if (srcResourceDictionary.TryGet(NameToken.Xobject, srcPage.pdfScanner, out DictionaryToken xobjectsDictionary)) + if (srcResourceDictionary.TryGet(NameToken.Xobject, srcPage.pdfScanner, out DictionaryToken? xobjectsDictionary)) { var pageXobjectsDictionary = resources.GetOrCreateDict(NameToken.Xobject); @@ -944,7 +947,7 @@ public PdfPageBuilder CopyFrom(Page srcPage) } // Since we don't directly add xobjects's to the pages resources, we have to go look at the document's xobjects - if (srcResourceDictionary.TryGet(NameToken.ExtGState, srcPage.pdfScanner, out DictionaryToken gsDictionary)) + if (srcResourceDictionary.TryGet(NameToken.ExtGState, srcPage.pdfScanner, out DictionaryToken? gsDictionary)) { var pageGstateDictionary = resources.GetOrCreateDict(NameToken.ExtGState); @@ -990,7 +993,7 @@ public PdfPageBuilder CopyFrom(Page srcPage) return this; } - private List DrawLetters(NameToken name, string text, IWritingFont font, TransformationMatrix fontMatrix, double fontSize, TransformationMatrix textMatrix) + private List DrawLetters(NameToken? name, string text, IWritingFont font, TransformationMatrix fontMatrix, double fontSize, TransformationMatrix textMatrix) { var horizontalScaling = 1; var rise = 0; diff --git a/src/UglyToad.PdfPig/Writer/PdfStreamWriter.cs b/src/UglyToad.PdfPig/Writer/PdfStreamWriter.cs index eb5e3c586..d25ca3c60 100644 --- a/src/UglyToad.PdfPig/Writer/PdfStreamWriter.cs +++ b/src/UglyToad.PdfPig/Writer/PdfStreamWriter.cs @@ -13,7 +13,7 @@ /// internal class PdfStreamWriter : IPdfStreamWriter { - private readonly Action recordVersion; + private readonly Action? recordVersion; protected const double DefaultVersion = 1.2; protected Dictionary offsets = new Dictionary(); protected bool DisposeStream { get; set; } @@ -34,8 +34,8 @@ public bool WritingPageContents internal PdfStreamWriter( Stream baseStream, bool disposeStream = true, - ITokenWriter tokenWriter = null, - Action recordVersion = null) + ITokenWriter? tokenWriter = null, + Action? recordVersion = null) { Stream = baseStream ?? throw new ArgumentNullException(nameof(baseStream)); @@ -96,7 +96,7 @@ public void InitializePdf(double version) Initialized = true; } - public void CompletePdf(IndirectReferenceToken catalogReference, IndirectReferenceToken documentInformationReference = null) + public void CompletePdf(IndirectReferenceToken catalogReference, IndirectReferenceToken? documentInformationReference = null) { TokenWriter.WriteCrossReferenceTable(offsets, catalogReference.Data, Stream, documentInformationReference?.Data); } @@ -115,7 +115,7 @@ public void Dispose() Stream?.Dispose(); } - Stream = null; + Stream = null!; } } } diff --git a/src/UglyToad.PdfPig/Writer/PdfTextRemover.cs b/src/UglyToad.PdfPig/Writer/PdfTextRemover.cs index f8f7b6797..d6e205521 100644 --- a/src/UglyToad.PdfPig/Writer/PdfTextRemover.cs +++ b/src/UglyToad.PdfPig/Writer/PdfTextRemover.cs @@ -19,7 +19,7 @@ public static class PdfTextRemover /// Path to PDF /// List of pages to emit; if null all pages are emitted ///
- public static byte[] RemoveText(string filePath, IReadOnlyList pagesBundle = null) + public static byte[] RemoveText(string filePath, IReadOnlyList? pagesBundle = null) { using (var output = new MemoryStream()) { @@ -34,7 +34,7 @@ public static byte[] RemoveText(string filePath, IReadOnlyList pagesBundle /// Path to PDF /// List of pages to emit; if null all pages are emitted ///
- public static void RemoveText(Stream output, string filePath, IReadOnlyList pagesBundle = null) + public static void RemoveText(Stream output, string filePath, IReadOnlyList? pagesBundle = null) { using (var stream = File.OpenRead(filePath)) { @@ -48,7 +48,7 @@ public static void RemoveText(Stream output, string filePath, IReadOnlyList /// List of pages to emit; if null all pages are emitted /// PDF without text (as a byte array) ///
- public static byte[] RemoveText(byte[] file, IReadOnlyList pagesBundle = null) + public static byte[] RemoveText(byte[] file, IReadOnlyList? pagesBundle = null) { _ = file ?? throw new ArgumentNullException(nameof(file)); @@ -66,7 +66,7 @@ public static byte[] RemoveText(byte[] file, IReadOnlyList pagesBundle = nu /// Must be writable /// List of pages to emit; if null all pages are emitted ///
- public static void RemoveText(Stream stream, Stream output, IReadOnlyList pagesBundle = null) + public static void RemoveText(Stream stream, Stream output, IReadOnlyList? pagesBundle = null) { _ = stream ?? throw new ArgumentNullException(nameof(stream)); _ = output ?? throw new ArgumentNullException(nameof(output)); @@ -81,7 +81,7 @@ public static void RemoveText(Stream stream, Stream output, IReadOnlyList p /// Must be writable /// List of pages to emit; if null all pages are emitted ///
- public static void RemoveText(PdfDocument file, Stream output, IReadOnlyList pagesBundle = null) + public static void RemoveText(PdfDocument file, Stream output, IReadOnlyList? pagesBundle = null) { var tokenWriter = new NoTextTokenWriter(); using (var document = new PdfDocumentBuilder(output, false, PdfWriterType.Default, file.Version, tokenWriter: tokenWriter)) diff --git a/src/UglyToad.PdfPig/Writer/TokenWriter.cs b/src/UglyToad.PdfPig/Writer/TokenWriter.cs index 3a084c92e..5097bf6c0 100644 --- a/src/UglyToad.PdfPig/Writer/TokenWriter.cs +++ b/src/UglyToad.PdfPig/Writer/TokenWriter.cs @@ -164,7 +164,7 @@ public void WriteCrossReferenceTable(IReadOnlyDictionary + var items = new List { // Zero entry null @@ -181,7 +181,7 @@ public void WriteCrossReferenceTable(IReadOnlyDictionary + items = new List { new XrefSeries.OffsetAndGeneration(item.Value, item.Key.Generation) }; @@ -661,9 +661,9 @@ private class XrefSeries { public long First { get; } - public IReadOnlyList Offsets { get; } + public IReadOnlyList Offsets { get; } - public XrefSeries(long first, IReadOnlyList offsets) + public XrefSeries(long first, IReadOnlyList offsets) { First = first; Offsets = offsets; diff --git a/src/UglyToad.PdfPig/Writer/WriterUtil.cs b/src/UglyToad.PdfPig/Writer/WriterUtil.cs index 38ce82711..52cbe4b4d 100644 --- a/src/UglyToad.PdfPig/Writer/WriterUtil.cs +++ b/src/UglyToad.PdfPig/Writer/WriterUtil.cs @@ -1,12 +1,12 @@ namespace UglyToad.PdfPig.Writer { - using Content; - using Core; - using Parser.Parts; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using Content; + using Core; + using Parser.Parts; using Tokenization.Scanner; using Tokens; @@ -72,13 +72,10 @@ public static Dictionary GetOrCreateDict(this DictionaryCall stack of indirect references /// A reference of the token that was copied. With all the reference updated public static IToken CopyToken(IPdfStreamWriter writer, IToken tokenToCopy, IPdfTokenScanner tokenScanner, - IDictionary referencesFromDocument, Dictionary callstack=null) + IDictionary referencesFromDocument, Dictionary? callstack = null) { - if (callstack is null) - { - callstack = new Dictionary(); - } - + callstack ??= []; + // This token need to be deep copied, because they could contain reference. So we have to update them. switch (tokenToCopy) { @@ -127,9 +124,9 @@ public static IToken CopyToken(IPdfStreamWriter writer, IToken tokenToCopy, IPdf // referencesFromDocument.Add(referenceToken.Data, newReferenceToken); // var tokenObject = DirectObjectFinder.Get(referenceToken.Data, tokenScanner); - if (tokenObject is null) //NullToken allowed + if (tokenObject is null) // NullToken allowed { - return null; + return null!; } Debug.Assert(!(tokenObject is IndirectReferenceToken)); @@ -137,7 +134,7 @@ public static IToken CopyToken(IPdfStreamWriter writer, IToken tokenToCopy, IPdf if (callstack[referenceToken.Data] != null) { - return writer.WriteToken(result, callstack[referenceToken.Data]); + return writer.WriteToken(result, callstack[referenceToken.Data]!); } newReferenceToken = writer.WriteToken(result); @@ -164,7 +161,7 @@ public static IToken CopyToken(IPdfStreamWriter writer, IToken tokenToCopy, IPdf return tokenToCopy; } - internal static IEnumerable<(DictionaryToken, IReadOnlyList)> WalkTree(PageTreeNode node, List parents=null) + internal static IEnumerable<(DictionaryToken, IReadOnlyList)> WalkTree(PageTreeNode node, List? parents = null) { if (parents is null) { @@ -179,7 +176,7 @@ public static IToken CopyToken(IPdfStreamWriter writer, IToken tokenToCopy, IPdf parents = parents.ToList(); parents.Add(node.NodeDictionary); - foreach (var child in node.Children) + foreach (var child in node.Children!) { foreach (var item in WalkTree(child, parents)) { diff --git a/src/UglyToad.PdfPig/Writer/Xmp/XmpWriter.cs b/src/UglyToad.PdfPig/Writer/Xmp/XmpWriter.cs index 1d3bf1b26..abc7bab03 100644 --- a/src/UglyToad.PdfPig/Writer/Xmp/XmpWriter.cs +++ b/src/UglyToad.PdfPig/Writer/Xmp/XmpWriter.cs @@ -38,8 +38,10 @@ internal static class XmpWriter private const string PdfAIdentificationExtensionPrefix = "pdfaid"; private const string PdfAIdentificationExtensionNamespace = "http://www.aiim.org/pdfa/ns/id/"; - public static StreamToken GenerateXmpStream(PdfDocumentBuilder.DocumentInformationBuilder builder, double version, - PdfAStandard standard, XDocument additionalXmpMetadata) + public static StreamToken GenerateXmpStream( + PdfDocumentBuilder.DocumentInformationBuilder builder, + double version, + PdfAStandard standard, XDocument? additionalXmpMetadata) { XNamespace xmpMeta = XmpMetaNamespace; XNamespace rdf = RdfNamespace; @@ -84,7 +86,7 @@ public static StreamToken GenerateXmpStream(PdfDocumentBuilder.DocumentInformati pdfAIdContainer ) ) - ), additionalXmpMetadata); + ), additionalXmpMetadata!); var xml = document.ToString(SaveOptions.None).Replace("\r\n", "\n"); xml = $"\n{xml}\n"; @@ -226,13 +228,13 @@ private static XElement GetSchemaPropertyListItem(XNamespace rdfNs, return li; } - private class SchemaMapper + private sealed class SchemaMapper { public string Name { get; } - public Func ValueFunc { get; } + public Func ValueFunc { get; } - public SchemaMapper(string name, Func valueFunc) + public SchemaMapper(string name, Func valueFunc) { Name = name; ValueFunc = valueFunc; diff --git a/src/UglyToad.PdfPig/XObjects/XObjectFactory.cs b/src/UglyToad.PdfPig/XObjects/XObjectFactory.cs index ccdd8ae04..60f5656ed 100644 --- a/src/UglyToad.PdfPig/XObjects/XObjectFactory.cs +++ b/src/UglyToad.PdfPig/XObjects/XObjectFactory.cs @@ -42,7 +42,7 @@ public static XObjectImage ReadImage(XObjectContentRecord xObject, IPdfTokenScan var width = dictionary.Get(NameToken.Width, pdfScanner).Int; var height = dictionary.Get(NameToken.Height, pdfScanner).Int; - var isImageMask = dictionary.TryGet(NameToken.ImageMask, pdfScanner, out BooleanToken isMaskToken) + var isImageMask = dictionary.TryGet(NameToken.ImageMask, pdfScanner, out BooleanToken? isMaskToken) && isMaskToken.Data; var isJpxDecode = dictionary.TryGet(NameToken.Filter, out var token) @@ -52,7 +52,7 @@ public static XObjectImage ReadImage(XObjectContentRecord xObject, IPdfTokenScan int bitsPerComponent = 0; if (!isImageMask && !isJpxDecode) { - if (!dictionary.TryGet(NameToken.BitsPerComponent, pdfScanner, out NumericToken bitsPerComponentToken)) + if (!dictionary.TryGet(NameToken.BitsPerComponent, pdfScanner, out NumericToken? bitsPerComponentToken)) { throw new PdfDocumentFormatException($"No bits per component defined for image: {dictionary}."); } @@ -70,18 +70,18 @@ public static XObjectImage ReadImage(XObjectContentRecord xObject, IPdfTokenScan intent = renderingIntentToken.Data.ToRenderingIntent(); } - var interpolate = dictionary.TryGet(NameToken.Interpolate, pdfScanner, out BooleanToken interpolateToken) + var interpolate = dictionary.TryGet(NameToken.Interpolate, pdfScanner, out BooleanToken? interpolateToken) && interpolateToken.Data; - DictionaryToken filterDictionary = xObject.Stream.StreamDictionary; + DictionaryToken? filterDictionary = xObject.Stream.StreamDictionary; if (xObject.Stream.StreamDictionary.TryGet(NameToken.Filter, out var filterToken) && filterToken is IndirectReferenceToken) { - if (filterDictionary.TryGet(NameToken.Filter, pdfScanner, out ArrayToken filterArray)) + if (filterDictionary.TryGet(NameToken.Filter, pdfScanner, out ArrayToken? filterArray)) { filterDictionary = filterDictionary.With(NameToken.Filter, filterArray); } - else if (filterDictionary.TryGet(NameToken.Filter, pdfScanner, out NameToken filterNameToken)) + else if (filterDictionary.TryGet(NameToken.Filter, pdfScanner, out NameToken? filterNameToken)) { filterDictionary = filterDictionary.With(NameToken.Filter, filterNameToken); } @@ -118,21 +118,21 @@ public static XObjectImage ReadImage(XObjectContentRecord xObject, IPdfTokenScan var decode = Array.Empty(); - if (dictionary.TryGet(NameToken.Decode, pdfScanner, out ArrayToken decodeArrayToken)) + if (dictionary.TryGet(NameToken.Decode, pdfScanner, out ArrayToken? decodeArrayToken)) { decode = decodeArrayToken.Data.OfType() .Select(x => x.Double) .ToArray(); } - ColorSpaceDetails details = null; + ColorSpaceDetails? details = null; if (!isImageMask) { - if (dictionary.TryGet(NameToken.ColorSpace, pdfScanner, out NameToken colorSpaceNameToken)) + if (dictionary.TryGet(NameToken.ColorSpace, pdfScanner, out NameToken? colorSpaceNameToken)) { details = resourceStore.GetColorSpaceDetails(colorSpaceNameToken, dictionary); } - else if (dictionary.TryGet(NameToken.ColorSpace, pdfScanner, out ArrayToken colorSpaceArrayToken) + else if (dictionary.TryGet(NameToken.ColorSpace, pdfScanner, out ArrayToken? colorSpaceArrayToken) && colorSpaceArrayToken.Length > 0 && colorSpaceArrayToken.Data[0] is NameToken firstColorSpaceName) { details = resourceStore.GetColorSpaceDetails(firstColorSpaceName, dictionary); diff --git a/src/UglyToad.PdfPig/XObjects/XObjectImage.cs b/src/UglyToad.PdfPig/XObjects/XObjectImage.cs index c2fff8e77..866d0fac9 100644 --- a/src/UglyToad.PdfPig/XObjects/XObjectImage.cs +++ b/src/UglyToad.PdfPig/XObjects/XObjectImage.cs @@ -2,13 +2,13 @@ { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using Content; using Core; using Graphics.Colors; using Graphics.Core; using Images.Png; using Tokens; - using Util.JetBrains.Annotations; /// /// @@ -16,8 +16,7 @@ /// public class XObjectImage : IPdfImage { - [CanBeNull] - private readonly Lazy> bytesFactory; + private readonly Lazy>? bytesFactory; /// public PdfRectangle Bounds { get; } @@ -54,14 +53,13 @@ public class XObjectImage : IPdfImage public bool IsInlineImage { get; } = false; /// - [NotNull] public DictionaryToken ImageDictionary { get; } /// public IReadOnlyList RawBytes { get; } /// - public ColorSpaceDetails ColorSpaceDetails { get; } + public ColorSpaceDetails? ColorSpaceDetails { get; } /// /// Creates a new . @@ -77,8 +75,8 @@ internal XObjectImage(PdfRectangle bounds, IReadOnlyList decode, DictionaryToken imageDictionary, IReadOnlyList rawBytes, - Lazy> bytes, - ColorSpaceDetails colorSpaceDetails) + Lazy>? bytes, + ColorSpaceDetails? colorSpaceDetails) { Bounds = bounds; WidthInSamples = widthInSamples; @@ -96,7 +94,7 @@ internal XObjectImage(PdfRectangle bounds, } /// - public bool TryGetBytes(out IReadOnlyList bytes) + public bool TryGetBytes([NotNullWhen(true)] out IReadOnlyList? bytes) { bytes = null; if (bytesFactory is null) @@ -110,7 +108,7 @@ public bool TryGetBytes(out IReadOnlyList bytes) } /// - public bool TryGetPng(out byte[] bytes) => PngFromPdfImageFactory.TryGenerate(this, out bytes); + public bool TryGetPng([NotNullWhen(true)] out byte[]? bytes) => PngFromPdfImageFactory.TryGenerate(this, out bytes); /// public override string ToString() diff --git a/tools/UglyToad.PdfPig.Package/UglyToad.PdfPig.Package.csproj b/tools/UglyToad.PdfPig.Package/UglyToad.PdfPig.Package.csproj index ca928db3a..eeb2403ee 100644 --- a/tools/UglyToad.PdfPig.Package/UglyToad.PdfPig.Package.csproj +++ b/tools/UglyToad.PdfPig.Package/UglyToad.PdfPig.Package.csproj @@ -1,6 +1,6 @@ - netstandard2.0;net451;net452;net46;net461;net462;net47;net6.0 + netstandard2.0;net462;net471;net6.0;net8.0 PdfPig full UglyToad