From 568e4c5f8539ab80cbe42abbe8e346b1e1b25b7b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 16 Oct 2026 06:51:34 +0000 Subject: [PATCH] Add GDI+ printing extensions to CADability.Forms (#412) The [Obsolete] messages of LayoutView.Print, GDI2DView.PrintSinglePage and PrintToGDI now name their replacement, as #412 requires for every class member removed in 2.0: the new extensions of CADability.Forms.GdiPrinting (PrintDocument.Print(LayoutView), PrintDocument.PrintSinglePage(GDI2DView), PrintDocument.PrintSinglePage(Project, string, bool) and Bitmap.DrawModel). In 1.x they forward to the kernel implementation; it moves into CADability.Forms in 2.0. The extensions take the PrintDocument or Bitmap as receiver because an extension on LayoutView or GDI2DView with the same name would be hidden by the instance method until 2.0. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01YXvDW91oXpy7RquGHNxgR5 --- CADability.Forms/GdiPrinting.cs | 69 ++++++++++++++++++++++ CADability/GDI2DView.cs | 2 +- CADability/LayoutView.cs | 2 +- CADability/PrintToGDI.cs | 2 +- tests/CADability.Tests/GdiPrintingTests.cs | 54 +++++++++++++++++ 5 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 CADability.Forms/GdiPrinting.cs create mode 100644 tests/CADability.Tests/GdiPrintingTests.cs diff --git a/CADability.Forms/GdiPrinting.cs b/CADability.Forms/GdiPrinting.cs new file mode 100644 index 00000000..1b979e37 --- /dev/null +++ b/CADability.Forms/GdiPrinting.cs @@ -0,0 +1,69 @@ +using CADability.Attribute; +using System.Drawing; +using System.Drawing.Printing; + +namespace CADability.Forms +{ + /// + /// Printing with GDI+ (System.Drawing.Printing): prints a or a to a + /// and renders a model into a . These methods replace + /// , and the public + /// members of , which are obsolete because GDI+ leaves the kernel in CADability 2.0 (issue #412). + /// In CADability 1.x they still use the implementation in the kernel; in 2.0 it moves here. + /// + public static class GdiPrinting + { +#pragma warning disable CS0618 // the implementation is still in the kernel in CADability 1.x + /// + /// Prints the layout of on a single page. Depending on the global setting + /// "Printing.PrintingMode" the patches are either output as vector graphics (mode 1, with hidden line removal and shading) + /// or each patch is rendered into a bitmap at the printer resolution which is placed on the page. The paper size of the + /// layout is assumed to be in mm. Exceptions of the printing system are swallowed. + /// + /// The print document to print to, with the printer and page settings already set + /// The layout to print + public static void Print(this PrintDocument printDocument, LayoutView layoutView) + { + layoutView.Print(printDocument); + } + /// + /// Prints the contents of on a single page. The paper of the view + /// ( by ) is fitted onto the page, so the paper size + /// should be set. Exceptions of the printing system are swallowed. + /// + /// The print document to print to, with the printer and page settings already set + /// The view to print + public static void PrintSinglePage(this PrintDocument printDocument, GDI2DView gdiView) + { + gdiView.PrintSinglePage(printDocument); + } + /// + /// Prints the named of on a single page. + /// Nothing is printed if the project has no such view. + /// + /// The print document to print to, null for the print document of the project + /// The project containing the view + /// The name of the view + /// True to print only the curves, false to print the faces too + public static void PrintSinglePage(this PrintDocument printDocument, Project project, string nameOfView, bool print2D) + { + PrintToGDI.PrintSinglePage(project, nameOfView, print2D, printDocument); + } + /// + /// Renders with the into , which is + /// filled white first. + /// + /// The bitmap to render into + /// The model to render + /// The projection to use + /// The layers to render + /// True to shade the faces + /// Not used: whether only the curves are rendered follows of + /// , as in + public static void DrawModel(this Bitmap bitmap, Model model, Projection projection, Layer[] visibleLayers, bool shading, bool curvesOnly) + { + new PrintToGDI(bitmap).PrintToBitmap(model, projection, visibleLayers, shading, curvesOnly); + } +#pragma warning restore CS0618 + } +} diff --git a/CADability/GDI2DView.cs b/CADability/GDI2DView.cs index e2f7f6b9..71b89eab 100644 --- a/CADability/GDI2DView.cs +++ b/CADability/GDI2DView.cs @@ -348,7 +348,7 @@ public bool ThinLinesOnly /// is fitted onto the page, so the paper size should be set. Exceptions of the printing system are swallowed. /// /// The print document to print to, with the printer and page settings already set - [Obsolete("Printing with GDI+ moves into CADability.Forms in CADability 2.0 (issue #412).")] + [Obsolete("Use the PrintDocument extension PrintSinglePage(GDI2DView) of CADability.Forms.GdiPrinting instead. Printing with GDI+ moves into CADability.Forms in CADability 2.0 (issue #412).")] public void PrintSinglePage(PrintDocument pd) { PrintToGDI pdg = new PrintToGDI(this); diff --git a/CADability/LayoutView.cs b/CADability/LayoutView.cs index 632cfcfd..d8e9d7e9 100644 --- a/CADability/LayoutView.cs +++ b/CADability/LayoutView.cs @@ -148,7 +148,7 @@ public void ZoomTotal(double factor) /// the printing system are swallowed. /// /// The print document to print to, with the printer and page settings already set - [Obsolete("Printing with GDI+ moves into CADability.Forms in CADability 2.0 (issue #412).")] + [Obsolete("Use the PrintDocument extension Print(LayoutView) of CADability.Forms.GdiPrinting instead. Printing with GDI+ moves into CADability.Forms in CADability 2.0 (issue #412).")] public void Print(PrintDocument pd) { bool printToGDI = Settings.GlobalSettings.GetIntValue("Printing.PrintingMode", 0) == 1; diff --git a/CADability/PrintToGDI.cs b/CADability/PrintToGDI.cs index 98943026..b4b93a3e 100644 --- a/CADability/PrintToGDI.cs +++ b/CADability/PrintToGDI.cs @@ -1453,7 +1453,7 @@ public override IGeoObject Debug /// ), to render a model into a () and for the display of /// the . Not available in the WebAssembly build. /// - [Obsolete("Printing with GDI+ moves into CADability.Forms in CADability 2.0 (issue #412).")] + [Obsolete("Use the extensions of CADability.Forms.GdiPrinting instead: PrintDocument.Print(LayoutView), PrintDocument.PrintSinglePage(GDI2DView) or PrintSinglePage(Project, string, bool), and Bitmap.DrawModel(...). Printing with GDI+ moves into CADability.Forms in CADability 2.0 (issue #412).")] public class PrintToGDI : IPaintTo3D, QuadTree.IIterateQuadTreeLists { diff --git a/tests/CADability.Tests/GdiPrintingTests.cs b/tests/CADability.Tests/GdiPrintingTests.cs new file mode 100644 index 00000000..0a2ee6a9 --- /dev/null +++ b/tests/CADability.Tests/GdiPrintingTests.cs @@ -0,0 +1,54 @@ +#if WINDOWS +using CADability.Attribute; +using CADability.Forms; +using CADability.GeoObject; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Drawing; + +namespace CADability.Tests +{ + /// + /// The printing extensions of in CADability.Forms replace the obsolete printing members of the + /// kernel (issue #412). In CADability 1.x they forward to the kernel, so they must produce the same output. + /// + [TestClass] + public class GdiPrintingTests + { + [TestMethod] + public void DrawModelRendersLikePrintToGdi() + { + Project project = Project.CreateSimpleProject(); + Model model = project.GetActiveModel(); + Line line = Line.Construct(); + line.SetTwoPoints(new GeoPoint(10, 10, 0), new GeoPoint(90, 90, 0)); + model.Add(line); + Layer[] layers = project.LayerList.ToArray(); + + Bitmap viaExtension = Render((bitmap, projection) => bitmap.DrawModel(model, projection, layers, false, true)); +#pragma warning disable CS0618 // the obsolete kernel implementation as the reference + Bitmap viaKernel = Render((bitmap, projection) => new PrintToGDI(bitmap).PrintToBitmap(model, projection, layers, false, true)); +#pragma warning restore CS0618 + + int drawn = 0; + for (int x = 0; x < viaKernel.Width; x++) + for (int y = 0; y < viaKernel.Height; y++) + { + Color expected = viaKernel.GetPixel(x, y); + Assert.AreEqual(expected.ToArgb(), viaExtension.GetPixel(x, y).ToArgb(), $"pixel {x}, {y}"); + if (expected.ToArgb() != Color.White.ToArgb()) ++drawn; + } + Assert.IsTrue(drawn > 0, "the line is drawn"); + } + + private static Bitmap Render(System.Action draw) + { + Bitmap bitmap = new Bitmap(100, 100); + Projection projection = new Projection(Projection.StandardProjection.FromTop); + projection.ShowFaces = false; + projection.SetPlacement(new Rectangle(0, 0, 100, 100), new BoundingRect(0, 0, 100, 100)); + draw(bitmap, projection); + return bitmap; + } + } +} +#endif