• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DomCR / ACadSharp / 28009637452

23 Jun 2026 07:26AM UTC coverage: 76.672% (-0.5%) from 77.204%
28009637452

Pull #1019

github

web-flow
Merge 6f8c6a3dc into 7f35d38e6
Pull Request #1019: Add mechanical entities and proxy graphics

8915 of 12597 branches covered (70.77%)

Branch coverage included in aggregate %.

452 of 909 new or added lines in 44 files covered. (49.72%)

32283 of 41136 relevant lines covered (78.48%)

154759.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.21
/src/ACadSharp/Entities/ProxyGraphics/ProxyGeometry.cs
1
using ACadSharp.IO;
2
using ACadSharp.IO.DWG;
3
using CSMath;
4
using CSUtilities.Converters;
5
using CSUtilities.IO;
6
using System;
7
using System.Collections.Generic;
8
using System.Diagnostics;
9
using System.Linq;
10
using System.Text;
11

12
namespace ACadSharp.Entities.ProxyGraphics;
13

14
// "TODO: VALIDATE" comments used to indicate type parser that have not yet been tested
15

16
public class ProxyGeometry
17
{
18
        internal static IEnumerable<IProxyGeometry> ReadGeometries(CadDocumentBuilder builder, byte[] arr)
19
        {
3,246✔
20
                List<IProxyGeometry> geometries = new();
3,246✔
21

22
                StreamIO stream = new StreamIO(arr);
3,246✔
23
                stream.EndianConverter = new LittleEndianConverter();
3,246✔
24
                var size = stream.ReadInt();
3,246✔
25
                var count = stream.ReadInt();
3,246✔
26

27
                for (int i = 0; i < count; i++)
367,836✔
28
                {
180,672✔
29
                        var objSize = stream.ReadInt(); //Includes size and type
180,672✔
30
                        GraphicsType type = (GraphicsType)stream.ReadInt();
180,672✔
31

32
                        var pos = stream.Position;
180,672✔
33

34
                        switch (type)
180,672!
35
                        {
36
                                case GraphicsType.Extents:
NEW
37
                                        geometries.Add(readExtents(stream));
×
NEW
38
                                        break;
×
39
                                case GraphicsType.Circle:
40
                                        geometries.Add(readCircle(stream));
441✔
41
                                        break;
441✔
42
                                case GraphicsType.CirclePt3:
NEW
43
                                        geometries.Add(readCirclePt3(stream));
×
NEW
44
                                        break;
×
45
                                case GraphicsType.CircularArc:
NEW
46
                                        geometries.Add(readCircularArc(stream));
×
NEW
47
                                        break;
×
48
                                case GraphicsType.CircularArc3Pt:
NEW
49
                                        geometries.Add(readCircularArc3Pt(stream));
×
NEW
50
                                        break;
×
51
                                case GraphicsType.Polyline:
52
                                        geometries.Add(readPolyline(stream));
45,282✔
53
                                        break;
45,282✔
54
                                case GraphicsType.Polygon:
55
                                        geometries.Add(readPolygon(stream));
2,205✔
56
                                        break;
2,205✔
57
                                case GraphicsType.Mesh:
NEW
58
                                        geometries.Add(readMesh(stream));
×
NEW
59
                                        break;
×
60
                                case GraphicsType.Shell:
61
                                        geometries.Add(readShell(stream));
147✔
62
                                        break;
147✔
63
                                case GraphicsType.Text:
NEW
64
                                        geometries.Add(readText(stream));
×
NEW
65
                                        break;
×
66
                                case GraphicsType.Text2:
67
                                        geometries.Add(readText2(stream));
3,717✔
68
                                        break;
3,717✔
69
                                case GraphicsType.XLine:
NEW
70
                                        geometries.Add(readXLine(stream));
×
NEW
71
                                        break;
×
72
                                case GraphicsType.Ray:
NEW
73
                                        geometries.Add(readRay(stream));
×
NEW
74
                                        break;
×
75
                                case GraphicsType.SubentColor:
76
                                        geometries.Add(readSubentColor(stream));
3,024✔
77
                                        break;
3,024✔
78
                                case GraphicsType.SubentLayer:
79
                                        geometries.Add(readSubentLayer(stream));
4,116✔
80
                                        break;
4,116✔
81
                                case GraphicsType.SubentLineType:
82
                                        geometries.Add(readSubentLineType(stream));
14,322✔
83
                                        break;
14,322✔
84
                                case GraphicsType.SubentMarker:
85
                                        geometries.Add(readSubentMarker(stream));
49,245✔
86
                                        break;
49,245✔
87
                                case GraphicsType.SubentFillon:
88
                                        geometries.Add(readSubentFillon(stream));
5,586✔
89
                                        break;
5,586✔
90
                                case GraphicsType.SubentTrueColor:
91
                                        geometries.Add(readSubentTrueColor(stream));
16,842✔
92
                                        break;
16,842✔
93
                                case GraphicsType.SubentLineWeight:
94
                                        geometries.Add(readSubentLineWeight(stream));
12,999✔
95
                                        break;
12,999✔
96
                                case GraphicsType.SubentLineTypeScale:
97
                                        geometries.Add(readSubentLineTypeScale(stream));
882✔
98
                                        break;
882✔
99
                                case GraphicsType.SubentThickness:
100
                                        geometries.Add(readSubentThickness(stream));
882✔
101
                                        break;
882✔
102
                                case GraphicsType.SubentPlotStyleName:
103
                                        geometries.Add(readSubentPlotStyleName(stream));
882✔
104
                                        break;
882✔
105
                                case GraphicsType.PushClip:
NEW
106
                                        geometries.Add(readPushClip(stream));
×
NEW
107
                                        break;
×
108
                                case GraphicsType.PopClip:
NEW
109
                                        geometries.Add(readPopClip(stream));
×
NEW
110
                                        break;
×
111
                                case GraphicsType.PushModelTransform:
112
                                        geometries.Add(readPushModelTransform(stream));
840✔
113
                                        break;
840✔
114
                                case GraphicsType.PushModelTransform2:
NEW
115
                                        geometries.Add(readPushModelTransform2(stream));
×
NEW
116
                                        break;
×
117
                                case GraphicsType.PophModelTransform:
118
                                        geometries.Add(readPopModelTransform(stream));
840✔
119
                                        break;
840✔
120
                                case GraphicsType.PolylineWithNormal:
121
                                        geometries.Add(readPolylineWithNormal(stream));
3,255✔
122
                                        break;
3,255✔
123
                                case GraphicsType.LwPolyine:
NEW
124
                                        geometries.Add(readLwPolyine(builder, stream));
×
NEW
125
                                        break;
×
126
                                case GraphicsType.SubEntityMaterial:
127
                                        geometries.Add(readSubEntityMaterial(stream));
630✔
128
                                        break;
630✔
129
                                case GraphicsType.SubEntityMapper:
NEW
130
                                        geometries.Add(readSubEntityMapper(stream));
×
NEW
131
                                        break;
×
132
                                case GraphicsType.UnicodeText:
133
                                        geometries.Add(readUnicodeText(stream));
12✔
134
                                        break;
12✔
135
                                case GraphicsType.Unknown37:
NEW
136
                                        geometries.Add(readUnknown37(stream));
×
NEW
137
                                        break;
×
138
                                case GraphicsType.UnicodeText2:
139
                                        geometries.Add(readUnicodeText2(stream));
4,956✔
140
                                        break;
4,956✔
141
                                case GraphicsType.Unknown:
142
                                default:
143
                                        // Type 51 (size 12, data: zeros)
144
                                        break;
9,567✔
145
                        }
146

147
                        long readDiff = objSize - (stream.Position - pos) - 8;
180,672✔
148
                        if (readDiff > 0)
180,672✔
149
                        {
9,555✔
150
                                //jump not implemented proxies
151
                                stream.ReadBytes((int) readDiff);
9,555✔
152
                        }
9,555✔
153
                }
180,672✔
154

155
                return geometries;
3,246✔
156
        }
3,246✔
157

158
        private static IProxyGeometry readCircle(StreamIO stream)
159
        {
441✔
160
                ProxyCircle circle = new ProxyCircle();
441✔
161

162
                circle.Center = readPoint(stream);
441✔
163
                circle.Radius = stream.ReadDouble();
441✔
164
                circle.Normal = readPoint(stream);
441✔
165

166
                return circle;
441✔
167
        }
441✔
168

169
        private static IProxyGeometry readCirclePt3(StreamIO stream)
NEW
170
        {
×
NEW
171
                ProxyCirclePt3 circle = new ProxyCirclePt3();
×
172

NEW
173
                circle.Point1 = readPoint(stream);
×
NEW
174
                circle.Point2 = readPoint(stream);
×
NEW
175
                circle.Point3 = readPoint(stream);
×
176

NEW
177
                return circle;
×
NEW
178
        }
×
179

180
        private static IProxyGeometry readCircularArc(StreamIO stream)
NEW
181
        {
×
NEW
182
                ProxyCircularArc arc = new ProxyCircularArc();
×
183

NEW
184
                arc.Center = readPoint(stream);
×
NEW
185
                arc.Radius = stream.ReadDouble();
×
NEW
186
                arc.Normal = readPoint(stream);
×
NEW
187
                arc.StartVectorDirection = readPoint(stream);
×
NEW
188
                arc.SweepAngle = stream.ReadDouble();
×
NEW
189
                arc.ArcType = stream.ReadInt();
×
190

NEW
191
                return arc;
×
NEW
192
        }
×
193

194
        private static IProxyGeometry readCircularArc3Pt(StreamIO stream)
NEW
195
        {
×
NEW
196
                ProxyCircularArc3Pt arc = new ProxyCircularArc3Pt();
×
197

NEW
198
                arc.Point1 = readPoint(stream);
×
NEW
199
                arc.Point2 = readPoint(stream);
×
NEW
200
                arc.Point3 = readPoint(stream);
×
NEW
201
                arc.ArcType = stream.ReadInt();
×
202

NEW
203
                return arc;
×
NEW
204
        }
×
205

206
        private static IProxyGeometry readExtents(StreamIO stream)
NEW
207
        {
×
NEW
208
                ProxyExtents extents = new ProxyExtents();
×
209

NEW
210
                extents.Min = readPoint(stream);
×
NEW
211
                extents.Max = readPoint(stream);
×
212

NEW
213
                return extents;
×
NEW
214
        }
×
215

216
        private static IProxyGeometry readLwPolyine(CadDocumentBuilder builder, StreamIO stream)
NEW
217
        {
×
NEW
218
                int dataSize = stream.ReadInt();
×
NEW
219
                ProxyLwPolyine polyline = new ProxyLwPolyine
×
NEW
220
                {
×
NEW
221
                        Entity = new LwPolyline()
×
NEW
222
                };
×
223

224
                // The following reads the LwPolyline entity like the DwgObjectReader
225

NEW
226
                IDwgStreamReader reader = DwgStreamReaderBase.GetStreamHandler(builder.Version, stream.Stream);
×
227

NEW
228
                short flags = reader.ReadBitShort();
×
NEW
229
                if ((flags & 0x100) != 0)
×
NEW
230
                {
×
NEW
231
                        polyline.Entity.Flags |= LwPolylineFlags.Plinegen;
×
NEW
232
                }
×
NEW
233
                if ((flags & 0x200) != 0)
×
NEW
234
                {
×
NEW
235
                        polyline.Entity.Flags |= LwPolylineFlags.Closed;
×
NEW
236
                }
×
NEW
237
                if ((flags & 0x4u) != 0)
×
NEW
238
                {
×
NEW
239
                        polyline.Entity.ConstantWidth = reader.ReadBitDouble();
×
NEW
240
                }
×
NEW
241
                if ((flags & 0x8u) != 0)
×
NEW
242
                {
×
NEW
243
                        polyline.Entity.Elevation = reader.ReadBitDouble();
×
NEW
244
                }
×
NEW
245
                if ((flags & 0x2u) != 0)
×
NEW
246
                {
×
NEW
247
                        polyline.Entity.Thickness = reader.ReadBitDouble();
×
NEW
248
                }
×
NEW
249
                if ((flags & (true ? 1u : 0u)) != 0)
×
NEW
250
                {
×
NEW
251
                        polyline.Entity.Normal = reader.Read3BitDouble();
×
NEW
252
                }
×
253

NEW
254
                int nvertices = reader.ReadBitLong();
×
255

NEW
256
                int nbulges = 0;
×
NEW
257
                if (((uint)flags & 0x10) != 0)
×
NEW
258
                {
×
NEW
259
                        nbulges = reader.ReadBitLong();
×
NEW
260
                }
×
261

NEW
262
                int nids = 0;
×
NEW
263
                if (((uint)flags & 0x400) != 0)
×
NEW
264
                {
×
NEW
265
                        nids = reader.ReadBitLong();
×
NEW
266
                }
×
267

NEW
268
                int ndiffwidth = 0;
×
NEW
269
                if (((uint)flags & 0x20) != 0)
×
NEW
270
                {
×
NEW
271
                        ndiffwidth = reader.ReadBitLong();
×
NEW
272
                }
×
273

NEW
274
                if (nvertices > 0)
×
NEW
275
                {
×
NEW
276
                        XY loc = reader.Read2RawDouble();
×
NEW
277
                        polyline.Entity.Vertices.Add(new LwPolyline.Vertex(loc));
×
NEW
278
                        for (int j = 1; j < nvertices; j++)
×
NEW
279
                        {
×
NEW
280
                                loc = reader.Read2BitDoubleWithDefault(loc);
×
NEW
281
                                polyline.Entity.Vertices.Add(new LwPolyline.Vertex(loc));
×
NEW
282
                        }
×
NEW
283
                }
×
284

NEW
285
                for (int k = 0; k < nbulges; k++)
×
NEW
286
                {
×
NEW
287
                        polyline.Entity.Vertices[k].Bulge = reader.ReadBitDouble();
×
NEW
288
                }
×
289

NEW
290
                for (int l = 0; l < nids; l++)
×
NEW
291
                {
×
NEW
292
                        polyline.Entity.Vertices[l].Id = reader.ReadBitLong();
×
NEW
293
                }
×
294

NEW
295
                for (int m = 0; m < ndiffwidth; m++)
×
NEW
296
                {
×
NEW
297
                        LwPolyline.Vertex vertex = polyline.Entity.Vertices[m];
×
NEW
298
                        vertex.StartWidth = reader.ReadBitDouble();
×
NEW
299
                        vertex.EndWidth = reader.ReadBitDouble();
×
NEW
300
                }
×
301

302
                // Read additional unknown data after regular LwPolyline Entity data
303

NEW
304
                polyline.Unknown1 = stream.ReadByte();
×
NEW
305
                polyline.Unknown2 = stream.ReadByte();
×
NEW
306
                polyline.Unknown3 = stream.ReadByte();
×
307

NEW
308
                return polyline;
×
NEW
309
        }
×
310

311
        private static IProxyGeometry readMesh(StreamIO stream)
NEW
312
        {
×
NEW
313
                throw new NotImplementedException();
×
314
        }
315

316
        private static IProxyGeometry readPolygon(StreamIO stream)
317
        {
2,205✔
318
                ProxyPolygon polygon = new ProxyPolygon();
2,205✔
319
                polygon.Points = [];
2,205✔
320

321
                int pointCount = stream.ReadInt();
2,205✔
322
                for (int i = 0; i < pointCount; i++)
17,640✔
323
                {
6,615✔
324
                        polygon.Points.Add(readPoint(stream));
6,615✔
325
                }
6,615✔
326

327
                return polygon;
2,205✔
328
        }
2,205✔
329

330
        private static IProxyGeometry readPolyline(StreamIO stream)
331
        {
45,282✔
332
                ProxyPolyline polyline = new ProxyPolyline();
45,282✔
333

334
                int pointCount = stream.ReadInt();
45,282✔
335
                for (int i = 0; i < pointCount; i++)
279,720✔
336
                {
94,578✔
337
                        polyline.Points.Add(readPoint(stream));
94,578✔
338
                }
94,578✔
339

340
                return polyline;
45,282✔
341
        }
45,282✔
342

343
        private static IProxyGeometry readPolylineWithNormal(StreamIO stream)
344
        {
3,255✔
345
                ProxyPolylineWithNormal polyline = new ProxyPolylineWithNormal();
3,255✔
346

347
                int pointCount = stream.ReadInt();
3,255✔
348
                for (int i = 0; i < pointCount; i++)
19,530✔
349
                {
6,510✔
350
                        polyline.Points.Add(readPoint(stream));
6,510✔
351
                }
6,510✔
352
                polyline.Normal = readPoint(stream);
3,255✔
353

354
                return polyline;
3,255✔
355
        }
3,255✔
356

357
        private static IProxyGeometry readPopClip(StreamIO stream)
NEW
358
        {
×
NEW
359
                return new ProxyPopClip();
×
NEW
360
        }
×
361

362
        private static IProxyGeometry readPopModelTransform(StreamIO stream)
363
        {
840✔
364
                return new ProxyPopModelTransform();
840✔
365
        }
840✔
366

367
        private static IProxyGeometry readPushClip(StreamIO stream)
NEW
368
        {
×
NEW
369
                ProxyPushClip clip = new ProxyPushClip();
×
370

NEW
371
                clip.Extrusion = readPoint(stream);
×
NEW
372
                clip.ClipBoundaryOrigin = readPoint(stream);
×
NEW
373
                clip.PointCount = stream.ReadInt();
×
NEW
374
                clip.Points = [];
×
NEW
375
                for (int i = 0; i < clip.PointCount; i++)
×
NEW
376
                {
×
NEW
377
                        clip.Points.Add(new XY(stream.ReadDouble(), stream.ReadDouble()));
×
NEW
378
                }
×
NEW
379
                clip.ClipBoundaryTransformMatrix = readMatrix(stream);
×
NEW
380
                clip.InverseBlockTransformMatrix = readMatrix(stream);
×
NEW
381
                clip.FrontClipOn = stream.ReadInt();
×
NEW
382
                clip.BackClipOn = stream.ReadInt();
×
NEW
383
                clip.FrontClip = stream.ReadDouble();
×
NEW
384
                clip.BackClip = stream.ReadDouble();
×
NEW
385
                clip.DrawBoundary = stream.ReadInt() == 1;
×
386

NEW
387
                Debugger.Break();    // TODO: VALIDATE
×
NEW
388
                return clip;
×
NEW
389
        }
×
390

391
        private static IProxyGeometry readPushModelTransform(StreamIO stream)
392
        {
840✔
393
                ProxyPushModelTransform modelTransform = new ProxyPushModelTransform();
840✔
394

395
                modelTransform.TransformationMatrix = readMatrix(stream);
840✔
396

397
                return modelTransform;
840✔
398
        }
840✔
399

400
        private static IProxyGeometry readPushModelTransform2(StreamIO stream)
NEW
401
        {
×
NEW
402
                throw new NotImplementedException();
×
403
        }
404

405
        private static IProxyGeometry readRay(StreamIO stream)
NEW
406
        {
×
NEW
407
                ProxyRay ray = new ProxyRay();
×
408

NEW
409
                ray.ConstructionLinePoint = readPoint(stream);
×
NEW
410
                ray.Point2 = readPoint(stream);
×
411

NEW
412
                return ray;
×
NEW
413
        }
×
414

415
        private static IProxyGeometry readShell(StreamIO stream)
416
        {
147✔
417
                ProxyShell shell = new ProxyShell();
147✔
418

419
                static bool adHasPrimTraits(int a) => (a & 0xFFFFL) != 0;
441✔
420
                static bool adPrimsHaveColors(int a) => (a & 0x0001L) != 0;
147✔
421
                static bool adPrimsHaveLayers(int a) => (a & 0x0002L) != 0;
147✔
422
                static bool adPrimsHaveLineTypes(int a) => (a & 0x0004L) != 0;
147✔
423
                static bool adPrimsHaveMarkers(int a) => (a & 0x0020L) != 0;
147✔
424
                static bool adPrimsHaveVisibilities(int a) => (a & 0x0040L) != 0;
147✔
NEW
425
                static bool adPrimsHaveNormal(int a) => (a & 0x0080L) != 0;
×
NEW
426
                static bool adPrimsHaveOrientation(int a) => (a & 0x0400L) != 0;
×
427

428
                shell.PointCount = stream.ReadInt();
147✔
429
                shell.Vertices = [];
147✔
430
                for (int i = 0; i < shell.PointCount; i++) {
2,058✔
431
                        shell.Vertices.Add(readPoint(stream));
588✔
432
                }
588✔
433
                shell.FaceCount = stream.ReadInt();
147✔
434
                shell.Faces = [];
147✔
435
                int faceCount = 0;
147✔
436
                int edgeCount = 0;
147✔
437
                for (int i = 0; i < shell.FaceCount; i++) {
735✔
438
                        int count = Math.Abs(stream.ReadInt());
147✔
439
                        i += count + 1;
147✔
440

441
                        List<int> faceIndices = [];
147✔
442
                        for (int j = 0; j < count; j++) {
2,058✔
443
                                faceIndices.Add(stream.ReadInt());
588✔
444
                        }
588✔
445

446
                        List<XYZ> face = [];
147✔
447
                        foreach (int index in faceIndices) {
2,205✔
448
                                face.Add(shell.Vertices[index]);
588✔
449
                        }
588✔
450
                        shell.Faces.Add(face);
147✔
451
                        faceCount++;
147✔
452
                        edgeCount += count;
147✔
453
                }
147✔
454

455
                // Parse traits for all edges
456
                int edgeFlags = stream.ReadInt();
147✔
457
                if (adHasPrimTraits(edgeFlags)) {
294✔
458
                        if (adPrimsHaveColors(edgeFlags)) {
147!
NEW
459
                                for (int i = 0; i < edgeCount; i++) {
×
NEW
460
                                        int edgeColor = stream.ReadInt();
×
NEW
461
                                }
×
NEW
462
                        }
×
463
                        if (adPrimsHaveLayers(edgeFlags)) {
147!
NEW
464
                                for (int i = 0; i < edgeCount; i++) {
×
NEW
465
                                        int layerIds = stream.ReadInt();
×
NEW
466
                                }
×
NEW
467
                        }
×
468
                        if (adPrimsHaveLineTypes(edgeFlags)) {
147!
NEW
469
                                for (int i = 0; i < edgeCount; i++) {
×
NEW
470
                                        int lineTypeIds = stream.ReadInt();
×
NEW
471
                                }
×
NEW
472
                        }
×
473
                        if (adPrimsHaveMarkers(edgeFlags)) {
294✔
474
                                for (int i = 0; i < edgeCount; i++) {
2,058✔
475
                                        int markerIndices = stream.ReadInt();
588✔
476
                                }
588✔
477
                        }
147✔
478
                        if (adPrimsHaveVisibilities(edgeFlags)) {
294✔
479
                                for (int i = 0; i < edgeCount; i++) {
2,058✔
480
                                        int visibilityIndicator = stream.ReadInt();
588✔
481
                                }
588✔
482
                        }
147✔
483
                }
147✔
484

485
                // Parse traits for all faces
486
                int faceFlags = stream.ReadInt();
147✔
487
                if (adHasPrimTraits(faceFlags)) {
147!
NEW
488
                        if (adPrimsHaveColors(faceFlags)) {
×
NEW
489
                                for (int i = 0; i < faceCount; i++) {
×
NEW
490
                                        int edgeColor = stream.ReadInt();
×
NEW
491
                                }
×
NEW
492
                        }
×
NEW
493
                        if (adPrimsHaveLayers(faceFlags)) {
×
NEW
494
                                for (int i = 0; i < faceCount; i++) {
×
NEW
495
                                        int layerIds = stream.ReadInt();
×
NEW
496
                                }
×
NEW
497
                        }
×
NEW
498
                        if (adPrimsHaveMarkers(faceFlags)) {
×
NEW
499
                                for (int i = 0; i < faceCount; i++) {
×
NEW
500
                                        int markerIndices = stream.ReadInt();
×
NEW
501
                                }
×
NEW
502
                        }
×
NEW
503
                        if (adPrimsHaveNormal(faceFlags)) {
×
NEW
504
                                for (int i = 0; i < faceCount; i++) {
×
NEW
505
                                        XYZ normal = readPoint(stream);
×
NEW
506
                                }
×
NEW
507
                        }
×
NEW
508
                        if (adPrimsHaveVisibilities(faceFlags)) {
×
NEW
509
                                for (int i = 0; i < faceCount; i++) {
×
NEW
510
                                        int visibilityIndicator = stream.ReadInt();
×
NEW
511
                                }
×
NEW
512
                        }
×
NEW
513
                }
×
514

515
                // Parse traits for all vertices
516
                int vertexFlags = stream.ReadInt();
147✔
517
                if (adHasPrimTraits(vertexFlags)) {
147!
NEW
518
                        if (adPrimsHaveNormal(vertexFlags)) {
×
519
                                // TODO: Check if this is the correct vertex count (As ODA stated "compute numvertices as rows * cols")
NEW
520
                                for (int i = 0; i < shell.Vertices.Count; i++) {
×
NEW
521
                                        XYZ normal = readPoint(stream);
×
NEW
522
                                }
×
NEW
523
                        }
×
NEW
524
                        if (adPrimsHaveOrientation(vertexFlags)) {
×
NEW
525
                                int orientation = stream.ReadInt();
×
NEW
526
                        }
×
NEW
527
                }
×
528

529
                return shell;
147✔
530
        }
147✔
531

532
        private static IProxyGeometry readSubentColor(StreamIO stream)
533
        {
3,024✔
534
                ProxySubentColor color = new ProxySubentColor();
3,024✔
535

536
                color.ColorIndex = stream.ReadInt();
3,024✔
537

538
                return color;
3,024✔
539
        }
3,024✔
540

541
        private static IProxyGeometry readSubentFillon(StreamIO stream)
542
        {
5,586✔
543
                ProxySubentFillon fillOn = new ProxySubentFillon();
5,586✔
544

545
                int fillValue = stream.ReadInt();
5,586✔
546
                fillOn.IsOn = fillValue == 1;        // Also seen value 2 as well
5,586✔
547

548
                return fillOn;
5,586✔
549
        }
5,586✔
550

551
        private static IProxyGeometry readSubEntityMapper(StreamIO stream)
NEW
552
        {
×
NEW
553
                ProxySubEntityMapper mapper = new ProxySubEntityMapper();
×
554

NEW
555
                mapper.DummyValue1 = stream.ReadInt();
×
NEW
556
                mapper.DummyValue2 = stream.ReadInt();
×
NEW
557
                mapper.Projection = stream.ReadInt();
×
NEW
558
                mapper.UTiling = stream.ReadInt();
×
NEW
559
                mapper.VTiling = stream.ReadInt();
×
NEW
560
                mapper.AutoTransform = stream.ReadInt();
×
NEW
561
                mapper.DummyValue3 = stream.ReadInt();
×
562

NEW
563
                Debugger.Break();    // TODO: VALIDATE
×
NEW
564
                return mapper;
×
NEW
565
        }
×
566

567
        private static IProxyGeometry readSubEntityMaterial(StreamIO stream)
568
        {
630✔
569
                ProxySubEntityMaterial material = new ProxySubEntityMaterial();
630✔
570

571
                material.MaterialHandle = (ulong) stream.ReadInt();
630✔
572
                int unknown1 = stream.ReadInt();
630✔
573

574
                return material;
630✔
575
        }
630✔
576

577
        private static IProxyGeometry readSubentLayer(StreamIO stream)
578
        {
4,116✔
579
                ProxySubentLayer layer = new ProxySubentLayer();
4,116✔
580

581
                layer.LayerIndex = stream.ReadInt();
4,116✔
582

583
                return layer;
4,116✔
584
        }
4,116✔
585

586
        private static IProxyGeometry readSubentLineType(StreamIO stream)
587
        {
14,322✔
588
                ProxySubentLineType lineType = new ProxySubentLineType();
14,322✔
589

590
                lineType.LineTypeIndex = stream.ReadUInt();
14,322✔
591

592
                return lineType;
14,322✔
593
        }
14,322✔
594

595
        private static IProxyGeometry readSubentLineTypeScale(StreamIO stream)
596
        {
882✔
597
                ProxySubentLineTypeScale scale = new ProxySubentLineTypeScale();
882✔
598

599
                scale.LineTypeScale = stream.ReadDouble();
882✔
600

601
                return scale;
882✔
602
        }
882✔
603

604
        private static IProxyGeometry readSubentLineWeight(StreamIO stream)
605
        {
12,999✔
606
                ProxySubentLineWeight lineWeight= new ProxySubentLineWeight();
12,999✔
607

608
                lineWeight.LineWeight = (LineWeightType) stream.ReadInt();
12,999✔
609

610
                return lineWeight;
12,999✔
611
        }
12,999✔
612

613
        private static IProxyGeometry readSubentMarker(StreamIO stream)
614
        {
49,245✔
615
                ProxySubentMarker marker = new ProxySubentMarker();
49,245✔
616

617
                marker.MarkerIndex = stream.ReadInt();
49,245✔
618

619
                return marker;
49,245✔
620
        }
49,245✔
621

622
        private static IProxyGeometry readSubentPlotStyleName(StreamIO stream)
623
        {
882✔
624
                ProxySubentPlotStyleName psName = new ProxySubentPlotStyleName();
882✔
625

626
                psName.Type = (ProxyPlotStyleType) stream.ReadInt();
882✔
627
                psName.PlotStyleIndex = stream.ReadInt();
882✔
628

629
                return psName;
882✔
630
        }
882✔
631

632
        private static IProxyGeometry readSubentThickness(StreamIO stream)
633
        {
882✔
634
                ProxySubentThickness thickness = new ProxySubentThickness();
882✔
635

636
                thickness.Thickness = stream.ReadDouble();
882✔
637

638
                return thickness;
882✔
639
        }
882✔
640

641
        private static IProxyGeometry readSubentTrueColor(StreamIO stream)
642
        {
16,842✔
643
                ProxySubentTrueColor trueColor = new ProxySubentTrueColor();
16,842✔
644

645
                // The first three bytes are the value and the fourth byte indicates how
646
                // those 3 previous bytes should be interpreted (see https://help.autodesk.com/view/OARX/2025/ENU/?guid=OARX-RefGuide-AcGiSubEntityTraits__setTrueColor_AcCmEntityColor_)
647

648
                byte b1 = stream.ReadByte();
16,842✔
649
                byte b2 = stream.ReadByte();
16,842✔
650
                byte b3 = stream.ReadByte();
16,842✔
651
                ProxyColorMethod method = (ProxyColorMethod) stream.ReadByte();
16,842✔
652

653
                switch (method) 
16,842!
654
                {
655
                        case ProxyColorMethod.ByLayer:
656
                                trueColor.Color = Color.ByLayer;
9,849✔
657
                                break;
9,849✔
658
                        case ProxyColorMethod.ByBlock:
NEW
659
                                trueColor.Color = Color.ByBlock;
×
NEW
660
                                break;
×
661
                        case ProxyColorMethod.ByColor:
NEW
662
                                trueColor.Color = new Color(b1, b2, b3);
×
NEW
663
                                break;
×
664
                        case ProxyColorMethod.ByACI:
665
                                trueColor.Color = new Color(b1);
6,993✔
666
                                break;
6,993✔
667
                        case ProxyColorMethod.Foreground:
NEW
668
                                trueColor.Color = new Color(7);        // TODO: Check if this is what foreground actually means
×
NEW
669
                                break;
×
670
                        case ProxyColorMethod.None:
NEW
671
                                break;
×
672
                        default:
NEW
673
                                break;
×
674
                }
675

676
                return trueColor;
16,842✔
677
        }
16,842✔
678

679
        private static IProxyGeometry readText(StreamIO stream)
NEW
680
        {
×
NEW
681
                ProxyText text = new ProxyText();
×
682

NEW
683
                text.StartPoint = readPoint(stream);
×
NEW
684
                text.Normal = readPoint(stream);
×
NEW
685
                text.TextDirection = readPoint(stream);
×
NEW
686
                text.Height = stream.ReadDouble();
×
NEW
687
                text.WidthFactor = stream.ReadDouble();
×
NEW
688
                text.ObliqueAngle = stream.ReadDouble();
×
NEW
689
                text.Text = readPaddedString(stream);
×
690

691
                // Padding to align the text to the next 4-byte boundary
NEW
692
                if ((text.Text.Length + 1) % 4 != 0)
×
NEW
693
                {
×
NEW
694
                        stream.ReadBytes(4 - (text.Text.Length + 1) % 4);
×
NEW
695
                }
×
696

NEW
697
                return text;
×
NEW
698
        }
×
699

700
        private static IProxyGeometry readText2(StreamIO stream)
701
        {
3,717✔
702
                ProxyText2 text = new ProxyText2();
3,717✔
703
                text.StartPoint = readPoint(stream);
3,717✔
704
                text.Normal = readPoint(stream);
3,717✔
705
                text.TextDirection = readPoint(stream);
3,717✔
706
                text.Text = readPaddedString(stream);
3,717✔
707

708
                // Padding to align the text to the next 4-byte boundary
709
                if ((text.Text.Length + 1) % 4 != 0)
3,717✔
710
                {
2,205✔
711
                        stream.ReadBytes(4 - (text.Text.Length + 1) % 4);
2,205✔
712
                }
2,205✔
713

714
                text.TextLength = stream.ReadInt();
3,717✔
715
                text.IsRaw = stream.ReadInt() == 0;
3,717✔
716
                text.Height = stream.ReadDouble();
3,717✔
717
                text.WidthFactor = stream.ReadDouble();
3,717✔
718
                text.ObliqueAngle = stream.ReadDouble();
3,717✔
719
                text.TrackingPercentage = stream.ReadDouble();
3,717✔
720

721
                text.IsBackwards = stream.ReadInt() == 1;
3,717✔
722
                text.IsUpsideDown = stream.ReadInt() == 1;
3,717✔
723
                text.IsVertical = stream.ReadInt() == 1;
3,717✔
724
                text.IsUnderlined = stream.ReadInt() == 1;
3,717✔
725
                text.IsOverlined = stream.ReadInt() == 1;
3,717✔
726

727
                text.FontFilename = readPaddedString(stream);
3,717✔
728

729
                // Padding to align the text to the next 4-byte boundary
730
                if ((text.FontFilename.Length + 1) % 4 != 0)
3,717✔
731
                {
3,717✔
732
                        stream.ReadBytes(4 - (text.FontFilename.Length + 1) % 4);
3,717✔
733
                }
3,717✔
734

735
                text.BigFontFilename = readPaddedString(stream);
3,717✔
736

737
                // Padding to align the text to the next 4-byte boundary
738
                if ((text.BigFontFilename.Length + 1) % 4 != 0)
3,717✔
739
                {
3,717✔
740
                        stream.ReadBytes(4 - (text.BigFontFilename.Length + 1) % 4);
3,717✔
741
                }
3,717✔
742

743
                return text;
3,717✔
744
        }
3,717✔
745

746
        private static IProxyGeometry readUnicodeText(StreamIO stream)
747
        {
12✔
748
                ProxyUnicodeText text = new ProxyUnicodeText();
12✔
749

750
                text.StartPoint = readPoint(stream);
12✔
751
                text.Normal = readPoint(stream);
12✔
752
                text.TextDirection = readPoint(stream);
12✔
753
                text.Height = stream.ReadDouble();
12✔
754
                text.WidthFactor = stream.ReadDouble();
12✔
755
                text.ObliqueAngle = stream.ReadDouble();
12✔
756
                text.Text = readPaddedUnicodeString(stream);
12✔
757

758
                // Padding to align the text to the next 4-byte boundary
759
                if (text.Text.Length % 2 == 0)
12!
NEW
760
                {
×
NEW
761
                        stream.ReadShort();
×
NEW
762
                }
×
763

764
                return text;
12✔
765
        }
12✔
766

767
        private static IProxyGeometry readUnicodeText2(StreamIO stream)
768
        {
4,956✔
769
                ProxyUnicodeText2 text = new ProxyUnicodeText2();
4,956✔
770
                text.StartPoint = readPoint(stream);
4,956✔
771
                text.Normal = readPoint(stream);
4,956✔
772
                text.TextDirection = readPoint(stream);
4,956✔
773
                text.Text = readPaddedUnicodeString(stream);
4,956✔
774

775
                // Padding to align the text to the next 4-byte boundary
776
                if (text.Text.Length % 2 == 0)
4,956✔
777
                {
2,184✔
778
                        stream.ReadShort();
2,184✔
779
                }
2,184✔
780

781
                text.TextLength = stream.ReadInt();
4,956✔
782
                text.IsRaw = stream.ReadInt() == 0;
4,956✔
783
                text.Height = stream.ReadDouble();
4,956✔
784
                text.WidthFactor = stream.ReadDouble();
4,956✔
785
                text.ObliqueAngle = stream.ReadDouble();
4,956✔
786
                text.TrackingPercentage = stream.ReadDouble();
4,956✔
787

788
                text.IsBackwards = stream.ReadInt() == 1;
4,956✔
789
                text.IsUpsideDown = stream.ReadInt() == 1;
4,956✔
790
                text.IsVertical = stream.ReadInt() == 1;
4,956✔
791
                text.IsUnderlined = stream.ReadInt() == 1;
4,956✔
792
                text.IsOverlined = stream.ReadInt() == 1;
4,956✔
793

794
                TrueTypeFontDescriptor fontDescriptor = new TrueTypeFontDescriptor();
4,956✔
795
                fontDescriptor.IsBold = stream.ReadInt() == 1;
4,956✔
796
                fontDescriptor.IsItalic = stream.ReadInt() == 1;
4,956✔
797
                fontDescriptor.Charset = (byte)stream.ReadInt();
4,956✔
798
                fontDescriptor.PitchAndFamily = (byte)stream.ReadInt();
4,956✔
799
                fontDescriptor.Typeface = readPaddedUnicodeString(stream);
4,956✔
800

801
                // Padding to align the text to the next 4-byte boundary
802
                if (fontDescriptor.Typeface.Length % 2 == 0)
4,956!
NEW
803
                {
×
NEW
804
                        stream.ReadShort();
×
NEW
805
                }
×
806

807
                fontDescriptor.FontFilename = readPaddedUnicodeString(stream);
4,956✔
808

809
                // Padding to align the text to the next 4-byte boundary
810
                if (fontDescriptor.FontFilename.Length % 2 == 0)
4,956✔
811
                {
4,956✔
812
                        stream.ReadShort();
4,956✔
813
                }
4,956✔
814

815
                text.FontDescriptor = fontDescriptor;
4,956✔
816
                text.BigFontFilename = readPaddedUnicodeString(stream);
4,956✔
817

818
                // Padding to align the text to the next 4-byte boundary
819
                if (fontDescriptor.FontFilename.Length % 2 == 0)
4,956✔
820
                {
4,956✔
821
                        stream.ReadShort();
4,956✔
822
                }
4,956✔
823

824
                return text;
4,956✔
825
        }
4,956✔
826

827
        private static IProxyGeometry readUnknown37(StreamIO stream)
NEW
828
        {
×
NEW
829
                Debugger.Break();    // TODO: VALIDATE
×
NEW
830
                return new ProxyUnknown37();
×
NEW
831
        }
×
832

833
        private static IProxyGeometry readXLine(StreamIO stream)
NEW
834
        {
×
NEW
835
                ProxyXLine xline = new ProxyXLine();
×
836

NEW
837
                xline.Point1 = readPoint(stream);
×
NEW
838
                xline.Point2 = readPoint(stream);
×
839

NEW
840
                return xline;
×
NEW
841
        }
×
842

843
        private static XYZ readPoint(StreamIO stream)
844
        {
138,483✔
845
                var x = stream.ReadDouble();
138,483✔
846
                var y = stream.ReadDouble();
138,483✔
847
                var z = stream.ReadDouble();
138,483✔
848
                return new XYZ(x, y, z);
138,483✔
849
        }
138,483✔
850

851
        private static Matrix4 readMatrix(StreamIO stream)
852
        {
840✔
853
                Matrix4 matrix = Matrix4.Identity;
840✔
854
                matrix.M00 = stream.ReadDouble();
840✔
855
                matrix.M01 = stream.ReadDouble();
840✔
856
                matrix.M02 = stream.ReadDouble();
840✔
857
                matrix.M03 = stream.ReadDouble();
840✔
858
                matrix.M10 = stream.ReadDouble();
840✔
859
                matrix.M11 = stream.ReadDouble();
840✔
860
                matrix.M12 = stream.ReadDouble();
840✔
861
                matrix.M13 = stream.ReadDouble();
840✔
862
                matrix.M20 = stream.ReadDouble();
840✔
863
                matrix.M21 = stream.ReadDouble();
840✔
864
                matrix.M22 = stream.ReadDouble();
840✔
865
                matrix.M23 = stream.ReadDouble();
840✔
866
                matrix.M30 = stream.ReadDouble();
840✔
867
                matrix.M31 = stream.ReadDouble();
840✔
868
                matrix.M32 = stream.ReadDouble();
840✔
869
                matrix.M33 = stream.ReadDouble();
840✔
870
                return matrix;
840✔
871
        }
840✔
872

873
        /// <summary>
874
        /// PUS : Padded Unicode string, The bytes are encoded using Unicode encoding. 
875
        /// The bytes consist of byte pairs and the string is terminated by 2 zero bytes.
876
        /// </summary>
877
        /// <returns></returns>
878
        private static string readPaddedUnicodeString(StreamIO stream)
879
        {
19,836✔
880
                byte[] nullTerminator = new byte[] { 0, 0 };
19,836✔
881

882
                List<byte> stringBytes = new List<byte>();
19,836✔
883
                byte[] character;
884
                while (!(character = stream.ReadBytes(2)).AsSpan().SequenceEqual(nullTerminator))
86,676✔
885
                {
66,840✔
886
                        stringBytes.AddRange(character);
66,840✔
887
                }
66,840✔
888
                return Encoding.Unicode.GetString(stringBytes.ToArray());
19,836✔
889
        }
19,836✔
890

891
        /// <summary>
892
        /// PS : Padded string. This is a string, terminated with a zero byte.
893
        /// The file’s text encoding (code page) is used to encode / decode 
894
        /// the bytes into a string
895
        /// </summary>
896
        /// <returns></returns>
897
        private static string readPaddedString(StreamIO stream)
898
        {
11,151✔
899
                List<byte> stringBytes = new List<byte>();
11,151✔
900
                byte character;
901
                while ((character = stream.ReadByte()) != 0)
61,047✔
902
                {
49,896✔
903
                        stringBytes.Add(character);
49,896✔
904
                }
49,896✔
905
                return stream.Encoding.GetString(stringBytes.ToArray());
11,151✔
906
        }
11,151✔
907

908
        public enum ProxyColorMethod : byte
909
        {
910
                ByLayer = 0xC0,
911
                ByBlock = 0xC1,
912
                ByColor = 0xC2,
913
                ByACI = 0xC3,
914
                Foreground = 0xC5,
915
                None = 0xC8
916
        }
917
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc