I've been trying to draw custom fonts in SharpDX. I basically followed the example from GitHub.
Whenever I try to draw the font using the D2D1 RenderTarget it throws the error below:
System.ObjectDisposedException: Cannot access a disposed object. Object name: "Cannot add a reference to a nonreferenced item"
So after a long time of debugging I couldn't find where was the issue so I decided to try to compile the project from the example above and I got the exact same error (it outputs to debug console that there is a 'System.ObjectDisposedException' Exception in SharpDX.dll)
Edit: The exit code for the program is 3; it may be useful.
I concluded that the issue was from the library itself. In my opinion there is a low chance that it's the case but if the example itself there is surely something wrong here. I'm not too familiar with DirectX in general either so I won't refuse an advise or two.
Note that in what I saw, the font was correctly loaded in the TextFormat and TextLayout.
I tried to modify my code, remove Dispose() method, replaced my whole code with the one of the example and tried to find the root of the problem, without success. I'm expecting the DrawText method from the RenderTarget shouldn't throw such error and draw the text with the font I imported.
UPDATE: The example shown is for SharpDX 3.0.0, this explains why it does not work properly. But I still need to know how can I fix the issue for SharpDX 4.2.0
How can I fix this issue if possible?
CodePudding user response:
The error basically means there's a COM object that has a refCount
value that is down to 0, so it shouldn't be used anymore. The code is located in SharpDX's CallbackBase.cs:
public int AddReference()
{
var old = refCount;
while (true)
{
if (old == 0)
{
throw new ObjectDisposedException("Cannot add a reference to a nonreferenced item");
}
var current = Interlocked.CompareExchange(ref refCount, old 1, old);
if (current == old)
{
return old 1;
}
old = current;
}
}
So it's "just" a COM reference issue. The error is thrown by the CustomFont.ResourceFontFileStream.cs
file that derives from CallbackBase
(it's implements a COM object), so there's a reference issue on the ResourceFontFileStream
type.
How SharpDX handles references in the general case is a bit obscure to me (it has lots of wrapper and boilerplate code) but you can fix it if you add a reference when a ResourceFontFileStream
is given out by a COM method. This is how things are done normally in COM methods: when an out object is given back to the caller, the callee calls AddRef ()
on the object.
So, you can change the ResourceFontLoader.cs file, like this:
// this implements IDWriteFontFileLoader::CreateStreamFromKey https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritefontfileloader-createstreamfromkey
FontFileStream FontFileLoader.CreateStreamFromKey(DataPointer fontFileReferenceKey)
{
var index = Utilities.Read<int>(fontFileReferenceKey.Pointer);
_fontStreams[index].AddReference(); // add this line
return _fontStreams[index];
}