Add Special Lithuanian Casing

https://bugzilla.mozilla.org/show_bug.cgi?id=1322992
This commit is contained in:
Andy 2026-02-16 11:10:31 -08:00 committed by OwnedByWuigi
commit f8d0b80bd8

View file

@ -230,11 +230,12 @@ GetParametersForInner(nsTransformedTextRun* aTextRun, uint32_t* aFlags,
// exhibit the behavior in question; multiple lang tags may map to the
// same setting here, if the behavior is shared by other languages.
enum LanguageSpecificCasingBehavior {
eLSCB_None, // default non-lang-specific behavior
eLSCB_Dutch, // treat "ij" digraph as a unit for capitalization
eLSCB_Greek, // strip accent when uppercasing Greek vowels
eLSCB_Irish, // keep prefix letters as lowercase when uppercasing Irish
eLSCB_Turkish // preserve dotted/dotless-i distinction in uppercase
eLSCB_None, // default non-lang-specific behavior
eLSCB_Dutch, // treat "ij" digraph as a unit for capitalization
eLSCB_Greek, // strip accent when uppercasing Greek vowels
eLSCB_Irish, // keep prefix letters as lowercase when uppercasing Irish
eLSCB_Turkish, // preserve dotted/dotless-i distinction in uppercase
eLSCB_Lithuanian // retain dot on lowercase i/j when an accent is present
};
static LanguageSpecificCasingBehavior
@ -259,6 +260,9 @@ GetCasingFor(const nsIAtom* aLang)
if (aLang == nsGkAtoms::ga) {
return eLSCB_Irish;
}
if (aLang == nsGkAtoms::lt_) {
return eLSCB_Lithuanian;
}
// Is there a region subtag we should ignore?
nsAtomString langStr(const_cast<nsIAtom*>(aLang));
@ -298,6 +302,8 @@ nsCaseTransformTextRunFactory::TransformString(
bool prevIsLetter = false;
bool ntPrefix = false; // true immediately after a word-initial 'n' or 't'
// when doing Irish lowercasing
bool seenSoftDotted = false; // true immediately after an I or J that is
// converted to lowercase in Lithuanian mode
uint32_t sigmaIndex = uint32_t(-1);
nsIUGenCategory::nsUGenCategory cat;
@ -362,6 +368,58 @@ nsCaseTransformTextRunFactory::TransformString(
}
}
if (languageSpecificCasing == eLSCB_Lithuanian) {
/* From SpecialCasing.txt:
* # Introduce an explicit dot above when lowercasing capital I's and J's
* # whenever there are more accents above.
* # (of the accents used in Lithuanian: grave, acute, tilde above, and ogonek)
*
* 0049; 0069 0307; 0049; 0049; lt More_Above; # LATIN CAPITAL LETTER I
* 004A; 006A 0307; 004A; 004A; lt More_Above; # LATIN CAPITAL LETTER J
* 012E; 012F 0307; 012E; 012E; lt More_Above; # LATIN CAPITAL LETTER I WITH OGONEK
* 00CC; 0069 0307 0300; 00CC; 00CC; lt; # LATIN CAPITAL LETTER I WITH GRAVE
* 00CD; 0069 0307 0301; 00CD; 00CD; lt; # LATIN CAPITAL LETTER I WITH ACUTE
* 0128; 0069 0307 0303; 0128; 0128; lt; # LATIN CAPITAL LETTER I WITH TILDE
*/
if (ch == 'I' || ch == 'J' || ch == 0x012E) {
ch = ToLowerCase(ch);
prevIsLetter = true;
seenSoftDotted = true;
sigmaIndex = uint32_t(-1);
break;
}
if (ch == 0x00CC) {
aConvertedString.Append('i');
aConvertedString.Append(0x0307);
extraChars += 2;
ch = 0x0300;
prevIsLetter = true;
seenSoftDotted = false;
sigmaIndex = uint32_t(-1);
break;
}
if (ch == 0x00CD) {
aConvertedString.Append('i');
aConvertedString.Append(0x0307);
extraChars += 2;
ch = 0x0301;
prevIsLetter = true;
seenSoftDotted = false;
sigmaIndex = uint32_t(-1);
break;
}
if (ch == 0x0128) {
aConvertedString.Append('i');
aConvertedString.Append(0x0307);
extraChars += 2;
ch = 0x0303;
prevIsLetter = true;
seenSoftDotted = false;
sigmaIndex = uint32_t(-1);
break;
}
}
cat = mozilla::unicode::GetGenCategory(ch);
if (languageSpecificCasing == eLSCB_Irish &&
@ -380,6 +438,15 @@ nsCaseTransformTextRunFactory::TransformString(
ntPrefix = false;
}
if (seenSoftDotted && cat == nsIUGenCategory::kMark) {
// The seenSoftDotted flag will only be set in Lithuanian mode.
if (ch == 0x0300 || ch == 0x0301 || ch == 0x0303) {
aConvertedString.Append(0x0307);
++extraChars;
}
}
seenSoftDotted = false;
// Special lowercasing behavior for Greek Sigma: note that this is listed
// as context-sensitive in Unicode's SpecialCasing.txt, but is *not* a
// language-specific mapping; it applies regardless of the language of
@ -458,6 +525,26 @@ nsCaseTransformTextRunFactory::TransformString(
break;
}
if (languageSpecificCasing == eLSCB_Lithuanian) {
/*
* # Remove DOT ABOVE after "i" with upper or titlecase
*
* 0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE
*/
if (ch == 'i' || ch == 'j' || ch == 0x012F) {
seenSoftDotted = true;
ch = ToTitleCase(ch);
break;
}
if (seenSoftDotted) {
seenSoftDotted = false;
if (ch == 0x0307) {
ch = uint32_t(-1);
break;
}
}
}
if (languageSpecificCasing == eLSCB_Irish) {
bool mark;
uint8_t action;
@ -551,6 +638,25 @@ nsCaseTransformTextRunFactory::TransformString(
capitalizeDutchIJ = true;
break;
}
if (languageSpecificCasing == eLSCB_Lithuanian) {
/*
* # Remove DOT ABOVE after "i" with upper or titlecase
*
* 0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE
*/
if (ch == 'i' || ch == 'j' || ch == 0x012F) {
seenSoftDotted = true;
ch = ToTitleCase(ch);
break;
}
if (seenSoftDotted) {
seenSoftDotted = false;
if (ch == 0x0307) {
ch = uint32_t(-1);
break;
}
}
}
mcm = mozilla::unicode::SpecialTitle(ch);
if (mcm) {