Unable to read beyond the end of the stream

1
Chris Smith
3/2/2022 3:35 AM

Hi Wout &c,

We're having an issue where ImageExporter.CreateBitmap is throwing:

Unable to read beyond the end of the stream
.

I cant work out how to reproduce it in a simple application - if I write the DxfModel out as a DWG and then read it back in it works fine.

I'm wondering if you could give me any pointers on what kinds of streams might be present in a DxfModel constructed in memory which wouldn't be in the loaded DWG?

Maybe fonts or blocks or something?

Code that simulates what we're doing (but obviously not well enough to cause the error):

C# Code:
void Main()
{
    DxfModel dxf = DwgReader.Read(@"C:\temp\render_past_stream_end.dwg");

    var width = 256;
    var height = 256;

    var color = new ArgbColor(0, 0, 0, 0);
    GraphicsConfig config = new GraphicsConfig(false, color, IndexedColorHandling.BehaveLikeAutocad)
    {
        DrawImageFrame = false,
        TryDrawingTextAsText = true,
        DisplayLineWeight = true,
        DisplayLineTypeElementShapes = true
    };

    Matrix4D transform = new Matrix4D {
        M00 = 1.674581061986476,
        M01 = 0,
        M02 = 0,
        M03 = 0,
        M10 = 0,
        M11 = -1.6745810619456694,
        M12 = 0,
        M13 = 256,
        M20 = 0,
        M21 = 0,
        M22 = 1,
        M23 = 0,
        M30 = 0,
        M31 = 0,
        M32 = 0,
        M33 = 1,
    };

    var img = ImageExporter.CreateBitmap(dxf, transform, config,
                        System.Drawing.Drawing2D.SmoothingMode.HighQuality, width, height);
    img.Dump();
}

DWG attached.

Thanks for any help,
Chris

Chris Smith
3/2/2022 3:37 AM

Here's the stack trace - looks like a font issue:

at System.IO.__Error.EndOfFile()
at System.IO.BinaryReader.ReadByte()
at WW.Cad.Model.Entities.ShxFile.(Byte[] )
at WW.Cad.Model.Entities.ShxFile.()
at WW.Cad.Model.Entities.ShxFile..ctor(String , Stream )
at WW.Cad.Model.Entities.ShxFile.GetShxFile(String filename, String filenameWithExtension, IFontFileLoader fontFileLoader)
at WW.Cad.Model.DxfModel.(String )
at .get_()
at ..ctor( )
at .(String , Double , Double , Double , DxfTextStyle , Color , String& )
at .(DxfText , Color , Int16 , Matrix4D , Bounds2D , Vector2D& , Vector2D& ,  )
at WW.Cad.Drawing.GDI.GDIGraphics3D..CreateText(DxfText , Wireframe )
at WW.Cad.Model.Entities.DxfText.DrawInternal(Wireframe context, IWireframeGraphicsFactory graphicsFactory)
at WW.Cad.Model.Entities.DxfEntity.Draw(Wireframe context, IWireframeGraphicsFactory graphicsFactory)
at WW.Cad.Model.Tables.DxfBlock.( , Boolean )
at WW.Cad.Model.Entities.DxfInsert.( , Boolean )
at WW.Cad.Model.Entities.DxfInsert.DrawInternal(Wireframe context, IWireframeGraphicsFactory graphicsFactory)
at WW.Cad.Model.Entities.DxfEntity.Draw(Wireframe context, IWireframeGraphicsFactory graphicsFactory)
at WW.Cad.Model.DxfModel.Draw(Wireframe context, IWireframeGraphicsFactory graphicsFactory)
at WW.Cad.Drawing.WireframeGraphicsFactoryUtil.CreateDrawables(IWireframeGraphicsFactory graphicsFactory, GraphicsConfig graphicsConfig, DxfModel model, Matrix4D modelTransform)
at WW.Cad.Drawing.GDI.GDIGraphics3D.CreateDrawables(DxfModel model)
at WW.Cad.IO.ImageExporter.CreateBitmap(DxfModel model, Matrix4D transform, GraphicsConfig graphicsConfig, SmoothingMode smoothingMode, Int32 width, Int32 height)
at SpatialInfo.Platform.Web.Formats.Graphic.Images.CadRenderer.Render(IVectorDrawing drawing, Double renderWidth, Double renderHeight, IEnumerable`1 imagePaths, String contentType, GraphicsMetrics stats) in C:\TFS\Product.SpatialSTORM\main.dev\DEV

Chris Smith
3/2/2022 8:26 AM

Humm - ok - I've got past that - it looks like our font resolver was not behaving properly.

But now I get this error (below). Its the same test case. There are no DxfText or DxfMTexts in the drawing but there is a Block that has some text / attributes in it. The drawing looks fine if I write it to DWG and then render but rendering it from an in-memory model causes this error.

Any clues what it might be having a key conflict with? It appears to only use "Standard" text style and txt.shx.

at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at WW.Cad.Model.Entities.ShxFile.GetShxFile(String filename, String filenameWithExtension, IFontFileLoader fontFileLoader)
at WW.Cad.Model.DxfModel.(String )
at WW.Cad.Model.Tables.DxfTextStyle.()
at WW.Cad.Model.Entities.DxfText.()
at WW.Cad.Model.Entities.DxfText.DrawInternal(Wireframe context, IWireframeGraphicsFactory graphicsFactory)
at WW.Cad.Model.Entities.DxfEntity.Draw(Wireframe context, IWireframeGraphicsFactory graphicsFactory)
at WW.Cad.Model.Tables.DxfBlock.( , Boolean )
at WW.Cad.Model.Entities.DxfInsert.( , Boolean )
at WW.Cad.Model.Entities.DxfInsert.DrawInternal(Wireframe context, IWireframeGraphicsFactory graphicsFactory)
at WW.Cad.Model.Entities.DxfEntity.Draw(Wireframe context, IWireframeGraphicsFactory graphicsFactory)
at WW.Cad.Model.DxfModel.Draw(Wireframe context, IWireframeGraphicsFactory graphicsFactory)
at WW.Cad.Drawing.WireframeGraphicsFactoryUtil.CreateDrawables(IWireframeGraphicsFactory graphicsFactory, GraphicsConfig graphicsConfig, DxfModel model, Matrix4D modelTransform)
at WW.Cad.Drawing.GDI.GDIGraphics3D.CreateDrawables(DxfModel model)
at WW.Cad.IO.ImageExporter.CreateBitmap(DxfModel model, Matrix4D transform, GraphicsConfig graphicsConfig, SmoothingMode smoothingMode, Int32 width, Int32 height)
at SpatialInfo.Platform.Web.Formats.Graphic.Images.CadRenderer.Render(IVectorDrawing drawing, Double renderWidth, Double renderHeight, IEnumerable`1 imagePaths, String contentType, GraphicsMetrics stats) in C:\TFS\Product.SpatialSTORM\main.dev\DEV\Platform\Web\Formats\Graphic\Images\CadRenderer.cs:line 2257

Chris Smith
3/2/2022 9:36 AM

So in the interests of trying to a) not drive myself crazy, b) help out, I had a look at what ILSpy could tell me 🙂 and I'd say this is a bug?

The method:

C# Code:
public static ShxFile GetShxFile(string filename, IList<IFontFileLoader> path, out IFontFileLoader foundFontFileLoader)

appears to lock around a static lock and checks whether the file has already been loaded into a static dictionary whereas the method:

C# Code:
public static ShxFile GetShxFile(string filename, string filenameWithExtension, IFontFileLoader fontFileLoader)

doesn't appear to lock or test the global dictionary before it sticks the value in there.

Any chance of a fix to apply the same lock and TryGetValue calls?

I'm still not sure why I cant reproduce this in a simpler program...

Wout
3/2/2022 10:46 AM

Hi Chris,

There was indeed a missing lock in that area, I was able to get an exception by running 4 threads simultaneously running your code. I've added extra locks, can you try the latest version?

I did not get a beyond end of stream problem though.

- Wout

Chris Smith
3/2/2022 10:48 AM

Awesome! thank you! Will give it a test

Yes end of stream thing was our fault - for some reason all our shx files were full of zeros and we were returning null streams in some cases.

Chris Smith
3/2/2022 11:14 AM

And again big thank you! I can confirm this has fixed it!

1