SixLabors / Fonts

:black_nib: Font loading and layout library.
https://sixlabors.com/products/fonts
Other
305 stars 69 forks source link

Support Brazilian portuguese accents #20

Closed zogbi closed 6 years ago

zogbi commented 7 years ago

I have an issue when i use words with accents on azure app service.

When i use word with accent, like á é í ó ú ç ã õ, i receive an error: Object reference not set to an instance of an object

i try to use font family like Arial and Comic Sans, and problem still happen.

if i remove all accents, all error desapear.

tocsoft commented 7 years ago

I don't seem to be able to reproduce your error. 😞 a e i o u c a o

Can you write a minimal test case that reproduces your issues? Please also let me know what versions of libraries your using.

tocsoft commented 7 years ago

I've just realised that my current alpha was a little out of date, can you try upgrading your SixLabors.Fonts package to version 0.1.0-alpha0003 and see if that fixes it for you.

zogbi commented 7 years ago

This is our code:

` var fontFamily = FontCollection.SystemFonts.Find(textOverlay.FontFamily.ToString());

            var style = FontStyle.Regular;

            if (textOverlay.IsBold)
                style = FontStyle.Bold;

            if (textOverlay.IsItalic)
                style = FontStyle.Italic;

            if (textOverlay.IsBold && textOverlay.IsItalic)
                style = FontStyle.BoldItalic;

            var font = new Font(fontFamily, textOverlay.FontSize, style);

            var location = new HalfVector2(textOverlay.X, textOverlay.Y);

            var color = new Color(textOverlay.FontColorRed, textOverlay.FontColorGreen, textOverlay.FontColorBlue, textOverlay.FontColorAlpha);

            image.DrawText(textOverlay?.Content ?? "", font, color, location.ToVector2());`

This is our packages:

Include="SixLabors.Fonts" Version="0.1.0-ci0050"

`

<PackageReference Include="CoreCompat.System.Drawing" Version="1.0.0-beta006" />
<PackageReference Include="ImageSharp" Version="1.0.0-alpha5-00059" />
<PackageReference Include="ImageSharp.Drawing" Version="1.0.0-alpha5-00053" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.1" />
<PackageReference Include="Microsoft.NETCore.App" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Routing" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.1" />
<PackageReference Include="NLog" Version="5.0.0-beta06" />
**<PackageReference Include="SixLabors.Fonts" Version="0.1.0-ci0050" />**
<PackageReference Include="System.Text.Encoding" Version="4.3.0" />

`

tocsoft commented 7 years ago

Looks like you updated ImageSharp and SixLabors.Fonts half way through me accidentally breaking the public API there (the break shouldn't effect the null reference but might effect the position of the rendering).

So first can you update all three, ImageSharp, ImageSharp.Drawing and SixLabors.Fonts, to their latest versions for me, sorry about that.

And secondly can you refactor your code sample into a simple, self contained, test case for me? at the moment I can't grab your code and just run it to reproduce the exception. (something I can copy and paste into a console app and causes the error would be wonderful)

Also if you can give me the the details from the exception, stacktrace etc, that would also help me track down the null value.

zogbi commented 7 years ago

Sorry to delay answer.

We have updated all three packages before do a new test and the problem still happen.

Follow below our code.

'using ImageSharp; using System.IO; using ImageSharp.Formats; using System.Collections.Generic; using System.Linq; using ImageSharp.Drawing; using SixLabors.Fonts; using ImageSharp.Drawing.Pens; using System; using System.Diagnostics; using System.Globalization; using System.Text;

namespace ImageTest { static class Program { static void Main(string[] args) { ProcessImage("success text");

        try
        {
            ProcessImage("error téxt");

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    private static void AddText(this Image image, string text)
    {

        var fontFamily = FontCollection.SystemFonts.Find("Arial");

        var style = FontStyle.Regular;

        var font = new Font(fontFamily, 30, style);

        var location = new HalfVector2(20, 20);

        var color = new Color(0, 0, 0, 90);

        image.DrawText(text, font, color, location.ToVector2());
    }

    private static void AddBg(this Image image)
    {
        var size = new ImageSharp.Size(800, 600);
        var imageOv = Image.Load($"{Directory.GetCurrentDirectory()}\\bg.jpg");

        imageOv.Resize(new ImageSharp.Processing.ResizeOptions()
        {
            Size = size,
            Mode = ImageSharp.Processing.ResizeMode.Crop
        });

        var location = new HalfVector2(0, 0);
        var point = new Point(location.ToVector2());

        image.DrawImage(imageOv, 100, size, point);
    }

    public static void ProcessImage(string text)
    {
        var config = new Configuration();
        config.AddImageFormat(new JpegFormat());
        config.AddImageFormat(new PngFormat());

        using (var image = new Image(800, 600, config))
        {
            image.AddBg();
            image.AddText(text);

            image.Save($"{Directory.GetCurrentDirectory()}\\{text}.jpg");
        }
    }
}

}'

tocsoft commented 7 years ago

nope sorry that code works perfectly on my machine... 😞

I'm going to need the stack traces & messages of the exception, (including any inner-exceptions).

On a side note you don't want to be using the HalfVector2 type for locations just use System.Numerics.Vector2 directly.

kmr299 commented 7 years ago

I tested the code in the azure app and this error happened:

System.NullReferenceException: Object reference not set to an instance of an object. at SixLabors.Fonts.Tables.General.Glyphs.CompositeGlyphLoader.CreateGlyph(GlyphTable table) at SixLabors.Fonts.Tables.General.GlyphTable.GetGlyph(Int32 index) at SixLabors.Fonts.FontInstance.GetGlyph(Char character) at SixLabors.Fonts.FileFontInstance.GetGlyph(Char character) at SixLabors.Fonts.TextLayout.GenerateLayout(String text, FontSpan style) at SixLabors.Fonts.TextRenderer.RenderText(String text, FontSpan style, Vector2 location) at ImageSharp.ImageExtensions.DrawText[TPixel](Image1 source, String text, Font font, IBrush1 brush, IPen1 pen, Vector2 location, TextGraphicsOptions options) at ImageSharp.ImageExtensions.DrawText[TPixel](Image1 source, String text, Font font, TPixel color, Vector2 location) at MSE.Business.Image.ImageProccessBusiness.AddText(Image image, OverlayText textOverlay) in D:\Desenvolvimento\MK\mobile-service\MSE\MSE.Business\Image\ImageProccessBusiness.cs:line 60 at MSE.Business.Image.ImageProccessBusiness.ProcessImage(Int32 width, Int32 height, OverlayText[] textOverlays, OverlayImage[] imageOverlays) in D:\Desenvolvimento\MK\mobile-service\MSE\MSE.Business\Image\ImageProccessBusiness.cs:line 113 at MSE.Business.Notifications.NotificationConsultantBusiness.<GenerateSkinAsync>d__10.MoveNext() in D:\Desenvolvimento\MK\mobile-service\MSE\MSE.Business\Notifications\NotificationConsultantBusiness.cs:line 320 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at MSE.Service.Controllers.NotificationController.d9.MoveNext() in D:\Desenvolvimento\MK\mobile-service\MSE\MSE.Service\Controllers\NotificationController.cs:line 135 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d27.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d25.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d22.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ResourceExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d20.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Builder.RouterMiddleware.d4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.<Invoke>d__18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.d4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.d8.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.d3.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame1.<RequestProcessingAsync>d__2.MoveNext()

tocsoft commented 7 years ago

That's really strange, I can't see how the code anywhere around there could throw null reference exceptions... Could you please provide the actual font file that the your using... seems there is some differences between the version of Arial I've got on my machine and the one causing you issues.

kmr299 commented 7 years ago

My code is the same as Zogbi is using. The weirdest part is that on my machine it works but on azurewebapp it does not. I think it should be something with regard to installing windows server that runs on azurewebapp. I stress that the installed version is the server core that has no GUI and support of some windows APIs. I have backends with libs to generate PDFs that do not work in this environment because most libs use GDI + for example.

I have already tried doing the same work with Comic Sans and the same error occurs.

And sorry for my bad English ...

tocsoft commented 7 years ago

Ok can you try using the local your local version of the font (just copy out of your local fonts directory) and load it into a custom FontCollection instead of using the the FontCollection.SystemFonts property.

instead of using

var fontFamily = FontCollection.SystemFonts.Find("Arial");

do

// the next 2 lines should be done in some global location
// and passed as a singleton as loading fonts is expensive.
var collection = new FontCollection();
collection.Install("path/to/copy/of/Arial.ttf");
// now  you can use `collection`  instead of `FontCollection.SystemFonts`
var fontFamily = collection.Find("Arial");

Personally I would never use copies of fonts that come installed on a server, for exactly these reasons, the fonts used are state that your application depends on so ship that dependency with your app so your not dependent on some OS update breaking you in unexpected ways.

kmr299 commented 7 years ago

Good night, I may have found the problem. I made a gitclone of your code and everything worked as it should. I updated your lib to version xxxx and tried to execute the following code: font.GetGlyph('á'); This code fires for the exception: System.NullReferenceException: Object reference not set to an instance of an object. at SixLabors.Fonts.Tables.General.Glyphs.CompositeGlyphLoader.CreateGlyph(GlyphTable table) at SixLabors.Fonts.Tables.General.GlyphTable.GetGlyph(Int32 index) at SixLabors.Fonts.FontInstance.GetGlyph(Char character) at SixLabors.Fonts.Font.GetGlyph(Char character) at MSE.Business.Image.ImageProccessBusiness.AddText(Image1 image, OverlayText textOverlay) in D:\Desenvolvimento\MK\mobile-service\MSE\MSE.Business\Image\ImageProccessBusiness.cs:line 71 If it is used: font.GetGlyph('a')` Run normally.

I'm going to design the project as a reference instead of installing via nuget for now, because this way it worked normally. Here is the complete exception when you run image.DrawText (): System.NullReferenceException: Object reference not set to an instance of an object. at SixLabors.Fonts.Tables.General.Glyphs.CompositeGlyphLoader.CreateGlyph(GlyphTable table) at SixLabors.Fonts.Tables.General.GlyphTable.GetGlyph(Int32 index) at SixLabors.Fonts.FontInstance.GetGlyph(Char character) at SixLabors.Fonts.TextLayout.GenerateLayout(String text, FontSpan style) at SixLabors.Fonts.TextRenderer.RenderText(String text, FontSpan style, Vector2 location) at ImageSharp.ImageExtensions.DrawText[TPixel](Image1 source, String text, Font font, IBrush1 brush, IPen1 pen, Vector2 location, TextGraphicsOptions options) at ImageSharp.ImageExtensions.DrawText[TPixel](Image1 source, String text, Font font, TPixel color, Vector2 location, TextGraphicsOptions options) at MSE.Business.Image.ImageProccessBusiness.AddText(Image1 image, OverlayText textOverlay) in D:\Desenvolvimento\MK\mobile-service\MSE\MSE.Business\Image\ImageProccessBusiness.cs:line 103 at MSE.Business.Image.ImageProccessBusiness.ProcessImage(Int32 width, Int32 height, OverlayText[] textOverlays, OverlayImage[] imageOverlays) in D:\Desenvolvimento\MK\mobile-service\MSE\MSE.Business\Image\ImageProccessBusiness.cs:line 158 at MSE.Business.Notifications.NotificationConsultantBusiness.d10.MoveNext() in D:\Desenvolvimento\MK\mobile-service\MSE\MSE.Business\Notifications\NotificationConsultantBusiness.cs:line 341 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at MSE.Service.Controllers.NotificationController.d9.MoveNext() in D:\Desenvolvimento\MK\mobile-service\MSE\MSE.Service\Controllers\NotificationController.cs:line 135 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__27.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__25.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextResourceFilter>d__22.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ResourceExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeAsync>d__20.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.d4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.d8.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.d3.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame`1.d2.MoveNext()`

tocsoft commented 7 years ago

Closing this, as without being given the problematic font file I can't do much to fix this.

rhegner commented 7 years ago

I'm experiencing the same problem with German umlauts ('ä' for example). It works fine on my Windows 10 development machine, but on some other machine (Windows 7) I get a similar exception.

I created a minimal test program (with an embedded font) which reproduces the problem. The test program basically just tries to measure the size of a string containing umlauts. You can find the sources of that test program here.

I noticed some problems with character encoding, that's why the program accepts a command line parameter which determines how to handle encoding.

Here is the output of the program on my development machine:

>dotnet LocalizedFontTest.dll none
The output encoding of the console is Unicode (UTF-8)
This tool measures the size of 'Mobilitätsanalyse'
Size of text 'Mobilitätsanalyse' is 132.5078x17.11719

Press Enter to exit...

>dotnet LocalizedFontTest.dll utf8
The output encoding of the console is Unicode (UTF-8)
This tool measures the size of 'Mobilitätsanalyse'
Size of text 'Mobilitätsanalyse' is 132.5078x17.11719

Press Enter to exit...

>dotnet LocalizedFontTest.dll cpep
The output encoding of the console is Unicode (UTF-8)
This tool measures the size of 'Mobilitätsanalyse'
Size of text 'Mobilitätsanalyse' is 132.5078x17.11719

Press Enter to exit...

On the other machine, the output is this:

>dotnet LocalizedFontTest.dll none
The output encoding of the console is Unicode (UTF-8)
This tool measures the size of 'Mobilitätsanalyse'
TextMeasurer.Measure failed with
System.NullReferenceException: Object reference not set to an instance of an obj
ect.
   at SixLabors.Fonts.Tables.General.Glyphs.CompositeGlyphLoader.CreateGlyph(Gly
phTable table)
   at SixLabors.Fonts.Tables.General.GlyphTable.GetGlyph(Int32 index)
   at SixLabors.Fonts.FontInstance.GetGlyph(Char character)
   at SixLabors.Fonts.TextLayout.GenerateLayout(String text, RendererOptions opt
ions)
   at SixLabors.Fonts.TextMeasurer.TextMeasurerInt.Measure(String text, Renderer
Options options)
   at LocalizedFontTest.Program.Main(String[] args) in C:\Robert\CCMCMService\Te
stProjects\LocalizedFontTest\Program.cs:line 37

>dotnet LocalizedFontTest.dll utf8
The output encoding of the console is Unicode (UTF-8)
This tool measures the size of 'Mobilitätsanalyse'
TextMeasurer.Measure failed with
System.NullReferenceException: Object reference not set to an instance of an obj
ect.
   at SixLabors.Fonts.Tables.General.Glyphs.CompositeGlyphLoader.CreateGlyph(Gly
phTable table)
   at SixLabors.Fonts.Tables.General.GlyphTable.GetGlyph(Int32 index)
   at SixLabors.Fonts.FontInstance.GetGlyph(Char character)
   at SixLabors.Fonts.TextLayout.GenerateLayout(String text, RendererOptions opt
ions)
   at SixLabors.Fonts.TextMeasurer.TextMeasurerInt.Measure(String text, Renderer
Options options)
   at LocalizedFontTest.Program.Main(String[] args) in C:\Robert\CCMCMService\Te
stProjects\LocalizedFontTest\Program.cs:line 37

>dotnet LocalizedFontTest.dll cpep
The output encoding of the console is Unicode (UTF-8)
This tool measures the size of 'Mobilitätsanalyse'
TextMeasurer.Measure failed with
System.NullReferenceException: Object reference not set to an instance of an obj
ect.
   at SixLabors.Fonts.Tables.General.Glyphs.CompositeGlyphLoader.CreateGlyph(Gly
phTable table)
   at SixLabors.Fonts.Tables.General.GlyphTable.GetGlyph(Int32 index)
   at SixLabors.Fonts.FontInstance.GetGlyph(Char character)
   at SixLabors.Fonts.TextLayout.GenerateLayout(String text, RendererOptions opt
ions)
   at SixLabors.Fonts.TextMeasurer.TextMeasurerInt.Measure(String text, Renderer
Options options)
   at LocalizedFontTest.Program.Main(String[] args) in C:\Robert\CCMCMService\Te
stProjects\LocalizedFontTest\Program.cs:line 37

Note that on this second machine, with none of the 3 options for encoding, the word 'Mobilitätsanalyse' is printed correctly. I think this is only a problem of the console output. But I'm not sure. It might also give a hint of what goes wrong in the fonts library.

tocsoft commented 7 years ago

@rhegner 👍 thanks for the reproduction.

I'll try and get a chance to look over it soon... can't think what could cause the issue seeing as your using a local font file.

rhegner commented 7 years ago

Yeah I already spent quite some time trying to debug this... The behavior really doesn't make much sense to me...

kmr299 commented 7 years ago

I solved the problem as follows: 1 - I downloaded the project on github 2 - I removed the nuget package from my application 3 - I added the project as reference 4 - and published my api in debug mode

While I do not have a solution to this problem, I'm using it this way. A test you can do to find the error in the code is to run on your machine in release mode.

alizim commented 7 years ago

I had the same Issue with German umlauts. The Problem occures only in ReleaseMode. The System.NullReferenceException is thrown in the foreach-loop in CompositeGlyphLoader.CreateGlyph

        foreach (Composite composite in this.result)
        {...

I changed it to foreach (Composite composite in this.result.ToArray()) {... and all works fine, also it doesn't make sense to me

tocsoft commented 7 years ago

thanks for that ... i'm guessing there must be some bug somewhere in the .net jitter that I must be hitting. I'll see what impacts the just adding the ToArray will cause but hopefully we should be able to get a fix out soon.

alizim commented 7 years ago

I have another possible fix: This morning i changed Composite from class to struct --> this seems to work too

dlemstra commented 7 years ago

I tried to reproduce this issue on a Windows 7, Windows 10 and Linux machine but I was unable to reproduce the issue. I really wonder what kind of machine setup we need to reproduce this issue.

tocsoft commented 7 years ago

I've added a commit to master that that converts the result to an array to see if that sorts it... will sort out a fresh release soon

rhegner commented 6 years ago

I updated my project to use SixLabors.ImageSharp.Drawing v1.0.0-beta0001 and we can't reproduce the problem anymore.

tocsoft commented 6 years ago

awesome 👍