Skip to content

Commit b328565

Browse files
Fix cache and drawing OOBE
1 parent 0b7e559 commit b328565

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,14 @@ void Draw(IEnumerable<DrawingOperation> operations)
9393
firstRow = -startY;
9494
}
9595

96+
int maxWidth = source.Width - startX;
9697
int maxHeight = source.Height - startY;
9798
int end = Math.Min(operation.Map.Height, maxHeight);
9899

99100
for (int row = firstRow; row < end; row++)
100101
{
101102
int y = startY + row;
102-
Span<float> span = buffer.DangerousGetRowSpan(row).Slice(offsetSpan, Math.Min(buffer.Width - offsetSpan, source.Width));
103+
Span<float> span = buffer.DangerousGetRowSpan(row).Slice(offsetSpan, Math.Min(buffer.Width - offsetSpan, maxWidth));
103104
app.Apply(span, startX, y);
104105
}
105106
}

src/ImageSharp.Drawing/Processing/Processors/Text/RichTextGlyphRenderer.cs

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Runtime.CompilerServices;
66
using SixLabors.Fonts;
77
using SixLabors.Fonts.Rendering;
8+
using SixLabors.Fonts.Unicode;
89
using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing;
910
using SixLabors.ImageSharp.Drawing.Shapes.Rasterization;
1011
using SixLabors.ImageSharp.Drawing.Text;
@@ -41,12 +42,12 @@ internal sealed partial class RichTextGlyphRenderer : BaseGlyphBuilder, IDisposa
4142
// - Provide a good accuracy (smaller than 0.2% image difference compared to the non-caching variant)
4243
// - Cache hit ratio above 60%
4344
private const float AccuracyMultiple = 8;
44-
private readonly Dictionary<(GlyphRendererParameters Glyph, RectangleF Bounds), List<GlyphRenderData>> glyphCache = [];
45+
private readonly Dictionary<CacheKey, List<GlyphRenderData>> glyphCache = [];
4546
private int cacheReadIndex;
4647

4748
private bool rasterizationRequired;
4849
private readonly bool noCache;
49-
private (GlyphRendererParameters Glyph, RectangleF Bounds) currentCacheKey;
50+
private CacheKey currentCacheKey;
5051

5152
public RichTextGlyphRenderer(
5253
RichTextOptions textOptions,
@@ -128,7 +129,7 @@ protected override void BeginGlyph(in FontRectangle bounds, in GlyphRendererPara
128129
MathF.Round(currentBounds.Width * AccuracyMultiple) / AccuracyMultiple,
129130
MathF.Round(currentBounds.Height * AccuracyMultiple) / AccuracyMultiple);
130131

131-
this.currentCacheKey = (parameters, new RectangleF(subPixelLocation, subPixelSize));
132+
this.currentCacheKey = CacheKey.FromParameters(parameters, new RectangleF(subPixelLocation, subPixelSize));
132133
if (this.glyphCache.ContainsKey(this.currentCacheKey))
133134
{
134135
// We have already drawn the glyph vectors.
@@ -588,7 +589,7 @@ private void Dispose(bool disposing)
588589
{
589590
if (disposing)
590591
{
591-
foreach (KeyValuePair<(GlyphRendererParameters Glyph, RectangleF Bounds), List<GlyphRenderData>> kv in this.glyphCache)
592+
foreach (KeyValuePair<CacheKey, List<GlyphRenderData>> kv in this.glyphCache)
592593
{
593594
foreach (GlyphRenderData data in kv.Value)
594595
{
@@ -624,4 +625,49 @@ public readonly void Dispose()
624625
this.OutlineMap?.Dispose();
625626
}
626627
}
628+
629+
private readonly struct CacheKey
630+
{
631+
public string Font { get; init; }
632+
633+
public GlyphColor GlyphColor { get; init; }
634+
635+
public GlyphType GlyphType { get; init; }
636+
637+
public FontStyle FontStyle { get; init; }
638+
639+
public ushort GlyphId { get; init; }
640+
641+
public ushort CompositeGlyphId { get; init; }
642+
643+
public CodePoint CodePoint { get; init; }
644+
645+
public float PointSize { get; init; }
646+
647+
public float Dpi { get; init; }
648+
649+
public GlyphLayoutMode LayoutMode { get; init; }
650+
651+
public TextRun TextRun { get; init; }
652+
653+
public RectangleF Bounds { get; init; }
654+
655+
public static CacheKey FromParameters(in GlyphRendererParameters parameters, RectangleF bounds)
656+
=> new()
657+
{
658+
// Our caching does not need the grapheme index as that is only relevant to the text layout.
659+
Font = parameters.Font,
660+
GlyphColor = parameters.GlyphColor,
661+
GlyphType = parameters.GlyphType,
662+
FontStyle = parameters.FontStyle,
663+
GlyphId = parameters.GlyphId,
664+
CompositeGlyphId = parameters.CompositeGlyphId,
665+
CodePoint = parameters.CodePoint,
666+
PointSize = parameters.PointSize,
667+
Dpi = parameters.Dpi,
668+
LayoutMode = parameters.LayoutMode,
669+
TextRun = parameters.TextRun,
670+
Bounds = bounds
671+
};
672+
}
627673
}

0 commit comments

Comments
 (0)