Skip to content

Commit b716ed9

Browse files
authored
fix(high-memory-usage): reuse SKTypeface to avoid high memory usage (#20 #21)
1 parent 4e82bcc commit b716ed9

File tree

3 files changed

+13
-29
lines changed

3 files changed

+13
-29
lines changed

src/Captcha.Core/Constants.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,17 @@ public static class Constants
1010
public const int DefaultCaptchaHeight = 100;
1111
public const float DefaultFrequency = 100F;
1212
public const int FrequencyScalingFactor = 40000; // on a 400 x 100 image
13-
public const string DefaultCaptchaFontName = "Captcha.Core.Resources.Fonts.Caveat-SemiBold.ttf";
14-
public const string DefaultCaptchaFallbackFontName = "Captcha.Core.Resources.Fonts.Unifont.ttf";
1513
public static readonly SKColor DefaultPrimaryColor = SKColor.Parse("FFD3D3D3");
1614
public static readonly SKColor DefaultSecondaryColor = SKColor.Parse("FFFFFFFF");
1715
public const string CaptchaContentType = "image/jpeg";
1816
public const float WarpCaptchaTextFrequency = 4F;
1917
public const int CaptchaNoise = 50;
18+
19+
// According to https://learn.microsoft.com/en-us/dotnet/api/skiasharp.sktypeface, this should be thread-safe
20+
public static SKTypeface MainFontTypeface { get; } =
21+
SKTypeface.FromStream(typeof(Constants).Assembly.GetManifestResourceStream("Captcha.Core.Resources.Fonts.Caveat-SemiBold.ttf"));
22+
23+
// According to https://learn.microsoft.com/en-us/dotnet/api/skiasharp.sktypeface, this should be thread-safe
24+
public static SKTypeface FallbackFontTypeface { get; } =
25+
SKTypeface.FromStream(typeof(Constants).Assembly.GetManifestResourceStream("Captcha.Core.Resources.Fonts.Unifont.ttf"));
2026
}

src/Captcha.Core/Services/CaptchaImageService.cs

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,6 @@ namespace Captcha.Core.Services;
66

77
public class CaptchaImageService : ICaptchaImageService
88
{
9-
private readonly SKTypeface _mainFontTypeface;
10-
private readonly SKTypeface _fallbackFontTypeface;
11-
12-
public CaptchaImageService()
13-
{
14-
var assembly = typeof(CaptchaImageService).Assembly;
15-
16-
_mainFontTypeface = SKTypeface.FromStream(
17-
assembly.GetManifestResourceStream(Constants.DefaultCaptchaFontName)
18-
);
19-
20-
_fallbackFontTypeface = SKTypeface.FromStream(
21-
assembly.GetManifestResourceStream(Constants.DefaultCaptchaFallbackFontName)
22-
);
23-
}
24-
259
public SKBitmap CreateCaptchaImage(CaptchaConfigurationData config)
2610
{
2711
var bitmap = new SKBitmap(new SKImageInfo(config.Width, config.Height));
@@ -89,7 +73,7 @@ private static void DrawWarpedText(CaptchaConfigurationData config, SKFont font,
8973
graphics.DrawPath(path, fillPaint);
9074
}
9175

92-
private SKFont GetFontThatFitsRectangle(CaptchaConfigurationData config, SKRect rectangle)
76+
private static SKFont GetFontThatFitsRectangle(CaptchaConfigurationData config, SKRect rectangle)
9377
{
9478
var typeface = GetTypefaceThatCanRenderText(config.Text);
9579

@@ -123,16 +107,16 @@ private static void FillInTheBackground(CaptchaConfigurationData config, SKRect
123107
graphics.DrawRect(rectangle, paint);
124108
}
125109

126-
private SKTypeface GetTypefaceThatCanRenderText(string text)
110+
private static SKTypeface GetTypefaceThatCanRenderText(string text)
127111
{
128-
using var mainFont = new SKFont(_mainFontTypeface);
112+
using var mainFont = new SKFont(Constants.MainFontTypeface);
129113

130114
if (mainFont.ContainsGlyphs(text))
131115
{
132-
return _mainFontTypeface;
116+
return Constants.MainFontTypeface;
133117
}
134118

135-
return _fallbackFontTypeface;
119+
return Constants.FallbackFontTypeface;
136120
}
137121

138122
/// <summary>

tests/Captcha.UnitTests/ConstantsTests.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@ public class ConstantsTests
2222
[Test]
2323
public void DefaultFrequencyShouldBe100() => Assert.That(Constants.DefaultFrequency, Is.EqualTo(100F));
2424

25-
[Test]
26-
public void DefaultCaptchaFontNameShouldBeCaveat() => Assert.That(Constants.DefaultCaptchaFontName, Is.EqualTo("Captcha.Core.Resources.Fonts.Caveat-SemiBold.ttf"));
27-
28-
[Test]
29-
public void FallbackCaptchaFontNameShouldBeUnifont() => Assert.That(Constants.DefaultCaptchaFallbackFontName, Is.EqualTo("Captcha.Core.Resources.Fonts.Unifont.ttf"));
30-
3125
[Test]
3226
public void DefaultPrimaryColorShouldBeDarkGray() => Assert.That(Constants.DefaultPrimaryColor, Is.EqualTo(SKColor.Parse("FFD3D3D3")));
3327

0 commit comments

Comments
 (0)