From 5fbf6ed14740bc4e16786816882d32e43af3ff5d Mon Sep 17 00:00:00 2001 From: PDFsharp-Team Date: Tue, 13 Aug 2024 12:11:02 +0200 Subject: [PATCH] =?UTF-8?q?=E2=80=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PdfSharp.sln | 47 ++ PdfSharp.sln.DotSettings | 3 + README.md | 10 +- dev/run-tests.ps1 | 88 ++- docs/BeforeReleases.md | 75 +++ docs/BoilerplateText.md | 4 +- docs/DevNotes.md | 6 +- docs/MakeNewReleaseNotes.md | 2 +- docs/MigraDoc/AboutLineSpacing.md | 33 + docs/README.md | 3 + docs/Signatures/CertificateCreation.md | 53 ++ docs/changes/v6.2.0-log.md | 48 ++ gitversion.yml | 6 +- src/Directory.Build.targets | 2 +- src/Directory.Packages.props | 181 +++--- src/dotnet-test.Build.props | 34 +- .../nuget/src/Directory.Build.props | 106 ++-- .../Dummy-PDFsharp.NuGet-wpf.csproj | 2 +- .../MigraDoc.NuGet-gdi.csproj | 3 +- .../MigraDoc.NuGet-gdi.nuspec | 25 +- .../src/MigraDoc.NuGet-gdi/ReleaseNotes.txt | 2 +- .../MigraDoc.NuGet-wpf.csproj | 3 +- .../MigraDoc.NuGet-wpf.nuspec | 25 +- .../src/MigraDoc.NuGet-wpf/ReleaseNotes.txt | 2 +- .../src/MigraDoc.NuGet/MigraDoc.NuGet.csproj | 3 +- .../src/MigraDoc.NuGet/MigraDoc.NuGet.nuspec | 20 +- .../nuget/src/MigraDoc.NuGet/ReleaseNotes.txt | 2 +- .../PDFsharp.NuGet-gdi.csproj | 3 +- .../PDFsharp.NuGet-gdi.nuspec | 20 +- .../src/PDFsharp.NuGet-gdi/ReleaseNotes.txt | 4 +- .../PDFsharp.NuGet-wpf.csproj | 3 +- .../PDFsharp.NuGet-wpf.nuspec | 20 +- .../src/PDFsharp.NuGet-wpf/ReleaseNotes.txt | 4 +- .../src/PDFsharp.NuGet/PDFsharp.NuGet.csproj | 4 +- .../src/PDFsharp.NuGet/PDFsharp.NuGet.nuspec | 15 +- .../nuget/src/PDFsharp.NuGet/ReleaseNotes.txt | 4 +- src/foundation/src/MigraDoc/docs/.gitkeep | 0 .../Capabilities.cs | 2 +- .../BookmarkField.cs | 2 +- .../DocumentObjectModel.Fields/InfoField.cs | 4 +- .../NumericFieldBase.cs | 6 +- .../DocumentObjectModel.IO/DdlParser.cs | 555 ++++++++--------- .../DdlParserException.cs | 50 +- .../DocumentObjectModel.IO/DdlReader.cs | 17 +- .../DocumentObjectModel.IO/DdlReaderError.cs | 49 +- .../DocumentObjectModel.IO/DdlReaderErrors.cs | 7 +- .../DocumentObjectModel.IO/DdlScanner.cs | 261 ++++---- .../DocumentObjectModel.IO/DdlWriter.cs | 25 +- .../DocumentObjectModel.IO/Symbols.cs | 11 +- .../ErrorHelpers.cs | 42 +- .../DocumentObjectModel.Internals/Meta.cs | 43 +- .../ValueDescriptor.cs | 3 +- .../Messages.de.restext | 71 --- .../Messages.restext | 70 --- .../Gridlines.cs | 4 +- .../SeriesCollection.cs | 2 +- .../SeriesElements.cs | 2 +- .../XValues.cs | 2 +- .../DocumentObjectModel.Shapes/Barcode.cs | 2 +- .../DocumentObjectModel.Shapes/Image.cs | 8 +- .../LeftPosition.cs | 4 +- .../DocumentObjectModel.Shapes/TopPosition.cs | 4 +- .../DocumentObjectModel.Tables/Cell.cs | 5 +- .../DocumentObjectModel.Tables/Column.cs | 8 +- .../DocumentObjectModel.Tables/Row.cs | 21 +- .../CellComparer.cs | 1 - .../ElementsExtensions.cs | 1 - .../MergedCellList.cs | 12 +- .../PdfFlattenVisitor.cs | 9 +- .../VisitorBase.cs | 2 +- .../DocumentObjectModel/Borders.cs | 4 +- .../DocumentObjectModel/Chars.cs | 36 +- .../DocumentObjectModel/Color.cs | 28 +- .../DocumentObjectModel/DdlEncoder.cs | 6 +- .../DocumentObjectModel/Document.cs | 4 - .../DocumentObjectModel/DocumentObject.cs | 2 +- .../DocumentObjectCollection.cs | 16 +- .../DocumentObjectModel/DomSR.cs | 212 ------- .../DocumentObjectModel/EmbeddedFiles.cs | 2 +- .../DocumentObjectModel/Font.cs | 2 +- .../DocumentObjectModel/HeadersFooters.cs | 17 +- .../DocumentObjectModel/Hyperlink.cs | 6 +- .../DocumentObjectModel/ImageHelper.cs | 14 +- .../DocumentObjectModel/MdDomMsg.cs | 21 + .../DocumentObjectModel/MdDomMsgs.cs | 200 +++++++ .../DocumentObjectModel/Paragraph.cs | 4 +- .../DocumentObjectModel/ParagraphElements.cs | 2 +- .../DocumentObjectModel/Sections.cs | 5 +- .../DocumentObjectModel/Style.cs | 4 +- .../DocumentObjectModel/Styles.cs | 11 +- .../DocumentObjectModel/TabStops.cs | 2 - .../DocumentObjectModel/Unit.cs | 26 +- .../enums/{DomMsgID.cs => MdDomMsgId.cs} | 26 +- .../MigraDoc.DocumentObjectModel.csproj | 23 +- .../MigraDocProductVersionInformation.cs | 2 + .../MigraDoc.DocumentObjectModel/README.md | 6 + .../MigraDoc.Rendering-gdi.csproj | 175 ++++-- .../src/MigraDoc.Rendering-gdi/README.md | 2 + .../MigraDoc.Rendering-wpf.csproj | 373 ++++-------- .../src/MigraDoc.Rendering-wpf/README.md | 2 + .../MigraDoc.Rendering.csproj | 29 +- .../Properties/VersionInfo.cs | 20 - .../MigraDoc/src/MigraDoc.Rendering/README.md | 2 + .../Rendering.Resources/Messages.de.restext | 21 - .../Rendering.Resources/Messages.restext | 16 - .../Rendering.Resources/Messages2.cs | 128 ---- .../Rendering.UnitTest/TestLayout.cs | 2 +- .../TestParagraphRenderer.cs | 4 +- .../Rendering.Windows/DocumentPreview.xaml.cs | 2 +- .../Rendering/BordersRenderer.cs | 4 +- .../Rendering/DocumentRenderer.cs | 8 +- .../Rendering/ImageRenderer.cs | 17 +- .../MigraDoc.Rendering/Rendering/MdPdfMsg.cs | 21 + .../MdPdfMsg.de.resx} | 0 .../MdPdfMsg.resx} | 0 .../MigraDoc.Rendering/Rendering/MdPdfMsgs.cs | 78 +++ .../Rendering/MdPdfMsgs.de.resx} | 62 +- .../Rendering/MdPdfMsgs.resx | 160 +++++ .../MigraDocRenderingBuildInformation.cs | 6 +- .../Rendering/NumberFormatter.cs | 20 +- .../Rendering/ParagraphFormatInfo.cs | 10 +- .../Rendering/ParagraphIterator.cs | 8 +- .../Rendering/ParagraphRenderer.cs | 14 +- .../Rendering/PdfDocumentRenderer.cs | 35 +- .../Rendering/TableRenderer.cs | 4 +- .../Rendering/TopDownFormatter.cs | 9 +- .../MigraDoc.RtfRendering-gdi.csproj | 227 ++----- .../MigraDoc.RtfRendering-gdi.csproj.txt | 332 ---------- .../MigraDoc.RtfRendering-wpf.csproj | 236 ++------ .../MigraDoc.RtfRendering.csproj | 24 +- .../Properties/VersionInfo.cs | 17 - .../Messages.de.restext | 17 - .../RtfRendering.Resources/Messages.restext | 16 - .../RtfRendering.Resources/Messages2.cs | 115 ---- .../RtfRendering.Resources/Messages2.resx | 148 ----- .../RtfRendering/BookmarkFieldRenderer.cs | 6 +- .../RtfRendering/CellFormatRenderer.cs | 2 +- .../RtfRendering/CharacterRenderer.cs | 32 +- .../RtfRendering/ChartRenderer.cs | 181 +++--- .../RtfRendering/DateFieldRenderer.cs | 5 +- .../RtfRendering/FieldRenderer.cs | 3 +- .../RtfRendering/ImageRenderer.cs | 13 +- .../RtfRendering/MdRtfMsg.cs | 18 + .../RtfRendering/MdRtfMsgs.cs | 58 ++ .../RtfRendering/NumericFieldRendererBase.cs | 4 +- .../RtfRendering/RendererBase.cs | 1 - .../RtfRendering/RowRenderer.cs | 2 +- .../RtfRendering/RtfDocumentRenderer.cs | 137 ++--- .../RtfRendering/TextFrameRenderer.cs | 3 +- .../MigraDoc.DocumentObjectModel.Tests.csproj | 2 +- .../SerializerTests.cs | 109 ++++ .../ddlparser/BasicTests.cs | 50 +- .../MigraDoc.GBE-Runner.csproj | 2 +- .../MigraDoc.GrammarByExample-GDI.csproj | 2 +- .../MigraDoc.GrammarByExample-WPF.csproj | 2 +- .../MigraDoc.GrammarByExample.csproj | 2 +- .../helper/DdlGbeTestBase.cs | 5 +- .../helper/DdlToPdfHelper.cs | 32 +- .../helper/TestContext.cs | 13 +- .../helper/VisualComparisonTestBase.cs | 41 +- .../MigraDoc.Tests-gdi.csproj | 122 ++-- .../MigraDoc.Tests-wpf.csproj | 108 ++-- .../MigraDoc.Tests/Extensions/XunitHelper.cs | 2 +- .../Helper/SecurityTestHelper.cs | 67 +++ .../tests/MigraDoc.Tests/ImageFormats.cs | 15 +- .../MigraDoc.Tests/MigraDoc.Tests.csproj | 6 +- .../MigraDoc.Tests.csproj.DotSettings | 2 +- .../tests/MigraDoc.Tests/PageSizeTests.cs | 88 +++ .../tests/MigraDoc.Tests/RtfRendererTests.cs | 16 - .../tests/MigraDoc.Tests/SecurityTests.cs | 4 +- .../tests/MigraDoc.Tests/SpaceBeforeTests.cs | 4 +- .../tests/MigraDoc.Tests/TableTests.cs | 53 ++ .../src/PDFsharp/docs/AboutFonts.md | 6 +- .../src/PDFsharp/docs/AboutImages.md | 2 +- .../src/PDFsharp/docs/Coding-Issues.md | 56 ++ src/foundation/src/PDFsharp/docs/Notebook.md | 9 +- .../src/PDFsharp/docs/PortingNotes.md | 10 +- src/foundation/src/PDFsharp/docs/README.md | 3 + .../src/PDFsharp/docs/pdf-features/PDF-A.md | 9 + .../src/PDFsharp/docs/pdf/Strings.md | 7 + .../PDFsharp.Features-gdi.csproj | 4 +- .../PDFsharp.Features-wpf.csproj | 4 +- .../PDFsharp.Features.Runner-gdi.csproj | 2 +- .../PDFsharp.Features.Runner-wpf.csproj | 2 +- .../PdfSharp.Features.Runner.csproj | 4 +- .../PdfSharp.Features.Runner/Program.cs | 10 +- .../PdfSharp.Features/Drawing/lines/Lines1.cs | 2 +- .../Font/RenderInstalledFonts.cs | 10 +- .../Font/RotisWinAnsiTester.cs | 2 +- .../Pdf/annotations/LinkAnnotations.cs | 2 +- .../PdfSharp.Features/Pdf/pdfa/PDF-A.cs | 79 +++ .../PdfSharp.Features.csproj.DotSettings | 3 +- .../PdfSharp.Features/PdfSharpFeatures.cs | 11 + .../src/PdfSharp-gdi/PdfSharp-gdi.csproj | 45 +- .../src/PdfSharp-wpf/PdfSharp-wpf.csproj | 48 +- .../PdfSharp.Charting-gdi.csproj | 407 ++++--------- .../PdfSharp.Charting-gdi.csproj - save | 300 ++++++++++ .../PdfSharp.Charting-wpf.csproj | 408 ++++--------- .../Charting.Renderers/AreaChartRenderer.cs | 2 +- .../Charting.Renderers/BarChartRenderer.cs | 2 +- .../Charting.Renderers/Colors.cs | 40 +- .../Charting.Renderers/ColumnChartRenderer.cs | 2 +- .../CombinationChartRenderer.cs | 2 +- .../HorizontalXAxisRenderer.cs | 6 +- .../HorizontalYAxisRenderer.cs | 4 +- .../Charting.Renderers/LineChartRenderer.cs | 2 +- .../Charting.Renderers/PieChartRenderer.cs | 2 +- .../VerticalXAxisRenderer.cs | 4 +- .../VerticalYAxisRenderer.cs | 4 +- .../src/PdfSharp.Charting/Charting/Axis.cs | 4 +- .../PdfSharp.Charting/Charting/DataLabel.cs | 4 +- .../Charting/DocumentObjectCollection.cs | 4 +- .../src/PdfSharp.Charting/Charting/Legend.cs | 2 +- .../src/PdfSharp.Charting/Charting/Point.cs | 10 - .../src/PdfSharp.Charting/Charting/Series.cs | 4 +- .../src/PdfSharp.Charting/Charting/XSeries.cs | 1 - .../PdfSharp.Charting.csproj | 12 +- .../Resources/Messages.de.restext | 8 +- .../Resources/Messages.restext | 8 +- .../src/PdfSharp/!internal/Directives.cs | 4 +- .../src/PdfSharp/!internal/TargetContext.cs | 1 + .../src/PdfSharp/Drawing.BarCodes/BarCode.cs | 2 +- .../Drawing.BarCodes/Code2of5Interleaved.cs | 28 +- .../Drawing.BarCodes/Code3of9Standard.cs | 94 +-- .../src/PdfSharp/Drawing.BarCodes/CodeOmr.cs | 2 +- .../Drawing.BarCodes/DataMatrixImage.cs | 70 +-- .../ThickThinBarcodeRenderer.cs | 4 +- .../Drawing.Internal/ImageImporter.cs | 10 +- .../Drawing.Internal/ImageImporterJpeg.cs | 6 +- .../Drawing.Internal/ImageImporterPng.cs | 39 +- .../PdfSharp/Drawing.Layout/XTextFormatter.cs | 2 +- .../PdfSharp/Drawing.Pdf/PdfGraphicsState.cs | 1 + .../Drawing.Pdf/XGraphicsPdfRenderer.cs | 217 +++++-- .../src/PdfSharp/Drawing/CoreGraphicsPath.cs | 4 +- .../src/PdfSharp/Drawing/GeometryHelper.cs | 12 +- .../PdfSharp/Drawing/InternalGraphicsState.cs | 1 - .../src/PdfSharp/Drawing/PdfFontOptions.cs | 48 +- .../src/PdfSharp/Drawing/XBitmapDecoder.cs | 2 +- .../src/PdfSharp/Drawing/XBitmapEncoder.cs | 2 +- .../src/PdfSharp/Drawing/XBitmapImage.cs | 4 +- .../src/PdfSharp/Drawing/XBitmapSource.cs | 6 +- .../PDFsharp/src/PdfSharp/Drawing/XBrush.cs | 4 +- .../PDFsharp/src/PdfSharp/Drawing/XColor.cs | 14 +- .../PdfSharp/Drawing/XColorResourceManager.cs | 344 +++++------ .../PDFsharp/src/PdfSharp/Drawing/XConvert.cs | 8 +- .../PDFsharp/src/PdfSharp/Drawing/XFont.cs | 10 +- .../src/PdfSharp/Drawing/XFontFamily.cs | 4 +- .../src/PdfSharp/Drawing/XFontSource.cs | 10 +- .../src/PdfSharp/Drawing/XFontWeight.cs | 2 +- .../src/PdfSharp/Drawing/XGlyphTypeface.cs | 18 +- .../src/PdfSharp/Drawing/XGradientBrush.cs | 2 +- .../src/PdfSharp/Drawing/XGraphics.cs | 168 +++--- .../src/PdfSharp/Drawing/XGraphicsPath.cs | 70 ++- .../Drawing/XGraphicsPathInternals.cs | 4 +- .../PDFsharp/src/PdfSharp/Drawing/XImage.cs | 104 +++- .../PdfSharp/Drawing/XLinearGradientBrush.cs | 6 +- .../PDFsharp/src/PdfSharp/Drawing/XMatrix.cs | 50 +- .../PDFsharp/src/PdfSharp/Drawing/XPdfForm.cs | 2 +- .../src/PDFsharp/src/PdfSharp/Drawing/XPen.cs | 22 +- .../PDFsharp/src/PdfSharp/Drawing/XPoint.cs | 8 +- .../Drawing/XPrivateFontCollection.cs | 401 ------------- .../PdfSharp/Drawing/XRadialGradientBrush.cs | 4 +- .../PDFsharp/src/PdfSharp/Drawing/XRect.cs | 12 +- .../PDFsharp/src/PdfSharp/Drawing/XSize.cs | 18 +- .../src/PdfSharp/Drawing/XSolidBrush.cs | 9 +- .../PDFsharp/src/PdfSharp/Drawing/XUnit.cs | 16 +- .../PDFsharp/src/PdfSharp/Drawing/XVector.cs | 1 - .../Drawing/enums/XGraphicRenderTarget.cs | 2 +- .../src/PdfSharp/Events/RenderEvents.cs | 48 +- .../src/PdfSharp/Fonts.Internal/FontHelper.cs | 4 +- .../PdfSharp/Fonts.Internal/UnicodeHelper.cs | 2 +- .../Fonts.OpenType/OpenTypeDescriptor.cs | 68 ++- .../Fonts.OpenType/OpenTypeFontTable.cs | 6 - .../Fonts.OpenType/OpenTypeFontTables.cs | 199 +++++- .../Fonts.OpenType/OpenTypeFontface.cs | 124 ++-- .../Fonts.OpenType/enums/TableTagNames.cs | 28 +- .../PdfSharp/Fonts/CodePointGlyphIndexPair.cs | 18 + .../PdfSharp/Fonts/CoreBuildFontResolver.cs | 8 + .../src/PdfSharp/Fonts/GlyphHelper.cs | 2 +- .../PdfSharp/Fonts/PlatformFontResolver.cs | 8 +- .../Fonts/PlatformFontResolverInfo.cs | 2 +- .../PDFsharp/src/PdfSharp/Internal/Calc.cs | 34 +- .../src/PdfSharp/Internal/DotNetHelper.cs | 15 +- .../src/PdfSharp/Internal/DoubleUtil.cs | 2 +- .../PDFsharp/src/PdfSharp/Internal/PsMsg.cs | 22 + .../PDFsharp/src/PdfSharp/Internal/PsMsgs.cs | 183 ++++++ .../PSMsgID.cs => Internal/enums/PsMsgId.cs} | 11 +- .../src/PdfSharp/Logging/LogMessages.cs | 54 +- .../PdfSharp/Pdf.AcroForms/PdfAcroField.cs | 6 +- .../PdfSharp/Pdf.AcroForms/PdfButtonField.cs | 1 - .../Pdf.AcroForms/PdfSignatureField.cs | 59 +- .../Pdf.Actions/PdfEmbeddedGoToAction.cs | 1 + .../src/PdfSharp/Pdf.Advanced/PdfCatalog.cs | 11 +- .../src/PdfSharp/Pdf.Advanced/PdfContents.cs | 2 +- .../Pdf.Advanced/PdfCrossReferenceTable.cs | 18 +- .../Pdf.Advanced/PdfEmbeddedFileStream.cs | 1 - .../src/PdfSharp/Pdf.Advanced/PdfExtGState.cs | 16 + .../Pdf.Advanced/PdfFontDescriptor.cs | 7 +- .../PdfSharp/Pdf.Advanced/PdfFontProgram.cs | 4 +- .../PdfSharp/Pdf.Advanced/PdfFormXObject.cs | 2 +- .../Pdf.Advanced/PdfImage.FaxEncode.cs | 566 +++++++++--------- .../src/PdfSharp/Pdf.Advanced/PdfImage.cs | 192 ++++-- .../PdfSharp/Pdf.Advanced/PdfImageTable.cs | 10 +- .../src/PdfSharp/Pdf.Advanced/PdfInternals.cs | 6 +- .../PdfNamedDestinationParameters.cs | 6 +- .../PdfSharp/Pdf.Advanced/PdfTilingPattern.cs | 2 +- .../src/PdfSharp/Pdf.Advanced/PdfType0Font.cs | 2 +- .../IAnnotationAppearanceHandler.cs | 20 + .../PdfSharp/Pdf.Content.Objects/CObjects.cs | 3 +- .../src/PdfSharp/Pdf.Content/CLexer.cs | 17 +- .../src/PdfSharp/Pdf.Content/CParser.cs | 2 +- .../src/PdfSharp/Pdf.Content/ContentWriter.cs | 4 +- .../src/PdfSharp/Pdf.Filters/FlateDecode.cs | 6 +- .../src/PdfSharp/Pdf.Filters/LzwDecode.cs | 2 +- .../src/PdfSharp/Pdf.Filters/PngFilter.cs | 1 - .../src/PDFsharp/src/PdfSharp/Pdf.IO/Lexer.cs | 24 +- .../PDFsharp/src/PdfSharp/Pdf.IO/Parser.cs | 66 +- .../PDFsharp/src/PdfSharp/Pdf.IO/PdfReader.cs | 14 +- .../PDFsharp/src/PdfSharp/Pdf.IO/PdfWriter.cs | 110 ++-- .../PdfSharp/Pdf.Internal/ColorSpaceHelper.cs | 4 +- .../src/PdfSharp/Pdf.Internal/DocEncoding.cs | 14 +- .../src/PdfSharp/Pdf.Internal/PdfEncoders.cs | 61 +- .../PdfEncryptionBase.cs | 0 .../PdfEncryptionV1To4.cs | 7 +- .../PdfEncryptionV5.cs | 38 +- .../RC4.cs | 0 .../SASLprep.cs | 0 .../PdfSharp/Pdf.Security/PdfCryptFilters.cs | 6 +- .../Pdf.Security/PdfSecuritySettings.cs | 2 +- .../PdfStandardSecurityHandler.cs | 30 +- .../enums/PdfUserAccessPermission.cs | 19 +- .../DefaultSignatureAppearanceHandler.cs | 38 ++ .../Pdf.Signatures/DigitalSignatureOptions.cs | 49 ++ .../Pdf.Signatures/PdfArrayWithPadding.cs | 35 ++ .../PdfSharp/Pdf.Signatures/PdfSignature.cs | 33 + .../Pdf.Signatures/PdfSignatureHandler.cs | 243 ++++++++ .../PdfSignaturePlaceholderItem.cs | 51 ++ .../PdfSharp/Pdf.Signatures/RangedStream.cs | 141 +++++ .../src/PDFsharp/src/PdfSharp/Pdf/KeysBase.cs | 11 +- .../src/PDFsharp/src/PdfSharp/Pdf/PdfArray.cs | 17 +- .../src/PdfSharp/Pdf/PdfCustomValue.cs | 4 +- .../src/PDFsharp/src/PdfSharp/Pdf/PdfDate.cs | 5 + .../src/PdfSharp/Pdf/PdfDictionary.cs | 27 +- .../PDFsharp/src/PdfSharp/Pdf/PdfDocument.cs | 243 +++++--- .../PDFsharp/src/PdfSharp/Pdf/PdfMetadata.cs | 17 +- .../src/PDFsharp/src/PdfSharp/Pdf/PdfName.cs | 3 +- .../src/PdfSharp/Pdf/PdfNameObject.cs | 2 +- .../src/PdfSharp/Pdf/PdfNumberTreeNode.cs | 21 +- .../PDFsharp/src/PdfSharp/Pdf/PdfObject.cs | 8 +- .../src/PdfSharp/Pdf/PdfOutlineCollection.cs | 8 +- .../src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs | 261 ++++++-- .../src/PDFsharp/src/PdfSharp/Pdf/PdfPages.cs | 20 +- .../PDFsharp/src/PdfSharp/Pdf/PdfRectangle.cs | 3 +- .../PDFsharp/src/PdfSharp/Pdf/PdfString.cs | 31 +- .../Pdf/enums/PdfFontColoredGlyphs.cs | 27 + .../src/PDFsharp/src/PdfSharp/PdfSharp.csproj | 28 +- .../src/PdfSharp/PdfSharp.csproj.DotSettings | 5 +- .../src/PDFsharp/src/PdfSharp/PngLib/Adam7.cs | 28 +- .../PdfSharp/PngLib/HeaderValidationResult.cs | 5 +- .../src/PdfSharp/PngLib/ImageHeader.cs | 15 +- .../PdfSharp/Properties/GlobalDeclarations.cs | 2 + .../PdfSharpProductVersionInformation.cs | 6 +- .../PdfSharp/Resources/Messages.de.restext | 20 - .../src/PdfSharp/Resources/Messages.restext | 20 - .../src/PdfSharp/Resources/sRGB2014.icc | Bin 0 -> 3024 bytes .../StructureBuilder.cs | 105 +++- .../UniversalAccessibility/UAManager.cs | 17 +- .../src/PdfSharp/Windows/VisualPresenter.cs | 12 +- .../src/PdfSharp/root/Capabilities.cs | 25 +- .../src/PDFsharp/src/PdfSharp/root/PSSR.cs | 271 --------- .../src/PdfSharp/root/PdfSharpException.cs | 4 +- .../PDFsharp/src/PdfSharp/root/VersionInfo.cs | 23 - .../PdfSharp/root/enums/PageOrientation.cs | 6 +- .../src/PdfSharp/root/enums/PageRotation.cs | 31 + .../PdfSharp.Tests-gdi.csproj | 21 +- .../Build/CSharpFeaturesTests.cs | 3 +- .../PdfSharp.Tests/Build/ReleaseBuildTests.cs | 7 +- .../Drawing/images/ImageTests.cs | 43 +- .../PdfSharp.Tests/Drawing/text/TextTests.cs | 351 ++++++++++- .../PdfSharp.Tests/Encodings/EncodingTests.cs | 3 +- .../PdfSharp.Tests/Helper/XunitHelper.cs | 39 ++ .../tests/PdfSharp.Tests/IO/ReaderTests.cs | 82 ++- .../PdfSharp.Tests/Pdf/pdf-a/PdfATests.cs | 49 ++ .../Pdf/signatures/BouncyCastleSignerTests.cs | 133 ++++ .../Pdf/signatures/DefaultSignerTests.cs | 405 +++++++++++++ .../PdfSharp.Tests/PdfSharp.Tests.csproj | 22 +- .../PdfSharp.Tests.csproj.DotSettings | 5 +- .../PdfSharp.tests-wpf.csproj | 17 +- .../Pdf.Signatures/PdfSharpDefaultSigner.cs | 183 ++++++ .../Pdf.Signatures/PsCryptoMgs.cs | 22 + .../Pdf.Signatures/PsCryptoMsg.cs | 21 + .../Pdf.Signatures/enum/PsCryptoMsgId.cs | 21 + .../PdfSharp.Cryptography.csproj | 32 + .../PdfSharp.Cryptography.csproj.DotSettings | 2 + .../shared/src/PdfSharp.Crytography/README.md | 7 + .../src/PdfSharp.Fonts/PdfSharp.Fonts.csproj | 2 +- .../src/shared/src/PdfSharp.Fonts/README.md | 2 +- .../PdfSharp.Quality-gdi.csproj | 8 +- .../PdfSharp.Quality-wpf.csproj | 8 +- .../PdfSharp.Quality/FeatureAndSnippetBase.cs | 5 +- .../shared/src/PdfSharp.Quality/IOHelper.cs | 16 +- .../shared/src/PdfSharp.Quality/IOUtility.cs | 9 +- .../shared/src/PdfSharp.Quality/PathHelper.cs | 4 +- .../src/PdfSharp.Quality/PdfFileUtility.cs | 2 +- .../PdfSharp.Quality/PdfSharp.Quality.csproj | 6 +- .../shared/src/PdfSharp.Quality/Snippet.cs | 1 - .../Diagnostics/NullabilityHelper.cs | 48 ++ .../PdfSharp.Shared/Internal/BuildVersion.cs | 24 + .../PdfSharp.Shared/Internal/Configuration.cs | 14 + .../src/PdfSharp.Shared/Internal/SyMsg.cs | 25 + .../src/PdfSharp.Shared/Internal/SyMsgs.cs | 26 + .../Internal/TH.cs} | 32 +- .../PdfSharp.Shared/Internal/UrlLiterals.cs | 29 + .../PdfSharp.Shared/Internal/enum/SyMsgId.cs | 36 ++ .../PdfSharp.Shared/PdfSharp.Shared.csproj | 65 ++ .../PdfSharp.Shared.csproj.DotSettings | 2 + .../Properties/GlobalDeclarations.cs | 20 + .../src/shared/src/PdfSharp.Shared/README.md | 28 + .../System/CompilerServices.cs | 290 +++++++++ .../PdfSharp.Snippets-gdi.csproj | 10 +- .../PdfSharp.Snippets-wpf.csproj | 22 +- .../Drawing/colors/ColorsCmyk.cs | 48 +- .../Drawing/colors/ColorsRgb.cs | 48 +- .../Drawing/graphics/GraphicsFromImage.cs | 48 +- .../Drawing/graphics/GraphicsUnitUpwards.cs | 1 - .../Drawing/lines/LineStyle.cs | 2 +- .../Drawing/lines/LineTestsNew.cs | 2 +- .../Drawing/lines/LineTypes.cs | 2 +- .../Drawing/paths/PathMisc.cs | 2 +- .../Font/encoding/FontAnsiEncoding.cs | 23 +- .../Font/selection/ChineseFont.cs | 2 +- .../selection/DefaultConstructionSnippets.cs | 10 +- .../Font/selection/HelloWorldSnippets.cs | 2 +- .../PrivateFontCollectionSnippets.cs | 8 +- .../shared/src/PdfSharp.Snippets/Pangrams.cs | 2 +- .../Pdf/signatures/BouncyCastleSigner.cs | 136 +++++ .../PdfSharp.Snippets.csproj | 9 +- .../Diagnostics/NullabilityHelper.cs | 88 +-- .../IO/StreamToMemoryReader.cs | 29 + .../PdfSharp.System/Internal/BuildVersion.cs | 24 + .../PdfSharp.System/Internal/Configuration.cs | 24 +- .../src/PdfSharp.System/Internal/SyMgs.cs | 26 + .../src/PdfSharp.System/Internal/SyMsg.cs | 25 + .../shared/src/PdfSharp.System/Internal/TH.cs | 73 +++ .../PdfSharp.System/Internal/UrlLiterals.cs | 53 +- .../PdfSharp.System/Internal/enum/SyMsgId.cs | 34 ++ .../Pdf.Signatures/IDigitalSigner.cs | 28 + .../enums/PdfMessageDigestType.cs | 38 ++ .../PdfSharp.System/PdfSharp.System.csproj | 6 +- .../PdfSharp.System.csproj.DotSettings | 3 + .../Properties/GlobalDeclarations.cs | 21 + .../System/CompilerServices.cs | 285 +-------- .../PdfSharp.Testing-gdi.csproj | 4 +- .../PdfSharp.Testing-wpf.csproj | 4 +- .../PdfSharp.Testing/PdfSharp.Testing.csproj | 4 +- .../PdfSharp.WPFonts/PdfSharp.WPFonts.csproj | 3 +- .../PdfSharp.Fonts.TestApp.csproj | 2 +- .../Shared.TestApp/Shared.TestApp.csproj | 4 +- .../PdfSharp.Fonts.Test.csproj | 2 +- .../tests/Shared.Tests/Shared.Tests.csproj | 6 +- .../tests/Shared.Tests/System/Messages.cs | 37 ++ .../HelloWorld,MigraDoc-gdi.csproj | 2 +- .../HelloWorld,MigraDoc-wpf.csproj | 2 +- .../src/HelloWorld/HelloWorld,MigraDoc.csproj | 4 +- .../src/MigraDoc/src/HelloWorld/Program.cs | 2 +- .../HelloWorld-gdi,PDFsharp.csproj | 2 +- .../HelloWorld-wpf,PDFsharp.csproj | 2 +- .../src/HelloWorld/HelloWorld,PDFsharp.csproj | 2 +- .../src/PDFsharp/src/HelloWorld/Program.cs | 8 +- src/tools/src/CopyAsLink/CopyAsLink.csproj | 10 + src/tools/src/CopyAsLink/Program.cs | 68 +++ src/tools/src/NRT-Tests/NRT-Tests.csproj | 2 +- .../src/PdfFileViewer/PdfFileViewer.csproj | 2 +- .../PdfSharp.TestHelper-gdi.csproj | 7 +- .../PdfSharp.TestHelper-wpf.csproj | 7 +- .../Analysis/ContentStream/GetText.cs | 23 +- .../src/PdfSharp.TestHelper/MemoryLogger.cs | 2 +- .../PdfSharp.TestHelper.csproj | 2 + .../SecurityTestHelper.cs | 67 +-- .../TestHelperExtensions.cs | 2 +- 480 files changed, 10368 insertions(+), 7210 deletions(-) create mode 100644 docs/BeforeReleases.md create mode 100644 docs/MigraDoc/AboutLineSpacing.md create mode 100644 docs/README.md create mode 100644 docs/Signatures/CertificateCreation.md create mode 100644 docs/changes/v6.2.0-log.md create mode 100644 src/foundation/src/MigraDoc/docs/.gitkeep delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Resources/Messages.de.restext delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Resources/Messages.restext delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DomSR.cs create mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/MdDomMsg.cs create mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/MdDomMsgs.cs rename src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/{DomMsgID.cs => MdDomMsgId.cs} (91%) delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Properties/VersionInfo.cs delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages.de.restext delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages.restext delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages2.cs create mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsg.cs rename src/foundation/src/MigraDoc/src/MigraDoc.Rendering/{Rendering.Resources/Messages2.de.resx => Rendering/MdPdfMsg.de.resx} (100%) rename src/foundation/src/MigraDoc/src/MigraDoc.Rendering/{Rendering.Resources/Messages2.resx => Rendering/MdPdfMsg.resx} (100%) create mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsgs.cs rename src/foundation/src/MigraDoc/src/{MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.de.resx => MigraDoc.Rendering/Rendering/MdPdfMsgs.de.resx} (79%) create mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsgs.resx delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-gdi/MigraDoc.RtfRendering-gdi.csproj.txt delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/Properties/VersionInfo.cs delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages.de.restext delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages.restext delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.cs delete mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.resx create mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/MdRtfMsg.cs create mode 100644 src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/MdRtfMsgs.cs create mode 100644 src/foundation/src/MigraDoc/tests/MigraDoc.Tests/Helper/SecurityTestHelper.cs create mode 100644 src/foundation/src/MigraDoc/tests/MigraDoc.Tests/PageSizeTests.cs create mode 100644 src/foundation/src/PDFsharp/docs/Coding-Issues.md create mode 100644 src/foundation/src/PDFsharp/docs/README.md create mode 100644 src/foundation/src/PDFsharp/docs/pdf-features/PDF-A.md create mode 100644 src/foundation/src/PDFsharp/docs/pdf/Strings.md create mode 100644 src/foundation/src/PDFsharp/features/PdfSharp.Features/Pdf/pdfa/PDF-A.cs create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp.Charting-gdi/PdfSharp.Charting-gdi.csproj - save create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Internal/PsMsg.cs create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Internal/PsMsgs.cs rename src/foundation/src/PDFsharp/src/PdfSharp/{root/enums/PSMsgID.cs => Internal/enums/PsMsgId.cs} (89%) create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/IAnnotationAppearanceHandler.cs rename src/foundation/src/PDFsharp/src/PdfSharp/{Pdf.Security/Encryption => Pdf.Security.Encryption}/PdfEncryptionBase.cs (100%) rename src/foundation/src/PDFsharp/src/PdfSharp/{Pdf.Security/Encryption => Pdf.Security.Encryption}/PdfEncryptionV1To4.cs (99%) rename src/foundation/src/PDFsharp/src/PdfSharp/{Pdf.Security/Encryption => Pdf.Security.Encryption}/PdfEncryptionV5.cs (96%) rename src/foundation/src/PDFsharp/src/PdfSharp/{Pdf.Security/Encryption => Pdf.Security.Encryption}/RC4.cs (100%) rename src/foundation/src/PDFsharp/src/PdfSharp/{Pdf.Security/Encryption => Pdf.Security.Encryption}/SASLprep.cs (100%) create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/DefaultSignatureAppearanceHandler.cs create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/DigitalSignatureOptions.cs create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfArrayWithPadding.cs create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignature.cs create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignatureHandler.cs create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignaturePlaceholderItem.cs create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/RangedStream.cs create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Pdf/enums/PdfFontColoredGlyphs.cs delete mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Resources/Messages.de.restext delete mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Resources/Messages.restext create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/Resources/sRGB2014.icc delete mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/root/PSSR.cs delete mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/root/VersionInfo.cs create mode 100644 src/foundation/src/PDFsharp/src/PdfSharp/root/enums/PageRotation.cs create mode 100644 src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Helper/XunitHelper.cs create mode 100644 src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/pdf-a/PdfATests.cs create mode 100644 src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/signatures/BouncyCastleSignerTests.cs create mode 100644 src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/signatures/DefaultSignerTests.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PdfSharpDefaultSigner.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PsCryptoMgs.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PsCryptoMsg.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/enum/PsCryptoMsgId.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Crytography/PdfSharp.Cryptography.csproj create mode 100644 src/foundation/src/shared/src/PdfSharp.Crytography/PdfSharp.Cryptography.csproj.DotSettings create mode 100644 src/foundation/src/shared/src/PdfSharp.Crytography/README.md create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/Diagnostics/NullabilityHelper.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/Internal/BuildVersion.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/Internal/Configuration.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/Internal/SyMsg.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/Internal/SyMsgs.cs rename src/foundation/src/shared/src/{PdfSharp.System/Internal/ErrorHelpers.cs => PdfSharp.Shared/Internal/TH.cs} (58%) create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/Internal/UrlLiterals.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/Internal/enum/SyMsgId.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/PdfSharp.Shared.csproj create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/PdfSharp.Shared.csproj.DotSettings create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/Properties/GlobalDeclarations.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/README.md create mode 100644 src/foundation/src/shared/src/PdfSharp.Shared/System/CompilerServices.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.Snippets/Pdf/signatures/BouncyCastleSigner.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.System/IO/StreamToMemoryReader.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.System/Internal/BuildVersion.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.System/Internal/SyMgs.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.System/Internal/SyMsg.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.System/Internal/TH.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.System/Internal/enum/SyMsgId.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.System/Pdf.Signatures/IDigitalSigner.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.System/Pdf.Signatures/enums/PdfMessageDigestType.cs create mode 100644 src/foundation/src/shared/src/PdfSharp.System/PdfSharp.System.csproj.DotSettings create mode 100644 src/foundation/src/shared/src/PdfSharp.System/Properties/GlobalDeclarations.cs create mode 100644 src/foundation/src/shared/tests/Shared.Tests/System/Messages.cs create mode 100644 src/tools/src/CopyAsLink/CopyAsLink.csproj create mode 100644 src/tools/src/CopyAsLink/Program.cs rename src/{foundation/src/MigraDoc/tests/MigraDoc.Tests => tools/src/PdfSharp.TestHelper}/SecurityTestHelper.cs (85%) diff --git a/PdfSharp.sln b/PdfSharp.sln index 3b786de9..67e5bbc5 100644 --- a/PdfSharp.sln +++ b/PdfSharp.sln @@ -42,6 +42,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{18E75E2F-2 ProjectSection(SolutionItems) = preProject src\foundation\src\PDFsharp\docs\AboutFonts.md = src\foundation\src\PDFsharp\docs\AboutFonts.md src\foundation\src\PDFsharp\docs\AboutImages.md = src\foundation\src\PDFsharp\docs\AboutImages.md + src\foundation\src\PDFsharp\docs\Coding-Issues.md = src\foundation\src\PDFsharp\docs\Coding-Issues.md src\foundation\src\PDFsharp\docs\GlobalStuff.md = src\foundation\src\PDFsharp\docs\GlobalStuff.md src\foundation\src\PDFsharp\docs\Notebook.md = src\foundation\src\PDFsharp\docs\Notebook.md src\foundation\src\PDFsharp\docs\PortingNotes.md = src\foundation\src\PDFsharp\docs\PortingNotes.md @@ -59,6 +60,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D564E33D EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{9EB8E8CC-3BA3-4B0F-B853-5B2443C40015}" + ProjectSection(SolutionItems) = preProject + AboutLineSpacing.md = AboutLineSpacing.md + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MigraDoc.Tests", "src\foundation\src\MigraDoc\tests\MigraDoc.Tests\MigraDoc.Tests.csproj", "{CA022FCC-7A23-4759-8789-9FC86C805557}" EndProject @@ -191,6 +195,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PDFsharp.NuGet-wpf", "src\f EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{76BA9372-65AE-479C-AEF7-D50E6B486CEF}" ProjectSection(SolutionItems) = preProject + docs\BeforeReleases.md = docs\BeforeReleases.md docs\BoilerplateText.md = docs\BoilerplateText.md docs\DevNotes.md = docs\DevNotes.md docs\MakeNewReleaseNotes.md = docs\MakeNewReleaseNotes.md @@ -252,6 +257,29 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfSharp.Testing-gdi", "src EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfSharp.Testing-wpf", "src\foundation\src\shared\src\PdfSharp.Testing-wpf\PdfSharp.Testing-wpf.csproj", "{1F9EE0B3-4BA1-4CE4-9301-1735732B61B6}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "psf", "psf", "{D2B0EC1F-CF81-4756-B20C-9BB786A151E0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfSharp.Cryptography", "src\foundation\src\shared\src\PdfSharp.Crytography\PdfSharp.Cryptography.csproj", "{2BA35CF7-9851-4B19-A170-0B66BE87ACE5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Signatures", "Signatures", "{8CE97B3D-BECA-436D-86EC-E053A99E3A81}" + ProjectSection(SolutionItems) = preProject + docs\Signatures\CertificateCreation.md = docs\Signatures\CertificateCreation.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "changes", "changes", "{C39DF31C-2938-4EC3-B50D-52FFA8453866}" + ProjectSection(SolutionItems) = preProject + docs\changes\v6.2.0-log.md = docs\changes\v6.2.0-log.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CopyAsLink", "src\tools\src\CopyAsLink\CopyAsLink.csproj", "{60D307AC-D7D6-4AA4-BF9F-DDC6809CBCC7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfSharp.Shared", "src\foundation\src\shared\src\PdfSharp.Shared\PdfSharp.Shared.csproj", "{8C20115B-AA17-41A7-837D-F5CFD286DFC9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MigraDoc", "MigraDoc", "{08BB5B79-D6B5-4EEF-8D37-77FBD0F04AA6}" + ProjectSection(SolutionItems) = preProject + docs\MigraDoc\AboutLineSpacing.md = docs\MigraDoc\AboutLineSpacing.md + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -518,6 +546,18 @@ Global {1F9EE0B3-4BA1-4CE4-9301-1735732B61B6}.Debug|Any CPU.Build.0 = Debug|Any CPU {1F9EE0B3-4BA1-4CE4-9301-1735732B61B6}.Release|Any CPU.ActiveCfg = Release|Any CPU {1F9EE0B3-4BA1-4CE4-9301-1735732B61B6}.Release|Any CPU.Build.0 = Release|Any CPU + {2BA35CF7-9851-4B19-A170-0B66BE87ACE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BA35CF7-9851-4B19-A170-0B66BE87ACE5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BA35CF7-9851-4B19-A170-0B66BE87ACE5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BA35CF7-9851-4B19-A170-0B66BE87ACE5}.Release|Any CPU.Build.0 = Release|Any CPU + {60D307AC-D7D6-4AA4-BF9F-DDC6809CBCC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60D307AC-D7D6-4AA4-BF9F-DDC6809CBCC7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60D307AC-D7D6-4AA4-BF9F-DDC6809CBCC7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60D307AC-D7D6-4AA4-BF9F-DDC6809CBCC7}.Release|Any CPU.Build.0 = Release|Any CPU + {8C20115B-AA17-41A7-837D-F5CFD286DFC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C20115B-AA17-41A7-837D-F5CFD286DFC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C20115B-AA17-41A7-837D-F5CFD286DFC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C20115B-AA17-41A7-837D-F5CFD286DFC9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -617,6 +657,13 @@ Global {BA039CC9-132E-4103-BB47-87C3E3398F82} = {31FE507C-F342-4DA4-9BE5-B3D2ED93E9CC} {C7CCB288-8372-41AD-9F65-6224CE0D6358} = {DE458BB2-5942-4588-A74A-AE9CA86F284C} {1F9EE0B3-4BA1-4CE4-9301-1735732B61B6} = {DE458BB2-5942-4588-A74A-AE9CA86F284C} + {D2B0EC1F-CF81-4756-B20C-9BB786A151E0} = {18E75E2F-2A27-408C-BC02-9B68D7F0817F} + {2BA35CF7-9851-4B19-A170-0B66BE87ACE5} = {DE458BB2-5942-4588-A74A-AE9CA86F284C} + {8CE97B3D-BECA-436D-86EC-E053A99E3A81} = {76BA9372-65AE-479C-AEF7-D50E6B486CEF} + {C39DF31C-2938-4EC3-B50D-52FFA8453866} = {76BA9372-65AE-479C-AEF7-D50E6B486CEF} + {60D307AC-D7D6-4AA4-BF9F-DDC6809CBCC7} = {CC13B431-6963-480F-8C21-1F78A220A399} + {8C20115B-AA17-41A7-837D-F5CFD286DFC9} = {DE458BB2-5942-4588-A74A-AE9CA86F284C} + {08BB5B79-D6B5-4EEF-8D37-77FBD0F04AA6} = {76BA9372-65AE-479C-AEF7-D50E6B486CEF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D5FF5562-3C79-434B-B951-B84542D01625} diff --git a/PdfSharp.sln.DotSettings b/PdfSharp.sln.DotSettings index 1e387f83..648fcaef 100644 --- a/PdfSharp.sln.DotSettings +++ b/PdfSharp.sln.DotSettings @@ -6,6 +6,9 @@ IO IV SASL + TSA + URI + URL True ID True diff --git a/README.md b/README.md index a247667c..167fe407 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -# PDFsharp & MigraDoc 6 +# PDFsharp & MigraDoc 6 -Version **6.1.1** -Published **2024-07-01** +Version **6.2.0 Preview 1** +Published **2024-08-12** -This is a version of the **PDFsharp** project, the main project of PDFsharp & MigraDoc 6 with updates for C# 12 and .NET 6. +This is a preview version of the **PDFsharp** project, the main project of PDFsharp & MigraDoc 6 with updates for C# 12 and .NET 6. PDFsharp: Copyright (c) 2005-2024 empira Software GmbH, Troisdorf (Cologne Area), Germany MigraDoc: Copyright (c) 2001-2024 empira Software GmbH, Troisdorf (Cologne Area), Germany @@ -35,7 +35,7 @@ Execute * You need the latest .NET SDK version installed * Please note that you need a git repository with at least one commit in order to build the PDFsharp solution. Without a git repo with at least one commit, you will get an error message from `GitVersion.MsBuild` while building the solution. - You can set a tag to define a valid version, e.g.: `git tag v6.1.0` to make it build with a specific version number. Without tag, version 0.1.0 will be used. + You can set a tag to define a valid version, e.g.: `git tag v6.2.0` to make it build with a specific version number. Without tag, version 0.1.0 will be used. ### Central package management diff --git a/dev/run-tests.ps1 b/dev/run-tests.ps1 index 81c9b90b..72198d0b 100644 --- a/dev/run-tests.ps1 +++ b/dev/run-tests.ps1 @@ -4,13 +4,16 @@ .DESCRIPTION The script builds the solution located in the script’s root parent folder and runs 'dotnet test' for all libraries to test, that are found via its projects. - These tests are run in the following environment, as far as available: Windows with net6, Windows with net472 and Linux/WSL (net6). - For each environment libraries not to be run (like WPF in Linux or Linux-targeting DLLs in Windows) are excluded from testing. + These tests are run in the following environment, as far as available: Windows with NET8 or NET6, Windows with NET462 and Linux/WSL (NET8 or NET6). + For each environment, libraries not to be run (like WPF in Linux or Linux-targeting DLLs in Windows) are excluded from testing. The test results are displayed in tables per library / code base comparing the test results in the different environments. .PARAMETER Config Specifies the configuration to build and test the solution ("Debug" or "Release"). "Debug" is the default. +.PARAMETER Net6 + Specifies whether NET6 shall be tested instead of NET8. $False is the default. + .PARAMETER SkipBuild Specifies whether the build of the solution shall be skipped. $False is the default. @@ -28,7 +31,7 @@ Not implemented: The test result was only found for other environments. Maybe the project is not targeting or the test is not implemented for this environment. - Not Applicable: The test library was not expected to be executed, as it is not intended to be run in this environment or as this environment is not available. + Not applicable: The test library was not expected to be executed, as it is not intended to be run in this environment or as this environment is not available. No trx file: The test library was expected to be executed, but no trx file was found. Maybe an error occurred in this script or in the 'dotnet test' call. @@ -64,6 +67,7 @@ BUG: Allow to run all tests, including GBE. param ( [Parameter(Mandatory = $false)] [string]$Config = 'Debug', + [Parameter(Mandatory = $false)] [bool]$Net6 = $false, [Parameter(Mandatory = $false)] [bool]$SkipBuild = $false, [Parameter(Mandatory = $false)] [bool]$RunAllTests = $false ) @@ -71,8 +75,9 @@ param ( $script:SystemNameWindows = "Windows" $script:SystemNameLinux = "Linux" $script:SystemNameWsl = "WSL" -$script:NetName472 = "net472" +$script:NetName462 = "net462" $script:NetName6 = "net6" +$script:NetName8 = "net8" $script:Solution @@ -173,6 +178,12 @@ function InitializeScript() } Write-Host + if ($script:Net6) + { + Write-Host "NET6 Tests will be run instead of NET8." + Write-Host + } + if ($script:SkipBuild) { Write-Host "Building solution in $script:Config build will be skipped." @@ -232,6 +243,23 @@ function LoadTestDllInfos() $testDllInfos = $dllInfos | Where-Object { $_.IsTestDll } + # If Net6 parameter is true, remove net8 DLLs. + if ($script:Net6) + { + $testDllInfos = $testDllInfos | Where-Object ` + { + $_.TargetFramework.Contains("net8") -eq $false + } + } + # If Net6 parameter is false, remove net6 DLLs. + else + { + $testDllInfos = $testDllInfos | Where-Object ` + { + $_.TargetFramework.Contains("net6") -eq $false + } + } + # Test-HACK: Only include explicit projects. #$testDllInfos = $testDllInfos | Where-Object {$_.DllFileName.EndsWith("PdfSharp.Tests.dll", "OrdinalIgnoreCase") -or $_.DllFileName.EndsWith("Shared.Tests.dll", "OrdinalIgnoreCase")} @@ -252,12 +280,12 @@ function LoadTestDllInfos() # Set $script:TestDllInfosLinux list if running on Linux host or if tests will run in hosted WSL. if ($script:RunOnLinuxHost -or $script:RunOnHostedWsl) { - # Exclude WPF and GDI projects and net472 and Windows target frameworks for Linux. + # Exclude WPF and GDI projects and net462 and Windows target frameworks for Linux. $script:TestDllInfosLinux = $testDllInfos | Where-Object ` { $_.DllFileName.EndsWith("-gdi.dll", "OrdinalIgnoreCase") -eq $false -and ` $_.DllFileName.EndsWith("-wpf.dll", "OrdinalIgnoreCase") -eq $false -and ` - $_.TargetFramework.Contains("net472") -eq $false -and ` + $_.TargetFramework.Contains("net462") -eq $false -and ` $_.TargetFramework.Contains("windows") -eq $false } | ForEach-Object { $_.PSObject.Copy() } @@ -527,14 +555,17 @@ function RunTestsForSystem($testDllInfos, $systemName, $isHostedWsl) # Gets the name of the environment for the given system and framework. function GetEnvironmentName($systemName, $targetFramework) { - # HACK: Some projects use net7.0 instead of net6.0, but we don’t want to differentiate this in the environment names which define the test result columns. - if ($targetFramework.Contains("net6") -or $targetFramework.Contains("net7")) + if ($script:Net6 -and $targetFramework.Contains("net6")) { $frameworkName = $script:NetName6 } - elseif ($targetFramework.Contains("net472")) + elseif ($script:Net6 -eq $false -and $targetFramework.Contains("net8")) + { + $frameworkName = $script:NetName8 + } + elseif ($targetFramework.Contains("net462")) { - $frameworkName = $script:NetName472 + $frameworkName = $script:NetName462 } else { @@ -544,9 +575,13 @@ function GetEnvironmentName($systemName, $targetFramework) # HACK: For Linux the frameworkName shall not be shown. if ($systemName -eq $script:SystemNameCurrentLinux) { - if ($frameworkName -ne "net6") + if ($script:Net6 -and $frameworkName -ne "net6") + { + Write-Error ("For Linux there’s only one column supported (net6) by test script with Net6 parameter set to true.") + } + elseif ($script:Net6 -eq $false -and $frameworkName -ne "net8") { - Write-Error ("For Linux there’s only one column supported for net6 by test script.") + Write-Error ("For Linux there’s only one column supported (net8) by test script with Net6 parameter set to false.") } return "$systemName" } @@ -590,12 +625,21 @@ function LoadAndShowTestResults() Write-Host "TestResults" -ForegroundColor Green # Green color is used to make it the same conspicuity like the given green Format-Table header output. Write-Host "==================================================" -ForegroundColor Green + if ($script:Net6) + { + $netNameX = $script:NetName6 + } + else + { + $netNameX = $script:NetName8 + } + # Environment names to be displayed in separate columns. - $environmentNameWindowsNet6 = GetEnvironmentName $script:SystemNameWindows $script:NetName6 - $environmentNameWindowsNet472 = GetEnvironmentName $script:SystemNameWindows $script:NetName472 - $environmentNameLinuxNet6 = GetEnvironmentName $script:SystemNameCurrentLinux $script:NetName6 + $environmentNameWindowsNetX = GetEnvironmentName $script:SystemNameWindows $netNameX + $environmentNameWindowsNet462 = GetEnvironmentName $script:SystemNameWindows $script:NetName462 + $environmentNameLinuxNetX = GetEnvironmentName $script:SystemNameCurrentLinux $netNameX - $environmentNames = @($environmentNameWindowsNet6, $environmentNameWindowsNet472, $environmentNameLinuxNet6) + $environmentNames = @($environmentNameWindowsNetX, $environmentNameWindowsNet462, $environmentNameLinuxNetX) # Get unique GenericCodeBaseinformation for all Windows and Linux test DLLs. $genericCodeBaseInfos = ($script:TestDllInfosWindows + $script:TestDllInfosLinux) | Select-Object -Property GenericCodeBase, GenericCodeBaseExtension, ProjectFolder -Unique @@ -621,18 +665,18 @@ function LoadAndShowTestResults() Width = $testColumnWidth }, @{ - Label = $firstResultColumnLeftPaddingStr + "$environmentNameWindowsNet6" - Expression = { ColorizedCellFormatExpressionResult($firstResultColumnLeftPaddingStr + $_.($environmentNameWindowsNet6)) } + Label = $firstResultColumnLeftPaddingStr + "$environmentNameWindowsNetX" + Expression = { ColorizedCellFormatExpressionResult($firstResultColumnLeftPaddingStr + $_.($environmentNameWindowsNetX)) } Width = $firstResultColumnLeftPadding + $resultColumnWidth }, @{ - Label = "$environmentNameWindowsNet472" - Expression = { ColorizedCellFormatExpressionResult($_.($environmentNameWindowsNet472)) } + Label = "$environmentNameWindowsNet462" + Expression = { ColorizedCellFormatExpressionResult($_.($environmentNameWindowsNet462)) } Width = $resultColumnWidth }, @{ - Label = "$environmentNameLinuxNet6" - Expression = { ColorizedCellFormatExpressionResult($_.($environmentNameLinuxNet6)) } + Label = "$environmentNameLinuxNetX" + Expression = { ColorizedCellFormatExpressionResult($_.($environmentNameLinuxNetX)) } Width = $resultColumnWidth } ) diff --git a/docs/BeforeReleases.md b/docs/BeforeReleases.md new file mode 100644 index 00000000..702712f3 --- /dev/null +++ b/docs/BeforeReleases.md @@ -0,0 +1,75 @@ +# Before released + +Before you follow the instructions from the Azure DevOps wiki how to publish PDFsharp +complete the following tasks. + +## General todos + +### Update the assembly build version + +Set the assembly build version in file in `gitversion.yml` to the number of days from +January 1st 2005 to the release day. **This is essential for users that use intaller tools.** +``` +assembly-file-versioning-format: '{Major}.{Minor}.{Patch}.{env:PDFSHARP_BUILD_VERSION ?? 9999}' +``` + +### Check specific files + +* Search for **`CHECK_BEFORE_RELEASE`** and verify the code at this places. +* Check `Directory.Build.targets` + * `USE_LONG_SIZE` must be defined. + * `TEST_CODE_xxx` must be 'undefined' by the suffix `_xxx`. + +### Run all test + +* Run all tests in both RELEASE and DEBUG configuration. + UnitTest with `RunTests` including all skipped tests. +* Run all text under WSL2 + +## Update files and configurations + +### Update .md files + +* Check and update [README.md](../README.md) + +### Update NuGet configuration + +* ??? +* Check packages with NuGet Package Explorer + +## Test other repositories + +Rebuild both DEBUG and RELEASE and update local NuGet packages. + +### GBE test + +* Use ComparePdf with GBE + +### PDFsharp.Samples + +* Build solution +* Run the script that executes all samples + +### PDFsharp.Tests + +* Build solution +* Run the tests + +### PDFsharp.Lab + +* Build solution +* Run the script that executes all samples + +### PDFsharp.MAUI + +* Build solution +* Run the script that executes all samples + +### PDFsharp.Blazor + +* Build solution +* Run the script that executes all samples + +### Test with QBX + +* Test with QBX diff --git a/docs/BoilerplateText.md b/docs/BoilerplateText.md index a93cbed3..693f606d 100644 --- a/docs/BoilerplateText.md +++ b/docs/BoilerplateText.md @@ -71,7 +71,7 @@ The package ’PdfSharp’ can be used on any platform including Windows and Lin The packages ’PDFsharp-gdi’ and ’PDFsharp-wpf’ can be used under Windows only. The Target Frameworks are ’net6.0-windows’ and ’net472’. We also publish packages that contain PDFsharp plus MigraDoc. See the project docs site for further information: -https://docs.pdfsharp.net/link/readme-v6.1.html +https://docs.pdfsharp.net/link/readme-v6.2.html PDFsharp & MigraDoc: @@ -79,4 +79,4 @@ This is a version of PDFsharp and MigraDoc Foundation using .NET 6. The package ’PDFsharp-MigraDoc’ can be used on any platform including Windows and Linux. The Target Frameworks are ’net6.0’ and ’netstandard2.0’. The packages ’PDFsharp-MigraDoc-GDI’ and ’PDFsharp-MigraDoc-WPF’ can be used under Windows only. The Target Frameworks are ’net6.0-windows’ and ’net472’. See the project docs site for further information: -https://docs.pdfsharp.net/link/readme-v6.1.html +https://docs.pdfsharp.net/link/readme-v6.2.html diff --git a/docs/DevNotes.md b/docs/DevNotes.md index db681c27..cad284e5 100644 --- a/docs/DevNotes.md +++ b/docs/DevNotes.md @@ -1,4 +1,8 @@ -# Developer notes +# Developer notes + + +„“ ’ ‚‘ »« ›‹ – | · × ² ³ ½ € † … | ✔ ✘ ↯ ± − × ÷ ⋅ √ ≠ ≤ ≥ ≡ | ® © ← ↑ → ↓ ↔ ↕ ∅ |"; +“English” | „German“ | ‘English’ | ‚German‘ ## Do this first diff --git a/docs/MakeNewReleaseNotes.md b/docs/MakeNewReleaseNotes.md index c8eee157..cafa700c 100644 --- a/docs/MakeNewReleaseNotes.md +++ b/docs/MakeNewReleaseNotes.md @@ -1,4 +1,4 @@ -# Files to check +# Files to check [README.md](..\README.md) diff --git a/docs/MigraDoc/AboutLineSpacing.md b/docs/MigraDoc/AboutLineSpacing.md new file mode 100644 index 00000000..466c1850 --- /dev/null +++ b/docs/MigraDoc/AboutLineSpacing.md @@ -0,0 +1,33 @@ +# Line spacing + +This article is about the definition of line spacing in MigraDoc. + +## Line positioning + +The line positioning, depending on the line spacing, should be identical to the positioning done by Microsoft Word. + +The baseline is calculated as follows. + +### Relative line spacings + +For a line’s baseline position in a paragraph using the **Single**, **OnePtFive**, **Double** or **Multiple** line spacing, +the **maximum** of the **paragraph’s baseline** and all **FormattedText’s baselines** is used. + +All baselines used for calculation are the result of the used **font size multiplied with the given line spacing value**. + +### Absolute line spacings + +#### LineSpacingRule.AtLeast + +For a line’s baseline position in a paragraph using the **AtLeast** line spacing, +the **maximum** of the **paragraph’s baseline** and all **FormattedText’s baselines** is used. + +All baselines used for calculation are the **maximum** of the **used font size** and the **paragraph’s line spacing value**. + +#### LineSpacingRule.Exactly + +For a line’s baseline position in a paragraph using the **Exactly** line spacing, +**only the paragraph’s font and line spacing** are considered. +This way, FormattedTexts with a larger font size have no impact on the line’s baseline position. + +The baseline is calculated by using the **paragraph’s font baseline scaled to the paragraph’s line spacing**. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..14b2758f --- /dev/null +++ b/docs/README.md @@ -0,0 +1,3 @@ +# README of PDFsharp/docs + +This folder contains technical information for the PDFsharp team. diff --git a/docs/Signatures/CertificateCreation.md b/docs/Signatures/CertificateCreation.md new file mode 100644 index 00000000..291f65c4 --- /dev/null +++ b/docs/Signatures/CertificateCreation.md @@ -0,0 +1,53 @@ +# Certificate creation + +This file introduces how OpenSSL can be used to create self-signed certificates that can be used to sign PDF files. + +## Creating self-signed certificates + +OpenSSL is one option to create certificates for signing. + +### Self-signed RSA certificates + +For testing, you can easily create an RSA certificate using three calls to OpenSSL: + +* Generating a private key +* Generating the self signed certificate +* Create a PFX file containing certificate and private key + +Here is code that creates an RSA certificate with a 2048-bits key: + +```pwsh +openssl genrsa 2048 > private.pem +openssl req -days 32767 -x509 -new -key private.pem -out public.pem +openssl pkcs12 -export -in public.pem -inkey private.pem -out mycert.pfx +``` + +The *-days* parameter specifies how long the certificate will be valid. For some use cases you should not exceed 397 days. + +Note that the three statements above will prompt for input like location, company name, and passwords. + +### Self-signed DSA certificates + +Theoretically, you can create DSA certificates using four calls to OpenSSL. Practically, we did not have success and all DSA certificates we created were rejected by Windows as invalid. + +The code is very similar to the RSA case, but specifying the key length requires am extra OpenSSL call to create a parameter file. + +```pwsh +openssl dsaparam 2048 > dsaparam.txt +openssl gendsa dsaparam.txt > private.pem +openssl req -days 32767 -x509 -new -key private.pem -out public.pem +openssl pkcs12 -export -in public.pem -inkey private.pem -out mycert.pfx +``` + +Please let us know what we were doing wrong if you manage to create DSA certificates using OpenSSL. Thanks in advance. + +### Automization of certificate creation + +OpenSSL will prompt for information while creating the certificate. +To avoid this, the *subj* parameter can be used: + +```txt +-subj "/C=US/ST=Washington/L=Seattle/O=John Doe Ltd./OU=PR/CN=John Doe" +``` + +Alternatively, you can write the answers into a text file and redirect input to that file. diff --git a/docs/changes/v6.2.0-log.md b/docs/changes/v6.2.0-log.md new file mode 100644 index 00000000..7936f8e7 --- /dev/null +++ b/docs/changes/v6.2.0-log.md @@ -0,0 +1,48 @@ +# 6.2.0 change log + +This text is copied to `docs.pdfsharp.net`. + +## Version 6.2 + +PDFsharp Library changes come here. + +### PDFsharp 6.2.0 Preview 1 + +#### Features + +**Digital signatures** +PDF documents can now be signed with a digital signature. + +**Multi-colored glyphs** +Multi-colored glyphs like emojis are now supported. + +**.NET Framework 4.6.2** +All assemblies have downgraded .NET Framework references in `` from 4.7.2 to 4.6.2. +`net472` becomes `net462`. + +**.NET 8** +We added .NET 8 (`net8.0`) to ``. + +**PDF/A** +PDF documents can now be PDF/A conforming. We are still working on this feature, so currently there are some limitations. + +#### Bug fixes + +**Cleanup NuGet packages** +MigraDoc packages now depend on PDFsharp NuGet packages instead of including assemblies directly. +All packages now depend on e.g. `Microsoft.Extensions.Logging` instead of including the Microsoft assembly. + +**.restext files removed** +Some assemblies had a subfolder `de` containing German messages. +We removed all `.restext` resources. All messages are now available in US English only. + +**PDFsharp.Shared** +Code that grants friendly access to all PDFsharp Foundation assemblies lives in this new assembly. + +**Bug in parsing object referenced** +Lexer now supports white-space within object references. + +**Page orientation now works as expected** +The connection between page Width, Height, PageOrientation, and PageRotation was weird. +It was replaced by a consistent concept. +This is a breaking change. diff --git a/gitversion.yml b/gitversion.yml index 647af53c..021d0e2a 100644 --- a/gitversion.yml +++ b/gitversion.yml @@ -1,7 +1,7 @@ -# 25-06-30 +# 24-08-07 assembly-versioning-scheme: MajorMinorPatch -# PDFSHARP_BUILD_VERSION are the days since 2005-01-01. -assembly-file-versioning-format: '{Major}.{Minor}.{Patch}.{env:PDFSHARP_BUILD_VERSION ?? 7121}' +# PDFSHARP_BUILD_VERSION are the days since 2005-01-01. #CHECK_BEFORE_RELEASE +assembly-file-versioning-format: '{Major}.{Minor}.{Patch}.{env:PDFSHARP_BUILD_VERSION ?? 7164}' mode: Mainline assembly-informational-format: '{NuGetVersion}' branches: diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 91ad376d..a87c9b4d 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -2,6 +2,6 @@ - $(DefineConstants);USE_LONG_SIZE;_TEST_CODE_XXX + $(DefineConstants);USE_LONG_SIZE;TEST_CODE_xxx \ No newline at end of file diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index fe9f2272..7aa5470c 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -1,113 +1,142 @@ - 6.0.0 - 6.0.0 - 6.0.0 - 6.0.0 + 8.0.0 + 8.0.0 + - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - + - - + + - - - - - - - - - - - + + + + + + + + + + + - - - - - + + + + - + + \ No newline at end of file diff --git a/src/dotnet-test.Build.props b/src/dotnet-test.Build.props index a0e96f7a..00675e9b 100644 --- a/src/dotnet-test.Build.props +++ b/src/dotnet-test.Build.props @@ -1,19 +1,19 @@  - - true - - - - - - - - all - - - all - runtime; build; native; contentfiles; analyzers - - - + + true + + + + + + + + all + + + all + runtime; build; native; contentfiles; analyzers + + + diff --git a/src/foundation/nuget/src/Directory.Build.props b/src/foundation/nuget/src/Directory.Build.props index 5dc9ce07..618588a9 100644 --- a/src/foundation/nuget/src/Directory.Build.props +++ b/src/foundation/nuget/src/Directory.Build.props @@ -1,53 +1,57 @@  - - - - - - - - - - @(DescriptionFileContents->'%(Identity)', '%0d') - @(ReleaseNotesFileContents->'%(Identity)', '%0d') - ***** THIS IS A DEBUG BUILD - DO NOT PUBLISH *****%0d - - - https://docs.pdfsharp.net - PDFsharp PDF creation - MigraDoc PDFsharp PDF Document Generation - - - - - - - - - - - - - - $(NuspecProperties);id=$(NuGetId) - $(NuspecProperties);title=$(NuGetTitle) - $(NuspecProperties);config=$(Configuration) - $(NuspecProperties);version=$(PackageVersion) - $(NuspecProperties);description=$(NuGetDescription) - $(NuspecProperties);summary=$(NuGetSummary) - $(NuspecProperties);authors=$(Authors) - $(NuspecProperties);owners=$(Owners) - $(NuspecProperties);projectUrl=$(NuGetProjectUrl) - $(NuspecProperties);copyright=$(Copyright) - $(NuspecProperties);releaseNotes=$(NuGetReleaseNotes) - $(NuspecProperties);tags=$(NuGetTags) - - - - - + + + + + + + + + + @(DescriptionFileContents->'%(Identity)', '%0d') + @(ReleaseNotesFileContents->'%(Identity)', '%0d') + ***** THIS IS A DEBUG BUILD - DO NOT PUBLISH *****%0d + + + https://docs.pdfsharp.net + PDFsharp PDF creation + MigraDoc PDFsharp PDF Document Generation + + + + + + + + + + + + + + $(NuspecProperties);id=$(NuGetId) + $(NuspecProperties);title=$(NuGetTitle) + $(NuspecProperties);config=$(Configuration) + $(NuspecProperties);version=$(PackageVersion) + $(NuspecProperties);description=$(NuGetDescription) + $(NuspecProperties);summary=$(NuGetSummary) + $(NuspecProperties);authors=$(Authors) + $(NuspecProperties);owners=$(Owners) + $(NuspecProperties);projectUrl=$(NuGetProjectUrl) + $(NuspecProperties);copyright=$(Copyright) + $(NuspecProperties);releaseNotes=$(NuGetReleaseNotes) + $(NuspecProperties);tags=$(NuGetTags) + + $(NuspecProperties);NetCore_PackageVersion=$(NetCore_PackageVersion) + $(NuspecProperties);Logging_PackageVersion=$(Logging_PackageVersion) + $(NuspecProperties);Cryptography_PackageVersion=$(Cryptography_PackageVersion) + + + + + diff --git a/src/foundation/nuget/src/Dummy-PDFsharp.NuGet-wpf/Dummy-PDFsharp.NuGet-wpf.csproj b/src/foundation/nuget/src/Dummy-PDFsharp.NuGet-wpf/Dummy-PDFsharp.NuGet-wpf.csproj index 43266be4..57239e66 100644 --- a/src/foundation/nuget/src/Dummy-PDFsharp.NuGet-wpf/Dummy-PDFsharp.NuGet-wpf.csproj +++ b/src/foundation/nuget/src/Dummy-PDFsharp.NuGet-wpf/Dummy-PDFsharp.NuGet-wpf.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net462 true diff --git a/src/foundation/nuget/src/MigraDoc.NuGet-gdi/MigraDoc.NuGet-gdi.csproj b/src/foundation/nuget/src/MigraDoc.NuGet-gdi/MigraDoc.NuGet-gdi.csproj index 7d17012a..fb74332b 100644 --- a/src/foundation/nuget/src/MigraDoc.NuGet-gdi/MigraDoc.NuGet-gdi.csproj +++ b/src/foundation/nuget/src/MigraDoc.NuGet-gdi/MigraDoc.NuGet-gdi.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true true false @@ -26,6 +26,7 @@ + diff --git a/src/foundation/nuget/src/MigraDoc.NuGet-gdi/MigraDoc.NuGet-gdi.nuspec b/src/foundation/nuget/src/MigraDoc.NuGet-gdi/MigraDoc.NuGet-gdi.nuspec index 95d31f6c..9a3b155a 100644 --- a/src/foundation/nuget/src/MigraDoc.NuGet-gdi/MigraDoc.NuGet-gdi.nuspec +++ b/src/foundation/nuget/src/MigraDoc.NuGet-gdi/MigraDoc.NuGet-gdi.nuspec @@ -19,24 +19,37 @@ $title$ - + + + - - + + + + + + + + + - + + + + - - + + + diff --git a/src/foundation/nuget/src/MigraDoc.NuGet-gdi/ReleaseNotes.txt b/src/foundation/nuget/src/MigraDoc.NuGet-gdi/ReleaseNotes.txt index 8ecec0e5..d130ed4d 100644 --- a/src/foundation/nuget/src/MigraDoc.NuGet-gdi/ReleaseNotes.txt +++ b/src/foundation/nuget/src/MigraDoc.NuGet-gdi/ReleaseNotes.txt @@ -2,4 +2,4 @@ The package ’PDFsharp-MigraDoc’ can be used on any platform including Windows and Linux. The Target Frameworks are ’net6.0’ and ’netstandard2.0’. The packages ’PDFsharp-MigraDoc-GDI’ and ’PDFsharp-MigraDoc-WPF’ can be used under Windows only. The Target Frameworks are ’net6.0-windows’ and ’net472’. See the project docs site for further information: -https://docs.pdfsharp.net/link/readme-v6.1.html +https://docs.pdfsharp.net/link/readme-v6.2.html diff --git a/src/foundation/nuget/src/MigraDoc.NuGet-wpf/MigraDoc.NuGet-wpf.csproj b/src/foundation/nuget/src/MigraDoc.NuGet-wpf/MigraDoc.NuGet-wpf.csproj index 99218c23..fd280f7b 100644 --- a/src/foundation/nuget/src/MigraDoc.NuGet-wpf/MigraDoc.NuGet-wpf.csproj +++ b/src/foundation/nuget/src/MigraDoc.NuGet-wpf/MigraDoc.NuGet-wpf.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true true false @@ -26,6 +26,7 @@ + diff --git a/src/foundation/nuget/src/MigraDoc.NuGet-wpf/MigraDoc.NuGet-wpf.nuspec b/src/foundation/nuget/src/MigraDoc.NuGet-wpf/MigraDoc.NuGet-wpf.nuspec index bea3f8b4..7a5a15e7 100644 --- a/src/foundation/nuget/src/MigraDoc.NuGet-wpf/MigraDoc.NuGet-wpf.nuspec +++ b/src/foundation/nuget/src/MigraDoc.NuGet-wpf/MigraDoc.NuGet-wpf.nuspec @@ -19,24 +19,37 @@ $title$ - + + + - - + + + + + + + + + - + + + + - - + + + diff --git a/src/foundation/nuget/src/MigraDoc.NuGet-wpf/ReleaseNotes.txt b/src/foundation/nuget/src/MigraDoc.NuGet-wpf/ReleaseNotes.txt index 8ecec0e5..d130ed4d 100644 --- a/src/foundation/nuget/src/MigraDoc.NuGet-wpf/ReleaseNotes.txt +++ b/src/foundation/nuget/src/MigraDoc.NuGet-wpf/ReleaseNotes.txt @@ -2,4 +2,4 @@ The package ’PDFsharp-MigraDoc’ can be used on any platform including Windows and Linux. The Target Frameworks are ’net6.0’ and ’netstandard2.0’. The packages ’PDFsharp-MigraDoc-GDI’ and ’PDFsharp-MigraDoc-WPF’ can be used under Windows only. The Target Frameworks are ’net6.0-windows’ and ’net472’. See the project docs site for further information: -https://docs.pdfsharp.net/link/readme-v6.1.html +https://docs.pdfsharp.net/link/readme-v6.2.html diff --git a/src/foundation/nuget/src/MigraDoc.NuGet/MigraDoc.NuGet.csproj b/src/foundation/nuget/src/MigraDoc.NuGet/MigraDoc.NuGet.csproj index 3293205f..81290b7c 100644 --- a/src/foundation/nuget/src/MigraDoc.NuGet/MigraDoc.NuGet.csproj +++ b/src/foundation/nuget/src/MigraDoc.NuGet/MigraDoc.NuGet.csproj @@ -1,7 +1,7 @@  - net6.0;netstandard2.0 + net6.0;net8.0;netstandard2.0 true false True @@ -25,6 +25,7 @@ + diff --git a/src/foundation/nuget/src/MigraDoc.NuGet/MigraDoc.NuGet.nuspec b/src/foundation/nuget/src/MigraDoc.NuGet/MigraDoc.NuGet.nuspec index ddc0beb8..3f2b5634 100644 --- a/src/foundation/nuget/src/MigraDoc.NuGet/MigraDoc.NuGet.nuspec +++ b/src/foundation/nuget/src/MigraDoc.NuGet/MigraDoc.NuGet.nuspec @@ -19,22 +19,34 @@ $title$ - + + + + + + + + - + + + + + - - + + + diff --git a/src/foundation/nuget/src/MigraDoc.NuGet/ReleaseNotes.txt b/src/foundation/nuget/src/MigraDoc.NuGet/ReleaseNotes.txt index 8ecec0e5..d130ed4d 100644 --- a/src/foundation/nuget/src/MigraDoc.NuGet/ReleaseNotes.txt +++ b/src/foundation/nuget/src/MigraDoc.NuGet/ReleaseNotes.txt @@ -2,4 +2,4 @@ The package ’PDFsharp-MigraDoc’ can be used on any platform including Windows and Linux. The Target Frameworks are ’net6.0’ and ’netstandard2.0’. The packages ’PDFsharp-MigraDoc-GDI’ and ’PDFsharp-MigraDoc-WPF’ can be used under Windows only. The Target Frameworks are ’net6.0-windows’ and ’net472’. See the project docs site for further information: -https://docs.pdfsharp.net/link/readme-v6.1.html +https://docs.pdfsharp.net/link/readme-v6.2.html diff --git a/src/foundation/nuget/src/PDFsharp.NuGet-gdi/PDFsharp.NuGet-gdi.csproj b/src/foundation/nuget/src/PDFsharp.NuGet-gdi/PDFsharp.NuGet-gdi.csproj index 30755ac9..e4f19073 100644 --- a/src/foundation/nuget/src/PDFsharp.NuGet-gdi/PDFsharp.NuGet-gdi.csproj +++ b/src/foundation/nuget/src/PDFsharp.NuGet-gdi/PDFsharp.NuGet-gdi.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true true false @@ -23,6 +23,7 @@ + diff --git a/src/foundation/nuget/src/PDFsharp.NuGet-gdi/PDFsharp.NuGet-gdi.nuspec b/src/foundation/nuget/src/PDFsharp.NuGet-gdi/PDFsharp.NuGet-gdi.nuspec index 6943779d..e44df4b4 100644 --- a/src/foundation/nuget/src/PDFsharp.NuGet-gdi/PDFsharp.NuGet-gdi.nuspec +++ b/src/foundation/nuget/src/PDFsharp.NuGet-gdi/PDFsharp.NuGet-gdi.nuspec @@ -19,24 +19,34 @@ $title$ - + + - - + + + + + + + - + + + + - + + diff --git a/src/foundation/nuget/src/PDFsharp.NuGet-gdi/ReleaseNotes.txt b/src/foundation/nuget/src/PDFsharp.NuGet-gdi/ReleaseNotes.txt index 105311d2..30bfd364 100644 --- a/src/foundation/nuget/src/PDFsharp.NuGet-gdi/ReleaseNotes.txt +++ b/src/foundation/nuget/src/PDFsharp.NuGet-gdi/ReleaseNotes.txt @@ -1,6 +1,6 @@ This is a version of PDFsharp using .NET 6. The package ’PdfSharp’ can be used on any platform including Windows and Linux. The Target Frameworks are ’net6.0’ and ’netstandard2.0’. The packages ’PDFsharp-gdi’ and ’PDFsharp-wpf’ can be used under Windows only. The Target Frameworks are ’net6.0-windows’ and ’net472’. -We also publish packages that contain PDFsharp plus MigraDoc. +We also publish packages that contain MigraDoc and reference the corresponding PDFsharp package. See the project docs site for further information: -https://docs.pdfsharp.net/link/readme-v6.1.html +https://docs.pdfsharp.net/link/readme-v6.2.html diff --git a/src/foundation/nuget/src/PDFsharp.NuGet-wpf/PDFsharp.NuGet-wpf.csproj b/src/foundation/nuget/src/PDFsharp.NuGet-wpf/PDFsharp.NuGet-wpf.csproj index 9f268bcb..66dfe4bd 100644 --- a/src/foundation/nuget/src/PDFsharp.NuGet-wpf/PDFsharp.NuGet-wpf.csproj +++ b/src/foundation/nuget/src/PDFsharp.NuGet-wpf/PDFsharp.NuGet-wpf.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true true false @@ -23,6 +23,7 @@ + diff --git a/src/foundation/nuget/src/PDFsharp.NuGet-wpf/PDFsharp.NuGet-wpf.nuspec b/src/foundation/nuget/src/PDFsharp.NuGet-wpf/PDFsharp.NuGet-wpf.nuspec index 111f4c1f..d930f34b 100644 --- a/src/foundation/nuget/src/PDFsharp.NuGet-wpf/PDFsharp.NuGet-wpf.nuspec +++ b/src/foundation/nuget/src/PDFsharp.NuGet-wpf/PDFsharp.NuGet-wpf.nuspec @@ -19,24 +19,34 @@ $title$ - + + - - + + + + + + + - + + + + - + + diff --git a/src/foundation/nuget/src/PDFsharp.NuGet-wpf/ReleaseNotes.txt b/src/foundation/nuget/src/PDFsharp.NuGet-wpf/ReleaseNotes.txt index 105311d2..30bfd364 100644 --- a/src/foundation/nuget/src/PDFsharp.NuGet-wpf/ReleaseNotes.txt +++ b/src/foundation/nuget/src/PDFsharp.NuGet-wpf/ReleaseNotes.txt @@ -1,6 +1,6 @@ This is a version of PDFsharp using .NET 6. The package ’PdfSharp’ can be used on any platform including Windows and Linux. The Target Frameworks are ’net6.0’ and ’netstandard2.0’. The packages ’PDFsharp-gdi’ and ’PDFsharp-wpf’ can be used under Windows only. The Target Frameworks are ’net6.0-windows’ and ’net472’. -We also publish packages that contain PDFsharp plus MigraDoc. +We also publish packages that contain MigraDoc and reference the corresponding PDFsharp package. See the project docs site for further information: -https://docs.pdfsharp.net/link/readme-v6.1.html +https://docs.pdfsharp.net/link/readme-v6.2.html diff --git a/src/foundation/nuget/src/PDFsharp.NuGet/PDFsharp.NuGet.csproj b/src/foundation/nuget/src/PDFsharp.NuGet/PDFsharp.NuGet.csproj index e67a364b..f89e2496 100644 --- a/src/foundation/nuget/src/PDFsharp.NuGet/PDFsharp.NuGet.csproj +++ b/src/foundation/nuget/src/PDFsharp.NuGet/PDFsharp.NuGet.csproj @@ -1,8 +1,9 @@  - net6.0;netstandard2.0 + net6.0;net8.0;netstandard2.0 true + false True ..\..\..\..\StrongnameKey.snk @@ -22,6 +23,7 @@ + diff --git a/src/foundation/nuget/src/PDFsharp.NuGet/PDFsharp.NuGet.nuspec b/src/foundation/nuget/src/PDFsharp.NuGet/PDFsharp.NuGet.nuspec index ce478397..4c01c173 100644 --- a/src/foundation/nuget/src/PDFsharp.NuGet/PDFsharp.NuGet.nuspec +++ b/src/foundation/nuget/src/PDFsharp.NuGet/PDFsharp.NuGet.nuspec @@ -19,22 +19,31 @@ $title$ - + + + + + + - + + + + - + + diff --git a/src/foundation/nuget/src/PDFsharp.NuGet/ReleaseNotes.txt b/src/foundation/nuget/src/PDFsharp.NuGet/ReleaseNotes.txt index 105311d2..30bfd364 100644 --- a/src/foundation/nuget/src/PDFsharp.NuGet/ReleaseNotes.txt +++ b/src/foundation/nuget/src/PDFsharp.NuGet/ReleaseNotes.txt @@ -1,6 +1,6 @@ This is a version of PDFsharp using .NET 6. The package ’PdfSharp’ can be used on any platform including Windows and Linux. The Target Frameworks are ’net6.0’ and ’netstandard2.0’. The packages ’PDFsharp-gdi’ and ’PDFsharp-wpf’ can be used under Windows only. The Target Frameworks are ’net6.0-windows’ and ’net472’. -We also publish packages that contain PDFsharp plus MigraDoc. +We also publish packages that contain MigraDoc and reference the corresponding PDFsharp package. See the project docs site for further information: -https://docs.pdfsharp.net/link/readme-v6.1.html +https://docs.pdfsharp.net/link/readme-v6.2.html diff --git a/src/foundation/src/MigraDoc/docs/.gitkeep b/src/foundation/src/MigraDoc/docs/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/Capabilities.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/Capabilities.cs index 7290eb56..036cb87a 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/Capabilities.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/Capabilities.cs @@ -116,7 +116,7 @@ public static class Compatibility { /// /// Gets or sets a flag that specifies if the renderer should silently ignore charts if they are not supported. - /// Otherwise an exception will be thrown. + /// Otherwise, an exception will be thrown. /// public static FeatureNotAvailableAction ChartsCannotBeRendered { get; set; } = FeatureNotAvailableAction.DoNothing; diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/BookmarkField.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/BookmarkField.cs index d5f2c2ca..a225b068 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/BookmarkField.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/BookmarkField.cs @@ -55,7 +55,7 @@ public string Name internal override void Serialize(Serializer serializer) { if (String.IsNullOrEmpty(Values.Name)) - throw new InvalidOperationException(DomSR.MissingObligatoryProperty("Name", "BookmarkField")); + throw new InvalidOperationException(MdDomMsgs.MissingObligatoryProperty(nameof(Name), nameof(BookmarkField)).Message); serializer.Write("\\field(Bookmark)[Name = \"" + Name.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"]"); } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/InfoField.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/InfoField.cs index 1f0b5dcd..684ee21f 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/InfoField.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/InfoField.cs @@ -41,7 +41,7 @@ public string Name if (IsValidName(value)) Values.Name = value; else - throw new ArgumentException(DomSR.InvalidInfoFieldName(value)); + throw new ArgumentException(MdDomMsgs.InvalidInfoFieldName(value).Message); } } @@ -75,7 +75,7 @@ internal override void Serialize(Serializer serializer) { string str = "\\field(Info)"; if (Name == "") - throw new InvalidOperationException(DomSR.MissingObligatoryProperty("Name", "InfoField")); + throw new InvalidOperationException(MdDomMsgs.MissingObligatoryProperty(nameof(Name), nameof(InfoField)).Message); str += "[Name = \"" + Name + "\"]"; serializer.Write(str); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/NumericFieldBase.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/NumericFieldBase.cs index fdbbb829..ba61bb26 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/NumericFieldBase.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Fields/NumericFieldBase.cs @@ -16,13 +16,13 @@ public abstract class NumericFieldBase : DocumentObject /// The valid format strings for the supported numeric types. /// protected static readonly string[] ValidFormatStrings = - { + [ "", "ROMAN", "roman", "ALPHABETIC", "alphabetic" - }; + ]; /// /// Initializes a new instance of the NumericFieldBase class. @@ -62,7 +62,7 @@ public string Format if (IsValidFormat(value)) Values.Format = value; else - throw new ArgumentException(DomSR.InvalidFieldFormat(value)); + throw new ArgumentException(MdDomMsgs.InvalidFieldFormat(value).Message); } } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs index 710dcd4b..d996ceaf 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParser.cs @@ -1,8 +1,6 @@ // MigraDoc - Creating Documents on the Fly // See the LICENSE file in the solution root for more information. -#define SECTIONFIX // BUG: Verify changes and clean if checked. - using MigraDoc.DocumentObjectModel.Tables; using MigraDoc.DocumentObjectModel.Shapes; using MigraDoc.DocumentObjectModel.Shapes.Charts; @@ -42,12 +40,12 @@ internal Document ParseDocument(Document? document) document ??= new Document(); MoveToCode(); - AssertSymbol(Symbol.Document); + EnsureSymbol(Symbol.Document); ReadCode(); if (Symbol == Symbol.BracketLeft) ParseAttributes(document); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); ReadCode(); while (Symbol == Symbol.EmbeddedFile) @@ -60,9 +58,9 @@ internal Document ParseDocument(Document? document) while (Symbol == Symbol.Section) ParseSection(document.Sections); - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); ReadCode(); - AssertCondition(Symbol == Symbol.Eof, DomMsgID.EndOfFileExpected); + EnsureCondition(Symbol == Symbol.Eof, () => MdDomMsgs.EndOfFileExpected); return document; } @@ -114,11 +112,11 @@ internal Document ParseDocument(Document? document) break; default: - ThrowParserException(DomMsgID.UnexpectedSymbol); + ThrowParserException(MdDomMsgs.UnexpectedSymbol(Token)); break; } ReadCode(); - AssertCondition(Symbol == Symbol.Eof, DomMsgID.EndOfFileExpected); + EnsureCondition(Symbol == Symbol.Eof, () => MdDomMsgs.EndOfFileExpected); return obj; } @@ -129,17 +127,17 @@ internal Document ParseDocument(Document? document) Styles ParseStyles(Styles styles) { MoveToCode(); - AssertSymbol(Symbol.Styles); + EnsureSymbol(Symbol.Styles); ReadCode(); // read '{' - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); ReadCode(); // read first style name // An empty \styles block is valid. while (Symbol is Symbol.Identifier or Symbol.StringLiteral) ParseStyleDefinition(styles); - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); ReadCode(); // read beyond '}' return styles; @@ -157,11 +155,11 @@ Styles ParseStyles(Styles styles) Style? style = null; try { - var styleName = _scanner.Token; + var styleName = Token; string? baseStyleName = null; if (Symbol != Symbol.Identifier && Symbol != Symbol.StringLiteral) - ThrowParserException(DomMsgID.StyleNameExpected, styleName); + ThrowParserException(MdDomMsgs.StyleNameExpected(styleName)); ReadCode(); @@ -169,13 +167,13 @@ Styles ParseStyles(Styles styles) { ReadCode(); if (Symbol != Symbol.Identifier && Symbol != Symbol.StringLiteral) - ThrowParserException(DomMsgID.StyleNameExpected, styleName); + ThrowParserException(MdDomMsgs.StyleNameExpected(styleName)); // If baseStyle is not valid, choose InvalidStyleName by default. - baseStyleName = _scanner.Token; + baseStyleName = Token; if (styles.GetIndex(baseStyleName) == -1) { - ReportParserInfo(DdlErrorLevel.Warning, DomMsgID.UseOfUndefinedBaseStyle, baseStyleName); + ReportParserInfo(DdlErrorLevel.Warning, MdDomMsgs.UseOfUndefinedBaseStyle(baseStyleName)); baseStyleName = StyleNames.InvalidStyleName; } @@ -196,14 +194,12 @@ Styles ParseStyles(Styles styles) if (String.IsNullOrEmpty(baseStyleName)) { baseStyleName = StyleNames.InvalidStyleName; - ReportParserInfo(DdlErrorLevel.Warning, DomMsgID.UseOfUndefinedStyle, styleName); + ReportParserInfo(DdlErrorLevel.Warning, MdDomMsgs.UseOfUndefinedStyle(styleName)); } - style = styles.AddStyle(styleName, baseStyleName); } // Parse definition (if any). - if (Symbol == Symbol.BraceLeft) { ParseAttributeBlock(style); @@ -237,7 +233,7 @@ EmbeddedFiles ParseEmbeddedFiles(EmbeddedFiles embeddedFiles) Debug.Assert(embeddedFiles != null); MoveToCode(); - AssertSymbol(Symbol.EmbeddedFile); + EnsureSymbol(Symbol.EmbeddedFile); try { @@ -264,7 +260,7 @@ EmbeddedFiles ParseEmbeddedFiles(EmbeddedFiles embeddedFiles) Debug.Assert(sections != null); MoveToCode(); - AssertSymbol(Symbol.Section); + EnsureSymbol(Symbol.Section); Section? section = null; try @@ -275,18 +271,22 @@ EmbeddedFiles ParseEmbeddedFiles(EmbeddedFiles embeddedFiles) if (Symbol == Symbol.BracketLeft) ParseAttributes(section); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); -#if SECTIONFIX // DllParser was not able to read directly added paragraph content after headers and footers. This was an old error already existing in MigraDoc 1.51. ReadMoreContent: - if (IsParagraphContent()) // IsParagraphContent() must be checked first, before moving to the next token by ReadCode(). + // If a section contains only one paragraph, the paragraph keyword is omitted in MDDDL and the paragraph content is directly inserted into the section. + // The IsParagraphContent() check has to be made, before moving to the next token by ReadCode(). + if (IsParagraphContent()) { + // Paragraph content was inserted directly into the section. var paragraph = section.Elements.AddParagraph(); ParseParagraphContent(section.Elements, paragraph); + // After paragraph content, there must not be any HeaderFooter or other document elements in the section. } else { - ReadCode(); // Read next token. + // Read next token to check for HeaderFooter or the section’s document elements. + ReadCode(); if (IsHeaderFooter()) { @@ -297,26 +297,8 @@ EmbeddedFiles ParseEmbeddedFiles(EmbeddedFiles embeddedFiles) } ParseDocumentElements(section.Elements, Symbol.Section); } -#else - // Consider the case that the keyword «\paragraph» can be omitted. - if (IsParagraphContent()) - { - var paragraph = section.Elements.AddParagraph(); - ParseParagraphContent(section.Elements, paragraph); - } - else - { - ReadCode(); // read beyond '{' - // 1st parse headers and footers - while (IsHeaderFooter()) - ParseHeaderFooter(section); - - // 2nd parse all other stuff - ParseDocumentElements(section.Elements, Symbol.Section); - } -#endif - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); ReadCode(); // read beyond '}' } catch (DdlParserException ex) @@ -327,16 +309,10 @@ EmbeddedFiles ParseEmbeddedFiles(EmbeddedFiles embeddedFiles) return section; } -#if SECTIONFIX /// /// Parses the keywords «\header». /// Doesn’t move to next token as paragraph content may follow, which has to be checked before moving to the next token. /// -#else - /// - /// Parses the keywords «\header». - /// -#endif void ParseHeaderFooter(Section section) { if (section == null) @@ -358,7 +334,7 @@ void ParseHeaderFooter(Section section) if (Symbol == Symbol.BracketLeft) ParseAttributes(headerFooter); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); if (IsParagraphContent()) { Paragraph paragraph = headerFooter.Elements.AddParagraph(); @@ -369,12 +345,7 @@ void ParseHeaderFooter(Section section) ReadCode(); // parse '{' ParseDocumentElements(headerFooter.Elements, Symbol.HeaderOrFooter); } - AssertSymbol(Symbol.BraceRight); -#if SECTIONFIX - // Removed ReadCode() as a check for paragraph content after headers and footers has to be made before moving to the next token. -#else - ReadCode(); // parse beyond '{' -#endif + EnsureSymbol(Symbol.BraceRight); HeadersFooters headersFooters = isHeader ? section.Headers : section.Footers; if (hdrFtrSym is Symbol.Header or Symbol.Footer) @@ -500,7 +471,7 @@ DocumentElements ParseDocumentElements(DocumentElements elements, Symbol context break; default: - ThrowParserException(DomMsgID.UnexpectedSymbol, _scanner.Token); + ThrowParserException(MdDomMsgs.UnexpectedSymbol(Token)); break; } } @@ -513,7 +484,7 @@ DocumentElements ParseDocumentElements(DocumentElements elements, Symbol context void ParseParagraph(DocumentElements elements) { MoveToCode(); - AssertSymbol(Symbol.Paragraph); + EnsureSymbol(Symbol.Paragraph); Paragraph paragraph = elements.AddParagraph(); try @@ -526,7 +497,7 @@ void ParseParagraph(DocumentElements elements) if (Symbol == Symbol.BraceLeft) { ParseParagraphContent(elements, paragraph); - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); ReadCode(); // read beyond '}' } } @@ -587,7 +558,7 @@ void ParseFormattedText(ParagraphElements elements, int nestingLevel) switch (Symbol) { case Symbol.Eof: - ThrowParserException(DomMsgID.UnexpectedEndOfFile); + ThrowParserException(MdDomMsgs.UnexpectedEndOfFile); break; case Symbol.EmptyLine: @@ -691,7 +662,7 @@ void ParseFormattedText(ParagraphElements elements, int nestingLevel) break; default: - ThrowParserException(DomMsgID.UnexpectedSymbol, Token); + ThrowParserException(MdDomMsgs.UnexpectedSymbol(Token)); break; } } @@ -703,9 +674,9 @@ void ParseFormattedText(ParagraphElements elements, int nestingLevel) void ParseBoldItalicEtc(FormattedText formattedText, int nestingLevel) { ReadCode(); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); ParseFormattedText(formattedText.Elements, nestingLevel); - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); } /// @@ -713,7 +684,7 @@ void ParseBoldItalicEtc(FormattedText formattedText, int nestingLevel) /// void ParseFont(FormattedText formattedText, int nestingLevel) { - AssertSymbol(Symbol.Font); + EnsureSymbol(Symbol.Font); ReadCode(); if (Symbol == Symbol.ParenLeft) @@ -725,9 +696,9 @@ void ParseFont(FormattedText formattedText, int nestingLevel) if (Symbol == Symbol.BracketLeft) ParseAttributes(formattedText); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); ParseFormattedText(formattedText.Elements, nestingLevel); - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); } /// @@ -735,14 +706,14 @@ void ParseFont(FormattedText formattedText, int nestingLevel) /// string ParseElementName() { - AssertSymbol(Symbol.ParenLeft); + EnsureSymbol(Symbol.ParenLeft); ReadCode(); if (Symbol != Symbol.StringLiteral) - ThrowParserException(DomMsgID.StringExpected, Token); + ThrowParserException(MdDomMsgs.StringValueExpected(Token)); string name = Token; ReadCode(); - AssertSymbol(Symbol.ParenRight); + EnsureSymbol(Symbol.ParenRight); return name; } @@ -752,20 +723,20 @@ string ParseElementName() /// void ParseFontSize(FormattedText formattedText, int nestingLevel) { - AssertSymbol(Symbol.FontSize); + EnsureSymbol(Symbol.FontSize); ReadCode(); - AssertSymbol(Symbol.ParenLeft); + EnsureSymbol(Symbol.ParenLeft); ReadCode(); //NYI: Check token for correct Unit format formattedText.Font.Size = Token; ReadCode(); - AssertSymbol(Symbol.ParenRight); + EnsureSymbol(Symbol.ParenRight); ReadCode(); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); ParseFormattedText(formattedText.Elements, nestingLevel); - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); } /// @@ -773,18 +744,18 @@ void ParseFontSize(FormattedText formattedText, int nestingLevel) /// void ParseFontColor(FormattedText formattedText, int nestingLevel) { - AssertSymbol(Symbol.FontColor); + EnsureSymbol(Symbol.FontColor); ReadCode(); // read '(' - AssertSymbol(Symbol.ParenLeft); + EnsureSymbol(Symbol.ParenLeft); ReadCode(); // read color token Color color = ParseColor(); formattedText.Font.Color = color; - AssertSymbol(Symbol.ParenRight); + EnsureSymbol(Symbol.ParenRight); ReadCode(); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); ParseFormattedText(formattedText.Elements, nestingLevel); - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); } /// @@ -792,10 +763,10 @@ void ParseFontColor(FormattedText formattedText, int nestingLevel) /// void ParseSymbol(ParagraphElements elements) { - AssertSymbol(Symbol.Symbol); + EnsureSymbol(Symbol.Symbol); ReadCode(); // read '(' - AssertSymbol(Symbol.ParenLeft); + EnsureSymbol(Symbol.ParenLeft); const char ch = (char)0; SymbolName symType = 0; @@ -808,18 +779,18 @@ void ParseSymbol(ParagraphElements elements) { if (Enum.IsDefined(typeof(SymbolName), Token)) { - AssertCondition(IsSymbolType(Token), DomMsgID.InvalidSymbolType, Token); + EnsureCondition(IsSymbolType(Token), () => MdDomMsgs.InvalidSymbolType(Token)); symType = (SymbolName)Enum.Parse(typeof(SymbolName), Token, true); } } catch (Exception ex) { - ThrowParserException(ex, DomMsgID.InvalidEnum, Token); + ThrowParserException(MdDomMsgs.InvalidEnum(Token, nameof(SymbolName)), ex); } } else { - ThrowParserException(DomMsgID.UnexpectedSymbol, Token); + ThrowParserException(MdDomMsgs.UnexpectedSymbol(Token)); } ReadCode(); // read integer or identifier @@ -831,7 +802,7 @@ void ParseSymbol(ParagraphElements elements) ReadCode(); } - AssertSymbol(Symbol.ParenRight); + EnsureSymbol(Symbol.ParenRight); if (symType != 0) elements.AddCharacter(symType, count); @@ -844,10 +815,10 @@ void ParseSymbol(ParagraphElements elements) /// void ParseChr(ParagraphElements elements) { - AssertSymbol(Symbol.Chr); + EnsureSymbol(Symbol.Chr); ReadCode(); // read '(' - AssertSymbol(Symbol.ParenLeft); + EnsureSymbol(Symbol.ParenLeft); char ch = (char)0; SymbolName symType = 0; @@ -860,11 +831,11 @@ void ParseChr(ParagraphElements elements) if (val is >= 1 and <= 255) ch = (char)val; else - ThrowParserException(DomMsgID.OutOfRange, "1 - 255"); + ThrowParserException(MdDomMsgs.OutOfRange("1 - 255")); } else { - ThrowParserException(DomMsgID.UnexpectedSymbol, Token); + ThrowParserException(MdDomMsgs.UnexpectedSymbol(Token)); } ReadCode(); // read integer or identifier @@ -876,7 +847,7 @@ void ParseChr(ParagraphElements elements) ReadCode(); } - AssertSymbol(Symbol.ParenRight); + EnsureSymbol(Symbol.ParenRight); if (symType != 0) elements.AddCharacter(symType, count); @@ -891,17 +862,17 @@ void ParseChr(ParagraphElements elements) void ParseField(ParagraphElements elements, int nestingLevel) #pragma warning restore IDE0060 { - AssertSymbol(Symbol.Field); + EnsureSymbol(Symbol.Field); ReadCode(); // read '(' - AssertSymbol(Symbol.ParenLeft); + EnsureSymbol(Symbol.ParenLeft); ReadCode(); // read identifier - AssertSymbol(Symbol.Identifier); + EnsureSymbol(Symbol.Identifier); string fieldType = Token.ToLower(); ReadCode(); // read ')' - AssertSymbol(Symbol.ParenRight); + EnsureSymbol(Symbol.ParenRight); DocumentObject? field = null; switch (fieldType) @@ -914,6 +885,7 @@ void ParseField(ParagraphElements elements, int nestingLevel) field = elements.AddPageField(); break; + // ReSharper disable once StringLiteralTypo case "numpages": field = elements.AddNumPagesField(); break; @@ -922,6 +894,7 @@ void ParseField(ParagraphElements elements, int nestingLevel) field = elements.AddInfoField(0); break; + // ReSharper disable once StringLiteralTypo case "sectionpages": field = elements.AddSectionPagesField(); break; @@ -934,11 +907,12 @@ void ParseField(ParagraphElements elements, int nestingLevel) field = elements.AddBookmark(""); break; + // ReSharper disable once StringLiteralTypo case "pageref": field = elements.AddPageRefField(""); break; } - AssertCondition(field != null, DomMsgID.InvalidFieldType, Token); + EnsureCondition(field != null, () => MdDomMsgs.InvalidFieldType(Token)); if (_scanner.PeekSymbol() == Symbol.BracketLeft) { @@ -954,14 +928,14 @@ void ParseField(ParagraphElements elements, int nestingLevel) void ParseFootnote(ParagraphElements elements, int nestingLevel) #pragma warning restore IDE0060 { - AssertSymbol(Symbol.Footnote); + EnsureSymbol(Symbol.Footnote); ReadCode(); - Footnote footnote = elements.AddFootnote(); + var footnote = elements.AddFootnote(); if (Symbol == Symbol.BracketLeft) ParseAttributes(footnote); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); // The keyword «\paragraph» is typically omitted. if (IsParagraphContent()) @@ -974,7 +948,7 @@ void ParseFootnote(ParagraphElements elements, int nestingLevel) ReadCode(); // read beyond '{' ParseDocumentElements(footnote.Elements, Symbol.Footnote); } - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); } /// @@ -982,7 +956,7 @@ void ParseFootnote(ParagraphElements elements, int nestingLevel) /// void ParseHyperlink(ParagraphElements elements, int nestingLevel) { - AssertSymbol(Symbol.Hyperlink); + EnsureSymbol(Symbol.Hyperlink); ReadCode(); Hyperlink hyperlink = elements.AddHyperlink(""); @@ -990,9 +964,9 @@ void ParseHyperlink(ParagraphElements elements, int nestingLevel) if (Symbol == Symbol.BracketLeft) ParseAttributes(hyperlink); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); ParseFormattedText(hyperlink.Elements, nestingLevel); - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); } /// @@ -1007,7 +981,7 @@ void ParseSpace(ParagraphElements elements, int nestingLevel) // \space(5) // \space(em) // \space(em,5) - AssertSymbol(Symbol.Space); + EnsureSymbol(Symbol.Space); Character space = elements.AddSpace(1); @@ -1015,14 +989,14 @@ void ParseSpace(ParagraphElements elements, int nestingLevel) if (_scanner.PeekSymbol() == Symbol.ParenLeft) { ReadCode(); // read '(' - AssertSymbol(Symbol.ParenLeft); + EnsureSymbol(Symbol.ParenLeft); ReadCode(); // read beyond '(' if (Symbol == Symbol.Identifier) { string type = Token; if (!IsSpaceType(type)) - ThrowParserException(DomMsgID.InvalidEnum, type); + ThrowParserException(MdDomMsgs.InvalidEnum(type, nameof(SymbolName))); space.SymbolName = (SymbolName)Enum.Parse(typeof(SymbolName), type, true); @@ -1030,7 +1004,7 @@ void ParseSpace(ParagraphElements elements, int nestingLevel) if (Symbol == Symbol.Comma) { ReadCode(); // read integer - AssertSymbol(Symbol.IntegerLiteral); + EnsureSymbol(Symbol.IntegerLiteral); space.Count = _scanner.GetTokenValueAsInt(); ReadCode(); // read ')' } @@ -1040,7 +1014,7 @@ void ParseSpace(ParagraphElements elements, int nestingLevel) space.Count = _scanner.GetTokenValueAsInt(); ReadCode(); } - AssertSymbol(Symbol.ParenRight); + EnsureSymbol(Symbol.ParenRight); } } @@ -1049,7 +1023,7 @@ void ParseSpace(ParagraphElements elements, int nestingLevel) /// void ParsePageBreak(DocumentElements elements) { - AssertSymbol(Symbol.PageBreak); + EnsureSymbol(Symbol.PageBreak); elements.AddPageBreak(); ReadCode(); } @@ -1070,24 +1044,24 @@ void ParseTable(DocumentElements? elements, Table? table) } MoveToCode(); - AssertSymbol(Symbol.Table); + EnsureSymbol(Symbol.Table); ReadCode(); - if (_scanner.Symbol == Symbol.BracketLeft) + if (Symbol == Symbol.BracketLeft) ParseAttributes(tbl); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); ReadCode(); // Table must start with «\columns»... - AssertSymbol(Symbol.Columns); + EnsureSymbol(Symbol.Columns); ParseColumns(tbl); // ...followed by «\rows». - AssertSymbol(Symbol.Rows); + EnsureSymbol(Symbol.Rows); ParseRows(tbl); - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); ReadCode(); // read beyond '}' } catch (DdlParserException ex) @@ -1109,7 +1083,7 @@ void ParseColumns(Table table) if (Symbol == Symbol.BracketLeft) ParseAttributes(table.Columns); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); ReadCode(); var loop = true; @@ -1118,7 +1092,7 @@ void ParseColumns(Table table) switch (Symbol) { case Symbol.Eof: - ThrowParserException(DomMsgID.UnexpectedEndOfFile); + ThrowParserException(MdDomMsgs.UnexpectedEndOfFile); break; case Symbol.BraceRight: @@ -1131,7 +1105,7 @@ void ParseColumns(Table table) break; default: - AssertSymbol(Symbol.Column); + EnsureSymbol(Symbol.Column); break; } } @@ -1153,7 +1127,7 @@ void ParseColumn(Column column) if (Symbol == Symbol.BraceLeft) { ReadCode(); - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); ReadCode(); } } @@ -1170,7 +1144,7 @@ void ParseRows(Table table) if (Symbol == Symbol.BracketLeft) ParseAttributes(table.Rows); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); ReadCode(); var loop = true; @@ -1179,7 +1153,7 @@ void ParseRows(Table table) switch (Symbol) { case Symbol.Eof: - ThrowParserException(DomMsgID.UnexpectedEndOfFile); + ThrowParserException(MdDomMsgs.UnexpectedEndOfFile); break; case Symbol.BraceRight: @@ -1192,7 +1166,7 @@ void ParseRows(Table table) break; default: - AssertSymbol(Symbol.Row); + EnsureSymbol(Symbol.Row); break; } } @@ -1222,7 +1196,7 @@ void ParseRow(Row row) switch (Symbol) { case Symbol.Eof: - ThrowParserException(DomMsgID.UnexpectedEndOfFile); + ThrowParserException(MdDomMsgs.UnexpectedEndOfFile); break; case Symbol.BraceRight: @@ -1236,7 +1210,7 @@ void ParseRow(Row row) break; default: - ThrowParserException(DomMsgID.UnexpectedSymbol, Token); + ThrowParserException(MdDomMsgs.UnexpectedSymbol(Token)); break; } } @@ -1268,7 +1242,7 @@ void ParseCell(Cell cell) if (Symbol != Symbol.BraceRight) ParseDocumentElements(cell.Elements, Symbol.Cell); } - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); ReadCode(); // read '}' } } @@ -1288,10 +1262,10 @@ void ParseImage(Image image, bool paragraphContent) try { MoveToCode(); - AssertSymbol(Symbol.Image); + EnsureSymbol(Symbol.Image); ReadCode(); - if (_scanner.Symbol == Symbol.ParenLeft) + if (Symbol == Symbol.ParenLeft) image.Name = ParseElementName(); if (_scanner.PeekSymbol() == Symbol.BracketLeft) @@ -1316,14 +1290,14 @@ void ParseTextFrame(DocumentElements elements) { Debug.Assert(elements != null); - TextFrame textFrame = elements.AddTextFrame(); + var textFrame = elements.AddTextFrame(); try { ReadCode(); - if (_scanner.Symbol == Symbol.BracketLeft) + if (Symbol == Symbol.BracketLeft) ParseAttributes(textFrame); - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); if (IsParagraphContent()) { ParseParagraphContent(textFrame.Elements, null); @@ -1333,7 +1307,7 @@ void ParseTextFrame(DocumentElements elements) ReadCode(); // read '{' ParseDocumentElements(textFrame.Elements, Symbol.TextFrame); } - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); ReadCode(); // read beyond '}' } catch (DdlParserException ex) @@ -1354,22 +1328,22 @@ void ParseBarcode(DocumentElements elements) try { ReadCode(); - AssertSymbol(Symbol.ParenLeft, DomMsgID.MissingParenLeft, GetSymbolText(Symbol.Barcode)); + EnsureSymbol(Symbol.ParenLeft, () => MdDomMsgs.MissingParenLeft(GetSymbolText(Symbol.Barcode))); ReadCode(); - AssertSymbol(Symbol.StringLiteral, DomMsgID.UnexpectedSymbol); + EnsureSymbol(Symbol.StringLiteral, () => MdDomMsgs.UnexpectedSymbol(Token)); - Barcode barcode = elements.AddBarcode(); + var barcode = elements.AddBarcode(); barcode.SetValue("Code", Token); ReadCode(); if (Symbol == Symbol.Comma) { ReadCode(); - AssertSymbol(Symbol.Identifier, DomMsgID.IdentifierExpected, Token); + EnsureSymbol(Symbol.Identifier, () => MdDomMsgs.IdentifierExpected(Token)); BarcodeType barcodeType = (BarcodeType)Enum.Parse(typeof(BarcodeType), Token, true); barcode.SetValue("type", barcodeType); ReadCode(); } - AssertSymbol(Symbol.ParenRight, DomMsgID.MissingParenRight, GetSymbolText(Symbol.Barcode)); + EnsureSymbol(Symbol.ParenRight, () => MdDomMsgs.MissingParenRight(GetSymbolText(Symbol.Barcode))); ReadCode(); if (Symbol == Symbol.BracketLeft) @@ -1398,14 +1372,14 @@ void ParseChart(DocumentElements elements) try { ReadCode(); // read '(' - AssertSymbol(Symbol.ParenLeft, DomMsgID.MissingParenLeft, GetSymbolText(Symbol.Chart)); + EnsureSymbol(Symbol.ParenLeft, () => MdDomMsgs.MissingParenLeft(GetSymbolText(Symbol.Chart))); ReadCode(); // ChartType name - AssertSymbol(Symbol.Identifier, DomMsgID.IdentifierExpected, Token); + EnsureSymbol(Symbol.Identifier, () => MdDomMsgs.IdentifierExpected(Token)); string chartTypeName = Token; ReadCode(); // read ')' - AssertSymbol(Symbol.ParenRight, DomMsgID.MissingParenRight, GetSymbolText(Symbol.Chart)); + EnsureSymbol(Symbol.ParenRight, () => MdDomMsgs.MissingParenRight(GetSymbolText(Symbol.Chart))); try { @@ -1413,16 +1387,16 @@ void ParseChart(DocumentElements elements) } catch (Exception ex) { - ThrowParserException(ex, DomMsgID.UnknownChartType, chartTypeName); + ThrowParserException(MdDomMsgs.UnknownChartType(chartTypeName), ex); } - Chart chart = elements.AddChart(chartType); + var chart = elements.AddChart(chartType); ReadCode(); if (Symbol == Symbol.BracketLeft) ParseAttributes(chart); - AssertSymbol(Symbol.BraceLeft, DomMsgID.MissingBraceLeft, GetSymbolText(Symbol.Chart)); + EnsureSymbol(Symbol.BraceLeft, () => MdDomMsgs.MissingBraceLeft(GetSymbolText(Symbol.Chart))); ReadCode(); // read beyond '{' @@ -1432,7 +1406,7 @@ void ParseChart(DocumentElements elements) switch (Symbol) { case Symbol.Eof: - ThrowParserException(DomMsgID.UnexpectedEndOfFile); + ThrowParserException(MdDomMsgs.UnexpectedEndOfFile); break; case Symbol.BraceRight: @@ -1488,7 +1462,7 @@ void ParseChart(DocumentElements elements) break; default: - ThrowParserException(DomMsgID.UnexpectedSymbol, Token); + ThrowParserException(MdDomMsgs.UnexpectedSymbol(Token)); break; } } @@ -1534,10 +1508,11 @@ void ParseArea(PlotArea area) default: // Ignore all? Issue warning? + _ = typeof(int); break; } } - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); ReadCode(); // read beyond '}' } catch (DdlParserException pe) @@ -1608,12 +1583,12 @@ void ParseArea(TextArea area) break; default: - ThrowParserException(DomMsgID.UnexpectedSymbol, Token); + ThrowParserException(MdDomMsgs.UnexpectedSymbol(Token)); break; } } } - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); ReadCode(); // read beyond '}' } catch (DdlParserException pe) @@ -1649,7 +1624,7 @@ void ParseAxes(Axis axis, Symbol symbolAxis) while (Symbol != Symbol.BraceRight) ReadCode(); - AssertSymbol(Symbol.BraceRight, DomMsgID.MissingBraceRight, GetSymbolText(symbolAxis)); + EnsureSymbol(Symbol.BraceRight, () => MdDomMsgs.MissingBraceRight(GetSymbolText(symbolAxis))); ReadCode(); // read beyond '}' } catch (DdlParserException pe) @@ -1674,7 +1649,7 @@ void ParseSeries(Series series) if (Symbol == Symbol.BracketLeft) ParseAttributes(series); - AssertSymbol(Symbol.BraceLeft, DomMsgID.MissingBraceLeft, GetSymbolText(Symbol.Series)); + EnsureSymbol(Symbol.BraceLeft, () => MdDomMsgs.MissingBraceLeft(GetSymbolText(Symbol.Series))); ReadCode(); // read beyond '{' bool fContinue = true; @@ -1684,7 +1659,7 @@ void ParseSeries(Series series) switch (Symbol) { case Symbol.Eof: - ThrowParserException(DomMsgID.UnexpectedEndOfFile); + ThrowParserException(MdDomMsgs.UnexpectedEndOfFile); break; case Symbol.BraceRight: @@ -1697,27 +1672,27 @@ void ParseSeries(Series series) break; case Symbol.Point: - AssertCondition(fFoundComma, DomMsgID.MissingComma); + EnsureCondition(fFoundComma, () => MdDomMsgs.MissingComma); ParsePoint(series.Add(0)); fFoundComma = false; break; case Symbol.Null: - AssertCondition(fFoundComma, DomMsgID.MissingComma); + EnsureCondition(fFoundComma, () => MdDomMsgs.MissingComma); series.AddBlank(); fFoundComma = false; ReadCode(); break; default: - AssertCondition(fFoundComma, DomMsgID.MissingComma); + EnsureCondition(fFoundComma, () => MdDomMsgs.MissingComma); series.Add(_scanner.GetTokenValueAsReal()); fFoundComma = false; ReadCode(); break; } } - AssertSymbol(Symbol.BraceRight, DomMsgID.MissingBraceRight, GetSymbolText(Symbol.Series)); + EnsureSymbol(Symbol.BraceRight, () => MdDomMsgs.MissingBraceRight(GetSymbolText(Symbol.Series))); ReadCode(); // read beyond '}' } catch (DdlParserException pe) @@ -1738,7 +1713,7 @@ void ParseSeries(XSeries series) try { ReadCode(); - AssertSymbol(Symbol.BraceLeft, DomMsgID.MissingBraceLeft, GetSymbolText(Symbol.Series)); + EnsureSymbol(Symbol.BraceLeft, () => MdDomMsgs.MissingBraceLeft(GetSymbolText(Symbol.Series))); bool fFoundComma = true; bool fContinue = true; @@ -1748,7 +1723,7 @@ void ParseSeries(XSeries series) switch (Symbol) { case Symbol.Eof: - ThrowParserException(DomMsgID.UnexpectedEndOfFile); + ThrowParserException(MdDomMsgs.UnexpectedEndOfFile); break; case Symbol.BraceRight: @@ -1760,7 +1735,7 @@ void ParseSeries(XSeries series) break; case Symbol.Null: - AssertCondition(fFoundComma, DomMsgID.MissingComma); + EnsureCondition(fFoundComma, () => MdDomMsgs.MissingComma); series.AddBlank(); fFoundComma = false; break; @@ -1769,17 +1744,17 @@ void ParseSeries(XSeries series) case Symbol.IntegerLiteral: case Symbol.RealLiteral: case Symbol.HexIntegerLiteral: - AssertCondition(fFoundComma, DomMsgID.MissingComma); + EnsureCondition(fFoundComma, () => MdDomMsgs.MissingComma); series.Add(Token); fFoundComma = false; break; default: - ThrowParserException(DomMsgID.UnexpectedSymbol, Token); + ThrowParserException(MdDomMsgs.UnexpectedSymbol(Token)); break; } } - AssertSymbol(Symbol.BraceRight, DomMsgID.MissingBraceRight, GetSymbolText(Symbol.Series)); + EnsureSymbol(Symbol.BraceRight, () => MdDomMsgs.MissingBraceRight(GetSymbolText(Symbol.Series))); ReadCode(); // read beyond '}' } catch (DdlParserException pe) @@ -1804,12 +1779,12 @@ void ParsePoint(Point point) if (Symbol == Symbol.BracketLeft) ParseAttributes(point); - AssertSymbol(Symbol.BraceLeft, DomMsgID.MissingBraceLeft, GetSymbolText(Symbol.Point)); + EnsureSymbol(Symbol.BraceLeft, () => MdDomMsgs.MissingBraceLeft(GetSymbolText(Symbol.Point))); ReadCode(); // read beyond '{' point.Value = _scanner.GetTokenValueAsReal(); ReadCode(); // read '}' - AssertSymbol(Symbol.BraceRight, DomMsgID.MissingBraceRight, GetSymbolText(Symbol.Point)); + EnsureSymbol(Symbol.BraceRight, () => MdDomMsgs.MissingBraceRight(GetSymbolText(Symbol.Point))); ReadCode(); // read beyond '}' } catch (DdlParserException pe) @@ -1857,13 +1832,13 @@ void ParseLegend(Legend legend) /// void ParseAttributes(DocumentObject element, bool readNextSymbol) { - AssertSymbol(Symbol.BracketLeft); + EnsureSymbol(Symbol.BracketLeft); ReadCode(); // read beyond '[' while (Symbol == Symbol.Identifier) ParseAttributeStatement(element); - AssertSymbol(Symbol.BracketRight); + EnsureSymbol(Symbol.BracketRight); // Do not read ']' when parsing in paragraph content. if (readNextSymbol) @@ -1897,7 +1872,7 @@ void ParseAttributeStatement(DocumentObject? doc) var valueName = ""; try { - valueName = _scanner.Token; + valueName = Token; ReadCode(); // Resolve path, if it exists. @@ -1912,14 +1887,14 @@ void ParseAttributeStatement(DocumentObject? doc) val = documentObject.CreateValue(valueName); doc.SetValue(valueName, val); } - AssertCondition(val != null, DomMsgID.InvalidValueName, valueName); + EnsureCondition(val != null, () => MdDomMsgs.InvalidValueName(valueName)); doc = val as DocumentObject; - AssertCondition(doc != null, DomMsgID.SymbolIsNotAnObject, valueName); + EnsureCondition(doc != null, () => MdDomMsgs.SymbolIsNotAnObject(valueName)); ReadCode(); - AssertCondition(Symbol == Symbol.Identifier, DomMsgID.InvalidValueName, _scanner.Token); - valueName = _scanner.Token; - AssertCondition(valueName[0] != '_', DomMsgID.NoAccess, _scanner.Token); + EnsureCondition(Symbol == Symbol.Identifier, () => MdDomMsgs.InvalidValueName(Token)); + valueName = Token; + EnsureCondition(valueName[0] != '_', () => MdDomMsgs.NoAccess(Token)); ReadCode(); } @@ -1930,7 +1905,7 @@ void ParseAttributeStatement(DocumentObject? doc) case Symbol.Assign: //DomValueDescriptor is needed from assignment routine. var pvd = doc.Meta[valueName]; - AssertCondition(pvd != null, DomMsgID.InvalidValueName, valueName); + EnsureCondition(pvd != null, () => MdDomMsgs.InvalidValueName(valueName)); ParseAssign(doc, pvd); break; @@ -1938,9 +1913,9 @@ void ParseAttributeStatement(DocumentObject? doc) case Symbol.MinusAssign: // Hard-coded for TabStops only... if (doc is not ParagraphFormat) - ThrowParserException(DomMsgID.SymbolNotAllowed, _scanner.Token); + ThrowParserException(MdDomMsgs.SymbolNotAllowed(Token)); if (String.Compare(valueName, "TabStops", StringComparison.OrdinalIgnoreCase) != 0) - ThrowParserException(DomMsgID.InvalidValueForOperation, valueName, _scanner.Token); + ThrowParserException(MdDomMsgs.InvalidValueForOperation(valueName, Token)); ParagraphFormat paragraphFormat = (ParagraphFormat)doc; TabStops tabStops = paragraphFormat.TabStops; @@ -1965,7 +1940,7 @@ void ParseAttributeStatement(DocumentObject? doc) ReadCode(); } else - ThrowParserException(DomMsgID.UnexpectedSymbol, Token); + ThrowParserException(MdDomMsgs.UnexpectedSymbol(Token)); if (fAddItem) tabStops.AddTabStop(tabStop); @@ -1976,16 +1951,16 @@ void ParseAttributeStatement(DocumentObject? doc) case Symbol.BraceLeft: val = doc.GetValue(valueName); - AssertCondition(val != null, DomMsgID.InvalidValueName, valueName); + EnsureCondition(val != null, () => MdDomMsgs.InvalidValueName(valueName)); if (val is DocumentObject doc2) ParseAttributeBlock(doc2); else - ThrowParserException(DomMsgID.SymbolIsNotAnObject, valueName); + ThrowParserException(MdDomMsgs.SymbolIsNotAnObject(valueName)); break; default: - ThrowParserException(DomMsgID.SymbolNotAllowed, _scanner.Token); + ThrowParserException(MdDomMsgs.SymbolNotAllowed(Token)); return; } } @@ -1994,9 +1969,9 @@ void ParseAttributeStatement(DocumentObject? doc) ReportParserException(ex); AdjustToNextBlock(); } - catch (ArgumentException e) + catch (ArgumentException ex) { - ReportParserException(e, DomMsgID.InvalidAssignment, valueName); + ReportParserException(MdDomMsgs.InvalidAssignment(valueName), ex); } } @@ -2007,13 +1982,13 @@ void ParseAttributeBlock(DocumentObject element) { // Technically the same as ParseAttributes - AssertSymbol(Symbol.BraceLeft); + EnsureSymbol(Symbol.BraceLeft); ReadCode(); // move beyond '{' while (Symbol == Symbol.Identifier) ParseAttributeStatement(element); - AssertSymbol(Symbol.BraceRight); + EnsureSymbol(Symbol.BraceRight); ReadCode(); // move beyond '}' } @@ -2056,12 +2031,12 @@ void ParseAssign(DocumentObject dom, ValueDescriptor vd) else { AdjustToNextStatement(); - ThrowParserException(DomMsgID.InvalidType, vd.ValueType.Name, vd.ValueName); + ThrowParserException(MdDomMsgs.InvalidType(vd.ValueType.Name, vd.ValueName)); } } catch (Exception ex) { - ReportParserException(ex, DomMsgID.InvalidAssignment, vd.ValueName); + ReportParserException(MdDomMsgs.InvalidAssignment(vd.ValueName), ex); } } @@ -2070,8 +2045,8 @@ void ParseAssign(DocumentObject dom, ValueDescriptor vd) /// void ParseBoolAssignment(DocumentObject dom, ValueDescriptor vd) { - AssertCondition(Symbol is Symbol.True or Symbol.False, DomMsgID.BoolExpected, - _scanner.Token); + EnsureCondition(Symbol is Symbol.True or Symbol.False, + () => MdDomMsgs.BoolValueExpected(Token)); dom.SetValue(vd.ValueName, Symbol == Symbol.True); ReadCode(); @@ -2082,10 +2057,10 @@ void ParseBoolAssignment(DocumentObject dom, ValueDescriptor vd) /// void ParseIntegerAssignment(DocumentObject dom, ValueDescriptor vd) { - AssertCondition(Symbol is Symbol.IntegerLiteral or Symbol.HexIntegerLiteral or Symbol.StringLiteral, - DomMsgID.IntegerExpected, Token); + EnsureCondition(Symbol is Symbol.IntegerLiteral or Symbol.HexIntegerLiteral or Symbol.StringLiteral, + () => MdDomMsgs.IntegerValueExpected(Token)); - int n = Int32.Parse(_scanner.Token, CultureInfo.InvariantCulture); + int n = Int32.Parse(Token, CultureInfo.InvariantCulture); dom.SetValue(vd.ValueName, n); ReadCode(); @@ -2096,10 +2071,10 @@ void ParseIntegerAssignment(DocumentObject dom, ValueDescriptor vd) /// void ParseRealAssignment(DocumentObject dom, ValueDescriptor vd) { - AssertCondition(Symbol is Symbol.RealLiteral or Symbol.IntegerLiteral or Symbol.StringLiteral, - DomMsgID.RealExpected, _scanner.Token); + EnsureCondition(Symbol is Symbol.RealLiteral or Symbol.IntegerLiteral or Symbol.StringLiteral, + () => MdDomMsgs.RealValueExpected(Token)); - double r = double.Parse(_scanner.Token, CultureInfo.InvariantCulture); + double r = double.Parse(Token, CultureInfo.InvariantCulture); dom.SetValue(vd.ValueName, r); ReadCode(); @@ -2110,8 +2085,8 @@ void ParseRealAssignment(DocumentObject dom, ValueDescriptor vd) /// void ParseUnitAssignment(DocumentObject dom, ValueDescriptor vd) { - AssertCondition(Symbol is Symbol.RealLiteral or Symbol.IntegerLiteral or Symbol.StringLiteral, - DomMsgID.RealExpected, _scanner.Token); + EnsureCondition(Symbol is Symbol.RealLiteral or Symbol.IntegerLiteral or Symbol.StringLiteral, + () => MdDomMsgs.RealValueExpected(Token)); Unit unit = Token; dom.SetValue(vd.ValueName, unit); @@ -2123,7 +2098,7 @@ void ParseUnitAssignment(DocumentObject dom, ValueDescriptor vd) /// void ParseStringAssignment(DocumentObject dom, ValueDescriptor vd) { - AssertCondition(Symbol == Symbol.StringLiteral, DomMsgID.StringExpected, _scanner.Token); + EnsureCondition(Symbol == Symbol.StringLiteral, () => MdDomMsgs.StringValueExpected(_scanner.Token)); vd.SetValue(dom, Token); //dom.SetValue(vd.ValueName, scanner.Token); @@ -2135,7 +2110,7 @@ void ParseStringAssignment(DocumentObject dom, ValueDescriptor vd) /// void ParseEnumAssignment(DocumentObject dom, ValueDescriptor vd) { - AssertSymbol(Symbol.Identifier, DomMsgID.IdentifierExpected, _scanner.Token); + EnsureSymbol(Symbol.Identifier, () => MdDomMsgs.IdentifierExpected(Token)); try { @@ -2144,7 +2119,7 @@ void ParseEnumAssignment(DocumentObject dom, ValueDescriptor vd) } catch (Exception ex) { - ThrowParserException(ex, DomMsgID.InvalidEnum, _scanner.Token, vd.ValueName); + ThrowParserException(MdDomMsgs.InvalidEnum(Token, vd.ValueName), ex); } ReadCode(); // read next token @@ -2165,7 +2140,7 @@ void ParseValueTypeAssignment(DocumentObject dom, ValueDescriptor vd) } catch (Exception ex) { - ReportParserException(ex, DomMsgID.InvalidAssignment, vd.ValueName); + ReportParserException(MdDomMsgs.InvalidAssignment(vd.ValueName), ex); } } @@ -2193,7 +2168,7 @@ void ParseDocumentObjectAssignment(DocumentObject dom, ValueDescriptor vd) else if (typeof(TabStops) == type) (val as TabStops)?.ClearAll(); else - ThrowParserException(DomMsgID.NullAssignmentNotSupported, vd.ValueName); + ThrowParserException(MdDomMsgs.NullAssignmentNotSupported(vd.ValueName)); ReadCode(); } @@ -2205,7 +2180,7 @@ void ParseDocumentObjectAssignment(DocumentObject dom, ValueDescriptor vd) } catch (Exception ex) { - ReportParserException(ex, DomMsgID.InvalidAssignment, vd.ValueName); + ReportParserException(MdDomMsgs.InvalidAssignment(vd.ValueName), ex); } } @@ -2221,7 +2196,7 @@ void ParseValueAssignment(DocumentObject dom, ValueDescriptor vd) } catch (Exception ex) { - ThrowParserException(ex, DomMsgID.InvalidEnum, _scanner.Token, vd.ValueName); + ThrowParserException(MdDomMsgs.InvalidEnum(Token, vd.ValueName), ex); } ReadCode(); // read next token @@ -2275,7 +2250,7 @@ Color ParseColor() } catch (Exception ex) { - ThrowParserException(ex, DomMsgID.InvalidColor, _scanner.Token); + ThrowParserException(MdDomMsgs.InvalidColor(Token), ex); } break; } @@ -2290,7 +2265,7 @@ Color ParseColor() throw new NotImplementedException("ParseColor(color-name)"); } else - ThrowParserException(DomMsgID.StringExpected, _scanner.Token); + ThrowParserException(MdDomMsgs.StringValueExpected(Token)); return color; } @@ -2301,34 +2276,34 @@ Color ParseColor() Color ParseRGB() { ReadCode(); // read '(' - AssertSymbol(Symbol.ParenLeft); + EnsureSymbol(Symbol.ParenLeft); ReadCode(); // read red value - AssertCondition(Symbol is Symbol.IntegerLiteral or Symbol.HexIntegerLiteral, - DomMsgID.IntegerExpected, _scanner.Token); + EnsureCondition(Symbol is Symbol.IntegerLiteral or Symbol.HexIntegerLiteral, + () => MdDomMsgs.IntegerValueExpected(Token)); var r = _scanner.GetTokenValueAsUInt(); - AssertCondition(r is >= 0 and <= 255, DomMsgID.InvalidRange, "0 - 255"); + EnsureCondition(r is >= 0 and <= 255, () => MdDomMsgs.InvalidRange("0 - 255")); ReadCode(); // read ',' - AssertSymbol(Symbol.Comma); + EnsureSymbol(Symbol.Comma); ReadCode(); // read green value - AssertCondition(Symbol is Symbol.IntegerLiteral or Symbol.HexIntegerLiteral, - DomMsgID.IntegerExpected, _scanner.Token); + EnsureCondition(Symbol is Symbol.IntegerLiteral or Symbol.HexIntegerLiteral, + () => MdDomMsgs.IntegerValueExpected(Token)); var g = _scanner.GetTokenValueAsUInt(); - AssertCondition(g is >= 0 and <= 255, DomMsgID.InvalidRange, "0 - 255"); + EnsureCondition(g is >= 0 and <= 255, () => MdDomMsgs.InvalidRange("0 - 255")); ReadCode(); // read ',' - AssertSymbol(Symbol.Comma); + EnsureSymbol(Symbol.Comma); ReadCode(); // read blue value - AssertCondition(Symbol is Symbol.IntegerLiteral or Symbol.HexIntegerLiteral, - DomMsgID.IntegerExpected, _scanner.Token); + EnsureCondition(Symbol is Symbol.IntegerLiteral or Symbol.HexIntegerLiteral, + () => MdDomMsgs.IntegerValueExpected(Token)); var b = _scanner.GetTokenValueAsUInt(); - AssertCondition(b is >= 0 and <= 255, DomMsgID.InvalidRange, "0 - 255"); + EnsureCondition(b is >= 0 and <= 255, () => MdDomMsgs.InvalidRange("0 - 255")); ReadCode(); // read ')' - AssertSymbol(Symbol.ParenRight); + EnsureSymbol(Symbol.ParenRight); ReadCode(); // read next token @@ -2338,43 +2313,44 @@ Color ParseRGB() /// /// Parses «CMYK(c, m, y, k)» or «CMYK(a, c, m, y, k)». /// + // ReSharper disable once InconsistentNaming Color ParseCMYK() { ReadCode(); // read '(' - AssertSymbol(Symbol.ParenLeft); + EnsureSymbol(Symbol.ParenLeft); ReadCode(); // read v1 value - AssertCondition(Symbol is Symbol.IntegerLiteral or Symbol.RealLiteral, - DomMsgID.NumberExpected, _scanner.Token); + EnsureCondition(Symbol is Symbol.IntegerLiteral or Symbol.RealLiteral, + () => MdDomMsgs.NumberValueExpected(Token)); double v1 = _scanner.GetTokenValueAsReal(); - AssertCondition(v1 is >= 0 and <= 100, DomMsgID.InvalidRange, "0..100"); + EnsureCondition(v1 is >= 0 and <= 100, () => MdDomMsgs.InvalidRange("0..100")); ReadCode(); // read ',' - AssertSymbol(Symbol.Comma); + EnsureSymbol(Symbol.Comma); ReadCode(); // read v2 value - AssertCondition(Symbol is Symbol.IntegerLiteral or Symbol.RealLiteral, - DomMsgID.NumberExpected, _scanner.Token); + EnsureCondition(Symbol is Symbol.IntegerLiteral or Symbol.RealLiteral, + () => MdDomMsgs.NumberValueExpected(Token)); double v2 = _scanner.GetTokenValueAsReal(); - AssertCondition(v2 is >= 0 and <= 100, DomMsgID.InvalidRange, "0..100"); + EnsureCondition(v2 is >= 0 and <= 100, () => MdDomMsgs.InvalidRange("0..100")); ReadCode(); // read ',' - AssertSymbol(Symbol.Comma); + EnsureSymbol(Symbol.Comma); ReadCode(); // read v3 value - AssertCondition(Symbol is Symbol.IntegerLiteral or Symbol.RealLiteral, - DomMsgID.NumberExpected, _scanner.Token); + EnsureCondition(Symbol is Symbol.IntegerLiteral or Symbol.RealLiteral, + () => MdDomMsgs.NumberValueExpected(Token)); double v3 = _scanner.GetTokenValueAsReal(); - AssertCondition(v3 is >= 0 and <= 100, DomMsgID.InvalidRange, "0..100"); + EnsureCondition(v3 is >= 0 and <= 100, () => MdDomMsgs.InvalidRange("0..100")); ReadCode(); // read ',' - AssertSymbol(Symbol.Comma); + EnsureSymbol(Symbol.Comma); ReadCode(); // read v4 value - AssertCondition(Symbol is Symbol.IntegerLiteral or Symbol.RealLiteral, - DomMsgID.NumberExpected, _scanner.Token); + EnsureCondition(Symbol is Symbol.IntegerLiteral or Symbol.RealLiteral, + () => MdDomMsgs.NumberValueExpected(Token)); double v4 = _scanner.GetTokenValueAsReal(); - AssertCondition(v4 is >= 0 and <= 100, DomMsgID.InvalidRange, "0..100"); + EnsureCondition(v4 is >= 0 and <= 100, () => MdDomMsgs.InvalidRange("0..100")); ReadCode(); // read ')' or ',' bool hasAlpha = false; @@ -2383,14 +2359,14 @@ Color ParseCMYK() { hasAlpha = true; ReadCode(); // read v5 value - AssertCondition(Symbol is Symbol.IntegerLiteral or Symbol.RealLiteral, - DomMsgID.NumberExpected, _scanner.Token); + EnsureCondition(Symbol is Symbol.IntegerLiteral or Symbol.RealLiteral, + () => MdDomMsgs.NumberValueExpected(Token)); v5 = _scanner.GetTokenValueAsReal(); - AssertCondition(v5 is >= 0 and <= 100, DomMsgID.InvalidRange, "0..100"); + EnsureCondition(v5 is >= 0 and <= 100, () => MdDomMsgs.InvalidRange("0..100")); ReadCode(); // read ')' } - AssertSymbol(Symbol.ParenRight); + EnsureSymbol(Symbol.ParenRight); ReadCode(); // read next token @@ -2412,16 +2388,16 @@ Color ParseCMYK() Color ParseGray() { ReadCode(); // read '(' - AssertSymbol(Symbol.ParenLeft); + EnsureSymbol(Symbol.ParenLeft); ReadCode(); // read gray value - AssertCondition(Symbol is Symbol.IntegerLiteral or Symbol.HexIntegerLiteral, - DomMsgID.IntegerExpected, _scanner.Token); + EnsureCondition(Symbol is Symbol.IntegerLiteral or Symbol.HexIntegerLiteral, + () => MdDomMsgs.IntegerValueExpected(Token)); double gray = _scanner.GetTokenValueAsReal(); - AssertCondition(gray is >= 0 and <= 100, DomMsgID.InvalidRange, "0..100"); + EnsureCondition(gray is >= 0 and <= 100, () => MdDomMsgs.InvalidRange("0..100")); ReadCode(); // read ')' - AssertSymbol(Symbol.ParenRight); + EnsureSymbol(Symbol.ParenRight); ReadCode(); // read next token @@ -2433,9 +2409,7 @@ Color ParseGray() /// Determines the name/text of the given symbol. /// static string GetSymbolText(Symbol docSym) - { - return KeyWords.NameFromSymbol(docSym); - } + => KeyWords.NameFromSymbol(docSym); /// /// Returns whether the specified type is a valid SpaceType. @@ -2460,7 +2434,6 @@ static bool IsSpaceType(string type) return true; } } - return false; } @@ -2492,91 +2465,79 @@ static bool IsSymbolType(string type) return true; } } - return false; } /// /// If cond is evaluated to false, a DdlParserException with the specified error will be thrown. /// - void AssertCondition( -#if NET6_0_OR_GREATER - [DoesNotReturnIf(false)] -#endif - bool cond, DomMsgID error, params object[] args) + void EnsureCondition([DoesNotReturnIf(false)] bool cond, Func func) { if (!cond) - ThrowParserException(error, args); + ThrowParserException(func()); } /// /// If current symbol is not equal symbol a DdlParserException will be thrown. /// - void AssertSymbol(Symbol symbol) + void EnsureSymbol(Symbol symbol) { if (Symbol != symbol) - ThrowParserException(DomMsgID.SymbolExpected, KeyWords.NameFromSymbol(symbol), Token); + ThrowParserException(MdDomMsgs.SymbolExpected(KeyWords.NameFromSymbol(symbol), Token)); } /// /// If current symbol is not equal symbol a DdlParserException with the specified message ID /// will be thrown. /// - void AssertSymbol(Symbol symbol, DomMsgID err) + void EnsureSymbol(Symbol symbol, Func func) { if (Symbol != symbol) - ThrowParserException(err, KeyWords.NameFromSymbol(symbol), Token); + { + var domMsg = func(); + //ThrowParserException(err, KeyWords.NameFromSymbol(symbol), Token); + ThrowParserException(domMsg); + } } - /// - /// If current symbol is not equal symbol a DdlParserException with the specified message ID - /// will be thrown. - /// - void AssertSymbol(Symbol symbol, DomMsgID err, params object[] parms) - { - if (Symbol != symbol) - ThrowParserException(err, KeyWords.NameFromSymbol(symbol), parms); - } + ///// + ///// If current symbol is not equal symbol a DdlParserException with the specified message ID + ///// will be thrown. + ///// + //void EnsureSymbol(Symbol symbol, DomMsgID err, params object[] parms) + //{ + // if (Symbol != symbol) + // ThrowParserException(err, KeyWords.NameFromSymbol(symbol), parms); + //} /// /// Creates an ErrorInfo based on the given errorlevel, error and parms and adds it to the ErrorManager2. /// - void ReportParserInfo(DdlErrorLevel level, DomMsgID errorCode, params string[] parms) + void ReportParserInfo(DdlErrorLevel level, MdDomMsg domMsg) { - string message = DomSR.FormatMessage(errorCode, parms); - var error = new DdlReaderError(level, message, (int)errorCode, + var error = new DdlReaderError(level, domMsg, _scanner.DocumentFileName, _scanner.CurrentLine, _scanner.CurrentLinePos); _errors.AddError(error); } - /// - /// Creates an ErrorInfo based on the given error and parms and adds it to the ErrorManager2. - /// - void ReportParserException(DomMsgID error, params string[] parms) - { - ReportParserException(null, error, parms); - } - /// /// Adds the ErrorInfo from the ErrorInfoException2 to the ErrorManager2. /// void ReportParserException(DdlParserException ex) - { - _errors.AddError(ex.Error); - } + => _errors.AddError(ex.Error); /// /// Creates an ErrorInfo based on the given inner exception, error, and parms and adds it to the ErrorManager2. /// - void ReportParserException(Exception? innerException, DomMsgID errorCode, params string[] parms) + void ReportParserException(MdDomMsg domMsg, Exception? innerException = null) { - var message = ""; + var message = domMsg.Message; if (innerException != null) - message = ": " + innerException; + message = " Inner exception: " + innerException; - message += DomSR.FormatMessage(errorCode, parms); - var error = new DdlReaderError(DdlErrorLevel.Error, message, (int)errorCode, + //message += DomSR.FormatMessage(errorCode, parms); + var error = new DdlReaderError(DdlErrorLevel.Error, message, (int)domMsg.Id, _scanner.DocumentFileName, _scanner.CurrentLine, _scanner.CurrentLinePos); _errors.AddError(error); @@ -2586,29 +2547,17 @@ void ReportParserException(Exception? innerException, DomMsgID errorCode, params /// Creates an ErrorInfo based on the DomMsgID and the specified parameters. /// Throws a DdlParserException with that ErrorInfo. /// -#if NET6_0_OR_GREATER [DoesNotReturn] -#endif - void ThrowParserException(DomMsgID errorCode, params object[] parms) + void ThrowParserException(MdDomMsg domMsg, Exception? innerException = null) { - var message = DomSR.FormatMessage(errorCode, parms); - var error = new DdlReaderError(DdlErrorLevel.Error, message, (int)errorCode, - _scanner.DocumentFileName, _scanner.CurrentLine, _scanner.CurrentLinePos); + var message = domMsg.Message; + if (innerException != null) + message = " Inner exception: " + innerException; - throw new DdlParserException(error); - } + var error = new DdlReaderError(DdlErrorLevel.Error, message, (int)domMsg.Id, + _scanner.DocumentFileName, _scanner.CurrentLine, _scanner.CurrentLinePos); - /// - /// Determines the error message based on the DomMsgID and the parameters. - /// Throws a DdlParserException with that error message and the Exception as the inner exception. - /// -#if NET6_0_OR_GREATER - [DoesNotReturn] -#endif - static void ThrowParserException(Exception innerException, DomMsgID errorCode, params object[] parms) - { - var message = DomSR.FormatMessage(errorCode, parms); - throw new DdlParserException(message, innerException); + throw new DdlParserException(error, innerException); } /// @@ -2638,7 +2587,7 @@ void AdjustToNextBlock() break; case Symbol.Eof: - ThrowParserException(DomMsgID.UnexpectedEndOfFile); + ThrowParserException(MdDomMsgs.UnexpectedEndOfFile); break; default: diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParserException.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParserException.cs index 79bc5b95..9d18e836 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParserException.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlParserException.cs @@ -4,45 +4,45 @@ namespace MigraDoc.DocumentObjectModel.IO { /// - /// Represents an exception used by the DDL parser. This exception will always be caught inside - /// the DDL parser. + /// Represents an exception issued by the DDL parser. + /// This exception will always be caught inside the DDL parser. /// - class DdlParserException : Exception + sealed class DdlParserException : Exception { - /// - /// Initializes a new instance of the DdlParserException class with the specified message. - /// - public DdlParserException(string message) - : base(message) - { - Error = new DdlReaderError(DdlErrorLevel.Error, message, 0); - } + ///// + ///// Initializes a new instance of the DdlParserException class with the specified message. + ///// + //public DdlParserException(MdDomMsg domMsg) + // : base(domMsg.Message) + //{ + // Error = new DdlReaderError(DdlErrorLevel.Error, domMsg); + //} /// /// Initializes a new instance of the DdlParserException class with the specified message and the /// inner exception. /// - public DdlParserException(string message, Exception innerException) - : base(message, innerException) + public DdlParserException(MdDomMsg domMsg, Exception? innerException = null) + : base(domMsg.Message, innerException) { - Error = new DdlReaderError(DdlErrorLevel.Error, message, 0); + Error = new DdlReaderError(DdlErrorLevel.Error, domMsg); } - /// - /// Initializes a new instance of the DdlParserException class with the specified error level, name, - /// error code and message. - /// - public DdlParserException(DdlErrorLevel level, string message, DomMsgID errorCode) - : base(message) - { - Error = new DdlReaderError(level, message, (int)errorCode); - } + ///// + ///// Initializes a new instance of the DdlParserException class with the specified error level, name, + ///// error code and message. + ///// + //public DdlParserException(DdlErrorLevel level, string message, DomMsgId errorCode) + // : base(message) + //{ + // Error = new DdlReaderError(level, message, (int)errorCode); + //} /// /// Initializes a new instance of the DdlParserException class with the DdlReaderError. /// - public DdlParserException(DdlReaderError error) - : base(error.ErrorMessage) + public DdlParserException(DdlReaderError error, Exception? innerException = null) + : base(error.ErrorMessage, innerException) { Error = error; } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReader.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReader.cs index 77ec3d7a..fbe203c3 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReader.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReader.cs @@ -126,8 +126,7 @@ public static Document DocumentFromFile(string documentFileName) //, ErrorManage } finally { - if (reader != null) - reader.Close(); + reader?.Close(); } return document; } @@ -164,7 +163,7 @@ public static Document DocumentFromString(string ddl) DocumentObject? domObj; try { - reader = new DdlReader(documentFileName, errors); + reader = new(documentFileName, errors); domObj = reader.ReadObject(); } finally @@ -177,14 +176,15 @@ public static Document DocumentFromString(string ddl) /// /// Reads and returns a domain object from the specified file. /// - public static DocumentObject? ObjectFromFile(string documentFileName) + public static DocumentObject? ObjectFromFile(string documentFileName) => ObjectFromFile(documentFileName, null); /// /// Reads and returns a domain object from the specified DDL string. /// - public static DocumentObject? ObjectFromString(string ddl, DdlReaderErrors? errors) + public static DocumentObject? ObjectFromString(string ddl, DdlReaderErrors? errors = null) { + _ = errors; StringReader? stringReader = null; DocumentObject? domObj; DdlReader? reader = null; @@ -198,18 +198,11 @@ public static Document DocumentFromString(string ddl) finally { stringReader?.Close(); - reader?.Close(); } return domObj; } - /// - /// Reads and returns a domain object from the specified DDL string. - /// - public static DocumentObject? ObjectFromString(string ddl) - => ObjectFromString(ddl, null); - readonly bool _doClose = true; TextReader? _reader; readonly DdlReaderErrors? _errorManager; diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReaderError.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReaderError.cs index 58212b6d..3771169d 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReaderError.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReaderError.cs @@ -6,62 +6,43 @@ namespace MigraDoc.DocumentObjectModel.IO /// /// Represents an error or diagnostic message reported by the DDL reader. /// + // Better name would be DdlReaderProblemDetails. But this class name + // is public. Therefore, we stay with it. public class DdlReaderError { /// /// Initializes a new instance of the DdlReaderError class. /// - public DdlReaderError(DdlErrorLevel errorLevel, string errorMessage, int errorNumber, - string sourceFile, int sourceLine, int sourceColumn) + internal DdlReaderError(DdlErrorLevel level, MdDomMsg domMsg, + string sourceFile = "", int sourceLine = 0, int sourceColumn = 0) { - ErrorLevel = errorLevel; - ErrorMessage = errorMessage; - ErrorNumber = errorNumber; + ErrorLevel = level; + ErrorMessage = domMsg.Message; + ErrorNumber = (int)domMsg.Id; SourceFile = sourceFile; SourceLine = sourceLine; SourceColumn = sourceColumn; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the DdlReaderError class. /// - public DdlReaderError(DdlErrorLevel errorLevel, string errorMessage, int errorNumber) + public DdlReaderError(DdlErrorLevel errorLevel, string errorMessage, int errorNumber, + string sourceFile, int sourceLine, int sourceColumn) { ErrorLevel = errorLevel; ErrorMessage = errorMessage; ErrorNumber = errorNumber; - SourceFile = ""; + SourceFile = sourceFile; + SourceLine = sourceLine; + SourceColumn = sourceColumn; } - // public DdlReaderError(string errorName, DdlReaderError _level, DomMsgID _error, string message, string msg2, - // string DocumentFileName, int CurrentLine, int CurrentLinePos) - // { - // } - // - // public DdlReaderError(string errorName, int _level, string _error, string message, string adf, - // string DocumentFileName, int CurrentLine, int CurrentLinePos) - // { - // } - // - // public DdlReaderError(string errorName, DdlErrorLevel errorInfo , string _error, string message, string adf, - // string DocumentFileName, int CurrentLine, int CurrentLinePos) - // { - // } - // - // public DdlReaderError(string errorName, DdlErrorLevel errorInfo , DomMsgID _error, string message, string adf, - // string DocumentFileName, int CurrentLine, int CurrentLinePos) - // { - // } - - //public const int NoErrorNumber = -1; - /// /// Returns a string that represents the current DdlReaderError. /// - public override string ToString() - { - return $"[{SourceFile}({SourceLine},{SourceColumn}):] {"xxx"} DDL{ErrorNumber}: {ErrorMessage}"; - } + public override string ToString() + => $"[{SourceFile}({SourceLine},{SourceColumn}):] {"xxx"} DDL{ErrorNumber}: {ErrorMessage}"; /// /// Specifies the severity of this diagnostic. diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReaderErrors.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReaderErrors.cs index aeed3a56..a3409c79 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReaderErrors.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlReaderErrors.cs @@ -36,14 +36,11 @@ public int ErrorCount return count; } } - readonly List _errors = new(); + readonly List _errors = []; /// /// Returns an enumerator that iterates through the error collection. /// - public IEnumerator GetEnumerator() - { - return _errors.GetEnumerator(); - } + public IEnumerator GetEnumerator() => _errors.GetEnumerator(); } } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlScanner.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlScanner.cs index e025eb4e..59332d10 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlScanner.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlScanner.cs @@ -25,20 +25,20 @@ sealed class DdlScanner /// internal DdlScanner(string documentFileName, string ddl, DdlReaderErrors errors) { - _errors = errors; + //_errors = errors; Not (yet?) used. - _documentPath = documentFileName; + DocumentPath = documentFileName; _strDocument = ddl; _ddlLength = _strDocument.Length; _idx = 0; _idxLine = 1; _idxLinePos = 0; - _documentFileName = documentFileName; + DocumentFileName = documentFileName; - _nCurDocumentIndex = _idx; - _nCurDocumentLine = _idxLine; - _nCurDocumentLinePos = _idxLinePos; + //_curDocumentIndex = _idx; Not (yet?) used. + CurrentLine = _idxLine; + CurrentLinePos = _idxLinePos; ScanNextChar(); } @@ -59,62 +59,62 @@ internal DdlScanner(string ddl, DdlReaderErrors errors) /// internal Symbol ReadCode() { - Again: - _symbol = Symbol.None; - _tokenType = TokenType.None; - _token = ""; + Again: + Symbol = Symbol.None; + TokenType = TokenType.None; + Token = ""; MoveToNonWhiteSpace(); SaveCurDocumentPos(); if (_currChar == Chars.Null) { - _symbol = Symbol.Eof; + Symbol = Symbol.Eof; return Symbol.Eof; } if (IsIdentifierChar(_currChar, true)) { // Token is identifier. - _symbol = ScanIdentifier(); - _tokenType = TokenType.Identifier; - // Some keywords do not start with a backslash: true, false, and null. - Symbol sym = KeyWords.SymbolFromName(_token); + Symbol = ScanIdentifier(); + TokenType = TokenType.Identifier; + // Some keywords do not start with a backslash: + // true, false, and null. + var sym = KeyWords.SymbolFromName(Token); if (sym != Symbol.None) { - _symbol = sym; - _tokenType = TokenType.KeyWord; + Symbol = sym; + TokenType = TokenType.KeyWord; } } else if (_currChar == '"') { // Token is string literal. - _token += ScanStringLiteral(); - _symbol = Symbol.StringLiteral; - _tokenType = TokenType.StringLiteral; + Token += ScanStringLiteral(); + Symbol = Symbol.StringLiteral; + TokenType = TokenType.StringLiteral; } //NYI: else if (IsNumber()) // symbol = ScanNumber(false); else if (IsDigit(_currChar) || - _currChar == '-' && IsDigit(_nextChar) || - _currChar == '+' && IsDigit(_nextChar)) + _currChar is '-' or '+' && IsDigit(_nextChar)) { // Token is number literal. - _symbol = ScanNumber(false); - _tokenType = _symbol == Symbol.RealLiteral ? TokenType.RealLiteral : TokenType.IntegerLiteral; + Symbol = ScanNumber(false); + TokenType = Symbol == Symbol.RealLiteral ? TokenType.RealLiteral : TokenType.IntegerLiteral; } else if (_currChar == '.' && IsDigit(_nextChar)) { // Token is real literal. - _symbol = ScanNumber(true); - _tokenType = TokenType.RealLiteral; + Symbol = ScanNumber(true); + TokenType = TokenType.RealLiteral; } else if (_currChar == '\\') { // Token is keyword or escaped character. - _token = "\\"; - _symbol = ScanKeyword(); - _tokenType = _symbol != Symbol.None ? TokenType.KeyWord : TokenType.None; + Token = "\\"; + Symbol = ScanKeyword(); + TokenType = Symbol != Symbol.None ? TokenType.KeyWord : TokenType.None; } else if (_currChar == '/' && _nextChar == '/') { @@ -126,16 +126,16 @@ internal Symbol ReadCode() { // Token is verbatim string literal. ScanNextChar(); - _token += ScanVerbatimStringLiteral(); - _symbol = Symbol.StringLiteral; - _tokenType = _symbol != Symbol.None ? TokenType.StringLiteral : TokenType.None; + Token += ScanVerbatimStringLiteral(); + Symbol = Symbol.StringLiteral; + TokenType = Symbol != Symbol.None ? TokenType.StringLiteral : TokenType.None; } else { // Punctuator or syntax error. - _symbol = ScanPunctuator(); + Symbol = ScanPunctuator(); } - return _symbol; + return Symbol; } /// @@ -337,17 +337,17 @@ internal Symbol ReadText(bool rootLevel) if (_emptyLine) { _emptyLine = false; - _symbol = Symbol.EmptyLine; - _tokenType = TokenType.None; - _token = ""; + Symbol = Symbol.EmptyLine; + TokenType = TokenType.None; + Token = ""; return Symbol.EmptyLine; } // Init for scanning. - _prevSymbol = _symbol; - _symbol = Symbol.None; - _tokenType = TokenType.None; - _token = ""; + _prevSymbol = Symbol; + Symbol = Symbol.None; + TokenType = TokenType.None; + Token = ""; // Save where we are SaveCurDocumentPos(); @@ -355,7 +355,7 @@ internal Symbol ReadText(bool rootLevel) // Check for EOF. if (_currChar == Chars.Null) { - _symbol = Symbol.Eof; + Symbol = Symbol.Eof; return Symbol.Eof; } @@ -372,7 +372,7 @@ internal Symbol ReadText(bool rootLevel) return ReadPlainText(rootLevel); } // Either key word or syntax error. - _token = "\\"; + Token = "\\"; return ScanKeyword(); } @@ -381,14 +381,14 @@ internal Symbol ReadText(bool rootLevel) { case '{': AppendAndScanNextChar(); - _symbol = Symbol.BraceLeft; - _tokenType = TokenType.OperatorOrPunctuator; + Symbol = Symbol.BraceLeft; + TokenType = TokenType.OperatorOrPunctuator; return Symbol.BraceLeft; // Syntax error in any case. case '}': AppendAndScanNextChar(); - _symbol = Symbol.BraceRight; - _tokenType = TokenType.OperatorOrPunctuator; + Symbol = Symbol.BraceRight; + TokenType = TokenType.OperatorOrPunctuator; return Symbol.BraceRight; } @@ -399,10 +399,10 @@ internal Symbol ReadText(bool rootLevel) if (MoveToNextParagraphContentLine(rootLevel)) { // Paragraph continues in next line. Simulate the read of a blank to separate words. - _token = " "; + Token = " "; if (IgnoreLineBreak()) - _token = ""; - _symbol = Symbol.Text; + Token = ""; + Symbol = Symbol.Text; return Symbol.Text; } else @@ -410,15 +410,15 @@ internal Symbol ReadText(bool rootLevel) // Paragraph ends here. Return NewLine or BraceRight. if (_currChar != Chars.BraceRight) { - _symbol = Symbol.EmptyLine; - _tokenType = TokenType.None; //??? + Symbol = Symbol.EmptyLine; + TokenType = TokenType.None; //??? return Symbol.EmptyLine; } else { AppendAndScanNextChar(); - _symbol = Symbol.BraceRight; - _tokenType = TokenType.OperatorOrPunctuator; + Symbol = Symbol.BraceRight; + TokenType = TokenType.OperatorOrPunctuator; return Symbol.BraceRight; } } @@ -472,6 +472,7 @@ Symbol ReadPlainText(bool rootLevel) loop = false; break; } + continue; } @@ -502,8 +503,8 @@ Symbol ReadPlainText(bool rootLevel) if (MoveToNextParagraphContentLine(rootLevel)) { // Paragraph continues in next line. Add a blank to separate words. - if (!_token.EndsWith(" ", StringComparison.Ordinal)) - _token += ' '; + if (!Token.EndsWith(" ", StringComparison.Ordinal)) + Token += ' '; continue; } else @@ -515,7 +516,7 @@ Symbol ReadPlainText(bool rootLevel) } } - ValidCharacter: + ValidCharacter: // Compress multiple blanks to one if (_currChar == ' ') { @@ -524,6 +525,7 @@ Symbol ReadPlainText(bool rootLevel) ScanNextChar(); continue; } + foundSpace = true; } else @@ -532,8 +534,8 @@ Symbol ReadPlainText(bool rootLevel) AppendAndScanNextChar(); } - _symbol = Symbol.Text; - _tokenType = TokenType.Text; + Symbol = Symbol.Text; + TokenType = TokenType.Text; return Symbol.Text; } @@ -542,9 +544,9 @@ Symbol ReadPlainText(bool rootLevel) /// internal Symbol MoveToCode() { - if (_symbol == Symbol.None || _symbol == Symbol.CR /*|| this .symbol == Symbol.comment*/) + if (Symbol is Symbol.None or Symbol.CR /*|| this .symbol == Symbol.comment*/) ReadCode(); - return _symbol; + return Symbol; } /// @@ -554,7 +556,7 @@ internal Symbol MoveToCode() /// internal bool MoveToParagraphContent() { - Again: + Again: MoveToNonWhiteSpace(); if (_currChar == Chars.Slash && _nextChar == Chars.Slash) { @@ -703,7 +705,7 @@ internal Symbol ScanSingleLineComment() char ch = ScanNextChar(); while (ch != Chars.Null && ch != Chars.LF) { - _token += _currChar; + Token += _currChar; ch = ScanNextChar(); } ScanNextChar(); // read beyond EOL @@ -713,64 +715,57 @@ internal Symbol ScanSingleLineComment() /// /// Gets the current symbol. /// - internal Symbol Symbol => _symbol; + internal Symbol Symbol { get; private set; } = Symbol.None; /// /// Gets the current token type. /// - internal TokenType TokenType => _tokenType; + internal TokenType TokenType { get; private set; } = TokenType.None; /// /// Gets the current token. /// - internal string Token => _token; + internal string Token { get; private set; } = ""; /// /// Interpret current token as integer literal. /// - /// internal int GetTokenValueAsInt() { - if (_symbol == Symbol.IntegerLiteral) - return Int32.Parse(_token, CultureInfo.InvariantCulture); + if (Symbol == Symbol.IntegerLiteral) + return Int32.Parse(Token, CultureInfo.InvariantCulture); - if (_symbol == Symbol.HexIntegerLiteral) + if (Symbol == Symbol.HexIntegerLiteral) { - string number = _token.Substring(2); + string number = Token.Substring(2); return Int32.Parse(number, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); } - //TODO NiSc Check? - //Check.Assert(false); + Debug.Assert(false, "Should not come here."); return 0; } /// /// Interpret current token as unsigned integer literal. /// - /// internal uint GetTokenValueAsUInt() { - if (_symbol == Symbol.IntegerLiteral) - return UInt32.Parse(_token, CultureInfo.InvariantCulture); + if (Symbol == Symbol.IntegerLiteral) + return UInt32.Parse(Token, CultureInfo.InvariantCulture); - if (_symbol == Symbol.HexIntegerLiteral) + if (Symbol == Symbol.HexIntegerLiteral) { - string number = _token.Substring(2); + string number = Token.Substring(2); return UInt32.Parse(number, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); } - //TODO NiSc Check. - //Check.Assert(false); + Debug.Assert(false, "Should not come here."); return 0; } /// /// Interpret current token as real literal. /// - /// - internal double GetTokenValueAsReal() - { - return Double.Parse(_token, CultureInfo.InvariantCulture); - } + internal double GetTokenValueAsReal() + => Double.Parse(Token, CultureInfo.InvariantCulture); /// /// Gets the current character or EOF. @@ -794,7 +789,7 @@ internal char ScanNextChar() } else { - SkipChar: + SkipChar: _currChar = _strDocument[_idx++]; _nextChar = _ddlLength <= _idx ? Chars.Null : _strDocument[_idx]; @@ -806,7 +801,7 @@ internal char ScanNextChar() _idxLinePos = 0; break; - // ignore CR + // Ignore CR case Chars.CR: if (_nextChar == Chars.LF) { @@ -844,7 +839,7 @@ internal void ScanToEol() /// internal char AppendAndScanNextChar() { - _token += _currChar; + Token += _currChar; return ScanNextChar(); } @@ -857,7 +852,7 @@ internal void AppendAndScanToEol() char ch = ScanNextChar(); while (ch != Chars.Null && ch != Chars.CR && ch != Chars.LF) { - _token += _currChar; + Token += _currChar; ch = ScanNextChar(); } } @@ -865,42 +860,30 @@ internal void AppendAndScanToEol() /// /// Is character in '0' ... '9'. /// - internal static bool IsDigit(char ch) - { - return Char.IsDigit(ch); - } + internal static bool IsDigit(char ch) + => Char.IsDigit(ch); /// /// Is character a hexadecimal digit. /// - internal static bool IsHexDigit(char ch) - { - return Char.IsDigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f'); - } + internal static bool IsHexDigit(char ch) + => Char.IsDigit(ch) || ch is >= 'A' and <= 'F' || ch is >= 'a' and <= 'f'; /// /// Is character an octal digit. /// internal static bool IsOctDigit(char ch) - { - return Char.IsDigit(ch) && ch < '8'; - } + => Char.IsDigit(ch) && ch < '8'; /// /// Is character an alphabetic letter. /// - internal static bool IsLetter(char ch) - { - return Char.IsLetter(ch); - } + internal static bool IsLetter(char ch) => Char.IsLetter(ch); /// /// Is character a white space. /// - internal static bool IsWhiteSpace(char ch) - { - return Char.IsWhiteSpace(ch); - } + internal static bool IsWhiteSpace(char ch) => Char.IsWhiteSpace(ch); /// /// Is character an identifier character. First character can be letter or underscore, following @@ -917,10 +900,7 @@ internal static bool IsIdentifierChar(char ch, bool firstChar) //IsId..Char /// /// Is character the end of file character. /// - internal static bool IsEof(char ch) - { - return ch == Chars.Null; - } + internal static bool IsEof(char ch) => ch == Chars.Null; //internal bool IsNumber(); //internal bool IsFormat(); @@ -1027,14 +1007,13 @@ internal static bool IsHeaderFooterElement(Symbol symbol) if (IsParagraphElement(symbol)) return true; - // All document elements except pagebreak. + // All document elements except page break. if (IsDocumentElement(symbol)) { if (symbol == Symbol.PageBreak) return false; return true; } - return false; } @@ -1056,22 +1035,22 @@ internal static bool IsFootnoteElement(Symbol symbol) /// /// Gets the current filename of the document. /// - internal string DocumentFileName => _documentFileName; + internal string DocumentFileName { get; } /// /// Gets the current path of the document. /// - internal string DocumentPath => _documentPath; + internal string DocumentPath { get; } /// /// Gets the current scanner line in the document. /// - internal int CurrentLine => _nCurDocumentLine; + internal int CurrentLine { get; private set; } /// /// Gets the current scanner column in the document. /// - internal int CurrentLinePos => _nCurDocumentLinePos; + internal int CurrentLinePos { get; private set; } /// /// Scans an identifier. @@ -1091,7 +1070,7 @@ Symbol ScanIdentifier() Symbol ScanNumber(bool mantissa) { char ch = _currChar; - _token += _currChar; + Token += _currChar; ScanNextChar(); if (!mantissa && ch == '0' && (_currChar == 'x' || _currChar == 'X')) @@ -1119,7 +1098,7 @@ Symbol ScanNumber(bool mantissa) /// Symbol ReadHexNumber() { - _token = "0x"; + Token = "0x"; ScanNextChar(); while (_currChar != Chars.Null) { @@ -1144,7 +1123,7 @@ Symbol ScanKeyword() // \- is a soft hyphen == char(173). if (ch == '-') { - _token += "-"; + Token += "-"; ScanNextChar(); return Symbol.SoftHyphen; } @@ -1152,8 +1131,8 @@ Symbol ScanKeyword() // \( is a shortcut for symbol. if (ch == '(') { - _token += "("; - _symbol = Symbol.Chr; + Token += "("; + Symbol = Symbol.Chr; return Symbol.Chr; // Shortcut for \chr( } @@ -1166,12 +1145,11 @@ Symbol ScanKeyword() return Symbol.Chr; } #endif - while (!IsEof(ch) && IsIdentifierChar(ch, false)) ch = AppendAndScanNextChar(); - _symbol = KeyWords.SymbolFromName(_token); - return _symbol; + Symbol = KeyWords.SymbolFromName(Token); + return Symbol; } /// @@ -1265,7 +1243,7 @@ Symbol ScanPunctuator() case '+': if (_nextChar == '=') { - _token += _currChar; + Token += _currChar; ScanNextChar(); sym = Symbol.PlusAssign; } @@ -1276,7 +1254,7 @@ Symbol ScanPunctuator() case '-': if (_nextChar == '=') { - _token += _currChar; + Token += _currChar; ScanNextChar(); sym = Symbol.MinusAssign; } @@ -1300,7 +1278,7 @@ Symbol ScanPunctuator() sym = Symbol.Eof; return sym; } - _token += _currChar; + Token += _currChar; ScanNextChar(); return sym; } @@ -1309,7 +1287,6 @@ Symbol ScanPunctuator() ///// ///// Scans string literals used as identifiers. ///// - ///// //protected string ReadRawString() //ScanStringLiteralIdentifier //{ // string str = ""; @@ -1355,7 +1332,6 @@ string ScanVerbatimStringLiteral() str += ch; ch = ScanNextChar(); } - ScanNextChar(); return str; } @@ -1430,8 +1406,6 @@ string ScanStringLiteral() if (hexNrCount <= 2) str.Append("?????"); //(char)AscULongFromHexString(hexString); else - //throw new DdlParserException(DdlErrorLevel.Error, - // DomSR.GetString(DomMsgID.EscapeSequenceNotAllowed), DomMsgID.EscapeSequenceNotAllowed); throw TH.DdlParserException_EscapeSequenceNotAllowed(str.ToString()); } break; @@ -1456,14 +1430,10 @@ string ScanStringLiteral() // break; default: - //throw new DdlParserException(DdlErrorLevel.Error, - // DomSR.GetString(DomMsgID.EscapeSequenceNotAllowed), DomMsgID.EscapeSequenceNotAllowed); throw TH.DdlParserException_EscapeSequenceNotAllowed(str.ToString()); } } else if (_currChar is Chars.Null or Chars.CR or Chars.LF) - //throw new DdlParserException(DdlErrorLevel.Error, - // DomSR.GetString(DomMsgID.NewlineInString), DomMsgID.NewlineInString); throw TH.DdlParserException_NewlineInString(); else str.Append(_currChar); @@ -1479,17 +1449,13 @@ string ScanStringLiteral() /// void SaveCurDocumentPos() { - _nCurDocumentIndex = _idx - 1; - _nCurDocumentLine = _idxLine; - _nCurDocumentLinePos = _idxLinePos; + //_curDocumentIndex = _idx - 1; Not (yet?) used. + CurrentLine = _idxLine; + CurrentLinePos = _idxLinePos; } - int _nCurDocumentIndex; - int _nCurDocumentLine; - int _nCurDocumentLinePos; + //int _curDocumentIndex; Not(yet?) used. - readonly string _documentFileName; - readonly string _documentPath; readonly string _strDocument; readonly int _ddlLength; int _idx; @@ -1498,12 +1464,9 @@ void SaveCurDocumentPos() char _currChar; char _nextChar; - string _token = ""; - Symbol _symbol = Symbol.None; Symbol _prevSymbol = Symbol.None; - TokenType _tokenType = TokenType.None; bool _emptyLine; - DdlReaderErrors _errors; + //DdlReaderErrors _errors; Not (yet?) used. } } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlWriter.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlWriter.cs index 38542c37..1a437ec6 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlWriter.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/DdlWriter.cs @@ -43,17 +43,14 @@ public void Close() { _serializer = null!; - if (_writer != null) - { - _writer.Close(); - _writer = null; - } + _writer?.Close(); + _writer = null; } /// /// Flushes the underlying TextWriter. /// - public void Flush() + public void Flush() => _serializer.Flush(); /// @@ -95,13 +92,13 @@ public void WriteDocument(DocumentObjectCollection documentObjectContainer) /// /// Writes a DocumentObject type object to string. /// - public static string WriteToString(DocumentObject docObject) + public static string WriteToString(DocumentObject docObject) => WriteToString(docObject, 2, 0); /// /// Writes a DocumentObject type object to string. Indent a new block by indent characters. /// - public static string WriteToString(DocumentObject docObject, int indent) + public static string WriteToString(DocumentObject docObject, int indent) => WriteToString(docObject, indent, 0); /// @@ -135,13 +132,13 @@ public static string WriteToString(DocumentObject docObject, int indent, int ini /// /// Writes a DocumentObjectCollection type object to string. /// - public static string WriteToString(DocumentObjectCollection docObjectContainer) + public static string WriteToString(DocumentObjectCollection docObjectContainer) => WriteToString(docObjectContainer, 2, 0); /// /// Writes a DocumentObjectCollection type object to string. Indent a new block by _indent characters. /// - public static string WriteToString(DocumentObjectCollection docObjectContainer, int indent) + public static string WriteToString(DocumentObjectCollection docObjectContainer, int indent) => WriteToString(docObjectContainer, indent, 0); /// @@ -176,13 +173,13 @@ public static string WriteToString(DocumentObjectCollection docObjectContainer, /// /// Writes a document object to a DDL file. /// - public static void WriteToFile(DocumentObject docObject, string filename) + public static void WriteToFile(DocumentObject docObject, string filename) => WriteToFile(docObject, filename, 2, 0); /// /// Writes a document object to a DDL file. Indent a new block by the specified number of characters. /// - public static void WriteToFile(DocumentObject docObject, string filename, int indent) + public static void WriteToFile(DocumentObject docObject, string filename, int indent) => WriteToFile(docObject, filename, indent, 0); /// @@ -209,14 +206,14 @@ public static void WriteToFile(DocumentObject docObject, string filename, int in /// /// Writes a DocumentObjectCollection type object to a DDL file. /// - public static void WriteToFile(DocumentObjectCollection docObjectContainer, string filename) + public static void WriteToFile(DocumentObjectCollection docObjectContainer, string filename) => WriteToFile(docObjectContainer, filename, 2, 0); /// /// Writes a DocumentObjectCollection type object to a DDL file. Indent a new block by /// indent + initialIndent characters. /// - public static void WriteToFile(DocumentObjectCollection docObjectContainer, string filename, int indent) + public static void WriteToFile(DocumentObjectCollection docObjectContainer, string filename, int indent) => WriteToFile(docObjectContainer, filename, indent, 0); /// diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/Symbols.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/Symbols.cs index b839a0a5..38b4e30a 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/Symbols.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.IO/Symbols.cs @@ -174,7 +174,7 @@ internal static Symbol SymbolFromName(string name) Symbol symbol; if (!NameToEnum.TryGetValue(name, out symbol)) { - // Check for case sensitive keywords. Allow first character upper case only. + // Check for case-sensitive keywords. Allow first character upper case only. if (string.Compare(name, "True", StringComparison.OrdinalIgnoreCase) == 0) symbol = Symbol.True; else if (string.Compare(name, "False", StringComparison.OrdinalIgnoreCase) == 0) @@ -190,12 +190,9 @@ internal static Symbol SymbolFromName(string name) /// /// Returns string from Symbol value. /// - internal static string NameFromSymbol(Symbol symbol) - { - return EnumToName[symbol]; - } + internal static string NameFromSymbol(Symbol symbol) => EnumToName[symbol]; - static readonly Dictionary EnumToName = new(); - static readonly Dictionary NameToEnum = new(); + static readonly Dictionary EnumToName = []; + static readonly Dictionary NameToEnum = []; } } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/ErrorHelpers.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/ErrorHelpers.cs index 62f4aee4..9a75ef52 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/ErrorHelpers.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/ErrorHelpers.cs @@ -35,17 +35,17 @@ static class TH // #RENAME TODO // return FormatMessage(DomMsgID.InvalidInfoFieldName, name); //} - // StyleExpected = The value must be of type MigraDoc.DocumentObjectModel.Style. - public static ArgumentException ArgumentException_StyleExpected(Type type) => - new($"The value is of type '{type.FullName}' but must be of type 'MigraDoc.DocumentObjectModel.Style'."); - - // BaseStyleRequired = Base style name must be defined. - public static ArgumentException ArgumentException_UndefinedBaseStyle(string baseStyle) => - new($"Base style name '{baseStyle}' is undefined."); - - //{ - // return FormatMessage(DomMsgID.UndefinedBaseStyle, baseStyle); - //} + /// + /// The specified object must be of type Style. + /// + public static ArgumentException ArgumentException_StyleExpected(Type wrongType) + => new(MdDomMsgs.StyleExpected(wrongType).Message); + + /// + /// The base style of style that is not a root style must be defined. + /// + public static ArgumentException ArgumentException_UndefinedBaseStyle(string style) + => new(MdDomMsgs.UndefinedBaseStyle(style).Message); //public static string InvalidValueName(string name) //{ @@ -216,17 +216,17 @@ public static ArgumentException ArgumentException_UndefinedBaseStyle(string base //// FileNotFound, //// NotSupported, - //NewlineInString, + /// + /// A new-line occurs in a string literal. + /// public static DdlParserException DdlParserException_NewlineInString() - => new(DdlErrorLevel.Error, - "Newline in string not allowed.", - DomMsgID.NewlineInString); - - //EscapeSequenceNotAllowed - public static DdlParserException DdlParserException_EscapeSequenceNotAllowed(string s) - => new(DdlErrorLevel.Error, - $"Invalid escape sequence '{s}'.", - DomMsgID.EscapeSequenceNotAllowed); + => new(MdDomMsgs.NewlineInString); + + /// + /// An illegal escape sequence occured. + /// + public static DdlParserException DdlParserException_EscapeSequenceNotAllowed(string token) + => new(MdDomMsgs.EscapeSequenceNotAllowed(token)); //// SymbolsNotAllowedInsideText, //NullAssignmentNotSupported, diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/Meta.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/Meta.cs index 38fe8337..a5cf597b 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/Meta.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/Meta.cs @@ -34,29 +34,18 @@ public Meta(Type documentObjectType) #else int dot = name.IndexOf(".", StringComparison.Ordinal); #endif -#if NET6_0_OR_GREATER || true if (dot == 0) - throw new ArgumentException(DomSR.InvalidValueName(name)); + throw new ArgumentException(MdDomMsgs.InvalidValueName(name).Message); string? trail = null; if (dot > 0) { trail = name[(dot + 1)..]; name = name[..dot]; } -#else - if (dot == 0) - throw new ArgumentException(DomSR.InvalidValueName(name)); - string? trail = null; - if (dot > 0) - { - trail = name.Substring(dot + 1); - name = name.Substring(0, dot); - } -#endif var vd = ValueDescriptors[name]; if (vd == null) - throw new ArgumentException(DomSR.InvalidValueName(name)); + throw new ArgumentException(MdDomMsgs.InvalidValueName(name).Message); var value = vd.GetValue(dom, flags); if (value == null && flags == GV.GetNull) //??? also for GV.ReadOnly? @@ -66,9 +55,9 @@ public Meta(Type documentObjectType) if (trail != null) { if (value == null || trail == "") - throw new ArgumentException(DomSR.InvalidValueName(name)); + throw new ArgumentException(MdDomMsgs.InvalidValueName(name).Message); if (value is not DocumentObject doc) - throw new ArgumentException(DomSR.InvalidValueName(name)); + throw new ArgumentException(MdDomMsgs.InvalidValueName(name).Message); value = doc.GetValue(trail, flags); } return value; @@ -86,21 +75,16 @@ public void SetValue(DocumentObject dom, string name, object? val) int dot = name.IndexOf(".", StringComparison.Ordinal); #endif if (dot == 0) - throw new ArgumentException(DomSR.InvalidValueName(name)); + throw new ArgumentException(MdDomMsgs.InvalidValueName(name).Message); string? trail = null; if (dot > 0) { -#if NET6_0_OR_GREATER || true trail = name[(dot + 1)..]; name = name[..dot]; -#else - trail = name.Substring(dot + 1); - name = name.Substring(0, dot); -#endif } var vd = ValueDescriptors[name]; if (vd == null) - throw new ArgumentException(DomSR.InvalidValueName(name)); + throw new ArgumentException(MdDomMsgs.InvalidValueName(name).Message); if (trail != null) { @@ -138,7 +122,7 @@ public void SetNull(DocumentObject dom, string name) var vd = ValueDescriptors[name]; if (vd == null) - throw new ArgumentException(DomSR.InvalidValueName(name)); + throw new ArgumentException(MdDomMsgs.InvalidValueName(name).Message); vd.SetNull(dom); } @@ -159,22 +143,17 @@ public void SetNull(DocumentObject dom, string name) int dot = name.IndexOf(".", StringComparison.Ordinal); #endif if (dot == 0) - throw new ArgumentException(DomSR.InvalidValueName(name)); + throw new ArgumentException(MdDomMsgs.InvalidValueName(name).Message); string? trail = null; if (dot > 0) { -#if NET6_0_OR_GREATER || true trail = name[(dot + 1)..]; name = name[..dot]; -#else - trail = name.Substring(dot + 1); - name = name.Substring(0, dot); -#endif } var vd = ValueDescriptors[name]; if (vd == null) - throw new ArgumentException(DomSR.InvalidValueName(name)); + throw new ArgumentException(MdDomMsgs.InvalidValueName(name).Message); #if true if (trail == null) @@ -185,9 +164,9 @@ public void SetNull(DocumentObject dom, string name) return true; if (/*value == null || */trail == "") - throw new ArgumentException(DomSR.InvalidValueName(name)); + throw new ArgumentException(MdDomMsgs.InvalidValueName(name).Message); if (value is not DocumentObject doc) - throw new ArgumentException(DomSR.InvalidValueName(name)); + throw new ArgumentException(MdDomMsgs.InvalidValueName(name).Message); return doc.IsNull(trail); #else diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/ValueDescriptor.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/ValueDescriptor.cs index 69abf417..d933bf4a 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/ValueDescriptor.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Internals/ValueDescriptor.cs @@ -34,7 +34,6 @@ public object CreateValue() /// /// The document object. /// The GetValue flags. - /// public abstract object? GetValue(DocumentObject doc, GV flags); /// @@ -137,7 +136,7 @@ internal static ValueDescriptor CreateValueDescriptor(PropertyInfo propertyInfo, protected void EnsureGetValueFlags(GV flags) { if (!Enum.IsDefined(typeof(GV), flags)) - throw new InvalidEnumArgumentException(DomSR.InvalidEnumValue(flags)); + throw new InvalidEnumArgumentException(MdDomMsgs.InvalidEnumValue(flags).Message); } /// diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Resources/Messages.de.restext b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Resources/Messages.de.restext deleted file mode 100644 index 20ac82a3..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Resources/Messages.de.restext +++ /dev/null @@ -1,71 +0,0 @@ -; ----- German (de) Messages --------------------------------------------------- -; Messages for German language -; that differ from the default messages. -; -; Must be saved with encoding UTF8. Otherwise German umlauts get not processed correctly. -; -; ------------------------------------------------------------------------------ - -StyleExpected = Der übergebene Wert muss vom Typ MigraDoc.DocumentObjectModel.Style sein. -BaseStyleRequired = Es muss eine Basis-Formatvorlage definiert werden. -EmptyBaseStyle = Die Basis-Formatvorlage darf nicht leer sein. -InvalidFieldFormat = '{0}' ist kein gültiges Format für ein numerisches Feld. -InvalidInfoFieldName = Die Eigenschaft 'Name' an 'InfoField' hat den ungültigen Wert '{0}'. -UndefinedBaseStyle = Die Basis-Formatvorlage '{0}' ist nicht definiert. -InvalidUnitValue = '{0}' ist keine gültige Zeichenkette für ein 'Unit'-Objekt. -InvalidUnitType = '{0}' ist eine unbekannte Maßeinheit für ein 'Unit'-Objekt. -InvalidEnumValue = Der Wert '{0:X}' ist für den enum-Type '{1}' nicht gültig. -InvalidEnumForLeftPosition = ShapePosition muss einer der Werte 'Left', 'Center', oder 'Right' sein. -InvalidEnumForTopPosition = ShapePosition muss einer der Werte 'Top', 'Center', oder 'Bottom' sein. -InvalidColorString = Aus der Zeichenkette '{0}' konnte keine Farbe eingelesen werden. -InvalidFontSize = Die Fontgröße '{0}' is außerhalb des erlaubten Bereichs. -InsertNullNotAllowed = In ein Collection-Objekt darf keine null eingefügt werden. -ParentAlreadySet = Wert vom Typ '{0}' muss geklont werden, bevor er an '{1}' gesetzt werden kann. -MissingObligatoryProperty = Obligatorische Eigenschaft '{0}' wurde an '{1}' nicht gesetzt. -InvalidDocumentObjectType = Das übergebene Dokumentobjekt ist in diesem Zusammenhang nicht gültig. - -; ----- DdlReader Messages ------------------------------------------------------------------------ - -;DomMsgID -SymbolExpected = Symbol '{0}' erwartet, '{1}' vorgefunden. -SymbolsExpected = Eines der folgenden Symbole {0} erwartet. -OperatorExpected = Syntaxfehler: Operator '{0}' erwartet. -KeyWordExpected = Schlüsselwort '{1}' - '{0}' erwartet. -EndOfFileExpected = Ende der Datei erwartet. -UnexpectedEndOfFile = Unerwartetes Dateiende. -StyleNameExpected = '{0}' ist kein gültiger Name für eine Formatvorlage. -UnexpectedSymbol = Unerwartetes Symbol '{0}'. -IdentifierExpected = Bezeichner erwartet: '{0}'. -BoolExpected = Boolescher Wert erwartet: '{0}'. -RealExpected = Fließkomma-Wert erwartet: '{0}'. -IntegerExpected = Ganze Zahl erwartet: '{0}'. -StringExpected = Zeichenkette erwartet: '{0}'. -NullExpected = Null erwartet: '{0}'. -NumberExpected = Zahl erwartet: '{0}'. -InvalidEnum = '{0}' '{1}'. -InvalidType = Variablentyp '{0}' wird von '{1}' nicht unterstützt. -InvalidAssignment = Ungültige Zuweisung an '{0}'. -InvalidValueName = '{0}' ist ein ungültiger Wertname. -InvalidRange = Ungültiger Bereich: '{0}'. -InvalidColor = Ungültiger Farbwert: '{0}'. -InvalidFieldType = Ungültiger Feldtyp: '{0}'. -InvalidValueForOperation = Operation '{1}' ist für den Wert '{0}' nicht gültig. -InvalidSymbolType = Ungültiges Symbol '{0}'. -MissingBraceLeft = Öffnende geschweifte Klammer nach '{0}' fehlt. -MissingBraceRight = Schließende geschweifte Klammer nach '{0}' fehlt. -MissingBracketLeft = Öffnende eckige Klammer nach '{0}' fehlt. -MissingBracketRight = Schließende eckige Klammer nach '{0}' fehlt. -MissingParenLeft = Öffnende runde Klammer nach '{0}' fehlt. -MissingParenRight = Schließende runde Klammer nach '{0}' fehlt. -MissingComma = Komma fehlt. -SymbolNotAllowed = Symbol '{0}' ist in diesem Zusammenhang nichterlaubt. -SymbolIsNotAnObject = Symbol '{0}' ist kein Objekt. -UnknownChartType = Unbekannter Diagrammtyp: '{0}' -NoAccess = Zugriff verweigert: '{0}' existiert nur für den internen Gebrauch. -NewlineInString = Zeilenumbruch in Zeichenkette nicht erlaubt. -EscapeSequenceNotAllowed = Ungültige Escapesequenz. -NullAssignmentNotSupported = Zuweisung von 'null' an '{0}' ist nicht erlaubt. -OutOfRange = Der gültige Bereich liegt innerhalb von '{0}'. - -UseOfUndefinedBaseStyle = Die unbekannte Basis-Formatvorlage '{0}' wurde verwendet. -UseOfUndefinedStyle = Die unbekannte Formatvorlage '{0}' wurde verwendet. diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Resources/Messages.restext b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Resources/Messages.restext deleted file mode 100644 index 9ee1942d..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Resources/Messages.restext +++ /dev/null @@ -1,70 +0,0 @@ -; ----- Default Messages ------------------------------------------------------- -; Each Message will be shown for any language -; that does not override it in its specific .txt-file. -; ------------------------------------------------------------------------------ - -; ----- General Messages -------------------------------------------------------------------------- - -StyleExpected = The value must be of type MigraDoc.DocumentObjectModel.Style. -BaseStyleRequired = Base style name must be defined. -EmptyBaseStyle = Attempt to set empty base style is invalid. -InvalidFieldFormat = '{0}' is not a valid numeric field format. -InvalidInfoFieldName = Property 'Name' of 'InfoField' has invalid value '{0}'. -UndefinedBaseStyle = Base style name '{0}' is undefined. -InvalidUnitValue = String '{0}' is not a valid value for structure 'Unit'. -InvalidUnitType = '{0}' is an unknown unit type. -InvalidEnumValue = The value '{0:X}' is not valid for enum type '{1}'. -InvalidEnumForLeftPosition = ShapePosition must be Left, Center, or Right. -InvalidEnumForTopPosition = ShapePosition must be Top, Center, or Bottom. -InvalidColorString = Color could not be parsed from string '{0}'. -InvalidFontSize = The font size '{0}' is out of range. -InsertNullNotAllowed = Inserting null into a collection is not allowed. -ParentAlreadySet = Value of type '{0}' must be cloned before set into '{1}'. -MissingObligatoryProperty = Obligatory property '{0}' not set in '{1}'. -InvalidDocumentObjectType = The given document object is not valid in this context. - -; ----- DdlReader Messages ------------------------------------------------------------------------ - -;DomMsgID -SymbolExpected = '{0}' expected, found '{1}'. -SymbolsExpected = One of the following symbols {0} is expected. -OperatorExpected = Syntax error: Operator '{0}' is expected. -KeyWordExpected = '{1}' - '{0}' expected. -EndOfFileExpected = End of file expected. -UnexpectedEndOfFile = Unexpected end of file. -StyleNameExpected = Invalid style name '{0}'. -UnexpectedSymbol = Unexpected symbol '{0}'. -IdentifierExpected = Identifier expected: '{0}'. -BoolExpected = Bool expected: '{0}'. -RealExpected = Real expected: '{0}'. -IntegerExpected = Integer expected: '{0}'. -StringExpected = String expected: '{0}'. -NullExpected = Null expected: '{0}'. -NumberExpected = Number expected: '{0}'. -InvalidEnum = '{0}' '{1}'. -InvalidType = Variable type '{0}' not supported by '{1}'. -InvalidAssignment = Invalid assignment to '{0}'. -InvalidValueName = Invalid value name: '{0}'. -InvalidRange = Invalid range: '{0}'. -InvalidColor = Invalid color: '{0}'. -InvalidFieldType = Invalid field type: '{0}'. -InvalidValueForOperation = Operation '{1}' not valid for Value '{0}'. -InvalidSymbolType = Symbol not valid '{0}'. -MissingBraceLeft = Missing left brace after '{0}'. -MissingBraceRight = Missing right brace after '{0}'. -MissingBracketLeft = Missing left bracket after '{0}'. -MissingBracketRight = Missing right bracket after '{0}'. -MissingParenLeft = Missing left parenthesis after '{0}'. -MissingParenRight = Missing right parenthesis after '{0}'. -MissingComma = Missing comma. -SymbolNotAllowed = Symbol '{0}' in this context not allowed. -SymbolIsNotAnObject = Symbol '{0}' is not an object. -UnknownChartType = Unknown chart type: '{0}' -NoAccess = Access denied: '{0}' for internal use only. -NewlineInString = Newline in string not allowed. -EscapeSequenceNotAllowed = Invalid escape sequence. -NullAssignmentNotSupported = Assign 'null' to '{0}' not allowed. -OutOfRange = Valid range only within '{0}'. - -UseOfUndefinedBaseStyle = Use of undefined base style '{0}'. -UseOfUndefinedStyle = Use of undefined style '{0}'. diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Gridlines.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Gridlines.cs index 34420d28..847bf311 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Gridlines.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/Gridlines.cs @@ -62,9 +62,9 @@ public LineFormat LineFormat /// internal override void Serialize(Serializer serializer) { - var axisObject = Parent as Axis; + var axisObject = Parent as Axis ?? throw new InvalidOperationException("Parent is not of type Axis."); - var pos = serializer.BeginContent(axisObject!.CheckGridlines(this)); // HACK // BUG: What if Parent is not Axis? + var pos = serializer.BeginContent(axisObject.CheckGridlines(this)); // H/ACK // BUG: What if Parent is not Axis? Values.LineFormat?.Serialize(serializer); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesCollection.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesCollection.cs index d6bfe77e..e666a261 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesCollection.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesCollection.cs @@ -51,7 +51,7 @@ public Series AddSeries() internal override void Serialize(Serializer serializer) { int count = Count; - for (int index = 0; index < count; ++index) + for (int index = 0; index < count; index++) { var series = this[index]; series?.Serialize(serializer); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesElements.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesElements.cs index 7acea4a9..9978d300 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesElements.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/SeriesElements.cs @@ -61,7 +61,7 @@ public void Add(params double[] values) internal override void Serialize(Serializer serializer) { int count = Count; - for (int index = 0; index < count; ++index) + for (int index = 0; index < count; index++) { if (this[index] is not Point point) serializer.Write("null, "); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValues.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValues.cs index ff0d4300..8ad36a26 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValues.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes.Charts/XValues.cs @@ -51,7 +51,7 @@ public XSeries AddXSeries() internal override void Serialize(Serializer serializer) { int count = Count; - for (int index = 0; index < count; ++index) + for (int index = 0; index < count; index++) { var xSeries = this[index] as XSeries; xSeries?.Serialize(serializer); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs index a5b8f7dd..efef6a1a 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Barcode.cs @@ -108,7 +108,7 @@ public double NarrowLineWidth internal override void Serialize(Serializer serializer) { if (String.IsNullOrEmpty(Values.Code)) - throw new InvalidOperationException(DomSR.MissingObligatoryProperty("Name", "BookmarkField")); + throw new InvalidOperationException(MdDomMsgs.MissingObligatoryProperty(nameof(Code), nameof(Barcode)).Message); serializer.WriteLine("\\barcode(\"" + Code + "\")"); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs index df36da5f..61dbce45 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/Image.cs @@ -166,13 +166,13 @@ public string GetFilePath(string workingDir) if (!String.IsNullOrEmpty(workingDir)) filePath = workingDir; else - filePath = Directory.GetCurrentDirectory() + "\\"; + filePath = Directory.GetCurrentDirectory() + "/"; if (!Document.Values.ImagePath.IsValueNullOrEmpty()) { - string? foundfile = ImageHelper.GetImageName(filePath, Name, Document.ImagePath); - if (foundfile != null) - filePath = foundfile; + string? foundFile = ImageHelper.GetImageName(filePath, Name, Document.ImagePath); + if (foundFile != null) + filePath = foundFile; else filePath = Path.Combine(filePath, Name); } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LeftPosition.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LeftPosition.cs index 9e260af3..277ac6ce 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LeftPosition.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/LeftPosition.cs @@ -23,7 +23,7 @@ public struct LeftPosition : INullableValue LeftPosition(ShapePosition value) { if (!(value == ShapePosition.Undefined || IsValid(value))) - throw new ArgumentException(DomSR.InvalidEnumForLeftPosition); + throw new ArgumentException(MdDomMsgs.InvalidEnumForLeftPosition.Message); ShapePosition = value; Position = Unit.Empty; @@ -35,7 +35,7 @@ public struct LeftPosition : INullableValue void SetFromEnum(ShapePosition shapePosition) { if (!IsValid(shapePosition)) - throw new ArgumentException(DomSR.InvalidEnumForLeftPosition); + throw new ArgumentException(MdDomMsgs.InvalidEnumForLeftPosition.Message); ShapePosition = shapePosition; Position = Unit.Empty; diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TopPosition.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TopPosition.cs index 739e2530..3ac29ef3 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TopPosition.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Shapes/TopPosition.cs @@ -23,7 +23,7 @@ public struct TopPosition : INullableValue TopPosition(ShapePosition value) { if (!(IsValid(value) || value == ShapePosition.Undefined)) - throw new ArgumentException(DomSR.InvalidEnumForTopPosition); + throw new ArgumentException(MdDomMsgs.InvalidEnumForTopPosition.Message); ShapePosition = value; Position = Unit.Empty; @@ -35,7 +35,7 @@ public struct TopPosition : INullableValue void SetFromEnum(ShapePosition shapePosition) { if (!IsValid(shapePosition)) - throw new ArgumentException(DomSR.InvalidEnumForTopPosition); + throw new ArgumentException(MdDomMsgs.InvalidEnumForTopPosition.Message); ShapePosition = shapePosition; Position = Unit.Empty; diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs index 32010a43..5e831877 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Cell.cs @@ -84,9 +84,8 @@ internal override void ResetCachedValues() // Lazy execution makes properties slow. Calculate frequently required property values in advance. if (Parent is Cells cells) { - _table = cells.Table; - _row = cells.Row; + _table = cells.Table; } } @@ -176,7 +175,7 @@ public Column Column return _clm; if (/*_clm == null &&*/ Parent is Cells cells) { - for (int index = 0; index < cells.Count; ++index) + for (int index = 0; index < cells.Count; index++) { //if (cells[index] == this) // _clm = Table.Columns[index]; diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Column.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Column.cs index 7e35a148..88b489e8 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Column.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Column.cs @@ -99,11 +99,11 @@ public int Index return _idx; if (Values.Index is null && Parent is Columns clms) { - for (int i = 0; i < clms.Count; ++i) + for (int idx = 0; idx < clms.Count; idx++) { - clms[i].Values.Index = i; - clms[i]._idx = i; - clms[i]._hasIdx = true; + clms[idx].Values.Index = idx; + clms[idx]._idx = idx; + clms[idx]._hasIdx = true; } if (_hasIdx) return _idx; diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Row.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Row.cs index f8612970..82b0a861 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Row.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Tables/Row.cs @@ -39,7 +39,6 @@ internal Row(DocumentObject parent) : base(parent) protected override object DeepCopy() { var row = (Row)base.DeepCopy(); - row.ResetCachedValues(); if (row.Values.Format != null) { row.Values.Format = row.Values.Format.Clone(); @@ -60,6 +59,17 @@ protected override object DeepCopy() row.Values.Cells = row.Values.Cells.Clone(); row.Values.Cells.Parent = row; } + + // Now reset cached values. + + row.ResetCachedValues(); + row.Cells.ResetCachedValues(); + for (var columnIndex = 0; columnIndex < row.Cells.Count; columnIndex++) + { + var cell = row.Cells[columnIndex]; + cell.ResetCachedValues(); + } + return row; } @@ -85,7 +95,16 @@ internal override void ResetCachedValues() if (Parent is Rows rws) { + // All children must update their ancestors. + // Now reset cached values. + Cells.ResetCachedValues(); + // Assign _table before resetting children that may depend on Table of their parent. _table = rws.Table; + for (var columnIndex = 0; columnIndex < Cells.Count; columnIndex++) + { + var cell = Cells[columnIndex]; + cell.ResetCachedValues(); + } } } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/CellComparer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/CellComparer.cs index 1482aba4..a6fad976 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/CellComparer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/CellComparer.cs @@ -49,7 +49,6 @@ public class CellComparer : IComparer /// /// Compares the specified cells. /// - /// public int Compare(Cell? cellLhs, Cell? cellRhs) { if (cellLhs != null && cellRhs != null) diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/ElementsExtensions.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/ElementsExtensions.cs index d780b17f..dbcfa7f5 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/ElementsExtensions.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/ElementsExtensions.cs @@ -173,7 +173,6 @@ public static IEnumerable GetElementsRecursively(this DocumentObject docum /// /// The type to be filtered. /// The document objects. - /// public static IEnumerable Filter(this IEnumerable elements) where T : DocumentObject { diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/MergedCellList.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/MergedCellList.cs index 23aec100..22db1b49 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/MergedCellList.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/MergedCellList.cs @@ -60,9 +60,9 @@ void Init(Table table) if (clmIdx + mergeRight >= columns) throw TH.InvalidOperationException_MergeRightTooLarge(rwIdx, clmIdx, mergeRight); - for (int idxMergedRows = 0; idxMergedRows <= mergeDown; ++idxMergedRows) + for (int idxMergedRows = 0; idxMergedRows <= mergeDown; idxMergedRows++) { - for (int idxMergedColumns = 0; idxMergedColumns <= mergeRight; ++idxMergedColumns) + for (int idxMergedColumns = 0; idxMergedColumns <= mergeRight; idxMergedColumns++) { flags[rwIdx + idxMergedRows, clmIdx + idxMergedColumns] = true; } @@ -426,7 +426,7 @@ static Unit GetEffectiveBorderWidth(Borders? borders, BorderType type) if (cell2.Row.Index == cell.Row.Index) return cell2; } - for (int index = cellIdx + 1; index < Count; ++index) + for (int index = cellIdx + 1; index < Count; index++) { var currCell = this[index]; if (IsNeighbor(cell, currCell, position)) @@ -435,7 +435,7 @@ static Unit GetEffectiveBorderWidth(Borders? borders, BorderType type) break; case NeighborPosition.Bottom: - for (int index = cellIdx + 1; index < Count; ++index) + for (int index = cellIdx + 1; index < Count; index++) { var currCell = this[index]; if (IsNeighbor(cell, currCell, position)) @@ -501,7 +501,7 @@ static Unit GetEffectiveBorderWidth(Borders? borders, BorderType type) if (cell2.Row.Index == cell.Row.Index) return cell2; } - for (var index = cellIdx + 2; index < Count; ++index) + for (var index = cellIdx + 2; index < Count; index++) { var currCell = this[index]; if (IsNeighborRight(cell, currCell)) @@ -516,7 +516,7 @@ static Unit GetEffectiveBorderWidth(Borders? borders, BorderType type) if (cell.Row.Index + cell.MergeDown == cell.Table.Rows.Count - 1) return null; - for (var index = cellIdx + 1; index < Count; ++index) + for (var index = cellIdx + 1; index < Count; index++) { var currCell = this[index]; if (IsNeighborBottom(cell, currCell)) diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/PdfFlattenVisitor.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/PdfFlattenVisitor.cs index 7b5cfb0d..05b21b2d 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/PdfFlattenVisitor.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/PdfFlattenVisitor.cs @@ -21,7 +21,7 @@ internal override void VisitDocumentElements(DocumentElements elements) #if true // New version without sorted list. int count = elements.Count; - for (int idx = 0; idx < count; ++idx) + for (int idx = 0; idx < count; idx++) { if (elements[idx] is Paragraph paragraph) { @@ -41,7 +41,7 @@ internal override void VisitDocumentElements(DocumentElements elements) #else SortedList splitParaList = new SortedList(); - for (int idx = 0; idx < elements.Count; ++idx) + for (int idx = 0; idx < elements.Count; idx++) { Paragraph paragraph = elements[idx] as Paragraph; if (paragraph != null) @@ -53,7 +53,7 @@ internal override void VisitDocumentElements(DocumentElements elements) } int insertedObjects = 0; - for (int idx = 0; idx < splitParaList.Count; ++idx) + for (int idx = 0; idx < splitParaList.Count; idx++) { int insertPosition = (int)splitParaList.GetKey(idx); Paragraph[] paragraphs = (Paragraph[])splitParaList.GetByIndex(idx); @@ -78,7 +78,7 @@ internal override void VisitDocumentObjectCollection(DocumentObjectCollection el List textIndices = new List(); if (elements is ParagraphElements) { - for (int idx = 0; idx < elements.Count; ++idx) + for (int idx = 0; idx < elements.Count; idx++) { if (elements[idx] is Text) textIndices.Add(idx); @@ -236,7 +236,6 @@ internal override void VisitHyperlink(Hyperlink hyperlink) /// Get the font for the parent of a given object. /// /// The object to start with. - /// /// Exception that is thrown of the parent object is neither Paragraph nor Hyperlink or FormattedText. protected Font? GetParentFont(DocumentObject obj) { diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/VisitorBase.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/VisitorBase.cs index 63ae89ca..968d996c 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/VisitorBase.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel.Visitors/VisitorBase.cs @@ -273,7 +273,7 @@ protected static void FlattenTabStops(TabStops tabStops, TabStops refTabStops) { TabStop tabStop = tabStops[i]; if (!tabStop.AddTab) - tabStops.RemoveObjectAt(i); + tabStops.RemoveObjectAt(i--); } // The TabStopCollection is complete now. diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Borders.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Borders.cs index 44e2c6d8..a4450c3d 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Borders.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Borders.cs @@ -33,7 +33,7 @@ internal Borders(DocumentObject parent) : base(parent) public bool HasBorder(BorderType type) { if (!Enum.IsDefined(typeof(BorderType), type)) - throw new /*InvalidEnum*/ArgumentException(DomSR.InvalidEnumValue(type), "type"); + throw new /*InvalidEnum*/ArgumentException(MdDomMsgs.InvalidEnumValue(type).Message, nameof(type)); return GetBorder(type) is not null; } @@ -66,7 +66,7 @@ public bool HasBorder(BorderType type) } if (!Enum.IsDefined(typeof(BorderType), type)) - throw new InvalidEnumArgumentException(DomSR.InvalidEnumValue(type)); + throw new InvalidEnumArgumentException(MdDomMsgs.InvalidEnumValue(type).Message); return null; } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Chars.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Chars.cs index bb0858c8..e235b510 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Chars.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Chars.cs @@ -13,34 +13,42 @@ public sealed class Chars /// The null or EOF character. /// public const char Null = '\0'; // EOF + /// /// The carriage-return character. /// - public const char CR = '\x0D'; // ignored by scanner + public const char CR = '\x0D'; // Ignored by scanner + /// /// The line-feed character. /// public const char LF = '\x0A'; + /// /// The bell character. /// public const char BEL = '\a'; // Bell + /// /// The backspace character. /// public const char BS = '\b'; // Backspace + /// /// The form-feed character. /// public const char FF = '\f'; // Form feed + /// /// The horizontal-tab character. /// public const char HT = '\t'; // Horizontal tab + /// /// The vertical-tab character. /// public const char VT = '\v'; // Vertical tab + /// /// The no-break space. /// @@ -49,106 +57,132 @@ public sealed class Chars // ===== The following names come from "PDF Reference Third Edition" ===== // ===== Appendix D.1, Latin Character Set and Encoding ===== + /// /// A regular blank. /// public const char Space = ' '; + /// /// A double quote '"'. /// public const char QuoteDbl = '"'; + /// /// A single quote "'". /// public const char QuoteSingle = '\''; + /// /// A left parenthesis '('. /// public const char ParenLeft = '('; + /// /// A right parenthesis ')'. /// public const char ParenRight = ')'; + /// /// A left brace '{'. /// public const char BraceLeft = '{'; + /// /// A right brace '}'. /// public const char BraceRight = '}'; + /// /// A left bracket '['. /// public const char BracketLeft = '['; + /// /// A right bracket ']'. /// public const char BracketRight = ']'; + /// /// A less sign '<'. /// public const char Less = '<'; + /// /// A greater sign '>'. /// public const char Greater = '>'; + /// /// An equal sign '='. /// public const char Equal = '='; + /// /// A period '.'. /// public const char Period = '.'; + /// /// A semicolon ';'. /// public const char Semicolon = ';'; + /// /// A colon ':'. /// public const char Colon = ':'; + /// /// A slash '/'. /// public const char Slash = '/'; + /// /// A bar '|'. /// public const char Bar = '|'; + /// /// A back-slash '\'. /// public const char BackSlash = '\\'; + /// /// A percent sign '%'. /// public const char Percent = '%'; + /// /// A dollar sign '$'. /// public const char Dollar = '$'; + /// /// An at sign '@'. /// public const char At = '@'; + /// /// A number sign '#'. /// public const char NumberSign = '#'; + /// /// A question mark '?'. /// public const char Question = '?'; + /// /// A hyphen. /// public const char Hyphen = '-'; // char(45) + /// /// A soft-hyphen. /// public const char SoftHyphen = '\u00AD'; // char(173) + /// /// A currency sign '¤'. /// diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Color.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Color.cs index 908c2b46..7e36471e 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Color.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Color.cs @@ -345,24 +345,21 @@ public static Color Parse(string color) if (number.StartsWith("0x", StringComparison.Ordinal)) { numberStyle = NumberStyles.HexNumber; -#if NET6_0_OR_GREATER || true number = color[2..]; -#else - number = color.Substring(2); -#endif } else if (number.StartsWith("#", StringComparison.Ordinal)) { numberStyle = NumberStyles.HexNumber; switch (color.Length) { -#if NET6_0_OR_GREATER || true case 9: // Format "#aarrggbb". number = color[1..]; break; + case 7: // Format "#rrggbb". number = "ff" + color[1..]; break; + case 4: // Format "#rgb". var r = color[1..2]; var g = color[2..3]; @@ -371,24 +368,9 @@ public static Color Parse(string color) g + g + b + b; break; -#else - case 9: // Format "#aarrggbb". - number = color.Substring(1); - break; - case 7: // Format "#rrggbb". - number = "ff" + color.Substring(1); - break; - case 4: // Format "#rgb". - var r = color.Substring(1, 1); - var g = color.Substring(2, 1); - var b = color.Substring(3, 1); - number = "ff" + r + r + - g + g + - b + b; - break; -#endif + default: - throw new ArgumentException(DomSR.InvalidColorString(color), nameof(color)); + throw new ArgumentException(MdDomMsgs.InvalidColorString(color).Message); } } clr = UInt32.Parse(number, numberStyle); @@ -396,7 +378,7 @@ public static Color Parse(string color) } catch (FormatException ex) { - throw new ArgumentException(DomSR.InvalidColorString(color), ex); + throw new ArgumentException(MdDomMsgs.InvalidColorString(color).Message, ex); } } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DdlEncoder.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DdlEncoder.cs index f01ec8e1..806174bc 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DdlEncoder.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DdlEncoder.cs @@ -20,7 +20,7 @@ public static class DdlEncoder int length = str.Length; var sb = new StringBuilder(length + (length >> 2)); - for (int index = 0; index < length; ++index) + for (int index = 0; index < length; index++) { // Dont convert characters into DDL. char ch = str[index]; @@ -43,7 +43,7 @@ public static class DdlEncoder if (index < length - 1 && str[index + 1] == '/') { sb.Append("\\//"); - ++index; + index++; } else sb.Append("/"); @@ -68,7 +68,7 @@ public static string StringToLiteral(string? str) var sb = new StringBuilder(length + (length >> 2)); sb.Append("\""); - for (int index = 0; index < length; ++index) + for (int index = 0; index < length; index++) { char ch = str[index]; switch (ch) diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Document.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Document.cs index d7aac1e0..4e82b4be 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Document.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Document.cs @@ -142,11 +142,7 @@ public Section LastSection // TODO: LastTable, etc., docu var sections = Values.Sections; if (sections is { Count: > 0 }) -#if NET6_0_OR_GREATER || true return sections[^1]; -#else - return sections[sections.Count - 1]; -#endif return Capabilities.BackwardCompatibility.DoNotCreateLastSection ? null! : AddSection(); } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObject.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObject.cs index 7eeab199..e5da7119 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObject.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObject.cs @@ -179,7 +179,7 @@ protected void SetParent(DocumentObject? val) if (val != null) { if (val.Parent != null) - throw new ArgumentException(DomSR.ParentAlreadySet(val, this)); + throw new ArgumentException(MdDomMsgs.ParentAlreadySet(val, this).Message); val.Parent = this; val._document = null; diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObjectCollection.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObjectCollection.cs index d5320390..712745eb 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObjectCollection.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DocumentObjectCollection.cs @@ -45,7 +45,7 @@ protected override object DeepCopy() int count = Count; coll._elements = new List(count); - for (int index = 0; index < count; ++index) + for (int index = 0; index < count; index++) { var doc = this[index]; if (doc != null) @@ -85,7 +85,7 @@ public void Clear() { // Call ResetCachedValues for all affected objects. int count = ((IList)this).Count; - for (int idx = 0; idx < count; ++idx) + for (int idx = 0; idx < count; idx++) { var obj = (DocumentObject)((IList)this)[idx]!; obj.ResetCachedValues(); @@ -106,7 +106,7 @@ public virtual void InsertObject(int index, DocumentObject val) ((IList)this).Insert(index, val); // Call ResetCachedValues for all objects moved by the Insert operation. int count = ((IList)this).Count; - for (int idx = index + 1; idx < count; ++idx) + for (int idx = index + 1; idx < count; idx++) { var obj = ((IList)this)[idx]!; if (obj is Row row) @@ -157,7 +157,7 @@ public void RemoveObjectAt(int index) ((IList)this).RemoveAt(index); // Call ResetCachedValues for all objects moved by the RemoveAt operation. int count = ((IList)this).Count; - for (int idx = index; idx < count; ++idx) + for (int idx = index; idx < count; idx++) { var obj = (DocumentObject)((IList)this)[idx]!; if (obj is Row row) @@ -195,12 +195,12 @@ static void UpdateRowCachedValues(Row row, bool reset = false) else { // Called from Clear, InsertObject, or RemoveObjectAt: use a loop. - for (int i = 0; i < rws.Count; ++i) + for (int idx = 0; idx < rws.Count; idx++) { - if (row == rws[i]) + if (row == rws[idx]) { - row.Values.Index = i; - row.ResetIndex(i); + row.Values.Index = idx; + row.ResetIndex(idx); } } } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DomSR.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DomSR.cs deleted file mode 100644 index b11ad7a7..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/DomSR.cs +++ /dev/null @@ -1,212 +0,0 @@ -// MigraDoc - Creating Documents on the Fly -// See the LICENSE file in the solution root for more information. - -using System.Diagnostics; -using System.Reflection; -using System.Resources; -#if DEBUG -using System.Text.RegularExpressions; -#endif - -namespace MigraDoc.DocumentObjectModel -{ - /// - /// String resources of MigraDoc.DocumentObjectModel. Provides all localized text strings - /// for this assembly. - /// - static class DomSR - { - /// - /// Loads the message from the resource associated with the enum type and formats it - /// using 'string.Format'. Because this function is intended to be used during error - /// handling it never raises an exception. - /// - /// The type of the parameter identifies the resource - /// and the name of the enum identifies the message in the resource. - /// Parameters passed through 'string.Format'. - /// The formatted message. - public static string FormatMessage(DomMsgID id, params object[] args) - { - string? message; - try - { - message = GetString(id); - if (message != null) - { -#if DEBUG - if (Regex.Matches(message, @"\{[0-9]\}").Count > args.Length) - { - //TODO too many placeholders or too few args... - } -#endif - message = String.Format(message, args); - } - else - message = "<<>>"; - return message; - } - catch (Exception ex) - { - message = "INTERNAL ERROR while formatting error message: " + ex; - } - return message; - } - - public static string CompareJustCells => "Only cells can be compared by this Comparer."; - - /// - /// Gets the localized message identified by the specified DomMsgID. - /// - public static string? GetString(DomMsgID id) - { - return ResMngr.GetString(id.ToString()) ?? $"(could not get string for {id})"; // BUG ResMngr is to be deleted and replaced by string interpolation - } - - #region How to use -#if true_ - // Message with no parameter is property. - public static string SampleMessage1 - { - // In the first place English only - get { return "This is sample message 1."; } - } - - // Message with no parameter is property. - public static string SampleMessage2 - { - // Then localized: - get { return DomSR.GetString(DomMsgID.SampleMessage1); } - } - - // Message with parameters is function. - public static string SampleMessage3(string parm) - { - // In the first place English only - //return String.Format("This is sample message 2: {0}.", parm); - } - public static string SampleMessage4(string parm) - { - // Then localized: - return String.Format(GetString(DomMsgID.SampleMessage2), parm); - } -#endif - #endregion - - #region General Messages - - public static string? StyleExpected => GetString(DomMsgID.StyleExpected); - - public static string? BaseStyleRequired => GetString(DomMsgID.BaseStyleRequired); - - public static string? EmptyBaseStyle => GetString(DomMsgID.EmptyBaseStyle); - - public static string InvalidFieldFormat(string format) - { - return FormatMessage(DomMsgID.InvalidFieldFormat, format); - } - - public static string InvalidInfoFieldName(string name) - { - return FormatMessage(DomMsgID.InvalidInfoFieldName, name); - } - - public static string UndefinedBaseStyle(string baseStyle) - { - return FormatMessage(DomMsgID.UndefinedBaseStyle, baseStyle); - } - - public static string InvalidValueName(string name) - { - return FormatMessage(DomMsgID.InvalidValueName, name); - } - - public static string InvalidUnitValue(string unitValue) - { - return FormatMessage(DomMsgID.InvalidUnitValue, unitValue); - } - - public static string InvalidUnitType(string unitType) - { - return FormatMessage(DomMsgID.InvalidUnitType, unitType); - } - - public static string InvalidEnumValue(T value) where T : Enum // struct, Enum - { - // ... where T : enum - // -or- - // ... where T : Enum - // is not implemented in C# because nobody has done this. - // See Eric Lippert on this topic: http://stackoverflow.com/questions/1331739/enum-type-constraints-in-c-sharp - // UPDATE: Enum constraint comes with C# 7.3, see: https://devblogs.microsoft.com/premier-developer/dissecting-new-generics-constraints-in-c-7-3/ - Debug.Assert(typeof(T).IsSubclassOf(typeof(Enum))); - return FormatMessage(DomMsgID.InvalidEnumValue, value, typeof(T).Name); - } - - public static string? InvalidEnumForLeftPosition => GetString(DomMsgID.InvalidEnumForLeftPosition); - - public static string? InvalidEnumForTopPosition => GetString(DomMsgID.InvalidEnumForTopPosition); - - public static string InvalidColorString(string colorString) - { - return FormatMessage(DomMsgID.InvalidColorString, colorString); - } - - public static string InvalidFontSize(double value) - { - return FormatMessage(DomMsgID.InvalidFontSize, value); - } - - public static string InsertNullNotAllowed() - { - return "Insert null not allowed."; - } - - public static string ParentAlreadySet(DocumentObject value, DocumentObject docObject) - { - return $"Value of type '{value.GetType()}' must be cloned before setting into '{docObject.GetType()}'."; - } - - public static string MissingObligatoryProperty(string propertyName, string className) - { - return FormatMessage(DomMsgID.MissingObligatoryProperty, propertyName, className); - } - - public static string InvalidDocumentObjectType => "The given document object is not valid in this context."; - - #endregion - - #region DdlReader Messages - - #endregion - - #region Resource Manager - - public static ResourceManager ResMngr - { - // ReSharper disable ConvertIfStatementToNullCoalescingExpression - get - { - _resmngr ??= new ResourceManager("MigraDoc.DocumentObjectModel.Resources.Messages", Assembly.GetExecutingAssembly()); - return _resmngr; - } - // ReSharper restore ConvertIfStatementToNullCoalescingExpression - } - - /// - /// Writes all messages defined by DomMsgID. - /// - [Conditional("DEBUG")] - public static void TestResourceMessages() - { - string[] names = Enum.GetNames(typeof(DomMsgID)); - foreach (string name in names) - { - string message = $"{name}: '{ResMngr.GetString(name)}'"; - Debug.WriteLine(message); - } - } - static ResourceManager? _resmngr; - - #endregion - } -} diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/EmbeddedFiles.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/EmbeddedFiles.cs index cace31b9..ad5440fb 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/EmbeddedFiles.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/EmbeddedFiles.cs @@ -39,7 +39,7 @@ public EmbeddedFile Add(string name, string path) internal override void Serialize(Serializer serializer) { var count = Count; - for (var index = 0; index < count; ++index) + for (var index = 0; index < count; index++) { var embeddedFile = this[index]; embeddedFile.Serialize(serializer); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Font.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Font.cs index bdcc62e2..c562cb78 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Font.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Font.cs @@ -324,7 +324,7 @@ internal void Serialize(Serializer serializer, Font? font) serializer.WriteSimpleAttribute("Name", Name); #if DEBUG_ // Test - if (!_size.IsNull && Size != 0 && Size.Point == 0) + if (Size != Unit.Empty && Size != 0 && Size.Point == 0) _ = typeof(int); #endif diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs index 7fb060a9..24938de1 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/HeadersFooters.cs @@ -82,14 +82,15 @@ public bool IsHeader } } - /// - /// Determines whether a particular header or footer exists. - /// - [Obsolete("Uses IsNull and should be avoided.")] // BUG??? - public bool HasHeaderFooter(HeaderFooterIndex index) - { - return !IsNull(index.ToString()); - } + // #DELETE + ///// + ///// Determines whether a particular header or footer exists. + ///// + //[Obsolete("Uses IsNull and should be avoided.")] // BUG??? + //public bool HasHeaderFooter(HeaderFooterIndex index) + //{ + // return !IsNull(index.ToString()); + //} /// /// Determines whether a particular header or footer exists. diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Hyperlink.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Hyperlink.cs index c33b1767..e8fa7212 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Hyperlink.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Hyperlink.cs @@ -581,14 +581,14 @@ internal override void Serialize(Serializer serializer) if (Type is HyperlinkType.ExternalBookmark or HyperlinkType.File or HyperlinkType.Url) { if (String.IsNullOrEmpty(Values.Filename)) - throw new InvalidOperationException(DomSR.MissingObligatoryProperty("Filename", $"Hyperlink {Type.ToString()}")); + throw new InvalidOperationException(MdDomMsgs.MissingObligatoryProperty(nameof(Filename), $"Hyperlink {Type.ToString()}").Message); str += " Filename = \"" + Filename.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\""; } if (Type is HyperlinkType.ExternalBookmark or HyperlinkType.Bookmark or HyperlinkType.EmbeddedDocument) { if (String.IsNullOrEmpty(Values.BookmarkName)) - throw new InvalidOperationException(DomSR.MissingObligatoryProperty("BookmarkName", $"Hyperlink {Type.ToString()}")); + throw new InvalidOperationException(MdDomMsgs.MissingObligatoryProperty(nameof(BookmarkName), $"Hyperlink {Type.ToString()}").Message); str += " BookmarkName = \"" + BookmarkName.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\""; } @@ -659,7 +659,7 @@ internal HyperlinkValues(DocumentObject owner) : base(owner) /// public string? Name { - get => Owner.Name; + get => Owner.Name; set => Owner.Name = value ?? ""; // BUG??? "null" becomes "". } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ImageHelper.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ImageHelper.cs index 46c7134a..a13c8d2f 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ImageHelper.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ImageHelper.cs @@ -14,8 +14,7 @@ public static class ImageHelper public static string? GetImageName(string root, string filename, string imagePath) { List subfolders = new(imagePath.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries)); - subfolders.Add(""); - + foreach (string subfolder in subfolders) { string fullname = Path.Combine(Path.Combine(root, subfolder), filename); @@ -32,14 +31,14 @@ public static class ImageHelper /// public static bool InSubfolder(string root, string filename, string imagePath, string referenceFilename) { - List subfolders = new List(imagePath.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); + List subfolders = new List(imagePath.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); subfolders.Add(""); foreach (string subfolder in subfolders) { - string fullname = System.IO.Path.Combine(System.IO.Path.Combine(root, subfolder), filename); + string fullname = System.IO.Path.Combine(Path.Combine(root, subfolder), filename); string realFile = ExtractPageNumber(fullname, out _); - if (System.IO.File.Exists(realFile)) + if (File.Exists(realFile)) { if (fullname == referenceFilename) return true; @@ -76,13 +75,8 @@ public static string ExtractPageNumber(string path, out int pageNumber) if (path.IndexOf(".", StringComparison.Ordinal) != -1) #endif { -#if NET6_0_OR_GREATER || true pageNumber = Int32.Parse(path[(length + 1)..]); path = path[..length]; -#else - pageNumber = Int32.Parse(path.Substring(length + 1)); - path = path.Substring(0, length); -#endif } } } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/MdDomMsg.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/MdDomMsg.cs new file mode 100644 index 00000000..e81ea0c1 --- /dev/null +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/MdDomMsg.cs @@ -0,0 +1,21 @@ +// MigraDoc - Creating Documents on the Fly +// See the LICENSE file in the solution root for more information. + +using Microsoft.Extensions.Logging; + +namespace MigraDoc.DocumentObjectModel +{ + /// + /// MigraDoc DOM message. + /// + readonly struct MdDomMsg(MdDomMsgId id, string message) + { + public MdDomMsgId Id { get; init; } = id; + + public string Message { get; init; } = message; + + public EventId EventId => new((int)Id, EventName); + + public string EventName => Id.ToString(); + } +} diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/MdDomMsgs.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/MdDomMsgs.cs new file mode 100644 index 00000000..ad47d6e6 --- /dev/null +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/MdDomMsgs.cs @@ -0,0 +1,200 @@ +// MigraDoc - Creating Documents on the Fly +// See the LICENSE file in the solution root for more information. + +using Microsoft.Extensions.Logging; + +namespace MigraDoc.DocumentObjectModel +{ + /// + /// MigraDoc DOM messages. + /// String resources of MigraDoc.DocumentObjectModel. Provides all localized text strings + /// for this assembly. + /// + // ReSharper disable once InconsistentNaming + // ReSharper disable once IdentifierTypo + static class MdDomMsgs + { + #region General Messages + + public static MdDomMsg StyleExpected(Type wrongType) + => new(MdDomMsgId.StyleExpected, $"The value must be of type 'Style', but it is of type '{wrongType.Name}'."); + + public static MdDomMsg BaseStyleRequired + => new(MdDomMsgId.BaseStyleRequired, "Base style name must be defined."); + + public static MdDomMsg EmptyBaseStyle + => new(MdDomMsgId.EmptyBaseStyle, "Attempt to set empty base style is invalid."); + + public static MdDomMsg InvalidFieldFormat(string format) + => new(MdDomMsgId.InvalidFieldFormat, $"'{format}' is not a valid numeric field format."); + + public static MdDomMsg InvalidInfoFieldName(string name) + => new(MdDomMsgId.InvalidInfoFieldName, $"Property 'Name' of 'InfoField' has invalid value '{name}'."); + + public static MdDomMsg UndefinedBaseStyle(string style) + => new(MdDomMsgId.UndefinedBaseStyle, $"The base style of style '{style}' is undefined."); + + public static MdDomMsg InvalidValueName(string name) + => new(MdDomMsgId.InvalidValueName, $"Invalid value name: '{name}'."); + + public static MdDomMsg InvalidUnitValue(string unitValue) + => new(MdDomMsgId.InvalidUnitValue, $"String '{unitValue}' is not a valid value for structure 'Unit'."); + + public static MdDomMsg InvalidUnitType(string unitType) + => new(MdDomMsgId.InvalidUnitType, $"'{unitType}' is an unknown unit type."); + + public static MdDomMsg InvalidEnumValue(T value) where T : Enum + => new(MdDomMsgId.InvalidEnumValue, $"The value '{value:X}' is not valid for enum type '{typeof(T)}'."); + + public static MdDomMsg InvalidEnumForLeftPosition + => new(MdDomMsgId.InvalidEnumForLeftPosition, "ShapePosition must be 'Left', 'Center', or 'Right'."); + + public static MdDomMsg InvalidEnumForTopPosition + => new(MdDomMsgId.InvalidEnumForTopPosition, "ShapePosition must be 'Top', 'Center', or 'Bottom'."); + + public static MdDomMsg InvalidColorString(string colorString) + => new(MdDomMsgId.InvalidColorString, $"Color could not be parsed from string '{colorString}'."); + + public static MdDomMsg InvalidFontSize(double value) + => new(MdDomMsgId.InvalidFontSize, $"The font size '{value}' is out of range."); + + public static MdDomMsg InsertNullNotAllowed() + => new(MdDomMsgId.InsertNullNotAllowed, "Insert null not allowed."); + + public static MdDomMsg ParentAlreadySet(DocumentObject value, DocumentObject docObject) + => new(MdDomMsgId.ParentAlreadySet, $"Value of type '{value.GetType()}' must be cloned before setting into '{docObject.GetType()}'."); + + public static MdDomMsg MissingObligatoryProperty(string propertyName, string className) + => new(MdDomMsgId.MissingObligatoryProperty, $"Obligatory property '{propertyName}' not set in '{className}'."); + + public static MdDomMsg InvalidDocumentObjectType + => new(MdDomMsgId.InvalidDocumentObjectType, "The given document object is not valid in this context."); + + #endregion + + #region DdlReader Messages + + public static MdDomMsg SymbolExpected(string expected, string token) + => new(MdDomMsgId.SymbolExpected, $"'{expected}' expected, found '{token}'."); + + //public static MdDomMsg SymbolsExpected + // => new(DomMsgId.SymbolsExpected, "One of the following symbols {x} is expected."); + + //public static MdDomMsg OperatorExpected + // => new(DomMsgId.OperatorExpected, "Syntax error: Operator '{x}' is expected."); + + //public static MdDomMsg KeyWordExpected + // => new(DomMsgID.KeyWordExpected, "'{y}' - '{x}' expected."); + + public static MdDomMsg EndOfFileExpected + => new(MdDomMsgId.EndOfFileExpected, "End of file expected."); + public static MdDomMsg UnexpectedEndOfFile + => new(MdDomMsgId.UnexpectedEndOfFile, "Unexpected end of file."); + + public static MdDomMsg StyleNameExpected(string name) + => new(MdDomMsgId.StyleNameExpected, $"Invalid style name '{name}'."); + + public static MdDomMsg UnexpectedSymbol(string token) + => new(MdDomMsgId.UnexpectedSymbol, $"Unexpected symbol '{token}'."); + + public static MdDomMsg IdentifierExpected(string token) + => new(MdDomMsgId.IdentifierExpected, $"Identifier expected: '{token}'."); + + public static MdDomMsg BoolValueExpected(string token) + => new(MdDomMsgId.BoolValueExpected, $"Bool value expected: '{token}'."); + + public static MdDomMsg RealValueExpected(string token) + => new(MdDomMsgId.RealValueExpected, $"Real value expected: '{token}'."); + + public static MdDomMsg IntegerValueExpected(string token) + => new(MdDomMsgId.IntegerValueExpected, $"Integer value expected: '{token}'."); + + public static MdDomMsg StringValueExpected(string token) + => new(MdDomMsgId.StringValueExpected, $"String value expected: '{token}'."); + + public static MdDomMsg NullValueExpected(string token) + => new(MdDomMsgId.NullValueExpected, $"Null value expected: '{token}'."); + + public static MdDomMsg NumberValueExpected(string token) + => new(MdDomMsgId.NumberValueExpected, $"Number value expected: '{token}'."); + + public static MdDomMsg InvalidEnum(string token, string typeName) + => new(MdDomMsgId.InvalidEnum, $"'{token}' is not a valid value for type '{typeName}'."); + + public static MdDomMsg InvalidType(string typeName, string valueName) + => new(MdDomMsgId.InvalidType, $"Variable type '{typeName}' not supported by '{valueName}'."); + + public static MdDomMsg InvalidAssignment(string name) + => new(MdDomMsgId.InvalidAssignment, $"Invalid assignment to '{name}'."); + + //public static MdDomMsg InvalidValueName => "Invalid value name: '{x}'."); + + public static MdDomMsg InvalidRange(string range) + => new(MdDomMsgId.InvalidRange, $"Invalid range: '{range}'."); + + public static MdDomMsg InvalidColor(string token) + => new(MdDomMsgId.InvalidColor, $"Invalid color: '{token}'."); + + public static MdDomMsg InvalidFieldType(string token) + => new(MdDomMsgId.InvalidFieldType, $"Invalid field type: '{token}'."); + + public static MdDomMsg InvalidValueForOperation(string value, string token) + => new(MdDomMsgId.InvalidValueForOperation, $"Operation '{token}' is not valid for value '{value}'."); + + public static MdDomMsg InvalidSymbolType(string token) + => new(MdDomMsgId.InvalidSymbolType, $"Symbol not valid '{token}'."); + + public static MdDomMsg MissingBraceLeft(string token) + => new(MdDomMsgId.MissingBraceLeft, $"Missing left brace after '{token}'."); + + public static MdDomMsg MissingBraceRight(string token) + => new(MdDomMsgId.MissingBraceRight, $"Missing right brace after '{token}'."); + + public static MdDomMsg MissingBracketLeft(string token) + => new(MdDomMsgId.MissingBracketLeft, $"Missing left bracket after '{token}'."); + + public static MdDomMsg MissingBracketRight(string token) + => new(MdDomMsgId.MissingBracketRight, $"Missing right bracket after '{token}'."); + + public static MdDomMsg MissingParenLeft(string token) + => new(MdDomMsgId.MissingParenLeft, $"Missing left parenthesis after '{token}'."); + + public static MdDomMsg MissingParenRight(string token) + => new(MdDomMsgId.MissingParenRight, $"Missing right parenthesis after '{token}'."); + + public static MdDomMsg MissingComma + => new(MdDomMsgId.MissingComma, "Missing comma."); + + public static MdDomMsg SymbolNotAllowed(string token) + => new(MdDomMsgId.SymbolNotAllowed, $"Symbol '{token}' is not allowed in this context."); + + public static MdDomMsg SymbolIsNotAnObject(string token) + => new(MdDomMsgId.SymbolIsNotAnObject, $"Symbol '{token}' is not an object."); + + public static MdDomMsg UnknownChartType(string name) + => new(MdDomMsgId.UnknownChartType, $"Unknown chart type: '{name}'."); + + public static MdDomMsg NoAccess(string name) + => new(MdDomMsgId.NoAccess, $"Access denied: '{name}' for internal use only."); + + public static MdDomMsg NewlineInString + => new(MdDomMsgId.NewlineInString, "Newline in string not allowed."); + + public static MdDomMsg EscapeSequenceNotAllowed(string token) + => new(MdDomMsgId.EscapeSequenceNotAllowed, $"Invalid escape sequence '{token}'."); + + public static MdDomMsg NullAssignmentNotSupported(string name) + => new(MdDomMsgId.NullAssignmentNotSupported, $"Assigning 'null' to '{name}' not allowed."); + + public static MdDomMsg OutOfRange(string range) + => new(MdDomMsgId.OutOfRange, $"Valid range only within '{range}'."); + + public static MdDomMsg UseOfUndefinedBaseStyle(string styleName) + => new(MdDomMsgId.UseOfUndefinedBaseStyle, $"Use of undefined base style '{styleName}'."); + + public static MdDomMsg UseOfUndefinedStyle(string styleName) + => new(MdDomMsgId.UseOfUndefinedStyle, $"Use of undefined style '{styleName}'."); + + #endregion + } +} diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Paragraph.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Paragraph.cs index 34439bb9..2f4fb728 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Paragraph.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Paragraph.cs @@ -486,7 +486,7 @@ internal override void Serialize(Serializer serializer) int startIdx = 0; List paragraphs = new List(); - for (int idx = 0; idx < Elements.Count; ++idx) + for (int idx = 0; idx < Elements.Count; idx++) { var element = Elements[idx]; if (element is Character) @@ -530,7 +530,7 @@ ParagraphElements SubsetElements(int startIdx, int endIdx) var paragraphElements = new ParagraphElements(); if (Values.Elements is not null) { - for (int idx = startIdx; idx <= endIdx; ++idx) + for (int idx = startIdx; idx <= endIdx; idx++) paragraphElements.Add((DocumentObject)Values.Elements[idx]!.Clone()); // BUG??? "!" added. } return paragraphElements; diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs index 33329c56..bd650f1b 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/ParagraphElements.cs @@ -483,7 +483,7 @@ public override void Add(DocumentObject? docObj) internal override void Serialize(Serializer serializer) { int count = Count; - for (int index = 0; index < count; ++index) + for (int index = 0; index < count; index++) { DocumentObject element = this[index]!; element.Serialize(serializer); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Sections.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Sections.cs index ea44aded..942f9104 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Sections.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Sections.cs @@ -29,7 +29,8 @@ internal Sections(DocumentObject parent) : base(parent) /// /// Gets a section by its index. First section has index 0. /// - public new Section this[int index] => (base[index] as Section)!; // HACK // BUG: May return null TODO: Section? Exception? + //public new Section this[int index] => (base[index] as Section)!; // H/ACK // BUG: May return null TODO: Section? Exception? + public new Section this[int index] => (base[index] as Section) ?? throw new InvalidOperationException("DocumentObject is not a Section."); /// /// Creates a deep copy of this object. @@ -53,7 +54,7 @@ public Section AddSection() internal override void Serialize(Serializer serializer) { int count = Count; - for (int index = 0; index < count; ++index) + for (int index = 0; index < count; index++) { var section = this[index]; section.Serialize(serializer); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Style.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Style.cs index 6f47c99d..214c7e8e 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Style.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Style.cs @@ -69,7 +69,7 @@ protected override object DeepCopy() if (name == null) throw new ArgumentNullException(nameof(name)); if (name == "") - throw new ArgumentException("name"); + throw new ArgumentException(nameof(name)); if (name.ToLower().StartsWith("font", StringComparison.Ordinal)) return ParagraphFormat.GetValue(name); @@ -132,7 +132,7 @@ public string BaseStyle set { if (value == null || value == "" && !String.IsNullOrEmpty(Values.BaseStyle)) - throw new ArgumentException(DomSR.EmptyBaseStyle); + throw new ArgumentException(MdDomMsgs.EmptyBaseStyle.Message); // Self assignment is allowed. Treat null like "". if (value == "" && String.IsNullOrEmpty(Values.BaseStyle)) // BUG??? diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Styles.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Styles.cs index 1abecad9..0136f8d6 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Styles.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Styles.cs @@ -47,7 +47,7 @@ public Style? this[string? styleName] { int count = Count; // index starts from 1; DefaultParagraphFont cannot be modified. - for (int index = 1; index < count; ++index) + for (int index = 1; index < count; index++) { var style = this[index]; if (String.Compare(style.Name, styleName, StringComparison.OrdinalIgnoreCase) == 0) @@ -75,7 +75,7 @@ public int GetIndex(string styleName) throw new ArgumentNullException(nameof(styleName)); int count = Count; - for (int index = 0; index < count; ++index) + for (int index = 0; index < count; index++) { var style = this[index]; if (String.Compare(style.Name, styleName, StringComparison.OrdinalIgnoreCase) == 0) @@ -114,14 +114,12 @@ public override void Add(DocumentObject? value) throw new ArgumentNullException(nameof(value)); if (value is not Style style) - //throw new InvalidOperationException(DomSR.StyleExpected); throw TH.ArgumentException_StyleExpected(value.GetType()); bool isRootStyle = style.IsRootStyle; if (style.BaseStyle == "" && !isRootStyle) - //throw new ArgumentException(DomSR.UndefinedBaseStyle(style.BaseStyle)); - throw TH.ArgumentException_UndefinedBaseStyle(style.BaseStyle); + throw TH.ArgumentException_UndefinedBaseStyle(style.Name); Style? baseStyle = null; int styleIndex = GetIndex(style.BaseStyle); @@ -129,8 +127,7 @@ public override void Add(DocumentObject? value) if (styleIndex != -1) baseStyle = this[styleIndex]; else if (!isRootStyle) - //throw new ArgumentException(DomSR.UndefinedBaseStyle(style.BaseStyle)); - throw TH.ArgumentException_UndefinedBaseStyle(style.BaseStyle); + throw TH.ArgumentException_UndefinedBaseStyle(style.Name); if (baseStyle != null) style.Values.StyleType = baseStyle.Type; diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStops.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStops.cs index 20ea7924..78063020 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStops.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/TabStops.cs @@ -47,9 +47,7 @@ internal TabStops(DocumentObject parent) : base(parent) /// Gets a TabStop by its index. /// public new TabStop this[int index] -#nullable disable => (base[index] as TabStop)!; // HACK // BUG: May return null TODO: TabStop? Exception? -#nullable restore /// /// Gets a TabStop by its position. Returns null if no matching tab stop can be found. diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Unit.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Unit.cs index bbfc41ef..c5d27904 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Unit.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/Unit.cs @@ -25,7 +25,7 @@ public Unit(double point) public Unit(double value, UnitType type) { if (!Enum.IsDefined(typeof(UnitType), type)) - throw new /*InvalidEnum*/ArgumentException(DomSR.InvalidEnumValue(type), nameof(type)); + throw new /*InvalidEnum*/ArgumentException(MdDomMsgs.InvalidEnumValue(type).Message, nameof(type)); _value = (float)value; _type = type; @@ -460,22 +460,14 @@ public static implicit operator Unit(string? value) unit._value = 1; try { -#if NET6_0_OR_GREATER || true unit._value = float.Parse(value[..valLen].Trim(), CultureInfo.InvariantCulture); -#else - unit._value = float.Parse(value.Substring(0, valLen).Trim(), CultureInfo.InvariantCulture); -#endif } catch (FormatException ex) { - throw new ArgumentException(DomSR.InvalidUnitValue(value), ex); + throw new ArgumentException(MdDomMsgs.InvalidUnitValue(value).Message, ex); } -#if NET6_0_OR_GREATER || true var typeStr = value[valLen..].Trim().ToLower(); -#else - var typeStr = value.Substring(valLen).Trim().ToLower(); -#endif unit._type = UnitType.Point; switch (typeStr) { @@ -501,7 +493,7 @@ public static implicit operator Unit(string? value) break; default: - throw new ArgumentException(DomSR.InvalidUnitType(typeStr)); + throw new ArgumentException(MdDomMsgs.InvalidUnitType(typeStr).Message); } return unit; @@ -555,7 +547,7 @@ public static implicit operator float(Unit value) => (float)value.Point; /// - /// Memberwise comparison checking exact value und unit. + /// Memberwise comparison checking exact value and unit. /// To compare by value tolerating rounding errors, use IsSameValue() or code like Math.Abs(a.Point - b.Point) < 1e-5. /// public static bool operator ==(Unit l, Unit r) @@ -567,7 +559,7 @@ public static implicit operator float(Unit value) } /// - /// Memberwise comparison checking exact value und unit. + /// Memberwise comparison checking exact value and unit. /// To compare by value tolerating rounding errors, use IsSameValue() or code like Math.Abs(a.Point - b.Point) < 1e-5. /// public static bool operator ==(Unit? l, Unit? r) @@ -582,14 +574,14 @@ public static implicit operator float(Unit value) } /// - /// Memberwise comparison checking exact value und unit. + /// Memberwise comparison checking exact value and unit. /// To compare by value tolerating rounding errors, use code like Math.Abs(a.Point - b.Point) < 1e-5. /// public static bool operator !=(Unit l, Unit r) => !(l == r); /// - /// Memberwise comparison checking exact value und unit. + /// Memberwise comparison checking exact value and unit. /// To compare by value tolerating rounding errors, use code like Math.Abs(a.Point - b.Point) < 1e-5. /// public static bool operator !=(Unit? l, Unit? r) @@ -634,7 +626,7 @@ public static implicit operator float(Unit value) /// Compares two Unit? values. /// public static bool operator <=(Unit? l, Unit? r) => Compare(l, r) <= 0; - + /// /// Returns the negative value of a Unit. /// @@ -839,7 +831,7 @@ public void ConvertType(UnitType type) default: if (!Enum.IsDefined(typeof(UnitType), type)) - throw new ArgumentException(DomSR.InvalidUnitType(type.ToString())); + throw new ArgumentException(MdDomMsgs.InvalidUnitType(type.ToString()).Message); // Remember missing unit type. Debug.Assert(false, "Missing unit type."); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/DomMsgID.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/MdDomMsgId.cs similarity index 91% rename from src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/DomMsgID.cs rename to src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/MdDomMsgId.cs index cd262992..2cded80d 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/DomMsgID.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/DocumentObjectModel/enums/MdDomMsgId.cs @@ -1,15 +1,23 @@ // MigraDoc - Creating Documents on the Fly // See the LICENSE file in the solution root for more information. +using PdfSharp.Internal; + namespace MigraDoc.DocumentObjectModel { /// + /// MigraDoc DOM message ID. /// Represents IDs for error and diagnostic messages generated by the MigraDoc DOM. /// - enum DomMsgID + enum MdDomMsgId { + None = 0, + + Success = 100, + // ----- General Messages --------------------------------------------------------------------- - StyleExpected, + + StyleExpected = MessageIdOffset.MdDom, BaseStyleRequired, EmptyBaseStyle, InvalidFieldFormat, @@ -29,8 +37,6 @@ enum DomMsgID // ----- DdlReader Messages ------------------------------------------------------------------- - Success = 1000, - SymbolExpected, SymbolsExpected, OperatorExpected, @@ -46,14 +52,14 @@ enum DomMsgID UnexpectedSymbol, IdentifierExpected, - BoolExpected, - RealExpected, - IntegerExpected, + BoolValueExpected, + RealValueExpected, + IntegerValueExpected, // IntegerOrIdentifierExpected, - StringExpected, - NullExpected, + StringValueExpected, + NullValueExpected, // SymbolExpected, - NumberExpected, + NumberValueExpected, InvalidEnum, // InvalidFlag, diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/MigraDoc.DocumentObjectModel.csproj b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/MigraDoc.DocumentObjectModel.csproj index 36998c91..b97949f3 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/MigraDoc.DocumentObjectModel.csproj +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/MigraDoc.DocumentObjectModel.csproj @@ -1,7 +1,7 @@  - net6.0;netstandard2.0;net472 + net6.0;net8.0;net462;netstandard2.0 MigraDoc True ..\..\..\..\..\StrongnameKey.snk @@ -15,11 +15,11 @@ ; - + 0 - + 0 @@ -31,25 +31,12 @@ 0 - - - - - - - - - - - - - + + diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/MigraDocProductVersionInformation.cs b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/MigraDocProductVersionInformation.cs index afbb915f..c7420d9d 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/MigraDocProductVersionInformation.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/Properties/MigraDocProductVersionInformation.cs @@ -1,6 +1,8 @@ // MigraDoc - Creating Documents on the Fly // See the LICENSE file in the solution root for more information. +#pragma warning disable 0436 + namespace MigraDoc { /// diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/README.md b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/README.md index 6b9465ea..d13aed35 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/README.md +++ b/src/foundation/src/MigraDoc/src/MigraDoc.DocumentObjectModel/README.md @@ -1 +1,7 @@ # MigraDoc.DocumentObjectModel + +One single build with all target frameworks: + +```xml +net6.0;net8.0;net472;netstandard2.0 +``` diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-gdi/MigraDoc.Rendering-gdi.csproj b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-gdi/MigraDoc.Rendering-gdi.csproj index 8374f22b..ba85e789 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-gdi/MigraDoc.Rendering-gdi.csproj +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-gdi/MigraDoc.Rendering-gdi.csproj @@ -1,44 +1,119 @@  - - net6.0-windows;net472 - true - MigraDoc - true - - GDI - True - ..\..\..\..\..\StrongnameKey.snk - + + net6.0-windows;net8.0-windows;net462 + true + MigraDoc + true + + GDI + True + ..\..\..\..\..\StrongnameKey.snk + - - true - + + true + - - 0 - + + 0 + - - 0 - + + 0 + - - - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + --> + + + + - - - - - + + + + + + + diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-gdi/README.md b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-gdi/README.md index 4b86626c..13ac4563 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-gdi/README.md +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-gdi/README.md @@ -1 +1,3 @@ # MigraDoc.Rendering-gdi + +PDF Rendering GDI build. diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-wpf/MigraDoc.Rendering-wpf.csproj b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-wpf/MigraDoc.Rendering-wpf.csproj index 23219d9d..0f9d85e1 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-wpf/MigraDoc.Rendering-wpf.csproj +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-wpf/MigraDoc.Rendering-wpf.csproj @@ -1,257 +1,136 @@  - - net6.0-windows;net472 - true - MigraDoc - true - - WPF - True - ..\..\..\..\..\StrongnameKey.snk - + + net6.0-windows;net8.0-windows;net462 + true + MigraDoc + true + + WPF + True + ..\..\..\..\..\StrongnameKey.snk + - - true - + + true + - - 0 - + + 0 + - - 0 - + + 0 + - - - + + + - - - Properties\GlobalDeclarations.cs - - - Rendering.Resources\Messages2.cs - - - Properties\VersionInfo.cs - - - Rendering.ChartMapper\AxisMapper.cs - - - Rendering.ChartMapper\ChartMapper.cs - - - Rendering.ChartMapper\DataLabelMapper.cs - - - Rendering.ChartMapper\FillFormatMapper.cs - - - Rendering.ChartMapper\FontMapper.cs - - - Rendering.ChartMapper\LegendMapper.cs - - - Rendering.ChartMapper\LineFormatMapper.cs - - - Rendering.ChartMapper\PlotAreaMapper.cs - - - Rendering.ChartMapper\SeriesCollectionMapper.cs - - - Rendering.ChartMapper\XValuesMapper.cs - - - Rendering.Extensions\UnitConversions.cs - - - - - - - Rendering\BordersRenderer.cs - - - Rendering\ChartFormatInfo.cs - - - Rendering\ChartRenderer.cs - - - Rendering\ChartRenderInfo.cs - - - Rendering\ColorHelper.cs - - - Rendering\DocumentRenderer.cs - - - Rendering\enums\ElementAlignment.cs - - - Rendering\enums\Floating.cs - - - Rendering\enums\HorizontalReference.cs - - - Rendering\enums\ImageFailure.cs - - - Rendering\enums\PageRenderOptions.cs - - - Rendering\enums\VerticalReference.cs - - - Rendering\FieldInfos.cs - - - Rendering\FillFormatRenderer.cs - - - Rendering\FontHandler.cs - - - Rendering\FormatInfo.cs - - - Rendering\FormattedCell.cs - - - Rendering\FormattedDocument.cs - - - Rendering\FormattedHeaderFooter.cs - - - Rendering\FormattedTextArea.cs - - - Rendering\FormattedTextFrame.cs - - - Rendering\IAreaProvider.cs - - - Rendering\ImageFormatInfo.cs - - - Rendering\ImageRenderer.cs - - - Rendering\ImageRenderInfo.cs - - - Rendering\LayoutInfo.cs - - - Rendering\LineFormatRenderer.cs - - - - Rendering\NumberFormatter.cs - - - Rendering\PageBreakFormatInfo.cs - - - Rendering\PageBreakRenderer.cs - - - Rendering\PageBreakRenderInfo.cs - - - Rendering\PageInfo.cs - - - Rendering\ParagraphFormatInfo.cs - - - Rendering\ParagraphIterator.cs - - - Rendering\ParagraphRenderer.cs - - - Rendering\ParagraphRenderInfo.cs - - - Rendering\PdfDocumentRenderer.cs - - - - Rendering\Renderer.cs - - - Rendering\RenderInfo.cs - - - Rendering\ShadingRenderer.cs - - - Rendering\ShapeFormatInfo.cs - - - Rendering\ShapeRenderer.cs - - - Rendering\ShapeRenderInfo.cs - - - Rendering\TableFormatInfo.cs - - - Rendering\TableRenderer.cs - - - Rendering\TableRenderInfo.cs - - - Rendering\TextFrameFormatInfo.cs - - - Rendering\TextFrameRenderer.cs - - - Rendering\TextFrameRenderInfo.cs - - - Rendering\TopDownFormatter.cs - - - - - MSBuild:Compile - - - - - Rendering.Resources\Messages.de.restext - - - Rendering.Resources\Messages.restext - - - StrongnameKey.snk - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + MSBuild:Compile + + + + + + + + + + + + diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-wpf/README.md b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-wpf/README.md index 69bd0c5e..3831d7d2 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-wpf/README.md +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering-wpf/README.md @@ -1 +1,3 @@ # MigraDoc.Rendering-wpf + +PDF Rendering WPF build. \ No newline at end of file diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/MigraDoc.Rendering.csproj b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/MigraDoc.Rendering.csproj index 1a7583d7..ef218854 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/MigraDoc.Rendering.csproj +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/MigraDoc.Rendering.csproj @@ -1,7 +1,7 @@  - net6.0;netstandard2.0 + net6.0;net8.0;netstandard2.0 MigraDoc True ..\..\..\..\..\StrongnameKey.snk @@ -11,6 +11,14 @@ true + + 0 + + + + 0 + + 0 @@ -36,19 +44,24 @@ - - + + + + + - - + + Designer + + + Designer + - - - + diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Properties/VersionInfo.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Properties/VersionInfo.cs deleted file mode 100644 index f088a920..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Properties/VersionInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -// MigraDoc - Creating Documents on the Fly -// See the LICENSE file in the solution root for more information. - -namespace MigraDoc.Rendering -{ - using MigraDoc; - - //class VersionInfo - //{ - // public const string Title = "MigraDoc.Rendering.dll"; - // public const string Description = ""; - // public const string Version = ProductVersionInfo.Version; - // public static readonly string Creator = ProductVersionInfo.Creator; - // public const string Company = ProductVersionInfo.Company; - // public const string Product = ProductVersionInfo.Product; - // public const string Copyright = ProductVersionInfo.Copyright; - // public const string Trademark = ProductVersionInfo.Trademark; - // public const string Culture = ""; - //} -} \ No newline at end of file diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/README.md b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/README.md index f81db0de..f6e89d46 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/README.md +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/README.md @@ -1 +1,3 @@ # MigraDoc.Rendering + +PDF Rendering CORE build. diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages.de.restext b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages.de.restext deleted file mode 100644 index 159e02fe..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages.de.restext +++ /dev/null @@ -1,21 +0,0 @@ -; // MigraDoc - Creating Documents on the Fly -; // See the LICENSE file in the solution root for more information. - -; ----- German (de) Messages --------------------------------------------------- -; Messages for German language -; that differ from the default messages. -; ------------------------------------------------------------------------------ - -PropertyNotSetBefore = '{0}' muss vor dem Aufruf von '{1}' gesetzt werden. -BookmarkNotDefined = Lesezeichen '{0}' ist innerhalb des Dokuments nicht definiert. -ImageNotFound = Bild '{0}' nicht gefunden. -InvalidImageType = Ungültiger Bildtyp: '{0}'. -ImageNotReadable = Bild '{0}' konnte nicht eingelesen werden. Es trat eine Ausnahme mit der folgenden Meldung auf:\n{1} -EmptyImageSize = Ihre Benutzereingaben führten zu einem leeren Bildbereich. -ObjectNotRenderable = Nur Bilder, Textrahmen, Diagramme und Absätze können frei gerendert werden. -NumberTooLargeForRoman = Die Zahl {0} ist zu groß für eine Darstellung in römischen Ziffern. -NumberTooLargeForLetters = Die Zahl {0} ist zu groß für eine Darstellung in Buchstaben. -DisplayEmptyImageSize = Leerer Bildbereich. -DisplayImageFileNotFound = Bild nicht gefunden. -DisplayInvalidImageType = Ungültiger Bildtyp. -DisplayImageNotRead = Bild nicht eingelesen. \ No newline at end of file diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages.restext b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages.restext deleted file mode 100644 index fa9cd39f..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages.restext +++ /dev/null @@ -1,16 +0,0 @@ -; // MigraDoc - Creating Documents on the Fly -; // See the LICENSE file in the solution root for more information. - -PropertyNotSetBefore = '{0}' must be set before calling '{1}'. -BookmarkNotDefined = Bookmark '{0}' is not defined within the document. -ImageNotFound = Image '{0}' not found. -InvalidImageType = Invalid image type: '{0}'. -ImageNotReadable = Image {0} could not be read.\n Inner exception: {1} -EmptyImageSize = The specified image size is empty. -ObjectNotRenderable = Only images, textframes, charts and paragraphs can be rendered freely. -NumberTooLargeForRoman = The number {0} is to large to be displayed as roman. -NumberTooLargeForLetters = The number {0} is to large to be displayed as letters. -DisplayEmptyImageSize = Image has empty size. -DisplayImageFileNotFound = Image not found. -DisplayInvalidImageType = Image has no valid type. -DisplayImageNotRead = Image could not be read. diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages2.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages2.cs deleted file mode 100644 index 92d923de..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages2.cs +++ /dev/null @@ -1,128 +0,0 @@ -// MigraDoc - Creating Documents on the Fly -// See the LICENSE file in the solution root for more information. - -using System.Resources; -using System.Reflection; -#if DEBUG -using System.Text.RegularExpressions; -#endif - -namespace MigraDoc.Rendering.Resources -{ - /// - /// Provides diagnostic messages taken from the resources. - /// - static class Messages2 - { - internal static string NumberTooLargeForRoman(int number) - { - return FormatMessage(IDs.NumberTooLargeForRoman, number); - } - - internal static string NumberTooLargeForLetters(int number) - { - return FormatMessage(IDs.NumberTooLargeForLetters, number); - } - - internal static string DisplayEmptyImageSize - => FormatMessage(IDs.DisplayEmptyImageSize); - - internal static string DisplayImageFileNotFound - => FormatMessage(IDs.DisplayImageFileNotFound); - - internal static string DisplayInvalidImageType => FormatMessage(IDs.DisplayInvalidImageType); - - internal static string DisplayImageNotRead => FormatMessage(IDs.DisplayImageNotRead); - - internal static string PropertyNotSetBefore(string propertyName, string functionName) - { - return FormatMessage(IDs.PropertyNotSetBefore, propertyName, functionName); - } - - internal static string BookmarkNotDefined(string bookmarkName) - { - return FormatMessage(IDs.BookmarkNotDefined, bookmarkName); - } - - internal static string ImageNotFound(string imageName) - { - return FormatMessage(IDs.ImageNotFound, imageName); - } - - internal static string InvalidImageType(string type) - { - return FormatMessage(IDs.InvalidImageType, type); - } - - internal static string ImageNotReadable(string imageName, string innerException) - { - return FormatMessage(IDs.ImageNotReadable, imageName, innerException); - } - - internal static string EmptyImageSize => FormatMessage(IDs.EmptyImageSize); - - internal static string ObjectNotRenderable => FormatMessage(IDs.ObjectNotRenderable); - - // ReSharper disable InconsistentNaming - enum IDs - { - PropertyNotSetBefore, - BookmarkNotDefined, - ImageNotFound, - InvalidImageType, - ImageNotReadable, - EmptyImageSize, - ObjectNotRenderable, - NumberTooLargeForRoman, - NumberTooLargeForLetters, - DisplayEmptyImageSize, - DisplayImageFileNotFound, - DisplayInvalidImageType, - DisplayImageNotRead - } - // ReSharper restore InconsistentNaming - - static ResourceManager ResourceManager - { - // ReSharper disable ConvertIfStatementToNullCoalescingExpression - get - { - if (_resourceManager == null) - _resourceManager = new ResourceManager("MigraDoc.Rendering.Resources.Messages", Assembly.GetExecutingAssembly()); - - return _resourceManager; - } - // ReSharper restore ConvertIfStatementToNullCoalescingExpression - } - - static ResourceManager? _resourceManager; - - static string FormatMessage(IDs id, params object[] args) - { - string? message; - try - { - message = ResourceManager.GetString(id.ToString()); - if (message != null) - { -#if DEBUG - if (Regex.Matches(message, @"\{[0-9]\}").Count > args.Length) - { - //TODO too many placeholders or too few args... - } -#endif - message = String.Format(message, args); - } - else - message = "<<>>"; - return message; - } - catch (Exception /*ex*/) - { - //message = "INTERNAL ERROR while formatting error message: " + ex; - message = "INTERNAL ERROR while formatting error message: " + id; - } - return message; - } - } -} diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.UnitTest/TestLayout.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.UnitTest/TestLayout.cs index 12fd9247..26d9cd35 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.UnitTest/TestLayout.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.UnitTest/TestLayout.cs @@ -50,7 +50,7 @@ public static void A1000Paragraphs(string outputFile) sec.PageSetup.TopMargin = 0; sec.PageSetup.BottomMargin = 0; - for (int idx = 1; idx <= 1000; ++idx) + for (int idx = 1; idx <= 1000; idx++) { var par = sec.AddParagraph(); par.AddText("Paragraph " + idx + ": "); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.UnitTest/TestParagraphRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.UnitTest/TestParagraphRenderer.cs index 866ab957..14b32b1f 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.UnitTest/TestParagraphRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.UnitTest/TestParagraphRenderer.cs @@ -18,7 +18,7 @@ public static void TextAndBlanks(string pdfOutputFile) var document = new Document(); var section = document.AddSection(); var par = section.AddParagraph("Dies"); - for (int idx = 0; idx <= 40; ++idx) + for (int idx = 0; idx <= 40; idx++) { par.AddCharacter(SymbolName.Blank); par.AddText(idx.ToString()); @@ -48,7 +48,7 @@ public static void Formatted(string pdfOutputFile) internal static void FillFormattedParagraph(Paragraph par) { - for (int idx = 0; idx <= 140; ++idx) + for (int idx = 0; idx <= 140; idx++) { if (idx < 60) { diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Windows/DocumentPreview.xaml.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Windows/DocumentPreview.xaml.cs index 8ff31853..1c1e5541 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Windows/DocumentPreview.xaml.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Windows/DocumentPreview.xaml.cs @@ -261,7 +261,7 @@ public void SetDocument(Document document, RenderEvents renderEvents) Document = document; RenderEvents = renderEvents; - Renderer = new DocumentRenderer(Document); + Renderer = new(Document); Renderer.PrepareDocument(RenderEvents); Page = 1; //this.preview.Invalidate(); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/BordersRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/BordersRenderer.cs index 10445f20..c52afe12 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/BordersRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/BordersRenderer.cs @@ -237,11 +237,11 @@ internal void RenderRounded(RoundedCorner roundedCorner, XUnitPt x, XUnitPt y, X break; case BorderStyle.DashLargeGap: - pen.DashPattern = new double[] { 3, 3 }; + pen.DashPattern = [3, 3]; break; case BorderStyle.DashSmallGap: - pen.DashPattern = new double[] { 5, 1 }; + pen.DashPattern = [5, 1]; break; case BorderStyle.Dot: diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/DocumentRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/DocumentRenderer.cs index 4d70a68f..ccd409ae 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/DocumentRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/DocumentRenderer.cs @@ -3,14 +3,13 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using PdfSharp.Events; using PdfSharp.Pdf; using PdfSharp.Drawing; using MigraDoc.DocumentObjectModel; using MigraDoc.DocumentObjectModel.Visitors; using MigraDoc.DocumentObjectModel.Shapes; using MigraDoc.DocumentObjectModel.Tables; -using MigraDoc.Rendering.Resources; -using PdfSharp.Events; namespace MigraDoc.Rendering { @@ -158,9 +157,10 @@ public void RenderObject(XGraphics graphics, XUnitPt xPosition, XUnitPt yPositio if (documentObject == null) throw new ArgumentNullException(nameof(documentObject)); - if (documentObject is not Shape && documentObject is not Table && + if (documentObject is not Shape && + documentObject is not Table && documentObject is not Paragraph) - throw new ArgumentException(Messages2.ObjectNotRenderable, nameof(documentObject)); + throw new ArgumentException(MdPdfMsgs.ObjectNotRenderable(documentObject.GetType().Name).Message); var renderer = Renderer.Create(graphics, this, documentObject, null); renderer!.Format(new Rectangle(xPosition, yPosition, width, double.MaxValue), null); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageRenderer.cs index e299b2b5..f981cab7 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ImageRenderer.cs @@ -5,7 +5,6 @@ using Microsoft.Extensions.Logging; using PdfSharp.Drawing; using MigraDoc.DocumentObjectModel.Shapes; -using MigraDoc.Rendering.Resources; using MigraDoc.DocumentObjectModel; using MigraDoc.Logging; @@ -38,7 +37,7 @@ internal override void Format(Area area, FormatInfo? previousFormatInfo) !XImage.ExistsFile(_imageFilePath)) { _failure = ImageFailure.FileNotFound; - MigraDocLogHost.PdfRenderingLogger.LogWarning(Messages2.ImageNotFound(_image.Name)); + MigraDocLogHost.PdfRenderingLogger.LogWarning(MdPdfMsgs.ImageNotFound(_image.Name).Message); //Debug.WriteLine(Messages2.ImageNotFound(_image.Name), "warning"); } ImageFormatInfo formatInfo = (ImageFormatInfo)_renderInfo.FormatInfo; @@ -110,20 +109,20 @@ void RenderFailureImage(XRect destRect) switch (formatInfo.Failure) { case ImageFailure.EmptySize: - failureString = Messages2.DisplayEmptyImageSize; + failureString = MdPdfMsgs.DisplayEmptyImageSize.Message; break; case ImageFailure.FileNotFound: - failureString = Messages2.DisplayImageFileNotFound; + failureString = MdPdfMsgs.DisplayImageFileNotFound("???").Message; break; case ImageFailure.InvalidType: - failureString = Messages2.DisplayInvalidImageType; + failureString = MdPdfMsgs.DisplayInvalidImageType.Message; break; case ImageFailure.NotRead: default: - failureString = Messages2.DisplayImageNotRead; + failureString = MdPdfMsgs.DisplayImageNotRead.Message; break; } @@ -147,7 +146,7 @@ void CalculateImageDimensions() catch (InvalidOperationException ex) { //Debug.WriteLine(Messages2.InvalidImageType(ex.Message)); - MigraDocLogHost.DocumentModelLogger.LogError(Messages2.InvalidImageType(ex.Message)); + MigraDocLogHost.DocumentModelLogger.LogError(MdPdfMsgs.InvalidImageType(ex.Message).Message); formatInfo.Failure = ImageFailure.InvalidType; } @@ -281,7 +280,7 @@ void CalculateImageDimensions() formatInfo.Width = XUnitPt.FromCentimeter(2.5); formatInfo.Height = XUnitPt.FromCentimeter(2.5); //Debug.WriteLine(Messages2.EmptyImageSize); - MigraDocLogHost.PdfRenderingLogger.LogError(Messages2.EmptyImageSize); + MigraDocLogHost.PdfRenderingLogger.LogError(MdPdfMsgs.EmptyImageSize.Message); _failure = ImageFailure.EmptySize; } else @@ -293,7 +292,7 @@ void CalculateImageDimensions() catch (Exception ex) { //Debug.WriteLine(Messages2.ImageNotReadable(_image.Name, ex.Message)); - MigraDocLogHost.PdfRenderingLogger.LogError(Messages2.ImageNotReadable(_image.Name, ex.Message)); + MigraDocLogHost.PdfRenderingLogger.LogError(MdPdfMsgs.ImageNotReadable(_image.Name, ex.Message).Message); formatInfo.Failure = ImageFailure.NotRead; } finally diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsg.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsg.cs new file mode 100644 index 00000000..4ed0508f --- /dev/null +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsg.cs @@ -0,0 +1,21 @@ +// MigraDoc - Creating Documents on the Fly +// See the LICENSE file in the solution root for more information. + +using Microsoft.Extensions.Logging; + +namespace MigraDoc.Rendering +{ + /// + /// MigraDoc PDF renderer message. + /// + readonly struct MdPdfMsg(MdPdfMsgId id, string message) + { + public MdPdfMsgId Id { get; init; } = id; + + public string Message { get; init; } = message; + + public EventId EventId => new((int)Id, EventName); + + public string EventName => Id.ToString(); + } +} diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages2.de.resx b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsg.de.resx similarity index 100% rename from src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages2.de.resx rename to src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsg.de.resx diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages2.resx b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsg.resx similarity index 100% rename from src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering.Resources/Messages2.resx rename to src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsg.resx diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsgs.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsgs.cs new file mode 100644 index 00000000..dd207cc1 --- /dev/null +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsgs.cs @@ -0,0 +1,78 @@ +// MigraDoc - Creating Documents on the Fly +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Internal; + +namespace MigraDoc.Rendering +{ + /// + /// MigraDoc PDF renderer message id. + /// + // ReSharper disable InconsistentNaming + enum MdPdfMsgId + { + PropertyNotSetBefore = MessageIdOffset.MdPdf, + BookmarkNotDefined, + ImageNotFound, + InvalidImageType, + ImageNotReadable, + EmptyImageSize, + ObjectNotRenderable, + NumberTooLargeForRoman, + NumberTooLargeForLetters, + DisplayEmptyImageSize, + DisplayImageFileNotFound, + DisplayInvalidImageType, + DisplayImageNotRead + } + + // ReSharper restore InconsistentNaming + + /// + /// MigraDoc PDF renderer messages. + /// Provides diagnostic messages taken from the resources. + /// + // ReSharper disable once IdentifierTypo + static class MdPdfMsgs + { + internal static MdPdfMsg NumberTooLargeForRoman(int number) + => new(MdPdfMsgId.NumberTooLargeForRoman, Invariant($"The number {number} is to large to be displayed as roman number.")); + + internal static MdPdfMsg NumberTooLargeForLetters(int number) + => new(MdPdfMsgId.NumberTooLargeForLetters, $"The number {number} is to large to be displayed as letters."); + + internal static MdPdfMsg DisplayEmptyImageSize + => new(MdPdfMsgId.DisplayEmptyImageSize, "Image has empty size."); + + internal static MdPdfMsg DisplayImageFileNotFound(string fileName) + => new(MdPdfMsgId.DisplayImageFileNotFound, $"Image '{fileName}' not found."); + + internal static MdPdfMsg DisplayInvalidImageType + => new(MdPdfMsgId.DisplayInvalidImageType, "Image has no valid type."); + + internal static MdPdfMsg DisplayImageNotRead + => new(MdPdfMsgId.DisplayImageNotRead, "Image could not be read."); + + internal static MdPdfMsg PropertyNotSetBefore(string propertyName, string functionName) + => new(MdPdfMsgId.PropertyNotSetBefore, $"'{propertyName}' must be set before calling '{functionName}'."); + + internal static MdPdfMsg BookmarkNotDefined(string bookmarkName) + => new(MdPdfMsgId.BookmarkNotDefined, $"Bookmark '{bookmarkName}' is not defined within the document."); + + internal static MdPdfMsg ImageNotFound(string imageName) + => new(MdPdfMsgId.ImageNotFound, $"Image '{imageName}' not found."); + + internal static MdPdfMsg InvalidImageType(string type) + => new(MdPdfMsgId.InvalidImageType, $"Invalid image type: '{type}'."); + + internal static MdPdfMsg ImageNotReadable(string imageName, string innerException) + => new(MdPdfMsgId.ImageNotReadable, + $"Image '{imageName}' could not be read.\\n Inner exception: {innerException}"); + + internal static MdPdfMsg EmptyImageSize + => new(MdPdfMsgId.EmptyImageSize, "The specified image size is empty."); + + internal static MdPdfMsg ObjectNotRenderable(string typeName) + => new(MdPdfMsgId.ObjectNotRenderable, "Only images, text-frames, charts and paragraphs can be rendered freely."); + } +} diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.de.resx b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsgs.de.resx similarity index 79% rename from src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.de.resx rename to src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsgs.de.resx index 18936e51..1b7707d9 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.de.resx +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MdPdfMsgs.de.resx @@ -2,16 +2,16 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The specified image size is empty. + + + Image not found. + + + Image could not be read. + + + The number {0} is to large to be displayed as letters. + + + Bookmark '{0}' is not defined within the document. + + + Invalid image type: '{0}'. + + + The number {0} is to large to be displayed as roman. + + + Image '{0}' not found. + + + '{0}' must be set before calling '{1}'. + + + Image has empty size. + + + Image has no valid type. + + + Only images, textframes, charts and paragraphs can be rendered freely. + + + Image {0} could not be read. + Inner exception: {1} + + \ No newline at end of file diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MigraDocRenderingBuildInformation.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MigraDocRenderingBuildInformation.cs index 809a3614..32e34786 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MigraDocRenderingBuildInformation.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/MigraDocRenderingBuildInformation.cs @@ -4,6 +4,8 @@ using System.Reflection; using System.Runtime.Versioning; +#pragma warning disable 0436 + namespace MigraDoc.Rendering { /// @@ -40,7 +42,7 @@ public static string TargetPlatform { get { - // Hack since TargetPlatformAttribute is not available. + // TargetPlatformAttribute is not available under .NET Framework. return "Unknown Target Platform"; } } @@ -53,7 +55,7 @@ public static string TargetPlatform get { var attribute = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(TargetPlatformAttribute), false); - return attribute.Length == 1 ? ((TargetPlatformAttribute)attribute[0]).PlatformName : ""; + return attribute.Length == 1 ? ((TargetPlatformAttribute)attribute[0]).PlatformName : "Unknown Target Platform"; } } #endif diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/NumberFormatter.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/NumberFormatter.cs index 8db1ddb9..89cdfc96 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/NumberFormatter.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/NumberFormatter.cs @@ -1,11 +1,9 @@ // MigraDoc - Creating Documents on the Fly // See the LICENSE file in the solution root for more information. -using System.Diagnostics; using System.Globalization; using Microsoft.Extensions.Logging; using MigraDoc.Logging; -using MigraDoc.Rendering.Resources; namespace MigraDoc.Rendering { @@ -30,7 +28,7 @@ static string AsRoman(int number, bool lowercase) { if (Math.Abs(number) > 32768) { - MigraDocLogHost.PdfRenderingLogger.LogWarning(Messages2.NumberTooLargeForRoman(number)); + MigraDocLogHost.PdfRenderingLogger.LogWarning(MdPdfMsgs.NumberTooLargeForRoman(number).Message); //Debug.WriteLine(Messages2.NumberTooLargeForRoman(number), "warning"); return number.ToString(CultureInfo.InvariantCulture); } @@ -45,18 +43,18 @@ static string AsRoman(int number, bool lowercase) string[] roman; if (lowercase) - roman = new[] { "m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i" }; + roman = ["m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i"]; else - roman = new[] { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" }; + roman = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]; - int[] numberValues = new int[] { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }; + int[] numberValues = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]; - for (int i = 0; i < numberValues.Length; ++i) + for (int idx = 0; idx < numberValues.Length; idx++) { - while (number >= numberValues[i]) + while (number >= numberValues[idx]) { - res += roman[i]; - number -= numberValues[i]; + res += roman[idx]; + number -= numberValues[idx]; } } return res; @@ -66,7 +64,7 @@ static string AsLetters(int number, bool lowercase) { if (Math.Abs(number) > 32768) { - MigraDocLogHost.PdfRenderingLogger.LogWarning(Messages2.NumberTooLargeForLetters(number)); + MigraDocLogHost.PdfRenderingLogger.LogWarning(MdPdfMsgs.NumberTooLargeForLetters(number).Message); //Debug.WriteLine(Messages2.NumberTooLargeForLetters(number)); return number.ToString(); } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphFormatInfo.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphFormatInfo.cs index 16973ae1..4e7efb65 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphFormatInfo.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphFormatInfo.cs @@ -65,11 +65,11 @@ internal void AddLineInfo(LineInfo lineInfo) internal int LineCount => _lineInfos.Count; - /// - /// - /// - /// - /// + // Fake docs is not allowed. + /////// + /////// + /////// + /////// internal void Append(FormatInfo mergeInfo) { ParagraphFormatInfo formatInfo = (ParagraphFormatInfo)mergeInfo; diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphIterator.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphIterator.cs index 08740f0a..4e61814d 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphIterator.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphIterator.cs @@ -173,7 +173,8 @@ DocumentObject GetNodeObject(DocumentObject obj) if (newIndex < 0) return null; - List indices = new(parIterator._positionIndices) { newIndex };//(Array_List)parIterator.positionIndices.Clone(); + //List indices = new(parIterator._positionIndices) { newIndex }; + List indices = [..parIterator._positionIndices, newIndex]; var obj = GetNodeObject(parEls[newIndex] ?? NRT.ThrowOnNull()); var iterator = new ParagraphIterator(_rootNode, obj, indices); @@ -275,13 +276,8 @@ int LastIndex { get { -#if NET6_0_OR_GREATER || true if (_positionIndices.Count != 0) return _positionIndices[^1]; -#else - if (_positionIndices.Count != 0) - return _positionIndices[_positionIndices.Count - 1]; -#endif return -1; } } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphRenderer.cs index 82c75958..a1b2c75b 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/ParagraphRenderer.cs @@ -5,12 +5,11 @@ using System.Text; using MigraDoc.DocumentObjectModel; using PdfSharp.Pdf; +using PdfSharp.Pdf.Advanced; using PdfSharp.Drawing; using MigraDoc.DocumentObjectModel.Fields; using MigraDoc.DocumentObjectModel.Shapes; using MigraDoc.Rendering.Extensions; -using MigraDoc.Rendering.Resources; -using PdfSharp.Pdf.Advanced; namespace MigraDoc.Rendering { @@ -113,7 +112,7 @@ internal override void Render() RenderBorders(); ParagraphFormatInfo parFormatInfo = (ParagraphFormatInfo)_renderInfo.FormatInfo; - for (int idx = 0; idx < parFormatInfo.LineCount; ++idx) + for (int idx = 0; idx < parFormatInfo.LineCount; idx++) { LineInfo lineInfo = parFormatInfo.GetLineInfo(idx); _isLastLine = (idx == parFormatInfo.LineCount - 1); @@ -147,7 +146,7 @@ string GetFieldValue(DocumentObject field) { if (_phase == Phase.Formatting) return "XX"; - return Messages2.BookmarkNotDefined(pageRefField.Name); + return MdPdfMsgs.BookmarkNotDefined(pageRefField.Name).Message; } } else if (field is SectionField) @@ -548,11 +547,7 @@ XUnitPt ProbeAfterDecimalAlignedTab(XUnitPt tabStopPosition, out bool notFitting } if (decimalPosIndex >= 0) -#if NET6_0_OR_GREATER || true word = word[..decimalPosIndex]; -#else - word = word.Substring(0, decimalPosIndex); -#endif XUnitPt wordLength = MeasureString(word); notFitting = _currentXPosition + wordLength >= _formattingArea.X + _formattingArea.Width + Tolerance; @@ -1039,7 +1034,7 @@ void RenderSymbol(Character character) { string sym = GetSymbol(character); string completeWord = sym; - for (int idx = 1; idx < character.Count; ++idx) + for (int idx = 1; idx < character.Count; idx++) completeWord += sym; RenderWord(completeWord); @@ -1627,7 +1622,6 @@ void SaveBlankWidth(XUnitPt blankWidth) /// Processes the elements when formatting. /// /// - /// FormatResult FormatElement(DocumentObject docObj) { // Check for available space in the area must be made for each element and explicitly for the last paragraph’s element, because in formatting phase, diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/PdfDocumentRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/PdfDocumentRenderer.cs index b4494567..38c0917a 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/PdfDocumentRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/PdfDocumentRenderer.cs @@ -3,11 +3,10 @@ using System.Diagnostics; using System.Reflection; -using MigraDoc.DocumentObjectModel; -using MigraDoc.Rendering.Internals; -using MigraDoc.Rendering.Resources; using PdfSharp.Pdf; using PdfSharp.Drawing; +using MigraDoc.DocumentObjectModel; +using MigraDoc.Rendering.Internals; namespace MigraDoc.Rendering { @@ -26,19 +25,19 @@ public PdfDocumentRenderer() /// Initializes a new instance of the class. /// /// If true Unicode encoding is used for all text. If false, WinAnsi encoding is used. - [Obsolete("Code is always unicode.")] + [Obsolete("Code is always Unicode.")] // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local public PdfDocumentRenderer(bool unicode) { if (unicode is false) - throw new ArgumentException("Text is always rendered as unicode."); + throw new ArgumentException("Text is always rendered as Unicode."); } /// /// Gets a value indicating whether the text is rendered as Unicode. /// Returns true because text is rendered always in unicode. /// - [Obsolete("Code is always unicode.")] + [Obsolete("Code is always Unicode.")] public bool Unicode => true; /// @@ -94,7 +93,7 @@ void PrepareDocumentRenderer() void PrepareDocumentRenderer(bool prepareCompletely) { if (_document == null) - throw new InvalidOperationException(Messages2.PropertyNotSetBefore("DocumentRenderer", MethodBase.GetCurrentMethod()!.Name)); + throw new InvalidOperationException(MdPdfMsgs.PropertyNotSetBefore(nameof(Document), MethodBase.GetCurrentMethod()!.Name).Message); _documentRenderer ??= new(_document) { @@ -204,6 +203,28 @@ public void RenderPages(int startPage, int endPage) pdfPage.Height = pageInfo.Height; pdfPage.Orientation = pageInfo.Orientation; +#if true_ + // Starting with 6.2.0, PDFsharp sometimes swaps width and height when setting the orientation. + // This code ensures that MigraDoc gets the Width and Height it asks for. + if (pageInfo.Orientation == PageOrientation.Portrait) + { + // Make sure page sizes are correct, but ignore pdfPage orientation here. + // Assign Width and Height again if they do not match. + if (pdfPage.Width.Point != pageInfo.Width) + pdfPage.Width = pageInfo.Width; + if (pdfPage.Height.Point != pageInfo.Height) + pdfPage.Height = pageInfo.Height; + } + else + { + // Assign Width to Height and vice versa if they do not match. + if (pdfPage.Width.Point != pageInfo.Height) + pdfPage.Width = pageInfo.Height; + if (pdfPage.Height.Point != pageInfo.Width) + pdfPage.Height = pageInfo.Width; + } +#endif + using var gfx = XGraphics.FromPdfPage(pdfPage); DocumentRenderer.RenderPage(gfx, pageNr); } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/TableRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/TableRenderer.cs index 7becf19e..c746eb5c 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/TableRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/TableRenderer.cs @@ -782,7 +782,7 @@ void CreateNextBottomBorderPosition(ref int skipIndex, ref int lastBorderRow) first = false; int cells = _mergedCells.Count; - for (int idx = skipIndex; idx < cells; ++idx) + for (int idx = skipIndex; idx < cells; idx++) { var cell = _mergedCells[idx]; @@ -884,7 +884,7 @@ Cell GetMinMergedCell(int row) var resultRowIndex = row; var resultRow = _table.Rows[resultRowIndex]; int clsCount = _table.Columns.Count; - for (int idx = 0; idx < clsCount; ++idx) + for (int idx = 0; idx < clsCount; idx++) { var cell = resultRow[idx]; if (resultRowIndex + cell.MergeDown == row) diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/TopDownFormatter.cs b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/TopDownFormatter.cs index 2d528cee..2ded913e 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/TopDownFormatter.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.Rendering/Rendering/TopDownFormatter.cs @@ -16,7 +16,6 @@ class TopDownFormatter /// /// The bottom margin of the previous element. /// The top margin of the next element. - /// XUnitPt MarginMax(XUnitPt prevBottomMargin, XUnitPt nextTopMargin) { if (prevBottomMargin >= 0 && nextTopMargin >= 0) @@ -91,7 +90,7 @@ public void FormatOnAreas(XGraphics gfx, bool topLevel) ready = idx == _elements.Count - 1; if (ready) _areaProvider.StoreRenderInfos(renderInfos); - ++idx; + idx++; continue; } /////////////////////////////////////////// @@ -152,7 +151,7 @@ public void FormatOnAreas(XGraphics gfx, bool topLevel) prevFormatInfo = null; prevRenderInfo = null; - ++idx; + idx++; } } else @@ -171,7 +170,7 @@ public void FormatOnAreas(XGraphics gfx, bool topLevel) ready = idx == _elements.Count - 1; - ++idx; + idx++; } prevRenderInfo = FinishPage(renderer.RenderInfo, pagebreakBefore, ref renderInfos); if (prevRenderInfo != null) @@ -283,7 +282,7 @@ bool NextElementsDoNotFit(int idx, Area remainingArea, XUnitPt previousMarginBot { XUnitPt elementDistance = previousMarginBottom; Area area = remainingArea; - for (int index = idx + 1; index < _elements.Count; ++index) + for (int index = idx + 1; index < _elements.Count; index++) { // Never combine more than MaxCombineElements elements if (index - idx > MaxCombineElements) diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-gdi/MigraDoc.RtfRendering-gdi.csproj b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-gdi/MigraDoc.RtfRendering-gdi.csproj index ce07a007..bfdc5e72 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-gdi/MigraDoc.RtfRendering-gdi.csproj +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-gdi/MigraDoc.RtfRendering-gdi.csproj @@ -1,6 +1,6 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true MigraDoc GDI @@ -14,172 +14,67 @@ true - + 0 - + 0 - - Properties\VersionInfo.cs - - - RtfRendering.Resources\Messages2.cs - - - RtfRendering\BookmarkFieldRenderer.cs - - - RtfRendering\BorderRenderer.cs - - - RtfRendering\BorderRendererBase.cs - - - RtfRendering\BordersRenderer.cs - - - RtfRendering\CellFormatRenderer.cs - - - RtfRendering\CellRenderer.cs - - - RtfRendering\CharacterRenderer.cs - - - RtfRendering\ChartRenderer.cs - - - RtfRendering\DateFieldRenderer.cs - - - RtfRendering\enums\RtfUnit.cs - - - RtfRendering\FieldRenderer.cs - - - RtfRendering\FontRenderer.cs - - - RtfRendering\FootnoteRenderer.cs - - - RtfRendering\FormattedTextRenderer.cs - - - RtfRendering\HeaderFooterRenderer.cs - - - RtfRendering\HeadersFootersRenderer.cs - - - RtfRendering\HyperlinkRenderer.cs - - - RtfRendering\ImageRenderer.cs - - - RtfRendering\InfoFieldRenderer.cs - - - RtfRendering\ListInfoOverrideRenderer.cs - - - RtfRendering\ListInfoRenderer.cs - - - RtfRendering\NumericFieldRendererBase.cs - - - RtfRendering\NumPagesFieldRenderer.cs - - - RtfRendering\PageBreakRenderer.cs - - - RtfRendering\PageFieldRenderer.cs - - - RtfRendering\PageRefFieldRenderer.cs - - - RtfRendering\PageSetupRenderer.cs - - - RtfRendering\ParagraphFormatRenderer.cs - - - RtfRendering\ParagraphRenderer.cs - - - RtfRendering\RendererBase.cs - - - RtfRendering\RendererFactory.cs - - - RtfRendering\RowRenderer.cs - - - RtfRendering\RowsRenderer.cs - - - RtfRendering\RtfDocumentRenderer.cs - - - RtfRendering\RtfWriter.cs - - - RtfRendering\SectionFieldRenderer.cs - - - RtfRendering\SectionPagesFieldRenderer.cs - - - RtfRendering\SectionRenderer.cs - - - RtfRendering\ShadingRenderer.cs - - - RtfRendering\ShapeRenderer.cs - - - RtfRendering\StyleAndFormatRenderer.cs - - - RtfRendering\StyleRenderer.cs - - - RtfRendering\TableRenderer.cs - - - RtfRendering\TabStopRenderer.cs - - - RtfRendering\TabStopsRenderer.cs - - - RtfRendering\TextFrameRenderer.cs - - - RtfRendering\TextRenderer.cs - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - RtfRendering.Resources\Messages.de.restext - - - RtfRendering.Resources\Messages.restext - - - + + + + + + + + + - \ No newline at end of file + diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-gdi/MigraDoc.RtfRendering-gdi.csproj.txt b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-gdi/MigraDoc.RtfRendering-gdi.csproj.txt deleted file mode 100644 index 31292c00..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-gdi/MigraDoc.RtfRendering-gdi.csproj.txt +++ /dev/null @@ -1,332 +0,0 @@ - - - - Local - 9.0.30729 - 2.0 - {22010032-52DC-464D-B8BB-6CD9BF230D1F} - Debug - AnyCPU - - - - - MigraDoc.RtfRendering-gdi - StrongnameKey.snk - JScript - Grid - IE50 - false - Library - MigraDoc - OnBuildSuccess - - - - - - - true - 3.5 - v3.5 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - SAK - SAK - SAK - SAK - - - - bin\Debug\ - false - 285212672 - false - - - TRACE;DEBUG;NET_2_0 - - - true - 4096 - false - 1030 - false - false - false - true - 4 - full - prompt - AllRules.ruleset - - - bin\Release\ - false - 285212672 - false - - - TRACE;NET_2_0 - bin\Release\MigraDoc.RtfRendering-gdi.xml - false - 4096 - false - - true - false - false - false - 4 - none - prompt - AllRules.ruleset - - - - System - - - System.Data - - - System.Drawing - - - System.XML - - - - - RtfRendering.Resources\Messages2.cs - - - MigraDoc.RtfRendering.resources\Messages2.cs - - - MigraDoc.RtfRendering\BookmarkFieldRenderer.cs - - - MigraDoc.RtfRendering\BorderRenderer.cs - - - MigraDoc.RtfRendering\BorderRendererBase.cs - - - MigraDoc.RtfRendering\BordersRenderer.cs - - - MigraDoc.RtfRendering\CellFormatRenderer.cs - - - MigraDoc.RtfRendering\CellRenderer.cs - - - MigraDoc.RtfRendering\CharacterRenderer.cs - - - MigraDoc.RtfRendering\ChartRenderer.cs - - - MigraDoc.RtfRendering\DateFieldRenderer.cs - - - MigraDoc.RtfRendering\enums\RtfUnit.cs - - - MigraDoc.RtfRendering\FieldRenderer.cs - - - MigraDoc.RtfRendering\FontRenderer.cs - - - MigraDoc.RtfRendering\FootnoteRenderer.cs - - - MigraDoc.RtfRendering\FormattedTextRenderer.cs - - - MigraDoc.RtfRendering\HeaderFooterRenderer.cs - - - MigraDoc.RtfRendering\HeadersFootersRenderer.cs - - - MigraDoc.RtfRendering\HyperlinkRenderer.cs - - - MigraDoc.RtfRendering\ImageRenderer.cs - - - MigraDoc.RtfRendering\InfoFieldRenderer.cs - - - MigraDoc.RtfRendering\ListInfoOverrideRenderer.cs - - - MigraDoc.RtfRendering\ListInfoRenderer.cs - - - MigraDoc.RtfRendering\NumericFieldRendererBase.cs - - - MigraDoc.RtfRendering\NumPagesFieldRenderer.cs - - - MigraDoc.RtfRendering\PageBreakRenderer.cs - - - MigraDoc.RtfRendering\PageFieldRenderer.cs - - - MigraDoc.RtfRendering\PageRefFieldRenderer.cs - - - MigraDoc.RtfRendering\PageSetupRenderer.cs - - - MigraDoc.RtfRendering\ParagraphFormatRenderer.cs - - - MigraDoc.RtfRendering\ParagraphRenderer.cs - - - MigraDoc.RtfRendering\RendererBase.cs - - - MigraDoc.RtfRendering\RendererFactory.cs - - - MigraDoc.RtfRendering\RowRenderer.cs - - - MigraDoc.RtfRendering\RowsRenderer.cs - - - MigraDoc.RtfRendering\RtfDocumentRenderer.cs - - - MigraDoc.RtfRendering\RtfWriter.cs - - - MigraDoc.RtfRendering\SectionFieldRenderer.cs - - - MigraDoc.RtfRendering\SectionPagesFieldRenderer.cs - - - MigraDoc.RtfRendering\SectionRenderer.cs - - - MigraDoc.RtfRendering\ShadingRenderer.cs - - - MigraDoc.RtfRendering\ShapeRenderer.cs - - - MigraDoc.RtfRendering\StyleAndFormatRenderer.cs - - - MigraDoc.RtfRendering\StyleRenderer.cs - - - MigraDoc.RtfRendering\TableRenderer.cs - - - MigraDoc.RtfRendering\TabStopRenderer.cs - - - MigraDoc.RtfRendering\TabStopsRenderer.cs - - - MigraDoc.RtfRendering\TextFrameRenderer.cs - - - MigraDoc.RtfRendering\TextRenderer.cs - - - Properties\AssemblyInfo.cs - - - Properties\VersionInfo.cs - - - RtfRendering.Resources\Messages2.de.resx - Messages2.cs - - - RtfRendering.Resources\Messages2.resx - Messages2.cs - - - RtfRendering.Resources\Messages.de.restext - - - RtfRendering.Resources\Messages.restext - - - RtfRendering.Resources\PDF.png - - - - - {5384ce57-1f94-4d22-860d-2e9c1ac12ddf} - PdfSharp-gdi - - - {cfdb7d46-ea8d-47de-b10a-9e755a1b48ba} - PdfSharp.Charting-gdi - - - {4666abf3-efe5-49bd-b2e8-9e04f5949145} - MigraDoc.DocumentObjectModel-gdi - - - {febbe5be-9f58-4967-bbcf-801f1cfcd774} - MigraDoc.Rendering-gdi - - - - - StrongnameKey.snk - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - - - - - \ No newline at end of file diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-wpf/MigraDoc.RtfRendering-wpf.csproj b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-wpf/MigraDoc.RtfRendering-wpf.csproj index 44b34fed..fd29b11a 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-wpf/MigraDoc.RtfRendering-wpf.csproj +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering-wpf/MigraDoc.RtfRendering-wpf.csproj @@ -1,11 +1,11 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true MigraDoc WPF true - true + OnBuildSuccess True ..\..\..\..\..\StrongnameKey.snk @@ -15,196 +15,80 @@ true - + 0 - + 0 - - Properties\VersionInfo.cs - - - Properties\GlobalDeclarations.cs - - - RtfRendering.Resources\Messages2.cs - - - RtfRendering\BookmarkFieldRenderer.cs - - - RtfRendering\BorderRenderer.cs - - - RtfRendering\BorderRendererBase.cs - - - RtfRendering\BordersRenderer.cs - - - RtfRendering\CellFormatRenderer.cs - - - RtfRendering\CellRenderer.cs - - - RtfRendering\CharacterRenderer.cs - - - RtfRendering\ChartRenderer.cs - - - RtfRendering\DateFieldRenderer.cs - - - RtfRendering\enums\RtfUnit.cs - - - RtfRendering\FieldRenderer.cs - - - RtfRendering\FontRenderer.cs - - - RtfRendering\FootnoteRenderer.cs - - - RtfRendering\FormattedTextRenderer.cs - - - RtfRendering\HeaderFooterRenderer.cs - - - RtfRendering\HeadersFootersRenderer.cs - - - RtfRendering\HyperlinkRenderer.cs - - - RtfRendering\ImageRenderer.cs - - - RtfRendering\InfoFieldRenderer.cs - - - RtfRendering\ListInfoOverrideRenderer.cs - - - RtfRendering\ListInfoRenderer.cs - - - RtfRendering\NumericFieldRendererBase.cs - - - RtfRendering\NumPagesFieldRenderer.cs - - - RtfRendering\PageBreakRenderer.cs - - - RtfRendering\PageFieldRenderer.cs - - - RtfRendering\PageRefFieldRenderer.cs - - - RtfRendering\PageSetupRenderer.cs - - - RtfRendering\ParagraphFormatRenderer.cs - - - RtfRendering\ParagraphRenderer.cs - - - RtfRendering\RendererBase.cs - - - RtfRendering\RendererFactory.cs - - - RtfRendering\RowRenderer.cs - - - RtfRendering\RowsRenderer.cs - - - RtfRendering\RtfDocumentRenderer.cs - - - RtfRendering\RtfWriter.cs - - - RtfRendering\SectionFieldRenderer.cs - - - RtfRendering\SectionPagesFieldRenderer.cs - - - RtfRendering\SectionRenderer.cs - - - RtfRendering\ShadingRenderer.cs - - - RtfRendering\ShapeRenderer.cs - - - RtfRendering\StyleAndFormatRenderer.cs - - - RtfRendering\StyleRenderer.cs - - - RtfRendering\TableRenderer.cs - - - RtfRendering\TabStopRenderer.cs - - - RtfRendering\TabStopsRenderer.cs - - - RtfRendering\TextFrameRenderer.cs - - - RtfRendering\TextRenderer.cs - - - - - RtfRendering.Resources\Messages.de.restext - - - RtfRendering.Resources\Messages.restext - - - - - RtfRendering.Resources\Messages2.de.resx - Messages2.cs - - - RtfRendering.Resources\Messages2.resx - Messages2.cs - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - RtfRendering.Resources\PDF.png - + + $(DefineConstants);TRACE;WPF + + + - \ No newline at end of file + diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/MigraDoc.RtfRendering.csproj b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/MigraDoc.RtfRendering.csproj index 582a4a10..10518896 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/MigraDoc.RtfRendering.csproj +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/MigraDoc.RtfRendering.csproj @@ -1,7 +1,7 @@  - net6.0;netstandard2.0 + net6.0;net8.0;netstandard2.0 MigraDoc ..\..\..\..\..\StrongnameKey.snk True @@ -32,26 +32,8 @@ - - - - - - - - - - - - - - + + diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/Properties/VersionInfo.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/Properties/VersionInfo.cs deleted file mode 100644 index 0cbd3e88..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/Properties/VersionInfo.cs +++ /dev/null @@ -1,17 +0,0 @@ -// MigraDoc - Creating Documents on the Fly -// See the LICENSE file in the solution root for more information. - -namespace MigraDoc.RtfRendering -{ - class VersionInfo - { - public static readonly string Title = "MigraDoc.RtfRendering.dll"; - public static readonly string Description = ""; - public static readonly string Version = MigraDocProductVersionInformation.Version; - public static readonly string Culture = MigraDocProductVersionInformation.Culture; - public static readonly string Company = MigraDocProductVersionInformation.Company; - public static readonly string Product = MigraDocProductVersionInformation.Product; - public static readonly string Copyright = MigraDocProductVersionInformation.Copyright; - public static readonly string Trademark = MigraDocProductVersionInformation.Trademark; - } -} diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages.de.restext b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages.de.restext deleted file mode 100644 index f511b19a..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages.de.restext +++ /dev/null @@ -1,17 +0,0 @@ -; // MigraDoc - Creating Documents on the Fly -; // See the LICENSE file in the solution root for more information. - -; ----- German (de) Messages --------------------------------------------------- -; Messages for German language -; that differ from the default messages. -; ------------------------------------------------------------------------------ - -UpdateField = < Feld bitte aktualisieren. > -TextframeContentsNotTurned = Textrahmen-Inhalt konnte nicht gedreht werden. Nur Absätze können innerhalb von Textrahmen gedreht werden. -ImageFreelyPlacedInWrongContext = Bilder können nur innerhalb von Abschnitten und Kopf- und Fußzeilen absolut auf der Seite platziert werden. Das Bild {0} wird ignoriert. -ChartFreelyPlacedInWrongContext = Ein Diagramm wird ignoriert. Diagramme können nur innerhalb von Abschnitten und Kopf- und Fußzeilen absolut auf der Seite platziert werden. -ImageNotFound = Bild '{0}' konnte nicht gefunden werden. -ImageNotReadable = Bild '{0}' konnte nicht eingelesen werden. Es trat eine Ausnahme mit der folgenden Meldung auf:\n{1} -ImageTypeNotSupported = Der Typ des Bildes '{0}' wird nicht unterstützt. Das Bild wird ignoriert. -CharacterNotAllowedInDateFormat = Das Zeichen '{0}' ist für das Format eines Datumsfeldes nicht erlaubt und wird ignoriert. -InvalidNumericFieldFormat = '{0}' ist kein gültiges Format für ein numerisches Feld und wird ignoriert. \ No newline at end of file diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages.restext b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages.restext deleted file mode 100644 index 4ed1fd49..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages.restext +++ /dev/null @@ -1,16 +0,0 @@ -; // MigraDoc - Creating Documents on the Fly -; // See the LICENSE file in the solution root for more information. - -; ----- Default Messages ------------------------------------------------------- -; Default Messages for any system culture. -; ------------------------------------------------------------------------------ - -UpdateField = < Please update this field. > -TextframeContentsNotTurned = Textframe contents could not be turned. Only paragraphs can be turned within textframes. -ImageFreelyPlacedInWrongContext = Images can be placed freely only within headers, footers and sections. Image {0} will be ignored. -ChartFreelyPlacedInWrongContext = Chart is being ignored. A chart can be placed freely only within headers, footers and sections. -ImageNotFound = Image '{0}' could not be found. -ImageNotReadable = Image '{0}' could not be read. Inner Exception:\n{1}. -ImageTypeNotSupported = Type of image '{0}' is not supported. -CharacterNotAllowedInDateFormat = The character '{0}' is not allowed in a date fields format string and will be ignored. -InvalidNumericFieldFormat = '{0}' is not a valid format for a numeric field und will be ignored. \ No newline at end of file diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.cs deleted file mode 100644 index 20acb01e..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.cs +++ /dev/null @@ -1,115 +0,0 @@ -// MigraDoc - Creating Documents on the Fly -// See the LICENSE file in the solution root for more information. - -using System; -using System.Resources; -using System.Reflection; -#if DEBUG -using System.Text.RegularExpressions; -#endif - -namespace MigraDoc.RtfRendering.Resources -{ - /// - /// Provides diagnostic messages taken from the resources. - /// - class Messages2 - { - internal static string TextframeContentsNotTurned - { - get { return FormatMessage(IDs.TextframeContentsNotTurned); } - } - - internal static string ImageFreelyPlacedInWrongContext(string imageName) - { - return FormatMessage(IDs.ImageFreelyPlacedInWrongContext, imageName); - } - - internal static string ChartFreelyPlacedInWrongContext - { - get { return FormatMessage(IDs.ChartFreelyPlacedInWrongContext); } - } - - internal static string ImageNotFound(string imageName) - { - return FormatMessage(IDs.ImageNotFound, imageName); - } - - internal static string ImageNotReadable(string imageName, string innerException) - { - return FormatMessage(IDs.ImageNotReadable, imageName, innerException); - } - - internal static string ImageTypeNotSupported(string imageName) - { - return FormatMessage(IDs.ImageTypeNotSupported, imageName); - } - - internal static string InvalidNumericFieldFormat(string format) - { - return FormatMessage(IDs.InvalidNumericFieldFormat, format); - } - - internal static string CharacterNotAllowedInDateFormat(char character) - { - string charString = character.ToString(); - return FormatMessage(IDs.CharacterNotAllowedInDateFormat, charString); - } - - internal static string UpdateField - { - get { return FormatMessage(IDs.UpdateField); } - } - - // ReSharper disable InconsistentNaming - enum IDs - { - UpdateField, - TextframeContentsNotTurned, - InvalidNumericFieldFormat, - ImageFreelyPlacedInWrongContext, - ChartFreelyPlacedInWrongContext, - ImageNotFound, - ImageNotReadable, - ImageTypeNotSupported, - CharacterNotAllowedInDateFormat - } - // ReSharper restore InconsistentNaming - - static ResourceManager ResourceManager - { - get - { - return _resourceManager ??= new("MigraDoc.RtfRendering.Resources.Messages", Assembly.GetExecutingAssembly()); - } - } - static ResourceManager? _resourceManager; - - static string FormatMessage(IDs id, params object[] args) - { - string? message; - try - { - message = ResourceManager.GetString(id.ToString()); - if (message != null) - { -#if DEBUG - if (Regex.Matches(message, @"\{[0-9]\}").Count > args.Length) - { - //TODO too many placeholders or too few args... - } -#endif - message = String.Format(message, args); - } - else - message = "<<>>"; - return message; - } - catch (Exception ex) - { - message = "INTERNAL ERROR while formatting error message: " + ex; - } - return message; - } - } -} diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.resx b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.resx deleted file mode 100644 index 20b237bc..00000000 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering.Resources/Messages2.resx +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Chart is being ignored. A chart can be placed freely only within headers, footers and sections. - - - Type of image '{0}' is not supported. - - - The character '{0}' is not allowed in a date field’s format string and will be ignored. - - - Images can be placed freely only within headers, footers and sections. Image {0} will be ignored. - - - '{0}' is not a valid format for a numeric field und will be ignored. - - - Image '{0}' could not be found. - - - Textframe contents could not be turned. Only paragraphs can be turned within textframes. - - - < Please update this field. > - - - Image '{0}' could not be read. Inner Exception: -{1}. - - \ No newline at end of file diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/BookmarkFieldRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/BookmarkFieldRenderer.cs index 08e780e9..0da8eaf2 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/BookmarkFieldRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/BookmarkFieldRenderer.cs @@ -42,14 +42,14 @@ internal override void Render() internal static string MakeValidBookmarkName(string originalName) { //Bookmarks (at least in Word) have the following limitations: - //1. First character must be a letter (umlauts und ß are allowed) - //2. All further characters must be letters, numbers or underscores. + //1. First character must be a letter (umlauts and ß are allowed). + //2. All further characters must be letters, numbers or underscores. // For example, '-' is NOT allowed). StringBuilder strBuilder = new StringBuilder(originalName.Length); if (!Char.IsLetter(originalName[0])) strBuilder.Append("BM__"); - for (int idx = 0; idx < originalName.Length; ++idx) + for (int idx = 0; idx < originalName.Length; idx++) { char ch = originalName[idx]; strBuilder.Append(Char.IsLetterOrDigit(ch) ? ch : '_'); diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/CellFormatRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/CellFormatRenderer.cs index ebe6fd58..a7764637 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/CellFormatRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/CellFormatRenderer.cs @@ -92,7 +92,7 @@ int GetRightCellBoundary() { int rightClmIdx = _coveringCell.Column!.Index + _coveringCell.MergeRight; double width = RowsRenderer.CalculateLeftIndent(_cell.Table!.Rows).Point; - for (int idx = 0; idx <= rightClmIdx; ++idx) + for (int idx = 0; idx <= rightClmIdx; idx++) { var obj = _cell.Table.Columns[idx].Values.Width; if (obj != null) diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/CharacterRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/CharacterRenderer.cs index f272351d..9550de19 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/CharacterRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/CharacterRenderer.cs @@ -35,23 +35,23 @@ internal override void Render() switch (_character.SymbolName) { case SymbolName.Blank: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteBlank(); //WriteText wouldnt work if there was a control before. break; case SymbolName.Bullet: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteControl("bullet"); break; case SymbolName.Copyright: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteHex(0xa9); break; case SymbolName.Em: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) { _rtfWriter.WriteControl("u", "8195"); //I dont know why, but it works: @@ -60,7 +60,7 @@ internal override void Render() break; case SymbolName.Em4: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) { _rtfWriter.WriteControl("u", "8197"); //I dont know why, but it works: @@ -69,7 +69,7 @@ internal override void Render() break; case SymbolName.En: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) { _rtfWriter.WriteControl("u", "8194"); //I dont know why, but it works: @@ -78,53 +78,53 @@ internal override void Render() break; case SymbolName.EmDash: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteControl("emdash"); break; case SymbolName.EnDash: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteControl("endash"); break; case SymbolName.Euro: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteHex(0x80); break; case SymbolName.NonBreakableBlank: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) // Must not have a blank after "\~", so pass false as first parameter. _rtfWriter.WriteControl(false, "~"); break; case SymbolName.LineBreak: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteControl("line"); break; case SymbolName.Not: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteHex(0xac); break; case SymbolName.ParaBreak: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteControl("par"); break; case SymbolName.RegisteredTrademark: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteHex(0xae); break; case SymbolName.Tab: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteControl("tab"); break; case SymbolName.Trademark: - for (int i = 0; i < count; ++i) + for (int idx = 0; idx < count; idx++) _rtfWriter.WriteHex(0x99); break; } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/ChartRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/ChartRenderer.cs index 6c055f2c..cc52f1d0 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/ChartRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/ChartRenderer.cs @@ -10,8 +10,11 @@ using MigraDoc.DocumentObjectModel; using MigraDoc.DocumentObjectModel.Shapes.Charts; using MigraDoc.Logging; -using MigraDoc.RtfRendering.Resources; +#if GDI +using PdfSharp.Drawing; using PdfSharp.Events; +using MigraDoc.Rendering; +#endif #if WPF using PdfSharp.Drawing; using MigraDoc.Rendering; @@ -45,7 +48,7 @@ internal override void Render() if (DocumentRelations.GetParent(_chart) is DocumentElements elms && !renderInParagraph && !(DocumentRelations.GetParent(elms) is Section || DocumentRelations.GetParent(elms) is HeaderFooter)) { - MigraDocLogHost.RtfRenderingLogger.LogWarning(Messages2.ChartFreelyPlacedInWrongContext); + MigraDocLogHost.RtfRenderingLogger.LogWarning(MdRtfMsgs.ChartFreelyPlacedInWrongContext.Message); //Debug.WriteLine(Messages2.ChartFreelyPlacedInWrongContext, "warning"); return; } @@ -150,7 +153,7 @@ void RenderDimensionSettings() bool StoreTempImage(string fileName) { -#if !WPF +#if !GDI // ReviewSTLA THHO4STLA // EXPERIMENTAL switch (Capabilities.Compatibility.ChartsCannotBeRendered) @@ -185,13 +188,17 @@ bool StoreTempImage(string fileName) const float resolution = 96; int horzPixels = (int)(GetShapeWidth().Inch * resolution); int vertPixels = (int)(GetShapeHeight().Inch * resolution); - Bitmap bmp = new Bitmap(horzPixels, vertPixels); -#if true +#if false XGraphics gfx = XGraphics.CreateMeasureContext(new XSize(horzPixels, vertPixels), XGraphicsUnit.Point, XPageDirection.Downwards, new RenderEvents()); #else #if GDI - XGraphics gfx = XGraphics.FromGraphics(Graphics.FromImage(bmp), new XSize(horzPixels, vertPixels)); + Bitmap bmp = new Bitmap(horzPixels, vertPixels); + XGraphics gfx = XGraphics.FromGraphics(Graphics.FromImage(bmp), new XSize(horzPixels, vertPixels), new RenderEvents()); +#else + // TODOWPF + // TODOCORE + return false; #endif #if WPF // TODOWPF @@ -204,8 +211,10 @@ bool StoreTempImage(string fileName) DocumentRenderer renderer = new MigraDoc.Rendering.DocumentRenderer(_chart.Document!); renderer.RenderObject(gfx, 0, 0, GetShapeWidth().Point, _chart); +#if GDI bmp.SetResolution(resolution, resolution); bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Png); +#endif } catch (Exception) { @@ -213,7 +222,7 @@ bool StoreTempImage(string fileName) } return true; #endif - } + } //-/*private void CalculateImageDimensions() //{ // try @@ -226,85 +235,85 @@ bool StoreTempImage(string fileName) // float origHorzRes = bip.HorizontalResolution; // float origVertRes = bip.VerticalResolution; - // this.originalHeight = bip.Height * 72 / origVertRes; - // this.originalWidth = bip.Width * 72 / origHorzRes; - - // horzResolution = bip.HorizontalResolution; - // vertResolution = bip.VerticalResolution; - // } - // else - // { - // horzResolution= (float)GetValueAsIntended("Resolution"); - // vertResolution= horzResolution; - // } - - // Unit origHeight = bip.Size.Height * 72 / vertResolution; - // Unit origWidth = bip.Size.Width * 72 / horzResolution; - - // this.imageHeight = origHeight; - // this.imageWidth = origWidth; - - // bool scaleWidthIsNull = this.image.IsNull("ScaleWidth"); - // bool scaleHeightIsNull = this.image.IsNull("ScaleHeight"); - // float sclHeight = scaleHeightIsNull ? 1 : (float)GetValueAsIntended("ScaleHeight"); - // this.scaleHeight= sclHeight; - // float sclWidth = scaleWidthIsNull ? 1 : (float)GetValueAsIntended("ScaleWidth"); - // this.scaleWidth = sclWidth; - - // bool doLockAspectRatio = this.image.IsNull("LockAspectRatio") || this.image.LockAspectRatio; - - // if (doLockAspectRatio && (scaleHeightIsNull || scaleWidthIsNull)) - // { - // if (!this.image.IsNull("Width") && this.image.IsNull("Height")) - // { - // imageWidth = this.image.Width; - // imageHeight = origHeight * imageWidth / origWidth; - // } - // else if (!this.image.IsNull("Height") && this.image.IsNull("Width")) - // { - // imageHeight = this.image.Height; - // imageWidth = origWidth * imageHeight / origHeight; - // } - // else if (!this.image.IsNull("Height") && !this.image.IsNull("Width")) - // { - // imageWidth = this.image.Width; - // imageHeight = this.image.Height; - // } - // if (scaleWidthIsNull && !scaleHeightIsNull) - // scaleWidth = scaleHeight; - // else if (scaleHeightIsNull && ! scaleWidthIsNull) - // scaleHeight = scaleWidth; - // } - // else - // { - // if (!this.image.IsNull("Width")) - // imageWidth = this.image.Width; - // if (!this.image.IsNull("Height")) - // imageHeight = this.image.Height; - // } - - // return; - // } - // catch(FileNotFoundException) - // { - // Debug.WriteLine(Messages.ImageNotFound(this.image.Name), "warning"); - // } - // catch(Exception exc) - // { - // Debug.WriteLine(Messages.ImageNotReadable(this.image.Name, exc.Message), "warning"); - // } - - // //Setting defaults in case an error occurred. - // this.imageFile = null; - // this.imageHeight = (Unit)GetValueOrDefault("Height", Unit.FromInch(1)); - // this.imageWidth = (Unit)GetValueOrDefault("Width", Unit.FromInch(1)); - // this.scaleHeight = (double)GetValueOrDefault("ScaleHeight", 1.0); - // this.scaleWidth = (double)GetValueOrDefault("ScaleWidth", 1.0); - //}*/ - - /// - /// Renders the image file as byte series. - /// + // this.originalHeight = bip.Height * 72 / origVertRes; + // this.originalWidth = bip.Width * 72 / origHorzRes; + + // horzResolution = bip.HorizontalResolution; + // vertResolution = bip.VerticalResolution; + // } + // else + // { + // horzResolution= (float)GetValueAsIntended("Resolution"); + // vertResolution= horzResolution; + // } + + // Unit origHeight = bip.Size.Height * 72 / vertResolution; + // Unit origWidth = bip.Size.Width * 72 / horzResolution; + + // this.imageHeight = origHeight; + // this.imageWidth = origWidth; + + // bool scaleWidthIsNull = this.image.IsNull("ScaleWidth"); + // bool scaleHeightIsNull = this.image.IsNull("ScaleHeight"); + // float sclHeight = scaleHeightIsNull ? 1 : (float)GetValueAsIntended("ScaleHeight"); + // this.scaleHeight= sclHeight; + // float sclWidth = scaleWidthIsNull ? 1 : (float)GetValueAsIntended("ScaleWidth"); + // this.scaleWidth = sclWidth; + + // bool doLockAspectRatio = this.image.IsNull("LockAspectRatio") || this.image.LockAspectRatio; + + // if (doLockAspectRatio && (scaleHeightIsNull || scaleWidthIsNull)) + // { + // if (!this.image.IsNull("Width") && this.image.IsNull("Height")) + // { + // imageWidth = this.image.Width; + // imageHeight = origHeight * imageWidth / origWidth; + // } + // else if (!this.image.IsNull("Height") && this.image.IsNull("Width")) + // { + // imageHeight = this.image.Height; + // imageWidth = origWidth * imageHeight / origHeight; + // } + // else if (!this.image.IsNull("Height") && !this.image.IsNull("Width")) + // { + // imageWidth = this.image.Width; + // imageHeight = this.image.Height; + // } + // if (scaleWidthIsNull && !scaleHeightIsNull) + // scaleWidth = scaleHeight; + // else if (scaleHeightIsNull && ! scaleWidthIsNull) + // scaleHeight = scaleWidth; + // } + // else + // { + // if (!this.image.IsNull("Width")) + // imageWidth = this.image.Width; + // if (!this.image.IsNull("Height")) + // imageHeight = this.image.Height; + // } + + // return; + // } + // catch(FileNotFoundException) + // { + // Debug.WriteLine(Messages.ImageNotFound(this.image.Name), "warning"); + // } + // catch(Exception exc) + // { + // Debug.WriteLine(Messages.ImageNotReadable(this.image.Name, exc.Message), "warning"); + // } + + // //Setting defaults in case an error occurred. + // this.imageFile = null; + // this.imageHeight = (Unit)GetValueOrDefault("Height", Unit.FromInch(1)); + // this.imageWidth = (Unit)GetValueOrDefault("Width", Unit.FromInch(1)); + // this.scaleHeight = (double)GetValueOrDefault("ScaleHeight", 1.0); + // this.scaleWidth = (double)GetValueOrDefault("ScaleWidth", 1.0); + //}*/ + + /// + /// Renders the image file as byte series. + /// void RenderByteSeries(string fileName) { FileStream? imageFile = null; diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/DateFieldRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/DateFieldRenderer.cs index f9cb0a31..704e9a77 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/DateFieldRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/DateFieldRenderer.cs @@ -8,7 +8,6 @@ using Microsoft.Extensions.Logging; using MigraDoc.DocumentObjectModel.Fields; using MigraDoc.Logging; -using MigraDoc.RtfRendering.Resources; namespace MigraDoc.RtfRendering { @@ -104,7 +103,7 @@ void TranslateFormat() format = dtfInfo.SortableDateTimePattern; break; - //TODO: Output universal time for u und U. + //TODO: Output universal time for u and U. case "u": format = dtfInfo.UniversalSortableDateTimePattern; break; @@ -141,7 +140,7 @@ void TranslateFormat() if (isEscaped) { //Doesn’t work in Word format strings. - MigraDocLogHost.RtfRenderingLogger.LogWarning(Messages2.CharacterNotAllowedInDateFormat(c)); + MigraDocLogHost.RtfRenderingLogger.LogWarning(MdRtfMsgs.CharacterNotAllowedInDateFormat(c).Message); //Debug.WriteLine(Messages2.CharacterNotAllowedInDateFormat(c), "warning"); isEscaped = false; } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/FieldRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/FieldRenderer.cs index 7d916cc8..5a74a1b1 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/FieldRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/FieldRenderer.cs @@ -2,7 +2,6 @@ // See the LICENSE file in the solution root for more information. using MigraDoc.DocumentObjectModel; -using MigraDoc.RtfRendering.Resources; namespace MigraDoc.RtfRendering { @@ -46,7 +45,7 @@ protected void EndField() /// protected virtual string GetFieldResult() { - return Messages2.UpdateField; + return MdRtfMsgs.UpdateField.Message; } } } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/ImageRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/ImageRenderer.cs index 15fabe13..1aeec6f9 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/ImageRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/ImageRenderer.cs @@ -5,16 +5,11 @@ using System.Diagnostics; using System.Reflection; using Microsoft.Extensions.Logging; -#if true || GDI || WPF using PdfSharp.Drawing; -#endif using MigraDoc.DocumentObjectModel; using MigraDoc.DocumentObjectModel.Shapes; using MigraDoc.Logging; -using MigraDoc.RtfRendering.Resources; -using PdfSharp.Diagnostics; using Image = MigraDoc.DocumentObjectModel.Shapes.Image; -//using System.Security.Policy; namespace MigraDoc.RtfRendering { @@ -45,7 +40,7 @@ internal override void Render() if (DocumentRelations.GetParent(_image) is DocumentElements elms && !renderInParagraph && !(DocumentRelations.GetParent(elms) is Section || DocumentRelations.GetParent(elms) is HeaderFooter)) { - MigraDocLogHost.RtfRenderingLogger.LogWarning(Messages2.ImageFreelyPlacedInWrongContext(_image.Name)); + MigraDocLogHost.RtfRenderingLogger.LogWarning(MdRtfMsgs.ImageFreelyPlacedInWrongContext(_image.Name).Message); //Debug.WriteLine(Messages2.ImageFreelyPlacedInWrongContext(_image.Name), "warning"); return; } @@ -168,7 +163,7 @@ void RenderSourceType() break; default: - MigraDocLogHost.RtfRenderingLogger.LogError(Messages2.ImageTypeNotSupported(_image.Name)); + MigraDocLogHost.RtfRenderingLogger.LogError(MdRtfMsgs.ImageTypeNotSupported(_image.Name).Message); //Debug.WriteLine(Messages2.ImageTypeNotSupported(_image.Name), "warning"); _imageFile = null; break; @@ -286,12 +281,12 @@ void CalculateImageDimensions() } catch (FileNotFoundException) { - MigraDocLogHost.RtfRenderingLogger.LogError(Messages2.ImageNotFound(_image.Name)); + MigraDocLogHost.RtfRenderingLogger.LogError(MdRtfMsgs.ImageNotFound(_image.Name).Message); //Debug.WriteLine(Messages2.ImageNotFound(_image.Name), "warning"); } catch (Exception exc) { - MigraDocLogHost.RtfRenderingLogger.LogError(Messages2.ImageNotReadable(_image.Name, exc.Message)); + MigraDocLogHost.RtfRenderingLogger.LogError(MdRtfMsgs.ImageNotReadable(_image.Name, exc.Message).Message); //Debug.WriteLine(Messages2.ImageNotReadable(_image.Name, exc.Message), "warning"); } finally diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/MdRtfMsg.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/MdRtfMsg.cs new file mode 100644 index 00000000..27770448 --- /dev/null +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/MdRtfMsg.cs @@ -0,0 +1,18 @@ +// MigraDoc - Creating Documents on the Fly +// See the LICENSE file in the solution root for more information. + +using Microsoft.Extensions.Logging; + +namespace MigraDoc.RtfRendering +{ + readonly struct MdRtfMsg(MdRtfMsgId id, string message) + { + public MdRtfMsgId Id { get; } = id; + + public string Message { get; } = message; + + public EventId EventId => new((int)Id, EventName); + + public string EventName => Id.ToString(); + } +} diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/MdRtfMsgs.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/MdRtfMsgs.cs new file mode 100644 index 00000000..c5bfca27 --- /dev/null +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/MdRtfMsgs.cs @@ -0,0 +1,58 @@ +// MigraDoc - Creating Documents on the Fly +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Internal; + +namespace MigraDoc.RtfRendering +{ + enum MdRtfMsgId + { + None = 0, + + UpdateField = MessageIdOffset.MdRtf, + TextFrameContentsNotTurned, + InvalidNumericFieldFormat, + ImageFreelyPlacedInWrongContext, + ChartFreelyPlacedInWrongContext, + ImageNotFound, + ImageNotReadable, + ImageTypeNotSupported, + CharacterNotAllowedInDateFormat + } + + /// + /// Provides diagnostic messages taken from the resources. + /// + // ReSharper disable once IdentifierTypo + class MdRtfMsgs + { + internal static MdRtfMsg TextFrameContentsNotTurned + => new(MdRtfMsgId.TextFrameContentsNotTurned, "Text-frame contents could not be turned. Only paragraphs can be turned within text-frames."); + + internal static MdRtfMsg ImageFreelyPlacedInWrongContext(string imageName) + => new(MdRtfMsgId.ImageFreelyPlacedInWrongContext, $"Images can be placed freely only within headers, footers and sections. Image {imageName} will be ignored."); + + internal static MdRtfMsg ChartFreelyPlacedInWrongContext + => new(MdRtfMsgId.ChartFreelyPlacedInWrongContext, "Chart is being ignored. A chart can be placed freely only within headers, footers and sections."); + + internal static MdRtfMsg ImageNotFound(string imageName) + => new(MdRtfMsgId.ImageNotFound, $"Image '{imageName}' could not be found."); + + internal static MdRtfMsg ImageNotReadable(string imageName, string innerException) + => new(MdRtfMsgId.ImageNotReadable, $"Image '{imageName}' could not be read. Inner Exception:\r\n{innerException}."); + + internal static MdRtfMsg ImageTypeNotSupported(string imageName) + => new(MdRtfMsgId.ImageTypeNotSupported, $"Type of image '{imageName}' is not supported."); + + internal static MdRtfMsg InvalidNumericFieldFormat(string format) + => new(MdRtfMsgId.InvalidNumericFieldFormat, $"'{format}' is not a valid format for a numeric field and will be ignored."); + + internal static MdRtfMsg CharacterNotAllowedInDateFormat(char character) + => new(MdRtfMsgId.CharacterNotAllowedInDateFormat, $"The character '{character}' is not allowed in a date fields format string and will be ignored."); + + internal static MdRtfMsg UpdateField + => new(MdRtfMsgId.UpdateField, "< Please update this field. >"); + + // ReSharper disable InconsistentNaming + } +} diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/NumericFieldRendererBase.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/NumericFieldRendererBase.cs index d2ec701e..dc9027c7 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/NumericFieldRendererBase.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/NumericFieldRendererBase.cs @@ -1,12 +1,10 @@ // MigraDoc - Creating Documents on the Fly // See the LICENSE file in the solution root for more information. -using System.Diagnostics; using Microsoft.Extensions.Logging; using MigraDoc.DocumentObjectModel; using MigraDoc.DocumentObjectModel.Fields; using MigraDoc.Logging; -using MigraDoc.RtfRendering.Resources; namespace MigraDoc.RtfRendering { @@ -48,7 +46,7 @@ protected void TranslateFormat() break; default: - MigraDocLogHost.RtfRenderingLogger.LogError(Messages2.InvalidNumericFieldFormat(_numericField.Format)); + MigraDocLogHost.RtfRenderingLogger.LogError(MdRtfMsgs.InvalidNumericFieldFormat(_numericField.Format).Message); //Debug.WriteLine(Messages2.InvalidNumericFieldFormat(_numericField.Format), "warning"); break; } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RendererBase.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RendererBase.cs index 7413e55f..dfd5c9e5 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RendererBase.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RendererBase.cs @@ -210,7 +210,6 @@ static void CreateEnumTranslationTable() /// /// /// - /// internal static int ToRtfUnit(Unit unit, RtfUnit rtfUnit) { switch (rtfUnit) diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RowRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RowRenderer.cs index 5d0ade14..c03cf6f2 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RowRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RowRenderer.cs @@ -45,7 +45,7 @@ internal override void Render() RenderTopBottomPadding(); //Cell borders etc. are written before the contents. - for (int idx = 0; idx < _row.Table!.Columns.Count; ++idx) + for (int idx = 0; idx < _row.Table!.Columns.Count; idx++) { Cell cell = _row.Cells[idx]; CellFormatRenderer cellFrmtRenderer = diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RtfDocumentRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RtfDocumentRenderer.cs index 7d4bc429..5d41a986 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RtfDocumentRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/RtfDocumentRenderer.cs @@ -1,14 +1,11 @@ // MigraDoc - Creating Documents on the Fly // See the LICENSE file in the solution root for more information. -using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Text; using MigraDoc.DocumentObjectModel; using MigraDoc.DocumentObjectModel.Internals; using MigraDoc.DocumentObjectModel.Visitors; -using PdfSharp.Diagnostics; +using PdfSharp.Pdf.Internal; using Color = MigraDoc.DocumentObjectModel.Color; using Font = MigraDoc.DocumentObjectModel.Font; @@ -38,38 +35,40 @@ internal override void Render() /// public void Render(Document doc, string file, string workingDirectory) { -#if NET6_0_OR_GREATER - var ansiEncoding = CodePagesEncodingProvider.Instance.GetEncoding(1252)!; -#else - Encoding? ansiEncoding; - try - { - // Try to get ANSI encoding. - ansiEncoding = Encoding.GetEncoding(1252); - } - catch (NotSupportedException) - { -#if NET6_0_OR_GREATER - // Register provider if ANSI encoding is not available. - Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); -#endif - ansiEncoding = Encoding.GetEncoding(1252); - } -#endif + // #DELETE + //#if NET6_0_OR_GREATER + // var ansiEncoding = CodePagesEncodingProvider.Instance.GetEncoding(1252)!; + //#else + // Encoding? ansiEncoding; + // try + // { + // // Try to get ANSI encoding. + // ansiEncoding = Encoding.GetEncoding(1252); + // } + // catch (NotSupportedException) + // { + //#if NET6_0_OR_GREATER + // // Register provider if ANSI encoding is not available. + // Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + //#endif + // ansiEncoding = Encoding.GetEncoding(1252); + // } + //#endif + var ansiEncoding = PdfEncoders.WinAnsiEncoding; StreamWriter? streamWriter = null; try { - _document = doc; + Document = doc; _docObject = doc; - _workingDirectory = workingDirectory; + WorkingDirectory = workingDirectory; string path = file; // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract if (workingDirectory != null) path = Path.Combine(workingDirectory, file); - streamWriter = new StreamWriter(path, false, ansiEncoding); - _rtfWriter = new RtfWriter(streamWriter); + streamWriter = new(path, false, ansiEncoding); + _rtfWriter = new(streamWriter); WriteDocument(); } finally @@ -96,22 +95,24 @@ public void Render(Document document, Stream stream, string workingDirectory) public void Render(Document document, Stream stream, bool closeStream, string workingDirectory) { if (document == null) - throw new ArgumentNullException("document"); + throw new ArgumentNullException(nameof(document)); if (document.UseCmykColor) throw new InvalidOperationException("Cannot create RTF document with CMYK colors."); -#if NET6_0_OR_GREATER - var ansiEncoding = CodePagesEncodingProvider.Instance.GetEncoding(1252)!; -#else - var ansiEncoding = Encoding.GetEncoding(1252); -#endif + // #DELETE + //#if NET6_0_OR_GREATER + // var ansiEncoding = CodePagesEncodingProvider.Instance.GetEncoding(1252)!; + //#else + // var ansiE ncoding = Encoding.GetEncoding(1252); + //#endif + var ansiEncoding = PdfEncoders.WinAnsiEncoding; StreamWriter? streamWriter = null; try { streamWriter = new(stream, ansiEncoding); - _document = document; + Document = document; _docObject = document; - _workingDirectory = workingDirectory; + WorkingDirectory = workingDirectory; _rtfWriter = new(streamWriter); WriteDocument(); } @@ -138,13 +139,13 @@ public void Render(Document document, Stream stream, bool closeStream, string wo public string RenderToString(Document document, string workingDirectory) { if (document == null) - throw new ArgumentNullException("document"); + throw new ArgumentNullException(nameof(document)); if (document.UseCmykColor) throw new InvalidOperationException("Cannot create RTF document with CMYK colors."); - _document = document; + Document = document; _docObject = document; - _workingDirectory = workingDirectory; + WorkingDirectory = workingDirectory; StringWriter? writer = null; try { @@ -169,8 +170,8 @@ void WriteDocument() if (Document.EmbeddedFiles.Count > 0) throw new InvalidOperationException("Embedded files are not supported in RTF documents."); - RtfFlattenVisitor flattener = new RtfFlattenVisitor(); - flattener.Visit(_document); + var flattener = new RtfFlattenVisitor(); + flattener.Visit(Document); Prepare(); _rtfWriter.StartContent(); RenderHeader(); @@ -192,7 +193,7 @@ void Prepare() _listList.Clear(); ListInfoRenderer.Clear(); ListInfoOverrideRenderer.Clear(); - CollectTables(_document); + CollectTables(Document); } /// @@ -215,7 +216,7 @@ void RenderHeader() } /// - /// Fills the font, color and (later!) list hashtables so they can be rendered and used by other renderers. + /// Fills the font, color and (later!) list hashtables, so they can be rendered and used by other renderers. /// void CollectTables(DocumentObject dom) { @@ -277,10 +278,10 @@ void RenderFontTable() _rtfWriter.StartContent(); _rtfWriter.WriteControl("fonttbl"); - for (int idx = 0; idx < _fontList.Count; ++idx) + for (int idx = 0; idx < _fontList.Count; idx++) { _rtfWriter.StartContent(); - string name = (string)_fontList[idx]; + string name = _fontList[idx]; _rtfWriter.WriteControl("f", idx); #if true //System.Drawing.Font font = new System.Drawing.Font(name, 12); //any size @@ -311,9 +312,8 @@ void RenderColorTable() //this would indicate index 0 as auto color: //this.rtfWriter.WriteSeparator(); //left away cause there is no auto color in MigraDoc. - foreach (var obj in _colorList) + foreach (var color in _colorList) { - Color color = (Color)obj; _rtfWriter.WriteControl("red", (int)color.R); _rtfWriter.WriteControl("green", (int)color.G); _rtfWriter.WriteControl("blue", (int)color.B); @@ -331,7 +331,7 @@ internal int GetFontIndex(string fontName) return (int)_fontList.IndexOf(fontName); //development purpose exception - throw new ArgumentException(@"Font does not exist in this document’s font table.", "fontName"); + throw new ArgumentException(@"Font does not exist in this document’s font table.", nameof(fontName)); } /// @@ -340,10 +340,10 @@ internal int GetFontIndex(string fontName) internal int GetColorIndex(Color color) { Color clr = color.GetMixedTransparencyColor(); - int idx = (int)_colorList.IndexOf(clr); + int idx = _colorList.IndexOf(clr); // Development purpose exception. if (idx < 0) - throw new ArgumentException(@"Color does not exist in this document’s color table.", "color"); + throw new ArgumentException(@"Color does not exist in this document’s color table.", nameof(color)); return idx; } @@ -352,7 +352,7 @@ internal int GetColorIndex(Color color) /// internal int GetStyleIndex(string styleName) { - return _document.Styles.GetIndex(styleName); + return Document.Styles.GetIndex(styleName); } /// @@ -362,7 +362,7 @@ void RenderStyles() { _rtfWriter.StartContent(); _rtfWriter.WriteControl("stylesheet"); - foreach (var style in _document.Styles) + foreach (var style in Document.Styles) { Debug.Assert(style != null, nameof(style) + " != null"); RendererFactory.CreateRenderer(style, this).Render(); @@ -380,9 +380,8 @@ void RenderListTable() _rtfWriter.StartContent(); _rtfWriter.WriteControlWithStar("listtable"); - foreach (var obj in _listList) + foreach (var lst in _listList) { - ListInfo lst = (ListInfo)obj; ListInfoRenderer lir = new ListInfoRenderer(lst, this); lir.Render(); } @@ -390,9 +389,8 @@ void RenderListTable() _rtfWriter.StartContent(); _rtfWriter.WriteControlWithStar("listoverridetable"); - foreach (var obj in _listList) + foreach (var lst in _listList) { - ListInfo lst = (ListInfo)obj; ListInfoOverrideRenderer lir = new ListInfoOverrideRenderer(lst, this); lir.Render(); @@ -408,7 +406,7 @@ void RenderDocumentArea() RenderInfo(); RenderDocumentFormat(); RenderGlobalPorperties(); - foreach (var sect in _document.Sections) + foreach (var sect in Document.Sections) { Debug.Assert(sect != null, nameof(sect) + " != null"); RendererFactory.CreateRenderer(sect, this).Render(); @@ -439,7 +437,7 @@ void RenderGlobalPorperties() // Word cannot realize the mirror margins property for single sections, // although rtf control words exist for this purpose. // Thus, the mirror margins property is set globally if it’s true for the first section. - var sec = _document.Sections.First as Section; + var sec = Document.Sections.First as Section; if (sec != null) { if (sec.PageSetup.Values.MirrorMargins is not null && sec.PageSetup.MirrorMargins) @@ -475,13 +473,13 @@ internal void RenderSectionProperties() /// void RenderInfo() { - if (_document.Values.Info.IsValueNullOrEmpty()) + if (Document.Values.Info.IsValueNullOrEmpty()) return; _rtfWriter.StartContent(); _rtfWriter.WriteControl("f", 0); // Font with ID 0 is Courier New. See Prepare(). _rtfWriter.WriteControl("info"); - DocumentInfo info = _document.Info; + DocumentInfo info = Document.Info; if (!info.Values.Title.IsValueNullOrEmpty()) { _rtfWriter.StartContent(); @@ -516,29 +514,18 @@ void RenderInfo() /// /// Gets the MigraDoc document that is currently rendered. /// - internal Document Document - { - get { return _document; } - } - - Document _document = null!; + internal Document Document { get; private set; } = null!; /// /// Gets the RtfWriter the document is rendered with. /// internal RtfWriter RtfWriter - { - get { return _rtfWriter; } - } + => _rtfWriter; - internal string WorkingDirectory - { - get { return _workingDirectory; } - } - string _workingDirectory = null!; + internal string WorkingDirectory { get; private set; } = null!; - readonly List _colorList = new List(); - readonly List _fontList = new List(); - readonly List _listList = new List(); + readonly List _colorList = new(); + readonly List _fontList = new(); + readonly List _listList = new(); } } diff --git a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/TextFrameRenderer.cs b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/TextFrameRenderer.cs index 9f79047d..f78ed4ce 100644 --- a/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/TextFrameRenderer.cs +++ b/src/foundation/src/MigraDoc/src/MigraDoc.RtfRendering/RtfRendering/TextFrameRenderer.cs @@ -7,7 +7,6 @@ using MigraDoc.DocumentObjectModel.Shapes; using MigraDoc.DocumentObjectModel.Tables; using MigraDoc.Logging; -using MigraDoc.RtfRendering.Resources; namespace MigraDoc.RtfRendering { @@ -51,7 +50,7 @@ internal override void Render() TextOrientation orient = _textFrame.Orientation; if (orient != TextOrientation.Horizontal && orient != TextOrientation.HorizontalRotatedFarEast) { - MigraDocLogHost.RtfRenderingLogger.LogWarning(Messages2.TextframeContentsNotTurned); + MigraDocLogHost.RtfRenderingLogger.LogWarning(MdRtfMsgs.TextFrameContentsNotTurned.Message); //Debug.WriteLine(Messages2.TextframeContentsNotTurned, "warning"); } } diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/MigraDoc.DocumentObjectModel.Tests.csproj b/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/MigraDoc.DocumentObjectModel.Tests.csproj index 766c721e..c746f081 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/MigraDoc.DocumentObjectModel.Tests.csproj +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/MigraDoc.DocumentObjectModel.Tests.csproj @@ -1,7 +1,7 @@  - net6.0;net472 + net6.0;net8.0;net462 diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/SerializerTests.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/SerializerTests.cs index 1f102def..31cad738 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/SerializerTests.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/SerializerTests.cs @@ -1324,6 +1324,115 @@ public void Test_WriteAndReadMdddl_Section_Header_Not_Empty_And_Paragraphs(int p } } + [Theory] // Generate Section with no, one and two paragraphs, to use and avoid direct paragraph content in section. + [InlineData(0)] + [InlineData(1)] + [InlineData(2)] + public void Test_WriteAndReadMdddl_Section_Three_Headers_And_Paragraphs(int paragraphCount) + { + var doc = new Document(); + + TestHelper.RemoveStyles(doc); + + // Set desired value in doc and write MDDDL. + var section = doc.AddSection(); + section.Headers.Primary.AddParagraph("PrimaryHeaderText"); + section.Headers.FirstPage.AddParagraph("FirstPageHeaderText"); + section.Headers.EvenPage.AddParagraph("EvenPageHeaderText"); + + doc.Values.Sections.Should().HaveCount(1); + section.Should().Be(doc.Sections.First); + + var headers = section.Values.Headers; + headers.Should().NotBeNull(); + + var primaryHeader = headers!.Values.Primary; + primaryHeader.Should().NotBeNull(); + primaryHeader!.Elements.Should().HaveCount(1); + + var firstPageHeader = headers!.Values.FirstPage; + firstPageHeader.Should().NotBeNull(); + firstPageHeader!.Elements.Should().HaveCount(1); + + var evenPageHeader = headers!.Values.EvenPage; + evenPageHeader.Should().NotBeNull(); + evenPageHeader!.Elements.Should().HaveCount(1); + + for (var i = 0; i < paragraphCount; i++) + section.AddParagraph($"ParagraphText{i + 1}"); + + var mdddl = DdlWriter.WriteToString(doc); + + mdddl.Should().Contain("\\primaryheader"); + mdddl.Should().Contain("\\firstpageheader"); + mdddl.Should().Contain("\\evenpageheader"); + + // For 0 there is no paragraph, for 1 the paragraph content is added directly to section due to MDDDL optimization. + if (paragraphCount < 2) + mdddl.Should().NotContain("\\paragraph"); + else + mdddl.Should().Contain("\\paragraph"); + + // Read Mdddl and check if desired value is restored correctly. + var docRead = DdlReader.DocumentFromString(mdddl); + docRead.Values.Sections.Should().HaveCount(1); + + var sectionRead = docRead.Values.Sections!.First as Section; + sectionRead.Should().NotBeNull(); + + var headersRead = sectionRead!.Values.Headers; + headersRead.Should().NotBeNull(); + + var primaryHeaderRead = headersRead!.Values.Primary; + primaryHeaderRead.Should().NotBeNull(); + primaryHeaderRead!.Elements.Should().HaveCount(1); + + var primaryHeaderParagraphRead = primaryHeaderRead.Elements.First as Paragraph; + primaryHeaderParagraphRead.Should().NotBeNull(); + + var primaryHeaderTextRead = primaryHeaderParagraphRead!.Elements.First as Text; + primaryHeaderTextRead.Should().NotBeNull(); + primaryHeaderTextRead!.Content.Should().Be("PrimaryHeaderText"); + + var firstPageHeaderRead = headersRead!.Values.FirstPage; + firstPageHeaderRead.Should().NotBeNull(); + firstPageHeaderRead!.Elements.Should().HaveCount(1); + + var firstPageHeaderParagraphRead = firstPageHeaderRead.Elements.First as Paragraph; + firstPageHeaderParagraphRead.Should().NotBeNull(); + + var firstPageHeaderTextRead = firstPageHeaderParagraphRead!.Elements.First as Text; + firstPageHeaderTextRead.Should().NotBeNull(); + firstPageHeaderTextRead!.Content.Should().Be("FirstPageHeaderText"); + + var evenPageHeaderRead = headersRead!.Values.EvenPage; + evenPageHeaderRead.Should().NotBeNull(); + evenPageHeaderRead!.Elements.Should().HaveCount(1); + + var evenPageHeaderParagraphRead = evenPageHeaderRead.Elements.First as Paragraph; + evenPageHeaderParagraphRead.Should().NotBeNull(); + + var evenPageHeaderTextRead = evenPageHeaderParagraphRead!.Elements.First as Text; + evenPageHeaderTextRead.Should().NotBeNull(); + evenPageHeaderTextRead!.Content.Should().Be("EvenPageHeaderText"); + + if (paragraphCount == 0) + { + sectionRead.Elements.Should().HaveCount(0); + return; + } + + for (var i = 0; i < paragraphCount; i++) + { + var paragraphRead = sectionRead.Elements[i] as Paragraph; + paragraphRead.Should().NotBeNull(); + + var textRead = paragraphRead!.Elements.First as Text; + textRead.Should().NotBeNull(); + textRead!.Content.Should().Be($"ParagraphText{i + 1}"); + } + } + [Fact(Skip = "Escaping bug in current implementation")] public void Test_Write_And_Read_MDDDL_CommentEscaping() { diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/ddlparser/BasicTests.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/ddlparser/BasicTests.cs index 22b695aa..71059cc4 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/ddlparser/BasicTests.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.DocumentObjectModel.Tests/ddlparser/BasicTests.cs @@ -14,30 +14,30 @@ namespace MigraDoc.DocumentObjectModel.Tests [Collection("PDFsharp")] public class BasicTests2 { - [Fact] - public void ResourceTests() - { - DomSR.TestResourceMessages(); - //var r1 = typeof(int); - //var r2 = typeof(int?).IsValueType; - //var r3 = typeof(BorderStyle).IsValueType; - //var r4 = typeof(BorderStyle?).IsValueType; - //var r5 = typeof(Paragraph).IsValueType; - //var r6 = typeof(int?); - //var r7 = typeof(int?); - //var r8 = typeof(int?); - - //var value = new Test1Object(); - //var meta = value.Meta; - - ////_ = typeof(int); - - //var p = new Border(); - //var m = p.Meta; - - //var s = m.GetValue(p, "Style", GV.ReadWrite); - - //m.SetValue(p, "Color", Color.Empty); - } + //[Fact] + //public void ResourceTests() + //{ + // DomSR.TestResourceMessages(); + // //var r1 = typeof(int); + // //var r2 = typeof(int?).IsValueType; + // //var r3 = typeof(BorderStyle).IsValueType; + // //var r4 = typeof(BorderStyle?).IsValueType; + // //var r5 = typeof(Paragraph).IsValueType; + // //var r6 = typeof(int?); + // //var r7 = typeof(int?); + // //var r8 = typeof(int?); + + // //var value = new Test1Object(); + // //var meta = value.Meta; + + // ////_ = typeof(int); + + // //var p = new Border(); + // //var m = p.Meta; + + // //var s = m.GetValue(p, "Style", GV.ReadWrite); + + // //m.SetValue(p, "Color", Color.Empty); + //} } } diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.GBE-Runner/MigraDoc.GBE-Runner.csproj b/src/foundation/src/MigraDoc/tests/MigraDoc.GBE-Runner/MigraDoc.GBE-Runner.csproj index 0436150d..ec813c2b 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.GBE-Runner/MigraDoc.GBE-Runner.csproj +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.GBE-Runner/MigraDoc.GBE-Runner.csproj @@ -2,7 +2,7 @@ Exe - net6.0;net472 + net6.0;net8.0;net462 MigraDoc.GBE_Runner MigraDoc.GBE_Runner.Program diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample-GDI/MigraDoc.GrammarByExample-GDI.csproj b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample-GDI/MigraDoc.GrammarByExample-GDI.csproj index 62f2ccf7..b25f466e 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample-GDI/MigraDoc.GrammarByExample-GDI.csproj +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample-GDI/MigraDoc.GrammarByExample-GDI.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 MigraDoc.GrammarByExample_GDI true true diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample-WPF/MigraDoc.GrammarByExample-WPF.csproj b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample-WPF/MigraDoc.GrammarByExample-WPF.csproj index 119b3723..ec74ce24 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample-WPF/MigraDoc.GrammarByExample-WPF.csproj +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample-WPF/MigraDoc.GrammarByExample-WPF.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 MigraDoc.GrammarByExample_WPF true true diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/MigraDoc.GrammarByExample.csproj b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/MigraDoc.GrammarByExample.csproj index 6cd6fe06..8ca94c86 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/MigraDoc.GrammarByExample.csproj +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/MigraDoc.GrammarByExample.csproj @@ -1,7 +1,7 @@  - net6.0;net472 + net6.0;net8.0;net462 false diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/DdlGbeTestBase.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/DdlGbeTestBase.cs index 883116c0..675abd76 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/DdlGbeTestBase.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/DdlGbeTestBase.cs @@ -8,7 +8,6 @@ #endif using MigraDoc.DocumentObjectModel; using MigraDoc.GrammarByExample; -using PdfSharp.Fonts; using PdfSharp.Quality; #if CORE using PdfSharp.Snippets.Font; @@ -110,7 +109,7 @@ void CompatibilityPatchCallback(Document document) internal static string WslPathHack(string path) { #if !NET6_0_OR_GREATER - // .NET 4.7.2 or .NETStandard 2.0, for Windows only. + // .NET 4.6.2 or .NETStandard 2.0, for Windows only. return path; #else if (OperatingSystem.IsWindows()) @@ -119,7 +118,7 @@ internal static string WslPathHack(string path) } if (OperatingSystem.IsLinux()) { - // Hack: Assume WSL and use drive C:\ instead of D:\. + // Assume WSL and use drive C:\ instead of D:\. return path.Replace(@"D:\", "/mnt/c/").Replace('\\', '/'); } diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/DdlToPdfHelper.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/DdlToPdfHelper.cs index e84558e2..da1f6196 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/DdlToPdfHelper.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/DdlToPdfHelper.cs @@ -140,9 +140,9 @@ public void AppendToResultPdf(string pdfFile, string referenceFile, int pages, u string originalFileName = Path.Combine(OutputDirectory, "!!TestResult_References.pdf"); var pdfOriginalDocument = CreateOrOpenResultFile(originalFileName); PdfPage pageOrg = pdfOriginalDocument.AddPage(); // Page from original/reference PDF. - for (int i = 0; i < total; ++i) + for (int idx = 0; idx < total; idx++) { - bool landscape = ((1 << i) & bitmapLandscape) != 0; + bool landscape = ((1 << idx) & bitmapLandscape) != 0; var page = pdfResultDocument.AddPage(); // Page from generated PDF. page.Orientation = landscape ? PageOrientation.Landscape : PageOrientation.Portrait; @@ -150,11 +150,11 @@ public void AppendToResultPdf(string pdfFile, string referenceFile, int pages, u var box = new XRect(0, 0, page.Width.Point, page.Height.Point); // Copy page. - CopyPdfPage(inputDocument1, gfx, i + 1, box); + CopyPdfPage(inputDocument1, gfx, idx + 1, box); // Write document file name and page number on each page. box.Inflate(0, -10); - gfx.DrawString(String.Format("- {2} - {0} of {1} -", i + 1, pages1, testName), + gfx.DrawString(String.Format("- {2} - {0} of {1} -", idx + 1, pages1, testName), font, XBrushes.Red, box, format); pageOrg.Orientation = page.Orientation; @@ -162,11 +162,11 @@ public void AppendToResultPdf(string pdfFile, string referenceFile, int pages, u var boxOrg = new XRect(0, 0, pageOrg.Width.Point, pageOrg.Height.Point); // Copy page. - CopyPdfPage(inputDocument2, gfxOrg, i + 1, boxOrg); + CopyPdfPage(inputDocument2, gfxOrg, idx + 1, boxOrg); // Write document file name and page number on each page. boxOrg.Inflate(0, -10); - gfxOrg.DrawString(String.Format("- {0} of {1} -", i + 1, pages2), + gfxOrg.DrawString(String.Format("- {0} of {1} -", idx + 1, pages2), font, XBrushes.Red, boxOrg, format); } pdfOriginalDocument.Save(originalFileName); @@ -182,9 +182,9 @@ public void AppendToResultPdf(string pdfFile, string referenceFile, int pages, u string resultFileNameSideBySide = Path.Combine(OutputDirectory, "!!TestResult_side_by_side.pdf"); var pdfResultDocumentSideBySide = CreateOrOpenResultFile(resultFileNameSideBySide); - for (int i = 0; i < total; ++i) + for (int idx = 0; idx < total; idx++) { - bool landscape = ((1 << i) & bitmapLandscape) != 0; + bool landscape = ((1 << idx) & bitmapLandscape) != 0; var page = pdfResultDocumentSideBySide.AddPage(); page.Orientation = landscape ? PageOrientation.Portrait : PageOrientation.Landscape; var gfx = XGraphics.FromPdfPage(page); @@ -199,20 +199,20 @@ public void AppendToResultPdf(string pdfFile, string referenceFile, int pages, u var box = new XRect(0, 0, width, height / 2); // Copy page. - CopyPdfPage(inputDocument1, gfx, i + 1, box); + CopyPdfPage(inputDocument1, gfx, idx + 1, box); // Write document file name and page number on each page. box.Inflate(0, -10); - gfx.DrawString(FormattableString.Invariant($"- {testName} - {i + 1} of {pages1} -"), + gfx.DrawString(FormattableString.Invariant($"- {testName} - {idx + 1} of {pages1} -"), font, XBrushes.Red, box, format); box = new XRect(0, height / 2, width, height / 2); // Copy page - CopyPdfPage(inputDocument2, gfx, i + 1, box); + CopyPdfPage(inputDocument2, gfx, idx + 1, box); // Write document file name and page number on each page. box.Inflate(0, -10); - gfx.DrawString(FormattableString.Invariant($"- {i + 1} of {pages2} -"), + gfx.DrawString(FormattableString.Invariant($"- {idx + 1} of {pages2} -"), font, XBrushes.Red, box, format); } else @@ -222,20 +222,20 @@ public void AppendToResultPdf(string pdfFile, string referenceFile, int pages, u var box = new XRect(0, 0, width / 2, height); // Copy page - CopyPdfPage(inputDocument1, gfx, i + 1, box); + CopyPdfPage(inputDocument1, gfx, idx + 1, box); // Write document file name and page number on each page. box.Inflate(0, -10); - gfx.DrawString(FormattableString.Invariant($"- {testName} - {i + 1} of {pages1} -"), + gfx.DrawString(FormattableString.Invariant($"- {testName} - {idx + 1} of {pages1} -"), font, XBrushes.Red, box, format); box = new XRect(width / 2, 0, width / 2, height); // Copy page. - CopyPdfPage(inputDocument2, gfx, i + 1, box); + CopyPdfPage(inputDocument2, gfx, idx + 1, box); // Write document file name and page number on each page. box.Inflate(0, -10); - gfx.DrawString(FormattableString.Invariant($"- {i + 1} of {pages2} -"), + gfx.DrawString(FormattableString.Invariant($"- {idx + 1} of {pages2} -"), font, XBrushes.Red, box, format); } } diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/TestContext.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/TestContext.cs index c824d4c3..d348e33e 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/TestContext.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/TestContext.cs @@ -32,7 +32,18 @@ public TestContext() #elif WPF const string tag = "WPF"; #endif - var folder = $"Testrun-{tag}-" + now.ToString("yyyy-MM-dd_HH-mm-ss"); +#if NET8_0 + const string tag2 = "NET80"; +#elif NET6_0 + const string tag2 = "NET60"; +#elif NET462 + const string tag2 = "NET462"; +#elif NETSTANDARD2_0 + const string tag2 = "NETstandard20"; +#else + const string tag2 = "UNKOWN"; +#endif + var folder = $"Testrun-{tag}-{tag2}-" + now.ToString("yyyy-MM-dd_HH-mm-ss"); OutputDirectory = folder0 + folder; //Console.WriteLine($"OutputDirectory {OutputDirectory})"); Directory.CreateDirectory(DdlGbeTestBase.WslPathHack(OutputDirectory)); diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/VisualComparisonTestBase.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/VisualComparisonTestBase.cs index 793c0555..f632bd75 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/VisualComparisonTestBase.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.GrammarByExample/helper/VisualComparisonTestBase.cs @@ -11,6 +11,7 @@ using PdfSharp; using PdfSharp.Drawing; using PdfSharp.Pdf; +using PdfSharp.Pdf.Internal; using PdfSharp.Pdf.IO; namespace GdiGrammarByExample @@ -79,13 +80,13 @@ public string CreatePdfFromMdddlFile(string pdfFile, string mdddlPath, string te #endif #else #if CORE - document.Info.Author += "[.NET 4.7.2+ Core build]"; + document.Info.Author += "[.NET 4.6.2+ Core build]"; #elif GDI - document.Info.Author += "[.NET 4.7.2+ GDI build]"; + document.Info.Author += "[.NET 4.6.2+ GDI build]"; #elif WPF - document.Info.Author += "[.NET 4.7.2+ WPF build]"; + document.Info.Author += "[.NET 4.6.2+ WPF build]"; #else - document.Info.Author += "[.NET 4.7.2+ ??? build]"; + document.Info.Author += "[.NET 4.6.2+ ??? build]"; #endif #endif @@ -101,11 +102,13 @@ public string CreatePdfFromDdlString(string pdfFile, string ddlString, string te Document DdlReaderDocumentFromFile(string file) { -#if NET6_0_OR_GREATER - var ansiEncoding = CodePagesEncodingProvider.Instance.GetEncoding(1252)!; -#else - var ansiEncoding = Encoding.GetEncoding(1252); -#endif + //#if NET6_0_OR_GREATER + // var ansiEncoding = CodePagesEncodingProvider.Instance.GetEncoding(1252)!; + //#else + // var ansiEncoding = Encoding.GetEncoding(1252); + //#endif + var ansiEncoding = PdfEncoders.WinAnsiEncoding; + //Console.WriteLine($"DdlReaderDocumentFromFile(string {file})"); Document document; DdlReader? reader = null; @@ -217,9 +220,9 @@ public void AppendToResultPdf(TestContext testContext, string pdfFile, string? r string resultFileNameSideBySide = testContext.AddResultFileEx("!!TestResult_side_by_side.pdf"); var pdfResultDocumentSideBySide = CreateOrOpenResultFile(resultFileNameSideBySide); - for (int i = 0; i < total; ++i) + for (int idx = 0; idx < total; idx++) { - bool landscape = ((1 << i) & bitmapLandscape) != 0; + bool landscape = ((1 << idx) & bitmapLandscape) != 0; var page = pdfResultDocumentSideBySide.AddPage(); page.Orientation = landscape ? PageOrientation.Portrait : PageOrientation.Landscape; var gfx = XGraphics.FromPdfPage(page); @@ -232,20 +235,20 @@ public void AppendToResultPdf(TestContext testContext, string pdfFile, string? r var box = new XRect(0, 0, width, height / 2); // Copy page. - CopyPdfPage(inputDocument1, gfx, i + 1, box); + CopyPdfPage(inputDocument1, gfx, idx + 1, box); // Write document file name and page number on each page. box.Inflate(0, -10); - gfx.DrawString(FormattableString.Invariant($"- {testName} - {i + 1} of {pages1} -"), + gfx.DrawString(FormattableString.Invariant($"- {testName} - {idx + 1} of {pages1} -"), font, XBrushes.Red, box, format); box = new XRect(0, height / 2, width, height / 2); // Copy page. - CopyPdfPage(inputDocument2, gfx, i + 1, box); + CopyPdfPage(inputDocument2, gfx, idx + 1, box); // Write document file name and page number on each page. box.Inflate(0, -10); - gfx.DrawString(FormattableString.Invariant($"- {i + 1} of {pages2} -"), + gfx.DrawString(FormattableString.Invariant($"- {idx + 1} of {pages2} -"), font, XBrushes.Red, box, format); } else @@ -254,21 +257,21 @@ public void AppendToResultPdf(TestContext testContext, string pdfFile, string? r var box = new XRect(0, 0, width / 2, height); // Copy page. - CopyPdfPage(inputDocument1, gfx, i + 1, box); + CopyPdfPage(inputDocument1, gfx, idx + 1, box); // Write document file name and page number on each page. box.Inflate(0, -10); - gfx.DrawString(FormattableString.Invariant($"- {testName} - {i + 1} of {pages1} -"), + gfx.DrawString(FormattableString.Invariant($"- {testName} - {idx + 1} of {pages1} -"), font, XBrushes.Red, box, format); box = new XRect(width / 2, 0, width / 2, height); // Copy page. - CopyPdfPage(inputDocument2, gfx, i + 1, box); + CopyPdfPage(inputDocument2, gfx, idx + 1, box); // Write document file name and page number on each page. box.Inflate(0, -10); - gfx.DrawString(FormattableString.Invariant($"- {i + 1} of {pages2} -"), + gfx.DrawString(FormattableString.Invariant($"- {idx + 1} of {pages2} -"), font, XBrushes.Red, box, format); } } diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests-gdi/MigraDoc.Tests-gdi.csproj b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests-gdi/MigraDoc.Tests-gdi.csproj index 1af88188..f2a51709 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests-gdi/MigraDoc.Tests-gdi.csproj +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests-gdi/MigraDoc.Tests-gdi.csproj @@ -1,63 +1,67 @@  - - net6.0-windows;net472 - true - - - - $(DefineConstants);TRACE;GDI - - - - $(DefineConstants);TRACE;GDI - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + net6.0-windows;net8.0-windows;net462 + true + True + ..\..\..\..\..\StrongnameKey.snk + + + + $(DefineConstants);TRACE;GDI + + + + $(DefineConstants);TRACE;GDI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests-wpf/MigraDoc.Tests-wpf.csproj b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests-wpf/MigraDoc.Tests-wpf.csproj index 21e16d4b..7d4f0ea1 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests-wpf/MigraDoc.Tests-wpf.csproj +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests-wpf/MigraDoc.Tests-wpf.csproj @@ -1,64 +1,68 @@  - - net6.0-windows;net472 - true - true - + + net6.0-windows;net8.0-windows;net462 + true + true + True + ..\..\..\..\..\StrongnameKey.snk + - - $(DefineConstants);TRACE;WPF - + + $(DefineConstants);TRACE;WPF + - - $(DefineConstants);TRACE;WPF - + + $(DefineConstants);TRACE;WPF + - - - - - + + + + + - - - + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/Extensions/XunitHelper.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/Extensions/XunitHelper.cs index d1a79337..209a0881 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/Extensions/XunitHelper.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/Extensions/XunitHelper.cs @@ -24,7 +24,7 @@ public static bool SkipSlowTests() /// /// Gets a value indicating whether slow unit tests should be skipped. - /// This method is used for tests that run slow under .NET Framework 4.7.2, but much faster under .NET 6. + /// This method is used for tests that run slow under .NET Framework 4.6.2, but much faster under .NET 6. /// /// True if slow tests should be skipped. public static bool SkipSlowTestsUnderDotNetFramework() diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/Helper/SecurityTestHelper.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/Helper/SecurityTestHelper.cs new file mode 100644 index 00000000..31fb7813 --- /dev/null +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/Helper/SecurityTestHelper.cs @@ -0,0 +1,67 @@ +// MigraDoc - Creating Documents on the Fly +// See the LICENSE file in the solution root for more information. + +using MigraDoc.DocumentObjectModel; +using MigraDoc.Rendering; +using static PdfSharp.TestHelper.SecurityTestHelper; + +namespace MigraDoc.Tests.Helper +{ + static class SecurityTestHelper + { + public static Document CreateEmptyTestDocument() + { + var doc = new Document(); + return doc; + } + + public static Document CreateStandardTestDocument() + { + var doc = CreateEmptyTestDocument(); + doc.AddSection().AddParagraph().AddText("Text"); + + return doc; + } + + public static PdfDocumentRenderer RenderDocument(Document document) + { + var pdfRenderer = new PdfDocumentRenderer { Document = document }; + pdfRenderer.RenderDocument(); + + return pdfRenderer; + } + + public static PdfDocumentRenderer RenderSecuredDocument(Document document, TestOptions options) + { + var pdfRenderer = new PdfDocumentRenderer { Document = document }; + pdfRenderer.RenderDocument(); + + SecureDocument(pdfRenderer.PdfDocument, options); + + return pdfRenderer; + } + + public static void WriteSecuredTestDocument(Document document, string filename, TestOptions options) + { + var pdfRenderer = RenderSecuredDocument(document, options); + pdfRenderer.Save(filename); + } + + public static PdfDocumentRenderer RenderSecuredStandardTestDocument(TestOptions options) + { + return RenderSecuredDocument(CreateStandardTestDocument(), options); + } + + public static void WriteStandardTestDocument(string filename) + { + var pdfRenderer = RenderDocument(CreateStandardTestDocument()); + pdfRenderer.Save(filename); + } + + public static void WriteSecuredStandardTestDocument(string filename, TestOptions options) + { + var pdfRenderer = RenderSecuredStandardTestDocument(options); + pdfRenderer.Save(filename); + } + } +} diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/ImageFormats.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/ImageFormats.cs index 45688b19..79bbc0b8 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/ImageFormats.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/ImageFormats.cs @@ -17,6 +17,8 @@ #if WPF using System.IO; #endif +using SecurityTestHelper = PdfSharp.TestHelper.SecurityTestHelper; +using SecurityTestHelperMD = MigraDoc.Tests.Helper.SecurityTestHelper; namespace MigraDoc.Tests { @@ -35,8 +37,6 @@ public void Test_Image_Formats() // Create a MigraDoc document. var document = CreateDocument(true); - // ----- Unicode encoding in MigraDoc is demonstrated here. ----- - // Create a renderer for the MigraDoc document. var pdfRenderer = new PdfDocumentRenderer() { @@ -189,7 +189,7 @@ public void Test_Image_Formats_Encrypted_Gdi(SecurityTestHelper.TestOptionsEnum public void Test_Image_Formats_Encrypted(SecurityTestHelper.TestOptionsEnum optionsEnum) #endif { - // Attempt to avoid "image file locked" under .NET 4.7.2. + // Attempt to avoid "image file locked" under .NET 4.6.2. GC.Collect(); GC.WaitForFullGCComplete(); @@ -202,7 +202,7 @@ public void Test_Image_Formats_Encrypted(SecurityTestHelper.TestOptionsEnum opti var document = CreateDocument(true); - var pdfRenderer = SecurityTestHelper.RenderSecuredDocument(document, options); + var pdfRenderer = SecurityTestHelperMD.RenderSecuredDocument(document, options); pdfRenderer.Save(filename); // ReSharper disable once RedundantAssignment pdfRenderer = null; @@ -222,7 +222,7 @@ public void Test_Image_Formats_Encrypted(SecurityTestHelper.TestOptionsEnum opti PdfFileUtility.ShowDocumentIfDebugging(filenameRead); } - // Attempt to avoid "image file locked" under .NET 4.7.2. + // Attempt to avoid "image file locked" under .NET 4.6.2. GC.Collect(); GC.WaitForFullGCComplete(); } @@ -294,7 +294,8 @@ struct TestImage public Unit? Width { get; set; } } - readonly TestImage[] _testImages = { + readonly TestImage[] _testImages = + [ // JPEG new() { Path = @"jpeg\windows7problem.jpg", Comment = "JPEG image", Width = "12cm" }, new() { Path = @"jpeg\TruecolorNoAlpha.jpg", Comment = "JPEG image" }, @@ -346,6 +347,6 @@ struct TestImage new() { Path = @"misc\Rose (RGB 8).tif", Comment = "TIFF, not supported by Core build" }, new() { Path = @"misc\Test.gif", Comment = "GIF, not supported by Core build" }, new() { Path = @"misc\Test.png", Comment = "PNG image" } - }; + ]; } } diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/MigraDoc.Tests.csproj b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/MigraDoc.Tests.csproj index 4b9ae50f..60f0258a 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/MigraDoc.Tests.csproj +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/MigraDoc.Tests.csproj @@ -1,7 +1,9 @@  - net6.0;net472 + net6.0;net8.0;net462 + True + ..\..\..\..\..\StrongnameKey.snk @@ -28,6 +30,8 @@ + + diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/MigraDoc.Tests.csproj.DotSettings b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/MigraDoc.Tests.csproj.DotSettings index 16c7a3d1..632c2681 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/MigraDoc.Tests.csproj.DotSettings +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/MigraDoc.Tests.csproj.DotSettings @@ -1,2 +1,2 @@  - CSharp110 \ No newline at end of file + CSharp120 \ No newline at end of file diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/PageSizeTests.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/PageSizeTests.cs new file mode 100644 index 00000000..a1be7624 --- /dev/null +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/PageSizeTests.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MigraDoc.DocumentObjectModel; +using MigraDoc.DocumentObjectModel.Fields; +using MigraDoc.Rendering; +using PdfSharp.Quality; +using Xunit; + +namespace MigraDoc.Tests +{ + [Collection("PDFsharp")] + public class PageSizeTests + { + [Fact] + public void Test_Image_Formats() + { + // Create a MigraDoc document. + var document = CreateDocument(); + + // Create a renderer for the MigraDoc document. + var pdfRenderer = new PdfDocumentRenderer() + { + // Associate the MigraDoc document with a renderer. + Document = document + }; + + // Layout and render document to PDF. + pdfRenderer.RenderDocument(); + + // Save the document... + var filename = PdfFileUtility.GetTempPdfFileName("Page_Formats"); + pdfRenderer.PdfDocument.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); + } + + private Document CreateDocument() + { + var document = new Document(); + + // Add a section to the document. + var section = document.AddSection(); + + section.AddParagraph("Default section."); + + // Create the primary footer. + var footer = section.Footers.Primary; + + // Add content to footer. + var paragraph = footer.AddParagraph(); + paragraph.Add(new DateField { Format = "yyyy/MM/dd HH:mm:ss" }); + paragraph.Format.Alignment = ParagraphAlignment.Center; + +#if DEBUG___ + for (PageFormat pf = PageFormat.Ledger; pf <= PageFormat.Ledger; pf++) + { + section = document.AddSection(); + section.PageSetup.PageFormat = pf; + section.PageSetup.Orientation = Orientation.Portrait; + section.AddParagraph($"Custom section {pf.ToString()}."); + + section = document.AddSection(); + section.PageSetup.PageFormat = pf; + section.PageSetup.Orientation = Orientation.Landscape; + section.AddParagraph($"Custom section {pf.ToString()} Landscape."); + } +#endif + + for (PageFormat pf = PageFormat.A0; pf <= PageFormat.P11x17; pf++) + { + section = document.AddSection(); + section.PageSetup.PageFormat = pf; + section.PageSetup.Orientation = Orientation.Portrait; + section.AddParagraph($"Custom section {pf.ToString()}."); + + section = document.AddSection(); + section.PageSetup.PageFormat = pf; + section.PageSetup.Orientation = Orientation.Landscape; + section.AddParagraph($"Custom section {pf.ToString()} Landscape."); + } + + return document; + } + } +} diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/RtfRendererTests.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/RtfRendererTests.cs index 2bfce0cb..25acd196 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/RtfRendererTests.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/RtfRendererTests.cs @@ -832,11 +832,7 @@ public void Test_Heading_Border() var bottomBorderPart = rowBorderParts[3]; bottomBorderPart.Should().StartWith("b", "last border should be bottom border"); -#if NET6_0_OR_GREATER || true bottomBorderPart[1..].Should().Be(rtfHeadingBottomString, "heading bottom border should be defined heading bottom border"); -#else - bottomBorderPart.Substring(1).Should().Be(rtfHeadingBottomString, "heading bottom border should be defined heading bottom border"); -#endif // Row 1. rowBorderParts = rowsByBorders[1]; @@ -848,11 +844,7 @@ public void Test_Heading_Border() bottomBorderPart = rowBorderParts[3]; bottomBorderPart.Should().StartWith("b", "last border should be bottom border"); -#if NET6_0_OR_GREATER || true bottomBorderPart[1..].Should().Be(rtfBottomString, "row 1 bottom border should be defined content bottom border"); -#else - bottomBorderPart.Substring(1).Should().Be(rtfBottomString, "row 1 bottom border should be defined content bottom border"); -#endif // Row 2-4. for (var r = 2; r < 5; r++) @@ -861,19 +853,11 @@ public void Test_Heading_Border() topBorderPart = rowBorderParts[0]; topBorderPart.Should().StartWith("t", "first border should be top border"); -#if NET6_0_OR_GREATER || true topBorderPart[1..].Should().Be(rtfBottomString, $"row {r} top border should be the defined content bottom border of the top neighbor row"); -#else - topBorderPart.Substring(1).Should().Be(rtfBottomString, $"row {r} top border should be the defined content bottom border of the top neighbor row"); -#endif bottomBorderPart = rowBorderParts[3]; bottomBorderPart.Should().StartWith("b", "last border should be bottom border"); -#if NET6_0_OR_GREATER || true bottomBorderPart[1..].Should().Be(rtfBottomString, $"row {r} bottom border should be defined content bottom border"); -#else - bottomBorderPart.Substring(1).Should().Be(rtfBottomString, $"row {r} bottom border should be defined content bottom border"); -#endif } } } diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/SecurityTests.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/SecurityTests.cs index c4cedb49..a9723f84 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/SecurityTests.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/SecurityTests.cs @@ -1,7 +1,6 @@ // MigraDoc - Creating Documents on the Fly // See the LICENSE file in the solution root for more information. -using System.Runtime.InteropServices; using PdfSharp.Pdf; using PdfSharp.Pdf.IO; using PdfSharp.Pdf.Security; @@ -17,7 +16,8 @@ using PdfSharp.Logging; using PdfSharp.TestHelper; using PdfSharp.TestHelper.Analysis.ContentStream; -using static MigraDoc.Tests.SecurityTestHelper; +using static PdfSharp.TestHelper.SecurityTestHelper; +using static MigraDoc.Tests.Helper.SecurityTestHelper; namespace MigraDoc.Tests { diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/SpaceBeforeTests.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/SpaceBeforeTests.cs index 171b1b38..6a04fa6b 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/SpaceBeforeTests.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/SpaceBeforeTests.cs @@ -91,9 +91,9 @@ static Document CreateDocument() paragraph.Add(new DateField { Format = "yyyy/MM/dd HH:mm:ss" }); paragraph.Format.Alignment = ParagraphAlignment.Center; - for (int i = 1; i <= 10; ++i) + for (int idx = 1; idx <= 10; idx++) { - paragraph = header.AddParagraph("Paragraph " + i); + paragraph = header.AddParagraph("Paragraph " + idx); paragraph.Format.Alignment = ParagraphAlignment.Center; } diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/TableTests.cs b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/TableTests.cs index dfdf5f9e..604b3547 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/TableTests.cs +++ b/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/TableTests.cs @@ -107,5 +107,58 @@ public void Create_a_cloned_table() // ...and start a viewer. PdfFileUtility.ShowDocumentIfDebugging(filename); } + + [Fact] + public void Create_a_table_with_cloned_rows() + { + // Create a MigraDoc document. + var document = new Document(); + + // Add a section to the document. + var section = document.AddSection(); + + // Add a paragraph to the section. + var paragraph = section.AddParagraph("Dummy"); + + Style style = document.Styles[StyleNames.Normal]!; + style.Font.Name = "Arial"; + + var sec = document.LastSection; + var p = sec.AddParagraph("Creating a table"); + var table = sec.AddTable(); + table.Tag = "Original"; + table.AddColumn("2cm"); + table.AddColumn("2cm"); + var row = table.AddRow(); + row[0].AddParagraph("H1"); + row[1].AddParagraph("H2"); + row.HeadingFormat = true; + row = table.AddRow(); + row[0].AddParagraph("C1"); + row[1].AddParagraph("C2"); + row = table.Rows[1].Clone(); + table.Rows.Add(row); + row = table.Rows[2].Clone(); + table.Rows.Add(row); + row = table.Rows[1].Clone(); + table.Rows.Add(row); + sec.AddParagraph("End of table test"); + + // Create a renderer for the MigraDoc document. + var pdfRenderer = new PdfDocumentRenderer() + { + // Associate the MigraDoc document with a renderer. + Document = document + }; + + // Layout and render document to PDF. + pdfRenderer.RenderDocument(); + + // Save the document... + var filename = PdfFileUtility.GetTempPdfFileName("ClonedTable"); + pdfRenderer.PdfDocument.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); + } } } diff --git a/src/foundation/src/PDFsharp/docs/AboutFonts.md b/src/foundation/src/PDFsharp/docs/AboutFonts.md index 5fad215b..664e05b4 100644 --- a/src/foundation/src/PDFsharp/docs/AboutFonts.md +++ b/src/foundation/src/PDFsharp/docs/AboutFonts.md @@ -1,4 +1,4 @@ -# Fonts +# Fonts **This document is under construction** @@ -112,7 +112,7 @@ The class **XGlyphTypeface** specifies a physical font face that corresponds to While a **XFont** or a **XTypeface** specifiy what you want to get from the font resolver, a **XGlypeTypeface** identifies what you actually get. For instance, when you specify you want to get an italic typeface of a particular font family, you may actually get a font face of a non-italic physical font, but the **XGlyphTypeface** specifies that the italic style is simulated -by skewing characters from the font face by 20. +by skewing characters from the font face by 20�. The concept was taken from WPF. @@ -123,7 +123,7 @@ PDFsharp only supports TrueType font files. TrueType font collections and OpenTy ### XStyleSimulations The class **XStyleSimulation** describes the simulation style of a font. -Bold, Italic, or both can be simulated for a font that doesnt have these faces physically. +Bold, Italic, or both can be simulated for a font that doesn�t have these faces physically. The concept was taken from WPF. PDFsharp only simules the italic face by sloping the font 20 degrees to the right. diff --git a/src/foundation/src/PDFsharp/docs/AboutImages.md b/src/foundation/src/PDFsharp/docs/AboutImages.md index fb3eeec7..d081e32f 100644 --- a/src/foundation/src/PDFsharp/docs/AboutImages.md +++ b/src/foundation/src/PDFsharp/docs/AboutImages.md @@ -1,3 +1,3 @@ -# Images +# Images ## Image classes diff --git a/src/foundation/src/PDFsharp/docs/Coding-Issues.md b/src/foundation/src/PDFsharp/docs/Coding-Issues.md new file mode 100644 index 00000000..02fa2da6 --- /dev/null +++ b/src/foundation/src/PDFsharp/docs/Coding-Issues.md @@ -0,0 +1,56 @@ +# Coding issues + +This article is about coding issues that may/should be fixed over time. + +## Console output + +We habe `Console.WriteLine` in the source code. + +* Remove every occurence of `Console.WriteLine` used for diagnostic purposes +* Use `(PdfSharp/MigraDoc)LogHost.Logger`instead + +## Logging + +* Use semantic logging instead of string interpolation +* Use the correct logging category + +## Asserts vs. exceptions + +Asserts are for checking correctness of code, NOT for checking correctness of external ressources like images or PDF files. + +Exceptions are for external ressources that does not fulfill the expectations. + +## Nested types + +We use sometimes public types nested in other public types. +Public types must be always top-level types. + +You can use nested types (classes, structres or enums), but only when they are private or internal + +Here is a list of such type found by Martin: + +**PDFsharp** +* PngBuilder.SaveOptions +* XGraphics.SpaceTransformer +* XGraphics.XGraphicsInternals +* PdfArray.ArrayElements +* PdfDictionary.DictionaryElements +* PdfDictionary.PdfStream +* PdfDictionary.PdfStream.Keys +* ... .Keys +* PdfName.PdfXNameComparer +* PdfPage.InheritablePageKeys +* PdfAcroField.PdfAcroFieldCollection +* PdfCrossReferenceStream.CrossReferenceStreamEntry +* PdfFormXObjectTable.Selector +* PdfImageTable.ImageSelector +* PdfCryptFilter.CryptFilterMethod + +**MigraDoc.ObjectModel** + +* Capabilities.FeatureNotAvailableAction +* Border.BorderValues +* ... .XxxValues + +**MigraDoc.Rendering** +* DocumentRenderer.PrepareDocumentProgressEventArgs diff --git a/src/foundation/src/PDFsharp/docs/Notebook.md b/src/foundation/src/PDFsharp/docs/Notebook.md index 81398e07..db7b5c80 100644 --- a/src/foundation/src/PDFsharp/docs/Notebook.md +++ b/src/foundation/src/PDFsharp/docs/Notebook.md @@ -1,6 +1,8 @@ -# Notebook +# Notebook +## Changes in 6.2 + ## Changes in 6.1 @@ -8,7 +10,6 @@ * Support for .NET Standard and .NET Framework 4.72 * Logging factory can be set. - ## New C# features PDFsharp uses should be compatible with .NET Framework 4.7x and .NET Standard 2.0. @@ -28,8 +29,8 @@ PDFsharp currently uses the following: } #endif ``` - See [manuelroemer/IsExternalInit](https://github.com/manuelroemer/IsExternalInit). Why a NuGet package - with an empty class? + See [manuelroemer/IsExternalInit](https://github.com/manuelroemer/IsExternalInit). + Why a NuGet package with an empty class? * **Indices and ranges** The new range and index from end operator make C# code more readable. diff --git a/src/foundation/src/PDFsharp/docs/PortingNotes.md b/src/foundation/src/PDFsharp/docs/PortingNotes.md index 144e41a4..33585591 100644 --- a/src/foundation/src/PDFsharp/docs/PortingNotes.md +++ b/src/foundation/src/PDFsharp/docs/PortingNotes.md @@ -31,4 +31,12 @@ Drop * Drop code from Silverlight, Windows Phone, WinRT, and other UWP versions. -* + +## From 4.7.2 to 4.6.2 + +Replace **net472** with **net462** in all `*.csproj` and in all `*.nuspec` files. + +Add (or change) `NET462` in the following files: +`CompilerServices.cs` line 56 +`FlateDecode.cs` line 34 + diff --git a/src/foundation/src/PDFsharp/docs/README.md b/src/foundation/src/PDFsharp/docs/README.md new file mode 100644 index 00000000..3e559559 --- /dev/null +++ b/src/foundation/src/PDFsharp/docs/README.md @@ -0,0 +1,3 @@ +# PDFsharp internal docs + +The docs folder contains internal notes and documentation. \ No newline at end of file diff --git a/src/foundation/src/PDFsharp/docs/pdf-features/PDF-A.md b/src/foundation/src/PDFsharp/docs/pdf-features/PDF-A.md new file mode 100644 index 00000000..e56353c6 --- /dev/null +++ b/src/foundation/src/PDFsharp/docs/pdf-features/PDF-A.md @@ -0,0 +1,9 @@ +# PDF/A + +We use [veraPDF](https://docs.verapdf.org/) to check PDF files to be PDF/A conform. +The goal is to make it PDF/A-3 conform, same as Microsoft Word do. + +Modification in PDFsharp done for PDF/A conformance are tagged with `#PDF-A`. + +## Current issues + diff --git a/src/foundation/src/PDFsharp/docs/pdf/Strings.md b/src/foundation/src/PDFsharp/docs/pdf/Strings.md new file mode 100644 index 00000000..e44d1a96 --- /dev/null +++ b/src/foundation/src/PDFsharp/docs/pdf/Strings.md @@ -0,0 +1,7 @@ +# Strings + +This article is about the **PdfString** class. + +## Notes +* The public interface uses **System.String** only which is always UTF-16(BE) Unicode for all fonts that are no symbol fonts. +* \ No newline at end of file diff --git a/src/foundation/src/PDFsharp/features/PDFsharp.Features-gdi/PDFsharp.Features-gdi.csproj b/src/foundation/src/PDFsharp/features/PDFsharp.Features-gdi/PDFsharp.Features-gdi.csproj index 81b5728c..0bb0db5e 100644 --- a/src/foundation/src/PDFsharp/features/PDFsharp.Features-gdi/PDFsharp.Features-gdi.csproj +++ b/src/foundation/src/PDFsharp/features/PDFsharp.Features-gdi/PDFsharp.Features-gdi.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net462 true PDFsharp.Features true @@ -38,6 +38,8 @@ + + diff --git a/src/foundation/src/PDFsharp/features/PDFsharp.Features-wpf/PDFsharp.Features-wpf.csproj b/src/foundation/src/PDFsharp/features/PDFsharp.Features-wpf/PDFsharp.Features-wpf.csproj index 42c2fd19..95f17553 100644 --- a/src/foundation/src/PDFsharp/features/PDFsharp.Features-wpf/PDFsharp.Features-wpf.csproj +++ b/src/foundation/src/PDFsharp/features/PDFsharp.Features-wpf/PDFsharp.Features-wpf.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net462 true PDFsharp.Features true @@ -38,6 +38,8 @@ + + diff --git a/src/foundation/src/PDFsharp/features/PDFsharp.Features.Runner-gdi/PDFsharp.Features.Runner-gdi.csproj b/src/foundation/src/PDFsharp/features/PDFsharp.Features.Runner-gdi/PDFsharp.Features.Runner-gdi.csproj index dba78fcb..3b391394 100644 --- a/src/foundation/src/PDFsharp/features/PDFsharp.Features.Runner-gdi/PDFsharp.Features.Runner-gdi.csproj +++ b/src/foundation/src/PDFsharp/features/PDFsharp.Features.Runner-gdi/PDFsharp.Features.Runner-gdi.csproj @@ -2,7 +2,7 @@ Exe - net6.0-windows;net472 + net6.0-windows;net462 true PDFsharp.Features true diff --git a/src/foundation/src/PDFsharp/features/PDFsharp.Features.Runner-wpf/PDFsharp.Features.Runner-wpf.csproj b/src/foundation/src/PDFsharp/features/PDFsharp.Features.Runner-wpf/PDFsharp.Features.Runner-wpf.csproj index 6d70f3cd..9f46155e 100644 --- a/src/foundation/src/PDFsharp/features/PDFsharp.Features.Runner-wpf/PDFsharp.Features.Runner-wpf.csproj +++ b/src/foundation/src/PDFsharp/features/PDFsharp.Features.Runner-wpf/PDFsharp.Features.Runner-wpf.csproj @@ -2,7 +2,7 @@ Exe - net6.0-windows;net472 + net6.0-windows;net462 true PDFsharp.Features true diff --git a/src/foundation/src/PDFsharp/features/PdfSharp.Features.Runner/PdfSharp.Features.Runner.csproj b/src/foundation/src/PDFsharp/features/PdfSharp.Features.Runner/PdfSharp.Features.Runner.csproj index 0d98aa4e..5a877abf 100644 --- a/src/foundation/src/PDFsharp/features/PdfSharp.Features.Runner/PdfSharp.Features.Runner.csproj +++ b/src/foundation/src/PDFsharp/features/PdfSharp.Features.Runner/PdfSharp.Features.Runner.csproj @@ -1,8 +1,8 @@ - + Exe - net6.0;net472 + net6.0;net462 CORE diff --git a/src/foundation/src/PDFsharp/features/PdfSharp.Features.Runner/Program.cs b/src/foundation/src/PDFsharp/features/PdfSharp.Features.Runner/Program.cs index 8d955f5d..4893e1c8 100644 --- a/src/foundation/src/PDFsharp/features/PdfSharp.Features.Runner/Program.cs +++ b/src/foundation/src/PDFsharp/features/PdfSharp.Features.Runner/Program.cs @@ -7,6 +7,7 @@ //using PdfSharp.Quality; //using PdfSharp.Snippets.Font; +using PdfSharp.UniversalAccessibility; using Features = PdfSharp.Features.PdfSharpFeatures; namespace PdfSharp.Features @@ -31,7 +32,7 @@ static void Main(string[] args) //features[PdfSharpFeatures.Names.Drawing_paths_Paths__PathMisc].Run(); //features[PdfSharpFeatures.Names.Drawing_paths_Paths__PathShapes].Run(); //features[PdfSharpFeatures.Names.Drawing_paths_Paths__PathText].Run(); - features[PdfSharpFeatures.Names.Drawing_paths_Paths__PathWpf].Run(); + //features[PdfSharpFeatures.Names.Drawing_paths_Paths__PathWpf].Run(); // Drawing/graphics //features[PdfSharpFeatures.Names.Drawing_graphics_GraphicsUnit__Upwards].Run(); @@ -44,6 +45,13 @@ static void Main(string[] args) //features[PdfSharpFeatures.Names.Font_encoding_Encodings_AnsiEncoding].Run(); + // Pdf/annotations + + // Pdf/pdfa + features[PdfSharpFeatures.Names.Pdf_pdfa_PdfA].Run(); + + + // === reviewed up to here === //Action act = () => new Drawing.Paths().PathCurves(); diff --git a/src/foundation/src/PDFsharp/features/PdfSharp.Features/Drawing/lines/Lines1.cs b/src/foundation/src/PDFsharp/features/PdfSharp.Features/Drawing/lines/Lines1.cs index 5a0257c4..aa1210e2 100644 --- a/src/foundation/src/PDFsharp/features/PdfSharp.Features/Drawing/lines/Lines1.cs +++ b/src/foundation/src/PDFsharp/features/PdfSharp.Features/Drawing/lines/Lines1.cs @@ -63,7 +63,7 @@ public override void RenderSnippet(XGraphics gfx) { // Custom pattern //pen.DashStyle = XDashStyle.Custom; - DashPattern = new[] { 3, 1, 2.5, 1.5 }, + DashPattern = [3, 1, 2.5, 1.5], Width = 7, DashOffset = 1 }; diff --git a/src/foundation/src/PDFsharp/features/PdfSharp.Features/Font/RenderInstalledFonts.cs b/src/foundation/src/PDFsharp/features/PdfSharp.Features/Font/RenderInstalledFonts.cs index a24e9e71..14a06063 100644 --- a/src/foundation/src/PDFsharp/features/PdfSharp.Features/Font/RenderInstalledFonts.cs +++ b/src/foundation/src/PDFsharp/features/PdfSharp.Features/Font/RenderInstalledFonts.cs @@ -21,7 +21,7 @@ public void RenderInstalledFontsTest() protected static void RenderSnippetAsPdf(RenderInstalledFontsSnippet snippet) { snippet.RenderSnippetAsPdfMultiPage(); -#if !UWP +#if !WUI snippet.SaveAndShowFile(snippet.PdfBytes, "Test_tempfile.pdf", true); #else snippet.UwpSaveAndShowFile(snippet.PdfBytes, "Test_tempfile.pdf", true); @@ -52,13 +52,13 @@ public class RenderInstalledFontsSnippet : Snippet const int FaceOffset = 20; // ReSharper disable once FieldCanBeMadeReadOnly.Local - /*readonly*/ List _fonts = new List(); + /*readonly*/ List _fonts = new(); int _fontIdx = -1; // Fonts starting with one of the strings in _excludedFonts* are excluded. Use "/r", "/b", "/i", "/bi" to exclude only regular, bold, italic or bolditalic face (Combine it to exclude several faces: e.g. "/b/i/bi"). - readonly List _excludedFonts = new List(); - readonly List _excludedFontsUnicode = new List(); - readonly List _excludedFontsWinAnsi = new List { "Myriad Pro", "rotis" }; + readonly List _excludedFonts = []; + readonly List _excludedFontsUnicode = []; + readonly List _excludedFontsWinAnsi = ["Myriad Pro", "rotis"]; XFont? _headingFont; XFont? _exceptionFont; diff --git a/src/foundation/src/PDFsharp/features/PdfSharp.Features/Font/RotisWinAnsiTester.cs b/src/foundation/src/PDFsharp/features/PdfSharp.Features/Font/RotisWinAnsiTester.cs index e3d45cbe..fe5d790f 100644 --- a/src/foundation/src/PDFsharp/features/PdfSharp.Features/Font/RotisWinAnsiTester.cs +++ b/src/foundation/src/PDFsharp/features/PdfSharp.Features/Font/RotisWinAnsiTester.cs @@ -325,7 +325,7 @@ public byte[] GetFont(string faceName) #endif } // PDFsharp never calls GetFont with a face name that was not returned by ResolveTypeface. - throw new ArgumentException(String.Format("Invalid face name '{0}'", faceName)); + throw new ArgumentException($"Invalid face name '{faceName}'"); } } diff --git a/src/foundation/src/PDFsharp/features/PdfSharp.Features/Pdf/annotations/LinkAnnotations.cs b/src/foundation/src/PDFsharp/features/PdfSharp.Features/Pdf/annotations/LinkAnnotations.cs index b4d44de6..d44c99ff 100644 --- a/src/foundation/src/PDFsharp/features/PdfSharp.Features/Pdf/annotations/LinkAnnotations.cs +++ b/src/foundation/src/PDFsharp/features/PdfSharp.Features/Pdf/annotations/LinkAnnotations.cs @@ -5,7 +5,7 @@ using PdfSharp.Quality; #pragma warning disable 1591 -namespace PdfSharp.Features.Annotations +namespace PdfSharp.Features.Pdf { public class LinkAnnotations { diff --git a/src/foundation/src/PDFsharp/features/PdfSharp.Features/Pdf/pdfa/PDF-A.cs b/src/foundation/src/PDFsharp/features/PdfSharp.Features/Pdf/pdfa/PDF-A.cs new file mode 100644 index 00000000..205f5a58 --- /dev/null +++ b/src/foundation/src/PDFsharp/features/PdfSharp.Features/Pdf/pdfa/PDF-A.cs @@ -0,0 +1,79 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using Microsoft.Extensions.Logging; +using PdfSharp.Drawing; +using PdfSharp.Logging; +using PdfSharp.Pdf; +using PdfSharp.Quality; +using PdfSharp.UniversalAccessibility; + +#pragma warning disable 1591 +namespace PdfSharp.Features.Pdf +{ + public class PdfA + { + public void CreatePdfA() + { + using var loggerFactory = LoggerFactory.Create(builder => + { + builder + .AddFilter("PDFsharp", LogLevel.Warning) + .AddFilter(_ => true) + .AddConsole(); + }); + LogHost.Factory = loggerFactory; + + // Create a new PDF document. + var document = new PdfDocument(); + document.ViewerPreferences.FitWindow = true; + document.PageLayout = PdfPageLayout.SinglePage; + document.Info.Title = "Created with PDFsharp"; + document.Info.Author = "PDFsharp team"; + document.Info.Subject = "Hello, World!"; + + // Get the manager for universal accessibility. + var uaManager = UAManager.ForDocument(document); + uaManager.SetDocumentLanguage("en-US"); + + // Get structure builder. + var sb = uaManager.StructureBuilder; + + // Create an empty page in this document. + var page = document.AddPage(); + + sb.BeginElement(PdfBlockLevelElementTag.Paragraph); + { + + // Get an XGraphics object for drawing on this page. + var gfx = XGraphics.FromPdfPage(page); + + // Draw two lines with a red default pen. + var width = page.Width.Point; + var height = page.Height.Point; + gfx.DrawLine(XPens.Red, 0, 0, width, height); + gfx.DrawLine(XPens.Red, width, 0, 0, height); + + // Draw a circle with a red pen which is 1.5 point thick. + var r = width / 5; + gfx.DrawEllipse(new XPen(XColors.Red, 1.5), XBrushes.White, + new XRect(width / 2 - r, height / 2 - r, 2 * r, 2 * r)); + + // Create a font. + var font = new XFont("Times New Roman", 20, XFontStyleEx.BoldItalic); + + // Draw the text. + gfx.DrawString("Hello, PDFsharp!", font, XBrushes.Black, + new XRect(0, 0, width, height), XStringFormats.Center); + } + sb.End(); + + // Save the document... + var fullName = PdfFileUtility.GetTempPdfFullFileName("Features/Pdf-A/Test1" + Capabilities.Build.BuildTag); + document.Save(fullName); + + // ...and start a viewer. + PdfFileUtility.ShowDocument(fullName); + } + } +} diff --git a/src/foundation/src/PDFsharp/features/PdfSharp.Features/PdfSharp.Features.csproj.DotSettings b/src/foundation/src/PDFsharp/features/PdfSharp.Features/PdfSharp.Features.csproj.DotSettings index e95e3eff..ca302dac 100644 --- a/src/foundation/src/PDFsharp/features/PdfSharp.Features/PdfSharp.Features.csproj.DotSettings +++ b/src/foundation/src/PDFsharp/features/PdfSharp.Features/PdfSharp.Features.csproj.DotSettings @@ -3,4 +3,5 @@ True True True - True \ No newline at end of file + True + True \ No newline at end of file diff --git a/src/foundation/src/PDFsharp/features/PdfSharp.Features/PdfSharpFeatures.cs b/src/foundation/src/PDFsharp/features/PdfSharp.Features/PdfSharpFeatures.cs index c2e5c5ee..9aba016b 100644 --- a/src/foundation/src/PDFsharp/features/PdfSharp.Features/PdfSharpFeatures.cs +++ b/src/foundation/src/PDFsharp/features/PdfSharp.Features/PdfSharpFeatures.cs @@ -30,6 +30,12 @@ public static class Names // Font/encoding public const string Font_encoding_Encodings_AnsiEncoding = "Font/encoding/Encodings:AnsiEncoding"; + + // Pdf/annotations + + // Pdf/pdfa + public const string Pdf_pdfa_PdfA = "Pdf/pdfa/PDFA:Create"; + } // ReSharper restore InconsistentNaming @@ -57,6 +63,11 @@ public static class Names // Font/encoding { Names.Font_encoding_Encodings_AnsiEncoding, new(Names.Font_encoding_Encodings_AnsiEncoding, () => new Font.Encodings().AnsiEncodingTable()) }, + // Pdf/annotations + + // Pdf/pdfa + { Names.Pdf_pdfa_PdfA, new(Names.Pdf_pdfa_PdfA, () => new Pdf.PdfA().CreatePdfA()) }, + }; public FeatureAction this[string name] => Features[name]; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj b/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj index 023351e0..7a99cdfc 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj +++ b/src/foundation/src/PDFsharp/src/PdfSharp-gdi/PdfSharp-gdi.csproj @@ -2,7 +2,7 @@ library - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true PdfSharp true @@ -16,11 +16,11 @@ true - + 0 - + 0 @@ -175,6 +175,7 @@ + @@ -185,6 +186,8 @@ + + @@ -256,6 +259,7 @@ + @@ -306,11 +310,6 @@ - - - - - @@ -320,6 +319,18 @@ + + + + + + + + + + + + @@ -334,6 +345,7 @@ + @@ -389,13 +401,11 @@ + - - - @@ -407,16 +417,9 @@ - - - - - - - - + @@ -425,4 +428,8 @@ + + + + diff --git a/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj b/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj index ad4b551b..aba01182 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj +++ b/src/foundation/src/PDFsharp/src/PdfSharp-wpf/PdfSharp-wpf.csproj @@ -2,7 +2,7 @@ library - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true PdfSharp true @@ -15,11 +15,11 @@ true - + 0 - + 0 @@ -174,6 +174,7 @@ + @@ -184,6 +185,8 @@ + + @@ -255,6 +258,7 @@ + @@ -305,11 +309,6 @@ - - - - - @@ -319,6 +318,18 @@ + + + + + + + + + + + + @@ -333,6 +344,7 @@ + @@ -388,13 +400,11 @@ + - - - @@ -410,15 +420,7 @@ - - - - - - - - - + @@ -427,8 +429,8 @@ - + + + diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting-gdi/PdfSharp.Charting-gdi.csproj b/src/foundation/src/PDFsharp/src/PdfSharp.Charting-gdi/PdfSharp.Charting-gdi.csproj index 1d359784..f17a5188 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting-gdi/PdfSharp.Charting-gdi.csproj +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting-gdi/PdfSharp.Charting-gdi.csproj @@ -1,306 +1,115 @@  - - library - net6.0-windows;net472 - true - PdfSharp.Charting - true - True - ..\..\..\..\..\StrongnameKey.snk - + + library + net6.0-windows;net8.0-windows;net462 + true + PdfSharp.Charting + true + True + ..\..\..\..\..\StrongnameKey.snk + - - true - + + true + - - - Charting.Renderers\AreaChartRenderer.cs - - - Charting.Renderers\AreaPlotAreaRenderer.cs - - - Charting.Renderers\AxisRenderer.cs - - - Charting.Renderers\AxisTitleRenderer.cs - - - Charting.Renderers\BarChartRenderer.cs - - - Charting.Renderers\BarClusteredLegendRenderer.cs - - - Charting.Renderers\BarClusteredPlotAreaRenderer.cs - - - Charting.Renderers\BarDataLabelRenderer.cs - - - Charting.Renderers\BarGridlinesRenderer.cs - - - Charting.Renderers\BarPlotAreaRenderer.cs - - - Charting.Renderers\BarStackedPlotAreaRenderer.cs - - - Charting.Renderers\ChartRenderer.cs - - - Charting.Renderers\Colors.cs - - - Charting.Renderers\ColumnChartRenderer.cs - - - Charting.Renderers\ColumnClusteredPlotAreaRenderer.cs - - - Charting.Renderers\ColumnDataLabelRenderer.cs - - - Charting.Renderers\ColumnLikeChartRenderer.cs - - - Charting.Renderers\ColumnLikeGridlinesRenderer.cs - - - Charting.Renderers\ColumnLikeLegendRenderer.cs - - - Charting.Renderers\ColumnLikePlotAreaRenderer.cs - - - Charting.Renderers\ColumnPlotAreaRenderer.cs - - - Charting.Renderers\ColumnStackedPlotAreaRenderer.cs - - - Charting.Renderers\CombinationChartRenderer.cs - - - Charting.Renderers\Converter.cs - - - Charting.Renderers\DataLabelRenderer.cs - - - Charting.Renderers\GridlinesRenderer.cs - - - Charting.Renderers\HorizontalStackedYAxisRenderer.cs - - - Charting.Renderers\HorizontalXAxisRenderer.cs - - - Charting.Renderers\HorizontalYAxisRenderer.cs - - - Charting.Renderers\LegendEntryRenderer.cs - - - Charting.Renderers\LegendRenderer.cs - - - Charting.Renderers\LineChartRenderer.cs - - - Charting.Renderers\LineFormatRenderer.cs - - - Charting.Renderers\LinePlotAreaRenderer.cs - - - Charting.Renderers\MarkerRenderer.cs - - - Charting.Renderers\PieChartRenderer.cs - - - Charting.Renderers\PieClosedPlotAreaRenderer.cs - - - Charting.Renderers\PieDataLabelRenderer.cs - - - Charting.Renderers\PieExplodedPlotAreaRenderer.cs - - - Charting.Renderers\PieLegendRenderer.cs - - - Charting.Renderers\PiePlotAreaRenderer.cs - - - Charting.Renderers\PlotAreaBorderRenderer.cs - - - Charting.Renderers\PlotAreaRenderer.cs - - - Charting.Renderers\Renderer.cs - - - Charting.Renderers\RendererInfo.cs - - - Charting.Renderers\RendererParameters.cs - - - Charting.Renderers\VerticalStackedYAxisRenderer.cs - - - Charting.Renderers\VerticalXAxisRenderer.cs - - - Charting.Renderers\VerticalYAxisRenderer.cs - - - Charting.Renderers\WallRenderer.cs - - - Charting.Renderers\XAxisRenderer.cs - - - Charting.Renderers\YAxisRenderer.cs - - - Charting\Axis.cs - - - Charting\AxisTitle.cs - - - Charting\Chart.cs - - - Charting\ChartFrame.cs - - - Charting\ChartObject.cs - - - Charting\DataLabel.cs - - - Charting\DocumentObject.cs - - - Charting\DocumentObjectCollection.cs - - - Charting\enums\BlankType.cs - - - Charting\enums\ChartType.cs - - - Charting\enums\DataLabelPosition.cs - - - Charting\enums\DataLabelType.cs - - - Charting\enums\DockingType.cs - - - Charting\enums\FontProperties.cs - - - Charting\enums\HorizontalAlignment.cs - - - Charting\enums\LineStyle.cs - - - Charting\enums\MarkerStyle.cs - - - Charting\enums\TickMarkType.cs - - - Charting\enums\Underline.cs - - - Charting\enums\VerticalAlignment.cs - - - Charting\FillFormat.cs - - - Charting\Font.cs - - - Charting\Gridlines.cs - - - Charting\Legend.cs - - - Charting\LineFormat.cs - - - Charting\PlotArea.cs - - - Charting\Point.cs - - - Charting\PSCSR.cs - - - Charting\Series.cs - - - Charting\SeriesCollection.cs - - - Charting\SeriesElements.cs - - - Charting\TickLabels.cs - - - Charting\XSeries.cs - - - Charting\XSeriesElements.cs - - - Charting\XValue.cs - - - Charting\XValues.cs - - - Properties\GlobalDeclarations.cs - - - root\VersionInfo.cs - - - - - Resources\Messages.de.restext - - - Resources\Messages.restext - - - StrongnameKey.snk - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting-gdi/PdfSharp.Charting-gdi.csproj - save b/src/foundation/src/PDFsharp/src/PdfSharp.Charting-gdi/PdfSharp.Charting-gdi.csproj - save new file mode 100644 index 00000000..303c62a8 --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting-gdi/PdfSharp.Charting-gdi.csproj - save @@ -0,0 +1,300 @@ + + + + library + net6.0-windows;net8.0-windows;net462 + true + PdfSharp.Charting + true + True + ..\..\..\..\..\StrongnameKey.snk + + + + true + + + + + Charting.Renderers\AreaChartRenderer.cs + + + Charting.Renderers\AreaPlotAreaRenderer.cs + + + Charting.Renderers\AxisRenderer.cs + + + Charting.Renderers\AxisTitleRenderer.cs + + + Charting.Renderers\BarChartRenderer.cs + + + Charting.Renderers\BarClusteredLegendRenderer.cs + + + Charting.Renderers\BarClusteredPlotAreaRenderer.cs + + + Charting.Renderers\BarDataLabelRenderer.cs + + + Charting.Renderers\BarGridlinesRenderer.cs + + + Charting.Renderers\BarPlotAreaRenderer.cs + + + Charting.Renderers\BarStackedPlotAreaRenderer.cs + + + Charting.Renderers\ChartRenderer.cs + + + Charting.Renderers\Colors.cs + + + Charting.Renderers\ColumnChartRenderer.cs + + + Charting.Renderers\ColumnClusteredPlotAreaRenderer.cs + + + Charting.Renderers\ColumnDataLabelRenderer.cs + + + Charting.Renderers\ColumnLikeChartRenderer.cs + + + Charting.Renderers\ColumnLikeGridlinesRenderer.cs + + + Charting.Renderers\ColumnLikeLegendRenderer.cs + + + Charting.Renderers\ColumnLikePlotAreaRenderer.cs + + + Charting.Renderers\ColumnPlotAreaRenderer.cs + + + Charting.Renderers\ColumnStackedPlotAreaRenderer.cs + + + Charting.Renderers\CombinationChartRenderer.cs + + + Charting.Renderers\Converter.cs + + + Charting.Renderers\DataLabelRenderer.cs + + + Charting.Renderers\GridlinesRenderer.cs + + + Charting.Renderers\HorizontalStackedYAxisRenderer.cs + + + Charting.Renderers\HorizontalXAxisRenderer.cs + + + Charting.Renderers\HorizontalYAxisRenderer.cs + + + Charting.Renderers\LegendEntryRenderer.cs + + + Charting.Renderers\LegendRenderer.cs + + + Charting.Renderers\LineChartRenderer.cs + + + Charting.Renderers\LineFormatRenderer.cs + + + Charting.Renderers\LinePlotAreaRenderer.cs + + + Charting.Renderers\MarkerRenderer.cs + + + Charting.Renderers\PieChartRenderer.cs + + + Charting.Renderers\PieClosedPlotAreaRenderer.cs + + + Charting.Renderers\PieDataLabelRenderer.cs + + + Charting.Renderers\PieExplodedPlotAreaRenderer.cs + + + Charting.Renderers\PieLegendRenderer.cs + + + Charting.Renderers\PiePlotAreaRenderer.cs + + + Charting.Renderers\PlotAreaBorderRenderer.cs + + + Charting.Renderers\PlotAreaRenderer.cs + + + Charting.Renderers\Renderer.cs + + + Charting.Renderers\RendererInfo.cs + + + Charting.Renderers\RendererParameters.cs + + + Charting.Renderers\VerticalStackedYAxisRenderer.cs + + + Charting.Renderers\VerticalXAxisRenderer.cs + + + Charting.Renderers\VerticalYAxisRenderer.cs + + + Charting.Renderers\WallRenderer.cs + + + Charting.Renderers\XAxisRenderer.cs + + + Charting.Renderers\YAxisRenderer.cs + + + Charting\Axis.cs + + + Charting\AxisTitle.cs + + + Charting\Chart.cs + + + Charting\ChartFrame.cs + + + Charting\ChartObject.cs + + + Charting\DataLabel.cs + + + Charting\DocumentObject.cs + + + Charting\DocumentObjectCollection.cs + + + Charting\enums\BlankType.cs + + + Charting\enums\ChartType.cs + + + Charting\enums\DataLabelPosition.cs + + + Charting\enums\DataLabelType.cs + + + Charting\enums\DockingType.cs + + + Charting\enums\FontProperties.cs + + + Charting\enums\HorizontalAlignment.cs + + + Charting\enums\LineStyle.cs + + + Charting\enums\MarkerStyle.cs + + + Charting\enums\TickMarkType.cs + + + Charting\enums\Underline.cs + + + Charting\enums\VerticalAlignment.cs + + + Charting\FillFormat.cs + + + Charting\Font.cs + + + Charting\Gridlines.cs + + + Charting\Legend.cs + + + Charting\LineFormat.cs + + + Charting\PlotArea.cs + + + Charting\Point.cs + + + Charting\PSCSR.cs + + + Charting\Series.cs + + + Charting\SeriesCollection.cs + + + Charting\SeriesElements.cs + + + Charting\TickLabels.cs + + + Charting\XSeries.cs + + + Charting\XSeriesElements.cs + + + Charting\XValue.cs + + + Charting\XValues.cs + + + Properties\GlobalDeclarations.cs + + + + + + + + + + + + diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting-wpf/PdfSharp.Charting-wpf.csproj b/src/foundation/src/PDFsharp/src/PdfSharp.Charting-wpf/PdfSharp.Charting-wpf.csproj index 63defefa..f615f461 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting-wpf/PdfSharp.Charting-wpf.csproj +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting-wpf/PdfSharp.Charting-wpf.csproj @@ -1,307 +1,115 @@  - - library - net6.0-windows;net472 - true - PdfSharp.Charting - true - True - ..\..\..\..\..\StrongnameKey.snk - + + library + net6.0-windows;net8.0-windows;net462 + true + PdfSharp.Charting + true + True + ..\..\..\..\..\StrongnameKey.snk + - - true - + + true + - - - Charting.Renderers\AreaChartRenderer.cs - - - Charting.Renderers\AreaPlotAreaRenderer.cs - - - Charting.Renderers\AxisRenderer.cs - - - Charting.Renderers\AxisTitleRenderer.cs - - - Charting.Renderers\BarChartRenderer.cs - - - Charting.Renderers\BarClusteredLegendRenderer.cs - - - Charting.Renderers\BarClusteredPlotAreaRenderer.cs - - - Charting.Renderers\BarDataLabelRenderer.cs - - - Charting.Renderers\BarGridlinesRenderer.cs - - - Charting.Renderers\BarPlotAreaRenderer.cs - - - Charting.Renderers\BarStackedPlotAreaRenderer.cs - - - Charting.Renderers\ChartRenderer.cs - - - Charting.Renderers\Colors.cs - - - Charting.Renderers\ColumnChartRenderer.cs - - - Charting.Renderers\ColumnClusteredPlotAreaRenderer.cs - - - Charting.Renderers\ColumnDataLabelRenderer.cs - - - Charting.Renderers\ColumnLikeChartRenderer.cs - - - Charting.Renderers\ColumnLikeGridlinesRenderer.cs - - - Charting.Renderers\ColumnLikeLegendRenderer.cs - - - Charting.Renderers\ColumnLikePlotAreaRenderer.cs - - - Charting.Renderers\ColumnPlotAreaRenderer.cs - - - Charting.Renderers\ColumnStackedPlotAreaRenderer.cs - - - Charting.Renderers\CombinationChartRenderer.cs - - - Charting.Renderers\Converter.cs - - - Charting.Renderers\DataLabelRenderer.cs - - - Charting.Renderers\GridlinesRenderer.cs - - - Charting.Renderers\HorizontalStackedYAxisRenderer.cs - - - Charting.Renderers\HorizontalXAxisRenderer.cs - - - Charting.Renderers\HorizontalYAxisRenderer.cs - - - Charting.Renderers\LegendEntryRenderer.cs - - - Charting.Renderers\LegendRenderer.cs - - - Charting.Renderers\LineChartRenderer.cs - - - Charting.Renderers\LineFormatRenderer.cs - - - Charting.Renderers\LinePlotAreaRenderer.cs - - - Charting.Renderers\MarkerRenderer.cs - - - Charting.Renderers\PieChartRenderer.cs - - - Charting.Renderers\PieClosedPlotAreaRenderer.cs - - - Charting.Renderers\PieDataLabelRenderer.cs - - - Charting.Renderers\PieExplodedPlotAreaRenderer.cs - - - Charting.Renderers\PieLegendRenderer.cs - - - Charting.Renderers\PiePlotAreaRenderer.cs - - - Charting.Renderers\PlotAreaBorderRenderer.cs - - - Charting.Renderers\PlotAreaRenderer.cs - - - Charting.Renderers\Renderer.cs - - - Charting.Renderers\RendererInfo.cs - - - Charting.Renderers\RendererParameters.cs - - - Charting.Renderers\VerticalStackedYAxisRenderer.cs - - - Charting.Renderers\VerticalXAxisRenderer.cs - - - Charting.Renderers\VerticalYAxisRenderer.cs - - - Charting.Renderers\WallRenderer.cs - - - Charting.Renderers\XAxisRenderer.cs - - - Charting.Renderers\YAxisRenderer.cs - - - Charting\Axis.cs - - - Charting\AxisTitle.cs - - - Charting\Chart.cs - - - Charting\ChartFrame.cs - - - Charting\ChartObject.cs - - - Charting\DataLabel.cs - - - Charting\DocumentObject.cs - - - Charting\DocumentObjectCollection.cs - - - Charting\enums\BlankType.cs - - - Charting\enums\ChartType.cs - - - Charting\enums\DataLabelPosition.cs - - - Charting\enums\DataLabelType.cs - - - Charting\enums\DockingType.cs - - - Charting\enums\FontProperties.cs - - - Charting\enums\HorizontalAlignment.cs - - - Charting\enums\LineStyle.cs - - - Charting\enums\MarkerStyle.cs - - - Charting\enums\TickMarkType.cs - - - Charting\enums\Underline.cs - - - Charting\enums\VerticalAlignment.cs - - - Charting\FillFormat.cs - - - Charting\Font.cs - - - Charting\Gridlines.cs - - - Charting\Legend.cs - - - Charting\LineFormat.cs - - - Charting\PlotArea.cs - - - Charting\Point.cs - - - Charting\PSCSR.cs - - - Charting\Series.cs - - - Charting\SeriesCollection.cs - - - Charting\SeriesElements.cs - - - Charting\TickLabels.cs - - - Charting\XSeries.cs - - - Charting\XSeriesElements.cs - - - Charting\XValue.cs - - - Charting\XValues.cs - - - Properties\GlobalDeclarations.cs - - - root\VersionInfo.cs - - - - - Resources\Messages.de.restext - - - Resources\Messages.restext - - - StrongnameKey.snk - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/AreaChartRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/AreaChartRenderer.cs index 6ae244d6..2d7de575 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/AreaChartRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/AreaChartRenderer.cs @@ -118,7 +118,7 @@ void InitSeriesRendererInfo() var seriesColl = cri.Chart.SeriesCollection; cri.SeriesRendererInfos = new SeriesRendererInfo[seriesColl.Count]; - for (int idx = 0; idx < seriesColl.Count; ++idx) + for (int idx = 0; idx < seriesColl.Count; idx++) { var sri = new SeriesRendererInfo(); sri.Series = seriesColl[idx]; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/BarChartRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/BarChartRenderer.cs index c222f60f..d611e07b 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/BarChartRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/BarChartRenderer.cs @@ -181,7 +181,7 @@ void InitSeriesRendererInfo() var seriesColl = cri.Chart.SeriesCollection; cri.SeriesRendererInfos = new SeriesRendererInfo[seriesColl.Count]; // Lowest series is the first, like in Excel - for (int idx = 0; idx < seriesColl.Count; ++idx) + for (int idx = 0; idx < seriesColl.Count; idx++) { SeriesRendererInfo sri = new SeriesRendererInfo(); sri.Series = seriesColl[idx]; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/Colors.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/Colors.cs index 84485212..3acb583e 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/Colors.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/Colors.cs @@ -19,8 +19,8 @@ public static XColor Item(int index) /// /// Colors for column/bar charts taken from Excel. /// - static readonly uint[] SeriesColorValues = new uint[] - { + static readonly uint[] SeriesColorValues = + [ 0xFF9999FF, 0xFF993366, 0xFFFFFFCC, 0xFFCCFFFF, 0xFF660066, 0xFFFF8080, 0xFF0066CC, 0xFFCCCCFF, 0xFF000080, 0xFFFF00FF, 0xFFFFFF00, 0xFF00FFFF, 0xFF800080, 0xFF800000, 0xFF008080, 0xFF0000FF, 0xFF00CCFF, 0xFFCCFFFF, @@ -31,7 +31,7 @@ public static XColor Item(int index) 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFF800000, 0xFF008000, 0xFF000080, 0xFF808000, 0xFF800080, 0xFF008080, 0xFFC0C0C0, 0xFF808080 - }; + ]; } /// @@ -42,25 +42,25 @@ static class LineColors /// /// Gets the color for line charts from the specified index. /// - public static XColor Item(int index) + public static XColor Item(int index) => XColor.FromArgb((int)LineColorValues[index]); /// /// Colors for line charts taken from Excel. /// - static readonly uint[] LineColorValues = new uint[] - { - 0xFF000080, 0xFFFF00FF, 0xFFFFFF00, 0xFF00FFFF, 0xFF800080, 0xFF800000, - 0xFF008080, 0xFF0000FF, 0xFF00CCFF, 0xFFCCFFFF, 0xFFCCFFCC, 0xFFFFFF99, - 0xFF99CCFF, 0xFFFF99CC, 0xFFCC99FF, 0xFFFFCC99, 0xFF3366FF, 0xFF33CCCC, - 0xFF99CC00, 0xFFFFCC00, 0xFFFF9900, 0xFFFF6600, 0xFF666699, 0xFF969696, - 0xFF003366, 0xFF339966, 0xFF003300, 0xFF333300, 0xFF993300, 0xFF993366, - 0xFF333399, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, - 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFF800000, 0xFF008000, 0xFF000080, - 0xFF808000, 0xFF800080, 0xFF008080, 0xFFC0C0C0, 0xFF808080, 0xFF9999FF, - 0xFF993366, 0xFFFFFFCC, 0xFFCCFFFF, 0xFF660066, 0xFFFF8080, 0xFF0066CC, - 0xFFCCCCFF - }; + static readonly uint[] LineColorValues = + [ + 0xFF000080, 0xFFFF00FF, 0xFFFFFF00, 0xFF00FFFF, 0xFF800080, 0xFF800000, + 0xFF008080, 0xFF0000FF, 0xFF00CCFF, 0xFFCCFFFF, 0xFFCCFFCC, 0xFFFFFF99, + 0xFF99CCFF, 0xFFFF99CC, 0xFFCC99FF, 0xFFFFCC99, 0xFF3366FF, 0xFF33CCCC, + 0xFF99CC00, 0xFFFFCC00, 0xFFFF9900, 0xFFFF6600, 0xFF666699, 0xFF969696, + 0xFF003366, 0xFF339966, 0xFF003300, 0xFF333300, 0xFF993300, 0xFF993366, + 0xFF333399, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, + 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFF800000, 0xFF008000, 0xFF000080, + 0xFF808000, 0xFF800080, 0xFF008080, 0xFFC0C0C0, 0xFF808080, 0xFF9999FF, + 0xFF993366, 0xFFFFFFCC, 0xFFCCFFFF, 0xFF660066, 0xFFFF8080, 0xFF0066CC, + 0xFFCCCCFF + ]; } /// @@ -71,14 +71,14 @@ static class PieColors /// /// Gets the color for pie charts from the specified index. /// - public static XColor Item(int index) + public static XColor Item(int index) => XColor.FromArgb((int)SectorColorValues[index]); /// /// Colors for pie charts taken from Excel. /// static readonly uint[] SectorColorValues = - { + [ 0xFF9999FF, 0xFF993366, 0xFFFFFFCC, 0xFFCCFFFF, 0xFF660066, 0xFFFF8080, 0xFF0066CC, 0xFFCCCCFF, 0xFF000080, 0xFFFF00FF, 0xFFFFFF00, 0xFF00FFFF, 0xFF800080, 0xFF800000, 0xFF008080, 0xFF0000FF, 0xFF00CCFF, 0xFFCCFFFF, @@ -89,6 +89,6 @@ public static XColor Item(int index) 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFF800000, 0xFF008000, 0xFF000080, 0xFF808000, 0xFF800080, 0xFF008080, 0xFFC0C0C0, 0xFF808080 - }; + ]; } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/ColumnChartRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/ColumnChartRenderer.cs index e0cb7b85..641161c9 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/ColumnChartRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/ColumnChartRenderer.cs @@ -153,7 +153,7 @@ void InitSeriesRendererInfo() var seriesColl = cri.Chart.SeriesCollection; cri.SeriesRendererInfos = new SeriesRendererInfo[seriesColl.Count]; - for (int idx = 0; idx < seriesColl.Count; ++idx) + for (int idx = 0; idx < seriesColl.Count; idx++) { SeriesRendererInfo sri = new SeriesRendererInfo(); sri.Series = seriesColl[idx]; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/CombinationChartRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/CombinationChartRenderer.cs index 08c122a7..c5d7cf35 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/CombinationChartRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/CombinationChartRenderer.cs @@ -209,7 +209,7 @@ void InitSeriesRendererInfo() var cri = (CombinationRendererInfo)_rendererParms.RendererInfo; var seriesColl = cri.Chart.SeriesCollection; cri.SeriesRendererInfos = new SeriesRendererInfo[seriesColl.Count]; - for (int idx = 0; idx < seriesColl.Count; ++idx) + for (int idx = 0; idx < seriesColl.Count; idx++) { SeriesRendererInfo sri = new SeriesRendererInfo(); sri.Series = seriesColl[idx]; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/HorizontalXAxisRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/HorizontalXAxisRenderer.cs index 81c6977a..b5f224c4 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/HorizontalXAxisRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/HorizontalXAxisRenderer.cs @@ -115,7 +115,7 @@ internal override void Draw() startPos.Y += xari.MajorTickMarkWidth; foreach (var xs in (xari.XValues ?? throw new InvalidOperationException()).Cast()) // BUG??? { - for (int idx = 0; idx < countTickLabels && idx < xs.Count; ++idx) + for (int idx = 0; idx < countTickLabels && idx < xs.Count; idx++) { var xv = xs[idx]; if (xv != null!) @@ -227,8 +227,8 @@ void InitXValues(AxisRendererInfo rendererInfo) { rendererInfo.XValues = new XValues(); XSeries xs = rendererInfo.XValues.AddXSeries(); - for (double i = rendererInfo.MinimumScale + 1; i <= rendererInfo.MaximumScale; ++i) - xs.Add(i.ToString(rendererInfo.TickLabelsFormat)); + for (double idx = rendererInfo.MinimumScale + 1; idx <= rendererInfo.MaximumScale; idx++) + xs.Add(idx.ToString(rendererInfo.TickLabelsFormat)); } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/HorizontalYAxisRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/HorizontalYAxisRenderer.cs index 1b72f8fb..1db1392f 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/HorizontalYAxisRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/HorizontalYAxisRenderer.cs @@ -136,9 +136,9 @@ internal override void Draw() var xsf = new XStringFormat(); xsf.LineAlignment = XLineAlignment.Near; int countTickLabels = (int)((yMax - yMin) / yMajorTick) + 1; - for (int i = 0; i < countTickLabels; ++i) + for (int idx = 0; idx < countTickLabels; idx++) { - double y = yMin + yMajorTick * i; + double y = yMin + yMajorTick * idx; string str = y.ToString(yari.TickLabelsFormat); XSize labelSize = gfx.MeasureString(str, yari.TickLabelsFont); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/LineChartRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/LineChartRenderer.cs index 8c1dd14d..60ab3441 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/LineChartRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/LineChartRenderer.cs @@ -116,7 +116,7 @@ void InitSeriesRendererInfo() var seriesColl = cri.Chart.SeriesCollection; cri.SeriesRendererInfos = new SeriesRendererInfo[seriesColl.Count]; - for (int idx = 0; idx < seriesColl.Count; ++idx) + for (int idx = 0; idx < seriesColl.Count; idx++) { SeriesRendererInfo sri = new SeriesRendererInfo(); sri.Series = seriesColl[idx]; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/PieChartRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/PieChartRenderer.cs index 2a8548fb..76cf8267 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/PieChartRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/PieChartRenderer.cs @@ -113,7 +113,7 @@ protected void InitSeries(ChartRendererInfo rendererInfo) { var seriesColl = rendererInfo.Chart.SeriesCollection; rendererInfo.SeriesRendererInfos = new SeriesRendererInfo[seriesColl.Count]; - for (int idx = 0; idx < seriesColl.Count; ++idx) + for (int idx = 0; idx < seriesColl.Count; idx++) { SeriesRendererInfo sri = new SeriesRendererInfo(); rendererInfo.SeriesRendererInfos[idx] = sri; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/VerticalXAxisRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/VerticalXAxisRenderer.cs index d1995c10..89fd7c4e 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/VerticalXAxisRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/VerticalXAxisRenderer.cs @@ -217,8 +217,8 @@ void InitXValues(AxisRendererInfo rendererInfo) { rendererInfo.XValues = new XValues(); XSeries xs = rendererInfo.XValues.AddXSeries(); - for (double i = rendererInfo.MinimumScale + 1; i <= rendererInfo.MaximumScale; ++i) - xs.Add(i.ToString(CultureInfo.InvariantCulture)); + for (double idx = rendererInfo.MinimumScale + 1; idx <= rendererInfo.MaximumScale; idx++) + xs.Add(idx.ToString(CultureInfo.InvariantCulture)); } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/VerticalYAxisRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/VerticalYAxisRenderer.cs index 4f6ddbe9..89b3f0ba 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/VerticalYAxisRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting.Renderers/VerticalYAxisRenderer.cs @@ -148,9 +148,9 @@ internal override void Draw() labelSize.Height = lineSpace * xHeight / cellSpace; int countTickLabels = (int)((yMax - yMin) / yMajorTick) + 1; - for (int i = 0; i < countTickLabels; ++i) + for (int idx = 0; idx < countTickLabels; idx++) { - double y = yMin + yMajorTick * i; + double y = yMin + yMajorTick * idx; string str = y.ToString(yari.TickLabelsFormat); labelSize.Width = gfx.MeasureString(str, yari.TickLabelsFont).Width; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Axis.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Axis.cs index a07d281f..f698d33a 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Axis.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Axis.cs @@ -90,7 +90,7 @@ public TickMarkType MajorTickMark set { if (!Enum.IsDefined(typeof(TickMarkType), value)) - throw new InvalidEnumArgumentException("value", (int)value, typeof(TickMarkType)); + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(TickMarkType)); _majorTickMark = value; _majorTickMarkInitialized = true; } @@ -109,7 +109,7 @@ public TickMarkType MinorTickMark set { if (!Enum.IsDefined(typeof(TickMarkType), value)) - throw new InvalidEnumArgumentException("value", (int)value, typeof(TickMarkType)); + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(TickMarkType)); _minorTickMark = value; _minorTickMarkInitialized = true; } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/DataLabel.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/DataLabel.cs index e04bf466..009470a3 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/DataLabel.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/DataLabel.cs @@ -66,7 +66,7 @@ public DataLabelPosition Position set { if (!Enum.IsDefined(typeof(DataLabelPosition), value)) - throw new InvalidEnumArgumentException("value", (int)value, typeof(DataLabelPosition)); + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(DataLabelPosition)); _position = value; _positionInitialized = true; @@ -86,7 +86,7 @@ public DataLabelType Type set { if (!Enum.IsDefined(typeof(DataLabelType), value)) - throw new InvalidEnumArgumentException("value", (int)value, typeof(DataLabelType)); + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(DataLabelType)); _type = value; _typeInitialized = true; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/DocumentObjectCollection.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/DocumentObjectCollection.cs index 8da7946d..b231a414 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/DocumentObjectCollection.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/DocumentObjectCollection.cs @@ -46,7 +46,7 @@ protected override object DeepCopy() int count = Count; coll._elements = new List(count); - for (int index = 0; index < count; ++index) + for (int index = 0; index < count; index++) coll._elements.Add((DocumentObject?)this[index]?.Clone()); return coll; } @@ -55,7 +55,7 @@ protected override object DeepCopy() /// Copies the Array or a portion of it to a one-dimensional array. /// public void CopyTo(Array array, int index) - => _elements.CopyTo(_elements.ToArray(), index); // 4STLA Check this implementation. "array" is not used. + => _elements.ToArray().CopyTo(array, index); /// /// Removes all elements from the collection. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Legend.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Legend.cs index 433c4fc4..14dd02c6 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Legend.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Legend.cs @@ -72,7 +72,7 @@ public DockingType Docking set { if (!Enum.IsDefined(typeof(DockingType), value)) - throw new InvalidEnumArgumentException("value", (int)value, typeof(DockingType)); + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(DockingType)); _docking = value; } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Point.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Point.cs index 4df96dd7..14872acd 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Point.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Point.cs @@ -20,16 +20,6 @@ internal Point() public Point(double value) : this() => Value = value; - ///// - ///// Initializes a new instance of the Point class with a string value. - ///// - //public Point(string value) : this() - //{ - // // = "34.5 23.9" - // Value = 0; // BUG: Not implemented - // throw new NotImplementedException("Point from string."); - //} - /// /// Creates a deep copy of this object. /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Series.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Series.cs index 828d9cda..47127cd3 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Series.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/Series.cs @@ -116,7 +116,7 @@ public MarkerStyle MarkerStyle set { if (!Enum.IsDefined(typeof(MarkerStyle), value)) - throw new InvalidEnumArgumentException("value", (int)value, typeof(MarkerStyle)); + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(MarkerStyle)); _markerStyle = value; _markerStyleInitialized = true; @@ -147,7 +147,7 @@ public ChartType ChartType set { if (!Enum.IsDefined(typeof(ChartType), value)) - throw new InvalidEnumArgumentException("value", (int)value, typeof(ChartType)); + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(ChartType)); _chartType = value; } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/XSeries.cs b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/XSeries.cs index 2d67efc0..3fe86199 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/XSeries.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Charting/XSeries.cs @@ -65,7 +65,6 @@ public void Add(params string[] values) /// /// Gets the enumerator. /// - /// public IEnumerator GetEnumerator() => _xSeriesElements.GetEnumerator(); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/PdfSharp.Charting.csproj b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/PdfSharp.Charting.csproj index dbe327dc..0cb4ed7b 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/PdfSharp.Charting.csproj +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/PdfSharp.Charting.csproj @@ -2,7 +2,7 @@ library - net6.0;netstandard2.0 + net6.0;net8.0;netstandard2.0 PdfSharp True ..\..\..\..\..\StrongnameKey.snk @@ -12,16 +12,6 @@ true - - - - - - - - - - diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Resources/Messages.de.restext b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Resources/Messages.de.restext index ddbdd0f6..b966fa02 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Resources/Messages.de.restext +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Resources/Messages.de.restext @@ -1,4 +1,10 @@ -; PDFsharp string resources (German) +; ========================== +; === NOT IN USE ANYMORE === +; ========================== + +-- create a syntax error if accidentally compiled -- + +; PDFsharp string resources (German) ; ; Must be saved as Unicode (UTF-8 with signature) to force resgen.exe to process German umlauts. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Resources/Messages.restext b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Resources/Messages.restext index 5f53d327..d69395ec 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Resources/Messages.restext +++ b/src/foundation/src/PDFsharp/src/PdfSharp.Charting/Resources/Messages.restext @@ -1,4 +1,10 @@ -; PDFsharp string resources (English) +; ========================== +; === NOT IN USE ANYMORE === +; ========================== + +-- create a syntax error if accidentally compiled -- + +; PDFsharp string resources (English) ; ; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/!internal/Directives.cs b/src/foundation/src/PDFsharp/src/PdfSharp/!internal/Directives.cs index 33e6b051..0ca45b67 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/!internal/Directives.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/!internal/Directives.cs @@ -27,9 +27,9 @@ #elif CORE // PDFsharp independent of any particular .NET library. -#elif UWP +#elif WUI // PDFsharp based on 'Windows Universal Platform'. -#error UWP is not supported anymore +#error WUI is not supported anymore #else #error Either 'CORE', 'GDI', or 'WPF' must be defined. #endif diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/!internal/TargetContext.cs b/src/foundation/src/PDFsharp/src/PdfSharp/!internal/TargetContext.cs index 6996a455..4152fa81 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/!internal/TargetContext.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/!internal/TargetContext.cs @@ -8,6 +8,7 @@ namespace PdfSharp.Internal // In PDFsharp hybrid build both GDI and WPF is defined. // This is for development and testing only. #if GDI && WPF +#error PDFsharp 6 does not support hybrid builds anymore. /// /// Internal switch indicating what context has to be used if both GDI and WPF are defined. /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/BarCode.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/BarCode.cs index f582aee2..c0f43288 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/BarCode.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/BarCode.cs @@ -39,7 +39,7 @@ public static BarCode FromType(CodeType type, string text, XSize size, CodeDirec return new Code3of9Standard(text, size, direction); default: - throw new InvalidEnumArgumentException("type", (int)type, typeof(CodeType)); + throw new InvalidEnumArgumentException(nameof(type), (int)type, typeof(CodeType)); } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/Code2of5Interleaved.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/Code2of5Interleaved.cs index 5cbe66e9..946b2479 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/Code2of5Interleaved.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/Code2of5Interleaved.cs @@ -47,18 +47,18 @@ static bool[] ThickAndThinLines(int digit) } static readonly bool[][] Lines = - { - new [] {false, false, true, true, false}, - new [] {true, false, false, false, true}, - new [] {false, true, false, false, true}, - new [] {true, true, false, false, false}, - new [] {false, false, true, false, true}, - new [] {true, false, true, false, false}, - new [] {false, true, true, false, false}, - new [] {false, false, false, true, true}, - new [] {true, false, false, true, false}, - new [] {false, true, false, true, false}, - }; + [ + [false, false, true, true, false], + [true, false, false, false, true], + [false, true, false, false, true], + [true, true, false, false, false], + [false, false, true, false, true], + [true, false, true, false, false], + [false, true, true, false, false], + [false, false, false, true, true], + [true, false, false, true, false], + [false, true, false, true, false] + ]; /// /// Renders the bar code. @@ -133,7 +133,7 @@ void RenderNextPair(BarCodeRenderInfo info) int digitForGaps = Int32.Parse(Text[info.CurrPosInString + 1].ToString()); bool[] linesArray = Lines[digitForLines]; bool[] gapsArray = Lines[digitForGaps]; - for (int idx = 0; idx < 5; ++idx) + for (int idx = 0; idx < 5; idx++) { RenderBar(info, linesArray[idx]); RenderGap(info, gapsArray[idx]); @@ -149,7 +149,7 @@ protected override void CheckCode(string text) { #if true_ if (text == null) - throw new ArgumentNullException("text"); + throw new ArgumentNullException(nameof(text)); if (text == "") throw new ArgumentException(BcgSR.Invalid2Of5Code(text)); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/Code3of9Standard.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/Code3of9Standard.cs index 3c439f16..701bbdba 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/Code3of9Standard.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/Code3of9Standard.cs @@ -50,96 +50,96 @@ static bool[] ThickThinLines(char ch) } static readonly bool[][] Lines = - { + [ // '0' - new bool[] {false, false, false, true, true, false, true, false, false}, + [false, false, false, true, true, false, true, false, false], // '1' - new bool[] {true, false, false, true, false, false, false, false, true}, + [true, false, false, true, false, false, false, false, true], // '2' - new bool[] {false, false, true, true, false, false, false, false, true}, + [false, false, true, true, false, false, false, false, true], // '3' - new bool[] {true, false, true, true, false, false, false, false, false}, + [true, false, true, true, false, false, false, false, false], // '4' - new bool[] {false, false, false, true, true, false, false, false, true}, + [false, false, false, true, true, false, false, false, true], // '5' - new bool[] {true, false, false, true, true, false, false, false, false}, + [true, false, false, true, true, false, false, false, false], // '6' - new bool[] {false, false, true, true, true, false, false, false, false}, + [false, false, true, true, true, false, false, false, false], // '7' - new bool[] {false, false, false, true, false, false, true, false, true}, + [false, false, false, true, false, false, true, false, true], // '8' - new bool[] {true, false, false, true, false, false, true, false, false}, + [true, false, false, true, false, false, true, false, false], // '9' - new bool[] {false, false, true, true, false, false, true, false, false}, + [false, false, true, true, false, false, true, false, false], // 'A' - new bool[] {true, false, false, false, false, true, false, false, true}, + [true, false, false, false, false, true, false, false, true], // 'B' - new bool[] {false, false, true, false, false, true, false, false, true}, + [false, false, true, false, false, true, false, false, true], // 'C' - new bool[] {true, false, true, false, false, true, false, false, false}, + [true, false, true, false, false, true, false, false, false], // 'D' - new bool[] {false, false, false, false, true, true, false, false, true}, + [false, false, false, false, true, true, false, false, true], // 'E' - new bool[] {true, false, false, false, true, true, false, false, false}, + [true, false, false, false, true, true, false, false, false], // 'F' - new bool[] {false, false, true, false, true, true, false, false, false}, + [false, false, true, false, true, true, false, false, false], // 'G' - new bool[] {false, false, false, false, false, true, true, false, true}, + [false, false, false, false, false, true, true, false, true], // 'H' - new bool[] {true, false, false, false, false, true, true, false, false}, + [true, false, false, false, false, true, true, false, false], // 'I' - new bool[] {false, false, true, false, false, true, true, false, false}, + [false, false, true, false, false, true, true, false, false], // 'J' - new bool[] {false, false, false, false, true, true, true, false, false}, + [false, false, false, false, true, true, true, false, false], // 'K' - new bool[] {true, false, false, false, false, false, false, true, true}, + [true, false, false, false, false, false, false, true, true], // 'L' - new bool[] {false, false, true, false, false, false, false, true, true}, + [false, false, true, false, false, false, false, true, true], // 'M' - new bool[] {true, false, true, false, false, false, false, true, false}, + [true, false, true, false, false, false, false, true, false], // 'N' - new bool[] {false, false, false, false, true, false, false, true, true}, + [false, false, false, false, true, false, false, true, true], // 'O' - new bool[] {true, false, false, false, true, false, false, true, false}, + [true, false, false, false, true, false, false, true, false], // 'P': - new bool[] {false, false, true, false, true, false, false, true, false}, + [false, false, true, false, true, false, false, true, false], // 'Q' - new bool[] {false, false, false, false, false, false, true, true, true}, + [false, false, false, false, false, false, true, true, true], // 'R' - new bool[] {true, false, false, false, false, false, true, true, false}, + [true, false, false, false, false, false, true, true, false], // 'S' - new bool[] {false, false, true, false, false, false, true, true, false}, + [false, false, true, false, false, false, true, true, false], // 'T' - new bool[] {false, false, false, false, true, false, true, true, false}, + [false, false, false, false, true, false, true, true, false], // 'U' - new bool[] {true, true, false, false, false, false, false, false, true}, + [true, true, false, false, false, false, false, false, true], // 'V' - new bool[] {false, true, true, false, false, false, false, false, true}, + [false, true, true, false, false, false, false, false, true], // 'W' - new bool[] {true, true, true, false, false, false, false, false, false}, + [true, true, true, false, false, false, false, false, false], // 'X' - new bool[] {false, true, false, false, true, false, false, false, true}, + [false, true, false, false, true, false, false, false, true], // 'Y' - new bool[] {true, true, false, false, true, false, false, false, false}, + [true, true, false, false, true, false, false, false, false], // 'Z' - new bool[] {false, true, true, false, true, false, false, false, false}, + [false, true, true, false, true, false, false, false, false], // '-' - new bool[] {false, true, false, false, false, false, true, false, true}, + [false, true, false, false, false, false, true, false, true], // '.' - new bool[] {true, true, false, false, false, false, true, false, false}, + [true, true, false, false, false, false, true, false, false], // ' ' - new bool[] {false, true, true, false, false, false, true, false, false}, + [false, true, true, false, false, false, true, false, false], // '$' - new bool[] {false, true, false, true, false, true, false, false, false}, + [false, true, false, true, false, true, false, false, false], // '/' - new bool[] {false, true, false, true, false, false, false, true, false}, + [false, true, false, true, false, false, false, true, false], // '+' - new bool[] {false, true, false, false, false, true, false, true, false}, + [false, true, false, false, false, true, false, true, false], // '%' - new bool[] {false, false, false, true, false, true, false, true, false}, + [false, false, false, true, false, true, false, true, false], // '*' - new bool[] {false, true, false, false, true, false, true, false, false}, - }; + [false, true, false, false, true, false, true, false, false] + ]; /// /// Calculates the thick and thin line widths, @@ -215,7 +215,7 @@ protected internal override void Render(XGraphics gfx, XBrush brush, XFont? font void RenderNextChar(BarCodeRenderInfo info) { RenderChar(info, Text[info.CurrPosInString]); - ++info.CurrPosInString; + info.CurrPosInString++; } void RenderChar(BarCodeRenderInfo info, char ch) diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/CodeOmr.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/CodeOmr.cs index 62836395..0a086838 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/CodeOmr.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/CodeOmr.cs @@ -132,7 +132,7 @@ public double MakerThickness // case MarkDistance.Inch2_8: // return XUnit.FromInch(2.0 / 8.0); // default: - // throw new ArgumentOutOfRangeException("markDistance"); + // throw new ArgumentOutOfRangeException(nameof(markDistance)); // } //} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/DataMatrixImage.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/DataMatrixImage.cs index 94a14df3..60ef2b81 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/DataMatrixImage.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/DataMatrixImage.cs @@ -42,40 +42,40 @@ public DataMatrixImage(string text, string encoding, int rows, int columns, XBru /// /// Possible ECC200 Matrices. /// - static Ecc200Block[] ecc200Sizes = - { - new Ecc200Block( 10, 10, 10, 10, 3, 3, 5), // - new Ecc200Block( 12, 12, 12, 12, 5, 5, 7), // - new Ecc200Block( 8, 18, 8, 18, 5, 5, 7), // - new Ecc200Block( 14, 14, 14, 14, 8, 8, 10), // - new Ecc200Block( 8, 32, 8, 16, 10, 10, 11), // - new Ecc200Block( 16, 16, 16, 16, 12, 12, 12), // - new Ecc200Block( 12, 26, 12, 26, 16, 16, 14), // - new Ecc200Block( 18, 18, 18, 18, 18, 18, 14), // - new Ecc200Block( 20, 20, 20, 20, 22, 22, 18), // - new Ecc200Block( 12, 36, 12, 18, 22, 22, 18), // - new Ecc200Block( 22, 22, 22, 22, 30, 30, 20), // Post - new Ecc200Block( 16, 36, 16, 18, 32, 32, 24), // - new Ecc200Block( 24, 24, 24, 24, 36, 36, 24), // - new Ecc200Block( 26, 26, 26, 26, 44, 44, 28), // Post - new Ecc200Block( 16, 48, 16, 24, 49, 49, 28), // - new Ecc200Block( 32, 32, 16, 16, 62, 62, 36), // - new Ecc200Block( 36, 36, 18, 18, 86, 86, 42), // - new Ecc200Block( 40, 40, 20, 20, 114, 114, 48), // - new Ecc200Block( 44, 44, 22, 22, 144, 144, 56), // - new Ecc200Block( 48, 48, 24, 24, 174, 174, 68), // - new Ecc200Block( 52, 52, 26, 26, 204, 102, 42), // - new Ecc200Block( 64, 64, 16, 16, 280, 140, 56), // - new Ecc200Block( 72, 72, 18, 18, 368, 92, 36), // - new Ecc200Block( 80, 80, 20, 20, 456, 114, 48), // - new Ecc200Block( 88, 88, 22, 22, 576, 144, 56), // - new Ecc200Block( 96, 96, 24, 24, 696, 174, 68), // - new Ecc200Block(104, 104, 26, 26, 816, 136, 56), // - new Ecc200Block(120, 120, 20, 20, 1050, 175, 68), // - new Ecc200Block(132, 132, 22, 22, 1304, 163, 62), // - new Ecc200Block(144, 144, 24, 24, 1558, 156, 62), // 156*4+155*2 - new Ecc200Block( 0, 0, 0, 0, 0, 0, 0) // terminate - }; + static readonly Ecc200Block[] ecc200Sizes = + [ + new( 10, 10, 10, 10, 3, 3, 5), // + new( 12, 12, 12, 12, 5, 5, 7), // + new( 8, 18, 8, 18, 5, 5, 7), // + new( 14, 14, 14, 14, 8, 8, 10), // + new( 8, 32, 8, 16, 10, 10, 11), // + new( 16, 16, 16, 16, 12, 12, 12), // + new( 12, 26, 12, 26, 16, 16, 14), // + new( 18, 18, 18, 18, 18, 18, 14), // + new( 20, 20, 20, 20, 22, 22, 18), // + new( 12, 36, 12, 18, 22, 22, 18), // + new( 22, 22, 22, 22, 30, 30, 20), // Post + new( 16, 36, 16, 18, 32, 32, 24), // + new( 24, 24, 24, 24, 36, 36, 24), // + new( 26, 26, 26, 26, 44, 44, 28), // Post + new( 16, 48, 16, 24, 49, 49, 28), // + new( 32, 32, 16, 16, 62, 62, 36), // + new( 36, 36, 18, 18, 86, 86, 42), // + new( 40, 40, 20, 20, 114, 114, 48), // + new( 44, 44, 22, 22, 144, 144, 56), // + new( 48, 48, 24, 24, 174, 174, 68), // + new( 52, 52, 26, 26, 204, 102, 42), // + new( 64, 64, 16, 16, 280, 140, 56), // + new( 72, 72, 18, 18, 368, 92, 36), // + new( 80, 80, 20, 20, 456, 114, 48), // + new( 88, 88, 22, 22, 576, 144, 56), // + new( 96, 96, 24, 24, 696, 174, 68), // + new(104, 104, 26, 26, 816, 136, 56), // + new(120, 120, 20, 20, 1050, 175, 68), // + new(132, 132, 22, 22, 1304, 163, 62), // + new(144, 144, 24, 24, 1558, 156, 62), // 156*4+155*2 + new( 0, 0, 0, 0, 0, 0, 0) // terminate + ]; public XImage DrawMatrix() { @@ -726,7 +726,7 @@ public XImage CreateImage(char[] code, int rows, int columns, int pixelSize) // WPFHACK return null; #endif -#if CORE || UWP +#if CORE || WUI return null; #endif } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/ThickThinBarcodeRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/ThickThinBarcodeRenderer.cs index a446c9c1..8b45083e 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/ThickThinBarcodeRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.BarCodes/ThickThinBarcodeRenderer.cs @@ -13,7 +13,7 @@ public abstract class ThickThinBarCode : BarCode // TODO: The name is not optim /// /// Initializes a new instance of the class. /// - public ThickThinBarCode(string code, XSize size, CodeDirection direction) + protected ThickThinBarCode(string code, XSize size, CodeDirection direction) : base(code, size, direction) { } @@ -22,7 +22,7 @@ internal override void InitRendering(BarCodeRenderInfo info) base.InitRendering(info); CalcThinBarWidth(info); info.BarHeight = Size.Height; - // HACK in ThickThinBarCode + // HACK in ThickThinBarCode. if (TextLocation != TextLocation.None) info.BarHeight *= 4.0 / 5; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporter.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporter.cs index 75fc662d..e16fe00e 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporter.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporter.cs @@ -14,7 +14,7 @@ class ImageImporter /// /// Gets the image importer. /// - public static ImageImporter GetImageImporter() + public static ImageImporter GetImageImporter() // StL: To what kind of design pattern this function identifies itself? { return new ImageImporter(); } @@ -39,8 +39,7 @@ public static ImageImporter GetImageImporter() } // ReSharper disable once EmptyGeneralCatchClause catch (Exception) - { - } + { } if (length < -1 || length > Int32.MaxValue) throw new InvalidOperationException($"Image files with a size of {length} bytes are not supported. Use image files smaller than 2 GiB."); @@ -61,7 +60,7 @@ public static ImageImporter GetImageImporter() return TryImageImport(helper); } - private ImportedImage? TryImageImport(StreamReaderHelper helper) + ImportedImage? TryImageImport(StreamReaderHelper helper) { // Try all registered importers to see if any of them can handle the image. foreach (var importer in _importers) @@ -74,7 +73,6 @@ public static ImageImporter GetImageImporter() return null; } #endif - - readonly List _importers = new(); + readonly List _importers = []; } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporterJpeg.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporterJpeg.cs index cee3674f..29ab817d 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporterJpeg.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporterJpeg.cs @@ -160,7 +160,7 @@ bool TestApp2HeaderWorker(StreamReaderHelper stream) break; } identifier.Append((char)c); - ++idx; + idx++; } while (idx < length); var id = identifier.ToString(); @@ -191,7 +191,7 @@ bool TestApp13HeaderWorker(StreamReaderHelper stream) break; } identifier.Append((char)c); - ++idx; + idx++; } while (idx < length); var id = identifier.ToString(); @@ -200,7 +200,7 @@ bool TestApp13HeaderWorker(StreamReaderHelper stream) return false; } - ++idx; + idx++; if (idx + 3 < length && stream.GetDWord(idx, true) == 0x3842494d) // 8BIM { return true; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporterPng.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporterPng.cs index 74cc1cc9..19fd74e3 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporterPng.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Internal/ImageImporterPng.cs @@ -34,8 +34,7 @@ class ImageImporterPng : ImageImporterRoot, IImageImporter } // ReSharper disable once EmptyGeneralCatchClause catch (Exception) - { - } + { } return null; #endif } @@ -111,7 +110,7 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) ii.Information.ImageFormat = ImageInformation.ImageFormats.Grayscale8; break; default: - throw new Exception($"Unsupported bit depth {bitDepth} for PNG color type {colorType}."); + throw new InvalidOperationException($"Unsupported bit depth {bitDepth} for PNG color type {colorType}."); } // ReSharper disable once HeuristicUnreachableCode #pragma warning disable CS0162 @@ -126,7 +125,7 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) ii.Information.ImageFormat = ImageInformation.ImageFormats.RGB24; break; default: - throw new Exception($"Unsupported bit depth {bitDepth} for PNG color type {colorType}."); + throw new InvalidOperationException($"Unsupported bit depth {bitDepth} for PNG color type {colorType}."); } break; @@ -144,7 +143,7 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) ii.Information.ImageFormat = ImageInformation.ImageFormats.Palette8; break; default: - throw new Exception($"Unsupported bit depth {bitDepth} for PNG color type {colorType}."); + throw new InvalidOperationException($"Unsupported bit depth {bitDepth} for PNG color type {colorType}."); } break; @@ -156,7 +155,7 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) ii.Information.ImageFormat = ImageInformation.ImageFormats.Grayscale8; break; default: - throw new Exception($"Unsupported bit depth {bitDepth} for PNG color type {colorType}."); + throw new InvalidOperationException($"Unsupported bit depth {bitDepth} for PNG color type {colorType}."); } break; // TODO case 4: @@ -169,28 +168,29 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) ii.Information.ImageFormat = ImageInformation.ImageFormats.ARGB32; break; default: - throw new Exception($"Unsupported bit depth {bitDepth} for PNG color type {colorType}."); + throw new InvalidOperationException($"Unsupported bit depth {bitDepth} for PNG color type {colorType}."); } break; default: - throw new Exception($"Unsupported PNG color type {colorType}."); + throw new InvalidOperationException($"Unsupported PNG color type {colorType}."); } // Now access the PNG pixels. // Png does not implement IDisposable. { - if (stream.OriginalStream != null!) + // Do not use OriginalStream if we have Data. + if (stream.Data == null! && stream.OriginalStream != null!) stream.OriginalStream.Position = 0; var myVisitor = new MyVisitor(); - var png = stream.OriginalStream != null ? + var png = stream.Data == null! && stream.OriginalStream != null ? Png.Open(stream.OriginalStream, myVisitor) : - Png.Open(stream.Data, myVisitor); + Png.Open(stream.Data!, myVisitor); if (png.Width != ii.Information.Width || png.Height != ii.Information.Height) { - throw new Exception($"Unsupported PNG image - internal error."); + throw new InvalidOperationException($"Unsupported PNG image - internal error."); } if (myVisitor.IsValid) @@ -213,12 +213,12 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) if (png.HasAlphaChannel != true && ii.Information.ImageFormat == ImageInformation.ImageFormats.ARGB32) { - throw new Exception($"Unsupported PNG ARGB32 image - internal error."); + throw new InvalidOperationException($"Unsupported PNG ARGB32 image - internal error."); } if (png.HasAlphaChannel != false && ii.Information.ImageFormat == ImageInformation.ImageFormats.RGB24) { - throw new Exception($"Unsupported PNG RGB24 image - internal error."); + throw new InvalidOperationException($"Unsupported PNG RGB24 image - internal error."); } bool hasMask = ii.Information.ImageFormat == ImageInformation.ImageFormats.ARGB32; @@ -263,7 +263,7 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) var hasAlpha = png.HasAlphaChannel; var palette = png.GetPalette(); if (palette!.HasAlphaValues != hasAlpha) - throw new Exception($"Unsupported PNG Palette4 image - internal error."); + throw new InvalidOperationException($"Unsupported PNG Palette4 image - internal error."); var lineBytes = (png.Width + 1) / 2; var length = lineBytes * png.Height; @@ -299,7 +299,7 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) { // TODO Add GetRow to PNG library? Performance optimization. int pels = 0; - for (var index = 0; index < 8; ++index) + for (var index = 0; index < 8; index++) { var pel = png.GetPixelIndex(x * 8 + index, y); pels |= pel << (7 - index); @@ -329,7 +329,7 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) var hasAlpha = png.HasAlphaChannel; var palette = png.GetPalette(); if (palette!.HasAlphaValues != hasAlpha) - throw new Exception($"Unsupported PNG Palette4 image - internal error."); + throw new InvalidOperationException($"Unsupported PNG Palette4 image - internal error."); var lineBytes = (png.Width + 1) / 2; var length = lineBytes * png.Height; @@ -395,7 +395,7 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) var hasAlpha = png.HasAlphaChannel; var palette = png.GetPalette(); if (palette!.HasAlphaValues != hasAlpha) - throw new Exception($"Unsupported PNG Palette8 image - internal error."); + throw new InvalidOperationException($"Unsupported PNG Palette8 image - internal error."); var length = png.Width * png.Height; var data = new Byte[length]; @@ -438,7 +438,6 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) alphaMask[offset] = alpha[pel]; alphaUsed |= alphaMask[offset] != 255; } - ++offset; } } @@ -487,7 +486,7 @@ private Boolean TestPngInfoHeader(StreamReaderHelper stream, ImportedImage ii) break; default: - throw new Exception($"Unsupported PNG format {ii.Information.ImageFormat}."); + throw new InvalidOperationException($"Unsupported PNG format {ii.Information.ImageFormat}."); } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Layout/XTextFormatter.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Layout/XTextFormatter.cs index 93247ace..dd05daca 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Layout/XTextFormatter.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Layout/XTextFormatter.cs @@ -42,7 +42,7 @@ public XFont Font get => _font; set { - _font = value ?? throw new ArgumentNullException("Font"); + _font = value ?? throw new ArgumentNullException(nameof(Font)); _lineSpace = _font.GetHeight(); // old: _font.GetHeight(_gfx); _cyAscent = _lineSpace * _font.CellAscent / _font.CellSpace; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Pdf/PdfGraphicsState.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Pdf/PdfGraphicsState.cs index d6f256dd..5fb4adf4 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Pdf/PdfGraphicsState.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Pdf/PdfGraphicsState.cs @@ -277,6 +277,7 @@ void RealizeFillColor(XColor color, bool overPrint, PdfColorMode colorMode) renderer.AppendFormatString("{0} gs\n", gs); // Must create transparency group. + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract if (renderer._page != null && color.A < 1) renderer._page.TransparencyUsed = true; } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Pdf/XGraphicsPdfRenderer.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Pdf/XGraphicsPdfRenderer.cs index 6651f045..fe50ccc1 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Pdf/XGraphicsPdfRenderer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Pdf/XGraphicsPdfRenderer.cs @@ -15,7 +15,7 @@ using SysPoint = System.Windows.Point; using SysSize = System.Windows.Size; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media; using SysPoint = Windows.Foundation.Point; using SysSize = Windows.Foundation.Size; @@ -23,6 +23,7 @@ using PdfSharp.Fonts.OpenType; using PdfSharp.Internal; using PdfSharp.Logging; +using PdfSharp.Fonts; using PdfSharp.Pdf; using PdfSharp.Pdf.Internal; using PdfSharp.Pdf.Advanced; @@ -104,7 +105,7 @@ public void Close() /// public void DrawLine(XPen pen, double x1, double y1, double x2, double y2) { - DrawLines(pen, new XPoint[] { new(x1, y1), new(x2, y2) }); + DrawLines(pen, [new(x1, y1), new(x2, y2)]); } // ----- DrawLines ---------------------------------------------------------------------------- @@ -139,7 +140,7 @@ public void DrawLines(XPen pen, XPoint[] points) public void DrawBezier(XPen pen, double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { - DrawBeziers(pen, new XPoint[] { new(x1, y1), new(x2, y2), new(x3, y3), new(x4, y4) }); + DrawBeziers(pen, [new(x1, y1), new(x2, y2), new(x3, y3), new(x4, y4)]); } // ----- DrawBeziers -------------------------------------------------------------------------- @@ -239,7 +240,7 @@ public void DrawRectangle(XPen? pen, XBrush? brush, double x, double y, double w if (pen == null && brush == null) { // ReSharper disable once NotResolvedInText - throw new ArgumentNullException("pen and brush"); + throw new ArgumentNullException(nameof(pen) + " and " + nameof(brush)); } const string format = Config.SignificantDecimalPlaces4; @@ -325,7 +326,7 @@ public void DrawPolygon(XPen? pen, XBrush? brush, XPoint[] points, XFillMode fil int count = points.Length; if (points.Length < 2) - throw new ArgumentException(PSSR.PointArrayAtLeast(2), nameof(points)); + throw new ArgumentException(PsMsgs.PointArrayAtLeast(2), nameof(points)); const string format = Config.SignificantDecimalPlaces4; AppendFormatPoint("{0:" + format + "} {1:" + format + "} m\n", points[0].X, points[0].Y); @@ -420,7 +421,7 @@ public void DrawPath(XPen? pen, XBrush? brush, XGraphicsPath path) AppendPath(path._pathGeometry); AppendStrokeFill(pen, brush, path.FillMode, false); #endif -#if UWP +#if WUI Realize(pen, brush); AppendPath(path._pathGeometry); AppendStrokeFill(pen, brush, path.FillMode, false); @@ -443,10 +444,15 @@ public void DrawString(string s, XFont font, XBrush brush, XRect rect, XStringFo double cyAscent = lineSpace * font.CellAscent / font.CellSpace; double cyDescent = lineSpace * font.CellDescent / font.CellSpace; - bool italicSimulation = (font.GlyphTypeface.StyleSimulations & XStyleSimulations.ItalicSimulation) != 0; + //bool italicSimulation = (font.GlyphTypeface.StyleSimulations & XStyleSimulations.ItalicSimulation) != 0; bool boldSimulation = (font.GlyphTypeface.StyleSimulations & XStyleSimulations.BoldSimulation) != 0; - bool strikeout = (font.Style & XFontStyleEx.Strikeout) != 0; - bool underline = (font.Style & XFontStyleEx.Underline) != 0; + //bool strikeout = (font.Style & XFontStyleEx.Strikeout) != 0; + //bool underline = (font.Style & XFontStyleEx.Underline) != 0; + + // Invoke PrepareTextEvent. + var args2 = new PrepareTextEventArgs(Owner, font, s); + Owner.RenderEvents.OnPrepareTextEvent(this, args2); + s = args2.Text; //var otDescriptor = font.OpenTypeDescriptor; //var ids = otDescriptor.GlyphIndicesFromCodepoints(codePoints); @@ -458,18 +464,14 @@ public void DrawString(string s, XFont font, XBrush brush, XRect rect, XStringFo var otDescriptor = font.OpenTypeDescriptor; var codePointsWithGlyphIndices = otDescriptor.GlyphIndicesFromCodePoints(codePoints); - // Invoke RenderEvent. - var args = new RenderTextEventArgs(Owner) - { - Font = font, - CodePointGlyphIndexPairs = codePointsWithGlyphIndices - }; + // Invoke RenderTextEvent. + var args = new RenderTextEventArgs(Owner, font, codePointsWithGlyphIndices); Owner.RenderEvents.OnRenderTextEvent(this, args); codePointsWithGlyphIndices = args.CodePointGlyphIndexPairs; if (args.ReevaluateGlyphIndices) { - codePoints = args.CodePointGlyphIndexPairs.Select(x => x.CodePoint).ToArray(); + codePoints = args.CodePointGlyphIndexPairs.Select(pair => pair.CodePoint).ToArray(); codePointsWithGlyphIndices = otDescriptor.GlyphIndicesFromCodePoints(codePoints); } @@ -567,36 +569,156 @@ public void DrawString(string s, XFont font, XBrush brush, XRect rect, XStringFo } } - string? text; - if (isAnsi) + var glyphCount = codePoints.Length; + // Check font whether colored glyphs are opt-in. + bool isDefaultCase = font.PdfOptions.ColoredGlyphs == PdfFontColoredGlyphs.None; + DefaultCase: + if (isDefaultCase) { - // Use ANSI character encoding. - var length = codePoints.Length; - byte[] bytes = new byte[length]; - for (int idx = 0; idx < length; idx++) + string text; + if (isAnsi) { - ref var item = ref codePoints[idx]; - //Debug.Assert(item.Character == item.Codepoint); - var ch = AnsiEncoding.UnicodeToAnsi((char)item); - bytes[idx] = (byte)ch; + // Use ANSI character encoding. + byte[] bytes = new byte[glyphCount]; + for (int idx = 0; idx < glyphCount; idx++) + { + ref var item = ref codePoints[idx]; + var ch = AnsiEncoding.UnicodeToAnsi((char)item); + bytes[idx] = (byte)ch; + } + text = PdfEncoders.ToStringLiteral(bytes, false, null); } - //bytes = PdfEncoders.WinAnsiEncoding.GetBytes(s); - text = PdfEncoders.ToStringLiteral(bytes, false, null); + else + { + // Use Unicode glyph encoding. + var bytes = new byte[2 * glyphCount]; + for (int idx = 0; idx < glyphCount; idx++) + { + ref var item = ref codePointsWithGlyphIndices[idx]; + bytes[idx * 2] = (byte)((item.GlyphIndex & 0xFF00) >>> 8); + bytes[idx * 2 + 1] = (byte)(item.GlyphIndex & 0xFF); + } + text = PdfEncoders.ToHexStringLiteral(bytes, true, false, null); + } + RenderText(text, font, brush, x, y, width); + return; } - else + + // Get glyph color records for all glyph indices. + var glyphColorRecords = otDescriptor.GlyphColorRecordsFromGlyphIndices(codePointsWithGlyphIndices); + + isDefaultCase = glyphColorRecords.All(item => item is null); + if (isDefaultCase) + { + // There is no glyph index with a glyph color record. + goto DefaultCase; + } + + // Case: At least one glyph is colorized, e.g. an emoji in an emoji font. + + // We split the text based on whether special color-handling is required for a glyph. + List> textParts = []; + var partGlyphs = new List(); + var isColorized = false; + for (int idx = 0; idx < glyphCount; idx++) { - // Use Unicode glyph encoding. - int length = codePointsWithGlyphIndices.Length; - var bytes = new byte[2 * length]; - for (int idx = 0; idx < length; idx++) + ref var cp = ref codePointsWithGlyphIndices[idx]; + ref var cr = ref glyphColorRecords[idx]; + + // If glyph is colored, render individually, else add to list. + if (cr != null || (cr == null && isColorized)) + { + if (partGlyphs.Count > 0) + textParts.Add(partGlyphs); + partGlyphs = []; + isColorized = cr is not null; + } + partGlyphs.Add(new(cp.GlyphIndex, cr)); + } + if (partGlyphs.Count > 0) + textParts.Add(partGlyphs); + + Debug.Assert(textParts.Sum(p => p.Count) == glyphCount, "Character count mismatch."); + + const string format2 = Config.SignificantDecimalPlaces4; + var layerBytes = new byte[2]; + foreach (var textPart in textParts) + { + // textPart is either a single item having a color-record or 1-n items without color. + // if (textPart is [{ ColorRecord: not null } _]) ...when pattern matching is over the top. At least for me. + if (textPart.Count == 1 && textPart[0].ColorRecord != null) + { + var chunkWidth = 0.0; + var glyphRecord = textPart[0].ColorRecord!.Value; + for (var i = 0; i < glyphRecord.numLayers; i++) + { + var layer = otDescriptor.FontFace.colr!.layerRecords[i + glyphRecord.firstLayerIndex]; + var cp = new CodePointGlyphIndexPair(layer.glyphId, layer.glyphId); + // 0xffff is a special entry denoting the current foreground-color. + if (layer.paletteIndex != 0xffff) + { + var color = otDescriptor.FontFace.cpal!.colorRecords[layer.paletteIndex]; + _gfxState.RealizeBrush(new XSolidBrush(color), _colorMode, 0, 0); + } + else + { + _gfxState.RealizeBrush(brush, _colorMode, 0, 0); + } + realizedFont.AddChars([cp]); + var partWidth = otDescriptor.GlyphIndexToEmWidth(layer.glyphId, font.Size); + chunkWidth = Math.Max(chunkWidth, partWidth); + layerBytes[0] = (byte)((layer.glyphId & 0xFF00) >>> 8); + layerBytes[1] = (byte)(layer.glyphId & 0xFF); + var text = PdfEncoders.ToHexStringLiteral(layerBytes, true, false, null); + if (i == 0) + { + var pos = new XPoint(x, y); + pos = WorldToView(pos); + AdjustTdOffset(ref pos, 0, false); + AppendFormatArgs("{0:" + format2 + "} {1:" + format2 + "} Td {2} Tj\n", pos.X, pos.Y, text); + } + else + { + // Rest of the layers are rendered on top of the first layer. + AppendFormatArgs("0 0 Td {0} Tj\n", text); + } + } + x += chunkWidth; + } + else { - ref var item = ref codePointsWithGlyphIndices[idx]; - bytes[idx * 2] = (byte)((item.GlyphIndex & 0xFF00) >>> 8); - bytes[idx * 2 + 1] = (byte)(item.GlyphIndex & 0xFF); + Debug.Assert(textPart.All(p => p.ColorRecord == null), "Colors should be null here."); + + width = 0.0; + var bytes = new byte[textPart.Count * 2]; + for (var idx = 0; idx < textPart.Count; idx++) + { + var cp = textPart[idx]; + width += otDescriptor.GlyphIndexToWidth(cp.GlyphIndex); + bytes[idx * 2] = (byte)((cp.GlyphIndex & 0xFF00) >>> 8); + bytes[idx * 2 + 1] = (byte)(cp.GlyphIndex & 0xFF); + } + width = width * font.Size / otDescriptor.UnitsPerEm; + var text = PdfEncoders.ToHexStringLiteral(bytes, true, false, null); + _gfxState.RealizeBrush(brush, _colorMode, 0, 0); + RenderText(text, font, brush, x, y, width); + x += width; } - text = PdfEncoders.ToHexStringLiteral(bytes, true, false, null); } + } + + void RenderText(string text, XFont font, XBrush brush, double x, double y, double width) + { + double lineSpace = font.GetHeight(); + double cyAscent = lineSpace * font.CellAscent / font.CellSpace; + double cyDescent = lineSpace * font.CellDescent / font.CellSpace; + bool italicSimulation = (font.GlyphTypeface.StyleSimulations & XStyleSimulations.ItalicSimulation) != 0; + bool boldSimulation = (font.GlyphTypeface.StyleSimulations & XStyleSimulations.BoldSimulation) != 0; + bool strikeout = (font.Style & XFontStyleEx.Strikeout) != 0; + bool underline = (font.Style & XFontStyleEx.Underline) != 0; + + var realizedFont = _gfxState.RealizedFont!; // Map absolute position to PDF world space. var pos = new XPoint(x, y); pos = WorldToView(pos); @@ -696,6 +818,7 @@ public void DrawString(string s, XFont font, XBrush brush, XRect rect, XStringFo DrawRectangle(null, brush, x, strikeoutRectY, width, strikeoutSize); } } + // ReSharper disable InconsistentNaming static string? s_format1; static string? s_format2; @@ -1030,7 +1153,7 @@ public void ResetClip() public void WriteComment(string comment) { comment = comment.Replace("\n", "\n% "); - // TODO: Some more checks necessary? + // Nothing right of '% ' can break a PDF file. Append("% " + comment + "\n"); } @@ -1251,7 +1374,7 @@ void AppendPartialArcQuadrant(double x, double y, double width, double height, d } } -#if WPF || UWP +#if WPF || WUI void AppendPartialArc(SysPoint point1, SysPoint point2, double rotationAngle, SysSize size, bool isLargeArc, SweepDirection sweepDirection, PathStart pathStart) { @@ -1457,7 +1580,7 @@ internal void AppendPath(GraphicsPath path) #endif #if CORE || GDI - void AppendPath(XPoint[] points, Byte[] types) + void AppendPath(XPoint[] points, byte[] types) { const string format = Config.SignificantDecimalPlaces4; int count = points.Length; @@ -1468,14 +1591,14 @@ void AppendPath(XPoint[] points, Byte[] types) { // ReSharper disable InconsistentNaming // From GDI+ documentation: - const byte PathPointTypeStart = 0; // move - const byte PathPointTypeLine = 1; // line - const byte PathPointTypeBezier = 3; // default Bezier (= cubic Bezier) + const byte PathPointTypeStart = 0; // move + const byte PathPointTypeLine = 1; // line + const byte PathPointTypeBezier = 3; // default Bézier (= cubic Bézier) const byte PathPointTypePathTypeMask = 0x07; // type mask (lowest 3 bits). - //const byte PathPointTypeDashMode = 0x10; // currently in dash mode. - //const byte PathPointTypePathMarker = 0x20; // a marker for the path. + //const byte PathPointTypeDashMode = 0x10; // currently in dash mode. + //const byte PathPointTypePathMarker = 0x20; // a marker for the path. const byte PathPointTypeCloseSubpath = 0x80; // closed flag - // ReSharper restore InconsistentNaming + // ReSharper restore InconsistentNaming byte type = types[idx]; switch (type & PathPointTypePathTypeMask) @@ -1507,7 +1630,7 @@ void AppendPath(XPoint[] points, Byte[] types) } #endif -#if WPF || UWP +#if WPF || WUI /// /// Appends the content of a PathGeometry object. /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/CoreGraphicsPath.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/CoreGraphicsPath.cs index 1fafa909..646d2bba 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/CoreGraphicsPath.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/CoreGraphicsPath.cs @@ -20,8 +20,8 @@ public CoreGraphicsPath() public CoreGraphicsPath(CoreGraphicsPath path) { - _points = new(path._points); - _types = new(path._types); + _points = [..path._points]; + _types = [..path._types]; } public void MoveOrLineTo(double x, double y) diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/GeometryHelper.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/GeometryHelper.cs index 4dbb5f80..61233900 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/GeometryHelper.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/GeometryHelper.cs @@ -11,7 +11,7 @@ using SysPoint = System.Windows.Point; using SysSize = System.Windows.Size; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media; using SysPoint = Windows.Foundation.Point; using SysSize = Windows.Foundation.Size; @@ -28,7 +28,7 @@ namespace PdfSharp.Drawing /// static class GeometryHelper { -#if WPF || UWP +#if WPF || WUI /// /// Appends a Bézier segment from a curve. /// @@ -49,7 +49,7 @@ public static BezierSegment CreateCurveSegment(XPoint pt0, XPoint pt1, XPoint pt } #endif -#if WPF || UWP +#if WPF || WUI /// /// Creates a path geometry from a polygon. /// @@ -77,7 +77,7 @@ public static PathGeometry CreatePolygonGeometry(SysPoint[] points, XFillMode fi } #endif -#if WPF || UWP +#if WPF || WUI /// /// Creates a path geometry from a polygon. /// @@ -93,7 +93,7 @@ public static PolyLineSegment CreatePolyLineSegment(SysPoint[] points, XFillMode } #endif -#if WPF || UWP +#if WPF || WUI /// /// Creates the arc segment from parameters of the GDI+ DrawArc function. /// @@ -460,7 +460,7 @@ public static List BezierCurveFromArc(XPoint point1, XPoint point2, XSiz // with the MinBar Test Suite from QualityLogic and could not find out why it does not match. // My Bézier curves came very close to the arc, but in some cases they do simply not match. // So I gave up and use the original WPF code. -#if WPF || UWP +#if WPF || WUI // ReSharper disable InconsistentNaming const double FUZZ = 1e-6; // Relative 0 diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/InternalGraphicsState.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/InternalGraphicsState.cs index 65d7a38e..29dcb636 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/InternalGraphicsState.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/InternalGraphicsState.cs @@ -61,7 +61,6 @@ public InternalGraphicsState(XGraphics gfx, XGraphicsState state) public InternalGraphicsState(XGraphics gfx, XGraphicsContainer container) { _gfx = gfx; - //State = null!; // BUG container.InternalState = this; } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/PdfFontOptions.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/PdfFontOptions.cs index 1a7ad21b..d4114648 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/PdfFontOptions.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/PdfFontOptions.cs @@ -36,16 +36,55 @@ public XPdfFontOptions(PdfFontEncoding encoding) FontEncoding = encoding; } - //DELETE /// /// Initializes a new instance of the class. /// public XPdfFontOptions(PdfFontEmbedding embedding) { - FontEmbedding = PdfFontEmbedding.TryComputeSubset; + FontEmbedding = embedding; FontEncoding = PdfFontEncoding.Automatic; } + /// + /// Initializes a new instance of the class. + /// + public XPdfFontOptions(PdfFontEncoding encoding, PdfFontEmbedding embedding, PdfFontColoredGlyphs coloredGlyphs) + { + FontEncoding = encoding; + FontEmbedding = embedding; + ColoredGlyphs = coloredGlyphs; + } + + /// + /// Initializes a new instance of the class. + /// + public XPdfFontOptions(PdfFontEmbedding embedding, PdfFontColoredGlyphs coloredGlyphs) + { + FontEmbedding = embedding; + FontEncoding = PdfFontEncoding.Unicode; + ColoredGlyphs = coloredGlyphs; + } + + /// + /// Initializes a new instance of the class. + /// + public XPdfFontOptions(PdfFontEncoding encoding, PdfFontColoredGlyphs coloredGlyphs) + { + FontEmbedding = PdfFontEmbedding.TryComputeSubset; + FontEncoding = encoding; + ColoredGlyphs = coloredGlyphs; + } + + /// + /// Initializes a new instance of the class. + /// + public XPdfFontOptions(PdfFontColoredGlyphs coloredGlyphs) + { + FontEmbedding = PdfFontEmbedding.TryComputeSubset; + FontEncoding = PdfFontEncoding.Unicode; + ColoredGlyphs = coloredGlyphs; + } + /// /// Gets a value indicating the font embedding. /// @@ -56,6 +95,11 @@ public XPdfFontOptions(PdfFontEmbedding embedding) /// public PdfFontEncoding FontEncoding { get; } + /// + /// Gets a value indicating how the font is encoded. + /// + public PdfFontColoredGlyphs ColoredGlyphs { get; } + /// /// Gets the default options with WinAnsi encoding and always font embedding. /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapDecoder.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapDecoder.cs index 1bfff2ae..20c67d47 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapDecoder.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapDecoder.cs @@ -11,7 +11,7 @@ using System.Windows.Media; using System.Windows.Media.Imaging; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media.Imaging; #endif diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapEncoder.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapEncoder.cs index 3117b01e..b200bab5 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapEncoder.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapEncoder.cs @@ -12,7 +12,7 @@ using System.Windows.Media; using System.Windows.Media.Imaging; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media.Imaging; #endif diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapImage.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapImage.cs index 1b608d90..63d2c041 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapImage.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapImage.cs @@ -7,7 +7,7 @@ #if WPF using PdfSharp.Internal; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media.Imaging; using PdfSharp.Internal; #endif @@ -38,7 +38,7 @@ internal XBitmapImage(int width, int height) #if WPF DiagnosticsHelper.ThrowNotImplementedException("CreateBitmap"); #endif -#if UWP +#if WUI DiagnosticsHelper.ThrowNotImplementedException("CreateBitmap"); #endif #if CORE || GDI && !WPF // Prevent unreachable code error diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapSource.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapSource.cs index 1a840e03..8e967a05 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapSource.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBitmapSource.cs @@ -8,7 +8,7 @@ #endif #if WPF #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media.Imaging; #endif @@ -50,7 +50,7 @@ public override int PixelWidth #if WPF && !GDI return _wpfImage.PixelWidth; #endif -#if UWP +#if WUI return _wrtImage.PixelWidth; #endif } @@ -85,7 +85,7 @@ public override int PixelHeight #if WPF && !GDI return _wpfImage.PixelHeight; #endif -#if UWP +#if WUI return _wrtImage.PixelHeight; #endif } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBrush.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBrush.cs index 85e58656..2304ed2e 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBrush.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XBrush.cs @@ -6,7 +6,7 @@ #endif #if WPF #endif -#if UWP +#if WUI using Microsoft.Graphics.Canvas.Brushes; using UwpColor = Windows.UI.Color; #endif @@ -49,7 +49,7 @@ public static implicit operator XBrush(Brush brush) #if WPF internal abstract System.Windows.Media.Brush RealizeWpfBrush(); #endif -#if UWP +#if WUI internal abstract ICanvasBrush RealizeCanvasBrush(); #endif } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XColor.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XColor.cs index 7b736b36..79886098 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XColor.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XColor.cs @@ -8,7 +8,7 @@ #if WPF using WpfColor = System.Windows.Media.Color; #endif -#if UWP +#if WUI using UwpColor = Windows.UI.Color; #endif @@ -112,7 +112,7 @@ public struct XColor { } #endif -#if UWP +#if WUI XColor(UwpColor color) : this(color.A, color.R, color.G, color.B) { } @@ -189,7 +189,7 @@ public static XColor FromArgb(WpfColor color) } #endif -#if UWP +#if WUI /// /// Creates an XColor structure from the specified Windows.UI.Color. /// @@ -230,7 +230,7 @@ public static XColor FromArgb(int alpha, WpfColor color) } #endif -#if UWP +#if WUI /// /// Creates an XColor structure from the specified alpha value and color. /// @@ -313,7 +313,7 @@ public XColorSpace ColorSpace set { if (!Enum.IsDefined(typeof(XColorSpace), value)) - throw new InvalidEnumArgumentException("value", (int)value, typeof(XColorSpace)); + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(XColorSpace)); _cs = value; } } @@ -351,7 +351,7 @@ public WpfColor ToWpfColor() } #endif -#if UWP +#if WUI /// /// Creates a Windows.UI.Color object from this color. /// @@ -756,7 +756,7 @@ public string RgbCmykG static void CheckByte(int val, string name) { if (val is < 0 or > 0xFF) - throw new ArgumentException(PSSR.InvalidValue(val, name, 0, 255)); + throw new ArgumentException(PsMsgs.InvalidValue(val, name, 0, 255)); } XColorSpace _cs; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XColorResourceManager.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XColorResourceManager.cs index d2d78e08..3a167ead 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XColorResourceManager.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XColorResourceManager.cs @@ -132,178 +132,178 @@ static ColorResourceInfo GetColorInfo(XKnownColor knownColor) // http://blog.patrickkempf.de/archives/2004/04/10/html-farben/ // http://www.grafikwunder.de/Grafikecke/Farbtabelle/farbtabelle-006.php // Silke changed some German translations (women know more colors than men :-) - internal static ColorResourceInfo[] colorInfos = new ColorResourceInfo[] - { - new ColorResourceInfo(XKnownColor.Transparent, XColors.Transparent, 0x00FFFFFF, "Transparent", "Transparent"), - new ColorResourceInfo(XKnownColor.Black, XColors.Black, 0xFF000000, "Black", "Schwarz"), - new ColorResourceInfo(XKnownColor.DarkSlateGray, XColors.DarkSlateGray, 0xFF8FBC8F, "Darkslategray", "Dunkles Schiefergrau"), - new ColorResourceInfo(XKnownColor.SlateGray, XColors.SlateGray, 0xFF708090, "Slategray", "Schiefergrau"), - new ColorResourceInfo(XKnownColor.LightSlateGray, XColors.LightSlateGray, 0xFF778899, "Lightslategray", "Helles Schiefergrau"), - new ColorResourceInfo(XKnownColor.LightSteelBlue, XColors.LightSteelBlue, 0xFFB0C4DE, "Lightsteelblue", "Helles Stahlblau"), - //new ColorResourceInfo(XKnownColor.DimGray, XColors.DimGray, 0xFF696969, "Dimgray", "Mattes Grau"), - new ColorResourceInfo(XKnownColor.DimGray, XColors.DimGray, 0xFF696969, "Dimgray", "Gedecktes Grau"), - new ColorResourceInfo(XKnownColor.Gray, XColors.Gray, 0xFF808080, "Gray", "Grau"), - new ColorResourceInfo(XKnownColor.DarkGray, XColors.DarkGray, 0xFFA9A9A9, "Darkgray", "Dunkelgrau"), - new ColorResourceInfo(XKnownColor.Silver, XColors.Silver, 0xFFC0C0C0, "Silver", "Silber"), - //new ColorResourceInfo(XKnownColor.Gainsboro, XColors.Gainsboro, 0xFFDCDCDC, "Gainsboro", "Gainsboro"), - new ColorResourceInfo(XKnownColor.Gainsboro, XColors.Gainsboro, 0xFFDCDCDC, "Gainsboro", "Helles Blaugrau"), - //new ColorResourceInfo(XKnownColor.WhiteSmoke, XColors.WhiteSmoke, 0xFFF5F5F5, "Whitesmoke", "Rauchiges Weiß"), - new ColorResourceInfo(XKnownColor.WhiteSmoke, XColors.WhiteSmoke, 0xFFF5F5F5, "Whitesmoke", "Rauchweiß"), - //new ColorResourceInfo(XKnownColor.GhostWhite, XColors.GhostWhite, 0xFFF8F8FF, "Ghostwhite", "Geisterweiß"), - new ColorResourceInfo(XKnownColor.GhostWhite, XColors.GhostWhite, 0xFFF8F8FF, "Ghostwhite", "Schattenweiß"), - new ColorResourceInfo(XKnownColor.White, XColors.White, 0xFFFFFFFF, "White", "Weiß"), - new ColorResourceInfo(XKnownColor.Snow, XColors.Snow, 0xFFFFFAFA, "Snow", "Schneeweiß"), - new ColorResourceInfo(XKnownColor.Ivory, XColors.Ivory, 0xFFFFFFF0, "Ivory", "Elfenbein"), - new ColorResourceInfo(XKnownColor.FloralWhite, XColors.FloralWhite, 0xFFFFFAF0, "Floralwhite", "Blütenweiß"), - new ColorResourceInfo(XKnownColor.SeaShell, XColors.SeaShell, 0xFFFFF5EE, "Seashell", "Muschel"), - //new ColorResourceInfo(XKnownColor.OldLace, XColors.OldLace, 0xFFFDF5E6, "Oldlace", "Altgold"), - new ColorResourceInfo(XKnownColor.OldLace, XColors.OldLace, 0xFFFDF5E6, "Oldlace", "Altweiß"), - //new ColorResourceInfo(XKnownColor.Linen, XColors.Linen, 0xFFFAF0E6, "Linen", "Leinenfarbe"), - new ColorResourceInfo(XKnownColor.Linen, XColors.Linen, 0xFFFAF0E6, "Linen", "Leinen"), - new ColorResourceInfo(XKnownColor.AntiqueWhite, XColors.AntiqueWhite, 0xFFFAEBD7, "Antiquewhite", "Antikes Weiß"), - new ColorResourceInfo(XKnownColor.BlanchedAlmond, XColors.BlanchedAlmond, 0xFFFFEBCD, "Blanchedalmond", "Mandelweiß"), - //new ColorResourceInfo(XKnownColor.PapayaWhip, XColors.PapayaWhip, 0xFFFFEFD5, "Papayawhip", "Cremiges Papaya"), - new ColorResourceInfo(XKnownColor.PapayaWhip, XColors.PapayaWhip, 0xFFFFEFD5, "Papayawhip", "Papayacreme"), - new ColorResourceInfo(XKnownColor.Beige, XColors.Beige, 0xFFF5F5DC, "Beige", "Beige"), - new ColorResourceInfo(XKnownColor.Cornsilk, XColors.Cornsilk, 0xFFFFF8DC, "Cornsilk", "Mais"), - //new ColorResourceInfo(XKnownColor.LightGoldenrodYellow, XColors.LightGoldenrodYellow, 0xFFFAFAD2, "Lightgoldenrodyellow", "Helles Goldrutengelb"), - new ColorResourceInfo(XKnownColor.LightGoldenrodYellow, XColors.LightGoldenrodYellow, 0xFFFAFAD2, "Lightgoldenrodyellow", "Helles Goldgelb"), - new ColorResourceInfo(XKnownColor.LightYellow, XColors.LightYellow, 0xFFFFFFE0, "Lightyellow", "Hellgelb"), - new ColorResourceInfo(XKnownColor.LemonChiffon, XColors.LemonChiffon, 0xFFFFFACD, "Lemonchiffon", "Pastellgelb"), - //new ColorResourceInfo(XKnownColor.PaleGoldenrod, XColors.PaleGoldenrod, 0xFFEEE8AA, "Palegoldenrod", "Blasse Goldrutenfarbe"), - new ColorResourceInfo(XKnownColor.PaleGoldenrod, XColors.PaleGoldenrod, 0xFFEEE8AA, "Palegoldenrod", "Blasses Goldgelb"), - new ColorResourceInfo(XKnownColor.Khaki, XColors.Khaki, 0xFFF0E68C, "Khaki", "Khaki"), - new ColorResourceInfo(XKnownColor.Yellow, XColors.Yellow, 0xFFFFFF00, "Yellow", "Gelb"), - new ColorResourceInfo(XKnownColor.Gold, XColors.Gold, 0xFFFFD700, "Gold", "Gold"), - new ColorResourceInfo(XKnownColor.Orange, XColors.Orange, 0xFFFFA500, "Orange", "Orange"), - new ColorResourceInfo(XKnownColor.DarkOrange, XColors.DarkOrange, 0xFFFF8C00, "Darkorange", "Dunkles Orange"), - //new ColorResourceInfo(XKnownColor.Goldenrod, XColors.Goldenrod, 0xFFDAA520, "Goldenrod", "Goldrute"), - new ColorResourceInfo(XKnownColor.Goldenrod, XColors.Goldenrod, 0xFFDAA520, "Goldenrod", "Goldgelb"), - //new ColorResourceInfo(XKnownColor.DarkGoldenrod, XColors.DarkGoldenrod, 0xFFB8860B, "Darkgoldenrod", "Dunkle Goldrutenfarbe"), - new ColorResourceInfo(XKnownColor.DarkGoldenrod, XColors.DarkGoldenrod, 0xFFB8860B, "Darkgoldenrod", "Dunkles Goldgelb"), - new ColorResourceInfo(XKnownColor.Peru, XColors.Peru, 0xFFCD853F, "Peru", "Peru"), - new ColorResourceInfo(XKnownColor.Chocolate, XColors.Chocolate, 0xFFD2691E, "Chocolate", "Schokolade"), - new ColorResourceInfo(XKnownColor.SaddleBrown, XColors.SaddleBrown, 0xFF8B4513, "Saddlebrown", "Sattelbraun"), - new ColorResourceInfo(XKnownColor.Sienna, XColors.Sienna, 0xFFA0522D, "Sienna", "Ocker"), - new ColorResourceInfo(XKnownColor.Brown, XColors.Brown, 0xFFA52A2A, "Brown", "Braun"), - new ColorResourceInfo(XKnownColor.DarkRed, XColors.DarkRed, 0xFF8B0000, "Darkred", "Dunkelrot"), - new ColorResourceInfo(XKnownColor.Maroon, XColors.Maroon, 0xFF800000, "Maroon", "Kastanienbraun"), - new ColorResourceInfo(XKnownColor.PaleTurquoise, XColors.PaleTurquoise, 0xFFAFEEEE, "Paleturquoise", "Blasses Türkis"), - //new ColorResourceInfo(XKnownColor.Firebrick, XColors.Firebrick, 0xFFB22222, "Firebrick", "Ziegelfarbe"), - new ColorResourceInfo(XKnownColor.Firebrick, XColors.Firebrick, 0xFFB22222, "Firebrick", "Ziegel"), - new ColorResourceInfo(XKnownColor.IndianRed, XColors.IndianRed, 0xFFCD5C5C, "Indianred", "Indischrot"), - new ColorResourceInfo(XKnownColor.Crimson, XColors.Crimson, 0xFFDC143C, "Crimson", "Karmesinrot"), - new ColorResourceInfo(XKnownColor.Red, XColors.Red, 0xFFFF0000, "Red", "Rot"), - //new ColorResourceInfo(XKnownColor.OrangeRed, XColors.OrangeRed, 0xFFFF4500, "Orangered", "Orangenrot"), - new ColorResourceInfo(XKnownColor.OrangeRed, XColors.OrangeRed, 0xFFFF4500, "Orangered", "Orangerot"), - //new ColorResourceInfo(XKnownColor.Tomato, XColors.Tomato, 0xFFFF6347, "Tomato", "Tomatenrot"), - new ColorResourceInfo(XKnownColor.Tomato, XColors.Tomato, 0xFFFF6347, "Tomato", "Tomate"), - new ColorResourceInfo(XKnownColor.Coral, XColors.Coral, 0xFFFF7F50, "Coral", "Koralle"), - new ColorResourceInfo(XKnownColor.Salmon, XColors.Salmon, 0xFFFA8072, "Salmon", "Lachs"), - new ColorResourceInfo(XKnownColor.LightCoral, XColors.LightCoral, 0xFFF08080, "Lightcoral", "Helles Korallenrot"), - //new ColorResourceInfo(XKnownColor.DarkSalmon, XColors.DarkSalmon, 0xFFE9967A, "Darksalmon", "Dunkle Lachsfarbe"), - new ColorResourceInfo(XKnownColor.DarkSalmon, XColors.DarkSalmon, 0xFFE9967A, "Darksalmon", "Dunkles Lachs"), - //new ColorResourceInfo(XKnownColor.LightSalmon, XColors.LightSalmon, 0xFFFFA07A, "Lightsalmon", "Helle Lachsfarbe"), - new ColorResourceInfo(XKnownColor.LightSalmon, XColors.LightSalmon, 0xFFFFA07A, "Lightsalmon", "Helles Lachs"), - new ColorResourceInfo(XKnownColor.SandyBrown, XColors.SandyBrown, 0xFFF4A460, "Sandybrown", "Sandbraun"), - //new ColorResourceInfo(XKnownColor.RosyBrown, XColors.RosyBrown, 0xFFBC8F8F, "Rosybrown", "Rosiges Braun"), - new ColorResourceInfo(XKnownColor.RosyBrown, XColors.RosyBrown, 0xFFBC8F8F, "Rosybrown", "Rotbraun"), - new ColorResourceInfo(XKnownColor.Tan, XColors.Tan, 0xFFD2B48C, "Tan", "Gelbbraun"), - //new ColorResourceInfo(XKnownColor.BurlyWood, XColors.BurlyWood, 0xFFDEB887, "Burlywood", "Grobes Braun"), - new ColorResourceInfo(XKnownColor.BurlyWood, XColors.BurlyWood, 0xFFDEB887, "Burlywood", "Kräftiges Sandbraun"), - new ColorResourceInfo(XKnownColor.Wheat, XColors.Wheat, 0xFFF5DEB3, "Wheat", "Weizen"), - new ColorResourceInfo(XKnownColor.PeachPuff, XColors.PeachPuff, 0xFFFFDAB9, "Peachpuff", "Pfirsich"), - //new ColorResourceInfo(XKnownColor.NavajoWhite, XColors.NavajoWhite, 0xFFFFDEAD, "Navajowhite", "Navajoweiß"), - new ColorResourceInfo(XKnownColor.NavajoWhite, XColors.NavajoWhite, 0xFFFFDEAD, "Navajowhite", "Orangeweiß"), - //new ColorResourceInfo(XKnownColor.Bisque, XColors.Bisque, 0xFFFFE4C4, "Bisque", "Tomatencreme"), - new ColorResourceInfo(XKnownColor.Bisque, XColors.Bisque, 0xFFFFE4C4, "Bisque", "Blasses Rotbraun"), - //new ColorResourceInfo(XKnownColor.Moccasin, XColors.Moccasin, 0xFFFFE4B5, "Moccasin", "Moccasin"), - new ColorResourceInfo(XKnownColor.Moccasin, XColors.Moccasin, 0xFFFFE4B5, "Moccasin", "Mokassin"), - //new ColorResourceInfo(XKnownColor.LavenderBlush, XColors.LavenderBlush, 0xFFFFF0F5, "Lavenderblush", "Rosige Lavenderfarbe"), - new ColorResourceInfo(XKnownColor.LavenderBlush, XColors.LavenderBlush, 0xFFFFF0F5, "Lavenderblush", "Roter Lavendel"), - new ColorResourceInfo(XKnownColor.MistyRose, XColors.MistyRose, 0xFFFFE4E1, "Mistyrose", "Altrosa"), - new ColorResourceInfo(XKnownColor.Pink, XColors.Pink, 0xFFFFC0CB, "Pink", "Rosa"), - new ColorResourceInfo(XKnownColor.LightPink, XColors.LightPink, 0xFFFFB6C1, "Lightpink", "Hellrosa"), - new ColorResourceInfo(XKnownColor.HotPink, XColors.HotPink, 0xFFFF69B4, "Hotpink", "Leuchtendes Rosa"), - new ColorResourceInfo(XKnownColor.Fuchsia, XColors.Fuchsia, 0xFFFF00FF, "Fuchsia", "Fuchsie"), // Same as Magenta, but needed to avoid exception at ToColorName(). - new ColorResourceInfo(XKnownColor.Magenta, XColors.Magenta, 0xFFFF00FF, "Magenta", "Magentarot"), - new ColorResourceInfo(XKnownColor.DeepPink, XColors.DeepPink, 0xFFFF1493, "Deeppink", "Tiefrosa"), - new ColorResourceInfo(XKnownColor.MediumVioletRed, XColors.MediumVioletRed, 0xFFC71585, "Mediumvioletred", "Mittleres Violettrot"), - new ColorResourceInfo(XKnownColor.PaleVioletRed, XColors.PaleVioletRed, 0xFFDB7093, "Palevioletred", "Blasses Violettrot"), - new ColorResourceInfo(XKnownColor.Plum, XColors.Plum, 0xFFDDA0DD, "Plum", "Pflaume"), - new ColorResourceInfo(XKnownColor.Thistle, XColors.Thistle, 0xFFD8BFD8, "Thistle", "Distel"), - //new ColorResourceInfo(XKnownColor.Lavender, XColors.Lavender, 0xFFE6E6FA, "Lavender", "Lavendelfarbe"), - new ColorResourceInfo(XKnownColor.Lavender, XColors.Lavender, 0xFFE6E6FA, "Lavender", "Lavendel"), - new ColorResourceInfo(XKnownColor.Violet, XColors.Violet, 0xFFEE82EE, "Violet", "Violett"), - new ColorResourceInfo(XKnownColor.Orchid, XColors.Orchid, 0xFFDA70D6, "Orchid", "Orchidee"), - new ColorResourceInfo(XKnownColor.DarkMagenta, XColors.DarkMagenta, 0xFF8B008B, "Darkmagenta", "Dunkles Magentarot"), - new ColorResourceInfo(XKnownColor.Purple, XColors.Purple, 0xFF800080, "Purple", "Violett"), - new ColorResourceInfo(XKnownColor.Indigo, XColors.Indigo, 0xFF4B0082, "Indigo", "Indigo"), - new ColorResourceInfo(XKnownColor.BlueViolet, XColors.BlueViolet, 0xFF8A2BE2, "Blueviolet", "Blauviolett"), - new ColorResourceInfo(XKnownColor.DarkViolet, XColors.DarkViolet, 0xFF9400D3, "Darkviolet", "Dunkles Violett"), - //new ColorResourceInfo(XKnownColor.DarkOrchid, XColors.DarkOrchid, 0xFF9932CC, "Darkorchid", "Dunkle Orchideenfarbe"), - new ColorResourceInfo(XKnownColor.DarkOrchid, XColors.DarkOrchid, 0xFF9932CC, "Darkorchid", "Dunkle Orchidee"), - new ColorResourceInfo(XKnownColor.MediumPurple, XColors.MediumPurple, 0xFF9370DB, "Mediumpurple", "Mittleres Violett"), - //new ColorResourceInfo(XKnownColor.MediumOrchid, XColors.MediumOrchid, 0xFFBA55D3, "Mediumorchid", "Mittlere Orchideenfarbe"), - new ColorResourceInfo(XKnownColor.MediumOrchid, XColors.MediumOrchid, 0xFFBA55D3, "Mediumorchid", "Mittlere Orchidee"), - new ColorResourceInfo(XKnownColor.MediumSlateBlue, XColors.MediumSlateBlue, 0xFF7B68EE, "Mediumslateblue", "Mittleres Schieferblau"), - new ColorResourceInfo(XKnownColor.SlateBlue, XColors.SlateBlue, 0xFF6A5ACD, "Slateblue", "Schieferblau"), - new ColorResourceInfo(XKnownColor.DarkSlateBlue, XColors.DarkSlateBlue, 0xFF483D8B, "Darkslateblue", "Dunkles Schiefergrau"), - new ColorResourceInfo(XKnownColor.MidnightBlue, XColors.MidnightBlue, 0xFF191970, "Midnightblue", "Mitternachtsblau"), - new ColorResourceInfo(XKnownColor.Navy, XColors.Navy, 0xFF000080, "Navy", "Marineblau"), - new ColorResourceInfo(XKnownColor.DarkBlue, XColors.DarkBlue, 0xFF00008B, "Darkblue", "Dunkelblau"), - new ColorResourceInfo(XKnownColor.LightGray, XColors.LightGray, 0xFFD3D3D3, "Lightgray", "Hellgrau"), - new ColorResourceInfo(XKnownColor.MediumBlue, XColors.MediumBlue, 0xFF0000CD, "Mediumblue", "Mittelblau"), - new ColorResourceInfo(XKnownColor.Blue, XColors.Blue, 0xFF0000FF, "Blue", "Blau"), - new ColorResourceInfo(XKnownColor.RoyalBlue, XColors.RoyalBlue, 0xFF4169E1, "Royalblue", "Königsblau"), - new ColorResourceInfo(XKnownColor.SteelBlue, XColors.SteelBlue, 0xFF4682B4, "Steelblue", "Stahlblau"), - new ColorResourceInfo(XKnownColor.CornflowerBlue, XColors.CornflowerBlue, 0xFF6495ED, "Cornflowerblue", "Kornblumenblau"), - new ColorResourceInfo(XKnownColor.DodgerBlue, XColors.DodgerBlue, 0xFF1E90FF, "Dodgerblue", "Dodger-Blau"), - new ColorResourceInfo(XKnownColor.DeepSkyBlue, XColors.DeepSkyBlue, 0xFF00BFFF, "Deepskyblue", "Tiefes Himmelblau"), - new ColorResourceInfo(XKnownColor.LightSkyBlue, XColors.LightSkyBlue, 0xFF87CEFA, "Lightskyblue", "Helles Himmelblau"), - new ColorResourceInfo(XKnownColor.SkyBlue, XColors.SkyBlue, 0xFF87CEEB, "Skyblue", "Himmelblau"), - new ColorResourceInfo(XKnownColor.LightBlue, XColors.LightBlue, 0xFFADD8E6, "Lightblue", "Hellblau"), - new ColorResourceInfo(XKnownColor.Aqua, XColors.Aqua, 0xFF00FFFF, "Aqua", "Blaugrün"), // Same as Cyan, but needed to avoid exception at ToColorName(). - new ColorResourceInfo(XKnownColor.Cyan, XColors.Cyan, 0xFF00FFFF, "Cyan", "Zyan"), - new ColorResourceInfo(XKnownColor.PowderBlue, XColors.PowderBlue, 0xFFB0E0E6, "Powderblue", "Taubenblau"), - new ColorResourceInfo(XKnownColor.LightCyan, XColors.LightCyan, 0xFFE0FFFF, "Lightcyan", "Helles Cyanblau"), - new ColorResourceInfo(XKnownColor.AliceBlue, XColors.AliceBlue, 0xFFA0CE00, "Aliceblue", "Aliceblau"), - new ColorResourceInfo(XKnownColor.Azure, XColors.Azure, 0xFFF0FFFF, "Azure", "Himmelblau"), - //new ColorResourceInfo(XKnownColor.MintCream, XColors.MintCream, 0xFFF5FFFA, "Mintcream", "Cremige Pfefferminzfarbe"), - new ColorResourceInfo(XKnownColor.MintCream, XColors.MintCream, 0xFFF5FFFA, "Mintcream", "Helles Pfefferminzgrün"), - new ColorResourceInfo(XKnownColor.Honeydew, XColors.Honeydew, 0xFFF0FFF0, "Honeydew", "Honigmelone"), - new ColorResourceInfo(XKnownColor.Aquamarine, XColors.Aquamarine, 0xFF7FFFD4, "Aquamarine", "Aquamarinblau"), - new ColorResourceInfo(XKnownColor.Turquoise, XColors.Turquoise, 0xFF40E0D0, "Turquoise", "Türkis"), - new ColorResourceInfo(XKnownColor.MediumTurquoise, XColors.MediumTurquoise, 0xFF48D1CC, "Mediumturqoise", "Mittleres Türkis"), - new ColorResourceInfo(XKnownColor.DarkTurquoise, XColors.DarkTurquoise, 0xFF00CED1, "Darkturquoise", "Dunkles Türkis"), - new ColorResourceInfo(XKnownColor.MediumAquamarine, XColors.MediumAquamarine, 0xFF66CDAA, "Mediumaquamarine", "Mittleres Aquamarinblau"), - new ColorResourceInfo(XKnownColor.LightSeaGreen, XColors.LightSeaGreen, 0xFF20B2AA, "Lightseagreen", "Helles Seegrün"), - new ColorResourceInfo(XKnownColor.DarkCyan, XColors.DarkCyan, 0xFF008B8B, "Darkcyan", "Dunkles Zyanblau"), - //new ColorResourceInfo(XKnownColor.Teal, XColors.Teal, 0xFF008080, "Teal", "Entenbraun"), - new ColorResourceInfo(XKnownColor.Teal, XColors.Teal, 0xFF008080, "Teal", "Entenblau"), - new ColorResourceInfo(XKnownColor.CadetBlue, XColors.CadetBlue, 0xFF5F9EA0, "Cadetblue", "Kadettblau"), - new ColorResourceInfo(XKnownColor.MediumSeaGreen, XColors.MediumSeaGreen, 0xFF3CB371, "Mediumseagreen", "Mittleres Seegrün"), - new ColorResourceInfo(XKnownColor.DarkSeaGreen, XColors.DarkSeaGreen, 0xFF8FBC8F, "Darkseagreen", "Dunkles Seegrün"), - new ColorResourceInfo(XKnownColor.LightGreen, XColors.LightGreen, 0xFF90EE90, "Lightgreen", "Hellgrün"), - new ColorResourceInfo(XKnownColor.PaleGreen, XColors.PaleGreen, 0xFF98FB98, "Palegreen", "Blassgrün"), - new ColorResourceInfo(XKnownColor.MediumSpringGreen, XColors.MediumSpringGreen, 0xFF00FA9A, "Mediumspringgreen", "Mittleres Frühlingsgrün"), - new ColorResourceInfo(XKnownColor.SpringGreen, XColors.SpringGreen, 0xFF00FF7F, "Springgreen", "Frühlingsgrün"), - new ColorResourceInfo(XKnownColor.Lime, XColors.Lime, 0xFF00FF00, "Lime", "Zitronengrün"), - new ColorResourceInfo(XKnownColor.LimeGreen, XColors.LimeGreen, 0xFF32CD32, "Limegreen", "Gelbgrün"), - new ColorResourceInfo(XKnownColor.SeaGreen, XColors.SeaGreen, 0xFF2E8B57, "Seagreen", "Seegrün"), - new ColorResourceInfo(XKnownColor.ForestGreen, XColors.ForestGreen, 0xFF228B22, "Forestgreen", "Waldgrün"), - new ColorResourceInfo(XKnownColor.Green, XColors.Green, 0xFF008000, "Green", "Grün"), - new ColorResourceInfo(XKnownColor.LawnGreen, XColors.LawnGreen, 0xFF008000, "LawnGreen", "Grasgrün"), - new ColorResourceInfo(XKnownColor.DarkGreen, XColors.DarkGreen, 0xFF006400, "Darkgreen", "Dunkelgrün"), - //new ColorResourceInfo(XKnownColor.OliveDrab, XColors.OliveDrab, 0xFF6B8E23, "Olivedrab", "Olivfarbiges Graubraun"), - new ColorResourceInfo(XKnownColor.OliveDrab, XColors.OliveDrab, 0xFF6B8E23, "Olivedrab", "Reife Olive"), - new ColorResourceInfo(XKnownColor.DarkOliveGreen, XColors.DarkOliveGreen, 0xFF556B2F, "Darkolivegreen", "Dunkles Olivgrün"), - new ColorResourceInfo(XKnownColor.Olive, XColors.Olive, 0xFF808000, "Olive", "Olivgrün"), - new ColorResourceInfo(XKnownColor.DarkKhaki, XColors.DarkKhaki, 0xFFBDB76B, "Darkkhaki", "Dunkles Khaki"), - new ColorResourceInfo(XKnownColor.YellowGreen, XColors.YellowGreen, 0xFF9ACD32, "Yellowgreen", "Gelbgrün"), - new ColorResourceInfo(XKnownColor.Chartreuse, XColors.Chartreuse, 0xFF7FFF00, "Chartreuse", "Hellgrün"), - new ColorResourceInfo(XKnownColor.GreenYellow, XColors.GreenYellow, 0xFFADFF2F, "Greenyellow", "Grüngelb"), - }; + internal static ColorResourceInfo[] colorInfos = + [ + new(XKnownColor.Transparent, XColors.Transparent, 0x00FFFFFF, "Transparent", "Transparent"), + new(XKnownColor.Black, XColors.Black, 0xFF000000, "Black", "Schwarz"), + new(XKnownColor.DarkSlateGray, XColors.DarkSlateGray, 0xFF8FBC8F, "Darkslategray", "Dunkles Schiefergrau"), + new(XKnownColor.SlateGray, XColors.SlateGray, 0xFF708090, "Slategray", "Schiefergrau"), + new(XKnownColor.LightSlateGray, XColors.LightSlateGray, 0xFF778899, "Lightslategray", "Helles Schiefergrau"), + new(XKnownColor.LightSteelBlue, XColors.LightSteelBlue, 0xFFB0C4DE, "Lightsteelblue", "Helles Stahlblau"), + //new(XKnownColor.DimGray, XColors.DimGray, 0xFF696969, "Dimgray", "Mattes Grau"), + new(XKnownColor.DimGray, XColors.DimGray, 0xFF696969, "Dimgray", "Gedecktes Grau"), + new(XKnownColor.Gray, XColors.Gray, 0xFF808080, "Gray", "Grau"), + new(XKnownColor.DarkGray, XColors.DarkGray, 0xFFA9A9A9, "Darkgray", "Dunkelgrau"), + new(XKnownColor.Silver, XColors.Silver, 0xFFC0C0C0, "Silver", "Silber"), + //new(XKnownColor.Gainsboro, XColors.Gainsboro, 0xFFDCDCDC, "Gainsboro", "Gainsboro"), + new(XKnownColor.Gainsboro, XColors.Gainsboro, 0xFFDCDCDC, "Gainsboro", "Helles Blaugrau"), + //new(XKnownColor.WhiteSmoke, XColors.WhiteSmoke, 0xFFF5F5F5, "Whitesmoke", "Rauchiges Weiß"), + new(XKnownColor.WhiteSmoke, XColors.WhiteSmoke, 0xFFF5F5F5, "Whitesmoke", "Rauchweiß"), + //new(XKnownColor.GhostWhite, XColors.GhostWhite, 0xFFF8F8FF, "Ghostwhite", "Geisterweiß"), + new(XKnownColor.GhostWhite, XColors.GhostWhite, 0xFFF8F8FF, "Ghostwhite", "Schattenweiß"), + new(XKnownColor.White, XColors.White, 0xFFFFFFFF, "White", "Weiß"), + new(XKnownColor.Snow, XColors.Snow, 0xFFFFFAFA, "Snow", "Schneeweiß"), + new(XKnownColor.Ivory, XColors.Ivory, 0xFFFFFFF0, "Ivory", "Elfenbein"), + new(XKnownColor.FloralWhite, XColors.FloralWhite, 0xFFFFFAF0, "Floralwhite", "Blütenweiß"), + new(XKnownColor.SeaShell, XColors.SeaShell, 0xFFFFF5EE, "Seashell", "Muschel"), + //new(XKnownColor.OldLace, XColors.OldLace, 0xFFFDF5E6, "Oldlace", "Altgold"), + new(XKnownColor.OldLace, XColors.OldLace, 0xFFFDF5E6, "Oldlace", "Altweiß"), + //new(XKnownColor.Linen, XColors.Linen, 0xFFFAF0E6, "Linen", "Leinenfarbe"), + new(XKnownColor.Linen, XColors.Linen, 0xFFFAF0E6, "Linen", "Leinen"), + new(XKnownColor.AntiqueWhite, XColors.AntiqueWhite, 0xFFFAEBD7, "Antiquewhite", "Antikes Weiß"), + new(XKnownColor.BlanchedAlmond, XColors.BlanchedAlmond, 0xFFFFEBCD, "Blanchedalmond", "Mandelweiß"), + //new(XKnownColor.PapayaWhip, XColors.PapayaWhip, 0xFFFFEFD5, "Papayawhip", "Cremiges Papaya"), + new(XKnownColor.PapayaWhip, XColors.PapayaWhip, 0xFFFFEFD5, "Papayawhip", "Papayacreme"), + new(XKnownColor.Beige, XColors.Beige, 0xFFF5F5DC, "Beige", "Beige"), + new(XKnownColor.Cornsilk, XColors.Cornsilk, 0xFFFFF8DC, "Cornsilk", "Mais"), + //new(XKnownColor.LightGoldenrodYellow, XColors.LightGoldenrodYellow, 0xFFFAFAD2, "Lightgoldenrodyellow", "Helles Goldrutengelb"), + new(XKnownColor.LightGoldenrodYellow, XColors.LightGoldenrodYellow, 0xFFFAFAD2, "Lightgoldenrodyellow", "Helles Goldgelb"), + new(XKnownColor.LightYellow, XColors.LightYellow, 0xFFFFFFE0, "Lightyellow", "Hellgelb"), + new(XKnownColor.LemonChiffon, XColors.LemonChiffon, 0xFFFFFACD, "Lemonchiffon", "Pastellgelb"), + //new(XKnownColor.PaleGoldenrod, XColors.PaleGoldenrod, 0xFFEEE8AA, "Palegoldenrod", "Blasse Goldrutenfarbe"), + new(XKnownColor.PaleGoldenrod, XColors.PaleGoldenrod, 0xFFEEE8AA, "Palegoldenrod", "Blasses Goldgelb"), + new(XKnownColor.Khaki, XColors.Khaki, 0xFFF0E68C, "Khaki", "Khaki"), + new(XKnownColor.Yellow, XColors.Yellow, 0xFFFFFF00, "Yellow", "Gelb"), + new(XKnownColor.Gold, XColors.Gold, 0xFFFFD700, "Gold", "Gold"), + new(XKnownColor.Orange, XColors.Orange, 0xFFFFA500, "Orange", "Orange"), + new(XKnownColor.DarkOrange, XColors.DarkOrange, 0xFFFF8C00, "Darkorange", "Dunkles Orange"), + //new(XKnownColor.Goldenrod, XColors.Goldenrod, 0xFFDAA520, "Goldenrod", "Goldrute"), + new(XKnownColor.Goldenrod, XColors.Goldenrod, 0xFFDAA520, "Goldenrod", "Goldgelb"), + //new(XKnownColor.DarkGoldenrod, XColors.DarkGoldenrod, 0xFFB8860B, "Darkgoldenrod", "Dunkle Goldrutenfarbe"), + new(XKnownColor.DarkGoldenrod, XColors.DarkGoldenrod, 0xFFB8860B, "Darkgoldenrod", "Dunkles Goldgelb"), + new(XKnownColor.Peru, XColors.Peru, 0xFFCD853F, "Peru", "Peru"), + new(XKnownColor.Chocolate, XColors.Chocolate, 0xFFD2691E, "Chocolate", "Schokolade"), + new(XKnownColor.SaddleBrown, XColors.SaddleBrown, 0xFF8B4513, "Saddlebrown", "Sattelbraun"), + new(XKnownColor.Sienna, XColors.Sienna, 0xFFA0522D, "Sienna", "Ocker"), + new(XKnownColor.Brown, XColors.Brown, 0xFFA52A2A, "Brown", "Braun"), + new(XKnownColor.DarkRed, XColors.DarkRed, 0xFF8B0000, "Darkred", "Dunkelrot"), + new(XKnownColor.Maroon, XColors.Maroon, 0xFF800000, "Maroon", "Kastanienbraun"), + new(XKnownColor.PaleTurquoise, XColors.PaleTurquoise, 0xFFAFEEEE, "Paleturquoise", "Blasses Türkis"), + //new(XKnownColor.Firebrick, XColors.Firebrick, 0xFFB22222, "Firebrick", "Ziegelfarbe"), + new(XKnownColor.Firebrick, XColors.Firebrick, 0xFFB22222, "Firebrick", "Ziegel"), + new(XKnownColor.IndianRed, XColors.IndianRed, 0xFFCD5C5C, "Indianred", "Indischrot"), + new(XKnownColor.Crimson, XColors.Crimson, 0xFFDC143C, "Crimson", "Karmesinrot"), + new(XKnownColor.Red, XColors.Red, 0xFFFF0000, "Red", "Rot"), + //new(XKnownColor.OrangeRed, XColors.OrangeRed, 0xFFFF4500, "Orangered", "Orangenrot"), + new(XKnownColor.OrangeRed, XColors.OrangeRed, 0xFFFF4500, "Orangered", "Orangerot"), + //new(XKnownColor.Tomato, XColors.Tomato, 0xFFFF6347, "Tomato", "Tomatenrot"), + new(XKnownColor.Tomato, XColors.Tomato, 0xFFFF6347, "Tomato", "Tomate"), + new(XKnownColor.Coral, XColors.Coral, 0xFFFF7F50, "Coral", "Koralle"), + new(XKnownColor.Salmon, XColors.Salmon, 0xFFFA8072, "Salmon", "Lachs"), + new(XKnownColor.LightCoral, XColors.LightCoral, 0xFFF08080, "Lightcoral", "Helles Korallenrot"), + //new(XKnownColor.DarkSalmon, XColors.DarkSalmon, 0xFFE9967A, "Darksalmon", "Dunkle Lachsfarbe"), + new(XKnownColor.DarkSalmon, XColors.DarkSalmon, 0xFFE9967A, "Darksalmon", "Dunkles Lachs"), + //new(XKnownColor.LightSalmon, XColors.LightSalmon, 0xFFFFA07A, "Lightsalmon", "Helle Lachsfarbe"), + new(XKnownColor.LightSalmon, XColors.LightSalmon, 0xFFFFA07A, "Lightsalmon", "Helles Lachs"), + new(XKnownColor.SandyBrown, XColors.SandyBrown, 0xFFF4A460, "Sandybrown", "Sandbraun"), + //new(XKnownColor.RosyBrown, XColors.RosyBrown, 0xFFBC8F8F, "Rosybrown", "Rosiges Braun"), + new(XKnownColor.RosyBrown, XColors.RosyBrown, 0xFFBC8F8F, "Rosybrown", "Rotbraun"), + new(XKnownColor.Tan, XColors.Tan, 0xFFD2B48C, "Tan", "Gelbbraun"), + //new(XKnownColor.BurlyWood, XColors.BurlyWood, 0xFFDEB887, "Burlywood", "Grobes Braun"), + new(XKnownColor.BurlyWood, XColors.BurlyWood, 0xFFDEB887, "Burlywood", "Kräftiges Sandbraun"), + new(XKnownColor.Wheat, XColors.Wheat, 0xFFF5DEB3, "Wheat", "Weizen"), + new(XKnownColor.PeachPuff, XColors.PeachPuff, 0xFFFFDAB9, "Peachpuff", "Pfirsich"), + //new(XKnownColor.NavajoWhite, XColors.NavajoWhite, 0xFFFFDEAD, "Navajowhite", "Navajoweiß"), + new(XKnownColor.NavajoWhite, XColors.NavajoWhite, 0xFFFFDEAD, "Navajowhite", "Orangeweiß"), + //new(XKnownColor.Bisque, XColors.Bisque, 0xFFFFE4C4, "Bisque", "Tomatencreme"), + new(XKnownColor.Bisque, XColors.Bisque, 0xFFFFE4C4, "Bisque", "Blasses Rotbraun"), + //new(XKnownColor.Moccasin, XColors.Moccasin, 0xFFFFE4B5, "Moccasin", "Moccasin"), + new(XKnownColor.Moccasin, XColors.Moccasin, 0xFFFFE4B5, "Moccasin", "Mokassin"), + //new(XKnownColor.LavenderBlush, XColors.LavenderBlush, 0xFFFFF0F5, "Lavenderblush", "Rosige Lavenderfarbe"), + new(XKnownColor.LavenderBlush, XColors.LavenderBlush, 0xFFFFF0F5, "Lavenderblush", "Roter Lavendel"), + new(XKnownColor.MistyRose, XColors.MistyRose, 0xFFFFE4E1, "Mistyrose", "Altrosa"), + new(XKnownColor.Pink, XColors.Pink, 0xFFFFC0CB, "Pink", "Rosa"), + new(XKnownColor.LightPink, XColors.LightPink, 0xFFFFB6C1, "Lightpink", "Hellrosa"), + new(XKnownColor.HotPink, XColors.HotPink, 0xFFFF69B4, "Hotpink", "Leuchtendes Rosa"), + new(XKnownColor.Fuchsia, XColors.Fuchsia, 0xFFFF00FF, "Fuchsia", "Fuchsie"), // Same as Magenta, but needed to avoid exception at ToColorName(). + new(XKnownColor.Magenta, XColors.Magenta, 0xFFFF00FF, "Magenta", "Magentarot"), + new(XKnownColor.DeepPink, XColors.DeepPink, 0xFFFF1493, "Deeppink", "Tiefrosa"), + new(XKnownColor.MediumVioletRed, XColors.MediumVioletRed, 0xFFC71585, "Mediumvioletred", "Mittleres Violettrot"), + new(XKnownColor.PaleVioletRed, XColors.PaleVioletRed, 0xFFDB7093, "Palevioletred", "Blasses Violettrot"), + new(XKnownColor.Plum, XColors.Plum, 0xFFDDA0DD, "Plum", "Pflaume"), + new(XKnownColor.Thistle, XColors.Thistle, 0xFFD8BFD8, "Thistle", "Distel"), + //new(XKnownColor.Lavender, XColors.Lavender, 0xFFE6E6FA, "Lavender", "Lavendelfarbe"), + new(XKnownColor.Lavender, XColors.Lavender, 0xFFE6E6FA, "Lavender", "Lavendel"), + new(XKnownColor.Violet, XColors.Violet, 0xFFEE82EE, "Violet", "Violett"), + new(XKnownColor.Orchid, XColors.Orchid, 0xFFDA70D6, "Orchid", "Orchidee"), + new(XKnownColor.DarkMagenta, XColors.DarkMagenta, 0xFF8B008B, "Darkmagenta", "Dunkles Magentarot"), + new(XKnownColor.Purple, XColors.Purple, 0xFF800080, "Purple", "Violett"), + new(XKnownColor.Indigo, XColors.Indigo, 0xFF4B0082, "Indigo", "Indigo"), + new(XKnownColor.BlueViolet, XColors.BlueViolet, 0xFF8A2BE2, "Blueviolet", "Blauviolett"), + new(XKnownColor.DarkViolet, XColors.DarkViolet, 0xFF9400D3, "Darkviolet", "Dunkles Violett"), + //new(XKnownColor.DarkOrchid, XColors.DarkOrchid, 0xFF9932CC, "Darkorchid", "Dunkle Orchideenfarbe"), + new(XKnownColor.DarkOrchid, XColors.DarkOrchid, 0xFF9932CC, "Darkorchid", "Dunkle Orchidee"), + new(XKnownColor.MediumPurple, XColors.MediumPurple, 0xFF9370DB, "Mediumpurple", "Mittleres Violett"), + //new(XKnownColor.MediumOrchid, XColors.MediumOrchid, 0xFFBA55D3, "Mediumorchid", "Mittlere Orchideenfarbe"), + new(XKnownColor.MediumOrchid, XColors.MediumOrchid, 0xFFBA55D3, "Mediumorchid", "Mittlere Orchidee"), + new(XKnownColor.MediumSlateBlue, XColors.MediumSlateBlue, 0xFF7B68EE, "Mediumslateblue", "Mittleres Schieferblau"), + new(XKnownColor.SlateBlue, XColors.SlateBlue, 0xFF6A5ACD, "Slateblue", "Schieferblau"), + new(XKnownColor.DarkSlateBlue, XColors.DarkSlateBlue, 0xFF483D8B, "Darkslateblue", "Dunkles Schiefergrau"), + new(XKnownColor.MidnightBlue, XColors.MidnightBlue, 0xFF191970, "Midnightblue", "Mitternachtsblau"), + new(XKnownColor.Navy, XColors.Navy, 0xFF000080, "Navy", "Marineblau"), + new(XKnownColor.DarkBlue, XColors.DarkBlue, 0xFF00008B, "Darkblue", "Dunkelblau"), + new(XKnownColor.LightGray, XColors.LightGray, 0xFFD3D3D3, "Lightgray", "Hellgrau"), + new(XKnownColor.MediumBlue, XColors.MediumBlue, 0xFF0000CD, "Mediumblue", "Mittelblau"), + new(XKnownColor.Blue, XColors.Blue, 0xFF0000FF, "Blue", "Blau"), + new(XKnownColor.RoyalBlue, XColors.RoyalBlue, 0xFF4169E1, "Royalblue", "Königsblau"), + new(XKnownColor.SteelBlue, XColors.SteelBlue, 0xFF4682B4, "Steelblue", "Stahlblau"), + new(XKnownColor.CornflowerBlue, XColors.CornflowerBlue, 0xFF6495ED, "Cornflowerblue", "Kornblumenblau"), + new(XKnownColor.DodgerBlue, XColors.DodgerBlue, 0xFF1E90FF, "Dodgerblue", "Dodger-Blau"), + new(XKnownColor.DeepSkyBlue, XColors.DeepSkyBlue, 0xFF00BFFF, "Deepskyblue", "Tiefes Himmelblau"), + new(XKnownColor.LightSkyBlue, XColors.LightSkyBlue, 0xFF87CEFA, "Lightskyblue", "Helles Himmelblau"), + new(XKnownColor.SkyBlue, XColors.SkyBlue, 0xFF87CEEB, "Skyblue", "Himmelblau"), + new(XKnownColor.LightBlue, XColors.LightBlue, 0xFFADD8E6, "Lightblue", "Hellblau"), + new(XKnownColor.Aqua, XColors.Aqua, 0xFF00FFFF, "Aqua", "Blaugrün"), // Same as Cyan, but needed to avoid exception at ToColorName(). + new(XKnownColor.Cyan, XColors.Cyan, 0xFF00FFFF, "Cyan", "Zyan"), + new(XKnownColor.PowderBlue, XColors.PowderBlue, 0xFFB0E0E6, "Powderblue", "Taubenblau"), + new(XKnownColor.LightCyan, XColors.LightCyan, 0xFFE0FFFF, "Lightcyan", "Helles Cyanblau"), + new(XKnownColor.AliceBlue, XColors.AliceBlue, 0xFFA0CE00, "Aliceblue", "Aliceblau"), + new(XKnownColor.Azure, XColors.Azure, 0xFFF0FFFF, "Azure", "Himmelblau"), + //new(XKnownColor.MintCream, XColors.MintCream, 0xFFF5FFFA, "Mintcream", "Cremige Pfefferminzfarbe"), + new(XKnownColor.MintCream, XColors.MintCream, 0xFFF5FFFA, "Mintcream", "Helles Pfefferminzgrün"), + new(XKnownColor.Honeydew, XColors.Honeydew, 0xFFF0FFF0, "Honeydew", "Honigmelone"), + new(XKnownColor.Aquamarine, XColors.Aquamarine, 0xFF7FFFD4, "Aquamarine", "Aquamarinblau"), + new(XKnownColor.Turquoise, XColors.Turquoise, 0xFF40E0D0, "Turquoise", "Türkis"), + new(XKnownColor.MediumTurquoise, XColors.MediumTurquoise, 0xFF48D1CC, "Mediumturqoise", "Mittleres Türkis"), + new(XKnownColor.DarkTurquoise, XColors.DarkTurquoise, 0xFF00CED1, "Darkturquoise", "Dunkles Türkis"), + new(XKnownColor.MediumAquamarine, XColors.MediumAquamarine, 0xFF66CDAA, "Mediumaquamarine", "Mittleres Aquamarinblau"), + new(XKnownColor.LightSeaGreen, XColors.LightSeaGreen, 0xFF20B2AA, "Lightseagreen", "Helles Seegrün"), + new(XKnownColor.DarkCyan, XColors.DarkCyan, 0xFF008B8B, "Darkcyan", "Dunkles Zyanblau"), + //new(XKnownColor.Teal, XColors.Teal, 0xFF008080, "Teal", "Entenbraun"), + new(XKnownColor.Teal, XColors.Teal, 0xFF008080, "Teal", "Entenblau"), + new(XKnownColor.CadetBlue, XColors.CadetBlue, 0xFF5F9EA0, "Cadetblue", "Kadettblau"), + new(XKnownColor.MediumSeaGreen, XColors.MediumSeaGreen, 0xFF3CB371, "Mediumseagreen", "Mittleres Seegrün"), + new(XKnownColor.DarkSeaGreen, XColors.DarkSeaGreen, 0xFF8FBC8F, "Darkseagreen", "Dunkles Seegrün"), + new(XKnownColor.LightGreen, XColors.LightGreen, 0xFF90EE90, "Lightgreen", "Hellgrün"), + new(XKnownColor.PaleGreen, XColors.PaleGreen, 0xFF98FB98, "Palegreen", "Blassgrün"), + new(XKnownColor.MediumSpringGreen, XColors.MediumSpringGreen, 0xFF00FA9A, "Mediumspringgreen", "Mittleres Frühlingsgrün"), + new(XKnownColor.SpringGreen, XColors.SpringGreen, 0xFF00FF7F, "Springgreen", "Frühlingsgrün"), + new(XKnownColor.Lime, XColors.Lime, 0xFF00FF00, "Lime", "Zitronengrün"), + new(XKnownColor.LimeGreen, XColors.LimeGreen, 0xFF32CD32, "Limegreen", "Gelbgrün"), + new(XKnownColor.SeaGreen, XColors.SeaGreen, 0xFF2E8B57, "Seagreen", "Seegrün"), + new(XKnownColor.ForestGreen, XColors.ForestGreen, 0xFF228B22, "Forestgreen", "Waldgrün"), + new(XKnownColor.Green, XColors.Green, 0xFF008000, "Green", "Grün"), + new(XKnownColor.LawnGreen, XColors.LawnGreen, 0xFF008000, "LawnGreen", "Grasgrün"), + new(XKnownColor.DarkGreen, XColors.DarkGreen, 0xFF006400, "Darkgreen", "Dunkelgrün"), + //new(XKnownColor.OliveDrab, XColors.OliveDrab, 0xFF6B8E23, "Olivedrab", "Olivfarbiges Graubraun"), + new(XKnownColor.OliveDrab, XColors.OliveDrab, 0xFF6B8E23, "Olivedrab", "Reife Olive"), + new(XKnownColor.DarkOliveGreen, XColors.DarkOliveGreen, 0xFF556B2F, "Darkolivegreen", "Dunkles Olivgrün"), + new(XKnownColor.Olive, XColors.Olive, 0xFF808000, "Olive", "Olivgrün"), + new(XKnownColor.DarkKhaki, XColors.DarkKhaki, 0xFFBDB76B, "Darkkhaki", "Dunkles Khaki"), + new(XKnownColor.YellowGreen, XColors.YellowGreen, 0xFF9ACD32, "Yellowgreen", "Gelbgrün"), + new(XKnownColor.Chartreuse, XColors.Chartreuse, 0xFF7FFF00, "Chartreuse", "Hellgrün"), + new(XKnownColor.GreenYellow, XColors.GreenYellow, 0xFFADFF2F, "Greenyellow", "Grüngelb") + ]; internal struct ColorResourceInfo { diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XConvert.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XConvert.cs index 1d7f7472..275b4495 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XConvert.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XConvert.cs @@ -26,7 +26,7 @@ public static LineJoin ToLineJoin(XLineJoin lineJoin) { return GdiLineJoin[(int)lineJoin]; } - static readonly LineJoin[] GdiLineJoin = new LineJoin[] { LineJoin.Miter, LineJoin.Round, LineJoin.Bevel }; + static readonly LineJoin[] GdiLineJoin = [LineJoin.Miter, LineJoin.Round, LineJoin.Bevel]; #endif #if GDI @@ -37,7 +37,7 @@ public static LineCap ToLineCap(XLineCap lineCap) { return GdiLineCap[(int)lineCap]; } - static readonly LineCap[] GdiLineCap = new[] { LineCap.Flat, LineCap.Round, LineCap.Square }; + static readonly LineCap[] GdiLineCap = [LineCap.Flat, LineCap.Round, LineCap.Square]; #endif #if WPF @@ -48,7 +48,7 @@ public static PenLineJoin ToPenLineJoin(XLineJoin lineJoin) { return WpfLineJoin[(int)lineJoin]; } - static readonly PenLineJoin[] WpfLineJoin = new PenLineJoin[] { PenLineJoin.Miter, PenLineJoin.Round, PenLineJoin.Bevel }; + static readonly PenLineJoin[] WpfLineJoin = [PenLineJoin.Miter, PenLineJoin.Round, PenLineJoin.Bevel]; #endif #if WPF @@ -59,7 +59,7 @@ public static PenLineCap ToPenLineCap(XLineCap lineCap) { return WpfLineCap[(int)lineCap]; } - static readonly PenLineCap[] WpfLineCap = { PenLineCap.Flat, PenLineCap.Round, PenLineCap.Square }; + static readonly PenLineCap[] WpfLineCap = [PenLineCap.Flat, PenLineCap.Round, PenLineCap.Square]; #endif } } \ No newline at end of file diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFont.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFont.cs index f4fd7900..100ca5d4 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFont.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFont.cs @@ -15,7 +15,7 @@ using WpfTypeface = System.Windows.Media.Typeface; using WpfGlyphTypeface = System.Windows.Media.GlyphTypeface; #endif -#if UWP +#if WUI using UwpFontFamily = Windows.UI.Xaml.Media.FontFamily; #endif using PdfSharp.Fonts; @@ -526,8 +526,9 @@ void CreateDescriptorAndInitializeFontMetrics() // TODO: refactor /// public bool Underline => (_style & XFontStyleEx.Underline) == XFontStyleEx.Underline; +#if true_ // #DELETE /// - /// Temporary HACK for XPS to PDF converter. + /// Temporary H/ACK for XPS to PDF converter. /// internal bool IsVertical { @@ -535,6 +536,7 @@ internal bool IsVertical set => _isVertical = value; } bool _isVertical; +#endif /// /// Indicates whether this XFont object is a symbol font. @@ -620,7 +622,7 @@ public XFontMetrics Metrics public double GetHeight() { double value = CellSpace * _emSize / UnitsPerEm; -#if CORE || UWP +#if CORE || WUI return value; #endif #if GDI && !WPF @@ -649,7 +651,7 @@ public double GetHeight(XGraphics graphics) #if true throw new InvalidOperationException("Honestly: Use GetHeight() without parameter!"); #else -#if CORE || UWP +#if CORE || WUI double value = CellSpace * _emSize / UnitsPerEm; return value; #endif diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontFamily.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontFamily.cs index ff39488a..67e28fa9 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontFamily.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontFamily.cs @@ -222,8 +222,8 @@ public bool IsStyleAvailable(XFontStyleEx style) #endif return FontHelper.IsStyleAvailable(this, xStyle); #endif -#if UWP - throw new InvalidOperationException("In UWP build it is the responsibility of the developer to provide all required font faces."); +#if WUI + throw new InvalidOperationException("In WUI build it is the responsibility of the developer to provide all required font faces."); #endif } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontSource.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontSource.cs index a1343ef3..dfeb07d6 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontSource.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontSource.cs @@ -29,7 +29,7 @@ public class XFontSource // * XFontSource represents a single font (file) in memory. // * An XFontSource holds a reference to its OpenTypeFontFace. // * To prevent large heap fragmentation this class must exist only once. - // * TODO: ttcf + // * ttcf postponed to PDFsharp.Fonts. // Signature of a true type collection font. const uint ttcf = 0x66637474; @@ -73,8 +73,8 @@ public static XFontSource CreateFromFile(string path) #if CORE internal static XFontSource GetOrCreateFromGlyphTypeface(string typefaceKey, XGlyphTypeface? glyphTypeface) { - // #CORE HACK - throw new NotImplementedException(); + // #CORE NYI + throw new NotImplementedException(nameof(GetOrCreateFromGlyphTypeface)); //byte[] bytes = null; //FontDataHelper.SegoeWP; //XFontSource fontSource = GetOrCreateFrom(typefaceKey, bytes); @@ -230,9 +230,9 @@ internal ulong Key } ulong _key; - //public void IncrementKey() + //public void IncrementKey() // #DELETE //{ - // // HACK: Depends on implementation of CalcChecksum. + // // H/ACK: Depends on implementation of CalcChecksum. // // Increment check sum and keep length untouched. // _key += 1ul << 32; //} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontWeight.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontWeight.cs index d3e11ab9..167c35b9 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontWeight.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XFontWeight.cs @@ -22,7 +22,7 @@ internal XFontWeight(int weight) //public static XFontWeight FromOpenTypeWeight(int weightValue) //{ // if (weightValue < 1 || weightValue > 999) - // throw new ArgumentOutOfRangeException("weightValue", "Parameter must be between 1 and 999."); + // throw new ArgumentOutOfRangeException(nameof(weightValue), "Parameter must be between 1 and 999."); // return new XFontWeight(weightValue); //} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGlyphTypeface.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGlyphTypeface.cs index a1c9d9cb..735a93fd 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGlyphTypeface.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGlyphTypeface.cs @@ -17,7 +17,7 @@ using WpfGlyphTypeface = System.Windows.Media.GlyphTypeface; using WpfStyleSimulations = System.Windows.Media.StyleSimulations; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media; #endif using Microsoft.Extensions.Logging; @@ -115,7 +115,7 @@ public XGlyphTypeface(XFontSource fontSource) } #endif -#if UWP +#if WUI XGlyphTypeface(string key, XFontFamily fontFamily, XFontSource fontSource, XStyleSimulations styleSimulations) { _key = key; @@ -201,7 +201,7 @@ internal static XGlyphTypeface GetOrCreateFrom(string familyName, FontResolvingO WpfTypeface? wpfTypeface = null; WpfGlyphTypeface? wpfGlyphTypeface = null; #endif -#if UWP +#if WUI // Nothing to do. #endif // Now create the font family at the first. @@ -229,7 +229,7 @@ internal static XGlyphTypeface GetOrCreateFrom(string familyName, FontResolvingO wpfGlyphTypeface = platformFontResolverInfo.WpfGlyphTypeface; fontFamily = XFontFamily.GetOrCreateFromWpf(wpfFontFamily); #endif -#if UWP +#if WUI fontFamily = null; #endif } @@ -255,7 +255,7 @@ internal static XGlyphTypeface GetOrCreateFrom(string familyName, FontResolvingO #if WPF glyphTypeface = new XGlyphTypeface(typefaceKey, fontFamily, fontSource, fontResolverInfo.StyleSimulations, wpfTypeface, wpfGlyphTypeface); #endif -#if UWP +#if WUI glyphTypeface = new XGlyphTypeface(typefaceKey, fontFamily, fontSource, fontResolverInfo.StyleSimulations); #endif GlyphTypefaceCache.AddGlyphTypeface(glyphTypeface); @@ -452,19 +452,11 @@ internal string GetBaseName() // #NFM { string name = DisplayName; int ich = name.IndexOf("bold", StringComparison.OrdinalIgnoreCase); -#if NET6_0_OR_GREATER || true if (ich > 0) name = name[..ich] + name.Substring(ich + 4, name.Length - ich - 4); ich = name.IndexOf("italic", StringComparison.OrdinalIgnoreCase); if (ich > 0) name = name[..ich] + name.Substring(ich + 6, name.Length - ich - 6); -#else - if (ich > 0) - name = name.Substring(0, ich) + name.Substring(ich + 4, name.Length - ich - 4); - ich = name.IndexOf("italic", StringComparison.OrdinalIgnoreCase); - if (ich > 0) - name = name.Substring(0, ich) + name.Substring(ich + 6, name.Length - ich - 6); -#endif //name = name.Replace(" ", ""); name = name.Trim(); name += GetFaceNameSuffix(); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGradientBrush.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGradientBrush.cs index d4b7695f..d09b6613 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGradientBrush.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGradientBrush.cs @@ -17,7 +17,7 @@ using SysRect = System.Windows.Rect; using WpfBrush = System.Windows.Media.Brush; #endif -#if UWP +#if WUI using Windows.UI; using Windows.UI.Xaml.Media; using Microsoft.Graphics.Canvas; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphics.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphics.cs index 769b7331..3565c9eb 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphics.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphics.cs @@ -28,7 +28,7 @@ using WpfPen = System.Windows.Media.Pen; using WpfBrushes = System.Windows.Media.Brushes; #endif -#if UWP +#if WUI using System.Numerics; using Windows.UI; using Windows.UI.Xaml.Controls; @@ -248,7 +248,7 @@ public sealed class XGraphics : IDisposable } #endif -#if UWP +#if WUI /// /// Initializes a new instance of the XGraphics class. /// @@ -259,7 +259,7 @@ public sealed class XGraphics : IDisposable XGraphics(CanvasDrawingSession canvasDrawingSession, XSize size, XGraphicsUnit pageUnit, XPageDirection pageDirection) { if (canvasDrawingSession == null) - throw new ArgumentNullException("canvasDrawingSession"); + throw new ArgumentNullException(nameof(canvasDrawingSession)); _cds = canvasDrawingSession; @@ -344,8 +344,7 @@ public sealed class XGraphics : IDisposable TargetContext = XGraphicTargetContext.CORE; #endif #if GDI - // HACK: This does not work with #MediumTrust - //_gfx = Graphics.FromHwnd(IntPtr.Zero); // _gfx should not be necessary anymore. + // _gfx is not needed anymore for drawing on a page. _gfx = default!; TargetContext = XGraphicTargetContext.GDI; #endif @@ -564,7 +563,7 @@ public static XGraphics CreateMeasureContext(XSize size, XGraphicsUnit pageUnit, return gfx; #endif -#if UWP +#if WUI return null; #endif } @@ -644,13 +643,13 @@ public static XGraphics FromCanvas(Canvas canvas, XSize size, XGraphicsUnit unit } #endif -#if UWP +#if WUI /// /// Creates a new instance of the XGraphics class from a Microsoft.Graphics.Canvas.CanvasDrawingSession object. /// public static XGraphics FromCanvasDrawingSession(CanvasDrawingSession drawingSession, XSize size, XGraphicsUnit unit) { - PdfSharpLogHost.Logger.XGraphicsCreated -- TODO + PdfSharpLogHost.Logger.XGraphicsCreated return new XGraphics(drawingSession, size, unit, XPageDirection.Downwards); } #endif @@ -815,8 +814,8 @@ public static XGraphics FromForm(XForm form) DiagnosticsHelper.ThrowNotImplementedException("WPF image"); return null; #endif -#if UWP - DiagnosticsHelper.ThrowNotImplementedException("UWP image"); +#if WUI + DiagnosticsHelper.ThrowNotImplementedException("WUI image"); return null; #endif } @@ -1120,7 +1119,7 @@ public void DrawLine(XPen pen, double x1, double y1, double x2, double y2) if (TargetContext == XGraphicTargetContext.WPF) _dc.DrawLine(pen.RealizeWpfPen(), new SysPoint(x1, y1), new SysPoint(x2, y2)); #endif -#if UWP +#if WUI _cds.DrawLine(new Vector2((float)x1, (float)x2), new Vector2((float)x2, (float)y2), Colors.Red, (float)pen.Width); #endif } @@ -1138,7 +1137,7 @@ public void DrawLines(XPen pen, GdiPoint[] points) => DrawLines(pen, MakePointFArray(points, 0, points.Length)); #endif -#if WPF || UWP +#if WPF || WUI /// /// Draws a series of line segments that connect an array of points. /// @@ -1155,11 +1154,11 @@ public void DrawLines(XPen pen, SysPoint[] points) public void DrawLines(XPen pen, GdiPointF[] points) { if (pen == null) - throw new ArgumentNullException("pen"); + throw new ArgumentNullException(nameof(pen)); if (points == null) - throw new ArgumentNullException("points"); + throw new ArgumentNullException(nameof(points)); if (points.Length < 2) - throw new ArgumentException(PSSR.PointArrayAtLeast(2), "points"); + throw new ArgumentException(PsMsgs.PointArrayAtLeast(2), "points"); if (_drawGraphics) { @@ -1185,7 +1184,7 @@ public void DrawLines(XPen pen, XPoint[] points) if (points == null) throw new ArgumentNullException(nameof(points)); if (points.Length < 2) - throw new ArgumentException(PSSR.PointArrayAtLeast(2), nameof(points)); + throw new ArgumentException(PsMsgs.PointArrayAtLeast(2), nameof(points)); if (_drawGraphics) { @@ -1222,7 +1221,7 @@ public void DrawLines(XPen pen, XPoint[] points) _dc.DrawGeometry(null, pen.RealizeWpfPen(), geo); } #endif -#if UWP +#if WUI var pathBuilder = new CanvasPathBuilder(_cds.Device); pathBuilder.BeginFigure((float)points[0].X, (float)points[0].Y, CanvasFigureFill.DoesNotAffectFills); int length = points.Length; @@ -1345,8 +1344,7 @@ public void DrawBezier(XPen pen, double x1, double y1, double x2, double y2, #endif } - _renderer?.DrawBeziers(pen, - new[] { new XPoint(x1, y1), new XPoint(x2, y2), new XPoint(x3, y3), new XPoint(x4, y4) }); + _renderer?.DrawBeziers(pen, [new XPoint(x1, y1), new XPoint(x2, y2), new XPoint(x3, y3), new XPoint(x4, y4)]); } // ----- DrawBeziers -------------------------------------------------------------------------- @@ -1755,8 +1753,8 @@ public void DrawRectangle(XPen pen, double x, double y, double width, double hei _dc.DrawRectangle(null, pen.RealizeWpfPen(), new Rect(x, y, width, height)); } #endif -#if UWP - if (TargetContext == XGraphicTargetContext.UWP) +#if WUI + if (TargetContext == XGraphicTargetContext.WUI) { _cds.DrawRectangle((float)x, (float)y, (float)width, (float)height, pen.Color.ToUwpColor()); } @@ -1822,8 +1820,8 @@ public void DrawRectangle(XBrush brush, double x, double y, double width, double if (TargetContext == XGraphicTargetContext.WPF) _dc.DrawRectangle(brush.RealizeWpfBrush(), null, new Rect(x, y, width, height)); #endif -#if UWP - if (TargetContext == XGraphicTargetContext.UWP) +#if WUI + if (TargetContext == XGraphicTargetContext.WUI) { _cds.DrawRectangle((float)x, (float)y, (float)width, (float)height, brush.RealizeCanvasBrush()); } @@ -1872,7 +1870,7 @@ public void DrawRectangle(XPen? pen, XBrush? brush, double x, double y, double w if (pen == null && brush == null) { // ReSharper disable once NotResolvedInText - throw new ArgumentNullException("pen and brush", PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(pen) + " and " + nameof(brush), PsMsgs.NeedPenOrBrush); } if (_drawGraphics) @@ -1914,9 +1912,9 @@ public void DrawRectangle(XPen? pen, XBrush? brush, double x, double y, double w public void DrawRectangles(XPen pen, GdiRect[] rectangles) { if (pen == null) - throw new ArgumentNullException("pen"); + throw new ArgumentNullException(nameof(pen)); if (rectangles == null) - throw new ArgumentNullException("rectangles"); + throw new ArgumentNullException(nameof(rectangles)); DrawRectangles(pen, null, rectangles); } @@ -1929,9 +1927,9 @@ public void DrawRectangles(XPen pen, GdiRect[] rectangles) public void DrawRectangles(XPen pen, GdiRectF[] rectangles) { if (pen == null) - throw new ArgumentNullException("pen"); + throw new ArgumentNullException(nameof(pen)); if (rectangles == null) - throw new ArgumentNullException("rectangles"); + throw new ArgumentNullException(nameof(rectangles)); DrawRectangles(pen, null, rectangles); } @@ -1959,9 +1957,9 @@ public void DrawRectangles(XPen pen, XRect[] rectangles) public void DrawRectangles(XBrush brush, GdiRect[] rectangles) { if (brush == null) - throw new ArgumentNullException("brush"); + throw new ArgumentNullException(nameof(brush)); if (rectangles == null) - throw new ArgumentNullException("rectangles"); + throw new ArgumentNullException(nameof(rectangles)); DrawRectangles(null, brush, rectangles); } @@ -1974,9 +1972,9 @@ public void DrawRectangles(XBrush brush, GdiRect[] rectangles) public void DrawRectangles(XBrush brush, GdiRectF[] rectangles) { if (brush == null) - throw new ArgumentNullException("brush"); + throw new ArgumentNullException(nameof(brush)); if (rectangles == null) - throw new ArgumentNullException("rectangles"); + throw new ArgumentNullException(nameof(rectangles)); DrawRectangles(null, brush, rectangles); } @@ -2004,9 +2002,9 @@ public void DrawRectangles(XBrush brush, XRect[] rectangles) public void DrawRectangles(XPen? pen, XBrush? brush, Rectangle[] rectangles) { if (pen == null && brush == null) - throw new ArgumentNullException("pen and brush", PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(pen) + " and " + nameof(brush), PsMsgs.NeedPenOrBrush); if (rectangles == null) - throw new ArgumentNullException("rectangles"); + throw new ArgumentNullException(nameof(rectangles)); if (_drawGraphics) { @@ -2039,9 +2037,9 @@ public void DrawRectangles(XPen? pen, XBrush? brush, Rectangle[] rectangles) public void DrawRectangles(XPen? pen, XBrush? brush, GdiRectF[] rectangles) { if (pen == null && brush == null) - throw new ArgumentNullException("pen and brush", PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(pen) + " and " + nameof(brush), PsMsgs.NeedPenOrBrush); if (rectangles == null) - throw new ArgumentNullException("rectangles"); + throw new ArgumentNullException(nameof(rectangles)); if (_drawGraphics) { @@ -2075,7 +2073,7 @@ public void DrawRectangles(XPen? pen, XBrush? brush, XRect[] rectangles) if (pen == null && brush == null) { // ReSharper disable once NotResolvedInText - throw new ArgumentNullException("pen and brush", PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(pen) + " and " + nameof(brush), PsMsgs.NeedPenOrBrush); } if (rectangles == null) throw new ArgumentNullException(nameof(rectangles)); @@ -2278,7 +2276,7 @@ public void DrawRoundedRectangle(XPen? pen, XBrush? brush, double x, double y, d if (pen == null && brush == null) { // ReSharper disable once NotResolvedInText - throw new ArgumentNullException("pen and brush", PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(pen) + " and " + nameof(brush), PsMsgs.NeedPenOrBrush); } if (_drawGraphics) @@ -2479,7 +2477,7 @@ public void DrawEllipse(XPen? pen, XBrush? brush, double x, double y, double wid if (pen == null && brush == null) { // ReSharper disable once NotResolvedInText - throw new ArgumentNullException("pen and brush", PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(pen) + " and " + nameof(brush), PsMsgs.NeedPenOrBrush); } if (_drawGraphics) @@ -2509,11 +2507,11 @@ public void DrawEllipse(XPen? pen, XBrush? brush, double x, double y, double wid new SysPoint(x + radiusX, y + radiusY), radiusX, radiusY); } #endif -#if UWP +#if WUI //var cds = new CanvasDrawingSession(); //cds.DrawCachedGeometry(); - if (TargetContext == XGraphicTargetContext.UWP) + if (TargetContext == XGraphicTargetContext.WUI) { var radiusX = (float)width / 2; var radiusY = (float)height / 2; @@ -2575,7 +2573,7 @@ public void DrawPolygon(XPen pen, XPoint[] points) if (points == null) throw new ArgumentNullException(nameof(points)); if (points.Length < 2) - throw new ArgumentException(PSSR.PointArrayAtLeast(2), nameof(points)); + throw new ArgumentException(PsMsgs.PointArrayAtLeast(2), nameof(points)); if (_drawGraphics) { @@ -2643,7 +2641,7 @@ public void DrawPolygon(XBrush brush, XPoint[] points, XFillMode fillMode) if (points == null) throw new ArgumentNullException(nameof(points)); if (points.Length < 2) - throw new ArgumentException(PSSR.PointArrayAtLeast(2), nameof(points)); + throw new ArgumentException(PsMsgs.PointArrayAtLeast(2), nameof(points)); if (_drawGraphics) { @@ -2707,13 +2705,13 @@ public void DrawPolygon(XPen? pen, XBrush? brush, XPoint[] points, XFillMode fil if (pen == null && brush == null) { // ReSharper disable once NotResolvedInText - throw new ArgumentNullException("pen and brush", PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(pen) + " and " + nameof(brush), PsMsgs.NeedPenOrBrush); } if (points == null) throw new ArgumentNullException(nameof(points)); if (points.Length < 2) - throw new ArgumentException(PSSR.PointArrayAtLeast(2), nameof(points)); + throw new ArgumentException(PsMsgs.PointArrayAtLeast(2), nameof(points)); if (_drawGraphics) { @@ -2787,7 +2785,7 @@ public void DrawPie(XPen pen, XRect rect, double startAngle, double sweepAngle) public void DrawPie(XPen pen, double x, double y, double width, double height, double startAngle, double sweepAngle) { if (pen == null) - throw new ArgumentNullException(nameof(pen), PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(pen), PsMsgs.NeedPenOrBrush); if (_drawGraphics) { @@ -2848,7 +2846,7 @@ public void DrawPie(XBrush brush, XRect rect, double startAngle, double sweepAng public void DrawPie(XBrush brush, double x, double y, double width, double height, double startAngle, double sweepAngle) { if (brush == null) - throw new ArgumentNullException(nameof(brush), PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(brush), PsMsgs.NeedPenOrBrush); if (_drawGraphics) { @@ -2908,7 +2906,7 @@ public void DrawPie(XPen? pen, XBrush? brush, XRect rect, double startAngle, dou public void DrawPie(XPen? pen, XBrush? brush, double x, double y, double width, double height, double startAngle, double sweepAngle) { if (pen == null && brush == null) - throw new ArgumentNullException(nameof(pen), PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(pen), PsMsgs.NeedPenOrBrush); if (_drawGraphics) { @@ -3267,7 +3265,7 @@ public void DrawClosedCurve(XPen? pen, XBrush? brush, XPoint[] points, XFillMode if (pen == null && brush == null) { // ReSharper disable once NotResolvedInText - throw new ArgumentNullException("pen and brush", PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(pen) + " and " + nameof(brush), PsMsgs.NeedPenOrBrush); } int count = points.Length; @@ -3408,7 +3406,7 @@ public void DrawPath(XPen? pen, XBrush? brush, XGraphicsPath path) if (pen == null && brush == null) { // ReSharper disable once NotResolvedInText - throw new ArgumentNullException("pen and brush", PSSR.NeedPenOrBrush); + throw new ArgumentNullException(nameof(pen) + " and " + nameof(brush), PsMsgs.NeedPenOrBrush); } if (path == null) throw new ArgumentNullException(nameof(path)); @@ -3594,7 +3592,7 @@ public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectan //GlyphRun glyphRun=new GlyphRun(font.GlyphTypeface , 0,); #if DEBUG_ - if (font.WpfTypeface.FontFamily.Source == "Segoe UI Light") + if (font.WpfTypeface!.FontFamily.Source == "Segoe UI Light") _ = typeof(int); #endif var formattedText = FontHelper.CreateFormattedText(text, font.WpfTypeface ?? NRT.ThrowOnNull(), @@ -3628,8 +3626,20 @@ public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectan case XLineAlignment.Center: // TODO use CapHeight. PDFlib also uses 3/4 of ascent +#if DEBUG + var test = y; +#endif y += -formattedText.Baseline + (cyAscent * 1 / 3) + layoutRectangle.Height / 2; //y += -formattedText.Baseline + (font.Size * font.Metrics.CapHeight / font.unitsPerEm / 2) + layoutRectangle.Height / 2; +#if DEBUG + test += -formattedText.Baseline + (font.Size * font.Metrics.CapHeight / font.UnitsPerEm / 2) + layoutRectangle.Height / 2; + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (test != y) + { + PdfSharpLogHost.Logger.LogInformation($"DrawString XLineAlignment.Center: y={y} test={test}"); + } + +#endif break; case XLineAlignment.Far: @@ -3706,6 +3716,15 @@ public XSize MeasureString(string text, XFont font, XStringFormat stringFormat) if (stringFormat == null) throw new ArgumentNullException(nameof(stringFormat)); #if true + var renderEvents = RenderEvents ?? Owner?.RenderEvents; + if (renderEvents != null) + { + // Invoke PrepareTextEvent. + var args = new PrepareTextEventArgs(Owner!, font, text); // Owner may be null here. + renderEvents.OnPrepareTextEvent(this, args); + text = args.Text; + } + //var codePoints = UnicodeHelper.Utf32FromString(text /*, font.AnsiEncoding*/); var codePoints = font.IsSymbolFont ? UnicodeHelper.SymbolCodePointsFromString(text, font.OpenTypeDescriptor) @@ -3714,18 +3733,11 @@ public XSize MeasureString(string text, XFont font, XStringFormat stringFormat) var otDescriptor = font.OpenTypeDescriptor; var codePointsWithGlyphIndices = otDescriptor.GlyphIndicesFromCodePoints(codePoints); - var renderEvents = RenderEvents ?? Owner?.RenderEvents; if (renderEvents != null) { - // Invoke RenderEvent. - var args = new RenderTextEventArgs(Owner!) // Owner may be null here. - { - Font = font, - CodePointGlyphIndexPairs = codePointsWithGlyphIndices - }; + // Invoke RenderTextEvent. + var args = new RenderTextEventArgs(Owner!, font, codePointsWithGlyphIndices); // Owner may be null here. renderEvents.OnRenderTextEvent(this, args); - codePointsWithGlyphIndices = args.CodePointGlyphIndexPairs; - codePointsWithGlyphIndices = args.CodePointGlyphIndexPairs; if (args.ReevaluateGlyphIndices) { @@ -3853,7 +3865,7 @@ public XSize MeasureString(string text, XFont font, XStringFormat stringFormat) return size23; #endif #endif -#if CORE || UWP +#if CORE || WUI XSize size = FontHelper.MeasureString(text, font, XStringFormats.Default); return size; #endif @@ -4175,10 +4187,10 @@ public void DrawImage(XImage image, XRect destRect, XRect srcRect, XGraphicsUnit // //gfx.InterpolationMode = InterpolationMode.NearestNeighbor; //} - // HACK: srcRect is ignored - not implemented. - // BUG: srcRect is ignored - not implemented. + // srcRect is ignored - NYI //double x = destRect.X; //double y = destRect.Y; + PdfSharpLogHost.Logger.LogWarning("DrawImage: srcRect is not used in WPF build."); _dc.DrawImage(image._wpfImage, new SysRect(destRect.X, destRect.Y, destRect.Width, destRect.Height)); //if (!image.Interpolate) @@ -4319,7 +4331,7 @@ public void DrawMatrixCode(BarCodes.MatrixCode matrixcode, XBrush brush, XPoint public XGraphicsState Save() { XGraphicsState xState = null!; -#if CORE || UWP +#if CORE || WUI if (TargetContext == XGraphicTargetContext.CORE || TargetContext == XGraphicTargetContext.NONE) { xState = new XGraphicsState(); @@ -4456,7 +4468,7 @@ public XGraphicsContainer BeginContainer(Rect dstrect, Rect srcrect, XGraphicsUn /// Saves a graphics container with the current state of this XGraphics and /// opens and uses a new graphics container. /// - public XGraphicsContainer BeginContainer(XRect dstrect, XRect srcrect, XGraphicsUnit unit) + public XGraphicsContainer BeginContainer(XRect dstRect, XRect srcRect, XGraphicsUnit unit) { // TODO: unit if (unit != XGraphicsUnit.Point) @@ -4493,14 +4505,14 @@ public XGraphicsContainer BeginContainer(XRect dstrect, XRect srcrect, XGraphics _gsStack.Push(iState); - _renderer?.BeginContainer(xContainer, dstrect, srcrect, unit); + _renderer?.BeginContainer(xContainer, dstRect, srcRect, unit); XMatrix matrix = new XMatrix(); - double scaleX = dstrect.Width / srcrect.Width; - double scaleY = dstrect.Height / srcrect.Height; - matrix.TranslatePrepend(-srcrect.X, -srcrect.Y); + double scaleX = dstRect.Width / srcRect.Width; + double scaleY = dstRect.Height / srcRect.Height; + matrix.TranslatePrepend(-srcRect.X, -srcRect.Y); matrix.ScalePrepend(scaleX, scaleY); - matrix.TranslatePrepend(dstrect.X / scaleX, dstrect.Y / scaleY); + matrix.TranslatePrepend(dstRect.X / scaleX, dstRect.Y / scaleY); AddTransform(matrix, XMatrixOrder.Prepend); return xContainer; @@ -4831,12 +4843,10 @@ void AddTransform(XMatrix transform, XMatrixOrder order) _transform = matrix; matrix = DefaultViewMatrix; matrix.Multiply(_transform, XMatrixOrder.Prepend); -#if CORE +#if CORE_ // No concept of target context in CORE build. if (TargetContext == XGraphicTargetContext.CORE) { _ = typeof(int); - // TODO: _gsStack... - // ReviewSTLA THHO4STLA } #endif #if GDI @@ -4990,12 +5000,12 @@ public void WriteComment(string comment) { if (comment == null) throw new ArgumentNullException(nameof(comment)); - +#if GDI || WPF if (_drawGraphics) { - // TODO: Do something if metafile? + PdfSharpLogHost.Logger.LogDebug("WriteComment has no effect in GDI or WPF build."); } - +#endif _renderer?.WriteComment(comment); } @@ -5082,7 +5092,7 @@ internal static XPoint[] MakeXPointArray(GdiPoint[]? points, int offset, int cou } #endif -#if WPF || UWP +#if WPF || WUI /// /// Converts a Point[] into a XPoint[]. /// @@ -5142,7 +5152,7 @@ internal static GdiRectF[] MakeRectangleFArray(XRect[]? rects, int offset, int c } #endif -#if WPF || UWP +#if WPF || WUI /// /// Converts an XPoint[] into a Point[]. /// @@ -5219,7 +5229,7 @@ internal XImage? AssociatedImage internal DrawingContext _dc = default!; #endif -#if UWP +#if WUI readonly CanvasDrawingSession _cds; #endif diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphicsPath.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphicsPath.cs index 147754c5..0c2377ed 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphicsPath.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphicsPath.cs @@ -12,7 +12,7 @@ using SysRect = System.Windows.Rect; using WpfBrushes = System.Windows.Media.Brushes; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media; using SysPoint = Windows.Foundation.Point; using SysSize = Windows.Foundation.Size; @@ -44,7 +44,7 @@ public XGraphicsPath() } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI PathGeometry = new PathGeometry(); #endif } @@ -81,7 +81,7 @@ public XGraphicsPath(PathGeometry geometry) } #endif -#if WPF || UWP +#if WPF || WUI /// /// Gets the current path figure. /// @@ -148,7 +148,7 @@ public XGraphicsPath Clone() } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI path.PathGeometry = PathGeometry.Clone(); #endif return path; @@ -874,7 +874,7 @@ public void AddRectangle(XRect rect) // Draw the rectangle manually. GdipPath.StartFigure(); - GdipPath.AddLines(new PointF[] { rect.TopLeft.ToPointF(), rect.TopRight.ToPointF(), rect.BottomRight.ToPointF(), rect.BottomLeft.ToPointF() }); + GdipPath.AddLines([rect.TopLeft.ToPointF(), rect.TopRight.ToPointF(), rect.BottomRight.ToPointF(), rect.BottomLeft.ToPointF()]); GdipPath.CloseFigure(); } finally { Lock.ExitGdiPlus(); } @@ -1014,7 +1014,7 @@ public void AddRoundedRectangle(Rectangle rect, System.Drawing.Size ellipseSize) } #endif -#if WPF || UWP +#if WPF || WUI /// /// Adds a rectangle with rounded corners to this path. /// @@ -1105,7 +1105,7 @@ public void AddRoundedRectangle(double x, double y, double width, double height, } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI double ex = ellipseWidth / 2; double ey = ellipseHeight / 2; StartFigure(); @@ -1258,7 +1258,7 @@ public void AddEllipse(double x, double y, double width, double height) } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI #if true PathGeometry.AddGeometry(new EllipseGeometry(new Rect(x, y, width, height))); #else @@ -1307,7 +1307,7 @@ public void AddPolygon(System.Drawing.Point[] points) } #endif -#if WPF || UWP +#if WPF || WUI /// /// Adds a polygon to this path. /// @@ -1362,7 +1362,7 @@ public void AddPolygon(XPoint[] points) } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI #if true PathGeometry.AddGeometry(GeometryHelper.CreatePolygonGeometry(XGraphics.MakePointArray(points), XFillMode.Alternate, true)); #else @@ -1436,7 +1436,7 @@ public void AddPie(double x, double y, double width, double height, double start } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI const string message = "AddPie: This operation is not yet implemented in WPF build."; DiagnosticsHelper.HandleNotImplemented(message, Capabilities.Action.PathOperations); #endif @@ -1454,7 +1454,7 @@ public void AddClosedCurve(System.Drawing.Point[] points) } #endif -#if WPF || UWP +#if WPF || WUI /// /// Adds a closed curve to this path. /// @@ -1492,7 +1492,7 @@ public void AddClosedCurve(System.Drawing.Point[] points, double tension) } #endif -#if WPF || UWP +#if WPF || WUI /// /// Adds a closed curve to this path. /// @@ -1537,7 +1537,7 @@ public void AddClosedCurve(XPoint[] points, double tension) } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI tension /= 3; StartFigure(); @@ -1578,7 +1578,7 @@ public void AddPath(XGraphicsPath path, bool connect) } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI PathGeometry.AddGeometry(path.PathGeometry); #endif } @@ -1604,7 +1604,7 @@ public void AddString(string s, XFontFamily family, XFontStyleEx style, double e } #endif -#if WPF || UWP +#if WPF || WUI /// /// Adds a text string to this path. /// @@ -1639,7 +1639,7 @@ public void AddString(string s, XFontFamily family, XFontStyleEx style, double e #endif #if GDI if (family.GdiFamily == null) - throw new NotImplementedException(PSSR.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); + throw new NotImplementedException(PsMsgs.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); PointF p = origin.ToPointF(); p.Y += SimulateBaselineOffset(family, style, emSize, format); @@ -1653,7 +1653,7 @@ public void AddString(string s, XFontFamily family, XFontStyleEx style, double e #endif #if WPF if (family.WpfFamily == null) - throw new NotImplementedException(PSSR.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); + throw new NotImplementedException(PsMsgs.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); XFont font = new XFont(family.Name, emSize, style); @@ -1719,7 +1719,7 @@ public void AddString(string s, XFontFamily family, XFontStyleEx style, double e public void AddString(string s, XFontFamily family, XFontStyleEx style, double emSize, Rectangle layoutRect, XStringFormat format) { if (family.GdiFamily == null) - throw new NotFiniteNumberException(PSSR.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); + throw new NotFiniteNumberException(PsMsgs.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); Rectangle rect = new Rectangle(layoutRect.X, layoutRect.Y, layoutRect.Width, layoutRect.Height); rect.Offset(new System.Drawing.Point(0, (int)SimulateBaselineOffset(family, style, emSize, format))); @@ -1738,7 +1738,7 @@ public void AddString(string s, XFontFamily family, XFontStyleEx style, double e public void AddString(string s, XFontFamily family, XFontStyleEx style, double emSize, RectangleF layoutRect, XStringFormat format) { if (family.GdiFamily == null) - throw new NotFiniteNumberException(PSSR.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); + throw new NotFiniteNumberException(PsMsgs.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); RectangleF rect = new RectangleF(layoutRect.X, layoutRect.Y, layoutRect.Width, layoutRect.Height); rect.Offset(new PointF(0, SimulateBaselineOffset(family, style, emSize, format))); @@ -1761,7 +1761,6 @@ public void AddString(string s, XFontFamily family, XFontStyleEx style, double e /// /// /// - /// private float SimulateBaselineOffset(XFontFamily family, XFontStyleEx style, double emSize, XStringFormat format) { XFont font = new XFont(family.Name, emSize, style); @@ -1822,7 +1821,7 @@ public void AddString(string s, XFontFamily family, XFontStyleEx style, double e // format != null ? format.RealizeGdiStringFormat() : null); if (family.GdiFamily == null) - throw new NotFiniteNumberException(PSSR.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); + throw new NotFiniteNumberException(PsMsgs.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); RectangleF rect = layoutRect.ToRectangleF(); rect.Offset(new PointF(0, SimulateBaselineOffset(family, style, emSize, format))); @@ -1836,7 +1835,7 @@ public void AddString(string s, XFontFamily family, XFontStyleEx style, double e #endif #if WPF && !GDI if (family.WpfFamily == null) - throw new NotFiniteNumberException(PSSR.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); + throw new NotFiniteNumberException(PsMsgs.NotImplementedForFontsRetrievedWithFontResolver(family.Name)); // Just a first sketch, but currently we do not need it and there is enough to do... double x = layoutRect.X; @@ -1978,7 +1977,7 @@ public void CloseFigure() } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI PathFigure figure = PeekCurrentFigure; if (figure != null && figure.Segments.Count != 0) figure.IsClosed = true; @@ -1991,8 +1990,7 @@ public void CloseFigure() public void StartFigure() { #if CORE - // ReviewSTLA THHO4STLA - // TODO: ??? + // Nothing to do. #endif #if GDI try @@ -2002,7 +2000,7 @@ public void StartFigure() } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI PathFigure figure = CurrentPathFigure; if (figure.Segments.Count != 0) { @@ -2034,7 +2032,7 @@ public XFillMode FillMode } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI PathGeometry.FillRule = value == XFillMode.Winding ? FillRule.Nonzero : FillRule.EvenOdd; #endif } @@ -2061,7 +2059,7 @@ public void Flatten() } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI PathGeometry = PathGeometry.GetFlattenedPathGeometry(); #endif } @@ -2083,7 +2081,7 @@ public void Flatten(XMatrix matrix) } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI PathGeometry = PathGeometry.GetFlattenedPathGeometry(); PathGeometry.Transform = new MatrixTransform(matrix.ToWpfMatrix()); #endif @@ -2106,7 +2104,7 @@ public void Flatten(XMatrix matrix, double flatness) } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI PathGeometry = PathGeometry.GetFlattenedPathGeometry(); // TODO: matrix handling not yet tested if (!matrix.IsIdentity) @@ -2134,7 +2132,7 @@ public void Widen(XPen pen) } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI PathGeometry = PathGeometry.GetWidenedPathGeometry(pen.RealizeWpfPen()); #endif } @@ -2159,7 +2157,7 @@ public void Widen(XPen pen, XMatrix matrix) } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI PathGeometry = PathGeometry.GetWidenedPathGeometry(pen.RealizeWpfPen()); #endif } @@ -2181,7 +2179,7 @@ public void Widen(XPen pen, XMatrix matrix, double flatness) } finally { Lock.ExitGdiPlus(); } #endif -#if WPF || UWP +#if WPF || WUI PathGeometry = PathGeometry.GetWidenedPathGeometry(pen.RealizeWpfPen()); #endif } @@ -2207,9 +2205,9 @@ public void Widen(XPen pen, XMatrix matrix, double flatness) internal GraphicsPath GdipPath; #endif -#if WPF || UWP +#if WPF || WUI /// - /// Gets access to underlying WPF/UWP path geometry. + /// Gets access to underlying WPF/WUI path geometry. /// internal PathGeometry PathGeometry; #endif diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphicsPathInternals.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphicsPathInternals.cs index 09c25c38..cddf8e49 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphicsPathInternals.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XGraphicsPathInternals.cs @@ -9,7 +9,7 @@ using System.Windows; using System.Windows.Media; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media; #endif @@ -38,7 +38,7 @@ public GraphicsPath GdiPath } #endif -#if WPF || UWP +#if WPF || WUI /// /// Gets the underlying WPF path geometry object. /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XImage.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XImage.cs index b3a56423..4b2fb1d4 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XImage.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XImage.cs @@ -14,7 +14,7 @@ using System.Text; using System.Windows.Media.Imaging; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media.Imaging; #endif using PdfSharp.Drawing.Internal; @@ -133,9 +133,9 @@ public static BitmapImage BitmapFromUri(Uri uri) } #endif -#if UWP +#if WUI /// - /// Initializes a new instance of the class from a UWP image. + /// Initializes a new instance of the class from a WUI image. /// XImage(BitmapSource image) { @@ -147,11 +147,11 @@ public static BitmapImage BitmapFromUri(Uri uri) // Useful stuff here: http://stackoverflow.com/questions/350027/setting-wpf-image-source-in-code XImage(string path) { -#if !UWP +#if !WUI path = Path.GetFullPath(path); if (!File.Exists(path)) - throw new FileNotFoundException(PSSR.FileNotFound(path)); - //throw new FileNotFoundException(PSSR.FileNotFound(path), path); + throw new FileNotFoundException(PsMsgs.FileNotFound(path)); + //throw new FileNotFoundException(PsMgs.FileNotFound(path), path); #endif _path = path; @@ -252,7 +252,7 @@ public static XImage FromBitmapSource(BitmapSource image) } #endif -#if UWP +#if WUI /// /// Conversion from BitmapSource to XImage. /// @@ -283,10 +283,38 @@ public static XImage FromStream(Stream stream) if (stream == null) throw new ArgumentNullException(nameof(stream)); + if (!stream.CanSeek) + { +#if GDI + throw new InvalidOperationException("The stream is not seekable. If your stream is not a PDF file use FromBitmapImageStreamThatCannotSeek instead."); +#endif +#if WPF + throw new InvalidOperationException("Images can be loaded from seekable streams only."); +#endif + } + if (PdfReader.TestPdfFile(stream) > 0) return new XPdfForm(stream); return new XImage(stream); } + +#if GDI + /// + /// Creates an image from the specified bitmap image stream.
+ /// Use this function if your stream does not support seek. + ///
+ /// The stream containing a BMP, PNG, GIF, JPEG, TIFF, but not PDF file. + public static XImage FromBitmapImageStreamThatCannotSeek(Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + if (stream.CanSeek) + throw new InvalidOperationException("Use this function only for streams that do not support Seek."); + + return new XImage(stream); + } +#endif #endif #if CORE @@ -300,10 +328,7 @@ public static XImage FromFile(string path) return new XPdfForm(path); var ii = ImageImporter.GetImageImporter(); - var i = ii.ImportImage(path); - - if (i == null) - throw new InvalidOperationException("Unsupported image format."); + var i = ii.ImportImage(path) ?? throw new InvalidOperationException("Unsupported image format."); var image = new XImage(i); image._path = path; @@ -319,14 +344,35 @@ public static XImage FromStream(Stream stream) if (stream == null) throw new ArgumentNullException(nameof(stream)); + if (!stream.CanSeek) + throw new InvalidOperationException("The stream is not seekable. If your stream is not a PDF file use FromBitmapImageStreamThatCannotSeek instead."); + + // Test for PDF requires a seekable stream. if (PdfReader.TestPdfFile(stream) > 0) return new XPdfForm(stream); var ii = ImageImporter.GetImageImporter(); - var i = ii.ImportImage(stream); + var i = ii.ImportImage(stream) ?? throw new InvalidOperationException("Unsupported image format."); - if (i == null) - throw new InvalidOperationException("Unsupported image format."); + XImage image = new XImage(i); + image._stream = stream; + return image; + } + + /// + /// Creates an image from the specified stream.
+ ///
+ /// The stream containing a BMP, PNG, JPEG, but not PDF file. + public static XImage FromBitmapImageStreamThatCannotSeek(Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + if (stream.CanSeek) + throw new InvalidOperationException("Use this function only for streams that do not support Seek."); + + var ii = ImageImporter.GetImageImporter(); + var i = ii.ImportImage(stream) ?? throw new InvalidOperationException("Unsupported image format."); XImage image = new XImage(i); image._stream = stream; @@ -349,10 +395,7 @@ public static XImage FromFile(string path, bool platformIndependent) // TODO: Check PDF file. var ii = ImageImporter.GetImageImporter(); - var i = ii.ImportImage(path); - - if (i == null) - throw new InvalidOperationException("Unsupported image format."); + var i = ii.ImportImage(path) ?? throw new InvalidOperationException("Unsupported image format."); ; var image = new XImage(i); image._path = path; @@ -376,10 +419,7 @@ public static XImage FromStream(Stream stream, bool platformIndependent) throw new ArgumentNullException(nameof(stream)); var ii = ImageImporter.GetImageImporter(); - var i = ii.ImportImage(stream); - - if (i == null) - throw new InvalidOperationException("Unsupported image format."); + var i = ii.ImportImage(stream) ?? throw new InvalidOperationException("Unsupported image format."); XImage image = new XImage(i); image._stream = stream; @@ -416,7 +456,7 @@ public static bool ExistsFile(string path) if (PdfReader.TestPdfFile(path) > 0) return true; -#if !UWP +#if !WUI return File.Exists(path); #else return false; @@ -813,7 +853,7 @@ public virtual double Width #if WPF && !GDI return _wpfImage.PixelWidth; #endif -#if UWP +#if WUI return 100; #endif } @@ -855,7 +895,7 @@ public virtual double Height #if WPF && !GDI return _wpfImage.PixelHeight; #endif -#if UWP +#if WUI return _wrtImage.PixelHeight; #endif } @@ -918,7 +958,7 @@ public virtual double PointWidth Debug.Assert(Math.Abs(_wpfImage.PixelWidth * 72 / _wpfImage.DpiX - _wpfImage.Width * (72.0 / 96.0)) < 0.001); return _wpfImage.Width * (72.0 / 96.0); #endif -#if UWP +#if WUI //var wb = new WriteableBitmap(); //GetImagePropertiesAsync return 100; @@ -968,7 +1008,7 @@ public virtual double PointHeight Debug.Assert(Math.Abs(_wpfImage.PixelHeight * 72 / _wpfImage.DpiY - _wpfImage.Height * (72.0 / 96.0)) < 0.001); return _wpfImage.Height * (72.0 / 96.0); #endif -#if UWP +#if WUI return _wrtImage.PixelHeight; //_gdi Image.Width * 72 / _gdiImage.HorizontalResolution; #endif } @@ -1008,7 +1048,7 @@ public virtual int PixelWidth #if WPF && !GDI return _wpfImage.PixelWidth; #endif -#if UWP +#if WUI return _wrtImage.PixelWidth; #endif } @@ -1048,7 +1088,7 @@ public virtual int PixelHeight #if WPF && !GDI return _wpfImage.PixelHeight; #endif -#if UWP +#if WUI return _wrtImage.PixelHeight; #endif } @@ -1101,7 +1141,7 @@ public virtual double HorizontalResolution #if WPF && !GDI return _wpfImage.DpiX; //.PixelWidth * 96.0 / _wpfImage.Width; #endif -#if UWP +#if WUI return 96; #endif } @@ -1146,7 +1186,7 @@ public virtual double VerticalResolution #if WPF && !GDI return _wpfImage.DpiY; //.PixelHeight * 96.0 / _wpfImage.Height; #endif -#if UWP +#if WUI return 96; #endif } @@ -1369,7 +1409,7 @@ internal XGraphics? AssociatedGraphics #if WPF internal BitmapSource _wpfImage = null!; #endif -#if UWP +#if WUI internal BitmapSource _wrtImage = null!; #endif diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XLinearGradientBrush.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XLinearGradientBrush.cs index be9baeaa..3db8a5f3 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XLinearGradientBrush.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XLinearGradientBrush.cs @@ -18,7 +18,7 @@ using WpfBrush = System.Windows.Media.Brush; using WpfLinearGradientBrush = System.Windows.Media.LinearGradientBrush; #endif -#if UWP +#if WUI using Windows.UI; using Windows.UI.Xaml.Media; using Microsoft.Graphics.Canvas; @@ -101,7 +101,7 @@ public XLinearGradientBrush(Rect rect, XColor color1, XColor color2, XLinearGrad public XLinearGradientBrush(XRect rect, XColor color1, XColor color2, XLinearGradientMode linearGradientMode) { if (!Enum.IsDefined(typeof(XLinearGradientMode), linearGradientMode)) - throw new InvalidEnumArgumentException("linearGradientMode", (int)linearGradientMode, typeof(XLinearGradientMode)); + throw new InvalidEnumArgumentException(nameof(linearGradientMode), (int)linearGradientMode, typeof(XLinearGradientMode)); if (rect.Width == 0 || rect.Height == 0) throw new ArgumentException("Invalid rectangle.", nameof(rect)); @@ -337,7 +337,7 @@ internal override WpfBrush RealizeWpfBrush() } #endif -#if UWP +#if WUI internal override ICanvasBrush RealizeCanvasBrush() { ICanvasBrush brush; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XMatrix.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XMatrix.cs index 598de0e3..f776e7f2 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XMatrix.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XMatrix.cs @@ -84,8 +84,8 @@ public bool IsIdentity public double[] GetElements() { if (_type == XMatrixTypes.Identity) - return new double[] { 1, 0, 0, 1, 0, 0 }; - return new[] { _m11, _m12, _m21, _m22, _offsetX, _offsetY }; + return [1, 0, 0, 1, 0, 0]; + return [_m11, _m12, _m21, _m22, _offsetX, _offsetY]; } /// @@ -391,7 +391,7 @@ public void ScaleAtPrepend(double scaleX, double scaleY, double centerX, double public void Rotate(double angle) { throw new InvalidOperationException("Temporarily out of order."); - //angle = angle % 360.0; + //angle %= 360.0; //this *= CreateRotationRadians(angle * Const.Deg2Rad); } @@ -400,7 +400,7 @@ public void Rotate(double angle) /// public void RotateAppend(double angle) // TODO: will become default Rotate { - angle = angle % 360.0; + angle %= 360.0; this *= CreateRotationRadians(angle * Const.Deg2Rad); } @@ -409,7 +409,7 @@ public void Rotate(double angle) ///
public void RotatePrepend(double angle) { - angle = angle % 360.0; + angle %= 360.0; this = CreateRotationRadians(angle * Const.Deg2Rad) * this; } @@ -421,7 +421,7 @@ public void Rotate(double angle, XMatrixOrder order) if (_type == XMatrixTypes.Identity) this = CreateIdentity(); - angle = angle * Const.Deg2Rad; + angle *= Const.Deg2Rad; double cos = Math.Cos(angle); double sin = Math.Sin(angle); if (order == XMatrixOrder.Append) @@ -463,7 +463,7 @@ public void Rotate(double angle, XMatrixOrder order) public void RotateAt(double angle, double centerX, double centerY) { throw new InvalidOperationException("Temporarily out of order."); - //angle = angle % 360.0; + //angle %= 360.0; //this *= CreateRotationRadians(angle * Const.Deg2Rad, centerX, centerY); } @@ -472,7 +472,7 @@ public void RotateAt(double angle, double centerX, double centerY) /// public void RotateAtAppend(double angle, double centerX, double centerY) // TODO: will become default { - angle = angle % 360.0; + angle %= 360.0; this *= CreateRotationRadians(angle * Const.Deg2Rad, centerX, centerY); } @@ -481,7 +481,7 @@ public void RotateAt(double angle, double centerX, double centerY) /// public void RotateAtPrepend(double angle, double centerX, double centerY) { - angle = angle % 360.0; + angle %= 360.0; this = CreateRotationRadians(angle * Const.Deg2Rad, centerX, centerY) * this; } @@ -520,7 +520,7 @@ public void RotateAt(double angle, XPoint point, XMatrixOrder order) { if (order == XMatrixOrder.Append) { - angle = angle % 360.0; + angle %= 360.0; this *= CreateRotationRadians(angle * Const.Deg2Rad, point.X, point.Y); //Translate(point.X, point.Y, order); @@ -529,7 +529,7 @@ public void RotateAt(double angle, XPoint point, XMatrixOrder order) } else { - angle = angle % 360.0; + angle %= 360.0; this = CreateRotationRadians(angle * Const.Deg2Rad, point.X, point.Y) * this; } @@ -604,8 +604,8 @@ public void Shear(double shearX, double shearY, XMatrixOrder order) public void Skew(double skewX, double skewY) { throw new InvalidOperationException("Temporarily out of order."); - //skewX = skewX % 360.0; - //skewY = skewY % 360.0; + //skewX %= 360.0; + //skewY %= 360.0; //this *= CreateSkewRadians(skewX * Const.Deg2Rad, skewY * Const.Deg2Rad); } @@ -614,8 +614,8 @@ public void Skew(double skewX, double skewY) /// public void SkewAppend(double skewX, double skewY) { - skewX = skewX % 360.0; - skewY = skewY % 360.0; + skewX %= 360.0; + skewY %= 360.0; this *= CreateSkewRadians(skewX * Const.Deg2Rad, skewY * Const.Deg2Rad); } @@ -624,8 +624,8 @@ public void SkewAppend(double skewX, double skewY) /// public void SkewPrepend(double skewX, double skewY) { - skewX = skewX % 360.0; - skewY = skewY % 360.0; + skewX %= 360.0; + skewY %= 360.0; this = CreateSkewRadians(skewX * Const.Deg2Rad, skewY * Const.Deg2Rad) * this; } @@ -637,7 +637,7 @@ public XPoint Transform(XPoint point) double x = point.X; double y = point.Y; MultiplyPoint(ref x, ref y); - return new XPoint(x, y); + return new(x, y); } /// @@ -687,7 +687,7 @@ public void TransformPoints(XPoint[] points) public void TransformPoints(System.Drawing.Point[] points) { if (points == null) - throw new ArgumentNullException("points"); + throw new ArgumentNullException(nameof(points)); if (IsIdentity) return; @@ -710,7 +710,7 @@ public void TransformPoints(System.Drawing.Point[] points) public void TransformPoints(System.Windows.Point[] points) { if (points == null) - throw new ArgumentNullException("points"); + throw new ArgumentNullException(nameof(points)); if (IsIdentity) return; @@ -734,7 +734,7 @@ public XVector Transform(XVector vector) double x = vector.X; double y = vector.Y; MultiplyVector(ref x, ref y); - return new XVector(x, y); + return new(x, y); } /// @@ -764,7 +764,7 @@ public void Transform(XVector[] vectors) public void TransformVectors(PointF[] points) { if (points == null) - throw new ArgumentNullException("points"); + throw new ArgumentNullException(nameof(points)); if (IsIdentity) return; @@ -1158,7 +1158,7 @@ public static XMatrix Parse(string source) } /// - /// Converts this XMatrix to a human readable string. + /// Converts this XMatrix to a human-readable string. /// public override string ToString() { @@ -1166,7 +1166,7 @@ public override string ToString() } /// - /// Converts this XMatrix to a human readable string. + /// Converts this XMatrix to a human-readable string. /// public string ToString(IFormatProvider provider) { @@ -1174,7 +1174,7 @@ public string ToString(IFormatProvider provider) } /// - /// Converts this XMatrix to a human readable string. + /// Converts this XMatrix to a human-readable string. /// string IFormattable.ToString(string? format, IFormatProvider? provider) { diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPdfForm.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPdfForm.cs index 555587dd..9856899c 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPdfForm.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPdfForm.cs @@ -36,7 +36,7 @@ internal XPdfForm(string path) path = Path.GetFullPath(path); if (!File.Exists(path)) - throw new FileNotFoundException(PSSR.FileNotFound(path)); + throw new FileNotFoundException(PsMsgs.FileNotFound(path)); if (PdfReader.TestPdfFile(path) == 0) throw new ArgumentException("The specified file has no valid PDF file header.", nameof(path)); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPen.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPen.cs index 44e68b6c..97a6d6a2 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPen.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPen.cs @@ -76,7 +76,7 @@ public XColor Color set { if (_immutable) - throw new ArgumentException(PSSR.CannotChangeImmutableObject("XPen")); + throw new ArgumentException(PsMsgs.CannotChangeImmutableObject(nameof(XPen))); _dirty = _dirty || _color != value; _color = value; } @@ -92,7 +92,7 @@ public double Width set { if (_immutable) - throw new ArgumentException(PSSR.CannotChangeImmutableObject("XPen")); + throw new ArgumentException(PsMsgs.CannotChangeImmutableObject(nameof(XPen))); // ReSharper disable once CompareOfFloatsByEqualityOperator _dirty = _dirty || _width != value; _width = value; @@ -109,7 +109,7 @@ public XLineJoin LineJoin set { if (_immutable) - throw new ArgumentException(PSSR.CannotChangeImmutableObject("XPen")); + throw new ArgumentException(PsMsgs.CannotChangeImmutableObject(nameof(XPen))); _dirty = _dirty || _lineJoin != value; _lineJoin = value; } @@ -125,7 +125,7 @@ public XLineCap LineCap set { if (_immutable) - throw new ArgumentException(PSSR.CannotChangeImmutableObject("XPen")); + throw new ArgumentException(PsMsgs.CannotChangeImmutableObject(nameof(XPen))); _dirty = _dirty || _lineCap != value; _lineCap = value; } @@ -141,7 +141,7 @@ public double MiterLimit set { if (_immutable) - throw new ArgumentException(PSSR.CannotChangeImmutableObject("XPen")); + throw new ArgumentException(PsMsgs.CannotChangeImmutableObject(nameof(XPen))); // ReSharper disable once CompareOfFloatsByEqualityOperator _dirty = _dirty || _miterLimit != value; _miterLimit = value; @@ -158,7 +158,7 @@ public XDashStyle DashStyle set { if (_immutable) - throw new ArgumentException(PSSR.CannotChangeImmutableObject("XPen")); + throw new ArgumentException(PsMsgs.CannotChangeImmutableObject(nameof(XPen))); _dirty = _dirty || _dashStyle != value; _dashStyle = value; } @@ -174,7 +174,7 @@ public double DashOffset set { if (_immutable) - throw new ArgumentException(PSSR.CannotChangeImmutableObject("XPen")); + throw new ArgumentException(PsMsgs.CannotChangeImmutableObject(nameof(XPen))); // ReSharper disable once CompareOfFloatsByEqualityOperator _dirty = _dirty || _dashOffset != value; _dashOffset = value; @@ -190,13 +190,13 @@ public double[] DashPattern get { if (_dashPattern == null) - _dashPattern = new double[0]; + _dashPattern = []; return _dashPattern; } set { if (_immutable) - throw new ArgumentException(PSSR.CannotChangeImmutableObject("XPen")); + throw new ArgumentException(PsMsgs.CannotChangeImmutableObject(nameof(XPen))); int length = value.Length; //if (length == 0) @@ -225,7 +225,7 @@ public bool Overprint set { if (_immutable) - throw new ArgumentException(PSSR.CannotChangeImmutableObject("XPen")); + throw new ArgumentException(PsMsgs.CannotChangeImmutableObject(nameof(XPen))); _overprint = value; } } @@ -369,4 +369,4 @@ internal WpfPen RealizeWpfPen() WpfPen _wpfPen = null!; #endif } -} \ No newline at end of file +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPoint.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPoint.cs index dd365b77..b5823136 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPoint.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPoint.cs @@ -10,7 +10,7 @@ using SysPoint = System.Windows.Point; using SysSize = System.Windows.Size; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media; using SysPoint = Windows.Foundation.Point; using SysSize = Windows.Foundation.Size; @@ -48,7 +48,7 @@ public XPoint(Point point) } #endif -#if WPF || UWP +#if WPF || WUI /// /// Initializes a new instance of the XPoint class with the specified point. /// @@ -183,7 +183,7 @@ public PointF ToPointF() } #endif -#if WPF || UWP +#if WPF || WUI /// /// Converts this XPoint to a System.Windows.Point. /// @@ -352,7 +352,7 @@ public static explicit operator XVector(XPoint point) return new XVector(point._x, point._y); } -#if WPF || UWP +#if WPF || WUI /// /// Performs an implicit conversion from XPoint to Point. /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPrivateFontCollection.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPrivateFontCollection.cs index f4ca9b47..b83b1b0c 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPrivateFontCollection.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XPrivateFontCollection.cs @@ -21,411 +21,10 @@ namespace PdfSharp.Drawing { -#if true /// /// This class is out of order. Use a font resolver instead. /// [Obsolete("XPrivateFontCollection is out of order now. Use a font resolver instead.")] public sealed class XPrivateFontCollection { } -#else - /// - /// Makes fonts that are not installed on the system available within the current application domain.
- ///
- public sealed class XPrivateFontCollection - { - // This one is global and can only grow. It is not possible to remove fonts that have been added. - - /// - /// Initializes a new instance of the class. - /// - XPrivateFontCollection() - { - // HACK: Use one global PrivateFontCollection in GDI+ - } - -#if GDI - //internal PrivateFontCollection PrivateFontCollection - //{ - // get { return privateFontCollection; } - // set { privateFontCollection = value; } - //} - - GdiPrivateFontCollection GetPrivateFontCollection() - { - // Create only if really needed. - if (_privateFontCollection == null) - _privateFontCollection = new GdiPrivateFontCollection(); - return _privateFontCollection; - } - - // PrivateFontCollection of GDI+ - GdiPrivateFontCollection? _privateFontCollection; -#endif - - /// - /// Gets the global font collection. - /// - internal static XPrivateFontCollection Singleton { get; } = new(); - - //internal static XPrivateFontCollection Singleton => _singleton; - //internal static XPrivateFontCollection _singleton = new XPrivateFontCollection(); - -#if GDI - /// - /// Adds the font data to the font collections. - /// - [Obsolete("Use Add(Stream stream)")] - public void AddFont(byte[] data, string familyName) - { - if (String.IsNullOrEmpty(familyName)) - throw new ArgumentNullException("familyName"); - - //if (glyphTypeface == null) - // throw new ArgumentNullException("glyphTypeface"); - - // Add to GDI+ PrivateFontCollection - int length = data.Length; - - // Copy data without unsafe code - IntPtr ip = Marshal.AllocCoTaskMem(length); - Marshal.Copy(data, 0, ip, length); - GetPrivateFontCollection().AddMemoryFont(ip, length); - // Do not free the memory here, AddMemoryFont stores a pointer, not a copy! - //Marshal.FreeCoTaskMem(ip); - //privateFonts.Add(glyphTypeface); - } -#endif - - /// - /// Adds the specified font data to the global PrivateFontCollection. - /// Family name and style are automatically retrieved from the font. - /// -#if GDI - [Obsolete("Use Add(Stream stream)")] -#else - [Obsolete("Use the GDI build of PDFsharp and use Add(Stream stream)")] -#endif - public static void AddFont(string filename) - { - throw new NotImplementedException(); - //XGlyphTypeface glyphTypeface = new XGlyphTypeface(filename); - //Global.AddGlyphTypeface(glyphTypeface); - } - -#if GDI - /// - /// Adds the specified font data to the global PrivateFontCollection. - /// Family name and style are automatically retrieved from the font. - /// - [Obsolete("Use Add(stream).")] - public static void AddFont(Stream stream) - { - Add(stream); - } - - /// - /// Adds the specified font data to the global PrivateFontCollection. - /// Family name and style are automatically retrieved from the font. - /// - public static void Add(Stream stream) - { - int length = (int)stream.Length; - byte[] bytes = new byte[length]; - stream.Read(bytes, 0, length); - Add(bytes); - } - - /// - /// Adds the specified font data to the global PrivateFontCollection. - /// Family name and style are automatically retrieved from the font. - /// - public static void Add(byte[] font) - { - IntPtr unmanagedPointer = Marshal.AllocCoTaskMem(font.Length); - Marshal.Copy(font, 0, unmanagedPointer, font.Length); - Singleton.GetPrivateFontCollection().AddMemoryFont(unmanagedPointer, font.Length); - // Do not free the memory here, AddMemoryFont stores a pointer, not a copy! - //Marshal.FreeCoTaskMem(ip); - - XFontSource fontSource = XFontSource.GetOrCreateFrom(font); - - string familyName = fontSource.FontName; - - if (familyName.EndsWith(" Regular", StringComparison.OrdinalIgnoreCase)) - familyName = familyName.Substring(0, familyName.Length - 8); - - bool bold = fontSource.FontFace.os2.IsBold; - bool italic = fontSource.FontFace.os2.IsItalic; - IncompetentlyMakeAHackToFixAProblemYouWouldNeverHaveIfYouUsedAFontResolver(fontSource, ref familyName, ref bold, ref italic); - string key = MakeKey(familyName, bold, italic); - Singleton._fontSources.Add(key, fontSource); - - string typefaceKey = XGlyphTypeface.ComputeGtfKey(familyName, bold, italic); - FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource); - } - - static void IncompetentlyMakeAHackToFixAProblemYouWouldNeverHaveIfYouUsedAFontResolver(XFontSource fontSource, - ref string familyName, ref bool bold, ref bool italic) - { - const string regularSuffix = " Regular"; - const string boldSuffix = " Bold"; - const string italicSuffix = " Italic"; - const string boldItalicSuffix = " Bold Italic"; - const string italicBoldSuffix = " Italic Bold"; - - if (familyName.EndsWith(regularSuffix, StringComparison.OrdinalIgnoreCase)) - { - familyName = familyName.Substring(0, familyName.Length - regularSuffix.Length); - Debug.Assert(!bold && !italic); - bold = italic = false; - } - else if (familyName.EndsWith(boldItalicSuffix, StringComparison.OrdinalIgnoreCase) || familyName.EndsWith(italicBoldSuffix, StringComparison.OrdinalIgnoreCase)) - { - familyName = familyName.Substring(0, familyName.Length - boldItalicSuffix.Length); - Debug.Assert(bold && italic); - bold = italic = true; - } - else if (familyName.EndsWith(boldSuffix, StringComparison.OrdinalIgnoreCase)) - { - familyName = familyName.Substring(0, familyName.Length - boldSuffix.Length); - Debug.Assert(bold && !italic); - bold = true; - italic = false; - } - else if (familyName.EndsWith(italicSuffix, StringComparison.OrdinalIgnoreCase)) - { - familyName = familyName.Substring(0, familyName.Length - italicSuffix.Length); - Debug.Assert(!bold && italic); - bold = false; - italic = true; - } - else - { - Debug.Assert(!bold && !italic); - bold = false; - italic = false; - } - } -#endif - - /// - /// Adds the specified font data to the global PrivateFontCollection. - /// Family name and style are automatically retrieved from the font. - /// -#if GDI - [Obsolete("Use Add(Stream stream)")] -#else - [Obsolete("Use the GDI build of PDFsharp and use Add(Stream stream)")] -#endif - public static void AddFont(Stream stream, string facename) - { - throw new NotImplementedException(); - //XGlyphTypeface glyphTypeface = new XGlyphTypeface(stream, facename); - //Global.AddGlyphTypeface(glyphTypeface); - } - - // /// - // /// Adds XGlyphTypeface to internal collection. - // /// Family name and style are automatically retrieved from the font. - // /// - // void AddGlyphTypeface(XGlyphTypeface glyphTypeface) - // { - // string name = MakeName(glyphTypeface); - // if (_typefaces.ContainsKey(name)) - // throw new InvalidOperationException(PSSR.FontAlreadyAdded(glyphTypeface.DisplayName)); - - // _typefaces.Add(name, glyphTypeface); - // //De/bug.WriteLine("Font added: " + name); - - //#if GDI - // // Add to GDI+ PrivateFontCollection singleton. - // byte[] data = glyphTypeface.FontFace.FontSource.Bytes; - // int length = data.Length; - - // IntPtr ip = Marshal.AllocCoTaskMem(length); - // Marshal.Copy(data, 0, ip, length); - // _privateFontCollection.AddMemoryFont(ip, length); - // // Do not free the memory here, AddMemoryFont stores a pointer, not a copy! - // // Marshal.FreeCoTaskMem(ip); - //#endif - - //#if WPF - //#endif - // } - -#if WPF - /// - /// Initializes a new instance of the FontFamily class from the specified font family name and an optional base uniform resource identifier (URI) value. - /// Sample: Add(new Uri("pack://application:,,,/"), "./myFonts/#FontFamilyName");) - /// - /// Specifies the base URI that is used to resolve familyName. - /// The family name or names that comprise the new FontFamily. Multiple family names should be separated by commas. - public static void Add(Uri baseUri, string familyName) - { - Uri uri = new Uri("pack://application:,,,/"); - - // TODO: What means 'Multiple family names should be separated by commas.'? - // does not work - - if (String.IsNullOrEmpty(familyName)) - throw new ArgumentNullException(nameof(familyName)); - - if (familyName.Contains(",")) - throw new NotImplementedException("Only one family name is supported."); - - // Family name starts right of '#'. -#if NET6_0_OR_GREATER - int idxHash = familyName.IndexOf('#', StringComparison.Ordinal); -#else - int idxHash = familyName.IndexOf('#'); // Searching for '#' works fine even without "StringComparison.Ordinal". -#endif - if (idxHash < 0) - throw new ArgumentException("Family name must contain a '#'. Example './#MyFontFamilyName'", nameof(familyName)); - - string key = familyName.Substring(idxHash + 1); - if (String.IsNullOrEmpty(key)) - throw new ArgumentException("familyName has invalid format."); - - if (Singleton._fontFamilies.ContainsKey(key)) - throw new ArgumentException("An entry with the specified family name already exists."); - -#if true -#if DEBUG_ - foreach (WpfFontFamily fontFamily1 in WpfFonts.GetFontFamilies(baseUri, familyName)) - { - ICollection wpfTypefaces = fontFamily1.GetTypefaces(); - wpfTypefaces.GetType(); - } -#endif - // Create WPF font family. - WpfFontFamily fontFamily = new WpfFontFamily(baseUri, familyName); - //System.Windows.Media.FontFamily x; - // Required for new Uri("pack://application:,,,/") - // ReSharper disable once ObjectCreationAsStatement - // new System.Windows.Application(); - -#else - System.Windows.Media.FontFamily fontFamily = new System.Windows.Media.FontFamily(familyName); -#endif - - // Check whether font data really exists. - ICollection list = fontFamily.GetTypefaces(); - foreach (WpfTypeface typeFace in list) - { - //De/bug.WriteLine($"{familyName}, {typeFace.FaceNames[FontHelper.XmlLanguageEnUs]}, {typeFace.Style}, {typeFace.Weight}, {typeFace.Stretch}"); - if (!typeFace.TryGetGlyphTypeface(out var glyphTypeface)) - { - //De/bug.WriteLine(" Glyph typeface does not exist."); - //throw new ArgumentException("Font with the specified family name does not exist."); - } - } - - Singleton._fontFamilies.Add(key, fontFamily); - } -#endif - - //internal static XGlyphTypeface TryGetXGlyphTypeface(string familyName, XFontStyleEx style) - //{ - // string name = MakeName(familyName, style); - - // XGlyphTypeface typeface; - // _global._typefaces.TryGetValue(name, out typeface); - // return typeface; - //} - -#if CORE - internal static XTypeface? TryCreateTypeface(string name, XFontStyleEx style, out XFontFamily? fontFamily) - { - if (Singleton._fontFamilies.TryGetValue(name, out fontFamily)) - { - var typeface = FontHelper.CreateTypeface(fontFamily, style); - return typeface; - } - return null; - } -#endif - -#if GDI - internal static GdiFont? TryCreateFont(string name, double size, GdiFontStyle style, out XFontSource? fontSource) - { - fontSource = null; - try - { - var pfc = Singleton._privateFontCollection; - if (pfc == null) - return null; -#if true - string key = MakeKey(name, (XFontStyleEx)style); - if (Singleton._fontSources.TryGetValue(key, out fontSource)) - { - GdiFont font = new GdiFont(name, (float)size, style, GraphicsUnit.World); -#if DEBUG_ - Debug.Assert(StringComparer.OrdinalIgnoreCase.Compare(name, font.Name) == 0); - Debug.Assert(font.Bold == ((style & GdiFontStyle.Bold) != 0)); - Debug.Assert(font.Italic == ((style & GdiFontStyle.Italic) != 0)); -#endif - return font; - } - return null; -#else - foreach (GdiFontFamily family in pfc.Families) - { - if (string.Compare(family.Name, name, StringComparison.OrdinalIgnoreCase) == 0) - { - GdiFont font = new GdiFont(family, (float)size, style, GraphicsUnit.World); - if (string.Compare(font.Name, name, StringComparison.OrdinalIgnoreCase) != 0) - { - // Style simulation is not implemented in GDI+. - // Use WPF build. - } - return font; - } - } -#endif - } - catch (Exception ex) - { - // Ignore exception and return null. - PdfSharpLogHost.FontManagementLogger.LogError(ex.Message); - } - return null; - } -#endif - -#if WPF - internal static WpfTypeface TryCreateTypeface(string name, XFontStyleEx style, out WpfFontFamily fontFamily) - { - if (Singleton._fontFamilies.TryGetValue(name, out fontFamily!)) // NRT HACK - { - WpfTypeface typeface = FontHelper.CreateTypeface(fontFamily, style); - return typeface; - } - return default!; - } -#endif - - static string MakeKey(string familyName, XFontStyleEx style) - => MakeKey(familyName, (style & XFontStyleEx.Bold) != 0, (style & XFontStyleEx.Italic) != 0); - - static string MakeKey(string familyName, bool bold, bool italic) - => familyName + "#" + (bold ? "b" : "") + (italic ? "i" : ""); - - // ReSharper disable once UnusedMember.Local - // ReSharper disable once InconsistentNaming - readonly Dictionary _typefaces_unused = new(); -#if CORE - // ReSharper disable once UnusedMember.Local - // ReSharper disable once InconsistentNaming - readonly Dictionary _fontFamilies = new(StringComparer.OrdinalIgnoreCase); -#endif -#if GDI - //List privateFonts = new List(); - readonly Dictionary _fontSources = new Dictionary(StringComparer.OrdinalIgnoreCase); -#endif -#if WPF - readonly Dictionary _fontFamilies = new Dictionary(StringComparer.OrdinalIgnoreCase); -#endif - } -#endif } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XRadialGradientBrush.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XRadialGradientBrush.cs index 292c5105..6b9bf292 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XRadialGradientBrush.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XRadialGradientBrush.cs @@ -18,7 +18,7 @@ using WpfBrush = System.Windows.Media.Brush; using WpfRadialGradientBrush = System.Windows.Media.RadialGradientBrush; #endif -#if UWP +#if WUI using Windows.UI; using Windows.UI.Xaml.Media; using Microsoft.Graphics.Canvas; @@ -275,7 +275,7 @@ internal override WpfBrush RealizeWpfBrush() } #endif -#if UWP +#if WUI internal override ICanvasBrush RealizeCanvasBrush() { ICanvasBrush brush; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XRect.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XRect.cs index b6343b83..b16bdd65 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XRect.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XRect.cs @@ -11,7 +11,7 @@ using SysSize = System.Windows.Size; using SysRect = System.Windows.Rect; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media; using SysPoint = Windows.Foundation.Point; using SysSize = Windows.Foundation.Size; @@ -34,7 +34,7 @@ public struct XRect : IFormattable public XRect(double x, double y, double width, double height) { if (width < 0 || height < 0) - throw new ArgumentException("WidthAndHeightCannotBeNegative"); //SR.Get(SRID.Size_WidthAndHeightCannotBeNegative, new object[0])); + throw new ArgumentException("WidthAndHeightCannotBeNegative"); // TODO SR.Get(SRID.Size_WidthAndHeightCannotBeNegative, new object[0])); _x = x; _y = y; _width = width; @@ -116,7 +116,7 @@ public XRect(RectangleF rect) } #endif -#if WPF || UWP +#if WPF || WUI /// /// Initializes a new instance of the XRect class. /// @@ -341,9 +341,9 @@ public double Width set { if (IsEmpty) - throw new InvalidOperationException("CannotModifyEmptyRect"); //SR.Get(SRID.Rect_CannotModifyEmptyRect, new object[0])); + throw new InvalidOperationException("CannotModifyEmptyRect"); // TODO SR.Get(SRID.Rect_CannotModifyEmptyRect, new object[0])); if (value < 0) - throw new ArgumentException("WidthCannotBeNegative"); //SR.Get(SRID.Size_WidthCannotBeNegative, new object[0])); + throw new ArgumentException("WidthCannotBeNegative"); // TODO SR.Get(SRID.Size_WidthCannotBeNegative, new object[0])); _width = value; } @@ -725,7 +725,7 @@ public static implicit operator XRect(RectangleF rect) } #endif -#if WPF || UWP +#if WPF || WUI /// /// Performs an implicit conversion from System.Windows.Rect to XRect. /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XSize.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XSize.cs index 46613ae5..f986d410 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XSize.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XSize.cs @@ -8,7 +8,7 @@ using SysPoint = System.Windows.Point; using SysSize = System.Windows.Size; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media; using SysPoint = Windows.Foundation.Point; using SysSize = Windows.Foundation.Size; @@ -31,7 +31,7 @@ public struct XSize : IFormattable public XSize(double width, double height) { if (width < 0 || height < 0) - throw new ArgumentException("WidthAndHeightCannotBeNegative"); //SR.Get(SRID.Size_WidthAndHeightCannotBeNegative, new object[0])); + throw new ArgumentException("WidthAndHeightCannotBeNegative"); // TODO SR.Get(SRID.Size_WidthAndHeightCannotBeNegative, new object[0])); _width = width; _height = height; @@ -146,7 +146,7 @@ public SizeF ToSizeF() } #endif -#if WPF || UWP +#if WPF || WUI /// /// Converts this XSize to a System.Windows.Size. /// @@ -175,7 +175,7 @@ public static implicit operator XSize(Size size) } #endif -#if WPF || UWP +#if WPF || WUI /// /// Creates an XSize from a System.Drawing.Size. /// @@ -257,9 +257,9 @@ public double Width set { if (IsEmpty) - throw new InvalidOperationException("CannotModifyEmptySize"); //SR.Get(SRID.Size_CannotModifyEmptySize, new object[0])); + throw new InvalidOperationException("CannotModifyEmptySize"); // TODO SR.Get(SRID.Size_CannotModifyEmptySize, new object[0])); if (value < 0) - throw new ArgumentException("WidthCannotBeNegative"); //SR.Get(SRID.Size_WidthCannotBeNegative, new object[0])); + throw new ArgumentException("WidthCannotBeNegative"); // TODO SR.Get(SRID.Size_WidthCannotBeNegative, new object[0])); _width = value; } } @@ -274,9 +274,9 @@ public double Height set { if (IsEmpty) - throw new InvalidOperationException("CannotModifyEmptySize"); // SR.Get(SRID.Size_CannotModifyEmptySize, new object[0])); + throw new InvalidOperationException("CannotModifyEmptySize"); // TODO SR.Get(SRID.Size_CannotModifyEmptySize, new object[0])); if (value < 0) - throw new ArgumentException("HeightCannotBeNegative"); //SR.Get(SRID.Size_HeightCannotBeNegative, new object[0])); + throw new ArgumentException("HeightCannotBeNegative"); // TODO SR.Get(SRID.Size_HeightCannotBeNegative, new object[0])); _height = value; } } @@ -298,7 +298,7 @@ public static explicit operator XPoint(XSize size) return new XPoint(size._width, size._height); } -#if WPF || UWP +#if WPF || WUI /// /// Performs an explicit conversion from Size to XSize. /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XSolidBrush.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XSolidBrush.cs index 2c919574..9bd1f7b7 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XSolidBrush.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XSolidBrush.cs @@ -10,11 +10,12 @@ using System.Windows; using System.Windows.Media; #endif -#if UWP +#if WUI using Microsoft.Graphics.Canvas; using Microsoft.Graphics.Canvas.Brushes; using UwpBrush = Windows.UI.Xaml.Media.Brush; #endif +using PdfSharp.Internal; namespace PdfSharp.Drawing { @@ -59,7 +60,7 @@ public XColor Color set { if (_immutable) - throw new ArgumentException(PSSR.CannotChangeImmutableObject("XSolidBrush")); + throw new ArgumentException(PsMsgs.CannotChangeImmutableObject(nameof(XSolidBrush))); #if GDI _gdiDirty = _gdiDirty || _color != value; #endif @@ -84,7 +85,7 @@ public bool Overprint set { if (_immutable) - throw new ArgumentException(PSSR.CannotChangeImmutableObject("XSolidBrush")); + throw new ArgumentException(PsMsgs.CannotChangeImmutableObject(nameof(XSolidBrush))); _overprint = value; } } @@ -132,7 +133,7 @@ internal override System.Windows.Media.Brush RealizeWpfBrush() } #endif -#if UWP +#if WUI internal override ICanvasBrush RealizeCanvasBrush() { return new CanvasSolidColorBrush(CanvasDevice.GetSharedDevice(), _color.ToUwpColor()); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XUnit.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XUnit.cs index afc5f60f..46c57ff0 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XUnit.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XUnit.cs @@ -2,6 +2,8 @@ // See the LICENSE file in the solution root for more information. using System.ComponentModel; +using Microsoft.Extensions.Logging; +using PdfSharp.Logging; namespace PdfSharp.Drawing { @@ -275,8 +277,12 @@ public static implicit operator XUnit(string value) XUnit unit = default; value = value.Trim(); - // HACK for Germans... - value = value.Replace(',', '.'); + // #DELETE 2024-12-31 - Replace this special treatment for German numbers with an exception. + if (value.Contains(',')) + { + PdfSharpLogHost.Logger.LogError("A number string contains an illegal ','. It is replaced by '.'. Will throw exception in the future."); + value = value.Replace(',', '.'); + } int count = value.Length; int valLen = 0; @@ -335,7 +341,7 @@ public static implicit operator XUnit(string value) /// /// Converts a double to an XUnit object with type set to point. /// - [Obsolete("In PDFsharp 6.1 implicit conversion from double is marked obsolete, because it led to misunderstandings and unexpected behavior. "+ + [Obsolete("In PDFsharp 6.1 implicit conversion from double is marked obsolete, because it led to misunderstandings and unexpected behavior. " + "Provide the unit by XUnit.FromPoint() or use the new class XUnitPt instead.")] public static implicit operator XUnit(double value) => new(value/*, XGraphicsUnit.Point*/); @@ -346,7 +352,7 @@ public static implicit operator XUnit(string value) public static implicit operator double(XUnit value) => value.PointValue; /// - /// Memberwise comparison checking the exact value und unit. + /// Memberwise comparison checking the exact value and unit. /// To compare by value tolerating rounding errors, use IsSameValue() or code like Math.Abs(a.Pt - b.Pt) < 1e-5. /// // ReSharper disable CompareOfFloatsByEqualityOperator @@ -354,7 +360,7 @@ public static implicit operator XUnit(string value) // ReSharper restore CompareOfFloatsByEqualityOperator /// - /// Memberwise comparison checking exact value und unit. + /// Memberwise comparison checking exact value and unit. /// To compare by value tolerating rounding errors, use IsSameValue() or code like Math.Abs(a.Pt - b.Pt) < 1e-5. /// public static bool operator !=(XUnit l, XUnit r) => !(l == r); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XVector.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XVector.cs index 78438d0a..ae81cfee 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XVector.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/XVector.cs @@ -246,7 +246,6 @@ public static XVector Add(XVector vector1, XVector vector2) ///
/// The vector from which vector2 is subtracted. /// The vector to subtract from vector1. - /// public static XVector Subtract(XVector vector1, XVector vector2) => new(vector1._x - vector2._x, vector1._y - vector2._y); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/enums/XGraphicRenderTarget.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/enums/XGraphicRenderTarget.cs index c193127a..40c96b76 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/enums/XGraphicRenderTarget.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Drawing/enums/XGraphicRenderTarget.cs @@ -31,6 +31,6 @@ enum XGraphicTargetContext /// /// Universal Windows Platform. /// - UWP = 10, + WUI = 10, } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Events/RenderEvents.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Events/RenderEvents.cs index 1d43a2ef..82a4ffbd 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Events/RenderEvents.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Events/RenderEvents.cs @@ -7,10 +7,35 @@ namespace PdfSharp.Events { + /// + /// EventArgs for PrepareTextEvent. + /// + public class PrepareTextEventArgs(PdfObject source, XFont font, string text) : PdfSharpEventArgs(source) + { + /// + /// Gets the font used to draw the text. + /// The font cannot be changed in an event handler. + /// + public XFont Font { get; init; } = font; + + /// + /// Gets or sets the text to be processed. + /// + public string Text { get; set; } = text; + } + + /// + /// EventHandler for DrawString and MeasureString. + /// Gives a document the opportunity to inspect or modify the string before it is used for drawing or measuring text. + /// + /// The sender of the event. + /// The RenderTextEventHandler of the event. + public delegate void PrepareTextEventHandler(object sender, PrepareTextEventArgs e); + /// /// EventArgs for RenderTextEvent. /// - public class RenderTextEventArgs(PdfObject source) : PdfSharpEventArgs(source) + public class RenderTextEventArgs(PdfObject source, XFont font, CodePointGlyphIndexPair[] codePointGlyphIndexPair) : PdfSharpEventArgs(source) { /// /// Gets or sets a value indicating whether the determination of the glyph identifiers must be reevaluated. @@ -23,19 +48,19 @@ public class RenderTextEventArgs(PdfObject source) : PdfSharpEventArgs(source) /// Gets the font used to draw the text. /// The font cannot be changed in an event handler. /// - public XFont Font { get; init; } = default!; + public XFont Font { get; init; } = font; /// /// Gets or sets the array containing the code points and glyph indices. /// An event handler can modify or replace this array. /// - public CodePointGlyphIndexPair[] CodePointGlyphIndexPairs { get; set; } = default!; + public CodePointGlyphIndexPair[] CodePointGlyphIndexPairs { get; set; } = codePointGlyphIndexPair; } /// /// EventHandler for DrawString and MeasureString. /// Gives a document the opportunity to inspect or modify the UTF-32 code points with their corresponding - /// glyph identifiers before used for drawing or measuring text. + /// glyph identifiers before they are used for drawing or measuring text. /// /// The sender of the event. /// The RenderTextEventHandler of the event. @@ -46,6 +71,21 @@ public class RenderTextEventArgs(PdfObject source) : PdfSharpEventArgs(source) ///
public class RenderEvents { + /// + /// An event raised whenever text is about to be drawn or measured in a PDF document. + /// + /// The sender of the event. + /// The PrepareTextEventArgs of the event. + public void OnPrepareTextEvent(object sender, PrepareTextEventArgs args) + { + PrepareTextEvent?.Invoke(sender, args); + } + + /// + /// EventHandler for PrepareTextEvent. + /// + public event PrepareTextEventHandler? PrepareTextEvent; + /// /// An event raised whenever text is drawn or measured in a PDF document. /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.Internal/FontHelper.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.Internal/FontHelper.cs index 089356c0..6e6bcef7 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.Internal/FontHelper.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.Internal/FontHelper.cs @@ -18,7 +18,7 @@ using WpfTypeface = System.Windows.Media.Typeface; using WpfGlyphTypeface = System.Windows.Media.GlyphTypeface; #endif -#if UWP +#if WUI using Windows.UI.Text; using Windows.UI.Xaml.Media; #endif @@ -80,7 +80,7 @@ public static XSize MeasureString(string text, XFont font) for (int idx = 0; idx < length; idx++) { char ch = text[idx]; - // HACK: Unclear what to do here. + // H/ACK: Unclear what to do here. if (ch < 32) continue; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.Internal/UnicodeHelper.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.Internal/UnicodeHelper.cs index fed407e9..c0ea21a6 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.Internal/UnicodeHelper.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.Internal/UnicodeHelper.cs @@ -19,7 +19,7 @@ static class UnicodeHelper internal const char LowSurrogateStart = '\uDC00'; internal const char LowSurrogateEnd = '\uDFFF'; internal const int HighSurrogateRange = 0x3FF; - internal const int UnicodePlane01Start = 0x10000; + internal const int UnicodePlane01Start = 0x1_0000; /// /// Converts a UTF-16 string into an array of Unicode code points. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeDescriptor.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeDescriptor.cs index a4fe24e1..d2268069 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeDescriptor.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeDescriptor.cs @@ -14,7 +14,6 @@ using PdfSharp.Pdf.Internal; using PdfSharp.Drawing; using PdfSharp.Fonts.Internal; -using PdfSharp.Internal; using PdfSharp.Logging; namespace PdfSharp.Fonts.OpenType @@ -132,7 +131,7 @@ void Initialize() // Calculate Ascent, Descent, Leading and LineSpacing like in WPF Source Code (see FontDriver.ReadBasicMetrics) // OS/2 is an optional table, but we can’t determine if it is existing in this font. - bool os2SeemsToBeEmpty = FontFace.os2.sTypoAscender == 0 && FontFace.os2.sTypoDescender == 0 && FontFace.os2.sTypoLineGap == 0; + bool os2SeemsToBeEmpty = FontFace.os2 is { sTypoAscender: 0, sTypoDescender: 0, sTypoLineGap: 0 }; //Debug.Assert(!os2SeemsToBeEmpty); // Are there fonts without OS/2 table? bool dontUseWinLineMetrics = (FontFace.os2.fsSelection & 128) != 0; @@ -214,7 +213,6 @@ void Initialize() //flags = image. Encoding ansi = PdfEncoders.WinAnsiEncoding; - Encoding unicode = Encoding.Unicode; byte[] bytes = new byte[256]; @@ -288,7 +286,7 @@ public ushort BmpCodepointToGlyphIndex(char ch) if (ch <= cmap.endCount[seg]) break; } - //Debug.Assert(seg < segCount); + if (seg == segCount) return 0; @@ -477,17 +475,17 @@ public CodePointGlyphIndexPair[] GlyphIndicesFromCodePoints(int[] codePoints, bo if (codePoints == null!) return []; - int length = codePoints.Length; - if (length == 0) + int count = codePoints.Length; + if (count == 0) return []; - var result = new CodePointGlyphIndexPair[length]; + var result = new CodePointGlyphIndexPair[count]; int iRes = 0; // Is the font a symbol font? if (IsSymbolFont) { - for (int idx = 0; idx < length; idx++) + for (int idx = 0; idx < count; idx++) { ref var item = ref result[iRes++]; int codePoint = codePoints[idx]; @@ -508,27 +506,10 @@ public CodePointGlyphIndexPair[] GlyphIndicesFromCodePoints(int[] codePoints, bo else { // It is not a symbol font, i.e. it is a regular open type font. - for (int idx = 0; idx < length; idx++) + for (int idx = 0; idx < count; idx++) { - ref var item = ref result[iRes++]; item.CodePoint = codePoints[idx]; - - //if (useAnsiCharactersOnly) - //{ - // var ansi = AnsiEncoding.UnicodeToAnsi(ch); - // if (ansi == '\uFFFF') - // { - // PdfSharpLogHost.FontManagementLogger.LogDebug("Unexpected low surrogate found: 0x{Char:X2}", ch); - // result[iRes++] = new CodepointGlyphID(ch, ch, 0); // unclear what to do - // } - // else - // { - // result[iRes++] = new CodepointGlyphID(ch, ch, 0); // unclear what to do - // } - // continue; - //} - item.GlyphIndex = item.CodePoint < UnicodeHelper.UnicodePlane01Start ? BmpCodepointToGlyphIndex((char)item.CodePoint) : CodepointToGlyphIndex(item.CodePoint); @@ -537,6 +518,25 @@ public CodePointGlyphIndexPair[] GlyphIndicesFromCodePoints(int[] codePoints, bo return result; } + public ColorTable.GlyphRecord?[] GlyphColorRecordsFromGlyphIndices(CodePointGlyphIndexPair[] pairs) + { + if (pairs == null!) + return []; + + int count = pairs.Length; + if (count == 0) + return []; + + var glyphRecords = new ColorTable.GlyphRecord?[count]; + + for (int idx = 0; idx < count; idx++) + { + glyphRecords[idx] = GetColorRecord(pairs[idx].GlyphIndex); + } + + return glyphRecords; + } + /// /// Remaps a character of a symbol font. /// Required to get the correct glyph identifier @@ -559,5 +559,21 @@ public char RemapSymbolChar(char ch) // Used | instead of + because of: http://pdfsharp.codeplex.com/workitem/15954 return (char)(ch | (FontFace.os2.usFirstCharIndex & 0xFF00)); } + + /// + /// Gets the color-record of the glyph with the specified index. + /// + /// + /// The color-record for the specified glyph or null, if the specified glyph has no color record. + public ColorTable.GlyphRecord? GetColorRecord(int glyphIndex) + { + // Both tables COLR and CPAL are required according to the spec. + // ref: https://learn.microsoft.com/en-us/typography/opentype/spec/colr + if (FontFace is { cpal: not null, colr: not null }) + { + return FontFace.colr.GetLayers(glyphIndex); + } + return null; + } } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontTable.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontTable.cs index c858bd22..88a1db95 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontTable.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontTable.cs @@ -1,14 +1,8 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. -//using Fixed = System.Int32; -//using FWord = System.Int16; -//using UFWord = System.UInt16; - namespace PdfSharp.Fonts.OpenType { - // TODO: Create a font driver for reading and writing OpenType font files. - /// /// Base class for all OpenType tables used in PDFsharp. /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontTables.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontTables.cs index eb05f354..85cd44a4 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontTables.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontTables.cs @@ -1,9 +1,9 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. -#define VERBOSE_ - using System.Text; +using PdfSharp.Internal; +using PdfSharp.Drawing; using Fixed = System.Int32; using FWord = System.Int16; @@ -108,7 +108,7 @@ internal void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -165,7 +165,7 @@ internal void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -248,7 +248,158 @@ internal void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); + } + } + } + + /// + /// This table adds support for multi-colored glyphs in a manner that integrates with the rasterizers + /// of existing text engines and that is designed to be easy to support with current OpenType font files. + /// + class ColorTable : OpenTypeFontTable + { + public const string Tag = TableTagNames.COLR; + + internal struct GlyphRecord + { + public ushort glyphId; + public ushort firstLayerIndex; + public ushort numLayers; + } + + internal struct LayerRecord + { + public ushort glyphId; + public ushort paletteIndex; + } + + public ushort version; + // version 0 tables start + public ushort numBaseGlyphRecords; // Number of BaseGlyph records. + public uint baseGlyphRecordsOffset; // Offset to baseGlyphRecords array, from beginning of COLR table. + public uint layerRecordsOffset; // Offset to layerRecords array, from beginning of COLR table. + public ushort numLayerRecords; // Number of Layer records. + // version 0 tables end + + public GlyphRecord[] baseGlyphRecords = []; + public LayerRecord[] layerRecords = []; + + // Helper array that contains just the glyphIds for the baseGlyphRecords. + private int[] glyphRecordsHelperArray = []; + + public ColorTable(OpenTypeFontFace fontData) + : base(fontData, Tag) + { + Read(fontData); + } + + public GlyphRecord? GetLayers(int glyphId) + { + var index = Array.BinarySearch(glyphRecordsHelperArray, glyphId); + if (index >= 0) + return baseGlyphRecords[index]; + return null; + } + + void Read(OpenTypeFontFace fontData) + { + try + { + var tableStart = fontData.Position; + + version = fontData.ReadUShort(); + Debug.Assert(version == 0 || version == 1, "Version 0 or 1 of COLR table is expected"); + numBaseGlyphRecords = fontData.ReadUShort(); + baseGlyphRecordsOffset = fontData.ReadULong(); + layerRecordsOffset = fontData.ReadULong(); + numLayerRecords = fontData.ReadUShort(); + + baseGlyphRecords = new GlyphRecord[numBaseGlyphRecords]; + glyphRecordsHelperArray = new int[numBaseGlyphRecords]; + layerRecords = new LayerRecord[numLayerRecords]; + + fontData.Position = tableStart + (int)baseGlyphRecordsOffset; + for (var i = 0; i < numBaseGlyphRecords; i++) + { + var glyphId = fontData.ReadUShort(); + baseGlyphRecords[i] = new() + { + glyphId = glyphId, + firstLayerIndex = fontData.ReadUShort(), + numLayers = fontData.ReadUShort() + }; + glyphRecordsHelperArray[i] = glyphId; + } + fontData.Position = tableStart + (int)layerRecordsOffset; + for (var i = 0; i < numLayerRecords; i++) + { + layerRecords[i] = new() + { + glyphId = fontData.ReadUShort(), + paletteIndex = fontData.ReadUShort() + }; + } + } + catch (Exception ex) + { + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); + } + } + } + + /// + /// This table is a set of one or more palettes, each containing a predefined number of color records. + /// It may also contain 'name' table IDs describing the palettes and their entries. + /// + class ColorPalletTable : OpenTypeFontTable + { + public const string Tag = TableTagNames.CPAL; + + public ushort version; + public ushort numPaletteEntries; // Number of palette entries in each palette. + public ushort numPalettes; // Number of palettes in the table. + public ushort numColorRecords; // Total number of color records, combined for all palettes. + public uint colorRecordsArrayOffset; // Offset from the beginning of CPAL table to the first ColorRecord. + public ushort[] colorRecordIndices = []; // Index of each palette’s first color record in the combined color record array. + public XColor[] colorRecords = []; + + public ColorPalletTable(OpenTypeFontFace fontData) + : base(fontData, Tag) + { + Read(fontData); + } + + void Read(OpenTypeFontFace fontData) + { + try + { + var tableStart = fontData.Position; + + version = fontData.ReadUShort(); + numPaletteEntries = fontData.ReadUShort(); + numPalettes = fontData.ReadUShort(); + numColorRecords = fontData.ReadUShort(); + colorRecordsArrayOffset = fontData.ReadULong(); + + colorRecordIndices = new ushort[numPalettes]; + for (int idx = 0; idx < numPalettes; idx++) + { + colorRecordIndices[idx] = fontData.ReadUShort(); + } + colorRecords = new XColor[numColorRecords]; + for (int idx = 0; idx < numColorRecords; idx++) + { + var blue = fontData.ReadByte(); + var green = fontData.ReadByte(); + var red = fontData.ReadByte(); + var alpha = fontData.ReadByte(); + colorRecords[idx] = XColor.FromArgb(alpha, red, green, blue); + } + } + catch (Exception ex) + { + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -307,7 +458,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -370,7 +521,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -397,7 +548,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -448,7 +599,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -458,7 +609,7 @@ class VerticalHeaderTable : OpenTypeFontTable { public const string Tag = TableTagNames.VHea; - // code comes from HorizontalHeaderTable + // Code comes from HorizontalHeaderTable. public Fixed Version; // 0x00010000 for Version 1.0. public FWord Ascender; // Typographic ascent. (Distance from baseline of highest Ascender) public FWord Descender; // Typographic descent. (Distance from baseline of lowest Descender) @@ -507,7 +658,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -535,7 +686,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -568,7 +719,7 @@ public void Read() { var hhea = _fontData!.hhea; var maxp = _fontData.maxp; - if (hhea != null && maxp != null) + if (hhea != null! && maxp != null!) { int numMetrics = hhea.numberOfHMetrics; //->NumberOfHMetrics(); int numLsbs = maxp.numGlyphs - numMetrics; @@ -590,7 +741,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -650,13 +801,13 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } /// - /// The naming table allows multilingual strings to be associated with the OpenTypeTM font file. + /// The naming table allows multilingual strings to be associated with the OpenType font file. /// These strings can represent copyright notices, font names, family names, style names, and so on. /// To keep this table short, the font manufacturer may wish to make a limited set of entries in some /// small set of languages; later, the font can be "localized" and the strings translated or added. @@ -764,7 +915,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } @@ -906,7 +1057,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } @@ -916,7 +1067,7 @@ public void Read() } /// - /// This table contains additional information needed to use TrueType or OpenTypeTM fonts + /// This table contains additional information needed to use TrueType or OpenType fonts /// on PostScript printers. /// class PostScriptTable : OpenTypeFontTable @@ -955,7 +1106,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -990,7 +1141,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -1025,7 +1176,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -1061,7 +1212,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } @@ -1089,7 +1240,7 @@ public void Read() } catch (Exception ex) { - throw new InvalidOperationException(PSSR.ErrorReadingFontData, ex); + throw new InvalidOperationException(PsMsgs.ErrorReadingFontData, ex); } } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontface.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontface.cs index 77f75d5e..7e559296 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontface.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/OpenTypeFontface.cs @@ -112,7 +112,7 @@ public ulong CheckSum public void SetFontEmbedding(PdfFontEmbedding fontEmbedding) { Debug.Assert(fontEmbedding is PdfFontEmbedding.TryComputeSubset or PdfFontEmbedding.EmbedCompleteFontFile); - + if (_fontEmbedding == (PdfFontEmbedding)(-1)) { _fontEmbedding = fontEmbedding; @@ -149,9 +149,11 @@ public XFontSource FontSource XFontSource? _fontSource; #pragma warning disable CS0414 // Field is assigned but its value is never used - /*internal*/ FontTechnology? _fontTechnology; + /*internal*/ + FontTechnology? _fontTechnology; #pragma warning restore CS0414 // Field is assigned but its value is never used - /*internal*/ OffsetTable _offsetTable; + /*internal*/ + OffsetTable _offsetTable; /// /// The dictionary of all font tables. @@ -162,6 +164,8 @@ public XFontSource FontSource // ReSharper disable InconsistentNaming // ReSharper disable IdentifierTypo internal CMapTable cmap = default!; // NRT TODO Change programming model so that it fits NRTs. + internal ColorTable? colr; + internal ColorPalletTable? cpal; internal ControlValueTable cvt = default!; // NRT internal FontProgram fpgm = default!; // NRT internal MaximumProfileTable maxp = default!; // NRT @@ -292,7 +296,7 @@ internal void Read() { #if DEBUG_ if (Name == "Cambria") - Debug-Break.Break(); + _ = typeof(int); #endif // Check if data is a TrueType collection font. uint startTag = ReadULong(); @@ -310,7 +314,7 @@ internal void Read() _offsetTable.RangeShift = ReadUShort(); // Move to table dictionary at position 12 - Debug.Assert(_pos == 12); + Debug.Assert(Position == 12); //tableDictionary = (offsetTable.TableCount); if (_offsetTable.Version == OTTO) @@ -335,6 +339,12 @@ internal void Read() if (Seek(CMapTable.Tag) != -1) cmap = new CMapTable(this); + if (Seek(ColorTable.Tag) != -1) + colr = new ColorTable(this); + + if (Seek(ColorPalletTable.Tag) != -1) + cpal = new ColorPalletTable(this); + if (Seek(ControlValueTable.Tag) != -1) cvt = new ControlValueTable(this); @@ -391,15 +401,15 @@ public OpenTypeFontFace CreateFontSubset(Dictionary glyphs, boo if (_fontEmbedding == PdfFontEmbedding.EmbedCompleteFontFile || loca == null!) return this; - // Create new font image + // Create new font image. var fontData = new OpenTypeFontFace(this); - // Create new loca and glyf table + // Create new loca and glyf table. var locaNew = new IndexToLocationTable(); locaNew.ShortIndex = loca.ShortIndex; var glyfNew = new GlyphDataTable(); - // Add all required tables + // Add all required tables. //fontData.AddTable(os2); if (!cidFont) fontData.AddTable(cmap); @@ -522,47 +532,33 @@ void Compile() FontSource = XFontSource.CreateCompiledFont(stream.ToArray()); } // 2^entrySelector[n] <= n - static readonly int[] _entrySelectors = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }; + static readonly int[] _entrySelectors = [0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]; - public int Position - { - get => _pos; - set => _pos = value; - } - int _pos; + public int Position { get; set; } public int Seek(string tag) { if (TableDictionary.TryGetValue(tag, out var entry)) { - _pos = entry.Offset; - return _pos; + Position = entry.Offset; + return Position; } return -1; } - public int SeekOffset(int offset) - { - return (_pos += offset); - } + public int SeekOffset(int offset) => (Position += offset); /// /// Reads a System.Byte. /// - public byte ReadByte() => FontSource.Bytes[_pos++]; + public byte ReadByte() => FontSource.Bytes[Position++]; /// /// Reads a System.Int16. /// public short ReadShort() { -#if true - return (short)((FontSource.Bytes[_pos++] << 8) | (FontSource.Bytes[_pos++])); -#else - int pos = _pos; - _pos += 2; - return (short)((FontSource.Bytes[pos] << 8) | (FontSource.Bytes[pos + 1])); -#endif + return (short)((FontSource.Bytes[Position++] << 8) | (FontSource.Bytes[Position++])); } /// @@ -570,13 +566,7 @@ public short ReadShort() /// public ushort ReadUShort() { -#if true - return (ushort)((FontSource.Bytes[_pos++] << 8) | (FontSource.Bytes[_pos++])); -#else - int pos = _pos; - _pos += 2; - return (ushort)((FontSource.Bytes[pos] << 8) | (FontSource.Bytes[pos + 1])); -#endif + return (ushort)((FontSource.Bytes[Position++] << 8) | (FontSource.Bytes[Position++])); } /// @@ -584,13 +574,7 @@ public ushort ReadUShort() /// public int ReadLong() { -#if true - return (FontSource.Bytes[_pos++] << 24) | (FontSource.Bytes[_pos++] << 16) | (FontSource.Bytes[_pos++] << 8) | FontSource.Bytes[_pos++]; -#else - int pos = _pos; - _pos += 4; - return (FontSource.Bytes[pos] << 24) | (FontSource.Bytes[pos + 1] << 16) | (FontSource.Bytes[pos + 2] << 8) | FontSource.Bytes[pos + 3]; -#endif + return (FontSource.Bytes[Position++] << 24) | (FontSource.Bytes[Position++] << 16) | (FontSource.Bytes[Position++] << 8) | FontSource.Bytes[Position++]; } /// @@ -598,13 +582,7 @@ public int ReadLong() /// public uint ReadULong() { -#if true - return (uint)((FontSource.Bytes[_pos++] << 24) | (FontSource.Bytes[_pos++] << 16) | (FontSource.Bytes[_pos++] << 8) | FontSource.Bytes[_pos++]); -#else - int pos = _pos; - _pos += 4; - return (uint)((FontSource.Bytes[pos] << 24) | (FontSource.Bytes[pos + 1] << 16) | (FontSource.Bytes[pos + 2] << 8) | FontSource.Bytes[pos + 3]); -#endif + return (uint)((FontSource.Bytes[Position++] << 24) | (FontSource.Bytes[Position++] << 16) | (FontSource.Bytes[Position++] << 8) | FontSource.Bytes[Position++]); } /// @@ -612,13 +590,7 @@ public uint ReadULong() /// public Fixed ReadFixed() { -#if true - return (FontSource.Bytes[_pos++] << 24) | (FontSource.Bytes[_pos++] << 16) | (FontSource.Bytes[_pos++] << 8) | FontSource.Bytes[_pos++]; -#else - int pos = _pos; - _pos += 4; - return (FontSource.Bytes[pos] << 24) | (FontSource.Bytes[pos + 1] << 16) | (FontSource.Bytes[pos + 2] << 8) | FontSource.Bytes[pos + 3]; -#endif + return (FontSource.Bytes[Position++] << 24) | (FontSource.Bytes[Position++] << 16) | (FontSource.Bytes[Position++] << 8) | FontSource.Bytes[Position++]; } /// @@ -626,13 +598,7 @@ public Fixed ReadFixed() /// public short ReadFWord() { -#if true - return (short)((FontSource.Bytes[_pos++] << 8) | FontSource.Bytes[_pos++]); -#else - int pos = _pos; - _pos += 2; - return (short)((FontSource.Bytes[pos] << 8) | FontSource.Bytes[pos + 1]); -#endif + return (short)((FontSource.Bytes[Position++] << 8) | FontSource.Bytes[Position++]); } /// @@ -641,13 +607,7 @@ public short ReadFWord() // ReSharper disable once InconsistentNaming public ushort ReadUFWord() { -#if true - return (ushort)((FontSource.Bytes[_pos++] << 8) | FontSource.Bytes[_pos++]); -#else - int pos = _pos; - _pos += 2; - return (ushort)((FontSource.Bytes[pos] << 8) | FontSource.Bytes[pos + 1]); -#endif + return (ushort)((FontSource.Bytes[Position++] << 8) | FontSource.Bytes[Position++]); } /// @@ -655,8 +615,8 @@ public ushort ReadUFWord() /// public long ReadLongDate() { - int pos = _pos; - _pos += 8; + int pos = Position; + Position += 8; byte[] bytes = FontSource.Bytes; return (((long)bytes[pos]) << 56) | (((long)bytes[pos + 1]) << 48) | (((long)bytes[pos + 2]) << 40) | (((long)bytes[pos + 3]) << 32) | (((long)bytes[pos + 4]) << 24) | (((long)bytes[pos + 5]) << 16) | (((long)bytes[pos + 6]) << 8) | bytes[pos + 7]; @@ -669,7 +629,7 @@ public string ReadString(int size) { char[] chars = new char[size]; for (int idx = 0; idx < size; idx++) - chars[idx] = (char)FontSource.Bytes[_pos++]; + chars[idx] = (char)FontSource.Bytes[Position++]; return new string(chars); } @@ -680,34 +640,28 @@ public byte[] ReadBytes(int size) { byte[] bytes = new byte[size]; for (int idx = 0; idx < size; idx++) - bytes[idx] = FontSource.Bytes[_pos++]; + bytes[idx] = FontSource.Bytes[Position++]; return bytes; } /// /// Reads the specified buffer. /// - public void Read(byte[] buffer) - { - Read(buffer, 0, buffer.Length); - } + public void Read(byte[] buffer) => Read(buffer, 0, buffer.Length); /// /// Reads the specified buffer. /// public void Read(byte[] buffer, int offset, int length) { - Buffer.BlockCopy(FontSource.Bytes, _pos, buffer, offset, length); - _pos += length; + Buffer.BlockCopy(FontSource.Bytes, Position, buffer, offset, length); + Position += length; } /// /// Reads a System.Char[4] as System.String. /// - public string ReadTag() - { - return ReadString(4); - } + public string ReadTag() => ReadString(4); /// /// Gets the DebuggerDisplayAttribute text. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/enums/TableTagNames.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/enums/TableTagNames.cs index 5b204679..6313cfda 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/enums/TableTagNames.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts.OpenType/enums/TableTagNames.cs @@ -6,11 +6,11 @@ namespace PdfSharp.Fonts.OpenType { /// - /// TrueType font table names. + /// Case-sensitive TrueType font table names. /// static class TableTagNames { - // --- Required Tables --- + // --- Required tables --- /// /// Character to glyph mapping. @@ -52,7 +52,7 @@ static class TableTagNames /// public const string Post = "post"; - // --- Tables Related to TrueType Outlines --- + // --- Tables related to TrueType outlines --- /// /// Control Value Table. @@ -79,7 +79,7 @@ static class TableTagNames /// public const string Prep = "prep"; - // --- Tables Related to PostScript Outlines --- + // --- Tables related to PostScript outlines --- /// /// PostScript font program (compact font format). @@ -91,7 +91,7 @@ static class TableTagNames /// public const string VOrg = "VORG"; - // --- Tables Related to Bitmap Glyphs --- + // --- Tables related to bitmap glyphs --- /// /// Embedded bitmap data. @@ -108,7 +108,7 @@ static class TableTagNames /// public const string EBSC = "EBSC"; - // --- Advanced Typographic Tables --- + // --- Advanced typographic tables --- /// /// Baseline data. @@ -135,7 +135,19 @@ static class TableTagNames /// public const string JSTF = "JSTF"; - // --- Other OpenType Tables --- + // --- Tables related to glyph color --- + + /// + /// Color table. + /// + public const string COLR = "COLR"; + + /// + /// Color pallet table. + /// + public const string CPAL = "CPAL"; + + // --- Other OpenType tables --- /// /// Digital signature. @@ -182,4 +194,4 @@ static class TableTagNames /// public const string VMtx = "vmtx"; } -} \ No newline at end of file +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/CodePointGlyphIndexPair.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/CodePointGlyphIndexPair.cs index 747181cf..8455cbf4 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/CodePointGlyphIndexPair.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/CodePointGlyphIndexPair.cs @@ -1,6 +1,8 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. +using PdfSharp.Fonts.OpenType; + namespace PdfSharp.Fonts { /// @@ -21,4 +23,20 @@ public struct CodePointGlyphIndexPair(int codePoint, ushort glyphIndex) /// public ushort GlyphIndex = glyphIndex; } + + /// + /// The combination of a glyph index and its glyph record in the color table, if it exists. + /// + struct GlyphIndexGlyphColorRecordPair(ushort glyphIndex, ColorTable.GlyphRecord? colorRecord) + { + /// + /// The glyph index. + /// + public ushort GlyphIndex = glyphIndex; + + /// + /// The color-record of the glyph if provided by the font. + /// + internal ColorTable.GlyphRecord? ColorRecord = colorRecord; + } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/CoreBuildFontResolver.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/CoreBuildFontResolver.cs index cf6354d2..2b353ac5 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/CoreBuildFontResolver.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/CoreBuildFontResolver.cs @@ -194,14 +194,22 @@ static CoreBuildFontResolver() if (_isWindows == null) { +#if NET462 + _isWindows = true; +#else // May be too simple. _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); +#endif } if (_isLinux == null) { +#if NET462 + _isLinux = false; +#else // May be too simple. _isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); +#endif } if (_isWindows.Value) diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/GlyphHelper.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/GlyphHelper.cs index b7053c37..8dca01a3 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/GlyphHelper.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/GlyphHelper.cs @@ -43,7 +43,7 @@ public static ushort GlyphIndexFromCodePoint(int codePoint, XFont font) public static CodePointGlyphIndexPair[] GlyphIndicesFromString(string s, XFont font) => font.OpenTypeDescriptor.GlyphIndicesFromString(s); -#if NET6_0_OR_GREATER_ +#if true_ /// /// Maps the characters of a string to an array of code points. /// It uses the concept of runes, which is not implemented in .NET Framework or .NET Standard. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/PlatformFontResolver.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/PlatformFontResolver.cs index 41580fa3..a7f37dff 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/PlatformFontResolver.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/PlatformFontResolver.cs @@ -79,11 +79,11 @@ public static class if (fontSource == null || wpfFontFamily == null || wpfTypeface == null || wpfGlyphTypeface == null) return null; #endif -#if UWP +#if WUI //GlyphTypeface wpfGlyphTypeface; XFontSource fontSource = null;//CreateFontSource(familyName, isBold, isItalic, out wpfGlyphTypeface, typefaceKey); #endif -#if GDI || WPF || UWP +#if GDI || WPF || WUI // If no such font exists return null. PDFsharp will fail. // Re/Sharper disable once ConditionIsAlwaysTrueOrFalse because code is under construction. if (fontSource == null) @@ -310,7 +310,7 @@ public static class } //if (!WpfTypeface.TryGetGlyphTypeface(out glyphTypeface)) - // throw new InvalidOperationException(PSSR.CannotGetGlyphTypeface(familyName)); + // throw new InvalidOperationException(PsMgs.CannotGetGlyphTypeface(familyName)); } #endif wpfFontFamily ??= new WpfFontFamily(familyName); @@ -327,7 +327,7 @@ public static class } #endif -#if UWP +#if WUI internal static XFontSource CreateFontSource(string familyName, bool isBold, bool isItalic, string typefaceKey) { throw new NotImplementedException(); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/PlatformFontResolverInfo.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/PlatformFontResolverInfo.cs index fa384982..4ed9d0da 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/PlatformFontResolverInfo.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Fonts/PlatformFontResolverInfo.cs @@ -71,7 +71,7 @@ public PlatformFontResolverInfo(string faceName, bool mustSimulateBold, bool mus /// public WpfGlyphTypeface WpfGlyphTypeface { get; } #endif -#if UWP +#if WUI public PlatformFontResolverInfo(string faceName, bool mustSimulateBold, bool mustSimulateItalic) : base(faceName, mustSimulateBold, mustSimulateItalic) { diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Internal/Calc.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/Calc.cs index f19f3709..620801d7 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Internal/Calc.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/Calc.cs @@ -28,25 +28,25 @@ public static XSize PageSizeToSize(PageSize value) { // Source: https://www.din-formate.de/reihe-a-din-groessen-mm-pixel-dpi.html // See also: PageSizeConverter.cs. - PageSize.A0 => new XSize(2384, 3370), - PageSize.A1 => new XSize(1684, 2384), - PageSize.A2 => new XSize(1191, 1684), - PageSize.A3 => new XSize(842, 1191), - PageSize.A4 => new XSize(595, 842), - PageSize.A5 => new XSize(420, 595), - PageSize.B4 => new XSize(709, 1001), - PageSize.B5 => new XSize(499, 709), + PageSize.A0 => new(2384, 3370), + PageSize.A1 => new(1684, 2384), + PageSize.A2 => new(1191, 1684), + PageSize.A3 => new(842, 1191), + PageSize.A4 => new(595, 842), + PageSize.A5 => new(420, 595), + PageSize.B4 => new(709, 1001), + PageSize.B5 => new(499, 709), // The strange sizes from overseas... - PageSize.Letter => new XSize(612, 792), - PageSize.Legal => new XSize(612, 1008), - PageSize.Tabloid => new XSize(792, 1224), - PageSize.Ledger => new XSize(1224, 792), - PageSize.Statement => new XSize(396, 612), - PageSize.Executive => new XSize(540, 720), - PageSize.Folio => new XSize(612, 936), - PageSize.Quarto => new XSize(576, 720), - PageSize.Size10x14 => new XSize(720, 1008), + PageSize.Letter => new(612, 792), + PageSize.Legal => new(612, 1008), + PageSize.Tabloid => new(792, 1224), + PageSize.Ledger => new(1224, 792), + PageSize.Statement => new(396, 612), + PageSize.Executive => new(540, 720), + PageSize.Folio => new(612, 936), + PageSize.Quarto => new(576, 720), + PageSize.Size10x14 => new(720, 1008), _ => throw new ArgumentException("Invalid PageSize.") }; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Internal/DotNetHelper.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/DotNetHelper.cs index 53584589..e8d9f177 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Internal/DotNetHelper.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/DotNetHelper.cs @@ -8,18 +8,17 @@ namespace PdfSharp.Internal { /// - /// Class containing replacements for net 6 methods missing in net framework 4.7.2. + /// Class containing replacements for net 6 methods missing in net framework 4.6.2. /// static class DotNetHelper { /// - /// Implements the net 6 BigInteger constructor missing in net framework 4.7.2. + /// Implements the net 6 BigInteger constructor missing in net framework 4.6.2. /// Initializes a new instance of the BigInteger structure using the values in a read-only span of bytes, and optionally indicating the signing encoding and the endianness byte order. /// /// /// /// - /// public static BigInteger CreateBigInteger(ReadOnlySpan value, bool isUnsigned = false, bool isBigEndian = false) { var bytes = value.ToArray(); @@ -31,7 +30,17 @@ public static BigInteger CreateBigInteger(ReadOnlySpan value, bool isUnsig // A leading bit of 1 defines a negative number. If the input should be interpreted as unsigned, prepend a new zero byte, if there’s a leading 1. // As bytes is in little endian order, check the most significant bit of the last byte. If it is 1, append the zero byte. if (isUnsigned && bytes.Length > 0 && (bytes.Last() & 0x80) > 0) + { +#if NET462 + var len = bytes.Length; + var bytes2 = new byte[len + 1]; + bytes.CopyTo(bytes2, 0); + bytes2[len] = 0; + bytes = bytes2; +#else bytes = bytes.Append((byte)0).ToArray(); +#endif + } return new BigInteger(bytes); } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Internal/DoubleUtil.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/DoubleUtil.cs index cd63e31c..16b338c8 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Internal/DoubleUtil.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/DoubleUtil.cs @@ -40,7 +40,7 @@ public static bool AreRoughlyEqual(double value1, double value2, int decimalPlac return Math.Abs(value1 - value2) < decs[decimalPlace]; } - static readonly double[] decs = { 1, 1E-1, 1E-2, 1E-3, 1E-4, 1E-5, 1E-6, 1E-7, 1E-8, 1E-9, 1E-10, 1E-11, 1E-12, 1E-13, 1E-14, 1E-15, 1E-16 }; + static readonly double[] decs = [1, 1E-1, 1E-2, 1E-3, 1E-4, 1E-5, 1E-6, 1E-7, 1E-8, 1E-9, 1E-10, 1E-11, 1E-12, 1E-13, 1E-14, 1E-15, 1E-16]; /// /// Indicates whether the values are so close that they can be considered as equal. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Internal/PsMsg.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/PsMsg.cs new file mode 100644 index 00000000..1ffcd495 --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/PsMsg.cs @@ -0,0 +1,22 @@ +// PDFsharp - A .NET library for processing PDF +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using Microsoft.Extensions.Logging; + +namespace PdfSharp.Internal +{ + /// + /// PDFsharp message. + /// + readonly struct PsMsg(PsMsgId id, string message) + { + public PsMsgId Id { get; init; } = id; + + public string Message { get; init; } = message; + + public EventId EventId => new((int)Id, EventName); + + public string EventName => Id.ToString(); + } +} \ No newline at end of file diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Internal/PsMsgs.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/PsMsgs.cs new file mode 100644 index 00000000..6246de7a --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/PsMsgs.cs @@ -0,0 +1,183 @@ +// PDFsharp - A .NET library for processing PDF +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Drawing; +using PdfSharp.Pdf; + +namespace PdfSharp.Internal +{ + /// + /// PDFsharp messages. + /// + // ReSharper disable once InconsistentNaming + // ReSharper disable once IdentifierTypo + static class PsMsgs + { + // Old stuff + //// How to use: + //// Create a function or property for each message text, depending on how many parameters are + //// part of the message. For the beginning, type plain English text in the function or property. + //// The use of functions is safe when a parameter must be changed. The compiler tells you all + //// places in your code that must be modified. + //// For localization, create an enum value for each function or property with the same name. Then + //// create localized message files with the enum values as messages identifiers. In the properties + //// and functions all text is replaced by Format or GetString functions with the corresponding enum value + //// as first parameter. The use of enums ensures that typing errors in message resource names are + //// simply impossible. Use the TestResourceMessages function to ensure that each enum value has an + //// appropriate message text. + + #region General messages + + //public static string IndexOutOfRange + // => "The index is out of range."; + + public static string ListEnumCurrentOutOfRange + => "Enumeration out of range."; + + public static string PageIndexOutOfRange + => "The index of a page is out of range."; + + public static string OutlineIndexOutOfRange + => "The index of an outline is out of range."; + + public static string SetValueMustNotBeNull + => "The set value property must not be null."; + + public static string InvalidValue(int val, string name, int min, int max) + => Invariant($"{val} is not a valid value for {name}. {name} should be greater than or equal to {min} and less than or equal to {max}."); + + public static string ObsoleteFunctionCalled + => "The function is obsolete and must not be called."; + + public static string OwningDocumentRequired + => "The PDF object must belong to a PdfDocument, but property Document is null."; + + public static string FileNotFound(string path) + => $"The file '{path}' does not exist."; + + public static string FontDataReadOnly + => "Font data is read-only."; + + public static string ErrorReadingFontData + => "Error while parsing an OpenType font."; + + #endregion + + #region XGraphics specific messages + + // ----- XGraphics ---------------------------------------------------------------------------- + + public static string PointArrayEmpty + => "The PointF array must not be empty."; + + public static string PointArrayAtLeast(int count) + => Invariant($"The point array must contain {count} or more points."); + + public static string NeedPenOrBrush + => "XPen or XBrush or both must not be null."; + + public static string CannotChangeImmutableObject(string typename) + => $"You cannot change this immutable {typename} object."; + + public static string FontAlreadyAdded(string fontName) + => $"FontFace with the name '{fontName}' already added to font collection."; + + public static string NotImplementedForFontsRetrievedWithFontResolver(string name) + => $"Not implemented for font '{name}', because it was retrieved with font resolver."; + + #endregion + + #region PDF specific messages + + // ----- PDF ---------------------------------------------------------------------------------- + + public static string InvalidPdf + => "The file is not a valid PDF document."; + + public static string InvalidVersionNumber(int value) + => Invariant($"The value {value} is not a valid version number."); // Valid values are 12, 13, and 14. + + public static string PasswordRequired + => "A password is required to open the PDF document."; + + public static string InvalidPassword + => "The specified password is invalid."; + + public static string OwnerPasswordRequired + => "To modify the document the owner password is required"; + + public static string UserOrOwnerPasswordRequired + => "At least a user or an owner password is required to encrypt the document."; + + public static string CannotModify + => "The document cannot be modified."; + + public static string NameMustStartWithSlash + => "A PDF name must start with a slash (/)."; + + public static string ImportPageNumberOutOfRange(int pageNumber, int maxPage, string path) + { + return String.Format("The page cannot be imported from document '{2}', because the page number is out of range. " + + "The specified page number is {0}, but it must be in the range from 1 to {1}.", pageNumber, maxPage, path); + } + + public static string MultiplePageInsert => "The page cannot be added to this document because the document already owned this page."; + + public static string UnexpectedTokenInPdfFile => "Unexpected token in PDF file. The PDF file may be corrupt. If it is not, please send us the file for service (issues (at) pdfsharp.net)."; + + public static string InappropriateColorSpace(PdfColorMode colorMode, XColorSpace colorSpace) + { + string mode; + switch (colorMode) + { + case PdfColorMode.Rgb: + mode = "RGB"; + break; + + case PdfColorMode.Cmyk: + mode = "CMYK"; + break; + + default: + mode = "(undefined)"; + break; + } + + string space; + switch (colorSpace) + { + case XColorSpace.Rgb: + space = "RGB"; + break; + + case XColorSpace.Cmyk: + space = "CMYK"; + break; + + case XColorSpace.GrayScale: + space = "grayscale"; + break; + + default: + space = "(undefined)"; + break; + } + return $"The document requires color mode {mode}, but a color is defined using {space}. " + + "Use only colors that match the color mode of the PDF document"; + } + + public static string CannotGetGlyphTypeface(string fontName) + => Invariant($"Cannot get a matching glyph typeface for font '{fontName}'."); + + // ----- PdfParser ---------------------------------------------------------------------------- + + public static string UnexpectedToken(string token) => $"Token '{token}' was not expected."; + //{ + // return Format(PSMsgID.UnexpectedToken, token); + // //return Format("Token '{0}' was not expected.", token); + //} + + #endregion + } +} \ No newline at end of file diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/root/enums/PSMsgID.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/enums/PsMsgId.cs similarity index 89% rename from src/foundation/src/PDFsharp/src/PdfSharp/root/enums/PSMsgID.cs rename to src/foundation/src/PDFsharp/src/PdfSharp/Internal/enums/PsMsgId.cs index 4793d771..859c4e40 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/root/enums/PSMsgID.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Internal/enums/PsMsgId.cs @@ -1,20 +1,23 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. -namespace PdfSharp +namespace PdfSharp.Internal { /// + /// PDFsharp message ID. /// Represents IDs for error and diagnostic messages generated by PDFsharp. /// // ReSharper disable once InconsistentNaming - enum PSMsgID + enum PsMsgId { + None = 0, + // ----- General Messages --------------------------------------------------------------------- /// /// PSMsgID. /// - SampleMessage1, + SampleMessage1 = MessageIdOffset.Ps, /// /// PSMsgID. @@ -47,4 +50,4 @@ enum PSMsgID /// UnknownEncryption, } -} \ No newline at end of file +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Logging/LogMessages.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Logging/LogMessages.cs index 22e26243..0e008bf7 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Logging/LogMessages.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Logging/LogMessages.cs @@ -12,10 +12,12 @@ namespace PdfSharp.Logging /// public static class PdfSharpEventId // draft... { - public const int DocumentCreate = StartId + 0; - public const int PageCreate = StartId + 1; - public const int GraphicsCreate = StartId + 2; - public const int FontCreate = StartId + 3; + public const int DocumentCreated = StartId + 1; + public const int DocumentSaved = StartId + 2; + public const int PageCreated = StartId + 3; + public const int PageAdded = StartId + 4; + public const int GraphicsCreated = StartId + 5; + public const int FontCreated = StartId + 6; public const int PdfReaderIssue = StartId + 10; @@ -25,22 +27,26 @@ public static class PdfSharpEventId // draft... public static class PdfSharpEventName { - public const string DocumentCreate = "Document creation"; - public const string PageCreate = "Page creation"; - public const string GraphicsCreate = "Graphics creation"; - public const string FontCreate = "Font creation"; + public const string DocumentCreated = "Document created"; + public const string DocumentSaved = "Document saved"; + public const string PageCreated = "Page created"; + public const string PageAdded = "Page creation2"; + public const string GraphicsCreated = "Graphics created"; + public const string FontCreated = "Font created"; public const string PdfReaderIssue = "PDF reader issue"; } public static class PdfSharpEvent { - public static EventId DocumentCreate = new(PdfSharpEventId.DocumentCreate, PdfSharpEventName.DocumentCreate); - public static EventId PageCreate = new(PdfSharpEventId.PageCreate, PdfSharpEventName.PageCreate); - public static EventId FontCreate = new(PdfSharpEventId.FontCreate, PdfSharpEventName.FontCreate); + public static EventId DocumentCreate = new(PdfSharpEventId.DocumentCreated, PdfSharpEventName.DocumentCreated); + public static EventId DocumentSaved = new(PdfSharpEventId.DocumentSaved, PdfSharpEventName.DocumentSaved); + public static EventId PageCreate = new(PdfSharpEventId.PageCreated, PdfSharpEventName.PageCreated); + public static EventId PageAdded = new(PdfSharpEventId.PageAdded, PdfSharpEventName.PageAdded); + public static EventId FontCreate = new(PdfSharpEventId.FontCreated, PdfSharpEventName.FontCreated); public static EventId PdfReaderIssue = new(PdfSharpEventId.PdfReaderIssue, PdfSharpEventName.PdfReaderIssue); - + public static EventId Placeholder = new(999999, "Placeholder"); } @@ -53,40 +59,40 @@ public static partial class LogMessages [LoggerMessage( Level = LogLevel.Information, - EventId = PdfSharpEventId.DocumentCreate, - EventName = PdfSharpEventName.DocumentCreate, + EventId = PdfSharpEventId.DocumentCreated, + EventName = PdfSharpEventName.DocumentCreated, Message = "New PDF document '{DocumentName}' created.")] - public static partial void PdfDocumentCreated(this ILogger logger, + public static partial void PdfDocumentCreated(this ILogger logger, string? documentName); [LoggerMessage( Level = LogLevel.Information, - EventId = PdfSharpEventId.DocumentCreate, - EventName = PdfSharpEventName.DocumentCreate, + EventId = PdfSharpEventId.DocumentSaved, + EventName = PdfSharpEventName.DocumentSaved, Message = "PDF document '{documentName}' saved.")] public static partial void PdfDocumentSaved(this ILogger logger, string? documentName); [LoggerMessage( Level = LogLevel.Information, - EventId = PdfSharpEventId.PageCreate, - EventName = PdfSharpEventName.PageCreate, + EventId = PdfSharpEventId.PageCreated, + EventName = PdfSharpEventName.PageCreated, Message = "New PDF page added to document '{documentName}'.")] - public static partial void NewPdfPageAdded(this ILogger logger, + public static partial void NewPdfPageCreated(this ILogger logger, string? documentName); [LoggerMessage( Level = LogLevel.Information, - EventId = PdfSharpEventId.PageCreate, - EventName = PdfSharpEventName.PageCreate, + EventId = PdfSharpEventId.PageAdded, + EventName = PdfSharpEventName.PageAdded, Message = "Existing PDF page added to document '{documentName}'.")] public static partial void ExistingPdfPageAdded(this ILogger logger, string? documentName); [LoggerMessage( Level = LogLevel.Information, - EventId = PdfSharpEventId.GraphicsCreate, - EventName = PdfSharpEventName.GraphicsCreate, + EventId = PdfSharpEventId.GraphicsCreated, + EventName = PdfSharpEventName.GraphicsCreated, Message = "New XGraphics created from '{source}'.")] public static partial void XGraphicsCreated(this ILogger logger, string? source); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfAcroField.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfAcroField.cs index 79afe41b..9a4111da 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfAcroField.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfAcroField.cs @@ -125,13 +125,13 @@ public bool HasKids /// public string[] GetDescendantNames() { - List names = new List(); + List names = []; if (HasKids) { PdfAcroFieldCollection fields = Fields; fields.GetDescendantNames(ref names, null); } - List temp = new List(); + List temp = []; foreach (string name in names) temp.Add(name); return temp.ToArray(); @@ -267,7 +267,7 @@ public PdfAcroFieldCollection Fields /// public sealed class PdfAcroFieldCollection : PdfArray { - PdfAcroFieldCollection(PdfArray array) + internal PdfAcroFieldCollection(PdfArray array) : base(array) { } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfButtonField.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfButtonField.cs index f1a601ce..1982cf1f 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfButtonField.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfButtonField.cs @@ -52,7 +52,6 @@ protected string GetNonOffValue() internal override void GetDescendantNames(ref List names, string? partialName) { string t = Elements.GetString(PdfAcroField.Keys.T); - // HACK: ??? if (t == "") t = "???"; Debug.Assert(t != ""); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfSignatureField.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfSignatureField.cs index d1f84691..4ddda2bf 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfSignatureField.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.AcroForms/PdfSignatureField.cs @@ -2,6 +2,8 @@ // See the LICENSE file in the solution root for more information. using PdfSharp.Pdf.IO; +using PdfSharp.Drawing; +using PdfSharp.Pdf.Annotations; namespace PdfSharp.Pdf.AcroForms { @@ -15,11 +17,64 @@ public sealed class PdfSignatureField : PdfAcroField /// internal PdfSignatureField(PdfDocument document) : base(document) - { } + { + CustomAppearanceHandler = null!; + } internal PdfSignatureField(PdfDictionary dict) : base(dict) - { } + { + CustomAppearanceHandler = null!; + } + + /// + /// Handler that creates the visual representation of the digital signature in PDF. + /// + public IAnnotationAppearanceHandler CustomAppearanceHandler { get; internal set; } + + /// + /// Creates the custom appearance form X object for the annotation that represents + /// this acro form text field. + /// + void RenderCustomAppearance() + { + PdfRectangle rect = Elements.GetRectangle(PdfAnnotation.Keys.Rect); + + var visible = rect.X1 + rect.X2 + rect.Y1 + rect.Y2 != 0; + + if (!visible) + return; + + if (CustomAppearanceHandler == null) + throw new Exception("AppearanceHandler is null"); + + XForm form = new XForm(_document, rect.Size); + XGraphics gfx = XGraphics.FromForm(form); + + CustomAppearanceHandler.DrawAppearance(gfx, rect.ToXRect()); + + form.DrawingFinished(); + + // Get existing or create new appearance dictionary + if (Elements[PdfAnnotation.Keys.AP] is not PdfDictionary ap) + { + ap = new PdfDictionary(_document); + Elements[PdfAnnotation.Keys.AP] = ap; + } + + // Set XRef to normal state + ap.Elements["/N"] = form.PdfForm.Reference; + + // PdfRenderer can be null. + form.PdfRenderer?.Close(); + } + + internal override void PrepareForSave() + { + base.PrepareForSave(); + if (CustomAppearanceHandler != null!) + RenderCustomAppearance(); + } /// /// Writes a key/value pair of this signature field dictionary. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Actions/PdfEmbeddedGoToAction.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Actions/PdfEmbeddedGoToAction.cs index 5e57d7d6..0a7066b6 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Actions/PdfEmbeddedGoToAction.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Actions/PdfEmbeddedGoToAction.cs @@ -127,6 +127,7 @@ void ParseDestinationName() /// Separator for splitting destination path segments ans destination name. /// public const char Separator = '\\'; + /// /// Path segment string used to move to the parent document. /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfCatalog.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfCatalog.cs index 77534360..d083f351 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfCatalog.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfCatalog.cs @@ -69,7 +69,11 @@ public PdfPages Pages { _pages = (PdfPages?)Elements.GetValue(Keys.Pages, VCF.CreateIndirect) ?? NRT.ThrowOnNull(); if (Owner.IsImported) + { _pages.FlattenPageTree(); + //foreach (var page in _pages) + // page.InitPageSize(); + } } return _pages; } @@ -157,7 +161,7 @@ public PdfAcroForm AcroForm get { if (_acroForm == null) - _acroForm = (PdfAcroForm?)Elements.GetValue(Keys.AcroForm)??NRT.ThrowOnNull(); + _acroForm = (PdfAcroForm?)Elements.GetValue(Keys.AcroForm) ?? NRT.ThrowOnNull(); return _acroForm; } } @@ -189,7 +193,8 @@ internal override void PrepareForSave() _pages.PrepareForSave(); // Create outline objects. - if (_outline != null && _outline.Outlines.Count > 0) + //if (_outline != null && _outline.Outlines.Count > 0) + if (_outline is { Outlines.Count: > 0 }) { if (Elements[Keys.PageMode] == null) PageMode = PdfPageMode.UseOutlines; @@ -343,7 +348,7 @@ internal sealed class Keys : KeysBase /// /// (Optional; PDF 1.4; must be an indirect reference) A metadata stream - /// containing metadata for the document. + /// containing metadata for the document. /// [KeyInfo("1.4", KeyType.Dictionary | KeyType.Optional | KeyType.MustBeIndirect)] public const string Metadata = "/Metadata"; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfContents.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfContents.cs index d11544c9..971ed13f 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfContents.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfContents.cs @@ -221,7 +221,7 @@ public PdfContent Current get { if (_index == -1 || _index >= _contents.Elements.Count) - throw new InvalidOperationException(PSSR.ListEnumCurrentOutOfRange); + throw new InvalidOperationException(PsMsgs.ListEnumCurrentOutOfRange); return _currentElement??throw new InvalidOperationException("Current called before MoveNext."); } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfCrossReferenceTable.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfCrossReferenceTable.cs index 6042dc55..7c181066 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfCrossReferenceTable.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfCrossReferenceTable.cs @@ -43,18 +43,20 @@ public void Add(PdfReference iref) // ReSharper disable once CanSimplifyDictionaryLookupWithTryAdd because it would not build with .NET Framework. if (ObjectTable.ContainsKey(iref.ObjectID)) { -#if true_ - // Really happens with existing (bad) PDF files. - // See file 'Detaljer.ARGO.KOD.rev.B.pdf' from https://github.com/ststeiger/PdfSharpCore/issues/362 - throw new InvalidOperationException("Object already in table."); -#else +#if true + var oldIref = ObjectTable.First(x => x.Key == iref.ObjectID).Value; + // We remove the existing one and use the latter reference. - // HACK: This is just a quick fix that may not be the best solution in all cases. + // Choosing the latter reference may not be the best solution in all cases. // On GitHub user packdat provides a PR that orders objects. This code is not yet integrated, // because releasing 6.1.0 had a higher priority. We will fix this in 6.2.0. - // However, this quick fix is better than throwing an exception in all cases. - PdfSharpLogHost.PdfReadingLogger.LogError("Object '{ObjectID}' already exists in xref table. The latter one is used.", iref.ObjectID); + // However, using the last added object and logging an error is better than throwing an exception in all cases. + PdfSharpLogHost.PdfReadingLogger.LogError("Object '{ObjectID}' already exists in xref table’s objects, referring to position {Position}. The latter one referring to position {Position} is used. " + + "This should not occur. If somebody came here, please send us your PDF file so that we can fix it (issues (at) pdfsharp.net.", oldIref.ObjectID, oldIref.Position, iref.Position); + ObjectTable.Remove(iref.ObjectID); +#else + throw new InvalidOperationException("Object already in table."); #endif } ObjectTable.Add(iref.ObjectID, iref); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfEmbeddedFileStream.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfEmbeddedFileStream.cs index 2f4f46e5..9b403097 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfEmbeddedFileStream.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfEmbeddedFileStream.cs @@ -19,7 +19,6 @@ public PdfEmbeddedFileStream(PdfDocument document, Stream stream) : base(documen { stream.Read(_data, 0, (int)stream.Length); } - Initialize(); } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfExtGState.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfExtGState.cs index 33f9d950..8c8eef34 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfExtGState.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfExtGState.cs @@ -1,6 +1,8 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. +using Microsoft.Extensions.Logging; +using PdfSharp.Logging; #if GDI using System.Drawing; using System.Drawing.Imaging; @@ -114,6 +116,13 @@ public double StrokeAlpha { set { + // #PDF-A + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (_document.IsPdfA && value != 1.0) + { + PdfSharpLogHost.Logger.LogWarning("PDF/A: Stroke alpha value set to 1."); + value = 1.0; + } _strokeAlpha = value; Elements.SetReal(Keys.CA, value); UpdateKey(); @@ -129,6 +138,13 @@ public double NonStrokeAlpha { set { + // #PDF-A + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (_document.IsPdfA && value != 1.0) + { + PdfSharpLogHost.Logger.LogWarning("PDF/A: Non-stroke alpha value set to 1."); + value = 1.0; + } _nonStrokeAlpha = value; Elements.SetReal(Keys.ca, value); UpdateKey(); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFontDescriptor.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFontDescriptor.cs index aaee6686..737f334c 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFontDescriptor.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFontDescriptor.cs @@ -99,7 +99,6 @@ internal PdfFontDescriptor(PdfDocument document, OpenTypeDescriptor otDescriptor Elements.SetInteger(Keys.XHeight, Descriptor.DesignUnitsToPdf(Descriptor.XHeight)); } - //HACK OpenTypeDescriptor descriptor internal OpenTypeDescriptor Descriptor { get; } /// @@ -173,14 +172,10 @@ internal string CreateEmbeddedFontSubsetName(string name) var newName = s.ToString(); // The probability is low for a single document // with a handful of fonts, but it is better to check. -#if NET6_0_OR_GREATER_ - if (!_fontSubsetNames.TryAdd(newName, null)) - goto TryAgain; -#else + if (_fontSubsetNames.ContainsKey(newName)) goto TryAgain; _fontSubsetNames.Add(newName, null); -#endif return newName; } readonly Dictionary _fontSubsetNames = []; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFontProgram.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFontProgram.cs index 1e74dc84..0c362698 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFontProgram.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFontProgram.cs @@ -23,13 +23,13 @@ internal PdfFontProgram(PdfDocument document) internal void CreateFontFileAndAddToDescriptor(PdfFontDescriptor pdfFontDescriptor, CMapInfo cmapInfo, bool cidFont) { var x = pdfFontDescriptor.Elements[PdfFontDescriptor.Keys.FontFile2]; - + OpenTypeFontFace subSet = pdfFontDescriptor.Descriptor.FontFace.CreateFontSubset(cmapInfo.GlyphIndices, cidFont); byte[] fontData = subSet.FontSource.Bytes; Owner.Internals.AddObject(this); pdfFontDescriptor.Elements[PdfFontDescriptor.Keys.FontFile2] = Reference; - + Elements["/Length1"] = new PdfInteger(fontData.Length); if (!Owner.Options.NoCompression) { diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFormXObject.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFormXObject.cs index 6f8d2005..a4d6b9f8 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFormXObject.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfFormXObject.cs @@ -58,7 +58,7 @@ internal PdfFormXObject(PdfDocument thisDocument, PdfImportedObjectTable importe // Get import page var importPages = importedObjectTable.ExternalDocument!.Pages; // NRT if (pdfForm.PageNumber < 1 || pdfForm.PageNumber > importPages.Count) - PSSR.ImportPageNumberOutOfRange(pdfForm.PageNumber, importPages.Count, form._path); + PsMsgs.ImportPageNumberOutOfRange(pdfForm.PageNumber, importPages.Count, form._path); PdfPage importPage = importPages[pdfForm.PageNumber - 1]; // Import resources diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImage.FaxEncode.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImage.FaxEncode.cs index 593aeed7..742119c9 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImage.FaxEncode.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImage.FaxEncode.cs @@ -9,286 +9,286 @@ namespace PdfSharp.Pdf.Advanced { partial class PdfImage { - internal readonly static uint[] WhiteTerminatingCodes = - { - 0x35, 8, //00110101 // 0 - 0x07, 6, //000111 - 0x07, 4, //0111 - 0x08, 4, //1000 - 0x0b, 4, //1011 - 0x0c, 4, //1100 - 0x0e, 4, //1110 - 0x0f, 4, //1111 - 0x13, 5, //10011 - 0x14, 5, //10100 - 0x07, 5, //00111 // 10 - 0x08, 5, //01000 - 0x08, 6, //001000 - 0x03, 6, //000011 - 0x34, 6, //110100 - 0x35, 6, //110101 - 0x2a, 6, //101010 // 16 - 0x2b, 6, //101011 - 0x27, 7, //0100111 - 0x0c, 7, //0001100 - 0x08, 7, //0001000 // 20 - 0x17, 7, //0010111 - 0x03, 7, //0000011 - 0x04, 7, //0000100 - 0x28, 7, //0101000 - 0x2b, 7, //0101011 - 0x13, 7, //0010011 - 0x24, 7, //0100100 - 0x18, 7, //0011000 - 0x02, 8, //00000010 - 0x03, 8, //00000011 // 30 - 0x1a, 8, //00011010 - 0x1b, 8, //00011011 // 32 - 0x12, 8, //00010010 - 0x13, 8, //00010011 - 0x14, 8, //00010100 - 0x15, 8, //00010101 - 0x16, 8, //00010110 - 0x17, 8, //00010111 - 0x28, 8, //00101000 - 0x29, 8, //00101001 // 40 - 0x2a, 8, //00101010 - 0x2b, 8, //00101011 - 0x2c, 8, //00101100 - 0x2d, 8, //00101101 - 0x04, 8, //00000100 - 0x05, 8, //00000101 - 0x0a, 8, //00001010 - 0x0b, 8, //00001011 // 48 - 0x52, 8, //01010010 - 0x53, 8, //01010011 // 50 - 0x54, 8, //01010100 - 0x55, 8, //01010101 - 0x24, 8, //00100100 - 0x25, 8, //00100101 - 0x58, 8, //01011000 - 0x59, 8, //01011001 - 0x5a, 8, //01011010 - 0x5b, 8, //01011011 - 0x4a, 8, //01001010 - 0x4b, 8, //01001011 // 60 - 0x32, 8, //00110010 - 0x33, 8, //00110011 - 0x34, 8, //00110100 // 63 - }; - - internal readonly static uint[] BlackTerminatingCodes = - { - 0x37, 10, //0000110111 // 0 - 0x02, 3, //010 - 0x03, 2, //11 - 0x02, 2, //10 - 0x03, 3, //011 - 0x03, 4, //0011 - 0x02, 4, //0010 - 0x03, 5, //00011 - 0x05, 6, //000101 - 0x04, 6, //000100 - 0x04, 7, //0000100 - 0x05, 7, //0000101 - 0x07, 7, //0000111 - 0x04, 8, //00000100 - 0x07, 8, //00000111 - 0x18, 9, //000011000 - 0x17, 10, //0000010111 // 16 - 0x18, 10, //0000011000 - 0x08, 10, //0000001000 - 0x67, 11, //00001100111 - 0x68, 11, //00001101000 - 0x6c, 11, //00001101100 - 0x37, 11, //00000110111 - 0x28, 11, //00000101000 - 0x17, 11, //00000010111 - 0x18, 11, //00000011000 - 0xca, 12, //000011001010 - 0xcb, 12, //000011001011 - 0xcc, 12, //000011001100 - 0xcd, 12, //000011001101 - 0x68, 12, //000001101000 // 30 - 0x69, 12, //000001101001 - 0x6a, 12, //000001101010 // 32 - 0x6b, 12, //000001101011 - 0xd2, 12, //000011010010 - 0xd3, 12, //000011010011 - 0xd4, 12, //000011010100 - 0xd5, 12, //000011010101 - 0xd6, 12, //000011010110 - 0xd7, 12, //000011010111 - 0x6c, 12, //000001101100 - 0x6d, 12, //000001101101 - 0xda, 12, //000011011010 - 0xdb, 12, //000011011011 - 0x54, 12, //000001010100 - 0x55, 12, //000001010101 - 0x56, 12, //000001010110 - 0x57, 12, //000001010111 - 0x64, 12, //000001100100 // 48 - 0x65, 12, //000001100101 - 0x52, 12, //000001010010 - 0x53, 12, //000001010011 - 0x24, 12, //000000100100 - 0x37, 12, //000000110111 - 0x38, 12, //000000111000 - 0x27, 12, //000000100111 - 0x28, 12, //000000101000 - 0x58, 12, //000001011000 - 0x59, 12, //000001011001 - 0x2b, 12, //000000101011 - 0x2c, 12, //000000101100 - 0x5a, 12, //000001011010 - 0x66, 12, //000001100110 - 0x67, 12, //000001100111 // 63 - }; - - internal readonly static uint[] WhiteMakeUpCodes = - { - 0x1b, 5, //11011 64 // 0 - 0x12, 5, //10010 128 - 0x17, 6, //010111 192 - 0x37, 7, //0110111 256 - 0x36, 8, //00110110 320 - 0x37, 8, //00110111 384 - 0x64, 8, //01100100 448 - 0x65, 8, //01100101 512 - 0x68, 8, //01101000 576 - 0x67, 8, //01100111 640 - 0xcc, 9, //011001100 704 // 10 - 0xcd, 9, //011001101 768 - 0xd2, 9, //011010010 832 - 0xd3, 9, //011010011 896 - 0xd4, 9, //011010100 960 - 0xd5, 9, //011010101 1024 - 0xd6, 9, //011010110 1088 // 16 - 0xd7, 9, //011010111 1152 - 0xd8, 9, //011011000 1216 - 0xd9, 9, //011011001 1280 - 0xda, 9, //011011010 1344 - 0xdb, 9, //011011011 1408 - 0x98, 9, //010011000 1472 - 0x99, 9, //010011001 1536 - 0x9a, 9, //010011010 1600 - 0x18, 6, //011000 1664 - 0x9b, 9, //010011011 1728 - // Common codes for white and black: - 0x08, 11, //00000001000 1792 - 0x0c, 11, //00000001100 1856 - 0x0d, 11, //00000001101 1920 - 0x12, 12, //000000010010 1984 - 0x13, 12, //000000010011 2048 - 0x14, 12, //000000010100 2112 // 32 - 0x15, 12, //000000010101 2176 - 0x16, 12, //000000010110 2240 - 0x17, 12, //000000010111 2304 - 0x1c, 12, //000000011100 2368 - 0x1d, 12, //000000011101 2432 - 0x1e, 12, //000000011110 2496 - 0x1f, 12, //000000011111 2560 - 0x01, 12, //000000000001 EOL // 40 - }; + internal static readonly uint[] WhiteTerminatingCodes = + [ + 0x35, 8, //00110101 // 0 + 0x07, 6, //000111 + 0x07, 4, //0111 + 0x08, 4, //1000 + 0x0b, 4, //1011 + 0x0c, 4, //1100 + 0x0e, 4, //1110 + 0x0f, 4, //1111 + 0x13, 5, //10011 + 0x14, 5, //10100 + 0x07, 5, //00111 // 10 + 0x08, 5, //01000 + 0x08, 6, //001000 + 0x03, 6, //000011 + 0x34, 6, //110100 + 0x35, 6, //110101 + 0x2a, 6, //101010 // 16 + 0x2b, 6, //101011 + 0x27, 7, //0100111 + 0x0c, 7, //0001100 + 0x08, 7, //0001000 // 20 + 0x17, 7, //0010111 + 0x03, 7, //0000011 + 0x04, 7, //0000100 + 0x28, 7, //0101000 + 0x2b, 7, //0101011 + 0x13, 7, //0010011 + 0x24, 7, //0100100 + 0x18, 7, //0011000 + 0x02, 8, //00000010 + 0x03, 8, //00000011 // 30 + 0x1a, 8, //00011010 + 0x1b, 8, //00011011 // 32 + 0x12, 8, //00010010 + 0x13, 8, //00010011 + 0x14, 8, //00010100 + 0x15, 8, //00010101 + 0x16, 8, //00010110 + 0x17, 8, //00010111 + 0x28, 8, //00101000 + 0x29, 8, //00101001 // 40 + 0x2a, 8, //00101010 + 0x2b, 8, //00101011 + 0x2c, 8, //00101100 + 0x2d, 8, //00101101 + 0x04, 8, //00000100 + 0x05, 8, //00000101 + 0x0a, 8, //00001010 + 0x0b, 8, //00001011 // 48 + 0x52, 8, //01010010 + 0x53, 8, //01010011 // 50 + 0x54, 8, //01010100 + 0x55, 8, //01010101 + 0x24, 8, //00100100 + 0x25, 8, //00100101 + 0x58, 8, //01011000 + 0x59, 8, //01011001 + 0x5a, 8, //01011010 + 0x5b, 8, //01011011 + 0x4a, 8, //01001010 + 0x4b, 8, //01001011 // 60 + 0x32, 8, //00110010 + 0x33, 8, //00110011 + 0x34, 8 //00110100 // 63 + ]; + + internal static readonly uint[] BlackTerminatingCodes = + [ + 0x37, 10, //0000110111 // 0 + 0x02, 3, //010 + 0x03, 2, //11 + 0x02, 2, //10 + 0x03, 3, //011 + 0x03, 4, //0011 + 0x02, 4, //0010 + 0x03, 5, //00011 + 0x05, 6, //000101 + 0x04, 6, //000100 + 0x04, 7, //0000100 + 0x05, 7, //0000101 + 0x07, 7, //0000111 + 0x04, 8, //00000100 + 0x07, 8, //00000111 + 0x18, 9, //000011000 + 0x17, 10, //0000010111 // 16 + 0x18, 10, //0000011000 + 0x08, 10, //0000001000 + 0x67, 11, //00001100111 + 0x68, 11, //00001101000 + 0x6c, 11, //00001101100 + 0x37, 11, //00000110111 + 0x28, 11, //00000101000 + 0x17, 11, //00000010111 + 0x18, 11, //00000011000 + 0xca, 12, //000011001010 + 0xcb, 12, //000011001011 + 0xcc, 12, //000011001100 + 0xcd, 12, //000011001101 + 0x68, 12, //000001101000 // 30 + 0x69, 12, //000001101001 + 0x6a, 12, //000001101010 // 32 + 0x6b, 12, //000001101011 + 0xd2, 12, //000011010010 + 0xd3, 12, //000011010011 + 0xd4, 12, //000011010100 + 0xd5, 12, //000011010101 + 0xd6, 12, //000011010110 + 0xd7, 12, //000011010111 + 0x6c, 12, //000001101100 + 0x6d, 12, //000001101101 + 0xda, 12, //000011011010 + 0xdb, 12, //000011011011 + 0x54, 12, //000001010100 + 0x55, 12, //000001010101 + 0x56, 12, //000001010110 + 0x57, 12, //000001010111 + 0x64, 12, //000001100100 // 48 + 0x65, 12, //000001100101 + 0x52, 12, //000001010010 + 0x53, 12, //000001010011 + 0x24, 12, //000000100100 + 0x37, 12, //000000110111 + 0x38, 12, //000000111000 + 0x27, 12, //000000100111 + 0x28, 12, //000000101000 + 0x58, 12, //000001011000 + 0x59, 12, //000001011001 + 0x2b, 12, //000000101011 + 0x2c, 12, //000000101100 + 0x5a, 12, //000001011010 + 0x66, 12, //000001100110 + 0x67, 12 //000001100111 // 63 + ]; + + internal static readonly uint[] WhiteMakeUpCodes = + [ + 0x1b, 5, //11011 64 // 0 + 0x12, 5, //10010 128 + 0x17, 6, //010111 192 + 0x37, 7, //0110111 256 + 0x36, 8, //00110110 320 + 0x37, 8, //00110111 384 + 0x64, 8, //01100100 448 + 0x65, 8, //01100101 512 + 0x68, 8, //01101000 576 + 0x67, 8, //01100111 640 + 0xcc, 9, //011001100 704 // 10 + 0xcd, 9, //011001101 768 + 0xd2, 9, //011010010 832 + 0xd3, 9, //011010011 896 + 0xd4, 9, //011010100 960 + 0xd5, 9, //011010101 1024 + 0xd6, 9, //011010110 1088 // 16 + 0xd7, 9, //011010111 1152 + 0xd8, 9, //011011000 1216 + 0xd9, 9, //011011001 1280 + 0xda, 9, //011011010 1344 + 0xdb, 9, //011011011 1408 + 0x98, 9, //010011000 1472 + 0x99, 9, //010011001 1536 + 0x9a, 9, //010011010 1600 + 0x18, 6, //011000 1664 + 0x9b, 9, //010011011 1728 + // Common codes for white and black: + 0x08, 11, //00000001000 1792 + 0x0c, 11, //00000001100 1856 + 0x0d, 11, //00000001101 1920 + 0x12, 12, //000000010010 1984 + 0x13, 12, //000000010011 2048 + 0x14, 12, //000000010100 2112 // 32 + 0x15, 12, //000000010101 2176 + 0x16, 12, //000000010110 2240 + 0x17, 12, //000000010111 2304 + 0x1c, 12, //000000011100 2368 + 0x1d, 12, //000000011101 2432 + 0x1e, 12, //000000011110 2496 + 0x1f, 12, //000000011111 2560 + 0x01, 12 //000000000001 EOL // 40 + ]; internal readonly static uint[] BlackMakeUpCodes = - { - 0x0f, 10, //0000001111 64 // 0 - 0xc8, 12, //000011001000 128 - 0xc9, 12, //000011001001 192 - 0x5b, 12, //000001011011 256 - 0x33, 12, //000000110011 320 - 0x34, 12, //000000110100 384 - 0x35, 12, //000000110101 448 - 0x6c, 13, //0000001101100 512 - 0x6d, 13, //0000001101101 576 - 0x4a, 13, //0000001001010 640 - 0x4b, 13, //0000001001011 704 - 0x4c, 13, //0000001001100 768 - 0x4d, 13, //0000001001101 832 - 0x72, 13, //0000001110010 896 - 0x73, 13, //0000001110011 960 - 0x74, 13, //0000001110100 1024 - 0x75, 13, //0000001110101 1088 // 16 - 0x76, 13, //0000001110110 1152 - 0x77, 13, //0000001110111 1216 - 0x52, 13, //0000001010010 1280 - 0x53, 13, //0000001010011 1344 - 0x54, 13, //0000001010100 1408 - 0x55, 13, //0000001010101 1472 - 0x5a, 13, //0000001011010 1536 - 0x5b, 13, //0000001011011 1600 - 0x64, 13, //0000001100100 1664 - 0x65, 13, //0000001100101 1728 - // Common codes for white and black: - 0x08, 11, //00000001000 1792 - 0x0c, 11, //00000001100 1856 - 0x0d, 11, //00000001101 1920 - 0x12, 12, //000000010010 1984 - 0x13, 12, //000000010011 2048 - 0x14, 12, //000000010100 2112 // 32 - 0x15, 12, //000000010101 2176 - 0x16, 12, //000000010110 2240 - 0x17, 12, //000000010111 2304 - 0x1c, 12, //000000011100 2368 - 0x1d, 12, //000000011101 2432 - 0x1e, 12, //000000011110 2496 - 0x1f, 12, //000000011111 2560 - 0x01, 12, //000000000001 EOL // 40 - }; - - internal readonly static uint[] HorizontalCodes = { 0x1, 3 }; /* 001 */ - internal readonly static uint[] PassCodes = { 0x1, 4, }; /* 0001 */ - internal readonly static uint[] VerticalCodes = - { - 0x03, 7, /* 0000 011 */ - 0x03, 6, /* 0000 11 */ - 0x03, 3, /* 011 */ - 0x1, 1, /* 1 */ - 0x2, 3, /* 010 */ - 0x02, 6, /* 0000 10 */ - 0x02, 7, /* 0000 010 */ - }; - - readonly static uint[] _zeroRuns = - { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */ - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */ - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */ - }; - - readonly static uint[] _oneRuns = - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */ - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */ - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */ - 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */ - }; + [ + 0x0f, 10, //0000001111 64 // 0 + 0xc8, 12, //000011001000 128 + 0xc9, 12, //000011001001 192 + 0x5b, 12, //000001011011 256 + 0x33, 12, //000000110011 320 + 0x34, 12, //000000110100 384 + 0x35, 12, //000000110101 448 + 0x6c, 13, //0000001101100 512 + 0x6d, 13, //0000001101101 576 + 0x4a, 13, //0000001001010 640 + 0x4b, 13, //0000001001011 704 + 0x4c, 13, //0000001001100 768 + 0x4d, 13, //0000001001101 832 + 0x72, 13, //0000001110010 896 + 0x73, 13, //0000001110011 960 + 0x74, 13, //0000001110100 1024 + 0x75, 13, //0000001110101 1088 // 16 + 0x76, 13, //0000001110110 1152 + 0x77, 13, //0000001110111 1216 + 0x52, 13, //0000001010010 1280 + 0x53, 13, //0000001010011 1344 + 0x54, 13, //0000001010100 1408 + 0x55, 13, //0000001010101 1472 + 0x5a, 13, //0000001011010 1536 + 0x5b, 13, //0000001011011 1600 + 0x64, 13, //0000001100100 1664 + 0x65, 13, //0000001100101 1728 + // Common codes for white and black: + 0x08, 11, //00000001000 1792 + 0x0c, 11, //00000001100 1856 + 0x0d, 11, //00000001101 1920 + 0x12, 12, //000000010010 1984 + 0x13, 12, //000000010011 2048 + 0x14, 12, //000000010100 2112 // 32 + 0x15, 12, //000000010101 2176 + 0x16, 12, //000000010110 2240 + 0x17, 12, //000000010111 2304 + 0x1c, 12, //000000011100 2368 + 0x1d, 12, //000000011101 2432 + 0x1e, 12, //000000011110 2496 + 0x1f, 12, //000000011111 2560 + 0x01, 12 //000000000001 EOL // 40 + ]; + + internal static readonly uint[] HorizontalCodes = [0x1, 3]; /* 001 */ + internal static readonly uint[] PassCodes = [0x1, 4]; /* 0001 */ + internal static readonly uint[] VerticalCodes = + [ + 0x03, 7, /* 0000 011 */ + 0x03, 6, /* 0000 11 */ + 0x03, 3, /* 011 */ + 0x1, 1, /* 1 */ + 0x2, 3, /* 010 */ + 0x02, 6, /* 0000 10 */ + 0x02, 7 /* 0000 010 */ + ]; + + static readonly uint[] _zeroRuns = + [ + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 - 0xff */ + ]; + + static readonly uint[] _oneRuns = + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */ + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8 /* 0xf0 - 0xff */ + ]; /// /// Counts the consecutive one bits in an image line. @@ -406,8 +406,8 @@ static void FaxEncode2DRow(BitWriter writer, uint bytesFileOffset, byte[] imageB else { byte[] tmpImageBits = new byte[bytesPerLineBmp]; - for (int i = 0; i < bytesPerLineBmp; ++i) - tmpImageBits[i] = 255; + for (int idx = 0; idx < bytesPerLineBmp; idx++) + tmpImageBits[idx] = 255; readerReference = new BitReader(tmpImageBits, 0, width); } @@ -687,7 +687,7 @@ internal void FlushBuffer() /// /// Masks for n bits in a byte (with n = 0 through 8). /// - static readonly uint[] masks = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; + static readonly uint[] masks = [0, 1, 3, 7, 15, 31, 63, 127, 255]; /// /// Writes bits to the byte array. @@ -715,8 +715,8 @@ internal void WriteBits(uint value, uint bits) bits = bitsRemainder; goto SimulateRecursion; #else - WriteBits(value, bitsRemainder); - return; + WriteBits(value, bitsRemainder); + return; #endif } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImage.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImage.cs index 106bf78d..183bee83 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImage.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImage.cs @@ -8,8 +8,10 @@ using System.Windows.Media.Imaging; using System.Windows.Shapes; #endif +using Microsoft.Extensions.Logging; using PdfSharp.Drawing; using PdfSharp.Drawing.Internal; +using PdfSharp.Logging; using PdfSharp.Pdf.Filters; namespace PdfSharp.Pdf.Advanced @@ -317,7 +319,7 @@ void InitializeJpeg(PdfDocumentOptions options) if (_image._importedImage == null) _image._importedImage = i; } - + memory = _image.Memory; } else @@ -352,7 +354,7 @@ void InitializeJpeg(PdfDocumentOptions options) Debug.Assert(false, "Internal error? JPEG image, but file not read!"); } #endif -#if UWP +#if WUI memory = new MemoryStream(); ownMemory = true; #endif @@ -389,7 +391,7 @@ void InitializeJpeg(PdfDocumentOptions options) Elements["/Length"] = new PdfInteger(streamLength); Elements["/Filter"] = new PdfName("/DCTDecode"); } - if (_image.Interpolate) + if (_image.Interpolate && !_document.IsPdfA) // @@@PDF-A-Hack Elements[Keys.Interpolate] = PdfBoolean.True; Elements[Keys.Width] = new PdfInteger(_image.PixelWidth); Elements[Keys.Height] = new PdfInteger(_image.PixelHeight); @@ -634,21 +636,29 @@ void CreateIndexedMemoryBitmap(int bits, PdfDocumentOptions options) if (hasAlphaMask && pdfVersion >= 14) { - // The image provides an alpha mask (requires Arcrobat 5.0 or higher). - byte[] alphaMaskCompressed = fd.Encode(idb.AlphaMask, _document.Options.FlateEncodeMode); - var smask = new PdfDictionary(_document); - smask.Elements.SetName(Keys.Type, "/XObject"); - smask.Elements.SetName(Keys.Subtype, "/Image"); - - Owner.IrefTable.Add(smask); - smask.Stream = new PdfStream(alphaMaskCompressed, smask); - smask.Elements["/Length"] = new PdfInteger(alphaMaskCompressed.Length); - smask.Elements["/Filter"] = new PdfName("/FlateDecode"); - smask.Elements[Keys.Width] = new PdfInteger((int)ii.Width); - smask.Elements[Keys.Height] = new PdfInteger((int)ii.Height); - smask.Elements[Keys.BitsPerComponent] = new PdfInteger(8); - smask.Elements[Keys.ColorSpace] = new PdfName("/DeviceGray"); - Elements[Keys.SMask] = smask.Reference; + // #PDF-A + if (_document.IsPdfA) + { + PdfSharpLogHost.Logger.LogWarning("PDF/A: Alpha mask of PdfImage suppressed."); + } + else + { + // The image provides an alpha mask (requires Arcrobat 5.0 or higher). + byte[] alphaMaskCompressed = fd.Encode(idb.AlphaMask, _document.Options.FlateEncodeMode); + var smask = new PdfDictionary(_document); + smask.Elements.SetName(Keys.Type, "/XObject"); + smask.Elements.SetName(Keys.Subtype, "/Image"); + + Owner.IrefTable.Add(smask); + smask.Stream = new PdfStream(alphaMaskCompressed, smask); + smask.Elements["/Length"] = new PdfInteger(alphaMaskCompressed.Length); + smask.Elements["/Filter"] = new PdfName("/FlateDecode"); + smask.Elements[Keys.Width] = new PdfInteger((int)ii.Width); + smask.Elements[Keys.Height] = new PdfInteger((int)ii.Height); + smask.Elements[Keys.BitsPerComponent] = new PdfInteger(8); + smask.Elements[Keys.ColorSpace] = new PdfName("/DeviceGray"); + Elements[Keys.SMask] = smask.Reference; + } } byte[] imageDataCompressed = fd.Encode(idb.Data, _document.Options.FlateEncodeMode); @@ -750,7 +760,17 @@ void CreateIndexedMemoryBitmap(int bits, PdfDocumentOptions options) Elements[Keys.ColorSpace] = new PdfName("/DeviceGray"); } if (_image.Interpolate) - Elements[Keys.Interpolate] = PdfBoolean.True; + { + // #PDF-A + if (_document.IsPdfA) + { + PdfSharpLogHost.Logger.LogWarning("PDF/A: Image interpolation suppressed."); + } + else + { + Elements[Keys.Interpolate] = PdfBoolean.True; + } + } } } @@ -764,7 +784,7 @@ void CreateTrueColorMemoryBitmap(int components, int bits, bool hasAlpha, PdfDoc bool hasMask = idb.AlphaMaskLength > 0 || idb.BitmapMaskLength > 0; bool hasAlphaMask = idb.AlphaMaskLength > 0; - if (hasMask && idb.BitmapMask != null) + if (hasMask && idb.BitmapMask != null!) { // Monochrome mask is either sufficient or // provided for compatibility with older reader versions. @@ -785,21 +805,29 @@ void CreateTrueColorMemoryBitmap(int components, int bits, bool hasAlpha, PdfDoc } if (hasMask && hasAlphaMask && pdfVersion >= 14) { - // The image provides an alpha mask (requires Acrobat 5.0 or higher). - byte[] alphaMaskCompressed = fd.Encode(idb.AlphaMask, _document.Options.FlateEncodeMode); - var smask = new PdfDictionary(_document); - smask.Elements.SetName(Keys.Type, "/XObject"); - smask.Elements.SetName(Keys.Subtype, "/Image"); - - Owner.IrefTable.Add(smask); - smask.Stream = new PdfStream(alphaMaskCompressed, smask); - smask.Elements["/Length"] = new PdfInteger(alphaMaskCompressed.Length); - smask.Elements["/Filter"] = new PdfName("/FlateDecode"); - smask.Elements[Keys.Width] = new PdfInteger((int)ii.Width); - smask.Elements[Keys.Height] = new PdfInteger((int)ii.Height); - smask.Elements[Keys.BitsPerComponent] = new PdfInteger(8); - smask.Elements[Keys.ColorSpace] = new PdfName("/DeviceGray"); - Elements[Keys.SMask] = smask.Reference; + // #PDF-A + if (_document.IsPdfA) + { + PdfSharpLogHost.Logger.LogWarning("PDF/A: Alpha mask of PdfImage suppressed."); + } + else + { + // The image provides an alpha mask (requires Acrobat 5.0 or higher). + byte[] alphaMaskCompressed = fd.Encode(idb.AlphaMask, _document.Options.FlateEncodeMode); + var smask = new PdfDictionary(_document); + smask.Elements.SetName(Keys.Type, "/XObject"); + smask.Elements.SetName(Keys.Subtype, "/Image"); + + Owner.IrefTable.Add(smask); + smask.Stream = new PdfStream(alphaMaskCompressed, smask); + smask.Elements["/Length"] = new PdfInteger(alphaMaskCompressed.Length); + smask.Elements["/Filter"] = new PdfName("/FlateDecode"); + smask.Elements[Keys.Width] = new PdfInteger((int)ii.Width); + smask.Elements[Keys.Height] = new PdfInteger((int)ii.Height); + smask.Elements[Keys.BitsPerComponent] = new PdfInteger(8); + smask.Elements[Keys.ColorSpace] = new PdfName("/DeviceGray"); + Elements[Keys.SMask] = smask.Reference; + } } byte[] imageDataCompressed = fd.Encode(idb.Data, _document.Options.FlateEncodeMode); @@ -813,7 +841,17 @@ void CreateTrueColorMemoryBitmap(int components, int bits, bool hasAlpha, PdfDoc // Anything needed for CMYK? Do we have sample images? Elements[Keys.ColorSpace] = new PdfName(components == 1 ? "/DeviceGray" : "/DeviceRGB"); if (_image.Interpolate) - Elements[Keys.Interpolate] = PdfBoolean.True; + { + // #PDF-A + if (_document.IsPdfA) + { + PdfSharpLogHost.Logger.LogWarning("PDF/A: Image interpolation suppressed."); + } + else + { + Elements[Keys.Interpolate] = PdfBoolean.True; + } + } } #endif @@ -847,9 +885,9 @@ static int ReadDWord(ReadOnlySpan bytes, int offset) /// true (ARGB), false (RGB) void ReadTrueColorMemoryBitmap(int components, int bits, bool hasAlpha) { -//#if DEBUG_ -// image.image.Save("$$$.bmp", ImageFormat.Bmp); -//#endif + //#if DEBUG_ + // image.image.Save("$$$.bmp", ImageFormat.Bmp); + //#endif int pdfVersion = Owner.Version; var memory = new MemoryStream(); #if GDI @@ -866,7 +904,7 @@ void ReadTrueColorMemoryBitmap(int components, int bits, bool hasAlpha) Debug.Assert(streamLength > 0, "Bitmap image encoding failed."); if (streamLength > 0) { -#if !UWP +#if !WUI // Available with wrt, but not with wrt81. // Note: imageBits.Length can be larger than streamLength. Do not use these extra bytes! byte[] imageBits = memory.GetBuffer(); @@ -984,21 +1022,29 @@ void ReadTrueColorMemoryBitmap(int components, int bits, bool hasAlpha) } if (hasMask && hasAlphaMask && pdfVersion >= 14 && alphaMask != null) { - // The image provides an alpha mask (requires Arcrobat 5.0 or higher). - byte[] alphaMaskCompressed = fd.Encode(alphaMask, _document.Options.FlateEncodeMode); - var smask = new PdfDictionary(_document); - smask.Elements.SetName(Keys.Type, "/XObject"); - smask.Elements.SetName(Keys.Subtype, "/Image"); - - Owner.IrefTable.Add(smask); - smask.Stream = new PdfStream(alphaMaskCompressed, smask); - smask.Elements[PdfStream.Keys.Length] = new PdfInteger(alphaMaskCompressed.Length); - smask.Elements[PdfStream.Keys.Filter] = new PdfName("/FlateDecode"); - smask.Elements[Keys.Width] = new PdfInteger(width); - smask.Elements[Keys.Height] = new PdfInteger(height); - smask.Elements[Keys.BitsPerComponent] = new PdfInteger(8); - smask.Elements[Keys.ColorSpace] = new PdfName("/DeviceGray"); - Elements[Keys.SMask] = smask.Reference; + // #PDF-A + if (_document.IsPdfA) + { + PdfSharpLogHost.Logger.LogWarning("PDF/A: Alpha mask of PdfImage suppressed."); + } + else + { + // The image provides an alpha mask (requires Acrobat 5.0 or higher). + byte[] alphaMaskCompressed = fd.Encode(alphaMask, _document.Options.FlateEncodeMode); + var smask = new PdfDictionary(_document); + smask.Elements.SetName(Keys.Type, "/XObject"); + smask.Elements.SetName(Keys.Subtype, "/Image"); + + Owner.IrefTable.Add(smask); + smask.Stream = new PdfStream(alphaMaskCompressed, smask); + smask.Elements[PdfStream.Keys.Length] = new PdfInteger(alphaMaskCompressed.Length); + smask.Elements[PdfStream.Keys.Filter] = new PdfName("/FlateDecode"); + smask.Elements[Keys.Width] = new PdfInteger(width); + smask.Elements[Keys.Height] = new PdfInteger(height); + smask.Elements[Keys.BitsPerComponent] = new PdfInteger(8); + smask.Elements[Keys.ColorSpace] = new PdfName("/DeviceGray"); + Elements[Keys.SMask] = smask.Reference; + } } byte[] imageDataCompressed = fd.Encode(imageData, _document.Options.FlateEncodeMode); @@ -1012,7 +1058,17 @@ void ReadTrueColorMemoryBitmap(int components, int bits, bool hasAlpha) // Anything needed for CMYK? Do we have sample images? Elements[Keys.ColorSpace] = new PdfName("/DeviceRGB"); if (_image.Interpolate) - Elements[Keys.Interpolate] = PdfBoolean.True; + { + // #PDF-A + if (_document.IsPdfA) + { + PdfSharpLogHost.Logger.LogWarning("PDF/A: Image interpolation suppressed."); + } + else + { + Elements[Keys.Interpolate] = PdfBoolean.True; + } + } } } @@ -1059,7 +1115,7 @@ void ReadIndexedMemoryBitmap(int bits) byte[] imageBits = new byte[streamLength]; memory.Seek(0, SeekOrigin.Begin); memory.Read(imageBits, 0, streamLength); -#if !UWP +#if !WUI memory.Close(); #else memory.Dispose(); @@ -1082,11 +1138,11 @@ void ReadIndexedMemoryBitmap(int bits) throw new NotImplementedException("ReadIndexedMemoryBitmap: unsupported format"); } -//#if WPF -// // These two lines should be superfluous, otherwise an exception would have been thrown above. -// width = ReadDWord(imageBits, 18); -// height = ReadDWord(imageBits, 22); -//#endif + //#if WPF + // // These two lines should be superfluous, otherwise an exception would have been thrown above. + // width = ReadDWord(imageBits, 18); + // height = ReadDWord(imageBits, 22); + //#endif int fileBits = ReadWord(imageBits, 28); if (fileBits != bits) @@ -1413,7 +1469,17 @@ void ReadIndexedMemoryBitmap(int bits) Elements[Keys.ColorSpace] = new PdfName("/DeviceGray"); } if (_image.Interpolate) - Elements[Keys.Interpolate] = PdfBoolean.True; + { + // #PDF-A + if (_document.IsPdfA) + { + PdfSharpLogHost.Logger.LogWarning("PDF/A: Image interpolation suppressed."); + } + else + { + Elements[Keys.Interpolate] = PdfBoolean.True; + } + } } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImageTable.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImageTable.cs index 08018f9d..ae0b7ef5 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImageTable.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfImageTable.cs @@ -127,14 +127,18 @@ public ImageSelector(XImage image, PdfDocumentOptions options) // Use full path plus value of interpolate to identify an image. // Path must be at start because '*' identifies pseudo path names. // We assume a case-insensitive filesystem under Windows. +#if NET462 + Path = image._path.ToLowerInvariant() + '|' + image.Interpolate; +#else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) Path = image._path.ToLowerInvariant() + '|' + image.Interpolate; else Path = image._path + '|' + image.Interpolate; +#endif #else - // HACK: implement a way to identify images when they are reused - // TODO 4STLA Implementation that calculates MD5 hashes for images generated for the images can be found here: http://forum.pdfsharp.net/viewtopic.php?p=6959#p6959 - if (image._path == null!) + // HACK: implement a way to identify images when they are reused + // TODO 4STLA Implementation that calculates MD5 hashes for images generated for the images can be found here: http://forum.pdfsharp.net/viewtopic.php?p=6959#p6959 + if (image._path == null!) image._path = "*" + Guid.NewGuid().ToString("B"); #endif } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfInternals.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfInternals.cs index 01c7bcd2..dc6eea6b 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfInternals.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfInternals.cs @@ -244,8 +244,10 @@ public PdfObject[] GetClosure(PdfObject obj, int depth) public void WriteObject(Stream stream, PdfItem item) { // Never write an encrypted object - PdfWriter writer = new(stream, null); - writer.Options = PdfWriterOptions.OmitStream; + PdfWriter writer = new(stream, _document, null) + { + Options = PdfWriterOptions.OmitStream + }; item.WriteObject(writer); } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfNamedDestinationParameters.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfNamedDestinationParameters.cs index 42ed77f1..1f06400b 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfNamedDestinationParameters.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfNamedDestinationParameters.cs @@ -177,10 +177,6 @@ static string Format(string format, params double?[] values) /// /// Returns the parameters string for the named destination. /// - /// - public override string ToString() - { - return _parameters; - } + public override string ToString() => _parameters; } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfTilingPattern.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfTilingPattern.cs index 2a9d7c7f..2af54d94 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfTilingPattern.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfTilingPattern.cs @@ -32,7 +32,7 @@ public PdfTilingPattern(PdfDocument document) //public void SetupFromBrush(XLinearGradientBrush brush, XMatrix matrix) //{ // if (brush == null) - // throw new ArgumentNullException("brush"); + // throw new ArgumentNullException(nameof(brush)); // PdfShading shading = new PdfShading(document); // shading.SetupFromBrush(brush); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfType0Font.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfType0Font.cs index 63754670..74562ec0 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfType0Font.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Advanced/PdfType0Font.cs @@ -86,7 +86,7 @@ public PdfType0Font(PdfDocument document, string idName, byte[] fontData, bool v BaseFont = otDescriptor.FontName; // CID fonts are always embedded - if (!BaseFont.Contains("+")) // HACK in PdfType0Font + if (!BaseFont.Contains("+")) // H/ACK in PdfType0Font BaseFont = FontDescriptor.CreateEmbeddedFontSubsetName(BaseFont); FontDescriptor.FontName = BaseFont; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/IAnnotationAppearanceHandler.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/IAnnotationAppearanceHandler.cs new file mode 100644 index 00000000..e74aac4a --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Annotations/IAnnotationAppearanceHandler.cs @@ -0,0 +1,20 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Drawing; + +namespace PdfSharp.Pdf.Annotations +{ + /// + /// Draws the visual representation of an AcroForm element. + /// + public interface IAnnotationAppearanceHandler // kann man Annotation generell selber malen? + { + /// + /// Draws the visual representation of an AcroForm element. + /// + /// + /// + void DrawAppearance(XGraphics gfx, XRect rect); + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content.Objects/CObjects.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content.Objects/CObjects.cs index 351c2fcb..cbade410 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content.Objects/CObjects.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content.Objects/CObjects.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Text; +using PdfSharp.Internal; namespace PdfSharp.Pdf.Content.Objects // TODO: split into single files { @@ -557,7 +558,7 @@ public string Name if (String.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value)); if (value[0] != '/') - throw new ArgumentException(PSSR.NameMustStartWithSlash); + throw new ArgumentException(PsMsgs.NameMustStartWithSlash); _name = value; } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/CLexer.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/CLexer.cs index 27432c72..e3a5dcc3 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/CLexer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/CLexer.cs @@ -173,7 +173,7 @@ public CSymbol ScanName() if (ch == '#') { ScanNextChar(); -#if true + var newChar = (_currChar switch { >= '0' and <= '9' => _currChar - '0', @@ -195,21 +195,12 @@ static char LogError(char ch) PdfSharpLogHost.Logger.LogError("Illegal character {char} in hex string.", ch); return '\0'; } -#else - char[] hex = new char[2]; - hex[0] = _currChar; - hex[1] = _nextChar; - ScanNextChar(); - // TODO Check syntax - ch = (char)(ushort)Int32.Parse(new string(hex), NumberStyles.AllowHexSpecifier); - _currChar = ch; -#endif } } var name = Token; // Check token for UTF-8 encoding. - for (int idx = 0; idx < name.Length; ++idx) + for (int idx = 0; idx < name.Length; idx++) { // If the two top most significant bits are set this identifies a 2, 3, or 4 // byte UTF-8 encoding sequence. @@ -218,7 +209,7 @@ static char LogError(char ch) // Special characters in Name objects use UTF-8 encoding. var length = name.Length; var bytes = new byte[length]; - for (int idx2 = 0; idx2 < length; ++idx2) + for (int idx2 = 0; idx2 < length; idx2++) bytes[idx2] = (byte)name[idx2]; var decodedName = Encoding.UTF8.GetString(bytes); @@ -532,7 +523,7 @@ public CSymbol ScanLiteralString() else if (ch == '\xFF' && _nextChar == '\xFE') // Little endian? { // Is this possible? - Debug.Assert(false, "Found UTF-16 LE string. Please send us the PDF file and we will fix it (issues (at) pdfsharp.net)."); + Debug.Assert(false, "Found UTF-16LE string. Please send us the PDF file and we will fix it (issues (at) pdfsharp.net)."); return Symbol = CSymbol.None; } else diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/CParser.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/CParser.cs index 95ec75f5..fda05cde 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/CParser.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/CParser.cs @@ -213,7 +213,7 @@ CSymbol ReadSymbol(CSymbol symbol) { CSymbol current = _lexer.ScanNextToken(); if (symbol != current) - ContentReaderDiagnostics.ThrowContentReaderException(PSSR.UnexpectedToken(_lexer.Token)); + ContentReaderDiagnostics.ThrowContentReaderException(PsMsgs.UnexpectedToken(_lexer.Token)); return current; } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/ContentWriter.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/ContentWriter.cs index a8174fd5..a8821dae 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/ContentWriter.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Content/ContentWriter.cs @@ -75,7 +75,7 @@ public void WriteLineRaw(string rawString) //AppendBlank(rawString[0]); byte[] bytes = PdfEncoders.RawEncoding.GetBytes(rawString); _stream!.Write(bytes, 0, bytes.Length); - _stream!.Write(new byte[] { (byte)'\n' }, 0, 1); + _stream!.Write([(byte)'\n'], 0, 1); _lastCat = GetCategory((char)bytes[bytes.Length - 1]); } @@ -95,7 +95,7 @@ internal int Indent set => _indent = value; } protected int _indent = 2; - int _writeIndent = 0; + int _writeIndent = 0; /// /// Increases indent level. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/FlateDecode.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/FlateDecode.cs index 192f5d1d..fa2f113f 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/FlateDecode.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/FlateDecode.cs @@ -31,7 +31,7 @@ public byte[] Encode(byte[] data, PdfFlateEncodeMode mode) switch (mode) { case PdfFlateEncodeMode.BestCompression: -#if NET472 || NETSTANDARD2_0 +#if NET462 || NETSTANDARD2_0 level = CompressionLevel.Optimal; #else level = CompressionLevel.SmallestSize; @@ -112,8 +112,8 @@ public byte[] Encode(byte[] data, PdfFlateEncodeMode mode) using var zip = new DeflateStream(ms, level, true); zip.Write(data, 0, data.Length); // Flush has no effect on DeflateStream. - // Must call Close to ensure all bytes are written with .NET 4.7.2. - // Works with .NET 6 even without Close. But when adding support for .NET 4.7.2, we searched a while until we found that only the Close was needed. + // Must call Close to ensure all bytes are written with .NET 4.6.2. + // Works with .NET 6 even without Close. But when adding support for .NET 4.6.2, we searched a while until we found that only the Close was needed. zip.Close(); ms.Capacity = (int)ms.Length; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/LzwDecode.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/LzwDecode.cs index 11f0b762..04a6bf07 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/LzwDecode.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/LzwDecode.cs @@ -149,7 +149,7 @@ int NextCode } } - readonly int[] _andTable = { 511, 1023, 2047, 4095 }; + readonly int[] _andTable = [511, 1023, 2047, 4095]; byte[][] _stringTable = default!; byte[] _data = default!; int _tableIndex, _bitsToGet = 9; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/PngFilter.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/PngFilter.cs index 499a6b57..98626e56 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/PngFilter.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/PngFilter.cs @@ -16,7 +16,6 @@ static class PngFilter /// Bytes per pixel /// The input data /// The target array where the unfiltered data is stored - /// internal static void Unfilter(int stride, int bpp, byte[] inData, byte[] outData) { var prevRow = new byte[stride]; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/Lexer.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/Lexer.cs index d80e9ffb..6935f61d 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/Lexer.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/Lexer.cs @@ -227,7 +227,7 @@ static char LogError(char ch) var name = Token; // Check for UTF-8 encoding. - for (int idx = 0; idx < name.Length; ++idx) + for (int idx = 0; idx < name.Length; idx++) { // If the two top most significant bits are set this identifies a 2, 3, or 4 // byte UTF-8 encoding sequence. @@ -236,7 +236,7 @@ static char LogError(char ch) // Special characters in Name objects use UTF-8 encoding. var length = name.Length; var bytes = new byte[length]; - for (int idx2 = 0; idx2 < length; ++idx2) + for (int idx2 = 0; idx2 < length; idx2++) bytes[idx2] = (byte)name[idx2]; var decodedName = Encoding.UTF8.GetString(bytes); @@ -337,7 +337,7 @@ public Symbol ScanNumber(bool testForObjectReference) // Can the scanned number be the first part of an object reference? if (testForObjectReference && period is false && totalDigits <= maxDigitsForObjectNumber - && _currChar == Chars.SP) + && IsWhiteSpace(_currChar)) { #if DEBUG LexerHelper.TryCheckReferenceCount++; @@ -392,7 +392,7 @@ public Symbol ScanNumber(bool testForObjectReference) // Returns -1 if not an object reference. int TryReadReference() { - Debug.Assert(_currChar == Chars.SP); + Debug.Assert(IsWhiteSpace(_currChar)); // A Reference has the form "nnn ggg R". The original implementation of the parser used a // reduce/shift algorithm in the first place. But this case is the only one we need to @@ -404,12 +404,12 @@ int TryReadReference() SizeType position = Position; string token = _token.ToString(); - // Space expected. - if (_currChar != Chars.SP) + // White-space expected. + if (!IsWhiteSpace(_currChar)) goto NotAReference; - // Skip spaces. - while (_currChar == Chars.SP) + // Skip white-spaces. + while (IsWhiteSpace(_currChar)) ScanNextChar(true); // First digit of generation expected. @@ -428,12 +428,12 @@ int TryReadReference() ScanNextChar(true); } - // Space expected. - if (_currChar != Chars.SP) + // White-space expected. + if (!IsWhiteSpace(_currChar)) goto NotAReference; - // Skip spaces. - while (_currChar == Chars.SP) + // Skip white-spaces. + while (IsWhiteSpace(_currChar)) ScanNextChar(true); // "R" expected. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/Parser.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/Parser.cs index 0b88e539..c2b18952 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/Parser.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/Parser.cs @@ -334,7 +334,7 @@ PdfObject ReadObjectInternal(PdfObject? pdfObject, PdfObjectID objectID, bool in symbol = ScanNextToken(); } if (fromObjectStream is false && symbol != Symbol.EndObj) - ParserDiagnostics.ThrowParserException(PSSR.UnexpectedToken(_lexer.Token)); + ParserDiagnostics.ThrowParserException(PsMsgs.UnexpectedToken(_lexer.Token)); return pdfObject ?? NRT.ThrowOnNull(); } @@ -362,7 +362,8 @@ void ReadDictionaryStream(PdfDictionary dict, SuppressExceptions? suppressObject int streamLength = GetStreamLength(dict, suppressObjectOrderExceptions); if (SuppressExceptions.HasError(suppressObjectOrderExceptions)) return; - +//#warning THHO4STLA What to do if startPosition + streamLength is larger than length of stream? => Better not show "Please send us your PDF file" but another error message. +// TODO THHO4STLA What to do if startPosition + streamLength is larger than length of stream? => Better not show "Please send us your PDF file" but another error message. int retryCount = 0; RetryReadStream: // Step 3: We try to read the stream content. @@ -618,7 +619,7 @@ internal PdfDictionary ReadDictionary(PdfDictionary? dict, bool includeReference { var val = items[idx]; if (val is not PdfName) - ParserDiagnostics.ThrowParserException("Name expected."); // TODO L10N using PSSR. + ParserDiagnostics.ThrowParserException("Name expected."); // TODO L10N using PsMsgs string key = val.ToString() ?? NRT.ThrowOnNull(); val = items[idx + 1]; @@ -761,7 +762,7 @@ List ParseObject(Symbol stopSymbol) return items; } } - ParserDiagnostics.ThrowParserException("Unexpected end of file."); // TODO L10N using PSSR. + ParserDiagnostics.ThrowParserException("Unexpected end of file."); // TODO L10N using PsMsgs return items; // Dummy code. } @@ -859,7 +860,7 @@ int ReadInteger() if (symbol == Symbol.LongInteger) { // Should not happen or is a bug in the parser. - Debug.Assert(false, "ReadInteger founds a long integer."); + Debug.Assert(false, "ReadInteger found a long integer."); } if (symbol == Symbol.R) @@ -1095,7 +1096,7 @@ internal void ReadAllObjectStreamsAndTheirReferences() var objectStream = ReadObjectStream(objectStreamReference!, suppressObjectOrderExceptions); if (SuppressExceptions.HasError(suppressObjectOrderExceptions)) { - // Exceptional case: Reset objectStreamReference.Value back to null, because it could not be read properly and that may cause further errors. + // Exceptional case: Reset objectStreamReference. Value back to null, because it could not be read properly and that may cause further errors. objectStreamReference?.SetObject(null!); // Try it again in the next round. @@ -1183,7 +1184,7 @@ internal int[][] ReadObjectStreamHeader(int n, int first) _ = typeof(int); #endif int offset = ReadInteger() + first; // Calculate absolute offset. - header[idx] = new int[] { number, offset }; + header[idx] = [number, offset]; } return header; } @@ -1317,7 +1318,7 @@ internal PdfTrailer ReadTrailer() { // File is corrupt, but try to recover it by using the ID we found at the location. idToUse = idChecked; - //ParserDiagnostics.ThrowParserException("Invalid entry in XRef table, ID=" + id + ", Generation=" + generation + ", Position=" + position + ", ID of referenced object=" + idChecked + ", Generation of referenced object=" + generationChecked); // TODO L10N using PSSR. + //ParserDiagnostics.ThrowParserException("Invalid entry in XRef table, ID=" + id + ", Generation=" + generation + ", Position=" + position + ", ID of referenced object=" + idChecked + ", Generation of referenced object=" + generationChecked); // TODO L10N using PsMsgs } var message = Invariant( $"Object ID mismatch: Object at position {position} has ID '{id}' according to xref table and ID '{idChecked}' at its position of file."); @@ -1367,7 +1368,6 @@ internal PdfTrailer ReadTrailer() /// The generation from the XRef table. /// The identifier found in the PDF file. /// The generation found in the PDF file. - /// bool CheckXRefTableEntry(SizeType position, int id, int generation, out int idChecked, out int generationChecked) { SizeType origin = _lexer.Position; @@ -1383,7 +1383,7 @@ bool CheckXRefTableEntry(SizeType position, int id, int generation, out int idCh //string token = _lexer.Token; Symbol symbol = _lexer.ScanNextToken(false); if (symbol != Symbol.Obj) - ParserDiagnostics.ThrowParserException(Invariant($"Invalid entry in XRef table, ID={id} {generation} at position={position}")); // TODO L10N using PSSR. + ParserDiagnostics.ThrowParserException(Invariant($"Invalid entry in XRef table, ID={id} {generation} at position={position}")); // TODO L10N using PsMsgs if (id != idChecked || generation != generationChecked) return false; @@ -1394,7 +1394,7 @@ bool CheckXRefTableEntry(SizeType position, int id, int generation, out int idCh } catch (Exception ex) { - ParserDiagnostics.ThrowParserException("Invalid entry in XRef table, ID=" + id + ", Generation=" + generation + ", Position=" + position, ex); // TODO L10N using PSSR. + ParserDiagnostics.ThrowParserException("Invalid entry in XRef table, ID=" + id + ", Generation=" + generation + ", Position=" + position, ex); // TODO L10N using PsMsgs } finally { @@ -1443,13 +1443,35 @@ PdfTrailer ReadXRefStream(PdfCrossReferenceTable xrefTable) ReadStreamFromXRefTable(xrefStream); #endif - var iref = new PdfReference(xrefStream) + // Usually, the cross-reference stream and its reference have not been read yet. + if (!xrefTable.Contains(objectID)) { - ObjectID = objectID, - Value = xrefStream, - Position = xrefStart - }; - xrefTable.Add(iref); + var iref = new PdfReference(xrefStream) + { + ObjectID = objectID, + Value = xrefStream, + Position = xrefStart + }; + xrefTable.Add(iref); + } + // If a cross-reference stream B is referenced in the /Prev key of another cross-reference stream A dictionary, + // it doesn’t have to be referenced in the cross-reference stream A itself. + // But if it is, its reference has been already created, when reading all the cross-reference stream A + // references. So we reuse this reference here, but set the value, + // as the object itself has not been read, when reading the references. + else + { + var oldIref = xrefTable.AllReferences.First(x => x.ObjectID == objectID); + oldIref.Value = xrefStream; + + if (oldIref.Position != xrefStart) + { + PdfSharpLogHost.PdfReadingLogger.LogError("Object '{ObjectID}' already exists in xref table’s references, referring to position {Position}. The latter one referring to position {Position} is used. " + + "This should not occur. If somebody came here, please send us your PDF file so that we can fix it (issues (at) pdfsharp.net.", oldIref.ObjectID, oldIref.Position, xrefStart); + + oldIref.Position = xrefStart; + } + } Debug.Assert(xrefStream.Stream != null); //string sValue = new RawEncoding().GetString(xrefStream.Stream.UnfilteredValue,); @@ -1485,7 +1507,7 @@ PdfTrailer ReadXRefStream(PdfCrossReferenceTable xrefTable) // Setup with default values. subsectionCount = 1; subsections = new int[subsectionCount][]; - subsections[0] = new int[] { 0, size }; // HACK: What is size? Contradiction in PDF reference. + subsections[0] = [0, size]; // HACK: What is size? Contradiction in PDF reference. subsectionEntryCount = size; } else @@ -1496,14 +1518,14 @@ PdfTrailer ReadXRefStream(PdfCrossReferenceTable xrefTable) subsections = new int[subsectionCount][]; for (int idx = 0; idx < subsectionCount; idx++) { - subsections[idx] = new int[] { index.Elements.GetInteger(2 * idx), index.Elements.GetInteger(2 * idx + 1) }; + subsections[idx] = [index.Elements.GetInteger(2 * idx), index.Elements.GetInteger(2 * idx + 1)]; subsectionEntryCount += subsections[idx][1]; } } // W key. Debug.Assert(w?.Elements.Count == 3); - int[] wsize = { w.Elements.GetInteger(0), w.Elements.GetInteger(1), w.Elements.GetInteger(2) }; + int[] wsize = [w.Elements.GetInteger(0), w.Elements.GetInteger(1), w.Elements.GetInteger(2)]; int wsum = StreamHelper.WSize(wsize); #if DEBUG_ if (wsum * subsectionEntryCount != bytes.Length) @@ -1571,14 +1593,14 @@ PdfTrailer ReadXRefStream(PdfCrossReferenceTable xrefTable) //// Even if it is restricted, an object can exist in more than one subsection. //// (PDF Reference Implementation Notes 15). - SizeType position = item.Field2; + SizeType position = (SizeType)item.Field2; objectID = ReadObjectNumber(position); #if DEBUG_ if (objectID.ObjectNumber == 1074) _ = typeof(int); #endif Debug.Assert(objectID.GenerationNumber == item.Field3); - + // Ignore the latter one. if (!xrefTable.Contains(objectID)) { diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/PdfReader.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/PdfReader.cs index 95f4826e..45ab116b 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/PdfReader.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/PdfReader.cs @@ -282,7 +282,7 @@ PdfDocument OpenFromStream(Stream stream, string? password, PdfDocumentOpenMode _document = new PdfDocument(lexer); _document._state |= DocumentState.Imported; _document._openMode = openMode; - _document._fileSize = stream.Length; + _document.FileSize = stream.Length; // Get file version. byte[] header = new byte[1024]; @@ -290,7 +290,7 @@ PdfDocument OpenFromStream(Stream stream, string? password, PdfDocumentOpenMode var _ = stream.Read(header, 0, 1024); _document._version = GetPdfFileVersion(header); if (_document._version == 0) - throw new InvalidOperationException(PSSR.InvalidPdf); + throw new InvalidOperationException(PsMsgs.InvalidPdf); // Set IsUnderConstruction for IrefTable to true. This allows Parser.ParseObject() to insert placeholder references for objects not yet known. // This is necessary for documents with objects saved in objects streams, which are read and decoded after reading the file level PdfObjects. @@ -303,7 +303,7 @@ PdfDocument OpenFromStream(Stream stream, string? password, PdfDocumentOpenMode _document.Trailer = parser.ReadTrailer(); if (_document.Trailer == null!) ParserDiagnostics.ThrowParserException( - "Invalid PDF file: no trailer found."); // TODO L10N using PSSR. + "Invalid PDF file: no trailer found."); // TODO L10N using PsMsgs // References available by now: All references to file-level objects. // Reference.Values available by now: All trailers and cross-reference streams (which are not encrypted by definition). @@ -340,9 +340,9 @@ PdfDocument OpenFromStream(Stream stream, string? password, PdfDocumentOpenMode else { if (password == null) - throw new PdfReaderException(PSSR.PasswordRequired); + throw new PdfReaderException(PsMsgs.PasswordRequired); else - throw new PdfReaderException(PSSR.InvalidPassword); + throw new PdfReaderException(PsMsgs.InvalidPassword); } } else if (validity == PasswordValidity.UserPassword && openMode == PdfDocumentOpenMode.Modify) @@ -357,7 +357,7 @@ PdfDocument OpenFromStream(Stream stream, string? password, PdfDocumentOpenMode goto TryAgain; } else - throw new PdfReaderException(PSSR.OwnerPasswordRequired); + throw new PdfReaderException(PsMsgs.OwnerPasswordRequired); } // ReSharper restore RedundantIfElseBlock } @@ -498,7 +498,7 @@ void FinishItemReferences(PdfItem? pdfItem, PdfDocument document, HashSet finishedObjects) { - // Dictionary elements are modified inside loop. Avoid "Collection was modified; enumeration operation may not execute" error occuring in net 4.7.2. + // Dictionary elements are modified inside loop. Avoid "Collection was modified; enumeration operation may not execute" error occuring in net 4.6.2. // There is no way to access KeyValuePairs via index natively to use a for loop with. // Instead, enumerate Keys and get value via Elements[key], which shall be O(1). foreach (var key in dictionary.Elements.Keys) diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/PdfWriter.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/PdfWriter.cs index c67b7416..64f8e8ad 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/PdfWriter.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.IO/PdfWriter.cs @@ -5,6 +5,7 @@ using PdfSharp.Pdf.Advanced; using PdfSharp.Pdf.Security; using PdfSharp.Pdf.Internal; +using PdfSharp.Pdf.Signatures; namespace PdfSharp.Pdf.IO { @@ -13,26 +14,20 @@ namespace PdfSharp.Pdf.IO /// class PdfWriter { - public PdfWriter(Stream pdfStream, PdfStandardSecurityHandler? effectiveSecurityHandler) + public PdfWriter(Stream pdfStream, PdfDocument document, PdfStandardSecurityHandler? effectiveSecurityHandler) { - _stream = pdfStream; + _stream = pdfStream ?? throw new ArgumentNullException(nameof(pdfStream)); + _document = document ?? throw new ArgumentNullException(nameof(document)); EffectiveSecurityHandler = effectiveSecurityHandler; - //System.Xml.XmlTextWriter #if DEBUG - _layout = PdfWriterLayout.Verbose; + Layout = PdfWriterLayout.Verbose; #endif } public void Close(bool closeUnderlyingStream) { - if (_stream != null! && closeUnderlyingStream) - { -#if UWP - _stream.Dispose(); -#else + if (closeUnderlyingStream) _stream.Close(); -#endif - } _stream = null!; } @@ -43,19 +38,9 @@ public void Close(bool closeUnderlyingStream) /// /// Gets or sets the kind of layout. /// - public PdfWriterLayout Layout - { - get => _layout; - set => _layout = value; - } - PdfWriterLayout _layout; + public PdfWriterLayout Layout { get; set; } - public PdfWriterOptions Options - { - get => _options; - set => _options = value; - } - PdfWriterOptions _options; + public PdfWriterOptions Options { get; set; } // ----------------------------------------------------------- @@ -202,6 +187,23 @@ public void Write(PdfString value) _lastCat = CharCat.Delimiter; } + /// + /// Writes a signature placeholder hexadecimal string to the PDF stream. + /// + public void Write(PdfSignaturePlaceholderItem item, out SizeType startPosition, out SizeType endPosition) + { + WriteSeparator(CharCat.Delimiter); + + // ReSharper disable once RedundantCast + startPosition = (SizeType)Position; + // A PDF hex string with question marks '' + WriteRaw(item.ToString()); + // ReSharper disable once RedundantCast + endPosition = (SizeType)Position; + + _lastCat = CharCat.Delimiter; + } + /// /// Writes the specified value to the PDF stream. /// @@ -223,7 +225,7 @@ public void Write(PdfName value) // in any natural language, subject to the implementation limit on the length of a // name. - WriteSeparator(CharCat.Delimiter, '/'); + WriteSeparator(CharCat.Delimiter/*, '/'*/); string name = value.Value; Debug.Assert(name[0] == '/'); @@ -254,7 +256,6 @@ public void Write(PdfName value) { switch (ch) { - // TODO: is this all? case '%': case '/': case '<': @@ -292,7 +293,7 @@ public void Write(PdfLiteral value) public void Write(PdfRectangle rect) { const string format = Config.SignificantDecimalPlaces3; - WriteSeparator(CharCat.Delimiter, '/'); + WriteSeparator(CharCat.Delimiter/*, '/'*/); WriteRaw(PdfEncoders.Format("[{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "}]", rect.X1, rect.Y1, rect.X2, rect.Y2)); _lastCat = CharCat.Delimiter; } @@ -374,7 +375,7 @@ public void WriteBeginObject(PdfObject obj) _lastCat = CharCat.NewLine; } } - if (_layout == PdfWriterLayout.Verbose) + if (Layout == PdfWriterLayout.Verbose) IncreaseIndent(); } @@ -393,7 +394,7 @@ public void WriteEndObject() var indirect = value.IsIndirect; if (indirect) EffectiveSecurityHandler?.LeaveObject(); - if (_layout == PdfWriterLayout.Verbose) + if (Layout == PdfWriterLayout.Verbose) DecreaseIndent(); if (value is PdfArray) { @@ -427,7 +428,7 @@ public void WriteEndObject() { NewLine(); WriteRaw("endobj\n"); - if (_layout == PdfWriterLayout.Verbose) + if (Layout == PdfWriterLayout.Verbose) WriteRaw("%--------------------------------------------------------------------------------------------------\n"); } } @@ -437,7 +438,7 @@ public void WriteEndObject() /// public void WriteStream(PdfDictionary value, bool omitStream) { - var stackItem = _stack[_stack.Count - 1]; + var stackItem = _stack[^1]; Debug.Assert(stackItem.Object is PdfDictionary); Debug.Assert(stackItem.Object.IsIndirect); stackItem.HasStream = true; @@ -466,7 +467,7 @@ public void WriteRaw(string rawString) byte[] bytes = PdfEncoders.RawEncoding.GetBytes(rawString); _stream.Write(bytes, 0, bytes.Length); - _lastCat = GetCategory((char)bytes[bytes.Length - 1]); + _lastCat = GetCategory((char)bytes[^1]); } public void WriteRaw(char ch) @@ -483,20 +484,39 @@ public void Write(byte[] bytes) return; _stream.Write(bytes, 0, bytes.Length); - _lastCat = GetCategory((char)bytes[bytes.Length - 1]); + _lastCat = GetCategory((char)bytes[^1]); } void WriteObjectAddress(PdfObject value) { - if (_layout == PdfWriterLayout.Verbose) + if (Layout == PdfWriterLayout.Verbose) { string comment = value.Comment; if (!String.IsNullOrEmpty(comment)) comment = $" -- {value.Comment}"; - WriteRaw(Invariant($"{value.ObjectID.ObjectNumber} {value.ObjectID.GenerationNumber} obj % {value.GetType().FullName}{comment}\n")); + +#if DEBUG_ + if (_document is null) + _ = typeof(int); +#endif + // #PDF-A + if (_document.IsPdfA) + { + // Write full type name and comment in a separate line to be PDF-A conform. + WriteRaw(Invariant($"% {value.GetType().FullName}{comment}\n")); + WriteRaw(Invariant($"{value.ObjectID.ObjectNumber} {value.ObjectID.GenerationNumber} obj\n")); + } + else + { + // Write object number and full type name and comment in one line. + WriteRaw(Invariant($"{value.ObjectID.ObjectNumber} {value.ObjectID.GenerationNumber} obj % {value.GetType().FullName}{comment}\n")); + } } else + { + // Write object number only. WriteRaw(Invariant($"{value.ObjectID.ObjectNumber} {value.ObjectID.GenerationNumber} obj\n")); + } } public void WriteFileHeader(PdfDocument document) @@ -508,7 +528,7 @@ public void WriteFileHeader(PdfDocument document) header.Append(Invariant($"{version / 10}.{version % 10}\n%\xD3\xF4\xCC\xE1\n")); WriteRaw(header.ToString()); - if (_layout == PdfWriterLayout.Verbose) + if (Layout == PdfWriterLayout.Verbose) { WriteRaw($"% PDFsharp Version {PdfSharpProductVersionInformation.Version} (verbose mode)\n"); // Keep some space for later fix-up. @@ -532,7 +552,7 @@ public void WriteEof(PdfDocument document, SizeType startxref) WriteRaw(startxref.ToString(CultureInfo.InvariantCulture)); WriteRaw("\n%%EOF\n"); SizeType fileSize = (SizeType)_stream.Position; - if (_layout == PdfWriterLayout.Verbose) + if (Layout == PdfWriterLayout.Verbose) { TimeSpan duration = DateTime.Now - document._creation; @@ -590,12 +610,12 @@ void WriteIndent() WriteRaw(IndentBlanks); } - void WriteSeparator(CharCat cat, char ch = '\0') + void WriteSeparator(CharCat cat /*, char ch = '\0'*/) { switch (_lastCat) { case CharCat.NewLine: - if (_layout == PdfWriterLayout.Verbose) + if (Layout == PdfWriterLayout.Verbose) WriteIndent(); break; @@ -603,7 +623,7 @@ void WriteSeparator(CharCat cat, char ch = '\0') break; case CharCat.Character: - if (_layout == PdfWriterLayout.Verbose) + if (Layout == PdfWriterLayout.Verbose) { _stream.WriteByte((byte)' '); } @@ -645,21 +665,17 @@ enum CharCat internal Stream Stream => _stream; Stream _stream; + readonly PdfDocument _document; internal PdfStandardSecurityHandler? EffectiveSecurityHandler { get; set; } - class StackItem + class StackItem(PdfObject value) { - public StackItem(PdfObject value) - { - Object = value; - } - - public readonly PdfObject Object; + public readonly PdfObject Object = value; public bool HasStream; } - readonly List _stack = new(); + readonly List _stack = []; int _commentPosition; } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/ColorSpaceHelper.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/ColorSpaceHelper.cs index eac69a1b..62c82f92 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/ColorSpaceHelper.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/ColorSpaceHelper.cs @@ -25,10 +25,10 @@ public static XColor EnsureColorMode(PdfColorMode colorMode, XColor color) return color; #else if (colorMode == PdfColorMode.Rgb && color.ColorSpace != XColorSpace.Rgb) - throw new InvalidOperationException(PSSR.InappropriateColorSpace(colorMode, color.ColorSpace)); + throw new InvalidOperationException(PsMgs.InappropriateColorSpace(colorMode, color.ColorSpace)); if (colorMode == PdfColorMode.Cmyk && color.ColorSpace != XColorSpace.Cmyk) - throw new InvalidOperationException(PSSR.InappropriateColorSpace(colorMode, color.ColorSpace)); + throw new InvalidOperationException(PsMgs.InappropriateColorSpace(colorMode, color.ColorSpace)); #endif } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/DocEncoding.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/DocEncoding.cs index 49b7a15c..f517ad95 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/DocEncoding.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/DocEncoding.cs @@ -47,7 +47,8 @@ public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] /// /// Converts WinAnsi to DocEncode characters. Based upon PDF Reference 1.6. /// - static readonly byte[] AnsiToDoc = /*new byte[256]*/ { // keep brace to ensure that Visual Studio does not reformat + static readonly byte[] AnsiToDoc = /*new byte[256]*/ + [ // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf /* 00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 10 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, @@ -64,11 +65,12 @@ public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] /* c0 */ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, /* d0 */ 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, /* e0 */ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, - /* f0 */ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, - }; + /* f0 */ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF + ]; // TODO: use this table - static readonly char[] PdfDocToUnicode = { + static readonly char[] PdfDocToUnicode = + [ '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', '\x1E', '\x1F', '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', '\x28', '\x29', '\x2A', '\x2B', '\x2C', '\x2D', '\x2E', '\x2F', @@ -84,7 +86,7 @@ public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF', '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF', - '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF', - }; + '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF' + ]; } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/PdfEncoders.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/PdfEncoders.cs index 180af6ad..29049ffd 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/PdfEncoders.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Internal/PdfEncoders.cs @@ -1,9 +1,6 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. -using System; -using System.Diagnostics; -using System.Globalization; using System.Text; using Microsoft.Extensions.Logging; using PdfSharp.Drawing; @@ -36,22 +33,24 @@ public static class PdfEncoders /// public static Encoding WinAnsiEncoding { - get - { - if (_winAnsiEncoding == null) - { - //// Use own implementation because there is no ANSI encoding in .NET 6. - //_winAnsiEncoding = new AnsiEncoding(); -#if NET6_0_OR_GREATER___ // - // There is ANSI encoding available with .NET 6. Use it. - _winAnsiEncoding = CodePagesEncodingProvider.Instance.GetEncoding(1252)!; -#else - // StL 24-02-24: We are consistent on all platforms. - _winAnsiEncoding = new AnsiEncoding(); -#endif - } - return _winAnsiEncoding; - } + // We consistently use our own WinAnsiEncoding implementation in PDFsharp. + get => _winAnsiEncoding ??= new AnsiEncoding(); + // #DELETE + // { + // if (_winAnsiEncoding == null) + // { + // //// Use own implementation because there is no ANSI encoding in .NET 6. + // //_winAnsiEncoding = new AnsiEncoding(); + //#if NET6_0_OR_GREATER___ // + // // There is ANSI encoding available with .NET 6. Use it. + // _winAnsiEncoding = CodePagesEncodingProvider.Instance.GetEncoding(1252)!; + //#else + // // StL 24-02-24: We are consistent on all platforms. + // _winAnsiEncoding = new AnsiEncoding(); + //#endif + // } + // return _winAnsiEncoding; + // } } static Encoding? _winAnsiEncoding; @@ -393,8 +392,8 @@ public static byte[] FormatStringLiteral(byte[]? bytes, bool unicode, bool prefi /// /// Converts WinAnsi to DocEncode characters. Incomplete, just maps € and some other characters. /// - static byte[] docencode_______ = new byte[256] - { + static byte[] docencode_______ = + [ // TODO: ??? Note: See table in DocEncoding.cs. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, @@ -411,8 +410,8 @@ public static byte[] FormatStringLiteral(byte[]? bytes, bool unicode, bool prefi 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, - 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, - }; + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF + ]; //public static string DocEncode(string text, bool unicode)//, PdfStandardSecurityHandler securityHandler) //{ @@ -566,13 +565,13 @@ public static string ToString(XColor color, PdfColorMode colorMode) switch (colorMode) { case PdfColorMode.Rgb: - { - s_formatRGB ??= "{0:" + format + "} {1:" + format + "} {2:" + format + "}"; - // earlier: - // return String.Format(CultureInfo.InvariantCulture, "{0:" + format + "} {1:" + format + "} {2:" + format + "}", - // color.R / 255.0, color.G / 255.0, color.B / 255.0); - return String.Format(CultureInfo.InvariantCulture, s_formatRGB, color.R / 255.0, color.G / 255.0, color.B / 255.0); - } + { + s_formatRGB ??= "{0:" + format + "} {1:" + format + "} {2:" + format + "}"; + // earlier: + // return String.Format(CultureInfo.InvariantCulture, "{0:" + format + "} {1:" + format + "} {2:" + format + "}", + // color.R / 255.0, color.G / 255.0, color.B / 255.0); + return String.Format(CultureInfo.InvariantCulture, s_formatRGB, color.R / 255.0, color.G / 255.0, color.B / 255.0); + } case PdfColorMode.Cmyk: { @@ -585,7 +584,7 @@ public static string ToString(XColor color, PdfColorMode colorMode) } default: - Debug.Assert(false,"Cannot come here."); + Debug.Assert(false, "Cannot come here."); PdfSharpLogHost.Logger.LogError("Render a color with invalid color mode."); goto case PdfColorMode.Rgb; } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/PdfEncryptionBase.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/PdfEncryptionBase.cs similarity index 100% rename from src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/PdfEncryptionBase.cs rename to src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/PdfEncryptionBase.cs diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/PdfEncryptionV1To4.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/PdfEncryptionV1To4.cs similarity index 99% rename from src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/PdfEncryptionV1To4.cs rename to src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/PdfEncryptionV1To4.cs index 2bfa22cd..53003d41 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/PdfEncryptionV1To4.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/PdfEncryptionV1To4.cs @@ -182,7 +182,6 @@ public override void PrepareEncryptionForSaving(string userPassword, string owne /// /// Calculates the Revision from the set version and permission values. /// - /// int CalculateRevisionValue(int versionValue, uint permissionsValue) { var revisionValue = versionValue switch @@ -211,10 +210,10 @@ static byte[] PadPassword(string password) } static readonly byte[] PasswordPadding = // 32 bytes password padding defined by Adobe - { + [ 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, - 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A, - }; + 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A + ]; /// /// Computes the user and owner values. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/PdfEncryptionV5.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/PdfEncryptionV5.cs similarity index 96% rename from src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/PdfEncryptionV5.cs rename to src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/PdfEncryptionV5.cs index e6d424a1..7284a3b1 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/PdfEncryptionV5.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/PdfEncryptionV5.cs @@ -8,6 +8,7 @@ using PdfSharp.Internal; using PdfSharp.Pdf.Advanced; using PdfSharp.Pdf.Internal; +using System.Runtime.CompilerServices; namespace PdfSharp.Pdf.Security.Encryption { @@ -207,11 +208,11 @@ public override void PrepareEncryptionForSaving(string userPassword, string owne Debug.Assert(ownerPassword.Length > 0, "Empty owner password."); - var utf8userPassword = CreateUtf8Password(userPassword); - var utf8ownerPassword = CreateUtf8Password(ownerPassword); + var utf8UserPassword = CreateUtf8Password(userPassword); + var utf8OwnerPassword = CreateUtf8Password(ownerPassword); - var (userValueArray, userEValueArray) = ComputeUserValues(utf8userPassword); - var (ownerValueArray, ownerEValueArray) = ComputeOwnerValues(utf8ownerPassword, userValueArray); + var (userValueArray, userEValueArray) = ComputeUserValues(utf8UserPassword); + var (ownerValueArray, ownerEValueArray) = ComputeOwnerValues(utf8OwnerPassword, userValueArray); var userValue = PdfEncoders.RawEncoding.GetString(userValueArray, 0, userValueArray.Length); SecurityHandler.Elements.SetString(PdfStandardSecurityHandler.Keys.U, userValue); @@ -383,7 +384,7 @@ static byte[] ComputeHashInternal(byte[] password, byte[] salt, bool computeOwne using var aes = CreateAesForHashCryptography(); // Run steps (a)-(d) at least 64 times - // and afterwards as long as the last byte of e is greater than round number - 32. e) is f) this check only. + // and afterward as long as the last byte of e is greater than round number - 32. e) is f) this check only. for (var i = 0; i < 64 || lastByteOfE > i - 32; i++) { // a): Create k1 containing 64 repetitions of input and k @@ -393,28 +394,19 @@ static byte[] ComputeHashInternal(byte[] password, byte[] salt, bool computeOwne sequenceEnumerable = sequenceEnumerable.Concat(userValue!); var sequence = sequenceEnumerable.ToArray(); - IEnumerable k1Enumerable = Array.Empty(); + IEnumerable k1Enumerable = []; for (var j = 0; j < 64; j++) k1Enumerable = k1Enumerable.Concat(sequence); var k1 = k1Enumerable.ToArray(); // b): Create e: Encrypt k1 using AES-128 (CBC, no padding), with the first 16 bytes of k as the key and the second 16 bytes of k as the initialization vector. -#if NET6_0_OR_GREATER || true var aesKey = k[..16]; var aesIV = k[16..32]; -#else - var aesKey = k.Take(16).ToArray(); - var aesIV = k.Skip(16).Take(16).ToArray(); -#endif using var encryptor = aes.CreateEncryptor(aesKey, aesIV); var e = encryptor.TransformFinalBlock(k1, 0, k1.Length); // c) + d): Take the first 16 bytes of e as an unsigned big-endian integer. -#if NET6_0_OR_GREATER || true var e16 = e[..16]; -#else - var e16 = e.Take(16).ToArray(); -#endif #if NET6_0_OR_GREATER var e16BigEndianUnsigned = new BigInteger(e16, true, true); #else @@ -443,11 +435,7 @@ static byte[] ComputeHashInternal(byte[] password, byte[] salt, bool computeOwne } // The first 32 bytes of the final K are the output of the algorithm. -#if NET6_0_OR_GREATER || true var result = k[..32]; -#else - var result = k.Take(32).ToArray(); -#endif return result; } @@ -613,11 +601,7 @@ void RetrieveAndStoreEncryptionKey(byte[] utf8InputPassword, byte[] userValue, b /// static byte[] GetUserOwnerHashValue(byte[] userOwnerValue) { -#if NET6_0_OR_GREATER || true return userOwnerValue[..32]; -#else - return userOwnerValue.Take(32).ToArray(); -#endif } /// @@ -625,11 +609,7 @@ static byte[] GetUserOwnerHashValue(byte[] userOwnerValue) /// static byte[] GetUserOwnerValidationSalt(byte[] userOwnerValue) { -#if NET6_0_OR_GREATER || true return userOwnerValue[32..40]; -#else - return userOwnerValue.Skip(32).Take(8).ToArray(); -#endif } /// @@ -637,11 +617,7 @@ static byte[] GetUserOwnerValidationSalt(byte[] userOwnerValue) /// static byte[] GetUserOwnerKeySalt(byte[] userOwnerValue) { -#if NET6_0_OR_GREATER || true return userOwnerValue[40..48]; -#else - return userOwnerValue.Skip(40).Take(8).ToArray(); -#endif } /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/RC4.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/RC4.cs similarity index 100% rename from src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/RC4.cs rename to src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/RC4.cs diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/SASLprep.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/SASLprep.cs similarity index 100% rename from src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/Encryption/SASLprep.cs rename to src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security.Encryption/SASLprep.cs diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfCryptFilters.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfCryptFilters.cs index 45576d75..3ef3cd99 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfCryptFilters.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfCryptFilters.cs @@ -57,7 +57,7 @@ public bool RemoveCryptFilter(string name) /// public IEnumerable<(string Name, PdfCryptFilter CryptFilter)> GetCryptFilters() { - // Convert() modifies Elements. Avoid "Collection was modified; enumeration operation may not execute" error occuring in net 4.7.2. + // Convert() modifies Elements. Avoid "Collection was modified; enumeration operation may not execute" error occuring in net 4.6.2. // There is no way to access KeyValuePairs via index natively to use a for loop with. // Instead, enumerate Keys and get value via Elements[key], which shall be O(1). foreach (var key in Elements.Keys) @@ -97,9 +97,9 @@ PdfCryptFilter Convert(PdfItem pdfItem, string? keyToUpdate = null) var type = typeof(PdfCryptFilter); var ctorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - null, new[] { typeof(PdfDictionary) }, null); + null, [typeof(PdfDictionary)], null); Debug.Assert(ctorInfo != null, "No appropriate constructor found for type: " + type.Name); - var cryptFilter = (PdfCryptFilter)ctorInfo.Invoke(new object[] { pdfItem }); + var cryptFilter = (PdfCryptFilter)ctorInfo.Invoke([pdfItem]); if (keyToUpdate is not null) Elements[keyToUpdate] = cryptFilter; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfSecuritySettings.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfSecuritySettings.cs index 59bfb82f..ae93599f 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfSecuritySettings.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfSecuritySettings.cs @@ -64,7 +64,7 @@ internal bool CanSave(ref string message) { if (String.IsNullOrEmpty(effectiveSecurityHandler.UserPassword) && String.IsNullOrEmpty(effectiveSecurityHandler.OwnerPassword)) { - message = PSSR.UserOrOwnerPasswordRequired; + message = PsMsgs.UserOrOwnerPasswordRequired; return false; } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfStandardSecurityHandler.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfStandardSecurityHandler.cs index 992e88c3..c207f65c 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfStandardSecurityHandler.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/PdfStandardSecurityHandler.cs @@ -216,10 +216,12 @@ internal uint GetCorrectedPermissionsValue() // Correct permission bits. permissionsValue &= 0xfffffffc; // 1... 1111 1111 1100 - Bit 1 & 2 must be 0. #if true - permissionsValue |= 0x000002c0; // 0... 0010 1100 0000 - Bit 7 & 8 must be 1. Also, Bit 10 is no longer used and shall be always set to 1. + //permissionsValue |= 0x000002c0; // 0... 0010 1100 0000 - Bit 7 & 8 must be 1. Also, Bit 10 is no longer used and shall be always set to 1. + // Top-most bit not correct, but can also be read with PDFsharp up to 6.1.0. + permissionsValue |= 0x7ffff2c0; // 01.. 1110 1100 0000 - Bit 7 & 8 & 13 through 32 must be 1. Also, Bit 10 is no longer used and shall be always set to 1. #else // Include this later as files can not be read with PDFsharp up to 6.1.0. - permissionsValue |= 0xfffff2c0; // 0... 0010 1100 0000 - Bit 7 & 8 & 13 through 32 must be 1. Also, Bit 10 is no longer used and shall be always set to 1. + permissionsValue |= 0xfffff2c0; // 1... 1110 1100 0000 - Bit 7 & 8 & 13 through 32 must be 1. Also, Bit 10 is no longer used and shall be always set to 1. #endif return permissionsValue; @@ -276,7 +278,7 @@ public void DecryptObject(PdfObject value) // Cross-reference streams are not encrypted. if (value is PdfCrossReferenceStream) return; - + Debug.Assert(value.Reference != null); EnterObject(value.ObjectID); @@ -504,7 +506,7 @@ internal void PrepareForWriting() Elements[PdfSecurityHandler.Keys.Filter] = new PdfName("/Standard"); GetEncryption().PrepareEncryptionForSaving(UserPassword, OwnerPassword); - + // Load and prepare crypt filters. LoadCryptFilters(false); if (_loadedCryptFilters is not null) @@ -549,7 +551,7 @@ internal PdfEncryptionBase GetEncryption() } PdfEncryptionBase? _encryption; -#region CryptFilters + #region CryptFilters bool VersionSupportsCryptFilter() { return GetEncryption().VersionValue is 4 or 5; @@ -639,7 +641,7 @@ public void AddCryptFilter(string name, PdfCryptFilter cryptFilter, bool asDefau pdfCryptFilters = new PdfCryptFilters(); Elements.SetObject(PdfSecurityHandler.Keys.CF, pdfCryptFilters); } - + // Add CryptFilter. pdfCryptFilters.AddCryptFilter(name, cryptFilter); @@ -730,7 +732,7 @@ void SetCryptFilterAsDefaultInternal(string key, string? name) if (pdfCryptFilters?.GetCryptFilter(name) is null) throw TH.ArgumentException_UnknownCryptFilterSetToDefault(); } - + Elements.SetName(key, name); } @@ -771,7 +773,7 @@ CryptFilterBase GetDefaultCryptFilter(string cryptFilterName, CryptFilterBase @d if (string.IsNullOrEmpty(cryptFilterName)) return @default; - + var cryptFilter = _loadedCryptFilters?[cryptFilterName]; if (cryptFilter is null) @@ -788,7 +790,7 @@ public void ResetCryptFilter(PdfDictionary dictionary) dictionary.Elements.ArrayOrSingleItem.Remove(PdfStream.Keys.Filter, CryptFilterConstants.FilterValue); dictionary.Elements.ArrayOrSingleItem.Remove(PdfStream.Keys.DecodeParms, CryptFilterConstants.DecodeParmsPredicate); } - + void ResetCryptFilterEntriesInAllElements() { foreach (var iref in _document.IrefTable.AllReferences) @@ -817,7 +819,7 @@ public void SetCryptFilter(PdfDictionary dictionary, string cryptFilterName) ResetCryptFilter(dictionary); EnsureCryptFiltersAreSupported(); - + if (PdfName.AddSlash(cryptFilterName) != CryptFilterConstants.IdentityFilterValue) { var cryptFilters = (PdfCryptFilters?)Elements.GetValue(PdfSecurityHandler.Keys.CF); @@ -882,11 +884,11 @@ public void SetCryptFilter(PdfDictionary dictionary, string cryptFilterName) if (PdfEmbeddedFileStream.IsEmbeddedFile(dictionary)) return _defaultCryptFilterEmbeddedFileStreams; - + // Otherwise return the default crypt filter for streams. return _defaultCryptFilterStreams; } -#endregion CryptFilters + #endregion CryptFilters Dictionary? _loadedCryptFilters; CryptFilterBase? _defaultCryptFilterStreams; @@ -960,7 +962,7 @@ static class CryptFilterConstants public const string StandardFilterName = "StdCF"; } -#region Keys + #region Keys /// /// Predefined keys of this dictionary. /// @@ -1055,6 +1057,6 @@ static class CryptFilterConstants /// internal override DictionaryMeta Meta => Keys.Meta; -#endregion + #endregion } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/enums/PdfUserAccessPermission.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/enums/PdfUserAccessPermission.cs index a3e99bfa..9c3f4324 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/enums/PdfUserAccessPermission.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Security/enums/PdfUserAccessPermission.cs @@ -7,41 +7,42 @@ namespace PdfSharp.Pdf.Security /// Specifies which operations are permitted when the document is opened with user access. /// [Flags] - enum PdfUserAccessPermission + enum PdfUserAccessPermission : uint { /// /// Permits everything. This is the default value. /// - PermitAll = -3, // = 0xFFFFFFFC, + //PermitAll = -3, // = 0xFFFFFFFC, + PermitAll = 0xFFFF_FFFC, // Bit 1–2 Reserved. Must be zero (0). // Bit 3 (Security handlers of revision 2) Print the document. // (Security handlers of revision 3 or greater) Print the document (possibly not at the highest // quality level, depending on whether bit 12 is also set). - PermitPrint = 0x00000004, //1 << (3 - 1), + PermitPrint = 0x0000_0004, // 1 << (3 - 1), // Bit 4 Modify the contents of the document by operations other than // those controlled by bits 6, 9, and 11. - PermitModifyDocument = 0x00000008, //1 << (4 - 1), + PermitModifyDocument = 0x0000_0008, // 1 << (4 - 1), // Bit 5 Copy or otherwise extract text and graphics from the // document. However, for the limited purpose of providing this content to assistive technology, // a PDF reader should behave as if this bit was set to 1. // NOTE For accessibility, ISO 32000-1 had this option restricted by bit 10, // but that exception has been deprecated in PDF 2.0. - PermitExtractContent = 0x00000010, //1 << (5 - 1), + PermitExtractContent = 0x0000_0010, // 1 << (5 - 1), // Bit 6 Add or modify text annotations, fill in interactive form fields, and, // if bit 4 is also set, create or modify interactive form fields (including // signature fields). - PermitAnnotations = 0x00000020, //1 << (6 - 1), + PermitAnnotations = 0x0000_0020, // 1 << (6 - 1), // Bit 7–8 Reserved. Must be 1. // 9 (Security handlers of revision 3 or greater) Fill in existing interactive form fields (including // signature fields), even if bit 6 is clear. - PermitFormsFill = 0x00000100, //1 << (9 - 1), + PermitFormsFill = 0x0000_0100, // 1 << (9 - 1), // Bit 10 Not used. // This bit was previously used to determine whether content could be extracted for the @@ -52,13 +53,13 @@ enum PdfUserAccessPermission // Bit 11 (Security handlers of revision 3 or greater) Assemble the document (insert, rotate, or delete // pages and create document outline items or thumbnail images), even if bit 4 // is clear. - PermitAssembleDocument = 0x00000400, //1 << (11 - 1), + PermitAssembleDocument = 0x0000_0400, // 1 << (11 - 1), // Bit 12 (Security handlers of revision 3 or greater) Print the document to a representation from // which a faithful digital copy of the PDF content could be generated, based on an implementation-dependent algorithm. // When this bit is clear (and bit 3 is set), printing shall be limited to a low-level // representation of the appearance, possibly of degraded quality. - PermitFullQualityPrint = 0x00000800, //1 << (12 - 1), + PermitFullQualityPrint = 0x0000_0800, // 1 << (12 - 1), // Bit 13–32 (Security handlers of revision 3 or greater) Reserved. Must be 1. } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/DefaultSignatureAppearanceHandler.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/DefaultSignatureAppearanceHandler.cs new file mode 100644 index 00000000..e46e9f1e --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/DefaultSignatureAppearanceHandler.cs @@ -0,0 +1,38 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Drawing; +using PdfSharp.Drawing.Layout; +using PdfSharp.Pdf.Annotations; + +namespace PdfSharp.Pdf.Signatures +{ + class DefaultSignatureAppearanceHandler : IAnnotationAppearanceHandler + { + public string? Location { get; set; } + + public string? Reason { get; set; } + + public string? Signer { get; set; } + + public void DrawAppearance(XGraphics gfx, XRect rect) + { + var defaultText = $"Signed by: {Signer}\nLocation: {Location}\nReason: {Reason}\nDate: {DateTime.Now}"; + + var font = new XFont("Verdana", 7, XFontStyleEx.Regular); + + var txtFormat = new XTextFormatter(gfx); + + var currentPosition = new XPoint(0, 0); + double width = rect.Width; + double height = rect.Height; + + // Leave 5% space on each side. + txtFormat.DrawString(defaultText, font, + new XSolidBrush(XColor.FromKnownColor(XKnownColor.Black)), + new XRect(currentPosition.X + width * .05, currentPosition.Y + height * .05, + width * .9, height * .9), + XStringFormats.TopLeft); + } + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/DigitalSignatureOptions.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/DigitalSignatureOptions.cs new file mode 100644 index 00000000..c51bc051 --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/DigitalSignatureOptions.cs @@ -0,0 +1,49 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Drawing; +using PdfSharp.Pdf.Annotations; + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// Sets the options of the DigitalSignatureHandler class. + /// + public class DigitalSignatureOptions() + { + /// + /// Gets or sets the appearance handler that draws the visual representation of the signature in the PDF. + /// + public IAnnotationAppearanceHandler? AppearanceHandler { get; init; } + + /// + /// Gets or sets a string associated with the signature. + /// + public string ContactInfo { get; init; } = ""; + + /// + /// Gets or sets a string associated with the signature. + /// + public string Location { get; init; } = ""; + + /// + /// Gets or sets a string associated with the signature. + /// + public string Reason { get; init; } = ""; + + /// + /// Gets or sets the name of the application used to sign the document. + /// + public string AppName { get; init; } = "PDFsharp http://www.pdfsharp.net"; + + /// + /// The location of the visual representation on the selected page. + /// + public XRect Rectangle { get; init; } + + /// + /// The page index, zero-based, of the page showing the signature. + /// + public int PageIndex { get; init; } + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfArrayWithPadding.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfArrayWithPadding.cs new file mode 100644 index 00000000..8c4af860 --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfArrayWithPadding.cs @@ -0,0 +1,35 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Pdf.IO; + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// Internal PDF array used for digital signatures. + /// For digital signatures, we have to add an array with four integers, + /// but at the time we add the array we cannot yet determine + /// how many digits those integers will have. + /// + /// The document. + /// The count of spaces added after the array. + /// The contents of the array. + sealed class PdfArrayWithPadding(PdfDocument document, int paddingRight, params PdfItem[] items) + : PdfArray(document, items) + { + public int PaddingRight { get; init; } = paddingRight; + + internal override void WriteObject(PdfWriter writer) + { + StartPosition = writer.Position; + + base.WriteObject(writer); + writer.WriteRaw(new String(' ', PaddingRight)); + } + + /// + /// Position of the first byte of this string in PdfWriter’s stream. + /// + public SizeType StartPosition { get; internal set; } + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignature.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignature.cs new file mode 100644 index 00000000..dc384b1f --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignature.cs @@ -0,0 +1,33 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// The signature dictionary added to a PDF file when it is to be signed. + /// + public sealed class PdfSignature : PdfDictionary + { + /// + /// Initializes a new instance of the class. + /// + public PdfSignature() + { } + + /// + /// Initializes a new instance of the class. + /// + public PdfSignature(PdfDocument dict) : base(dict) + { } + + ///// + ///// Encrypts the given bytes. Returns true if the crypt filter encrypted the bytes, or false, if the security handler shall do it. + ///// + //internal abstract bool EncryptForEnteredObject(ref byte[] bytes); + + ///// + ///// Decrypts the given bytes. Returns true if the crypt filter decrypted the bytes, or false, if the security handler shall do it. + ///// + //internal abstract bool DecryptForEnteredObject(ref byte[] bytes); + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignatureHandler.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignatureHandler.cs new file mode 100644 index 00000000..85f7cba6 --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignatureHandler.cs @@ -0,0 +1,243 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +#if !NET6_0_OR_GREATER +using System.Text; +#endif +using PdfSharp.Pdf.AcroForms; +using PdfSharp.Pdf.Advanced; +using PdfSharp.Pdf.Internal; +using PdfSharp.Pdf.IO; + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// PdfDocument signature handler. + /// Attaches a PKCS#7 signature digest to PdfDocument. + /// + // DigitalSignatureHandler rename file + public class DigitalSignatureHandler + { + /// + /// Space ... big enough reserved space to replace ByteRange placeholder [0 0 0 0] with the actual computed value of the byte range to sign + /// Worst case: signature dictionary is near the end of an 10 GB PDF file. + /// + const int ByteRangePaddingLength = 36; // = "[0 9999999999 9999999999 9999999999]".Length + + DigitalSignatureHandler(PdfDocument document, IDigitalSigner signer, DigitalSignatureOptions options) + { + Document = document ?? throw new ArgumentNullException(nameof(document)); + Signer = signer ?? throw new ArgumentNullException(nameof(signer)); + Options = options ?? throw new ArgumentNullException(nameof(options)); + + if (options.PageIndex < 0) + { + throw new ArgumentOutOfRangeException(nameof(options.PageIndex), + "Signature page index cannot be negative."); + } + + // TODO in document: Set document version depending on digest type from options. + } + + /// + /// Gets or creates the digital signature handler for the specified document. + /// + public static DigitalSignatureHandler ForDocument(PdfDocument document, IDigitalSigner signer, DigitalSignatureOptions options) + { + return document._digitalSignatureHandler ??= new(document, signer, options); + } + + + /// + /// Gets the PDF document the signature will be attached to. + /// + public PdfDocument Document { get; init; } + + /// + /// Gets the options for the digital signature. + /// + public DigitalSignatureOptions Options { get; init; } + + IDigitalSigner Signer { get; init; } + + internal async Task ComputeSignatureAndRange(PdfWriter writer) + { + var (rangedStreamToSign, byteRangeArray) = GetRangeToSignAndByteRangeArray(writer.Stream); + + Debug.Assert(_signatureFieldByteRangePdfArray != null); + writer.Stream.Position = _signatureFieldByteRangePdfArray.StartPosition; + byteRangeArray.WriteObject(writer); + + // Computing signature from document’s digest. + var signature = await Signer.GetSignatureAsync(rangedStreamToSign).ConfigureAwait(false); + + Debug.Assert(_placeholderItem != null); + int expectedLength = _placeholderItem.Size; + if (signature.Length > expectedLength) + throw new Exception($"The actual digest length {signature.Length} is larger than the approximation made {expectedLength}. Not enough room in the placeholder to fit the signature."); + + // Write the signature at the space reserved by placeholder item. + writer.Stream.Position = _placeholderItem.StartPosition; + + // When the signature includes a timestamp, the exact length is unknown until the signature is definitely calculated. + // Therefore, we write the angle brackets here and override the placeholder white spaces. + writer.WriteRaw('<'); + writer.Write(PdfEncoders.RawEncoding.GetBytes(FormatHex(signature))); + + // Fill up the allocated placeholder. Signature is sometimes considered invalid if there are spaces after '>'. + for (int x = signature.Length; x < expectedLength; ++x) + writer.WriteRaw("00"); + + writer.WriteRaw('>'); + } + + string FormatHex(byte[] bytes) // ...use RawEncoder + { +#if NET6_0_OR_GREATER + return Convert.ToHexString(bytes); +#else + var result = new StringBuilder(); + + for (int idx = 0; idx < bytes.Length; idx++) + result.AppendFormat("{0:X2}", bytes[idx]); + + return result.ToString(); +#endif + } + + /// + /// Get the bytes ranges to sign. + /// As recommended in PDF specs, whole document will be signed, except for the hexadecimal signature token value in the /Contents entry. + /// Example: '/Contents <aaaaa111111>' => '<aaaaa111111>' will be excluded from the bytes to sign. + /// + /// + (RangedStream rangedStream, PdfArray byteRangeArray) GetRangeToSignAndByteRangeArray(Stream stream) + { + Debug.Assert( _placeholderItem !=null, nameof(_placeholderItem) + " must not be null here."); + + SizeType firstRangeOffset = 0; + SizeType firstRangeLength = _placeholderItem.StartPosition; + SizeType secondRangeOffset = _placeholderItem.EndPosition; + SizeType secondRangeLength = stream.Length - _placeholderItem.EndPosition; + + var byteRangeArray = new PdfArray(); + byteRangeArray.Elements.Add(new PdfLongInteger(firstRangeOffset)); + byteRangeArray.Elements.Add(new PdfLongInteger(firstRangeLength)); + byteRangeArray.Elements.Add(new PdfLongInteger(secondRangeOffset)); + byteRangeArray.Elements.Add(new PdfLongInteger(secondRangeLength)); + + var rangedStream = new RangedStream(stream, + [ + new(firstRangeOffset, firstRangeLength), + new(secondRangeOffset, secondRangeLength) + ]); + + return (rangedStream, byteRangeArray); + } + + /// + /// Adds the PDF objects required for a digital signature. + /// + /// + internal async Task AddSignatureComponentsAsync() + { + if (Options.PageIndex >= Document.PageCount) + throw new ArgumentOutOfRangeException($"Signature page doesn't exist, specified page was {Options.PageIndex + 1} but document has only {Document.PageCount} page(s)."); + + var signatureSize = await Signer.GetSignatureSizeAsync().ConfigureAwait(false); + _placeholderItem = new(signatureSize); + _signatureFieldByteRangePdfArray = new PdfArrayWithPadding(Document, ByteRangePaddingLength, new PdfLongInteger(0), new PdfLongInteger(0), new PdfLongInteger(0), new PdfLongInteger(0)); + + var signatureDictionary = GetSignatureDictionary(_placeholderItem, _signatureFieldByteRangePdfArray); + var signatureField = GetSignatureField(signatureDictionary); + + var annotations = Document.Pages[Options.PageIndex].Elements.GetArray(PdfPage.Keys.Annots); + if (annotations == null) + Document.Pages[Options.PageIndex].Elements.Add(PdfPage.Keys.Annots, new PdfArray(Document, signatureField)); + else + annotations.Elements.Add(signatureField); + + // acroform + + var catalog = Document.Catalog; + + if (catalog.Elements.GetObject(PdfCatalog.Keys.AcroForm) == null) + catalog.Elements.Add(PdfCatalog.Keys.AcroForm, new PdfAcroForm(Document)); + + if (!catalog.AcroForm.Elements.ContainsKey(PdfAcroForm.Keys.SigFlags)) + catalog.AcroForm.Elements.Add(PdfAcroForm.Keys.SigFlags, new PdfInteger(3)); + else + { + var sigFlagVersion = catalog.AcroForm.Elements.GetInteger(PdfAcroForm.Keys.SigFlags); + if (sigFlagVersion < 3) + catalog.AcroForm.Elements.SetInteger(PdfAcroForm.Keys.SigFlags, 3); + } + + if (catalog.AcroForm.Elements.GetValue(PdfAcroForm.Keys.Fields) == null) + catalog.AcroForm.Elements.SetValue(PdfAcroForm.Keys.Fields, new PdfAcroField.PdfAcroFieldCollection(new PdfArray())); + catalog.AcroForm.Fields.Elements.Add(signatureField); + } + + PdfSignatureField GetSignatureField(PdfDictionary signatureDic) // PdfSignatureDictionary + { + var signatureField = new PdfSignatureField(Document); + + signatureField.Elements.Add(PdfAcroField.Keys.V, signatureDic); + + // Annotation keys. + signatureField.Elements.Add(PdfAcroField.Keys.FT, new PdfName("/Sig")); + signatureField.Elements.Add(PdfAcroField.Keys.T, new PdfString("Signature1")); // TODO If already exists, will it cause error? implement a name chooser if yes. + signatureField.Elements.Add(PdfAcroField.Keys.Ff, new PdfInteger(132)); + signatureField.Elements.Add(PdfAcroField.Keys.DR, new PdfDictionary()); + signatureField.Elements.Add(PdfSignatureField.Keys.Type, new PdfName("/Annot")); + signatureField.Elements.Add("/Subtype", new PdfName("/Widget")); + signatureField.Elements.Add("/P", Document.Pages[Options.PageIndex]); + + signatureField.Elements.Add("/Rect", new PdfRectangle(Options.Rectangle)); + + signatureField.CustomAppearanceHandler = Options.AppearanceHandler ?? new DefaultSignatureAppearanceHandler() + { + Location = Options.Location, + Reason = Options.Reason, + Signer = Signer.CertificateName + }; + // TODO Call RenderCustomAppearance(); here. + signatureField.PrepareForSave(); // TODO PdfSignatureField.PrepareForSave() is not triggered automatically so let's call it manually from here, but it would be better to be called automatically. + + Document.Internals.AddObject(signatureField); + + return signatureField; + } + + PdfDictionary GetSignatureDictionary(PdfSignaturePlaceholderItem contents, PdfArray byteRange) + { + PdfSignature signatureDic = new(Document); + + signatureDic.Elements.Add(PdfSignatureField.Keys.Type, new PdfName("/Sig")); + signatureDic.Elements.Add(PdfSignatureField.Keys.Filter, new PdfName("/Adobe.PPKLite")); + signatureDic.Elements.Add(PdfSignatureField.Keys.SubFilter, new PdfName("/adbe.pkcs7.detached")); + signatureDic.Elements.Add(PdfSignatureField.Keys.M, new PdfDate(DateTime.Now)); + + signatureDic.Elements.Add(PdfSignatureField.Keys.Contents, contents); + signatureDic.Elements.Add(PdfSignatureField.Keys.ByteRange, byteRange); + signatureDic.Elements.Add(PdfSignatureField.Keys.Reason, new PdfString(Options.Reason)); + signatureDic.Elements.Add(PdfSignatureField.Keys.Location, new PdfString(Options.Location)); + + var properties = new PdfDictionary(Document); + signatureDic.Elements.Add("/Prop_Build", properties); + var propertyItems = new PdfDictionary(Document); + properties.Elements.Add("/App", propertyItems); + propertyItems.Elements.Add("/Name", + String.IsNullOrWhiteSpace(Options.AppName) ? + new PdfName("/PDFsharp http://www.pdfsharp.net") : + new PdfName($"/{Options.AppName}")); + + Document.Internals.AddObject(signatureDic); + + return signatureDic; + } + + PdfSignaturePlaceholderItem? _placeholderItem; + PdfArrayWithPadding? _signatureFieldByteRangePdfArray; + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignaturePlaceholderItem.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignaturePlaceholderItem.cs new file mode 100644 index 00000000..7f0d2ab2 --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/PdfSignaturePlaceholderItem.cs @@ -0,0 +1,51 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Pdf.IO; + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// Initializes a new instance of the class. + /// It represents a placeholder for a digital signature. + /// Note that the placeholder must be completely overridden, if necessary the signature + /// must be padded with trailing zeros. Blanks between the end of the hex-sting and + /// the end of the reserved space is considered as a certificate error by Acrobat. + /// + /// The size of the signature in bytes. + [DebuggerDisplay("({" + nameof(Size) + "})")] + sealed class PdfSignaturePlaceholderItem(int size) : PdfItem + { + /// + /// Returns the placeholder string padded with question marks to ensure that the code + /// fails if it is not correctly overridden. + /// + public override string ToString() => "<" + new string('?', 2 * Size)+ ">"; + + /// + /// Writes the item DocEncoded. + /// + internal override void WriteObject(PdfWriter writer) + => writer.Write(this, out _startPosition, out _endPosition); + + /// + /// Gets the number of bytes of the signature. + /// + public int Size { get; init; } = size; + + /// + /// Position of the first byte of this item in PdfWriter’s stream. + /// Precisely: The index of the '<'. + /// + public SizeType StartPosition => _startPosition; + SizeType _startPosition; + + /// + /// Position of the last byte of this item in PdfWriter’s stream. + /// Precisely: The index of the line feed behind '>'. + /// For timestamped signatures, the maximum length must be used. + /// + public SizeType EndPosition => _endPosition; + SizeType _endPosition; + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/RangedStream.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/RangedStream.cs new file mode 100644 index 00000000..0746144e --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Signatures/RangedStream.cs @@ -0,0 +1,141 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// An internal stream class used to create digital signatures. + /// It is based on a stream plus a collection of ranges that define the significant content of this stream. + /// The ranges are used to exclude one or more areas of the original stream. + /// + class RangedStream : Stream // StL: Can I say 'RangedStream' in English? SlicedStream? + { + internal class Range(SizeType offset, SizeType length) + { + public SizeType Offset { get; set; } = offset; + + public SizeType Length { get; set; } = length; + } + + public RangedStream(Stream originalStream, List ranges) + { + if (originalStream.CanRead != true) + throw new InvalidOperationException("A readable stream is required when creating a signed PDF."); + + if (originalStream.CanSeek != true) + throw new InvalidOperationException("A seekable stream is required when creating a signed PDF."); + + Stream = originalStream; + SizeType previousPosition = 0; + _ranges = ranges.OrderBy(item => item.Offset).ToArray(); + // _ranges = [.. ranges.OrderBy(item => item.Offset)]; // Visual Studio considered this as the simpler expression. + foreach (var range in ranges) + { + if (range.Offset < previousPosition) + throw new ArgumentException("Ranges are not continuous.", nameof(range)); + previousPosition = range.Offset + range.Length; + } + } + + public override bool CanRead => true; + + public override bool CanSeek => throw new NotImplementedException($"Cannot seek in a {nameof(RangedStream)}."); + + public override bool CanWrite => false; + + public override long Length => _ranges.Sum(item => item.Length); + + private IEnumerable GetPreviousRanges(long position) + => _ranges.Where(item => item.Offset < position && item.Offset + item.Length < position); + + private Range? GetCurrentRange(long position) + => _ranges.FirstOrDefault(item => item.Offset <= position && item.Offset + item.Length > position); + + public override long Position + { + get => GetPreviousRanges(Stream.Position).Sum(item => item.Length) + Stream.Position - GetCurrentRange(Stream.Position)!.Offset; + set + { + Range? currentRange = null; + List previousRanges = []; + SizeType maxPosition = 0; + foreach (var range in _ranges) + { + currentRange = range; + maxPosition += range.Length; + if (maxPosition > value) + break; + previousRanges.Add(range); + } + Debug.Assert(currentRange != null); + + SizeType positionInCurrentRange = (SizeType)(value - previousRanges.Sum(item => item.Length)); + Stream.Position = currentRange.Offset + positionInCurrentRange; + } + } + + public override void Flush() => throw new NotImplementedException(nameof(Flush)); + + public override int Read(byte[] buffer, int offset, int count) + { + var length = Stream.Length; + + // Possible, but needs extra coding we do not need until there is a real world use case. + // Write to issues (at) pdfsharp.net if you need super large signed PDF files. + if (length > Int32.MaxValue) + throw new NotImplementedException("You currently cannot sign a PDF file larger than 2 GiByte. We'll check if it is possible if someone needs it."); + + int read = 0; + // Optimized read if possible. + if (offset == 0 && count == Length) + { + foreach (var range in _ranges) + { + Debug.Assert(range.Length <= UInt32.MaxValue, "Signing of large PDF files is not implemented."); + int rangeLength = (int)range.Length; + Stream.Position = range.Offset; + read += Stream.Read(buffer, offset, rangeLength); + offset += rangeLength; + } + Debug.Assert(read == count); + return read; + } + + // We come here e.g. with Bouncy Castle signer. + + // We calculate the current range for each byte in the stream using LINQ. + // This works, but is very slow. If we get performance issues + // it should be reimplemented by using the ranges here. + // But this works, so YAGNI. + for (int i = 0; i < count; i++) + { + if (Stream.Position == length) + break; + + PerformSkipIfNeeded(); + read += Stream.Read(buffer, offset++, 1); + } + return read; + } + + void PerformSkipIfNeeded() + { + var currentRange = GetCurrentRange(Stream.Position); + if (currentRange == null) + Stream.Position = GetNextRange().Offset; + } + + Range GetNextRange() + => _ranges.OrderBy(item => item.Offset).First(item => item.Offset > Stream.Position); + + public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException(nameof(Seek)); + + public override void SetLength(long value) => throw new NotImplementedException(nameof(SetLength)); + + public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException(nameof(Write)); + + readonly Range[] _ranges; + + Stream Stream { get; } + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/KeysBase.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/KeysBase.cs index 3e6923d8..9475496a 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/KeysBase.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/KeysBase.cs @@ -8,10 +8,7 @@ namespace PdfSharp.Pdf /// public class KeysBase { - internal static DictionaryMeta CreateMeta(Type type) - { - return new DictionaryMeta(type); - } + internal static DictionaryMeta CreateMeta(Type type) => new(type); /// /// Creates the DictionaryMeta with the specified default type to return in DictionaryElements.GetValue @@ -20,9 +17,7 @@ internal static DictionaryMeta CreateMeta(Type type) /// The type. /// Default type of the content key. /// Default type of the content. - internal static DictionaryMeta CreateMeta(Type type, KeyType defaultContentKeyType, Type defaultContentType) - { - return new DictionaryMeta(type, defaultContentKeyType, defaultContentType); - } + internal static DictionaryMeta CreateMeta(Type type, KeyType defaultContentKeyType, Type defaultContentType) + => new(type, defaultContentKeyType, defaultContentType); } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfArray.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfArray.cs index 3c75d163..a07c1e4b 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfArray.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfArray.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Text; +using PdfSharp.Internal; using PdfSharp.Pdf.Advanced; using PdfSharp.Pdf.IO; @@ -132,7 +133,7 @@ internal ArrayElements(PdfArray array) object ICloneable.Clone() { var elements = (ArrayElements)MemberwiseClone(); - elements._elements = new List(elements._elements); + elements._elements = [..elements._elements]; elements._ownerArray = null; return elements; } @@ -169,7 +170,7 @@ internal void ChangeOwner(PdfArray array) public bool GetBoolean(int index) { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), index, PSSR.IndexOutOfRange); + throw new ArgumentOutOfRangeException(nameof(index), index, SyMsgs.IndexOutOfRange3); object obj = this[index]; //object? obj = GetObject(index); // TODO Do this for all conversions! 2023-06-21 @@ -191,7 +192,7 @@ public bool GetBoolean(int index) public int GetInteger(int index) { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), index, PSSR.IndexOutOfRange); + throw new ArgumentOutOfRangeException(nameof(index), index, SyMsgs.IndexOutOfRange3); object obj = this[index]; //object? obj = GetObject(index); // TODO Do this for all conversions! 2023-06-21 @@ -213,7 +214,7 @@ public int GetInteger(int index) public double GetReal(int index) { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), index, PSSR.IndexOutOfRange); + throw new ArgumentOutOfRangeException(nameof(index), index, SyMsgs.IndexOutOfRange3); object obj = this[index]; //object? obj = GetObject(index); // TODO Do this for all conversions! 2023-06-21 @@ -252,7 +253,7 @@ public double GetReal(int index) public double? GetNullableReal(int index) { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), index, PSSR.IndexOutOfRange); + throw new ArgumentOutOfRangeException(nameof(index), index, SyMsgs.IndexOutOfRange3); object obj = this[index]; //object? obj = GetObject(index); // TODO Do this for all conversions! 2023-06-21 @@ -278,7 +279,7 @@ public double GetReal(int index) public string GetString(int index) { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), index, PSSR.IndexOutOfRange); + throw new ArgumentOutOfRangeException(nameof(index), index, SyMsgs.IndexOutOfRange3); object obj = this[index]; //object? obj = GetObject(index); // TODO Do this for all conversions! 2023-06-21 @@ -300,7 +301,7 @@ public string GetString(int index) public string GetName(int index) { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), index, PSSR.IndexOutOfRange); + throw new ArgumentOutOfRangeException(nameof(index), index, SyMsgs.IndexOutOfRange3); var obj = this[index]; if (obj == null!) @@ -324,7 +325,7 @@ public string GetName(int index) public PdfObject? GetObject(int index) { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), index, PSSR.IndexOutOfRange); + throw new ArgumentOutOfRangeException(nameof(index), index, SyMsgs.IndexOutOfRange3); var item = this[index]; if (item is PdfReference reference) diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfCustomValue.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfCustomValue.cs index 80219f9c..ba6eee6e 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfCustomValue.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfCustomValue.cs @@ -13,7 +13,7 @@ public class PdfCustomValue : PdfDictionary /// public PdfCustomValue() { - CreateStream(new byte[] { }); + CreateStream([]); } /// @@ -27,7 +27,7 @@ public PdfCustomValue(byte[] bytes) internal PdfCustomValue(PdfDocument document) : base(document) { - CreateStream(new byte[] { }); + CreateStream([]); } internal PdfCustomValue(PdfDictionary dict) diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDate.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDate.cs index b5bb90de..720d8d70 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDate.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDate.cs @@ -30,6 +30,11 @@ public PdfDate(string value) /// public PdfDate(DateTime value) { + // #PDF-A + // We cannot check here whether the document must be PDF/A conform or not. + // So we always chop milliseconds. + // Remove milliseconds to ensure that date values in Metadata and Info are equal. + value = new(value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second); Value = value; } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDictionary.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDictionary.cs index fa7c2850..27b1902d 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDictionary.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDictionary.cs @@ -135,7 +135,7 @@ public override string ToString() { // Get keys and sort. PdfName[] keys = Elements.KeyNames; - List list = new List(keys); + List list = [..keys]; list.Sort(PdfName.Comparer); list.CopyTo(keys, 0); @@ -883,25 +883,24 @@ internal void SetEnumAsName(string key, object value) PdfArray CreateArray(Type type, PdfArray? oldArray) { #if true - //ConstructorInfo ctorInfo; PdfArray? array; if (oldArray == null) { // Use constructor with signature 'Ctor(PdfDocument owner)'. var ctorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - null, new[] { typeof(PdfDocument) }, null); + null, [typeof(PdfDocument)], null); Debug.Assert(ctorInfo != null, "No appropriate constructor found for type: " + type.Name); //array = ctorInfo.Invoke(new object[] { _ownerDictionary.Owner }) as PdfArray; - array = ctorInfo.Invoke(new object[] { _ownerDictionary.Owner }) as PdfArray; + array = ctorInfo.Invoke([_ownerDictionary.Owner]) as PdfArray; } else { // Use constructor with signature 'Ctor(PdfDictionary dict)'. var ctorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - null, new[] { typeof(PdfArray) }, null); - Debug.Assert(ctorInfo != null, "No appropriate constructor found for type: " + type.Name); + null, types: [typeof(PdfArray)], null); + Debug.Assert(ctorInfo != null, $"No appropriate constructor found for type: {type.Name}."); //array = ctorInfo.Invoke(new object[] { oldArray }) as PdfArray; - array = ctorInfo.Invoke(new object[] { oldArray }) as PdfArray; + array = ctorInfo.Invoke([oldArray]) as PdfArray; } return array ?? NRT.ThrowOnNull(); #else @@ -952,17 +951,17 @@ PdfDictionary CreateDictionary(Type type, PdfDictionary? oldDictionary) { // Use constructor with signature 'Ctor(PdfDocument owner)'. ctorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - null, new[] { typeof(PdfDocument) }, null); + null, [typeof(PdfDocument)], null); Debug.Assert(ctorInfo != null, "No appropriate constructor found for type: " + type.Name); - dict = ctorInfo.Invoke(new object[] { _ownerDictionary.Owner }) as PdfDictionary; + dict = ctorInfo.Invoke([_ownerDictionary.Owner]) as PdfDictionary; } else { // Use constructor with signature 'Ctor(PdfDictionary dict)'. ctorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - null, new[] { typeof(PdfDictionary) }, null); + null, [typeof(PdfDictionary)], null); Debug.Assert(ctorInfo != null, "No appropriate constructor found for type: " + type.Name); - dict = ctorInfo.Invoke(new object[] { oldDictionary }) as PdfDictionary; + dict = ctorInfo.Invoke([oldDictionary]) as PdfDictionary; } return dict ?? NRT.ThrowOnNull(); #else @@ -1006,8 +1005,8 @@ PdfItem CreateValue(Type type, PdfDictionary? oldValue) { #if true var ctorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - null, new Type[] { typeof(PdfDocument) }, null); - var obj = ctorInfo!.Invoke(new object[] { _ownerDictionary.Owner }) as PdfObject; + null, [typeof(PdfDocument)], null); + var obj = ctorInfo!.Invoke([_ownerDictionary.Owner]) as PdfObject; if (oldValue != null) { obj!.Reference = oldValue.Reference; @@ -1056,7 +1055,7 @@ public void SetValue(string key, PdfItem value) Debug.Assert(value is PdfObject { Reference: null } or not PdfObject, "You try to set an indirect object directly into a dictionary."); - // HACK? + // Hammer the value in without further checks. _elements[key] = value; } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDocument.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDocument.cs index 9b3ad75d..3faccf65 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDocument.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfDocument.cs @@ -1,6 +1,7 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. +using System.Reflection; using System.Runtime.InteropServices; using Microsoft.Extensions.Logging; using PdfSharp.Drawing; @@ -11,7 +12,10 @@ using PdfSharp.Pdf.Internal; using PdfSharp.Pdf.IO; using PdfSharp.Pdf.AcroForms; +using PdfSharp.Pdf.Filters; using PdfSharp.Pdf.Security; +using PdfSharp.Pdf.Signatures; +using PdfSharp.Pdf.Structure; using PdfSharp.UniversalAccessibility; // ReSharper disable InconsistentNaming @@ -22,18 +26,9 @@ namespace PdfSharp.Pdf /// /// Represents a PDF document. /// - [DebuggerDisplay("(Name={" + nameof(Name) + "})")] // A name makes debugging easier + [DebuggerDisplay("(Name={" + nameof(Name) + "})")] // A name makes debugging easier. public sealed class PdfDocument : PdfObject, IDisposable { -#if DEBUG_ - static PdfDocument() - { - PSSR.TestResourceMessages(); - //string test = PSSR.ResMngr.GetString("SampleMessage1"); - //test.GetType(); - } -#endif - /// /// Creates a new PDF document in memory. /// To open an existing PDF file, use the PdfReader class. @@ -42,7 +37,7 @@ public PdfDocument() { PdfSharpLogHost.Logger.PdfDocumentCreated(Name); //PdfDocument.Gob.AttachDocument(Handle); - + _document = this; _creation = DateTime.Now; _state = DocumentState.Created; _version = 17; @@ -69,6 +64,7 @@ public PdfDocument(string outputFilename) : this() /// public PdfDocument(Stream outputStream) { + _document = this; _creation = DateTime.Now; _state = DocumentState.Created; _version = 14; @@ -82,6 +78,7 @@ internal PdfDocument(Lexer lexer) { //PdfDocument.Gob.AttachDocument(Handle); + _document = this; _creation = DateTime.Now; _state = DocumentState.Imported; @@ -148,6 +145,22 @@ void Dispose(bool disposing) /// public object? Tag { get; set; } + /// + /// Temporary hack to set a value that tells PDFsharp to create a PDF/A conform document. + /// + public void SetPdfA() // HACK + { + _isPdfA = true; + _ = UAManager.ForDocument(this); + } + + /// + /// Gets a value indicating that you create a PDF/A conform document. + /// This function is temporary and will change in the future. + /// + public bool IsPdfA => _isPdfA; // HACK + bool _isPdfA; + /// /// Encapsulates the document’s events. /// @@ -188,20 +201,20 @@ static string NewName() /// public void Close() { - if (!CanModify) - throw new InvalidOperationException(PSSR.CannotModify); - if (OutStream != null) { + if (!CanModify) + throw new InvalidOperationException(PsMsgs.CannotModify); + EnsureNotYetSaved(); // Get security handler if document gets encrypted. var effectiveSecurityHandler = SecuritySettings.EffectiveSecurityHandler; - var writer = new PdfWriter(OutStream, effectiveSecurityHandler); + var writer = new PdfWriter(OutStream, _document, effectiveSecurityHandler); try { - DoSave(writer); + DoSaveAsync(writer).GetAwaiter().GetResult(); } finally { @@ -215,53 +228,54 @@ public void Close() /// public void Save(string path) { - EnsureNotYetSaved(); - - if (!CanModify) - throw new InvalidOperationException(PSSR.CannotModify); - - using Stream stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); - Save(stream); + // Safely call the async version on the current thread. + SaveAsync(path).GetAwaiter().GetResult(); } -#if UWP /// - /// Saves the document to the specified path. If a file already exists, it will be overwritten. + /// Saves the document async to the specified path. If a file already exists, it will be overwritten. + /// The async version of save is useful if you want to create a signed PDF file with a time stamp. + /// A time stamp server should be accessed asynchronously, and therefore we introduced this function. /// - public async Task SaveAsync(string path, bool closeStream) + public async Task SaveAsync(string path) { EnsureNotYetSaved(); if (!CanModify) - throw new InvalidOperationException(PSSR.CannotModify); + throw new InvalidOperationException(PsMsgs.CannotModify); - // Just march through... + // We need ReadWrite when adding a signature. Write is sufficient if not adding a signature. + var fileAccess = _digitalSignatureHandler == null ? FileAccess.Write : FileAccess.ReadWrite; - var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("My1st.pdf", Windows.Storage.CreationCollisionOption.ReplaceExisting); - var stream = await file.OpenStreamForWriteAsync(); - using (var writer = new StreamWriter(stream)) - { - Save(stream, false); - } + // ReSharper disable once UseAwaitUsing because we need no DisposeAsync for a simple FileStream. + using var stream = new FileStream(path, FileMode.Create, fileAccess, FileShare.None); + await SaveAsync(stream).ConfigureAwait(false); + } - //var ms = new MemoryStream(); - //Save(ms, false); - //byte[] pdf = ms.ToArray(); - //ms.Close(); - //await stream.WriteAsync(pdf, 0, pdf.Length); - //stream.Close(); + /// + /// Saves the document to the specified stream. + /// + public void Save(Stream stream, bool closeStream = false) + { + // Safely call the async version on the current thread. + SaveAsync(stream, closeStream).GetAwaiter().GetResult(); } -#endif /// /// Saves the document to the specified stream. + /// The async version of save is useful if you want to create a signed PDF file with a time stamp. + /// A time stamp server should be accessed asynchronously, and therefore we introduced this function. /// - public void Save(Stream stream, bool closeStream) + public async Task SaveAsync(Stream stream, bool closeStream = false) { EnsureNotYetSaved(); if (!CanModify) - throw new InvalidOperationException(PSSR.CannotModify); + throw new InvalidOperationException(PsMsgs.CannotModify); + + // #PDF-A + if (IsPdfA) + PrepareForPdfA(); // TODO: more diagnostic checks string message = ""; @@ -274,19 +288,18 @@ public void Save(Stream stream, bool closeStream) PdfWriter? writer = null; try { - writer = new PdfWriter(stream, effectiveSecurityHandler); - DoSave(writer); + Debug.Assert(ReferenceEquals(_document, this)); + writer = new(stream, _document, effectiveSecurityHandler); + await DoSaveAsync(writer).ConfigureAwait(false); } finally { if (stream != null!) { if (closeStream) -#if UWP - stream.Dispose(); -#else + { stream.Close(); -#endif + } else { if (stream is { CanRead: true, CanSeek: true }) @@ -297,18 +310,10 @@ public void Save(Stream stream, bool closeStream) } } - /// - /// Saves the document to the specified stream. - /// The stream is not closed by this function. - /// (Older versions of PDFsharp close the stream. That was not very useful.) - /// - public void Save(Stream stream) - => Save(stream, false); - /// /// Implements saving a PDF file. /// - void DoSave(PdfWriter writer) + async Task DoSaveAsync(PdfWriter writer) { PdfSharpLogHost.Logger.PdfDocumentSaved(Name); @@ -324,7 +329,11 @@ void DoSave(PdfWriter writer) try { - // HACK: Remove XRefTrailer + // Prepare for signing. + if (_digitalSignatureHandler != null) + await _digitalSignatureHandler.AddSignatureComponentsAsync().ConfigureAwait(false); + + // Remove XRefTrailer if (Trailer is PdfCrossReferenceStream crossReferenceStream) { Trailer = new PdfTrailer(crossReferenceStream); @@ -359,12 +368,18 @@ void DoSave(PdfWriter writer) iref.Position = writer.Position; iref.Value.WriteObject(writer); } - SizeType startxref = writer.Position; + // ReSharper disable once RedundantCast. Redundant only if 64 bit. + var startXRef = (SizeType)writer.Position; IrefTable.WriteObject(writer); writer.WriteRaw("trailer\n"); Trailer.Elements.SetInteger("/Size", count + 1); Trailer.WriteObject(writer); - writer.WriteEof(this, startxref); + writer.WriteEof(this, startXRef); + + // #Signature: What about encryption + signing ?? + // Prepare for signing. + if (_digitalSignatureHandler != null) + await _digitalSignatureHandler.ComputeSignatureAndRange(writer).ConfigureAwait(false); //if (encrypt) //{ @@ -374,15 +389,64 @@ void DoSave(PdfWriter writer) } finally { - if (writer != null!) - { - writer.Stream.Flush(); - // DO NOT CLOSE WRITER HERE - } + //await writer.Stream.FlushAsync().ConfigureAwait(false); + writer.Stream.Flush(); + // Do not close the stream writer here. _state |= DocumentState.Saved; } } + void PrepareForPdfA() // Just a first hack. + { + var internals = Internals; + + Debug.Assert(_uaManager != null); + // UAManager sets MarkInformation. + if (_uaManager == null) + { + // Marked must be true in MarkInfo. + var markInfo = new PdfMarkInformation(); + //internals.AddObject(markInfo); + + markInfo.Elements.SetBoolean(PdfMarkInformation.Keys.Marked, true); + //internals.Catalog.Elements.SetReference(PdfCatalog.Keys.MarkInfo, markInfo); + internals.Catalog.Elements.Add(PdfCatalog.Keys.MarkInfo, markInfo); + } + + var outputIntentsArray = new PdfArray(this); + //internals.AddObject(outputIntentsArray); + var outputIntents = new PdfDictionary(this); + outputIntentsArray.Elements.Add(outputIntents); + + outputIntents.Elements.Add("/Type", new PdfName("/OutputIntent")); + outputIntents.Elements.Add("/S", new PdfName("/GTS_PDFA1")); + outputIntents.Elements.Add("/OutputConditionIdentifier", new PdfString("sRGB")); + outputIntents.Elements.Add("/RegistryName", new PdfString("http://www.color.org")); + outputIntents.Elements.Add("/Info", new PdfString("Creator: ColorOrg Manufacturer:IEC Model:sRGB")); + + var profileStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PdfSharp.Resources.sRGB2014.icc") + ?? throw new InvalidOperationException("Embedded color profile was not found."); + + var profile = new byte[profileStream.Length]; + var read = profileStream.Read(profile, 0, (int)profileStream.Length); + if (read != profileStream.Length) + throw new InvalidOperationException("Embedded color profile was not read."); + + var fd = new FlateDecode(); + byte[] profileCompressed = fd.Encode(profile, Options.FlateEncodeMode); + + var profileObject = new PdfDictionary(this); + IrefTable.Add(profileObject); + profileObject.Stream = new PdfDictionary.PdfStream(profileCompressed, profileObject); + profileObject.Elements["/N"] = new PdfInteger(3); + profileObject.Elements["/Length"] = new PdfInteger(profileCompressed.Length); + profileObject.Elements["/Filter"] = new PdfName("/FlateDecode"); + + outputIntents.Elements.Add("/DestOutputProfile", profileObject.Reference); + //internals.Catalog.Elements.SetReference(PdfCatalog.Keys.OutputIntents, outputIntentsArray); + internals.Catalog.Elements.Add(PdfCatalog.Keys.OutputIntents, outputIntentsArray); + } + /// /// Dispatches PrepareForSave to the objects that need it. /// @@ -428,7 +492,7 @@ internal override void PrepareForSave() int removed = IrefTable.Compact(); if (removed != 0 && PdfSharpLogHost.Logger.IsEnabled(LogLevel.Information)) { - PdfSharpLogHost.Logger.LogInformation($"\"PrepareForSave: Number of deleted unreachable objects: {removed}"); + PdfSharpLogHost.Logger.LogInformation($"PrepareForSave: Number of deleted unreachable objects: {removed}"); } IrefTable.Renumber(); #endif @@ -478,7 +542,7 @@ public PdfDocumentSettings Settings //internal bool EarlyWrite => false; /// - /// Gets or sets the PDF version number. Return value 14 e.g. means PDF 1.4 / Acrobat 5 etc. + /// Gets or sets the PDF version number as integer. Return value 14 e.g. means PDF 1.4 / Acrobat 5 etc. /// public int Version { @@ -488,9 +552,9 @@ public int Version EnsureNotYetSaved(); if (!CanModify) - throw new InvalidOperationException(PSSR.CannotModify); + throw new InvalidOperationException(PsMsgs.CannotModify); if (value is < 12 or > 20) // TODO not really implemented - throw new ArgumentException(PSSR.InvalidVersionNumber, nameof(value)); + throw new ArgumentException(PsMsgs.InvalidVersionNumber(value), nameof(value)); _version = value; } } @@ -535,9 +599,7 @@ public int PageCount /// /// Gets the file size of the document. /// - public long FileSize => _fileSize; - - internal long _fileSize; // TODO: make private + public long FileSize { get; internal set; } /// /// Gets the full qualified file name if the document was read form a file, or an empty string otherwise. @@ -567,10 +629,10 @@ internal DocumentHandle Handle /// public bool IsReadOnly => (_openMode != PdfDocumentOpenMode.Modify); - internal Exception DocumentNotImported() - { - return new InvalidOperationException("Document not imported."); - } + //internal Exception DocumentNotImported() + //{ + // return new InvalidOperationException("Document not imported."); + //} /// /// Gets information about the document. @@ -614,7 +676,7 @@ public PdfPageLayout PageLayout set { if (!CanModify) - throw new InvalidOperationException(PSSR.CannotModify); + throw new InvalidOperationException(PsMsgs.CannotModify); Catalog.PageLayout = value; } } @@ -628,7 +690,7 @@ public PdfPageMode PageMode set { if (!CanModify) - throw new InvalidOperationException(PSSR.CannotModify); + throw new InvalidOperationException(PsMsgs.CannotModify); Catalog.PageMode = value; } } @@ -746,7 +808,7 @@ public PdfPage AddPage() EnsureNotYetSaved(); if (!CanModify) - throw new InvalidOperationException(PSSR.CannotModify); + throw new InvalidOperationException(PsMsgs.CannotModify); return Catalog.Pages.Add(); } @@ -760,7 +822,7 @@ public PdfPage AddPage(PdfPage page) EnsureNotYetSaved(); if (!CanModify) - throw new InvalidOperationException(PSSR.CannotModify); + throw new InvalidOperationException(PsMsgs.CannotModify); return Catalog.Pages.Add(page); } @@ -772,7 +834,7 @@ public PdfPage InsertPage(int index) EnsureNotYetSaved(); if (!CanModify) - throw new InvalidOperationException(PSSR.CannotModify); + throw new InvalidOperationException(PsMsgs.CannotModify); return Catalog.Pages.Insert(index); } @@ -786,7 +848,7 @@ public PdfPage InsertPage(int index, PdfPage page) EnsureNotYetSaved(); if (!CanModify) - throw new InvalidOperationException(PSSR.CannotModify); + throw new InvalidOperationException(PsMsgs.CannotModify); return Catalog.Pages.Insert(index, page); } @@ -882,9 +944,9 @@ internal class DocumentHandle(PdfDocument document) public readonly string ID = document._guid.ToString("B").ToUpper(); - - - + + + public override bool Equals(object? obj) { if (obj is DocumentHandle handle) @@ -920,5 +982,14 @@ internal void EnsureNotYetSaved() internal DocumentState _state; internal PdfDocumentOpenMode _openMode; internal UAManager? _uaManager; + internal DigitalSignatureHandler? _digitalSignatureHandler; } + +#if true_ + // UNDER_CONSTRUCTION + static class PDFA_ + { + public static bool IsPdfA => true; + } +#endif } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfMetadata.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfMetadata.cs index 7b17ee79..529e790f 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfMetadata.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfMetadata.cs @@ -44,11 +44,7 @@ void SetupStream() // Preserve "" if text is UTF8 encoded. var i = stream.IndexOf(begin, StringComparison.Ordinal); var pos = i + begin.Length; -#if NET6_0_OR_GREATER || true stream = stream[..pos] + "xxx" + stream[(pos + 3)..]; -#else - stream = stream.Substring(0, pos) + "xxx" + stream.Substring(pos + 3); -#endif byte[] bytes = Encoding.UTF8.GetBytes(stream); bytes[pos++] = (byte)'ï'; @@ -73,6 +69,18 @@ string GenerateXmp() var subject = _document.Info.Subject; var keywords = _document.Info.Keywords; + // #PDF-A Tag PDF as PDF/A-1A conform. + string? pdfA = null; + if (_document.IsPdfA) + { + // #PDF-A + pdfA = $""" + + 1 + A + + """; + } #if true // Created based on a PDF created with Microsoft Word. var str = $""" @@ -96,6 +104,7 @@ string GenerateXmp() uuid:{documentId} uuid:{instanceId} + {pdfA} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfName.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfName.cs index 3a8bbf31..313cebcf 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfName.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfName.cs @@ -1,6 +1,7 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. +using PdfSharp.Internal; using PdfSharp.Pdf.IO; namespace PdfSharp.Pdf @@ -28,7 +29,7 @@ public PdfName(string value) if (value == null) throw new ArgumentNullException(nameof(value)); if (value.Length == 0 || value[0] != '/') - throw new ArgumentException(PSSR.NameMustStartWithSlash); + throw new ArgumentException(PsMsgs.NameMustStartWithSlash); _value = value; } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfNameObject.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfNameObject.cs index f29fd33d..c7511c0c 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfNameObject.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfNameObject.cs @@ -32,7 +32,7 @@ public PdfNameObject(PdfDocument document, string value) if (value == null) throw new ArgumentNullException(nameof(value)); if (value.Length == 0 || value[0] != '/') - throw new ArgumentException(PSSR.NameMustStartWithSlash); + throw new ArgumentException(PsMsgs.NameMustStartWithSlash); Value = value; } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfNumberTreeNode.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfNumberTreeNode.cs index 726185c6..a6252b48 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfNumberTreeNode.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfNumberTreeNode.cs @@ -19,13 +19,7 @@ public sealed class PdfNumberTreeNode : PdfDictionary /// /// Initializes a new instance of the class. /// - public PdfNumberTreeNode() - { } - - /// - /// Initializes a new instance of the class. - /// - public PdfNumberTreeNode(bool isRoot) //??? Needed HACK StLa + public PdfNumberTreeNode(bool isRoot = false) { IsRoot = isRoot; } @@ -33,12 +27,7 @@ public PdfNumberTreeNode(bool isRoot) //??? Needed HACK StLa /// /// Gets a value indicating whether this instance is a root node. /// - public bool IsRoot - { - get => _isRoot; - private init => _isRoot = value; - } - readonly bool _isRoot; + public bool IsRoot { get; private init; } /// /// Gets the number of Kids elements. @@ -99,12 +88,12 @@ public void AddNumber(int key, PdfObject value) /// /// Gets the least key. /// - public string LeastKey => "todo"; + public string LeastKey => throw new NotImplementedException(nameof(LeastKey)); // NYI /// /// Gets the greatest key. /// - public string GreatestKey => "todo"; + public string GreatestKey => throw new NotImplementedException(nameof(GreatestKey)); // NYI /// /// Updates the limits by inspecting Kids and Names. @@ -113,7 +102,7 @@ void UpdateLimits() { if (_updateRequired) { - //TODO Recalc Limits + // NYI Recalculate Limits _updateRequired = false; } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfObject.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfObject.cs index 7ed1f2f1..d36bbacc 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfObject.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfObject.cs @@ -51,10 +51,7 @@ protected PdfObject(PdfObject obj) /// /// Creates a copy of this object. The clone does not belong to a document, i.e. its owner and its iref are null. /// - public new PdfObject Clone() - { - return (PdfObject)Copy(); - } + public new PdfObject Clone() => (PdfObject)Copy(); /// /// Implements the copy mechanism. Must be overridden in derived classes. @@ -108,8 +105,7 @@ internal void SetObjectID(int objectNumber, int generationNumber) var objectID = new PdfObjectID(objectNumber, generationNumber); // TODO: check imported - if (_iref == null) - _iref = _document.IrefTable[objectID]; + _iref ??= _document.IrefTable[objectID]; if (_iref == null) { // ReSharper disable once ObjectCreationAsStatement because the new object is set to this object diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfOutlineCollection.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfOutlineCollection.cs index bfd79899..e49007bc 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfOutlineCollection.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfOutlineCollection.cs @@ -179,7 +179,7 @@ public void Insert(int index, PdfOutline outline) if (outline == null) throw new ArgumentNullException(nameof(outline)); if (index < 0 || index >= _outlines.Count) - throw new ArgumentOutOfRangeException(nameof(index), index, PSSR.OutlineIndexOutOfRange); + throw new ArgumentOutOfRangeException(nameof(index), index, PsMsgs.OutlineIndexOutOfRange); AddToOutlinesTree(outline); _outlines.Insert(index, outline); @@ -203,15 +203,15 @@ public PdfOutline this[int index] get { if (index < 0 || index >= _outlines.Count) - throw new ArgumentOutOfRangeException(nameof(index), index, PSSR.OutlineIndexOutOfRange); + throw new ArgumentOutOfRangeException(nameof(index), index, PsMsgs.OutlineIndexOutOfRange); return _outlines[index]; } set { if (index < 0 || index >= _outlines.Count) - throw new ArgumentOutOfRangeException(nameof(index), index, PSSR.OutlineIndexOutOfRange); + throw new ArgumentOutOfRangeException(nameof(index), index, PsMsgs.OutlineIndexOutOfRange); if (value == null) - throw new ArgumentOutOfRangeException(nameof(value), null, PSSR.SetValueMustNotBeNull); + throw new ArgumentOutOfRangeException(nameof(value), null, PsMsgs.SetValueMustNotBeNull); AddToOutlinesTree(value); _outlines[index] = value; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs index 1f167908..e231370a 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPage.cs @@ -2,6 +2,7 @@ // See the LICENSE file in the solution root for more information. using System.ComponentModel; +using Microsoft.Extensions.Logging; using PdfSharp.Pdf.IO; using PdfSharp.Drawing; using PdfSharp.Logging; @@ -42,18 +43,22 @@ public PdfPage(PdfDocument document) internal PdfPage(PdfDictionary dict) : base(dict) { - // Set Orientation depending on /Rotate. + // #DELETE Delete old page orientation code 2024-12-24. - //!!!modTHHO 2016-06-16 Do not set Orientation here. Setting Orientation is not enough. Other properties must also be changed when setting Orientation. - //!!!modTHHO 2018-04-05 Restored the old behavior. Commenting the next three lines out is not enough either. - // New approach: remember that Orientation was set based on rotation. + ////// Set Orientation depending on /Rotate. + + //////!!!modTHHO 2016-06-16 Do not set Orientation here. Setting Orientation is not enough. Other properties must also be changed when setting Orientation. + //////!!!modTHHO 2018-04-05 Restored the old behavior. Commenting the next three lines out is not enough either. + ////// New approach: remember that Orientation was set based on rotation. + + // NEW: Rotate has nothing to do with Orientation. int rotate = Elements.GetInteger(InheritablePageKeys.Rotate); if (Math.Abs((rotate / 90)) % 2 == 1) { #if true _orientation = PageOrientation.Landscape; // Hacky approach: do not swap width and height on saving when orientation was set here. - _orientationSetByCodeForRotatedDocument = true; + //_orientationSetByCodeForRotatedDocument = true; #else // Cleaner approach: Swap width and height here. But some drawing routines will not draw the XPdfForm correctly, so this needs more testing and more changes. // When saving, width and height will be swapped. So we have to swap them here too. @@ -61,14 +66,21 @@ internal PdfPage(PdfDictionary dict) MediaBox = new PdfRectangle(mediaBox.X1, mediaBox.Y1, mediaBox.Y2, mediaBox.X2); #endif } + + // Setup page size from MediaBox. + var rectangle = Elements.GetRectangle(InheritablePageKeys.MediaBox, true); + _width = XUnit.FromPoint(rectangle.X2 - rectangle.X1); + _height = XUnit.FromPoint(rectangle.Y2 - rectangle.Y1); + UpdateOrientation(); } void Initialize() { Size = RegionInfo.CurrentRegion.IsMetric ? PageSize.A4 : PageSize.Letter; - // Force creation of MediaBox object by invoking property. - _ = MediaBox; + // Done by Size. + ////// Force creation of MediaBox object by getting the value. + ////Elements.GetRectangle(InheritablePageKeys.MediaBox, true); ; } /// @@ -116,45 +128,87 @@ internal override PdfDocument Document } /// - /// Gets or sets the orientation of the page. The default value PageOrientation.Portrait. - /// If an imported page has a /Rotate value that matches the formula 90 + n * 180 the - /// orientation is set to PageOrientation.Landscape. + /// Gets or sets the orientation of the page. The default value is PageOrientation.Portrait. + /// If the page width is less than or equal to page height, the orientation is Portrait; + /// otherwise Landscape. /// + // Old and wrong: + // If an imported page has a /Rotate value that matches the formula 90 + n * 180 the + // orientation is set to PageOrientation.Landscape. public PageOrientation Orientation { get => _orientation; set { +#if true + switch (value) + { + case PageOrientation.Portrait: + if (_width > _height) // Is it currently Landscape? + { + Debug.Assert(_orientation == PageOrientation.Landscape); + (_width, _height) = (_height, _width); + _orientation = value; + MediaBox = new PdfRectangle(0, 0, _width.Point, _height.Point); + } + break; + + case PageOrientation.Landscape: // Is it currently Portrait? + if (_width < _height) + { + Debug.Assert(_orientation == PageOrientation.Portrait); + (_width, _height) = (_height, _width); + _orientation = value; + MediaBox = new PdfRectangle(0, 0, _width.Point, _height.Point); + } + //else + //{ + // // Quadratic page cannot be set to Landscape. + // if (_width == _height) + // return; + //} + break; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } +#else _orientation = value; _orientationSetByCodeForRotatedDocument = false; +#endif } } - PageOrientation _orientation; - bool _orientationSetByCodeForRotatedDocument; - // TODO Simplify the implementation. Should /Rotate 90 lead to Landscape format? - // TODO Clean implementation without _orientationSetByCodeForRotatedDocument. + //////////bool _orientationSetByCodeForRotatedDocument; + ////// TODO Simplify the implementation. Should /Rotate 90 lead to Landscape format? + ////// TODO Clean implementation without _orientationSetByCodeForRotatedDocument. + + void UpdateOrientation() + { + _orientation = _width <= _height + ? PageOrientation.Portrait + : PageOrientation.Landscape; + } /// - /// Gets or sets one of the predefined standard sizes like. + /// Sets one of the predefined standard sizes like. /// public PageSize Size { + [Obsolete("Use PageSize to get the absolute size of the page.")] get => _pageSize; set { if (!Enum.IsDefined(typeof(PageSize), value)) - throw new InvalidEnumArgumentException("value", (int)value, typeof(PageSize)); + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(PageSize)); var size = PageSizeConverter.ToSize(value); - // MediaBox is always in Portrait mode (see Height, Width). - // So take Orientation NOT into account. + //// MediaBox is always in Portrait mode (see Height, Width). + //// So take Orientation NOT into account. MediaBox = new PdfRectangle(0, 0, size.Width, size.Height); - _pageSize = value; } } - PageSize _pageSize; /// @@ -192,7 +246,17 @@ public TrimMargins TrimMargins public PdfRectangle MediaBox { get => Elements.GetRectangle(InheritablePageKeys.MediaBox, true); - set => Elements.SetRectangle(InheritablePageKeys.MediaBox, value); + set + { + // Can be different from 0 in case of imported PDF. + //if (value is not { X1: 0, Y1: 0 }) + // throw new ArgumentException("MediaBox origin cannot be other than (0,0)."); + + _width = XUnit.FromPoint(value.X2 - value.X1); + _height = XUnit.FromPoint(value.Y2 - value.Y1); + UpdateOrientation(); + Elements.SetRectangle(InheritablePageKeys.MediaBox, value); + } } /// @@ -232,69 +296,138 @@ public PdfRectangle TrimBox } /// - /// Gets or sets the height of the page. If orientation is Landscape, this function applies to - /// the width. + /// Gets or sets the height of the page. + /// If the page width is less than or equal to page height, the orientation is Portrait; + /// otherwise Landscape. /// + // --- + // If orientation is Landscape, this function applies to + // the width. public XUnit Height { get { +#if true // #PageOrientation + return _height; +#else var rect = MediaBox; return _orientation == PageOrientation.Portrait ? XUnit.FromPoint(rect.Height) : XUnit.FromPoint(rect.Width); +#endif } set { +#if true // #PageOrientation + _height = value; + var rect = MediaBox; + MediaBox = new PdfRectangle(rect.X1, 0, rect.X2, _height.Point); +#else var rect = MediaBox; if (_orientation == PageOrientation.Portrait) MediaBox = new PdfRectangle(rect.X1, 0, rect.X2, value.Point); else MediaBox = new PdfRectangle(0, rect.Y1, value.Point, rect.Y2); +#endif _pageSize = PageSize.Undefined; + UpdateOrientation(); } } + XUnit _height; /// - /// Gets or sets the width of the page. If orientation is Landscape, this function applies to - /// the height. + /// Gets or sets the width of the page. + /// If the page width is less than or equal to page height, the orientation is Portrait; + /// otherwise Landscape. /// + // --- + // If orientation is Landscape, this function applies to + // the height. public XUnit Width { get { +#if true // #PageOrientation + return _width; +#else var rect = MediaBox; return _orientation == PageOrientation.Portrait ? XUnit.FromPoint(rect.Width) : XUnit.FromPoint(rect.Height); +#endif } set { +#if true // #PageOrientation + _width = value; + var rect = MediaBox; + MediaBox = new PdfRectangle(0, rect.Y1, _width.Point, rect.Y2); +#else var rect = MediaBox; if (_orientation == PageOrientation.Portrait) MediaBox = new PdfRectangle(0, rect.Y1, value.Point, rect.Y2); else MediaBox = new PdfRectangle(rect.X1, 0, rect.X2, value.Point); +#endif _pageSize = PageSize.Undefined; + UpdateOrientation(); } } + XUnit _width; + /// /// Gets or sets the /Rotate entry of the PDF page. The value is the number of degrees by which the page /// should be rotated clockwise when displayed or printed. The value must be a multiple of 90. - /// PDFsharp does not set this value, but for imported pages this value can be set and must be taken - /// into account when adding graphic to such a page. + /// This property does the same as the Rotation property, but uses an integer value. /// + // #PageOrientation + // PDFsharp does not set this value, but for imported pages this value can be set and must be taken + // into account when adding graphic to such a page. public int Rotate { get => Elements.GetInteger(InheritablePageKeys.Rotate); set { - if (value % 90 != 0) - throw new ArgumentException("Value must be a multiple of 90."); + if (value >= 360) + { + // An imported PDF may contain a value larger than or equal to 360. + var message = Invariant($"Illegal /Rotate value {value}."); + PdfSharpLogHost.Logger.LogError(message); + while (value >= 360) + value -= 360; + } + + if (value % 90 != 0 || value > 270) + throw new ArgumentException("Value must be 0, 90, 180, or 270."); Elements.SetInteger(InheritablePageKeys.Rotate, value); } } - // TODO: PdfAnnotations - // TODO: PdfActions - // TODO: PdfPageTransition + /// + /// Gets or sets a value how a PDF viewer application should rotate this page. + /// This property does the same as the Rotate property, but uses an enum value. + /// + public PageRotation Rotation + { + get + { + var value = Elements.GetInteger(InheritablePageKeys.Rotate); + return value switch + { + 0 => PageRotation.None, + 90 => PageRotation.Rotate90DegreesRight, + 180 => PageRotation.RotateUpsideDown, + 270 => PageRotation.Rotate90DegreesLeft, + _ => throw new InvalidEnumArgumentException(nameof(value), value, typeof(PageRotation)) + }; + } + set + { + if (value != PageRotation.None && + value != PageRotation.Rotate90DegreesRight && + value != PageRotation.RotateUpsideDown && + value != PageRotation.Rotate90DegreesLeft) + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(PageRotation)); + Elements.SetInteger(InheritablePageKeys.Rotate, (int)value); + } + } /// /// The content stream currently used by an XGraphics object for rendering. @@ -497,6 +630,11 @@ public PdfLinkAnnotation AddFileLink(PdfRectangle rect, string fileName) #endregion + // TODO: PdfActions + + // TODO: PdfPageTransition + + /// /// Gets or sets the custom values. /// @@ -612,34 +750,43 @@ string IContentStream.GetFormName(XForm form) internal override void WriteObject(PdfWriter writer) { - // HACK: temporarily flip media box if Landscape - PdfRectangle mediaBox = MediaBox; - // TODO: Take /Rotate into account - //!!!newTHHO 2018-04-05 Stop manipulating the MediaBox - Height and Width properties already take orientation into account. - //!!!delTHHO 2018-04-05 if (_orientation == PageOrientation.Landscape) - //!!!delTHHO 2018-04-05 MediaBox = new PdfRectangle(mediaBox.X1, mediaBox.Y1, mediaBox.Y2, mediaBox.X2); - // One step back - swap members in MediaBox for landscape orientation. + ////// HACK: temporarily flip media box if Landscape + ////PdfRectangle mediaBox = MediaBox; + ////// TODO: Take /Rotate into account + //////!!!newTHHO 2018-04-05 Stop manipulating the MediaBox - Height and Width properties already take orientation into account. + //////!!!delTHHO 2018-04-05 if (_orientation == PageOrientation.Landscape) + //////!!!delTHHO 2018-04-05 MediaBox = new PdfRectangle(mediaBox.X1, mediaBox.Y1, mediaBox.Y2, mediaBox.X2); + ////// One step back - swap members in MediaBox for landscape orientation. + +#if false // #PageOrientation if (_orientation == PageOrientation.Landscape && !_orientationSetByCodeForRotatedDocument) MediaBox = new PdfRectangle(mediaBox.X1, mediaBox.Y1, mediaBox.Y2, mediaBox.X2); +#endif -#if true - // Add transparency group to prevent rendering problems of Adobe viewer. - // Update (PDFsharp 1.50 beta 3): Add transparency group only if ColorMode is defined. - // Rgb is the default for the ColorMode, but if user sets it to Undefined then - // we respect this and skip the transparency group. - TransparencyUsed = true; // TODO: check XObjects - if (TransparencyUsed && !Elements.ContainsKey(Keys.Group) && - _document.Options.ColorMode != PdfColorMode.Undefined) +#if true // #PDF-A Suppress transparency group if PDF-A is required + if (!_document.IsPdfA) { - var group = new PdfDictionary(); - Elements["/Group"] = group; - if (_document.Options.ColorMode != PdfColorMode.Cmyk) - group.Elements.SetName("/CS", "/DeviceRGB"); - else - group.Elements.SetName("/CS", "/DeviceCMYK"); - group.Elements.SetName("/S", "/Transparency"); - //False is default: group.Elements["/I"] = new PdfBoolean(false); - //False is default: group.Elements["/K"] = new PdfBoolean(false); + // Add transparency group to prevent rendering problems of Adobe viewer. + // Update (PDFsharp 1.50 beta 3): Add transparency group only if ColorMode is defined. + // Rgb is the default for the ColorMode, but if user sets it to Undefined then + // we respect this and skip the transparency group. + TransparencyUsed = true; // TODO: check XObjects + if (TransparencyUsed && !Elements.ContainsKey(Keys.Group) && + _document.Options.ColorMode != PdfColorMode.Undefined) + { + var group = new PdfDictionary(); + Elements["/Group"] = group; + if (_document.Options.ColorMode != PdfColorMode.Cmyk) + group.Elements.SetName("/CS", "/DeviceRGB"); + else + group.Elements.SetName("/CS", "/DeviceCMYK"); + + // #PDF-A + group.Elements.SetName("/S", "/Transparency"); + + //False is default: group.Elements["/I"] = new PdfBoolean(false); + //False is default: group.Elements["/K"] = new PdfBoolean(false); + } } #endif @@ -653,8 +800,10 @@ internal override void WriteObject(PdfWriter writer) //!!!delTHHO 2018-04-05 if (_orientation == PageOrientation.Landscape) //!!!delTHHO 2018-04-05 MediaBox = mediaBox; // One step back - swap members in MediaBox for landscape orientation. +#if false // #PageOrientation if (_orientation == PageOrientation.Landscape && !_orientationSetByCodeForRotatedDocument) MediaBox = mediaBox; +#endif } /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPages.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPages.cs index c4c539ba..e4b9280e 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPages.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfPages.cs @@ -45,7 +45,7 @@ public PdfPage this[int index] get { if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index), index, PSSR.PageIndexOutOfRange); + throw new ArgumentOutOfRangeException(nameof(index), index, PsMsgs.PageIndexOutOfRange); var dict = (PdfDictionary)((PdfReference)PagesArray.Elements[index]).Value; if (dict is not PdfPage) @@ -98,7 +98,7 @@ public PdfPage Add(PdfPage page) /// public PdfPage Insert(int index) { - PdfPage page = new PdfPage(); + var page = new PdfPage(); Insert(index, page); return page; } @@ -121,7 +121,7 @@ public PdfPage Insert(int index, PdfPage page) for (int idx = 0; idx < count; idx++) { if (ReferenceEquals(this[idx], page)) - throw new InvalidOperationException(PSSR.MultiplePageInsert); + throw new InvalidOperationException(PsMsgs.MultiplePageInsert); } // Because the owner of the inserted page is this document we assume that the page was former part of it, @@ -179,7 +179,7 @@ public PdfPage Insert(int index, PdfPage page) _document.Events.OnPageAdded(_document, new PageEventArgs(_document) { Page = page, PageIndex = index, EventType = PageEventType.Imported }); } - PdfSharpLogHost.Logger.NewPdfPageAdded(_document?.Name); + PdfSharpLogHost.Logger.NewPdfPageCreated(_document?.Name); if (Owner.Settings.TrimMargins.AreSet) page.TrimMargins = Owner.Settings.TrimMargins; @@ -404,7 +404,7 @@ public void Remove(PdfPage page) /// public void RemoveAt(int index) { - PdfPage? page = PagesArray.Elements[index] as PdfPage; + var page = PagesArray.Elements[index] as PdfPage; PagesArray.Elements.RemoveAt(index); Elements.SetInteger(Keys.Count, PagesArray.Elements.Count); @@ -448,7 +448,7 @@ PdfPage ImportExternalPage(PdfPage importPage) if (importPage.Owner._openMode != PdfDocumentOpenMode.Import) throw new InvalidOperationException("A PDF document must be opened with PdfDocumentOpenMode.Import to import pages from it."); - PdfPage page = new PdfPage(_document); + var page = new PdfPage(_document); // ReSharper disable AccessToStaticMemberViaDerivedType for a better code readability. CloneElement(page, importPage, PdfPage.Keys.Resources, false); @@ -590,7 +590,7 @@ static PdfDictionary[] GetKids(PdfReference iref, PdfPage.InheritedValues values if (type == "/Page") { PdfPage.InheritValues(kid, values); - return new PdfDictionary[] { kid }; + return [kid]; } // If it has kids, it’s logically not going to be type page. @@ -599,7 +599,7 @@ static PdfDictionary[] GetKids(PdfReference iref, PdfPage.InheritedValues values // Type is required. If type is missing, assume it is "/Page" and hope it will work. // TODO Implement a "Strict" mode in PDFsharp and don’t do this in "Strict" mode. PdfPage.InheritValues(kid, values); - return new PdfDictionary[] { kid }; + return [kid]; } #else @@ -612,7 +612,7 @@ static PdfDictionary[] GetKids(PdfReference iref, PdfPage.InheritedValues values Debug.Assert(kid.Elements.GetName(Keys.Type) == "/Pages"); PdfPage.InheritValues(kid, ref values); - List list = new(); + List list = []; var kids = kid.Elements["/Kids"] as PdfArray; if (kids == null) @@ -694,7 +694,7 @@ public PdfPage Current get { if (_index == -1 || _index >= _list.Count) - throw new InvalidOperationException(PSSR.ListEnumCurrentOutOfRange); + throw new InvalidOperationException(PsMsgs.ListEnumCurrentOutOfRange); return _currentElement ?? throw new InvalidOperationException("Current called before MoveNext."); } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfRectangle.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfRectangle.cs index 622b4147..da5019c2 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfRectangle.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfRectangle.cs @@ -7,6 +7,7 @@ #if WPF using System.Windows.Media; #endif +using PdfSharp.Internal; using PdfSharp.Drawing; using PdfSharp.Pdf.Advanced; using PdfSharp.Pdf.IO; @@ -116,7 +117,7 @@ internal PdfRectangle(PdfItem item) var array = item as PdfArray; if (array == null) - throw new InvalidOperationException(PSSR.UnexpectedTokenInPdfFile); + throw new InvalidOperationException(PsMsgs.UnexpectedTokenInPdfFile); _x1 = array.Elements.GetReal(0); _y1 = array.Elements.GetReal(1); diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfString.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfString.cs index 9d83a5ce..f60b4958 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfString.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/PdfString.cs @@ -9,6 +9,7 @@ namespace PdfSharp.Pdf { // TODO: Make code more readable with PDF 1.7 strings: text string, ASCII string, byte string etc. + // See [xx]() /// /// Determines the encoding of a PdfString or PdfStringObject. @@ -240,16 +241,15 @@ internal static bool TryRereadAsUnicode(ref string? value, ref PdfStringFlags fl static bool TryRereadAsUnicode(ref string? value) { // UTF-16BE Unicode strings start with U+FEFF ("þÿ"). There can be empty strings with UTF-16BE prefix. -#if NET6_0_OR_GREATER || true + // Old code: + // if (value.Length >= 2 && value[0] == '\xFE' && value[1] == '\xFF') + // // Check for UTF-16BE encoding. // --- // Fun fact (Jan 2024): The following line of code was originally suggested by ReSharper, but the new // JetBrains AI Assistant considered it as illegal C# because of '..' in the array pattern. // ChatGPT 4 however explains the next line correctly. if (value is ['\xFE', '\xFF', ..]) -#else - if (value.Length >= 2 && value[0] == '\xFE' && value[1] == '\xFF') -#endif { #if DEBUG && true // Q: Does this code compile on every target framework? @@ -277,13 +277,12 @@ static bool TryRereadAsUnicode(ref string? value) return true; } -#if false // UTF-16LE is not defined as valid text string encoding in PDF reference. - // Adobe Reader also supports UTF-16LE. -#if NET6_0_OR_GREATER || true +#if true // UTF-16LE is not defined as valid text string encoding in PDF reference. if (value is ['\xFF', '\xFE', ..]) + throw new NotImplementedException("Found UTF-16LE string. Please send us the PDF file and we will fix it (issues (at) pdfsharp.net)."); #else - if (value.Length >= 2 && value[0] == '\xFF' && value[1] == '\xFE') -#endif + // Adobe Reader also supports UTF-16LE. + if (value is ['\xFF', '\xFE', ..]) { // Combine two ANSI characters to get one Unicode character. var temp = new StringBuilder(value); @@ -307,11 +306,7 @@ static bool TryRereadAsUnicode(ref string? value) #endif // UTF-8 Unicode strings start with U+EFBBBF (""). -#if NET6_0_OR_GREATER || true if (value is ['\xEF', '\xBB', '\xBF', ..]) -#else - if (value.Length >= 3 && value[0] == '\xEF' && value[1] == '\xBB' && value[2] == '\xBF') -#endif { // UTF8 is not implemented as Encoding for PdfStrings. After conversion, value holds the UTF-16 representation. // We return true, so it will be handled as UTF-16 from now. @@ -340,8 +335,9 @@ public override string ToString() #endif } +#if true_ /// - /// Hack for document encoded bookmarks. + /// H/ack for document encoded bookmarks. /// public string ToStringFromPdfDocEncoded() { @@ -367,9 +363,10 @@ public string ToStringFromPdfDocEncoded() sb.Append(bytes[idx]); return sb.ToString(); } +#endif static readonly char[] Encode = - { + [ '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', '\x1E', '\x1F', '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', '\x28', '\x29', '\x2A', '\x2B', '\x2C', '\x2D', '\x2E', '\x2F', @@ -385,8 +382,8 @@ public string ToStringFromPdfDocEncoded() '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF', '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF', - '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF', - }; + '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF' + ]; [Conditional("DEBUG")] static void AssertRawEncoding(string s) diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/enums/PdfFontColoredGlyphs.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/enums/PdfFontColoredGlyphs.cs new file mode 100644 index 00000000..ca151c6f --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Pdf/enums/PdfFontColoredGlyphs.cs @@ -0,0 +1,27 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +namespace PdfSharp.Pdf +{ + /// + /// Specifies whether the glyphs of an XFont are rendered multicolored into PDF. + /// Useful for emoji fonts that have a COLR and a CPAL table. + /// + public enum PdfFontColoredGlyphs + { + /// + /// Glyphs are rendered monochrome. This is the default. + /// + None = 0, + + /// + /// Glyphs are rendered using color information from the version 0 of the fonts + /// COLR table. This option has no effect if the font has no COLR table or there + /// is no entry for a particular glyph index. + /// + Version0 = 1, + + // Note: Version1 is also possible, but with significantly more code. Version 1 + // uses extended graphical capabilities like gradient brushes and much more. + } +} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/PdfSharp.csproj b/src/foundation/src/PDFsharp/src/PdfSharp/PdfSharp.csproj index cefdd52c..3c4f39f7 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/PdfSharp.csproj +++ b/src/foundation/src/PDFsharp/src/PdfSharp/PdfSharp.csproj @@ -1,7 +1,8 @@  library - net6.0;netstandard2.0 + net6.0;net8.0;netstandard2.0 + PdfSharp CORE True @@ -12,6 +13,13 @@ true + + 0 + + + + 0 + 0 @@ -30,23 +38,22 @@ + + + + + - + - - - - - - @@ -54,8 +61,7 @@ - - + diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/PdfSharp.csproj.DotSettings b/src/foundation/src/PDFsharp/src/PdfSharp/PdfSharp.csproj.DotSettings index e9ed987a..9f8b5819 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/PdfSharp.csproj.DotSettings +++ b/src/foundation/src/PDFsharp/src/PdfSharp/PdfSharp.csproj.DotSettings @@ -2,8 +2,11 @@ True True + True + True True True True True - True \ No newline at end of file + True + True \ No newline at end of file diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/Adam7.cs b/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/Adam7.cs index b342498f..f0320fb2 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/Adam7.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/Adam7.cs @@ -13,24 +13,24 @@ internal static class Adam7 /// static readonly IReadOnlyDictionary PassToScanlineGridIndex = new Dictionary { - { 1, new []{ 0 } }, - { 2, new []{ 0 } }, - { 3, new []{ 4 } }, - { 4, new []{ 0, 4 } }, - { 5, new []{ 2, 6 } }, - { 6, new[] { 0, 2, 4, 6 } }, - { 7, new[] { 1, 3, 5, 7 } } + { 1, [0] }, + { 2, [0] }, + { 3, [4] }, + { 4, [0, 4] }, + { 5, [2, 6] }, + { 6, [0, 2, 4, 6] }, + { 7, [1, 3, 5, 7] } }; static readonly IReadOnlyDictionary PassToScanlineColumnIndex = new Dictionary { - { 1, new []{ 0 } }, - { 2, new []{ 4 } }, - { 3, new []{ 0, 4 } }, - { 4, new []{ 2, 6 } }, - { 5, new []{ 0, 2, 4, 6 } }, - { 6, new []{ 1, 3, 5, 7 } }, - { 7, new []{ 0, 1, 2, 3, 4, 5, 6, 7 } } + { 1, [0] }, + { 2, [4] }, + { 3, [0, 4] }, + { 4, [2, 6] }, + { 5, [0, 2, 4, 6] }, + { 6, [1, 3, 5, 7] }, + { 7, [0, 1, 2, 3, 4, 5, 6, 7] } }; /* diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/HeaderValidationResult.cs b/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/HeaderValidationResult.cs index 80537eaa..3c4a2be4 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/HeaderValidationResult.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/HeaderValidationResult.cs @@ -6,7 +6,8 @@ namespace PdfSharp.BigGustave { internal readonly struct HeaderValidationResult { - public static readonly byte[] ExpectedHeader = { + public static readonly byte[] ExpectedHeader = + [ 137, 80, 78, @@ -15,7 +16,7 @@ internal readonly struct HeaderValidationResult 10, 26, 10 - }; + ]; public int Byte1 { get; } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/ImageHeader.cs b/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/ImageHeader.cs index 92fe2f83..3a99313f 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/ImageHeader.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/PngLib/ImageHeader.cs @@ -12,17 +12,18 @@ namespace PdfSharp.BigGustave /// public readonly struct ImageHeader { - internal static readonly byte[] HeaderBytes = { + internal static readonly byte[] HeaderBytes = + [ 73, 72, 68, 82 - }; + ]; static readonly IReadOnlyDictionary> PermittedBitDepths = new Dictionary> { - {ColorType.None, new HashSet {1, 2, 4, 8, 16}}, - {ColorType.ColorUsed, new HashSet {8, 16}}, - {ColorType.PaletteUsed | ColorType.ColorUsed, new HashSet {1, 2, 4, 8}}, - {ColorType.AlphaChannelUsed, new HashSet {8, 16}}, - {ColorType.AlphaChannelUsed | ColorType.ColorUsed, new HashSet {8, 16}}, + {ColorType.None, [1, 2, 4, 8, 16] }, + {ColorType.ColorUsed, [8, 16] }, + {ColorType.PaletteUsed | ColorType.ColorUsed, [1, 2, 4, 8] }, + {ColorType.AlphaChannelUsed, [8, 16] }, + {ColorType.AlphaChannelUsed | ColorType.ColorUsed, [8, 16] }, }; /// diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Properties/GlobalDeclarations.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Properties/GlobalDeclarations.cs index c8a1ebbb..8b461870 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Properties/GlobalDeclarations.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Properties/GlobalDeclarations.cs @@ -2,6 +2,8 @@ // See the LICENSE file in the solution root for more information. global using System.IO; +global using PdfSharp.Internal; + #if USE_LONG_SIZE global using SizeType = System.Int64; diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Properties/PdfSharpProductVersionInformation.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Properties/PdfSharpProductVersionInformation.cs index c807973e..11602a9f 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Properties/PdfSharpProductVersionInformation.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Properties/PdfSharpProductVersionInformation.cs @@ -1,6 +1,8 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. +#pragma warning disable 0436 + namespace PdfSharp { /// @@ -221,8 +223,8 @@ public static class PdfSharpProductVersionInformation // Hybrid - for testing only public const string Technology = "-h"; #error Should not come here anymore. May be revived in the future. -#elif UWP - // UWP - Universal Windows Platform +#elif WUI + // WUI - Universal Windows Platform public const string Technology = "-uwp"; #endif } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Resources/Messages.de.restext b/src/foundation/src/PDFsharp/src/PdfSharp/Resources/Messages.de.restext deleted file mode 100644 index c463242b..00000000 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Resources/Messages.de.restext +++ /dev/null @@ -1,20 +0,0 @@ -; PDFsharp string resources (German) -; -; Must be saved as Unicode (UTF-8 with signature) to force resgen.exe to process German umlauts. - -; ----- General Messages -------------------------------------------------------------------------- - -SampleMessage1 = Das ist Beispielnachricht 1 (de). -SampleMessage2 = Das ist Beispielnachricht 2: {0}. - -; ----- XGraphics Messages ------------------------------------------------------------------------ - -; ----- Pdf Messages ------------------------------------------------------------------------------ - -NameMustStartWithSlash = Ein PDF-Name muss mit einem Schrägstrich ('/') beginnen. -UserOrOwnerPasswordRequired = Zum Verschlüsseln des Dokuments muss ein Kennwort zum Öffnen (UserPassword) oder ein Berechtigungskennwort (OwnerPassword) gesetzt sein. - -; ----- PdfParser Messages ------------------------------------------------------------------------ - -UnexpectedToken = Token '{0}' wird an dieser Stelle nicht erwartet. -UnknownEncryption = Das PDF-Dokument ist mit einer von PDFsharp nicht unterstützten Verschlüsselung geschützt. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Resources/Messages.restext b/src/foundation/src/PDFsharp/src/PdfSharp/Resources/Messages.restext deleted file mode 100644 index e47d27ff..00000000 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Resources/Messages.restext +++ /dev/null @@ -1,20 +0,0 @@ -; PDFsharp string resources (English) -; -; - -; ----- General Messages -------------------------------------------------------------------------- - -SampleMessage1 = This is sample message 1 (2.0). -SampleMessage2 = This is sample message 2: {0}. - -; ----- XGraphics Messages ------------------------------------------------------------------------ - -; ----- Pdf Messages ------------------------------------------------------------------------------ - -NameMustStartWithSlash = A PDF name must start with a slash ('/'). -UserOrOwnerPasswordRequired = At least a user or an owner password is required to encrypt the document. - -; ----- PdfParser Messages ------------------------------------------------------------------------ - -UnexpectedToken = Token '{0}' was not expected. -UnknownEncryption = The PDF document is protected with an encryption not supported by PDFsharp. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Resources/sRGB2014.icc b/src/foundation/src/PDFsharp/src/PdfSharp/Resources/sRGB2014.icc new file mode 100644 index 0000000000000000000000000000000000000000..49afbfef10f22a1832590b68369d2f248ea553b9 GIT binary patch literal 3024 zcmb`Jc{r5o8^@pboqe;-klom~#=Z=)?<7n1RL0C;EQ4W?v`H$Qlq6e;oU(N2=!6`p zq_j9fq0&N*O8IqkN}I~>9j@P{b6vkb&vRYx^M3C8x$pP6pZoda{Q^K51jvAqCy}2f z2yl0zhlYjIaZeGKxM&3c7CSY0nf@_DE7pfmuw>n3hyBge}>zEF^|hhw$p<`Vm43NktlHVq|Q#Wc`bi=uVbDr*Q%R@mv7f?y!Y| z^kpAf^uhola$__g2b6(2&;bl!0xW?IZ~(5r3;2RS5C%2@Hi!j@Kmam8HrNI7Kmj-i zj(`eK4eCGxXa=pI9dv;!;5xVs2Ehmz2NPf#yasdN16Y6{2nSIhDkKM~K$?&~WCAfE zJIEDU3k5)7P$U!s@gX6U4ef>spkk;3s(~7yU!e=o73d~31U-Nzp&96J=nIU3$uJF8 zg0)~nm^L%}Fw^fA^LPfRE#29trw!<1r9Va{W&VMZ|1m=9PiRtBq$wZwX0 z!?1DKt=K~BF>DL=GIj_%g`LOYaB?_(oGs25$HJxI@^Iz2Gq_8*VcazC6P|=u!JFXS z@ZoqqJ_lclZ^U=whw(4)3j_&*Cc&EEOW+W;5Q+$OgigX8!ZcxlC`r^N+7bhaal~E3 zGGa6F8u1bF9f?FzBUzFBNj%a{QW@zi=>}<%^qDM0)+0NUBgjJX0rF|`W%2{^I|_xO zMRA~nQ_?60C=HaWlqZx=VpK5$F;6j$*bcEuu{N<`u{YubaZPbY@lE1c;-%u}#P5jD zN)RNpB%CE!65AyzB`!#eNz6-9C5m zB-1K0D)VKP(kjPQ+*SKmHLn_8^-)$q);f{g-OAzz_Y;h`d|sHYg9xK;6_V!z_NlCqM!QnFIH(p9BdWf^4$ z67?SSISmyJAB}8{CXI)h1Wl%9tmaY8KFyC>+FBu6d$roNUTVu~dunHC zH)%i8q3GD_r0CS@+|$MCGIis1kLeET!FuL;v3iwycl2R>3w@scG5w*{nAKLR`KxPJ zk1@y$M@BlMi7{y)W3bjB$DrNdjiH8NxZxqgKEv-u=0*udbw=aHQpR4!ImVsFf1Bu; zuuUpW?wL|d-As3wc9_03(>LRq9XGpgPBr&2-)r7u{>{SDLSWHsF=MG=8EIK%ImV{PDV}wr}Iu9ovod>IbU``xwyOJy9~HW zxdypbxIS@HbBl3na+`BEci-xM*#qO@?QzIs%u~se?b+Zt=Vj@&&8yd&?7iN*!u#1; zy|se1oj$OSm(O9JN9#1#@z=Hc0$)$x!@iIGwEa^2e)q@v`}tS;KMybt$PVaRPhG!x zedGEMflh%%f#X3sLBgP(VDaFH;D+FjAub`sArqm7q1!@lhslTW!aBln;lbgj!sj=* zZaA`GI>J06FJg3~_QuSOH#f;|O4xL9v-oD#=5vvl$dJg!$geD4RxN8j$}_4eYL4y9 zKFWU0ap072X1KQ8V(yD*+vwuxmoc_6hht`9?PE)0XL-)N3f|i|kGSf%kMX|or{fnB zLK0dM@rjX%7x+^Acz$n^a#Ci}P_lklKhhQM>Ze1S!z~VeUx}qcyyv{ZCOXTM)|?=uNAQsBb82-EmewD`>Q@4 z;~X14?r^-hTB*9A`pXI4iTgF~HEp$8wWTMqC(}uM0h$Hl62xH~9T@mugq#Md^!0-Nf$P?!`-4 zm*y`gU!J`Zb7iV$bIqdq~gGTRGoA)2d|5UxvdGp&}4uAE}h0aaC6}(;i zyYQXdyVLK@-uKM=%|H2&_+jB={wKLl^`Dua`@V#Hd9jf375BC5o9?&H@7~`ZEha85 z{-8k&JYAjX7RFW<77P=HG2Mk5%@QW0(M8J6IVmAYD4?%TX0f?+23;gpmIcJWHm~TE zsB!?>_W&UKaK(pgBT{F`Sk`1q_=ApIvi~>1Kja-poFc8Ycg2@f3jlK-0Mx-$UJPB7 zEaT{Co~CjhDoy^Z4|Cv`LizZ;q8ZSF~{&Hxtp1 zNS#T^TLiqA*fhE)KaDHkvqTlK5|(a9AgVDnNsz`9Ca$I)0svP6z_+5s#f6&1#cxP2P~!kx7XBBF2+<<| literal 0 HcmV?d00001 diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/UniversalAccessibility/StructureBuilder.cs b/src/foundation/src/PDFsharp/src/PdfSharp/UniversalAccessibility/StructureBuilder.cs index 61781de1..edc7b03c 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/UniversalAccessibility/StructureBuilder.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/UniversalAccessibility/StructureBuilder.cs @@ -25,7 +25,7 @@ internal StructureBuilder(UAManager uaManager) /// The structure type to be created. public void BeginElement(PdfGroupingElementTag tag) { - BeginGroupingElement(tag.ToString()); + BeginGroupingElement(TagToString(tag)); } /// @@ -46,7 +46,7 @@ public void BeginGroupingElement(string tag) /// The structure type to be created. public void BeginElement(PdfBlockLevelElementTag tag) { - BeginBlockLevelElement(tag.ToString()); + BeginBlockLevelElement(TagToString(tag)); } /// @@ -67,7 +67,7 @@ public void BeginBlockLevelElement(string tag) /// The structure type to be created. public void BeginElement(PdfInlineLevelElementTag tag) { - BeginInlineLevelElement(tag.ToString()); + BeginInlineLevelElement(TagToString(tag)); } /// @@ -90,7 +90,7 @@ public void BeginInlineLevelElement(string tag) /// The element’s bounding box. public void BeginElement(PdfIllustrationElementTag tag, string altText, XRect boundingBox) { - BeginIllustrationElement(tag.ToString(), altText, boundingBox); + BeginIllustrationElement(TagToString(tag), altText, boundingBox); } /// @@ -125,7 +125,7 @@ public void BeginArtifact() public void BeginElement(PdfLinkAnnotation linkAnnotation, string altText) { EndMarkedContentsWithId(); - var ste = CreateStructureElement(PdfInlineLevelElementTag.Link.ToString()); + var ste = CreateStructureElement(TagToString(PdfInlineLevelElementTag.Link)); var item = new InlineLevelItem(ste) { EndMark = true }; _elementStack.Push(item); item.BeginItem(); @@ -173,14 +173,15 @@ public void SetExpandedText(string expandedText) => _elementStack.MostInnerStructureElement.Elements.SetString(PdfStructureElement.Keys.E, expandedText); /// - /// Sets the content of the "/Lang" (language) key. The chosen language is used for all children of the current structure element until a child has a new language defined. + /// Sets the content of the "/Lang" (language) key. + /// The chosen language is used for all children of the current structure element until a child has a new language defined. /// /// The language of the structure element and its children. public void SetLanguage(string language) => _elementStack.MostInnerStructureElement.Elements.SetString(PdfStructureElement.Keys.Lang, language); /// - /// Sets the rowspan of a table cell. + /// Sets the row span of a table cell. /// /// The number of spanning cells. public void SetRowSpan(int rowSpan) @@ -334,10 +335,10 @@ void AddToParentTree(PdfStructureElement ste, int mcid) // Get /StructParents of Page. var structParentsItem = UaManager.CurrentPage.Elements.GetValue(PdfPage.Keys.StructParents); - var hasStructparents = structParentsItem != null; + var hasStructParents = structParentsItem != null; // Create it, if necessary. - if (!hasStructparents) + if (!hasStructParents) { UaManager.CurrentPage.Elements.SetInteger(PdfPage.Keys.StructParents, parentTreeNextKey); structTreeRoot.Elements.SetInteger(PdfStructureTreeRoot.Keys.ParentTreeNextKey, parentTreeNextKey + 1); @@ -347,7 +348,7 @@ void AddToParentTree(PdfStructureElement ste, int mcid) // Get the PdfArray for this page in parentTreeRootNums. var isInParentTree = parentTreeRootNums.Elements.OfType().Any(x => x.Value == structParents.Value); - Debug.Assert(hasStructparents == isInParentTree); + Debug.Assert(hasStructParents == isInParentTree); // Create it, if necessary. if (!isInParentTree) @@ -501,12 +502,92 @@ internal void OnDraw() current.OnDraw(); } - internal ContentWriter Content { get { return new ContentWriter(UaManager.CurrentGraphics); } } + internal ContentWriter Content => new(UaManager.CurrentGraphics); + +#pragma warning disable CS0618 // Type or member is obsolete + + string TagToString(PdfGroupingElementTag tag) + { + return tag switch + { + PdfGroupingElementTag.Document => nameof(PdfGroupingElementTag.Document), + PdfGroupingElementTag.Part => nameof(PdfGroupingElementTag.Part), + PdfGroupingElementTag.Art or PdfGroupingElementTag.Article => nameof(PdfGroupingElementTag.Art), + PdfGroupingElementTag.Sect or PdfGroupingElementTag.Section => nameof(PdfGroupingElementTag.Sect), + PdfGroupingElementTag.Div or PdfGroupingElementTag.Division => nameof(PdfGroupingElementTag.Div), + PdfGroupingElementTag.BlockQuote or PdfGroupingElementTag.BlockQuotation => nameof(PdfGroupingElementTag.BlockQuote), + PdfGroupingElementTag.Caption => nameof(PdfGroupingElementTag.Caption), + PdfGroupingElementTag.TOC or PdfGroupingElementTag.TableOfContents => nameof(PdfGroupingElementTag.TOC), + PdfGroupingElementTag.TOCI or PdfGroupingElementTag.TableOfContentsItem => nameof(PdfGroupingElementTag.TOCI), + PdfGroupingElementTag.Index => nameof(PdfGroupingElementTag.Index), + PdfGroupingElementTag.NonStruct or PdfGroupingElementTag.NonstructuralElement => nameof(PdfGroupingElementTag.NonStruct), + PdfGroupingElementTag.Private or PdfGroupingElementTag.PrivateElement => nameof(PdfGroupingElementTag.Private), + _ => throw new InvalidOperationException($"Invalid tag value '{(int)tag}'") + }; + } + + string TagToString(PdfBlockLevelElementTag tag) + { + return tag switch + { + PdfBlockLevelElementTag.P or PdfBlockLevelElementTag.Paragraph => nameof(PdfBlockLevelElementTag.P), + PdfBlockLevelElementTag.H or PdfBlockLevelElementTag.Heading => nameof(PdfBlockLevelElementTag.H), + PdfBlockLevelElementTag.H1 or PdfBlockLevelElementTag.Heading1 => nameof(PdfBlockLevelElementTag.H1), + PdfBlockLevelElementTag.H2 or PdfBlockLevelElementTag.Heading2 => nameof(PdfBlockLevelElementTag.H2), + PdfBlockLevelElementTag.H3 or PdfBlockLevelElementTag.Heading3 => nameof(PdfBlockLevelElementTag.H3), + PdfBlockLevelElementTag.H4 or PdfBlockLevelElementTag.Heading4 => nameof(PdfBlockLevelElementTag.H4), + PdfBlockLevelElementTag.H5 or PdfBlockLevelElementTag.Heading5 => nameof(PdfBlockLevelElementTag.H5), + PdfBlockLevelElementTag.H6 or PdfBlockLevelElementTag.Heading6 => nameof(PdfBlockLevelElementTag.H6), + PdfBlockLevelElementTag.L or PdfBlockLevelElementTag.List => nameof(PdfBlockLevelElementTag.L), + PdfBlockLevelElementTag.Lbl or PdfBlockLevelElementTag.Label => nameof(PdfBlockLevelElementTag.Lbl), + PdfBlockLevelElementTag.LI or PdfBlockLevelElementTag.ListItem => nameof(PdfBlockLevelElementTag.LI), + PdfBlockLevelElementTag.LBody or PdfBlockLevelElementTag.ListBody => nameof(PdfBlockLevelElementTag.LBody), + PdfBlockLevelElementTag.Table => nameof(PdfBlockLevelElementTag.Table), + PdfBlockLevelElementTag.TR or PdfBlockLevelElementTag.TableRow => nameof(PdfBlockLevelElementTag.TR), + PdfBlockLevelElementTag.TH or PdfBlockLevelElementTag.TableHeaderCell => nameof(PdfBlockLevelElementTag.TH), + PdfBlockLevelElementTag.TD or PdfBlockLevelElementTag.TableDataCell => nameof(PdfBlockLevelElementTag.TD), + PdfBlockLevelElementTag.THead or PdfBlockLevelElementTag.TableHeadRowGroup => nameof(PdfBlockLevelElementTag.THead), + PdfBlockLevelElementTag.TBody or PdfBlockLevelElementTag.TableBodyRowGroup => nameof(PdfBlockLevelElementTag.TBody), + PdfBlockLevelElementTag.TFoot or PdfBlockLevelElementTag.TableFooterRowGroup => nameof(PdfBlockLevelElementTag.TFoot), + _ => throw new InvalidOperationException($"Invalid tag value '{(int)tag}'") + }; + } + + string TagToString(PdfInlineLevelElementTag tag) + { + return tag switch + { + PdfInlineLevelElementTag.Span => nameof(PdfInlineLevelElementTag.Span), + PdfInlineLevelElementTag.Quote or PdfInlineLevelElementTag.Quotation => nameof(PdfInlineLevelElementTag.Quote), + PdfInlineLevelElementTag.Note => nameof(PdfInlineLevelElementTag.Note), + PdfInlineLevelElementTag.Reference => nameof(PdfInlineLevelElementTag.Reference), + PdfInlineLevelElementTag.BibEntry or PdfInlineLevelElementTag.BibliographyEntry => nameof(PdfInlineLevelElementTag.BibEntry), + PdfInlineLevelElementTag.Code => nameof(PdfInlineLevelElementTag.Code), + PdfInlineLevelElementTag.Link => nameof(PdfInlineLevelElementTag.Link), + PdfInlineLevelElementTag.Annot or PdfInlineLevelElementTag.Annotation => nameof(PdfInlineLevelElementTag.Annot), + PdfInlineLevelElementTag.Ruby => nameof(PdfInlineLevelElementTag.Ruby), + PdfInlineLevelElementTag.Warichu => nameof(PdfInlineLevelElementTag.Warichu), + _ => throw new InvalidOperationException($"Invalid tag value '{(int)tag}'") + }; + } + + string TagToString(PdfIllustrationElementTag tag) + { + return tag switch + { + PdfIllustrationElementTag.Figure => nameof(PdfIllustrationElementTag.Figure), + PdfIllustrationElementTag.Formula => nameof(PdfIllustrationElementTag.Formula), + PdfIllustrationElementTag.Form => nameof(PdfIllustrationElementTag.Form), + _ => throw new InvalidOperationException($"Invalid tag value '{(int)tag}'") + }; + } + +#pragma warning restore CS0618 // Type or member is obsolete /// /// Used to write text directly to the content stream. /// - public class ContentWriter + internal class ContentWriter { /// /// Constructor. diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/UniversalAccessibility/UAManager.cs b/src/foundation/src/PDFsharp/src/PdfSharp/UniversalAccessibility/UAManager.cs index 23456e35..8dd4f1f2 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/UniversalAccessibility/UAManager.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/UniversalAccessibility/UAManager.cs @@ -10,7 +10,8 @@ namespace PdfSharp.UniversalAccessibility { /// - /// This is just a scratch. + /// The UAManager adds PDF/UA (Accessibility) support to a PdfDocument. + /// By using its StructureBuilder, you can easily build up the structure tree to give hints to screen readers about how to read the document. /// // ReSharper disable once InconsistentNaming public class UAManager @@ -21,7 +22,7 @@ public class UAManager /// The PDF document. UAManager(PdfDocument document) { - document._uaManager = this; + //document._uaManager = this; done in ForDocument _document = document; // Set default language to English. @@ -78,12 +79,10 @@ public class UAManager public PdfStructureElement StructureTreeElementDocument { get; set; } /// - /// Gets the Universal Accessibility Manager for the document. + /// Gets or creates the Universal Accessibility Manager for the specified document. /// - public static UAManager ForDocument(PdfDocument document) - { - return document._uaManager ?? new UAManager(document); - } + public static UAManager ForDocument(PdfDocument document) + => document._uaManager ??= new UAManager(document); /// /// Gets the structure builder. @@ -104,9 +103,7 @@ void OnPageAdded(object sender, PageEventArgs e) } void OnPageRemoved(object sender, PageEventArgs e) - { - throw new InvalidOperationException("Cannot handle page removing."); - } + => throw new InvalidOperationException("Cannot handle page removing."); void OnPageGraphicsCreated(object sender, PageGraphicsEventArgs e) { diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/Windows/VisualPresenter.cs b/src/foundation/src/PDFsharp/src/PdfSharp/Windows/VisualPresenter.cs index 5e196745..9d812b7d 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/Windows/VisualPresenter.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/Windows/VisualPresenter.cs @@ -22,16 +22,14 @@ public class VisualPresenter : FrameworkElement /// public VisualPresenter() { - _children = new VisualCollection(this); + _children = new(this); } /// /// Gets the number of visual child elements within this element. /// protected override int VisualChildrenCount - { - get { return _children.Count; } - } + => _children.Count; /// /// Overrides , and returns a child at the specified index from a collection of child elements. @@ -39,7 +37,7 @@ protected override int VisualChildrenCount protected override Visual GetVisualChild(int index) { if (index < 0 || index >= _children.Count) - throw new ArgumentOutOfRangeException("index"); + throw new ArgumentOutOfRangeException(nameof(index)); return _children[index]; } @@ -48,9 +46,7 @@ protected override Visual GetVisualChild(int index) /// Gets the children collection. /// public VisualCollection Children - { - get { return _children; } - } + => _children; readonly VisualCollection _children; } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/root/Capabilities.cs b/src/foundation/src/PDFsharp/src/PdfSharp/root/Capabilities.cs index 4bce88fb..89ebfa7f 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/root/Capabilities.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/root/Capabilities.cs @@ -49,6 +49,7 @@ public static class Capabilities { static Capabilities() { + _ = PdfSharp.Internal.FooBarEnum3.xxx; #if DEBUG_ var x = Capabilities.IsAvailable.GlyphsToPathFrom(new XFontFamily("test")); @@ -68,7 +69,7 @@ public static void ResetAll() PdfSharpLogHost.Logger.LogInformation("All PDFsharp capability settings are about to be reset."); Action.GlyphsToPath = FeatureNotAvailableBehavior.SilentlyIgnore; - + // ... TODO } @@ -142,10 +143,28 @@ public static string BuildTag #endif public static string Framework -#if NET6_0_OR_GREATER +#if NET10_0_OR_GREATER + => "10.0"; +#elif NET9_0_OR_GREATER + => "9.0"; +#elif NET8_0_OR_GREATER + => "8.0"; +#elif NET7_0_OR_GREATER + => "7.0"; +#elif NET6_0_OR_GREATER => "6.0"; -#else +#elif NET481 + => "4.8"; +#elif NET472 => "4.7"; +#elif NET462 + => "4.6"; +#elif NETSTANDARD2_1 + => "2.1"; +#elif NETSTANDARD2_0 + => "2.0"; +#else + => "0.0"; #endif } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/root/PSSR.cs b/src/foundation/src/PDFsharp/src/PdfSharp/root/PSSR.cs deleted file mode 100644 index 388eb9b2..00000000 --- a/src/foundation/src/PDFsharp/src/PdfSharp/root/PSSR.cs +++ /dev/null @@ -1,271 +0,0 @@ -// PDFsharp - A .NET library for processing PDF -// See the LICENSE file in the solution root for more information. - -using PdfSharp.Drawing; -using PdfSharp.Pdf; - -namespace PdfSharp -{ - /// - /// The Pdf-Sharp-String-Resources. - /// - // ReSharper disable once InconsistentNaming - static class PSSR - { - // How to use: - // Create a function or property for each message text, depending on how many parameters are - // part of the message. For the beginning, type plain English text in the function or property. - // The use of functions is safe when a parameter must be changed. The compiler tells you all - // places in your code that must be modified. - // For localization, create an enum value for each function or property with the same name. Then - // create localized message files with the enum values as messages identifiers. In the properties - // and functions all text is replaced by Format or GetString functions with the corresponding enum value - // as first parameter. The use of enums ensures that typing errors in message resource names are - // simply impossible. Use the TestResourceMessages function to ensure that each enum value has an - // appropriate message text. - - #region Helper functions - ///// - ///// Loads the message from the resource associated with the enum type and formats it - ///// using 'string.Format'. Because this function is intended to be used during error - ///// handling it never raises an exception. - ///// - ///// The type of the parameter identifies the resource - ///// and the name of the enum identifies the message in the resource. - ///// Parameters passed through 'string.Format'. - ///// The formatted message. - //public static string Format(PSMsgID id, params object[] args) - //{ - // string message; - // try - // { - // message = GetString(id); - // message = message != null ? Format(message, args) : "INTERNAL ERROR: Message not found in resources."; - // return message; - // } - // catch (Exception ex) - // { - // message = String.Format("UNEXPECTED ERROR while formatting message with ID {0}: {1}", id.ToString(), ex.ToString()); - // } - // return message; - //} - - //public static string Format(string format, params object[] args) - //{ - // if (format == null) - // throw new ArgumentNullException(nameof(format)); - - // string message; - // try - // { - // message = String.Format(format, args); - // } - // catch (Exception ex) - // { - // message = $"UNEXPECTED ERROR while formatting message '{format}': {ex}"; - // } - // return message; - //} - - ///// - ///// Gets the localized message identified by the specified DomMsgID. - ///// - //public static string GetString(PSMsgID id) - //{ - // return ResMngr.GetString(id.ToString()); - //} - - #endregion - - #region General messages - - public static string IndexOutOfRange => "The index is out of range."; - - public static string ListEnumCurrentOutOfRange => "Enumeration out of range."; - - public static string PageIndexOutOfRange => "The index of a page is out of range."; - - public static string OutlineIndexOutOfRange => "The index of an outline is out of range."; - - public static string SetValueMustNotBeNull => "The set value property must not be null."; - - public static string InvalidValue(int val, string name, int min, int max) - => Invariant($"{val} is not a valid value for {name}. {name} should be greater than or equal to {min} and less than or equal to {max}."); - - public static string ObsoleteFunctionCalled => "The function is obsolete and must not be called."; - - public static string OwningDocumentRequired => "The PDF object must belong to a PdfDocument, but property Document is null."; - - public static string FileNotFound(string path) => $"The file '{path}' does not exist."; - - public static string FontDataReadOnly => "Font data is read-only."; - - public static string ErrorReadingFontData => "Error while parsing an OpenType font."; - - #endregion - - #region XGraphics specific messages - - // ----- XGraphics ---------------------------------------------------------------------------- - - public static string PointArrayEmpty - => "The PointF array must not be empty."; - - public static string PointArrayAtLeast(int count) - => Invariant($"The point array must contain {count} or more points."); - - public static string NeedPenOrBrush => "XPen or XBrush or both must not be null."; - - public static string CannotChangeImmutableObject(string typename) - => $"You cannot change this immutable {typename} object."; - - public static string FontAlreadyAdded(string fontName) - => $"FontFace with the name '{fontName}' already added to font collection."; - - public static string NotImplementedForFontsRetrievedWithFontResolver(string name) - => $"Not implemented for font '{name}', because it was retrieved with font resolver."; - - #endregion - - #region PDF specific messages - - // ----- PDF ---------------------------------------------------------------------------------- - - public static string InvalidPdf => "The file is not a valid PDF document."; - - public static string InvalidVersionNumber => "Invalid version number. Valid values are 12, 13, and 14."; - - public static string CannotHandleXRefStreams => "Cannot handle cross-reference streams. The current implementation of PDFsharp cannot handle this PDF feature introduced with Acrobat 6."; - - public static string PasswordRequired => "A password is required to open the PDF document."; - - public static string InvalidPassword => "The specified password is invalid."; - - public static string OwnerPasswordRequired => "To modify the document the owner password is required"; - - public static string UserOrOwnerPasswordRequired => "At least a user or an owner password is required to encrypt the document."; - - public static string CannotModify => "The document cannot be modified."; - - public static string NameMustStartWithSlash => "A PDF name must start with a slash (/)."; - - public static string ImportPageNumberOutOfRange(int pageNumber, int maxPage, string path) - { - return String.Format("The page cannot be imported from document '{2}', because the page number is out of range. " + - "The specified page number is {0}, but it must be in the range from 1 to {1}.", pageNumber, maxPage, path); - } - - public static string MultiplePageInsert => "The page cannot be added to this document because the document already owned this page."; - - public static string UnexpectedTokenInPdfFile => "Unexpected token in PDF file. The PDF file may be corrupt. If it is not, please send us the file for service (issues (at) pdfsharp.net)."; - - public static string InappropriateColorSpace(PdfColorMode colorMode, XColorSpace colorSpace) - { - string mode; - switch (colorMode) - { - case PdfColorMode.Rgb: - mode = "RGB"; - break; - - case PdfColorMode.Cmyk: - mode = "CMYK"; - break; - - default: - mode = "(undefined)"; - break; - } - - string space; - switch (colorSpace) - { - case XColorSpace.Rgb: - space = "RGB"; - break; - - case XColorSpace.Cmyk: - space = "CMYK"; - break; - - case XColorSpace.GrayScale: - space = "grayscale"; - break; - - default: - space = "(undefined)"; - break; - } - return String.Format("The document requires color mode {0}, but a color is defined using {1}. " + - "Use only colors that match the color mode of the PDF document", mode, space); - } - - public static string CannotGetGlyphTypeface(string fontName) - { - return Invariant($"Cannot get a matching glyph typeface for font '{fontName}'."); - } - - // ----- PdfParser ---------------------------------------------------------------------------- - - public static string UnexpectedToken(string token) => $"Token '{token}' was not expected."; - //{ - // return Format(PSMsgID.UnexpectedToken, token); - // //return Format("Token '{0}' was not expected.", token); - //} - - #endregion - - #region Resource manager - - // /// - // /// Gets the resource manager for this module. - // /// - // public static ResourceManager ResMngr - // { - // get - // { - // if (_resmngr == null) - // { - // try - // { - // Lock.EnterFontFactory(); - // if (_resmngr == null) - // { - //#if true_ - // // Force the English language. - // System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; - //#endif - // _resmngr = new ResourceManager("PdfSharp.Resources.Messages", Assembly.GetExecutingAssembly()); - // } - // } - // finally { Lock.ExitFontFactory(); } - // } - // return _resmngr; - // } - // } - - // static ResourceManager _resmngr; - - ///// - ///// Writes all messages defined by PSMsgID. - ///// - //[Conditional("DEBUG")] - //public static void TestResourceMessages() - //{ - // string[] names = Enum.GetNames(typeof(PSMsgID)); - // foreach (string name in names) - // { - // string message = String.Format("{0}: '{1}'", name, ResMngr.GetString(name)); - // Debug.Assert(message != null); - // Debug.WriteLine(message); - // } - //} - - //static PSSR() - //{ - // TestResourceMessages(); - //} - - #endregion - } -} \ No newline at end of file diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/root/PdfSharpException.cs b/src/foundation/src/PDFsharp/src/PdfSharp/root/PdfSharpException.cs index 15bd8365..9c4b662b 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/root/PdfSharpException.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/root/PdfSharpException.cs @@ -1,12 +1,10 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. -using System; - namespace PdfSharp { /// - /// Base class of all exceptions in the PDFsharp frame work. + /// Base class of all exceptions in the PDFsharp library. /// public class PdfSharpException : Exception { diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/root/VersionInfo.cs b/src/foundation/src/PDFsharp/src/PdfSharp/root/VersionInfo.cs deleted file mode 100644 index 1b968548..00000000 --- a/src/foundation/src/PDFsharp/src/PdfSharp/root/VersionInfo.cs +++ /dev/null @@ -1,23 +0,0 @@ -// PDFsharp - A .NET library for processing PDF -// See the LICENSE file in the solution root for more information. - -namespace PdfSharp -{ - ///// - ///// Version info of this assembly. - ///// - //static class VersionInfo - //{ - // public const string Title = ProductVersionInfo.Title; - // public const string Description = ProductVersionInfo.Description; - // public const string Producer = ProductVersionInfo.Producer; - // public const string Version = ProductVersionInfo.Version; - // public const string Url = ProductVersionInfo.Url; - // public const string Configuration = ""; - // public const string Company = ProductVersionInfo.Company; - // public const string Product = ProductVersionInfo.Product; - // public const string Copyright = ProductVersionInfo.Copyright; - // public const string Trademark = ProductVersionInfo.Trademark; - // public const string Culture = ""; - //} -} diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/root/enums/PageOrientation.cs b/src/foundation/src/PDFsharp/src/PdfSharp/root/enums/PageOrientation.cs index 6ee09e4b..44d8264c 100644 --- a/src/foundation/src/PDFsharp/src/PdfSharp/root/enums/PageOrientation.cs +++ b/src/foundation/src/PDFsharp/src/PdfSharp/root/enums/PageOrientation.cs @@ -10,12 +10,14 @@ public enum PageOrientation { /// /// The default page orientation. + /// The top and bottom width is less than or equal to the + /// left and right side. /// - Portrait, + Portrait = 0, /// /// The width and height of the page are reversed. /// - Landscape, + Landscape = 1 } } diff --git a/src/foundation/src/PDFsharp/src/PdfSharp/root/enums/PageRotation.cs b/src/foundation/src/PDFsharp/src/PdfSharp/root/enums/PageRotation.cs new file mode 100644 index 00000000..fdeb783f --- /dev/null +++ b/src/foundation/src/PDFsharp/src/PdfSharp/root/enums/PageRotation.cs @@ -0,0 +1,31 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +namespace PdfSharp +{ + /// + /// Identifies the rotation of a page in a PDF document. + /// + public enum PageRotation + { + /// + /// The page is displayed with no rotation by a viewer. + /// + None = 0, + + /// + /// The page is displayed rotated by 90 degrees clockwise by a viewer. + /// + Rotate90DegreesRight = 90, + + /// + /// The page is displayed rotated by 180 degrees by a viewer. + /// + RotateUpsideDown = 180, + + /// + /// The page is displayed rotated by 270 degrees clockwise by a viewer. + /// + Rotate90DegreesLeft = 270, + } +} diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests-gdi/PdfSharp.Tests-gdi.csproj b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests-gdi/PdfSharp.Tests-gdi.csproj index 951f71dc..b9582bf3 100644 --- a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests-gdi/PdfSharp.Tests-gdi.csproj +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests-gdi/PdfSharp.Tests-gdi.csproj @@ -1,13 +1,13 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true true GDI + PDFsharp internal class RuntimeHelpers is visible in this assembly because of InternalsVisibleTo. + This conflics with mscorlib, and therefore it is disabled. --> CS1685,CS0436 True ..\..\..\..\..\StrongnameKey.snk @@ -42,6 +42,7 @@ + @@ -52,15 +53,29 @@ + + + + + + + + + + + + + + diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Build/CSharpFeaturesTests.cs b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Build/CSharpFeaturesTests.cs index 8d0f70fa..2debdd88 100644 --- a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Build/CSharpFeaturesTests.cs +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Build/CSharpFeaturesTests.cs @@ -17,7 +17,8 @@ namespace PdfSharp.Tests.Build { /// /// Test what features of C# 11 to C# 12 can be used with - /// .NET 6 and C# 11 to C# 12 with .NET 4.72 / .NET Standard 2.0. + /// .NET 6/8 and C# 11 to C# 12 with .NET 4.62 / .NET Standard 2.0. + /// Thats amazing! /// [Collection("PDFsharp")] public class CSharpFeaturesTests diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Build/ReleaseBuildTests.cs b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Build/ReleaseBuildTests.cs index 059e4567..1cd610d7 100644 --- a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Build/ReleaseBuildTests.cs +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Build/ReleaseBuildTests.cs @@ -9,6 +9,7 @@ using FluentAssertions; using PdfSharp.Drawing; using PdfSharp.Fonts; +using PdfSharp.Internal; using PdfSharp.Pdf; using PdfSharp.Pdf.Internal; using PdfSharp.Quality; @@ -33,18 +34,22 @@ public void Check_renamed_identifiers() #endif [Fact(Skip = "Do not run this test always.")] + //[Fact] public void Check_CS_files_for_non_ASCII_characters() { #if NET6_0_OR_GREATER || CORE return; #else +#if DEBUG + _ = BuildInformation.BuildVersionNumber; +#endif var folder = IOUtility.GetAssetsPath(); folder.Should().NotBeNull(); Debug.Assert(folder != null); folder = Path.Combine(folder, "../src/"); -#if true +#if true_ folder = @"D:\repos\emp\PDFsharp-COPY\"; #endif diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Drawing/images/ImageTests.cs b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Drawing/images/ImageTests.cs index 307b2c67..ed53cd0c 100644 --- a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Drawing/images/ImageTests.cs +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Drawing/images/ImageTests.cs @@ -1,8 +1,12 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. +#if WPF using System.IO; +using System.Net.Http; +#endif using System.Reflection; +using FluentAssertions; using PdfSharp.Diagnostics; using PdfSharp.Drawing; using PdfSharp.Fonts; @@ -165,7 +169,7 @@ public void WriteAndRead_PDF_with_FlateDecode() "PDFsharp/images/samples/jpeg/windows7problem.jpg" }; - // Attempt to avoid "Out of memory" under .NET 4.7.2. + // Attempt to avoid "Out of memory" under .NET 4.6.2. GC.Collect(); GC.WaitForFullGCComplete(); @@ -232,7 +236,7 @@ void ExportJpeg(PdfDictionary image) [Fact] void PDF_with_Image_from_stream() { - // Attempt to avoid "image file locked" under .NET 4.7.2. + // Attempt to avoid "image file locked" under .NET 4.6.2. GC.Collect(); GC.WaitForFullGCComplete(); @@ -255,9 +259,42 @@ void PDF_with_Image_from_stream() PdfFileUtility.ShowDocumentIfDebugging(filename); } - // Attempt to avoid "image file locked" under .NET 4.7.2. + // Attempt to avoid "image file locked" under .NET 4.6.2. GC.Collect(); GC.WaitForFullGCComplete(); } + +#if NET6_0_OR_GREATER + [Fact] + async Task PDF_with_Image_from_http_stream() + { + { + var document = new PdfDocument(); + var page = document.AddPage(); + var gfx = XGraphics.FromPdfPage(page); + + using var client = new HttpClient(); + await using var imageStream = + await client.GetStreamAsync("https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png").ConfigureAwait(false); + +#if WPF + XImage xImage = null!; + // ReSharper disable once AccessToDisposedClosure + Action createImage = () => xImage = XImage.FromStream(imageStream); + createImage.Should().Throw(); +#else + var xImage = XImage.FromBitmapImageStreamThatCannotSeek(imageStream); + gfx.DrawImage(xImage, 100, 100, 100, 100); + + // Save the document... + var filename = PdfFileUtility.GetTempPdfFileName("ImageFromStream"); + document.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); +#endif + + } + } +#endif } } diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Drawing/text/TextTests.cs b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Drawing/text/TextTests.cs index c966e74d..66d67e02 100644 --- a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Drawing/text/TextTests.cs +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Drawing/text/TextTests.cs @@ -2,18 +2,42 @@ // See the LICENSE file in the solution root for more information. using FluentAssertions; -using PdfSharp.Diagnostics; using PdfSharp.Drawing; using PdfSharp.FontResolver; using PdfSharp.Fonts; +using PdfSharp.Fonts.Internal; using PdfSharp.Pdf; using PdfSharp.Quality; -using PdfSharp.Snippets.Font; using PdfSharp.TestHelper; using Xunit; namespace PdfSharp.Tests.Drawing { + public static class FontHelper + { + /// + /// Checks if a font has glyphs for all characters in a string. + /// + /// + /// + public static bool HasGlyph(this XFont font, string text) + { + var codePoints = font.IsSymbolFont + ? UnicodeHelper.SymbolCodePointsFromString(text, font.OpenTypeDescriptor) + : UnicodeHelper.Utf32FromString(text /*, font.AnsiEncoding*/); + var otDescriptor = font.OpenTypeDescriptor; + var codePointsWithGlyphIndices = otDescriptor.GlyphIndicesFromCodePoints(codePoints); + bool hasGlyph = codePointsWithGlyphIndices.Length > 0; + foreach (var item in codePointsWithGlyphIndices) + { + if (item.GlyphIndex == 0) + return false; + } + + return hasGlyph; + } + } + [Collection("PDFsharp")] public class TextTests : IDisposable { @@ -46,13 +70,15 @@ public void PDF_with_Emojis() var width = page.Width.Point; var height = page.Height.Point; - XPdfFontOptions options = new XPdfFontOptions(PdfFontEncoding.Unicode); - XFont font = new XFont(UnitTestFontResolver.EmojiFont, 12, XFontStyleEx.Regular, options); - gfx.DrawString("111😢😞💪", font, XBrushes.Black, new XRect(0, 0, width, height), XStringFormats.Center); - gfx.DrawString("\ud83d\udca9\ud83d\udca9\ud83d\udca9\u2713\u2714\u2705\ud83d\udc1b\ud83d\udc4c\ud83c\udd97\ud83d\udd95 \ud83e\udd84 \ud83e\udd82 \ud83c\udf47 \ud83c\udf46 \u2615 \ud83d\ude82 \ud83d\udef8 \u2601 \u2622 \u264c \u264f \u2705 \u2611 \u2714 \u2122 \ud83c\udd92 \u25fb", font, XBrushes.Black, new XRect(0, 50, width, height), XStringFormats.Center); + //var options = new XPdfFontOptions(PdfFontEncoding.Unicode); + var options = new XPdfFontOptions(PdfFontColoredGlyphs.Version0); + var font = new XFont(UnitTestFontResolver.EmojiFont, 12, XFontStyleEx.Regular, options); + gfx.DrawString("Colored 😍🎈🍕🚲🤑💪💕", font, XBrushes.Black, new XRect(0, 0, width, height), XStringFormats.Center); + gfx.DrawString("glyphs \ud83d\udca9\ud83d\udc1b\ud83e\udd84\u2615\ud83d\ude82\ud83d\udef8\u2714", font, XBrushes.Black, new XRect(0, 20, width, height), XStringFormats.Center); + gfx.DrawString("\ud83d\udca9\ud83d\udca9\ud83d\udca9\u2713\u2714\u2705\ud83d\udc1b\ud83d\udc4c\ud83c\udd97\ud83d\udd95 \ud83e\udd84 \ud83e\udd82 \ud83c\udf47 \ud83c\udf46 \u2615 \ud83d\ude82 \ud83d\udef8 \u2601 \u2622 \u264c \u264f \u2705 \u2611 \u2714 \u2122 \ud83c\udd92 \u25fb", font, XBrushes.Black, new XRect(0, 100, width, height), XStringFormats.Center); // Save the document... - string filename = PdfFileUtility.GetTempPdfFileName("HelloEmoji"); + string filename = PdfFileUtility.GetTempPdfFullFileName("PDFsharp/UnitTests/Drawing/text/HelloEmoji"); document.Save(filename); // ...and start a viewer. PdfFileUtility.ShowDocumentIfDebugging(filename); @@ -153,5 +179,316 @@ public void PDF_with_Wingdings() containsNotFoundGlyphs.Should().BeFalse(); } + + [Fact] + public void PDF_with_ligatures_text_event() + { + bool enableLigatures = false; + + Dictionary ligatures = new() + { + { "ffi", 'ffi' }, + { "ffl", 'ffl' }, + { "ff", 'ff' }, + { "fi", 'fi' }, + { "fl", 'fl' }, + { "IJ", 'IJ' }, + { "ij", 'ij' } + }; + + // Create a new PDF document. + var document = new PdfDocument(); + document.Options.CompressContentStreams = false; + + document.RenderEvents.PrepareTextEvent += (sender, args) => + { + // ReSharper disable once AccessToModifiedClosure + if (enableLigatures) + { +#if true + //bool hits = false; + var preparedText = args.Text; + var font = args.Font; + foreach (var ligature in ligatures) + { + if (font.HasGlyph(ligature.Value.ToString())) + { + if (preparedText.IndexOf(ligature.Key, StringComparison.Ordinal) >= 0) + { + preparedText = preparedText.Replace(ligature.Key, ligature.Value.ToString()); + //hits = true; + } + } +#if DEBUG + else + { + _ = typeof(int); + } +#endif + } + + //if (hits) + args.Text = preparedText; +#else + bool hits = false; + var preparedText = args.Text; + foreach (var ligature in ligatures) + { + int idx; + do + { + idx = preparedText.IndexOf(ligature.Key, StringComparison.Ordinal); + if (idx >= 0) + { + preparedText = preparedText.Substring(0, idx) + + ligature.Value + + preparedText.Substring(idx + ligature.Key.Length); + hits = true; + } + } while (idx >= 0); + } + + if (hits) + { + args.Text = preparedText; + args.UseReturnedText = true; + } +#endif + } + }; + + // Create an empty page in this document. + var page = document.AddPage(); + + // Get an XGraphics object for drawing on this page. + var gfx = XGraphics.FromPdfPage(page); + +#if CORE + var fontName = "Times New Roman"; +#else + var fontName = "Georgia"; +#endif + + int pos = 10; + const string text = "Infinite off inflammable official offline off; IJsselmeer ijsvrij"; + var options = new XPdfFontOptions(PdfFontEncoding.Unicode); + //var font = new XFont("Times New Roman", 12, XFontStyleEx.Bold, options); + var font = new XFont(fontName, 12, XFontStyleEx.Regular, options); + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = true; + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos + 12, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = false; + pos += 30; + + font = new XFont("Arial", 12, XFontStyleEx.Regular, options); + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = true; + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos + 12, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = false; + pos += 30; + +#if !CORE + font = new XFont("Times New Roman", 12, XFontStyleEx.Regular, options); + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = true; + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos + 12, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = false; + pos += 30; + + // Comic Sans MS is an interesting test because there are no ligatures for "ff", "ffi", and "ffl". + font = new XFont("Comic Sans MS", 12, XFontStyleEx.Regular, options); + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = true; + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos + 12, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = false; + pos += 30; +#endif + + font = new XFont(fontName, 12, XFontStyleEx.Bold, options); + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = true; + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos + 12, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = false; + pos += 30; + + font = new XFont("Arial", 12, XFontStyleEx.Bold, options); + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = true; + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos + 12, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = false; + pos += 30; + +#if !CORE + font = new XFont("Times New Roman", 12, XFontStyleEx.Bold, options); + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = true; + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos + 12, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = false; + pos += 30; + + // Comic Sans MS is an interesting test because there are no ligatures for "ff", "ffi", and "ffl". + font = new XFont("Comic Sans MS", 12, XFontStyleEx.Bold, options); + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = true; + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, pos + 12, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = false; + pos += 30; +#endif + + // Save the document... + var filename = PdfFileUtility.GetTempPdfFileName("PdfLigatureTest-TextEvent"); + document.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); + + // Analyze the drawn text in the PDF’s content stream. + var streamEnumerator = PdfFileHelper.GetPageContentStreamEnumerator(document, 0); + + streamEnumerator.Text.MoveAndGetNext(true, out var textInfo).Should().BeTrue(); + textInfo!.IsHex.Should().BeTrue(); + var hexString = textInfo.Text; + hexString.Should().NotBeNull(); + + var glyphIds = PdfFileHelper.GetHexStringAsGlyphIndices(hexString); + glyphIds.Should().NotContain("0", + "no char (and no no-break hyphen) should be converted to an invalid glyph (\"0\")"); + } + + [Fact] + public void PDF_with_ligatures_render_event() + { + bool enableLigatures = false; + + Dictionary ligatures = new() + { + { "IJ", 'IJ' }, + { "ij", 'ij' }, + { "ffi", 'ffi' }, + { "ffl", 'ffl' }, + { "ff", 'ff' }, + { "fi", 'fi' }, + { "fl", 'fl' } + }; + + // Create a new PDF document. + var document = new PdfDocument(); + document.Options.CompressContentStreams = false; + + document.RenderEvents.RenderTextEvent += (sender, args) => + { + // ReSharper disable once AccessToModifiedClosure + if (enableLigatures) + { + var keys = new String[ligatures.Keys.Count]; + ligatures.Keys.CopyTo(keys, 0); + var length = args.CodePointGlyphIndexPairs.Length; + for (var idx = 0; idx < length; idx++) + { + ref var item = ref args.CodePointGlyphIndexPairs[idx]; + + for (int ligIdx = 0; ligIdx < ligatures.Keys.Count; ++ligIdx) + { + var lig = keys[ligIdx]; + if (item.CodePoint == lig[0] && idx + lig.Length <= length) + { + bool match = true; + // First character matches, check rest. + for (int ligIdx2 = 1; ligIdx2 < lig.Length; ++ligIdx2) + { + ref var item2 = ref args.CodePointGlyphIndexPairs[idx + ligIdx2]; + if (item2.CodePoint != lig[ligIdx2]) + { + match = false; + break; + } + } + + if (match) + { + item.CodePoint = ligatures[lig]; + args.ReevaluateGlyphIndices = true; + // Have to remove the remaining chars. + for (int ligIdx2 = 1; ligIdx2 < lig.Length; ++ligIdx2) + { + ref var item2 = ref args.CodePointGlyphIndexPairs[idx + ligIdx2]; + item2.CodePoint = -17; // Internal use. + //item2.GlyphIndex = 0; + } + } + } + } + } + + if (args.ReevaluateGlyphIndices) + { + var source = args.CodePointGlyphIndexPairs; + var dest = new List(); + foreach (var item in source) + { + // Remove obsolete entries. + if (item.CodePoint != -17) + dest.Add(item); + } + args.CodePointGlyphIndexPairs = new CodePointGlyphIndexPair[dest.Count]; + dest.CopyTo(args.CodePointGlyphIndexPairs, 0); + } + } + }; + + // Create an empty page in this document. + var page = document.AddPage(); + + // Get an XGraphics object for drawing on this page. + var gfx = XGraphics.FromPdfPage(page); + +#if CORE + var fontName = "Times New Roman"; +#else + var fontName = "Georgia"; +#endif + const string text = "Infinite inflammable official offline"; + var options = new XPdfFontOptions(PdfFontEncoding.Unicode); + //var font = new XFont("Times New Roman", 12, XFontStyleEx.Bold, options); + var font = new XFont(fontName, 12, XFontStyleEx.Regular, options); + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, 50, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + enableLigatures = true; + gfx.DrawString(text, font, XBrushes.Black, new XRect(50, 62, page.Width.Point, page.Height.Point), + XStringFormats.TopLeft); + + // Save the document... + var filename = PdfFileUtility.GetTempPdfFileName("PdfLigatureTest-RenderEvent"); + document.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); + + // Analyze the drawn text in the PDF’s content stream. + var streamEnumerator = PdfFileHelper.GetPageContentStreamEnumerator(document, 0); + + streamEnumerator.Text.MoveAndGetNext(true, out var textInfo).Should().BeTrue(); + textInfo!.IsHex.Should().BeTrue(); + var hexString = textInfo.Text; + hexString.Should().NotBeNull(); + + var glyphIds = PdfFileHelper.GetHexStringAsGlyphIndices(hexString); + glyphIds.Should().NotContain("0", + "no char (and no no-break hyphen) should be converted to an invalid glyph (\"0\")"); + } } } diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Encodings/EncodingTests.cs b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Encodings/EncodingTests.cs index 589e9e27..bc4aab7f 100644 --- a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Encodings/EncodingTests.cs +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Encodings/EncodingTests.cs @@ -135,7 +135,7 @@ public void AnsiEncoding_Unicode_to_Unicode_test_implementation() int[] abc = new int[128]; for (int i = 0, ach = 128; i <= 127; i++, ach++) - abc[i] = pdfSharpImplementation.GetChars(new byte[] { (byte)ach }, 0, 1)[0]; + abc[i] = pdfSharpImplementation.GetChars([(byte)ach], 0, 1)[0]; // Check Unicode chars. for (int i = 0; i <= 65535; i++) @@ -172,6 +172,7 @@ public void AnsiEncoding_Unicode_to_Unicode_test_implementation() } } + // Used test PDFsharp AnsiEncoding against Microsoft code page 1252. Encoding? GetDotNetAnsiEncoding() { #if NET6_0_OR_GREATER diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Helper/XunitHelper.cs b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Helper/XunitHelper.cs new file mode 100644 index 00000000..a94d9153 --- /dev/null +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Helper/XunitHelper.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +// ReSharper disable once CheckNamespace +namespace Xunit +{ + /// + /// Helper class used with the Xunit.SkippableFact NuGet package. + /// + public static class SkippableTests + { + /// + /// Gets a value indicating whether slow unit tests should be skipped. + /// + /// True if slow tests should be skipped. + public static bool SkipSlowTests() + { + var env = Environment.GetEnvironmentVariable("PDFsharpTests"); + return String.IsNullOrEmpty(env); + } + + // /// + // /// Gets a value indicating whether slow unit tests should be skipped. + // /// This method is used for tests that run slow under .NET Framework 4.6.2, but much faster under .NET 6. + // /// + // /// True if slow tests should be skipped. + // public static bool SkipSlowTestsUnderDotNetFramework() + // { + //#if NET6_0_OR_GREATER + // return false; + //#else + // return SkipSlowTests(); + //#endif + // } + } +} diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/IO/ReaderTests.cs b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/IO/ReaderTests.cs index 56a3f97c..7e4e3fd6 100644 --- a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/IO/ReaderTests.cs +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/IO/ReaderTests.cs @@ -3,18 +3,16 @@ using System.Diagnostics; using System.Globalization; +#if WPF using System.IO; -using FluentAssertions; -using PdfSharp.Diagnostics; +#endif using PdfSharp.Drawing; -using PdfSharp.Fonts; using PdfSharp.Pdf; using PdfSharp.Pdf.Advanced; using PdfSharp.Pdf.IO; using PdfSharp.Quality; -using PdfSharp.Snippets.Font; -using PdfSharp.TestHelper; using Xunit; +using FluentAssertions; namespace PdfSharp.Tests.IO { @@ -226,5 +224,79 @@ public void Custom_properties_test() doc4.Save(filename); PdfFileUtility.ShowDocumentIfDebugging(filename); } + + [Fact] + public void Read_and_modify_PDF_file_PageOrientation_test() + { + // This test creates all 8 possible variations of A4 pages. + // Step 1 draws a red frame around the page. + // Step 2 draws a narrower, yellow frame around the page. + // Step 3 draws a narrow, green frame around the page. + // All frames should be visible after step 3 and should be around the edges of the pages. + var document = new PdfDocument(); + + // There are 4 possible values for rotation and 2 options for orientation. + // We create 8 pages to cover all cases. + for (int i = 0; i < 8; ++i) + { + var page = document.AddPage(); + page.Size = PageSize.A4; + page.Rotate = i % 4 * 90; + page.Orientation = (i / 4) switch + { + 0 => PageOrientation.Portrait, + 1 => PageOrientation.Landscape, + _ => throw new ArgumentOutOfRangeException() + }; + DrawPageFrame(page, XColors.Red, 20, + $"Page {i + 1} - Rotate {page.Rotate} - Orientation {page.Orientation}"); + } + + // Save the document... + string filename = PdfFileUtility.GetTempPdfFullFileName("unittests/IO/ReaderTests/OrientationTestStep1"); + document.Save(filename); + + // Read the document from step 1. + document = PdfReader.Open(filename, PdfDocumentOpenMode.Modify); + for (int i = 0; i < 8; ++i) + { + var page = document.Pages[i]; +#if true_ // can be deleted now + // Modifying the PDF works with this hack. + page.Orientation = PageOrientation.Portrait; // Always set "Portrait" for imported pages. +#endif + DrawPageFrame(page, XColors.Yellow, 10); + } + + // Save the document... + filename = PdfFileUtility.GetTempPdfFullFileName("unittests/IO/ReaderTests/OrientationTestStep2"); + document.Save(filename); + + // Read the document from step 2. + document = PdfReader.Open(filename, PdfDocumentOpenMode.Modify); + for (int i = 0; i < 8; ++i) + { + var page = document.Pages[i]; + DrawPageFrame(page, XColors.Green, 5); + } + + // Save the document... + filename = PdfFileUtility.GetTempPdfFullFileName("unittests/IO/ReaderTests/OrientationTestStep3"); + document.Save(filename); + + static void DrawPageFrame(PdfPage page, XColor color, Int32 width, string? label = null) + { + // Draw a frame around the page. Add an optional label. + using var gfx = XGraphics.FromPdfPage(page); + var pen = new XPen(XColors.OrangeRed, 10) { LineCap = XLineCap.Round }; + gfx.DrawLine(pen, 0, 0, 200, 200); + gfx.DrawRectangle(new XPen(color, width), new XRect(0, 0, page.Width.Point, page.Height.Point)); + if (!String.IsNullOrWhiteSpace(label)) + { + var font = new XFont("Verdana", 10, XFontStyleEx.Regular); + gfx.DrawString(label ?? "", font, XBrushes.Firebrick, 20, 20); + } + } + } } } diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/pdf-a/PdfATests.cs b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/pdf-a/PdfATests.cs new file mode 100644 index 00000000..2382ae4b --- /dev/null +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/pdf-a/PdfATests.cs @@ -0,0 +1,49 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Drawing; +using PdfSharp.Pdf; +using PdfSharp.Quality; +using PdfSharp.UniversalAccessibility; +using Xunit; + +namespace PdfSharp.Tests.PDF +{ + [Collection("PDFsharp")] + public class PdfATests + { + [Fact] + public void Simple_PDF_A_document() + { + var document = new PdfDocument(); + document.SetPdfA(); + + // Get the manager for universal accessibility. + var uaManager = UAManager.ForDocument(document); + // Get structure builder. + var sb = uaManager.StructureBuilder; + + document.ViewerPreferences.FitWindow = true; + document.PageLayout = PdfPageLayout.SinglePage; + + var font = new XFont("Verdana", 10, XFontStyleEx.Regular); + var pdfPage = document.AddPage(); + var xGraphics = XGraphics.FromPdfPage(pdfPage); + + // Create article element in document. + sb.BeginElement(PdfGroupingElementTag.Article); + { + // Create paragraph element. + sb.BeginElement(PdfBlockLevelElementTag.Paragraph); + var layoutRectangle = new XRect(0, 72, pdfPage.Width.Point, pdfPage.Height.Point); + xGraphics.DrawString("PDF/A Test", font, XBrushes.Black, layoutRectangle, XStringFormats.TopCenter); + sb.End(); + } + sb.End(); + + string filename = PdfFileUtility.GetTempPdfFullFileName("PDFsharp/UnitTest/pdf-a/PdfATest"); + document.Save(filename); + PdfFileUtility.ShowDocumentIfDebugging(filename); + } + } +} diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/signatures/BouncyCastleSignerTests.cs b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/signatures/BouncyCastleSignerTests.cs new file mode 100644 index 00000000..3a61e869 --- /dev/null +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/signatures/BouncyCastleSignerTests.cs @@ -0,0 +1,133 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using System.Globalization; +#if WPF +using System.IO; +#endif +using System.Security.Cryptography.X509Certificates; +using PdfSharp.Drawing; +using PdfSharp.Drawing.Layout; +using PdfSharp.Pdf; +using PdfSharp.Pdf.Annotations; +using PdfSharp.Pdf.IO; +using PdfSharp.Pdf.Signatures; +using PdfSharp.Quality; +using PdfSharp.Snippets.Pdf; +using Xunit; + +namespace PdfSharp.Tests.Pdf +{ + [Collection("PDFsharp")] + public class BouncyCastleSignerTests + { + /// + /// The minimum assets version required. + /// + public const int RequiredAssets = 1014; + + [Fact] + public void Sign_new_file_Bouncy() + { + IOUtility.EnsureAssetsVersion(RequiredAssets); + + var font = new XFont("Verdana", 10, XFontStyleEx.Regular); + var fontHeader = new XFont("Verdana", 18, XFontStyleEx.Regular); + using var document = new PdfDocument(); + var pdfPage = document.AddPage(); + var xGraphics = XGraphics.FromPdfPage(pdfPage); + var layoutRectangle = new XRect(0, 72, pdfPage.Width.Point, pdfPage.Height.Point); + xGraphics.DrawString("Document Signature Test", fontHeader, XBrushes.Black, layoutRectangle, XStringFormats.TopCenter); + var textFormatter = new XTextFormatter(xGraphics); + layoutRectangle = new XRect(72, 144, pdfPage.Width.Point - 144, pdfPage.Height.Point - 144); + + var text = "Lorem ipsum..."; + textFormatter.DrawString(text, font, new XSolidBrush(XColor.FromKnownColor(XKnownColor.Black)), layoutRectangle, XStringFormats.TopLeft); + + var pdfPosition = xGraphics.Transformer.WorldToDefaultPage(new XPoint(144, 216)); + var options = new DigitalSignatureOptions + { + ContactInfo = "John Doe", + Location = "Seattle", + Reason = "License Agreement", + Rectangle = new XRect(pdfPosition.X, pdfPosition.Y, 200, 50), + AppearanceHandler = new SignAppearanceHandler() + }; + + var pdfSignatureHandler = DigitalSignatureHandler.ForDocument(document, new BouncyCastleSigner(GetCertificate(), PdfMessageDigestType.SHA512), options); + + // Save the document... + string filename = PdfFileUtility.GetTempPdfFullFileName("PDFsharp/UnitTest/signatures/BouncySignerTest"); + document.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); + } + + [Fact] + public void Sign_existing_file_Bouncy() + { + IOUtility.EnsureAssetsVersion(RequiredAssets); + var pdfFolder = IOUtility.GetAssetsPath("archives/samples-1.5/PDFs"); + var pdfFile = Path.Combine(pdfFolder ?? throw new InvalidOperationException("Call Download-Assets.ps1 before running the tests."), "SomeLayout.pdf"); + + PdfDocument document = PdfReader.Open(File.OpenRead(pdfFile)); + var options = new DigitalSignatureOptions + { + ContactInfo = "John Doe", + Location = "Seattle", + Reason = "License Agreement", + Rectangle = new(XUnit.FromCentimeter(1).Point, XUnit.FromCentimeter(0).Point, + XUnit.FromCentimeter(9.9).Point, XUnit.FromCentimeter(1.3).Point), + AppearanceHandler = new SignAppearanceHandler() + }; + var pdfSignatureHandler = DigitalSignatureHandler.ForDocument(document, new BouncyCastleSigner(GetCertificate(), PdfMessageDigestType.SHA512), options); + + // Save the document... + string filename = PdfFileUtility.GetTempPdfFullFileName("PDFsharp/UnitTest/signatures/BouncySignExistingPdfTest"); + document.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); + } + + static (X509Certificate2, X509Certificate2Collection) GetCertificate() + { + var certFolder = IOUtility.GetAssetsPath("pdfsharp-6.x/signatures"); + var pfxFile = Path.Combine(certFolder ?? throw new InvalidOperationException("Call Download-Assets.ps1 before running the tests."), "test-cert_rsa_1024.pfx"); + var rawData = File.ReadAllBytes(pfxFile); + + // Do not use password literals for real certificates in source code. + var certificatePassword = "Seecrit1243"; + + var certificate = new X509Certificate2(rawData, + certificatePassword, + X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); + + var collection = new X509Certificate2Collection(); + collection.Import(rawData, certificatePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); + + return (certificate, collection); + } + + class SignAppearanceHandler : IAnnotationAppearanceHandler + { + public void DrawAppearance(XGraphics gfx, XRect rect) + { + var imageFolder = IOUtility.GetAssetsPath("pdfsharp-6.x/signatures"); + var pngFile = Path.Combine(imageFolder ?? throw new InvalidOperationException("Call Download-Assets.ps1 before running the tests."), "JohnDoe.png"); + var image = XImage.FromFile(pngFile); + + string text = "John Doe\nSeattle, " + DateTime.Now.ToString(CultureInfo.GetCultureInfo("EN-US")); + var font = new XFont("Verdana", 7.0, XFontStyleEx.Regular); + var textFormatter = new XTextFormatter(gfx); + double num = (double)image.PixelWidth / image.PixelHeight; + double signatureHeight = rect.Height * .4; + var point = new XPoint(rect.Width / 10, rect.Height / 10); + // Draw image. + gfx.DrawImage(image, point.X, point.Y, signatureHeight * num, signatureHeight); + // Adjust position for text. We draw it below image. + point = new XPoint(point.X, rect.Height / 2d); + textFormatter.DrawString(text, font, new XSolidBrush(XColor.FromKnownColor(XKnownColor.Black)), new XRect(point.X, point.Y, rect.Width, rect.Height - point.Y), XStringFormats.TopLeft); + } + } + } +} diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/signatures/DefaultSignerTests.cs b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/signatures/DefaultSignerTests.cs new file mode 100644 index 00000000..b92364bd --- /dev/null +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/Pdf/signatures/DefaultSignerTests.cs @@ -0,0 +1,405 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using System.Globalization; +#if WPF +using System.IO; +#endif +using System.Security.Cryptography.X509Certificates; +using PdfSharp.Drawing; +using PdfSharp.Drawing.Layout; +using PdfSharp.Pdf; +using PdfSharp.Pdf.Annotations; +using PdfSharp.Pdf.IO; +using PdfSharp.Pdf.Signatures; +using PdfSharp.Quality; +using Xunit; +using SecurityTestHelper = PdfSharp.TestHelper.SecurityTestHelper; + +namespace PdfSharp.Tests.Pdf +{ + [Collection("PDFsharp")] + public class DefaultSignerTests + { + /// + /// The minimum assets version required. + /// + public const int RequiredAssets = 1014; + + [Theory] + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, null)] + public void Sign_new_file_with_DefaultAppearance(string certType, PdfMessageDigestType digestType, string timestampURL) + { +#if DEBUG + var version = PdfSharp.Internal.BuildInformation.BuildVersionNumber; +#endif + IOUtility.EnsureAssetsVersion(RequiredAssets); + + var font = new XFont("Verdana", 10, XFontStyleEx.Regular); + var fontHeader = new XFont("Verdana", 18, XFontStyleEx.Regular); + using var document = new PdfDocument(); + var pdfPage = document.AddPage(); + var xGraphics = XGraphics.FromPdfPage(pdfPage); + var layoutRectangle = new XRect(0, 72, pdfPage.Width.Point, pdfPage.Height.Point); + xGraphics.DrawString("Document Signature Test", fontHeader, XBrushes.Black, layoutRectangle, XStringFormats.TopCenter); + var textFormatter = new XTextFormatter(xGraphics); + layoutRectangle = new XRect(72, 144, pdfPage.Width.Point - 144, pdfPage.Height.Point - 144); + + var text = "Lorem ipsum..."; + textFormatter.DrawString(text, font, new XSolidBrush(XColor.FromKnownColor(XKnownColor.Black)), layoutRectangle, XStringFormats.TopLeft); + + var pdfPosition = xGraphics.Transformer.WorldToDefaultPage(new XPoint(144, 216)); + var options = new DigitalSignatureOptions + { + // We do not set an appearance handler, so the default handler is used. + // It is highly recommended to set an appearance handler to get a nicer representation of the signature. + ContactInfo = "John Doe", + Location = "Seattle", + Reason = "License Agreement", + Rectangle = new XRect(pdfPosition.X, pdfPosition.Y, 200, 50), + AppName = "PDFsharp Library" + }; + + Uri? timestampURI = String.IsNullOrEmpty(timestampURL) ? null : new Uri(timestampURL, UriKind.Absolute); + + var pdfSignatureHandler = DigitalSignatureHandler.ForDocument(document, new PdfSharpDefaultSigner(GetCertificate(certType), digestType, timestampURI), options); + + // Save the document... + string filename = PdfFileUtility.GetTempPdfFullFileName("PDFsharp/UnitTest/signatures/DefaultAppearanceHandler-" + certType); + document.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); + } + + [Theory] + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA1, null)] + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, null)] +#if NET6_0_OR_GREATER + // Time stamping not implemented for .NET Standard or .NET Framework. + // Some arbitrarily selected timestamp servers. + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, "http://zeitstempel.dfn.de")] + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, "http://timestamp.sectigo.com")] + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, "http://timestamp.apple.com/ts01")] +#if DEBUG + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, "http://timestamp.digicert.com")] + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, "http://ts.ssl.com")] +#endif +#endif + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA384, null)] + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA512, null)] + [InlineData("test-cert_rsa_2048", PdfMessageDigestType.SHA1, null)] + [InlineData("test-cert_rsa_2048", PdfMessageDigestType.SHA256, null)] + [InlineData("test-cert_rsa_2048", PdfMessageDigestType.SHA384, null)] + [InlineData("test-cert_rsa_2048", PdfMessageDigestType.SHA512, null)] + [InlineData("test-cert_rsa_3072", PdfMessageDigestType.SHA1, null)] + [InlineData("test-cert_rsa_3072", PdfMessageDigestType.SHA256, null)] + [InlineData("test-cert_rsa_3072", PdfMessageDigestType.SHA384, null)] + [InlineData("test-cert_rsa_3072", PdfMessageDigestType.SHA512, null)] + [InlineData("test-cert_rsa_4096", PdfMessageDigestType.SHA1, null)] + [InlineData("test-cert_rsa_4096", PdfMessageDigestType.SHA256, null)] + [InlineData("test-cert_rsa_4096", PdfMessageDigestType.SHA384, null)] + [InlineData("test-cert_rsa_4096", PdfMessageDigestType.SHA512, null)] + public void Sign_new_file_Default(string certType, PdfMessageDigestType digestType, string timestampURL) + { +#if DEBUG + var version = PdfSharp.Internal.BuildInformation.BuildVersionNumber; +#endif + IOUtility.EnsureAssetsVersion(RequiredAssets); + + var font = new XFont("Verdana", 10, XFontStyleEx.Regular); + var fontHeader = new XFont("Verdana", 18, XFontStyleEx.Regular); + using var document = new PdfDocument(); + var pdfPage = document.AddPage(); + var xGraphics = XGraphics.FromPdfPage(pdfPage); + var layoutRectangle = new XRect(0, 72, pdfPage.Width.Point, pdfPage.Height.Point); + xGraphics.DrawString("Document Signature Test", fontHeader, XBrushes.Black, layoutRectangle, XStringFormats.TopCenter); + var textFormatter = new XTextFormatter(xGraphics); + layoutRectangle = new XRect(72, 144, pdfPage.Width.Point - 144, pdfPage.Height.Point - 144); + + var text = "Lorem ipsum..."; + textFormatter.DrawString(text, font, new XSolidBrush(XColor.FromKnownColor(XKnownColor.Black)), layoutRectangle, XStringFormats.TopLeft); + + var pdfPosition = xGraphics.Transformer.WorldToDefaultPage(new XPoint(144, 216)); + var options = new DigitalSignatureOptions + { + ContactInfo = "John Doe", + Location = "Seattle", + Reason = "License Agreement", + Rectangle = new XRect(pdfPosition.X, pdfPosition.Y, 200, 50), + AppearanceHandler = new SignatureAppearanceHandler() + }; + + Uri? timestampURI = String.IsNullOrEmpty(timestampURL) ? null : new Uri(timestampURL, UriKind.Absolute); + + var pdfSignatureHandler = DigitalSignatureHandler.ForDocument(document, new PdfSharpDefaultSigner(GetCertificate(certType), digestType, timestampURI), options); + + // pdfSignatureHandler What to do with it? Set SHA-level? Set TimeStamp? + + // Save the document... + string filename = PdfFileUtility.GetTempPdfFullFileName("PDFsharp/UnitTest/signatures/DefaultSignerTest-" + certType); + document.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); + } + +#if NET6_0_OR_GREATER + [SkippableTheory] + //[InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA1, null)] + //[InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, null)] +#if NET6_0_OR_GREATER + // Time stamping not implemented for .NET Standard or .NET Framework. + // Some arbitrarily selected timestamp servers. + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, "http://zeitstempel.dfn.de")] + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, "http://timestamp.sectigo.com")] + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, "http://timestamp.apple.com/ts01")] +#if DEBUG + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, "http://timestamp.digicert.com")] + [InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA256, "http://ts.ssl.com")] +#endif +#endif + //[InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA384, null)] + //[InlineData("test-cert_rsa_1024", PdfMessageDigestType.SHA512, null)] + //[InlineData("test-cert_rsa_2048", PdfMessageDigestType.SHA1, null)] + //[InlineData("test-cert_rsa_2048", PdfMessageDigestType.SHA256, null)] + //[InlineData("test-cert_rsa_2048", PdfMessageDigestType.SHA384, null)] + //[InlineData("test-cert_rsa_2048", PdfMessageDigestType.SHA512, null)] + //[InlineData("test-cert_rsa_3072", PdfMessageDigestType.SHA1, null)] + //[InlineData("test-cert_rsa_3072", PdfMessageDigestType.SHA256, null)] + //[InlineData("test-cert_rsa_3072", PdfMessageDigestType.SHA384, null)] + //[InlineData("test-cert_rsa_3072", PdfMessageDigestType.SHA512, null)] + //[InlineData("test-cert_rsa_4096", PdfMessageDigestType.SHA1, null)] + //[InlineData("test-cert_rsa_4096", PdfMessageDigestType.SHA256, null)] + //[InlineData("test-cert_rsa_4096", PdfMessageDigestType.SHA384, null)] + //[InlineData("test-cert_rsa_4096", PdfMessageDigestType.SHA512, null)] + public void Sign_new_file_Default_in_a_loop(string certType, PdfMessageDigestType digestType, string timestampURL) + { + Skip.If(SkippableTests.SkipSlowTests()); + + int loops = 2; +#if DEBUG + var version = PdfSharp.Internal.BuildInformation.BuildVersionNumber; + loops = 100; + // Reduce loops for slow timestamp servers. + if (timestampURL.Contains("sect")) + loops = 5; +#endif + IOUtility.EnsureAssetsVersion(RequiredAssets); + + for (int loop = 1; loop <= loops; loop++) + { + + var font = new XFont("Verdana", 10, XFontStyleEx.Regular); + var fontHeader = new XFont("Verdana", 18, XFontStyleEx.Regular); + using var document = new PdfDocument(); + var pdfPage = document.AddPage(); + var xGraphics = XGraphics.FromPdfPage(pdfPage); + var layoutRectangle = new XRect(0, 72, pdfPage.Width.Point, pdfPage.Height.Point); + xGraphics.DrawString("Document Signature Test", fontHeader, XBrushes.Black, layoutRectangle, + XStringFormats.TopCenter); + var textFormatter = new XTextFormatter(xGraphics); + layoutRectangle = new XRect(72, 144, pdfPage.Width.Point - 144, pdfPage.Height.Point - 144); + + var text = "Lorem ipsum..."; + textFormatter.DrawString(text, font, new XSolidBrush(XColor.FromKnownColor(XKnownColor.Black)), + layoutRectangle, XStringFormats.TopLeft); + + var pdfPosition = xGraphics.Transformer.WorldToDefaultPage(new XPoint(144, 216)); + var options = new DigitalSignatureOptions + { + ContactInfo = "John Doe", + Location = "Seattle", + Reason = "License Agreement", + Rectangle = new XRect(pdfPosition.X, pdfPosition.Y, 200, 50), + AppearanceHandler = new SignatureAppearanceHandler() + }; + + Uri? timestampURI = String.IsNullOrEmpty(timestampURL) ? null : new Uri(timestampURL, UriKind.Absolute); + + var pdfSignatureHandler = DigitalSignatureHandler.ForDocument(document, + new PdfSharpDefaultSigner(GetCertificate(certType), digestType, timestampURI), options); + + // pdfSignatureHandler What to do with it? Set SHA-level? Set TimeStamp? + + // Save the document... + string filename = + PdfFileUtility.GetTempPdfFullFileName("PDFsharp/UnitTest/signatures/DefaultSignerTest-" + certType); + document.Save(filename); + // ...and start a viewer. + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (loops <= 2) + PdfFileUtility.ShowDocumentIfDebugging(filename); + } + } +#endif + + [Fact] + public void Sign_existing_file_Default() + { + IOUtility.EnsureAssetsVersion(RequiredAssets); + var pdfFolder = IOUtility.GetAssetsPath("archives/samples-1.5/PDFs"); + var pdfFile = Path.Combine(pdfFolder ?? throw new InvalidOperationException("Call Download-Assets.ps1 before running the tests."), "SomeLayout.pdf"); + + PdfDocument document = PdfReader.Open(File.OpenRead(pdfFile)); + var options = new DigitalSignatureOptions + { + ContactInfo = "John Doe", + Location = "Seattle", + Reason = "License Agreement", + Rectangle = new(XUnit.FromCentimeter(1).Point, XUnit.FromCentimeter(0).Point, + XUnit.FromCentimeter(9.9).Point, XUnit.FromCentimeter(1.3).Point), + AppearanceHandler = new SignatureAppearanceHandler() + }; + var pdfSignatureHandler = DigitalSignatureHandler.ForDocument(document, new PdfSharpDefaultSigner(GetCertificate("test-cert_rsa_1024"), PdfMessageDigestType.SHA512), options); + + // Save the document... + string filename = PdfFileUtility.GetTempPdfFullFileName("PDFsharp/UnitTest/signatures/DefaultSignExistingPdfTest"); + document.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); + } + + [SkippableFact] + public void Sign_with_Certificate_from_Store() + { + const string certName = "empira Software GmbH"; + X509Certificate2 certificate = null!; + var store = new X509Store(StoreLocation.CurrentUser); + store.Open(OpenFlags.ReadOnly); + X509Certificate2Collection cers = store.Certificates.Find(X509FindType.FindBySubjectName, certName, false); + Skip.If(cers.Count == 0); + + if (cers.Count > 0) + { + certificate = cers[0]; + }; + + for (int idx = 0; idx < cers.Count; idx++) + { + var cer = cers[idx]; + if (cer?.IssuerName.Name?.Contains("Sectigo") == true) + { + certificate = cer; + break; + } + } + store.Close(); + + var font = new XFont("Verdana", 10, XFontStyleEx.Regular); + var fontHeader = new XFont("Verdana", 18, XFontStyleEx.Regular); + using var document = new PdfDocument(); + var pdfPage = document.AddPage(); + var xGraphics = XGraphics.FromPdfPage(pdfPage); + var layoutRectangle = new XRect(0, 72, pdfPage.Width.Point, pdfPage.Height.Point); + xGraphics.DrawString("Document Signature Test", fontHeader, XBrushes.Black, layoutRectangle, XStringFormats.TopCenter); + var textFormatter = new XTextFormatter(xGraphics); + layoutRectangle = new XRect(72, 144, pdfPage.Width.Point - 144, pdfPage.Height.Point - 144); + + var text = "Lorem ipsum..."; + textFormatter.DrawString(text, font, new XSolidBrush(XColor.FromKnownColor(XKnownColor.Black)), layoutRectangle, XStringFormats.TopLeft); + + var pdfPosition = xGraphics.Transformer.WorldToDefaultPage(new XPoint(144, 216)); + var options = new DigitalSignatureOptions + { + ContactInfo = "John Doe", + Location = "Seattle", + Reason = "License Agreement", + Rectangle = new XRect(pdfPosition.X, pdfPosition.Y, 200, 50), + AppearanceHandler = new SignatureAppearanceHandler() + }; + var pdfSignatureHandler = DigitalSignatureHandler.ForDocument(document, new PdfSharpDefaultSigner(certificate, PdfMessageDigestType.SHA256), options); + + // Save the document... + string filename = PdfFileUtility.GetTempPdfFullFileName("PDFsharp/UnitTest/signatures/CertificateFromStore"); + document.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); + } + + [Theory(Skip = "errors on writing and maybe reading encrypted files with signature")] + [ClassData(typeof(SecurityTestHelper.TestData.AllVersions))] + [ClassData(typeof(SecurityTestHelper.TestData.AllVersionsSkipped), Skip = SecurityTestHelper.SkippedTestOptionsMessage)] + public void Sign_and_encrypt_file_Default(SecurityTestHelper.TestOptionsEnum optionsEnum) + { + var testOptions = SecurityTestHelper.TestOptions.ByEnum(optionsEnum); + testOptions.SetDefaultPasswords(true, true); +#if DEBUG + var version = PdfSharp.Internal.BuildInformation.BuildVersionNumber; +#endif + IOUtility.EnsureAssetsVersion(RequiredAssets); + + var font = new XFont("Verdana", 10.0, XFontStyleEx.Regular); + using var document = new PdfDocument(); + var pdfPage = document.AddPage(); + var xGraphics = XGraphics.FromPdfPage(pdfPage); + var layoutRectangle = new XRect(0.0, 0.0, pdfPage.Width.Point, pdfPage.Height.Point); + xGraphics.DrawString("Signed encrypted sample document", font, XBrushes.Black, layoutRectangle, XStringFormats.TopCenter); + var options = new DigitalSignatureOptions + { + ContactInfo = "John Doe", + Location = "Seattle", + Reason = "License Agreement", + Rectangle = new XRect(36.0, 700.0, 400.0, 50.0), + AppearanceHandler = new SignatureAppearanceHandler() + }; + + // Set encryption parameters. + SecurityTestHelper.SecureDocument(document, testOptions); + + var pdfSignatureHandler = DigitalSignatureHandler.ForDocument(document, new PdfSharpDefaultSigner(GetCertificate("test-cert_rsa_1024"), PdfMessageDigestType.SHA512), options); + + // pdfSignatureHandler What to do with it? Set SHA-level? Set TimeStamp? + + // Save the document... + var filename = PdfFileUtility.GetTempPdfFullFileName("PDFsharp/UnitTest/signatures/" + SecurityTestHelper.AddPrefixToFilename("DefaultSignAndEncryptPdfTest", testOptions)); + document.Save(filename); + // ...and start a viewer. + PdfFileUtility.ShowDocumentIfDebugging(filename); + + // Read encrypted file and write it without encryption. + var pdfDocRead = PdfReader.Open(filename, SecurityTestHelper.PasswordOwnerDefault); + + var filenameRead = PdfFileUtility.GetTempPdfFullFileName(SecurityTestHelper.AddPrefixToFilename("read DefaultSignAndEncryptedPdfTest", testOptions)); + pdfDocRead.Save(filenameRead); + + PdfFileUtility.ShowDocumentIfDebugging(filenameRead); + } + + static X509Certificate2 GetCertificate(string certName) + { + var certFolder = IOUtility.GetAssetsPath("pdfsharp-6.x/signatures"); + var pfxFile = Path.Combine(certFolder ?? throw new InvalidOperationException("Call Download-Assets.ps1 before running the tests."), $"{certName}.pfx"); + var rawData = File.ReadAllBytes(pfxFile); + + // Do not use password literals for real certificates in source code. + var certificatePassword = "Seecrit1243"; //@@@??? + + var certificate = new X509Certificate2(rawData, + certificatePassword, + X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); + + return certificate; + } + + class SignatureAppearanceHandler : IAnnotationAppearanceHandler + { + public void DrawAppearance(XGraphics gfx, XRect rect) + { + var imageFolder = IOUtility.GetAssetsPath("pdfsharp-6.x/signatures"); + var pngFile = Path.Combine(imageFolder ?? throw new InvalidOperationException("Call Download-Assets.ps1 before running the tests."), "JohnDoe.png"); + var image = XImage.FromFile(pngFile); + + string text = "John Doe\nSeattle, " + DateTime.Now.ToString(CultureInfo.GetCultureInfo("EN-US")); + var font = new XFont("Verdana", 7.0, XFontStyleEx.Regular); + var textFormatter = new XTextFormatter(gfx); + double num = (double)image.PixelWidth / image.PixelHeight; + double signatureHeight = rect.Height * .4; + var point = new XPoint(rect.Width / 10, rect.Height / 10); + // Draw image. + gfx.DrawImage(image, point.X, point.Y, signatureHeight * num, signatureHeight); + // Adjust position for text. We draw it below image. + point = new XPoint(point.X, rect.Height / 2d); + textFormatter.DrawString(text, font, new XSolidBrush(XColor.FromKnownColor(XKnownColor.Black)), new XRect(point.X, point.Y, rect.Width, rect.Height - point.Y), XStringFormats.TopLeft); + } + } + } +} diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/PdfSharp.Tests.csproj b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/PdfSharp.Tests.csproj index 6566f91e..76e4e825 100644 --- a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/PdfSharp.Tests.csproj +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/PdfSharp.Tests.csproj @@ -1,11 +1,11 @@  - net6.0;net472 + net6.0;net8.0;net462 CORE + This conflics with mscorlib, and therefore it is disabled. --> CS1685,CS0436 True ..\..\..\..\..\StrongnameKey.snk @@ -23,7 +23,7 @@ False - + False @@ -34,15 +34,27 @@ - + - + + + + + + + + + + + + + diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/PdfSharp.Tests.csproj.DotSettings b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/PdfSharp.Tests.csproj.DotSettings index f7204e92..cf35687a 100644 --- a/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/PdfSharp.Tests.csproj.DotSettings +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.Tests/PdfSharp.Tests.csproj.DotSettings @@ -7,4 +7,7 @@ True True True - True \ No newline at end of file + True + True + True + True \ No newline at end of file diff --git a/src/foundation/src/PDFsharp/tests/PdfSharp.tests-wpf/PdfSharp.tests-wpf.csproj b/src/foundation/src/PDFsharp/tests/PdfSharp.tests-wpf/PdfSharp.tests-wpf.csproj index 5c4f96a3..5d827a9f 100644 --- a/src/foundation/src/PDFsharp/tests/PdfSharp.tests-wpf/PdfSharp.tests-wpf.csproj +++ b/src/foundation/src/PDFsharp/tests/PdfSharp.tests-wpf/PdfSharp.tests-wpf.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true true WPF @@ -42,6 +42,7 @@ + @@ -52,15 +53,29 @@ + + + + + + + + + + + + + + diff --git a/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PdfSharpDefaultSigner.cs b/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PdfSharpDefaultSigner.cs new file mode 100644 index 00000000..e00ba03f --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PdfSharpDefaultSigner.cs @@ -0,0 +1,183 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +#if NET6_0_OR_GREATER +using System.Net.Http.Headers; +#endif +using System.Security.Cryptography; +using System.Security.Cryptography.Pkcs; +using System.Security.Cryptography.X509Certificates; + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// Signer implementation that uses .NET classes only. + /// + public class PdfSharpDefaultSigner : IDigitalSigner + { + static readonly Oid SignatureTimeStampOid = new("1.2.840.113549.1.9.16.2.14"); +#if NET6_0_OR_GREATER + const string TimestampQueryContentType = "application/timestamp-query"; + const string TimestampReplyContentType = "application/timestamp-reply"; +#endif + + /// + /// Creates a new instance of the PdfSharpDefaultSigner class. + /// + /// + /// + /// + public PdfSharpDefaultSigner(X509Certificate2 certificate, PdfMessageDigestType digestType, Uri? timeStampAuthorityUri = null) + { + Certificate = certificate; + DigestType = digestType; +#if NET6_0_OR_GREATER + TimeStampAuthorityUri = timeStampAuthorityUri; +#else + // We dont know how to get a time stamp with .NET Standard. + // If you need it you must implement your own signer. + if (timeStampAuthorityUri != null) + throw new ArgumentException(nameof(timeStampAuthorityUri) + " must be null when using .NET Framework or .NET Standard."); +#endif + MustAddTimeStamp = timeStampAuthorityUri is not null; + } + + /// + /// Gets the name of the certificate. + /// + public string CertificateName => Certificate.GetNameInfo(X509NameType.SimpleName, false) ?? "(undefined)"; + + /// + /// Determines the size of the contents to be reserved in the PDF file for the signature. + /// + public async Task GetSignatureSizeAsync() + { + if (_signatureSize == 0) + { + // The signature size varies depending on the length of the digest + // and the size of the certificate. + // We simply calculate it once by signing an empty stream. + _signatureSize = (await GetSignatureAsync(new MemoryStream([0])).ConfigureAwait(false)).Length; + if (MustAddTimeStamp) + { + // Add arbitrary padding because TSA timestamp responses length seems to vary from one call to another by 1 byte. + _signatureSize += 4; // 2 was found to be too small. + } + } + return _signatureSize; + } + int _signatureSize; + + /// + /// Creates the signature for a stream containing the PDF file. + /// + /// + /// + /// + public async Task GetSignatureAsync(Stream stream) + { + var content = new byte[stream.Length]; + stream.Position = 0; + // ReSharper disable once MethodHasAsyncOverload + int read = stream.Read(content, 0, content.Length); + if (read != content.Length) + throw new InvalidOperationException($"Tried to read {content.Length} bytes but got {read} bytes."); + + // Sign the byte range. + var contentInfo = new ContentInfo(content); + var signedCms = new SignedCms(contentInfo, true); + var signer = new CmsSigner(Certificate) + { + DigestAlgorithm = DigestType switch + { + PdfMessageDigestType.SHA1 => Oid.FromFriendlyName("sha1", OidGroup.HashAlgorithm), + PdfMessageDigestType.SHA256 => Oid.FromFriendlyName("sha256", OidGroup.HashAlgorithm), + PdfMessageDigestType.SHA384 => Oid.FromFriendlyName("sha384", OidGroup.HashAlgorithm), + PdfMessageDigestType.SHA512 => Oid.FromFriendlyName("sha512", OidGroup.HashAlgorithm), + // PdfMessageDigestType.RIPEMD160 => Oid.FromFriendlyName("???"), // ??? + _ => throw new NotImplementedException($"Digest type {DigestType} not supported by this signer.") + } + } /* { IncludeOption = X509IncludeOption.WholeChain } */; + signer.UnsignedAttributes.Add(new Pkcs9SigningTime()); + + signedCms.ComputeSignature(signer, true); + + if (TimeStampAuthorityUri is not null) + { +#if NET6_0_OR_GREATER + await AddTimestampFromTSAAsync(signedCms).ConfigureAwait(false); +#else + // Already checked in constructor. + await Task.CompletedTask.ConfigureAwait(false); +#endif + } + var bytes = signedCms.Encode(); + + return bytes; + } + + X509Certificate2 Certificate { get; init; } + + PdfMessageDigestType DigestType { get; init; } + + Uri? TimeStampAuthorityUri { get; init; } + + bool MustAddTimeStamp { get; init; } + +#if NET6_0_OR_GREATER + async Task AddTimestampFromTSAAsync(SignedCms signedCms) + { + // Generate our nonce to identify the pair request-response. + + var nonce = RandomNumberGenerator.GetBytes(8); + + // Create nonce in .NET Framework for future use. + // If we ever add timestamp code for .NET 4.6.2, here's how to get the nonce. + //using var cryptoProvider = new RNGCryptoServiceProvider(); + //byte[] nonce; + //cryptoProvider.GetBytes(nonce = new byte[8]); + + // Get our signing information and create the RFC3161 request. + var newSignerInfo = signedCms.SignerInfos[0]; + HashAlgorithmName hashAlgorithm = DigestType switch + { + PdfMessageDigestType.SHA1 => HashAlgorithmName.SHA1, + PdfMessageDigestType.SHA256 => HashAlgorithmName.SHA256, + PdfMessageDigestType.SHA384 => HashAlgorithmName.SHA384, + PdfMessageDigestType.SHA512 => HashAlgorithmName.SHA512, + // PdfMessageDigestType.RIPEMD160 => HashAlgorithmName.SHA512, // ??? + _ => throw new NotImplementedException($"Digest type {DigestType} not supported by this signer.") + }; + + // Now we generate the request to send to the RFC3161 signing authority. + var request = Rfc3161TimestampRequest.CreateFromSignerInfo( + newSignerInfo, + hashAlgorithm, + requestSignerCertificates: true, // Ask TSA to embed its signing certificate in the timestamp token. + nonce: nonce); + + var client = new HttpClient(); + var content = new ReadOnlyMemoryContent(request.Encode()); + content.Headers.ContentType = new MediaTypeHeaderValue(TimestampQueryContentType); + var httpResponse = await client.PostAsync(TimeStampAuthorityUri, content).ConfigureAwait(false); + + // Process our response. + if (!httpResponse.IsSuccessStatusCode) + { + throw new CryptographicException( + $"There was an error from the timestamp authority. It responded with {httpResponse.StatusCode} {(int)httpResponse.StatusCode}: {httpResponse.Content}"); + } + + // Response indicates success, so we assume there is content. + if (httpResponse.Content.Headers.ContentType?.MediaType != TimestampReplyContentType) + throw new CryptographicException("The reply from the time stamp server was in an invalid format."); + + var data = await httpResponse.Content.ReadAsByteArrayAsync().ConfigureAwait(false); + var timestampToken = request.ProcessResponse(data, out _); + + // The RFC3161 sign certificate is separate to the contents that was signed, we need to add it to the unsigned attributes. + newSignerInfo.AddUnsignedAttribute(new AsnEncodedData(SignatureTimeStampOid, timestampToken.AsSignedCms().Encode())); + } +#endif + } +} diff --git a/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PsCryptoMgs.cs b/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PsCryptoMgs.cs new file mode 100644 index 00000000..b4b2568c --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PsCryptoMgs.cs @@ -0,0 +1,22 @@ +// PDFsharp - A .NET library for processing PDF +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using Microsoft.Extensions.Logging; +using PdfSharp.Pdf; + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// The PDFsharp cryptography messages. + /// + // ReSharper disable once InconsistentNaming + // ReSharper disable once IdentifierTypo + static class PsCryptoMsgs + { + // Signature messages + + //public static string IndexOutOfRange + // => "The index is out of range."; + } +} diff --git a/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PsCryptoMsg.cs b/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PsCryptoMsg.cs new file mode 100644 index 00000000..b72438d9 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/PsCryptoMsg.cs @@ -0,0 +1,21 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using Microsoft.Extensions.Logging; + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// PDFsharp cryptography message. + /// + readonly struct PsCryptoMsg(PsCryptoMsgId id, string message) + { + public PsCryptoMsgId Id { get; init; } = id; + + public string Message { get; init; } = message; + + public EventId EventId => new((int)Id, EventName); + + public string EventName => Id.ToString(); + } +} \ No newline at end of file diff --git a/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/enum/PsCryptoMsgId.cs b/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/enum/PsCryptoMsgId.cs new file mode 100644 index 00000000..97bebb8d --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Crytography/Pdf.Signatures/enum/PsCryptoMsgId.cs @@ -0,0 +1,21 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using PdfSharp.Internal; + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// PDFsharp cryptography message IDs. + /// + // GPT 4 recommends to use Crypto instead of Cry as abbreviation, + // because Cry is too ambiguous. + enum PsCryptoMsgId + { + None = 0, + + // ----- Signature messages ---------------------------------------------------------------- + + SampleMessage1 = MessageIdOffset.PsCrypto, + } +} diff --git a/src/foundation/src/shared/src/PdfSharp.Crytography/PdfSharp.Cryptography.csproj b/src/foundation/src/shared/src/PdfSharp.Crytography/PdfSharp.Cryptography.csproj new file mode 100644 index 00000000..8ef98d21 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Crytography/PdfSharp.Cryptography.csproj @@ -0,0 +1,32 @@ + + + + net6.0;net8.0;netstandard2.0 + PdfSharp + True + ..\..\..\..\..\StrongnameKey.snk + + + + true + + + + + + + + + + + + + + + + + + + + + diff --git a/src/foundation/src/shared/src/PdfSharp.Crytography/PdfSharp.Cryptography.csproj.DotSettings b/src/foundation/src/shared/src/PdfSharp.Crytography/PdfSharp.Cryptography.csproj.DotSettings new file mode 100644 index 00000000..82047711 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Crytography/PdfSharp.Cryptography.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/src/foundation/src/shared/src/PdfSharp.Crytography/README.md b/src/foundation/src/shared/src/PdfSharp.Crytography/README.md new file mode 100644 index 00000000..a59a168b --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Crytography/README.md @@ -0,0 +1,7 @@ +# PDFsharp.Cryptography + +This is the PDFsharp.Cryptography project. +It contains classes for signing a PDF document with a digital signature using the +PDFsharp default signer. +This additional assembly prevents PDFsharp.dll from depending on `System.Security.Cryptography.Pkcs` +in case a customer project does not need digital signatures. diff --git a/src/foundation/src/shared/src/PdfSharp.Fonts/PdfSharp.Fonts.csproj b/src/foundation/src/shared/src/PdfSharp.Fonts/PdfSharp.Fonts.csproj index f99f0815..a18364b1 100644 --- a/src/foundation/src/shared/src/PdfSharp.Fonts/PdfSharp.Fonts.csproj +++ b/src/foundation/src/shared/src/PdfSharp.Fonts/PdfSharp.Fonts.csproj @@ -1,7 +1,7 @@  - net6.0;netstandard2.0;net472 + net6.0;net8.0;netstandard2.0 PdfSharp True ..\..\..\..\..\StrongnameKey.snk diff --git a/src/foundation/src/shared/src/PdfSharp.Fonts/README.md b/src/foundation/src/shared/src/PdfSharp.Fonts/README.md index 8bb97106..cdcc4545 100644 --- a/src/foundation/src/shared/src/PdfSharp.Fonts/README.md +++ b/src/foundation/src/shared/src/PdfSharp.Fonts/README.md @@ -1,5 +1,5 @@ # PDFsharp.Fonts This is the PDFsharp.Fonts build project. -It is not yet in use und currently a placeholder. +It is not yet in use and currently a placeholder. PDFsharp does not depend on this project. diff --git a/src/foundation/src/shared/src/PdfSharp.Quality-gdi/PdfSharp.Quality-gdi.csproj b/src/foundation/src/shared/src/PdfSharp.Quality-gdi/PdfSharp.Quality-gdi.csproj index 44b7f2a6..235ef245 100644 --- a/src/foundation/src/shared/src/PdfSharp.Quality-gdi/PdfSharp.Quality-gdi.csproj +++ b/src/foundation/src/shared/src/PdfSharp.Quality-gdi/PdfSharp.Quality-gdi.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true PdfSharp.Quality true @@ -14,11 +14,11 @@ true - + 0 - + 0 @@ -42,6 +42,8 @@ + + diff --git a/src/foundation/src/shared/src/PdfSharp.Quality-wpf/PdfSharp.Quality-wpf.csproj b/src/foundation/src/shared/src/PdfSharp.Quality-wpf/PdfSharp.Quality-wpf.csproj index 623aadb3..a9c809d2 100644 --- a/src/foundation/src/shared/src/PdfSharp.Quality-wpf/PdfSharp.Quality-wpf.csproj +++ b/src/foundation/src/shared/src/PdfSharp.Quality-wpf/PdfSharp.Quality-wpf.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true PdfSharp.Quality true @@ -14,11 +14,11 @@ true - + 0 - + 0 @@ -42,6 +42,8 @@ + + diff --git a/src/foundation/src/shared/src/PdfSharp.Quality/FeatureAndSnippetBase.cs b/src/foundation/src/shared/src/PdfSharp.Quality/FeatureAndSnippetBase.cs index 445e45bf..3962d51c 100644 --- a/src/foundation/src/shared/src/PdfSharp.Quality/FeatureAndSnippetBase.cs +++ b/src/foundation/src/shared/src/PdfSharp.Quality/FeatureAndSnippetBase.cs @@ -2,7 +2,7 @@ // See the LICENSE file in the solution root for more information. using System.IO; -//#if NET/FX_CORE || UWP || DNC10 +//#if NET/FX_CORE || WUI || DNC10 //using System.Threading.Tasks; //using Windows.Foundation; //using Windows.Storage; @@ -337,7 +337,6 @@ void DrawEmptyBox(XGraphics gfx, XRect box) /// The source bytes. /// The filepath. /// if set to true [start viewer]. - /// /// sourceBytes public string SaveAndShowFile(byte[]? sourceBytes, string filepath = "", bool startViewer = false) { @@ -540,7 +539,7 @@ private set #if GDI _gfx = null!; #endif - _pdfBytes = Array.Empty(); + _pdfBytes = []; } } PdfDocument? _document; diff --git a/src/foundation/src/shared/src/PdfSharp.Quality/IOHelper.cs b/src/foundation/src/shared/src/PdfSharp.Quality/IOHelper.cs index ed3cea0e..9f9405d1 100644 --- a/src/foundation/src/shared/src/PdfSharp.Quality/IOHelper.cs +++ b/src/foundation/src/shared/src/PdfSharp.Quality/IOHelper.cs @@ -25,9 +25,9 @@ protected async Task SaveToStreamOrSaveToFileAsync(PdfDocument document, if (stream == null) { if (show) - filename = await SaveAndShowDocumentAsync(document, filenameTag); + filename = await SaveAndShowDocumentAsync(document, filenameTag).ConfigureAwait(false); else - filename = await SaveDocumentAsync(document, filenameTag); + filename = await SaveDocumentAsync(document, filenameTag).ConfigureAwait(false); } else { @@ -43,7 +43,7 @@ protected async Task SaveToStreamOrSaveToFileAsync(PdfDocument document, protected async Task SaveAndShowDocumentAsync(PdfDocument document, string filenameTag) { // Save the PDF document... - var filename = await SaveDocumentAsync(document, filenameTag); + var filename = await SaveDocumentAsync(document, filenameTag).ConfigureAwait(false); // ... and start a viewer. Process.St7art(filename); @@ -52,11 +52,11 @@ protected async Task SaveAndShowDocumentAsync(PdfDocument document, stri } #endif - //#if NET/FX_CORE || UWP || DNC10 + //#if NET/FX_CORE || WUI || DNC10 // static async Task SaveAndShowDocumentAsync(PdfDocument document, string filenameTag) // { // // Save the PDF document... - // string filename = await SaveDocumentAsync(document, filenameTag); + // string filename = await SaveDocumentAsync(document, filenameTag).ConfigureAwait(false); // // ... and start a viewer. // //Process.St7art(filename); @@ -64,13 +64,13 @@ protected async Task SaveAndShowDocumentAsync(PdfDocument document, stri // } //#endif - //#if true && (CORE || GDI || WPF || UWP) - //#if true && (NET/FX_CORE || UWP) + //#if true && (CORE || GDI || WPF || WUI) + //#if true && (NET/FX_CORE || WUI) // static async Task SaveDocumentAsync(PdfDocument document, string filenameTag) // { // var filename = String.Format("{0:N}_{1}_tempfile.pdf", Guid.NewGuid(), filenameTag); // document.Save(filename); - // await Task.Factory.StartNew(() => { }); + // await Task.Factory.StartNew(() => { }).ConfigureAwait(false); // return filename; // } //#endif diff --git a/src/foundation/src/shared/src/PdfSharp.Quality/IOUtility.cs b/src/foundation/src/shared/src/PdfSharp.Quality/IOUtility.cs index 07c64571..73ab8f5e 100644 --- a/src/foundation/src/shared/src/PdfSharp.Quality/IOUtility.cs +++ b/src/foundation/src/shared/src/PdfSharp.Quality/IOUtility.cs @@ -12,7 +12,7 @@ namespace PdfSharp.Quality { /// /// Static utility functions for file IO. - /// These function are intended for unit test und sample in a solution code only. + /// These functions are intended for unit tests and samples in solution code only. /// public static class IOUtility { @@ -364,15 +364,12 @@ public static void EnsureAssetsVersion(int requiredAssetsVersion) if (assetsVersion >= requiredAssetsVersion) return; throw new IOException( - Invariant( - $"The required assets version is {requiredAssetsVersion}, but the current version is just {assetsVersion}. ") + + Invariant($"The required assets version is {requiredAssetsVersion}, but the current version is just {assetsVersion}. ") + AssetsInfo); } } - throw new IOException( - $"The assets version file '{AssetsVersionFileName}' does not exist in the assets folder. " + - AssetsInfo); + throw new IOException($"The assets version file '{AssetsVersionFileName}' does not exist in the assets folder. " + AssetsInfo); } throw new IOException(@"The assets folder does not exist. " + AssetsInfo); diff --git a/src/foundation/src/shared/src/PdfSharp.Quality/PathHelper.cs b/src/foundation/src/shared/src/PdfSharp.Quality/PathHelper.cs index 1521f0ef..b560346f 100644 --- a/src/foundation/src/shared/src/PdfSharp.Quality/PathHelper.cs +++ b/src/foundation/src/shared/src/PdfSharp.Quality/PathHelper.cs @@ -24,8 +24,8 @@ public static string FindPath(string folderName, string subPath) { //System.IO.BinaryWriter x = null; - string currentDirectory = Directory.GetCurrentDirectory(); - int x = currentDirectory.IndexOf("\\" + folderName + "\\", StringComparison.OrdinalIgnoreCase); + string currentDirectory = Directory.GetCurrentDirectory().Replace('\\', '/'); + int x = currentDirectory.IndexOf("/" + folderName + "/", StringComparison.OrdinalIgnoreCase); var l = x + folderName.Length + 1; var test = Path.Combine(currentDirectory[0..(x + folderName.Length + 1)], subPath); diff --git a/src/foundation/src/shared/src/PdfSharp.Quality/PdfFileUtility.cs b/src/foundation/src/shared/src/PdfSharp.Quality/PdfFileUtility.cs index 20a968eb..5c109882 100644 --- a/src/foundation/src/shared/src/PdfSharp.Quality/PdfFileUtility.cs +++ b/src/foundation/src/shared/src/PdfSharp.Quality/PdfFileUtility.cs @@ -10,7 +10,7 @@ namespace PdfSharp.Quality { /// /// Static helper functions for file IO. - /// These function are intended for unit test und sample in a solution code only. + /// These functions are intended for unit tests and samples in solution code only. /// public static class PdfFileUtility { diff --git a/src/foundation/src/shared/src/PdfSharp.Quality/PdfSharp.Quality.csproj b/src/foundation/src/shared/src/PdfSharp.Quality/PdfSharp.Quality.csproj index a3cec8dc..997f5f03 100644 --- a/src/foundation/src/shared/src/PdfSharp.Quality/PdfSharp.Quality.csproj +++ b/src/foundation/src/shared/src/PdfSharp.Quality/PdfSharp.Quality.csproj @@ -1,7 +1,7 @@  - net6.0;netstandard2.0 + net6.0;net8.0;netstandard2.0 CORE True ..\..\..\..\..\StrongnameKey.snk @@ -24,7 +24,9 @@ - + + + diff --git a/src/foundation/src/shared/src/PdfSharp.Quality/Snippet.cs b/src/foundation/src/shared/src/PdfSharp.Quality/Snippet.cs index 3775ffec..e353f77c 100644 --- a/src/foundation/src/shared/src/PdfSharp.Quality/Snippet.cs +++ b/src/foundation/src/shared/src/PdfSharp.Quality/Snippet.cs @@ -429,7 +429,6 @@ protected static XPoint[] Pentagram /// /// The scaling factor of the pentagram. /// The center of the pentagram. - /// protected static XPoint[] GetPentagram(double size, XPoint center) { var points = Pentagram; diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/Diagnostics/NullabilityHelper.cs b/src/foundation/src/shared/src/PdfSharp.Shared/Diagnostics/NullabilityHelper.cs new file mode 100644 index 00000000..4fb5f5b9 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/Diagnostics/NullabilityHelper.cs @@ -0,0 +1,48 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using System.Diagnostics.CodeAnalysis; + +namespace PdfSharp.Diagnostics +{ + /// + /// Helper class for code migration to nullable reference types. + /// + // ReSharper disable once InconsistentNaming + static class NRT + { + /// + /// Throws an InvalidOperationException because an expression which must not be null is null. + /// + /// The message. + /// + [DoesNotReturn] + public static void ThrowOnNull(string? message = null) + => throw new InvalidOperationException(message ?? "Expression must not be null here."); + + /// + /// Throws InvalidOperationException. Use this function during the transition from older C# code + /// to new code that uses nullable reference types. + /// + /// The type this function must return to be compiled correctly. + /// An optional message used for the exception. + /// Nothing, always throws. + /// + [DoesNotReturn] + public static TResult ThrowOnNull(string? message = null) + => throw new InvalidOperationException(message ?? $"'{typeof(TResult).Name}' must not be null here."); + + /// + /// Throws InvalidOperationException. Use this function during the transition from older C# code + /// to new code that uses nullable reference types. + /// + /// The type this function must return to be compiled correctly. + /// The type of the object that is null. + /// An optional message used for the exception. + /// Nothing, always throws. + /// + [DoesNotReturn] + public static TResult ThrowOnNull(string? message = null) + => throw new InvalidOperationException(message ?? $"'{typeof(TType).Name}' must not be null here."); + } +} diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/Internal/BuildVersion.cs b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/BuildVersion.cs new file mode 100644 index 00000000..f3cb8037 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/BuildVersion.cs @@ -0,0 +1,24 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +namespace PdfSharp.Internal +{ +#if DEBUG + /// + /// Internal class to calculate the PDFsharp build version. + /// + class BuildInformation + { + /// + /// The day we start counting. + /// + public const string VersionReferenceDate = "2005-01-01"; + + /// + /// The PDFsharp build version used as fourth value in AssemblyFileVersion. + /// Must be set in gitversion.yml. + /// + public static int BuildVersionNumber = (DateTime.Now - new DateTime(2005, 1, 1)).Days; + } +#endif +} diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/Internal/Configuration.cs b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/Configuration.cs new file mode 100644 index 00000000..938cdf0a --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/Configuration.cs @@ -0,0 +1,14 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +//global using System.Diagnostics; +//global using PdfSharp.Diagnostics; +//global using System.Globalization; +//global using static System.FormattableString; // Used for Invariant($"…") + +namespace PdfSharp.Internal +{ + //internal class Configuration + //{ + //} +} diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/Internal/SyMsg.cs b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/SyMsg.cs new file mode 100644 index 00000000..c6ec16a7 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/SyMsg.cs @@ -0,0 +1,25 @@ +// PDFsharp - A .NET library for processing PDF +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +#pragma warning disable 1591 // Because this is preview code. + // It should not be public. + +using Microsoft.Extensions.Logging; + +namespace PdfSharp.Internal +{ + /// + /// (PDFsharp) System message. + /// + readonly struct SyMsg(SyMsgId id, string message) + { + public SyMsgId Id { get; init; } = id; + + public string Message { get; init; } = message; + + public EventId EventId => new((int)Id, EventName); + + public string EventName => Id.ToString(); + } +} diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/Internal/SyMsgs.cs b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/SyMsgs.cs new file mode 100644 index 00000000..93d03e3e --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/SyMsgs.cs @@ -0,0 +1,26 @@ +// PDFsharp - A .NET library for processing PDF +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +#pragma warning disable 1591 // Because this is preview code. + +using System.Diagnostics.Contracts; + +namespace PdfSharp.Internal +{ + /// + /// (PDFsharp) System message. + /// + // ReSharper disable once InconsistentNaming + // ReSharper disable once IdentifierTypo + static class SyMsgs + { + public static string IndexOutOfRange3 + => "Index out of range."; + + public static SyMsg IndexOutOfRange2(string parameter, T lowerBound, T upperBound) + => new(SyMsgId.IndexOutOfRange, + $"The value of '{parameter}' is out of range. " + + Invariant($"The value must be between '{lowerBound}' and '{upperBound}'.")); + } +} \ No newline at end of file diff --git a/src/foundation/src/shared/src/PdfSharp.System/Internal/ErrorHelpers.cs b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/TH.cs similarity index 58% rename from src/foundation/src/shared/src/PdfSharp.System/Internal/ErrorHelpers.cs rename to src/foundation/src/shared/src/PdfSharp.Shared/Internal/TH.cs index 108302c9..8a47e396 100644 --- a/src/foundation/src/shared/src/PdfSharp.System/Internal/ErrorHelpers.cs +++ b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/TH.cs @@ -1,6 +1,8 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. +#pragma warning disable 1591 // Because this is preview code. + using System.Diagnostics.CodeAnalysis; namespace PdfSharp.Internal @@ -9,22 +11,46 @@ namespace PdfSharp.Internal /// Experimental throw helper. /// // ReSharper disable once InconsistentNaming - static class TH + class TH2 { // Microsoft throws in the helper function. Maybe this creates less code. // But we decided to throw at the position where the problem happens and // therefore we only compose the exception here and return it. + public static InvalidOperationException InvalidOperationException_ToDo( + string? info = null) + { + var message = info == null + ? "Here is something to do." + : $"Here is something to do: {info}"; + + return new(message); + } + [DoesNotReturn] - public static void ThrowInvalidOperationException_ToDo(string? info = null) + public static void ThrowInvalidOperationException_ToDo( + string? info = null) + => throw InvalidOperationException_ToDo(info); + + public static NotImplementedException NotImplementedException( + string? info = null, + Exception? innerException = null) { var message = info == null ? "Here is something to do." : $"Here is something to do: {info}"; - throw new InvalidOperationException(message); + return innerException == null + ? new(message) + : new(message, innerException); } + [DoesNotReturn] + public static void ThrowNotImplementedException( + string? info = null, + Exception? innerException = null) + => throw NotImplementedException(info); + [DoesNotReturn] internal static void ThrowInvalidOperationException_HandleIsNotPinned() { diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/Internal/UrlLiterals.cs b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/UrlLiterals.cs new file mode 100644 index 00000000..ee375899 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/UrlLiterals.cs @@ -0,0 +1,29 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +namespace PdfSharp.Internal +{ + /// + /// URLs used in PDFsharp are maintained only here. + /// + class UrlLiterals // #CHECK_BEFORE_RELEASE + { +#if DEBUG + const string DocsPdfSharpUrl = "http://localhost:8094/"; +#else + const string DocsPdfSharpUrl = "https://docs.pdfsharp.net/"; +#endif + + /// + /// URL for missing assets error message. + /// "https://docs.pdfsharp.net/link/download-assets.html" + /// + public const string LinkToAssetsDoc = DocsPdfSharpUrl + "link/download-assets.html"; + + /// + /// URL for missing font resolver. + /// "https://docs.pdfsharp.net/link/font-resolving.html" + /// + public const string LinkToFontResolving = DocsPdfSharpUrl + "link/font-resolving.html"; + } +} diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/Internal/enum/SyMsgId.cs b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/enum/SyMsgId.cs new file mode 100644 index 00000000..dc0e4a3d --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/Internal/enum/SyMsgId.cs @@ -0,0 +1,36 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +#pragma warning disable 1591 // Because this is preview code. + +namespace PdfSharp.Internal +{ + enum FooBarEnum3 { xxx = 843 } + + /// + /// System message ID. + /// + enum SyMsgId + { + None = 0, + + // ----- General Messages --------------------------------------------------------------------- + + IndexOutOfRange = MessageIdOffset.Sy, + IndexOutOfRange2, + } + + /// + /// Offsets to ensure that all message IDs are pairwise distinct + /// within PDFsharp foundation. + /// + public enum MessageIdOffset + { + Sy = 1000, + Ps = 3000, + PsCrypto = 4000, + MdDom = 5000, + MdPdf = 6000, + MdRtf = 7000, + } +} diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/PdfSharp.Shared.csproj b/src/foundation/src/shared/src/PdfSharp.Shared/PdfSharp.Shared.csproj new file mode 100644 index 00000000..40475612 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/PdfSharp.Shared.csproj @@ -0,0 +1,65 @@ + + + + net6.0;net8.0;netstandard2.0 + PdfSharp + True + ..\..\..\..\..\StrongnameKey.snk + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/PdfSharp.Shared.csproj.DotSettings b/src/foundation/src/shared/src/PdfSharp.Shared/PdfSharp.Shared.csproj.DotSettings new file mode 100644 index 00000000..ba737ec8 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/PdfSharp.Shared.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/Properties/GlobalDeclarations.cs b/src/foundation/src/shared/src/PdfSharp.Shared/Properties/GlobalDeclarations.cs new file mode 100644 index 00000000..9569c891 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/Properties/GlobalDeclarations.cs @@ -0,0 +1,20 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +//global using System.IO; + +#if USE_LONG_SIZE +global using SizeType = System.Int64; +#else +global using SizeType = System.Int32; +#endif + +global using static System.FormattableString; + +using System.Diagnostics.CodeAnalysis; +//using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: ComVisible(false)] +//[assembly: SuppressMessage("LoggingGenerator", "SYSLIB1006:Multiple logging methods cannot use the same event ID within a class", +// Justification = "We use logging event ids as documented, i.e. multiple times", Scope = "member"/*, Target = "~M:PdfSharp.Internal.Logging.LogMessages.XGraphicsCreated(Microsoft.Extensions.Logging.ILogger,System.String)"*/)] diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/README.md b/src/foundation/src/shared/src/PdfSharp.Shared/README.md new file mode 100644 index 00000000..f49f217e --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/README.md @@ -0,0 +1,28 @@ +# PDFsharp.Shared + +This is the PDFsharp.Shared project. +It contains code that is used in all PDFsharp foundation assemblies, but should not be publicly visible. +The visibility of all code in this assembly is internal and shared by the InternalsVisibleTo attribute. + +This approach has the following advantages. + +* Functionality can be shared between PDFsharp assemblies without making it publicly visible. +* It is easier to use code required by the C# compiler to use language features not available in + .NET Framework or .NET Stndard +* We have no public internal stuff anymore. E.g. the class **NRT** was introduced to transform the + code to nullable reference types. This class is now internal and not visible to PDFsharp users anymore. + +The approach has some technical consequences. + +* All PDFsharp assemblies has a strong name because some users may need it for the global assembly cache + still used with .NET Framework. Therefore, `PDFsharp.Shared` also has a strong name. And because + a strong named assembly can only grant friendly access to assemblies that also are strong named, + also test and other assemblies must have a strong name. +* We use GitVersion as our tool for creating version information. This tool generates the internal class + **GitVersionInformation** in the root namespace for every assembly. Because all internals of + `PDFsharp.Shared` are visible to all PDFsharp assemblies, **GitVersionInformation** from `PDFsharp.Shared` + clashes with the own version of every assembly with friendly access. This is not a problem, because firstly + all field of all copies of **GitVersionInformation** have the same value anyway and secondly the compiler + uses the class of the current assembly, not the imported one. We only have to disable the warning when + we access a field of **GitVersionInformation**. + diff --git a/src/foundation/src/shared/src/PdfSharp.Shared/System/CompilerServices.cs b/src/foundation/src/shared/src/PdfSharp.Shared/System/CompilerServices.cs new file mode 100644 index 00000000..79d88470 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Shared/System/CompilerServices.cs @@ -0,0 +1,290 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +// This file contains code from the .NET source to use some newer C# features in .NET Standard / Framework. +// All classes are internal, i.e. using PDFsharp packages does not make this functionality visible in +// your projects. + +#if NET462 || NETSTANDARD2_0 +namespace System.Runtime.CompilerServices +{ + /// + /// Required to compile init-only setters in .NET Standard and .NET Framework 4.71. + /// + internal static class IsExternalInit { } +} +#endif + +#if NET462 || NETSTANDARD2_0 +namespace System.Diagnostics.CodeAnalysis +{ + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + sealed class MaybeNullAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + sealed class MaybeNullWhenAttribute : Attribute + { + public MaybeNullWhenAttribute(bool returnValue) { } + } + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + sealed class NotNullWhenAttribute : Attribute + { + public NotNullWhenAttribute(bool returnValue) { } + } + + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + sealed class DoesNotReturnAttribute : Attribute + { } + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + sealed class DoesNotReturnIfAttribute : Attribute + { + public DoesNotReturnIfAttribute(bool parameterValue) { } + } +} + +static class StringExtensions +{ + /// + /// String.Contains implementation for .NET Framework and .NET Standard as an extension method. + /// + internal static bool Contains(this string s, string value, StringComparison comparisonType) => s.IndexOf(value, comparisonType) >= 0; +} +#endif + +#if (NET462 || NETSTANDARD2_0) + +// This is just experimental. If we use it in PDFsharp, the code will move to the PDFsharp assembly +// and the classes become internal. Otherwise, customers may run into problems of ambiguity of these classes. +// true is set in Directory.Build.targets. +// StL/24-03-04: We will use Index and Range in PDFsharp until we ger problem reports. + +namespace System +{ + // This is the original source code from GitHub.,Therefore, no problems are expected. + // https://github.com/dotnet/runtime/blob/419e949d258ecee4c40a460fb09c66d974229623/src/libraries/System.Private.CoreLib/src/System/Index.cs + // https://github.com/dotnet/runtime/blob/419e949d258ecee4c40a460fb09c66d974229623/src/libraries/System.Private.CoreLib/src/System/Range.cs + + using System.Runtime.CompilerServices; + + /// Represent a type can be used to index a collection either from the start or the end. + /// + /// Index is used by the C# compiler to support the new index syntax + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; + /// int lastElement = someArray[^1]; // lastElement = 5 + /// + /// + /*public*/ + readonly struct Index : IEquatable + { + private readonly int _value; + + /// Construct an Index using a value and indicating if the index is from the start or from the end. + /// The index value. it has to be zero or positive number. + /// Indicating if the index is from the start or from the end. + /// + /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Index(int value, bool fromEnd = false) + { + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + + if (fromEnd) + _value = ~value; + else + _value = value; + } + + // The following private constructors mainly created for perf reason to avoid the checks + private Index(int value) + { + _value = value; + } + + /// Create an Index pointing at first element. + public static Index Start => new Index(0); + + /// Create an Index pointing at beyond last element. + public static Index End => new Index(~0); + + /// Create an Index from the start at the position indicated by the value. + /// The index value from the start. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromStart(int value) + { + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + + return new Index(value); + } + + /// Create an Index from the end at the position indicated by the value. + /// The index value from the end. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromEnd(int value) + { + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + + return new Index(~value); + } + + /// Returns the index value. + public int Value + { + get + { + if (_value < 0) + return ~_value; + else + return _value; + } + } + + /// Indicates whether the index is from the start or the end. + public bool IsFromEnd => _value < 0; + + /// Calculate the offset from the start using the giving collection length. + /// The length of the collection that the Index will be used with. length has to be a positive value + /// + /// For performance reason, we dont validate the input length parameter and the returned offset value against negative values. + /// we dont validate either the returned offset is greater than the input length. + /// It is expected Index will be used with collections which always have non-negative length/count. If the returned offset is negative and + /// then used to index a collection will get out of range exception which will be same affect as the validation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int GetOffset(int length) + { + var offset = _value; + if (IsFromEnd) + { + // offset = length - (~value) + // offset = length + (~(~value) + 1) + // offset = length + value + 1 + + offset += length + 1; + } + return offset; + } + + /// Indicates whether the current Index object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value; + + /// Indicates whether the current Index object is equal to another Index object. + /// An object to compare with this object + public bool Equals(Index other) => _value == other._value; + + /// Returns the hash code for this instance. + public override int GetHashCode() => _value; + + /// Converts integer number to an Index. + public static implicit operator Index(int value) => FromStart(value); + + /// Converts the value of the current Index object to its equivalent string representation. + public override string ToString() + { + if (IsFromEnd) + return "^" + ((uint)Value).ToString(); + + return ((uint)Value).ToString(); + } + } + + /// Represent a range has start and end indexes. + /// + /// Range is used by the C# compiler to support the range syntax. + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; + /// int[] subArray1 = someArray[0..2]; // { 1, 2 } + /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } + /// + /// + /*public*/ + readonly struct Range : IEquatable + { + /// Represent the inclusive start index of the Range. + public Index Start { get; } + + /// Represent the exclusive end index of the Range. + public Index End { get; } + + /// Construct a Range object using the start and end indexes. + /// Represent the inclusive start index of the range. + /// Represent the exclusive end index of the range. + public Range(Index start, Index end) + { + Start = start; + End = end; + } + + /// Indicates whether the current Range object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => + value is Range r && + r.Start.Equals(Start) && + r.End.Equals(End); + + /// Indicates whether the current Range object is equal to another Range object. + /// An object to compare with this object + public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); + + /// Returns the hash code for this instance. + public override int GetHashCode() + { + return Start.GetHashCode() * 31 + End.GetHashCode(); + } + + /// Converts the value of the current Range object to its equivalent string representation. + public override string ToString() + { + return Start + ".." + End; + } + + /// Create a Range object starting from start index to the end of the collection. + public static Range StartAt(Index start) => new Range(start, Index.End); + + /// Create a Range object starting from first element in the collection to the end Index. + public static Range EndAt(Index end) => new Range(Index.Start, end); + + /// Create a Range object starting from first element to the end. + public static Range All => new Range(Index.Start, Index.End); + + /// Calculate the start offset and length of range object using a collection length. + /// The length of the collection that the range will be used with. length has to be a positive value. + /// + /// For performance reason, we dont validate the input length parameter against negative values. + /// It is expected Range will be used with collections which always have non-negative length/count. + /// We validate the range is inside the length scope though. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public (int Offset, int Length) GetOffsetAndLength(int length) + { + int start; + var startIndex = Start; + if (startIndex.IsFromEnd) + start = length - startIndex.Value; + else + start = startIndex.Value; + + int end; + var endIndex = End; + if (endIndex.IsFromEnd) + end = length - endIndex.Value; + else + end = endIndex.Value; + + if ((uint)end > (uint)length || (uint)start > (uint)end) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + + return (start, end - start); + } + } +} +#endif diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets-gdi/PdfSharp.Snippets-gdi.csproj b/src/foundation/src/shared/src/PdfSharp.Snippets-gdi/PdfSharp.Snippets-gdi.csproj index 9697d7c9..9bde7391 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets-gdi/PdfSharp.Snippets-gdi.csproj +++ b/src/foundation/src/shared/src/PdfSharp.Snippets-gdi/PdfSharp.Snippets-gdi.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true PdfSharp.Snippets true @@ -68,6 +68,7 @@ + @@ -76,6 +77,13 @@ + + + + + + + diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets-wpf/PdfSharp.Snippets-wpf.csproj b/src/foundation/src/shared/src/PdfSharp.Snippets-wpf/PdfSharp.Snippets-wpf.csproj index d6197348..9a1848ff 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets-wpf/PdfSharp.Snippets-wpf.csproj +++ b/src/foundation/src/shared/src/PdfSharp.Snippets-wpf/PdfSharp.Snippets-wpf.csproj @@ -1,7 +1,7 @@  - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 true PdfSharp.Snippets true @@ -14,12 +14,6 @@ false - - - - - - @@ -74,6 +68,7 @@ + @@ -81,6 +76,19 @@ + + + + + + + + + + + + + diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/colors/ColorsCmyk.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/colors/ColorsCmyk.cs index e154dcd3..b777e617 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/colors/ColorsCmyk.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/colors/ColorsCmyk.cs @@ -26,10 +26,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 1, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 0, 0, 0, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 0, 0, 0, 0)), rect); } } EndBox(gfx); @@ -38,10 +38,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 2, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 0, 0, 1, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 0, 0, 1, 0)), rect); } } EndBox(gfx); @@ -50,10 +50,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 3, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 1, 0, 0, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 1, 0, 0, 0)), rect); } } EndBox(gfx); @@ -62,10 +62,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 4, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 1, 0, 1, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 1, 0, 1, 0)), rect); } } EndBox(gfx); @@ -74,10 +74,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 5, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 0, 1, 0, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 0, 1, 0, 0)), rect); } } EndBox(gfx); @@ -86,10 +86,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 6, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 0, 1, 1, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 0, 1, 1, 0)), rect); } } EndBox(gfx); @@ -98,10 +98,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 7, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 1, 1, 0, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 1, 1, 0, 0)), rect); } } EndBox(gfx); @@ -110,10 +110,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 8, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 0, 0, 0, 1)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 0, 0, 0, 1)), rect); } } EndBox(gfx); diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/colors/ColorsRgb.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/colors/ColorsRgb.cs index e78dc5d6..c9130f4d 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/colors/ColorsRgb.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/colors/ColorsRgb.cs @@ -26,10 +26,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 1, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(i * 255 / 9, 255, 255, 255)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(idx * 255 / 9, 255, 255, 255)), rect); } } EndBox(gfx); @@ -38,10 +38,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 2, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(i * 255 / 9, 255, 255, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(idx * 255 / 9, 255, 255, 0)), rect); } } EndBox(gfx); @@ -50,10 +50,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 3, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(i * 255 / 9, 0, 255, 255)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(idx * 255 / 9, 0, 255, 255)), rect); } } EndBox(gfx); @@ -62,10 +62,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 4, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(i * 255 / 9, 0, 255, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(idx * 255 / 9, 0, 255, 0)), rect); } } EndBox(gfx); @@ -74,10 +74,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 5, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(i * 255 / 9, 255, 0, 255)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(idx * 255 / 9, 255, 0, 255)), rect); } } EndBox(gfx); @@ -86,10 +86,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 6, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(i * 255 / 9, 255, 0, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(idx * 255 / 9, 255, 0, 0)), rect); } } EndBox(gfx); @@ -98,10 +98,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 7, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(i * 255 / 9, 0, 0, 255)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(idx * 255 / 9, 0, 0, 255)), rect); } } EndBox(gfx); @@ -110,10 +110,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 8, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(i * 255 / 9, 0, 0, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromArgb(idx * 255 / 9, 0, 0, 0)), rect); } } EndBox(gfx); diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/graphics/GraphicsFromImage.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/graphics/GraphicsFromImage.cs index a52c8d22..3247c143 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/graphics/GraphicsFromImage.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/graphics/GraphicsFromImage.cs @@ -26,10 +26,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 1, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 0, 0, 0, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 0, 0, 0, 0)), rect); } } EndBox(gfx); @@ -38,10 +38,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 2, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 0, 0, 1, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 0, 0, 1, 0)), rect); } } EndBox(gfx); @@ -50,10 +50,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 3, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 1, 0, 0, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 1, 0, 0, 0)), rect); } } EndBox(gfx); @@ -62,10 +62,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 4, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 1, 0, 1, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 1, 0, 1, 0)), rect); } } EndBox(gfx); @@ -74,10 +74,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 5, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 0, 1, 0, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 0, 1, 0, 0)), rect); } } EndBox(gfx); @@ -86,10 +86,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 6, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 0, 1, 1, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 0, 1, 1, 0)), rect); } } EndBox(gfx); @@ -98,10 +98,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 7, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 1, 1, 0, 0)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 1, 1, 0, 0)), rect); } } EndBox(gfx); @@ -110,10 +110,10 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 8, BoxOptions.Tile); { gfx.DrawLines(new XPen(XColors.Black, 1), 0, 0, BoxWidth, BoxHeight); - for (int i = 0; i < 10; ++i) + for (int idx = 0; idx < 10; idx++) { - var rect = GetDeciRect(i); - gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(i / 9f, 0, 0, 0, 1)), rect); + var rect = GetDeciRect(idx); + gfx.DrawRectangle(new XSolidBrush(XColor.FromCmyk(idx / 9f, 0, 0, 0, 1)), rect); } } EndBox(gfx); diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/graphics/GraphicsUnitUpwards.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/graphics/GraphicsUnitUpwards.cs index aa0ce393..531ab0a3 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/graphics/GraphicsUnitUpwards.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/graphics/GraphicsUnitUpwards.cs @@ -5,7 +5,6 @@ namespace PdfSharp.Snippets.Drawing { - /// /// /// diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineStyle.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineStyle.cs index a8b43f72..06b2220b 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineStyle.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineStyle.cs @@ -53,7 +53,7 @@ public override void RenderSnippet(XGraphics gfx) // Custom pattern //pen.DashStyle = XDashStyle.Custom; - pen.DashPattern = new[] { 3, 1, 2.5, 1.5 }; + pen.DashPattern = [3, 1, 2.5, 1.5]; pen.Width = 7; pen.DashOffset = 1; diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineTestsNew.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineTestsNew.cs index 11903348..1e3f2a4c 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineTestsNew.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineTestsNew.cs @@ -35,7 +35,7 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 4, BoxOptions.Tile); { - gfx.DrawBeziers(XPens.Black, new []{new XPoint(160, 20), new XPoint(310, -30), new XPoint(-90, 170), new XPoint(60, 120), new XPoint(20, 120), new XPoint(60, 20), new XPoint(20, 20)}); + gfx.DrawBeziers(XPens.Black, new[] { new XPoint(160, 20), new XPoint(310, -30), new XPoint(-90, 170), new XPoint(60, 120), new XPoint(20, 120), new XPoint(60, 20), new XPoint(20, 20) }); } EndBox(gfx); diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineTypes.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineTypes.cs index e5fb7518..e8185447 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineTypes.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/lines/LineTypes.cs @@ -35,7 +35,7 @@ public override void RenderSnippet(XGraphics gfx) BeginBox(gfx, 4, BoxOptions.Tile); { - gfx.DrawBeziers(XPens.Black, new []{new XPoint(160, 20), new XPoint(310, -30), new XPoint(-90, 170), new XPoint(60, 120), new XPoint(20, 120), new XPoint(60, 20), new XPoint(20, 20)}); + gfx.DrawBeziers(XPens.Black, new[] { new XPoint(160, 20), new XPoint(310, -30), new XPoint(-90, 170), new XPoint(60, 120), new XPoint(20, 120), new XPoint(60, 20), new XPoint(20, 20) }); } EndBox(gfx); diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/paths/PathMisc.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/paths/PathMisc.cs index 95916912..ca6bdbeb 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/paths/PathMisc.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Drawing/paths/PathMisc.cs @@ -70,7 +70,7 @@ public override void RenderSnippet(XGraphics gfx) path.AddBezier(new XPoint(160, 60), new XPoint(140, 70), new XPoint(180, 70), new XPoint(160, 80)); path.CloseFigure(); - path.AddCurve(new []{new XPoint(190, 50), new XPoint(170, 30), new XPoint(210, 30), new XPoint(190, 10) }); + path.AddCurve(new[] { new XPoint(190, 50), new XPoint(170, 30), new XPoint(210, 30), new XPoint(190, 10) }); path.CloseFigure(); path.AddLine(new XPoint(90, 20), new XPoint(70, 40)); diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Font/encoding/FontAnsiEncoding.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Font/encoding/FontAnsiEncoding.cs index 6ab03ca1..02590334 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Font/encoding/FontAnsiEncoding.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Font/encoding/FontAnsiEncoding.cs @@ -1,14 +1,8 @@ // PDFsharp - A .NET library for processing PDF // See the LICENSE file in the solution root for more information. -using System; -using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; -using System.Resources; -using System.Text; using PdfSharp.Drawing; -using PdfSharp.Fonts; using PdfSharp.Quality; #if GDI using System.Drawing; @@ -38,25 +32,14 @@ public override void RenderSnippet(XGraphics gfx) var fontAnsi = new XFont("Arial", 10, XFontStyleEx.Regular, XPdfFontOptions.WinAnsiDefault); - int x, y; const int top = 90; const int left = 50; const int dx = 140; const int dy = 15; - //var encoder = Encoding.GetEncoding(1252); - //var encoder = CodePagesEncodingProvider.Instance.GetEncoding(1252)!; - _ = typeof(int); - - //PdfSharp.Pdf.Internal.AnsiEncoding.ProofImplementation(); - -#if NET6_0_OR_GREATER_ - var encoder = CodePagesEncodingProvider.Instance.GetEncoding(1252)!; -#else var encoder = new PdfSharp.Pdf.Internal.AnsiEncoding(); -#endif - byte[] ansi = new byte[1]; + var ansi = new byte[1]; for (int idx = 0; idx <= 255; idx++) { @@ -68,8 +51,8 @@ public override void RenderSnippet(XGraphics gfx) //GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) var sss = encoder.GetString(ansi); - x = left + (idx >> 6) * dx + (idx >= 192 ? 50 : 0); - y = top + (idx % 64) * dy; + var x = left + (idx >> 6) * dx + (idx >= 192 ? 50 : 0); + var y = top + (idx % 64) * dy; var item = Table[idx]; gfx.DrawString($"{idx,-3:0} {idx:X2} {item.Char} {sss}", fontAnsi, XBrushes.DarkBlue, x, y); //gfx.DrawString($"{item.Description}", font2, XBrushes.DarkBlue, x + 60, y); diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/ChineseFont.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/ChineseFont.cs index 49783889..7d33fe9d 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/ChineseFont.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/ChineseFont.cs @@ -32,7 +32,7 @@ // document.Outlines.Add("456 你好!", page); // // Save and show the document. -// string filename = await SaveAndShowDocumentAsync(document, "ChineseFont"); +// string filename = await SaveAndShowDocumentAsync(document, "ChineseFont").ConfigureAwait(false); // } // } //} diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/DefaultConstructionSnippets.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/DefaultConstructionSnippets.cs index abe11cd5..a7fd6204 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/DefaultConstructionSnippets.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/DefaultConstructionSnippets.cs @@ -32,7 +32,7 @@ using System.Windows; using System.Windows.Media; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media; #endif using PdfSharp.Drawing; @@ -70,7 +70,7 @@ public override void RenderSnippet(XGraphics gfx) { XPoint pos; -#if true || CORE || GDI || WPF || UWP +#if true || CORE || GDI || WPF || WUI var fntRegular = new XFont(FamilyName, EmSize, XFontStyleEx.Regular, _fontOptions); var fntBold = new XFont(FamilyName, EmSize, XFontStyleEx.Bold, _fontOptions); var fntItalic = new XFont(FamilyName, EmSize, XFontStyleEx.Italic, _fontOptions); @@ -272,9 +272,9 @@ public FontFamilyConstructionSnippet() public override void RenderSnippet(XGraphics gfx) { -#if CORE || GDI || UWP +#if CORE || GDI || WUI #if TIMES_NEW_ROMAN -#if !UWP +#if !WUI var times = new FontFamily("Times New Roman"); #else var times = "Times New Roman"; @@ -290,7 +290,7 @@ public override void RenderSnippet(XGraphics gfx) var timesBoldItalic2 = new XFont(times, 42, XFontStyleEx.BoldItalic); #endif #if SEGOE_UI -#if !UWP && false +#if !WUI && false var segoe = new FontFamily("Segoe UI"); #else var segoe = "Segoe UI"; diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/HelloWorldSnippets.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/HelloWorldSnippets.cs index d0e4fa37..23c04235 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/HelloWorldSnippets.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/HelloWorldSnippets.cs @@ -31,7 +31,7 @@ using System.Windows; using System.Windows.Media; #endif -#if UWP +#if WUI using Windows.UI.Xaml.Media; #endif using PdfSharp.Drawing; diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/PrivateFontCollectionSnippets.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/PrivateFontCollectionSnippets.cs index 361425e6..1f76a2e5 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/PrivateFontCollectionSnippets.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Font/selection/PrivateFontCollectionSnippets.cs @@ -64,10 +64,10 @@ public override void RenderSnippet(XGraphics gfx) // Add Arial and Tahoma from the Fonts directory to the private font collection. #if true // Register regular first. - string[] fonts = { - "arial.ttf", "arialbd.ttf", - "TAHOMA.ttf", "TAHOMABD.ttf" - }; + string[] fonts = + [ + "arial.ttf", "arialbd.ttf", "TAHOMA.ttf", "TAHOMABD.ttf" + ]; #else // Register bold first. // BOX3 causes an exception if bold fonts are loaded before regular fonts. diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Pangrams.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Pangrams.cs index 3d7305dd..d19aa8d2 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/Pangrams.cs +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Pangrams.cs @@ -19,7 +19,7 @@ public class Pangrams public static string TwelveBoxer = "Zwölf Boxkämpfer jagen Viktor quer über den großen Sylter Deich. 1234567890 +-*/"; } - public class xxxxxxxxxx + public class LeftToRightText { public static string Arabic = "نص حكيم له سر قاطع وذو شأن عظيم مكتوب على ثوب أخضر ومغلف بجلد أزرق"; public static string Arabic2 = "يقفز الثعلب البني السريع فوق الكسول. 1234567890 +-*/"; diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/Pdf/signatures/BouncyCastleSigner.cs b/src/foundation/src/shared/src/PdfSharp.Snippets/Pdf/signatures/BouncyCastleSigner.cs new file mode 100644 index 00000000..44d1b3eb --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/Pdf/signatures/BouncyCastleSigner.cs @@ -0,0 +1,136 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +#if WPF +using System.IO; +#endif +using System.Security.Cryptography.X509Certificates; +using System.Security.Cryptography; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Collections; +using PdfSharp.Pdf.Signatures; + +namespace PdfSharp.Snippets.Pdf +{ + /// + /// Implementation of IDigitalSigner using BouncyCastle. + /// + public class BouncyCastleSigner((X509Certificate2, X509Certificate2Collection) certificateData, PdfMessageDigestType digestType) : IDigitalSigner + { + /// + /// Gets the name of the certificate. + /// + public string CertificateName => Certificate.GetNameInfo(X509NameType.SimpleName, false); + + // public Int32 GetKeySize() + // { + //#if NET6_0_OR_GREATER + // return Certificate.PublicKey.GetRSAPublicKey()!.KeySize; + //#else + // return 17; // Hack! + //#endif + // } + + public async Task GetSignatureSizeAsync() + { + if (_signatureSize == 0) + { + // The signature size varies depending on the length of the digest and the size of the certificate. + // We simply calculate it once by signing an empty stream. + _signatureSize = (await GetSignatureAsync(new MemoryStream([0])).ConfigureAwait(false)).Length; + } + return _signatureSize; + } + int _signatureSize; + + public async Task GetSignatureAsync(Stream stream) + { + await Task.CompletedTask.ConfigureAwait(false); + + stream.Position = 0; + + var signedDataGenerator = new CmsSignedDataGenerator(); + + var cert = DotNetUtilities.FromX509Certificate(Certificate); + var key = DotNetUtilities.GetKeyPair(GetAsymmetricAlgorithm(Certificate)); +#if NET6_0_OR_GREATER + var allCerts = CertificateChain.Select(DotNetUtilities.FromX509Certificate); +#else + var allCerts = CertificateChain.OfType().Select(DotNetUtilities.FromX509Certificate); +#endif + + var store = CollectionUtilities.CreateStore(allCerts); + + signedDataGenerator.AddSigner(key.Private, cert, GetProperDigestAlgorithm(DigestType)); + signedDataGenerator.AddCertificates(store); + + var msg = new CmsProcessableInputStream(stream); + + var signedData = signedDataGenerator.Generate(msg, false); + + return signedData.GetEncoded(); + } + + + X509Certificate2 Certificate { get; set; } = certificateData.Item1; + + X509Certificate2Collection CertificateChain { get; } = certificateData.Item2; + + PdfMessageDigestType DigestType { get; } = digestType; + + //byte[] GetSignedCms(Stream rangedStream, int pdfVersion) + //{ + //} + + /// + /// adbe.pkcs7.detached supported algorithms: + /// SHA1 (PDF 1.3), SHA256 (PDF 1.6), SHA384/SHA512/RIPEMD160 (PDF 1.7) + /// + /// PDF version as int + string GetProperDigestAlgorithm(int pdfVersion) + { + return pdfVersion switch + { + >= 17 => CmsSignedGenerator.DigestSha512, + 16 => CmsSignedGenerator.DigestSha256, + >= 13 => CmsSignedGenerator.DigestSha256, // SHA1 is obsolete, use at least SHA256 + + _ => CmsSignedGenerator.DigestSha256 + }; + } + + string GetProperDigestAlgorithm(PdfMessageDigestType digestType) + { + return digestType switch + { + PdfMessageDigestType.SHA1 => CmsSignedGenerator.DigestSha1, // SHA1 is obsolete, but you can use it. + PdfMessageDigestType.SHA256 => CmsSignedGenerator.DigestSha256, + PdfMessageDigestType.SHA384 => CmsSignedGenerator.DigestSha384, + PdfMessageDigestType.SHA512 => CmsSignedGenerator.DigestSha512, + PdfMessageDigestType.RIPEMD160 => CmsSignedGenerator.DigestRipeMD160, + _ => throw new ArgumentOutOfRangeException(nameof(digestType), digestType, null) + }; + } + + AsymmetricAlgorithm? GetAsymmetricAlgorithm(X509Certificate2 cert) + { + const string RSA = "1.2.840.113549.1.1.1"; +#if NET6_0_OR_GREATER + const string DSA = "1.2.840.10040.4.1"; +#endif + const string ECC = "1.2.840.10045.2.1"; + + return cert.PublicKey.Oid.Value switch + { + RSA => cert.GetRSAPrivateKey(), +#if NET6_0_OR_GREATER + DSA => cert.GetDSAPrivateKey(), +#endif + ECC => cert.GetECDsaPrivateKey(), + + _ => throw new NotImplementedException($"Unexpected OID value '{cert.PublicKey.Oid.Value}' for certificate."), + }; + } + } +} diff --git a/src/foundation/src/shared/src/PdfSharp.Snippets/PdfSharp.Snippets.csproj b/src/foundation/src/shared/src/PdfSharp.Snippets/PdfSharp.Snippets.csproj index ba8bdbdd..f43843c7 100644 --- a/src/foundation/src/shared/src/PdfSharp.Snippets/PdfSharp.Snippets.csproj +++ b/src/foundation/src/shared/src/PdfSharp.Snippets/PdfSharp.Snippets.csproj @@ -1,7 +1,7 @@  - net6.0;netstandard2.0 + net6.0;net8.0;netstandard2.0 PdfSharp.Snippets PdfSharp.Snippets TRACE;CORE @@ -19,6 +19,8 @@ + + @@ -29,4 +31,9 @@ + + + + + diff --git a/src/foundation/src/shared/src/PdfSharp.System/Diagnostics/NullabilityHelper.cs b/src/foundation/src/shared/src/PdfSharp.System/Diagnostics/NullabilityHelper.cs index 08a3db03..83d95243 100644 --- a/src/foundation/src/shared/src/PdfSharp.System/Diagnostics/NullabilityHelper.cs +++ b/src/foundation/src/shared/src/PdfSharp.System/Diagnostics/NullabilityHelper.cs @@ -1,48 +1,48 @@ -// PDFsharp - A .NET library for processing PDF -// See the LICENSE file in the solution root for more information. +//// PDFsharp - A .NET library for processing PDF +//// See the LICENSE file in the solution root for more information. -using System.Diagnostics.CodeAnalysis; +//using System.Diagnostics.CodeAnalysis; -namespace PdfSharp.Diagnostics -{ - /// - /// Helper class for code migration to nullable reference types. - /// - // ReSharper disable once InconsistentNaming - public static class NRT - { - /// - /// Throws an InvalidOperationException because an expression which must not be null is null. - /// - /// The message. - /// - [DoesNotReturn] - public static void ThrowOnNull(string? message = null) - => throw new InvalidOperationException(message ?? "Expression must not be null here."); +//namespace PdfSharp.Diagnostics +//{ +// /// +// /// Helper class for code migration to nullable reference types. +// /// +// // ReSharper disable once InconsistentNaming +// public static class NRT +// { +// /// +// /// Throws an InvalidOperationException because an expression which must not be null is null. +// /// +// /// The message. +// /// +// [DoesNotReturn] +// public static void ThrowOnNull(string? message = null) +// => throw new InvalidOperationException(message ?? "Expression must not be null here."); - /// - /// Throws InvalidOperationException. Use this function during the transition from older C# code - /// to new code that uses nullable reference types. - /// - /// The type this function must return to be compiled correctly. - /// An optional message used for the exception. - /// Nothing, always throws. - /// - [DoesNotReturn] - public static TResult ThrowOnNull(string? message = null) - => throw new InvalidOperationException(message ?? $"'{typeof(TResult).Name}' must not be null here."); +// /// +// /// Throws InvalidOperationException. Use this function during the transition from older C# code +// /// to new code that uses nullable reference types. +// /// +// /// The type this function must return to be compiled correctly. +// /// An optional message used for the exception. +// /// Nothing, always throws. +// /// +// [DoesNotReturn] +// public static TResult ThrowOnNull(string? message = null) +// => throw new InvalidOperationException(message ?? $"'{typeof(TResult).Name}' must not be null here."); - /// - /// Throws InvalidOperationException. Use this function during the transition from older C# code - /// to new code that uses nullable reference types. - /// - /// The type this function must return to be compiled correctly. - /// The type of the object that is null. - /// An optional message used for the exception. - /// Nothing, always throws. - /// - [DoesNotReturn] - public static TResult ThrowOnNull(string? message = null) - => throw new InvalidOperationException(message ?? $"'{typeof(TType).Name}' must not be null here."); - } -} +// /// +// /// Throws InvalidOperationException. Use this function during the transition from older C# code +// /// to new code that uses nullable reference types. +// /// +// /// The type this function must return to be compiled correctly. +// /// The type of the object that is null. +// /// An optional message used for the exception. +// /// Nothing, always throws. +// /// +// [DoesNotReturn] +// public static TResult ThrowOnNull(string? message = null) +// => throw new InvalidOperationException(message ?? $"'{typeof(TType).Name}' must not be null here."); +// } +//} diff --git a/src/foundation/src/shared/src/PdfSharp.System/IO/StreamToMemoryReader.cs b/src/foundation/src/shared/src/PdfSharp.System/IO/StreamToMemoryReader.cs new file mode 100644 index 00000000..74c8f56b --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.System/IO/StreamToMemoryReader.cs @@ -0,0 +1,29 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System.IO; + +namespace PdfSharp.IO_dummy +{ + /// + /// Reads any stream into a Memory<byte>. + /// + public class StreamToMemoryReader(Stream stream) + { + /// + /// Reads a stream to the end. + /// + public Memory ReadToEnd() + { + // Just for testing and integration. + + var memoryStream = new MemoryStream(); + _stream.CopyTo(memoryStream); + return memoryStream.ToArray(); + } + + readonly Stream _stream = stream ?? throw new ArgumentNullException(nameof(stream)); + } +} diff --git a/src/foundation/src/shared/src/PdfSharp.System/Internal/BuildVersion.cs b/src/foundation/src/shared/src/PdfSharp.System/Internal/BuildVersion.cs new file mode 100644 index 00000000..39eccbb7 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.System/Internal/BuildVersion.cs @@ -0,0 +1,24 @@ +//// PDFsharp - A .NET library for processing PDF +//// See the LICENSE file in the solution root for more information. + +//namespace PdfSharp.Internal +//{ +//#if DEBUG +// /// +// /// Internal class to calculate the PDFsharp build version. +// /// +// public class BuildInformation +// { +// /// +// /// The day we start counting. +// /// +// public const string VersionReferenceDate = "2005-01-01"; + +// /// +// /// The PDFsharp build version used as fourth value in AssemblyFileVersion. +// /// Must be set in gitversion.yml. +// /// +// public static int BuildVersionNumber = (DateTime.Now - new DateTime(2005, 1, 1)).Days; +// } +//#endif +//} diff --git a/src/foundation/src/shared/src/PdfSharp.System/Internal/Configuration.cs b/src/foundation/src/shared/src/PdfSharp.System/Internal/Configuration.cs index b0512b69..f9a7913c 100644 --- a/src/foundation/src/shared/src/PdfSharp.System/Internal/Configuration.cs +++ b/src/foundation/src/shared/src/PdfSharp.System/Internal/Configuration.cs @@ -1,14 +1,14 @@ -// PDFsharp - A .NET library for processing PDF -// See the LICENSE file in the solution root for more information. +//// PDFsharp - A .NET library for processing PDF +//// See the LICENSE file in the solution root for more information. -global using System.Diagnostics; -global using PdfSharp.Diagnostics; -global using System.Globalization; -global using static System.FormattableString; // Used for Invariant($"…") +////global using System.Diagnostics; +////global using PdfSharp.Diagnostics; +////global using System.Globalization; +////global using static System.FormattableString; // Used for Invariant($"…") -namespace PdfSharp.Internal -{ - //internal class Configuration - //{ - //} -} +//namespace PdfSharp.Internal +//{ +// //internal class Configuration +// //{ +// //} +//} diff --git a/src/foundation/src/shared/src/PdfSharp.System/Internal/SyMgs.cs b/src/foundation/src/shared/src/PdfSharp.System/Internal/SyMgs.cs new file mode 100644 index 00000000..ec454771 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.System/Internal/SyMgs.cs @@ -0,0 +1,26 @@ +//// PDFsharp - A .NET library for processing PDF +//// PDFsharp - A .NET library for processing PDF +//// See the LICENSE file in the solution root for more information. + +//#pragma warning disable 1591 // Because this is preview code. + +//using System.Diagnostics.Contracts; + +//namespace PdfSharp.Internal +//{ +// /// +// /// (PDFsharp) System message. +// /// +// // ReSharper disable once InconsistentNaming +// // ReSharper disable once IdentifierTypo +// public static class SyMgs +// { +// public static string IndexOutOfRange3 +// => "Index out of range."; + +// public static SyMsg IndexOutOfRange2(string parameter, T lowerBound, T upperBound) +// => new(SyMsgId.IndexOutOfRange, +// $"The value of '{parameter}' is out of range. " + +// Invariant($"The value must be between '{lowerBound}' and '{upperBound}'.")); +// } +//} \ No newline at end of file diff --git a/src/foundation/src/shared/src/PdfSharp.System/Internal/SyMsg.cs b/src/foundation/src/shared/src/PdfSharp.System/Internal/SyMsg.cs new file mode 100644 index 00000000..9b3a6d0c --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.System/Internal/SyMsg.cs @@ -0,0 +1,25 @@ +//// PDFsharp - A .NET library for processing PDF +//// PDFsharp - A .NET library for processing PDF +//// See the LICENSE file in the solution root for more information. + +//#pragma warning disable 1591 // Because this is preview code. +//// It should not be public. + +//using Microsoft.Extensions.Logging; + +//namespace PdfSharp.Internal +//{ +// /// +// /// (PDFsharp) System message. +// /// +// public readonly struct SyMsg(SyMsgId id, string message) +// { +// public SyMsgId Id { get; init; } = id; + +// public string Message { get; init; } = message; + +// public EventId EventId => new((int)Id, EventName); + +// public string EventName => Id.ToString(); +// } +//} diff --git a/src/foundation/src/shared/src/PdfSharp.System/Internal/TH.cs b/src/foundation/src/shared/src/PdfSharp.System/Internal/TH.cs new file mode 100644 index 00000000..0f84679d --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.System/Internal/TH.cs @@ -0,0 +1,73 @@ +//// PDFsharp - A .NET library for processing PDF +//// See the LICENSE file in the solution root for more information. + +//#pragma warning disable 1591 // Because this is preview code. + +//using System.Diagnostics.CodeAnalysis; + +//namespace PdfSharp.Internal +//{ +// /// +// /// Experimental throw helper. +// /// +// // ReSharper disable once InconsistentNaming +// public static class TH2 +// { +// // Microsoft throws in the helper function. Maybe this creates less code. +// // But we decided to throw at the position where the problem happens and +// // therefore we only compose the exception here and return it. + +// public static InvalidOperationException InvalidOperationException_ToDo( +// string? info = null) +// { +// var message = info == null +// ? "Here is something to do." +// : $"Here is something to do: {info}"; + +// return new(message); +// } + +// [DoesNotReturn] +// public static void ThrowInvalidOperationException_ToDo( +// string? info = null) +// => throw InvalidOperationException_ToDo(info); + +// public static NotImplementedException NotImplementedException( +// string? info = null, +// Exception? innerException = null) +// { +// var message = info == null +// ? "Here is something to do." +// : $"Here is something to do: {info}"; + +// return innerException == null +// ? new(message) +// : new(message, innerException); +// } + +// [DoesNotReturn] +// public static void ThrowNotImplementedException( +// string? info = null, +// Exception? innerException = null) +// => throw NotImplementedException(info); + +// [DoesNotReturn] +// internal static void ThrowInvalidOperationException_HandleIsNotPinned() +// { +// // throw new InvalidOperationException(SR.InvalidOperation_HandleIsNotPinned); +// throw new Exception(); +// } + +// //[DoesNotReturn] +// //internal static void ThrowValueArgumentOutOfRange_NeedNonNegNumException() +// //{ +// // throw GetArgumentOutOfRangeException(ExceptionArgument.value, +// // ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); +// //} + +// //static ArgumentException GetArgumentException(ExceptionResource resource) +// //{ +// // return new ArgumentException(GetResourceString(resource)); +// //} +// } +//} diff --git a/src/foundation/src/shared/src/PdfSharp.System/Internal/UrlLiterals.cs b/src/foundation/src/shared/src/PdfSharp.System/Internal/UrlLiterals.cs index 2e2a2ac8..57ff83df 100644 --- a/src/foundation/src/shared/src/PdfSharp.System/Internal/UrlLiterals.cs +++ b/src/foundation/src/shared/src/PdfSharp.System/Internal/UrlLiterals.cs @@ -1,30 +1,29 @@ -// PDFsharp - A .NET library for processing PDF -// See the LICENSE file in the solution root for more information. +//// PDFsharp - A .NET library for processing PDF +//// See the LICENSE file in the solution root for more information. -namespace PdfSharp.Internal -{ - /// - /// URLs used in PDFsharp are maintained only here. - /// - public class UrlLiterals // #CHECK_BEFORE_RELEASE - { -#if DEBUG - const string DocsPdfSharpUrl = "http://localhost:8094/"; -#else - const string DocsPdfSharpUrl = "https://docs.pdfsharp.net/"; -#endif +//namespace PdfSharp.Internal +//{ +// /// +// /// URLs used in PDFsharp are maintained only here. +// /// +// public class UrlLiterals // #CHECK_BEFORE_RELEASE +// { +//#if DEBUG +// const string DocsPdfSharpUrl = "http://localhost:8094/"; +//#else +// const string DocsPdfSharpUrl = "https://docs.pdfsharp.net/"; +//#endif - /// - /// URL for missing assets error message. - /// "https://docs.pdfsharp.net/link/download-assets.html" - /// - public const string LinkToAssetsDoc = DocsPdfSharpUrl + "link/download-assets.html"; +// /// +// /// URL for missing assets error message. +// /// "https://docs.pdfsharp.net/link/download-assets.html" +// /// +// public const string LinkToAssetsDoc = DocsPdfSharpUrl + "link/download-assets.html"; - /// - /// URL for missing font resolver. - /// "https://docs.pdfsharp.net/link/font-resolving.html" - /// - public const string LinkToFontResolving = DocsPdfSharpUrl + "link/font-resolving.html"; - - } -} +// /// +// /// URL for missing font resolver. +// /// "https://docs.pdfsharp.net/link/font-resolving.html" +// /// +// public const string LinkToFontResolving = DocsPdfSharpUrl + "link/font-resolving.html"; +// } +//} diff --git a/src/foundation/src/shared/src/PdfSharp.System/Internal/enum/SyMsgId.cs b/src/foundation/src/shared/src/PdfSharp.System/Internal/enum/SyMsgId.cs new file mode 100644 index 00000000..059591e6 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.System/Internal/enum/SyMsgId.cs @@ -0,0 +1,34 @@ +//// PDFsharp - A .NET library for processing PDF +//// See the LICENSE file in the solution root for more information. + +//#pragma warning disable 1591 // Because this is preview code. + +//namespace PdfSharp.Internal +//{ +// /// +// /// System message ID. +// /// +// public enum SyMsgId +// { +// None = 0, + +// // ----- General Messages --------------------------------------------------------------------- + +// IndexOutOfRange = MessageIdOffset.Sy, +// IndexOutOfRange2, +// } + +// /// +// /// Offsets to ensure that all message IDs are pairwise distinct +// /// within PDFsharp foundation. +// /// +// public enum MessageIdOffset +// { +// Sy = 1000, +// Ps = 3000, +// PsCrypto = 4000, +// MdDom = 5000, +// MdPdf = 6000, +// MdRtf = 7000, +// } +//} diff --git a/src/foundation/src/shared/src/PdfSharp.System/Pdf.Signatures/IDigitalSigner.cs b/src/foundation/src/shared/src/PdfSharp.System/Pdf.Signatures/IDigitalSigner.cs new file mode 100644 index 00000000..73a960df --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.System/Pdf.Signatures/IDigitalSigner.cs @@ -0,0 +1,28 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// Interface for classes that generate digital signatures. + /// + public interface IDigitalSigner + { + /// + /// Gets a human-readable name of the used certificate. + /// + string CertificateName { get; } + + /// + /// Gets the size of the signature in bytes. + /// The size is used to reserve space in the PDF file that is later filled with the signature. + /// + Task GetSignatureSizeAsync(); + + /// + /// Gets the signatures of the specified stream. + /// + /// + Task GetSignatureAsync(Stream stream); + } +} diff --git a/src/foundation/src/shared/src/PdfSharp.System/Pdf.Signatures/enums/PdfMessageDigestType.cs b/src/foundation/src/shared/src/PdfSharp.System/Pdf.Signatures/enums/PdfMessageDigestType.cs new file mode 100644 index 00000000..db3bb3c7 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.System/Pdf.Signatures/enums/PdfMessageDigestType.cs @@ -0,0 +1,38 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +// ReSharper disable InconsistentNaming + +namespace PdfSharp.Pdf.Signatures +{ + /// + /// Specifies the algorithm used to generate the message digest. + /// + public enum PdfMessageDigestType + { + /// + /// (PDF 1.3) + /// + SHA1 = 0, + + /// + /// (PDF 1.6) + /// + SHA256 = 1, + + /// + /// (PDF 1.7) + /// + SHA384 = 2, + + /// + /// (PDF 1.7) + /// + SHA512 = 3, + + /// + /// (PDF 1.7) + /// + RIPEMD160 = 4 + } +} diff --git a/src/foundation/src/shared/src/PdfSharp.System/PdfSharp.System.csproj b/src/foundation/src/shared/src/PdfSharp.System/PdfSharp.System.csproj index 9fe7235a..7718d900 100644 --- a/src/foundation/src/shared/src/PdfSharp.System/PdfSharp.System.csproj +++ b/src/foundation/src/shared/src/PdfSharp.System/PdfSharp.System.csproj @@ -1,7 +1,7 @@  - net6.0;netstandard2.0;net472 + net6.0;net8.0;netstandard2.0 PdfSharp True @@ -16,6 +16,10 @@ --> + + + + diff --git a/src/foundation/src/shared/src/PdfSharp.System/PdfSharp.System.csproj.DotSettings b/src/foundation/src/shared/src/PdfSharp.System/PdfSharp.System.csproj.DotSettings new file mode 100644 index 00000000..5905f113 --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.System/PdfSharp.System.csproj.DotSettings @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file diff --git a/src/foundation/src/shared/src/PdfSharp.System/Properties/GlobalDeclarations.cs b/src/foundation/src/shared/src/PdfSharp.System/Properties/GlobalDeclarations.cs new file mode 100644 index 00000000..b05fbb8f --- /dev/null +++ b/src/foundation/src/shared/src/PdfSharp.System/Properties/GlobalDeclarations.cs @@ -0,0 +1,21 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +//global using System.IO; + + +#if USE_LONG_SIZE +global using SizeType = System.Int64; +#else +global using SizeType = System.Int32; +#endif + +global using static System.FormattableString; + +using System.Diagnostics.CodeAnalysis; +//using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: ComVisible(false)] +//[assembly: SuppressMessage("LoggingGenerator", "SYSLIB1006:Multiple logging methods cannot use the same event ID within a class", +// Justification = "We use logging event ids as documented, i.e. multiple times", Scope = "member"/*, Target = "~M:PdfSharp.Internal.Logging.LogMessages.XGraphicsCreated(Microsoft.Extensions.Logging.ILogger,System.String)"*/)] diff --git a/src/foundation/src/shared/src/PdfSharp.System/System/CompilerServices.cs b/src/foundation/src/shared/src/PdfSharp.System/System/CompilerServices.cs index f2b7ff73..83358612 100644 --- a/src/foundation/src/shared/src/PdfSharp.System/System/CompilerServices.cs +++ b/src/foundation/src/shared/src/PdfSharp.System/System/CompilerServices.cs @@ -5,283 +5,13 @@ // All classes are internal, i.e. using PDFsharp packages does not make this functionality visible in // your projects. -#if NET472 || NETSTANDARD2_0 namespace System.Runtime.CompilerServices { /// - /// Required to compile init-only setters in .NET Standard and .NET Framework 4.71. + /// Extension method GetSubArray required for the built-in range operator (e.g.'[1..9]'). + /// Fun fact: This class must be compiled into each assembly. If it is only visible through + /// InternalsVisibleTo code will not compile with .NET Framework 4.6.2 and .NET Standard 2.0. /// - internal static class IsExternalInit { } -} - -namespace System.Diagnostics.CodeAnalysis -{ - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] - sealed class MaybeNullAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] - sealed class MaybeNullWhenAttribute : Attribute - { - public MaybeNullWhenAttribute(bool returnValue) { } - } - - [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] - sealed class NotNullWhenAttribute : Attribute - { - public NotNullWhenAttribute(bool returnValue) { } - } - - [AttributeUsage(AttributeTargets.Method, Inherited = false)] - sealed class DoesNotReturnAttribute : Attribute - { } -} - -static class StringExtensions -{ - /// - /// String.Contains implementation for .NET Framework and .NET Standard as an extension method. - /// - public static bool Contains(this string s,string value, StringComparison comparisonType) => s.IndexOf(value, comparisonType) >= 0; -} -#endif - -#if (NET472 || NETSTANDARD2_0) && true - -// This is just experimental. If we use it in PDFsharp, the code will move to the PDFsharp assembly -// and the classes become internal. Otherwise, customers may run into problems of ambiguity of these classes. -// true is set in Directory.Build.targets. -// StL/24-03-04: We will use Index and Range in PDFsharp until we ger problem reports. - -namespace System -{ - // This is the original source code from GitHub.,Therefore, no problems are expected. - // https://github.com/dotnet/runtime/blob/419e949d258ecee4c40a460fb09c66d974229623/src/libraries/System.Private.CoreLib/src/System/Index.cs - // https://github.com/dotnet/runtime/blob/419e949d258ecee4c40a460fb09c66d974229623/src/libraries/System.Private.CoreLib/src/System/Range.cs - - using System.Runtime.CompilerServices; - - /// Represent a type can be used to index a collection either from the start or the end. - /// - /// Index is used by the C# compiler to support the new index syntax - /// - /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; - /// int lastElement = someArray[^1]; // lastElement = 5 - /// - /// - /*public*/ - readonly struct Index : IEquatable - { - private readonly int _value; - - /// Construct an Index using a value and indicating if the index is from the start or from the end. - /// The index value. it has to be zero or positive number. - /// Indicating if the index is from the start or from the end. - /// - /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Index(int value, bool fromEnd = false) - { - if (value < 0) - throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); - - if (fromEnd) - _value = ~value; - else - _value = value; - } - - // The following private constructors mainly created for perf reason to avoid the checks - private Index(int value) - { - _value = value; - } - - /// Create an Index pointing at first element. - public static Index Start => new Index(0); - - /// Create an Index pointing at beyond last element. - public static Index End => new Index(~0); - - /// Create an Index from the start at the position indicated by the value. - /// The index value from the start. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Index FromStart(int value) - { - if (value < 0) - throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); - - return new Index(value); - } - - /// Create an Index from the end at the position indicated by the value. - /// The index value from the end. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Index FromEnd(int value) - { - if (value < 0) - throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); - - return new Index(~value); - } - - /// Returns the index value. - public int Value - { - get - { - if (_value < 0) - return ~_value; - else - return _value; - } - } - - /// Indicates whether the index is from the start or the end. - public bool IsFromEnd => _value < 0; - - /// Calculate the offset from the start using the giving collection length. - /// The length of the collection that the Index will be used with. length has to be a positive value - /// - /// For performance reason, we dont validate the input length parameter and the returned offset value against negative values. - /// we dont validate either the returned offset is greater than the input length. - /// It is expected Index will be used with collections which always have non-negative length/count. If the returned offset is negative and - /// then used to index a collection will get out of range exception which will be same affect as the validation. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetOffset(int length) - { - var offset = _value; - if (IsFromEnd) - { - // offset = length - (~value) - // offset = length + (~(~value) + 1) - // offset = length + value + 1 - - offset += length + 1; - } - return offset; - } - - /// Indicates whether the current Index object is equal to another object of the same type. - /// An object to compare with this object - public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value; - - /// Indicates whether the current Index object is equal to another Index object. - /// An object to compare with this object - public bool Equals(Index other) => _value == other._value; - - /// Returns the hash code for this instance. - public override int GetHashCode() => _value; - - /// Converts integer number to an Index. - public static implicit operator Index(int value) => FromStart(value); - - /// Converts the value of the current Index object to its equivalent string representation. - public override string ToString() - { - if (IsFromEnd) - return "^" + ((uint)Value).ToString(); - - return ((uint)Value).ToString(); - } - } - - /// Represent a range has start and end indexes. - /// - /// Range is used by the C# compiler to support the range syntax. - /// - /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; - /// int[] subArray1 = someArray[0..2]; // { 1, 2 } - /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } - /// - /// - /*public*/ - readonly struct Range : IEquatable - { - /// Represent the inclusive start index of the Range. - public Index Start { get; } - - /// Represent the exclusive end index of the Range. - public Index End { get; } - - /// Construct a Range object using the start and end indexes. - /// Represent the inclusive start index of the range. - /// Represent the exclusive end index of the range. - public Range(Index start, Index end) - { - Start = start; - End = end; - } - - /// Indicates whether the current Range object is equal to another object of the same type. - /// An object to compare with this object - public override bool Equals(object? value) => - value is Range r && - r.Start.Equals(Start) && - r.End.Equals(End); - - /// Indicates whether the current Range object is equal to another Range object. - /// An object to compare with this object - public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); - - /// Returns the hash code for this instance. - public override int GetHashCode() - { - return Start.GetHashCode() * 31 + End.GetHashCode(); - } - - /// Converts the value of the current Range object to its equivalent string representation. - public override string ToString() - { - return Start + ".." + End; - } - - /// Create a Range object starting from start index to the end of the collection. - public static Range StartAt(Index start) => new Range(start, Index.End); - - /// Create a Range object starting from first element in the collection to the end Index. - public static Range EndAt(Index end) => new Range(Index.Start, end); - - /// Create a Range object starting from first element to the end. - public static Range All => new Range(Index.Start, Index.End); - - /// Calculate the start offset and length of range object using a collection length. - /// The length of the collection that the range will be used with. length has to be a positive value. - /// - /// For performance reason, we dont validate the input length parameter against negative values. - /// It is expected Range will be used with collections which always have non-negative length/count. - /// We validate the range is inside the length scope though. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public (int Offset, int Length) GetOffsetAndLength(int length) - { - int start; - var startIndex = Start; - if (startIndex.IsFromEnd) - start = length - startIndex.Value; - else - start = startIndex.Value; - - int end; - var endIndex = End; - if (endIndex.IsFromEnd) - end = length - endIndex.Value; - else - end = endIndex.Value; - - if ((uint)end > (uint)length || (uint)start > (uint)end) - { - throw new ArgumentOutOfRangeException(nameof(length)); - } - - return (start, end - start); - } - } -} - -namespace System.Runtime.CompilerServices -{ /*public*/ static class RuntimeHelpers { @@ -298,11 +28,9 @@ public static T[] GetSubArray(T[] array, Range range) if (default(T) != null || typeof(T[]) == array.GetType()) { // We know the type of the array to be exactly T[]. - if (length == 0) - { - return Array.Empty(); - } + //return Array.Empty(); + return []; var dest = new T[length]; Array.Copy(array, offset, dest, 0, length); @@ -311,11 +39,10 @@ public static T[] GetSubArray(T[] array, Range range) else { // The array is actually a U[] where U:T. - var dest = (T[])Array.CreateInstance(array.GetType().GetElementType(), length); + var dest = (T[])Array.CreateInstance(array.GetType().GetElementType()!, length); Array.Copy(array, offset, dest, 0, length); return dest; } } } } -#endif diff --git a/src/foundation/src/shared/src/PdfSharp.Testing-gdi/PdfSharp.Testing-gdi.csproj b/src/foundation/src/shared/src/PdfSharp.Testing-gdi/PdfSharp.Testing-gdi.csproj index 50ecb612..75abf89d 100644 --- a/src/foundation/src/shared/src/PdfSharp.Testing-gdi/PdfSharp.Testing-gdi.csproj +++ b/src/foundation/src/shared/src/PdfSharp.Testing-gdi/PdfSharp.Testing-gdi.csproj @@ -1,7 +1,7 @@ - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 PdfSharp.Testing_gdi enable enable @@ -18,6 +18,8 @@ + + diff --git a/src/foundation/src/shared/src/PdfSharp.Testing-wpf/PdfSharp.Testing-wpf.csproj b/src/foundation/src/shared/src/PdfSharp.Testing-wpf/PdfSharp.Testing-wpf.csproj index 52551ec9..9726c790 100644 --- a/src/foundation/src/shared/src/PdfSharp.Testing-wpf/PdfSharp.Testing-wpf.csproj +++ b/src/foundation/src/shared/src/PdfSharp.Testing-wpf/PdfSharp.Testing-wpf.csproj @@ -1,7 +1,7 @@ - net6.0-windows;net472 + net6.0-windows;net8.0-windows;net462 PdfSharp.Testing_wpf enable enable @@ -18,6 +18,8 @@ + + diff --git a/src/foundation/src/shared/src/PdfSharp.Testing/PdfSharp.Testing.csproj b/src/foundation/src/shared/src/PdfSharp.Testing/PdfSharp.Testing.csproj index 11b448f8..7e807ee0 100644 --- a/src/foundation/src/shared/src/PdfSharp.Testing/PdfSharp.Testing.csproj +++ b/src/foundation/src/shared/src/PdfSharp.Testing/PdfSharp.Testing.csproj @@ -1,7 +1,7 @@  - net6.0;netstandard2.0 + net6.0;net8.0;netstandard2.0 PdfSharp True @@ -26,6 +26,8 @@ + + diff --git a/src/foundation/src/shared/src/PdfSharp.WPFonts/PdfSharp.WPFonts.csproj b/src/foundation/src/shared/src/PdfSharp.WPFonts/PdfSharp.WPFonts.csproj index 59ec84b5..3dcb975c 100644 --- a/src/foundation/src/shared/src/PdfSharp.WPFonts/PdfSharp.WPFonts.csproj +++ b/src/foundation/src/shared/src/PdfSharp.WPFonts/PdfSharp.WPFonts.csproj @@ -1,7 +1,8 @@  - net6.0;netstandard2.0;net472 + + net6.0;net8.0;netstandard2.0 disable True ..\..\..\..\..\StrongnameKey.snk diff --git a/src/foundation/src/shared/testapps/PdfSharp.Fonts.TestApp/PdfSharp.Fonts.TestApp.csproj b/src/foundation/src/shared/testapps/PdfSharp.Fonts.TestApp/PdfSharp.Fonts.TestApp.csproj index ce16a400..b1c164c3 100644 --- a/src/foundation/src/shared/testapps/PdfSharp.Fonts.TestApp/PdfSharp.Fonts.TestApp.csproj +++ b/src/foundation/src/shared/testapps/PdfSharp.Fonts.TestApp/PdfSharp.Fonts.TestApp.csproj @@ -2,7 +2,7 @@ Exe - net6.0;net472 + net6.0;net8.0;net462 true diff --git a/src/foundation/src/shared/testapps/Shared.TestApp/Shared.TestApp.csproj b/src/foundation/src/shared/testapps/Shared.TestApp/Shared.TestApp.csproj index 96a9fc3a..cc373638 100644 --- a/src/foundation/src/shared/testapps/Shared.TestApp/Shared.TestApp.csproj +++ b/src/foundation/src/shared/testapps/Shared.TestApp/Shared.TestApp.csproj @@ -2,8 +2,7 @@ Exe - net6.0;net472 - + net6.0;net8.0;net462 true @@ -24,6 +23,7 @@ + diff --git a/src/foundation/src/shared/tests/PdfSharp.Fonts.Test/PdfSharp.Fonts.Test.csproj b/src/foundation/src/shared/tests/PdfSharp.Fonts.Test/PdfSharp.Fonts.Test.csproj index fcba760f..6023e4b8 100644 --- a/src/foundation/src/shared/tests/PdfSharp.Fonts.Test/PdfSharp.Fonts.Test.csproj +++ b/src/foundation/src/shared/tests/PdfSharp.Fonts.Test/PdfSharp.Fonts.Test.csproj @@ -1,7 +1,7 @@  - net6.0;net472 + net6.0;net462 diff --git a/src/foundation/src/shared/tests/Shared.Tests/Shared.Tests.csproj b/src/foundation/src/shared/tests/Shared.Tests/Shared.Tests.csproj index 55908fc8..b303c9ea 100644 --- a/src/foundation/src/shared/tests/Shared.Tests/Shared.Tests.csproj +++ b/src/foundation/src/shared/tests/Shared.Tests/Shared.Tests.csproj @@ -1,7 +1,9 @@  - net6.0;net472 + net6.0;net462 + True + ..\..\..\..\..\StrongnameKey.snk @@ -15,6 +17,8 @@ + + diff --git a/src/foundation/src/shared/tests/Shared.Tests/System/Messages.cs b/src/foundation/src/shared/tests/Shared.Tests/System/Messages.cs new file mode 100644 index 00000000..a85515c8 --- /dev/null +++ b/src/foundation/src/shared/tests/Shared.Tests/System/Messages.cs @@ -0,0 +1,37 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +using Xunit; +using FluentAssertions; +using PdfSharp.Internal; +using PdfSharp.Quality; +using System; + +// ReSharper disable RedundantArgumentDefaultValue because this is unit test code +// ReSharper disable UnusedVariable because this is unit test code +#pragma warning disable IDE0059 + +namespace Shared.Tests.System +{ + public class MessagesTests + { + [Fact] + public void IndexOutOfRange_Test() + { + var action = () => + { + var array = new int[3]; + //throw new IndexOutOfRangeException() + var msg = SyMsgs.IndexOutOfRange2("index", 0, array.Length - 1); + }; + //action.Should().Throw(); + + var array = new int[3]; + //throw new IndexOutOfRangeException() + var msg = SyMsgs.IndexOutOfRange2("index", 0, array.Length - 1); + msg.Message.Should().NotBeEmpty(); + int index = 7; + var ex = new ArgumentOutOfRangeException(nameof(index), index, SyMsgs.IndexOutOfRange3); + } + } +} diff --git a/src/samples/src/MigraDoc/src/HelloWorld-gdi/HelloWorld,MigraDoc-gdi.csproj b/src/samples/src/MigraDoc/src/HelloWorld-gdi/HelloWorld,MigraDoc-gdi.csproj index e778fb01..de1c7154 100644 --- a/src/samples/src/MigraDoc/src/HelloWorld-gdi/HelloWorld,MigraDoc-gdi.csproj +++ b/src/samples/src/MigraDoc/src/HelloWorld-gdi/HelloWorld,MigraDoc-gdi.csproj @@ -2,7 +2,7 @@ Exe - net6.0-windows;net472 + net6.0-windows;net462 true true HelloWorld_gdi diff --git a/src/samples/src/MigraDoc/src/HelloWorld-wpf/HelloWorld,MigraDoc-wpf.csproj b/src/samples/src/MigraDoc/src/HelloWorld-wpf/HelloWorld,MigraDoc-wpf.csproj index 39f79aa0..29dc10b0 100644 --- a/src/samples/src/MigraDoc/src/HelloWorld-wpf/HelloWorld,MigraDoc-wpf.csproj +++ b/src/samples/src/MigraDoc/src/HelloWorld-wpf/HelloWorld,MigraDoc-wpf.csproj @@ -2,7 +2,7 @@ Exe - net6.0-windows;net472 + net6.0-windows;net462 true true HelloWorld_wpf diff --git a/src/samples/src/MigraDoc/src/HelloWorld/HelloWorld,MigraDoc.csproj b/src/samples/src/MigraDoc/src/HelloWorld/HelloWorld,MigraDoc.csproj index bab77d7d..c8294de1 100644 --- a/src/samples/src/MigraDoc/src/HelloWorld/HelloWorld,MigraDoc.csproj +++ b/src/samples/src/MigraDoc/src/HelloWorld/HelloWorld,MigraDoc.csproj @@ -1,8 +1,8 @@ - + Exe - net6.0;net472 + net6.0;net462 diff --git a/src/samples/src/MigraDoc/src/HelloWorld/Program.cs b/src/samples/src/MigraDoc/src/HelloWorld/Program.cs index fe81e0c8..881155a2 100644 --- a/src/samples/src/MigraDoc/src/HelloWorld/Program.cs +++ b/src/samples/src/MigraDoc/src/HelloWorld/Program.cs @@ -21,7 +21,7 @@ class Program { static void Main() { - if (PdfSharp.Capabilities.Build.IsCoreBuild) + if (Capabilities.Build.IsCoreBuild) GlobalFontSettings.FontResolver = new FailsafeFontResolver(); // Create a MigraDoc document. diff --git a/src/samples/src/PDFsharp/src/HelloWorld-gdi/HelloWorld-gdi,PDFsharp.csproj b/src/samples/src/PDFsharp/src/HelloWorld-gdi/HelloWorld-gdi,PDFsharp.csproj index 0c104a78..27833e39 100644 --- a/src/samples/src/PDFsharp/src/HelloWorld-gdi/HelloWorld-gdi,PDFsharp.csproj +++ b/src/samples/src/PDFsharp/src/HelloWorld-gdi/HelloWorld-gdi,PDFsharp.csproj @@ -2,7 +2,7 @@ Exe - net6.0-windows;net472 + net6.0-windows;net462 true true diff --git a/src/samples/src/PDFsharp/src/HelloWorld-wpf/HelloWorld-wpf,PDFsharp.csproj b/src/samples/src/PDFsharp/src/HelloWorld-wpf/HelloWorld-wpf,PDFsharp.csproj index 3969f4a7..7a6d3f52 100644 --- a/src/samples/src/PDFsharp/src/HelloWorld-wpf/HelloWorld-wpf,PDFsharp.csproj +++ b/src/samples/src/PDFsharp/src/HelloWorld-wpf/HelloWorld-wpf,PDFsharp.csproj @@ -2,7 +2,7 @@ Exe - net6.0-windows;net472 + net6.0-windows;net462 true true diff --git a/src/samples/src/PDFsharp/src/HelloWorld/HelloWorld,PDFsharp.csproj b/src/samples/src/PDFsharp/src/HelloWorld/HelloWorld,PDFsharp.csproj index 68320592..319ff08c 100644 --- a/src/samples/src/PDFsharp/src/HelloWorld/HelloWorld,PDFsharp.csproj +++ b/src/samples/src/PDFsharp/src/HelloWorld/HelloWorld,PDFsharp.csproj @@ -2,7 +2,7 @@ Exe - net6.0;net472 + net6.0;net462 HelloWorld,PDFsharp diff --git a/src/samples/src/PDFsharp/src/HelloWorld/Program.cs b/src/samples/src/PDFsharp/src/HelloWorld/Program.cs index aa352f6c..d31aba20 100644 --- a/src/samples/src/PDFsharp/src/HelloWorld/Program.cs +++ b/src/samples/src/PDFsharp/src/HelloWorld/Program.cs @@ -50,10 +50,16 @@ static void Main(string[] _) // Create a font. var font = new XFont("Times New Roman", 20, XFontStyleEx.BoldItalic); +#if true + // Draw the text. + gfx.DrawString("H", font, XBrushes.Black, + new XRect(0, 0, width, height), XStringFormats.Center); +#else // Draw the text. gfx.DrawString("Hello, PDFsharp!", font, XBrushes.Black, new XRect(0, 0, width, height), XStringFormats.Center); - +#endif + // Save the document... var fullName = PdfFileUtility.GetTempPdfFullFileName("PdfSharpSamples/HelloWorld/HelloWorld" + Capabilities.Build.BuildTag); document.Save(fullName); diff --git a/src/tools/src/CopyAsLink/CopyAsLink.csproj b/src/tools/src/CopyAsLink/CopyAsLink.csproj new file mode 100644 index 00000000..edf7506b --- /dev/null +++ b/src/tools/src/CopyAsLink/CopyAsLink.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0-windows + CopyAsLink + true + + + diff --git a/src/tools/src/CopyAsLink/Program.cs b/src/tools/src/CopyAsLink/Program.cs new file mode 100644 index 00000000..3af34114 --- /dev/null +++ b/src/tools/src/CopyAsLink/Program.cs @@ -0,0 +1,68 @@ +// PDFsharp - A .NET library for processing PDF +// See the LICENSE file in the solution root for more information. + +// Years ago, there was a Visual Studio Add-in called VSCommand +// that added files from one project as links to another project. +// The 'Add/Existing Item/Add/Add as Link' is too simple. It adds +// only one directory in a flat hierarchy. So I wrote this tool. +// +// Such links look like these (taken from PDFsharp-gdi project) +// +// +// +// + +using System.Text; + +namespace CopyAsLink +{ + static class Program + { + // I didn’t manage to create a top-level program in a single thread apartment. + // A single thread apartment is needed for COM-based clipboard access. + // The code GPT 4.0 suggested doesn’t work. + [STAThread] + static void Main(string[] _) + { + var source = @"…\"; // The full source path. + var prefix = @"..\…"; // The relative path from destination to source. + var pattern = "*.cs;…"; // The files to be included, separated by ';'. + + // Root on your PC. + var root = @"D:\repos\emp\PDFsharp\src\foundation\src\"; + + // PdfSharp.Charting + source = root + @"PDFsharp\src\PdfSharp.Charting\"; + prefix = @"..\PdfSharp.Charting\"; + + // MigraDoc.Rendering + //source = root + @"MigraDoc\src\MigraDoc.Rendering\"; + //prefix = @"..\MigraDoc.Rendering\"; + + pattern = "*.cs"; + + var infos = Directory.GetFiles(source, pattern, SearchOption.AllDirectories); + Array.Sort(infos); + + var result = new StringBuilder(); + foreach (var info in infos) + { + if (info.Contains(@"\obj\")) + continue; + + var link = info[source.Length..]; + var include = prefix + link; + + var res = $" "; + + result.AppendLine(res); + + Console.WriteLine(res); + } + + Clipboard.SetText(result.ToString()); + + Console.WriteLine("Done."); + } + } +} diff --git a/src/tools/src/NRT-Tests/NRT-Tests.csproj b/src/tools/src/NRT-Tests/NRT-Tests.csproj index d5f2b3dd..047bbc8a 100644 --- a/src/tools/src/NRT-Tests/NRT-Tests.csproj +++ b/src/tools/src/NRT-Tests/NRT-Tests.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 NRT_Tests diff --git a/src/tools/src/PdfFileViewer/PdfFileViewer.csproj b/src/tools/src/PdfFileViewer/PdfFileViewer.csproj index 993af334..87e9c84f 100644 --- a/src/tools/src/PdfFileViewer/PdfFileViewer.csproj +++ b/src/tools/src/PdfFileViewer/PdfFileViewer.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 true true win-x64 diff --git a/src/tools/src/PdfSharp.TestHelper-gdi/PdfSharp.TestHelper-gdi.csproj b/src/tools/src/PdfSharp.TestHelper-gdi/PdfSharp.TestHelper-gdi.csproj index 2bbebbb4..787c790c 100644 --- a/src/tools/src/PdfSharp.TestHelper-gdi/PdfSharp.TestHelper-gdi.csproj +++ b/src/tools/src/PdfSharp.TestHelper-gdi/PdfSharp.TestHelper-gdi.csproj @@ -1,13 +1,13 @@  - net6.0-windows;net472 + net6.0-windows;net462 true true GDI + This conflics with mscorlib, and therefore it is disabled. --> CS1685 True ..\..\..\StrongnameKey.snk @@ -33,10 +33,13 @@ + + + diff --git a/src/tools/src/PdfSharp.TestHelper-wpf/PdfSharp.TestHelper-wpf.csproj b/src/tools/src/PdfSharp.TestHelper-wpf/PdfSharp.TestHelper-wpf.csproj index ccc251d9..a38e945d 100644 --- a/src/tools/src/PdfSharp.TestHelper-wpf/PdfSharp.TestHelper-wpf.csproj +++ b/src/tools/src/PdfSharp.TestHelper-wpf/PdfSharp.TestHelper-wpf.csproj @@ -1,13 +1,13 @@  - net6.0-windows;net472 + net6.0-windows;net462 true true WPF + This conflics with mscorlib, and therefore it is disabled. --> CS1685 True ..\..\..\StrongnameKey.snk @@ -25,10 +25,13 @@ + + + diff --git a/src/tools/src/PdfSharp.TestHelper/Analysis/ContentStream/GetText.cs b/src/tools/src/PdfSharp.TestHelper/Analysis/ContentStream/GetText.cs index dd001e22..c8b8734d 100644 --- a/src/tools/src/PdfSharp.TestHelper/Analysis/ContentStream/GetText.cs +++ b/src/tools/src/PdfSharp.TestHelper/Analysis/ContentStream/GetText.cs @@ -190,7 +190,7 @@ public class TextInfo public TextInfo(double x, double y, double xOffset, double yOffset, string text, bool isHex, ContentStreamEnumerator.IState tdXElement, ContentStreamEnumerator.IState tdYElement, ContentStreamEnumerator.IState tdElement, - ContentStreamEnumerator.IState textElement, ContentStreamEnumerator.IState tjElement, + ContentStreamEnumerator.IState textElement, ContentStreamEnumerator.IState tjElement, ContentStreamEnumerator contentStreamEnumerator) { X = x; @@ -256,18 +256,21 @@ public string GetTextWithCorrectEncoding(string text, XFont font) { // This code should be analog to XGraphicsPdfRenderer.DrawString(). - var codePoints = UnicodeHelper.Utf32FromString(text /*, font.AnsiEncoding*/); + var pdfDocument = _contentStreamEnumerator.PdfDocument; + + // Invoke TextEvent. + var args2 = new PrepareTextEventArgs(pdfDocument, font, text); + pdfDocument.RenderEvents.OnPrepareTextEvent(this, args2); + text = args2.Text; + + var codePoints = font.IsSymbolFont + ? UnicodeHelper.SymbolCodePointsFromString(text, font.OpenTypeDescriptor) + : UnicodeHelper.Utf32FromString(text /*, font.AnsiEncoding*/); var otDescriptor = font.OpenTypeDescriptor; var codePointsWithGlyphIndices = otDescriptor.GlyphIndicesFromCodePoints(codePoints); - var pdfDocument = _contentStreamEnumerator.PdfDocument; - // Invoke RenderEvent. - var args = new RenderTextEventArgs(pdfDocument) - { - Font = font, - CodePointGlyphIndexPairs = codePointsWithGlyphIndices - }; + var args = new RenderTextEventArgs(pdfDocument, font, codePointsWithGlyphIndices); pdfDocument.RenderEvents.OnRenderTextEvent(this, args); codePointsWithGlyphIndices = args.CodePointGlyphIndexPairs; @@ -288,7 +291,7 @@ public string GetTextWithCorrectEncoding(string text, XFont font) var fontType = font.FontTypeFromUnicodeFlag; isAnsi = fontType == FontType.TrueTypeWinAnsi; } - + if (isAnsi) { // Use ANSI character encoding. diff --git a/src/tools/src/PdfSharp.TestHelper/MemoryLogger.cs b/src/tools/src/PdfSharp.TestHelper/MemoryLogger.cs index edd613af..427e2751 100644 --- a/src/tools/src/PdfSharp.TestHelper/MemoryLogger.cs +++ b/src/tools/src/PdfSharp.TestHelper/MemoryLogger.cs @@ -48,7 +48,7 @@ public Boolean IsEnabled(LogLevel logLevel) return level != LogLevel.None && logLevel >= level; } - public IDisposable BeginScope(TState state) => default!; + public IDisposable? BeginScope(TState state) where TState : notnull => default!; public string Name { get; } diff --git a/src/tools/src/PdfSharp.TestHelper/PdfSharp.TestHelper.csproj b/src/tools/src/PdfSharp.TestHelper/PdfSharp.TestHelper.csproj index 4566fc5f..b203f0da 100644 --- a/src/tools/src/PdfSharp.TestHelper/PdfSharp.TestHelper.csproj +++ b/src/tools/src/PdfSharp.TestHelper/PdfSharp.TestHelper.csproj @@ -24,6 +24,8 @@ + + diff --git a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/SecurityTestHelper.cs b/src/tools/src/PdfSharp.TestHelper/SecurityTestHelper.cs similarity index 85% rename from src/foundation/src/MigraDoc/tests/MigraDoc.Tests/SecurityTestHelper.cs rename to src/tools/src/PdfSharp.TestHelper/SecurityTestHelper.cs index 153df7f4..6cad3939 100644 --- a/src/foundation/src/MigraDoc/tests/MigraDoc.Tests/SecurityTestHelper.cs +++ b/src/tools/src/PdfSharp.TestHelper/SecurityTestHelper.cs @@ -4,17 +4,11 @@ using System.Collections; using PdfSharp.Pdf; using PdfSharp.Pdf.Security; -using MigraDoc.DocumentObjectModel; -using MigraDoc.Rendering; -#if CORE -using PdfSharp.Fonts; -using PdfSharp.Snippets.Font; -#endif #if WPF using System.IO; #endif -namespace MigraDoc.Tests +namespace PdfSharp.TestHelper { public class SecurityTestHelper { @@ -43,9 +37,10 @@ public enum TestOptionsEnum V5WithoutMetadata } - static readonly TestOptionsEnum[] SkippedTestOptions = { + static readonly TestOptionsEnum[] SkippedTestOptions = + [ // Add test options to skip here. - }; + ]; public const string SkippedTestOptionsMessage = "Skipped through SkippedTestOptions."; @@ -204,37 +199,6 @@ public static TestOptions ByEnum(TestOptionsEnum? @enum) } } - public static Document CreateEmptyTestDocument() - { - var doc = new Document(); - return doc; - } - - public static Document CreateStandardTestDocument() - { - var doc = CreateEmptyTestDocument(); - doc.AddSection().AddParagraph().AddText("Text"); - - return doc; - } - - public static PdfDocumentRenderer RenderDocument(Document document) - { - var pdfRenderer = new PdfDocumentRenderer { Document = document }; - pdfRenderer.RenderDocument(); - - return pdfRenderer; - } - - public static PdfDocumentRenderer RenderSecuredDocument(Document document, TestOptions options) - { - var pdfRenderer = new PdfDocumentRenderer { Document = document }; - pdfRenderer.RenderDocument(); - - SecureDocument(pdfRenderer.PdfDocument, options); - - return pdfRenderer; - } public static void SecureDocument(PdfDocument pdfDoc, TestOptions options) { if (options.Encryption != PdfDefaultEncryption.None) @@ -259,29 +223,6 @@ public static void SecureDocument(PdfDocument pdfDoc, TestOptions options) } } - public static void WriteSecuredTestDocument(Document document, string filename, TestOptions options) - { - var pdfRenderer = RenderSecuredDocument(document, options); - pdfRenderer.Save(filename); - } - - public static PdfDocumentRenderer RenderSecuredStandardTestDocument(TestOptions options) - { - return RenderSecuredDocument(CreateStandardTestDocument(), options); - } - - public static void WriteStandardTestDocument(string filename) - { - var pdfRenderer = RenderDocument(CreateStandardTestDocument()); - pdfRenderer.Save(filename); - } - - public static void WriteSecuredStandardTestDocument(string filename, TestOptions options) - { - var pdfRenderer = RenderSecuredStandardTestDocument(options); - pdfRenderer.Save(filename); - } - /// /// Adds a prefix to the filename, depending on the options Encryption and EncryptMetadata properties. /// Other information must be added manually to the filename parameter (this applies also to the use of user and/or owner password). diff --git a/src/tools/src/PdfSharp.TestHelper/TestHelperExtensions.cs b/src/tools/src/PdfSharp.TestHelper/TestHelperExtensions.cs index aec1c8ca..97cd00e1 100644 --- a/src/tools/src/PdfSharp.TestHelper/TestHelperExtensions.cs +++ b/src/tools/src/PdfSharp.TestHelper/TestHelperExtensions.cs @@ -31,7 +31,7 @@ public static string GetOriginalLocation(this Assembly assembly) #if NET6_0_OR_GREATER var dllPath = assembly.Location; #else - // In net 4.7.2 assembly.Location returns a temporary folder, when executed via Test Explorer. + // In net 4.6.2 assembly.Location returns a temporary folder, when executed via Test Explorer. // Get the original dll’s path via CodeBase instead. var dllPath = assembly.CodeBase; if (dllPath.StartsWith("file:///"))