bug 231162 - support custom casing behavior for Turkish and similar writing systems. r=smontagu

This commit is contained in:
Jonathan Kew 2012-03-27 08:49:03 -07:00
parent c3f1fc2e7a
commit 3db8fb754a
3 changed files with 38 additions and 5 deletions

View File

@ -50,6 +50,8 @@ EXPORTS = \
gfx3DMatrix.h \
gfxASurface.h \
gfxAlphaRecovery.h \
gfxAtomList.h \
gfxAtoms.h \
gfxBlur.h \
gfxCachedTempSurface.h \
gfxColor.h \

View File

@ -95,3 +95,9 @@ GFX_ATOM(x_symbol, "x-symbol")
// referenced in all.js
GFX_ATOM(x_user_def, "x-user-def")
// additional languages that use Turkish-style case transformation
GFX_ATOM(az, "az")
GFX_ATOM(ba, "ba")
GFX_ATOM(crh, "crh")
GFX_ATOM(tt, "tt")

View File

@ -39,6 +39,7 @@
#include "nsTextFrameUtils.h"
#include "gfxSkipChars.h"
#include "gfxAtoms.h"
#include "nsStyleConsts.h"
#include "nsStyleContext.h"
@ -48,6 +49,10 @@
#define SZLIG 0x00DF
// Unicode characters needing special casing treatment in tr/az languages
#define LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE 0x0130
#define LATIN_SMALL_LETTER_DOTLESS_I 0x0131
nsTransformedTextRun *
nsTransformedTextRun::Create(const gfxTextRunFactory::Parameters* aParams,
nsTransformingTextRunFactory* aFactory,
@ -357,31 +362,49 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
nsAutoTArray<PRUint8,50> canBreakBeforeArray;
PRUint32 extraCharsCount = 0;
const nsIAtom* lang = nsnull;
bool turkishCasing = false;
PRUint32 i;
for (i = 0; i < length; ++i) {
PRUint32 ch = str[i];
nsStyleContext* styleContext = styles[i];
charsToMergeArray.AppendElement(false);
styleArray.AppendElement(styles[i]);
styleArray.AppendElement(styleContext);
canBreakBeforeArray.AppendElement(aTextRun->CanBreakLineBefore(i));
PRUint8 style = mAllUppercase ? NS_STYLE_TEXT_TRANSFORM_UPPERCASE
: styles[i]->GetStyleText()->mTextTransform;
: styleContext->GetStyleText()->mTextTransform;
bool extraChar = false;
if (NS_IS_HIGH_SURROGATE(ch) && i < length - 1 && NS_IS_LOW_SURROGATE(str[i + 1])) {
ch = SURROGATE_TO_UCS4(ch, str[i + 1]);
}
if (lang != styleContext->GetStyleFont()->mLanguage) {
lang = styleContext->GetStyleFont()->mLanguage;
turkishCasing = lang == gfxAtoms::tr ||
lang == gfxAtoms::az ||
lang == gfxAtoms::ba ||
lang == gfxAtoms::crh ||
lang == gfxAtoms::tt;
}
switch (style) {
case NS_STYLE_TEXT_TRANSFORM_LOWERCASE:
ch = ToLowerCase(ch);
if (turkishCasing && ch == 'I') {
ch = LATIN_SMALL_LETTER_DOTLESS_I;
} else {
ch = ToLowerCase(ch);
}
break;
case NS_STYLE_TEXT_TRANSFORM_UPPERCASE:
if (ch == SZLIG) {
convertedString.Append('S');
extraChar = true;
ch = 'S';
} else if (turkishCasing && ch == 'i') {
ch = LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE;
} else {
ch = ToUpperCase(ch);
}
@ -392,6 +415,8 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
convertedString.Append('S');
extraChar = true;
ch = 'S';
} else if (turkishCasing && ch == 'i') {
ch = LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE;
} else {
ch = ToTitleCase(ch);
}
@ -408,14 +433,14 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
convertedString.Append(L_SURROGATE(ch));
i++;
charsToMergeArray.AppendElement(false);
styleArray.AppendElement(styles[i]);
styleArray.AppendElement(styleContext);
canBreakBeforeArray.AppendElement(false);
}
if (extraChar) {
++extraCharsCount;
charsToMergeArray.AppendElement(true);
styleArray.AppendElement(styles[i]);
styleArray.AppendElement(styleContext);
canBreakBeforeArray.AppendElement(false);
}
}