fix(render): find comma-below letters by character (refs #1666)

A font naming a Latvian comma-below letter by its code point (/uni0136) or by
the glyph list's name for it (/Kcedilla, /Gcedilla...) still drew nothing:
the name resolves to the cedilla name the glyph list prefers, which the
composite table does not hold. The thirteen comma-below letters are now
looked up by character, which also replaces the special case for U+021A and
U+021B. T and t with a cedilla (U+0162, U+0163) are not in that table and
keep their cedilla.

Raised by CodeRabbit on the PR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Tiago Kiel
2026-10-19 20:51:29 -04:00
co-authored by Claude Opus 5.5
parent 8708cbb93d
commit 3b6d344eb5
3 changed files with 36 additions and 8 deletions
+11 -1
View File
@@ -5759,10 +5759,20 @@ trailer << /Root 1 0 R >>
/// `StandardKind`). The stand-ins have neither these letters nor a `commaaccent` to build
/// them from, so Romanian ș Ș (a form laid out from its XFA template names `/scommaaccent`)
/// and Latvian ķ ļ ņ ŗ Ģ drew nothing, and ț Ț drew a cedilla. Each is now its letter with a
/// comma under it, apart from the letter and inside the descender.
/// comma under it, apart from the letter and inside the descender, whichever name the font
/// gives it: the glyph list calls the Latvian letters `/Kcedilla`…, and `uni` names say only
/// the code point.
#[test]
fn comma_below_letters_in_standard_fonts_draw_a_comma_under_the_letter() {
let pairs = [
("s", "uni0219"),
("t", "uni021B"),
("T", "uni021A"),
("K", "uni0136"),
("k", "kcedilla"),
("G", "uni0122"),
("G", "Gcedilla"),
("R", "uni0156"),
("s", "scommaaccent"),
("S", "Scommaaccent"),
("t", "tcommaaccent"),
+1 -1
View File
File diff suppressed because one or more lines are too long
+24 -6
View File
@@ -729,9 +729,28 @@ const ACCENTED_LETTERS: &[(&str, &str, &str, Place)] = &[
("zdotaccent", "z", "dotaccent", Place::Above),
];
/// PdfCraft patch: the comma-below letters of [`ACCENTED_LETTERS`] by character. The glyph list
/// names the Latvian ones `Kcedilla`… (their comma is a cedilla in Unicode's names), has no name
/// for Ț ț, and gives `Tcommaaccent` and `tcommaaccent` to Ţ ţ, which keep their cedilla.
const COMMA_BELOW_BY_CHAR: &[(char, &str)] = &[
('\u{0122}', "Gcommaaccent"),
('\u{0136}', "Kcommaaccent"),
('\u{0137}', "kcommaaccent"),
('\u{013B}', "Lcommaaccent"),
('\u{013C}', "lcommaaccent"),
('\u{0145}', "Ncommaaccent"),
('\u{0146}', "ncommaaccent"),
('\u{0156}', "Rcommaaccent"),
('\u{0157}', "rcommaaccent"),
('\u{0218}', "Scommaaccent"),
('\u{0219}', "scommaaccent"),
('\u{021A}', "Tcommaaccent"),
('\u{021B}', "tcommaaccent"),
];
/// PdfCraft patch: the base letter, accent and placement of an accented letter in
/// [`ACCENTED_LETTERS`], by glyph name (`uni011E` and `u011E` forms too). Ș ș Ț ț by code point:
/// the glyph list names only the first two, and gives the names of the second two to Ţ ţ.
/// [`ACCENTED_LETTERS`], by glyph name (`uni011E` and `u011E` forms too). A comma-below letter
/// is found by its character ([`COMMA_BELOW_BY_CHAR`]), so `/uni0136` and `/Kcedilla` are Ķ too.
fn accented_parts(name: &str) -> Option<(&'static str, &'static str, Place)> {
let name = normalized_glyph_name(name);
let by_name = |n: &str| {
@@ -742,10 +761,9 @@ fn accented_parts(name: &str) -> Option<(&'static str, &'static str, Place)> {
};
by_name(name).or_else(|| {
let c = glyph_name_to_unicode(name)?;
match c {
'\u{021A}' => by_name("Tcommaaccent"),
'\u{021B}' => by_name("tcommaaccent"),
_ => by_name(glyph_names::get_reverse(c)?),
match COMMA_BELOW_BY_CHAR.iter().find(|(letter, _)| *letter == c) {
Some((_, comma_below)) => by_name(comma_below),
None => by_name(glyph_names::get_reverse(c)?),
}
})
}