diff --git a/src/UglyToad.PdfPig/Content/ResourceStore.cs b/src/UglyToad.PdfPig/Content/ResourceStore.cs
index a65347ec2..be75fa0be 100644
--- a/src/UglyToad.PdfPig/Content/ResourceStore.cs
+++ b/src/UglyToad.PdfPig/Content/ResourceStore.cs
@@ -232,7 +232,12 @@ private void LoadFontDictionary(DictionaryToken fontDictionary)
try
{
- loadedFonts[reference] = fontFactory.Get(fontObject);
+ var loadedFont = fontFactory.Get(fontObject);
+ // Stamp the font dictionary's indirect reference so consumers can
+ // distinguish same-named fonts (e.g. two subsets of one typeface
+ // embedded without unique subset prefixes). See FontDetails.FontDictionaryReference.
+ loadedFont.Details?.SetFontDictionaryReference(reference);
+ loadedFonts[reference] = loadedFont;
}
catch
{
@@ -286,6 +291,8 @@ public IFont GetFontDirectly(IndirectReferenceToken fontReferenceToken)
var font = fontFactory.Get(fontDictionaryToken);
+ font.Details?.SetFontDictionaryReference(fontReferenceToken.Data);
+
return font;
}
diff --git a/src/UglyToad.PdfPig/PdfFonts/FontDetails.cs b/src/UglyToad.PdfPig/PdfFonts/FontDetails.cs
index bd6066719..1a289e481 100644
--- a/src/UglyToad.PdfPig/PdfFonts/FontDetails.cs
+++ b/src/UglyToad.PdfPig/PdfFonts/FontDetails.cs
@@ -1,5 +1,7 @@
namespace UglyToad.PdfPig.PdfFonts
{
+ using Core;
+
///
/// Summary details of the font used to draw a glyph.
///
@@ -35,6 +37,16 @@ public sealed class FontDetails
///
public bool IsItalic { get; }
+ ///
+ /// The indirect reference of the font dictionary this font was loaded from,
+ /// when it was loaded from an indirect object. Uniquely identifies the font
+ /// within its source document even when multiple font objects share the same
+ /// name (e.g. two different subsets of one typeface embedded without unique
+ /// subset prefixes). null for fonts defined directly inside a resource
+ /// dictionary (no indirect object) or for synthetic/fallback fonts.
+ ///
+ public IndirectReference? FontDictionaryReference { get; private set; }
+
private readonly Lazy _bold;
///
@@ -47,7 +59,14 @@ public FontDetails(string? name, bool isBold, int weight, bool isItalic)
Weight = weight;
IsItalic = isItalic;
- _bold = isBold ? new Lazy(() => this) : new Lazy(() => new FontDetails(Name, true, Weight, IsItalic));
+ // Evaluated lazily so a FontDictionaryReference assigned after construction
+ // still propagates to the bold variant.
+ _bold = isBold
+ ? new Lazy(() => this)
+ : new Lazy(() => new FontDetails(Name, true, Weight, IsItalic)
+ {
+ FontDictionaryReference = FontDictionaryReference
+ });
}
///
@@ -66,8 +85,30 @@ public FontDetails AsBold()
internal FontDetails WithName(string? name) => name is not null
? new FontDetails(name, IsBold, Weight, IsItalic)
+ {
+ FontDictionaryReference = FontDictionaryReference
+ }
: this;
+ ///
+ /// Record the indirect reference of the font dictionary this font was loaded from.
+ /// Called by the resource system immediately after font construction; assigning the
+ /// same value again is a no-op.
+ ///
+ internal void SetFontDictionaryReference(IndirectReference reference)
+ {
+ FontDictionaryReference = reference;
+
+ // Propagate to an already-materialized bold variant. The bold Lazy caches its
+ // value, so a variant created before this stamp would otherwise keep a stale
+ // null reference forever. (A not-yet-materialized variant picks the reference
+ // up at evaluation time via the initializer closure.)
+ if (_bold.IsValueCreated && !ReferenceEquals(_bold.Value, this))
+ {
+ _bold.Value.SetFontDictionaryReference(reference);
+ }
+ }
+
///
public override string ToString()
{