bug 231162 - support custom casing behavior for Turkish and similar writing systems. r=smontagu
authorJonathan Kew <jkew@mozilla.com>
Tue, 27 Mar 2012 08:49:03 -0700
changeset 93736 4e28b565455db92b213a3443db5edad445463bfc
parent 93735 f2e02f954e780246d665207f052094ca1adf2e5c
child 93737 c510b7d0069c0895c977286be38036ac363d3f16
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmontagu
bugs231162
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 231162 - support custom casing behavior for Turkish and similar writing systems. r=smontagu
gfx/thebes/Makefile.in
gfx/thebes/gfxAtomList.h
layout/generic/nsTextRunTransformations.cpp
--- a/gfx/thebes/Makefile.in
+++ b/gfx/thebes/Makefile.in
@@ -45,16 +45,18 @@ LIBRARY_NAME	= thebes
 LIBXUL_LIBRARY	= 1
 EXPORT_LIBRARY	= 1
 
 EXPORTS	= \
         gfx2DGlue.h \
 	gfx3DMatrix.h \
 	gfxASurface.h \
 	gfxAlphaRecovery.h \
+	gfxAtomList.h \
+	gfxAtoms.h \
 	gfxBlur.h \
 	gfxCachedTempSurface.h \
 	gfxColor.h \
 	gfxContext.h \
 	gfxDrawable.h \
 	gfxFailure.h \
 	gfxFont.h \
 	gfxFontConstants.h \
--- a/gfx/thebes/gfxAtomList.h
+++ b/gfx/thebes/gfxAtomList.h
@@ -90,8 +90,14 @@ GFX_ATOM(x_tibt, "x-tibt")
 
 // used in gfxGDIFontList.h
 GFX_ATOM(ko_xxx, "ko-xxx")
 GFX_ATOM(x_central_euro, "x-central-euro")
 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")
--- a/layout/generic/nsTextRunTransformations.cpp
+++ b/layout/generic/nsTextRunTransformations.cpp
@@ -34,25 +34,30 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsTextRunTransformations.h"
 
 #include "nsTextFrameUtils.h"
 #include "gfxSkipChars.h"
+#include "gfxAtoms.h"
 
 #include "nsStyleConsts.h"
 #include "nsStyleContext.h"
 #include "gfxContext.h"
 #include "nsContentUtils.h"
 #include "nsUnicharUtils.h"
 
 #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,
                              gfxFontGroup* aFontGroup,
                              const PRUnichar* aString, PRUint32 aLength,
                              const PRUint32 aFlags, nsStyleContext** aStyles,
                              bool aOwnsFactory)
 {
@@ -352,75 +357,95 @@ nsCaseTransformTextRunFactory::RebuildTe
   nsRefPtr<nsStyleContext>* styles = aTextRun->mStyles.Elements();
 
   nsAutoString convertedString;
   nsAutoTArray<bool,50> charsToMergeArray;
   nsAutoTArray<nsStyleContext*,50> styleArray;
   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);
       }
       break;
     case NS_STYLE_TEXT_TRANSFORM_CAPITALIZE:
       if (i < aTextRun->mCapitalize.Length() && aTextRun->mCapitalize[i]) {
         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 = ToTitleCase(ch);
         }
       }
       break;
     default:
       break;
     }
 
     if (IS_IN_BMP(ch)) {
       convertedString.Append(ch);
     } else {
       convertedString.Append(H_SURROGATE(ch));
       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);
     }
   }
 
   PRUint32 flags;
   gfxTextRunFactory::Parameters innerParams =
       GetParametersForInner(aTextRun, &flags, aRefContext);
   gfxFontGroup* fontGroup = aTextRun->GetFontGroup();