Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
be8329f
Add a managed TrueType reader for text on every platform (#412)
claude Oct 15, 2026
cb05b5b
Get the fonts of texts from a font service of the kernel instead of G…
claude Oct 15, 2026
ec20031
Add a Windows CI workflow that builds and tests with GDI+ and WinForm…
claude Oct 15, 2026
c7225e2
Make the DXF dimension tests independent of the line endings of the c…
claude Oct 15, 2026
fc5326e
Read the CFF outlines of OpenType fonts in the managed font reader (#…
claude Oct 15, 2026
5e7a0be
Read variable fonts: gvar, CFF2, avar and HVAR (#412)
claude Oct 15, 2026
4d939ef
Compare the managed font reader with GDI on Windows (#412)
claude Oct 15, 2026
e08061f
Find a family by the name GDI cuts to 31 characters (#412)
claude Oct 15, 2026
318a1ed
Lay out glyphs, metrics and decorations like GDI (#412)
claude Oct 15, 2026
191927d
Name and measure variable instances like Windows (#412)
claude Oct 15, 2026
b30fcd0
Correct the documentation of HasOutlines and HasCffOutlines for CFF2 …
claude Oct 15, 2026
1d19182
Merge branch 'feature/variable-fonts' into feature/gdi-glyph-comparison
claude Oct 15, 2026
45b1a61
Keep the images of pictures and icons as image file bytes (#412)
claude Oct 15, 2026
10f0d2d
Test files with pictures written on .NET Framework 4.8 (#412)
claude Oct 15, 2026
cfba619
Save page settings as a neutral PageSetup (#412)
claude Oct 15, 2026
0e2982f
Use a relative path in the path fallback test (#412)
claude Oct 15, 2026
cc470a1
Merge branch 'feature/picture-encoded-images' into feature/neutral-pa…
claude Oct 15, 2026
3bf4b6e
Import all CSS named colors from SVG (#412)
claude Oct 15, 2026
a4de85a
Test texts without frame or GDI: save, export, finalizers (#412)
claude Oct 15, 2026
65fd037
Test pictures without frame or GDI: measure, export, finalizers (#412)
claude Oct 15, 2026
dccb145
Merge remote-tracking branch 'origin/master' into feature/picture-enc…
claude Oct 16, 2026
238a773
Merge branch 'feature/picture-encoded-images' into feature/neutral-pa…
claude Oct 16, 2026
e8a51eb
Merge branch 'feature/neutral-page-setup' into test/headless-picture-…
claude Oct 16, 2026
9ef832f
Sample BSpline2D.AddToGraphicsPath on 0..1 (#412)
claude Oct 16, 2026
72b4ecd
Merge remote-tracking branch 'origin/test/headless-text-export' into …
claude Oct 16, 2026
5a44ee0
Merge remote-tracking branch 'origin/test/headless-picture-export' in…
claude Oct 16, 2026
2a595e5
Merge remote-tracking branch 'origin/ci/windows-build-and-test' into …
claude Oct 16, 2026
85e2281
Merge remote-tracking branch 'origin/test/svg-css-colors' into integr…
claude Oct 16, 2026
28591f9
Merge remote-tracking branch 'origin/fix/bspline2d-graphicspath' into…
claude Oct 16, 2026
efdfdb1
Run the kernel as WebAssembly in the Linux CI (#412)
claude Oct 16, 2026
9392945
Keep Picture.Clip without [Obsolete] (#412)
claude Oct 16, 2026
2319a01
Merge branch 'feature/picture-encoded-images' into feature/neutral-pa…
claude Oct 16, 2026
293c493
Keep the printing members without [Obsolete] (#412)
claude Oct 16, 2026
072f639
Merge branch 'feature/neutral-page-setup' into test/headless-picture-…
claude Oct 16, 2026
188d4a7
Merge remote-tracking branch 'origin/test/headless-picture-export' in…
claude Oct 16, 2026
62cfb7d
Merge branch 'integration/issue-412' into test/wasm-smoke
claude Oct 16, 2026
3f1eb39
Merge master into feature/font-service
claude Oct 17, 2026
415fea4
Merge branch 'feature/font-service' into feature/cff-outlines
claude Oct 17, 2026
9a17a7b
Merge branch 'feature/cff-outlines' into feature/variable-fonts
claude Oct 17, 2026
95efb36
Merge branch 'feature/variable-fonts' into feature/gdi-glyph-comparison
claude Oct 17, 2026
020713a
Merge branch 'feature/gdi-glyph-comparison' into test/headless-text-e…
claude Oct 17, 2026
21ffff8
Merge branch 'test/headless-text-export' into integration/issue-412
claude Oct 17, 2026
8e288b1
Merge branch 'integration/issue-412' into test/wasm-smoke
claude Oct 17, 2026
ce437ab
Merge remote-tracking branch 'origin/master' into ci/windows-build-an…
claude Oct 17, 2026
970a5ee
Disambiguate PaintEventArgs in RendererRecoveryTests for the Windows …
claude Oct 17, 2026
113fa60
Merge branch 'ci/windows-build-and-test' into integration/issue-412
claude Oct 17, 2026
7aaff78
Merge branch 'integration/issue-412' into test/wasm-smoke
claude Oct 17, 2026
8d22a3f
Adapt the font cache test of #497 to the font service (#412)
claude Oct 17, 2026
8e4900a
Merge branch 'feature/font-service' into feature/cff-outlines
claude Oct 17, 2026
1e56c2e
Merge branch 'feature/cff-outlines' into feature/variable-fonts
claude Oct 17, 2026
1496f3b
Merge branch 'feature/variable-fonts' into feature/gdi-glyph-comparison
claude Oct 17, 2026
d90108c
Merge branch 'feature/gdi-glyph-comparison' into test/headless-text-e…
claude Oct 17, 2026
3b21a94
Merge branch 'test/headless-text-export' into integration/issue-412
claude Oct 17, 2026
42cb7da
Merge branch 'integration/issue-412' into test/wasm-smoke
claude Oct 17, 2026
6cd5777
Merge remote-tracking branch 'origin/master' into integration/issue-412
claude Oct 19, 2026
83debf3
Merge remote-tracking branch 'origin/master' into feature/managed-fon…
claude Oct 19, 2026
09dab93
Merge remote-tracking branch 'origin/master' into feature/picture-enc…
claude Oct 19, 2026
830f757
Merge remote-tracking branch 'origin/feature/managed-font-provider' i…
claude Oct 19, 2026
3163749
Pass Unicode code points instead of chars to FontFace (#412)
claude Oct 19, 2026
3e640f2
Merge branch 'feature/font-service' into feature/cff-outlines
claude Oct 19, 2026
8a07d38
Merge branch 'feature/cff-outlines' into feature/variable-fonts
claude Oct 19, 2026
23aa919
Merge branch 'feature/variable-fonts' into feature/gdi-glyph-comparison
claude Oct 19, 2026
cacc4d0
Merge branch 'feature/gdi-glyph-comparison' into test/headless-text-e…
claude Oct 19, 2026
2d09d7b
Merge branch 'test/headless-text-export' into integration/issue-412
claude Oct 19, 2026
dc316e2
Merge remote-tracking branch 'origin/feature/picture-encoded-images' …
claude Oct 19, 2026
d62de10
Merge branch 'integration/issue-412' into test/wasm-smoke
claude Oct 19, 2026
ac0ad17
Lock the shared sets of the parallel STEP import
claude Oct 19, 2026
c54ed31
Merge branch 'feature/managed-font-provider' into feature/font-service
claude Oct 19, 2026
5b325e3
Merge branch 'feature/font-service' into feature/cff-outlines
claude Oct 19, 2026
6b5e200
Merge branch 'feature/cff-outlines' into feature/variable-fonts
claude Oct 19, 2026
b846857
Lock the shared sets of the parallel STEP import
claude Oct 19, 2026
cfd97de
Merge branch 'feature/variable-fonts' into feature/gdi-glyph-comparison
claude Oct 19, 2026
a81efbe
Merge branch 'feature/picture-encoded-images' into feature/neutral-pa…
claude Oct 19, 2026
0c867f0
Merge branch 'feature/neutral-page-setup' into test/headless-picture-…
claude Oct 19, 2026
9d4fd4b
Merge branch 'feature/gdi-glyph-comparison' into test/headless-text-e…
claude Oct 19, 2026
ce5dc5b
Merge branches 'test/headless-text-export' and 'test/headless-picture…
claude Oct 19, 2026
0cad8fb
Merge branch 'integration/issue-412' into test/wasm-smoke
claude Oct 19, 2026
3ad812f
Synthesize a missing bold or italic face like GDI+ (#412)
claude Oct 19, 2026
15e2555
Merge branch 'feature/synthetic-bold-italic' into integration/issue-412
claude Oct 19, 2026
6fb1005
Merge branch 'integration/issue-412' into test/wasm-smoke
claude Oct 19, 2026
0565bb0
Make the quadratic TrueType outline wider for synthetic bold
claude Oct 19, 2026
ee067e1
Keep the synthetic bold shift within half the strength per axis like …
claude Oct 19, 2026
5151a54
Compare Sylfaen and Gabriola with GDI+ within 2% of the em height
claude Oct 19, 2026
51eadd9
Merge branch 'feature/synthetic-bold-italic' into integration/issue-412
claude Oct 19, 2026
b5f58f3
Merge branch 'integration/issue-412' into test/wasm-smoke
claude Oct 19, 2026
b23e6bb
Make the GDI font provider the default in CADability.Forms
claude Oct 19, 2026
8e84ce1
Merge branch 'feature/gdi-fonts-in-forms' into integration/issue-412
claude Oct 19, 2026
7256c88
Merge branch 'integration/issue-412' into test/wasm-smoke
claude Oct 19, 2026
4eba571
Merge branch 'master' into test/wasm-smoke
claude Oct 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/linux-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ jobs:
--logger "trx;LogFileName=CADability.ImportTests.trx"
--results-directory TestResults

- name: Run the kernel as WebAssembly
# CADability.dll in the browser runtime of .NET, under Node.js (preinstalled on the runner): fonts from bytes,
# solids, text, pictures, painting through an IPaintTo3D of its own, old project files, import and export.
# The exit code is the number of failed checks.
if: success() || failure()
run: |
dotnet build tests/CADability.WasmSmoke/CADability.WasmSmoke.csproj -c Release
node tests/CADability.WasmSmoke/bin/Release/net10.0/wwwroot/main.mjs

- name: Upload test results
if: success() || failure()
uses: actions/upload-artifact@v4
Expand Down
31 changes: 31 additions & 0 deletions tests/CADability.WasmSmoke/CADability.WasmSmoke.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk.WebAssembly">
<!-- Runs the kernel as WebAssembly under Node.js (issue #412): CADability.dll in the browser runtime of .NET, without
GDI+, with a renderer of its own that implements IPaintTo3D, as a browser front end would.
dotnet build -c Release, then node bin/Release/net10.0/wwwroot/main.mjs; the exit code is the number of failed checks.
No workload is needed. The project is not part of CADability.sln, so building the solution does not need the
WebAssembly SDK. -->
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<OutputType>Exe</OutputType>
<Nullable>disable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
<!-- IPaintTo3D and the CADability API still name GDI+ types like Bitmap and FontStyle; using them in signatures is
fine, only creating GDI+ objects fails outside Windows -->
<NoWarn>$(NoWarn);CA1416</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\CADability\CADability.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\CADability.Tests\Files\Fonts\LiberationSans-Regular.ttf" LogicalName="LiberationSans-Regular.ttf" />
<EmbeddedResource Include="..\CADability.Tests\Files\CDB\pictures-1x.cdb.json" LogicalName="pictures-1x.cdb.json" />
<EmbeddedResource Include="..\CADability.Tests\Files\CDB\pagesettings-1x-net48.cdb.json" LogicalName="pagesettings-1x-net48.cdb.json" />
<EmbeddedResource Include="..\CADability.Tests\Files\CDB\Volumes.cdb.json" LogicalName="Volumes.cdb.json" />
<EmbeddedResource Include="..\CADability.ImportTests\Files\Step\issue101.stp" LogicalName="issue101.stp" />
</ItemGroup>
<!-- Node.js starts the program with main.mjs, which loads _framework/dotnet.js from the same folder -->
<Target Name="CopyNodeEntryPoint" AfterTargets="Build">
<Copy SourceFiles="main.mjs" DestinationFolder="$(OutDir)wwwroot" SkipUnchangedFiles="true" />
</Target>
</Project>
177 changes: 177 additions & 0 deletions tests/CADability.WasmSmoke/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
using CADability;
using CADability.GeoObject;
using System.Reflection;
using Path = System.IO.Path;

namespace CADability.WasmSmoke
{
/// <summary>
/// Runs CADability.dll as WebAssembly (issue #412): the same checks a browser front end depends on, in the browser runtime
/// of .NET under Node.js, without a frame and without GDI+. Every check prints PASS or FAIL; the exit code is the number
/// of failed checks.
/// </summary>
internal static class Program
{
private static int failed;

private static int Main()
{
Console.WriteLine($"CADability WebAssembly smoke test on {System.Runtime.InteropServices.RuntimeInformation.OSDescription} ({System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture})");

Check("the font comes from bytes", () =>
{
// there are no system fonts in the browser: the front end supplies the font files
ManagedFontProvider fonts = new ManagedFontProvider(Array.Empty<string>(), false);
fonts.AddFontData(Resource("LiberationSans-Regular.ttf"));
FontProvider.Current = fonts;
});

Project project = null;
Check("a project is created", () =>
{
project = Project.CreateSimpleProject();
Expect(FrameImpl.MainFrame == null, "there is no frame");
});
Model model = project.GetActiveModel();

Check("a solid with a hole is made by a boolean operation", () =>
{
Solid box = Make3D.MakeBox(GeoPoint.Origin, 100 * GeoVector.XAxis, 60 * GeoVector.YAxis, 40 * GeoVector.ZAxis);
Solid cylinder = Make3D.MakeCylinder(new GeoPoint(50, 30, -10), 15 * GeoVector.XAxis, 60 * GeoVector.ZAxis);
Solid[] result = Make3D.Difference(box, cylinder);
Expect(result.Length == 1, $"one solid, got {result.Length}");
double expected = 100 * 60 * 40 - Math.PI * 15 * 15 * 40;
double volume = result[0].Volume(1e-3);
Expect(Math.Abs(volume - expected) < expected * 1e-3, $"volume {volume}, expected {expected}");
model.Add(result[0]);
});

Text text = null;
Check("a text is measured with the font of the kernel", () =>
{
text = Text.Construct();
text.Font = "Liberation Sans";
text.TextString = "CADability 412";
text.Location = new GeoPoint(0, 80, 0);
text.LineDirection = GeoVector.XAxis;
text.GlyphDirection = GeoVector.YAxis;
text.TextSize = 10;
BoundingCube extent = text.GetBoundingCube();
Expect(!extent.IsEmpty && extent.Xmax - extent.Xmin > 50 && extent.Ymax - extent.Ymin > 5, $"the extent of the glyphs, got {extent}");
Expect(text.GetOutline().Count > 0, "the glyph outlines");
model.Add(text);
});

Picture picture = null;
Check("a picture keeps its image file", () =>
{
picture = Picture.Construct();
picture.Set(Png3x2, new GeoPoint(0, -50, 0), new GeoVector(30, 0, 0), new GeoVector(0, 20, 0));
Expect((picture.PixelWidth, picture.PixelHeight) == (3, 2), $"3×2 pixels, got {picture.PixelWidth}×{picture.PixelHeight}");
model.Add(picture);
});

Check("the model is painted by a renderer of its own", () =>
{
RecordingPaintTo3D renderer = new RecordingPaintTo3D();
foreach (IGeoObject go in model.AllObjects) go.PrePaintTo3D(renderer);
foreach (IGeoObject go in model.AllObjects) go.PaintTo3D(renderer);
Console.WriteLine($" {renderer.Triangles} triangles, {renderer.Polylines} polylines, {renderer.TextCalls} text calls, {renderer.Bitmaps} bitmaps");
Expect(renderer.Triangles > 100, "the faces of the solid and the glyphs are triangulated");
Expect(renderer.Polylines > 10, "the edges are painted");
Expect(renderer.Extent.Xmin < 1 && renderer.Extent.Xmax > 99 && renderer.Extent.Ymin < -49 && renderer.Extent.Ymax > 85, $"the painted extent, got {renderer.Extent}");
});

Check("the project is saved and read as JSON", () =>
{
MemoryStream written = new MemoryStream();
project.WriteToJson(written);
Model read = Project.ReadFromJson(new MemoryStream(written.ToArray())).GetActiveModel();
Expect(read.AllObjects.OfType<Solid>().Count() == 1, "the solid");
Expect(read.AllObjects.OfType<Text>().Single().TextString == "CADability 412", "the text");
Expect(read.AllObjects.OfType<Picture>().Single().ImageData.SequenceEqual(Png3x2), "the image file of the picture");
});

Check("a project file of CADability 1.x with pictures opens", () =>
{
Project old = Project.ReadFromJson(new MemoryStream(Resource("pictures-1x.cdb.json")));
Picture[] pictures = old.GetActiveModel().AllObjects.OfType<Picture>().ToArray();
Expect(pictures.Length > 0 && pictures.All(p => p.PixelWidth > 0), $"pictures with their image files, got {pictures.Length}");
});

Check("a project file of CADability 1.x with page settings opens", () =>
{
Project old = Project.ReadFromJson(new MemoryStream(Resource("pagesettings-1x-net48.cdb.json")));
Expect(old.DefaultPageSetup.PaperName == "A3" && old.DefaultPageSetup.Landscape, "A3 landscape");
});

Check("a project file with solids opens", () =>
{
Project volumes = Project.ReadFromJson(new MemoryStream(Resource("Volumes.cdb.json")));
Expect(volumes.GetActiveModel().AllObjects.OfType<Solid>().Any(), "solids");
});

Check("a STEP file is imported", () =>
{
string file = Path.Combine(Path.GetTempPath(), "issue101.stp");
File.WriteAllBytes(file, Resource("issue101.stp"));
Project imported = Project.ReadFromFile(file, "stp");
Expect(imported.GetActiveModel().AllObjects.Count > 0, "objects");
});

Check("the project is exported to DXF and STL", () =>
{
string dxf = Path.Combine(Path.GetTempPath(), "smoke.dxf");
Expect(project.Export(dxf, "dxf") && new FileInfo(dxf).Length > 0, "the DXF file");
Project imported = Project.ReadFromFile(dxf, "dxf");
Expect(imported.GetActiveModel().AllObjects.OfType<Text>().Any(), "the text in the DXF file");
string stl = Path.Combine(Path.GetTempPath(), "smoke.stl");
project.ExportToSTL(stl);
Expect(new FileInfo(stl).Length > 0, "the STL file");
});

Check("the finalizers run", () =>
{
// the GDI version of the FontCache had a finalizer that threw without GDI and ended the process
for (int i = 0; i < 10; ++i) Text.Construct().GetBoundingCube();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
});

Console.WriteLine(failed == 0 ? "All checks passed." : $"{failed} check(s) failed.");
return failed;
}

// a PNG of 3×2 pixels
private static readonly byte[] Png3x2 = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAIAAAASFvFNAAAAG0lEQVR4nAXBAQEAAACCIDe5qbHOCgCHIeSyPCtwBd1HI03nAAAAAElFTkSuQmCC");

private static void Check(string name, Action check)
{
try
{
check();
Console.WriteLine("PASS " + name);
}
catch (Exception e)
{
++failed;
Console.WriteLine("FAIL " + name);
Console.WriteLine(" " + e.ToString().Replace("\n", "\n "));
}
}
private static void Expect(bool condition, string what)
{
if (!condition) throw new Exception("expected " + what);
}
private static byte[] Resource(string name)
{
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name))
using (MemoryStream copy = new MemoryStream())
{
stream.CopyTo(copy);
return copy.ToArray();
}
}
}
}
158 changes: 158 additions & 0 deletions tests/CADability.WasmSmoke/RecordingPaintTo3D.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
using CADability;
using CADability.Attribute;
using CADability.GeoObject;
using System.Drawing;

namespace CADability.WasmSmoke
{
/// <summary>
/// A renderer of its own, as a browser front end would write one: it implements <see cref="IPaintTo3D"/> and records
/// what the kernel paints. The interface still names GDI+ types (<see cref="Bitmap"/>, <see cref="FontStyle"/>); a
/// renderer outside Windows implements those members without ever creating a GDI+ object.
/// </summary>
internal sealed class RecordingPaintTo3D : IPaintTo3D
{
// the kernel paints glyphs and other objects into display lists once and then paints the lists: a list keeps the
// calls and replays them with the current transformation
private sealed class DisplayList : IPaintTo3DList, IDisposable
{
public readonly List<Action> Calls = new List<Action>();
public string Name { get; set; }
public List<IPaintTo3DList> containedSubLists { set { } }
public void Dispose() { }
}
private readonly Stack<DisplayList> openLists = new Stack<DisplayList>();

/// <summary>
/// Keeps the call in the open display list, if there is one, and returns true; false if it is to be recorded now.
/// </summary>
private bool IntoList(Action call)
{
if (openLists.Count == 0) return false;
openLists.Peek().Calls.Add(call);
return true;
}

public int Polylines, PolylinePoints, Triangles, TextCalls, Bitmaps, NurbsCalls, Arcs, PointCalls;
public BoundingCube Extent = BoundingCube.EmptyBoundingCube;
private readonly Stack<ModOp> modOps = new Stack<ModOp>();
private ModOp current = ModOp.Identity;

private void Record(GeoPoint p) => Extent.MinMax(current * p);

public bool PaintSurfaces => true;
public bool PaintEdges => true;
public bool PaintSurfaceEdges { get; set; } = true;
public bool UseLineWidth { get; set; }
public double Precision { get; set; } = 0.01;
public double PixelToWorld => 0.1;
public bool SelectMode { get; set; }
public Color SelectColor { get; set; }
public bool DelayText { get; set; }
public bool DelayAll { get; set; }
public bool TriangulateText { get; set; } = true;
public bool DontRecalcTriangulation { get; set; }
public PaintCapabilities Capabilities => PaintCapabilities.Standard;
public IDisposable FacesBehindEdgesOffset => new DisplayList();
public bool IsBitmap => false;

public void MakeCurrent() { }
public void SetColor(Color color, int lockColor = 0) { }
public void AvoidColor(Color color) { }
public void SetLineWidth(LineWidth lineWidth) { }
public void SetLinePattern(LinePattern pattern) { }
public void Polyline(GeoPoint[] points)
{
if (IntoList(() => Polyline(points))) return;
++Polylines;
PolylinePoints += points.Length;
foreach (GeoPoint p in points) Record(p);
}
public void FilledPolyline(GeoPoint[] points) => Polyline(points);
public void Points(GeoPoint[] points, float size, PointSymbol pointSymbol)
{
if (IntoList(() => Points(points, size, pointSymbol))) return;
++PointCalls;
foreach (GeoPoint p in points) Record(p);
}
public void Triangle(GeoPoint[] vertex, GeoVector[] normals, int[] indextriples)
{
if (IntoList(() => Triangle(vertex, normals, indextriples))) return;
Triangles += indextriples.Length / 3;
foreach (GeoPoint p in vertex) Record(p);
}
public void PrepareText(string fontName, string textString, FontStyle fontStyle) { }
public void PreparePointSymbol(PointSymbol pointSymbol) { }
public void PrepareIcon(Bitmap icon) { }
public void PrepareBitmap(Bitmap bitmap, int xoffset, int yoffset) { }
public void PrepareBitmap(Bitmap bitmap) { }
public void RectangularBitmap(Bitmap bitmap, GeoPoint location, GeoVector directionWidth, GeoVector directionHeight)
{
if (!IntoList(() => RectangularBitmap(bitmap, location, directionWidth, directionHeight))) ++Bitmaps;
}
public void Text(GeoVector lineDirection, GeoVector glyphDirection, GeoPoint location, string fontName, string textString, FontStyle fontStyle, Text.AlignMode alignment, Text.LineAlignMode lineAlignment)
{
if (IntoList(() => Text(lineDirection, glyphDirection, location, fontName, textString, fontStyle, alignment, lineAlignment))) return;
++TextCalls;
Record(location);
}
public void List(IPaintTo3DList paintThisList)
{
if (IntoList(() => List(paintThisList))) return;
if (paintThisList is DisplayList list) foreach (Action call in list.Calls) call();
}
public void SelectedList(IPaintTo3DList paintThisList, int wobbleRadius) { }
public void Nurbs(GeoPoint[] poles, double[] weights, double[] knots, int degree)
{
if (IntoList(() => Nurbs(poles, weights, knots, degree))) return;
++NurbsCalls;
foreach (GeoPoint p in poles) Record(p);
}
public void Line2D(int sx, int sy, int ex, int ey) { }
public void Line2D(PointF p1, PointF p2) { }
public void FillRect2D(PointF p1, PointF p2) { }
public void Point2D(int x, int y) { }
public void DisplayIcon(GeoPoint p, Bitmap icon) { if (!IntoList(() => DisplayIcon(p, icon))) ++Bitmaps; }
public void DisplayBitmap(GeoPoint p, Bitmap bitmap) { if (!IntoList(() => DisplayBitmap(p, bitmap))) ++Bitmaps; }
public void SetProjection(Projection projection, BoundingCube boundingCube) { }
public void Clear(Color background) { }
public void Resize(int width, int height) { }
public void OpenList(string name = null) => openLists.Push(new DisplayList { Name = name });
public IPaintTo3DList CloseList() => openLists.Pop();
public IPaintTo3DList MakeList(List<IPaintTo3DList> sublists)
{
DisplayList res = new DisplayList();
foreach (IPaintTo3DList sublist in sublists) res.Calls.Add(() => List(sublist));
return res;
}
public void OpenPath() { }
public void ClosePath(Color color) { }
public void CloseFigure() { }
public void Arc(GeoPoint center, GeoVector majorAxis, GeoVector minorAxis, double startParameter, double sweepParameter)
{
if (IntoList(() => Arc(center, majorAxis, minorAxis, startParameter, sweepParameter))) return;
++Arcs;
Record(center);
}
public void FreeUnusedLists() { }
public void UseZBuffer(bool use) { }
public void Blending(bool on) { }
public void FinishPaint() { }
public void PaintFaces(PaintTo3D.PaintMode paintMode) { }
public void Dispose() { }
public void PushState() { }
public void PopState() { }
public void PushMultModOp(ModOp insertion)
{
if (IntoList(() => PushMultModOp(insertion))) return;
modOps.Push(current);
current = current * insertion;
}
public void PopModOp()
{
if (IntoList(PopModOp)) return;
current = modOps.Pop();
}
public void SetClip(Rectangle clipRectangle) { }
}
}
5 changes: 5 additions & 0 deletions tests/CADability.WasmSmoke/main.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Starts the smoke test under Node.js: node bin/<configuration>/net10.0/wwwroot/main.mjs (the build copies this file there)
import { dotnet } from './_framework/dotnet.js'

const exitCode = await dotnet.run();
process.exit(exitCode);
Loading