You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fixes the still-broken half of the beta.7 real-world glyph-gap report: /Differences arrays naming a ligature glyph via the Adobe Glyph List's
underscore ligature-naming convention (f_i, f_l, f_f, f_f_i, f_f_l - two or more component glyph names joined by underscores) were
left unresolved, so the affected glyphs rendered as missing/tofu boxes
even though StandardGlyphNames already had a dedicated codepoint for
the same ligature under its own AGL name (fi, fl, ff, ffi, ffl). PR #35 already fixed the non-ligature uniXXXX/thinspace
half of this report; this closes the remaining gap.
Adds TryResolveLigatureUnderscoreName: resolves each underscore-
separated component recursively (so a component may itself use the uniXXXX/uXXXX hex convention), concatenates the resolved characters,
and looks the concatenated string up as an AGL glyph name in StandardGlyphNames.
The existing real-world text-type1c-differences-agl-ligatures.pdf
fixture already exercised an /f_f ligature in its content stream
(previously documented as a deliberate, out-of-scope limitation); it
now resolves and paints correctly, proving the fix against both a
synthetic regression test and a genuine real-world embedded font.
Type of Change
Bug fix (non-breaking change which fixes an issue)
New feature (non-breaking change which adds functionality)
Breaking change (fix or feature that would cause existing functionality to not work as expected)
Documentation update
Code quality improvement
Related Issues
Closes #
Pre-Submission Checklist
Build and Test
Code builds successfully and all tests pass: pwsh ./build.ps1 - all tests passed, 0 failures, 0 regressions
Code produces zero warnings
Code Quality
New code has appropriate XML documentation comments
Static analyzer warnings have been addressed
Quality Checks
All linters pass: pwsh ./lint.ps1 - clean (markdownlint, cspell, yamllint, dotnet format, reqstream, versionmark, reviewmark, sysml2tools)
Testing
Added unit tests for new functionality (f_i/f_l/f_f/f_f_i/f_f_l resolving end-to-end against an embedded Type1C font, plus an unrecognized-underscore-name fallback case)
Updated existing tests if behavior changed (fixture README/test remarks updated to reflect the formerly out-of-scope /f_f case now resolving)
All tests follow the AAA (Arrange, Act, Assert) pattern
Test coverage is maintained or improved
Documentation
Updated README.md (if applicable) - N/A, no end-user-visible API change
Updated docs/ documentation (reqstream/verification docs and fixture README updated)
Added code examples for new features (if applicable) - N/A
Updated requirements.yaml (if applicable) - N/A, no new top-level requirement; extends existing FontEncoding/Type1CFontResolution requirements
Additional Notes
Follow-up to PR #35 (PDF Type1C/Differences glyph lookup). Queued behind the PPTX Phase 1a-1d work per explicit sequencing instruction.
/Differences arrays naming a ligature glyph via the Adobe Glyph List's
underscore ligature-naming convention (two or more component glyph names
joined by underscores, e.g. f_i for the "fi" ligature) previously left
that code unresolved: neither StandardGlyphNames nor the uniXXXX/uXXXX
hex fallback recognized the underscore-joined spelling, so the affected
glyph rendered as a tofu box even though StandardGlyphNames already had
a dedicated codepoint for the same ligature under its AGL name (fi, fl,
ff, ffi, ffl).
Real-world PDF producers (XeTeX/LuaTeX-derived toolchains in particular)
routinely spell a subsetted font's own ligature glyphs this way. This
was the still-broken half of the beta.7 glyph-gap report on
BR_Cavro_Air_Displacement_Pipettor_396359.pdf pages 4-6 (/fi, /fl, /f_f
ligatures); the non-ligature uniXXXX/thinspace half was already fixed.
Adds TryResolveLigatureUnderscoreName: resolves each underscore-separated
component recursively (so a component may itself use the uniXXXX/uXXXX
hex convention), concatenates the resolved characters, and looks the
concatenated string up as an AGL glyph name in StandardGlyphNames.
The existing real-world text-type1c-differences-agl-ligatures.pdf
fixture already exercised an /f_f ligature in its content stream
(previously documented as a deliberate, out-of-scope limitation); it now
resolves and paints correctly, so this fix is proven against both a
synthetic regression test and a genuine real-world embedded font.
Adds regression tests (f_i/f_l/f_f/f_f_i/f_f_l resolving end-to-end
against an embedded Type1C font, plus an unrecognized-underscore-name
fallback case) and updates the FontEncoding/Type1CFontResolution
ReqStream requirements, verification doc, and fixture README
accordingly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Addresses PR #36 review finding: TryParseUppercaseHexDigits previously
only rejected values above 0x10FFFF, not the UTF-16 surrogate range
(0xD800-0xDFFF). A lone surrogate is not a valid standalone Unicode
scalar value, so a malformed /Differences glyph name like /uniD800 -
whether standalone or as a ligature component such as /uniD800_i -
would pass codepoint validation but then crash
TryResolveLigatureUnderscoreName's char.ConvertFromUtf32 call with
ArgumentOutOfRangeException instead of failing closed.
Fixed at the shared TryParseUppercaseHexDigits validator (used by both
the uniXXXX/uXXXX hex-name path and, transitively, the ligature path)
so any current or future consumer of resolved codepoints is protected,
not only the ligature resolver.
Added regression tests:
- PdfDocument_Fonts_Differences_SurrogateRangeUniHexName_FallsBackToBaseEncoding
- PdfDocument_Fonts_Differences_LigatureComponentSurrogateRange_FallsBackToBaseEncoding
Updated docs/reqstream and docs/verification for CanvasNetPdf-PdfDocument-FontEncoding.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The implementation explicitly supports hex-named components (for example uni0066_uni0069), but this theory only exercises literal f/i/l components. Add at least one such case so a regression in the component-to-codepoint fallback cannot pass the entire new test coverage.
The verification text says the broad real-world fixture now proves /f_f resolves, but its test only uses AssertPaintedSomePixel while the page also exercises /uni03BC and /thinspace; that assertion cannot distinguish a resolved ligature from a tofu glyph. Please add a glyph-specific check or qualify this statement so the verification record does not claim coverage the test does not provide.
This updated note overstates what the real-world fixture test proves: PdfDocument_Load_TextType1CDifferencesAglLigaturesFixture_PaintsVisibleGlyphInk only asserts that some pixel is painted, and the same page also contains /uni03BC and /thinspace, so it can pass even if /f_f remains unresolved. Please either add a glyph-specific assertion for the /f_f occurrence or soften this to say that the fixture contains the name; the theory test is the actual isolated coverage today.
…aims
- Add a uni0066_uni0069 InlineData case to
PdfDocument_Fonts_Differences_LigatureUnderscoreName_ResolvesViaEnrichedEmbeddedFontGlyphMap
so the theory also exercises AGL-hex-named components (not only
literal single-letter names), proving
TryResolveLigatureUnderscoreName's per-component recursion into
TryResolveGlyphNameToCodepoint, not just a direct StandardGlyphNames
lookup.
- Correct PdfFixtures/README.md and docs/verification/canvas-net-pdf/pdf-document.md:
the real-world text-type1c-differences-agl-ligatures.pdf fixture test
only asserts that some pixel paints somewhere on the page, which
cannot distinguish a resolved /f_f ligature glyph from an unresolved
tofu glyph (the page already painted ink before this fix, from
unrelated surrounding text). The isolated, glyph-specific proof is
the dedicated synthetic regression test; the fixture now documented
only as proof the real-world name occurs and the document still
opens/renders without error.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This line starts with - , so Markdown renders the continuation as a new unordered-list item instead of the closing dash in the surrounding sentence. Keep the dash inline with the preceding paragraph (or otherwise indent/escape it) so this explanation renders as a single sentence.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
Description
Fixes the still-broken half of the beta.7 real-world glyph-gap report:
/Differencesarrays naming a ligature glyph via the Adobe Glyph List'sunderscore ligature-naming convention (
f_i,f_l,f_f,f_f_i,f_f_l- two or more component glyph names joined by underscores) wereleft unresolved, so the affected glyphs rendered as missing/tofu boxes
even though
StandardGlyphNamesalready had a dedicated codepoint forthe same ligature under its own AGL name (
fi,fl,ff,ffi,ffl). PR #35 already fixed the non-ligatureuniXXXX/thinspacehalf of this report; this closes the remaining gap.
Adds
TryResolveLigatureUnderscoreName: resolves each underscore-separated component recursively (so a component may itself use the
uniXXXX/uXXXXhex convention), concatenates the resolved characters,and looks the concatenated string up as an AGL glyph name in
StandardGlyphNames.The existing real-world
text-type1c-differences-agl-ligatures.pdffixture already exercised an
/f_fligature in its content stream(previously documented as a deliberate, out-of-scope limitation); it
now resolves and paints correctly, proving the fix against both a
synthetic regression test and a genuine real-world embedded font.
Type of Change
Related Issues
Closes #
Pre-Submission Checklist
Build and Test
pwsh ./build.ps1- all tests passed, 0 failures, 0 regressionsCode Quality
Quality Checks
pwsh ./lint.ps1- clean (markdownlint, cspell, yamllint, dotnet format, reqstream, versionmark, reviewmark, sysml2tools)Testing
/f_fcase now resolving)Documentation
Additional Notes
Follow-up to PR #35 (PDF Type1C/Differences glyph lookup). Queued behind the PPTX Phase 1a-1d work per explicit sequencing instruction.