Arithmetic operation resulted in an overflow
On .NET-Core 2.0 x64, I get "Arithmetic operation resulted in an overflow." on reading the ascender...
/// <summary>
/// Gets the ascender in 26.6 fractional pixels.
/// </summary>
/// <see cref="Face"/>
public Fixed26Dot6 Ascender
{
get
{
// Here => (int)
return Fixed26Dot6.FromRawValue((int)rec.ascender);
}
}
I don't get what you're doing there - casting an int64 to an int32 ? This can't work...
SharpFont.Native.Init();
SharpFont.Library lib = new SharpFont.Library();
SharpFont.Face fontFace = new SharpFont.Face(lib, @"C:\Windows\Fonts\tahoma.ttf");
float size = 12;
if (fontFace!= null)
// fontFace.SetCharSize(0, size, 0, 96);
fontFace.SetCharSize(size, size, 96, 96);
System.Console.WriteLine(fontFace.Size.Metrics.Ascender.ToDouble()); // kaboom...
System.Console.WriteLine(fontFace.Size.Metrics.Descender.ToSingle());
System.Console.WriteLine(fontFace.Size.Metrics.Height.ToSingle());
Dll's from SharpFont\Dependencies\freetype2\2.6-alldeps\msvc12\x64
namespace SharpFont
{
public class Native
{
public static void Init()
{
if (System.Environment.OSVersion.Platform == System.PlatformID.Unix)
return;
System.Reflection.Assembly ass = typeof(Native).Assembly;
string dir = System.IO.Path.GetDirectoryName(ass.Location);
int bitness = System.IntPtr.Size * 8;
string[] embeddedResources = ass.GetManifestResourceNames();
string freetypeLib = "freetype6.x86-" + bitness.ToString() + ".dll";
string fileName = System.IO.Path.Combine(dir, "freetype6.dll");
string found = null;
for (int i = 0; i < embeddedResources.Length; ++i)
{
if (embeddedResources[i].EndsWith(freetypeLib, System.StringComparison.OrdinalIgnoreCase))
{
found = embeddedResources[i];
break;
}
} // Next i
if (string.IsNullOrEmpty(found))
throw new System.Exception("Resource \"" + freetypeLib + "\"not found");
using (System.IO.Stream strm = ass.GetManifestResourceStream(found))
{
using (System.IO.Stream output = System.IO.File.Create(fileName))
{
strm.CopyTo(output);
} // End Using output
} // End Using strm
} // End Sub Init
} // End Class Native
} // End Namespace SharpFont
Note: On Linux with the same code, this runs just fine (font file path changed of course).
The types for 64 bit Windows are incorrect.
You have
using FT_Long = System.IntPtr;
using FT_ULong = System.UIntPtr;
But this should be
#if WINDOWS
using FT_Long = System.Int32;
using FT_ULong = System.UInt32;
#else
using FT_Long = System.IntPtr;
using FT_ULong = System.UIntPtr;
#endif
// https://www.freetype.org/freetype2/docs/reference/ft2-basic_types.html
// (freetype/fttypes.h).
// FT_ULong: typedef unsigned long FT_ULong;
// FT_Long: typedef signed long FT_Long;
// Size of 'long integer' data type (C++)
// on various architectures and OS
// Windows IA-32 4 bytes
// Windows Intel® 64 or IA-64 4 bytes
// Linux IA-32 4 bytes
// Linux Intel® 64 or IA-64 8 bytes
// Mac OS X IA-32 4 bytes
// Mac OS X Intel® 64 or IA-64 8 bytes
| size of ulong in bytes | x86-32 | x86-64 |
|---|---|---|
| Linux | 4 | 8 |
| Windows | 4 | 4 |
| MacOS | 4 | 8 |
It is complicated. Whereas what you are saying is strictly speak correct in the FreeType universe:
#if WINDOWS
using FT_Long = System.Int32;
using FT_ULong = System.UInt32;
#else
using FT_Long = System.IntPtr;
using FT_ULong = System.UIntPtr;
#endif
SharpFont suffers from some limitation from inconsistensies between C# and c-runtime on windows.
To work around that, a special build of freetype is needed, patched with
freetype2/win64.patch from http://github.com/Robmaister/SharpFont.Dependencies. Are you doing that, or are you using vanilla-built FreeType?
Yea, I noticed. It's impossible to create ONE cross-platform binary that way.
I used the exact BINARY version from SharpFont.Dependencies. Unless those aren't patched, it has these patches.
If those are patched, and you know they are working on x64 on Windows, then it is possible that some other program installed a version of freetype in PATH without me knowing about that, and that it's using that - dllmap doesn't work in .NET Core btw - yet another problem.
Hmm, you probably should do new Fixed26Dot6() like the SetCharSize() calls in https://github.com/HinTak/Font-Validator/blob/master/Compat/Compat.cs . I am not sure C# is clever enough to convert - probably not . The problem is that float is 32-bit wide but not actually in Fixed26Dot6 which is also 32-bit wide. So you could be calling SetCharSize with some insane values, which can result in overflow in Fixed26Dot6 operations. Nothing to do with SharpFont but FreeType telling you that you are sending insane values as inputs.
It has nothing to do with float - it fails on (int)rec.ascender casting an int64 to int32. Which might indicate the native dll hasn't fully been patched - some places left as is, and it reads the wrong data.
By using regex to replace your FT_Long with mine, and using an unpatched freetype version, it works. Though now I have to build with a define depending on target platform.
Just checked - there is no freetype.dll in PATH anywhere.
I don't have access to 64-bit windows machine at the moment, but with win64 mono under 64-bit wine, I get same answer under win64 as under x86_64 linux, which is
17
-4
19
Granted I am using the freetype dll's I built though. You can have a go, grabbing the whole directory of https://github.com/HinTak/Font-Validator/tree/master/bin/Win64 . (it is built with mingw so have different dependencies; also I use a slightly larger win64 patch than freetype2/win64.patch from http://github.com/Robmaister/SharpFont.Dependencies ).
FWIW, I am trying to look at https://github.com/HinTak/Font-Validator/issues/27 , for my own purposes.
I have same problem.
when the following code is executed, the same exception Arithmetic operation resulted in an overflow is thrown.
float gAdvanceX = (float) face.Glyph.Advance.X; // same as the advance in metrics