|
@@ -1,4 +1,5 @@
|
|
|
using System;
|
|
using System;
|
|
|
|
|
+using System.Linq;
|
|
|
using HarfBuzzSharp;
|
|
using HarfBuzzSharp;
|
|
|
using QuestPDF.Infrastructure;
|
|
using QuestPDF.Infrastructure;
|
|
|
using SkiaSharp;
|
|
using SkiaSharp;
|
|
@@ -9,14 +10,16 @@ namespace QuestPDF.Drawing
|
|
|
internal class TextShaper
|
|
internal class TextShaper
|
|
|
{
|
|
{
|
|
|
public const int FontShapingScale = 512;
|
|
public const int FontShapingScale = 512;
|
|
|
-
|
|
|
|
|
- private Font Font { get; }
|
|
|
|
|
- private SKPaint Paint { get; }
|
|
|
|
|
|
|
|
|
|
- public TextShaper(TextStyle style)
|
|
|
|
|
|
|
+ private TextStyle TextStyle { get; }
|
|
|
|
|
+
|
|
|
|
|
+ private SKFont Font => TextStyle.ToFont();
|
|
|
|
|
+ private Font ShaperFont => TextStyle.ToShaperFont();
|
|
|
|
|
+ private SKPaint Paint => TextStyle.ToPaint();
|
|
|
|
|
+
|
|
|
|
|
+ public TextShaper(TextStyle textStyle)
|
|
|
{
|
|
{
|
|
|
- Font = style.ToShaperFont();
|
|
|
|
|
- Paint = style.ToPaint();
|
|
|
|
|
|
|
+ TextStyle = textStyle;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public TextShapingResult Shape(string text)
|
|
public TextShapingResult Shape(string text)
|
|
@@ -26,7 +29,7 @@ namespace QuestPDF.Drawing
|
|
|
PopulateBufferWithText(buffer, text);
|
|
PopulateBufferWithText(buffer, text);
|
|
|
buffer.GuessSegmentProperties();
|
|
buffer.GuessSegmentProperties();
|
|
|
|
|
|
|
|
- Font.Shape(buffer);
|
|
|
|
|
|
|
+ ShaperFont.Shape(buffer);
|
|
|
|
|
|
|
|
var length = buffer.Length;
|
|
var length = buffer.Length;
|
|
|
var glyphInfos = buffer.GlyphInfos;
|
|
var glyphInfos = buffer.GlyphInfos;
|
|
@@ -52,6 +55,9 @@ namespace QuestPDF.Drawing
|
|
|
xOffset += glyphPositions[i].XAdvance * scaleX;
|
|
xOffset += glyphPositions[i].XAdvance * scaleX;
|
|
|
yOffset += glyphPositions[i].YAdvance * scaleY;
|
|
yOffset += glyphPositions[i].YAdvance * scaleY;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if (Settings.CheckIfAllTextGlyphsAreAvailableInSpecifiedFont)
|
|
|
|
|
+ CheckIfAllGlyphsAreAvailable(glyphs, text);
|
|
|
|
|
|
|
|
return new TextShapingResult(glyphs);
|
|
return new TextShapingResult(glyphs);
|
|
|
}
|
|
}
|
|
@@ -72,6 +78,20 @@ namespace QuestPDF.Drawing
|
|
|
else
|
|
else
|
|
|
throw new NotSupportedException("TextEncoding of type GlyphId is not supported.");
|
|
throw new NotSupportedException("TextEncoding of type GlyphId is not supported.");
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ void CheckIfAllGlyphsAreAvailable(ShapedGlyph[] glyphs, string originalText)
|
|
|
|
|
+ {
|
|
|
|
|
+ var containsMissingGlyphs = glyphs.Any(x => x.Codepoint == default);
|
|
|
|
|
+
|
|
|
|
|
+ if (!containsMissingGlyphs)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ throw new ArgumentException(
|
|
|
|
|
+ $"Detected missing font glyphs while rendering text. " +
|
|
|
|
|
+ $"This means that the document contains text with characters not present in the assigned font. " +
|
|
|
|
|
+ $"Such characters are replaced by placeholders, usually visible as empty rectangles. " +
|
|
|
|
|
+ $"Font family used: {TextStyle.FontFamily}. Issue detected in text: '{originalText}'");
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
internal struct ShapedGlyph
|
|
internal struct ShapedGlyph
|